diff --git a/.ci/create-changes-html.sh b/.ci/create-changes-html.sh index 1a6fbeef27b..cdae3a49df8 100755 --- a/.ci/create-changes-html.sh +++ b/.ci/create-changes-html.sh @@ -62,21 +62,27 @@ for block in diff_blocks: match = re.search(r'^diff --git a/(.*) b/\1', block, flags=re.MULTILINE) if match: doc = match.group(1) - path = 'html/' + doc file_path = os.path.join('$DOC_REPOSITORY', doc) - with open(file_path, 'r') as file: - content = file.readlines() + try: + with open(file_path, 'r') as file: + content = file.readlines() + except FileNotFoundError: + content = [] count = 0 for line in block.splitlines(): if line.startswith('@@ -'): - line_number = int(re.search(r'@@ -(\d+)', line).group(1)) - for i in range(line_number, -1, -1): - if content[i].startswith('<'): - count += 1 - content[i] = f'' + content[i] - break - with open(file_path, 'w') as file: - file.writelines(content) + search_result = re.search(r'@@ -(\d+),(\d+) \+(\d+),(\d+)', line) + if search_result: + line_number = int(search_result.group(3)) + for i in range(line_number - 1, -1, -1): + if content[i].startswith('<'): + count += 1 + content[i] = f'' + content[i] + break + if content: + with open(file_path, 'w') as file: + file.writelines(content) + path = 'html/' + doc hunks = ' '.join(f'#{i + 1}' for i in range(count)) out_blocks.append(f'
{doc} ' + hunks + '
' + '\n'
diff --git a/.github/sync_labels.py b/.github/sync_labels.py
index 97ddf039a16..dbd8566c517 100755
--- a/.github/sync_labels.py
+++ b/.github/sync_labels.py
@@ -141,6 +141,7 @@ def __init__(self, url, actor):
self._commits = None
self._commit_date = None
self._bot_login = None
+ self._gh_version = None
s = url.split('/')
self._owner = s[3]
@@ -235,13 +236,30 @@ def bot_login(self):
"""
if self._bot_login:
return self._bot_login
- cmd = 'gh auth status'
from subprocess import run
+ cmd = 'gh version'
+ capt = run(cmd, shell=True, capture_output=True)
+ self._gh_version = str(capt.stdout).split('\\n')[0]
+ info('version: %s' % self._gh_version)
+ cmd = 'gh auth status'
capt = run(cmd, shell=True, capture_output=True)
- l = str(capt.stderr).split()
- if not 'as' in l:
- l = str(capt.stdout).split()
- self._bot_login = l[l.index('as')+1]
+ errtxt = str(capt.stderr)
+ outtxt = str(capt.stdout)
+ debug('auth status err: %s' % errtxt)
+ debug('auth status out: %s' % outtxt)
+ def read_login(txt, position_mark):
+ for t in txt:
+ for p in position_mark:
+ # the output text has changed from as to account
+ # around version 2.40.0
+ l = t.split()
+ if p in l:
+ return l[l.index(p)+1]
+ self._bot_login = read_login([errtxt, outtxt], ['account', 'as'])
+ if not self._bot_login:
+ self._bot_login = default_bot
+ warning('Bot is unknown')
+ return self._bot_login
if self._bot_login.endswith('[bot]'):
self._bot_login = self._bot_login.split('[bot]')[0]
info('Bot is %s' % self._bot_login)
diff --git a/.github/workflows/ci-conda-known-test-failures.json b/.github/workflows/ci-conda-known-test-failures.json
new file mode 100644
index 00000000000..2d828ac98fb
--- /dev/null
+++ b/.github/workflows/ci-conda-known-test-failures.json
@@ -0,0 +1,53 @@
+{
+ "sage_setup.clean": {
+ "failed": true
+ },
+ "sage.combinat.cluster_algebra_quiver.quiver": {
+ "failed": true
+ },
+ "sage.geometry.cone": {
+ "failed": true
+ },
+ "sage.groups.matrix_gps.finitely_generated_gap": {
+ "failed": true
+ },
+ "sage.interfaces.expect": {
+ "failed": true
+ },
+ "sage.libs.gap.element": {
+ "failed": true
+ },
+ "sage.libs.singular.singular": {
+ "failed": true
+ },
+ "sage.matrix.matrix2": {
+ "failed": true
+ },
+ "sage.matrix.matrix_integer_sparse": {
+ "failed": true
+ },
+ "sage.misc.lazy_import": {
+ "failed": true
+ },
+ "sage.misc.weak_dict": {
+ "failed": true
+ },
+ "sage.modular.modform.l_series_gross_zagier": {
+ "failed": true
+ },
+ "sage.rings.function_field.drinfeld_modules.morphism": {
+ "failed": true
+ },
+ "sage.rings.polynomial.multi_polynomial_ideal": {
+ "failed": true
+ },
+ "sage.rings.polynomial.multi_polynomial_libsingular": {
+ "failed": true
+ },
+ "sage.rings.polynomial.skew_polynomial_finite_field": {
+ "failed": true
+ },
+ "sage.tests.gap_packages": {
+ "failed": true
+ }
+}
diff --git a/.github/workflows/ci-conda.yml b/.github/workflows/ci-conda.yml
index 3b928fef58d..6432b7a0a6a 100644
--- a/.github/workflows/ci-conda.yml
+++ b/.github/workflows/ci-conda.yml
@@ -92,7 +92,7 @@ jobs:
- name: Test
if: success() || failure()
shell: bash -l {0}
- run: ./sage -t --all -p0
+ run: ./sage -t --all --baseline-stats-path=.github/workflows/ci-conda-known-test-failures.json -p0
- name: Print logs
if: always()
diff --git a/.github/workflows/doc-build-pdf.yml b/.github/workflows/doc-build-pdf.yml
index bfa32760934..7ae675d9e64 100644
--- a/.github/workflows/doc-build-pdf.yml
+++ b/.github/workflows/doc-build-pdf.yml
@@ -57,7 +57,7 @@ jobs:
export PATH="build/bin:$PATH"
eval $(sage-print-system-package-command auto update)
eval $(sage-print-system-package-command auto --yes --no-install-recommends install zip)
- eval $(sage-print-system-package-command auto --spkg --yes --no-install-recommends install git texlive)
+ eval $(sage-print-system-package-command auto --spkg --yes --no-install-recommends install git texlive texlive_luatex free_fonts xindy)
- name: Add prebuilt tree as a worktree
id: worktree
diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml
index 0c5200dbe81..9d82909ef5f 100644
--- a/.github/workflows/doc-build.yml
+++ b/.github/workflows/doc-build.yml
@@ -161,7 +161,7 @@ jobs:
export PATH="build/bin:$PATH"
eval $(sage-print-system-package-command auto update)
eval $(sage-print-system-package-command auto --yes --no-install-recommends install zip)
- eval $(sage-print-system-package-command auto --spkg --yes --no-install-recommends install git texlive)
+ eval $(sage-print-system-package-command auto --spkg --yes --no-install-recommends install git texlive texlive_luatex free_fonts xindy)
export SAGE_USE_CDNS=yes
export SAGE_LIVE_DOC=yes
export SAGE_JUPYTER_SERVER=binder:sagemath/sage-binder-env/dev
diff --git a/CITATION.cff b/CITATION.cff
index d05315fa584..a34996764e6 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.3.beta2
+version: 10.3.beta4
doi: 10.5281/zenodo.593563
-date-released: 2023-12-13
+date-released: 2023-12-26
repository-code: "https://github.com/sagemath/sage"
url: "https://www.sagemath.org/"
diff --git a/README.md b/README.md
index 4720c2b87ab..422582292af 100644
--- a/README.md
+++ b/README.md
@@ -424,8 +424,8 @@ For installation of `sage` in python using `pip` you need to install `sagemath-s
$ python3 -m pip install sage_conf
$ ls $(sage-config SAGE_SPKG_WHEELS)
- $ python3 -m pip install $(sage-config SAGE_SPKG_WHEELS)/*.whl
- $ python3 -m pip install sagemath-standard
+ $ python3 -m pip install $(sage-config SAGE_SPKG_WHEELS)/*.whl sage_setup
+ $ python3 -m pip install --no-build-isolation sagemath-standard
You need to install `sage_conf`, a wheelhouse of various python packages. You can list the wheels using `ls $(sage-config SAGE_SPKG_WHEELS)`. After manual installation of these wheels, you can install the sage library, `sagemath-standard`.
diff --git a/VERSION.txt b/VERSION.txt
index a6d9f480c1e..f34f97b89ee 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1 +1 @@
-SageMath version 10.3.beta2, Release Date: 2023-12-13
+SageMath version 10.3.beta4, Release Date: 2023-12-26
diff --git a/build/bin/sage-dist-helpers b/build/bin/sage-dist-helpers
index 2dc56b62466..ac588fc297c 100644
--- a/build/bin/sage-dist-helpers
+++ b/build/bin/sage-dist-helpers
@@ -244,7 +244,7 @@ sdh_pip_install() {
# Our default after #33789 (Sage 9.7): We allow the package to provision
# its build environment using the stored wheels.
# We pass --find-links.
- # The SPKG needs to declare "setuptools_wheel" as a dependency.
+ # The SPKG needs to declare "setuptools" as a dependency.
build_isolation_option="--find-links=$SAGE_SPKG_WHEELS"
;;
--no-build-isolation)
@@ -289,8 +289,6 @@ sdh_pip_install() {
sdh_pip_editable_install() {
echo "Installing $PKG_NAME (editable mode)"
- # Until https://github.com/sagemath/sage/issues/34209 switches us to PEP 660 editable wheels
- export SETUPTOOLS_ENABLE_FEATURES=legacy-editable
python3 -m pip install --verbose --no-deps --no-index --no-build-isolation --isolated --editable "$@" || \
sdh_die "Error installing $PKG_NAME"
}
diff --git a/build/bin/sage-get-system-packages b/build/bin/sage-get-system-packages
index c8b9314c3fe..1b8aae79c16 100755
--- a/build/bin/sage-get-system-packages
+++ b/build/bin/sage-get-system-packages
@@ -41,7 +41,7 @@ case "$SYSTEM" in
fi
fi
SYSTEM_PACKAGES_FILE_NAMES="distros/$SYSTEM.txt"
- STRIP_COMMENTS="sed s/#.*//;"
+ STRIP_COMMENTS="sed s/#.*//;s/\${PYTHON_MINOR}/${PYTHON_MINOR}/g"
COLLECT=echo
;;
esac
diff --git a/build/bin/sage-guess-package-system b/build/bin/sage-guess-package-system
index 09eafd510c9..8e679c2eac9 100755
--- a/build/bin/sage-guess-package-system
+++ b/build/bin/sage-guess-package-system
@@ -11,6 +11,8 @@ if conda --version > /dev/null 2>&1; then
fi
if brew --version > /dev/null 2>&1; then
echo homebrew
+elif port version > /dev/null 2>&1; then
+ echo macports
elif emerge --version > /dev/null 2>&1; then
echo gentoo
elif apt-get --version > /dev/null 2>&1; then
diff --git a/build/bin/sage-print-system-package-command b/build/bin/sage-print-system-package-command
index c36f64e19bf..722a7f75161 100755
--- a/build/bin/sage-print-system-package-command
+++ b/build/bin/sage-print-system-package-command
@@ -34,6 +34,16 @@ do
;;
--prompt)
PROMPT=' $ '
+ CONTINUATION=' '
+ ;;
+ --continuation=*)
+ CONTINUATION="${1#--continuation=}"
+ ;;
+ --wrap)
+ WRAP=78
+ ;;
+ --wrap=*)
+ WRAP="${1#--wrap=}"
;;
--no-install-recommends)
NO_INSTALL_RECOMMENDS=yes
@@ -79,7 +89,13 @@ function print_shell_command()
echo ".. CODE-BLOCK:: bash"
echo
fi
- echo "${PROMPT}$1"
+ # shell-quote arguments if necessary
+ quoted=$(for a in "$@"; do printf "%q " $a; done)
+ if [ -z "$WRAP" -o $# -lt 6 ]; then
+ echo "${PROMPT}${quoted}"
+ else
+ sage-bootstrap-python -c "import textwrap; print(' \\\\\n'.join(textwrap.wrap(r'''${quoted}''', $WRAP, initial_indent=r'''${PROMPT}''', subsequent_indent=r'''${CONTINUATION}''', break_long_words=False, break_on_hyphens=False)))"
+ fi
if [ -n "$OUTPUT_RST" ]; then
echo
fi
@@ -102,6 +118,15 @@ case $system:$command in
[ -n "$SAGE_ROOT" ] || SAGE_ROOT=.
echo "${PROMPT}source $SAGE_ROOT/.homebrew-build-env"
;;
+ macports*:setup-build-env)
+ $IF_VERBOSE echo "${COMMENT}"
+ $IF_VERBOSE echo "${COMMENT}WARNING: Use of MacPorts is experimental"
+ $IF_VERBOSE echo "${COMMENT}"
+ $IF_VERBOSE echo "${COMMENT}MacPorts does not provide unversioned gfortran executables by default"
+ $IF_VERBOSE echo "${COMMENT}To make gfortran available (and build with gcc from XCode), use:"
+ $IF_VERBOSE echo "${COMMENT}"
+ $IF_VERBOSE print_shell_command ./configure FC=gfortran-mp-11
+ ;;
*:setup-build-env)
# Nothing needed
;;
@@ -109,70 +134,74 @@ case $system:$command in
# Verbs handled above are our own inventions. Verbs handled below are apt-get verbs.
#
@(debian*|ubuntu*):update)
- print_shell_command "${SUDO}apt-get $command $system_packages"
+ print_shell_command ${SUDO}apt-get $command $system_packages
;;
@(debian*|ubuntu*):*)
[ "$NO_INSTALL_RECOMMENDS" = yes ] && options="$options --no-install-recommends"
[ "$YES" = yes ] && options="$options --yes" env="DEBIAN_FRONTEND=noninteractive "
- [ -n "$system_packages" ] && print_shell_command "${SUDO}${env}apt-get $command $options $system_packages"
+ [ -n "$system_packages" ] && print_shell_command ${SUDO}${env}apt-get $command $options $system_packages
;;
@(fedora*|redhat*|centos*):install)
[ "$YES" = yes ] && options="$options -y"
- [ -n "$system_packages" ] && print_shell_command "${SUDO}yum install $options $system_packages"
+ [ -n "$system_packages" ] && print_shell_command ${SUDO}yum install $options $system_packages
;;
gentoo*:install)
- [ -n "$system_packages" ] && print_shell_command "${SUDO}emerge $system_packages"
+ [ -n "$system_packages" ] && print_shell_command ${SUDO}emerge $system_packages
;;
arch*:update)
print_shell_command "${SUDO}pacman -Sy"
;;
arch*:install)
[ "$YES" = yes ] && options="$options --noconfirm"
- [ -n "$system_packages" ] && print_shell_command "${SUDO}pacman -S $options $system_packages"
+ [ -n "$system_packages" ] && print_shell_command ${SUDO}pacman -S $options $system_packages
;;
void*:update)
print_shell_command "${SUDO}xbps-install -Su"
;;
void*:install)
[ "$YES" = yes ] && options="$options --yes"
- [ -n "$system_packages" ] && print_shell_command "${SUDO}xbps-install $options $system_packages"
+ [ -n "$system_packages" ] && print_shell_command ${SUDO}xbps-install $options $system_packages
;;
opensuse*:install)
- [ -n "$system_packages" ] && print_shell_command "${SUDO}zypper install $system_packages"
+ [ -n "$system_packages" ] && print_shell_command ${SUDO}zypper install $system_packages
;;
*conda*:install)
[ "$YES" = yes ] && options="$options --yes"
- [ -n "$system_packages" ] && print_shell_command "conda install $options $system_packages"
+ [ -n "$system_packages" ] && print_shell_command conda install $options $system_packages
;;
homebrew*:install)
- [ -n "$system_packages" ] && print_shell_command "brew install $system_packages"
+ [ -n "$system_packages" ] && print_shell_command brew install $system_packages
+ ;;
+ macports*:install)
+ [ "$YES" = yes ] && options="$options -N"
+ [ -n "$system_packages" ] && print_shell_command ${SUDO}port $options install $system_packages
;;
slackware*:install)
- [ -n "$system_packages" ] && print_shell_command "${SUDO}slackpkg install $system_packages"
+ [ -n "$system_packages" ] && print_shell_command ${SUDO}slackpkg install $system_packages
;;
cygwin*:update)
print_comment "first install apt-cyg from https://github.com/transcode-open/apt-cyg"
;;
cygwin*:install)
- [ -n "$system_packages" ] && print_shell_command "apt-cyg install $system_packages"
+ [ -n "$system_packages" ] && print_shell_command apt-cyg install $system_packages
;;
freebsd*:install)
- [ -n "$system_packages" ] && print_shell_command "${SUDO}pkg install $system_packages"
+ [ -n "$system_packages" ] && print_shell_command ${SUDO}pkg install $system_packages
;;
nix*:install)
- [ -n "$system_packages" ] && print_shell_command "nix-env --install $system_packages"
+ [ -n "$system_packages" ] && print_shell_command nix-env --install $system_packages
;;
alpine:update)
print_shell_command "apk update"
;;
alpine:install)
- [ -n "$system_packages" ] && print_shell_command "apk add $system_packages"
+ [ -n "$system_packages" ] && print_shell_command apk add $system_packages
;;
pip:install)
- [ -n "$system_packages" ] && print_shell_command "sage -pip install $system_packages"
+ [ -n "$system_packages" ] && print_shell_command sage -pip install $system_packages
;;
cpan:install)
- [ -n "$system_packages" ] && print_shell_command "cpan -i $system_packages"
+ [ -n "$system_packages" ] && print_shell_command cpan -i $system_packages
;;
repology:install)
if [ -n "$system_packages" ]; then
diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg
index ed2e9090cf8..e2a151b4adc 100755
--- a/build/bin/sage-spkg
+++ b/build/bin/sage-spkg
@@ -341,7 +341,7 @@ fi
PKG_BASE_VER=`echo $PKG_VER | sed 's/\.p[0-9][0-9]*$//'`
if [ -f "$PKG_SCRIPTS/checksums.ini" ]; then
# Normal/wheel package
- PKG_NAME_UPSTREAM=`lookup_param tarball "$PKG_SCRIPTS/checksums.ini" | sed "s/VERSION/$PKG_BASE_VER/"`
+ PKG_NAME_UPSTREAM=`lookup_param tarball "$PKG_SCRIPTS/checksums.ini"`
fi
# Set the $SAGE_DESTDIR variable to be passed to the spkg-install
@@ -396,11 +396,11 @@ ensure_pkg_src() { ###############################################
if [ ! -f "$PKG_SRC" ]; then
if [ -n "$PKG_NAME_UPSTREAM" ]; then
# Normal or wheel package
- if ! sage-download-file $SAGE_DOWNLOAD_FILE_OPTIONS "$PKG_NAME_UPSTREAM"; then
- error_msg "Error downloading $PKG_NAME_UPSTREAM"
+ PKG_SRC=$(sage-package download $SAGE_DOWNLOAD_FILE_OPTIONS $PKG_BASE)
+ if [ $? != 0 ]; then
+ error_msg "Error downloading tarball of $PKG_BASE"
exit 1
fi
- PKG_SRC="$SAGE_DISTFILES/$PKG_NAME_UPSTREAM"
# Do a final check that PKG_SRC is a file with an absolute path
cd /
if [ ! -f "$PKG_SRC" ]; then
@@ -509,7 +509,9 @@ else
# just copy to dist/ and create a simple install script.
mkdir -p dist
cp "$PKG_SRC" dist/
- echo "sdh_store_and_pip_install_wheel ." > spkg-install.in
+ if [ ! -f spkg-install.in ]; then
+ echo "sdh_store_and_pip_install_wheel ." > spkg-install.in
+ fi
;;
*)
# Source tarball
diff --git a/build/bin/sage-spkg-info b/build/bin/sage-spkg-info
index e43e516dc5b..6b66e584331 100755
--- a/build/bin/sage-spkg-info
+++ b/build/bin/sage-spkg-info
@@ -5,11 +5,26 @@
#
# Assumes SAGE_ROOT is set
PKG_BASE=$1
+if [ -n "$OUTPUT_DIR" ]; then
+ exec > "$OUTPUT_DIR"/$PKG_BASE.rst
+fi
+if [ -n "$OUTPUT_RST" ]; then
+ echo ".. _spkg_$PKG_BASE:"
+ echo
+ ref () { echo ":ref:\`$1\`"; }
+ issue () { echo ":issue:\`$1\`"; }
+ code () { echo "\`\`$*\`\`"; }
+else
+ ref () { echo "$1"; }
+ issue () { echo "https://github.com/sagemath/sage/issues/$1"; }
+ code () { echo "$1"; }
+fi
PKG_SCRIPTS="$SAGE_ROOT/build/pkgs/$PKG_BASE"
for ext in rst txt; do
SPKG_FILE="$PKG_SCRIPTS/SPKG.$ext"
if [ -f "$SPKG_FILE" ]; then
- sed "1,3s/^ *Sage: Open Source Mathematics Software:/$PKG_BASE:/" "$SPKG_FILE"
+ # for sphinx 4.4 we need to replace all direct links by some "extlink" (issue 33272)
+ sed -e "1,3s/^ *Sage: Open Source Mathematics Software:/$PKG_BASE:/" -e "s|https://github.com/sagemath/sage/issues/\([0-9]*\)|:issue:\`\1\`|g" -e "s|https://arxiv.org/abs/cs/\([0-9]*\)|:arxiv:\`cs/\1\`|g" "$SPKG_FILE"
break
fi
done
@@ -39,9 +54,9 @@ for dep_file in dependencies dependencies_order_only; do
# Dependencies like $(BLAS)
\$\(*) echo "- $dep";;
# Looks like a package
- *) if [ -n "$OUTPUT_RST" -a -r "$SAGE_ROOT/build/pkgs/$dep/SPKG.rst" ]; then
+ *) if [ -r "$SAGE_ROOT/build/pkgs/$dep/SPKG.rst" ]; then
# This RST label is set in src/doc/bootstrap
- echo "- :ref:\`spkg_$dep\`"
+ echo "- $(ref spkg_$dep)"
else
echo "- $dep"
fi;;
@@ -103,7 +118,7 @@ for system in $systems; do
echo "$system:"
;;
esac
- sage-print-system-package-command $system --prompt=' $ ' --sudo install $system_packages
+ sage-print-system-package-command $system --wrap --prompt=' $ ' --continuation=' ' --sudo install $system_packages
echo
done
if [ -z "$system" ]; then
@@ -114,15 +129,15 @@ else
if [ -f "${SPKG_CONFIGURE}" ]; then
if grep -q SAGE_PYTHON_PACKAGE_CHECK "${SPKG_CONFIGURE}"; then
echo "If the system package is installed and if the (experimental) option"
- echo "--enable-system-site-packages is passed to ./configure, then ./configure"
+ echo "$(code --enable-system-site-packages) is passed to $(code ./configure), then $(code ./configure)"
echo "will check if the system package can be used."
else
- echo "If the system package is installed, ./configure will check if it can be used."
+ echo "If the system package is installed, $(code ./configure) will check if it can be used."
fi
else
echo "However, these system packages will not be used for building Sage"
- echo "because spkg-configure.m4 has not been written for this package;"
- echo "see https://github.com/sagemath/sage/issues/27330"
+ echo "because $(code spkg-configure.m4) has not been written for this package;"
+ echo "see $(issue 27330)"
fi
fi
echo
diff --git a/build/bin/write-dockerfile.sh b/build/bin/write-dockerfile.sh
index bfc4dd751a4..104f7c19b31 100755
--- a/build/bin/write-dockerfile.sh
+++ b/build/bin/write-dockerfile.sh
@@ -16,12 +16,15 @@ export PATH="$SAGE_ROOT"/build/bin:$PATH
SYSTEM_PACKAGES=$EXTRA_SYSTEM_PACKAGES
CONFIGURE_ARGS="--enable-option-checking "
for SPKG in $(sage-package list --has-file=spkg-configure.m4 $SAGE_PACKAGE_LIST_ARGS) $EXTRA_SAGE_PACKAGES; do
- SYSTEM_PACKAGE=$(sage-get-system-packages $SYSTEM $SPKG | sed 's/${PYTHON_MINOR}/'${PYTHON_MINOR}'/g')
+ SYSTEM_PACKAGE=$(sage-get-system-packages $SYSTEM $SPKG)
if [ -n "${SYSTEM_PACKAGE}" ]; then
- # SYSTEM_PACKAGE can be empty if, for example, the environment
- # variable ENABLE_SYSTEM_SITE_PACKAGES is empty.
- SYSTEM_PACKAGES+=" ${SYSTEM_PACKAGE}"
- CONFIGURE_ARGS+="--with-system-${SPKG}=${WITH_SYSTEM_SPKG} "
+ # SYSTEM_PACKAGE can be empty if, for example, the environment
+ # variable ENABLE_SYSTEM_SITE_PACKAGES is empty.
+ for a in $SYSTEM_PACKAGE; do
+ # shell-quote package if necessary
+ SYSTEM_PACKAGES+=$(printf " %q" "$a")
+ done
+ CONFIGURE_ARGS+="--with-system-${SPKG}=${WITH_SYSTEM_SPKG} "
fi
done
echo "# Automatically generated by SAGE_ROOT/build/bin/write-dockerfile.sh"
diff --git a/build/make/Makefile.in b/build/make/Makefile.in
index 0cbe86a90de..aac7a9164a2 100644
--- a/build/make/Makefile.in
+++ b/build/make/Makefile.in
@@ -324,7 +324,7 @@ all-toolchain: base-toolchain
# Shorthand for a list of packages sufficient for building and installing
# typical Python packages from source. Wheel packages only need pip.
-PYTHON_TOOLCHAIN = setuptools pip setuptools_scm wheel setuptools_wheel
+PYTHON_TOOLCHAIN = setuptools pip setuptools_scm wheel flit_core hatchling
# Trac #32056: Avoid installed setuptools leaking into the build of python3 by uninstalling it.
# It will have to be reinstalled anyway because of its dependency on $(PYTHON).
diff --git a/build/pkgs/4ti2/checksums.ini b/build/pkgs/4ti2/checksums.ini
index 275cf157a6a..047f39ece1d 100644
--- a/build/pkgs/4ti2/checksums.ini
+++ b/build/pkgs/4ti2/checksums.ini
@@ -1,5 +1,5 @@
-tarball=4ti2-VERSION.tar.gz
+tarball=4ti2-${VERSION}.tar.gz
sha1=3d41f30ea3ef94c293eae30c087494269fc1a6b9
md5=1215872325ddfc561865ecb22b2bccb2
cksum=2439180289
-upstream_url=https://github.com/4ti2/4ti2/releases/download/Release_1_6_10/4ti2-1.6.10.tar.gz
+upstream_url=https://github.com/4ti2/4ti2/releases/download/Release_${VERSION_MAJOR}_${VERSION_MINOR}_${VERSION_MICRO}/4ti2-${VERSION}.tar.gz
diff --git a/build/pkgs/_bootstrap/distros/arch.txt b/build/pkgs/_bootstrap/distros/arch.txt
index 33054ef918c..050de00ca70 100644
--- a/build/pkgs/_bootstrap/distros/arch.txt
+++ b/build/pkgs/_bootstrap/distros/arch.txt
@@ -1,3 +1,5 @@
# Packages needed for ./bootstrap
-autoconf automake libtool
+autoconf
+automake
+libtool
pkgconf
diff --git a/build/pkgs/_bootstrap/distros/cygwin.txt b/build/pkgs/_bootstrap/distros/cygwin.txt
index b5d2db8cfb2..bde788ee5d9 100644
--- a/build/pkgs/_bootstrap/distros/cygwin.txt
+++ b/build/pkgs/_bootstrap/distros/cygwin.txt
@@ -1,2 +1,4 @@
# Packages needed for ./bootstrap
-autoconf automake libtool
+autoconf
+automake
+libtool
diff --git a/build/pkgs/_bootstrap/distros/fedora.txt b/build/pkgs/_bootstrap/distros/fedora.txt
index e8e9330eca1..5fe960ac3a0 100644
--- a/build/pkgs/_bootstrap/distros/fedora.txt
+++ b/build/pkgs/_bootstrap/distros/fedora.txt
@@ -1,4 +1,5 @@
# Packages needed for ./bootstrap
-autoconf automake libtool
-# Fedora 26 needs:
+autoconf
+automake
+libtool
pkg-config
diff --git a/build/pkgs/_bootstrap/distros/freebsd.txt b/build/pkgs/_bootstrap/distros/freebsd.txt
index 93d91f5c84b..5fe960ac3a0 100644
--- a/build/pkgs/_bootstrap/distros/freebsd.txt
+++ b/build/pkgs/_bootstrap/distros/freebsd.txt
@@ -1,2 +1,5 @@
# Packages needed for ./bootstrap
-autoconf automake libtool pkg-config
+autoconf
+automake
+libtool
+pkg-config
diff --git a/build/pkgs/_bootstrap/distros/homebrew.txt b/build/pkgs/_bootstrap/distros/homebrew.txt
index 93d91f5c84b..5fe960ac3a0 100644
--- a/build/pkgs/_bootstrap/distros/homebrew.txt
+++ b/build/pkgs/_bootstrap/distros/homebrew.txt
@@ -1,2 +1,5 @@
# Packages needed for ./bootstrap
-autoconf automake libtool pkg-config
+autoconf
+automake
+libtool
+pkg-config
diff --git a/build/pkgs/_bootstrap/distros/macports.txt b/build/pkgs/_bootstrap/distros/macports.txt
new file mode 100644
index 00000000000..5f6a8a4c191
--- /dev/null
+++ b/build/pkgs/_bootstrap/distros/macports.txt
@@ -0,0 +1,6 @@
+# Packages needed for ./bootstrap
+gettext
+autoconf
+automake
+libtool
+pkgconfig
diff --git a/build/pkgs/_bootstrap/distros/nix.txt b/build/pkgs/_bootstrap/distros/nix.txt
index 93d91f5c84b..5fe960ac3a0 100644
--- a/build/pkgs/_bootstrap/distros/nix.txt
+++ b/build/pkgs/_bootstrap/distros/nix.txt
@@ -1,2 +1,5 @@
# Packages needed for ./bootstrap
-autoconf automake libtool pkg-config
+autoconf
+automake
+libtool
+pkg-config
diff --git a/build/pkgs/_bootstrap/distros/void.txt b/build/pkgs/_bootstrap/distros/void.txt
index 6490cf773e7..904bd61a232 100644
--- a/build/pkgs/_bootstrap/distros/void.txt
+++ b/build/pkgs/_bootstrap/distros/void.txt
@@ -1,4 +1,7 @@
# Packages needed for ./bootstrap
-autoconf automake libtool
-xtools mk-configure
+autoconf
+automake
+libtool
+xtools
+mk-configure
pkg-config
diff --git a/build/pkgs/_prereq/distros/alpine.txt b/build/pkgs/_prereq/distros/alpine.txt
index 159c452cf30..3986f8ac849 100644
--- a/build/pkgs/_prereq/distros/alpine.txt
+++ b/build/pkgs/_prereq/distros/alpine.txt
@@ -1,3 +1,12 @@
+# This file, build/pkgs/_prereq/distros/alpine.txt, contains names of
+# Alpine Linux packages needed for installation of Sage from source.
+#
+# In addition, the files build/pkgs/SPKG/distros/alpine.txt contain
+# the names of packages that provide the equivalent of SPKG.
+#
+# One package per line. No need to escape special characters.
+# Everything on a line after a # character is ignored.
+#
binutils
make
m4
diff --git a/build/pkgs/_prereq/distros/arch.txt b/build/pkgs/_prereq/distros/arch.txt
index 9b9bf09e7e2..aac6d8f5976 100644
--- a/build/pkgs/_prereq/distros/arch.txt
+++ b/build/pkgs/_prereq/distros/arch.txt
@@ -1,3 +1,12 @@
+# This file, build/pkgs/_prereq/distros/arch.txt, contains names of
+# Arch Linux packages needed for installation of Sage from source.
+#
+# In addition, the files build/pkgs/SPKG/distros/arch.txt contain
+# the names of packages that provide the equivalent of SPKG.
+#
+# One package per line. No need to escape special characters.
+# Everything on a line after a # character is ignored.
+#
binutils
make
m4
diff --git a/build/pkgs/_prereq/distros/conda.txt b/build/pkgs/_prereq/distros/conda.txt
index d76388ce7bb..e8fcb099093 100644
--- a/build/pkgs/_prereq/distros/conda.txt
+++ b/build/pkgs/_prereq/distros/conda.txt
@@ -1,4 +1,13 @@
-compilers
+# This file, build/pkgs/_prereq/distros/conda.txt, contains names of
+# conda packages needed for installation of Sage from source.
+#
+# In addition, the files build/pkgs/SPKG/distros/conda.txt contain
+# the names of packages that provide the equivalent of SPKG.
+#
+# One package per line. No need to escape special characters.
+# Everything on a line after a # character is ignored.
+#
+compilers<=1.6.0 # 1.7 pulls in c-compiler v.16
make
m4
perl
diff --git a/build/pkgs/_prereq/distros/cygwin.txt b/build/pkgs/_prereq/distros/cygwin.txt
index 2bf3164005b..7a05e1aaa54 100644
--- a/build/pkgs/_prereq/distros/cygwin.txt
+++ b/build/pkgs/_prereq/distros/cygwin.txt
@@ -1,19 +1,18 @@
-# This file, build/pkgs/cygwin.txt, contains name Cygwin packages
-# needed for installation of Sage from source.
+# This file, build/pkgs/_prereq/distros/cygwin.txt, contains names of
+# Cygwin packages needed for installation of Sage from source.
#
-# In addition, the files build/pkgs/SPKG/cygwin.txt contain the names
-# of packages that provide the equivalent of SPKG.
-#
-# See build/bin/sage-spkg, where this information is processed
-# for use in "sage -info SPKG".
+# In addition, the files build/pkgs/SPKG/distros/cygwin.txt contain
+# the names of packages that provide the equivalent of SPKG.
#
+# One package per line. No need to escape special characters.
# Everything on a line after a # character is ignored.
#
binutils
make
m4
# a system python is needed for downloading the sage packages, https://github.com/sagemath/sage/issues/29090
-python39-urllib3 python39
+python39-urllib3
+python39
perl
perl-ExtUtils-MakeMaker
tar
diff --git a/build/pkgs/_prereq/distros/debian.txt b/build/pkgs/_prereq/distros/debian.txt
index 50be6ac7e0b..785739528b4 100644
--- a/build/pkgs/_prereq/distros/debian.txt
+++ b/build/pkgs/_prereq/distros/debian.txt
@@ -1,16 +1,12 @@
-# This file, build/pkgs/debian.txt, contains names of Debian/Ubuntu packages
-# needed for installation of Sage from source.
+# This file, build/pkgs/_prereq/distros/debian.txt, contains names of
+# Debian/Ubuntu/... packages needed for installation of Sage from source.
#
-# In addition, the files build/pkgs/SPKG/debian.txt contain the names
-# of packages that provide the equivalent of SPKG.
-#
-# If distinctions between different distributions need to be made,
-# files named debian....txt or ubuntu.....txt can be used.
-#
-# See build/bin/sage-spkg, where this information is processed
-# for use in "sage -info SPKG".
+# In addition, the files build/pkgs/SPKG/distros/debian.txt contain
+# the names of packages that provide the equivalent of SPKG.
#
+# One package per line. No need to escape special characters.
# Everything on a line after a # character is ignored.
+#
binutils
make
m4
diff --git a/build/pkgs/_prereq/distros/fedora.txt b/build/pkgs/_prereq/distros/fedora.txt
index b35d7f64faf..2716e7eb0cd 100644
--- a/build/pkgs/_prereq/distros/fedora.txt
+++ b/build/pkgs/_prereq/distros/fedora.txt
@@ -1,15 +1,11 @@
-# This file, build/pkgs/fedora.txt, contains names of Fedora/Redhat/CentOS packages
-# needed for installation of Sage from source.
+# This file, build/pkgs/_prereq/distros/fedora.txt, contains names of
+# Fedora/Redhat/CentOS/AlmaLinux packages needed for installation
+# of Sage from source.
#
-# In addition, the files build/pkgs/SPKG/fedora.txt contain the names
-# of packages that provide the equivalent of SPKG.
-#
-# If distinctions between different distributions need to be made,
-# files named fedora....txt, redhat...txt, or centos....txt can be used.
-#
-# See build/bin/sage-spkg, where this information is processed
-# for use in "sage -info SPKG".
+# In addition, the files build/pkgs/SPKG/distros/fedora.txt contain
+# the names of packages that provide the equivalent of SPKG.
#
+# One package per line. No need to escape special characters.
# Everything on a line after a # character is ignored.
#
binutils
diff --git a/build/pkgs/_prereq/distros/freebsd.txt b/build/pkgs/_prereq/distros/freebsd.txt
index cc708ccfb2b..f9a4937520a 100644
--- a/build/pkgs/_prereq/distros/freebsd.txt
+++ b/build/pkgs/_prereq/distros/freebsd.txt
@@ -1,5 +1,5 @@
-# This file, build/pkgs/freebsd.txt, contains names of FreeBSD packages
-# needed for installation of Sage from source.
+# This file, build/pkgs/_prereq/distros/freebsd.txt, contains names of
+# FreeBSD packages needed for installation of Sage from source.
#
# In addition, the files build/pkgs/SPKG/distros/freebsd.txt contain the
# names of packages that provide the equivalent of SPKG.
@@ -8,10 +8,9 @@
# $ cd /usr/ports/math/sage
# $ sudo make install-missing-packages
#
-# See build/bin/sage-spkg, where this information is processed
-# for use in "sage -info SPKG".
-#
+# One package per line. No need to escape special characters.
# Everything on a line after a # character is ignored.
+#
gmake
automake
bash
diff --git a/build/pkgs/_prereq/distros/gentoo.txt b/build/pkgs/_prereq/distros/gentoo.txt
index 1e26c46cacc..455991e8a99 100644
--- a/build/pkgs/_prereq/distros/gentoo.txt
+++ b/build/pkgs/_prereq/distros/gentoo.txt
@@ -1,3 +1,12 @@
+# This file, build/pkgs/_prereq/distros/gentoo.txt, contains names of
+# Gentoo packages needed for installation of Sage from source.
+#
+# In addition, the files build/pkgs/SPKG/distros/gentoo.txt contain
+# the names of packages that provide the equivalent of SPKG.
+#
+# One package per line. No need to escape special characters.
+# Everything on a line after a # character is ignored.
+#
sys-devel/binutils
sys-libs/binutils-libs
sys-devel/make
diff --git a/build/pkgs/_prereq/distros/homebrew.txt b/build/pkgs/_prereq/distros/homebrew.txt
index 863c22a6bee..2a85c39abfc 100644
--- a/build/pkgs/_prereq/distros/homebrew.txt
+++ b/build/pkgs/_prereq/distros/homebrew.txt
@@ -1,12 +1,11 @@
-# This file, build/pkgs/homebrew.txt, contains names of homebrew packages
-# needed for installation of Sage from source (in addition to XCode).
+# This file, build/pkgs/_prereq/distros/homebrew.txt, contains names of
+# Homebrew packages needed for installation of Sage from source.
#
-# In addition, the files build/pkgs/SPKG/homebrew.txt contain the names
-# of packages that provide the equivalent of SPKG.
-#
-# See build/bin/sage-spkg, where this information is processed
-# for use in "sage -info SPKG".
+# In addition, the files build/pkgs/SPKG/distros/homebrew.txt contain
+# the names of packages that provide the equivalent of SPKG.
#
+# One package per line. No need to escape special characters.
# Everything on a line after a # character is ignored.
+#
# No packages needed
diff --git a/build/pkgs/_prereq/distros/macports.txt b/build/pkgs/_prereq/distros/macports.txt
new file mode 100644
index 00000000000..e887cd91e80
--- /dev/null
+++ b/build/pkgs/_prereq/distros/macports.txt
@@ -0,0 +1,12 @@
+# This file, build/pkgs/_prereq/distros/macports.txt, contains names of macports packages
+# needed for installation of Sage from source (in addition to XCode).
+#
+# In addition, the files build/pkgs/SPKG/distros/macports.txt contain the names
+# of packages that provide the equivalent of SPKG.
+#
+# See build/bin/sage-spkg, where this information is processed
+# for use in "sage -info SPKG".
+#
+# Everything on a line after a # character is ignored.
+
+# No packages needed
diff --git a/build/pkgs/_prereq/distros/nix.txt b/build/pkgs/_prereq/distros/nix.txt
index 01e5ed4e959..523fe272f7c 100644
--- a/build/pkgs/_prereq/distros/nix.txt
+++ b/build/pkgs/_prereq/distros/nix.txt
@@ -1,16 +1,12 @@
-# This file, build/pkgs/debian.txt, contains names of Debian/Ubuntu packages
-# needed for installation of Sage from source.
+# This file, build/pkgs/_prereq/distros/nix.txt, contains names of
+# nix packages needed for installation of Sage from source.
#
-# In addition, the files build/pkgs/SPKG/debian.txt contain the names
-# of packages that provide the equivalent of SPKG.
-#
-# If distinctions between different distributions need to be made,
-# files named debian....txt or ubuntu.....txt can be used.
-#
-# See build/bin/sage-spkg, where this information is processed
-# for use in "sage -info SPKG".
+# In addition, the files build/pkgs/SPKG/distros/nix.txt contain
+# the names of packages that provide the equivalent of SPKG.
#
+# One package per line. No need to escape special characters.
# Everything on a line after a # character is ignored.
+#
binutils
gnumake
gnum4
diff --git a/build/pkgs/_prereq/distros/opensuse.txt b/build/pkgs/_prereq/distros/opensuse.txt
index 6f7a11fea47..56f77da9bcf 100644
--- a/build/pkgs/_prereq/distros/opensuse.txt
+++ b/build/pkgs/_prereq/distros/opensuse.txt
@@ -1,13 +1,12 @@
-# This file, build/pkgs/opensuse.txt, contains names of OpenSuse packages
-# needed for installation of Sage from source.
+# This file, build/pkgs/_prereq/distros/opensuse.txt, contains names of
+# OpenSuse packages needed for installation of Sage from source.
#
-# In addition, the files build/pkgs/SPKG/opensuse.txt contain the names
-# of packages that provide the equivalent of SPKG.
-#
-# See build/bin/sage-spkg, where this information is processed
-# for use in "sage -info SPKG".
+# In addition, the files build/pkgs/SPKG/distros/opensuse.txt contain
+# the names of packages that provide the equivalent of SPKG.
#
+# One package per line. No need to escape special characters.
# Everything on a line after a # character is ignored.
+#
binutils
make
m4
diff --git a/build/pkgs/_prereq/distros/slackware.txt b/build/pkgs/_prereq/distros/slackware.txt
index 4c957e45264..117762dcd00 100644
--- a/build/pkgs/_prereq/distros/slackware.txt
+++ b/build/pkgs/_prereq/distros/slackware.txt
@@ -1,11 +1,26 @@
+# This file, build/pkgs/_prereq/distros/slackware.txt, contains names of
+# Slackware packages needed for installation of Sage from source.
+#
+# In addition, the files build/pkgs/SPKG/distros/slackware.txt contain
+# the names of packages that provide the equivalent of SPKG.
+#
+# One package per line. No need to escape special characters.
+# Everything on a line after a # character is ignored.
+#
binutils
make
-guile gc libffi # dependencies of make
-"gcc-[0-9]" # So that slackpkg pattern matching does not pull in all gcc-* packages
+# dependencies of make
+guile
+gc
+libffi
+gcc-[0-9] # So that slackpkg pattern matching does not pull in all gcc-* packages
gcc-11 # on slackware-current
gcc-g++
gcc-g++-11 # on slackware-current
-libmpc glibc kernel-headers # dependencies of gcc
+# dependencies of gcc
+libmpc
+glibc
+kernel-headers
perl
m4
bc
diff --git a/build/pkgs/_prereq/distros/void.txt b/build/pkgs/_prereq/distros/void.txt
index 552b5a415f2..d5c2143c56c 100644
--- a/build/pkgs/_prereq/distros/void.txt
+++ b/build/pkgs/_prereq/distros/void.txt
@@ -1,3 +1,12 @@
+# This file, build/pkgs/_prereq/distros/void.txt, contains names of
+# Void Linux packages needed for installation of Sage from source.
+#
+# In addition, the files build/pkgs/SPKG/distros/void.txt contain
+# the names of packages that provide the equivalent of SPKG.
+#
+# One package per line. No need to escape special characters.
+# Everything on a line after a # character is ignored.
+#
bc
binutils
gcc
diff --git a/build/pkgs/_recommended/dependencies b/build/pkgs/_recommended/dependencies
index f4baa9b1fb2..6e36fc6d390 100644
--- a/build/pkgs/_recommended/dependencies
+++ b/build/pkgs/_recommended/dependencies
@@ -1 +1 @@
-pandoc ffmpeg imagemagick texlive git libjpeg
+pandoc ffmpeg imagemagick git libjpeg texlive texlive_luatex free_fonts xindy
diff --git a/build/pkgs/_sagemath/distros/arch.txt b/build/pkgs/_sagemath/distros/arch.txt
index 825a91411b0..b58e3f244a7 100644
--- a/build/pkgs/_sagemath/distros/arch.txt
+++ b/build/pkgs/_sagemath/distros/arch.txt
@@ -1 +1,2 @@
-sagemath sagemath-doc
+sagemath
+sagemath-doc
diff --git a/build/pkgs/barvinok/distros/opensuse.txt b/build/pkgs/barvinok/distros/opensuse.txt
index b3369e09db7..65092b1978a 100644
--- a/build/pkgs/barvinok/distros/opensuse.txt
+++ b/build/pkgs/barvinok/distros/opensuse.txt
@@ -1,2 +1,2 @@
barvinok
-"pkgconfig(barvinok)"
+pkgconfig(barvinok)
diff --git a/build/pkgs/boost_cropped/spkg-legacy-uninstall b/build/pkgs/boost_cropped/spkg-legacy-uninstall
deleted file mode 100755
index ef170323b6a..00000000000
--- a/build/pkgs/boost_cropped/spkg-legacy-uninstall
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /usr/bin/env bash
-rm -rf "${SAGE_LOCAL}"/include/boost
diff --git a/build/pkgs/brial/spkg-legacy-uninstall b/build/pkgs/brial/spkg-legacy-uninstall
deleted file mode 100755
index 59e01958685..00000000000
--- a/build/pkgs/brial/spkg-legacy-uninstall
+++ /dev/null
@@ -1,5 +0,0 @@
-#! /usr/bin/env bash
-echo "Cleaning out old PolyBoRi and BRiAl installations"
-rm -f "$SAGE_LOCAL"/lib/lib{polybori,brial}*
-rm -rf "$SAGE_LOCAL"/include/polybori*
-rm -rf "$SAGE_LOCAL"/share/polybori
diff --git a/build/pkgs/bzip2/distros/cygwin.txt b/build/pkgs/bzip2/distros/cygwin.txt
index 8e127a3d331..8ef7f4d0734 100644
--- a/build/pkgs/bzip2/distros/cygwin.txt
+++ b/build/pkgs/bzip2/distros/cygwin.txt
@@ -1 +1,2 @@
-bzip2 libbz2-devel
+bzip2
+libbz2-devel
diff --git a/build/pkgs/bzip2/distros/fedora.txt b/build/pkgs/bzip2/distros/fedora.txt
index f62dee917bb..13c12f2a5f6 100644
--- a/build/pkgs/bzip2/distros/fedora.txt
+++ b/build/pkgs/bzip2/distros/fedora.txt
@@ -1 +1,2 @@
-bzip2 bzip2-devel
+bzip2
+bzip2-devel
diff --git a/build/pkgs/bzip2/distros/opensuse.txt b/build/pkgs/bzip2/distros/opensuse.txt
index ad77a92d4bb..ff839c0de00 100644
--- a/build/pkgs/bzip2/distros/opensuse.txt
+++ b/build/pkgs/bzip2/distros/opensuse.txt
@@ -1,3 +1,3 @@
# spkg-configure checks for both the program and the library
bzip2
-"pkgconfig(bzip2)"
+pkgconfig(bzip2)
diff --git a/build/pkgs/calver/dependencies b/build/pkgs/calver/dependencies
index 47296a7bace..644ad35f773 100644
--- a/build/pkgs/calver/dependencies
+++ b/build/pkgs/calver/dependencies
@@ -1,4 +1,4 @@
- | $(PYTHON_TOOLCHAIN) $(PYTHON)
+ | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/cbc/distros/fedora.txt b/build/pkgs/cbc/distros/fedora.txt
index 3e1af7ad66b..d63f4439b2a 100644
--- a/build/pkgs/cbc/distros/fedora.txt
+++ b/build/pkgs/cbc/distros/fedora.txt
@@ -1 +1,2 @@
-coin-or-Cbc coin-or-Cbc-devel
+coin-or-Cbc
+coin-or-Cbc-devel
diff --git a/build/pkgs/cddlib/distros/cygwin.txt b/build/pkgs/cddlib/distros/cygwin.txt
index f9eaae4c7ad..d406d903210 100644
--- a/build/pkgs/cddlib/distros/cygwin.txt
+++ b/build/pkgs/cddlib/distros/cygwin.txt
@@ -1 +1,2 @@
-cddlib-devel cddlib-tools
+cddlib-devel
+cddlib-tools
diff --git a/build/pkgs/cddlib/distros/opensuse.txt b/build/pkgs/cddlib/distros/opensuse.txt
index ffb93647443..0d299e7ad0e 100644
--- a/build/pkgs/cddlib/distros/opensuse.txt
+++ b/build/pkgs/cddlib/distros/opensuse.txt
@@ -1,2 +1,2 @@
cddlib-tools
-"pkgconfig(cddlib)"
+pkgconfig(cddlib)
diff --git a/build/pkgs/cliquer/distros/fedora.txt b/build/pkgs/cliquer/distros/fedora.txt
index 4dadef53faa..718f9f6b2cf 100644
--- a/build/pkgs/cliquer/distros/fedora.txt
+++ b/build/pkgs/cliquer/distros/fedora.txt
@@ -1 +1,2 @@
-cliquer cliquer-devel
+cliquer
+cliquer-devel
diff --git a/build/pkgs/cmake/distros/macports.txt b/build/pkgs/cmake/distros/macports.txt
index a3ea3e4380f..de0e65cf914 100644
--- a/build/pkgs/cmake/distros/macports.txt
+++ b/build/pkgs/cmake/distros/macports.txt
@@ -1 +1,2 @@
-cmake
+# Broken as of 2022-05-01
+#cmake
diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini
index deadbf67dc3..a10d1db6236 100644
--- a/build/pkgs/configure/checksums.ini
+++ b/build/pkgs/configure/checksums.ini
@@ -1,4 +1,4 @@
tarball=configure-VERSION.tar.gz
-sha1=7f2fe8137f5998559f8d3a0a7f965adf6d5ebc78
-md5=586738771174a2d26d29ce7ba571a95d
-cksum=1156937644
+sha1=05115739db242cb5a48ae17f97d06b179fc70334
+md5=adc8208885e6be527b089b682079c464
+cksum=3321256447
diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt
index 1596e721179..fbcbbd235f8 100644
--- a/build/pkgs/configure/package-version.txt
+++ b/build/pkgs/configure/package-version.txt
@@ -1 +1 @@
-2395f7bb45fd7da537a953055df5e0a70dd96c6a
+e95536ccbad199de456e804968a775f2744e4bff
diff --git a/build/pkgs/coxeter3/distros/fedora.txt b/build/pkgs/coxeter3/distros/fedora.txt
index 3cfeb2f9fa0..0c6fb8a3e95 100644
--- a/build/pkgs/coxeter3/distros/fedora.txt
+++ b/build/pkgs/coxeter3/distros/fedora.txt
@@ -1 +1,3 @@
-coxeter coxeter-devel coxeter-tools
+coxeter
+coxeter-devel
+coxeter-tools
diff --git a/build/pkgs/cunningham_tables/checksums.ini b/build/pkgs/cunningham_tables/checksums.ini
index d6de22c0850..360d9b647b7 100644
--- a/build/pkgs/cunningham_tables/checksums.ini
+++ b/build/pkgs/cunningham_tables/checksums.ini
@@ -2,4 +2,4 @@ tarball=cunningham_tables-VERSION.tar.gz
sha1=8bea1a113d85bb9c37d8f213dd19525d9d026f22
md5=e71b32f12e9a46c1c86e275e8441a06b
cksum=1990403877
-upstream_url=http://users.ox.ac.uk/~coml0531/sage/cunningham_tables-1.0.tar.gz
+upstream_url=http://users.ox.ac.uk/~coml0531/sage/cunningham_tables-VERSION.tar.gz
diff --git a/build/pkgs/curl/distros/cygwin.txt b/build/pkgs/curl/distros/cygwin.txt
index 7bcb9889a4d..26bfd4d1186 100644
--- a/build/pkgs/curl/distros/cygwin.txt
+++ b/build/pkgs/curl/distros/cygwin.txt
@@ -1 +1,2 @@
-libcurl-devel curl
+libcurl-devel
+curl
diff --git a/build/pkgs/curl/distros/fedora.txt b/build/pkgs/curl/distros/fedora.txt
index 7bcb9889a4d..26bfd4d1186 100644
--- a/build/pkgs/curl/distros/fedora.txt
+++ b/build/pkgs/curl/distros/fedora.txt
@@ -1 +1,2 @@
-libcurl-devel curl
+libcurl-devel
+curl
diff --git a/build/pkgs/curl/distros/macports.txt b/build/pkgs/curl/distros/macports.txt
index 13368f82902..284d14f8d01 100644
--- a/build/pkgs/curl/distros/macports.txt
+++ b/build/pkgs/curl/distros/macports.txt
@@ -1 +1,2 @@
-curl
+# Broken as of 2022-05-01
+#curl
diff --git a/build/pkgs/curl/distros/opensuse.txt b/build/pkgs/curl/distros/opensuse.txt
index ffd4f36dc86..a0ac40946fa 100644
--- a/build/pkgs/curl/distros/opensuse.txt
+++ b/build/pkgs/curl/distros/opensuse.txt
@@ -1,2 +1,2 @@
curl
-"pkgconfig(libcurl)"
+pkgconfig(libcurl)
diff --git a/build/pkgs/cvxopt/spkg-install.in b/build/pkgs/cvxopt/spkg-install.in
index 0081c40f819..8179125fc9a 100644
--- a/build/pkgs/cvxopt/spkg-install.in
+++ b/build/pkgs/cvxopt/spkg-install.in
@@ -82,10 +82,6 @@ sdh_pip_install .
if [ "x$SAGE_SPKG_INSTALL_DOCS" = xyes ] ; then
cd doc
- # checking to see if there is previously installed documentation.
- if [ -d $SAGE_LOCAL/share/doc/cvxopt/html ] ; then
- rm -rf $SAGE_LOCAL/share/doc/cvxopt/html
- fi
mkdir -p "${SAGE_DESTDIR}${SAGE_LOCAL}/share/doc/cvxopt/html"
cp -r html/* "${SAGE_DESTDIR}${SAGE_LOCAL}/share/doc/cvxopt/html/"
fi
diff --git a/build/pkgs/deprecation/SPKG.rst b/build/pkgs/deprecation/SPKG.rst
deleted file mode 100644
index 8aa6712f42b..00000000000
--- a/build/pkgs/deprecation/SPKG.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-deprecation: A library to handle automated deprecations
-=======================================================
-
-Description
------------
-
-A library to handle automated deprecations
-
-License
--------
-
-Apache 2
-
-Upstream Contact
-----------------
-
-https://pypi.org/project/deprecation/
-
diff --git a/build/pkgs/deprecation/checksums.ini b/build/pkgs/deprecation/checksums.ini
deleted file mode 100644
index b2e6c9d2964..00000000000
--- a/build/pkgs/deprecation/checksums.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-tarball=deprecation-VERSION.tar.gz
-sha1=34847e937ac203cfd0d8ea0a0f2579204cdb8fe4
-md5=6b79c6572fb241e3cecbbd7d539bb66b
-cksum=1034714094
-upstream_url=https://pypi.io/packages/source/d/deprecation/deprecation-VERSION.tar.gz
diff --git a/build/pkgs/deprecation/dependencies b/build/pkgs/deprecation/dependencies
deleted file mode 100644
index 47296a7bace..00000000000
--- a/build/pkgs/deprecation/dependencies
+++ /dev/null
@@ -1,4 +0,0 @@
- | $(PYTHON_TOOLCHAIN) $(PYTHON)
-
-----------
-All lines of this file are ignored except the first.
diff --git a/build/pkgs/deprecation/distros/conda.txt b/build/pkgs/deprecation/distros/conda.txt
deleted file mode 100644
index 4ba9b7530ed..00000000000
--- a/build/pkgs/deprecation/distros/conda.txt
+++ /dev/null
@@ -1 +0,0 @@
-deprecation
diff --git a/build/pkgs/deprecation/install-requires.txt b/build/pkgs/deprecation/install-requires.txt
deleted file mode 100644
index 4ba9b7530ed..00000000000
--- a/build/pkgs/deprecation/install-requires.txt
+++ /dev/null
@@ -1 +0,0 @@
-deprecation
diff --git a/build/pkgs/deprecation/package-version.txt b/build/pkgs/deprecation/package-version.txt
deleted file mode 100644
index 7ec1d6db408..00000000000
--- a/build/pkgs/deprecation/package-version.txt
+++ /dev/null
@@ -1 +0,0 @@
-2.1.0
diff --git a/build/pkgs/deprecation/spkg-install.in b/build/pkgs/deprecation/spkg-install.in
deleted file mode 100644
index 37ac1a53437..00000000000
--- a/build/pkgs/deprecation/spkg-install.in
+++ /dev/null
@@ -1,2 +0,0 @@
-cd src
-sdh_pip_install .
diff --git a/build/pkgs/deprecation/type b/build/pkgs/deprecation/type
deleted file mode 100644
index a6a7b9cd726..00000000000
--- a/build/pkgs/deprecation/type
+++ /dev/null
@@ -1 +0,0 @@
-standard
diff --git a/build/pkgs/distlib/SPKG.rst b/build/pkgs/distlib/SPKG.rst
index a4496c0427a..e59b0b7292c 100644
--- a/build/pkgs/distlib/SPKG.rst
+++ b/build/pkgs/distlib/SPKG.rst
@@ -9,7 +9,7 @@ Distribution utilities
License
-------
-Python license
+PSF-2.0
Upstream Contact
----------------
diff --git a/build/pkgs/distlib/checksums.ini b/build/pkgs/distlib/checksums.ini
index be255ceca11..b1a05ffc295 100644
--- a/build/pkgs/distlib/checksums.ini
+++ b/build/pkgs/distlib/checksums.ini
@@ -1,5 +1,5 @@
-tarball=distlib-VERSION.tar.gz
-sha1=5c99f8bd1cc58c387a8d22afa632f81c6fec9993
-md5=44e4357e35bbd77fdf1b81e174e34f20
-cksum=3690000669
-upstream_url=https://pypi.io/packages/source/d/distlib/distlib-VERSION.tar.gz
+tarball=distlib-VERSION-py2.py3-none-any.whl
+sha1=97ea3bb71040f0348eaea272ec17fefea5806e87
+md5=cf336842ba81996e554ae4eb2cd76d5d
+cksum=3779817199
+upstream_url=https://pypi.io/packages/py2.py3/d/distlib/distlib-VERSION-py2.py3-none-any.whl
diff --git a/build/pkgs/distlib/dependencies b/build/pkgs/distlib/dependencies
index 47296a7bace..644ad35f773 100644
--- a/build/pkgs/distlib/dependencies
+++ b/build/pkgs/distlib/dependencies
@@ -1,4 +1,4 @@
- | $(PYTHON_TOOLCHAIN) $(PYTHON)
+ | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/distlib/package-version.txt b/build/pkgs/distlib/package-version.txt
index 0f82685331e..66784322096 100644
--- a/build/pkgs/distlib/package-version.txt
+++ b/build/pkgs/distlib/package-version.txt
@@ -1 +1 @@
-0.3.7
+0.3.8
diff --git a/build/pkgs/distlib/spkg-install.in b/build/pkgs/distlib/spkg-install.in
deleted file mode 100644
index 37ac1a53437..00000000000
--- a/build/pkgs/distlib/spkg-install.in
+++ /dev/null
@@ -1,2 +0,0 @@
-cd src
-sdh_pip_install .
diff --git a/build/pkgs/e_antic/checksums.ini b/build/pkgs/e_antic/checksums.ini
index d24ae72e6f4..fe7fa852b76 100644
--- a/build/pkgs/e_antic/checksums.ini
+++ b/build/pkgs/e_antic/checksums.ini
@@ -1,5 +1,5 @@
tarball=e-antic-VERSION.tar.gz
-sha1=4f551cf2ab58201fb2137ae994cb670c6fa8b154
-md5=6c6f38408994f7d79f814bbad8183fcb
-cksum=2487959662
+sha1=587052e189f9a7a145ac3144e6b7f11fca54b1ff
+md5=0b54042461b28c4b45239480af062546
+cksum=589498373
upstream_url=https://github.com/flatsurf/e-antic/releases/download/VERSION/e-antic-VERSION.tar.gz
diff --git a/build/pkgs/e_antic/package-version.txt b/build/pkgs/e_antic/package-version.txt
index f0bb29e7638..227cea21564 100644
--- a/build/pkgs/e_antic/package-version.txt
+++ b/build/pkgs/e_antic/package-version.txt
@@ -1 +1 @@
-1.3.0
+2.0.0
diff --git a/build/pkgs/ecl/spkg-legacy-uninstall b/build/pkgs/ecl/spkg-legacy-uninstall
deleted file mode 100755
index 375d99ebcf1..00000000000
--- a/build/pkgs/ecl/spkg-legacy-uninstall
+++ /dev/null
@@ -1,6 +0,0 @@
-#! /usr/bin/env bash
-rm -f "$SAGE_LOCAL"/bin/ecl
-rm -rf "$SAGE_LOCAL"/include/ecl
-rm -rf "$SAGE_LOCAL"/lib/ecl
-rm -rf "$SAGE_LOCAL"/lib/ecl-*
-rm -rf "$SAGE_LOCAL"/lib/libecl.*
diff --git a/build/pkgs/eclib/checksums.ini b/build/pkgs/eclib/checksums.ini
index 266e6bfac1c..b6a7efd95aa 100644
--- a/build/pkgs/eclib/checksums.ini
+++ b/build/pkgs/eclib/checksums.ini
@@ -1,5 +1,5 @@
tarball=eclib-VERSION.tar.bz2
-sha1=bd49acf96c4e7246c8ca3e5d188ae1b03a3aeff3
-md5=42721f2f1343c49dc774763a57a85ca6
-cksum=3624641360
+sha1=3028ac95e1b76699f5f9e871ac706cda363ab842
+md5=c96e1bb39a50552aeac6675b907709b8
+cksum=2027019032
upstream_url=https://github.com/JohnCremona/eclib/releases/download/vVERSION/eclib-VERSION.tar.bz2
diff --git a/build/pkgs/eclib/distros/fedora.txt b/build/pkgs/eclib/distros/fedora.txt
index 7861ae6de2b..2bcdd8cb9a5 100644
--- a/build/pkgs/eclib/distros/fedora.txt
+++ b/build/pkgs/eclib/distros/fedora.txt
@@ -1 +1,2 @@
-eclib eclib-devel
+eclib
+eclib-devel
diff --git a/build/pkgs/eclib/package-version.txt b/build/pkgs/eclib/package-version.txt
index b5f339e560b..190b92f716b 100644
--- a/build/pkgs/eclib/package-version.txt
+++ b/build/pkgs/eclib/package-version.txt
@@ -1 +1 @@
-20230424
+20231212
diff --git a/build/pkgs/eclib/spkg-configure.m4 b/build/pkgs/eclib/spkg-configure.m4
index c98781201cc..133b44bfdc1 100644
--- a/build/pkgs/eclib/spkg-configure.m4
+++ b/build/pkgs/eclib/spkg-configure.m4
@@ -1,12 +1,12 @@
SAGE_SPKG_CONFIGURE([eclib], [
SAGE_SPKG_DEPCHECK([ntl pari flint], [
- dnl Trac #31443, #34029: use existing eclib only if the version reported by pkg-config is correct
- m4_pushdef([SAGE_ECLIB_VER],["20230424"])
+ dnl use existing eclib only if the version reported by pkg-config is recent enough
+ m4_pushdef([SAGE_ECLIB_VER],["20231212"])
PKG_CHECK_MODULES([ECLIB], [eclib = SAGE_ECLIB_VER], [
AC_CACHE_CHECK([for mwrank version == SAGE_ECLIB_VER], [ac_cv_path_MWRANK], [
AC_PATH_PROGS_FEATURE_CHECK([MWRANK], [mwrank], [
mwrank_version=`$ac_path_MWRANK -V 2>&1`
- AX_COMPARE_VERSION([$mwrank_version], [eq], [SAGE_ECLIB_VER], [
+ AX_COMPARE_VERSION([$mwrank_version], [ge], [SAGE_ECLIB_VER], [
ac_cv_path_MWRANK="$ac_path_MWRANK"
])
])
diff --git a/build/pkgs/eclib/spkg-install.in b/build/pkgs/eclib/spkg-install.in
index 2a83bdb5235..9618e8f5d19 100644
--- a/build/pkgs/eclib/spkg-install.in
+++ b/build/pkgs/eclib/spkg-install.in
@@ -3,35 +3,11 @@ CXXFLAGS="$CXXFLAGS_O3_NON_NATIVE"
export CFLAGS CXXFLAGS
-
-echo "Deleting old versions of eclib libraries, which"
-echo "would interfere with new builds..."
-# Delete any pre-autotools libraries:
-rm -f "$SAGE_LOCAL"/lib/lib{curvesntl,g0nntl,jcntl,rankntl,mwrank}.*
-# Delete autotools libraries:
-rm -f "$SAGE_LOCAL"/lib/lib{e,j}c.*
-echo "Deleting old include directory..."
-rm -rf "$SAGE_LOCAL"/include/eclib/
-
-
cd src/
-#############################################################
-# the workaround with SAGE_CONFIGURE_FLINT_ECLIB
-# introduced by #28401 may be removed once
-# github.com/JohnCremona/eclib/pull/57 is in Sage
-#############################################################
-if test x$SAGE_FLINT_PREFIX = x; then
- SAGE_CONFIGURE_FLINT_ECLIB="--with-flint"
-else
- SAGE_CONFIGURE_FLINT_ECLIB="--with-flint=$SAGE_FLINT_PREFIX"
-fi
-
-echo $SAGE_CONFIGURE_FLINT_ECLIB
-
sdh_configure $SAGE_CONFIGURE_NTL \
$SAGE_CONFIGURE_PARI \
- $SAGE_CONFIGURE_FLINT_ECLIB \
+ --with-flint=$SAGE_FLINT_PREFIX \
--with-boost="no" \
--disable-allprogs
sdh_make
diff --git a/build/pkgs/ecm/distros/fedora.txt b/build/pkgs/ecm/distros/fedora.txt
index 45e62aa8032..0625c82b8b9 100644
--- a/build/pkgs/ecm/distros/fedora.txt
+++ b/build/pkgs/ecm/distros/fedora.txt
@@ -1 +1,2 @@
-gmp-ecm gmp-ecm-devel
+gmp-ecm
+gmp-ecm-devel
diff --git a/build/pkgs/ecm/spkg-install.in b/build/pkgs/ecm/spkg-install.in
index edc6bb2df5f..03c6c109d7d 100644
--- a/build/pkgs/ecm/spkg-install.in
+++ b/build/pkgs/ecm/spkg-install.in
@@ -232,17 +232,6 @@ sdh_configure $SAGE_CONFIGURE_GMP $ECM_CONFIGURE
sdh_make
-###############################################################################
-# Remove old executable/header/libraries/manpage:
-###############################################################################
-
-echo
-echo "Build succeeded. Now removing old binary, header file, manual page and libraries..."
-rm -f "$SAGE_LOCAL"/bin/ecm
-rm -f "$SAGE_LOCAL"/lib/libecm.*
-rm -f "$SAGE_LOCAL"/include/ecm.h
-rm -f "$SAGE_LOCAL"/share/man/man1/ecm.1
-
###############################################################################
# Now install ECM:
###############################################################################
diff --git a/build/pkgs/editables/dependencies b/build/pkgs/editables/dependencies
index 47296a7bace..e0e94942dba 100644
--- a/build/pkgs/editables/dependencies
+++ b/build/pkgs/editables/dependencies
@@ -1,4 +1,4 @@
- | $(PYTHON_TOOLCHAIN) $(PYTHON)
+ | flit_core $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/fflas_ffpack/distros/opensuse.txt b/build/pkgs/fflas_ffpack/distros/opensuse.txt
index 2dda5369b8d..cf55f69f450 100644
--- a/build/pkgs/fflas_ffpack/distros/opensuse.txt
+++ b/build/pkgs/fflas_ffpack/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(fflas-ffpack)"
+pkgconfig(fflas-ffpack)
diff --git a/build/pkgs/filelock/checksums.ini b/build/pkgs/filelock/checksums.ini
index 0d412bb2ca3..6c597d2d7aa 100644
--- a/build/pkgs/filelock/checksums.ini
+++ b/build/pkgs/filelock/checksums.ini
@@ -1,5 +1,5 @@
tarball=filelock-VERSION-py3-none-any.whl
-sha1=74f5368865bf05ddc5b69949e4547ad25c078fc1
-md5=63b0f117cb65ef531ffafb566170661e
-cksum=1046951951
+sha1=f1fa92751023660a10b248f8559d09f3c461403f
+md5=d0af0f1a2ee56c24f630ece278cb062f
+cksum=3749691502
upstream_url=https://pypi.io/packages/py3/f/filelock/filelock-VERSION-py3-none-any.whl
diff --git a/build/pkgs/filelock/dependencies b/build/pkgs/filelock/dependencies
index 47296a7bace..644ad35f773 100644
--- a/build/pkgs/filelock/dependencies
+++ b/build/pkgs/filelock/dependencies
@@ -1,4 +1,4 @@
- | $(PYTHON_TOOLCHAIN) $(PYTHON)
+ | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/filelock/package-version.txt b/build/pkgs/filelock/package-version.txt
index 871f80a34be..c10780c628a 100644
--- a/build/pkgs/filelock/package-version.txt
+++ b/build/pkgs/filelock/package-version.txt
@@ -1 +1 @@
-3.12.3
+3.13.1
diff --git a/build/pkgs/flint/distros/fedora.txt b/build/pkgs/flint/distros/fedora.txt
index 8df1db2cd08..12eb8937aea 100644
--- a/build/pkgs/flint/distros/fedora.txt
+++ b/build/pkgs/flint/distros/fedora.txt
@@ -1 +1,2 @@
-flint flint-devel
+flint
+flint-devel
diff --git a/build/pkgs/fplll/distros/fedora.txt b/build/pkgs/fplll/distros/fedora.txt
index ccf2e14dfee..29c3b897ae1 100644
--- a/build/pkgs/fplll/distros/fedora.txt
+++ b/build/pkgs/fplll/distros/fedora.txt
@@ -1 +1,2 @@
-libfplll libfplll-devel
+libfplll
+libfplll-devel
diff --git a/build/pkgs/fplll/distros/opensuse.txt b/build/pkgs/fplll/distros/opensuse.txt
index ee87c038706..2589161f43c 100644
--- a/build/pkgs/fplll/distros/opensuse.txt
+++ b/build/pkgs/fplll/distros/opensuse.txt
@@ -1,3 +1,3 @@
-"pkgconfig(fplll)"
+pkgconfig(fplll)
fplll-devel
fplll
diff --git a/build/pkgs/fplll/spkg-install.in b/build/pkgs/fplll/spkg-install.in
index 68c0cb70ad2..d898db82687 100644
--- a/build/pkgs/fplll/spkg-install.in
+++ b/build/pkgs/fplll/spkg-install.in
@@ -22,7 +22,3 @@ export CXX="$CXX"
sdh_configure $CONFIGUREFLAGS
sdh_make
sdh_make_install
-
-# Pretend that the "libfplll" package is not installed. This is needed to
-# support renaming libfplll -> fplll done on Trac #24042
-rm -f "$SAGE_SPKG_INST/"libfplll-*
diff --git a/build/pkgs/free_fonts/SPKG.rst b/build/pkgs/free_fonts/SPKG.rst
new file mode 100644
index 00000000000..417954179a7
--- /dev/null
+++ b/build/pkgs/free_fonts/SPKG.rst
@@ -0,0 +1,23 @@
+free_fonts: a free family of scalable outline fonts
+===================================================
+
+Description
+-----------
+
+This dummy package represents the GNU free fonts: a free family of scalable
+outline fonts, suitable for general use on computers and for desktop
+publishing. It is Unicode-encoded for compatibility with all modern operating
+systems.
+
+We do not have an SPKG for it. The purpose of this dummy package is to
+associate system package lists with it.
+
+License
+-------
+
+GNU General Public License GPLv3+
+
+Upstream Contact
+----------------
+
+https://www.gnu.org/software/freefont/
diff --git a/build/pkgs/free_fonts/distros/alpine.txt b/build/pkgs/free_fonts/distros/alpine.txt
new file mode 100644
index 00000000000..756efd2627c
--- /dev/null
+++ b/build/pkgs/free_fonts/distros/alpine.txt
@@ -0,0 +1 @@
+ttf-freefont
diff --git a/build/pkgs/free_fonts/distros/arch.txt b/build/pkgs/free_fonts/distros/arch.txt
new file mode 100644
index 00000000000..b03a4525c08
--- /dev/null
+++ b/build/pkgs/free_fonts/distros/arch.txt
@@ -0,0 +1 @@
+gnu-free-fonts
diff --git a/build/pkgs/free_fonts/distros/conda.txt b/build/pkgs/free_fonts/distros/conda.txt
new file mode 100644
index 00000000000..bdf05c629cf
--- /dev/null
+++ b/build/pkgs/free_fonts/distros/conda.txt
@@ -0,0 +1 @@
+open-fonts
diff --git a/build/pkgs/free_fonts/distros/debian.txt b/build/pkgs/free_fonts/distros/debian.txt
new file mode 100644
index 00000000000..9dae6737769
--- /dev/null
+++ b/build/pkgs/free_fonts/distros/debian.txt
@@ -0,0 +1 @@
+fonts-freefont-otf
diff --git a/build/pkgs/free_fonts/distros/fedora.txt b/build/pkgs/free_fonts/distros/fedora.txt
new file mode 100644
index 00000000000..b03a4525c08
--- /dev/null
+++ b/build/pkgs/free_fonts/distros/fedora.txt
@@ -0,0 +1 @@
+gnu-free-fonts
diff --git a/build/pkgs/free_fonts/distros/freebsd.txt b/build/pkgs/free_fonts/distros/freebsd.txt
new file mode 100644
index 00000000000..34b729ae37f
--- /dev/null
+++ b/build/pkgs/free_fonts/distros/freebsd.txt
@@ -0,0 +1 @@
+x11-fonts/freefont-ttf
diff --git a/build/pkgs/free_fonts/distros/gentoo.txt b/build/pkgs/free_fonts/distros/gentoo.txt
new file mode 100644
index 00000000000..f9711d7a9f2
--- /dev/null
+++ b/build/pkgs/free_fonts/distros/gentoo.txt
@@ -0,0 +1 @@
+media-fonts/freefont
diff --git a/build/pkgs/free_fonts/distros/macports.txt b/build/pkgs/free_fonts/distros/macports.txt
new file mode 100644
index 00000000000..d5a8b479117
--- /dev/null
+++ b/build/pkgs/free_fonts/distros/macports.txt
@@ -0,0 +1 @@
+freefont-ttf
diff --git a/build/pkgs/free_fonts/distros/opensuse.txt b/build/pkgs/free_fonts/distros/opensuse.txt
new file mode 100644
index 00000000000..b03a4525c08
--- /dev/null
+++ b/build/pkgs/free_fonts/distros/opensuse.txt
@@ -0,0 +1 @@
+gnu-free-fonts
diff --git a/build/pkgs/free_fonts/distros/repology.txt b/build/pkgs/free_fonts/distros/repology.txt
new file mode 100644
index 00000000000..0870af23017
--- /dev/null
+++ b/build/pkgs/free_fonts/distros/repology.txt
@@ -0,0 +1 @@
+gnu-freefont
diff --git a/build/pkgs/free_fonts/distros/void.txt b/build/pkgs/free_fonts/distros/void.txt
new file mode 100644
index 00000000000..d5a8b479117
--- /dev/null
+++ b/build/pkgs/free_fonts/distros/void.txt
@@ -0,0 +1 @@
+freefont-ttf
diff --git a/build/pkgs/free_fonts/spkg-configure.m4 b/build/pkgs/free_fonts/spkg-configure.m4
new file mode 100644
index 00000000000..d6864f5b58c
--- /dev/null
+++ b/build/pkgs/free_fonts/spkg-configure.m4
@@ -0,0 +1,16 @@
+SAGE_SPKG_CONFIGURE([free_fonts], [
+ sage_spkg_install_free_fonts=yes
+ m4_foreach([font],
+ [FreeSerif.ttf,FreeSerif.otf],
+ [
+ AC_MSG_CHECKING([for ]font)
+ AS_IF([kpsewhich ]font[ >& AS_MESSAGE_LOG_FD 2>&1], [
+ AC_MSG_RESULT([yes])
+ sage_spkg_install_free_fonts=no
+ break
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+ ])
+])
+
diff --git a/build/pkgs/free_fonts/type b/build/pkgs/free_fonts/type
new file mode 100644
index 00000000000..134d9bc32d5
--- /dev/null
+++ b/build/pkgs/free_fonts/type
@@ -0,0 +1 @@
+optional
diff --git a/build/pkgs/freetype/distros/macports.txt b/build/pkgs/freetype/distros/macports.txt
index 098479093ff..a2e684ddd92 100644
--- a/build/pkgs/freetype/distros/macports.txt
+++ b/build/pkgs/freetype/distros/macports.txt
@@ -1 +1,2 @@
-freetype
+# Broken as of 2022-05-01
+#freetype
diff --git a/build/pkgs/freetype/distros/opensuse.txt b/build/pkgs/freetype/distros/opensuse.txt
index 33f8f6b7bdd..9205ba71e27 100644
--- a/build/pkgs/freetype/distros/opensuse.txt
+++ b/build/pkgs/freetype/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(freetype2)"
+pkgconfig(freetype2)
diff --git a/build/pkgs/freetype/spkg-install.in b/build/pkgs/freetype/spkg-install.in
index c1615626e72..9d8c0075ec0 100644
--- a/build/pkgs/freetype/spkg-install.in
+++ b/build/pkgs/freetype/spkg-install.in
@@ -4,9 +4,3 @@ cd src
GNUMAKE=${MAKE} sdh_configure --enable-freetype-config $FREETYPE_CONFIGURE
sdh_make
sdh_make_install
-
-# The following file may be present from old builds of freetype, and
-# its presence can break the matplotlib build. So remove it. (The
-# current version is $SAGE_LOCAL/include/freetype2/ftbuild.h.)
-
-rm -f "$SAGE_LOCAL/include/ft2build.h"
diff --git a/build/pkgs/frobby/spkg-install.in b/build/pkgs/frobby/spkg-install.in
index 1a97cc6b682..60ed2c67207 100644
--- a/build/pkgs/frobby/spkg-install.in
+++ b/build/pkgs/frobby/spkg-install.in
@@ -1,4 +1,3 @@
-rm -rf "$SAGE_LOCAL/bin/frobby"
GMP_INC_DIR="$SAGE_LOCAL/include"; export GMP_INC_DIR
ldflags="-Wl,-rpath,$SAGE_LOCAL/lib -L$SAGE_LOCAL/lib/ -lgmpxx -lgmp"; export ldflags
@@ -12,14 +11,4 @@ if [ $? -ne 0 ]; then
exit 1
fi
-if [ ! -f bin/release/frobby ]; then
- echo "Frobby executable not found."
- exit 1
-fi
-
-$CP bin/release/frobby "$SAGE_LOCAL/bin/"
-
-if [ ! -f "$SAGE_LOCAL/bin/frobby" ]; then
- echo "Frobby executable not copied."
- exit 1
-fi
+sdh_install bin/release/frobby "$SAGE_LOCAL/bin"
diff --git a/build/pkgs/frobby/spkg-legacy-uninstall b/build/pkgs/frobby/spkg-legacy-uninstall
new file mode 100755
index 00000000000..a262741b2a9
--- /dev/null
+++ b/build/pkgs/frobby/spkg-legacy-uninstall
@@ -0,0 +1,2 @@
+#!/usr/bin/env bash
+rm -f "$SAGE_LOCAL/bin/frobby"
diff --git a/build/pkgs/furo/spkg-install.in b/build/pkgs/furo/spkg-install.in
deleted file mode 100644
index 37ac1a53437..00000000000
--- a/build/pkgs/furo/spkg-install.in
+++ /dev/null
@@ -1,2 +0,0 @@
-cd src
-sdh_pip_install .
diff --git a/build/pkgs/gap/distros/debian.txt b/build/pkgs/gap/distros/debian.txt
index 883a55b9c20..66efa2824a6 100644
--- a/build/pkgs/gap/distros/debian.txt
+++ b/build/pkgs/gap/distros/debian.txt
@@ -1 +1,2 @@
+gap
libgap-dev
diff --git a/build/pkgs/gap/distros/fedora.txt b/build/pkgs/gap/distros/fedora.txt
new file mode 100644
index 00000000000..6c561683bf4
--- /dev/null
+++ b/build/pkgs/gap/distros/fedora.txt
@@ -0,0 +1,5 @@
+gap
+gap-core
+gap-devel
+gap-libs
+libgap
diff --git a/build/pkgs/gap/spkg-configure.m4 b/build/pkgs/gap/spkg-configure.m4
new file mode 100644
index 00000000000..72a0a999da7
--- /dev/null
+++ b/build/pkgs/gap/spkg-configure.m4
@@ -0,0 +1,96 @@
+SAGE_SPKG_CONFIGURE([gap], [
+ # Default to installing the SPKG, if the check is run at all.
+ sage_spkg_install_gap=yes
+
+ m4_pushdef([GAP_MINVER],["4.12.2"])
+
+ SAGE_SPKG_DEPCHECK([ncurses readline zlib], [
+ AC_PATH_PROG(GAP, gap)
+ AS_IF([test -n "${GAP}"], [
+ AC_MSG_CHECKING([for gap version GAP_MINVER or newer])
+
+ # GAP will later add the "user" path to the list of root paths
+ # so long as we don't initialize GAP with -r in Sage. But we
+ # don't want to include it in the hard-coded list.
+ GAPRUN="${GAP} -r -q --bare --nointeract -c"
+ _cmd='Display(GAPInfo.KernelInfo.KERNEL_VERSION);'
+ GAP_VERSION=$( ${GAPRUN} "${_cmd}" 2>/dev/null )
+ AX_COMPARE_VERSION(["${GAP_VERSION}"], [ge], [GAP_MINVER], [
+ AC_MSG_RESULT([yes])
+ AC_MSG_CHECKING([for gap root paths])
+ _cmd='Display(JoinStringsWithSeparator(GAPInfo.RootPaths,";"));'
+ SYS_GAP_ROOT_PATHS=$( ${GAPRUN} "${_cmd}" 2>/dev/null )
+ AC_MSG_RESULT([$SYS_GAP_ROOT_PATHS])
+ AS_IF([test -n "${SYS_GAP_ROOT_PATHS}"], [
+ AC_MSG_CHECKING([for the PrimGrp, SmallGrp, and TransGrp packages])
+ # Check for a very minimal set of packages without which the
+ # sage test suite will fail. The crazy thing below is a
+ # "quadrigraph" for a square bracket.
+ _cmd="Display(@<:@"
+ _cmd="${_cmd} TestPackageAvailability(\"PrimGrp\"),"
+ _cmd="${_cmd} TestPackageAvailability(\"SmallGrp\"),"
+ _cmd="${_cmd} TestPackageAvailability(\"TransGrp\")"
+ _cmd="${_cmd} @:>@);"
+ _output=$( ${GAPRUN} "${_cmd}" 2>/dev/null )
+ AS_IF([test $? -eq 0], [
+ AS_CASE([$_output],
+ [*fail*],[AC_MSG_RESULT([no (at least one package missing)])],[
+ # default case, i.e. no "fail"
+ AC_MSG_RESULT([yes])
+
+ AC_MSG_CHECKING([if we can link against libgap])
+ # That was all for the CLI. Now we check for libgap,
+ # too. There's a long list of headers we need in
+ # src/sage/libs/gap/gap_includes.pxd, but libgap-api.h
+ # combined with the version test above should be
+ # sufficient even on systems where the headers are
+ # packaged separately.
+ _old_libs=$LIBS
+ LIBS="${LIBS} -lgap"
+ AC_LANG_PUSH([C])
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM(
+ [[#include ]],
+ [[
+ int main(int argc, char** argv) {
+ GAP_Initialize(0, 0, 0, 0, 0);
+ return 0;
+ }
+ ]])
+ ],[
+ AC_MSG_RESULT([yes])
+ sage_spkg_install_gap=no
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+ AC_LANG_POP
+ LIBS="${_old_libs}"
+ ])
+ ], [
+ # The gap command itself failed
+ AC_MSG_RESULT([no (package check command failed)])
+ ])
+ ])
+ ],[
+ # Version too old
+ AC_MSG_RESULT([no])
+ ])
+ ])
+ ])
+
+ m4_popdef([GAP_MINVER])
+],[],[],[
+ # This is the post-check phase, where we make sage-conf
+ # substitutions, in this case of GAP_ROOT_PATHS. We begin with the
+ # two root paths used by the sage distribution. The '${prefix}' is
+ # a magic string that sage-conf will replace.
+ GAP_ROOT_PATHS='${prefix}/lib/gap;${prefix}/share/gap';
+
+ AS_IF([test "${sage_spkg_install_gap}" = "no"],[
+ # If we're using the system GAP, append the system root
+ # paths to the existing two sage paths.
+ GAP_ROOT_PATHS="${GAP_ROOT_PATHS};${SYS_GAP_ROOT_PATHS}"
+ ])
+
+ AC_SUBST(GAP_ROOT_PATHS, "${GAP_ROOT_PATHS}")
+])
diff --git a/build/pkgs/gap/spkg-install.in b/build/pkgs/gap/spkg-install.in
index 47a7a8700ac..7d207a47a48 100644
--- a/build/pkgs/gap/spkg-install.in
+++ b/build/pkgs/gap/spkg-install.in
@@ -16,46 +16,43 @@ if [ "$SAGE_DEBUG" = yes ] ; then
export CFLAGS="-O0 -g3 -DDEBUG_MASTERPOINTERS -DDEBUG_GLOBAL_BAGS -DDEBUG_FUNCTIONS_BAGS $CFLAGS"
fi
-# LDFLAGS hack below needed by Semigroups package
-sdh_configure $SAGE_CONFIGURE_GMP LDFLAGS="-pthread" --prefix=$SAGE_LOCAL
+sdh_configure $SAGE_CONFIGURE_GMP --prefix=$SAGE_LOCAL
sdh_make
-
sdh_make_install
-# sdh_make install-headers install-libgap
-# The 'packagemanager' package expects this https://github.com/gap-packages/PackageManager/issues/105
-mkdir -p "$SAGE_LOCAL/lib/gap/bin"
# Install only the minimal packages GAP needs to run
sdh_install pkg/gapdoc pkg/primgrp pkg/smallgrp pkg/transgrp "$GAP_ROOT"/pkg
-# Install additional packages that are not strictly required, but that are
-# typically "expected" to be loaded: These are the default packages that are
-# autoloaded at GAP startup (via the PackagesToLoad UserPreference) with an
-# out-of-the-box GAP installation; see
-# https://github.com/sagemath/sage/issues/22626#comment:393 for discussion on this
-#
-# Also include atlasrep which is a dependency of tomlib
+# Install additional packages that are automatically loaded in the
+# default GAP configuration. The list can be found in lib/package.gi
+# as part of the "PackagesToLoad" user preference. Also include
+# atlasrep because it is a dependency of tomlib.
sdh_install \
+ pkg/alnuth \
pkg/atlasrep \
- pkg/autodoc \
pkg/autpgrp \
- pkg/alnuth \
pkg/crisp \
pkg/ctbllib \
pkg/factint \
pkg/fga \
pkg/irredsol \
pkg/laguna \
- pkg/packagemanager \
pkg/polenta \
pkg/polycyclic \
- pkg/radiroot \
pkg/resclasses \
pkg/sophus \
pkg/tomlib \
- pkg/utils \
"$GAP_ROOT"/pkg
+# Finally, install packagemanager for the people who reject both
+# sage's and their system's package managers. We have to create
+# the local bin directory first:
+#
+# https://github.com/gap-packages/PackageManager/issues/105
+#
+mkdir -p "$SAGE_LOCAL/lib/gap/bin"
+sdh_install pkg/packagemanager "$GAP_ROOT"/pkg
+
# TODO: This seems unnecessary--we are already installing all of doc/ to
# GAP_ROOT, which is necessary for some functionality in GAP to work. Do
# we need this? Maybe doc/gap could just be a symlink to gap/doc??
diff --git a/build/pkgs/gap/spkg-legacy-uninstall b/build/pkgs/gap/spkg-legacy-uninstall
deleted file mode 100755
index a8e5c59e1fb..00000000000
--- a/build/pkgs/gap/spkg-legacy-uninstall
+++ /dev/null
@@ -1,11 +0,0 @@
-#! /usr/bin/env bash
-# Remove existing GAP 4.x install(s)
-rm -rf "$SAGE_LOCAL/gap/gap-4."*
-rm -rf "$SAGE_SHARE/gap"
-rm -f "$SAGE_LOCAL/gap/latest"
-rm -f "$SAGE_LOCAL/bin/gap"
-rm -f "$SAGE_LOCAL/bin/gac"
-
-# Remove old libgap headers and library
-rm -rf "$SAGE_LOCAL/include/gap"
-rm -rf "$SAGE_LOCAL/lib/gap"
diff --git a/build/pkgs/gap_packages/SPKG.rst b/build/pkgs/gap_packages/SPKG.rst
index 67d3256637a..96238eef804 100644
--- a/build/pkgs/gap_packages/SPKG.rst
+++ b/build/pkgs/gap_packages/SPKG.rst
@@ -7,6 +7,20 @@ Description
Several "official" and "undeposited" GAP packages available from
https://www.gap-system.org/Packages/packages.html
+Installing this SPKG will install the corresponding GAP packages, but
+before you can use them in Sage, they still have to be loaded into
+either the GAP interface or libgap::
+
+ sage: gap.eval('LoadPackage("Grape")') # optional - gap_packages
+ 'true'
+ sage: libgap.LoadPackage("Grape") # optional - gap_packages
+ true
+
+Those correspond to::
+
+ gap> LoadPackage("Grape");
+
+within the GAP interface and libgap, respectively.
Upstream Contact
----------------
diff --git a/build/pkgs/gap_packages/spkg-install.in b/build/pkgs/gap_packages/spkg-install.in
index 6dff182a48f..7005cc3d322 100644
--- a/build/pkgs/gap_packages/spkg-install.in
+++ b/build/pkgs/gap_packages/spkg-install.in
@@ -1,5 +1,34 @@
-GAP_ROOT="$SAGE_LOCAL/lib/gap"
-PKG_DIR="$GAP_ROOT/pkg"
+# Ask GAP for the directory where sysinfo.gap lives. This is to
+# support system GAP installations. This root-path gathering
+# command is borrowed from gap's spkg-configure.m4 and modified
+# to separate the paths with spaces.
+GAPRUN="gap -r -q --bare --nointeract -c"
+_cmd='Display(JoinStringsWithSeparator(GAPInfo.RootPaths," "));'
+GAP_ROOT_PATHS=$(${GAPRUN} "${_cmd}")
+
+# Loop though GAP_ROOT_PATHS looking for sysinfo.gap
+GAP_ROOT=""
+for grp in $GAP_ROOT_PATHS; do
+ if [ -f "${grp}/sysinfo.gap" ]; then
+ GAP_ROOT=$grp
+ echo "found GAP root $GAP_ROOT"
+ break
+ fi
+done
+
+# Try the old sage default if nothing else worked.
+if [ -z "$GAP_ROOT" ]; then
+ GAP_ROOT="$SAGE_LOCAL/lib/gap"
+ echo "falling back to GAP root $GAP_ROOT"
+fi
+
+# And finally, throw an error ASAP if the build is going to fail anyway.
+if [ ! -f "${GAP_ROOT}/sysinfo.gap" ]; then
+ sdh_die "no sysinfo.gap in your gap root"
+fi
+
+# Where to install these packages
+PKG_DIR="$SAGE_LOCAL/lib/gap/pkg"
PKG_SRC_DIR="$(pwd)/src/pkg"
cd "$PKG_SRC_DIR"
@@ -12,6 +41,7 @@ cd "$PKG_SRC_DIR"
sdh_install \
aclib \
+ autodoc \
corelg \
crime \
cryst \
@@ -31,11 +61,13 @@ sdh_install \
polymaking \
qpa \
quagroup \
+ radiroot \
repsn \
singular \
sla \
sonata \
toric \
+ utils \
"$PKG_DIR"
install_compiled_pkg()
diff --git a/build/pkgs/gc/distros/fedora.txt b/build/pkgs/gc/distros/fedora.txt
index 1d6df64a216..b6940f8b6aa 100644
--- a/build/pkgs/gc/distros/fedora.txt
+++ b/build/pkgs/gc/distros/fedora.txt
@@ -1 +1,2 @@
-gc gc-devel
+gc
+gc-devel
diff --git a/build/pkgs/gc/distros/opensuse.txt b/build/pkgs/gc/distros/opensuse.txt
index 4620f6a8cb4..f250631fcc2 100644
--- a/build/pkgs/gc/distros/opensuse.txt
+++ b/build/pkgs/gc/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(bdw-gc)"
+pkgconfig(bdw-gc)
diff --git a/build/pkgs/gf2x/checksums.ini b/build/pkgs/gf2x/checksums.ini
index 10a93c2c1bc..0eaf7657e40 100644
--- a/build/pkgs/gf2x/checksums.ini
+++ b/build/pkgs/gf2x/checksums.ini
@@ -2,4 +2,4 @@ tarball=gf2x-VERSION.tar.gz
sha1=1b9c7e14031afc5488b9aa27f5501f78c90f00b4
md5=842f087ce423c279dced26b85b0fd1d0
cksum=3368093312
-upstream_url=https://gitlab.inria.fr/gf2x/gf2x/uploads/c46b1047ba841c20d1225ae73ad6e4cd/gf2x-1.3.0.tar.gz
+upstream_url=https://gitlab.inria.fr/gf2x/gf2x/uploads/c46b1047ba841c20d1225ae73ad6e4cd/gf2x-VERSION.tar.gz
diff --git a/build/pkgs/gf2x/distros/fedora.txt b/build/pkgs/gf2x/distros/fedora.txt
index 726d8da490c..3d1d2bb46bb 100644
--- a/build/pkgs/gf2x/distros/fedora.txt
+++ b/build/pkgs/gf2x/distros/fedora.txt
@@ -1 +1,2 @@
-gf2x gf2x-devel
+gf2x
+gf2x-devel
diff --git a/build/pkgs/gf2x/distros/opensuse.txt b/build/pkgs/gf2x/distros/opensuse.txt
index 9a15ad0abe3..9fb7b9fd16e 100644
--- a/build/pkgs/gf2x/distros/opensuse.txt
+++ b/build/pkgs/gf2x/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(gf2x)"
+pkgconfig(gf2x)
diff --git a/build/pkgs/gf2x/spkg-install.in b/build/pkgs/gf2x/spkg-install.in
index 057be0a5953..c8e4c83e6d2 100644
--- a/build/pkgs/gf2x/spkg-install.in
+++ b/build/pkgs/gf2x/spkg-install.in
@@ -1,7 +1,3 @@
-echo "Deleting old gf2x files."
-rm -f "$SAGE_LOCAL"/lib/libgf2x*
-rm -rf "$SAGE_LOCAL"/include/gf2x*
-
cd src
# Use newer version of config.guess and config.sub (see Trac #19727)
diff --git a/build/pkgs/gfan/spkg-legacy-uninstall b/build/pkgs/gfan/spkg-legacy-uninstall
deleted file mode 100755
index 74552b0b71c..00000000000
--- a/build/pkgs/gfan/spkg-legacy-uninstall
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /usr/bin/env bash
-echo "Removing old version of gfan (if any)..."
-rm -f "$SAGE_LOCAL"/bin/gfan*
diff --git a/build/pkgs/gfortran/distros/macports.txt b/build/pkgs/gfortran/distros/macports.txt
index c2878adf893..dfa7190f158 100644
--- a/build/pkgs/gfortran/distros/macports.txt
+++ b/build/pkgs/gfortran/distros/macports.txt
@@ -1 +1,2 @@
-gcc10 +gfortran
+gcc10
++gfortran
diff --git a/build/pkgs/giac/distros/arch.txt b/build/pkgs/giac/distros/arch.txt
index 7bdbd844d6c..f54c3286e4f 100644
--- a/build/pkgs/giac/distros/arch.txt
+++ b/build/pkgs/giac/distros/arch.txt
@@ -1 +1,2 @@
-libgiac giac
+libgiac
+giac
diff --git a/build/pkgs/giac/spkg-install.in b/build/pkgs/giac/spkg-install.in
index e3eb86e6034..ceed3899be6 100644
--- a/build/pkgs/giac/spkg-install.in
+++ b/build/pkgs/giac/spkg-install.in
@@ -60,24 +60,6 @@ sdh_configure --disable-gui --disable-ao "$DISABLENLS" --enable-png=no --disable
sdh_make
-#############################################################
-# Clean old install
-#############################################################
-echo "Cleaning giac..."
-rm -f ${SAGE_LOCAL}/lib/libgiac*
-rm -f ${SAGE_LOCAL}/bin/icas
-rm -f ${SAGE_LOCAL}/bin/xcas
-rm -f ${SAGE_LOCAL}/bin/cas_help
-rm -f ${SAGE_LOCAL}/bin/pgiac
-rm -f ${SAGE_LOCAL}/bin/en_cas_help
-rm -f ${SAGE_LOCAL}/bin/es_cas_help
-rm -f ${SAGE_LOCAL}/bin/fr_cas_help
-rm -f ${SAGE_LOCAL}/bin/giac
-rm -f ${SAGE_LOCAL}/bin/xcasnew
-rm -rf ${SAGE_LOCAL}/share/giac
-rm -rf ${SAGE_LOCAL}/share/doc/giac
-rm -rf ${SAGE_LOCAL}/include/giac
-
#############################################################
# Install
#############################################################
diff --git a/build/pkgs/givaro/distros/fedora.txt b/build/pkgs/givaro/distros/fedora.txt
index 6848d8c4e7f..9016d00aaab 100644
--- a/build/pkgs/givaro/distros/fedora.txt
+++ b/build/pkgs/givaro/distros/fedora.txt
@@ -1 +1,2 @@
-givaro givaro-devel
+givaro
+givaro-devel
diff --git a/build/pkgs/givaro/distros/opensuse.txt b/build/pkgs/givaro/distros/opensuse.txt
index 2a8103e6f6b..8de5fadae90 100644
--- a/build/pkgs/givaro/distros/opensuse.txt
+++ b/build/pkgs/givaro/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(givaro)"
+pkgconfig(givaro)
diff --git a/build/pkgs/glpk/distros/cygwin.txt b/build/pkgs/glpk/distros/cygwin.txt
index 2e6c6a10cb8..0fbb959079e 100644
--- a/build/pkgs/glpk/distros/cygwin.txt
+++ b/build/pkgs/glpk/distros/cygwin.txt
@@ -1 +1,2 @@
-glpk libglpk-devel
+glpk
+libglpk-devel
diff --git a/build/pkgs/glpk/distros/fedora.txt b/build/pkgs/glpk/distros/fedora.txt
index 73ab7f14b14..e028b246574 100644
--- a/build/pkgs/glpk/distros/fedora.txt
+++ b/build/pkgs/glpk/distros/fedora.txt
@@ -1 +1,3 @@
-glpk glpk-devel glpk-utils
+glpk
+glpk-devel
+glpk-utils
diff --git a/build/pkgs/glpk/spkg-install.in b/build/pkgs/glpk/spkg-install.in
index a911c46f024..f592a562148 100644
--- a/build/pkgs/glpk/spkg-install.in
+++ b/build/pkgs/glpk/spkg-install.in
@@ -25,8 +25,4 @@ export CFLAGS LDFLAGS CPPFLAGS
sdh_configure --with-gmp --disable-static
sdh_make
-# Remove old libraries to make sure we can downgrade it if needed.
-# See https://github.com/sagemath/sage/issues/23596#comment:4 and later.
-rm -f "$SAGE_LOCAL"/lib/libglpk.*
-
sdh_make_install
diff --git a/build/pkgs/gmp/distros/fedora.txt b/build/pkgs/gmp/distros/fedora.txt
index bbe9ee39cab..1436ed982e7 100644
--- a/build/pkgs/gmp/distros/fedora.txt
+++ b/build/pkgs/gmp/distros/fedora.txt
@@ -1 +1,2 @@
-gmp gmp-devel
+gmp
+gmp-devel
diff --git a/build/pkgs/gnumake_tokenpool/checksums.ini b/build/pkgs/gnumake_tokenpool/checksums.ini
index 62f631ea40a..e79058d27e3 100644
--- a/build/pkgs/gnumake_tokenpool/checksums.ini
+++ b/build/pkgs/gnumake_tokenpool/checksums.ini
@@ -1,5 +1,5 @@
tarball=gnumake_tokenpool-VERSION-py3-none-any.whl
-sha1=a060f03e0306a85bc1a91a450e457be83ed371e9
-md5=834ccc4d6d52741c5eabac1bdb8f39b2
-cksum=1679797266
+sha1=3dfcc8c466c17f974d90694f81f4481c3d84aecc
+md5=5dae4c65e9609853085ae1970d4fe143
+cksum=612213211
upstream_url=https://pypi.io/packages/py3/g/gnumake_tokenpool/gnumake_tokenpool-VERSION-py3-none-any.whl
diff --git a/build/pkgs/gnumake_tokenpool/install-requires.txt b/build/pkgs/gnumake_tokenpool/install-requires.txt
index 0ee4452edd3..759ca97a680 100644
--- a/build/pkgs/gnumake_tokenpool/install-requires.txt
+++ b/build/pkgs/gnumake_tokenpool/install-requires.txt
@@ -1 +1 @@
-gnumake-tokenpool
+gnumake-tokenpool >= 0.0.4
diff --git a/build/pkgs/gnumake_tokenpool/package-version.txt b/build/pkgs/gnumake_tokenpool/package-version.txt
index bcab45af15a..81340c7e72d 100644
--- a/build/pkgs/gnumake_tokenpool/package-version.txt
+++ b/build/pkgs/gnumake_tokenpool/package-version.txt
@@ -1 +1 @@
-0.0.3
+0.0.4
diff --git a/build/pkgs/graphs/checksums.ini b/build/pkgs/graphs/checksums.ini
index 285778ef3a7..7ec4a8a6ada 100644
--- a/build/pkgs/graphs/checksums.ini
+++ b/build/pkgs/graphs/checksums.ini
@@ -2,4 +2,4 @@ tarball=graphs-VERSION.tar.bz2
sha1=c3b9fcbc92482efd6b7f6f3a33df5a78e1256aa1
md5=4357919410e8ac2611c9fe643976c8ff
cksum=2340933149
-upstream_url=http://users.ox.ac.uk/~coml0531/sage/graphs-20210214.tar.bz2
+upstream_url=http://users.ox.ac.uk/~coml0531/sage/graphs-VERSION.tar.bz2
diff --git a/build/pkgs/gsl/distros/fedora.txt b/build/pkgs/gsl/distros/fedora.txt
index 5577d09957b..ce35d3d80bd 100644
--- a/build/pkgs/gsl/distros/fedora.txt
+++ b/build/pkgs/gsl/distros/fedora.txt
@@ -1 +1,2 @@
-gsl gsl-devel
+gsl
+gsl-devel
diff --git a/build/pkgs/gsl/distros/opensuse.txt b/build/pkgs/gsl/distros/opensuse.txt
index ccfee4f4e43..c1867648576 100644
--- a/build/pkgs/gsl/distros/opensuse.txt
+++ b/build/pkgs/gsl/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(gsl)"
+pkgconfig(gsl)
diff --git a/build/pkgs/gsl/spkg-legacy-uninstall b/build/pkgs/gsl/spkg-legacy-uninstall
deleted file mode 100755
index 6c42f90b665..00000000000
--- a/build/pkgs/gsl/spkg-legacy-uninstall
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /usr/bin/env bash
-rm -rf "$SAGE_LOCAL"/include/gsl
-rm -rf "$SAGE_LOCAL"/lib/libgsl*
diff --git a/build/pkgs/hatch_fancy_pypi_readme/checksums.ini b/build/pkgs/hatch_fancy_pypi_readme/checksums.ini
index 6d48eb14be8..6da100dad5a 100644
--- a/build/pkgs/hatch_fancy_pypi_readme/checksums.ini
+++ b/build/pkgs/hatch_fancy_pypi_readme/checksums.ini
@@ -1,5 +1,5 @@
-tarball=hatch_fancy_pypi_readme-VERSION.tar.gz
-sha1=8c8568bb86bdc65133e9d8b27493a464fa3320da
-md5=8755cce1a4a4d5e5d84992089801acbf
-cksum=2176903739
-upstream_url=https://pypi.io/packages/source/h/hatch_fancy_pypi_readme/hatch_fancy_pypi_readme-VERSION.tar.gz
+tarball=hatch_fancy_pypi_readme-VERSION-py3-none-any.whl
+sha1=4076ea14577b3c711a8345498d8f91b1c8a13d09
+md5=d7acd13333f6c71dcbfa62420c7f257b
+cksum=1527082323
+upstream_url=https://pypi.io/packages/py3/h/hatch_fancy_pypi_readme/hatch_fancy_pypi_readme-VERSION-py3-none-any.whl
diff --git a/build/pkgs/hatch_fancy_pypi_readme/dependencies b/build/pkgs/hatch_fancy_pypi_readme/dependencies
index cfb7c484697..36380aee4e7 100644
--- a/build/pkgs/hatch_fancy_pypi_readme/dependencies
+++ b/build/pkgs/hatch_fancy_pypi_readme/dependencies
@@ -1,4 +1,4 @@
- | $(PYTHON_TOOLCHAIN) hatchling $(PYTHON)
+hatchling | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/hatch_fancy_pypi_readme/spkg-install.in b/build/pkgs/hatch_fancy_pypi_readme/spkg-install.in
deleted file mode 100644
index 37ac1a53437..00000000000
--- a/build/pkgs/hatch_fancy_pypi_readme/spkg-install.in
+++ /dev/null
@@ -1,2 +0,0 @@
-cd src
-sdh_pip_install .
diff --git a/build/pkgs/hatch_vcs/SPKG.rst b/build/pkgs/hatch_vcs/SPKG.rst
index 51f4780749e..6c11d8d95fb 100644
--- a/build/pkgs/hatch_vcs/SPKG.rst
+++ b/build/pkgs/hatch_vcs/SPKG.rst
@@ -9,6 +9,8 @@ Hatch plugin for versioning with your preferred VCS
License
-------
+MIT
+
Upstream Contact
----------------
diff --git a/build/pkgs/hatch_vcs/checksums.ini b/build/pkgs/hatch_vcs/checksums.ini
index 9c1290bda3b..e9908b1540e 100644
--- a/build/pkgs/hatch_vcs/checksums.ini
+++ b/build/pkgs/hatch_vcs/checksums.ini
@@ -1,5 +1,5 @@
-tarball=hatch_vcs-VERSION.tar.gz
-sha1=026b964066b38fd7e823900817fb9ea7af3f8d9b
-md5=c2f2cbe6851b7b2969cb4aa24c4b9b2f
-cksum=588874896
-upstream_url=https://pypi.io/packages/source/h/hatch_vcs/hatch_vcs-VERSION.tar.gz
+tarball=hatch_vcs-VERSION-py3-none-any.whl
+sha1=a4da813bf9a745ed2020bf462f4bc19a1ab7fc11
+md5=82bee9889b95170e550c98f8dd11bc61
+cksum=1575327634
+upstream_url=https://pypi.io/packages/py3/h/hatch_vcs/hatch_vcs-VERSION-py3-none-any.whl
diff --git a/build/pkgs/hatch_vcs/dependencies b/build/pkgs/hatch_vcs/dependencies
index cfb7c484697..36380aee4e7 100644
--- a/build/pkgs/hatch_vcs/dependencies
+++ b/build/pkgs/hatch_vcs/dependencies
@@ -1,4 +1,4 @@
- | $(PYTHON_TOOLCHAIN) hatchling $(PYTHON)
+hatchling | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/hatch_vcs/package-version.txt b/build/pkgs/hatch_vcs/package-version.txt
index 0d91a54c7d4..1d0ba9ea182 100644
--- a/build/pkgs/hatch_vcs/package-version.txt
+++ b/build/pkgs/hatch_vcs/package-version.txt
@@ -1 +1 @@
-0.3.0
+0.4.0
diff --git a/build/pkgs/hatch_vcs/spkg-install.in b/build/pkgs/hatch_vcs/spkg-install.in
deleted file mode 100644
index 37ac1a53437..00000000000
--- a/build/pkgs/hatch_vcs/spkg-install.in
+++ /dev/null
@@ -1,2 +0,0 @@
-cd src
-sdh_pip_install .
diff --git a/build/pkgs/hatchling/checksums.ini b/build/pkgs/hatchling/checksums.ini
index d21781abeba..5d8b02696c5 100644
--- a/build/pkgs/hatchling/checksums.ini
+++ b/build/pkgs/hatchling/checksums.ini
@@ -1,5 +1,5 @@
-tarball=hatchling-VERSION.tar.gz
-sha1=f3db8639e9bee89e2e2420d1bc7a048a910622c9
-md5=43f7203cacb6c3c178b93149b8a8151d
-cksum=235277633
-upstream_url=https://pypi.io/packages/source/h/hatchling/hatchling-VERSION.tar.gz
+tarball=hatchling-VERSION-py3-none-any.whl
+sha1=aa9d69b9dd820716440252d737a4aeaf9b4e541f
+md5=20e5ea4deea21f91759fb2269b71f0dd
+cksum=446304413
+upstream_url=https://pypi.io/packages/py3/h/hatchling/hatchling-VERSION-py3-none-any.whl
diff --git a/build/pkgs/hatchling/dependencies b/build/pkgs/hatchling/dependencies
index 479f1630979..b1769861625 100644
--- a/build/pkgs/hatchling/dependencies
+++ b/build/pkgs/hatchling/dependencies
@@ -1,4 +1,4 @@
- pathspec tomli editables pluggy packaging trove_classifiers | $(PYTHON_TOOLCHAIN) $(PYTHON)
+ pathspec tomli editables pluggy packaging trove_classifiers | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/hatchling/package-version.txt b/build/pkgs/hatchling/package-version.txt
index 84cc529467b..39893559155 100644
--- a/build/pkgs/hatchling/package-version.txt
+++ b/build/pkgs/hatchling/package-version.txt
@@ -1 +1 @@
-1.18.0
+1.20.0
diff --git a/build/pkgs/hatchling/spkg-install.in b/build/pkgs/hatchling/spkg-install.in
deleted file mode 100644
index 37ac1a53437..00000000000
--- a/build/pkgs/hatchling/spkg-install.in
+++ /dev/null
@@ -1,2 +0,0 @@
-cd src
-sdh_pip_install .
diff --git a/build/pkgs/igraph/checksums.ini b/build/pkgs/igraph/checksums.ini
index 279cba457a9..51192799072 100644
--- a/build/pkgs/igraph/checksums.ini
+++ b/build/pkgs/igraph/checksums.ini
@@ -1,5 +1,5 @@
tarball=igraph-VERSION.tar.gz
-sha1=fc3c6627f889b13581b2b468e1b16aceff453cfc
-md5=10a3f325425970c75a7ba8359376e208
-cksum=3103730646
+sha1=40efbd2adf3c1cc0a2bb3e14f4c7898d053f1fe4
+md5=87d287445c44fdd19ad67a25e0e0859b
+cksum=2559618807
upstream_url=https://github.com/igraph/igraph/releases/download/VERSION/igraph-VERSION.tar.gz
diff --git a/build/pkgs/igraph/distros/fedora.txt b/build/pkgs/igraph/distros/fedora.txt
index 8ca7a112d45..fa2dc51a2ce 100644
--- a/build/pkgs/igraph/distros/fedora.txt
+++ b/build/pkgs/igraph/distros/fedora.txt
@@ -1 +1,2 @@
-igraph igraph-devel
+igraph
+igraph-devel
diff --git a/build/pkgs/igraph/package-version.txt b/build/pkgs/igraph/package-version.txt
index 9b40aa6c214..1a46c7f13e7 100644
--- a/build/pkgs/igraph/package-version.txt
+++ b/build/pkgs/igraph/package-version.txt
@@ -1 +1 @@
-0.10.4
+0.10.8
diff --git a/build/pkgs/igraph/spkg-configure.m4 b/build/pkgs/igraph/spkg-configure.m4
index 30b5fcf9c53..5133fce98da 100644
--- a/build/pkgs/igraph/spkg-configure.m4
+++ b/build/pkgs/igraph/spkg-configure.m4
@@ -1,7 +1,9 @@
SAGE_SPKG_CONFIGURE([igraph], [
SAGE_SPKG_DEPCHECK([glpk openblas gmp], [
dnl check for igraph with pkg-config
- PKG_CHECK_MODULES([IGRAPH], [igraph >= 0.10 igraph < 0.11], [], [
+ dnl Per upstream in https://github.com/sagemath/sage/pull/36750#issuecomment-1826998762:
+ dnl each python-igraph release is only guaranteed to be compatible with the same C/igraph that it bundles
+ PKG_CHECK_MODULES([IGRAPH], [igraph >= 0.10.8 igraph < 0.10.9], [], [
sage_spkg_install_igraph=yes])
])
])
diff --git a/build/pkgs/iml/distros/fedora.txt b/build/pkgs/iml/distros/fedora.txt
index 32307096d65..88a895a10f6 100644
--- a/build/pkgs/iml/distros/fedora.txt
+++ b/build/pkgs/iml/distros/fedora.txt
@@ -1 +1,2 @@
-iml iml-devel
+iml
+iml-devel
diff --git a/build/pkgs/importlib_metadata/checksums.ini b/build/pkgs/importlib_metadata/checksums.ini
index 8c978b57c5b..506ef54e9a5 100644
--- a/build/pkgs/importlib_metadata/checksums.ini
+++ b/build/pkgs/importlib_metadata/checksums.ini
@@ -1,5 +1,5 @@
-tarball=importlib_metadata-VERSION.tar.gz
-sha1=0e5742cd1d559863573bfb4f6cb7ca9ad8dcf466
-md5=c04c814eee1abf42790cfa4bd0454af1
-cksum=1038169537
-upstream_url=https://pypi.io/packages/source/i/importlib_metadata/importlib_metadata-VERSION.tar.gz
+tarball=importlib_metadata-VERSION-py3-none-any.whl
+sha1=0e693ba704ac628065bab72a097dad3311213f4b
+md5=67eac786f2f9e8bf5879e88ef527250a
+cksum=1288292429
+upstream_url=https://pypi.io/packages/py3/i/importlib_metadata/importlib_metadata-VERSION-py3-none-any.whl
diff --git a/build/pkgs/importlib_metadata/package-version.txt b/build/pkgs/importlib_metadata/package-version.txt
index e029aa99b7d..66ce77b7ead 100644
--- a/build/pkgs/importlib_metadata/package-version.txt
+++ b/build/pkgs/importlib_metadata/package-version.txt
@@ -1 +1 @@
-6.8.0
+7.0.0
diff --git a/build/pkgs/importlib_metadata/spkg-install.in b/build/pkgs/importlib_metadata/spkg-install.in
deleted file mode 100644
index cc03b63f4f2..00000000000
--- a/build/pkgs/importlib_metadata/spkg-install.in
+++ /dev/null
@@ -1,14 +0,0 @@
-if [ -z "$SAGE_LOCAL" ]; then
- echo >&2 "SAGE_LOCAL undefined ... exiting"
- echo >&2 "Maybe run 'sage --sh'?"
- exit 1
-fi
-
-cd src
-
-sdh_pip_install .
-
-if [ $? -ne 0 ]; then
- echo "Error installing importlib_metadata ... exiting"
- exit 1
-fi
diff --git a/build/pkgs/importlib_resources/checksums.ini b/build/pkgs/importlib_resources/checksums.ini
index 39040fbf296..e733e142b52 100644
--- a/build/pkgs/importlib_resources/checksums.ini
+++ b/build/pkgs/importlib_resources/checksums.ini
@@ -1,5 +1,5 @@
-tarball=importlib_resources-VERSION.tar.gz
-sha1=4af82ed75a1672a45157bfa7d09c4dfd0605802a
-md5=525d238db212bdec2df06c0d4b479e73
-cksum=1494471486
-upstream_url=https://pypi.io/packages/source/i/importlib_resources/importlib_resources-VERSION.tar.gz
+tarball=importlib_resources-VERSION-py3-none-any.whl
+sha1=5caa4e8a9ee93123a5c3badb6edbc009b5d8494a
+md5=a4ba26d808eed58bde249276da04c9e1
+cksum=2487282894
+upstream_url=https://pypi.io/packages/py3/i/importlib_resources/importlib_resources-VERSION-py3-none-any.whl
diff --git a/build/pkgs/importlib_resources/dependencies b/build/pkgs/importlib_resources/dependencies
index 655283898b7..30f71335acb 100644
--- a/build/pkgs/importlib_resources/dependencies
+++ b/build/pkgs/importlib_resources/dependencies
@@ -1,4 +1,4 @@
- zipp | $(PYTHON_TOOLCHAIN) $(PYTHON)
+zipp | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/importlib_resources/package-version.txt b/build/pkgs/importlib_resources/package-version.txt
index dfda3e0b4f0..f3b5af39e43 100644
--- a/build/pkgs/importlib_resources/package-version.txt
+++ b/build/pkgs/importlib_resources/package-version.txt
@@ -1 +1 @@
-6.1.0
+6.1.1
diff --git a/build/pkgs/importlib_resources/spkg-install.in b/build/pkgs/importlib_resources/spkg-install.in
deleted file mode 100644
index 37ac1a53437..00000000000
--- a/build/pkgs/importlib_resources/spkg-install.in
+++ /dev/null
@@ -1,2 +0,0 @@
-cd src
-sdh_pip_install .
diff --git a/build/pkgs/info/distros/fedora.txt b/build/pkgs/info/distros/fedora.txt
index c0d8f74e0ad..c3ed35de973 100644
--- a/build/pkgs/info/distros/fedora.txt
+++ b/build/pkgs/info/distros/fedora.txt
@@ -1 +1,2 @@
-texinfo info
+texinfo
+info
diff --git a/build/pkgs/ipython/spkg-install.in b/build/pkgs/ipython/spkg-install.in
index 5096a907a95..058b1344dc2 100644
--- a/build/pkgs/ipython/spkg-install.in
+++ b/build/pkgs/ipython/spkg-install.in
@@ -1,7 +1,3 @@
-# Old installations of ipython can leave a symlink which can interfere
-# with proper installation.
-rm -f "$SAGE_LOCAL"/bin/ipython
-
cd src
sdh_pip_install .
diff --git a/build/pkgs/isl/distros/opensuse.txt b/build/pkgs/isl/distros/opensuse.txt
index 721c2bb0dcb..ec70829dde7 100644
--- a/build/pkgs/isl/distros/opensuse.txt
+++ b/build/pkgs/isl/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(isl)"
+pkgconfig(isl)
diff --git a/build/pkgs/jmol/spkg-legacy-uninstall b/build/pkgs/jmol/spkg-legacy-uninstall
deleted file mode 100755
index 6c9bd1a2c08..00000000000
--- a/build/pkgs/jmol/spkg-legacy-uninstall
+++ /dev/null
@@ -1,5 +0,0 @@
-#! /usr/bin/env bash
-# Cleanup of previous installation
-rm -rf "${SAGE_SHARE}/jsmol/"
-rm -rf "${SAGE_SHARE}/jmol/"
-rm -f "${SAGE_LOCAL}/bin/jmol"
diff --git a/build/pkgs/kenzo/checksums.ini b/build/pkgs/kenzo/checksums.ini
index ad2a7c4cc60..7fff82ca271 100644
--- a/build/pkgs/kenzo/checksums.ini
+++ b/build/pkgs/kenzo/checksums.ini
@@ -1,5 +1,5 @@
-tarball=kenzo-1.1.10.tar.gz
-upstream_url=https://github.com/miguelmarco/kenzo/releases/download/1.1.10/kenzo-1.1.10.tar.gz
+tarball=kenzo-VERSION.tar.gz
+upstream_url=https://github.com/miguelmarco/kenzo/releases/download/VERSION/kenzo-VERSION.tar.gz
sha1=76115aae9972090d5d51fee18592fc7a79461474
md5=3a3d5350fb17304f03e614713e585ed4
cksum=2981306888
diff --git a/build/pkgs/lcalc/spkg-legacy-uninstall b/build/pkgs/lcalc/spkg-legacy-uninstall
deleted file mode 100755
index 4cacdfd9367..00000000000
--- a/build/pkgs/lcalc/spkg-legacy-uninstall
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /usr/bin/env bash
-rm -fr "$SAGE_LOCAL"/include/libLfunction
diff --git a/build/pkgs/libatomic_ops/distros/fedora.txt b/build/pkgs/libatomic_ops/distros/fedora.txt
index 3417f891c11..d1f77fa5ad7 100644
--- a/build/pkgs/libatomic_ops/distros/fedora.txt
+++ b/build/pkgs/libatomic_ops/distros/fedora.txt
@@ -1 +1,2 @@
-libatomic_ops libatomic_ops-devel
+libatomic_ops
+libatomic_ops-devel
diff --git a/build/pkgs/libatomic_ops/distros/opensuse.txt b/build/pkgs/libatomic_ops/distros/opensuse.txt
index 6e7e1c4cecb..0d82eae1b32 100644
--- a/build/pkgs/libatomic_ops/distros/opensuse.txt
+++ b/build/pkgs/libatomic_ops/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(atomic_ops)"
+pkgconfig(atomic_ops)
diff --git a/build/pkgs/libbraiding/checksums.ini b/build/pkgs/libbraiding/checksums.ini
index bb76fa5b604..466c33c66a5 100644
--- a/build/pkgs/libbraiding/checksums.ini
+++ b/build/pkgs/libbraiding/checksums.ini
@@ -1,5 +1,5 @@
-tarball=libbraiding-VERSION.tar.gz
-sha1=06610e47eb243b27aea0ad399b41614fcdb179c9
-md5=5466605026b90bdca7ca20852f88b5c5
-cksum=704753563
-upstream_url=https://github.com/miguelmarco/libbraiding/releases/download/1.1/libbraiding-1.1.tar.gz
+tarball=libbraiding-VERSION-actually-VERSION.tar.gz
+sha1=b7e13778784fe1e36e7c0cbd7a4c234a090cd1b2
+md5=0513967c81b783ea66336b7ad0562534
+cksum=3619705925
+upstream_url=https://github.com/miguelmarco/libbraiding/releases/download/VERSION/libbraiding-VERSION.tar.gz
diff --git a/build/pkgs/libffi/distros/fedora.txt b/build/pkgs/libffi/distros/fedora.txt
index 8d342f491c1..70c40a27925 100644
--- a/build/pkgs/libffi/distros/fedora.txt
+++ b/build/pkgs/libffi/distros/fedora.txt
@@ -1 +1,2 @@
-libffi libffi-devel
+libffi
+libffi-devel
diff --git a/build/pkgs/libffi/distros/opensuse.txt b/build/pkgs/libffi/distros/opensuse.txt
index 1a6986d429e..39fa66806ec 100644
--- a/build/pkgs/libffi/distros/opensuse.txt
+++ b/build/pkgs/libffi/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(libffi)"
+pkgconfig(libffi)
diff --git a/build/pkgs/libgd/distros/fedora.txt b/build/pkgs/libgd/distros/fedora.txt
index d27cc48549e..1f276d6eb09 100644
--- a/build/pkgs/libgd/distros/fedora.txt
+++ b/build/pkgs/libgd/distros/fedora.txt
@@ -1 +1,2 @@
-gd gd-devel
+gd
+gd-devel
diff --git a/build/pkgs/libgd/distros/macports.txt b/build/pkgs/libgd/distros/macports.txt
index d44f88f27cc..ee5e3357f06 100644
--- a/build/pkgs/libgd/distros/macports.txt
+++ b/build/pkgs/libgd/distros/macports.txt
@@ -1 +1,2 @@
-gd2
+# broken as of 2022-05-01 -- and also has too many dependencies
+#gd2
diff --git a/build/pkgs/libgd/distros/opensuse.txt b/build/pkgs/libgd/distros/opensuse.txt
index 48195aa6b44..bcf953527f8 100644
--- a/build/pkgs/libgd/distros/opensuse.txt
+++ b/build/pkgs/libgd/distros/opensuse.txt
@@ -1,2 +1,2 @@
gd
-"pkgconfig(gdlib)"
+pkgconfig(gdlib)
diff --git a/build/pkgs/libgd/distros/slackware.txt b/build/pkgs/libgd/distros/slackware.txt
index 5d28bb87ae1..442f2e7f440 100644
--- a/build/pkgs/libgd/distros/slackware.txt
+++ b/build/pkgs/libgd/distros/slackware.txt
@@ -1,3 +1,8 @@
gd
# shared library dependencies of gd
-fontconfig libXpm libX11 libxcb libXau libXdmcp
+fontconfig
+libXpm
+libX11
+libxcb
+libXau
+libXdmcp
diff --git a/build/pkgs/libgd/spkg-legacy-uninstall b/build/pkgs/libgd/spkg-legacy-uninstall
deleted file mode 100755
index c67f4d2167d..00000000000
--- a/build/pkgs/libgd/spkg-legacy-uninstall
+++ /dev/null
@@ -1,5 +0,0 @@
-#! /usr/bin/env bash
-# Critical to get rid of old versions, since they will break the install, since
-# at some point one of the libraries accidently links against what's in SAGE_LOCAL,
-# instead of what is in the build directory!
-rm "$SAGE_LOCAL"/lib/libgd.*
diff --git a/build/pkgs/liblzma/distros/fedora.txt b/build/pkgs/liblzma/distros/fedora.txt
index 813a264efd5..87d41237fa8 100644
--- a/build/pkgs/liblzma/distros/fedora.txt
+++ b/build/pkgs/liblzma/distros/fedora.txt
@@ -1 +1,2 @@
-xz xz-devel
+xz
+xz-devel
diff --git a/build/pkgs/liblzma/distros/opensuse.txt b/build/pkgs/liblzma/distros/opensuse.txt
index f84d903df3e..96db709ccb8 100644
--- a/build/pkgs/liblzma/distros/opensuse.txt
+++ b/build/pkgs/liblzma/distros/opensuse.txt
@@ -1,2 +1,2 @@
xz
-"pkgconfig(liblzma)"
+pkgconfig(liblzma)
diff --git a/build/pkgs/libogg/distros/opensuse.txt b/build/pkgs/libogg/distros/opensuse.txt
index 886b7534f7b..cab88ad14f1 100644
--- a/build/pkgs/libogg/distros/opensuse.txt
+++ b/build/pkgs/libogg/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(ogg)"
+pkgconfig(ogg)
diff --git a/build/pkgs/libpng/distros/opensuse.txt b/build/pkgs/libpng/distros/opensuse.txt
index 3283fd2e697..40ec3d0a25c 100644
--- a/build/pkgs/libpng/distros/opensuse.txt
+++ b/build/pkgs/libpng/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(libpng16)"
+pkgconfig(libpng16)
diff --git a/build/pkgs/libsemigroups/distros/opensuse.txt b/build/pkgs/libsemigroups/distros/opensuse.txt
index aca27d4e0e3..3e58abf59c9 100644
--- a/build/pkgs/libsemigroups/distros/opensuse.txt
+++ b/build/pkgs/libsemigroups/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(libsemigroups)"
+pkgconfig(libsemigroups)
diff --git a/build/pkgs/libtheora/distros/opensuse.txt b/build/pkgs/libtheora/distros/opensuse.txt
index 19826d2aea6..156db81fdea 100644
--- a/build/pkgs/libtheora/distros/opensuse.txt
+++ b/build/pkgs/libtheora/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(theora)"
+pkgconfig(theora)
diff --git a/build/pkgs/linbox/distros/opensuse.txt b/build/pkgs/linbox/distros/opensuse.txt
index 1a52a7c51d3..efef6e5c743 100644
--- a/build/pkgs/linbox/distros/opensuse.txt
+++ b/build/pkgs/linbox/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(linbox)"
+pkgconfig(linbox)
diff --git a/build/pkgs/m4ri/distros/opensuse.txt b/build/pkgs/m4ri/distros/opensuse.txt
index c2a7c2c8f93..ea526e29d8e 100644
--- a/build/pkgs/m4ri/distros/opensuse.txt
+++ b/build/pkgs/m4ri/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(m4ri)"
+pkgconfig(m4ri)
diff --git a/build/pkgs/m4ri/spkg-install.in b/build/pkgs/m4ri/spkg-install.in
index c3ae2270406..0af3234ed16 100644
--- a/build/pkgs/m4ri/spkg-install.in
+++ b/build/pkgs/m4ri/spkg-install.in
@@ -24,9 +24,6 @@ else
DISABLE_SSE2=""
fi
-# otherwise we might run into problems with old headers
-rm -rf "$SAGE_LOCAL/include/m4ri"
-
cd src
# Configure and build M4RI
diff --git a/build/pkgs/m4rie/distros/opensuse.txt b/build/pkgs/m4rie/distros/opensuse.txt
index 4b8fbfa44df..78287631a6b 100644
--- a/build/pkgs/m4rie/distros/opensuse.txt
+++ b/build/pkgs/m4rie/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(m4rie)"
+pkgconfig(m4rie)
diff --git a/build/pkgs/m4rie/spkg-install.in b/build/pkgs/m4rie/spkg-install.in
index 925706f0581..bc0c13ffe1e 100644
--- a/build/pkgs/m4rie/spkg-install.in
+++ b/build/pkgs/m4rie/spkg-install.in
@@ -27,12 +27,6 @@ export CFLAGS
export CPPFLAGS
export LDFLAGS
-# otherwise we might run into problems with old headers
-
-if [ -d "$SAGE_LOCAL/include/m4rie" ]; then
- rm -rf "$SAGE_LOCAL/include/m4rie"
-fi
-
# build M4RIE
cd $ROOT_DIR/src/
diff --git a/build/pkgs/mathjax/distros/gentoo.txt b/build/pkgs/mathjax/distros/gentoo.txt
index a347f8c2348..e0d633a9b98 100644
--- a/build/pkgs/mathjax/distros/gentoo.txt
+++ b/build/pkgs/mathjax/distros/gentoo.txt
@@ -1 +1 @@
-">=dev-libs/mathjax-3"
+>=dev-libs/mathjax-3
diff --git a/build/pkgs/mathjax/spkg-install.in b/build/pkgs/mathjax/spkg-install.in
index 31cdb426992..2eeaf6e84b4 100644
--- a/build/pkgs/mathjax/spkg-install.in
+++ b/build/pkgs/mathjax/spkg-install.in
@@ -1,4 +1,2 @@
TARGET="${SAGE_SHARE}/mathjax"
-# Cleanup installed version
-rm -rf "${TARGET}"
sdh_install src/* "${TARGET}"
diff --git a/build/pkgs/meataxe/spkg-install.in b/build/pkgs/meataxe/spkg-install.in
index 433e5ba7c86..231519fac23 100644
--- a/build/pkgs/meataxe/spkg-install.in
+++ b/build/pkgs/meataxe/spkg-install.in
@@ -1,16 +1,3 @@
-# Delete old (Shared)MeatAxe libraries. This ensures a sane state if
-# installation of this package fails: the mtx library should exist if
-# and only if meataxe is installed. In detail: the build-time check in
-# src/setup.py checks whether or not the "meataxe" package is
-# marked as installed but the run-time check for the matrix_gfpn_dense
-# module checks whether it can be imported. We need to ensure that these
-# two conditions are equivalent, otherwise strange things can happen.
-# See also https://github.com/sagemath/sage/issues/24359#comment:154
-#
-# This also deletes the static library left behind from the installation
-# of MeatAxe (as opposed to SharedMeatAxe).
-rm -f "$SAGE_LOCAL"/lib/libmtx.*
-
# Directory where executables are installed.
export MTXBIN="$SAGE_LOCAL"/bin
@@ -34,4 +21,3 @@ sdh_make_install
if [ "$SAGE_SPKG_INSTALL_DOCS" = yes ] ; then
$MAKE doc || sdh_die "Error documenting SharedMeatAxe"
fi
-
diff --git a/build/pkgs/mpc/distros/fedora.txt b/build/pkgs/mpc/distros/fedora.txt
index 491a280bb72..19ae194c12c 100644
--- a/build/pkgs/mpc/distros/fedora.txt
+++ b/build/pkgs/mpc/distros/fedora.txt
@@ -1 +1,2 @@
-libmpc libmpc-devel
+libmpc
+libmpc-devel
diff --git a/build/pkgs/mpc/spkg-install.in b/build/pkgs/mpc/spkg-install.in
index b260b531f17..835bcc53ab2 100644
--- a/build/pkgs/mpc/spkg-install.in
+++ b/build/pkgs/mpc/spkg-install.in
@@ -12,13 +12,5 @@ EXTRA=""
sdh_configure $SAGE_CONFIGURE_GMP $SAGE_CONFIGURE_MPFR $EXTRA
sdh_make
-# Cleaning
-echo "Deleting old headers"
-rm -f "$SAGE_LOCAL"/include/mpc.h
-# Do not delete old libraries as this causes gcc to break during
-# parallel builds.
-# echo "Deleting old libraries"
-# rm -f "$SAGE_LOCAL"/lib/libmpc.*
-
# Installing
sdh_make_install
diff --git a/build/pkgs/mpfr/distros/opensuse.txt b/build/pkgs/mpfr/distros/opensuse.txt
index 564517323f0..dadf66949a4 100644
--- a/build/pkgs/mpfr/distros/opensuse.txt
+++ b/build/pkgs/mpfr/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(mpfr)"
+pkgconfig(mpfr)
diff --git a/build/pkgs/mpfr/spkg-install.in b/build/pkgs/mpfr/spkg-install.in
index a0ecd15ec43..b377e0a93b6 100644
--- a/build/pkgs/mpfr/spkg-install.in
+++ b/build/pkgs/mpfr/spkg-install.in
@@ -145,14 +145,6 @@ mpfr_build()
{
mpfr_configure
sdh_make
-
- echo
- echo "Building MPFR succeeded. Now deleting old headers..."
- rm -f "$SAGE_LOCAL"/include/*mpfr*
- # Do not delete old libraries as this causes gcc to break during
- # parallel builds.
- # rm -f "$SAGE_LOCAL"/lib/libmpfr.*
-
sdh_make_install
}
diff --git a/build/pkgs/mpfrcx/spkg-legacy-uninstall b/build/pkgs/mpfrcx/spkg-legacy-uninstall
deleted file mode 100755
index 3538ccc54e4..00000000000
--- a/build/pkgs/mpfrcx/spkg-legacy-uninstall
+++ /dev/null
@@ -1,4 +0,0 @@
-#! /usr/bin/env bash
-echo "Deleting old headers"
-rm -f "$SAGE_LOCAL"/include/mpfrcx.h
-rm -f "$SAGE_LOCAL"/lib/libmpfrcx.*
diff --git a/build/pkgs/nauty/checksums.ini b/build/pkgs/nauty/checksums.ini
index a9dd1246e91..f699a05e9fc 100644
--- a/build/pkgs/nauty/checksums.ini
+++ b/build/pkgs/nauty/checksums.ini
@@ -1,5 +1,5 @@
-tarball=nautyVERSION.tar.gz
-sha1=10c39117c55c69c18c6a107110e7c08f3d873652
-md5=7a82f4209f5d552da3078c67e5af872e
-cksum=2164796643
-upstream_url=https://pallini.di.uniroma1.it/nauty2_8_6.tar.gz
+tarball=nauty${VERSION}.tar.gz
+sha1=672e9fc9dfd07201af37ee65807a9b493331ed92
+md5=16c6edc1a8747c9281041b7c7092135f
+cksum=2663136901
+upstream_url=https://pallini.di.uniroma1.it/nauty${VERSION_MAJOR}_${VERSION_MINOR}_${VERSION_MICRO}.tar.gz
diff --git a/build/pkgs/nauty/package-version.txt b/build/pkgs/nauty/package-version.txt
index 04e60eaa37a..b8635c72de3 100644
--- a/build/pkgs/nauty/package-version.txt
+++ b/build/pkgs/nauty/package-version.txt
@@ -1 +1 @@
-2.8.6.p1
+2.8.8.p0
diff --git a/build/pkgs/nauty/patches/nauty-2.8.6-gentreeg-gentourng.patch b/build/pkgs/nauty/patches/nauty-2.8.6-gentreeg-gentourng.patch
deleted file mode 100644
index 322b25326ee..00000000000
--- a/build/pkgs/nauty/patches/nauty-2.8.6-gentreeg-gentourng.patch
+++ /dev/null
@@ -1,144 +0,0 @@
-From edb0474a4db8e69f971e4eebe18716309f5a7bb3 Mon Sep 17 00:00:00 2001
-From: Michael Orlitzky
-Date: Tue, 17 Jan 2023 19:44:49 -0500
-Subject: [PATCH 1/1] Upstream fixes for gentreeg and gentourng.
-
-https://mailman.anu.edu.au/pipermail/nauty/2023-January/000903.html
----
- gentourng.c | 2 +-
- gentreeg.c | 95 ++++++++++++++++++++++++++++-------------------------
- 2 files changed, 51 insertions(+), 46 deletions(-)
-
-diff --git a/gentourng.c b/gentourng.c
-index 634e5e8..5c7ffff 100644
---- a/gentourng.c
-+++ b/gentourng.c
-@@ -1408,7 +1408,7 @@ PLUGIN_INIT
- (*outproc)(outfile,g,1);
- }
- }
-- else
-+ else if (!connec || maxn != 2)
- {
- makeleveldata();
-
-diff --git a/gentreeg.c b/gentreeg.c
-index 946d5f8..15bf87b 100644
---- a/gentreeg.c
-+++ b/gentreeg.c
-@@ -1,4 +1,4 @@
--/* gentree version 1.3; Brendan McKay Oct 2022 */
-+/* gentree version 1.4; Brendan McKay Dec 2022 */
- /* This program is a wrapper for the program FreeTrees.c written
- * by Gang Li & Frank Ruskey. See below for their original
- * comments. */
-@@ -32,49 +32,54 @@ Counts for n=1..45:
- 1: 1
- 2: 1
- 3: 1
-- 4: 1
-- 5: 2
-- 6: 3
-- 7: 6
-- 8: 11
-- 9: 23
--10: 47
--11: 106
--12: 235
--13: 551
--14: 1301
--15: 3159
--16: 7741
--17: 19320
--18: 48629
--19: 123867
--20: 317955
--21: 823065
--22: 2144505
--23: 5623756
--24: 14828074
--25: 39299897
--26: 104636890
--27: 279793450
--28: 751065460
--29: 2023443032
--30: 5469566585
--31: 14830871802
--32: 40330829030
--33: 109972410221
--34: 300628862480
--35: 823779631721
--36: 2262366343746
--37: 6226306037178
--38: 17169677490714
--39: 47436313524262
--40: 131290543779126
--41: 363990257783343
--42: 1010748076717151
--43: 2810986483493475
--44: 7828986221515605
--45: 21835027912963086
--********************************/
-+ 4: 2
-+ 5: 3
-+ 6: 6
-+ 7: 11
-+ 8: 23
-+ 9: 47
-+10: 106
-+11: 235
-+12: 551
-+13: 1301
-+14: 3159
-+15: 7741
-+16: 19320
-+17: 48629
-+18: 123867
-+19: 317955
-+20: 823065
-+21: 2144505
-+22: 5623756
-+23: 14828074
-+24: 39299897
-+25: 104636890
-+26: 279793450
-+27: 751065460
-+28: 2023443032
-+29: 5469566585
-+30: 14830871802
-+31: 40330829030
-+32: 109972410221
-+33: 300628862480
-+34: 823779631721
-+35: 2262366343746
-+36: 6226306037178
-+37: 17169677490714
-+38: 47436313524262
-+39: 131290543779126
-+40: 363990257783343
-+41: 1010748076717151
-+42: 2810986483493475
-+43: 7828986221515605
-+44: 21835027912963086
-+45: 60978390985918906
-+46: 170508699155987862
-+47: 477355090753926460
-+48: 1337946100045842285
-+49: 3754194185716399992
-+50: 10545233702911509534
-+*******************************/
-
- /* Comments on original program by original authors */
- /*==============================================================*/
-@@ -676,7 +681,7 @@ PLUGIN_INIT
- }
- else if (nv == 2)
- {
-- if (res == 0 && maxdeg >= 1 && mindiam <= 1 && maxdiam >= 2)
-+ if (res == 0 && maxdeg >= 1 && mindiam <= 1 && maxdiam >= 1)
- {
- par[1] = 0;
- par[2] = 1;
---
-2.38.2
-
diff --git a/build/pkgs/nauty/spkg-configure.m4 b/build/pkgs/nauty/spkg-configure.m4
index 4d5bbcf2091..a0873e355c4 100644
--- a/build/pkgs/nauty/spkg-configure.m4
+++ b/build/pkgs/nauty/spkg-configure.m4
@@ -1,12 +1,9 @@
-# We don't use the "converseg" program, but we need to ensure that we
-# only detect nauty >= 2.6 because we use the digraph6 format from
-# that version -- and converseg was added in nauty-2.6.
-#
-# We also don't use the "genposetg" program (added in nauty 2.8) yet.
-# We require it here to prepare Sage for the use of the major new features
-# added in 2.7 and 2.8 (https://pallini.di.uniroma1.it/changes24-28.txt).
+# We use the "genktreeg" program (added in nauty 2.8.8). This ensures that we
+# detect nauty >= 2.8.8 and so we can use the major new features added in nauty
+# since version 2.6. For instance, we use the digraph6 format from nauty >= 2.6
+# (https://pallini.di.uniroma1.it/changes24-28.txt).
AC_DEFUN([SAGE_TEST_NAUTY_PROGS], [
- m4_foreach([nautyprog], [directg, gentourng, geng, genbg, gentreeg, converseg, genposetg], [
+ m4_foreach([nautyprog], [directg, gentourng, geng, genbg, gentreeg, genktreeg, genposetg], [
AC_PATH_PROG([$2]nautyprog, [[$1]nautyprog])
AS_IF([test x$[$2]nautyprog = x], [sage_spkg_install_nauty=yes])
])
diff --git a/build/pkgs/nauty/spkg-install.in b/build/pkgs/nauty/spkg-install.in
index 5a2f957511d..a2557c3cd8e 100644
--- a/build/pkgs/nauty/spkg-install.in
+++ b/build/pkgs/nauty/spkg-install.in
@@ -13,11 +13,12 @@ sdh_make
# No install target so we resort to manual copy
PROGRAMS="
-addedgeg addptg amtog ancestorg assembleg biplabg catg complg converseg copyg countg cubhamg deledgeg
-delptg dimacs2g directg dreadnaut dretodot dretog edgetransg genbg genbgL geng gengL genposetg genquarticg genrang
-genspecialg gentourng gentreeg hamheuristic labelg linegraphg listg multig nbrhoodg
-newedgeg pickg planarg productg ranlabg shortg showg subdivideg twohamg underlyingg vcolg
-watercluster2 NRswitchg"
+addedgeg addptg amtog ancestorg assembleg biplabg catg complg converseg copyg
+countg countneg cubhamg deledgeg delptg dimacs2g directg dreadnaut dretodot
+dretog edgetransg genbg genbgL geng gengL genposetg genquarticg genrang
+genspecialg gentourng gentreeg genktreeg hamheuristic labelg linegraphg listg
+multig nbrhoodg newedgeg pickg planarg productg ranlabg ransubg shortg showg
+subdivideg twohamg underlyingg vcolg watercluster2 NRswitchg"
sdh_install $PROGRAMS "$SAGE_LOCAL/bin"
sdh_install nauty.h "$SAGE_LOCAL/include/nauty"
diff --git a/build/pkgs/nbconvert/spkg-install.in b/build/pkgs/nbconvert/spkg-install.in
deleted file mode 100644
index deba1bb42bb..00000000000
--- a/build/pkgs/nbconvert/spkg-install.in
+++ /dev/null
@@ -1 +0,0 @@
-cd src && sdh_pip_install .
diff --git a/build/pkgs/ncurses/distros/opensuse.txt b/build/pkgs/ncurses/distros/opensuse.txt
index b31c6886b17..f50c62d6ac4 100644
--- a/build/pkgs/ncurses/distros/opensuse.txt
+++ b/build/pkgs/ncurses/distros/opensuse.txt
@@ -1,2 +1,2 @@
-"pkgconfig(ncurses)"
-"pkgconfig(ncursesw)"
+pkgconfig(ncurses)
+pkgconfig(ncursesw)
diff --git a/build/pkgs/networkx/checksums.ini b/build/pkgs/networkx/checksums.ini
index dd792a15a2e..6daf026581b 100644
--- a/build/pkgs/networkx/checksums.ini
+++ b/build/pkgs/networkx/checksums.ini
@@ -1,5 +1,5 @@
tarball=networkx-VERSION.tar.gz
-sha1=d4b1d6117b7c54db61f6cbec8f0ccfb0f7d47293
-md5=1a9baa93b7fd4470c80e29a7a6d93ccf
-cksum=1675580484
+sha1=b12cf95ed8bc3fe568e3c8e023473a3767c43f8d
+md5=e81583dcb3d929b60660721912f3faed
+cksum=2601544693
upstream_url=https://pypi.io/packages/source/n/networkx/networkx-VERSION.tar.gz
diff --git a/build/pkgs/networkx/package-version.txt b/build/pkgs/networkx/package-version.txt
index 8c50098d8ae..e4604e3afd0 100644
--- a/build/pkgs/networkx/package-version.txt
+++ b/build/pkgs/networkx/package-version.txt
@@ -1 +1 @@
-3.1
+3.2.1
diff --git a/build/pkgs/ninja_build/spkg-configure.m4 b/build/pkgs/ninja_build/spkg-configure.m4
index fb6c4f00985..5b83d189801 100644
--- a/build/pkgs/ninja_build/spkg-configure.m4
+++ b/build/pkgs/ninja_build/spkg-configure.m4
@@ -3,8 +3,10 @@ SAGE_SPKG_CONFIGURE(
dnl meson_python needs 1.8.2 or later
AC_CACHE_CHECK([for ninja >= 1.8.2], [ac_cv_path_NINJA], [
AC_PATH_PROGS_FEATURE_CHECK([NINJA], [ninja], [
+ dnl support both two- and three-component version schemes
+ dnl since samurai (a ninja alternative) uses two
ninja_version=`$ac_path_NINJA --version 2>&1 \
- | $SED -n -e 's/\([[0-9]]*\.[[0-9]]*\.[[0-9]]*\).*/\1/p'`
+ | $SED -n -e 's/\([[0-9]]*\(\.[[0-9]]*\)\{1,2\}\).*/\1/p'`
AS_IF([test -n "$ninja_version"], [
AX_COMPARE_VERSION([$ninja_version], [ge], [1.8.2], [
ac_cv_path_NINJA="$ac_path_NINJA"
diff --git a/build/pkgs/normaliz/package-version.txt b/build/pkgs/normaliz/package-version.txt
index f870be23bad..2377fe517a0 100644
--- a/build/pkgs/normaliz/package-version.txt
+++ b/build/pkgs/normaliz/package-version.txt
@@ -1 +1 @@
-3.10.1
+3.10.1.p0
diff --git a/build/pkgs/normaliz/patches/flint3_d-torrance.patch b/build/pkgs/normaliz/patches/flint3_d-torrance.patch
new file mode 100644
index 00000000000..5a6e36c51c4
--- /dev/null
+++ b/build/pkgs/normaliz/patches/flint3_d-torrance.patch
@@ -0,0 +1,55 @@
+--- a/source/libnormaliz/vector_operations.h
++++ b/source/libnormaliz/vector_operations.h
+@@ -547,7 +547,10 @@
+
+ fmpq_poly_fit_length(flp, n);
+ for (size_t i = 0; i < poly_vector.size(); ++i) {
+- fmpq_poly_set_coeff_mpq(flp, (slong)i, poly_vector[i].get_mpq_t());
++ fmpq_t fcurrent_coeff;
++ fmpq_init(fcurrent_coeff);
++ fmpq_set_mpq(fcurrent_coeff, poly_vector[i].get_mpq_t());
++ fmpq_poly_set_coeff_fmpq(flp, (slong)i, fcurrent_coeff);
+ }
+ }
+
+@@ -560,8 +563,11 @@
+ poly_vector.resize(length);
+ for (slong i = 0; i < length; i++) {
+ mpq_t current_coeff;
++ fmpq_t fcurrent_coeff;
+ mpq_init(current_coeff);
+- fmpq_poly_get_coeff_mpq(current_coeff, flp, (slong)i);
++ fmpq_init(fcurrent_coeff);
++ fmpq_poly_get_coeff_fmpq(fcurrent_coeff, flp, (slong)i);
++ fmpq_get_mpq(current_coeff, fcurrent_coeff);
+ poly_vector[i] = mpq_class(current_coeff);
+ }
+ }
+--- a/source/libnormaliz/HilbertSeries.cpp
++++ b/source/libnormaliz/HilbertSeries.cpp
+@@ -72,7 +72,10 @@
+ slong n = (slong)nmzp.size();
+ fmpz_poly_fit_length(flp, n);
+ for (size_t i = 0; i < nmzp.size(); ++i) {
+- fmpz_poly_set_coeff_mpz(flp, (slong)i, nmzp[i].get_mpz_t());
++ fmpz_t fc;
++ fmpz_init(fc);
++ fmpz_set_mpz(fc, nmzp[i].get_mpz_t());
++ fmpz_poly_set_coeff_fmpz(flp, (slong)i, fc);
+ }
+ }
+
+@@ -80,9 +83,12 @@
+ size_t n = (size_t)fmpz_poly_length(flp);
+ nmzp.resize(n);
+ mpz_t c;
++ fmpz_t fc;
+ mpz_init(c);
++ fmpz_init(fc);
+ for (size_t i = 0; i < nmzp.size(); ++i) {
+- fmpz_poly_get_coeff_mpz(c, flp, i);
++ fmpz_poly_get_coeff_fmpz(fc, flp, i);
++ fmpz_get_mpz(c, fc);
+ nmzp[i] = mpz_class(c);
+ }
+ mpz_clear(c);
diff --git a/build/pkgs/normaliz/spkg-install.in b/build/pkgs/normaliz/spkg-install.in
index 0d329656614..683a3200e5b 100644
--- a/build/pkgs/normaliz/spkg-install.in
+++ b/build/pkgs/normaliz/spkg-install.in
@@ -8,6 +8,8 @@ cd src
# that an error will be signalled if FLINT or E-ANTIC cannot be found, rather
# than building normaliz without it.
+export ac_cv_lib_flint_fmpz_poly_set_coeff_mpz=yes
+
sdh_configure --with-flint --with-e-antic --with-nauty
sdh_make
sdh_make_install
diff --git a/build/pkgs/ntl/spkg-install.in b/build/pkgs/ntl/spkg-install.in
index a26c3b5026e..d82ddf370e5 100644
--- a/build/pkgs/ntl/spkg-install.in
+++ b/build/pkgs/ntl/spkg-install.in
@@ -112,11 +112,6 @@ ntl_build()
ntl_install()
{
- echo
- echo "Removing old NTL files."
- rm -rf "$SAGE_LOCAL"/lib/libntl*
- rm -rf "$SAGE_LOCAL"/include/NTL
-
echo
echo "Installing NTL."
diff --git a/build/pkgs/numpy/spkg-legacy-uninstall b/build/pkgs/numpy/spkg-legacy-uninstall
deleted file mode 100755
index 9cb6a63a5a3..00000000000
--- a/build/pkgs/numpy/spkg-legacy-uninstall
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /usr/bin/env bash
-rm -rf "$SAGE_LOCAL"/lib/python*/site-packages/numpy
diff --git a/build/pkgs/openblas/distros/cygwin.txt b/build/pkgs/openblas/distros/cygwin.txt
index d2146131e38..055fa2733d1 100644
--- a/build/pkgs/openblas/distros/cygwin.txt
+++ b/build/pkgs/openblas/distros/cygwin.txt
@@ -1 +1,2 @@
-liblapack-devel libopenblas
+liblapack-devel
+libopenblas
diff --git a/build/pkgs/openblas/spkg-install.in b/build/pkgs/openblas/spkg-install.in
index 2f8aea512bc..dbfcb6c1a75 100644
--- a/build/pkgs/openblas/spkg-install.in
+++ b/build/pkgs/openblas/spkg-install.in
@@ -59,9 +59,6 @@ if ! (sdh_make libs $OPENBLAS_CONFIGURE && sdh_make netlib $OPENBLAS_CONFIGURE &
fi
fi
-# See https://github.com/sagemath/sage/issues/30335
-rm -f "$SAGE_LOCAL/lib/pkgconfig/cblas.pc" "$SAGE_LOCAL/lib/pkgconfig/blas.pc" "$SAGE_LOCAL/lib/pkgconfig/lapack.pc"
-
sdh_make_install PREFIX="$SAGE_LOCAL" NO_STATIC=1 $OPENBLAS_CONFIGURE
cd ..
./write_pc_file.py
diff --git a/build/pkgs/openblas/spkg-preinst.in b/build/pkgs/openblas/spkg-preinst.in
new file mode 100644
index 00000000000..ced306d2d4e
--- /dev/null
+++ b/build/pkgs/openblas/spkg-preinst.in
@@ -0,0 +1,2 @@
+# See https://github.com/sagemath/sage/issues/30335
+rm -f "$SAGE_LOCAL/lib/pkgconfig/cblas.pc" "$SAGE_LOCAL/lib/pkgconfig/blas.pc" "$SAGE_LOCAL/lib/pkgconfig/lapack.pc"
diff --git a/build/pkgs/openssl/distros/fedora.txt b/build/pkgs/openssl/distros/fedora.txt
index dda63a9f276..a9579db4fca 100644
--- a/build/pkgs/openssl/distros/fedora.txt
+++ b/build/pkgs/openssl/distros/fedora.txt
@@ -1 +1,2 @@
-openssl openssl-devel
+openssl
+openssl-devel
diff --git a/build/pkgs/openssl/distros/slackware.txt b/build/pkgs/openssl/distros/slackware.txt
index 6ed59c09128..14c745a6bc8 100644
--- a/build/pkgs/openssl/distros/slackware.txt
+++ b/build/pkgs/openssl/distros/slackware.txt
@@ -1 +1,2 @@
-openssl openssl-solibs
+openssl
+openssl-solibs
diff --git a/build/pkgs/pari/distros/conda.txt b/build/pkgs/pari/distros/conda.txt
index 88ec4bef346..018d16817d3 100644
--- a/build/pkgs/pari/distros/conda.txt
+++ b/build/pkgs/pari/distros/conda.txt
@@ -1,3 +1,6 @@
pari=*=*_pthread
# We add these data packages because they are checked by spkg-configure.m4
-pari-elldata pari-galdata pari-galpol pari-seadata
+pari-elldata
+pari-galdata
+pari-galpol
+pari-seadata
diff --git a/build/pkgs/pari/distros/fedora.txt b/build/pkgs/pari/distros/fedora.txt
index 95ba141d56c..d315900766c 100644
--- a/build/pkgs/pari/distros/fedora.txt
+++ b/build/pkgs/pari/distros/fedora.txt
@@ -2,7 +2,8 @@ pari-devel
# spkg-configure checks for gp, gphelp. Access to the documentation is crucial
# for the cypari2 build. #29342: By default configuration in /etc/dnf/dnf.conf,
# installation of documentation may be suppressed; we override this.
-pari-gp --setopt=tsflags=
+pari-gp
+--setopt=tsflags=
# spkg-configure checks for data
pari-galdata
pari-galpol
diff --git a/build/pkgs/pari/distros/gentoo.txt b/build/pkgs/pari/distros/gentoo.txt
index 449975ac8e1..cd13d54e8cc 100644
--- a/build/pkgs/pari/distros/gentoo.txt
+++ b/build/pkgs/pari/distros/gentoo.txt
@@ -1 +1,2 @@
-sci-mathematics/pari sci-mathematics/pari-data
+sci-mathematics/pari
+sci-mathematics/pari-data
diff --git a/build/pkgs/pari/distros/macports.txt b/build/pkgs/pari/distros/macports.txt
index 67abbc9dec6..8960baaba3e 100644
--- a/build/pkgs/pari/distros/macports.txt
+++ b/build/pkgs/pari/distros/macports.txt
@@ -1 +1,2 @@
-pari
+# incomplete, unusable for sage, causes cysignals build failure
+#pari
diff --git a/build/pkgs/pathspec/checksums.ini b/build/pkgs/pathspec/checksums.ini
index a98c270d6e1..a562884cca1 100644
--- a/build/pkgs/pathspec/checksums.ini
+++ b/build/pkgs/pathspec/checksums.ini
@@ -1,5 +1,5 @@
-tarball=pathspec-VERSION.tar.gz
-sha1=418ae4112af18af995c0f20a22e5a903b8ce50ae
-md5=28c87c3581b10152c4581d10fe33f765
-cksum=2161527634
-upstream_url=https://pypi.io/packages/source/p/pathspec/pathspec-VERSION.tar.gz
+tarball=pathspec-VERSION-py3-none-any.whl
+sha1=e31b7b2b1a59ab192eb2e92ac283211a11039769
+md5=53caa061bbda861c5b4766f41b084ec8
+cksum=1745881358
+upstream_url=https://pypi.io/packages/py3/p/pathspec/pathspec-VERSION-py3-none-any.whl
diff --git a/build/pkgs/pathspec/dependencies b/build/pkgs/pathspec/dependencies
index 47296a7bace..644ad35f773 100644
--- a/build/pkgs/pathspec/dependencies
+++ b/build/pkgs/pathspec/dependencies
@@ -1,4 +1,4 @@
- | $(PYTHON_TOOLCHAIN) $(PYTHON)
+ | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/pathspec/package-version.txt b/build/pkgs/pathspec/package-version.txt
index 5eef0f10e8c..34a83616bb5 100644
--- a/build/pkgs/pathspec/package-version.txt
+++ b/build/pkgs/pathspec/package-version.txt
@@ -1 +1 @@
-0.10.2
+0.12.1
diff --git a/build/pkgs/pathspec/spkg-install.in b/build/pkgs/pathspec/spkg-install.in
deleted file mode 100644
index 37ac1a53437..00000000000
--- a/build/pkgs/pathspec/spkg-install.in
+++ /dev/null
@@ -1,2 +0,0 @@
-cd src
-sdh_pip_install .
diff --git a/build/pkgs/perl_term_readline_gnu/distros/opensuse.txt b/build/pkgs/perl_term_readline_gnu/distros/opensuse.txt
index ba80f6c445f..60563e056ca 100644
--- a/build/pkgs/perl_term_readline_gnu/distros/opensuse.txt
+++ b/build/pkgs/perl_term_readline_gnu/distros/opensuse.txt
@@ -1 +1 @@
-"perl(Term::ReadLine::Gnu)"
+perl(Term::ReadLine::Gnu)
diff --git a/build/pkgs/pip/checksums.ini b/build/pkgs/pip/checksums.ini
index 52c2edb31f2..0558c5caa45 100644
--- a/build/pkgs/pip/checksums.ini
+++ b/build/pkgs/pip/checksums.ini
@@ -1,5 +1,5 @@
-tarball=pip-VERSION.tar.gz
-sha1=d1400a4eb662e4741ac68957f47bc97d600743f8
-md5=f0c9fba61e9d9badcc9921062e993d84
-cksum=309527365
-upstream_url=https://pypi.io/packages/source/p/pip/pip-VERSION.tar.gz
+tarball=pip-VERSION-py3-none-any.whl
+sha1=4b2baddc0673f73017e531648a9ee27e47925e7a
+md5=5d2d058044a3ae2800d18e358ddc72ca
+cksum=1470281176
+upstream_url=https://pypi.io/packages/py3/p/pip/pip-VERSION-py3-none-any.whl
diff --git a/build/pkgs/pip/dependencies b/build/pkgs/pip/dependencies
index dac3579f7e3..d45a397db36 100644
--- a/build/pkgs/pip/dependencies
+++ b/build/pkgs/pip/dependencies
@@ -1,4 +1,4 @@
- setuptools wheel | $(PYTHON)
+ | $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/pip/spkg-install.in b/build/pkgs/pip/spkg-install.in
index 651f5c1dc1e..567543149db 100644
--- a/build/pkgs/pip/spkg-install.in
+++ b/build/pkgs/pip/spkg-install.in
@@ -1,11 +1,6 @@
-cd src
+# pip can install its own wheel! But first we need to ensure that the
+# wheel file is on the PYTHONPATH
+export PYTHONPATH=$(pwd)/$(cd dist && for w in *.whl; do cp $w ..; echo $w; break; done)
-sdh_setup_bdist_wheel
-
-# pip can install its own wheel! But first we need to ensure that the pip
-# source directory in on the PYTHONPATH
-export PYTHONPATH="$(pwd)/src"
-
-# --ignore-installed makes sure that pip does not mistake
-# its own source tree as an existing installation
-sdh_store_and_pip_install_wheel --ignore-installed .
+# This line is the same as what sage-spkg uses to install the wheel.
+sdh_store_and_pip_install_wheel .
diff --git a/build/pkgs/pip/spkg-pipinst.in b/build/pkgs/pip/spkg-pipinst.in
index 3e3f6bbc94e..61007a3b8c8 100644
--- a/build/pkgs/pip/spkg-pipinst.in
+++ b/build/pkgs/pip/spkg-pipinst.in
@@ -1,5 +1,3 @@
-cd src
-
# pip can install its own wheel! But first we need to ensure that the pip
-# source directory in on the PYTHONPATH
-export PYTHONPATH="$(pwd)/src"
+# wheelfile is on the PYTHONPATH
+export PYTHONPATH=$(pwd)/$(echo *.whl)
diff --git a/build/pkgs/planarity/checksums.ini b/build/pkgs/planarity/checksums.ini
index 6227637695a..309daa93278 100644
--- a/build/pkgs/planarity/checksums.ini
+++ b/build/pkgs/planarity/checksums.ini
@@ -2,4 +2,4 @@ tarball=planarity-VERSION.tar.gz
sha1=8407bccf33c07bf0dae22d79b5e6ac7d89c62ea3
md5=200116e6a67544c8e94f9de7c3ba1b1a
cksum=4207261512
-upstream_url=http://users.ox.ac.uk/~coml0531/sage/planarity-3.0.1.0.tar.gz
+upstream_url=http://users.ox.ac.uk/~coml0531/sage/planarity-VERSION.tar.gz
diff --git a/build/pkgs/planarity/distros/fedora.txt b/build/pkgs/planarity/distros/fedora.txt
index b107ebbf96f..e3d211ca5d1 100644
--- a/build/pkgs/planarity/distros/fedora.txt
+++ b/build/pkgs/planarity/distros/fedora.txt
@@ -1 +1,2 @@
-planarity planarity-devel
+planarity
+planarity-devel
diff --git a/build/pkgs/plantri/checksums.ini b/build/pkgs/plantri/checksums.ini
index 05dc13d01e7..f999a981a69 100644
--- a/build/pkgs/plantri/checksums.ini
+++ b/build/pkgs/plantri/checksums.ini
@@ -1,5 +1,5 @@
-tarball=plantri53.tar.gz
+tarball=plantri${VERSION_MAJOR}${VERSION_MINOR}.tar.gz
sha1=a04aec2fa90c43f1c9bef59d041a54d8fa5bf562
md5=ea765b3508dd56384f94ad1f032e2dd4
cksum=3200215885
-upstream_url=https://users.cecs.anu.edu.au/~bdm/plantri/plantri53.tar.gz
+upstream_url=https://users.cecs.anu.edu.au/~bdm/plantri/plantri${VERSION_MAJOR}${VERSION_MINOR}.tar.gz
diff --git a/build/pkgs/platformdirs/checksums.ini b/build/pkgs/platformdirs/checksums.ini
index 99113c48626..3757f701faf 100644
--- a/build/pkgs/platformdirs/checksums.ini
+++ b/build/pkgs/platformdirs/checksums.ini
@@ -1,5 +1,5 @@
-tarball=platformdirs-VERSION.tar.gz
-sha1=82e215dc9c45eedf9168584fede36d795714f677
-md5=a6ba3a442347fac346982acb597c8bf8
-cksum=2465457023
-upstream_url=https://pypi.io/packages/source/p/platformdirs/platformdirs-VERSION.tar.gz
+tarball=platformdirs-VERSION-py3-none-any.whl
+sha1=cafa761738da959f2df0a8a92da4c72fd8eaf93e
+md5=487007776ff343efc509b68d08cd7fd7
+cksum=162426958
+upstream_url=https://pypi.io/packages/py3/p/platformdirs/platformdirs-VERSION-py3-none-any.whl
diff --git a/build/pkgs/platformdirs/dependencies b/build/pkgs/platformdirs/dependencies
index 952ebfb66cd..644ad35f773 100644
--- a/build/pkgs/platformdirs/dependencies
+++ b/build/pkgs/platformdirs/dependencies
@@ -1,4 +1,4 @@
- setuptools_scm | $(PYTHON_TOOLCHAIN) hatchling hatch_vcs $(PYTHON)
+ | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/platformdirs/package-version.txt b/build/pkgs/platformdirs/package-version.txt
index afad818663d..ee74734aa22 100644
--- a/build/pkgs/platformdirs/package-version.txt
+++ b/build/pkgs/platformdirs/package-version.txt
@@ -1 +1 @@
-3.11.0
+4.1.0
diff --git a/build/pkgs/platformdirs/spkg-install.in b/build/pkgs/platformdirs/spkg-install.in
deleted file mode 100644
index 37ac1a53437..00000000000
--- a/build/pkgs/platformdirs/spkg-install.in
+++ /dev/null
@@ -1,2 +0,0 @@
-cd src
-sdh_pip_install .
diff --git a/build/pkgs/pluggy/dependencies b/build/pkgs/pluggy/dependencies
index 47296a7bace..644ad35f773 100644
--- a/build/pkgs/pluggy/dependencies
+++ b/build/pkgs/pluggy/dependencies
@@ -1,4 +1,4 @@
- | $(PYTHON_TOOLCHAIN) $(PYTHON)
+ | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/polylib/distros/opensuse.txt b/build/pkgs/polylib/distros/opensuse.txt
index f6432c31dfe..8b7f1e54de7 100644
--- a/build/pkgs/polylib/distros/opensuse.txt
+++ b/build/pkgs/polylib/distros/opensuse.txt
@@ -1,2 +1,2 @@
polylib
-"pkgconfig(polylibgmp)"
+pkgconfig(polylibgmp)
diff --git a/build/pkgs/polytopes_db_4d/checksums.ini b/build/pkgs/polytopes_db_4d/checksums.ini
index edfee6b7841..d87e456c4a8 100644
--- a/build/pkgs/polytopes_db_4d/checksums.ini
+++ b/build/pkgs/polytopes_db_4d/checksums.ini
@@ -2,4 +2,4 @@ tarball=polytopes_db_4d-VERSION.spkg
sha1=c9779821e365df2d7f9bc684f9e2ec0e95fb8650
md5=fe775a26fd7b2afc187e9bfabfb1b86a
cksum=3415837678
-upstream_url=http://ftp.sparcs.org/sage/spkg/huge/polytopes_db_4d-1.0.spkg
+upstream_url=http://ftp.sparcs.org/sage/spkg/huge/polytopes_db_4d-VERSION.spkg
diff --git a/build/pkgs/ptyprocess/distros/conda.txt b/build/pkgs/ptyprocess/distros/conda.txt
index 4a518435c60..964d3f79453 100644
--- a/build/pkgs/ptyprocess/distros/conda.txt
+++ b/build/pkgs/ptyprocess/distros/conda.txt
@@ -1,3 +1,3 @@
# The version should be fixed to 0.5.1 (see https://github.com/sagemath/sage/issues/32147), but this is not available on conda-forge
-# thus don't install ptyprocess with conda, but let pip handle it
+# thus don't install ptyprocess with conda, but let pip handle it
# ptyprocess
diff --git a/build/pkgs/pycygwin/SPKG.rst b/build/pkgs/pycygwin/SPKG.rst
deleted file mode 100644
index fdf67a08dc1..00000000000
--- a/build/pkgs/pycygwin/SPKG.rst
+++ /dev/null
@@ -1,14 +0,0 @@
-pycygwin: Python bindings for Cygwin's C API
-============================================
-
-Description
------------
-
-Python bindings for Cygwin's C API. Provides some utilities to help with
-the Cygwin port. Naturally, this package should only be installed on
-Cygwin--for other platforms its installation is a no-op.
-
-Website
--------
-
-https://github.com/embray/PyCygwin
diff --git a/build/pkgs/pycygwin/checksums.ini b/build/pkgs/pycygwin/checksums.ini
deleted file mode 100644
index 7ce896982a4..00000000000
--- a/build/pkgs/pycygwin/checksums.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-tarball=PyCygwin-VERSION.tar.gz
-sha1=4021dbf77c353051761d277f5490b38a701ba51b
-md5=12c30c847b144282178bc546d4e2cbcd
-cksum=2254892419
diff --git a/build/pkgs/pycygwin/dependencies b/build/pkgs/pycygwin/dependencies
deleted file mode 100644
index 1db13c07e43..00000000000
--- a/build/pkgs/pycygwin/dependencies
+++ /dev/null
@@ -1,4 +0,0 @@
- cython | $(PYTHON_TOOLCHAIN) $(PYTHON)
-
-----------
-All lines of this file are ignored except the first.
diff --git a/build/pkgs/pycygwin/distros/repology.txt b/build/pkgs/pycygwin/distros/repology.txt
deleted file mode 100644
index eeeab661dc6..00000000000
--- a/build/pkgs/pycygwin/distros/repology.txt
+++ /dev/null
@@ -1 +0,0 @@
-python:pycygwin
diff --git a/build/pkgs/pycygwin/install-requires.txt b/build/pkgs/pycygwin/install-requires.txt
deleted file mode 100644
index 3bec679b60b..00000000000
--- a/build/pkgs/pycygwin/install-requires.txt
+++ /dev/null
@@ -1 +0,0 @@
-pycygwin >=0.1
diff --git a/build/pkgs/pycygwin/package-version.txt b/build/pkgs/pycygwin/package-version.txt
deleted file mode 100644
index 49d59571fbf..00000000000
--- a/build/pkgs/pycygwin/package-version.txt
+++ /dev/null
@@ -1 +0,0 @@
-0.1
diff --git a/build/pkgs/pycygwin/spkg-install.in b/build/pkgs/pycygwin/spkg-install.in
deleted file mode 100644
index eeb8dcdf62c..00000000000
--- a/build/pkgs/pycygwin/spkg-install.in
+++ /dev/null
@@ -1,3 +0,0 @@
-if [ "$UNAME" = "CYGWIN" ]; then
- cd src && sdh_pip_install .
-fi
diff --git a/build/pkgs/pycygwin/type b/build/pkgs/pycygwin/type
deleted file mode 100644
index a6a7b9cd726..00000000000
--- a/build/pkgs/pycygwin/type
+++ /dev/null
@@ -1 +0,0 @@
-standard
diff --git a/build/pkgs/pynormaliz/package-version.txt b/build/pkgs/pynormaliz/package-version.txt
index fc249e9a747..fae0ceb2953 100644
--- a/build/pkgs/pynormaliz/package-version.txt
+++ b/build/pkgs/pynormaliz/package-version.txt
@@ -1 +1 @@
-2.18
+2.18.p0
diff --git a/build/pkgs/python3/distros/macports.txt b/build/pkgs/python3/distros/macports.txt
index 6a2d05c5edb..92826c681b4 100644
--- a/build/pkgs/python3/distros/macports.txt
+++ b/build/pkgs/python3/distros/macports.txt
@@ -1 +1 @@
-python39
+python310
diff --git a/build/pkgs/python3/spkg-build.in b/build/pkgs/python3/spkg-build.in
index 0c08814a242..4cd421bf4b8 100644
--- a/build/pkgs/python3/spkg-build.in
+++ b/build/pkgs/python3/spkg-build.in
@@ -62,17 +62,6 @@ fi
# common in Cython-generated code.
export EXTRA_CFLAGS="`testcflags.sh -Wno-unused $OLD_CFLAGS`"
-# Remove old symbolic link: it is not needed and its presence can
-# interfere with the Python build.
-rm -f "$SAGE_LOCAL/lib/python"
-
-# Remove old libraries. We really need to do this before building Python
-# since Python tries to import some modules (e.g. ctypes) at build-time.
-# We need to make sure that the old installed libraries in local/lib are
-# not used for that. See https://github.com/sagemath/sage/issues/24605
-rm -f "$SAGE_LOCAL"/lib/lib"$PKG_BASE"*
-
-
# Note: --without-ensurepip ensures that setuptools+pip are *not* installed
# automatically when installing python3. They will be installed instead by
# the separate setuptools and pip packages; see
diff --git a/build/pkgs/python_igraph/checksums.ini b/build/pkgs/python_igraph/checksums.ini
index 7247680193c..e3ba512eb8f 100644
--- a/build/pkgs/python_igraph/checksums.ini
+++ b/build/pkgs/python_igraph/checksums.ini
@@ -1,5 +1,5 @@
tarball=python-igraph-VERSION.tar.gz
-sha1=807a95ad4080d8eb500e7797325d6f11a5c46892
-md5=2ac3561dda7e7321789041261a29aba4
-cksum=754615899
+sha1=ef7ee85cb1bc83109c744d5dd6bbe5e37598ce3f
+md5=788bd70bd286651774f15b20af956081
+cksum=1447848766
upstream_url=https://pypi.io/packages/source/i/igraph/igraph-VERSION.tar.gz
diff --git a/build/pkgs/python_igraph/package-version.txt b/build/pkgs/python_igraph/package-version.txt
index 9b40aa6c214..1a96df19c09 100644
--- a/build/pkgs/python_igraph/package-version.txt
+++ b/build/pkgs/python_igraph/package-version.txt
@@ -1 +1 @@
-0.10.4
+0.11.3
diff --git a/build/pkgs/qhull/distros/macports.txt b/build/pkgs/qhull/distros/macports.txt
index 95d316779cf..703b7aadad9 100644
--- a/build/pkgs/qhull/distros/macports.txt
+++ b/build/pkgs/qhull/distros/macports.txt
@@ -1 +1,2 @@
-qhull
+# broken as of 2022-05-01
+#qhull
diff --git a/build/pkgs/qhull/spkg-install.in b/build/pkgs/qhull/spkg-install.in
index 73810f54625..c3df534ad86 100644
--- a/build/pkgs/qhull/spkg-install.in
+++ b/build/pkgs/qhull/spkg-install.in
@@ -5,9 +5,4 @@ sdh_cmake -DCMAKE_VERBOSE_MAKEFILE=ON \
sdh_make
-# clean old install
-rm -rf "${SAGE_LOCAL}"/include/libqhull
-rm -rf "${SAGE_LOCAL}"/include/qhull
-rm -rf "${SAGE_LOCAL}"/lib/libqhull*
-
sdh_make_install
diff --git a/build/pkgs/r/distros/conda.txt b/build/pkgs/r/distros/conda.txt
index 42e26b8d8ed..4c235733c5f 100644
--- a/build/pkgs/r/distros/conda.txt
+++ b/build/pkgs/r/distros/conda.txt
@@ -1 +1,2 @@
-r r-essentials
+r
+r-essentials
diff --git a/build/pkgs/r/distros/fedora.txt b/build/pkgs/r/distros/fedora.txt
index a5148a636ee..088b10653bb 100644
--- a/build/pkgs/r/distros/fedora.txt
+++ b/build/pkgs/r/distros/fedora.txt
@@ -1 +1,2 @@
-R R-devel
+R
+R-devel
diff --git a/build/pkgs/r/distros/macports.txt b/build/pkgs/r/distros/macports.txt
index 331bae08fb7..5798a47ae13 100644
--- a/build/pkgs/r/distros/macports.txt
+++ b/build/pkgs/r/distros/macports.txt
@@ -1 +1,2 @@
-R
+# Broken as of 2022-05-01, and too many dependencies (X11)
+# R
diff --git a/build/pkgs/readline/distros/opensuse.txt b/build/pkgs/readline/distros/opensuse.txt
index fffe7fdb306..66fd20246e7 100644
--- a/build/pkgs/readline/distros/opensuse.txt
+++ b/build/pkgs/readline/distros/opensuse.txt
@@ -1,3 +1,3 @@
readline-devel
# not available on Leap 15.2:
-"pkgconfig(readline)"
+pkgconfig(readline)
diff --git a/build/pkgs/readline/spkg-install.in b/build/pkgs/readline/spkg-install.in
index 69b4e686d75..a9322e4bed8 100644
--- a/build/pkgs/readline/spkg-install.in
+++ b/build/pkgs/readline/spkg-install.in
@@ -4,16 +4,6 @@ sdh_configure --with-curses --enable-shared --disable-static
echo "Now building static and shared readline libraries..."
sdh_make
-echo "Build succeedeed. Deleting old readline headers and libs"
-echo "before installing the new ones..."
-# (Note; Actually also readline does this by itself, but doing it
-# here, too, doesn't hurt either.)
-rm -rf "$SAGE_LOCAL"/include/readline/ "$SAGE_LOCAL"/lib/libreadline.*
-if [[ $? -ne 0 ]]; then
- echo >&2 "Error removing old version of readline."
- exit 1
-fi
-
echo "Now installing the new readline headers and libraries..."
sdh_make_install
diff --git a/build/pkgs/referencing/dependencies b/build/pkgs/referencing/dependencies
index 12067bf5c3e..39c6d3527b3 100644
--- a/build/pkgs/referencing/dependencies
+++ b/build/pkgs/referencing/dependencies
@@ -1,4 +1,4 @@
-attrs | $(PYTHON_TOOLCHAIN) $(PYTHON)
+attrs pyrsistent | $(PYTHON_TOOLCHAIN) $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/sage_conf/install-requires.txt b/build/pkgs/sage_conf/install-requires.txt
index b136f4a2aff..3a9ab385d78 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.3b2
+sage-conf ~= 10.3b4
diff --git a/build/pkgs/sage_docbuild/install-requires.txt b/build/pkgs/sage_docbuild/install-requires.txt
index a9f3dad3be9..0c2be2f77db 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.3b2
+sage-docbuild ~= 10.3b4
diff --git a/build/pkgs/sage_setup/install-requires.txt b/build/pkgs/sage_setup/install-requires.txt
index 398467294a7..9e7d5a7398a 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.3b2
+sage-setup ~= 10.3b4
diff --git a/build/pkgs/sage_sws2rst/install-requires.txt b/build/pkgs/sage_sws2rst/install-requires.txt
index 86ccd89829a..d7e9353d351 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.3b2
+sage-sws2rst ~= 10.3b4
diff --git a/build/pkgs/sagelib/dependencies b/build/pkgs/sagelib/dependencies
index fa6e98df7db..b1ebfd0825e 100644
--- a/build/pkgs/sagelib/dependencies
+++ b/build/pkgs/sagelib/dependencies
@@ -1,4 +1,4 @@
-FORCE $(SCRIPTS) boost_cropped $(BLAS) brial cliquer cypari cysignals cython ecl eclib ecm flint libgd gap giac givaro glpk gmpy2 gsl iml importlib_metadata importlib_resources jupyter_core lcalc lrcalc_python libbraiding libhomfly libpng linbox m4ri m4rie memory_allocator mpc mpfi mpfr $(MP_LIBRARY) ntl numpy pari pip pkgconfig planarity ppl pplpy primesieve primecount primecountpy pycygwin $(PYTHON) requests rw sage_conf singular symmetrica typing_extensions $(PCFILES) | $(PYTHON_TOOLCHAIN) sage_setup $(PYTHON) pythran
+FORCE $(SCRIPTS) boost_cropped $(BLAS) brial cliquer cypari cysignals cython ecl eclib ecm flint libgd gap giac givaro glpk gmpy2 gsl iml importlib_metadata importlib_resources jupyter_core lcalc lrcalc_python libbraiding libhomfly libpng linbox m4ri m4rie memory_allocator mpc mpfi mpfr $(MP_LIBRARY) ntl numpy pari pip pkgconfig planarity ppl pplpy primesieve primecount primecountpy $(PYTHON) requests rw sage_conf singular symmetrica typing_extensions $(PCFILES) | $(PYTHON_TOOLCHAIN) sage_setup $(PYTHON) pythran
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/sagelib/install-requires.txt b/build/pkgs/sagelib/install-requires.txt
index 4760acdf3a5..4fddbc66d5f 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.3b2
+sagemath-standard ~= 10.3b4
diff --git a/build/pkgs/sagelib/spkg-install.in b/build/pkgs/sagelib/spkg-install.in
index 63cfd64fa59..39ffc25f270 100644
--- a/build/pkgs/sagelib/spkg-install.in
+++ b/build/pkgs/sagelib/spkg-install.in
@@ -51,6 +51,8 @@ if [ "$SAGE_EDITABLE" = yes ]; then
# and renamed the distribution to "sagemath-standard"). There is no clean way to uninstall
# them, so we just use rm.
(cd "$SITEPACKAGESDIR" && rm -rf sage sage-[1-9]*.egg-info sage-[1-9]*.dist-info)
+ # Until https://github.com/sagemath/sage/issues/34209 switches us to PEP 660 editable wheels
+ export SETUPTOOLS_ENABLE_FEATURES=legacy-editable
time sdh_pip_editable_install .
if [ "$SAGE_WHEELS" = yes ]; then
diff --git a/build/pkgs/sagemath_bliss/install-requires.txt b/build/pkgs/sagemath_bliss/install-requires.txt
index 78450942be8..24bd560a768 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.3b2
+sagemath-bliss ~= 10.3b4
diff --git a/build/pkgs/sagemath_categories/install-requires.txt b/build/pkgs/sagemath_categories/install-requires.txt
index dd5175f57fe..73fde138fd8 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.3b2
+sagemath-categories ~= 10.3b4
diff --git a/build/pkgs/sagemath_coxeter3/install-requires.txt b/build/pkgs/sagemath_coxeter3/install-requires.txt
index 05f8575b6a0..0a7cf53f9cb 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.3b2
+sagemath-coxeter3 ~= 10.3b4
diff --git a/build/pkgs/sagemath_doc_pdf/dependencies b/build/pkgs/sagemath_doc_pdf/dependencies
index 21eb5295b36..7e3e7f136d2 100644
--- a/build/pkgs/sagemath_doc_pdf/dependencies
+++ b/build/pkgs/sagemath_doc_pdf/dependencies
@@ -1 +1 @@
-sagemath_doc_html texlive
+sagemath_doc_html texlive texlive_luatex free_fonts xindy
diff --git a/build/pkgs/sagemath_environment/install-requires.txt b/build/pkgs/sagemath_environment/install-requires.txt
index 1eb9fe7e808..f2de063f119 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.3b2
+sagemath-environment ~= 10.3b4
diff --git a/build/pkgs/sagemath_mcqd/install-requires.txt b/build/pkgs/sagemath_mcqd/install-requires.txt
index cc46fb68674..f67c3865111 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.3b2
+sagemath-mcqd ~= 10.3b4
diff --git a/build/pkgs/sagemath_meataxe/install-requires.txt b/build/pkgs/sagemath_meataxe/install-requires.txt
index 76fc2369cb1..d574ec0df6d 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.3b2
+sagemath-meataxe ~= 10.3b4
diff --git a/build/pkgs/sagemath_objects/install-requires.txt b/build/pkgs/sagemath_objects/install-requires.txt
index b1d01c37823..73ce709a5f5 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.3b2
+sagemath-objects ~= 10.3b4
diff --git a/build/pkgs/sagemath_repl/install-requires.txt b/build/pkgs/sagemath_repl/install-requires.txt
index ce22d36e261..c9acb9a7e0b 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.3b2
+sagemath-repl ~= 10.3b4
diff --git a/build/pkgs/sagemath_sirocco/install-requires.txt b/build/pkgs/sagemath_sirocco/install-requires.txt
index 40949dd944f..8fd980605d7 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.3b2
+sagemath-sirocco ~= 10.3b4
diff --git a/build/pkgs/sagemath_tdlib/install-requires.txt b/build/pkgs/sagemath_tdlib/install-requires.txt
index cab1a072642..377b21f5a09 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.3b2
+sagemath-tdlib ~= 10.3b4
diff --git a/build/pkgs/sagetex/spkg-install.in b/build/pkgs/sagetex/spkg-install.in
index 55f0e9c76e5..058b1344dc2 100644
--- a/build/pkgs/sagetex/spkg-install.in
+++ b/build/pkgs/sagetex/spkg-install.in
@@ -1,6 +1,3 @@
cd src
sdh_pip_install .
-
-echo "Removing old SageTex version(s)"
-rm -rf $SAGE_LOCAL/share/texmf/tex/generic/sagetex
diff --git a/build/pkgs/setuptools/checksums.ini b/build/pkgs/setuptools/checksums.ini
index 150e3c25335..1a88d2a7464 100644
--- a/build/pkgs/setuptools/checksums.ini
+++ b/build/pkgs/setuptools/checksums.ini
@@ -1,5 +1,5 @@
-tarball=setuptools-VERSION.tar.gz
-sha1=b0c9b16863c57d70adc22651906eea7eaee09803
-md5=d967ca2ba7f46db887daee2d5c9bd6a2
-cksum=2346145273
-upstream_url=https://pypi.io/packages/source/s/setuptools/setuptools-VERSION.tar.gz
+tarball=setuptools-VERSION-py3-none-any.whl
+sha1=4227225bb193e3a45542f45966caf777d4c913e8
+md5=f096ed836f4036a11aa277fa16dc09ff
+cksum=263664173
+upstream_url=https://pypi.io/packages/py3/s/setuptools/setuptools-VERSION-py3-none-any.whl
diff --git a/build/pkgs/setuptools/dependencies b/build/pkgs/setuptools/dependencies
index d45a397db36..644ad35f773 100644
--- a/build/pkgs/setuptools/dependencies
+++ b/build/pkgs/setuptools/dependencies
@@ -1,4 +1,4 @@
- | $(PYTHON)
+ | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/setuptools/package-version.txt b/build/pkgs/setuptools/package-version.txt
index fc312b9c8c1..2c021f541a8 100644
--- a/build/pkgs/setuptools/package-version.txt
+++ b/build/pkgs/setuptools/package-version.txt
@@ -1 +1 @@
-68.2.2
+69.0.2
diff --git a/build/pkgs/setuptools/spkg-install.in b/build/pkgs/setuptools/spkg-install.in
deleted file mode 100644
index 09a8b8f65ce..00000000000
--- a/build/pkgs/setuptools/spkg-install.in
+++ /dev/null
@@ -1,5 +0,0 @@
-cd src
-# Use --single-version-externally-managed to prevent setuptools from installing itself with easy_install
-python3 setup.py --no-user-cfg install \
- --single-version-externally-managed --root="$SAGE_DESTDIR" || \
- sdh_die "Error building / installing setuptools for Python ${vers}"
diff --git a/build/pkgs/setuptools_wheel/SPKG.rst b/build/pkgs/setuptools_wheel/SPKG.rst
deleted file mode 100644
index c78602a296a..00000000000
--- a/build/pkgs/setuptools_wheel/SPKG.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-setuptools_wheel: Build the setuptools package as a wheel
-=========================================================
-
-After installing setuptools and wheel, we build a wheel of setuptools
-to complete the set of wheels stored in our wheelhouse.
diff --git a/build/pkgs/setuptools_wheel/checksums.ini b/build/pkgs/setuptools_wheel/checksums.ini
deleted file mode 120000
index 4f64d3ce107..00000000000
--- a/build/pkgs/setuptools_wheel/checksums.ini
+++ /dev/null
@@ -1 +0,0 @@
-../setuptools/checksums.ini
\ No newline at end of file
diff --git a/build/pkgs/setuptools_wheel/dependencies b/build/pkgs/setuptools_wheel/dependencies
deleted file mode 100644
index dac3579f7e3..00000000000
--- a/build/pkgs/setuptools_wheel/dependencies
+++ /dev/null
@@ -1,4 +0,0 @@
- setuptools wheel | $(PYTHON)
-
-----------
-All lines of this file are ignored except the first.
diff --git a/build/pkgs/setuptools_wheel/distros b/build/pkgs/setuptools_wheel/distros
deleted file mode 120000
index b22be5c01a6..00000000000
--- a/build/pkgs/setuptools_wheel/distros
+++ /dev/null
@@ -1 +0,0 @@
-../setuptools/distros
\ No newline at end of file
diff --git a/build/pkgs/setuptools_wheel/install-requires.txt b/build/pkgs/setuptools_wheel/install-requires.txt
deleted file mode 120000
index c5cfb4ff0a9..00000000000
--- a/build/pkgs/setuptools_wheel/install-requires.txt
+++ /dev/null
@@ -1 +0,0 @@
-../setuptools/install-requires.txt
\ No newline at end of file
diff --git a/build/pkgs/setuptools_wheel/package-version.txt b/build/pkgs/setuptools_wheel/package-version.txt
deleted file mode 120000
index 5268dbec8f6..00000000000
--- a/build/pkgs/setuptools_wheel/package-version.txt
+++ /dev/null
@@ -1 +0,0 @@
-../setuptools/package-version.txt
\ No newline at end of file
diff --git a/build/pkgs/setuptools_wheel/spkg-configure.m4 b/build/pkgs/setuptools_wheel/spkg-configure.m4
deleted file mode 100644
index db71392a8b0..00000000000
--- a/build/pkgs/setuptools_wheel/spkg-configure.m4
+++ /dev/null
@@ -1 +0,0 @@
-SAGE_SPKG_CONFIGURE([setuptools_wheel], [SAGE_PYTHON_PACKAGE_CHECK([setuptools_wheel])])
diff --git a/build/pkgs/setuptools_wheel/spkg-install.in b/build/pkgs/setuptools_wheel/spkg-install.in
deleted file mode 100644
index 7fdd493b5aa..00000000000
--- a/build/pkgs/setuptools_wheel/spkg-install.in
+++ /dev/null
@@ -1,3 +0,0 @@
-cd src
-sdh_setup_bdist_wheel
-sdh_store_wheel .
diff --git a/build/pkgs/setuptools_wheel/type b/build/pkgs/setuptools_wheel/type
deleted file mode 100644
index a6a7b9cd726..00000000000
--- a/build/pkgs/setuptools_wheel/type
+++ /dev/null
@@ -1 +0,0 @@
-standard
diff --git a/build/pkgs/singular/spkg-install.in b/build/pkgs/singular/spkg-install.in
index 1c24a5d7ef8..c64820f4af1 100644
--- a/build/pkgs/singular/spkg-install.in
+++ b/build/pkgs/singular/spkg-install.in
@@ -11,44 +11,6 @@ if [ "x$SAGE_DEBUG" = "xyes" ]; then
SINGULAR_CONFIGURE="$SINGULAR_CONFIGURE --enable-debug --disable-optimizationflags"
fi
-remove_old_version()
-{
- # the following is a little verbose but it ensures we leave no trace of 3.x
- # _or_ 4.x
- rm -f "$SAGE_LOCAL"/bin/*Singular*
- rm -f "$SAGE_LOCAL"/bin/*singular*
- rm -rf "$SAGE_LOCAL/include/singular" # 3.x and 4.x
- rm -rf "$SAGE_LOCAL/include/factory" # 3.x and 4.x
- rm -f "$SAGE_LOCAL/include/factor.h" # 3.x only
- rm -f "$SAGE_LOCAL/include/factoryconf.h" # 3.x only
- rm -rf "$SAGE_LOCAL/include/omalloc" #4.x only
- rm -f "$SAGE_LOCAL/include/omalloc.h" # 3.x only
- rm -f "$SAGE_LOCAL/include/omlimits.h" # 3.x only
- rm -rf "$SAGE_LOCAL/include/resources" #4.x only
- rm -rf "$SAGE_LOCAL/include/gfanlib" #4.x only
-
- # Clean up all Singular-related libraries
- libs=(
- singular # 3.x with lower case
- singcf # 3.x only additional archives
- singfac # 3.x only additional archives
- Singular # 4.x with upper case
- polys
- factory
- omalloc
- resources # 3.x
- singular_resources # 4.x and up
- gfan
- )
- for name in ${libs[*]}; do
- rm -f "$SAGE_LOCAL"/lib/lib${name}*
- done
-
- rm -f "$SAGE_LOCAL"/lib/p_Procs_Field* # 3.x only
- rm -rf "$SAGE_LOCAL/share/singular"
- rm -f "$SAGE_LOCAL"/share/info/singular*
-}
-
config()
{
# configure notes (dates from Singular 3.x, maybe outdated for 4.x):
@@ -92,7 +54,7 @@ build_singular()
# Actually run all the functions defined above
-for i in remove_old_version config build_singular; do
+for i in config build_singular; do
echo "############### Singular stage $i ###############"
cd "$SRC" && $i
done
diff --git a/build/pkgs/sqlite/checksums.ini b/build/pkgs/sqlite/checksums.ini
index 5cb33394ab3..777aa3953a3 100644
--- a/build/pkgs/sqlite/checksums.ini
+++ b/build/pkgs/sqlite/checksums.ini
@@ -1,5 +1,5 @@
-tarball=sqlite-autoconf-3360000.tar.gz
+tarball=sqlite-autoconf-${VERSION_MAJOR}${VERSION_MINOR}0${VERSION_MICRO}00.tar.gz
sha1=a4bcf9e951bfb9745214241ba08476299fc2dc1e
md5=f5752052fc5b8e1b539af86a3671eac7
cksum=763219165
-upstream_url=https://www.sqlite.org/2021/sqlite-autoconf-3360000.tar.gz
+upstream_url=https://www.sqlite.org/2021/sqlite-autoconf-${VERSION_MAJOR}${VERSION_MINOR}0${VERSION_MICRO}00.tar.gz
diff --git a/build/pkgs/sqlite/distros/opensuse.txt b/build/pkgs/sqlite/distros/opensuse.txt
index e5831abec57..80861d24415 100644
--- a/build/pkgs/sqlite/distros/opensuse.txt
+++ b/build/pkgs/sqlite/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(sqlite3)"
+pkgconfig(sqlite3)
diff --git a/build/pkgs/sqlite/spkg-install.in b/build/pkgs/sqlite/spkg-install.in
index d13df2ba1b8..0ddfea7a619 100644
--- a/build/pkgs/sqlite/spkg-install.in
+++ b/build/pkgs/sqlite/spkg-install.in
@@ -1,5 +1,3 @@
-rm -f "$SAGE_LOCAL/bin/sqlite3"
-
cd src
export CPPFLAGS="$CPPFLAGS -I$SAGE_LOCAL/include"
diff --git a/build/pkgs/suitesparse/distros/fedora.txt b/build/pkgs/suitesparse/distros/fedora.txt
index 473f5afeb82..add9f88182c 100644
--- a/build/pkgs/suitesparse/distros/fedora.txt
+++ b/build/pkgs/suitesparse/distros/fedora.txt
@@ -1 +1,2 @@
-suitesparse suitesparse-devel
+suitesparse
+suitesparse-devel
diff --git a/build/pkgs/suitesparse/distros/gentoo.txt b/build/pkgs/suitesparse/distros/gentoo.txt
index 3b1b625f3e6..36650ca82e3 100644
--- a/build/pkgs/suitesparse/distros/gentoo.txt
+++ b/build/pkgs/suitesparse/distros/gentoo.txt
@@ -1 +1,4 @@
-sci-libs/amd sci-libs/cholmod sci-libs/suitesparseconfig sci-libs/umfpack
+sci-libs/amd
+sci-libs/cholmod
+sci-libs/suitesparseconfig
+sci-libs/umfpack
diff --git a/build/pkgs/suitesparse/distros/macports.txt b/build/pkgs/suitesparse/distros/macports.txt
index 45d8956e69e..93b99b56740 100644
--- a/build/pkgs/suitesparse/distros/macports.txt
+++ b/build/pkgs/suitesparse/distros/macports.txt
@@ -1 +1,2 @@
-SuiteSparse
+# broken as of 2022-05-01
+#SuiteSparse
diff --git a/build/pkgs/symengine/checksums.ini b/build/pkgs/symengine/checksums.ini
index 8eb65f05ef9..9ba59940a9f 100644
--- a/build/pkgs/symengine/checksums.ini
+++ b/build/pkgs/symengine/checksums.ini
@@ -1,5 +1,6 @@
tarball=symengine-VERSION.tar.gz
-sha1=a2c8957f2099c9199751b165f107bf93d6823818
-md5=fe3c3fee1bd8dfdb9576fc2d28cb1076
-cksum=3544211225
+sha1=2dfee07108509963f3dbe3d9cad9de76d85e551f
+md5=4074f3c76570bdc2ae9914edafa29eb6
+cksum=3782541135
upstream_url=https://github.com/symengine/symengine/releases/download/vVERSION/symengine-VERSION.tar.gz
+
diff --git a/build/pkgs/symengine/package-version.txt b/build/pkgs/symengine/package-version.txt
index af88ba82486..a8839f70de0 100644
--- a/build/pkgs/symengine/package-version.txt
+++ b/build/pkgs/symengine/package-version.txt
@@ -1 +1 @@
-0.11.1
+0.11.2
\ No newline at end of file
diff --git a/build/pkgs/symengine/spkg-configure.m4 b/build/pkgs/symengine/spkg-configure.m4
index c037d2e5f72..a6a78791dbc 100644
--- a/build/pkgs/symengine/spkg-configure.m4
+++ b/build/pkgs/symengine/spkg-configure.m4
@@ -1,7 +1,7 @@
SAGE_SPKG_CONFIGURE([symengine], [
m4_pushdef(SAGE_SYMENGINE_VERSION_MAJOR, [0])
m4_pushdef(SAGE_SYMENGINE_VERSION_MINOR, [11])
- SAGE_SPKG_DEPCHECK([gmp arb ecm flint mpc mpfr], [
+ SAGE_SPKG_DEPCHECK([gmp ecm flint mpc mpfr], [
AC_CHECK_HEADER([symengine/symengine_config.h], [], [sage_spkg_install_symengine=yes])
AC_MSG_CHECKING([whether we can link a program using symengine])
SYMENGINE_SAVED_LIBS=$LIBS
diff --git a/build/pkgs/symmetrica/checksums.ini b/build/pkgs/symmetrica/checksums.ini
index 5f70ed5363c..6d06ebda462 100644
--- a/build/pkgs/symmetrica/checksums.ini
+++ b/build/pkgs/symmetrica/checksums.ini
@@ -2,4 +2,4 @@ tarball=symmetrica-VERSION.tar.xz
sha1=0044cc087ff04267c246e730c6570d89f6e593af
md5=cd4716c26b5c625a012c22656113ef6f
cksum=1186250347
-upstream_url=http://users.ox.ac.uk/~coml0531/sage/symmetrica-3.0.1.tar.xz
+upstream_url=http://users.ox.ac.uk/~coml0531/sage/symmetrica-VERSION.tar.xz
diff --git a/build/pkgs/sympow/checksums.ini b/build/pkgs/sympow/checksums.ini
index f6ad79b8f93..87bf0086178 100644
--- a/build/pkgs/sympow/checksums.ini
+++ b/build/pkgs/sympow/checksums.ini
@@ -2,4 +2,4 @@ tarball=sympow-vVERSION.tar.gz
sha1=37a909c26009415197b5088a2f1b53dd3558f494
md5=51f2c717c84ec9c2840af740751cf797
cksum=1444149964
-upstream_url=https://github.com/mkoeppe/sympow/releases/download/v2.023.6/sympow-v2.023.6.tar.gz
+upstream_url=https://github.com/mkoeppe/sympow/releases/download/vVERSION/sympow-vVERSION.tar.gz
diff --git a/build/pkgs/tachyon/distros/fedora.txt b/build/pkgs/tachyon/distros/fedora.txt
index b1ee1e1bdbe..035020a8d5b 100644
--- a/build/pkgs/tachyon/distros/fedora.txt
+++ b/build/pkgs/tachyon/distros/fedora.txt
@@ -1 +1,2 @@
-tachyon tachyon-devel
+tachyon
+tachyon-devel
diff --git a/build/pkgs/texlive_luatex/SPKG.rst b/build/pkgs/texlive_luatex/SPKG.rst
new file mode 100644
index 00000000000..0bb7f65eb8b
--- /dev/null
+++ b/build/pkgs/texlive_luatex/SPKG.rst
@@ -0,0 +1,21 @@
+texlive_luatex: LuaTeX packages
+===============================
+
+Description
+-----------
+
+Packages for LuaTeX, a TeX engine using Lua as an embedded scripting and
+extension language, with native support for Unicode, OpenType/TrueType fonts,
+and both PDF and DVI output.
+
+The purpose of this dummy package is to associate system package lists with it.
+
+License
+-------
+
+GNU General Public License version 2.0 (GPLv2)
+
+Upstream Contact
+----------------
+
+https://www.luatex.org/
diff --git a/build/pkgs/texlive_luatex/dependencies b/build/pkgs/texlive_luatex/dependencies
new file mode 100644
index 00000000000..ba0ee3a029f
--- /dev/null
+++ b/build/pkgs/texlive_luatex/dependencies
@@ -0,0 +1 @@
+texlive
diff --git a/build/pkgs/texlive_luatex/distros/alpine.txt b/build/pkgs/texlive_luatex/distros/alpine.txt
new file mode 100644
index 00000000000..d2b702df88a
--- /dev/null
+++ b/build/pkgs/texlive_luatex/distros/alpine.txt
@@ -0,0 +1 @@
+texlive-luatex
diff --git a/build/pkgs/texlive_luatex/distros/arch.txt b/build/pkgs/texlive_luatex/distros/arch.txt
new file mode 100644
index 00000000000..2eec092a978
--- /dev/null
+++ b/build/pkgs/texlive_luatex/distros/arch.txt
@@ -0,0 +1 @@
+texlive-collection-luatex
diff --git a/build/pkgs/texlive_luatex/distros/cygwin.txt b/build/pkgs/texlive_luatex/distros/cygwin.txt
new file mode 100644
index 00000000000..ba0ee3a029f
--- /dev/null
+++ b/build/pkgs/texlive_luatex/distros/cygwin.txt
@@ -0,0 +1 @@
+texlive
diff --git a/build/pkgs/texlive_luatex/distros/debian.txt b/build/pkgs/texlive_luatex/distros/debian.txt
new file mode 100644
index 00000000000..d2b702df88a
--- /dev/null
+++ b/build/pkgs/texlive_luatex/distros/debian.txt
@@ -0,0 +1 @@
+texlive-luatex
diff --git a/build/pkgs/texlive_luatex/distros/fedora.txt b/build/pkgs/texlive_luatex/distros/fedora.txt
new file mode 100644
index 00000000000..d2b702df88a
--- /dev/null
+++ b/build/pkgs/texlive_luatex/distros/fedora.txt
@@ -0,0 +1 @@
+texlive-luatex
diff --git a/build/pkgs/texlive_luatex/distros/gentoo.txt b/build/pkgs/texlive_luatex/distros/gentoo.txt
new file mode 100644
index 00000000000..6e651aec020
--- /dev/null
+++ b/build/pkgs/texlive_luatex/distros/gentoo.txt
@@ -0,0 +1 @@
+dev-texlive/texlive-luatex
diff --git a/build/pkgs/texlive_luatex/distros/macports.txt b/build/pkgs/texlive_luatex/distros/macports.txt
new file mode 100644
index 00000000000..d2b702df88a
--- /dev/null
+++ b/build/pkgs/texlive_luatex/distros/macports.txt
@@ -0,0 +1 @@
+texlive-luatex
diff --git a/build/pkgs/texlive_luatex/distros/opensuse.txt b/build/pkgs/texlive_luatex/distros/opensuse.txt
new file mode 100644
index 00000000000..d2b702df88a
--- /dev/null
+++ b/build/pkgs/texlive_luatex/distros/opensuse.txt
@@ -0,0 +1 @@
+texlive-luatex
diff --git a/build/pkgs/texlive_luatex/distros/repology.txt b/build/pkgs/texlive_luatex/distros/repology.txt
new file mode 100644
index 00000000000..d2b702df88a
--- /dev/null
+++ b/build/pkgs/texlive_luatex/distros/repology.txt
@@ -0,0 +1 @@
+texlive-luatex
diff --git a/build/pkgs/texlive_luatex/spkg-configure.m4 b/build/pkgs/texlive_luatex/spkg-configure.m4
new file mode 100644
index 00000000000..6fb53bbc171
--- /dev/null
+++ b/build/pkgs/texlive_luatex/spkg-configure.m4
@@ -0,0 +1,10 @@
+SAGE_SPKG_CONFIGURE([texlive_luatex], [
+ sage_spkg_install_texlive_luatex=no
+ AC_MSG_CHECKING([for luaotfload-main.lua])
+ AS_IF([kpsewhich luaotfload-main.lua >& AS_MESSAGE_LOG_FD 2>&1], [
+ AC_MSG_RESULT([yes])
+ ], [
+ AC_MSG_RESULT([no])
+ sage_spkg_install_texlive_luatex=yes
+ ])
+])
diff --git a/build/pkgs/texlive_luatex/type b/build/pkgs/texlive_luatex/type
new file mode 100644
index 00000000000..134d9bc32d5
--- /dev/null
+++ b/build/pkgs/texlive_luatex/type
@@ -0,0 +1 @@
+optional
diff --git a/build/pkgs/trove_classifiers/checksums.ini b/build/pkgs/trove_classifiers/checksums.ini
index d59736dbac2..7350f444667 100644
--- a/build/pkgs/trove_classifiers/checksums.ini
+++ b/build/pkgs/trove_classifiers/checksums.ini
@@ -1,5 +1,5 @@
-tarball=trove-classifiers-VERSION.tar.gz
-sha1=c6821e6c6d57dc2eec2d4156d63cdca939373759
-md5=154ae4cdb69ac37bb35a35c6fbc477cd
-cksum=84032195
-upstream_url=https://pypi.io/packages/source/t/trove_classifiers/trove-classifiers-VERSION.tar.gz
+tarball=trove_classifiers-VERSION-py3-none-any.whl
+sha1=c341abee77b5c87d913b86dc587e544553f0658c
+md5=78e67f128f53b8417134429192810701
+cksum=3034057088
+upstream_url=https://pypi.io/packages/py3/t/trove_classifiers/trove_classifiers-VERSION-py3-none-any.whl
diff --git a/build/pkgs/trove_classifiers/dependencies b/build/pkgs/trove_classifiers/dependencies
index 2134b2a4179..cbe3cae5550 100644
--- a/build/pkgs/trove_classifiers/dependencies
+++ b/build/pkgs/trove_classifiers/dependencies
@@ -1,4 +1,4 @@
-$(PYTHON) calver | $(PYTHON_TOOLCHAIN)
+calver | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/trove_classifiers/package-version.txt b/build/pkgs/trove_classifiers/package-version.txt
index b82d6dba095..a33bd2f9968 100644
--- a/build/pkgs/trove_classifiers/package-version.txt
+++ b/build/pkgs/trove_classifiers/package-version.txt
@@ -1 +1 @@
-2023.11.14
+2023.11.29
diff --git a/build/pkgs/trove_classifiers/spkg-install.in b/build/pkgs/trove_classifiers/spkg-install.in
deleted file mode 100644
index 37ac1a53437..00000000000
--- a/build/pkgs/trove_classifiers/spkg-install.in
+++ /dev/null
@@ -1,2 +0,0 @@
-cd src
-sdh_pip_install .
diff --git a/build/pkgs/virtualenv/checksums.ini b/build/pkgs/virtualenv/checksums.ini
index b7def1fa7e0..90a2a903926 100644
--- a/build/pkgs/virtualenv/checksums.ini
+++ b/build/pkgs/virtualenv/checksums.ini
@@ -1,5 +1,5 @@
tarball=virtualenv-VERSION-py3-none-any.whl
-sha1=a17fc6409d29b7e7b1427f37496bfc0fa399f9bf
-md5=6374ee91c1ed02956a334aa01d9414ed
-cksum=31593789
+sha1=9c942063d76d85361f0567b59cce8238c57f1183
+md5=7dec1148d91180767ae908dc49a7ebf5
+cksum=3612060825
upstream_url=https://pypi.io/packages/py3/v/virtualenv/virtualenv-VERSION-py3-none-any.whl
diff --git a/build/pkgs/virtualenv/dependencies b/build/pkgs/virtualenv/dependencies
index b0e964bba0c..148ef28948e 100644
--- a/build/pkgs/virtualenv/dependencies
+++ b/build/pkgs/virtualenv/dependencies
@@ -1,4 +1,4 @@
-distlib filelock platformdirs | $(PYTHON_TOOLCHAIN) $(PYTHON)
+distlib filelock platformdirs | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/virtualenv/package-version.txt b/build/pkgs/virtualenv/package-version.txt
index b744a5a46cb..242a1e92b72 100644
--- a/build/pkgs/virtualenv/package-version.txt
+++ b/build/pkgs/virtualenv/package-version.txt
@@ -1 +1 @@
-20.24.4
+20.25.0
diff --git a/build/pkgs/wheel/checksums.ini b/build/pkgs/wheel/checksums.ini
index b12a1973b0c..4f2b8c5c534 100644
--- a/build/pkgs/wheel/checksums.ini
+++ b/build/pkgs/wheel/checksums.ini
@@ -1,5 +1,5 @@
-tarball=wheel-VERSION.tar.gz
-sha1=34a787f7069762e267e5ed62ed31cc9c87ea910b
-md5=06271a9e90c948b7e93dd7ce0fd90272
-cksum=444550709
-upstream_url=https://pypi.io/packages/source/w/wheel/wheel-VERSION.tar.gz
+tarball=wheel-VERSION-py3-none-any.whl
+sha1=fcf4ad8d5d8216d661bc98eede0d9210cbc5b697
+md5=779d91395ceb12e15e3a585b30b53f9f
+cksum=1421399426
+upstream_url=https://pypi.io/packages/py3/w/wheel/wheel-VERSION-py3-none-any.whl
diff --git a/build/pkgs/wheel/dependencies b/build/pkgs/wheel/dependencies
index a8e327be793..644ad35f773 100644
--- a/build/pkgs/wheel/dependencies
+++ b/build/pkgs/wheel/dependencies
@@ -1,4 +1,4 @@
- setuptools | $(PYTHON)
+ | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/wheel/package-version.txt b/build/pkgs/wheel/package-version.txt
index 6599454d402..787ffc30a81 100644
--- a/build/pkgs/wheel/package-version.txt
+++ b/build/pkgs/wheel/package-version.txt
@@ -1 +1 @@
-0.41.2
+0.42.0
diff --git a/build/pkgs/wheel/spkg-install.in b/build/pkgs/wheel/spkg-install.in
deleted file mode 100644
index 5ad5c08fe0e..00000000000
--- a/build/pkgs/wheel/spkg-install.in
+++ /dev/null
@@ -1,13 +0,0 @@
-cd src
-
-python3 setup.py --no-user-cfg install \
- --single-version-externally-managed --root="$SAGE_DESTDIR" || \
- sdh_die "Error building / installing package 'wheel'"
-
-# Now build a wheel so that we have a complete set of wheels.
-
-# Because of staging, we cannot use the installed 'wheel' package yet.
-export PYTHONPATH="$(pwd)/src"
-
-sdh_setup_bdist_wheel
-sdh_store_wheel .
diff --git a/build/pkgs/xindy/SPKG.rst b/build/pkgs/xindy/SPKG.rst
new file mode 100644
index 00000000000..49733639b2f
--- /dev/null
+++ b/build/pkgs/xindy/SPKG.rst
@@ -0,0 +1,20 @@
+xindy: a general-purpose index processor
+========================================
+
+Description
+-----------
+
+This dummy package represents xindy: xindy was developed after an impasse had been encountered in the attempt to complete internationalisation of makeindex. Xindy can be used to process indexes for documents marked up using (LA)TEX, Nroff family and SGML-based languages. Xindy is highly configurable, both in markup terms and in terms of the collating order of the text being processed.
+
+We do not have an SPKG for it. The purpose of this dummy package is to
+associate system package lists with it.
+
+License
+-------
+
+GNU General Public License version 2.0 (GPLv2)
+
+Upstream Contact
+----------------
+
+http://www.xindy.org/
diff --git a/build/pkgs/xindy/distros/debian.txt b/build/pkgs/xindy/distros/debian.txt
new file mode 100644
index 00000000000..aeb5474c700
--- /dev/null
+++ b/build/pkgs/xindy/distros/debian.txt
@@ -0,0 +1 @@
+xindy
diff --git a/build/pkgs/xindy/distros/macports.txt b/build/pkgs/xindy/distros/macports.txt
new file mode 100644
index 00000000000..aeb5474c700
--- /dev/null
+++ b/build/pkgs/xindy/distros/macports.txt
@@ -0,0 +1 @@
+xindy
diff --git a/build/pkgs/xindy/distros/opensuse.txt b/build/pkgs/xindy/distros/opensuse.txt
new file mode 100644
index 00000000000..aeb5474c700
--- /dev/null
+++ b/build/pkgs/xindy/distros/opensuse.txt
@@ -0,0 +1 @@
+xindy
diff --git a/build/pkgs/xindy/distros/repology.txt b/build/pkgs/xindy/distros/repology.txt
new file mode 100644
index 00000000000..aeb5474c700
--- /dev/null
+++ b/build/pkgs/xindy/distros/repology.txt
@@ -0,0 +1 @@
+xindy
diff --git a/build/pkgs/xindy/spkg-configure.m4 b/build/pkgs/xindy/spkg-configure.m4
new file mode 100644
index 00000000000..07fbe71efa8
--- /dev/null
+++ b/build/pkgs/xindy/spkg-configure.m4
@@ -0,0 +1,5 @@
+SAGE_SPKG_CONFIGURE([xindy], [
+ sage_spkg_install_xindy=no
+ AC_PATH_PROG([XINDY], [xindy])
+ AS_IF([test -z "$XINDY"], [sage_spkg_install_xindy=yes])
+])
diff --git a/build/pkgs/xindy/type b/build/pkgs/xindy/type
new file mode 100644
index 00000000000..134d9bc32d5
--- /dev/null
+++ b/build/pkgs/xindy/type
@@ -0,0 +1 @@
+optional
diff --git a/build/pkgs/zeromq/distros/fedora.txt b/build/pkgs/zeromq/distros/fedora.txt
index 901dce11d4f..7ab081d69d9 100644
--- a/build/pkgs/zeromq/distros/fedora.txt
+++ b/build/pkgs/zeromq/distros/fedora.txt
@@ -1 +1,2 @@
-zeromq zeromq-devel
+zeromq
+zeromq-devel
diff --git a/build/pkgs/zeromq/distros/macports.txt b/build/pkgs/zeromq/distros/macports.txt
index 3f0b9927569..11d74369d60 100644
--- a/build/pkgs/zeromq/distros/macports.txt
+++ b/build/pkgs/zeromq/distros/macports.txt
@@ -1 +1,2 @@
-zmq-devel
+# Broken as of 2022-05-01
+#zmq-devel
diff --git a/build/pkgs/zeromq/distros/opensuse.txt b/build/pkgs/zeromq/distros/opensuse.txt
index bf80cc05be1..1d10c00df82 100644
--- a/build/pkgs/zeromq/distros/opensuse.txt
+++ b/build/pkgs/zeromq/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(libzmq)"
+pkgconfig(libzmq)
diff --git a/build/pkgs/zipp/checksums.ini b/build/pkgs/zipp/checksums.ini
index 66cd13339d6..7c9d001b307 100644
--- a/build/pkgs/zipp/checksums.ini
+++ b/build/pkgs/zipp/checksums.ini
@@ -1,5 +1,5 @@
-tarball=zipp-VERSION.tar.gz
-sha1=a9f9aebc205b7829c43b34e79c3f87c42b183176
-md5=a4cf8c530da863c27a04251724436681
-cksum=1303269799
-upstream_url=https://pypi.io/packages/source/z/zipp/zipp-VERSION.tar.gz
+tarball=zipp-VERSION-py3-none-any.whl
+sha1=8dd92e1b777b02ec6e1ebe72926d32a82c58b246
+md5=d93f0b8485000b37800a6de09ed6c1cb
+cksum=3547254189
+upstream_url=https://pypi.io/packages/py3/z/zipp/zipp-VERSION-py3-none-any.whl
diff --git a/build/pkgs/zipp/dependencies b/build/pkgs/zipp/dependencies
index 995ddecb8f4..644ad35f773 100644
--- a/build/pkgs/zipp/dependencies
+++ b/build/pkgs/zipp/dependencies
@@ -1,4 +1,4 @@
- | $(PYTHON_TOOLCHAIN) setuptools_scm $(PYTHON)
+ | pip $(PYTHON)
----------
All lines of this file are ignored except the first.
diff --git a/build/pkgs/zipp/spkg-install.in b/build/pkgs/zipp/spkg-install.in
deleted file mode 100644
index 6d596586150..00000000000
--- a/build/pkgs/zipp/spkg-install.in
+++ /dev/null
@@ -1,14 +0,0 @@
-if [ -z "$SAGE_LOCAL" ]; then
- echo >&2 "SAGE_LOCAL undefined ... exiting"
- echo >&2 "Maybe run 'sage --sh'?"
- exit 1
-fi
-
-cd src
-
-sdh_pip_install .
-
-if [ $? -ne 0 ]; then
- echo "Error installing zipp ... exiting"
- exit 1
-fi
diff --git a/build/pkgs/zlib/distros/opensuse.txt b/build/pkgs/zlib/distros/opensuse.txt
index 734537742c0..74ff91e4b69 100644
--- a/build/pkgs/zlib/distros/opensuse.txt
+++ b/build/pkgs/zlib/distros/opensuse.txt
@@ -1 +1 @@
-"pkgconfig(zlib)"
+pkgconfig(zlib)
diff --git a/build/sage_bootstrap/cmdline.py b/build/sage_bootstrap/cmdline.py
index 1b84cbf6461..e182321d7da 100644
--- a/build/sage_bootstrap/cmdline.py
+++ b/build/sage_bootstrap/cmdline.py
@@ -292,6 +292,9 @@ def make_parser():
parser_download.add_argument(
'--on-error', choices=['stop', 'warn'], default='stop',
help='What to do if the tarball cannot be downloaded')
+ parser.add_argument(
+ '--no-check-certificate', action='store_true',
+ help='Do not check SSL certificates for https connections')
parser_upload = subparsers.add_parser(
'upload', epilog=epilog_upload,
@@ -381,6 +384,12 @@ def run():
elif args.subcommand == 'update-latest':
app.update_latest_cls(args.package_name, commit=args.commit)
elif args.subcommand == 'download':
+ if args.no_check_certificate:
+ try:
+ import ssl
+ ssl._create_default_https_context = ssl._create_unverified_context
+ except ImportError:
+ pass
app.download_cls(args.package_name,
allow_upstream=args.allow_upstream,
on_error=args.on_error)
diff --git a/build/sage_bootstrap/package.py b/build/sage_bootstrap/package.py
index f6a5425005a..43bfbffa47c 100644
--- a/build/sage_bootstrap/package.py
+++ b/build/sage_bootstrap/package.py
@@ -121,6 +121,42 @@ def tarball(self):
self.__tarball = Tarball(self.tarball_filename, package=self)
return self.__tarball
+ def _substitute_variables_once(self, pattern):
+ """
+ Substitute (at most) one occurrence of variables in ``pattern`` by the values.
+
+ These variables are ``VERSION``, ``VERSION_MAJOR``, ``VERSION_MINOR``,
+ ``VERSION_MICRO``, either appearing like this or in the form ``${VERSION_MAJOR}``
+ etc.
+
+ Return a tuple:
+ - the string with the substitution done or the original string
+ - whether a substitution was done
+ """
+ for var in ('VERSION_MAJOR', 'VERSION_MINOR', 'VERSION_MICRO', 'VERSION'):
+ # As VERSION is a substring of the other three, it needs to be tested last.
+ dollar_brace_var = '${' + var + '}'
+ if dollar_brace_var in pattern:
+ value = getattr(self, var.lower())
+ return pattern.replace(dollar_brace_var, value, 1), True
+ elif var in pattern:
+ value = getattr(self, var.lower())
+ return pattern.replace(var, value, 1), True
+ return pattern, False
+
+ def _substitute_variables(self, pattern):
+ """
+ Substitute all occurrences of ``VERSION`` in ``pattern`` by the actual version.
+
+ Likewise for ``VERSION_MAJOR``, ``VERSION_MINOR``, ``VERSION_MICRO``,
+ either appearing like this or in the form ``${VERSION}``, ``${VERSION_MAJOR}``,
+ etc.
+ """
+ not_done = True
+ while not_done:
+ pattern, not_done = self._substitute_variables_once(pattern)
+ return pattern
+
@property
def tarball_pattern(self):
"""
@@ -150,7 +186,7 @@ def tarball_filename(self):
"""
pattern = self.tarball_pattern
if pattern:
- return pattern.replace('VERSION', self.version)
+ return self._substitute_variables(pattern)
else:
return None
@@ -177,7 +213,7 @@ def tarball_upstream_url(self):
"""
pattern = self.tarball_upstream_url_pattern
if pattern:
- return pattern.replace('VERSION', self.version)
+ return self._substitute_variables(pattern)
else:
return None
@@ -212,6 +248,39 @@ def version(self):
"""
return self.__version
+ @property
+ def version_major(self):
+ """
+ Return the major version
+
+ OUTPUT:
+
+ String. The package's major version.
+ """
+ return self.version.split('.')[0]
+
+ @property
+ def version_minor(self):
+ """
+ Return the minor version
+
+ OUTPUT:
+
+ String. The package's minor version.
+ """
+ return self.version.split('.')[1]
+
+ @property
+ def version_micro(self):
+ """
+ Return the micro version
+
+ OUTPUT:
+
+ String. The package's micro version.
+ """
+ return self.version.split('.')[2]
+
@property
def patchlevel(self):
"""
diff --git a/build/sage_bootstrap/updater.py b/build/sage_bootstrap/updater.py
index 7c1431967a1..67f1c961124 100644
--- a/build/sage_bootstrap/updater.py
+++ b/build/sage_bootstrap/updater.py
@@ -69,8 +69,11 @@ def _update_version(self, new_version):
def download_upstream(self, download_url=None):
tarball = self.package.tarball
if download_url is None:
+ pattern = self.package.tarball_upstream_url_pattern
+ if pattern and 'VERSION' not in pattern:
+ print('Warning: upstream_url pattern does not use the VERSION variable')
download_url = self.package.tarball_upstream_url
if download_url is None:
raise ValueError("package has no default upstream_url pattern, download_url needed")
- print('Downloading tarball to {0}'.format(tarball.upstream_fqn))
+ print('Downloading tarball from {0} to {1}'.format(download_url, tarball.upstream_fqn))
Download(download_url, tarball.upstream_fqn).run()
diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sage-conf/VERSION.txt
+++ b/pkgs/sage-conf/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sage-conf/_sage_conf/_conf.py.in b/pkgs/sage-conf/_sage_conf/_conf.py.in
index 895d6572d1e..ccc1c9695fb 100644
--- a/pkgs/sage-conf/_sage_conf/_conf.py.in
+++ b/pkgs/sage-conf/_sage_conf/_conf.py.in
@@ -9,6 +9,11 @@ VERSION = "@PACKAGE_VERSION@"
SAGE_LOCAL = "@prefix@"
SAGE_ROOT = "@SAGE_ROOT@"
+# The semicolon-separated list of GAP root paths. This is the list of
+# locations that are searched for GAP packages. This is passed directly
+# to GAP via the -l flag.
+GAP_ROOT_PATHS = "@GAP_ROOT_PATHS@".replace('${prefix}', SAGE_LOCAL)
+
# The path to the standalone maxima executable.
MAXIMA = "@SAGE_MAXIMA@".replace('${prefix}', SAGE_LOCAL)
diff --git a/pkgs/sage-conf_conda/VERSION.txt b/pkgs/sage-conf_conda/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sage-conf_conda/VERSION.txt
+++ b/pkgs/sage-conf_conda/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sage-conf_pypi/VERSION.txt
+++ b/pkgs/sage-conf_pypi/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sage-docbuild/VERSION.txt
+++ b/pkgs/sage-docbuild/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sage-setup/VERSION.txt
+++ b/pkgs/sage-setup/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sage-sws2rst/VERSION.txt
+++ b/pkgs/sage-sws2rst/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sagemath-bliss/VERSION.txt b/pkgs/sagemath-bliss/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sagemath-bliss/VERSION.txt
+++ b/pkgs/sagemath-bliss/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sagemath-bliss/pyproject.toml.m4 b/pkgs/sagemath-bliss/pyproject.toml.m4
index df61e7fac6a..40bfebf2489 100644
--- a/pkgs/sagemath-bliss/pyproject.toml.m4
+++ b/pkgs/sagemath-bliss/pyproject.toml.m4
@@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*-
[build-system]
# Minimum requirements for the build system to execute.
requires = [
- SPKG_INSTALL_REQUIRES_setuptools_wheel
+ SPKG_INSTALL_REQUIRES_setuptools
SPKG_INSTALL_REQUIRES_sage_conf
SPKG_INSTALL_REQUIRES_sage_setup
SPKG_INSTALL_REQUIRES_sagemath_environment
diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sagemath-categories/VERSION.txt
+++ b/pkgs/sagemath-categories/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sagemath-categories/pyproject.toml.m4 b/pkgs/sagemath-categories/pyproject.toml.m4
index 72c75ccd11e..eed48a1db15 100644
--- a/pkgs/sagemath-categories/pyproject.toml.m4
+++ b/pkgs/sagemath-categories/pyproject.toml.m4
@@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*-
[build-system]
# Minimum requirements for the build system to execute.
requires = [
- SPKG_INSTALL_REQUIRES_setuptools_wheel
+ SPKG_INSTALL_REQUIRES_setuptools
SPKG_INSTALL_REQUIRES_wheel
SPKG_INSTALL_REQUIRES_sage_setup
SPKG_INSTALL_REQUIRES_sagemath_environment
diff --git a/pkgs/sagemath-coxeter3/VERSION.txt b/pkgs/sagemath-coxeter3/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sagemath-coxeter3/VERSION.txt
+++ b/pkgs/sagemath-coxeter3/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sagemath-coxeter3/pyproject.toml.m4 b/pkgs/sagemath-coxeter3/pyproject.toml.m4
index a8d0e52a4b0..9f9c9dedd5e 100644
--- a/pkgs/sagemath-coxeter3/pyproject.toml.m4
+++ b/pkgs/sagemath-coxeter3/pyproject.toml.m4
@@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*-
[build-system]
# Minimum requirements for the build system to execute.
requires = [
- SPKG_INSTALL_REQUIRES_setuptools_wheel
+ SPKG_INSTALL_REQUIRES_setuptools
SPKG_INSTALL_REQUIRES_sage_setup
SPKG_INSTALL_REQUIRES_sagemath_environment
SPKG_INSTALL_REQUIRES_cython
diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sagemath-environment/VERSION.txt
+++ b/pkgs/sagemath-environment/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sagemath-environment/pyproject.toml.m4 b/pkgs/sagemath-environment/pyproject.toml.m4
index 4061c8c46eb..44ddd190f99 100644
--- a/pkgs/sagemath-environment/pyproject.toml.m4
+++ b/pkgs/sagemath-environment/pyproject.toml.m4
@@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*-
[build-system]
# Minimum requirements for the build system to execute.
requires = [
- SPKG_INSTALL_REQUIRES_setuptools_wheel
+ SPKG_INSTALL_REQUIRES_setuptools
SPKG_INSTALL_REQUIRES_wheel
]
build-backend = "setuptools.build_meta"
diff --git a/pkgs/sagemath-mcqd/VERSION.txt b/pkgs/sagemath-mcqd/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sagemath-mcqd/VERSION.txt
+++ b/pkgs/sagemath-mcqd/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sagemath-mcqd/pyproject.toml.m4 b/pkgs/sagemath-mcqd/pyproject.toml.m4
index c94aface3fd..55a58611334 100644
--- a/pkgs/sagemath-mcqd/pyproject.toml.m4
+++ b/pkgs/sagemath-mcqd/pyproject.toml.m4
@@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*-
[build-system]
# Minimum requirements for the build system to execute.
requires = [
- SPKG_INSTALL_REQUIRES_setuptools_wheel
+ SPKG_INSTALL_REQUIRES_setuptools
SPKG_INSTALL_REQUIRES_sage_setup
SPKG_INSTALL_REQUIRES_sagemath_environment
SPKG_INSTALL_REQUIRES_cython
diff --git a/pkgs/sagemath-meataxe/VERSION.txt b/pkgs/sagemath-meataxe/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sagemath-meataxe/VERSION.txt
+++ b/pkgs/sagemath-meataxe/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sagemath-meataxe/pyproject.toml.m4 b/pkgs/sagemath-meataxe/pyproject.toml.m4
index 0c8fd46d8be..b4a504c4f1f 100644
--- a/pkgs/sagemath-meataxe/pyproject.toml.m4
+++ b/pkgs/sagemath-meataxe/pyproject.toml.m4
@@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*-
[build-system]
# Minimum requirements for the build system to execute.
requires = [
- SPKG_INSTALL_REQUIRES_setuptools_wheel
+ SPKG_INSTALL_REQUIRES_setuptools
SPKG_INSTALL_REQUIRES_sage_setup
SPKG_INSTALL_REQUIRES_sagemath_environment
SPKG_INSTALL_REQUIRES_cython
diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sagemath-objects/VERSION.txt
+++ b/pkgs/sagemath-objects/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sagemath-objects/pyproject.toml.m4 b/pkgs/sagemath-objects/pyproject.toml.m4
index 9214f1ffb8d..a8d7d83a44a 100644
--- a/pkgs/sagemath-objects/pyproject.toml.m4
+++ b/pkgs/sagemath-objects/pyproject.toml.m4
@@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*-
[build-system]
# Minimum requirements for the build system to execute.
requires = [
- SPKG_INSTALL_REQUIRES_setuptools_wheel
+ SPKG_INSTALL_REQUIRES_setuptools
SPKG_INSTALL_REQUIRES_wheel
SPKG_INSTALL_REQUIRES_sage_setup
SPKG_INSTALL_REQUIRES_sagemath_environment
diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sagemath-repl/VERSION.txt
+++ b/pkgs/sagemath-repl/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sagemath-repl/pyproject.toml.m4 b/pkgs/sagemath-repl/pyproject.toml.m4
index dfdfb692c9b..2bc276158a4 100644
--- a/pkgs/sagemath-repl/pyproject.toml.m4
+++ b/pkgs/sagemath-repl/pyproject.toml.m4
@@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*-
[build-system]
# Minimum requirements for the build system to execute.
requires = [
- SPKG_INSTALL_REQUIRES_setuptools_wheel
+ SPKG_INSTALL_REQUIRES_setuptools
SPKG_INSTALL_REQUIRES_wheel
]
build-backend = "setuptools.build_meta"
diff --git a/pkgs/sagemath-sirocco/VERSION.txt b/pkgs/sagemath-sirocco/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sagemath-sirocco/VERSION.txt
+++ b/pkgs/sagemath-sirocco/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sagemath-sirocco/pyproject.toml.m4 b/pkgs/sagemath-sirocco/pyproject.toml.m4
index 55e400738d7..6f2874254ab 100644
--- a/pkgs/sagemath-sirocco/pyproject.toml.m4
+++ b/pkgs/sagemath-sirocco/pyproject.toml.m4
@@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*-
[build-system]
# Minimum requirements for the build system to execute.
requires = [
- SPKG_INSTALL_REQUIRES_setuptools_wheel
+ SPKG_INSTALL_REQUIRES_setuptools
SPKG_INSTALL_REQUIRES_sage_setup
SPKG_INSTALL_REQUIRES_sagemath_environment
SPKG_INSTALL_REQUIRES_cython
diff --git a/pkgs/sagemath-tdlib/VERSION.txt b/pkgs/sagemath-tdlib/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/pkgs/sagemath-tdlib/VERSION.txt
+++ b/pkgs/sagemath-tdlib/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/pkgs/sagemath-tdlib/pyproject.toml.m4 b/pkgs/sagemath-tdlib/pyproject.toml.m4
index 8e3bcdd988f..d3efaf52cc1 100644
--- a/pkgs/sagemath-tdlib/pyproject.toml.m4
+++ b/pkgs/sagemath-tdlib/pyproject.toml.m4
@@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*-
[build-system]
# Minimum requirements for the build system to execute.
requires = [
- SPKG_INSTALL_REQUIRES_setuptools_wheel
+ SPKG_INSTALL_REQUIRES_setuptools
SPKG_INSTALL_REQUIRES_sage_setup
SPKG_INSTALL_REQUIRES_sagemath_environment
SPKG_INSTALL_REQUIRES_cython
diff --git a/src/VERSION.txt b/src/VERSION.txt
index 4d40853d20c..201b86839ab 100644
--- a/src/VERSION.txt
+++ b/src/VERSION.txt
@@ -1 +1 @@
-10.3.beta2
+10.3.beta4
diff --git a/src/bin/sage b/src/bin/sage
index ba353116e7c..a198ed8f273 100755
--- a/src/bin/sage
+++ b/src/bin/sage
@@ -628,7 +628,9 @@ fi
if [ "$1" = '-gap' -o "$1" = '--gap' ]; then
shift
- exec gap "$@"
+ # Use "-A" to avoid warnings about missing packages. The gap
+ # interface and libgap within sage both already do this.
+ exec gap -A "$@"
fi
if [ "$1" = '-gap3' -o "$1" = '--gap3' ]; then
@@ -1001,6 +1003,7 @@ if [ "$1" = '-tox' -o "$1" = '--tox' ]; then
exec tox -c "$SAGE_SRC" "$@"
else
echo "Run 'sage -i tox' to install"
+ exit 1
fi
else
echo >&2 "error: Sage source directory or tox.ini not available"
@@ -1022,6 +1025,7 @@ if [ "$1" = '-pytest' -o "$1" = '--pytest' ]; then
exec pytest --rootdir="$SAGE_SRC" --doctest-modules "$@" "$SAGE_SRC"
else
echo "Run 'sage -i pytest' to install"
+ exit 1
fi
else
echo >&2 "error: Sage source directory or tox.ini not available"
diff --git a/src/bin/sage-env b/src/bin/sage-env
index 29b96c3c895..8fcfda48fb6 100644
--- a/src/bin/sage-env
+++ b/src/bin/sage-env
@@ -228,7 +228,7 @@ fi
# depending on SAGE_ROOT and SAGE_LOCAL which are already defined.
if [ -n "$SAGE_LOCAL" ]; then
export SAGE_SHARE="$SAGE_LOCAL/share"
- export SAGE_SPKG_INST="$SAGE_LOCAL/var/lib/sage/installed"
+ export SAGE_SPKG_INST="$SAGE_LOCAL/var/lib/sage/installed" # deprecated
fi
if [ -n "$SAGE_SHARE" ]; then
export SAGE_DOC="$SAGE_SHARE/doc/sage"
diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh
index 7d38e167623..701727e3543 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.3.beta2'
-SAGE_RELEASE_DATE='2023-12-13'
-SAGE_VERSION_BANNER='SageMath version 10.3.beta2, Release Date: 2023-12-13'
+SAGE_VERSION='10.3.beta4'
+SAGE_RELEASE_DATE='2023-12-26'
+SAGE_VERSION_BANNER='SageMath version 10.3.beta4, Release Date: 2023-12-26'
diff --git a/src/doc/bootstrap b/src/doc/bootstrap
index b6830ad7bb3..2371945a283 100755
--- a/src/doc/bootstrap
+++ b/src/doc/bootstrap
@@ -19,7 +19,6 @@ fi
cd "$SAGE_ROOT"
-STRIP_COMMENTS="sed s/#.*//;"
OUTPUT_DIR="src/doc/en/installation"
mkdir -p "$OUTPUT_DIR"
@@ -37,9 +36,8 @@ for SYSTEM in arch debian fedora homebrew opensuse; do
DEVELOP_SYSTEM_PACKAGES=
for PKG_BASE in $(sage-package list --has-file distros/$SYSTEM.txt); do
PKG_SCRIPTS=build/pkgs/$PKG_BASE
- SYSTEM_PACKAGES_FILE=$PKG_SCRIPTS/distros/$SYSTEM.txt
PKG_TYPE=$(cat $PKG_SCRIPTS/type)
- PKG_SYSTEM_PACKAGES=$(echo $(${STRIP_COMMENTS} $SYSTEM_PACKAGES_FILE))
+ PKG_SYSTEM_PACKAGES=$(sage-get-system-packages $SYSTEM $PKG_BASE)
if [ -n "PKG_SYSTEM_PACKAGES" ]; then
if [ -f $PKG_SCRIPTS/spkg-configure.m4 ]; then
case "$PKG_BASE:$PKG_TYPE" in
@@ -75,10 +73,10 @@ for SYSTEM in arch debian fedora homebrew opensuse; do
if [ "${BOOTSTRAP_QUIET}" = "no" ]; then
echo >&2 $0:$LINENO: installing "$OUTPUT_DIR"/$SYSTEM"*.txt"
fi
- echo "$(sage-print-system-package-command $SYSTEM --prompt --sudo install $(echo $(echo $SYSTEM_PACKAGES | xargs -n 1 echo | sort | uniq)))" > "$OUTPUT_DIR"/$SYSTEM.txt
- echo "$(sage-print-system-package-command $SYSTEM --prompt --sudo install $(echo $(echo $OPTIONAL_SYSTEM_PACKAGES | xargs -n 1 echo | sort | uniq)))" > "$OUTPUT_DIR"/$SYSTEM-optional.txt
- echo "$(sage-print-system-package-command $SYSTEM --prompt --sudo install $(echo $(echo $RECOMMENDED_SYSTEM_PACKAGES | xargs -n 1 echo | sort | uniq)))" > "$OUTPUT_DIR"/$SYSTEM-recommended.txt
- echo "$(sage-print-system-package-command $SYSTEM --prompt --sudo install $(echo $(echo $DEVELOP_SYSTEM_PACKAGES | xargs -n 1 echo | sort | uniq)))" > "$OUTPUT_DIR"/$SYSTEM-develop.txt
+ echo "$(sage-print-system-package-command $SYSTEM --prompt --wrap --sudo install $(echo $(echo $SYSTEM_PACKAGES | xargs -n 1 echo | sort | uniq)))" > "$OUTPUT_DIR"/$SYSTEM.txt
+ echo "$(sage-print-system-package-command $SYSTEM --prompt --wrap --sudo install $(echo $(echo $OPTIONAL_SYSTEM_PACKAGES | xargs -n 1 echo | sort | uniq)))" > "$OUTPUT_DIR"/$SYSTEM-optional.txt
+ echo "$(sage-print-system-package-command $SYSTEM --prompt --wrap --sudo install $(echo $(echo $RECOMMENDED_SYSTEM_PACKAGES | xargs -n 1 echo | sort | uniq)))" > "$OUTPUT_DIR"/$SYSTEM-recommended.txt
+ echo "$(sage-print-system-package-command $SYSTEM --prompt --wrap --sudo install $(echo $(echo $DEVELOP_SYSTEM_PACKAGES | xargs -n 1 echo | sort | uniq)))" > "$OUTPUT_DIR"/$SYSTEM-develop.txt
done
OUTPUT_DIR="src/doc/en/reference/spkg"
@@ -190,7 +188,7 @@ All External Packages
EOF
OUTPUT_INDEX="$OUTPUT_DIR"/index_alph.rst
-cat >> "$OUTPUT_INDEX" < "$OUTPUT_DIR"/$PKG_BASE.rst
- echo >> "$OUTPUT_INDEX" " $PKG_BASE"
+ echo " $PKG_BASE"
done
-cat >> "$OUTPUT_INDEX" < "$OUTPUT_INDEX"
+sage-package list --has-file SPKG.rst | OUTPUT_DIR=$OUTPUT_DIR OUTPUT_RST=1 xargs -P 0 -n 1 sage-spkg-info
diff --git a/src/doc/en/constructions/groups.rst b/src/doc/en/constructions/groups.rst
index 042d37088b1..da90efecfaa 100644
--- a/src/doc/en/constructions/groups.rst
+++ b/src/doc/en/constructions/groups.rst
@@ -180,8 +180,8 @@ Here's another way, working more directly with GAP::
sage: print(gap.eval("normal := NormalSubgroups( G )"))
[ Alt( [ 1 .. 5 ] ), Group(()) ]
sage: G = gap.new("DihedralGroup( 10 )")
- sage: G.NormalSubgroups()
- [ Group( [ f1, f2 ] ), Group( [ f2 ] ), Group( of ... ) ]
+ sage: G.NormalSubgroups().SortedList()
+ [ Group( of ... ), Group( [ f2 ] ), Group( [ f1, f2 ] ) ]
sage: print(gap.eval("G := SymmetricGroup( 4 )"))
Sym( [ 1 .. 4 ] )
sage: print(gap.eval("normal := NormalSubgroups( G );"))
diff --git a/src/doc/en/developer/coding_in_other.rst b/src/doc/en/developer/coding_in_other.rst
index 544add15b88..6fb31770815 100644
--- a/src/doc/en/developer/coding_in_other.rst
+++ b/src/doc/en/developer/coding_in_other.rst
@@ -714,7 +714,7 @@ dumps the user into an Octave interactive shell:
OUTPUT:
- An list x (if it exists) which solves M*x = b
+ A list x (if it exists) which solves M*x = b
EXAMPLES::
diff --git a/src/doc/en/developer/packaging.rst b/src/doc/en/developer/packaging.rst
index 4ed1762efe6..96eb302e2d3 100644
--- a/src/doc/en/developer/packaging.rst
+++ b/src/doc/en/developer/packaging.rst
@@ -512,10 +512,15 @@ containing files with names like ::
arch.txt
conda.txt
debian.txt
+ fedora.txt
homebrew.txt
...
-corresponding to different packaging systems.
+corresponding to different packaging systems. Each system package
+should appear on a separate line. If the shell-style variable reference
+``${PYTHON_MINOR}`` appears, it is replaced by the minor version of
+Python, e.g., 12 for Python 3.12.x. Everything on a line after a ``#``
+character is ignored, so comments can be included in the files.
For example, if ``./configure`` detects that the Homebrew packaging
system is in use, and if the current package can be provided by a
@@ -1048,9 +1053,11 @@ Sage mirrors when a new release is prepared. On GitHub PRs
upgrading a package, the PR description should no longer contain
the upstream URL to avoid duplication of information.
-Note that, like the ``tarball`` field, the ``tpstream_url`` is a
+Note that, like the ``tarball`` field, the ``upstream_url`` is a
template; the substring ``VERSION`` is substituted with the actual
-version.
+version. It can also be written as ``${VERSION}``, and it is possible
+to refer to the dot-separated components of a version by ``VERSION_MAJOR``,
+``VERSION_MINOR``, and ``VERSION_MICRO``.
For Python packages available from PyPI, you should use an
``upstream_url`` from ``pypi.io``, which follows the format
diff --git a/src/doc/en/developer/review.rst b/src/doc/en/developer/review.rst
index 44a9214b9fe..b2bc38353cb 100644
--- a/src/doc/en/developer/review.rst
+++ b/src/doc/en/developer/review.rst
@@ -134,7 +134,7 @@ the patches have been applied to a given release, the issue would
remain in limbo.
**No Patch Bombs**: Code that goes into Sage is peer-reviewed. If
-you show up with an 80,000 lines of code bundle that completely
+you show up with 80,000 lines of code bundle that completely
rips out a subsystem and replaces it with something else, you can
imagine that the review process will be a little tedious. These
huge patch bombs are problematic for several reasons and we prefer
diff --git a/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst b/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst
index c6f11452ce8..101cbcdb4e7 100644
--- a/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst
+++ b/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst
@@ -83,15 +83,13 @@ rather than just a list of numbers. This can be very powerful.
::
- sage: for K in D.normal_subgroups():
+ sage: len(D.normal_subgroups())
+ 7
+ sage: for K in sorted(D.normal_subgroups()):
....: print(K)
- Subgroup generated by [(1,2,3,4,5,6,7,8), (1,8)(2,7)(3,6)(4,5)] of (Dihedral group of order 16 as a permutation group)
- Subgroup generated by [(1,2,3,4,5,6,7,8), (1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8)] of (Dihedral group of order 16 as a permutation group)
- Subgroup generated by [(1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8), (1,8)(2,7)(3,6)(4,5)] of (Dihedral group of order 16 as a permutation group)
- Subgroup generated by [(2,8)(3,7)(4,6), (1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8)] of (Dihedral group of order 16 as a permutation group)
- Subgroup generated by [(1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8)] of (Dihedral group of order 16 as a permutation group)
- Subgroup generated by [(1,5)(2,6)(3,7)(4,8)] of (Dihedral group of order 16 as a permutation group)
Subgroup generated by [()] of (Dihedral group of order 16 as a permutation group)
+ ...
+ Subgroup generated by [(1,2,3,4,5,6,7,8), (1,8)(2,7)(3,6)(4,5)] of (Dihedral group of order 16 as a permutation group)
We can access specific subgroups if we know the generators as a
permutation group.
diff --git a/src/doc/en/reference/algebras/lie_algebras.rst b/src/doc/en/reference/algebras/lie_algebras.rst
index 23152ac0449..457eb90f14e 100644
--- a/src/doc/en/reference/algebras/lie_algebras.rst
+++ b/src/doc/en/reference/algebras/lie_algebras.rst
@@ -19,6 +19,7 @@ Lie Algebras
sage/algebras/lie_algebras/poincare_birkhoff_witt
sage/algebras/lie_algebras/quotient
sage/algebras/lie_algebras/rank_two_heisenberg_virasoro
+ sage/algebras/lie_algebras/representation
sage/algebras/lie_algebras/structure_coefficients
sage/algebras/lie_algebras/subalgebra
sage/algebras/lie_algebras/symplectic_derivation
diff --git a/src/doc/en/reference/coercion/index.rst b/src/doc/en/reference/coercion/index.rst
index 27459609dc9..73dfd978008 100644
--- a/src/doc/en/reference/coercion/index.rst
+++ b/src/doc/en/reference/coercion/index.rst
@@ -323,7 +323,7 @@ Methods to implement
the function is called on the potential codomain. To indicate that
there is no coercion from S to R (self), return ``False`` or
``None``. This is the default behavior. If there is a coercion,
- return ``True`` (in which case an morphism using
+ return ``True`` (in which case a morphism using
``R._element_constructor_`` will be created) or an actual
:class:`Morphism` object with S as the domain and R as the codomain.
@@ -386,87 +386,97 @@ but that would obscure the main points being made here.)
::
- class Localization(Ring):
- def __init__(self, primes):
- """
- Localization of `\ZZ` away from primes.
- """
- Ring.__init__(self, base=ZZ)
- self._primes = primes
- self._populate_coercion_lists_()
-
- def _repr_(self):
- """
- How to print self.
- """
- return "%s localized at %s" % (self.base(), self._primes)
-
- def _element_constructor_(self, x):
- """
- Make sure x is a valid member of self, and return the constructed element.
- """
- if isinstance(x, LocalizationElement):
- x = x._value
- else:
- x = QQ(x)
- for p, e in x.denominator().factor():
- if p not in self._primes:
- raise ValueError("Not integral at %s" % p)
- return LocalizationElement(self, x)
-
- def _coerce_map_from_(self, S):
- """
- The only things that coerce into this ring are:
-
- - the integer ring
-
- - other localizations away from fewer primes
- """
- if S is ZZ:
- return True
- elif isinstance(S, Localization):
- return all(p in self._primes for p in S._primes)
-
-
- class LocalizationElement(RingElement):
-
- def __init__(self, parent, x):
- RingElement.__init__(self, parent)
- self._value = x
-
-
- # We're just printing out this way to make it easy to see what's going on in the examples.
-
- def _repr_(self):
- return "LocalElt(%s)" % self._value
-
- # Now define addition, subtraction, and multiplication of elements.
- # Note that left and right always have the same parent.
-
- def _add_(left, right):
- return LocalizationElement(left.parent(), left._value + right._value)
-
- def _sub_(left, right):
- return LocalizationElement(left.parent(), left._value - right._value)
-
- def _mul_(left, right):
- return LocalizationElement(left.parent(), left._value * right._value)
-
- # The basering was set to ZZ, so c is guaranteed to be in ZZ
-
- def _rmul_(self, c):
- return LocalizationElement(self.parent(), c * self._value)
-
- def _lmul_(self, c):
- return LocalizationElement(self.parent(), self._value * c)
+ sage: from sage.structure.richcmp import richcmp
+ sage: from sage.structure.element import Element
+
+ sage: class MyLocalization(Parent):
+ ....: def __init__(self, primes):
+ ....: r"""
+ ....: Localization of `\ZZ` away from primes.
+ ....: """
+ ....: Parent.__init__(self, base=ZZ, category=Rings().Commutative())
+ ....: self._primes = primes
+ ....: self._populate_coercion_lists_()
+ ....:
+ ....: def _repr_(self) -> str:
+ ....: """
+ ....: How to print ``self``.
+ ....: """
+ ....: return "%s localized at %s" % (self.base(), self._primes)
+ ....:
+ ....: def _element_constructor_(self, x):
+ ....: """
+ ....: Make sure ``x`` is a valid member of ``self``, and return the constructed element.
+ ....: """
+ ....: if isinstance(x, MyLocalizationElement):
+ ....: x = x._value
+ ....: else:
+ ....: x = QQ(x)
+ ....: for p, e in x.denominator().factor():
+ ....: if p not in self._primes:
+ ....: raise ValueError("not integral at %s" % p)
+ ....: return self.element_class(self, x)
+ ....:
+ ....: def _an_element_(self):
+ ....: return self.element_class(self, 6)
+ ....:
+ ....: def _coerce_map_from_(self, S):
+ ....: """
+ ....: The only things that coerce into this ring are:
+ ....:
+ ....: - the integer ring
+ ....:
+ ....: - other localizations away from fewer primes
+ ....: """
+ ....: if S is ZZ:
+ ....: return True
+ ....: if isinstance(S, MyLocalization):
+ ....: return all(p in self._primes for p in S._primes)
+
+ sage: class MyLocalizationElement(Element):
+ ....:
+ ....: def __init__(self, parent, x):
+ ....: Element.__init__(self, parent)
+ ....: self._value = x
+ ....:
+ ....: # We are just printing out this way to make it easy to see what's going on in the examples.
+ ....:
+ ....: def _repr_(self) -> str:
+ ....: return f"LocalElt({self._value})"
+ ....:
+ ....: # Now define addition, subtraction and multiplication of elements.
+ ....: # Note that self and right always have the same parent.
+ ....:
+ ....: def _add_(self, right):
+ ....: return self.parent()(self._value + right._value)
+ ....:
+ ....: def _sub_(self, right):
+ ....: return self.parent()(self._value - right._value)
+ ....:
+ ....: def _mul_(self, right):
+ ....: return self.parent()(self._value * right._value)
+ ....:
+ ....: # The basering was set to ZZ, so c is guaranteed to be in ZZ
+ ....:
+ ....: def _rmul_(self, c):
+ ....: return self.parent()(c * self._value)
+ ....:
+ ....: def _lmul_(self, c):
+ ....: return self.parent()(self._value * c)
+ ....:
+ ....: def _richcmp_(self, other, op):
+ ....: return richcmp(self._value, other._value, op)
+
+ sage: MyLocalization.element_class = MyLocalizationElement
That's all there is to it. Now we can test it out:
-.. skip
+.. link
::
- sage: R = Localization([2]); R
+ sage: TestSuite(R).run(skip="_test_pickling")
+ sage: R = MyLocalization([2]); R
Integer Ring localized at [2]
sage: R(1)
LocalElt(1)
@@ -475,12 +485,12 @@ That's all there is to it. Now we can test it out:
sage: R(1/3)
Traceback (most recent call last):
...
- ValueError: Not integral at 3
+ ValueError: not integral at 3
sage: R.coerce(1)
LocalElt(1)
sage: R.coerce(1/4)
- Traceback (click to the left for traceback)
+ Traceback (most recent call last):
...
TypeError: no canonical coercion from Rational Field to Integer Ring localized at [2]
@@ -497,12 +507,10 @@ That's all there is to it. Now we can test it out:
sage: R(3/4) * 7
LocalElt(21/4)
- sage: R.get_action(ZZ)
- Right scalar multiplication by Integer Ring on Integer Ring localized at [2]
sage: cm = sage.structure.element.get_coercion_model()
sage: cm.explain(R, ZZ, operator.add)
Coercion on right operand via
- Conversion map:
+ Coercion map:
From: Integer Ring
To: Integer Ring localized at [2]
Arithmetic performed after coercions.
@@ -510,12 +518,15 @@ That's all there is to it. Now we can test it out:
Integer Ring localized at [2]
sage: cm.explain(R, ZZ, operator.mul)
- Action discovered.
- Right scalar multiplication by Integer Ring on Integer Ring localized at [2]
+ Coercion on right operand via
+ Coercion map:
+ From: Integer Ring
+ To: Integer Ring localized at [2]
+ Arithmetic performed after coercions.
Result lives in Integer Ring localized at [2]
Integer Ring localized at [2]
- sage: R6 = Localization([2,3]); R6
+ sage: R6 = MyLocalization([2,3]); R6
Integer Ring localized at [2, 3]
sage: R6(1/3) - R(1/2)
LocalElt(-1/6)
@@ -525,12 +536,12 @@ That's all there is to it. Now we can test it out:
sage: R.has_coerce_map_from(ZZ)
True
sage: R.coerce_map_from(ZZ)
- Conversion map:
+ Coercion map:
From: Integer Ring
To: Integer Ring localized at [2]
sage: R6.coerce_map_from(R)
- Conversion map:
+ Coercion map:
From: Integer Ring localized at [2]
To: Integer Ring localized at [2, 3]
@@ -539,7 +550,7 @@ That's all there is to it. Now we can test it out:
sage: cm.explain(R, R6, operator.mul)
Coercion on left operand via
- Conversion map:
+ Coercion map:
From: Integer Ring localized at [2]
To: Integer Ring localized at [2, 3]
Arithmetic performed after coercions.
diff --git a/src/doc/en/reference/databases/index.rst b/src/doc/en/reference/databases/index.rst
index 56289fa5236..7cff08ee68a 100644
--- a/src/doc/en/reference/databases/index.rst
+++ b/src/doc/en/reference/databases/index.rst
@@ -1,68 +1,40 @@
Databases
=========
-There are numerous specific mathematical databases either included
-in Sage or available as optional packages. Also, Sage includes two
-powerful general database packages.
+Sage includes mathematical databases as standard or optional packages,
+and provides convenient interfaces for easy access to the databases.
-Sage includes the ZOPE object oriented database ZODB, which
-"is a Python object persistence system. It provides transparent object-oriented persistency."
+Standard databases
+------------------
-Sage also includes the powerful relational database SQLite, along
-with a Python interface to SQLite. SQlite is a small C library that
-implements a self-contained, embeddable, zero-configuration SQL
-database engine.
+These databases are available in the standard install of Sage or if Sage can access
+Internet.
+.. toctree::
+ :maxdepth: 1
-- Transactions are atomic, consistent, isolated, and durable
- (ACID) even after system crashes and power failures.
-
-- Zero-configuration - no setup or administration needed.
-
-- Implements most of SQL92. (Features not supported)
-
-- A complete database is stored in a single disk file.
-
-- Database files can be freely shared between machines with
- different byte orders.
-
-- Supports databases up to 2 tebibytes (2^41 bytes) in size.
-
-- Strings and BLOBs up to 2 gibibytes (2^31 bytes) in size.
-
-- Small code footprint: less than 250KiB fully configured or less
- than 150KiB with optional features omitted.
-
-- Faster than popular client/server database engines for most
- common operations.
-
-- Simple, easy to use API.
-
-- TCL bindings included. Bindings for many other languages
- available separately.
-
-- Well-commented source code with over 95% test coverage.
+ sage/databases/conway
+ sage/databases/oeis
+ sage/databases/sloane
+ sage/databases/findstat
-- Self-contained: no external dependencies.
+Optional databases
+------------------
-- Sources are in the public domain. Use for any purpose.
+The following databases require you to install optional packages before full access.
.. toctree::
:maxdepth: 1
+ sage/databases/cunningham_tables
+ sage/databases/knotinfo_db
+ sage/databases/cubic_hecke_db
+ sage/databases/symbolic_data
sage/databases/cremona
sage/databases/stein_watkins
sage/databases/jones
- sage/databases/oeis
- sage/databases/sloane
- sage/databases/findstat
- sage/databases/conway
- sage/databases/odlyzko
- sage/databases/symbolic_data
- sage/databases/cunningham_tables
sage/databases/db_class_polynomials
sage/databases/db_modular_polynomials
- sage/databases/knotinfo_db
- sage/databases/cubic_hecke_db
+ sage/databases/odlyzko
.. include:: ../footer.txt
diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst
index d810bed4869..3f207ec0539 100644
--- a/src/doc/en/reference/references/index.rst
+++ b/src/doc/en/reference/references/index.rst
@@ -4520,6 +4520,10 @@ REFERENCES:
.. [Mat2002] Jiří Matousek, "Lectures on Discrete Geometry", Springer,
2002
+.. [Mathas2004] Andrew Mathas.
+ *Matrix units and generic degrees for the Ariki-Koike algebras*.
+ J. Algebra. **281** (2004) pp. 695-730.
+
.. [Mas1995] Mason, Geoffrey. *The quantum double of a finite group and its role
in conformal field theory*. Groups '93 Galway/St. Andrews, Vol. 2,
405-417, London Math. Soc. Lecture Note Ser., 212, Cambridge, 1995.
diff --git a/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/elliptic_curves.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/elliptic_curves.rst
index d1a2bda863b..6fe991abf45 100644
--- a/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/elliptic_curves.rst
+++ b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/elliptic_curves.rst
@@ -5,7 +5,7 @@ Cremona's Databases
-------------------
Cremona's databases of elliptic curves are part of Sage. The curves up
-to conductor 10,000 come standard with Sage, and an there is an optional
+to conductor 10,000 come standard with Sage, and there is an optional
download to gain access to his complete tables. From a shell, you
should run ::
diff --git a/src/doc/en/thematic_tutorials/numerical_sage/f2py.rst b/src/doc/en/thematic_tutorials/numerical_sage/f2py.rst
index 78cea180e2f..57fd4f1b977 100644
--- a/src/doc/en/thematic_tutorials/numerical_sage/f2py.rst
+++ b/src/doc/en/thematic_tutorials/numerical_sage/f2py.rst
@@ -204,7 +204,7 @@ you only care about its value before the function is called not
afterwards. So in the above n tells us how many fiboncci numbers to
compute we need to specify this as an input, however we don't need
to get n back as it doesn't contain anything new. Similarly A is
-intent(out) so we don't need A to have an specific value
+intent(out) so we don't need A to have a specific value
beforehand, we just care about the contents afterwards. F2py
generates a Python function so you only pass those declared
intent(in) and supplies empty workspaces for the remaining
diff --git a/src/doc/en/thematic_tutorials/sandpile.rst b/src/doc/en/thematic_tutorials/sandpile.rst
index 0d7907014b7..9c5c0919bcb 100644
--- a/src/doc/en/thematic_tutorials/sandpile.rst
+++ b/src/doc/en/thematic_tutorials/sandpile.rst
@@ -2865,7 +2865,7 @@ SandpileConfig
**\***
- If ``other`` is an configuration, the recurrent element equivalent
+ If ``other`` is a configuration, the recurrent element equivalent
to the sum. If ``other`` is an integer, the sum of configuration with
itself ``other`` times.
diff --git a/src/doc/fr/tutorial/conf.py b/src/doc/fr/tutorial/conf.py
index 7208ddada17..f44315072ff 100644
--- a/src/doc/fr/tutorial/conf.py
+++ b/src/doc/fr/tutorial/conf.py
@@ -39,9 +39,6 @@
'The Sage Group', 'manual'),
]
-# Additional LaTeX stuff for the French version
-#latex_elements['preamble'] += '\\DeclareUnicodeCharacter{00A0}{\\nobreakspace}\n'
-
# the definition of \\at in the standard preamble of the sphinx doc
# conflicts with that in babel/french[b]
latex_elements['preamble'] += '\\let\\at\\undefined'
diff --git a/src/doc/ja/a_tour_of_sage/conf.py b/src/doc/ja/a_tour_of_sage/conf.py
index bf1f84bf962..451d7cc5b58 100644
--- a/src/doc/ja/a_tour_of_sage/conf.py
+++ b/src/doc/ja/a_tour_of_sage/conf.py
@@ -25,6 +25,10 @@
name = 'a_tour_of_sage'
language = "ja"
+# The LaTeX engine to build the docs in Japanese.
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-latex_engine
+latex_engine = 'uplatex'
+
# The name for this set of Sphinx documents. If None, it defaults to
# " v documentation".
html_title = project + " v" + release
diff --git a/src/doc/ja/tutorial/conf.py b/src/doc/ja/tutorial/conf.py
index 9521bc91828..e4b79bd7875 100644
--- a/src/doc/ja/tutorial/conf.py
+++ b/src/doc/ja/tutorial/conf.py
@@ -25,6 +25,10 @@
name = 'tutorial-jp'
language = "ja"
+# The LaTeX engine to build the docs in Japanese.
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-latex_engine
+latex_engine = 'uplatex'
+
# The name for this set of Sphinx documents. If None, it defaults to
# " v documentation".
html_title = project + " v" + release
diff --git a/src/doc/ru/tutorial/conf.py b/src/doc/ru/tutorial/conf.py
index 0b7a8c4e3db..cda4d9762ed 100644
--- a/src/doc/ru/tutorial/conf.py
+++ b/src/doc/ru/tutorial/conf.py
@@ -38,6 +38,3 @@
('index', 'SageTutorial_ru.tex', 'Sage Tutorial in Russian',
'The Sage Development Team', 'manual'),
]
-
-# Additional LaTeX stuff if necessary:
-#latex_elements['preamble'] += '\\DeclareUnicodeCharacter{00A0}{\\nobreakspace}\n'
diff --git a/src/pyproject.toml.m4 b/src/pyproject.toml.m4
index 2b61ea041ea..2d60708affa 100644
--- a/src/pyproject.toml.m4
+++ b/src/pyproject.toml.m4
@@ -7,7 +7,7 @@ requires = [
# https://github.com/pypa/pip/issues/6144
esyscmd(`sage-get-system-packages install-requires-toml \
sage_conf \
- setuptools_wheel \
+ setuptools \
wheel \
sage_setup \
cypari \
diff --git a/src/requirements.txt.m4 b/src/requirements.txt.m4
index 346ea3c6301..34c42860cf1 100644
--- a/src/requirements.txt.m4
+++ b/src/requirements.txt.m4
@@ -32,7 +32,6 @@ dnl ... already needed by sage.env
pkgconfig==esyscmd(`printf $(sed "s/[.]p.*//;" ../pkgconfig/package-version.txt)')
pplpy==esyscmd(`printf $(sed "s/[.]p.*//;" ../pplpy/package-version.txt)')
primecountpy==esyscmd(`printf $(sed "s/[.]p.*//;" ../primecountpy/package-version.txt)')
-pycygwin==esyscmd(`printf $(sed "s/[.]p.*//;" ../pycygwin/package-version.txt)'); sys_platform == 'cygwin'
requests==esyscmd(`printf $(sed "s/[.]p.*//;" ../requests/package-version.txt)')
typing_extensions==esyscmd(`printf $(sed "s/[.]p.*//;" ../typing_extensions/package-version.txt)')
diff --git a/src/sage/algebras/cellular_basis.py b/src/sage/algebras/cellular_basis.py
index c80eee401ff..8c474420378 100644
--- a/src/sage/algebras/cellular_basis.py
+++ b/src/sage/algebras/cellular_basis.py
@@ -164,7 +164,7 @@ class CellularBasis(CombinatorialFreeModule):
- C([2, 1], [[1, 3], [2]], [[1, 3], [2]])
+ C([3], [[1, 2, 3]], [[1, 2, 3]])
"""
- def __init__(self, A):
+ def __init__(self, A, to_algebra=None, from_algebra=None, **kwargs):
r"""
Initialize ``self``.
@@ -181,21 +181,26 @@ def __init__(self, A):
# TODO: Use instead A.category().Realizations() so
# operations are defined by coercion?
+ prefix = kwargs.pop('prefix', 'C')
cat = Algebras(A.category().base_ring()).FiniteDimensional().WithBasis().Cellular()
CombinatorialFreeModule.__init__(self, A.base_ring(), I,
- prefix='C', bracket=False,
- category=cat)
+ prefix=prefix, bracket=False,
+ category=cat, **kwargs)
# Register coercions
- if A._to_cellular_element is not NotImplemented:
- to_cellular = A.module_morphism(A._to_cellular_element, codomain=self,
+ if from_algebra is None:
+ from_algebra = A._to_cellular_element
+ if to_algebra is None:
+ to_algebra = A._from_cellular_index
+ if from_algebra is not NotImplemented:
+ to_cellular = A.module_morphism(from_algebra, codomain=self,
category=cat)
- if A._from_cellular_index is NotImplemented:
+ if to_algebra is NotImplemented:
from_cellular = ~to_cellular
else:
- from_cellular = self.module_morphism(A._from_cellular_index, codomain=A,
+ from_cellular = self.module_morphism(to_algebra, codomain=A,
category=cat)
- if A._to_cellular_element is NotImplemented:
+ if from_algebra is NotImplemented:
to_cellular = ~from_cellular
to_cellular.register_as_coercion()
from_cellular.register_as_coercion()
diff --git a/src/sage/algebras/commutative_dga.py b/src/sage/algebras/commutative_dga.py
index 35facfa7866..a65581f8db1 100644
--- a/src/sage/algebras/commutative_dga.py
+++ b/src/sage/algebras/commutative_dga.py
@@ -3087,7 +3087,7 @@ def is_cohomologous_to(self, other):
def cohomology_class(self):
r"""
- Return the cohomology class of an homogeneous cycle, as an element
+ Return the cohomology class of a homogeneous cycle, as an element
of the corresponding cohomology group.
EXAMPLES::
diff --git a/src/sage/algebras/hecke_algebras/cubic_hecke_algebra.py b/src/sage/algebras/hecke_algebras/cubic_hecke_algebra.py
index 5a3bd2ceb47..4f2a604aa8b 100644
--- a/src/sage/algebras/hecke_algebras/cubic_hecke_algebra.py
+++ b/src/sage/algebras/hecke_algebras/cubic_hecke_algebra.py
@@ -1458,7 +1458,7 @@ def one_basis(self):
def _an_element_(self):
r"""
Overwrite the original method from :mod:`~sage.combinat.free_module`
- to obtain an more interesting element for ``TestSuite``.
+ to obtain a more interesting element for ``TestSuite``.
EXAMPLES::
@@ -2233,7 +2233,7 @@ def _braid_image_by_basis_extension(self, braid_tietze):
sage: CHA5._basis_extension
[[4], [-4], [4, 1]]
- case where the braid already has an corresponding basis element::
+ case where the braid already has a corresponding basis element::
sage: CHA5._braid_image_by_basis_extension((1,)) # optional - database_cubic_hecke
c0
diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pxd b/src/sage/algebras/lie_algebras/lie_algebra_element.pxd
index 9005eae72fd..227ce2559f9 100644
--- a/src/sage/algebras/lie_algebras/lie_algebra_element.pxd
+++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pxd
@@ -50,6 +50,7 @@ cdef class LieObject(SageObject):
cdef class LieGenerator(LieObject):
cdef public str _name
+ cpdef lift(self, dict UEA_gens_dict)
cdef class LieBracket(LieObject):
cdef public LieObject _left
diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx
index f221fe6ab55..ca53753153b 100644
--- a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx
+++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx
@@ -1232,9 +1232,9 @@ cdef class UntwistedAffineLieAlgebraElement(Element):
return type(self)(self._parent, negate(self._t_dict),
-self._c_coeff, -self._d_coeff)
- cpdef _acted_upon_(self, x, bint self_on_left) noexcept:
+ cpdef _acted_upon_(self, scalar, bint self_on_left) noexcept:
"""
- Return ``self`` acted upon by ``x``.
+ Return ``self`` acted upon by ``scalar``.
EXAMPLES::
@@ -1246,9 +1246,21 @@ cdef class UntwistedAffineLieAlgebraElement(Element):
sage: -2 * x
(-2*E[alpha[1]])#t^0 + (-2*h1)#t^-1 + -6*c + 4/5*d
"""
- return type(self)(self._parent, scal(x, self._t_dict, self_on_left),
- x * self._c_coeff,
- x * self._d_coeff)
+ # This was copied and IDK if it still applies (TCS):
+ # With the current design, the coercion model does not have
+ # enough information to detect apriori that this method only
+ # accepts scalars; so it tries on some elements(), and we need
+ # to make sure to report an error.
+ scalar_parent = parent(scalar)
+ if scalar_parent != self._parent.base_ring():
+ # Temporary needed by coercion (see Polynomial/FractionField tests).
+ if self._parent.base_ring().has_coerce_map_from(scalar_parent):
+ scalar = self._parent.base_ring()(scalar)
+ else:
+ return None
+ return type(self)(self._parent, scal(scalar, self._t_dict, self_on_left),
+ scalar * self._c_coeff,
+ scalar * self._d_coeff)
cpdef monomial_coefficients(self, bint copy=True) noexcept:
"""
@@ -1661,6 +1673,25 @@ cdef class LieGenerator(LieObject):
"""
return self._word
+ cpdef lift(self, dict UEA_gens_dict):
+ """
+ Lift ``self`` to the universal enveloping algebra.
+
+ ``UEA_gens_dict`` should be the dictionary for the
+ generators of the universal enveloping algebra.
+
+ EXAMPLES::
+
+ sage: L = LieAlgebra(QQ, 'x,y,z')
+ sage: Lyn = L.Lyndon()
+ sage: x,y,z = Lyn.gens()
+ sage: x.lift()
+ x
+ sage: x.lift().parent()
+ Free Algebra on 3 generators (x, y, z) over Rational Field
+ """
+ return UEA_gens_dict[self._name]
+
cdef class LieBracket(LieObject):
"""
An abstract Lie bracket (formally, just a binary tree).
diff --git a/src/sage/algebras/lie_algebras/representation.py b/src/sage/algebras/lie_algebras/representation.py
new file mode 100644
index 00000000000..9d96c42c6fc
--- /dev/null
+++ b/src/sage/algebras/lie_algebras/representation.py
@@ -0,0 +1,435 @@
+r"""
+Representations of Lie algebras
+
+AUTHORS:
+
+- Travis Scrimshaw (2023-08-31): initial version
+"""
+
+# ****************************************************************************
+# Copyright (C) 2023 Travis Scrimshaw
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+# https://www.gnu.org/licenses/
+# ****************************************************************************
+
+from sage.sets.family import Family, AbstractFamily
+from sage.combinat.free_module import CombinatorialFreeModule
+from sage.categories.modules import Modules
+from copy import copy
+
+
+class Representation_abstract:
+ r"""
+ Mixin class for (left) representations of Lie algebras.
+
+ INPUT:
+
+ - ``lie_algebra`` -- a Lie algebra
+ """
+ def __init__(self, lie_algebra):
+ r"""
+ Initialize ``self``.
+
+ EXAMPLES::
+
+ sage: L = lie_algebras.sp(QQ, 6)
+ sage: R = L.trivial_representation()
+ sage: TestSuite(R).run()
+ """
+ self._lie_algebra = lie_algebra
+
+ def lie_algebra(self):
+ r"""
+ Return the Lie algebra whose representation ``self`` is.
+
+ EXAMPLES::
+
+ sage: L = lie_algebras.sl(QQ, 4)
+ sage: R = L.trivial_representation()
+ sage: R.lie_algebra() is L
+ True
+ """
+ return self._lie_algebra
+
+ def side(self):
+ r"""
+ Return that ``self`` is a left representation.
+
+ OUTPUT:
+
+ - the string ``"left"``
+
+ EXAMPLES::
+
+ sage: L = lie_algebras.sl(QQ, 4)
+ sage: R = L.trivial_representation()
+ sage: R.side()
+ 'left'
+ """
+ return 'left'
+
+ def _test_representation(self, **options):
+ r"""
+ Check (on some elements) that ``self`` is a representation of the
+ given Lie algebra using the basis of the Lie algebra.
+
+ EXAMPLES::
+
+ sage: L = lie_algebras.Heisenberg(QQ, 3)
+ sage: f = {b: b.adjoint_matrix() for b in L.basis()}
+ sage: R = L.representation(f)
+ sage: R._test_representation()
+ """
+ tester = self._tester(**options)
+ S = tester.some_elements()
+ elts = self._lie_algebra.basis()
+ if elts.cardinality() == float('inf'):
+ elts = list(elts.some_elements())
+ from sage.misc.misc import some_tuples
+ for x, y in some_tuples(elts, 2, tester._max_runs):
+ for v in S:
+ tester.assertEqual(x.bracket(y) * v, x * (y * v) - y * (x * v))
+
+
+class RepresentationByMorphism(CombinatorialFreeModule, Representation_abstract):
+ r"""
+ Representation of a Lie algebra defined by a Lie algebra morphism.
+
+ INPUT:
+
+ - ``lie_algebra`` -- a Lie algebra
+ - ``f`` -- the Lie algebra morphism defining the action of the basis
+ elements of ``lie_algebra``
+ - ``index_set`` -- (optional) the index set of the module basis
+ - ``on_basis`` -- (default: ``False``) the function ``f`` defines a
+ map from the basis elements or from a generic element of ``lie_algebra``
+
+ If ``f`` is encoded as a ``dict`` or ``Family``, then the keys must
+ be indices of the basis of ``lie_algebra`` and the values being the
+ corresponding matrix defining the action. This sets ``on_basis=True``.
+
+ EXAMPLES::
+
+ sage: L. = LieAlgebra(QQ, {('x','y'): {'y':1}})
+ sage: f = {x: Matrix([[1,0],[0,0]]), y: Matrix([[0,1],[0,0]])}
+ sage: L.representation(f)
+ Representation of Lie algebra on 2 generators (x, y) over Rational Field defined by:
+ [1 0]
+ x |--> [0 0]
+ [0 1]
+ y |--> [0 0]
+
+ We construct the direct sum of two copies of the trivial representation
+ for an infinite dimensional Lie algebra::
+
+ sage: L = lie_algebras.Affine(QQ, ['E',6,1])
+ sage: R = L.representation(lambda b: matrix.zero(QQ, 2), index_set=['a','b'])
+ sage: x = L.an_element()
+ sage: v = R.an_element(); v
+ 2*R['a'] + 2*R['b']
+ sage: x * v
+ 0
+
+ We construct a finite dimensional representation of the affline Lie algebra
+ of type `A_2^{(1)}`::
+
+ sage: L = lie_algebras.Affine(QQ, ['A',2,1]).derived_subalgebra()
+ sage: Phi_plus = list(RootSystem(['A',2]).root_lattice().positive_roots())
+ sage: def aff_action(key):
+ ....: mat = matrix.zero(QQ, 3)
+ ....: if key == 'c': # central element
+ ....: return mat
+ ....: b, ell = key
+ ....: if b in Phi_plus: # positive root
+ ....: ind = tuple(sorted(b.to_ambient().support()))
+ ....: mat[ind] = 1
+ ....: if ind[0] + 1 != ind[1]:
+ ....: mat[ind] = -1
+ ....: elif -b in Phi_plus: # negative root
+ ....: ind = tuple(sorted(b.to_ambient().support(), reverse=True))
+ ....: mat[ind] = 1
+ ....: if ind[0] - 1 != ind[1]:
+ ....: mat[ind] = -1
+ ....: else: # must be in the Cartan
+ ....: i = b.leading_support()
+ ....: mat[i,i] = -1
+ ....: mat[i-1,i-1] = 1
+ ....: return mat
+ sage: F = Family(L.basis(), aff_action, name="lifted natural repr")
+ sage: R = L.representation(index_set=range(1,4), on_basis=F)
+ sage: x = L.an_element(); x
+ (E[alpha[2]] + E[alpha[1]] + h1 + h2 + E[-alpha[2]] + E[-alpha[1]])#t^0
+ + (E[-alpha[1] - alpha[2]])#t^1 + (E[alpha[1] + alpha[2]])#t^-1 + c
+ sage: v = R.an_element(); v
+ 2*R[1] + 2*R[2] + 3*R[3]
+ sage: x * v
+ R[1] + 5*R[2] - 3*R[3]
+ sage: R._test_representation() # verify that it is a representation
+ """
+ @staticmethod
+ def __classcall_private__(cls, lie_algebra, f=None, index_set=None, on_basis=False, **kwargs):
+ r"""
+ Normalize inpute to ensure a unique representation.
+
+ EXAMPLES::
+
+ sage: L. = LieAlgebra(QQ, {('x','y'): {'y':1}})
+ sage: f1 = {'x': Matrix([[1,0],[0,0]]), 'y': Matrix([[0,1],[0,0]])}
+ sage: R1 = L.representation(f1)
+ sage: f2 = Family({x: Matrix([[1,0],[0,0]]), y: Matrix(QQ, [[0,1],[0,0]])})
+ sage: R2 = L.representation(f2)
+ sage: R1 is R2
+ True
+
+ TESTS::
+
+ sage: L. = LieAlgebra(QQ, {('x','y'): {'y':1}})
+ sage: f = {'x': Matrix([[1,0]]), 'y': Matrix([[0,1]])}
+ sage: L.representation(f)
+ Traceback (most recent call last):
+ ...
+ ValueError: all matrices must be square
+
+ sage: f = {'x': Matrix([[1,0],[0,0]]), 'y': Matrix([[0]])}
+ sage: L.representation(f)
+ Traceback (most recent call last):
+ ...
+ ValueError: all matrices must be square of size 2
+
+ sage: L.representation(index_set=[1,2,3])
+ Traceback (most recent call last):
+ ...
+ ValueError: either 'f' or 'on_basis' must be specified
+ sage: L.representation(on_basis=lambda x: QQ.zero())
+ Traceback (most recent call last):
+ ...
+ ValueError: the index set needs to be specified
+ """
+ from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
+ base = lie_algebra.base_ring()
+ C = Modules(base).WithBasis().FiniteDimensional()
+ C = C.or_subcategory(kwargs.pop('category', C))
+ B = lie_algebra.basis()
+ if not isinstance(on_basis, bool):
+ f = on_basis
+ on_basis = True
+ if isinstance(f, AbstractFamily):
+ if f.cardinality() < float('inf'):
+ f = dict(f)
+ on_basis = True
+ if isinstance(f, dict):
+ data = {}
+ dim = None
+ for k, mat in f.items():
+ if k in B:
+ k = k.leading_support()
+ if not mat.is_square():
+ raise ValueError("all matrices must be square")
+ if dim is None:
+ dim = mat.nrows()
+ elif mat.nrows() != dim or mat.ncols() != dim:
+ raise ValueError("all matrices must be square of size {}".format(dim))
+ data[k] = mat.change_ring(base)
+ data[k].set_immutable()
+
+ if index_set is None:
+ index_set = FiniteEnumeratedSet(range(dim))
+ f = Family(data)
+ on_basis = True
+
+ if f is None:
+ raise ValueError("either 'f' or 'on_basis' must be specified")
+ if index_set is None:
+ raise ValueError("the index set needs to be specified")
+
+ index_set = FiniteEnumeratedSet(index_set)
+
+ return super(cls, RepresentationByMorphism).__classcall__(cls, lie_algebra,
+ f, index_set, on_basis, category=C, **kwargs)
+
+ def __init__(self, lie_algebra, f, index_set, on_basis, category, **kwargs):
+ r"""
+ Initialize ``self``.
+
+ EXAMPLES::
+
+ sage: L. = LieAlgebra(QQ, {('x','y'): {'y':1}})
+ sage: f = {'x': Matrix([[1,0],[0,0]]), 'y': Matrix([[0,1],[0,0]])}
+ sage: R = L.representation(f)
+ sage: TestSuite(R).run()
+ """
+ if on_basis:
+ self._family = f
+ self._f = f.__getitem__
+ else:
+ self._f = f
+ prefix = kwargs.pop("prefix", 'R')
+ self._on_basis = on_basis
+
+ Representation_abstract.__init__(self, lie_algebra)
+ CombinatorialFreeModule.__init__(self, lie_algebra.base_ring(), index_set,
+ category=category, prefix=prefix, **kwargs)
+
+ def _repr_(self):
+ r"""
+ Return a string representation of ``self``.
+
+ EXAMPLES::
+
+ sage: L. = LieAlgebra(QQ, {('x','y'): {'y':1}})
+ sage: f = {'x': Matrix([[1,0],[0,0]]), 'y': Matrix([[0,1],[0,0]])}
+ sage: L.representation(f)
+ Representation of Lie algebra on 2 generators (x, y) over Rational Field defined by:
+ [1 0]
+ x |--> [0 0]
+ [0 1]
+ y |--> [0 0]
+
+ sage: L = lie_algebras.Affine(QQ, ['E',6,1])
+ sage: F = Family(L.basis(), lambda b: matrix.zero(QQ, 2), name="zero map")
+ sage: L.representation(F, index_set=['a','b'], on_basis=True)
+ Representation of Affine Kac-Moody algebra of ['E', 6] in the Chevalley basis defined by:
+ Lazy family (zero map(i))_{i in Lazy family...}
+
+ sage: L.representation(lambda b: matrix.zero(QQ, 2), index_set=['a','b'])
+ Representation of Affine Kac-Moody algebra of ['E', 6] in the Chevalley basis defined by:
+ at 0x...>
+ """
+ ret = "Representation of {} defined by:".format(self._lie_algebra)
+ from sage.typeset.ascii_art import ascii_art
+ if self._on_basis:
+ B = self._lie_algebra.basis()
+ if B.cardinality() < float('inf'):
+ for k in B.keys():
+ ret += '\n' + repr(ascii_art(B[k], self._f(k), sep=" |--> ", sep_baseline=0))
+ else:
+ ret += '\n' + repr(self._family)
+ else:
+ ret += '\n' + repr(self._f)
+ return ret
+
+ class Element(CombinatorialFreeModule.Element):
+ def _acted_upon_(self, scalar, self_on_left=False):
+ r"""
+ Return the action of ``scalar`` on ``self``.
+
+ EXAMPLES::
+
+ sage: L. = LieAlgebra(QQ, {('x','y'): {'y':1}})
+ sage: f = {'x': Matrix([[1,0],[0,0]]), 'y': Matrix([[0,1],[0,0]])}
+ sage: R = L.representation(f)
+ sage: v = R.an_element(); v
+ 2*R[0] + 2*R[1]
+ sage: x * v
+ 2*R[0]
+ sage: y * v
+ 2*R[0]
+ sage: (2*x + 5*y) * v
+ 14*R[0]
+ sage: v * x
+ Traceback (most recent call last):
+ ...
+ TypeError: unsupported operand parent(s) for *: ...
+
+ sage: v = sum((i+4) * b for i, b in enumerate(R.basis())); v
+ 4*R[0] + 5*R[1]
+ sage: (1/3*x - 5*y) * v
+ -71/3*R[0]
+
+ sage: L = lie_algebras.Affine(QQ, ['E',6,1])
+ sage: F = Family(L.basis(), lambda b: matrix.zero(QQ, 2), name="zero map")
+ sage: R = L.representation(F, index_set=['a','b'], on_basis=True)
+ sage: R.an_element()
+ 2*R['a'] + 2*R['b']
+ sage: L.an_element() * R.an_element()
+ 0
+ """
+ P = self.parent()
+ if scalar in P._lie_algebra:
+ if self_on_left:
+ return None
+ if not self: # we are (already) the zero vector
+ return self
+ scalar = P._lie_algebra(scalar)
+ if not scalar: # we are acting by zero
+ return P.zero()
+ if P._on_basis:
+ mat = sum(c * P._f(k) for k, c in scalar.monomial_coefficients(copy=False).items())
+ else:
+ mat = P._f(scalar)
+ return P.from_vector(mat * self.to_vector())
+
+ return super()._acted_upon_(scalar, self_on_left)
+
+
+class TrivialRepresentation(CombinatorialFreeModule, Representation_abstract):
+ r"""
+ The trivial representation of a Lie algebra.
+
+ The trivial representation of a Lie algebra `L` over a commutative ring
+ `R` is the `1`-dimensional `R`-module on which every element of `L`
+ acts by zero.
+
+ INPUT:
+
+ - ``lie_algebra`` -- a Lie algebra
+
+ REFERENCES:
+
+ - :wikipedia:`Trivial_representation`
+ """
+ def __init__(self, lie_algebra, **kwargs):
+ r"""
+ Initialize ``self``.
+
+ EXAMPLES::
+
+ sage: L = lie_algebras.VirasoroAlgebra(QQ)
+ sage: R = L.trivial_representation()
+ sage: TestSuite(R).run()
+ """
+ R = lie_algebra.base_ring()
+ cat = Modules(R).WithBasis().FiniteDimensional()
+ Representation_abstract.__init__(self, lie_algebra)
+ CombinatorialFreeModule.__init__(self, R, ['v'], prefix='T', category=cat, **kwargs)
+
+ def _repr_(self):
+ r"""
+ Return a string representation of ``self``.
+
+ EXAMPLES::
+
+ sage: L = lie_algebras.VirasoroAlgebra(QQ)
+ sage: L.trivial_representation()
+ Trivial representation of The Virasoro algebra over Rational Field
+ """
+ return "Trivial representation of {}".format(self._lie_algebra)
+
+ class Element(CombinatorialFreeModule.Element):
+ def _acted_upon_(self, scalar, self_on_left=False):
+ r"""
+ Return the action of ``scalar`` on ``self``.
+
+ EXAMPLES::
+
+ sage: L = lie_algebras.VirasoroAlgebra(QQ)
+ sage: R = L.trivial_representation()
+ sage: L.an_element() * R.an_element()
+ 0
+ sage: R.an_element() * L.an_element()
+ Traceback (most recent call last):
+ ...
+ TypeError: unsupported operand parent(s) for *: ...
+ sage: 3 / 5 * R.an_element()
+ 6/5*T['v']
+ """
+ P = self.parent()
+ if scalar in P._lie_algebra:
+ if self_on_left:
+ return None
+ return P.zero()
+ return super()._acted_upon_(scalar, self_on_left)
diff --git a/src/sage/algebras/quantum_groups/fock_space.py b/src/sage/algebras/quantum_groups/fock_space.py
index 3daf03099d5..eb60fd89788 100644
--- a/src/sage/algebras/quantum_groups/fock_space.py
+++ b/src/sage/algebras/quantum_groups/fock_space.py
@@ -166,7 +166,7 @@ class FockSpace(Parent, UniqueRepresentation):
To go between the canonical basis and the natural basis, for level 1
Fock space, we follow the LLT algorithm [LLT1996]_. Indeed, we first
- construct an basis `\{ A(\nu) \}` that is an approximation to the
+ construct a basis `\{ A(\nu) \}` that is an approximation to the
lower global crystal basis, in the sense that it is bar-invariant,
and then use Gaussian elimination to construct the lower global
crystal basis. For higher level Fock space, we follow [Fayers2010]_,
diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py
index 5d3ef49f7c5..22fa53b5a29 100644
--- a/src/sage/arith/misc.py
+++ b/src/sage/arith/misc.py
@@ -3696,6 +3696,12 @@ def binomial(x, m, **kwds):
0
sage: binomial(RealField()('2.5'), 2) # needs sage.rings.real_mpfr
1.87500000000000
+ sage: binomial(Zp(5)(99),50)
+ 3 + 4*5^3 + 2*5^4 + 4*5^5 + 4*5^6 + 4*5^7 + 4*5^8 + 5^9 + 2*5^10 + 3*5^11 +
+ 4*5^12 + 4*5^13 + 2*5^14 + 3*5^15 + 3*5^16 + 4*5^17 + 4*5^18 + 2*5^19 + O(5^20)
+ sage: binomial(Qp(3)(2/3),2)
+ 2*3^-2 + 2*3^-1 + 2 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 +
+ 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + 2*3^12 + 2*3^13 + 2*3^14 + 2*3^15 + 2*3^16 + 2*3^17 + O(3^18)
sage: n = var('n'); binomial(n, 2) # needs sage.symbolic
1/2*(n - 1)*n
sage: n = var('n'); binomial(n, n) # needs sage.symbolic
@@ -3792,6 +3798,27 @@ def binomial(x, m, **kwds):
sage: binomial(n,2) # needs sage.symbolic
1/2*(n - 1)*n
+ Test p-adic numbers::
+
+ sage: binomial(Qp(3)(-1/2),4) # p-adic number with valuation >= 0
+ 1 + 3 + 2*3^2 + 3^3 + 2*3^4 + 3^6 + 3^7 + 3^8 + 3^11 + 2*3^14 + 2*3^16 + 2*3^17 + 2*3^19 + O(3^20)
+
+ Check that :trac:`35811` is fixed::
+
+ sage: binomial(Qp(3)(1/3),4) # p-adic number with negative valuation
+ 2*3^-5 + 2*3^-4 + 3^-3 + 2*3^-2 + 2*3^-1 + 2 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 +
+ 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + 2*3^12 + 2*3^13 + 2*3^14 + O(3^15)
+
+ sage: binomial(Qp(3)(1/3),10).parent()
+ 3-adic Field with capped relative precision 20
+
+ sage: F.=Qq(9); binomial(w,4) # p-adic extension field
+ (w + 2)*3^-1 + (w + 1) + (2*w + 1)*3 + 2*w*3^2 + (2*w + 2)*3^3 + 2*w*3^4 + (2*w + 2)*3^5 +
+ 2*w*3^6 + (2*w + 2)*3^7 + 2*w*3^8 + (2*w + 2)*3^9 + 2*w*3^10 + (2*w + 2)*3^11 + 2*w*3^12 +
+ (2*w + 2)*3^13 + 2*w*3^14 + (2*w + 2)*3^15 + 2*w*3^16 + (2*w + 2)*3^17 + 2*w*3^18 + O(3^19)
+ sage: F.=Qq(9); binomial(w,10).parent()
+ 3-adic Unramified Extension Field in w defined by x^2 + 2*x + 2
+
Invalid inputs::
sage: x = polygen(ZZ)
@@ -3872,7 +3899,7 @@ def binomial(x, m, **kwds):
# case 2: conversion to integers
try:
x = ZZ(x)
- except TypeError:
+ except (TypeError, ValueError):
pass
else:
# Check invertibility of factorial(m) in P
diff --git a/src/sage/calculus/interpolators.pyx b/src/sage/calculus/interpolators.pyx
index fb057f0fc2e..0e1f5fc7209 100644
--- a/src/sage/calculus/interpolators.pyx
+++ b/src/sage/calculus/interpolators.pyx
@@ -55,7 +55,7 @@ def polygon_spline(pts):
....: [lambda x: ps.derivative(real(x))], 0)
sage: show(m.plot_colored() + m.plot_spiderweb()) # needs sage.plot
- Polygon approximation of an circle::
+ Polygon approximation of a circle::
sage: pts = [e^(I*t / 25) for t in range(25)]
sage: ps = polygon_spline(pts)
diff --git a/src/sage/calculus/ode.pyx b/src/sage/calculus/ode.pyx
index 32ccfab5dfc..d7d0fc133f8 100644
--- a/src/sage/calculus/ode.pyx
+++ b/src/sage/calculus/ode.pyx
@@ -37,27 +37,27 @@ cdef class PyFunctionWrapper:
self.y_n = x
cdef class ode_system:
- cdef int c_j(self,double t, double *y, double *dfdy,double *dfdt) noexcept: #void *params):
+ cdef int c_j(self, double t, double *y, double *dfdy, double *dfdt) noexcept:
return 0
- cdef int c_f(self,double t, double* y, double* dydt) noexcept: #void *params):
+ cdef int c_f(self, double t, double* y, double* dydt) noexcept:
return 0
-cdef int c_jac_compiled(double t, double *y, double *dfdy,double *dfdt, void * params) noexcept:
+cdef int c_jac_compiled(double t, const double *y, double *dfdy, double *dfdt, void *params) noexcept:
cdef int status
cdef ode_system wrapper
wrapper = params
- status = wrapper.c_j(t,y,dfdy,dfdt) #Could add parameters
+ status = wrapper.c_j(t, y, dfdy, dfdt) # Could add parameters
return status
-cdef int c_f_compiled(double t, double *y, double *dydt, void *params) noexcept:
+cdef int c_f_compiled(double t, const double *y, double *dydt, void *params) noexcept:
cdef int status
cdef ode_system wrapper
wrapper = params
- status = wrapper.c_f(t,y,dydt) #Could add parameters
+ status = wrapper.c_f(t, y, dydt) # Could add parameters
return status
-cdef int c_jac(double t,double *y,double *dfdy,double *dfdt,void *params) noexcept:
+cdef int c_jac(double t, const double *y, double *dfdy, double *dfdt, void *params) noexcept:
cdef int i
cdef int j
cdef int y_n
@@ -84,7 +84,7 @@ cdef int c_jac(double t,double *y,double *dfdy,double *dfdt,void *params) noexce
except Exception:
return -1
-cdef int c_f(double t,double* y, double* dydt,void *params) noexcept:
+cdef int c_f(double t, const double *y, double *dydt, void *params) noexcept:
cdef int i
cdef int y_n
cdef int param_n
diff --git a/src/sage/calculus/test_sympy.py b/src/sage/calculus/test_sympy.py
index b99d5d7857e..0c360f8acab 100644
--- a/src/sage/calculus/test_sympy.py
+++ b/src/sage/calculus/test_sympy.py
@@ -156,7 +156,7 @@
sage: t1, t2
(omega + x, omega + x)
- sage: e = sympy.sin(var("y"))+sage.all.cos(sympy.Symbol("x"))
+ sage: e = sympy.sin(var("y")) + sage.functions.trig.cos(sympy.Symbol("x"))
sage: type(e)
sage: e
@@ -166,7 +166,7 @@
sage: e
cos(x) + sin(y)
- sage: e = sage.all.cos(var("y")**3)**4+var("x")**2
+ sage: e = sage.functions.trig.cos(var("y")**3)**4+var("x")**2
sage: e = e._sympy_()
sage: e
x**2 + cos(y**3)**4
diff --git a/src/sage/categories/algebras_with_basis.py b/src/sage/categories/algebras_with_basis.py
index dfd693a9520..0d1f72eb17c 100644
--- a/src/sage/categories/algebras_with_basis.py
+++ b/src/sage/categories/algebras_with_basis.py
@@ -1,13 +1,13 @@
r"""
Algebras With Basis
"""
-#*****************************************************************************
+# ****************************************************************************
# Copyright (C) 2008 Teresa Gomez-Diaz (CNRS)
# 2008-2013 Nicolas M. Thiery
#
# Distributed under the terms of the GNU General Public License (GPL)
# https://www.gnu.org/licenses/
-#******************************************************************************
+# *****************************************************************************
from sage.categories.cartesian_product import CartesianProductsCategory
from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring
@@ -106,7 +106,7 @@ class AlgebrasWithBasis(CategoryWithAxiom_over_base_ring):
sage: TestSuite(AlgebrasWithBasis(QQ)).run()
"""
- def example(self, alphabet=('a','b','c')):
+ def example(self, alphabet=('a', 'b', 'c')):
"""
Return an example of algebra with basis.
@@ -259,7 +259,7 @@ def one_from_cartesian_product_of_one_basis(self):
....: SymmetricGroupAlgebra(QQ, 4)]).one()
B[(0, [1, 2, 3])] + B[(1, [1, 2, 3, 4])]
"""
- return self.sum_of_monomials( zip( self._sets_keys(), (set.one_basis() for set in self._sets)) )
+ return self.sum_of_monomials(zip(self._sets_keys(), (set.one_basis() for set in self._sets)))
@lazy_attribute
def one(self):
@@ -370,7 +370,8 @@ def product_on_basis(self, t1, t2):
TODO: optimize this implementation!
"""
- return tensor( (module.monomial(x1)*module.monomial(x2) for (module, x1, x2) in zip(self._sets, t1, t2)) ) #.
+ return tensor(module.monomial(x1) * module.monomial(x2)
+ for module, x1, x2 in zip(self._sets, t1, t2))
class ElementMethods:
"""
diff --git a/src/sage/categories/category.py b/src/sage/categories/category.py
index 54e0df67278..87b66a6615f 100644
--- a/src/sage/categories/category.py
+++ b/src/sage/categories/category.py
@@ -565,7 +565,7 @@ def an_instance(cls):
def __call__(self, x, *args, **opts):
"""
Construct an object in this category from the data in ``x``,
- or throw ``TypeError`` or ``NotImplementedError``.
+ or throw :class:`TypeError` or :class:`NotImplementedError`.
If ``x`` is readily in ``self`` it is returned unchanged.
Categories wishing to extend this minimal behavior should
@@ -583,7 +583,7 @@ def __call__(self, x, *args, **opts):
def _call_(self, x):
"""
Construct an object in this category from the data in ``x``,
- or throw ``NotImplementedError``.
+ or throw :class:`NotImplementedError`.
EXAMPLES::
diff --git a/src/sage/categories/category_with_axiom.py b/src/sage/categories/category_with_axiom.py
index bb9dbbe2347..20668629649 100644
--- a/src/sage/categories/category_with_axiom.py
+++ b/src/sage/categories/category_with_axiom.py
@@ -500,7 +500,7 @@ class from the base category class::
(bilinearity). Of course this should be implemented at the level
of :class:`~.magmatic_algebras.MagmaticAlgebras`, if not higher.
- - :class:`Bialgebras`: defining an bialgebra as an algebra and
+ - :class:`Bialgebras`: defining a bialgebra as an algebra and
coalgebra where the coproduct is a morphism for the product.
- :class:`Bimodules`: defining a bimodule as a left and right
@@ -2667,7 +2667,7 @@ def Blue_extra_super_categories(self):
This currently fails because ``Blahs`` is the category where
the axiom ``Blue`` is defined, and the specifications
currently impose that a category defining an axiom should also
- implement it (here in an category with axiom
+ implement it (here in a category with axiom
``Blahs.Blue``). In practice, due to this violation of the
specifications, the axiom is lost during the join calculation.
diff --git a/src/sage/categories/complex_reflection_groups.py b/src/sage/categories/complex_reflection_groups.py
index 925ee1c228e..d9d30d41e40 100644
--- a/src/sage/categories/complex_reflection_groups.py
+++ b/src/sage/categories/complex_reflection_groups.py
@@ -21,7 +21,7 @@ class ComplexReflectionGroups(Category_singleton):
The category of complex reflection groups.
Let `V` be a complex vector space. A *complex reflection* is an
- element of `\operatorname{GL}(V)` fixing an hyperplane pointwise
+ element of `\operatorname{GL}(V)` fixing a hyperplane pointwise
and acting by multiplication by a root of unity on a complementary
line.
diff --git a/src/sage/categories/covariant_functorial_construction.py b/src/sage/categories/covariant_functorial_construction.py
index e64bbaa35aa..ce4909a7b63 100644
--- a/src/sage/categories/covariant_functorial_construction.py
+++ b/src/sage/categories/covariant_functorial_construction.py
@@ -96,7 +96,7 @@ class CovariantFunctorialConstruction(UniqueRepresentation, SageObject):
specify information and generic operations for elements of this
category.
- - ``_functor_name`` - an string which specifies the name of the
+ - ``_functor_name`` - a string which specifies the name of the
functor, and also (when relevant) of the method on parents and
elements used for calling the construction.
diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py
index 972d3b4d716..f3ef677638d 100644
--- a/src/sage/categories/coxeter_groups.py
+++ b/src/sage/categories/coxeter_groups.py
@@ -701,7 +701,7 @@ def _test_reduced_word(self, **options):
for x in tester.some_elements():
red = x.reduced_word()
tester.assertEqual(self.from_reduced_word(red), x)
- tester.assertEqual(self.prod((s[i] for i in red)), x)
+ tester.assertEqual(self.prod(s[i] for i in red), x)
def simple_projection(self, i, side='right', length_increasing=True):
r"""
diff --git a/src/sage/categories/crystals.py b/src/sage/categories/crystals.py
index ae900a93e66..c2a9b8de655 100644
--- a/src/sage/categories/crystals.py
+++ b/src/sage/categories/crystals.py
@@ -578,7 +578,7 @@ def _Hom_(self, Y, category=None, **options):
The sole purpose of this method is to construct the homset
as a :class:`~sage.categories.crystals.CrystalHomset`. If
``category`` is specified and is not a subcategory of
- :class:`Crystals`, a ``TypeError`` is raised instead.
+ :class:`Crystals`, a :class:`TypeError` is raised instead.
This method is not meant to be called directly. Please use
:func:`sage.categories.homset.Hom` instead.
diff --git a/src/sage/categories/discrete_valuation.py b/src/sage/categories/discrete_valuation.py
index 4bb61a5aa67..24b15bca488 100644
--- a/src/sage/categories/discrete_valuation.py
+++ b/src/sage/categories/discrete_valuation.py
@@ -147,22 +147,31 @@ def quo_rem(self, other):
Return the quotient and remainder for Euclidean division
of ``self`` by ``other``.
- TESTS::
+ EXAMPLES::
sage: R. = GF(5)[[]]
sage: (q^2 + q).quo_rem(q)
(1 + q, 0)
sage: (q + 1).quo_rem(q^2)
(0, 1 + q)
+
+ TESTS::
+
sage: q.quo_rem(0)
Traceback (most recent call last):
...
ZeroDivisionError: Euclidean division by the zero element not defined
+ sage: L = PowerSeriesRing(QQ, 't')
+ sage: t = L.gen()
+ sage: F = algebras.Free(L, ['A', 'B'])
+ sage: A, B = F.gens()
+ sage: f = t*A+t**2*B/2
"""
if not other:
raise ZeroDivisionError("Euclidean division by the zero element not defined")
P = self.parent()
+ other = P(other)
if self.valuation() >= other.valuation():
return P(self / other), P.zero()
else:
@@ -263,7 +272,7 @@ def residue_field(self):
def _matrix_hessenbergize(self, H):
r"""
- Replace `H` with an Hessenberg form of it.
+ Replace `H` with a Hessenberg form of it.
EXAMPLES::
diff --git a/src/sage/categories/enumerated_sets.py b/src/sage/categories/enumerated_sets.py
index 8ae3270491c..a5e0bbcefaf 100644
--- a/src/sage/categories/enumerated_sets.py
+++ b/src/sage/categories/enumerated_sets.py
@@ -182,7 +182,8 @@ def __iter__(self):
It is also possible to override ``__iter__`` method itself. Then
the methods of the first column are defined using ``__iter__``
- If none of these are provided, raise a ``NotImplementedError``.
+ If none of these are provided, this raises
+ a :class:`NotImplementedError`.
EXAMPLES:
@@ -928,7 +929,7 @@ def random_element(self):
the probability is uniform.
This is a generic implementation from the category
- ``EnumeratedSets()``. It raise a ``NotImplementedError``
+ ``EnumeratedSets()``. It raises a :class:`NotImplementedError`
since one does not know whether the set is finite.
EXAMPLES::
diff --git a/src/sage/categories/facade_sets.py b/src/sage/categories/facade_sets.py
index 746622743fb..7bf2ac2f067 100644
--- a/src/sage/categories/facade_sets.py
+++ b/src/sage/categories/facade_sets.py
@@ -209,8 +209,8 @@ def _an_element_(self):
For each parent ``self`` is a facade for, this default
implementation tries the method ``an_element`` until it finds an
- element in ``self``. If none is found raise a
- ``NotImplementedError``.
+ element in ``self``. If none is found, this raises a
+ :class:`NotImplementedError`.
EXAMPLES::
diff --git a/src/sage/categories/fields.py b/src/sage/categories/fields.py
index 63ab62aabff..4f8bb141467 100644
--- a/src/sage/categories/fields.py
+++ b/src/sage/categories/fields.py
@@ -808,7 +808,7 @@ def inverse_of_unit(self):
1/2
Trying to invert the zero element typically raises a
- ``ZeroDivisionError``::
+ :class:`ZeroDivisionError`::
sage: QQ(0).inverse_of_unit()
Traceback (most recent call last):
diff --git a/src/sage/categories/filtered_modules_with_basis.py b/src/sage/categories/filtered_modules_with_basis.py
index 15d0f490713..84e38b14976 100644
--- a/src/sage/categories/filtered_modules_with_basis.py
+++ b/src/sage/categories/filtered_modules_with_basis.py
@@ -156,7 +156,7 @@ def basis(self, d=None):
over Integer Ring(i))_{i in Partitions}
Checking this method on a filtered algebra. Note that this
- will typically raise a ``NotImplementedError`` when this
+ will typically raise a :class:`NotImplementedError` when this
feature is not implemented. ::
sage: A = AlgebrasWithBasis(ZZ).Filtered().example()
diff --git a/src/sage/categories/finite_complex_reflection_groups.py b/src/sage/categories/finite_complex_reflection_groups.py
index 1a5ed06c42a..b1e89676728 100644
--- a/src/sage/categories/finite_complex_reflection_groups.py
+++ b/src/sage/categories/finite_complex_reflection_groups.py
@@ -555,22 +555,22 @@ def milnor_fiber_poset(self):
sage: sum(x**P.rank(elt) for elt in P)
18*x^2 + 15*x + 1
- sage: W = ReflectionGroup(4) # optional - gap3
- sage: P = W.milnor_fiber_poset() # optional - gap3
- sage: P # optional - gap3
+ sage: # optional - gap3
+ sage: W = ReflectionGroup(4)
+ sage: P = W.milnor_fiber_poset(); P
Finite meet-semilattice containing 41 elements
- sage: sum(x**P.rank(elt) for elt in P) # optional - gap3
+ sage: sum(x**P.rank(elt) for elt in P)
24*x^2 + 16*x + 1
- sage: W = ReflectionGroup([4,2,2]) # optional - gap3
- sage: W.is_well_generated() # optional - gap3
+ sage: # optional - gap3
+ sage: W = ReflectionGroup([4,2,2])
+ sage: W.is_well_generated()
False
- sage: P = W.milnor_fiber_poset() # optional - gap3
- sage: P # optional - gap3
+ sage: P = W.milnor_fiber_poset(); P
Finite poset containing 47 elements
- sage: sum(x**P.rank(elt) for elt in P) # optional - gap3
+ sage: sum(x**P.rank(elt) for elt in P)
16*x^3 + 24*x^2 + 6*x + 1
- sage: P.is_meet_semilattice() # optional - gap3
+ sage: P.is_meet_semilattice()
False
"""
I = self.index_set()
diff --git a/src/sage/categories/finite_groups.py b/src/sage/categories/finite_groups.py
index 7461f6fabfd..c64b7fd8bf0 100644
--- a/src/sage/categories/finite_groups.py
+++ b/src/sage/categories/finite_groups.py
@@ -153,9 +153,9 @@ def conjugacy_classes(self):
Return a list with all the conjugacy classes of the group.
This will eventually be a fall-back method for groups not defined
- over GAP. Right now just raises a ``NotImplementedError``, until
- we include a non-GAP way of listing the conjugacy classes
- representatives.
+ over GAP. Right now, it just raises a
+ :class:`NotImplementedError`, until we include a non-GAP
+ way of listing the conjugacy classes representatives.
EXAMPLES::
diff --git a/src/sage/categories/finite_posets.py b/src/sage/categories/finite_posets.py
index 49d9f2ba53f..68317bbb4c3 100644
--- a/src/sage/categories/finite_posets.py
+++ b/src/sage/categories/finite_posets.py
@@ -906,7 +906,7 @@ def birational_toggle(self, v, labelling):
encoded to be understood by Sage. This implementation allows
`\mathbf{K}` to be a semifield, not just a field. The birational
`v`-toggle is only a rational map, so an exception (most
- likely, ``ZeroDivisionError``) will be thrown if the
+ likely, :class:`ZeroDivisionError`) will be thrown if the
denominator is zero.
INPUT:
@@ -1121,7 +1121,7 @@ def birational_toggles(self, vs, labelling):
encoded to be understood by Sage. This implementation allows
`\mathbf{K}` to be a semifield, not just a field. The birational
`v`-toggle is only a rational map, so an exception (most
- likely, ``ZeroDivisionError``) will be thrown if the
+ likely, :class:`ZeroDivisionError`) will be thrown if the
denominator is zero.
INPUT:
@@ -1194,9 +1194,10 @@ def birational_rowmotion(self, labelling):
`\mathbf{K}`-labellings and for an explanation of how
`\mathbf{K}`-labellings are to be encoded to be understood
by Sage. This implementation allows `\mathbf{K}` to be a
- semifield, not just a field. Birational rowmotion is only a
- rational map, so an exception (most likely, ``ZeroDivisionError``)
- will be thrown if the denominator is zero.
+ semifield, not just a field. Birational rowmotion is only
+ a rational map, so an exception (most likely,
+ :class:`ZeroDivisionError`) will be thrown if the
+ denominator is zero.
INPUT:
diff --git a/src/sage/categories/functor.pyx b/src/sage/categories/functor.pyx
index 32bd079fc73..e8cf2e5538f 100644
--- a/src/sage/categories/functor.pyx
+++ b/src/sage/categories/functor.pyx
@@ -74,9 +74,9 @@ cdef class Functor(SageObject):
default call method:
- ``_coerce_into_domain(self, x)``: Return an object of ``self``'s
- domain, corresponding to ``x``, or raise a ``TypeError``.
+ domain, corresponding to ``x``, or raise a :class:`TypeError`.
- - Default: Raise ``TypeError`` if ``x`` is not in ``self``'s domain.
+ - Default: Raise :class:`TypeError` if ``x`` is not in ``self``'s domain.
- ``_apply_functor(self, x)``: Apply ``self`` to an object ``x`` of
``self``'s domain.
@@ -282,11 +282,12 @@ cdef class Functor(SageObject):
NOTE:
A subclass of :class:`Functor` may overload this method. It should
- return an object of self's domain, and should raise a ``TypeError``
- if this is impossible.
+ return an object of self's domain, and should raise a
+ :class:`TypeError` if this is impossible.
- By default, the argument will not be changed, but a ``TypeError``
- will be raised if the argument does not belong to the domain.
+ By default, the argument will not be changed, but a
+ :class:`TypeError` will be raised if the argument does not
+ belong to the domain.
TESTS::
diff --git a/src/sage/categories/graded_algebras_with_basis.py b/src/sage/categories/graded_algebras_with_basis.py
index 95fcebbb7a7..62d4816b208 100644
--- a/src/sage/categories/graded_algebras_with_basis.py
+++ b/src/sage/categories/graded_algebras_with_basis.py
@@ -224,8 +224,8 @@ def product_on_basis(self, t0, t1):
TODO: optimize this implementation!
"""
- basic = tensor_signed((module.monomial(x0) * module.monomial(x1)
- for (module, x0, x1) in zip(self._sets, t0, t1)))
+ basic = tensor_signed(module.monomial(x0) * module.monomial(x1)
+ for (module, x0, x1) in zip(self._sets, t0, t1))
n = len(self._sets)
parity0 = [self._sets[idx].degree_on_basis(x0)
for (idx, x0) in enumerate(t0)]
diff --git a/src/sage/categories/hecke_modules.py b/src/sage/categories/hecke_modules.py
index 118e155654e..8a8da4f64ef 100644
--- a/src/sage/categories/hecke_modules.py
+++ b/src/sage/categories/hecke_modules.py
@@ -1,14 +1,14 @@
r"""
Hecke modules
"""
-#*****************************************************************************
+# ****************************************************************************
# Copyright (C) 2005 David Kohel
# William Stein
# 2008-2009 Nicolas M. Thiery
#
# Distributed under the terms of the GNU General Public License (GPL)
-# http://www.gnu.org/licenses/
-#******************************************************************************
+# https://www.gnu.org/licenses/
+# *****************************************************************************
from sage.categories.category_types import Category_module
from sage.categories.homsets import HomsetsCategory
@@ -114,7 +114,7 @@ def _Hom_(self, Y, category):
The sole purpose of this method is to construct the homset
as a :class:`~sage.modular.hecke.homspace.HeckeModuleHomspace`. If
``category`` is specified and is not a subcategory of
- :class:`HeckeModules`, a ``TypeError`` is raised instead
+ :class:`HeckeModules`, a :class:`TypeError` is raised instead
This method is not meant to be called directly. Please use
:func:`sage.categories.homset.Hom` instead.
diff --git a/src/sage/categories/highest_weight_crystals.py b/src/sage/categories/highest_weight_crystals.py
index 68e72a11b90..baf50566cc0 100644
--- a/src/sage/categories/highest_weight_crystals.py
+++ b/src/sage/categories/highest_weight_crystals.py
@@ -2,12 +2,12 @@
r"""
Highest Weight Crystals
"""
-#*****************************************************************************
+# ****************************************************************************
# Copyright (C) 2010 Anne Schilling
#
# Distributed under the terms of the GNU General Public License (GPL)
-# http://www.gnu.org/licenses/
-#******************************************************************************
+# https://www.gnu.org/licenses/
+# *****************************************************************************
from sage.misc.cachefunc import cached_method
from sage.categories.category_singleton import Category_singleton
@@ -15,6 +15,7 @@
CrystalMorphismByGenerators)
from sage.categories.tensor import TensorProductsCategory
+
class HighestWeightCrystals(Category_singleton):
"""
The category of highest weight crystals.
@@ -410,7 +411,8 @@ def _Hom_(self, Y, category=None, **options):
The sole purpose of this method is to construct the homset as a
:class:`~sage.categories.highest_weight_crystals.HighestWeightCrystalHomset`.
If ``category`` is specified and is not a subcategory of
- :class:`HighestWeightCrystals`, a ``TypeError`` is raised instead
+ :class:`HighestWeightCrystals`, a :class:`TypeError` is raised
+ instead
This method is not meant to be called directly. Please use
:func:`sage.categories.homset.Hom` instead.
diff --git a/src/sage/categories/homset.py b/src/sage/categories/homset.py
index d2203299512..bf4426aff87 100644
--- a/src/sage/categories/homset.py
+++ b/src/sage/categories/homset.py
@@ -178,7 +178,7 @@ def Hom(X, Y, category=None, check=True):
A parent (or a parent class of a category) may specify how to
construct certain homsets by implementing a method ``_Hom_(self,
codomain, category)``. This method should either construct the
- requested homset or raise a ``TypeError``. This hook is currently
+ requested homset or raise a :class:`TypeError`. This hook is currently
mostly used to create homsets in some specific subclass of
:class:`Homset` (e.g. :class:`sage.rings.homset.RingHomset`)::
diff --git a/src/sage/categories/infinite_enumerated_sets.py b/src/sage/categories/infinite_enumerated_sets.py
index 3c7a861a4b6..e65bf944b87 100644
--- a/src/sage/categories/infinite_enumerated_sets.py
+++ b/src/sage/categories/infinite_enumerated_sets.py
@@ -6,16 +6,17 @@
- Florent Hivert (2009-11): initial revision.
"""
-#*****************************************************************************
+# ****************************************************************************
# Copyright (C) 2009 Florent Hivert
#
# Distributed under the terms of the GNU General Public License (GPL)
-# http://www.gnu.org/licenses/
-#******************************************************************************
+# https://www.gnu.org/licenses/
+# *****************************************************************************
from sage.categories.category_with_axiom import CategoryWithAxiom
+
class InfiniteEnumeratedSets(CategoryWithAxiom):
"""
The category of infinite enumerated sets
@@ -99,9 +100,9 @@ def _test_enumerated_set_iter_cardinality(self, **options):
For infinite enumerated sets:
- * :meth:`.cardinality` is supposed to return `infinity`
+ * :meth:`.cardinality` is supposed to return ``infinity``
- * :meth:`.list` is supposed to raise a ``NotImplementedError``.
+ * :meth:`.list` is supposed to raise a :class:`NotImplementedError`.
EXAMPLES::
diff --git a/src/sage/categories/lie_algebras.py b/src/sage/categories/lie_algebras.py
index 32aa9f00041..4226c4dba61 100644
--- a/src/sage/categories/lie_algebras.py
+++ b/src/sage/categories/lie_algebras.py
@@ -697,6 +697,64 @@ def lie_group(self, name='G', **kwds):
Lie group G of Heisenberg algebra of rank 1 over Rational Field
"""
+ def trivial_representation(self):
+ """
+ Return the trivial representation of ``self``.
+
+ EXAMPLES::
+
+ sage: L = lie_algebras.strictly_upper_triangular_matrices(QQ, 4)
+ sage: L.trivial_representation()
+ Trivial representation of Lie algebra of 4-dimensional
+ strictly upper triangular matrices over Rational Field
+ """
+ from sage.algebras.lie_algebras.representation import TrivialRepresentation
+ return TrivialRepresentation(self)
+
+ def representation(self, f=None, index_set=None, on_basis=False, **kwargs):
+ """
+ Return a representation of ``self``.
+
+ If no arguments are given, then this returns the trivial
+ representation.
+
+ Currently the only implemented method of constructing a
+ representation is by explicitly specifying the action of
+
+ * the elements of ``self`` by matrices;
+ * the basis elements of ``self`` using a ``dict`` or
+ a :func:`Family`;
+ * a function on basis elements (either passed as ``on_basis``
+ or setting ``on_basis=True``).
+
+ INPUT:
+
+ - ``f`` -- the function that defines the action
+ - ``index_set`` -- the index set of the representation
+ - ``on_basis`` -- (optional) see above
+
+ .. SEEALSO::
+
+ :class:`~sage.algebras.lie_algebras.representation.RepresentationByMorphism`
+
+ EXAMPLES::
+
+ sage: L. = LieAlgebra(QQ, {('x','y'): {'y':1}})
+ sage: f = {x: Matrix([[1,0],[0,0]]), y: Matrix([[0,1],[0,0]])}
+ sage: L.representation(f)
+ Representation of Lie algebra on 2 generators (x, y) over Rational Field defined by:
+ [1 0]
+ x |--> [0 0]
+ [0 1]
+ y |--> [0 0]
+ sage: L.representation()
+ Trivial representation of Lie algebra on 2 generators (x, y) over Rational Field
+ """
+ if f is None and on_basis is False and index_set is None:
+ return self.trivial_representation(**kwargs)
+ from sage.algebras.lie_algebras.representation import RepresentationByMorphism
+ return RepresentationByMorphism(self, f, index_set, on_basis, **kwargs)
+
def _test_jacobi_identity(self, **options):
"""
Test that the Jacobi identity is satisfied on (not
diff --git a/src/sage/categories/magmas.py b/src/sage/categories/magmas.py
index 603e68ad186..72b037c30b0 100644
--- a/src/sage/categories/magmas.py
+++ b/src/sage/categories/magmas.py
@@ -438,7 +438,7 @@ class CartesianProducts(CartesianProductsCategory):
def extra_super_categories(self):
r"""
Implement the fact that a Cartesian product of commutative
- additive magmas is still an commutative additive magmas.
+ additive magmas is still a commutative additive magmas.
EXAMPLES::
diff --git a/src/sage/categories/map.pyx b/src/sage/categories/map.pyx
index fadd066d7f4..a931ceaa6cb 100644
--- a/src/sage/categories/map.pyx
+++ b/src/sage/categories/map.pyx
@@ -1880,7 +1880,7 @@ cdef class FormalCompositeMap(Map):
"""
Tell whether ``self`` is injective.
- It raises ``NotImplementedError`` if it can't be determined.
+ It raises :class:`NotImplementedError` if it cannot be determined.
EXAMPLES::
@@ -1955,7 +1955,7 @@ cdef class FormalCompositeMap(Map):
"""
Tell whether ``self`` is surjective.
- It raises ``NotImplementedError`` if it can't be determined.
+ It raises :class:`NotImplementedError` if it cannot be determined.
EXAMPLES::
diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py
index c4933d0657f..aad3469e072 100644
--- a/src/sage/categories/modules_with_basis.py
+++ b/src/sage/categories/modules_with_basis.py
@@ -1081,7 +1081,7 @@ def sum_of_monomials(self):
INPUT:
- - ``indices`` -- an list (or iterable) of indices of basis
+ - ``indices`` -- a list (or iterable) of indices of basis
elements
EXAMPLES::
diff --git a/src/sage/categories/number_fields.py b/src/sage/categories/number_fields.py
index 3c070bd65b2..6f9829cd499 100644
--- a/src/sage/categories/number_fields.py
+++ b/src/sage/categories/number_fields.py
@@ -95,7 +95,7 @@ def __contains__(self, x):
def _call_(self, x):
r"""
Construct an object in this category from the data in ``x``,
- or raise a ``TypeError``.
+ or raise a :class:`TypeError`.
EXAMPLES::
diff --git a/src/sage/categories/quotient_fields.py b/src/sage/categories/quotient_fields.py
index f5d8495489d..fe1b66a0fb4 100644
--- a/src/sage/categories/quotient_fields.py
+++ b/src/sage/categories/quotient_fields.py
@@ -632,7 +632,7 @@ def _derivative(self, var=None):
Returns the derivative of this rational function with respect to the
variable ``var``.
- Over an ring with a working gcd implementation, the derivative of a
+ Over a ring with a working gcd implementation, the derivative of a
fraction `f/g`, supposed to be given in lowest terms, is computed as
`(f'(g/d) - f(g'/d))/(g(g'/d))`, where `d` is a greatest common
divisor of `f` and `g`.
diff --git a/src/sage/categories/rings.py b/src/sage/categories/rings.py
index 60ca92f971b..24a858f3525 100644
--- a/src/sage/categories/rings.py
+++ b/src/sage/categories/rings.py
@@ -387,7 +387,7 @@ def _Hom_(self, Y, category):
The sole purpose of this method is to construct the homset
as a :class:`~sage.rings.homset.RingHomset`. If
``category`` is specified and is not a subcategory of
- :class:`Rings() `, a ``TypeError`` is raised instead
+ :class:`Rings() `, a :class:`TypeError` is raised instead
This method is not meant to be called directly. Please use
:func:`sage.categories.homset.Hom` instead.
@@ -1416,7 +1416,7 @@ def inverse_of_unit(self):
def _divide_if_possible(self, y):
"""
Divide ``self`` by ``y`` if possible and raise a
- ``ValueError`` otherwise.
+ :class:`ValueError` otherwise.
EXAMPLES::
diff --git a/src/sage/categories/sets_cat.py b/src/sage/categories/sets_cat.py
index 16c117b286e..df0e3abee86 100644
--- a/src/sage/categories/sets_cat.py
+++ b/src/sage/categories/sets_cat.py
@@ -1830,7 +1830,7 @@ def __invert__(self):
.. NOTE::
This is an optional method. A default implementation
- raising ``NotImplementedError`` could be provided instead.
+ raising :class:`NotImplementedError` could be provided instead.
"""
def is_injective(self):
diff --git a/src/sage/categories/simplicial_sets.py b/src/sage/categories/simplicial_sets.py
index 2b45c4c98cb..7b7bbf827af 100644
--- a/src/sage/categories/simplicial_sets.py
+++ b/src/sage/categories/simplicial_sets.py
@@ -1108,7 +1108,7 @@ def connectivity(self, max_dim=None):
return Infinity
class Finite(CategoryWithAxiom):
- class ParentMethods():
+ class ParentMethods:
def unset_base_point(self):
"""
diff --git a/src/sage/coding/abstract_code.py b/src/sage/coding/abstract_code.py
index 85cdce652b9..ed84dc12517 100644
--- a/src/sage/coding/abstract_code.py
+++ b/src/sage/coding/abstract_code.py
@@ -512,7 +512,7 @@ def list(self):
(1, 0, 1, 0, 1, 0, 1)
True
"""
- return [x for x in self]
+ return list(self)
def length(self):
r"""
diff --git a/src/sage/coding/ag_code.py b/src/sage/coding/ag_code.py
index f705f75d476..0f189bb69a0 100644
--- a/src/sage/coding/ag_code.py
+++ b/src/sage/coding/ag_code.py
@@ -332,7 +332,7 @@ def designed_distance(self):
"""
Return the designed distance of the AG code.
- If the code is of dimension zero, then a ``ValueError`` is raised.
+ If the code is of dimension zero, then a :class:`ValueError` is raised.
EXAMPLES::
@@ -576,7 +576,7 @@ def designed_distance(self):
"""
Return the designed distance of the differential AG code.
- If the code is of dimension zero, then a ``ValueError`` is raised.
+ If the code is of dimension zero, then a :class:`ValueError` is raised.
EXAMPLES::
diff --git a/src/sage/coding/ag_code_decoders.pyx b/src/sage/coding/ag_code_decoders.pyx
index 15231e6aa87..9ce2aa2f8ce 100644
--- a/src/sage/coding/ag_code_decoders.pyx
+++ b/src/sage/coding/ag_code_decoders.pyx
@@ -29,17 +29,18 @@ EXAMPLES::
The ``decoder`` is now ready for correcting vectors received from a noisy
channel::
- sage: channel = channels.StaticErrorRateChannel(code.ambient_space(), tau) # long time
- sage: message_space = decoder.message_space() # long time
- sage: message = message_space.random_element() # long time
- sage: encoder = decoder.connected_encoder() # long time
- sage: sent_codeword = encoder.encode(message) # long time
- sage: received_vector = channel(sent_codeword) # long time
- sage: (received_vector - sent_codeword).hamming_weight() # long time
+ sage: # long time
+ sage: channel = channels.StaticErrorRateChannel(code.ambient_space(), tau)
+ sage: message_space = decoder.message_space()
+ sage: message = message_space.random_element()
+ sage: encoder = decoder.connected_encoder()
+ sage: sent_codeword = encoder.encode(message)
+ sage: received_vector = channel(sent_codeword)
+ sage: (received_vector - sent_codeword).hamming_weight()
4
- sage: decoder.decode_to_code(received_vector) == sent_codeword # long time
+ sage: decoder.decode_to_code(received_vector) == sent_codeword
True
- sage: decoder.decode_to_message(received_vector) == message # long time
+ sage: decoder.decode_to_message(received_vector) == message
True
AUTHORS:
diff --git a/src/sage/coding/binary_code.pyx b/src/sage/coding/binary_code.pyx
index 6779708bfda..81065a7dbd3 100644
--- a/src/sage/coding/binary_code.pyx
+++ b/src/sage/coding/binary_code.pyx
@@ -3204,6 +3204,8 @@ cdef class BinaryCodeClassifier:
....: [0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1]])
sage: B = BinaryCode(M)
sage: gens, labeling, size, base = BC._aut_gp_and_can_label(B)
+
+ sage: # needs sage.groups
sage: S = SymmetricGroup(M.ncols())
sage: L = [S([x+1 for x in g]) for g in gens]
sage: PermutationGroup(L).order()
@@ -3218,6 +3220,8 @@ cdef class BinaryCodeClassifier:
....: [0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1]])
sage: B = BinaryCode(M)
sage: gens, labeling, size, base = BC._aut_gp_and_can_label(B)
+
+ sage: # needs sage.groups
sage: S = SymmetricGroup(M.ncols())
sage: L = [S([x+1 for x in g]) for g in gens]
sage: PermutationGroup(L).order()
@@ -3225,7 +3229,7 @@ cdef class BinaryCodeClassifier:
sage: size
2304
- sage: M=Matrix(GF(2),[
+ sage: M = Matrix(GF(2),[
....: [1,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0,0],
....: [0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0],
....: [0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,0],
@@ -3236,6 +3240,8 @@ cdef class BinaryCodeClassifier:
....: [0,0,0,0,0,0,0,1,0,0,1,1,1,1,0,0,1]])
sage: B = BinaryCode(M)
sage: gens, labeling, size, base = BC._aut_gp_and_can_label(B)
+
+ sage: # needs sage.groups
sage: S = SymmetricGroup(M.ncols())
sage: L = [S([x+1 for x in g]) for g in gens]
sage: PermutationGroup(L).order()
@@ -3243,7 +3249,7 @@ cdef class BinaryCodeClassifier:
sage: size
136
- sage: M=Matrix(GF(2),[
+ sage: M = Matrix(GF(2),[
....: [0,1,0,1,1,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1],
....: [1,0,1,1,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0],
....: [0,1,1,1,0,0,0,1,0,0,1,1,0,0,0,1,1,1,0,1,0,0],
@@ -3257,6 +3263,8 @@ cdef class BinaryCodeClassifier:
....: [0,0,1,0,1,1,1,0,0,0,1,1,0,0,1,0,0,0,1,1,1,0]])
sage: B = BinaryCode(M)
sage: gens, labeling, size, base = BC._aut_gp_and_can_label(B)
+
+ sage: # needs sage.groups
sage: S = SymmetricGroup(M.ncols())
sage: L = [S([x+1 for x in g]) for g in gens]
sage: PermutationGroup(L).order()
@@ -3956,7 +3964,7 @@ cdef class BinaryCodeClassifier:
sage: from sage.coding.binary_code import *
sage: BC = BinaryCodeClassifier()
sage: B = BinaryCode(Matrix(GF(2), [[1,1,1,1]]))
- sage: BC.generate_children(B, 6, 4)
+ sage: BC.generate_children(B, 6, 4) # needs sage.groups
[
[1 1 1 1 0 0]
[0 1 0 1 1 1]
diff --git a/src/sage/coding/channel.py b/src/sage/coding/channel.py
index 50ea5f5cb1f..160afef9bd1 100644
--- a/src/sage/coding/channel.py
+++ b/src/sage/coding/channel.py
@@ -454,12 +454,12 @@ class ErrorErasureChannel(Channel):
- ``space`` -- the input and output space
- ``number_errors`` -- the number of errors created in each transmitted
- message. It can be either an integer of a tuple. If an tuple is passed as
+ message. It can be either an integer of a tuple. If a tuple is passed as
an argument, the number of errors will be a random integer between the
two bounds of this tuple.
- ``number_erasures`` -- the number of erasures created in each transmitted
- message. It can be either an integer of a tuple. If an tuple is passed as an
+ message. It can be either an integer of a tuple. If a tuple is passed as an
argument, the number of erasures will be a random integer between the
two bounds of this tuple.
@@ -564,7 +564,7 @@ def transmit_unsafe(self, message):
Return ``message`` with as many errors as ``self._number_errors`` in it,
and as many erasures as ``self._number_erasures`` in it.
- If ``self._number_errors`` was passed as an tuple for the number of errors, it will
+ If ``self._number_errors`` was passed as a tuple for the number of errors, it will
pick a random integer between the bounds of the tuple and use it as the number of errors.
It does the same with ``self._number_erasures``.
diff --git a/src/sage/coding/code_bounds.py b/src/sage/coding/code_bounds.py
index c1e0eb77022..b192792f11f 100644
--- a/src/sage/coding/code_bounds.py
+++ b/src/sage/coding/code_bounds.py
@@ -192,10 +192,10 @@ def _check_n_q_d(n, q, d, field_based=True):
Check that the length `n`, alphabet size `q` and minimum distance `d` type
check and make sense for a code over a field.
- More precisely, checks that the parameters are positive integers, that `q`
- is a prime power for codes over a field, or, more generally, that
- `q` is of size at least 2, and that `n >= d`. Raises a ``ValueError``
- otherwise.
+ More precisely, this checks that the parameters are positive
+ integers, that `q` is a prime power for codes over a field, or,
+ more generally, that `q` is of size at least 2, and that `n >= d`.
+ This raises a :class:`ValueError` otherwise.
TESTS::
diff --git a/src/sage/coding/code_constructions.py b/src/sage/coding/code_constructions.py
index d96ad3c7627..6870c28ec87 100644
--- a/src/sage/coding/code_constructions.py
+++ b/src/sage/coding/code_constructions.py
@@ -155,8 +155,8 @@ def _is_a_splitting(S1, S2, n, return_automorphism=False):
This is a special case of Theorem 6.4.3 in [HP2003]_.
"""
R = IntegerModRing(n)
- S1 = set(R(x) for x in S1)
- S2 = set(R(x) for x in S2)
+ S1 = {R(x) for x in S1}
+ S2 = {R(x) for x in S2}
# we first check whether (S1,S2) is a partition of R - {0}
if (len(S1) + len(S2) != n-1 or len(S1) != len(S2) or
diff --git a/src/sage/coding/codecan/autgroup_can_label.pyx b/src/sage/coding/codecan/autgroup_can_label.pyx
index 29efd21af56..f656771e179 100644
--- a/src/sage/coding/codecan/autgroup_can_label.pyx
+++ b/src/sage/coding/codecan/autgroup_can_label.pyx
@@ -1,3 +1,4 @@
+# sage.doctest: needs sage.libs.pari
r"""
Canonical forms and automorphisms for linear codes over finite fields
diff --git a/src/sage/coding/databases.py b/src/sage/coding/databases.py
index 3826734c09b..989d67e89d8 100644
--- a/src/sage/coding/databases.py
+++ b/src/sage/coding/databases.py
@@ -174,7 +174,7 @@ def best_linear_code_in_codetables_dot_de(n, k, F, verbose=False):
i = s.find("")
j = s.find("
")
if i == -1 or j == -1:
- raise IOError("Error parsing data (missing pre tags).")
+ raise OSError("Error parsing data (missing pre tags).")
return s[i+5:j].strip()
diff --git a/src/sage/coding/decoder.py b/src/sage/coding/decoder.py
index 82a07775300..503c31a3b39 100644
--- a/src/sage/coding/decoder.py
+++ b/src/sage/coding/decoder.py
@@ -31,7 +31,7 @@ class Decoder(SageObject):
Every decoder class for linear codes (of any metric) should inherit from
this abstract class.
- To implement an decoder, you need to:
+ To implement a decoder, you need to:
- inherit from :class:`Decoder`
diff --git a/src/sage/coding/delsarte_bounds.py b/src/sage/coding/delsarte_bounds.py
index 47c84b2c59b..e25c0a4faf4 100644
--- a/src/sage/coding/delsarte_bounds.py
+++ b/src/sage/coding/delsarte_bounds.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Delsarte (or linear programming) bounds
@@ -24,9 +23,8 @@
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
-# http://www.gnu.org/licenses/
+# https://www.gnu.org/licenses/
# ****************************************************************************
-from __future__ import print_function, division
def krawtchouk(n, q, l, x, check=True):
@@ -142,7 +140,6 @@ def eberlein(n, w, k, u, check=True):
default. Otherwise, pass it as it is. Use ``check=False`` at
your own risk.
-
EXAMPLES::
sage: codes.bounds.eberlein(24,10,2,6)
@@ -169,13 +166,12 @@ def eberlein(n, w, k, u, check=True):
Traceback (most recent call last):
...
TypeError: either m or x-m must be an integer
-
"""
from sage.arith.misc import binomial
from sage.arith.srange import srange
- if 2*w > n:
- return eberlein(n, n-w, k, u)
+ if 2 * w > n:
+ return eberlein(n, n - w, k, u)
if check:
from sage.rings.integer_ring import ZZ
@@ -185,10 +181,10 @@ def eberlein(n, w, k, u, check=True):
n = n0
return sum([(-1)**j*binomial(u, j)*binomial(w-u, k-j)*binomial(n-w-u, k-j)
- for j in srange(0, k+1)])
+ for j in srange(k + 1)])
-def _delsarte_LP_building(n, d, d_star, q, isinteger, solver, maxc=0):
+def _delsarte_LP_building(n, d, d_star, q, isinteger, solver, maxc=0):
r"""
LP builder - common for the two functions; not exported.
@@ -211,18 +207,18 @@ def _delsarte_LP_building(n, d, d_star, q, isinteger, solver, maxc=0):
x_0 is a continuous variable (min=0, max=+oo)
...
x_7 is a continuous variable (min=0, max=+oo)
-
"""
from sage.numerical.mip import MixedIntegerLinearProgram
p = MixedIntegerLinearProgram(maximization=True, solver=solver)
A = p.new_variable(integer=isinteger, nonnegative=True)
- p.set_objective(sum([A[r] for r in range(n+1)]))
+ p.set_objective(sum([A[r] for r in range(n + 1)]))
p.add_constraint(A[0] == 1)
for i in range(1, d):
p.add_constraint(A[i] == 0)
- for j in range(1, n+1):
- rhs = sum([krawtchouk(n, q, j, r, check=False)*A[r] for r in range(n+1)])
+ for j in range(1, n + 1):
+ rhs = sum([krawtchouk(n, q, j, r, check=False) * A[r]
+ for r in range(n + 1)])
p.add_constraint(0 <= rhs)
if j >= d_star:
p.add_constraint(0 <= rhs)
@@ -230,7 +226,7 @@ def _delsarte_LP_building(n, d, d_star, q, isinteger, solver, maxc=0):
p.add_constraint(0 == rhs)
if maxc > 0:
- p.add_constraint(sum([A[r] for r in range(n+1)]), max=maxc)
+ p.add_constraint(sum([A[r] for r in range(n + 1)]), max=maxc)
return A, p
@@ -272,10 +268,9 @@ def _delsarte_cwc_LP_building(n, d, w, solver, isinteger):
Variables:
x_0 is a continuous variable (min=0, max=+oo)
x_1 is a continuous variable (min=0, max=+oo)
-
"""
- from sage.numerical.mip import MixedIntegerLinearProgram
from sage.arith.misc import binomial
+ from sage.numerical.mip import MixedIntegerLinearProgram
p = MixedIntegerLinearProgram(maximization=True, solver=solver)
A = p.new_variable(integer=isinteger, nonnegative=True)
@@ -287,12 +282,14 @@ def _q(k, i):
return mu_i*eberlein(n, w, i, k)/v_i
for k in range(1, w+1):
- p.add_constraint(sum([A[2*i]*_q(k, i) for i in range(d//2, w+1)]), min=-1)
+ p.add_constraint(sum([A[2*i]*_q(k, i) for i in range(d//2, w+1)]),
+ min=-1)
return A, p
-def delsarte_bound_constant_weight_code(n, d, w, return_data=False, solver="PPL", isinteger=False):
+def delsarte_bound_constant_weight_code(n, d, w, return_data=False,
+ solver="PPL", isinteger=False):
r"""
Find the Delsarte bound on a constant weight code.
@@ -337,15 +334,16 @@ def delsarte_bound_constant_weight_code(n, d, w, return_data=False, solver="PPL"
sage: codes.bounds.delsarte_bound_constant_weight_code(17, 4, 3, isinteger=True)
43
-
"""
from sage.numerical.mip import MIPSolverException
if d < 4:
- raise ValueError("Violated constraint d>=4 for Binary Constant Weight Codes")
+ raise ValueError("Violated constraint d>=4 for "
+ "Binary Constant Weight Codes")
if d >= 2*w or 2*w > n:
- raise ValueError("Violated constraint d<2w<=n for Binary Constant Weight Codes")
+ raise ValueError("Violated constraint d<2w<=n for "
+ "Binary Constant Weight Codes")
# minimum distance is even => if there is an odd lower bound on d we can
# increase it by 1
@@ -356,23 +354,19 @@ def delsarte_bound_constant_weight_code(n, d, w, return_data=False, solver="PPL"
try:
bd = p.solve()
except MIPSolverException as exc:
- print("Solver exception: {}".format(exc))
- if return_data:
- return A, p, False
- return False
+ print(f"Solver exception: {exc}")
+ return (A, p, False) if return_data else False
- if return_data:
- return A, p, bd
- else:
- return int(bd)
+ return (A, p, bd) if return_data else int(bd)
-def delsarte_bound_hamming_space(n, d, q, return_data=False, solver="PPL", isinteger=False):
+def delsarte_bound_hamming_space(n, d, q, return_data=False,
+ solver="PPL", isinteger=False):
r"""
Find the Delsarte bound on codes in ``H_q^n`` of minimal distance ``d``
- Find the Delsarte bound [De1973]_ on the size of codes in the Hamming space ``H_q^n``
- of minimal distance ``d``.
+ Find the Delsarte bound [De1973]_ on the size of codes in
+ the Hamming space ``H_q^n`` of minimal distance ``d``.
INPUT:
@@ -444,94 +438,92 @@ def delsarte_bound_hamming_space(n, d, q, return_data=False, solver="PPL", isint
try:
bd = p.solve()
except MIPSolverException as exc:
- print("Solver exception: {}".format(exc))
- if return_data:
- return A, p, False
- return False
+ print(f"Solver exception: {exc}")
+ return (A, p, False) if return_data else False
- if return_data:
- return A, p, bd
- else:
- return bd
+ return (A, p, bd) if return_data else bd
-def delsarte_bound_additive_hamming_space(n, d, q, d_star=1, q_base=0, return_data=False, solver="PPL", isinteger=False):
+def delsarte_bound_additive_hamming_space(n, d, q, d_star=1, q_base=0, return_data=False,
+ solver="PPL", isinteger=False):
r"""
- Find a modified Delsarte bound on additive codes in Hamming space `H_q^n` of minimal distance `d`
+ Find a modified Delsarte bound on additive codes in Hamming space `H_q^n` of minimal distance `d`.
- Find the Delsarte LP bound on ``F_{q_base}``-dimension of additive codes in
- Hamming space `H_q^n` of minimal distance ``d`` with minimal distance of the dual
- code at least ``d_star``. If ``q_base`` is set to
- non-zero, then ``q`` is a power of ``q_base``, and the code is, formally, linear over
- ``F_{q_base}``. Otherwise it is assumed that ``q_base==q``.
+ Find the Delsarte LP bound on ``F_{q_base}``-dimension of additive
+ codes in Hamming space `H_q^n` of minimal distance ``d`` with
+ minimal distance of the dual code at least ``d_star``. If
+ ``q_base`` is set to non-zero, then ``q`` is a power of
+ ``q_base``, and the code is, formally, linear over
+ ``F_{q_base}``. Otherwise it is assumed that ``q_base==q``.
+ INPUT:
- INPUT:
-
- - ``n`` -- the code length
+ - ``n`` -- the code length
- - ``d`` -- the (lower bound on) minimal distance of the code
+ - ``d`` -- the (lower bound on) minimal distance of the code
- - ``q`` -- the size of the alphabet
+ - ``q`` -- the size of the alphabet
- - ``d_star`` -- the (lower bound on) minimal distance of the dual code;
- only makes sense for additive codes.
+ - ``d_star`` -- the (lower bound on) minimal distance of the dual code;
+ only makes sense for additive codes.
- - ``q_base`` -- if ``0``, the code is assumed to be linear. Otherwise,
- ``q=q_base^m`` and the code is linear over ``F_{q_base}``.
+ - ``q_base`` -- if ``0``, the code is assumed to be linear. Otherwise,
+ ``q=q_base^m`` and the code is linear over ``F_{q_base}``.
- - ``return_data`` -- if ``True``, return a triple ``(W,LP,bound)``, where ``W`` is
- a weights vector, and ``LP`` the Delsarte bound LP; both of them are Sage LP
- data. ``W`` need not be a weight distribution of a code, or,
- if ``isinteger==False``, even have integer entries.
+ - ``return_data`` -- if ``True``, return a triple ``(W,LP,bound)``,
+ where ``W`` is a weights vector, and ``LP`` the Delsarte bound
+ LP; both of them are Sage LP data. ``W`` need not be a weight
+ distribution of a code, or, if ``isinteger==False``, even have
+ integer entries.
- - ``solver`` -- the LP/ILP solver to be used. Defaults to ``'PPL'``. It is arbitrary
- precision, thus there will be no rounding errors. With other solvers
- (see :class:`MixedIntegerLinearProgram` for the list), you are on your own!
+ - ``solver`` -- the LP/ILP solver to be used. Defaults to ``'PPL'``. It is
+ arbitrary precision, thus there will be no rounding errors. With
+ other solvers (see :class:`MixedIntegerLinearProgram` for the
+ list), you are on your own!
- - ``isinteger`` -- if ``True``, uses an integer programming solver (ILP), rather
- that an LP solver. Can be very slow if set to ``True``.
+ - ``isinteger`` -- if ``True``, uses an integer programming solver (ILP),
+ rather that an LP solver. Can be very slow if set to ``True``.
- EXAMPLES:
+ EXAMPLES:
- The bound on dimension of linear `\GF{2}`-codes of length 11 and minimal distance 6::
+ The bound on dimension of linear `\GF{2}`-codes of length 11 and minimal distance 6::
- sage: codes.bounds.delsarte_bound_additive_hamming_space(11, 6, 2)
- 3
- sage: a,p,val = codes.bounds.delsarte_bound_additive_hamming_space(\
- 11, 6, 2, return_data=True)
- sage: [j for i,j in p.get_values(a).items()]
- [1, 0, 0, 0, 0, 0, 5, 2, 0, 0, 0, 0]
+ sage: codes.bounds.delsarte_bound_additive_hamming_space(11, 6, 2)
+ 3
+ sage: a,p,val = codes.bounds.delsarte_bound_additive_hamming_space(\
+ 11, 6, 2, return_data=True)
+ sage: [j for i,j in p.get_values(a).items()]
+ [1, 0, 0, 0, 0, 0, 5, 2, 0, 0, 0, 0]
- The bound on the dimension of linear `\GF{4}`-codes of length 11 and minimal distance 3::
+ The bound on the dimension of linear `\GF{4}`-codes of length 11 and minimal distance 3::
- sage: codes.bounds.delsarte_bound_additive_hamming_space(11,3,4)
- 8
+ sage: codes.bounds.delsarte_bound_additive_hamming_space(11,3,4)
+ 8
- The bound on the `\GF{2}`-dimension of additive `\GF{4}`-codes of length 11 and minimal
- distance 3::
+ The bound on the `\GF{2}`-dimension of additive `\GF{4}`-codes of length 11 and minimal
+ distance 3::
- sage: codes.bounds.delsarte_bound_additive_hamming_space(11,3,4,q_base=2)
- 16
+ sage: codes.bounds.delsarte_bound_additive_hamming_space(11,3,4,q_base=2)
+ 16
- Such a ``d_star`` is not possible::
+ Such a ``d_star`` is not possible::
- sage: codes.bounds.delsarte_bound_additive_hamming_space(11,3,4,d_star=9)
- Solver exception: PPL : There is no feasible solution
- False
+ sage: codes.bounds.delsarte_bound_additive_hamming_space(11,3,4,d_star=9)
+ Solver exception: PPL : There is no feasible solution
+ False
- TESTS::
+ TESTS::
- sage: a,p,x = codes.bounds.delsarte_bound_additive_hamming_space(\
- 19,15,7,return_data=True,isinteger=True)
- sage: [j for i,j in p.get_values(a).items()]
- [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 307, 0, 0, 1, 34]
- sage: codes.bounds.delsarte_bound_additive_hamming_space(19,15,7,solver='glpk')
- 3
- sage: codes.bounds.delsarte_bound_additive_hamming_space(\
- 19,15,7, isinteger=True, solver='glpk')
- 3
- """
+ sage: a,p,x = codes.bounds.delsarte_bound_additive_hamming_space(\
+ 19,15,7,return_data=True,isinteger=True)
+ sage: [j for i,j in p.get_values(a).items()]
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 307, 0, 0, 1, 34]
+ sage: codes.bounds.delsarte_bound_additive_hamming_space(19,15,7,solver='glpk')
+ 3
+ sage: codes.bounds.delsarte_bound_additive_hamming_space(\
+ 19,15,7, isinteger=True, solver='glpk')
+ 3
+ """
from sage.numerical.mip import MIPSolverException
if q_base == 0:
q_base = q
@@ -550,18 +542,18 @@ def delsarte_bound_additive_hamming_space(n, d, q, d_star=1, q_base=0, return_da
m = kk*n # this is to emulate repeat/until block
bd = q**n+1
- while q_base**m < bd: # need to solve the LP repeatedly, as this is a new constraint!
+ while q_base**m < bd:
+ # need to solve the LP repeatedly, as this is a new constraint!
# we might become infeasible. More precisely, after rounding down
# to the closest value of q_base^m, the LP, with the constraint that
# the objective function is at most q_base^m,
- A, p = _delsarte_LP_building(n, d, d_star, q, isinteger, solver, q_base**m)
+ A, p = _delsarte_LP_building(n, d, d_star, q, isinteger,
+ solver, q_base**m)
try:
bd = p.solve()
except MIPSolverException as exc:
print("Solver exception:", exc)
- if return_data:
- return A, p, False
- return False
+ return (A, p, False) if return_data else False
# rounding the bound down to the nearest power of q_base, for q=q_base^m
# bd_r = roundres(log(bd, base=q_base))
m = -1
@@ -570,10 +562,7 @@ def delsarte_bound_additive_hamming_space(n, d, q, d_star=1, q_base=0, return_da
if q_base**(m+1) == bd:
m += 1
- if return_data:
- return A, p, m
- else:
- return m
+ return (A, p, m) if return_data else m
def _delsarte_Q_LP_building(q, d, solver, isinteger):
@@ -644,12 +633,13 @@ def _delsarte_Q_LP_building(q, d, solver, isinteger):
p.add_constraint(A[i] == 0)
for k in range(1, n):
- p.add_constraint(sum([q[k][i]*A[i] for i in range(n)]), min=0)
+ p.add_constraint(sum([q[k][i] * A[i] for i in range(n)]), min=0)
return A, p
-def delsarte_bound_Q_matrix(q, d, return_data=False, solver="PPL", isinteger=False):
+def delsarte_bound_Q_matrix(q, d, return_data=False,
+ solver="PPL", isinteger=False):
r"""
Delsarte bound on a code with Q matrix ``q`` and lower bound on min. dist. ``d``.
@@ -701,25 +691,19 @@ def delsarte_bound_Q_matrix(q, d, return_data=False, solver="PPL", isinteger=Fal
sage: a,p,val = codes.bounds.delsarte_bound_Q_matrix(q_matrix, 6, return_data=True)
sage: [j for i,j in p.get_values(a).items()]
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
-
"""
-
- from sage.structure.element import is_Matrix
from sage.numerical.mip import MIPSolverException
+ from sage.structure.element import is_Matrix
if not is_Matrix(q):
- raise ValueError("Input to delsarte_bound_Q_matrix should be a sage Matrix()")
+ raise ValueError("Input to delsarte_bound_Q_matrix "
+ "should be a sage Matrix()")
A, p = _delsarte_Q_LP_building(q, d, solver, isinteger)
try:
bd = p.solve()
except MIPSolverException as exc:
- print("Solver exception: {}".format(exc))
- if return_data:
- return A, p, False
- return False
+ print(f"Solver exception: {exc}")
+ return (A, p, False) if return_data else False
- if return_data:
- return A, p, bd
- else:
- return bd
+ return (A, p, bd) if return_data else bd
diff --git a/src/sage/coding/goppa_code.py b/src/sage/coding/goppa_code.py
index 2a974cf1ef2..a642fb86049 100644
--- a/src/sage/coding/goppa_code.py
+++ b/src/sage/coding/goppa_code.py
@@ -308,7 +308,7 @@ def distance_bound(self):
[8, 2] Goppa code over GF(2)
sage: C.distance_bound()
3
- sage: C.minimum_distance()
+ sage: C.minimum_distance() # needs sage.libs.gap
5
"""
return 1 + (self._generating_pol).degree()
diff --git a/src/sage/coding/guruswami_sudan/interpolation.py b/src/sage/coding/guruswami_sudan/interpolation.py
index eea537a115a..62ed9f3a8f1 100644
--- a/src/sage/coding/guruswami_sudan/interpolation.py
+++ b/src/sage/coding/guruswami_sudan/interpolation.py
@@ -130,7 +130,7 @@ def eqs_affine(x0, y0):
eqs = []
for i in range(s):
for j in range(s - i):
- eq = dict()
+ eq = {}
for monomial in monomials:
ihat = monomial[0]
jhat = monomial[1]
diff --git a/src/sage/coding/linear_code.py b/src/sage/coding/linear_code.py
index 0d84996a483..f8f051a00d9 100644
--- a/src/sage/coding/linear_code.py
+++ b/src/sage/coding/linear_code.py
@@ -1224,7 +1224,7 @@ def galois_closure(self, F0):
n = len(G.columns())
k = len(G.rows())
G0 = [[x**q0 for x in g.list()] for g in G.rows()]
- G1 = [[x for x in g.list()] for g in G.rows()]
+ G1 = [list(g.list()) for g in G.rows()]
G2 = G0+G1
MS = MatrixSpace(F,2*k,n)
G3 = MS(G2)
@@ -1342,7 +1342,7 @@ def minimum_distance(self, algorithm=None):
.. NOTE::
- When using GAP, this raises a ``NotImplementedError`` if
+ When using GAP, this raises a :class:`NotImplementedError` if
the base field of the code has size greater than 256 due
to limitations in GAP.
@@ -1657,7 +1657,7 @@ def permutation_automorphism_group(self, algorithm="partition"):
size = Gp.Size()
print("\n Using the %s codewords of weight %s \n Supergroup size: \n %s\n " % (wts[wt], wt, size))
Cwt = filter(lambda c: c.WeightCodeword() == wt, eltsC) # bottleneck 2 (repeated
- matCwt = list(map(lambda c: c.VectorCodeword(), Cwt)) # for each i until stop = 1)
+ matCwt = [c.VectorCodeword() for c in Cwt] # for each i until stop = 1)
if len(matCwt) > 0:
A = libgap(matCwt).MatrixAutomorphisms()
Gp = A.Intersection2(Gp) # bottleneck 3
diff --git a/src/sage/coding/reed_muller_code.py b/src/sage/coding/reed_muller_code.py
index 6885532757b..6ea8a904722 100644
--- a/src/sage/coding/reed_muller_code.py
+++ b/src/sage/coding/reed_muller_code.py
@@ -906,7 +906,7 @@ def unencode_nocheck(self, c):
OUTPUT:
- - An polynomial of degree less than ``self.code().order()``.
+ - A polynomial of degree less than ``self.code().order()``.
EXAMPLES::
diff --git a/src/sage/coding/source_coding/huffman.py b/src/sage/coding/source_coding/huffman.py
index 6c08a4d885a..1d41f84d77f 100644
--- a/src/sage/coding/source_coding/huffman.py
+++ b/src/sage/coding/source_coding/huffman.py
@@ -367,9 +367,9 @@ def pop():
# Build the binary tree of a Huffman code, where the root of the tree
# is associated with the empty string.
self._build_code_from_tree(self._tree, d, prefix="")
- self._index = dict((i, s) for i, (s, w) in enumerate(symbols))
- self._character_to_code = dict(
- (s, d[i]) for i, (s, w) in enumerate(symbols))
+ self._index = {i: s for i, (s, w) in enumerate(symbols)}
+ self._character_to_code = {
+ s: d[i] for i, (s, w) in enumerate(symbols)}
def encode(self, string):
r"""
diff --git a/src/sage/coding/subfield_subcode.py b/src/sage/coding/subfield_subcode.py
index 9ec9650c43a..c876ef73e63 100644
--- a/src/sage/coding/subfield_subcode.py
+++ b/src/sage/coding/subfield_subcode.py
@@ -38,7 +38,7 @@ class SubfieldSubcode(AbstractLinearCode):
- ``subfield`` -- the base field of ``self``.
- - ``embedding`` -- (default: ``None``) an homomorphism from ``subfield`` to
+ - ``embedding`` -- (default: ``None``) a homomorphism from ``subfield`` to
``original_code``'s base field. If ``None`` is provided, it will default
to the first homomorphism of the list of homomorphisms Sage can build.
diff --git a/src/sage/combinat/abstract_tree.py b/src/sage/combinat/abstract_tree.py
index ee797d990fa..e25c0606769 100644
--- a/src/sage/combinat/abstract_tree.py
+++ b/src/sage/combinat/abstract_tree.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Abstract Recursive Trees
@@ -73,7 +72,7 @@
# of it later.
-class AbstractTree():
+class AbstractTree:
"""
Abstract Tree.
@@ -1276,7 +1275,7 @@ def node_to_str(t):
if hasattr(t, "label"):
return str(t.label())
else:
- return u"o"
+ return "o"
# other possible choices for nodes would be u"█ ▓ ░ ╋ ╬"
if self.is_empty():
@@ -1291,9 +1290,9 @@ def node_to_str(t):
if len(self) == 1:
repr_child = self[0]._unicode_art_()
- sep = UnicodeArt([u" " * repr_child._root])
+ sep = UnicodeArt([" " * repr_child._root])
t_repr = UnicodeArt([node_to_str(self)])
- repr_root = (sep + t_repr) * (sep + UnicodeArt([u"│"]))
+ repr_root = (sep + t_repr) * (sep + UnicodeArt(["│"]))
t_repr = repr_root * repr_child
t_repr._root = repr_child._root
t_repr._baseline = t_repr._h - 1
@@ -1303,17 +1302,17 @@ def node_to_str(t):
l_repr = [subtree._unicode_art_() for subtree in self]
acc = l_repr.pop(0)
whitesep = acc._root
- lf_sep = u" " * whitesep + u"╭" + u"─" * (acc._l - acc._root)
- ls_sep = u" " * whitesep + u"│" + u" " * (acc._l - acc._root)
+ lf_sep = " " * whitesep + "╭" + "─" * (acc._l - acc._root)
+ ls_sep = " " * whitesep + "│" + " " * (acc._l - acc._root)
while l_repr:
tr = l_repr.pop(0)
- acc += UnicodeArt([u" "]) + tr
+ acc += UnicodeArt([" "]) + tr
if not len(l_repr):
- lf_sep += u"─" * (tr._root) + u"╮"
- ls_sep += u" " * (tr._root) + u"│"
+ lf_sep += "─" * (tr._root) + "╮"
+ ls_sep += " " * (tr._root) + "│"
else:
- lf_sep += u"─" * (tr._root) + u"┬" + u"─" * (tr._l - tr._root)
- ls_sep += u" " * (tr._root) + u"│" + u" " * (tr._l - tr._root)
+ lf_sep += "─" * (tr._root) + "┬" + "─" * (tr._l - tr._root)
+ ls_sep += " " * (tr._root) + "│" + " " * (tr._l - tr._root)
mid = whitesep + (len(lf_sep) - whitesep) // 2
node = node_to_str(self)
lf_sep = (lf_sep[:mid - len(node) // 2] + node +
@@ -1358,10 +1357,10 @@ def canonical_labelling(self, shift=1):
def to_hexacode(self):
r"""
- Transform a tree into an hexadecimal string.
+ Transform a tree into a hexadecimal string.
The definition of the hexacode is recursive. The first letter is
- the valence of the root as an hexadecimal (up to 15), followed by
+ the valence of the root as a hexadecimal (up to 15), followed by
the concatenation of the hexacodes of the subtrees.
This method only works for trees where every vertex has
@@ -1501,7 +1500,7 @@ def create_node(self):
. the matrix
. and the edges
"""
- name = "".join((chr(ord(x) + 49) for x in str(num[0])))
+ name = "".join(chr(ord(x) + 49) for x in str(num[0]))
node = cmd + name
nodes.append((name,
(str(self.label()) if hasattr(self, "label") else ""))
@@ -2460,11 +2459,11 @@ def map_labels(self, f):
def from_hexacode(ch, parent=None, label='@'):
r"""
- Transform an hexadecimal string into a tree.
+ Transform a hexadecimal string into a tree.
INPUT:
- - ``ch`` -- an hexadecimal string
+ - ``ch`` -- a hexadecimal string
- ``parent`` -- kind of trees to be produced. If ``None``, this will
be ``LabelledOrderedTrees``
@@ -2510,11 +2509,11 @@ def from_hexacode(ch, parent=None, label='@'):
def _from_hexacode_aux(ch, parent, label='@'):
r"""
- Transform an hexadecimal string into a tree and a remainder string.
+ Transform a hexadecimal string into a tree and a remainder string.
INPUT:
- - ``ch`` -- an hexadecimal string
+ - ``ch`` -- a hexadecimal string
- ``parent`` -- kind of trees to be produced.
diff --git a/src/sage/combinat/backtrack.py b/src/sage/combinat/backtrack.py
index d0669580484..ab9c35bc23c 100644
--- a/src/sage/combinat/backtrack.py
+++ b/src/sage/combinat/backtrack.py
@@ -36,7 +36,7 @@
from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
-class GenericBacktracker():
+class GenericBacktracker:
r"""
A generic backtrack tool for exploring a search space organized as a tree,
with branch pruning, etc.
diff --git a/src/sage/combinat/baxter_permutations.py b/src/sage/combinat/baxter_permutations.py
index 460969c062c..648ce9c6a26 100644
--- a/src/sage/combinat/baxter_permutations.py
+++ b/src/sage/combinat/baxter_permutations.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Baxter permutations
"""
diff --git a/src/sage/combinat/bijectionist.py b/src/sage/combinat/bijectionist.py
index b6c5cf53f98..60df5195e9e 100644
--- a/src/sage/combinat/bijectionist.py
+++ b/src/sage/combinat/bijectionist.py
@@ -2455,7 +2455,7 @@ def solutions_iterator(self):
yield from self._bmilp.solutions_iterator(False, [])
-class _BijectionistMILP():
+class _BijectionistMILP:
r"""
Wrapper class for the MixedIntegerLinearProgram (MILP).
diff --git a/src/sage/combinat/binary_tree.py b/src/sage/combinat/binary_tree.py
index f58f7558a73..d4afa9387cf 100644
--- a/src/sage/combinat/binary_tree.py
+++ b/src/sage/combinat/binary_tree.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Binary Trees
@@ -593,7 +592,7 @@ def _unicode_art_(self):
o o o o
"""
def node_to_str(bt):
- return str(bt.label()) if hasattr(bt, "label") else u"o"
+ return str(bt.label()) if hasattr(bt, "label") else "o"
if self.is_empty():
from sage.typeset.unicode_art import empty_unicode_art
@@ -609,14 +608,14 @@ def node_to_str(bt):
node = node_to_str(self)
rr_tree = self[1]._unicode_art_()
if rr_tree._root > 2:
- f_line = u" " * (rr_tree._root - 3) + node
- s_line = u" " * (len(node) + rr_tree._root - 3) + u"╲"
+ f_line = " " * (rr_tree._root - 3) + node
+ s_line = " " * (len(node) + rr_tree._root - 3) + "╲"
t_repr = UnicodeArt([f_line, s_line]) * rr_tree
t_repr._root = rr_tree._root - 2
else:
f_line = node
- s_line = u" ╲"
- t_line = u" " * (len(node) + 1)
+ s_line = " ╲"
+ t_line = " " * (len(node) + 1)
t_repr = UnicodeArt([f_line, s_line]) * (UnicodeArt([t_line]) + rr_tree)
t_repr._root = rr_tree._root
t_repr._baseline = t_repr._h - 1
@@ -625,8 +624,8 @@ def node_to_str(bt):
if self[1].is_empty():
node = node_to_str(self)
lr_tree = self[0]._unicode_art_()
- f_line = u" " * (lr_tree._root + 1) + node
- s_line = u" " * lr_tree._root + u"╱"
+ f_line = " " * (lr_tree._root + 1) + node
+ s_line = " " * lr_tree._root + "╱"
t_repr = UnicodeArt([f_line, s_line]) * lr_tree
t_repr._root = lr_tree._root + 2
t_repr._baseline = t_repr._h - 1
@@ -638,10 +637,10 @@ def node_to_str(bt):
nb_ = lr_tree._l - lr_tree._root + rr_tree._root - 1
nb_L = nb_ // 2
nb_R = nb_L + (nb_ % 2)
- f_line = u" " * (lr_tree._root + 1) + u"_" * nb_L + node
- f_line += u"_" * nb_R
- s_line = u" " * lr_tree._root + u"╱" + u" " * (len(node) + rr_tree._root - 1 + (lr_tree._l - lr_tree._root)) + u"╲"
- t_repr = UnicodeArt([f_line, s_line]) * (lr_tree + UnicodeArt([u" " * (len(node) + 2)]) + rr_tree)
+ f_line = " " * (lr_tree._root + 1) + "_" * nb_L + node
+ f_line += "_" * nb_R
+ s_line = " " * lr_tree._root + "╱" + " " * (len(node) + rr_tree._root - 1 + (lr_tree._l - lr_tree._root)) + "╲"
+ t_repr = UnicodeArt([f_line, s_line]) * (lr_tree + UnicodeArt([" " * (len(node) + 2)]) + rr_tree)
t_repr._root = lr_tree._root + nb_L + 2
t_repr._baseline = t_repr._h - 1
return t_repr
@@ -4262,7 +4261,7 @@ def random_element(self):
EXAMPLES::
- sage: BinaryTrees(5).random_element() # random # needs sage.combinat
+ sage: BinaryTrees(5).random_element() # random # needs sage.combinat
[., [., [., [., [., .]]]]]
sage: BinaryTrees(0).random_element() # needs sage.combinat
.
diff --git a/src/sage/combinat/combinatorial_map.py b/src/sage/combinat/combinatorial_map.py
index 5ec7871821c..84876e52f56 100644
--- a/src/sage/combinat/combinatorial_map.py
+++ b/src/sage/combinat/combinatorial_map.py
@@ -197,7 +197,7 @@ def combinatorial_map_wrapper(f=None, order=None, name=None):
# combinatorial_map = combinatorial_map_wrapper
-class CombinatorialMap():
+class CombinatorialMap:
r"""
This is a wrapper class for methods that are *combinatorial maps*.
diff --git a/src/sage/combinat/composition.py b/src/sage/combinat/composition.py
index 4d98a25108d..8d01e9ac081 100644
--- a/src/sage/combinat/composition.py
+++ b/src/sage/combinat/composition.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Integer compositions
diff --git a/src/sage/combinat/composition_tableau.py b/src/sage/combinat/composition_tableau.py
index 18b1b85966c..8ee363fb275 100644
--- a/src/sage/combinat/composition_tableau.py
+++ b/src/sage/combinat/composition_tableau.py
@@ -120,7 +120,7 @@ def __init__(self, parent, t):
CombinatorialElement.__init__(self, parent, t)
- def _repr_diagram(self):
+ def _repr_diagram(self) -> str:
r"""
Return a string representation of ``self`` as an array.
@@ -132,8 +132,8 @@ def _repr_diagram(self):
3 2
4 4
"""
- return '\n'.join(("".join(("%3s" % str(x) for x in row))
- for row in self))
+ return '\n'.join("".join("%3s" % str(x) for x in row)
+ for row in self)
def __call__(self, *cell):
r"""
diff --git a/src/sage/combinat/crystals/fully_commutative_stable_grothendieck.py b/src/sage/combinat/crystals/fully_commutative_stable_grothendieck.py
index 51a04179364..e63e1a4a3ce 100644
--- a/src/sage/combinat/crystals/fully_commutative_stable_grothendieck.py
+++ b/src/sage/combinat/crystals/fully_commutative_stable_grothendieck.py
@@ -769,7 +769,7 @@ def _check_decreasing_hecke_factorization(t):
"""
if not isinstance(t, DecreasingHeckeFactorization):
if not isinstance(t, (tuple, list)):
- raise ValueError("t should be an list or tuple")
+ raise ValueError("t should be a list or tuple")
for factor in t:
if not isinstance(factor, (tuple, list)):
raise ValueError("each factor in t should be a list or tuple")
diff --git a/src/sage/combinat/crystals/generalized_young_walls.py b/src/sage/combinat/crystals/generalized_young_walls.py
index 36f6c259942..2c859c4d492 100644
--- a/src/sage/combinat/crystals/generalized_young_walls.py
+++ b/src/sage/combinat/crystals/generalized_young_walls.py
@@ -285,7 +285,7 @@ def generate_signature(self, i):
strsig = ''.join( x[0] for x in sig)
reducedsig = strsig
while re.search(r"\+\s*-",reducedsig):
- reducedsig = re.sub(r"\+\s*-", lambda match : str().ljust(len(match.group(int(0)))) , reducedsig)
+ reducedsig = re.sub(r"\+\s*-", lambda match : ''.ljust(len(match.group(0))) , reducedsig)
return (sig,reducedsig)
def signature(self, i):
diff --git a/src/sage/combinat/crystals/tensor_product.py b/src/sage/combinat/crystals/tensor_product.py
index a1b94ccf541..5604a24665c 100644
--- a/src/sage/combinat/crystals/tensor_product.py
+++ b/src/sage/combinat/crystals/tensor_product.py
@@ -655,7 +655,7 @@ class Element(TensorProductOfSuperCrystalsElement):
pass
-class QueerSuperCrystalsMixin():
+class QueerSuperCrystalsMixin:
"""
Mixin class with methods for a finite queer supercrystal.
"""
diff --git a/src/sage/combinat/decorated_permutation.py b/src/sage/combinat/decorated_permutation.py
index e7281b7d3bb..f687818ef25 100644
--- a/src/sage/combinat/decorated_permutation.py
+++ b/src/sage/combinat/decorated_permutation.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Decorated permutations
diff --git a/src/sage/combinat/designs/database.py b/src/sage/combinat/designs/database.py
index 98b8f0e598e..5eb2b90802a 100644
--- a/src/sage/combinat/designs/database.py
+++ b/src/sage/combinat/designs/database.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Database of small combinatorial designs
diff --git a/src/sage/combinat/designs/difference_family.py b/src/sage/combinat/designs/difference_family.py
index b737b90b820..393ea4b9b47 100644
--- a/src/sage/combinat/designs/difference_family.py
+++ b/src/sage/combinat/designs/difference_family.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Difference families
@@ -1114,7 +1113,7 @@ def mcfarland_1973_construction(q, s):
D = []
for k, H in zip(K, V.subspaces(s)):
for v in H:
- D.append(G((tuple(v) + (k,))))
+ D.append(G(tuple(v) + (k,)))
return G,[D]
@@ -1749,7 +1748,7 @@ def supplementary_difference_set_from_rel_diff_set(q, existence=False, check=Tru
EXAMPLES::
sage: from sage.combinat.designs.difference_family import supplementary_difference_set_from_rel_diff_set
- sage: supplementary_difference_set_from_rel_diff_set(17) #random # needs sage.libs.pari
+ sage: supplementary_difference_set_from_rel_diff_set(17) #random # needs sage.libs.pari
(Additive abelian group isomorphic to Z/16,
[[(1), (5), (6), (7), (9), (13), (14), (15)],
[(0), (2), (3), (5), (6), (10), (11), (13), (14)],
diff --git a/src/sage/combinat/designs/ext_rep.py b/src/sage/combinat/designs/ext_rep.py
index 0f5bdf339fa..2227a1e9f63 100644
--- a/src/sage/combinat/designs/ext_rep.py
+++ b/src/sage/combinat/designs/ext_rep.py
@@ -601,7 +601,7 @@ def _encode_attribute(string):
else:
return string
-class XTree():
+class XTree:
'''
A lazy class to wrap a rooted tree representing an XML document.
The tree's nodes are tuples of the structure:
@@ -774,7 +774,7 @@ def __len__(self):
return len(self.xt_children)
-class XTreeProcessor():
+class XTreeProcessor:
'''
An incremental event-driven parser for ext-rep documents.
The processing stages:
diff --git a/src/sage/combinat/designs/incidence_structures.py b/src/sage/combinat/designs/incidence_structures.py
index 46aada66a6e..ad60d30a6a1 100644
--- a/src/sage/combinat/designs/incidence_structures.py
+++ b/src/sage/combinat/designs/incidence_structures.py
@@ -48,7 +48,7 @@
lazy_import('sage.libs.gap.libgap', 'libgap')
-class IncidenceStructure():
+class IncidenceStructure:
r"""
A base class for incidence structures (i.e. hypergraphs, i.e. set systems)
diff --git a/src/sage/combinat/designs/latin_squares.py b/src/sage/combinat/designs/latin_squares.py
index f67a2317a17..69b19540c22 100644
--- a/src/sage/combinat/designs/latin_squares.py
+++ b/src/sage/combinat/designs/latin_squares.py
@@ -291,12 +291,12 @@ def mutually_orthogonal_latin_squares(k, n, partitions=False, check=True):
sage: designs.orthogonal_arrays.is_available(5+2, 5) # 5 MOLS of order 5
False
- sage: designs.orthogonal_arrays.is_available(4+2,6) # 4 MOLS of order 6 # needs sage.schemes
+ sage: designs.orthogonal_arrays.is_available(4+2,6) # 4 MOLS of order 6 # needs sage.schemes
False
Sage, however, is not able to prove that the second MOLS do not exist::
- sage: designs.orthogonal_arrays.exists(4+2,6) # 4 MOLS of order 6 # needs sage.schemes
+ sage: designs.orthogonal_arrays.exists(4+2,6) # 4 MOLS of order 6 # needs sage.schemes
Unknown
If you ask for such a MOLS then you will respectively get an informative
diff --git a/src/sage/combinat/designs/orthogonal_arrays.py b/src/sage/combinat/designs/orthogonal_arrays.py
index b819d96c1db..312f6a4b375 100644
--- a/src/sage/combinat/designs/orthogonal_arrays.py
+++ b/src/sage/combinat/designs/orthogonal_arrays.py
@@ -2068,7 +2068,7 @@ def OA_from_wider_OA(OA,k):
return OA
return [L[:k] for L in OA]
-class OAMainFunctions():
+class OAMainFunctions:
r"""
Functions related to orthogonal arrays.
diff --git a/src/sage/combinat/designs/twographs.py b/src/sage/combinat/designs/twographs.py
index 54d684cb9d2..8ba2bc12681 100644
--- a/src/sage/combinat/designs/twographs.py
+++ b/src/sage/combinat/designs/twographs.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Two-graphs
diff --git a/src/sage/combinat/diagram_algebras.py b/src/sage/combinat/diagram_algebras.py
index 2838d1e38df..b09c2b40cca 100644
--- a/src/sage/combinat/diagram_algebras.py
+++ b/src/sage/combinat/diagram_algebras.py
@@ -2158,7 +2158,7 @@ def diagrams(self):
return self.support()
-class UnitDiagramMixin():
+class UnitDiagramMixin:
"""
Mixin class for diagram algebras that have the unit indexed by
the :func:`identity_set_partition`.
@@ -4558,59 +4558,59 @@ def is_planar(sp):
sage: da.is_planar( da.to_set_partition([[1,-1],[2,-2]]))
True
"""
- #Singletons don't affect planarity
+ # Singletons don't affect planarity
to_consider = [x for x in map(list, sp) if len(x) > 1]
n = len(to_consider)
for i in range(n):
- #Get the positive and negative entries of this part
+ # Get the positive and negative entries of this part
ap = [x for x in to_consider[i] if x > 0]
an = [abs(x) for x in to_consider[i] if x < 0]
- #Check if a includes numbers in both the top and bottom rows
+ # Check if a includes numbers in both the top and bottom rows
if ap and an:
for j in range(n):
if i == j:
continue
- #Get the positive and negative entries of this part
+ # Get the positive and negative entries of this part
bp = [x for x in to_consider[j] if x > 0]
bn = [abs(x) for x in to_consider[j] if x < 0]
- #Skip the ones that don't involve numbers in both
- #the bottom and top rows
+ # Skip the ones that don't involve numbers in both
+ # the bottom and top rows
if not bn or not bp:
continue
- #Make sure that if min(bp) > max(ap)
- #then min(bn) > max(an)
+ # Make sure that if min(bp) > max(ap)
+ # then min(bn) > max(an)
if max(bp) > max(ap):
if min(bn) < min(an):
return False
- #Go through the bottom and top rows
+ # Go through the bottom and top rows
for row in [ap, an]:
if len(row) > 1:
row.sort()
for s in range(len(row)-1):
if row[s] + 1 == row[s+1]:
- #No gap, continue on
+ # No gap, continue on
continue
rng = list(range(row[s] + 1, row[s+1]))
- #Go through and make sure any parts that
- #contain numbers in this range are completely
- #contained in this range
+ # Go through and make sure any parts that
+ # contain numbers in this range are completely
+ # contained in this range
for j in range(n):
if i == j:
continue
- #Make sure we make the numbers negative again
- #if we are in the bottom row
+ # Make sure we make the numbers negative again
+ # if we are in the bottom row
if row is ap:
sr = set(rng)
else:
- sr = set((-1*x for x in rng))
+ sr = set(-x for x in rng)
sj = set(to_consider[j])
intersection = sr.intersection(sj)
@@ -4773,12 +4773,11 @@ def to_set_partition(l, k=None):
[{-1, 1}, {-2, 3}, {2}, {-4, 4}, {-5, 5}, {-3}]
"""
if k is None:
- if l == []:
+ if not l:
return []
- else:
- k = max( (max( map(abs, x) ) for x in l) )
+ k = max(max(map(abs, x)) for x in l)
- to_be_added = set( list(range(1, ceil(k+1))) + [-1*x for x in range(1, ceil(k+1))] )
+ to_be_added = set(list(range(1, ceil(k+1))) + [-x for x in range(1, ceil(k+1))])
sp = []
for part in l:
@@ -4790,7 +4789,7 @@ def to_set_partition(l, k=None):
i = to_be_added.pop()
if -i in to_be_added:
to_be_added.remove(-i)
- sp.append(set([i,-i]))
+ sp.append(set([i, -i]))
else:
sp.append(set([i]))
diff --git a/src/sage/combinat/dyck_word.py b/src/sage/combinat/dyck_word.py
index 41a3c199599..06cf887c936 100644
--- a/src/sage/combinat/dyck_word.py
+++ b/src/sage/combinat/dyck_word.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Dyck Words
diff --git a/src/sage/combinat/finite_state_machine.py b/src/sage/combinat/finite_state_machine.py
index a76958e6e73..cc4588e676e 100644
--- a/src/sage/combinat/finite_state_machine.py
+++ b/src/sage/combinat/finite_state_machine.py
@@ -104,7 +104,7 @@
:meth:`~FiniteStateMachine.has_state` | Checks for a state
:meth:`~FiniteStateMachine.has_initial_state` | Checks for an initial state
:meth:`~FiniteStateMachine.has_initial_states` | Checks for initial states
- :meth:`~FiniteStateMachine.has_final_state` | Checks for an final state
+ :meth:`~FiniteStateMachine.has_final_state` | Checks for a final state
:meth:`~FiniteStateMachine.has_final_states` | Checks for final states
:meth:`~FiniteStateMachine.has_transition` | Checks for a transition
:meth:`~FiniteStateMachine.is_deterministic` | Checks for a deterministic machine
@@ -3667,7 +3667,7 @@ def __call__(self, *args, **kwargs):
sage: H.states()
[('A', 1), ('B', 1), ('B', 2)]
- An automaton or transducer can also act on an input (an list
+ An automaton or transducer can also act on an input (a list
or other iterable of letters)::
sage: binary_inverter = Transducer({'A': [('A', 0, 1), ('A', 1, 0)]},
@@ -12144,7 +12144,7 @@ class Transducer(FiniteStateMachine):
This creates a transducer, which is a finite state machine, whose
transitions have input and output labels.
- An transducer has additional features like creating a simplified
+ A transducer has additional features like creating a simplified
transducer.
See class :class:`FiniteStateMachine` for more information.
diff --git a/src/sage/combinat/finite_state_machine_generators.py b/src/sage/combinat/finite_state_machine_generators.py
index aacc520999a..94342f9b4a3 100644
--- a/src/sage/combinat/finite_state_machine_generators.py
+++ b/src/sage/combinat/finite_state_machine_generators.py
@@ -97,7 +97,7 @@
from sage.rings.rational_field import QQ
-class AutomatonGenerators():
+class AutomatonGenerators:
r"""
A collection of constructors for several common automata.
@@ -346,7 +346,7 @@ def transition_function(read, input):
final_states=[word])
-class TransducerGenerators():
+class TransducerGenerators:
r"""
A collection of constructors for several common transducers.
diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py
index d8092f4bea1..8a97fbdc796 100644
--- a/src/sage/combinat/free_module.py
+++ b/src/sage/combinat/free_module.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Free modules
"""
@@ -937,7 +936,7 @@ def get_order(self):
EXAMPLES::
sage: QS2 = SymmetricGroupAlgebra(QQ,2) # needs sage.combinat
- sage: QS2.get_order() # note: order changed on 2009-03-13 # needs sage.combinat
+ sage: QS2.get_order() # note: order changed on 2009-03-13 # needs sage.combinat
[[2, 1], [1, 2]]
"""
if self._order is None:
@@ -1670,7 +1669,7 @@ def _coerce_map_from_(self, R):
return super()._coerce_map_from_(R)
-class CartesianProductWithFlattening():
+class CartesianProductWithFlattening:
"""
A class for Cartesian product constructor, with partial flattening
"""
diff --git a/src/sage/combinat/free_prelie_algebra.py b/src/sage/combinat/free_prelie_algebra.py
index 965c459720c..cb81e811ade 100644
--- a/src/sage/combinat/free_prelie_algebra.py
+++ b/src/sage/combinat/free_prelie_algebra.py
@@ -15,6 +15,7 @@
# the License, or (at your option) any later version.
# https://www.gnu.org/licenses/
# ****************************************************************************
+from itertools import product
from sage.categories.magmatic_algebras import MagmaticAlgebras
from sage.categories.lie_algebras import LieAlgebras
@@ -26,6 +27,7 @@
from sage.categories.functor import Functor
from sage.combinat.free_module import CombinatorialFreeModule
+from sage.combinat.integer_vector import IntegerVectors
from sage.combinat.words.alphabet import Alphabet
from sage.combinat.rooted_tree import (RootedTrees, RootedTree,
LabelledRootedTrees,
@@ -34,6 +36,7 @@
from sage.misc.lazy_attribute import lazy_attribute
from sage.misc.cachefunc import cached_method
+from sage.functions.other import factorial
from sage.sets.family import Family
from sage.structure.coerce_exceptions import CoercionException
@@ -530,6 +533,135 @@ def nap_product(self):
codomain=self),
position=1)
+ def corolla(self, x, y, n, N):
+ """
+ Return the corolla obtained with ``x`` as root and ``y`` as leaves.
+
+ INPUT:
+
+ - ``x``, ``y`` -- two elements
+ - ``n`` -- integer; width of the corolla
+ - ``N`` -- integer; truncation order (up to order ``N`` included)
+
+ OUTPUT:
+
+ the sum over all possible ways to graft ``n`` copies of ``y``
+ on top of ``x`` (with at most ``N`` vertices in total)
+
+ This operation can be defined by induction starting from the
+ pre-Lie product.
+
+ EXAMPLES::
+
+ sage: A = algebras.FreePreLie(QQ)
+ sage: a = A.gen(0)
+ sage: b = A.corolla(a,a,1,4); b
+ B[[[]]]
+ sage: A.corolla(b,b,2,7)
+ B[[[[[]], [[]]]]] + 2*B[[[[]], [[[]]]]] + B[[[], [[]], [[]]]]
+
+ sage: A = algebras.FreePreLie(QQ, 'o')
+ sage: a = A.gen(0)
+ sage: b = A.corolla(a,a,1,4)
+
+ sage: A = algebras.FreePreLie(QQ,'ab')
+ sage: a, b = A.gens()
+ sage: A.corolla(a,b,1,4)
+ B[a[b[]]]
+ sage: A.corolla(b,a,3,4)
+ B[b[a[], a[], a[]]]
+
+ sage: A.corolla(a+b,a+b,2,4)
+ B[a[a[], a[]]] + 2*B[a[a[], b[]]] + B[a[b[], b[]]] + B[b[a[], a[]]] +
+ 2*B[b[a[], b[]]] + B[b[b[], b[]]]
+
+ TESTS::
+
+ sage: A = algebras.FreePreLie(QQ,'ab')
+ sage: a, b = A.gens()
+ sage: A.corolla(a,A.zero(),2,2)
+ 0
+ """
+ if not x or not y:
+ return self.zero()
+
+ basering = self.base_ring()
+ vx = x.valuation()
+ vy = y.valuation()
+ min_deg = vy * n + vx
+ if min_deg > N:
+ return self.zero()
+
+ try:
+ self.gen(0).support()[0].label()
+ labels = True
+ except AttributeError:
+ labels = False
+
+ deg_x = x.maximal_degree()
+ deg_y = y.maximal_degree()
+ max_x = min(deg_x, N - n * vy)
+ max_y = min(deg_y, N - vx - (n - 1) * vy)
+ xx = x.truncate(max_x + 1)
+ yy = y.truncate(max_y + 1)
+
+ y_homog = {i: list(yy.homogeneous_component(i))
+ for i in range(vy, max_y + 1)}
+ resu = self.zero()
+ for k in range(min_deg, N + 1): # total degree of (x ; y, y, y, y)
+ for mx, coef_x in xx:
+ dx = mx.node_number()
+ step = self.zero()
+ for pi in IntegerVectors(k - dx, n, min_part=vy, max_part=max_y):
+ for ly in product(*[y_homog[part] for part in pi]):
+ coef_y = basering.prod(mc[1] for mc in ly)
+ arbres_y = [mc[0] for mc in ly]
+ step += coef_y * self.sum(self(t)
+ for t in corolla_gen(mx, arbres_y, labels))
+ resu += coef_x * step
+ return resu
+
+ def group_product(self, x, y, n, N=10):
+ r"""
+ Return the truncated group product of ``x`` and ``y``.
+
+ This is a weighted sum of all corollas with up to ``n`` leaves, with
+ ``x`` as root and ``y`` as leaves.
+
+ The result is computed up to order ``N`` (included).
+
+ When considered with infinitely many terms and infinite precision,
+ this is an analogue of the Baker-Campbell-Hausdorff formula: it
+ defines an associative product on the completed free pre-Lie algebra.
+
+ INPUT:
+
+ - ``x``, ``y`` -- two elements
+ - ``n`` -- integer; the maximal width of corollas
+ - ``N`` -- integer (default: 10); truncation order
+
+ EXAMPLES:
+
+ In the free pre-Lie algebra with one generator::
+
+ sage: PL = algebras.FreePreLie(QQ)
+ sage: a = PL.gen(0)
+ sage: PL.group_product(a, a, 3, 3)
+ B[[]] + B[[[]]] + 1/2*B[[[], []]]
+
+ In the free pre-Lie algebra with several generators::
+
+ sage: PL = algebras.FreePreLie(QQ,'@O')
+ sage: a, b = PL.gens()
+ sage: PL.group_product(a, b, 3, 3)
+ B[@[]] + B[@[O[]]] + 1/2*B[@[O[], O[]]]
+ sage: PL.group_product(a, b, 3, 10)
+ B[@[]] + B[@[O[]]] + 1/2*B[@[O[], O[]]] + 1/6*B[@[O[], O[], O[]]]
+ """
+ br = self.base_ring()
+ return x + self.sum(self.corolla(x, y, i, N) * ~br(factorial(i))
+ for i in range(1, n + 1))
+
def _element_constructor_(self, x):
r"""
Convert ``x`` into ``self``.
@@ -703,6 +835,40 @@ def lift(self):
for x, cf in self.monomial_coefficients(copy=False).items()}
return UEA.element_class(UEA, data)
+ def valuation(self):
+ """
+ Return the valuation of ``self``.
+
+ EXAMPLES::
+
+ sage: a = algebras.FreePreLie(QQ).gen(0)
+ sage: a.valuation()
+ 1
+ sage: (a*a).valuation()
+ 2
+
+ sage: a, b = algebras.FreePreLie(QQ,'ab').gens()
+ sage: (a+b).valuation()
+ 1
+ sage: (a*b).valuation()
+ 2
+ sage: (a*b+a).valuation()
+ 1
+
+ TESTS::
+
+ sage: z = algebras.FreePreLie(QQ).zero()
+ sage: z.valuation()
+ +Infinity
+ """
+ if self == self.parent().zero():
+ return Infinity
+ i = 0
+ while True:
+ i += 1
+ if self.homogeneous_component(i):
+ return i
+
class PreLieFunctor(ConstructionFunctor):
"""
@@ -872,3 +1038,106 @@ def _repr_(self):
PreLie[x,y,z,t]
"""
return "PreLie[%s]" % ','.join(self.vars)
+
+
+def tree_from_sortkey(ch, labels=True):
+ r"""
+ Transform a list of ``(valence, label)`` into a tree and a remainder.
+
+ This is like an inverse of the ``sort_key`` method.
+
+ INPUT:
+
+ - ``ch`` -- a list of pairs ``(integer, label)``
+ - ``labels`` -- (default ``True``) whether to use labelled trees
+
+ OUTPUT:
+
+ a pair ``(tree, remainder of the input)``
+
+ EXAMPLES::
+
+ sage: from sage.combinat.free_prelie_algebra import tree_from_sortkey
+ sage: a = algebras.FreePreLie(QQ).gen(0)
+ sage: t = (a*a*a*a).support()
+ sage: all(tree_from_sortkey(u.sort_key(), False)[0] == u for u in t)
+ True
+
+ sage: a, b = algebras.FreePreLie(QQ,'ab').gens()
+ sage: t = (a*b*a*b).support()
+ sage: all(tree_from_sortkey(u.sort_key())[0] == u for u in t)
+ True
+ """
+ if labels:
+ Trees = LabelledRootedTrees()
+ width, label = ch[0]
+ else:
+ Trees = RootedTrees()
+ width = ch[0]
+
+ remainder = ch[1:]
+ if width == 0:
+ if labels:
+ return (Trees([], label), remainder)
+ return (Trees([]), remainder)
+
+ branches = {}
+ for i in range(width):
+ tree, remainder = tree_from_sortkey(remainder, labels=labels)
+ branches[i] = tree
+
+ if labels:
+ return (Trees(branches.values(), label), remainder)
+ return (Trees(branches.values()), remainder)
+
+
+def corolla_gen(tx, list_ty, labels=True):
+ """
+ Yield the terms in the corolla with given bottom tree and top trees.
+
+ These are the possible terms in the simultaneous grafting of the
+ top trees on vertices of the bottom tree.
+
+ INPUT:
+
+ - ``tx`` -- a tree
+ - ``list_ty`` -- a list of trees
+
+ EXAMPLES::
+
+ sage: from sage.combinat.free_prelie_algebra import corolla_gen
+ sage: a = algebras.FreePreLie(QQ).gen(0)
+ sage: ta = a.support()[0]
+ sage: list(corolla_gen(ta,[ta],False))
+ [[[]]]
+
+ sage: a, b = algebras.FreePreLie(QQ,'ab').gens()
+ sage: ta = a.support()[0]
+ sage: tb = b.support()[0]
+ sage: ab = (a*b).support()[0]
+ sage: list(corolla_gen(ta,[tb]))
+ [a[b[]]]
+ sage: list(corolla_gen(tb,[ta,ta]))
+ [b[a[], a[]]]
+ sage: list(corolla_gen(ab,[ab,ta]))
+ [a[a[], b[], a[b[]]], a[a[b[]], b[a[]]], a[a[], b[a[b[]]]],
+ a[b[a[], a[b[]]]]]
+ """
+ n = len(list_ty)
+ zx = tx.sort_key()
+ nx = len(zx)
+ liste_zy = [t.sort_key() for t in list_ty]
+ for list_pos in product(range(nx), repeat=n):
+ new_zx = tuple(zx)
+ data = zip(list_pos, liste_zy)
+ sorted_data = sorted(data, reverse=True)
+ for pos_t in sorted_data:
+ if labels:
+ idx, lbl = new_zx[pos_t[0]]
+ new_zx = (new_zx[:pos_t[0]] + ((idx + 1, lbl),) +
+ pos_t[1] + new_zx[pos_t[0] + 1:])
+ else:
+ idx = new_zx[pos_t[0]]
+ new_zx = (new_zx[:pos_t[0]] + (idx + 1,) +
+ pos_t[1] + new_zx[pos_t[0] + 1:])
+ yield tree_from_sortkey(new_zx, labels=labels)[0]
diff --git a/src/sage/combinat/growth.py b/src/sage/combinat/growth.py
index 951d774931e..1b711ddde5f 100644
--- a/src/sage/combinat/growth.py
+++ b/src/sage/combinat/growth.py
@@ -4348,7 +4348,7 @@ def union(la, mu):
#####################################################################
-class Rules():
+class Rules:
"""
Catalog of rules for growth diagrams.
"""
diff --git a/src/sage/combinat/hillman_grassl.py b/src/sage/combinat/hillman_grassl.py
index 1abbc3d56bd..5a85d4e48d3 100644
--- a/src/sage/combinat/hillman_grassl.py
+++ b/src/sage/combinat/hillman_grassl.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
The Hillman-Grassl correspondence
diff --git a/src/sage/combinat/integer_lists/invlex.pyx b/src/sage/combinat/integer_lists/invlex.pyx
index b517a108479..07036085ac0 100644
--- a/src/sage/combinat/integer_lists/invlex.pyx
+++ b/src/sage/combinat/integer_lists/invlex.pyx
@@ -99,7 +99,7 @@ class IntegerListsLex(IntegerLists, metaclass=ClasscallMetaclass):
value is `\infty`.
- ``min_slope`` -- an integer or `-\infty` (default: `-\infty`):
- an lower bound on the slope between consecutive parts:
+ a lower bound on the slope between consecutive parts:
``min_slope <= l[i+1]-l[i]`` for ``0 <= i < len(l)-1``
- ``max_slope`` -- an integer or `+\infty` (defaults: `+\infty`)
@@ -796,7 +796,7 @@ class IntegerListsLex(IntegerLists, metaclass=ClasscallMetaclass):
cdef class IntegerListsBackend_invlex(IntegerListsBackend):
"""
- Cython back-end of an set of lists of integers with specified
+ Cython back-end of a set of lists of integers with specified
constraints enumerated in inverse lexicographic order.
"""
def __init__(self, *args, check=True, **kwds):
diff --git a/src/sage/combinat/integer_vector.py b/src/sage/combinat/integer_vector.py
index 456eea36f44..4f1176c62a8 100644
--- a/src/sage/combinat/integer_vector.py
+++ b/src/sage/combinat/integer_vector.py
@@ -48,7 +48,7 @@
from sage.rings.integer import Integer
-def is_gale_ryser(r,s):
+def is_gale_ryser(r, s):
r"""
Tests whether the given sequences satisfy the condition
of the Gale-Ryser theorem.
@@ -314,20 +314,20 @@ def gale_ryser_theorem(p1, p2, algorithm="gale",
"""
from sage.matrix.constructor import matrix
- if not is_gale_ryser(p1,p2):
+ if not is_gale_ryser(p1, p2):
return False
- if algorithm == "ryser": # ryser's algorithm
+ if algorithm == "ryser": # ryser's algorithm
from sage.combinat.permutation import Permutation
# Sorts the sequences if they are not, and remembers the permutation
# applied
- tmp = sorted(enumerate(p1), reverse=True, key=lambda x:x[1])
+ tmp = sorted(enumerate(p1), reverse=True, key=lambda x: x[1])
r = [x[1] for x in tmp]
r_permutation = [x-1 for x in Permutation([x[0]+1 for x in tmp]).inverse()]
m = len(r)
- tmp = sorted(enumerate(p2), reverse=True, key=lambda x:x[1])
+ tmp = sorted(enumerate(p2), reverse=True, key=lambda x: x[1])
s = [x[1] for x in tmp]
s_permutation = [x-1 for x in Permutation([x[0]+1 for x in tmp]).inverse()]
@@ -340,12 +340,12 @@ def gale_ryser_theorem(p1, p2, algorithm="gale",
k = i + 1
while k < m and r[i] == r[k]:
k += 1
- if t >= k - i: # == number rows of the same length
+ if t >= k - i: # == number rows of the same length
for j in range(i, k):
r[j] -= 1
c[j] = 1
t -= k - i
- else: # Remove the t last rows of that length
+ else: # Remove the t last rows of that length
for j in range(k-t, k):
r[j] -= 1
c[j] = 1
@@ -366,17 +366,17 @@ def gale_ryser_theorem(p1, p2, algorithm="gale",
k1, k2 = len(p1), len(p2)
p = MixedIntegerLinearProgram(solver=solver)
b = p.new_variable(binary=True)
- for (i,c) in enumerate(p1):
- p.add_constraint(p.sum([b[i,j] for j in range(k2)]) == c)
- for (i,c) in enumerate(p2):
- p.add_constraint(p.sum([b[j,i] for j in range(k1)]) == c)
+ for (i, c) in enumerate(p1):
+ p.add_constraint(p.sum([b[i, j] for j in range(k2)]) == c)
+ for (i, c) in enumerate(p2):
+ p.add_constraint(p.sum([b[j, i] for j in range(k1)]) == c)
p.set_objective(None)
p.solve()
b = p.get_values(b, convert=ZZ, tolerance=integrality_tolerance)
M = [[0]*k2 for i in range(k1)]
for i in range(k1):
for j in range(k2):
- M[i][j] = b[i,j]
+ M[i][j] = b[i, j]
return matrix(M)
else:
@@ -780,6 +780,43 @@ def __contains__(self, x):
return False
return True
+ def _unrank_helper(self, x, rtn):
+ """
+ Return the element at rank ``x`` by iterating through all integer vectors beginning with ``rtn``.
+
+ INPUT:
+
+ - ``x`` - a nonnegative integer
+ - ``rtn`` - a list of nonnegative integers
+
+
+ EXAMPLES::
+
+ sage: IV = IntegerVectors(k=5)
+ sage: IV._unrank_helper(10, [2,0,0,0,0])
+ [1, 0, 0, 0, 1]
+
+ sage: IV = IntegerVectors(n=7)
+ sage: IV._unrank_helper(100, [7,0,0,0])
+ [2, 0, 0, 5]
+
+ sage: IV = IntegerVectors(n=12, k=7)
+ sage: IV._unrank_helper(1000, [12,0,0,0,0,0,0])
+ [5, 3, 1, 1, 1, 1, 0]
+ """
+ ptr = 0
+ while True:
+ current_rank = self.rank(rtn)
+ if current_rank < x:
+ rtn[ptr+1] = rtn[ptr]
+ rtn[ptr] = 0
+ ptr += 1
+ elif current_rank > x:
+ rtn[ptr] -= 1
+ rtn[ptr-1] += 1
+ else:
+ return self._element_constructor_(rtn)
+
class IntegerVectors_all(UniqueRepresentation, IntegerVectors):
"""
@@ -839,7 +876,10 @@ def __init__(self, n):
sage: TestSuite(IV).run()
"""
self.n = n
- IntegerVectors.__init__(self, category=InfiniteEnumeratedSets())
+ if self.n == 0:
+ IntegerVectors.__init__(self, category=EnumeratedSets())
+ else:
+ IntegerVectors.__init__(self, category=InfiniteEnumeratedSets())
def _repr_(self):
"""
@@ -898,6 +938,68 @@ def __contains__(self, x):
return False
return sum(x) == self.n
+ def rank(self, x):
+ """
+ Return the rank of a given element.
+
+ INPUT:
+
+ - ``x`` -- a list with ``sum(x) == n``
+
+ EXAMPLES::
+
+ sage: IntegerVectors(n=5).rank([5,0])
+ 1
+ sage: IntegerVectors(n=5).rank([3,2])
+ 3
+ """
+ if sum(x) != self.n:
+ raise ValueError("argument is not a member of IntegerVectors({},{})".format(self.n, None))
+
+ n, k, s = self.n, len(x), 0
+ r = binomial(k + n - 1, n + 1)
+ for i in range(k - 1):
+ s += x[k - 1 - i]
+ r += binomial(s + i, i + 1)
+ return r
+
+ def unrank(self, x):
+ """
+ Return the element at given rank x.
+
+ INPUT:
+
+ - ``x`` -- an integer.
+
+ EXAMPLES::
+
+ sage: IntegerVectors(n=5).unrank(2)
+ [4, 1]
+ sage: IntegerVectors(n=10).unrank(10)
+ [1, 9]
+ """
+ rtn = [self.n]
+ while self.rank(rtn) <= x:
+ rtn.append(0)
+ rtn.pop()
+
+ return IntegerVectors._unrank_helper(self, x, rtn)
+
+ def cardinality(self):
+ """
+ Return the cardinality of ``self``.
+
+ EXAMPLES::
+
+ sage: IntegerVectors(n=0).cardinality()
+ 1
+ sage: IntegerVectors(n=10).cardinality()
+ +Infinity
+ """
+ if self.n == 0:
+ return Integer(1)
+ return PlusInfinity()
+
class IntegerVectors_k(UniqueRepresentation, IntegerVectors):
"""
@@ -912,7 +1014,10 @@ def __init__(self, k):
sage: TestSuite(IV).run()
"""
self.k = k
- IntegerVectors.__init__(self, category=InfiniteEnumeratedSets())
+ if self.k == 0:
+ IntegerVectors.__init__(self, category=EnumeratedSets())
+ else:
+ IntegerVectors.__init__(self, category=InfiniteEnumeratedSets())
def _repr_(self):
"""
@@ -968,6 +1073,75 @@ def __contains__(self, x):
return False
return len(x) == self.k
+ def rank(self, x):
+ """
+ Return the rank of a given element.
+
+ INPUT:
+
+ - ``x`` -- a list with ``len(x) == k``
+
+ EXAMPLES::
+
+ sage: IntegerVectors(k=5).rank([0,0,0,0,0])
+ 0
+ sage: IntegerVectors(k=5).rank([1,1,0,0,0])
+ 7
+ """
+ if len(x) != self.k:
+ raise ValueError("argument is not a member of IntegerVectors({},{})".format(None, self.k))
+
+ n, k, s = sum(x), self.k, 0
+ r = binomial(n + k - 1, k)
+ for i in range(k - 1):
+ s += x[k - 1 - i]
+ r += binomial(s + i, i + 1)
+ return r
+
+ def unrank(self, x):
+ """
+ Return the element at given rank x.
+
+ INPUT:
+
+ - ``x`` -- an integer such that x < self.cardinality()``
+
+ EXAMPLES::
+
+ sage: IntegerVectors(k=5).unrank(10)
+ [1, 0, 0, 0, 1]
+ sage: IntegerVectors(k=5).unrank(15)
+ [0, 0, 2, 0, 0]
+ sage: IntegerVectors(k=0).unrank(0)
+ []
+ """
+ if self.k == 0 and x != 0:
+ raise IndexError(f"Index {x} is out of range for the IntegerVector.")
+ rtn = [0]*self.k
+ if self.k == 0 and x == 0:
+ return rtn
+
+ while self.rank(rtn) <= x:
+ rtn[0] += 1
+ rtn[0] -= 1
+
+ return IntegerVectors._unrank_helper(self, x, rtn)
+
+ def cardinality(self):
+ """
+ Return the cardinality of ``self``.
+
+ EXAMPLES::
+
+ sage: IntegerVectors(k=0).cardinality()
+ 1
+ sage: IntegerVectors(k=10).cardinality()
+ +Infinity
+ """
+ if self.k == 0:
+ return Integer(1)
+ return PlusInfinity()
+
class IntegerVectors_nk(UniqueRepresentation, IntegerVectors):
"""
@@ -1010,11 +1184,11 @@ def _list_rec(self, n, k):
res = []
if k == 1:
- return [ (n, ) ]
+ return [(n, )]
for nbar in range(n + 1):
n_diff = n - nbar
- for rest in self._list_rec( nbar , k - 1):
+ for rest in self._list_rec(nbar, k - 1):
res.append((n_diff,) + rest)
return res
@@ -1153,17 +1327,49 @@ def rank(self, x):
if x not in self:
raise ValueError("argument is not a member of IntegerVectors({},{})".format(self.n, self.k))
- n = self.n
- k = self.k
-
- r = 0
+ k, s, r = self.k, 0, 0
for i in range(k - 1):
- k -= 1
- n -= x[i]
- r += binomial(k + n - 1, k)
-
+ s += x[k - 1 - i]
+ r += binomial(s + i, i + 1)
return r
+ def unrank(self, x):
+ """
+ Return the element at given rank x.
+
+ INPUT:
+
+ - ``x`` -- an integer such that ``x < self.cardinality()``
+
+ EXAMPLES::
+
+ sage: IntegerVectors(4,5).unrank(30)
+ [1, 0, 1, 0, 2]
+ sage: IntegerVectors(2,3).unrank(5)
+ [0, 0, 2]
+ """
+ if x >= self.cardinality():
+ raise IndexError(f"Index {x} is out of range for the IntegerVector.")
+ rtn = [0]*self.k
+ rtn[0] = self.n
+ return IntegerVectors._unrank_helper(self, x, rtn)
+
+ def cardinality(self):
+ """
+ Return the cardinality of ``self``.
+
+ EXAMPLES::
+
+ sage: IntegerVectors(3,5).cardinality()
+ 35
+ sage: IntegerVectors(99, 3).cardinality()
+ 5050
+ sage: IntegerVectors(10^9 - 1, 3).cardinality()
+ 500000000500000000
+ """
+ n, k = self.n, self.k
+ return Integer(binomial(n + k - 1, n))
+
class IntegerVectors_nnondescents(UniqueRepresentation, IntegerVectors):
r"""
@@ -1320,11 +1526,11 @@ def __init__(self, n=None, k=None, **constraints):
category = FiniteEnumeratedSets()
else:
category = EnumeratedSets()
- elif k is not None and 'max_part' in constraints: # n is None
+ elif k is not None and 'max_part' in constraints: # n is None
category = FiniteEnumeratedSets()
else:
category = EnumeratedSets()
- IntegerVectors.__init__(self, category=category) # placeholder category
+ IntegerVectors.__init__(self, category=category) # placeholder category
def _repr_(self):
"""
diff --git a/src/sage/combinat/integer_vectors_mod_permgroup.py b/src/sage/combinat/integer_vectors_mod_permgroup.py
index 996d73a5efa..7877fedee44 100644
--- a/src/sage/combinat/integer_vectors_mod_permgroup.py
+++ b/src/sage/combinat/integer_vectors_mod_permgroup.py
@@ -1,6 +1,11 @@
# sage.doctest: needs sage.combinat sage.groups
r"""
Integer vectors modulo the action of a permutation group
+
+AUTHORS:
+
+* Nicolas Borie (2010-2012) - original module
+* Jukka Kohonen (2023) - fast cardinality method, :issue:`36787`, :issue:`36681`
"""
# ****************************************************************************
# Copyright (C) 2010-12 Nicolas Borie
@@ -24,6 +29,12 @@
from sage.combinat.integer_vector import IntegerVectors
+from sage.rings.power_series_ring import PowerSeriesRing
+from sage.rings.rational_field import QQ
+from sage.rings.integer import Integer
+from sage.misc.misc_c import prod
+from sage.arith.misc import binomial
+
class IntegerVectorsModPermutationGroup(UniqueRepresentation):
r"""
@@ -42,39 +53,39 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation):
v = \max_{\text{lex order}} \{g \cdot v | g \in G \}
The action of `G` is on position. This means for example that the
- simple transposition `s_1 = (1, 2)` swaps the first and the second entries
- of any integer vector `v = [a_1, a_2, a_3, \dots , a_n]`
+ simple transposition `s_1 = (1, 2)` swaps the first and the second
+ entries of any integer vector `v = [a_1, a_2, a_3, \dots , a_n]`
.. MATH::
s_1 \cdot v = [a_2, a_1, a_3, \dots , a_n]
- This functions returns a parent which contains a single integer
- vector by orbit under the action of the permutation group `G`. The
- approach chosen here is to keep the maximal integer vector for the
- lexicographic order in each orbit. Such maximal vector will be
- called canonical integer vector under the action of the
- permutation group `G`.
+ This function returns a parent which contains, from each orbit
+ orbit under the action of the permutation group `G`, a single
+ canonical vector. The canonical vector is the one that is maximal
+ within the orbit according to lexicographic order.
INPUT:
- ``G`` - a permutation group
- ``sum`` - (default: None) - a nonnegative integer
- ``max_part`` - (default: None) - a nonnegative integer setting the
- maximum of entries of elements
+ maximum value for every element
- ``sgs`` - (default: None) - a strong generating system of the
group `G`. If you do not provide it, it will be calculated at the
creation of the parent
OUTPUT:
- - If ``sum`` and ``max_part`` are None, it returns the infinite enumerated
- set of all integer vectors (list of integers) maximal in their orbit for
- the lexicographic order.
+ - If ``sum`` and ``max_part`` are None, it returns the infinite
+ enumerated set of all integer vectors (lists of integers) maximal
+ in their orbit for the lexicographic order. Exceptionally, if
+ the domain of ``G`` is empty, the result is a finite enumerated
+ set that contains one element, namely the empty vector.
- - If ``sum`` is an integer, it returns a finite enumerated set containing
- all integer vectors maximal in their orbit for the lexicographic order
- and whose entries sum to ``sum``.
+ - If ``sum`` is an integer, it returns a finite enumerated set
+ containing all integer vectors maximal in their orbit for the
+ lexicographic order and whose entries sum to ``sum``.
EXAMPLES:
@@ -105,7 +116,7 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation):
The method
:meth:`~sage.combinat.integer_vectors_mod_permgroup.IntegerVectorsModPermutationGroup_All.is_canonical`
- tests if any integer vector is maximal in its orbit. This method
+ tests if an integer vector is maximal in its orbit. This method
is also used in the containment test::
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
@@ -124,7 +135,7 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation):
sage: I.is_canonical('bla')
Traceback (most recent call last):
...
- AssertionError: bla should be a list or a integer vector
+ AssertionError: bla should be a list or an integer vector
If you give a value to the extra argument ``sum``, the set returned
will be a finite set containing only canonical vectors whose entries
@@ -153,10 +164,32 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation):
sage: I.orbit([2,2,2])
{[2, 2, 2]}
+ Even without constraints, for an empty domain the result is
+ a singleton set::
+
+ sage: G = PermutationGroup([], domain=[])
+ sage: sgs = tuple(tuple(s) for s in G.strong_generating_system())
+ sage: list(IntegerVectorsModPermutationGroup(G, sgs=sgs))
+ [[]]
+
+
+ .. WARNING::
+
+ Because of :issue:`36527`, permutation groups that have
+ different domains but similar generators can be erroneously
+ treated as the same group. This will silently produce
+ erroneous results. To avoid this issue, compute a strong
+ generating system for the group as::
+
+ sgs = tuple(tuple(s) for s in G.strong_generating_system())
+
+ and provide it as the optional ``sgs`` argument to the
+ constructor.
+
TESTS:
Let us check that canonical integer vectors of the symmetric group
- are just sorted list of integers::
+ are just nonincreasing lists of integers::
sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5)) # long time
sage: p = iter(I) # long time
@@ -164,9 +197,9 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation):
....: v = list(next(p))
....: assert sorted(v, reverse=True) == v
- We now check that there is as much of canonical vectors under the
- symmetric group `S_n` whose entries sum to `d` than partitions of
- `d` of at most `n` parts::
+ We now check that there are as many canonical vectors under the
+ symmetric group `S_n` whose entries sum to `d` as there are
+ partitions of `d` of at most `n` parts::
sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5)) # long time
sage: for i in range(10): # long time
@@ -185,15 +218,16 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation):
18
23
- We present a last corner case: trivial groups. For the trivial
- group ``G`` acting on a list of length `n`, all integer vectors of
- length `n` are canonical::
+ Another corner case is trivial groups. For the trivial group ``G``
+ acting on a list of length `n`, all integer vectors of length `n`
+ are canonical::
sage: # long time
sage: G = PermutationGroup([[(6,)]])
sage: G.cardinality()
1
- sage: I = IntegerVectorsModPermutationGroup(G)
+ sage: sgs = tuple(tuple(s) for s in G.strong_generating_system())
+ sage: I = IntegerVectorsModPermutationGroup(G, sgs=sgs)
sage: for i in range(10):
....: d1 = I.subset(i).cardinality()
....: d2 = IntegerVectors(i,6).cardinality()
@@ -209,6 +243,7 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation):
792
1287
2002
+
"""
@staticmethod
def __classcall__(cls, G, sum=None, max_part=None, sgs=None):
@@ -225,13 +260,22 @@ def __classcall__(cls, G, sum=None, max_part=None, sgs=None):
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3)]]), 8, max_part=5)
"""
if sum is None and max_part is None:
- return IntegerVectorsModPermutationGroup_All(G, sgs=sgs)
+ # No constraints.
+ if G.domain():
+ # Nonempty domain, infinite set.
+ return IntegerVectorsModPermutationGroup_All(G, sgs=sgs)
+ else:
+ # Empty domain, singleton set.
+ return IntegerVectorsModPermutationGroup_with_constraints(
+ G, 0, max_part=-1, sgs=sgs)
else:
+ # Some constraints, either sum or max_part or both.
if sum is not None:
assert sum == NN(sum)
if max_part is not None:
assert max_part == NN(max_part)
- return IntegerVectorsModPermutationGroup_with_constraints(G, sum, max_part, sgs=sgs)
+ return IntegerVectorsModPermutationGroup_with_constraints(
+ G, sum, max_part, sgs=sgs)
class IntegerVectorsModPermutationGroup_All(UniqueRepresentation, RecursivelyEnumeratedSet_forest):
@@ -435,7 +479,7 @@ def is_canonical(self, v, check=True):
False
"""
if check:
- assert isinstance(v, (ClonableIntArray, list)), '%s should be a list or a integer vector' % v
+ assert isinstance(v, (ClonableIntArray, list)), '%s should be a list or an integer vector' % v
assert (self.n == len(v)), '%s should be of length %s' % (v, self.n)
for p in v:
assert (p == NN(p)), 'Elements of %s should be integers' % v
@@ -634,17 +678,27 @@ def _repr_(self):
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6); S
Integer vectors of length 4 and of sum 6 enumerated up to the action of Permutation Group with generators [(1,2,3,4)]
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6, max_part=4); S
- Vectors of length 4 and of sum 6 whose entries is in {0, ..., 4} enumerated up to the action of Permutation Group with generators [(1,2,3,4)]
+ Vectors of length 4 and of sum 6 whose entries are in {0, ..., 4} enumerated up to the action of Permutation Group with generators [(1,2,3,4)]
sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), max_part=4); S
- Integer vectors of length 4 whose entries is in {0, ..., 4} enumerated up to the action of Permutation Group with generators [(1,2,3,4)]
+ Integer vectors of length 4 whose entries are in {0, ..., 4} enumerated up to the action of Permutation Group with generators [(1,2,3,4)]
"""
if self._sum is not None:
if self._max_part >= 0:
- return "Vectors of length %s and of sum %s whose entries is in {0, ..., %s} enumerated up to the action of %s" % (self.n, self._sum, self._max_part, self.permutation_group())
+ return ("Vectors of length %s and of sum %s"
+ " whose entries are in {0, ..., %s}"
+ " enumerated up to the action of %s"
+ % (self.n, self._sum, self._max_part,
+ self.permutation_group()))
else:
- return "Integer vectors of length %s and of sum %s enumerated up to the action of %s" % (self.n, self._sum, self.permutation_group())
+ return ("Integer vectors of length %s"
+ " and of sum %s"
+ " enumerated up to the action of %s"
+ % (self.n, self._sum, self.permutation_group()))
else:
- return "Integer vectors of length %s whose entries is in {0, ..., %s} enumerated up to the action of %s" % (self.n, self._max_part, self.permutation_group())
+ return ("Integer vectors of length %s"
+ " whose entries are in {0, ..., %s}"
+ " enumerated up to the action of %s"
+ % (self.n, self._max_part, self.permutation_group()))
def roots(self):
r"""
@@ -751,6 +805,7 @@ def __iter__(self):
[2, 0, 2, 0]
[2, 0, 1, 1]
[1, 1, 1, 1]
+
sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=7, max_part=3)
sage: for i in I: i
[3, 3, 1, 0]
@@ -763,18 +818,197 @@ def __iter__(self):
[3, 1, 1, 2]
[3, 0, 2, 2]
[2, 2, 2, 1]
+
+ Check that :issue:`36681` is fixed::
+
+ sage: G = PermutationGroup([], domain=[])
+ sage: I = IntegerVectorsModPermutationGroup(G, sum=0)
+ sage: list(iter(I))
+ [[]]
+
+ Check that :issue:`36681` is fixed::
+
+ sage: G = PermutationGroup([], domain=[])
+ sage: I = IntegerVectorsModPermutationGroup(G, sum=3)
+ sage: list(iter(I))
+ []
+
"""
+ # Special cases when domain is empty.
+ if self.n == 0:
+ if self._sum is not None and self._sum > 0:
+ # No empty vector can have positive sum.
+ return iter(())
+ else:
+ # Sum is allowed to be zero. It does not matter what
+ # the maxpart is, the empty vector is a solution.
+ return iter([self([])])
+
+ # General case, nonempty domain.
if self._max_part < 0:
return self.elements_of_depth_iterator(self._sum)
else:
- SF = RecursivelyEnumeratedSet_forest((self([0]*(self.n), check=False),),
- lambda x : [self(y, check=False) for y in canonical_children(self._sgs, x, self._max_part)],
- algorithm='breadth')
+ SF = RecursivelyEnumeratedSet_forest(
+ (self([0]*(self.n), check=False),),
+ lambda x: [self(y, check=False)
+ for y in canonical_children(
+ self._sgs, x, self._max_part)],
+ algorithm='breadth')
if self._sum is None:
return iter(SF)
else:
return SF.elements_of_depth_iterator(self._sum)
+ def cardinality(self):
+ r"""
+ Return the number of integer vectors in the set.
+
+ The algorithm utilises :wikipedia:`Cycle Index Theorem `, allowing
+ for a faster than a plain enumeration computation.
+
+ EXAMPLES:
+
+ With a trivial group all vectors are canonical::
+
+ sage: G = PermutationGroup([], domain=[1,2,3])
+ sage: IntegerVectorsModPermutationGroup(G, 5).cardinality()
+ 21
+ sage: IntegerVectors(5, 3).cardinality()
+ 21
+
+ With two interchangeable elements, the smaller one
+ ranges from zero to ``sum//2``::
+
+ sage: G = PermutationGroup([(1,2)])
+ sage: IntegerVectorsModPermutationGroup(G, 1000).cardinality()
+ 501
+
+ Binary vectors up to full symmetry are first some ones and
+ then some zeros::
+
+ sage: G = SymmetricGroup(10)
+ sage: I = IntegerVectorsModPermutationGroup(G, max_part=1)
+ sage: I.cardinality()
+ 11
+
+ Binary vectors of constant weight, up to PGL(2,17), which
+ is 3-transitive, but not 4-transitive::
+
+ sage: G=PGL(2,17)
+ sage: I = IntegerVectorsModPermutationGroup(G, sum=3, max_part=1)
+ sage: I.cardinality()
+ 1
+ sage: I = IntegerVectorsModPermutationGroup(G, sum=4, max_part=1)
+ sage: I.cardinality()
+ 3
+
+ TESTS:
+
+ Check that :issue:`36681` is fixed::
+
+ sage: G = PermutationGroup([], domain=[])
+ sage: sgs = tuple(tuple(t) for t in G.strong_generating_system())
+ sage: V = IntegerVectorsModPermutationGroup(G, sum=1, sgs=sgs)
+ sage: V.cardinality()
+ 0
+
+ The case when both ``sum`` and ``max_part`` are specified::
+
+ sage: G = PermutationGroup([(1,2,3)])
+ sage: I = IntegerVectorsModPermutationGroup(G, sum=10, max_part=5)
+ sage: I.cardinality()
+ 7
+
+ All permutation groups of degree 4::
+
+ sage: for G in SymmetricGroup(4).subgroups():
+ ....: sgs = tuple(tuple(t) for t in G.strong_generating_system())
+ ....: I1 = IntegerVectorsModPermutationGroup(G, sum=10, sgs=sgs)
+ ....: assert I1.cardinality() == len(list(I1))
+ ....: I2 = IntegerVectorsModPermutationGroup(G, max_part=3, sgs=sgs)
+ ....: assert I2.cardinality() == len(list(I2))
+ ....: I3 = IntegerVectorsModPermutationGroup(G, sum=10, max_part=3, sgs=sgs)
+ ....: assert I3.cardinality() == len(list(I3))
+
+ Symmetric group with sums 0 and 1::
+
+ sage: S10 = SymmetricGroup(10)
+ sage: IntegerVectorsModPermutationGroup(S10, 0).cardinality()
+ 1
+ sage: IntegerVectorsModPermutationGroup(S10, 1).cardinality()
+ 1
+
+ Trivial group with sums 1 and 100::
+
+ sage: T10 = PermutationGroup([], domain=range(1, 11))
+ sage: IntegerVectorsModPermutationGroup(T10, 1).cardinality()
+ 10
+ sage: IntegerVectorsModPermutationGroup(T10, 100).cardinality()
+ 4263421511271
+
+ """
+ G = self._permgroup
+ k = G.degree() # Vector length
+ d = self._sum # Required sum
+ m = self._max_part # Max of one entry, -1 for no limit
+ if m == -1:
+ m = d # Any entry cannot exceed total
+
+ # Some easy special cases.
+ if k == 0:
+ # Empty vectors. There is only one, and it has zero sum.
+ # Here _max_part does not matter because any _max_part
+ # condition is vacuously true (with no parts).
+ if d == 0 or d is None:
+ return Integer(1)
+ else:
+ return Integer(0)
+ if d == 0 or m == 0:
+ # All-zero vectors. There is only one of them.
+ return Integer(1)
+ if d == 1:
+ # Vectors with one 1 and all other elements zero.
+ # The 1 can be placed in any orbit, and by symmetry
+ # it will be on the first element of the orbit.
+ return Integer(len(G.orbits()))
+ if d is not None and m >= d and G.is_trivial():
+ # Simple calculation with stars and bars.
+ return Integer(binomial(d + k - 1, k - 1))
+
+ # General case.
+ #
+ # Cardinality is computed using the Cycle Index Theorem. We
+ # have two cases. With a fixed sum d we work with power
+ # series and extract the x^d coefficient. Without a fixed sum
+ # we can do with integer arithmetic.
+ Z = G.cycle_index()
+
+ if d is None:
+ # Case 1. Without a fixed sum, the sum can be up to k*m.
+ result = sum(coeff * (m+1)**len(cycle_type)
+ for cycle_type, coeff in Z)
+ # Computed as Rational, but should have an integer value
+ # by now.
+ return Integer(result)
+
+ # Case 2. Fixed sum d. Work with power series with enough
+ # precision that x^d is valid.
+ R = PowerSeriesRing(QQ, 'x', default_prec=d+1)
+ x = R.gen()
+
+ # The figure-counting series, for max_part==m, is (1-t**(m+1))
+ # / (1-t) = 1+t+...+t**m. For the function-counting series,
+ # we substitute x**cycle_length for t.
+ #
+ funcount = sum(
+ coeff * prod((1 - x**((m+1)*cycle_len)) / (1 - x**cycle_len)
+ for cycle_len in cycle_type)
+ for cycle_type, coeff in Z)
+
+ # Extract the d'th degree coefficient. Computed as Rational,
+ # but should have an integer value by now.
+ return Integer(funcount[d])
+
def is_canonical(self, v, check=True):
r"""
Return ``True`` if the integer list ``v`` is maximal in its
@@ -798,7 +1032,7 @@ def is_canonical(self, v, check=True):
True
"""
if check:
- assert isinstance(v, (ClonableIntArray, list)), '%s should be a list or a integer vector' % v
+ assert isinstance(v, (ClonableIntArray, list)), '%s should be a list or an integer vector' % v
assert (self.n == len(v)), '%s should be of length %s' % (v, self.n)
for p in v:
assert (p == NN(p)), 'Elements of %s should be integers' % v
@@ -980,7 +1214,7 @@ class Element(ClonableIntArray):
sage: v = I.element_class(I, [3,2,0,0])
Traceback (most recent call last):
...
- AssertionError: [3, 2, 0, 0] should be a integer vector of sum 4
+ AssertionError: [3, 2, 0, 0] should be an integer vector of sum 4
"""
def check(self):
@@ -1000,7 +1234,7 @@ def check(self):
AssertionError
"""
if self.parent()._sum is not None:
- assert sum(self) == self.parent()._sum, '%s should be a integer vector of sum %s' % (self, self.parent()._sum)
+ assert sum(self) == self.parent()._sum, '%s should be an integer vector of sum %s' % (self, self.parent()._sum)
if self.parent()._max_part >= 0:
assert max(self) <= self.parent()._max_part, 'Entries of %s must be inferior to %s' % (self, self.parent()._max_part)
assert self.parent().is_canonical(self)
diff --git a/src/sage/combinat/interval_posets.py b/src/sage/combinat/interval_posets.py
index c9f1e99984d..260a3aa6b48 100644
--- a/src/sage/combinat/interval_posets.py
+++ b/src/sage/combinat/interval_posets.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Tamari Interval-posets
diff --git a/src/sage/combinat/k_tableau.py b/src/sage/combinat/k_tableau.py
index 0e4bbc41758..69feb00dd8b 100644
--- a/src/sage/combinat/k_tableau.py
+++ b/src/sage/combinat/k_tableau.py
@@ -4225,7 +4225,7 @@ def add_marking( cls, unmarkedT, marking, k, weight ):
r"""
Add markings to a partially marked strong tableau.
- Given an partially marked standard tableau and a list of cells where the marks
+ Given a partially marked standard tableau and a list of cells where the marks
should be placed along with a ``weight``, return the semi-standard marked strong
tableau. The marking should complete the marking so that the result is a
strong standard marked tableau.
diff --git a/src/sage/combinat/knutson_tao_puzzles.py b/src/sage/combinat/knutson_tao_puzzles.py
index 72c3ea9c52e..1c0215fa093 100644
--- a/src/sage/combinat/knutson_tao_puzzles.py
+++ b/src/sage/combinat/knutson_tao_puzzles.py
@@ -51,7 +51,7 @@
from sage.structure.unique_representation import UniqueRepresentation
-class PuzzlePiece():
+class PuzzlePiece:
r"""
Abstract class for puzzle pieces.
@@ -621,7 +621,7 @@ def edges(self) -> tuple:
return ('north_west', 'north_east', 'south_east', 'south_west')
-class PuzzlePieces():
+class PuzzlePieces:
r"""
Construct a valid set of puzzle pieces.
@@ -1068,7 +1068,7 @@ def BK_pieces(max_letter):
return pieces
-class PuzzleFilling():
+class PuzzleFilling:
r"""
Create partial puzzles and provides methods to build puzzles from them.
"""
diff --git a/src/sage/combinat/matrices/hadamard_matrix.py b/src/sage/combinat/matrices/hadamard_matrix.py
index 0693941851e..29276a3ddad 100644
--- a/src/sage/combinat/matrices/hadamard_matrix.py
+++ b/src/sage/combinat/matrices/hadamard_matrix.py
@@ -324,7 +324,7 @@ def hadamard_matrix_miyamoto_construction(n, existence=False, check=True):
r"""
Construct Hadamard matrix using the Miyamoto construction.
- If `q = n/4` is a prime power, and there exists an Hadamard matrix of order
+ If `q = n/4` is a prime power, and there exists a Hadamard matrix of order
`q-1`, then a Hadamard matrix of order `n` can be constructed (see [Miy1991]_).
INPUT:
@@ -442,7 +442,7 @@ def hadamard_matrix_williamson_type(a, b, c, d, check=True):
- ``d`` -- (1,-1) list; the 1st row of `C`
- ``c`` -- (1,-1) list; the 1st row of `D`
- ``check`` -- boolean (default: ``True``); whether to check that the output
- is an Hadamard matrix before returning it
+ is a Hadamard matrix before returning it
EXAMPLES::
@@ -640,7 +640,7 @@ def williamson_hadamard_matrix_smallcases(n, existence=False, check=True):
def hadamard_matrix_156():
r"""
- Construct an Hadamard matrix of order 156.
+ Construct a Hadamard matrix of order 156.
The matrix is created using the construction detailed in [BH1965]_.
This uses four circulant matrices of size `13\times 13`,
@@ -1030,13 +1030,13 @@ def hadamard_matrix_from_sds(n, existence=False, check=True):
def hadamard_matrix_cooper_wallis_construction(x1, x2, x3, x4, A, B, C, D, check=True):
r"""
- Create an Hadamard matrix using the contruction detailed in [CW1972]_.
+ Create a Hadamard matrix using the contruction detailed in [CW1972]_.
Given four circulant matrices `X_1`, X_2, X_3, X_4` of order `n` with entries (0, 1, -1)
such that the entrywise product of two distinct matrices is always equal to `0` and that
`\sum_{i=1}^{4}X_iX_i^\top = nI_n` holds, and four matrices `A, B, C, D` of order `m` with
elements (1, -1) such that `MN^\top = NM^\top` for all distinct `M`, `N` and
- `AA^\top + BB^\top + CC^\top + DD^\top = 4mI_n` holds, we construct an Hadamard matrix
+ `AA^\top + BB^\top + CC^\top + DD^\top = 4mI_n` holds, we construct a Hadamard matrix
of order `4nm`.
INPUT:
@@ -1125,7 +1125,7 @@ def hadamard_matrix_cooper_wallis_smallcases(n, check=True, existence=False):
- ``n`` -- integer; the order of the matrix to be constructed
- ``check`` -- boolean (default: ``True``); if ``True``, check that the matrix
- is an Hadamard matrix before returning
+ is a Hadamard matrix before returning
- ``existence`` -- boolean (default: ``False``); if ``True``, only check if
the matrix exists.
@@ -1298,7 +1298,7 @@ def hadamard_matrix_turyn_type(a, b, c, d, e1, e2, e3, e4, check=True):
- ``e3`` -- Matrix; the third Baumert-Hall unit
- ``e4`` -- Matrix; the fourth Baumert-Hall unit
- ``check`` -- boolean (default: ``True``); whether to check that the output
- is an Hadamard matrix before returning it
+ is a Hadamard matrix before returning it
EXAMPLES::
@@ -1352,11 +1352,11 @@ def hadamard_matrix_turyn_type(a, b, c, d, e1, e2, e3, e4, check=True):
def turyn_type_hadamard_matrix_smallcases(n, existence=False, check=True):
r"""
- Construct an Hadamard matrix of order `n` from available 4-symbol `\delta` codes and Williamson quadruples.
+ Construct a Hadamard matrix of order `n` from available 4-symbol `\delta` codes and Williamson quadruples.
The function looks for Baumert-Hall units and Williamson type matrices from
:func:`four_symbol_delta_code_smallcases` and :func:`williamson_type_quadruples_smallcases`
- and use them to construct an Hadamard matrix with the Turyn construction
+ and use them to construct a Hadamard matrix with the Turyn construction
defined in :func:`hadamard_matrix_turyn_type`.
INPUT:
@@ -1365,7 +1365,7 @@ def turyn_type_hadamard_matrix_smallcases(n, existence=False, check=True):
- ``existence`` -- boolean (default: ``False``): if ``True``, only check if
the matrix exists
- ``check`` -- boolean (default: ``True``): if ``True``, check that the matrix
- is an Hadamard matrix before returning
+ is a Hadamard matrix before returning
EXAMPLES::
@@ -1407,7 +1407,7 @@ def turyn_type_hadamard_matrix_smallcases(n, existence=False, check=True):
def hadamard_matrix_spence_construction(n, existence=False, check=True):
r"""
- Create an Hadamard matrix of order `n` using the Spence construction.
+ Create a Hadamard matrix of order `n` using the Spence construction.
This construction (detailed in [Spe1975]_), uses supplementary difference sets implemented in
:func:`sage.combinat.designs.difference_family.supplementary_difference_set_from_rel_diff_set` to create the
@@ -1419,7 +1419,7 @@ def hadamard_matrix_spence_construction(n, existence=False, check=True):
- ``existence`` -- boolean (default: ``False``); if ``True``, only check if
the matrix exists
- ``check`` -- bolean (default: ``True``); if ``True``, check that the matrix
- is an Hadamard matrix before returning
+ is a Hadamard matrix before returning
OUTPUT:
@@ -2968,7 +2968,7 @@ def skew_hadamard_matrix_from_good_matrices_smallcases(n, existence=False, check
- ``existence`` -- boolean (default: ``False``); If ``True``, only return
whether the Hadamard matrix can be constructed
- ``check`` -- boolean (default: ``True``): if ``True``, check that the matrix
- is an Hadamard matrix before returning it
+ is a Hadamard matrix before returning it
OUTPUT:
diff --git a/src/sage/combinat/matrices/latin.py b/src/sage/combinat/matrices/latin.py
index 1a369bba355..460c44a6441 100644
--- a/src/sage/combinat/matrices/latin.py
+++ b/src/sage/combinat/matrices/latin.py
@@ -1531,7 +1531,7 @@ def isotopism(p):
if isinstance(p, tuple):
# We have a single cycle:
if isinstance(p[0], Integer):
- return Permutation(tuple((x+1 for x in p)))
+ return Permutation(tuple(x+1 for x in p))
# We have a tuple of cycles:
if isinstance(p[0], tuple):
diff --git a/src/sage/combinat/misc.py b/src/sage/combinat/misc.py
index 8034531ed19..2a4341e8f4c 100644
--- a/src/sage/combinat/misc.py
+++ b/src/sage/combinat/misc.py
@@ -19,7 +19,7 @@
from sage.misc.misc_c import prod
-class DoublyLinkedList():
+class DoublyLinkedList:
"""
A doubly linked list class that provides constant time hiding and
unhiding of entries.
diff --git a/src/sage/combinat/multiset_partition_into_sets_ordered.py b/src/sage/combinat/multiset_partition_into_sets_ordered.py
index c544d9ae2ef..967f6ad93af 100755
--- a/src/sage/combinat/multiset_partition_into_sets_ordered.py
+++ b/src/sage/combinat/multiset_partition_into_sets_ordered.py
@@ -3394,7 +3394,7 @@ def val(self, q='q'):
Verifying Example 4.5 from [BCHOPSY2017]_::
- sage: B = crystals.Minimaj(3, 4, 2) # for `Val_{4,1}^{(3)}` # needs sage.modules
+ sage: B = crystals.Minimaj(3, 4, 2) # for `Val_{4,1}^{(3)}` # needs sage.modules
sage: B.val() # needs sage.modules
(q^2+q+1)*s[2, 1, 1] + q*s[2, 2]
"""
diff --git a/src/sage/combinat/ncsf_qsym/ncsf.py b/src/sage/combinat/ncsf_qsym/ncsf.py
index 0d91379f408..91284a4186f 100644
--- a/src/sage/combinat/ncsf_qsym/ncsf.py
+++ b/src/sage/combinat/ncsf_qsym/ncsf.py
@@ -1999,7 +1999,7 @@ def image_of_L_k(k, i):
return x[i-1] * image_of_L_k(k - 1, i - 1) + image_of_L_k(k, i - 1)
def on_basis(comp):
- return P.prod((image_of_L_k(k, n) for k in comp))
+ return P.prod(image_of_L_k(k, n) for k in comp)
return L._apply_module_morphism(L(self), on_basis, codomain=P)
class MultiplicativeBases(Category_realization_of_parent):
diff --git a/src/sage/combinat/ordered_tree.py b/src/sage/combinat/ordered_tree.py
index 59f4a4ad115..5041dd434a4 100644
--- a/src/sage/combinat/ordered_tree.py
+++ b/src/sage/combinat/ordered_tree.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Ordered Rooted Trees
diff --git a/src/sage/combinat/output.py b/src/sage/combinat/output.py
index 6e9d2943cfd..7f223921d7e 100644
--- a/src/sage/combinat/output.py
+++ b/src/sage/combinat/output.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Output functions
@@ -505,7 +504,7 @@ def ascii_art_table(data, use_unicode=False, convention="English"):
def get_len(e):
if e is None:
return 0
- return len(e) - list(str(e)).count(u"\u0304")
+ return len(e) - list(str(e)).count("\u0304")
else:
def get_len(e):
if e is None:
@@ -692,7 +691,7 @@ def ascii_art_table_russian(data, use_unicode=False, compact=False):
def get_len(e):
if e is None:
return 0
- return len(e) - list(str(e)).count(u"\u0304")
+ return len(e) - list(str(e)).count("\u0304")
else:
def get_len(e):
if e is None:
diff --git a/src/sage/combinat/parallelogram_polyomino.py b/src/sage/combinat/parallelogram_polyomino.py
index 190eeedef72..53d35bca831 100644
--- a/src/sage/combinat/parallelogram_polyomino.py
+++ b/src/sage/combinat/parallelogram_polyomino.py
@@ -2088,7 +2088,7 @@ def is_k_directed(self, k) -> bool:
INPUT:
- - ``k`` -- An non negative integer.
+ - ``k`` -- A non negative integer.
EXAMPLES::
@@ -3958,7 +3958,7 @@ def _latex_drawing(self):
...
\end{tikzpicture}
"""
- latex.add_package_to_preamble_if_available(str("tikz"))
+ latex.add_package_to_preamble_if_available("tikz")
tikz_options = self.get_tikz_options()
res = "\n\\begin{tikzpicture}[scale=%s]" % (tikz_options['scale'])
res += self.to_tikz()
diff --git a/src/sage/combinat/partition.py b/src/sage/combinat/partition.py
index 7d16d5d3410..ee5a9fd85db 100644
--- a/src/sage/combinat/partition.py
+++ b/src/sage/combinat/partition.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Integer partitions
@@ -668,23 +667,23 @@ def _unicode_art_(self):
from sage.typeset.unicode_art import UnicodeArt
if not self._list:
- return UnicodeArt(u'∅', baseline=0)
+ return UnicodeArt('∅', baseline=0)
if self.parent().options.convention == "English":
data = list(self)
else:
data = list(reversed(self))
- txt = [u'┌' + u'┬' * (data[0] - 1) + u'┐']
+ txt = ['┌' + '┬' * (data[0] - 1) + '┐']
for i in range(len(data) - 1):
p = data[i]
q = data[i + 1]
if p < q:
- txt += [u'├' + u'┼' * p + u'┬' * (q - p - 1) + u'┐']
+ txt += ['├' + '┼' * p + '┬' * (q - p - 1) + '┐']
elif p == q:
- txt += [u'├' + u'┼' * (p - 1) + u'┤']
+ txt += ['├' + '┼' * (p - 1) + '┤']
else:
- txt += [u'├' + u'┼' * q + u'┴' * (p - q - 1) + u'┘']
- txt += [u'└' + u'┴' * (data[-1] - 1) + u'┘']
+ txt += ['├' + '┼' * q + '┴' * (p - q - 1) + '┘']
+ txt += ['└' + '┴' * (data[-1] - 1) + '┘']
return UnicodeArt(txt, baseline=0)
@@ -4900,14 +4899,14 @@ def remove_horizontal_border_strip(self, k):
:class:`Partitions_with_constraints`::
sage: Partition([5,3,1]).remove_horizontal_border_strip(5)
- The subpartitions of [5, 3, 1] obtained by removing an horizontal border strip of length 5
+ The subpartitions of [5, 3, 1] obtained by removing a horizontal border strip of length 5
TESTS::
sage: Partition([3,2,2]).remove_horizontal_border_strip(2).list()
[[3, 2], [2, 2, 1]]
sage: Partition([3,2,2]).remove_horizontal_border_strip(2).first().parent()
- The subpartitions of [3, 2, 2] obtained by removing an horizontal border strip of length 2
+ The subpartitions of [3, 2, 2] obtained by removing a horizontal border strip of length 2
sage: Partition([]).remove_horizontal_border_strip(0).list()
[[]]
sage: Partition([]).remove_horizontal_border_strip(6).list()
@@ -4919,7 +4918,7 @@ def remove_horizontal_border_strip(self, k):
floor=self[1:] + [0],
ceiling=self[:],
max_slope=0,
- name=f"The subpartitions of {self} obtained by removing an horizontal border strip of length {k}")
+ name=f"The subpartitions of {self} obtained by removing a horizontal border strip of length {k}")
def k_conjugate(self, k):
r"""
@@ -5549,9 +5548,9 @@ def simple_module_dimension(self, base_ring=None):
sage: Partition([2,2,1]).simple_module_dimension()
5
- sage: Partition([2,2,1]).specht_module_dimension(GF(3)) # optional - sage.rings.finite_rings
+ sage: Partition([2,2,1]).specht_module_dimension(GF(3)) # needs sage.rings.finite_rings
5
- sage: Partition([2,2,1]).simple_module_dimension(GF(3)) # optional - sage.rings.finite_rings
+ sage: Partition([2,2,1]).simple_module_dimension(GF(3)) # needs sage.rings.finite_rings
4
sage: for la in Partitions(6, regular=3):
@@ -6736,9 +6735,9 @@ def random_element(self, measure='uniform'):
EXAMPLES::
- sage: Partitions(5).random_element() # random # needs sage.libs.flint
+ sage: Partitions(5).random_element() # random # needs sage.libs.flint
[2, 1, 1, 1]
- sage: Partitions(5).random_element(measure='Plancherel') # random # needs sage.libs.flint
+ sage: Partitions(5).random_element(measure='Plancherel') # random # needs sage.libs.flint
[2, 1, 1, 1]
"""
if measure == 'uniform':
@@ -6756,7 +6755,7 @@ def random_element_uniform(self):
sage: Partitions(5).random_element_uniform() # random # needs sage.libs.flint
[2, 1, 1, 1]
- sage: Partitions(20).random_element_uniform() # random # needs sage.libs.flint
+ sage: Partitions(20).random_element_uniform() # random # needs sage.libs.flint
[9, 3, 3, 2, 2, 1]
TESTS::
diff --git a/src/sage/combinat/partition_algebra.py b/src/sage/combinat/partition_algebra.py
index a52fc93c338..b5caf31d84b 100644
--- a/src/sage/combinat/partition_algebra.py
+++ b/src/sage/combinat/partition_algebra.py
@@ -1931,7 +1931,7 @@ def to_set_partition(l, k=None):
if not l:
return Set([])
else:
- k = max((max(map(abs, x)) for x in l))
+ k = max(max(map(abs, x)) for x in l)
to_be_added = Set(list(range(1, k + 1)) + [-x for x in range(1, k + 1)])
diff --git a/src/sage/combinat/partition_kleshchev.py b/src/sage/combinat/partition_kleshchev.py
index 29936e4db39..df8b31b552e 100644
--- a/src/sage/combinat/partition_kleshchev.py
+++ b/src/sage/combinat/partition_kleshchev.py
@@ -861,7 +861,7 @@ def is_restricted(self):
return _is_restricted(self.to_list(), KP._multicharge, KP._convention)
-class KleshchevCrystalMixin():
+class KleshchevCrystalMixin:
"""
Mixin class for the crystal structure of a Kleshchev partition.
"""
diff --git a/src/sage/combinat/perfect_matching.py b/src/sage/combinat/perfect_matching.py
index 70c8652841c..84e481cb621 100644
--- a/src/sage/combinat/perfect_matching.py
+++ b/src/sage/combinat/perfect_matching.py
@@ -215,7 +215,7 @@ def _repr_(self):
sage: PerfectMatching([3,8,1,7,6,5,4,2])
[(1, 3), (2, 8), (4, 7), (5, 6)]
"""
- return '[' + ', '.join(('(' + repr(sorted(x))[1:-1] + ')' for x in self)) + ']'
+ return '[' + ', '.join('(' + repr(sorted(x))[1:-1] + ')' for x in self) + ']'
def _latex_(self):
r"""
diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py
index 3ed9a0a43fd..ba712588cf6 100644
--- a/src/sage/combinat/permutation.py
+++ b/src/sage/combinat/permutation.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Permutations
diff --git a/src/sage/combinat/plane_partition.py b/src/sage/combinat/plane_partition.py
index 21b8bb84334..b4f897b64f3 100644
--- a/src/sage/combinat/plane_partition.py
+++ b/src/sage/combinat/plane_partition.py
@@ -387,9 +387,9 @@ def _repr_diagram(self, show_box=False, use_unicode=False) -> str:
drawing = [[" " for i in range(2 * x + y + z)]
for j in range(y + z + 1)]
- hori = u"_" if use_unicode else "_"
- down = u"╲" if use_unicode else "\\"
- up = u"╱" if use_unicode else "/"
+ hori = "_" if use_unicode else "_"
+ down = "╲" if use_unicode else "\\"
+ up = "╱" if use_unicode else "/"
def superpose(l, c, letter):
# add the given letter at line l and column c
@@ -449,10 +449,10 @@ def add_leftside(i, j, k):
check = False
if not drawing:
- return u"∅" if use_unicode else ""
+ return "∅" if use_unicode else ""
if use_unicode:
- return u'\n'.join(u"".join(row) for row in drawing)
+ return '\n'.join("".join(row) for row in drawing)
return '\n'.join("".join(row) for row in drawing)
def _ascii_art_(self):
@@ -1548,7 +1548,7 @@ def __init__(self, box_size):
EXAMPLES::
sage: PP = PlanePartitions([4,3,2])
- sage: TestSuite(PP).run() # long time, needs sage.modules
+ sage: TestSuite(PP).run() # long time # needs sage.modules
"""
super().__init__(box_size, category=FiniteEnumeratedSets())
diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py
index 8fb9055afdb..6af274fd18a 100644
--- a/src/sage/combinat/posets/lattices.py
+++ b/src/sage/combinat/posets/lattices.py
@@ -2298,8 +2298,8 @@ def is_orthocomplemented(self, unique=False):
sage: D6.is_orthocomplemented(unique=True) # needs sage.groups
False
- sage: hexagon = LatticePoset({0:[1, 2], 1:[3], 2:[4], 3:[5], 4:[5]})
- sage: hexagon.is_orthocomplemented(unique=True)
+ sage: hexagon = LatticePoset({0: [1, 2], 1: [3], 2: [4], 3:[5], 4: [5]})
+ sage: hexagon.is_orthocomplemented(unique=True) # needs sage.groups
True
.. SEEALSO::
@@ -4046,7 +4046,7 @@ def is_subdirectly_reducible(self, certificate=False):
TESTS::
- sage: [posets.ChainPoset(i).is_subdirectly_reducible() for i in range(5)]
+ sage: [posets.ChainPoset(i).is_subdirectly_reducible() for i in range(5)] # needs sage.combinat
[False, False, False, True, True]
"""
H = self._hasse_diagram
@@ -4256,7 +4256,7 @@ def is_constructible_by_doublings(self, type) -> bool:
sage: L = L.day_doubling([(3,0), (1,1), (2,1)]) # An upper pseudo-interval
sage: L.is_constructible_by_doublings('upper')
False
- sage: L.is_constructible_by_doublings('convex')
+ sage: L.is_constructible_by_doublings('convex') # needs sage.combinat
True
An example of a lattice that can be constructed by doublings
@@ -4378,18 +4378,20 @@ def is_isoform(self, certificate=False):
EXAMPLES::
- sage: L = LatticePoset({1:[2, 3, 4], 2: [5, 6], 3: [6, 7], 4: [7], 5: [8], 6: [8], 7: [8]})
- sage: L.is_isoform()
+ sage: L = LatticePoset({1: [2, 3, 4], 2: [5, 6], 3: [6, 7],
+ ....: 4: [7], 5: [8], 6: [8], 7: [8]})
+ sage: L.is_isoform() # needs sage.combinat
True
Every isoform lattice is (trivially) uniform, but the converse is
not true::
- sage: L = LatticePoset({1: [2, 3, 6], 2: [4, 5], 3: [5], 4: [9, 8], 5: [7, 8], 6: [9], 7: [10], 8: [10], 9: [10]})
- sage: L.is_isoform(), L.is_uniform()
+ sage: L = LatticePoset({1: [2, 3, 6], 2: [4, 5], 3: [5], 4: [9, 8],
+ ....: 5: [7, 8], 6: [9], 7: [10], 8: [10], 9: [10]})
+ sage: L.is_isoform(), L.is_uniform() # needs sage.combinat
(False, True)
- sage: L.is_isoform(certificate=True)
+ sage: L.is_isoform(certificate=True) # needs sage.combinat
(False, {{1, 2, 4, 6, 9}, {3, 5, 7, 8, 10}})
.. SEEALSO::
@@ -4404,7 +4406,7 @@ def is_isoform(self, certificate=False):
sage: [posets.ChainPoset(i).is_isoform() for i in range(5)]
[True, True, True, False, False]
- sage: posets.DiamondPoset(5).is_isoform() # Simple, so trivially isoform
+ sage: posets.DiamondPoset(5).is_isoform() # Simple, so trivially isoform # needs sage.combinat
True
"""
ok = (True, None) if certificate else True
@@ -4451,8 +4453,9 @@ def is_uniform(self, certificate=False):
EXAMPLES::
- sage: L = LatticePoset({1: [2, 3, 4], 2: [6, 7], 3: [5], 4: [5], 5: [9, 8], 6: [9], 7: [10], 8: [10], 9: [10]})
- sage: L.is_uniform()
+ sage: L = LatticePoset({1: [2, 3, 4], 2: [6, 7], 3: [5], 4: [5],
+ ....: 5: [9, 8], 6: [9], 7: [10], 8: [10], 9: [10]})
+ sage: L.is_uniform() # needs sage.combinat
True
Every uniform lattice is regular, but the converse is not true::
@@ -4461,7 +4464,7 @@ def is_uniform(self, certificate=False):
sage: N6.is_uniform(), N6.is_regular()
(False, True)
- sage: N6.is_uniform(certificate=True)
+ sage: N6.is_uniform(certificate=True) # needs sage.combinat
(False, {{1, 2, 3, 4}, {5, 6}})
.. SEEALSO::
@@ -4475,7 +4478,7 @@ def is_uniform(self, certificate=False):
sage: [posets.ChainPoset(i).is_uniform() for i in range(5)]
[True, True, True, False, False]
- sage: posets.DiamondPoset(5).is_uniform() # Simple, so trivially uniform
+ sage: posets.DiamondPoset(5).is_uniform() # Simple, so trivially uniform # needs sage.combinat
True
"""
ok = (True, None) if certificate else True
@@ -4532,14 +4535,15 @@ def is_regular(self, certificate=False):
EXAMPLES::
- sage: L = LatticePoset({1: [2, 3, 4], 2: [5, 6], 3: [8, 7], 4: [6, 7], 5: [8], 6: [9], 7: [9], 8: [9]})
- sage: L.is_regular()
+ sage: L = LatticePoset({1: [2, 3, 4], 2: [5, 6], 3: [8, 7], 4: [6, 7],
+ ....: 5: [8], 6: [9], 7: [9], 8: [9]})
+ sage: L.is_regular() # needs sage.combinat
True
sage: N5 = posets.PentagonPoset()
- sage: N5.is_regular()
+ sage: N5.is_regular() # needs sage.combinat
False
- sage: N5.is_regular(certificate=True)
+ sage: N5.is_regular(certificate=True) # needs sage.combinat
(False, ({{0}, {1}, {2, 3}, {4}}, [0]))
.. SEEALSO::
@@ -4552,7 +4556,7 @@ def is_regular(self, certificate=False):
TESTS::
- sage: [posets.ChainPoset(i).is_regular() for i in range(5)]
+ sage: [posets.ChainPoset(i).is_regular() for i in range(5)] # needs sage.combinat
[True, True, True, False, False]
"""
ok = (True, None) if certificate else True
@@ -4598,6 +4602,7 @@ def is_simple(self, certificate=False):
EXAMPLES::
+ sage: # needs sage.combinat
sage: posets.DiamondPoset(5).is_simple() # Smallest nontrivial example
True
sage: L = LatticePoset({1: [2, 3], 2: [4, 5], 3: [6], 4: [6], 5: [6]})
@@ -4611,11 +4616,11 @@ def is_simple(self, certificate=False):
sage: L = LatticePoset({1: [2, 3, 4], 2: [5], 3: [5], 4: [6, 7],
....: 5: [8], 6: [8], 7: [8]})
- sage: L.is_simple()
+ sage: L.is_simple() # needs sage.combinat
False
sage: L = LatticePoset({1: [2, 3], 2: [4, 5], 3: [6, 7], 4: [8],
....: 5: [8], 6: [8], 7: [8]})
- sage: L.is_simple()
+ sage: L.is_simple() # needs sage.combinat
True
.. SEEALSO::
@@ -4652,9 +4657,10 @@ def subdirect_decomposition(self):
EXAMPLES::
- sage: posets.ChainPoset(3).subdirect_decomposition()
+ sage: posets.ChainPoset(3).subdirect_decomposition() # needs sage.combinat
[Finite lattice containing 2 elements, Finite lattice containing 2 elements]
+ sage: # needs sage.combinat
sage: L = LatticePoset({1: [2, 4], 2: [3], 3: [6, 7], 4: [5, 7],
....: 5: [9, 8], 6: [9], 7: [9], 8: [10], 9: [10]})
sage: Ldecomp = L.subdirect_decomposition()
@@ -4665,6 +4671,7 @@ def subdirect_decomposition(self):
TESTS::
+ sage: # needs sage.combinat
sage: posets.ChainPoset(0).subdirect_decomposition()
[Finite lattice containing 0 elements]
sage: posets.ChainPoset(1).subdirect_decomposition()
@@ -4676,7 +4683,7 @@ def subdirect_decomposition(self):
has only one element::
sage: N5 = posets.PentagonPoset()
- sage: N5.subdirect_decomposition()
+ sage: N5.subdirect_decomposition() # needs sage.combinat
[Finite lattice containing 5 elements]
"""
H = self._hasse_diagram
@@ -4737,6 +4744,7 @@ def congruence(self, S):
EXAMPLES::
+ sage: # needs sage.combinat
sage: L = posets.DivisorLattice(12)
sage: cong = L.congruence([[1, 3]])
sage: sorted(sorted(c) for c in cong)
@@ -4745,19 +4753,20 @@ def congruence(self, S):
{{1, 2, 4}, {3, 6, 12}}
sage: L = LatticePoset({1: [2, 3], 2: [4], 3: [4], 4: [5]})
- sage: L.congruence([[1, 2]])
+ sage: L.congruence([[1, 2]]) # needs sage.combinat
{{1, 2}, {3, 4}, {5}}
sage: L = LatticePoset({1: [2, 3], 2: [4, 5, 6], 4: [5], 5: [7, 8],
....: 6: [8], 3: [9], 7: [10], 8: [10], 9:[10]})
- sage: cong = L.congruence([[1, 2]])
- sage: cong[0]
+ sage: cong = L.congruence([[1, 2]]) # needs sage.combinat
+ sage: cong[0] # needs sage.combinat
frozenset({1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
.. SEEALSO:: :meth:`quotient`
TESTS::
+ sage: # needs sage.combinat
sage: P = posets.PentagonPoset()
sage: P.congruence([])
{{0}, {1}, {2}, {3}, {4}}
@@ -4774,13 +4783,13 @@ def congruence(self, S):
works::
sage: L = LatticePoset(DiGraph('P^??@_?@??B_?@??B??@_?@??B_?@??B??@??A??C??G??O???'))
- sage: sorted(sorted(p) for p in L.congruence([[1,6]]))
+ sage: sorted(sorted(p) for p in L.congruence([[1,6]])) # needs sage.combinat
[[0], [1, 6], [2], [3, 8], [4], [5, 10], [7, 12], [9, 14], [11], [13], [15], [16]]
Simple lattice, i.e. a lattice without any nontrivial congruence::
sage: L = LatticePoset(DiGraph('GPb_@?OC@?O?'))
- sage: L.congruence([[1,2]])
+ sage: L.congruence([[1,2]]) # needs sage.combinat
{{0, 1, 2, 3, 4, 5, 6, 7}}
"""
from sage.combinat.set_partition import SetPartition
@@ -4821,6 +4830,7 @@ def quotient(self, congruence, labels='tuple'):
EXAMPLES::
+ sage: # needs sage.combinat
sage: L = posets.PentagonPoset()
sage: c = L.congruence([[0, 1]])
sage: I = L.quotient(c); I
@@ -4831,6 +4841,7 @@ def quotient(self, congruence, labels='tuple'):
sage: I.top()
Finite lattice containing 3 elements
+ sage: # needs sage.combinat
sage: B3 = posets.BooleanLattice(3)
sage: c = B3.congruence([[0,1]])
sage: B2 = B3.quotient(c, labels='integer')
@@ -4846,7 +4857,7 @@ def quotient(self, congruence, labels='tuple'):
Finite lattice containing 0 elements
sage: L = posets.PentagonPoset()
- sage: L.quotient(L.congruence([[1]])).is_isomorphic(L)
+ sage: L.quotient(L.congruence([[1]])).is_isomorphic(L) # needs sage.combinat
True
"""
if labels not in ['lattice', 'tuple', 'integer']:
@@ -4894,6 +4905,7 @@ def congruences_lattice(self, labels='congruence'):
EXAMPLES::
+ sage: # needs sage.combinat
sage: N5 = posets.PentagonPoset()
sage: CL = N5.congruences_lattice(); CL
Finite lattice containing 5 elements
@@ -4903,12 +4915,13 @@ def congruences_lattice(self, labels='congruence'):
[{{0, 1}, {2, 3, 4}}, {{0, 2, 3}, {1, 4}}]
sage: C4 = posets.ChainPoset(4)
- sage: CL = C4.congruences_lattice(labels='integer')
- sage: CL.is_isomorphic(posets.BooleanLattice(3))
+ sage: CL = C4.congruences_lattice(labels='integer') # needs sage.combinat
+ sage: CL.is_isomorphic(posets.BooleanLattice(3)) # needs sage.combinat
True
TESTS::
+ sage: # needs sage.combinat
sage: posets.ChainPoset(0).congruences_lattice()
Finite lattice containing 1 elements
sage: posets.ChainPoset(1).congruences_lattice()
@@ -5002,6 +5015,7 @@ def feichtner_yuzvinsky_ring(self, G, use_defining=False, base_ring=None):
We reproduce the example from Section 5 of [Coron2023]_::
+ sage: # needs sage.geometry.polyhedron
sage: H. = HyperplaneArrangements(QQ)
sage: Arr = H(a-b, b-c, c-d, d-a)
sage: P = LatticePoset(Arr.intersection_poset())
diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py
index 47792a7118f..cca9b098d4a 100644
--- a/src/sage/combinat/posets/linear_extensions.py
+++ b/src/sage/combinat/posets/linear_extensions.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Linear Extensions of Posets
diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py
index f8d10257c1f..0a8352274ee 100644
--- a/src/sage/combinat/posets/posets.py
+++ b/src/sage/combinat/posets/posets.py
@@ -3745,9 +3745,9 @@ def magnitude(self) -> Integer:
sage: P.magnitude() == m1*m2
True
- sage: Poset({}).magnitude()
+ sage: Poset({}).magnitude() # needs sage.libs.flint
0
- sage: Poset({1:[]}).magnitude()
+ sage: Poset({1: []}).magnitude() # needs sage.libs.flint
1
"""
H = self._hasse_diagram
@@ -4314,7 +4314,7 @@ def coxeter_transformation(self):
EXAMPLES::
- sage: posets.PentagonPoset().coxeter_transformation()
+ sage: posets.PentagonPoset().coxeter_transformation() # needs sage.libs.flint
[ 0 0 0 0 -1]
[ 0 0 0 1 -1]
[ 0 1 0 0 -1]
@@ -4327,8 +4327,8 @@ def coxeter_transformation(self):
TESTS::
- sage: M = posets.PentagonPoset().coxeter_transformation()
- sage: M ** 8 == 1
+ sage: M = posets.PentagonPoset().coxeter_transformation() # needs sage.libs.flint
+ sage: M ** 8 == 1 # needs sage.libs.flint
True
"""
return self._hasse_diagram.coxeter_transformation()
@@ -4348,11 +4348,11 @@ def coxeter_polynomial(self):
EXAMPLES::
sage: P = posets.PentagonPoset()
- sage: P.coxeter_polynomial()
+ sage: P.coxeter_polynomial() # needs sage.libs.flint
x^5 + x^4 + x + 1
sage: p = posets.SymmetricGroupWeakOrderPoset(3) # needs sage.groups
- sage: p.coxeter_polynomial() # needs sage.groups
+ sage: p.coxeter_polynomial() # needs sage.groups sage.libs.flint
x^6 + x^5 - x^3 + x + 1
.. SEEALSO::
@@ -4398,7 +4398,7 @@ def coxeter_smith_form(self, algorithm='singular'):
TESTS::
sage: P = posets.PentagonPoset()
- sage: P.coxeter_smith_form(algorithm='sage')
+ sage: P.coxeter_smith_form(algorithm='sage') # needs sage.libs.flint
[1, 1, 1, 1, x^5 + x^4 + x + 1]
sage: P.coxeter_smith_form(algorithm='gap') # needs sage.libs.gap
[1, 1, 1, 1, x^5 + x^4 + x + 1]
@@ -8099,33 +8099,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()
+ sage: P.is_eulerian() # needs sage.libs.flint
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()
+ sage: P.is_eulerian() # needs sage.libs.flint
False
Canonical examples of Eulerian posets are the face lattices of
convex polytopes::
sage: P = polytopes.cube().face_lattice() # needs sage.geometry.polyhedron
- sage: P.is_eulerian() # needs sage.geometry.polyhedron
+ sage: P.is_eulerian() # needs sage.geometry.polyhedron sage.libs.flint
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)
+ sage: P.is_eulerian(k=3) # needs sage.libs.flint
True
- sage: P.is_eulerian(k=4)
+ sage: P.is_eulerian(k=4) # needs sage.libs.flint
False
Getting an interval that is not Eulerian::
sage: P = posets.DivisorLattice(12)
- sage: P.is_eulerian(certificate=True)
+ sage: P.is_eulerian(certificate=True) # needs sage.libs.flint
(False, (1, 4))
TESTS::
@@ -8143,7 +8143,7 @@ def is_eulerian(self, k=None, certificate=False):
...
ValueError: the poset is not graded
- sage: posets.BooleanLattice(3).is_eulerian(k=123, certificate=True)
+ sage: posets.BooleanLattice(3).is_eulerian(k=123, certificate=True) # needs sage.libs.flint
(True, None)
"""
if k is not None:
diff --git a/src/sage/combinat/q_analogues.py b/src/sage/combinat/q_analogues.py
index 358b60ff322..bf346f03ad5 100644
--- a/src/sage/combinat/q_analogues.py
+++ b/src/sage/combinat/q_analogues.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
`q`-Analogues
"""
diff --git a/src/sage/combinat/ranker.py b/src/sage/combinat/ranker.py
index c370800bf22..1d51b8a04d2 100644
--- a/src/sage/combinat/ranker.py
+++ b/src/sage/combinat/ranker.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Rankers
"""
diff --git a/src/sage/combinat/recognizable_series.py b/src/sage/combinat/recognizable_series.py
index 173e061276b..161a7e05ec4 100644
--- a/src/sage/combinat/recognizable_series.py
+++ b/src/sage/combinat/recognizable_series.py
@@ -70,7 +70,7 @@
from sage.structure.unique_representation import UniqueRepresentation
-class PrefixClosedSet():
+class PrefixClosedSet:
def __init__(self, words):
r"""
A prefix-closed set.
diff --git a/src/sage/combinat/regular_sequence.py b/src/sage/combinat/regular_sequence.py
index c585e51e194..a2d5c09d94b 100644
--- a/src/sage/combinat/regular_sequence.py
+++ b/src/sage/combinat/regular_sequence.py
@@ -2337,7 +2337,7 @@ def from_recurrence(self, *args, **kwds):
return self(mu, left, right)
-class RecurrenceParser():
+class RecurrenceParser:
r"""
A parser for recurrence relations that allow
the construction of a `k`-linear representation
diff --git a/src/sage/combinat/rigged_configurations/rigged_partition.pyx b/src/sage/combinat/rigged_configurations/rigged_partition.pyx
index 5b30b15608f..98a9047d6c9 100644
--- a/src/sage/combinat/rigged_configurations/rigged_partition.pyx
+++ b/src/sage/combinat/rigged_configurations/rigged_partition.pyx
@@ -7,7 +7,7 @@ configuration class. This is an internal class used by the rigged
configurations and KR tableaux during the bijection, and is not to be used by
the end-user.
-We hold the partitions as an 1-dim array of positive integers where each
+We hold the partitions as a 1-dim array of positive integers where each
value corresponds to the length of the row. This is the shape of the
partition which can be accessed by the regular index.
diff --git a/src/sage/combinat/root_system/ambient_space.py b/src/sage/combinat/root_system/ambient_space.py
index c9696b98fdb..a8aa765ee5d 100644
--- a/src/sage/combinat/root_system/ambient_space.py
+++ b/src/sage/combinat/root_system/ambient_space.py
@@ -55,9 +55,10 @@ class AmbientSpace(CombinatorialFreeModule):
TESTS::
- sage: types = CartanType.samples(crystallographic = True)+[CartanType(["A",2],["C",5])]
+ sage: # needs sage.libs.gap
+ sage: types = CartanType.samples(crystallographic=True) + [CartanType(["A",2],["C",5])]
sage: for e in [ct.root_system().ambient_space() for ct in types]:
- ....: TestSuite(e).run()
+ ....: TestSuite(e).run()
sage: e1 = RootSystem(['A',3]).ambient_lattice()
sage: e2 = RootSystem(['B',3]).ambient_lattice()
diff --git a/src/sage/combinat/root_system/associahedron.py b/src/sage/combinat/root_system/associahedron.py
index 24140007081..448b1009036 100644
--- a/src/sage/combinat/root_system/associahedron.py
+++ b/src/sage/combinat/root_system/associahedron.py
@@ -129,7 +129,7 @@ def Associahedron(cartan_type, backend='ppl'):
return parent(cartan_type)
-class Associahedron_class_base():
+class Associahedron_class_base:
r"""
The base class of the Python class of an associahedron
@@ -321,7 +321,7 @@ def Associahedra(base_ring, ambient_dim, backend='ppl'):
raise ValueError("unknown backend")
-class Associahedra_base():
+class Associahedra_base:
"""
Base class of parent of Associahedra of specified dimension
diff --git a/src/sage/combinat/root_system/braid_move_calculator.py b/src/sage/combinat/root_system/braid_move_calculator.py
index e932662bd5d..38931a00229 100644
--- a/src/sage/combinat/root_system/braid_move_calculator.py
+++ b/src/sage/combinat/root_system/braid_move_calculator.py
@@ -19,7 +19,7 @@
from sage.misc.cachefunc import cached_method
-class BraidMoveCalculator():
+class BraidMoveCalculator:
"""
Helper class to compute braid moves.
"""
diff --git a/src/sage/combinat/root_system/cartan_matrix.py b/src/sage/combinat/root_system/cartan_matrix.py
index c1ce04fba38..8019029d62a 100644
--- a/src/sage/combinat/root_system/cartan_matrix.py
+++ b/src/sage/combinat/root_system/cartan_matrix.py
@@ -452,7 +452,7 @@ def reflection_group(self, type="matrix"):
EXAMPLES::
sage: C = CartanMatrix(['A',3]) # needs sage.graphs
- sage: C.reflection_group() # needs sage.graphs
+ sage: C.reflection_group() # needs sage.graphs sage.libs.gap
Weyl Group of type ['A', 3] (as a matrix group acting on the root space)
"""
RS = self.root_space()
@@ -589,7 +589,7 @@ def subtype(self, index_set):
"""
ind = self.index_set()
I = [ind.index(i) for i in index_set]
- return CartanMatrix(self.matrix_from_rows_and_columns(I, I), index_set)
+ return CartanMatrix(self.matrix_from_rows_and_columns(I, I), index_set=index_set)
def rank(self):
r"""
@@ -1135,13 +1135,39 @@ def find_cartan_type_from_matrix(CM):
['C', 3] relabelled by {1: 0, 2: 1, 3: 2}
sage: CM = CartanMatrix([[2,-1,-2], [-1,2,-1], [-2,-1,2]])
sage: find_cartan_type_from_matrix(CM)
+
+ TESTS:
+
+ Check that :issue:`35987` is fixed::
+
+ sage: from sage.combinat.root_system.cartan_matrix import find_cartan_type_from_matrix
+ sage: cm = CartanMatrix(['A',7]).subtype([2,3,5])
+ sage: find_cartan_type_from_matrix(cm)
+ A2xA1 relabelled by {1: 2, 2: 3, 3: 5}
+
+ sage: cm = CartanMatrix(['B',10,1]).subtype([0,1,2,3,5,6,8,9,10])
+ sage: ct = find_cartan_type_from_matrix(cm); ct
+ D4xB3xA2 relabelled by {1: 0, 2: 2, 3: 1, 4: 3, 5: 8, 6: 9, 7: 10, 8: 5, 9: 6}
+ sage: ct.dynkin_diagram()
+ O 3
+ |
+ |
+ O---O---O
+ 0 2 1
+ O---O=>=O
+ 8 9 10
+ O---O
+ 5 6
+ D4xB3xA2 relabelled by {1: 0, 2: 2, 3: 1, 4: 3, 5: 8, 6: 9, 7: 10, 8: 5, 9: 6}
"""
types = []
+ relabel = []
for S in CM.dynkin_diagram().connected_components_subgraphs():
S = DiGraph(S) # We need a simple digraph here
n = S.num_verts()
# Build the list to test based upon rank
if n == 1:
+ relabel.append({1: S.vertices()[0]})
types.append(CartanType(['A', 1]))
continue
@@ -1178,7 +1204,8 @@ def find_cartan_type_from_matrix(CM):
T = DiGraph(ct.dynkin_diagram()) # We need a simple digraph here
iso, match = T.is_isomorphic(S, certificate=True, edge_labels=True)
if iso:
- types.append(ct.relabel(match))
+ types.append(ct)
+ relabel.append(match)
found = True
break
@@ -1189,10 +1216,20 @@ def find_cartan_type_from_matrix(CM):
T = DiGraph(ct.dynkin_diagram()) # We need a simple digraph here
iso, match = T.is_isomorphic(S, certificate=True, edge_labels=True)
if iso:
- types.append(ct.relabel(match))
+ types.append(ct)
+ relabel.append(match)
found = True
break
if not found:
return None
- return CartanType(types)
+ if len(types) == 1:
+ # Irreducible, so just relabel
+ return CartanType(types[0]).relabel(relabel[0])
+ ct = CartanType(types)
+ # ct._index_relabelling is a dict ``(ind, j): i``, where i is an index of
+ # ``ct``, ``ind`` is the position in the list of types, and j is the
+ # corresponding index of the type number ``ind``.
+ # In other words, the j-th node of ``types[ind]`` is the i-th node of ``ct``.
+ mapping = {i: relabel[d[0]][d[1]] for d, i in ct._index_relabelling.items()}
+ return ct.relabel(mapping)
diff --git a/src/sage/combinat/root_system/cartan_type.py b/src/sage/combinat/root_system/cartan_type.py
index 816fbadcd57..bd7ab5cdda4 100644
--- a/src/sage/combinat/root_system/cartan_type.py
+++ b/src/sage/combinat/root_system/cartan_type.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Cartan types
@@ -603,7 +602,7 @@ def __call__(self, *args):
return CartanType(t[:-1]).dual()
elif t[-1] == "~":
return CartanType(t[:-1]).affine()
- elif t in ["Aoo", u"A∞"]:
+ elif t in ["Aoo", "A∞"]:
return CartanType(['A', Infinity])
elif t == "A+oo":
from . import type_A_infinity
@@ -974,7 +973,7 @@ class options(GlobalOptions):
CartanType.__doc__ = __doc__
-class CartanType_abstract():
+class CartanType_abstract:
r"""
Abstract class for Cartan types
@@ -1438,7 +1437,7 @@ def is_implemented(self):
EXAMPLES::
- sage: CartanType(["A",4,1]).is_implemented()
+ sage: CartanType(["A",4,1]).is_implemented() # needs sage.graphs
True
sage: CartanType(['H',3]).is_implemented()
True
@@ -3075,7 +3074,7 @@ def __getitem__(self, i):
# For backward compatibility
-class CartanType_simple_finite():
+class CartanType_simple_finite:
def __setstate__(self, dict):
"""
Implements the unpickling of Cartan types pickled by Sage <= 4.0.
diff --git a/src/sage/combinat/root_system/coxeter_group.py b/src/sage/combinat/root_system/coxeter_group.py
index 8fadad6035c..012daffdf87 100644
--- a/src/sage/combinat/root_system/coxeter_group.py
+++ b/src/sage/combinat/root_system/coxeter_group.py
@@ -86,7 +86,7 @@ def CoxeterGroup(data, implementation="reflection", base_ring=None, index_set=No
[3 1 5]
[2 5 1]
- sage: W = CoxeterGroup(["H",3], implementation="reflection"); W # needs sage.rings.number_field
+ sage: W = CoxeterGroup(["H",3], implementation="reflection"); W # needs sage.libs.gap sage.rings.number_field
Finite Coxeter group over Number Field in a with defining polynomial x^2 - 5
with a = 2.236067977499790? with Coxeter matrix:
[1 3 2]
@@ -116,7 +116,7 @@ def CoxeterGroup(data, implementation="reflection", base_ring=None, index_set=No
TESTS::
- sage: W = groups.misc.CoxeterGroup(["H",3]) # needs sage.groups
+ sage: W = groups.misc.CoxeterGroup(["H",3]) # needs sage.graphs sage.groups
"""
if implementation not in ["permutation", "matrix", "coxeter3", "reflection", "chevie", None]:
raise ValueError("invalid type implementation")
diff --git a/src/sage/combinat/root_system/coxeter_matrix.py b/src/sage/combinat/root_system/coxeter_matrix.py
index 719d23c3409..57e6030b9c4 100644
--- a/src/sage/combinat/root_system/coxeter_matrix.py
+++ b/src/sage/combinat/root_system/coxeter_matrix.py
@@ -850,6 +850,7 @@ def bilinear_form(self, R=None):
EXAMPLES::
+ sage: # needs sage.libs.gap
sage: CoxeterType(['A', 2, 1]).bilinear_form()
[ 1 -1/2 -1/2]
[-1/2 1 -1/2]
diff --git a/src/sage/combinat/root_system/coxeter_type.py b/src/sage/combinat/root_system/coxeter_type.py
index ef1d4beb922..88a53e4bd98 100644
--- a/src/sage/combinat/root_system/coxeter_type.py
+++ b/src/sage/combinat/root_system/coxeter_type.py
@@ -357,7 +357,7 @@ def bilinear_form(self, R=None):
EXAMPLES::
- sage: # needs sage.graphs sage.rings.number_field
+ sage: # needs sage.graphs sage.libs.gap
sage: CoxeterType(['A', 2, 1]).bilinear_form()
[ 1 -1/2 -1/2]
[-1/2 1 -1/2]
diff --git a/src/sage/combinat/root_system/fundamental_group.py b/src/sage/combinat/root_system/fundamental_group.py
index 65426b786e3..8905471a5ab 100644
--- a/src/sage/combinat/root_system/fundamental_group.py
+++ b/src/sage/combinat/root_system/fundamental_group.py
@@ -1,4 +1,4 @@
-# sage.doctest: needs sage.graphs
+# sage.doctest: needs sage.graphs sage.groups
r"""
Fundamental Group of an Extended Affine Weyl Group
diff --git a/src/sage/combinat/root_system/integrable_representations.py b/src/sage/combinat/root_system/integrable_representations.py
index 0278617a2e5..a1cb764e19a 100644
--- a/src/sage/combinat/root_system/integrable_representations.py
+++ b/src/sage/combinat/root_system/integrable_representations.py
@@ -426,7 +426,7 @@ def _inner_pq(self, pelt, qelt):
def _inner_pp(self, pelt1, pelt2):
"""
- Symmetric form between an two elements of the weight lattice
+ Symmetric form between two elements of the weight lattice
associated to ``self``.
EXAMPLES::
@@ -860,21 +860,22 @@ def mult(self, mu):
EXAMPLES::
+ sage: # needs sage.libs.gap
sage: L = RootSystem("B3~").weight_lattice(extended=True)
sage: Lambda = L.fundamental_weights()
sage: delta = L.null_root()
sage: W = L.weyl_group(prefix="s")
sage: [s0,s1,s2,s3] = W.simple_reflections()
sage: V = IntegrableRepresentation(Lambda[0])
- sage: V.mult(Lambda[2]-2*delta)
+ sage: V.mult(Lambda[2] - 2*delta)
3
- sage: V.mult(Lambda[2]-Lambda[1])
+ sage: V.mult(Lambda[2] - Lambda[1])
0
- sage: weights = [w.action(Lambda[1]-4*delta) for w in [s1,s2,s0*s1*s2*s3]]
+ sage: weights = [w.action(Lambda[1] - 4*delta) for w in [s1,s2,s0*s1*s2*s3]]
sage: weights
[-Lambda[1] + Lambda[2] - 4*delta,
- Lambda[1] - 4*delta,
- -Lambda[1] + Lambda[2] - 4*delta]
+ Lambda[1] - 4*delta,
+ -Lambda[1] + Lambda[2] - 4*delta]
sage: [V.mult(mu) for mu in weights]
[35, 35, 35]
@@ -1093,7 +1094,7 @@ def branch(self, i=None, weyl_character_ring=None, sequence=None, depth=5):
sage: Lambda = RootSystem(['A',2,1]).weight_lattice(extended=true).fundamental_weights()
sage: V = IntegrableRepresentation(2*Lambda[0])
- sage: b = V.branch(); b
+ sage: b = V.branch(); b # needs sage.libs.gap
[A2(0,0),
A2(1,1),
A2(0,0) + 2*A2(1,1) + A2(2,2),
@@ -1104,7 +1105,7 @@ def branch(self, i=None, weyl_character_ring=None, sequence=None, depth=5):
If the parameter ``weyl_character_ring`` is omitted, the ring may be recovered
as the parent of one of the branched coefficients::
- sage: A2 = b[0].parent(); A2
+ sage: A2 = b[0].parent(); A2 # needs sage.libs.gap
The Weyl Character Ring of Type A2 with Integer Ring coefficients
If `i` is not zero then you should specify the :class:`WeylCharacterRing` that you
@@ -1125,8 +1126,8 @@ def branch(self, i=None, weyl_character_ring=None, sequence=None, depth=5):
Thus we have a branching to
`\mathfrak{sl}(2) \times \mathfrak{sl}(2) \times \mathfrak{sl}(2)`::
- sage: A1xA1xA1 = WeylCharacterRing("A1xA1xA1",style="coroots")
- sage: V.branch(i=2,weyl_character_ring=A1xA1xA1)
+ sage: A1xA1xA1 = WeylCharacterRing("A1xA1xA1",style="coroots") # needs sage.libs.gap
+ sage: V.branch(i=2,weyl_character_ring=A1xA1xA1) # needs sage.libs.gap
[A1xA1xA1(1,0,0),
A1xA1xA1(0,1,2),
A1xA1xA1(1,0,0) + A1xA1xA1(1,2,0) + A1xA1xA1(1,0,2),
@@ -1159,7 +1160,7 @@ def branch(self, i=None, weyl_character_ring=None, sequence=None, depth=5):
The nodes `0, 2, 3, 4` of ``F4~`` correspond to ``1, 4, 3, 2``
of ``A1xC3`` and so we encode this in a dictionary::
- sage: V.branch(i=1,weyl_character_ring=A1xC3,sequence={0:1,2:4,3:3,4:2}) # long time
+ sage: V.branch(i=1, weyl_character_ring=A1xC3, sequence={0:1,2:4,3:3,4:2}) # long time
[A1xC3(1,0,0,0),
A1xC3(0,0,0,1),
A1xC3(1,0,0,0) + A1xC3(1,2,0,0),
diff --git a/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py b/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py
index a29b26fdde3..34e7e0817f1 100644
--- a/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py
+++ b/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py
@@ -72,7 +72,7 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors):
Here is the nonsymmetric Macdonald polynomial with leading term
`[2,0,1]`::
- sage: E[L0([2,0,1])]
+ sage: E[L0([2,0,1])] # needs sage.libs.gap
((-q*q1-q*q2)/(-q*q1-q2))*B[(1, 1, 1)]
+ ((-q1-q2)/(-q*q1-q2))*B[(2, 1, 0)] + B[(2, 0, 1)]
@@ -92,7 +92,7 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors):
sage: q,t = K.gens()
sage: E = NonSymmetricMacdonaldPolynomials(["A",2,1], q=q, q1=t, q2=-1)
sage: vars = K['x0,x1,x2'].gens()
- sage: E[L0([2,0,1])].expand(vars)
+ sage: E[L0([2,0,1])].expand(vars) # needs sage.libs.gap
(t - 1)/(q*t - 1)*x0^2*x1 + x0^2*x2 + (q*t - q)/(q*t - 1)*x0*x1*x2
sage: from sage.combinat.sf.ns_macdonald import E # needs sage.combinat
@@ -104,7 +104,7 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors):
sage: E = NonSymmetricMacdonaldPolynomials(["G",2,1])
sage: L0 = E.keys()
sage: omega = L0.fundamental_weights()
- sage: E[ omega[2]-omega[1] ]
+ sage: E[omega[2] - omega[1]]
((-q*q1^3*q2-q*q1^2*q2^2)/(q*q1^4-q2^4))*B[(0, 0, 0)]
+ B[(1, -1, 0)] + ((-q1*q2^3-q2^4)/(q*q1^4-q2^4))*B[(1, 0, -1)]
@@ -1684,7 +1684,7 @@ def __getitem__(self, mu):
...
ValueError: 1/2*e[0] + 1/2*e[1] does not lift to a level 0 element
of the affine weight lattice
- sage: E[2*omega[2]]
+ sage: E[2*omega[2]] # needs sage.libs.gap
((q^2*q1^2+q^2*q1*q2)/(q^2*q1^2-q2^2))*B[(0, 0)]
+ ((-q^2*q1^2-q^2*q1*q2)/(-q^2*q1^2+q2^2))*B[(1, 0)] + B[(1, 1)]
+ ((-q^2*q1^2-q^2*q1*q2)/(-q^2*q1^2+q2^2))*B[(0, 1)]
@@ -1751,7 +1751,7 @@ def eigenvalue_experimental(self, mu, l):
sage: KL = RootSystem(["A",1,1]).ambient_space().algebra(K)
sage: E = NonSymmetricMacdonaldPolynomials(KL,q, q1, q2)
sage: L0 = E.keys()
- sage: E.eigenvalues(L0([0,0])) # Checked by hand by Mark and Arun
+ sage: E.eigenvalues(L0([0,0])) # Checked by hand by Mark and Arun # needs sage.libs.gap
[1/(q*t), t]
sage: alpha = E.Y().keys().simple_roots()
sage: E.eigenvalue_experimental(L0([0,0]), alpha[0]) # todo: not implemented
@@ -1761,6 +1761,7 @@ def eigenvalue_experimental(self, mu, l):
Some examples of eigenvalues (not mathematically checked!!!)::
+ sage: # needs sage.libs.gap
sage: E.eigenvalues(L0([1,0]))
[t, 1/(q*t)]
sage: E.eigenvalues(L0([0,1]))
@@ -1880,13 +1881,13 @@ def symmetric_macdonald_polynomial(self, mu):
sage: q,v,t = K.gens()
sage: E = NonSymmetricMacdonaldPolynomials(['A',2,1], q, v, -1/v)
sage: om = E.L0().fundamental_weights()
- sage: E.symmetric_macdonald_polynomial(om[2])
+ sage: E.symmetric_macdonald_polynomial(om[2]) # needs sage.libs.gap
B[(1, 1, 0)] + B[(1, 0, 1)] + B[(0, 1, 1)]
- sage: E.symmetric_macdonald_polynomial(2*om[1])
+ sage: E.symmetric_macdonald_polynomial(2*om[1]) # needs sage.libs.gap
((q*v^2+v^2-q-1)/(q*v^2-1))*B[(1, 1, 0)]
+ ((q*v^2+v^2-q-1)/(q*v^2-1))*B[(1, 0, 1)] + B[(2, 0, 0)]
+ ((q*v^2+v^2-q-1)/(q*v^2-1))*B[(0, 1, 1)] + B[(0, 2, 0)] + B[(0, 0, 2)]
- sage: f = E.symmetric_macdonald_polynomial(E.L0()((2,1,0))); f
+ sage: f = E.symmetric_macdonald_polynomial(E.L0()((2,1,0))); f # needs sage.libs.gap
((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(1, 1, 1)] + B[(1, 2, 0)]
+ B[(1, 0, 2)] + B[(2, 1, 0)] + B[(2, 0, 1)] + B[(0, 1, 2)] + B[(0, 2, 1)]
@@ -1899,11 +1900,11 @@ def symmetric_macdonald_polynomial(self, mu):
x0^2*x1 + x0*x1^2 + x0^2*x2
+ (2*q*t^2 - q*t - q + t^2 + t - 2)/(q*t^2 - 1)*x0*x1*x2
+ x1^2*x2 + x0*x2^2 + x1*x2^2
- sage: fe = f.expand(g.parent().gens()); fe
+ sage: fe = f.expand(g.parent().gens()); fe # needs sage.libs.gap
x0^2*x1 + x0*x1^2 + x0^2*x2
+ (2*q*v^4 - q*v^2 - q + v^4 + v^2 - 2)/(q*v^4 - 1)*x0*x1*x2
+ x1^2*x2 + x0*x2^2 + x1*x2^2
- sage: g.map_coefficients(lambda x: x.subs(t=v*v)) == fe
+ sage: g.map_coefficients(lambda x: x.subs(t=v*v)) == fe # needs sage.libs.gap
True
sage: E = NonSymmetricMacdonaldPolynomials(['C',3,1], q, v, -1/v)
diff --git a/src/sage/combinat/root_system/plot.py b/src/sage/combinat/root_system/plot.py
index a1eec40e8df..c81d86b8484 100644
--- a/src/sage/combinat/root_system/plot.py
+++ b/src/sage/combinat/root_system/plot.py
@@ -830,7 +830,7 @@
"RootLatticeRealizations")
-class PlotOptions():
+class PlotOptions:
r"""
A class for plotting options for root lattice realizations.
diff --git a/src/sage/combinat/root_system/reflection_group_c.pyx b/src/sage/combinat/root_system/reflection_group_c.pyx
index e2f5eff21b1..a44a5874b7f 100644
--- a/src/sage/combinat/root_system/reflection_group_c.pyx
+++ b/src/sage/combinat/root_system/reflection_group_c.pyx
@@ -1,4 +1,5 @@
# cython: wraparound=False, boundscheck=False
+# sage.doctest: needs sage.graphs
r"""
This contains a few time-critical auxiliary cython functions for
finite complex or real reflection groups.
diff --git a/src/sage/combinat/root_system/reflection_group_complex.py b/src/sage/combinat/root_system/reflection_group_complex.py
index 03fde46bf8d..6bf0e9936ea 100644
--- a/src/sage/combinat/root_system/reflection_group_complex.py
+++ b/src/sage/combinat/root_system/reflection_group_complex.py
@@ -1,4 +1,4 @@
-# sage.doctest: needs sage.libs.gap
+# sage.doctest: optional - gap3, needs sage.libs.gap
r"""
Finite complex reflection groups
----------------------------------
@@ -13,16 +13,15 @@
The point of entry to work with reflection groups is :func:`~sage.combinat.root_system.reflection_group_real.ReflectionGroup`
which can be used with finite Cartan-Killing types::
- sage: ReflectionGroup(['A',2]) # optional - gap3
+ sage: ReflectionGroup(['A',2])
Irreducible real reflection group of rank 2 and type A2
- sage: ReflectionGroup(['F',4]) # optional - gap3
+ sage: ReflectionGroup(['F',4])
Irreducible real reflection group of rank 4 and type F4
- sage: ReflectionGroup(['H',3]) # optional - gap3
+ sage: ReflectionGroup(['H',3])
Irreducible real reflection group of rank 3 and type H3
or with Shephard-Todd types::
- sage: # optional - gap3
sage: ReflectionGroup((1,1,3))
Irreducible real reflection group of rank 2 and type A2
sage: ReflectionGroup((2,1,3))
@@ -38,14 +37,14 @@
Also reducible types are allowed using concatenation::
- sage: ReflectionGroup(['A',3],(4,2,3)) # optional - gap3
+ sage: ReflectionGroup(['A',3],(4,2,3))
Reducible complex reflection group of rank 6 and type A3 x G(4,2,3)
Some special cases also occur, among them are::
- sage: W = ReflectionGroup((2,2,2)); W # optional - gap3
+ sage: W = ReflectionGroup((2,2,2)); W
Reducible real reflection group of rank 2 and type A1 x A1
- sage: W = ReflectionGroup((2,2,3)); W # optional - gap3
+ sage: W = ReflectionGroup((2,2,3)); W
Irreducible real reflection group of rank 3 and type A3
.. WARNING:: Uses the GAP3 package *Chevie* which is available as an
@@ -57,13 +56,13 @@
We start with the example type `B_2`::
- sage: W = ReflectionGroup(['B',2]); W # optional - gap3
+ sage: W = ReflectionGroup(['B',2]); W
Irreducible real reflection group of rank 2 and type B2
Most importantly, observe that the group elements are usually represented
by permutations of the roots::
- sage: for w in W: print(w) # optional - gap3
+ sage: for w in W: print(w)
()
(1,3)(2,6)(5,7)
(1,5)(2,4)(6,8)
@@ -76,7 +75,7 @@
This has the drawback that one can hardly see anything. Usually, one
would look at elements with either of the following methods::
- sage: for w in W: w.reduced_word() # optional - gap3
+ sage: for w in W: w.reduced_word()
[]
[2]
[1]
@@ -86,7 +85,7 @@
[1, 2, 1]
[1, 2, 1, 2]
- sage: for w in W: w.reduced_word_in_reflections() # optional - gap3
+ sage: for w in W: w.reduced_word_in_reflections()
[]
[2]
[1]
@@ -96,7 +95,7 @@
[4]
[1, 3]
- sage: for w in W: w.reduced_word(); w.to_matrix(); print("") # optional - gap3
+ sage: for w in W: w.reduced_word(); w.to_matrix(); print("")
[]
[1 0]
[0 1]
@@ -133,7 +132,7 @@
The standard references for actions of complex reflection groups have
the matrices acting on the right, so::
- sage: W.simple_reflection(1).to_matrix() # optional - gap3
+ sage: W.simple_reflection(1).to_matrix()
[-1 0]
[ 2 1]
@@ -233,8 +232,8 @@ def __init__(self, W_types, index_set=None, hyperplane_index_set=None, reflectio
TESTS::
sage: from sage.categories.complex_reflection_groups import ComplexReflectionGroups
- sage: W = ComplexReflectionGroups().example() # optional - gap3
- sage: TestSuite(W).run() # optional - gap3
+ sage: W = ComplexReflectionGroups().example()
+ sage: TestSuite(W).run()
"""
W_components = []
reflection_type = []
@@ -331,9 +330,9 @@ def _irrcomp_repr_(self,W_type):
TESTS::
- sage: W = ReflectionGroup(25,[4,1,4],[1,1,4],[5,5,2]); W # optional - gap3
+ sage: W = ReflectionGroup(25,[4,1,4],[1,1,4],[5,5,2]); W
Reducible complex reflection group of rank 12 and type ST25 x G(4,1,4) x A3 x I2(5)
- sage: for W_type in W._type: print(W._irrcomp_repr_(W_type)) # optional - gap3
+ sage: for W_type in W._type: print(W._irrcomp_repr_(W_type))
ST25
G(4,1,4)
A3
@@ -359,7 +358,7 @@ def _repr_(self):
EXAMPLES::
- sage: W = ReflectionGroup(25, [4,1,4],[1,1,4],[5,5,2]); W # optional - gap3
+ sage: W = ReflectionGroup(25, [4,1,4],[1,1,4],[5,5,2]); W
Reducible complex reflection group of rank 12 and type ST25 x G(4,1,4) x A3 x I2(5)
"""
type_str = ''
@@ -379,8 +378,8 @@ def iteration_tracking_words(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: for w in W.iteration_tracking_words(): w # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: for w in W.iteration_tracking_words(): w
()
(1,4)(2,3)(5,6)
(1,3)(2,5)(4,6)
@@ -400,7 +399,6 @@ def index_set(self):
EXAMPLES::
- sage: # optional - gap3
sage: W = ReflectionGroup((1,1,4))
sage: W.index_set()
(1, 2, 3)
@@ -419,10 +417,10 @@ def simple_reflection(self, i):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: W.simple_reflection(1) # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: W.simple_reflection(1)
(1,4)(2,3)(5,6)
- sage: W.simple_reflections() # optional - gap3
+ sage: W.simple_reflections()
Finite family {1: (1,4)(2,3)(5,6), 2: (1,3)(2,5)(4,6)}
"""
return self.gens()[self._index_set_inverse[i]]
@@ -439,9 +437,9 @@ def series(self):
EXAMPLES::
- sage: ReflectionGroup((1,1,3)).series() # optional - gap3
+ sage: ReflectionGroup((1,1,3)).series()
['A']
- sage: ReflectionGroup((3,1,3)).series() # optional - gap3
+ sage: ReflectionGroup((3,1,3)).series()
['ST']
"""
return [self._type[i]['series'] for i in range(len(self._type))]
@@ -453,7 +451,6 @@ def hyperplane_index_set(self):
EXAMPLES::
- sage: # optional - gap3
sage: W = ReflectionGroup((1,1,4))
sage: W.hyperplane_index_set()
(1, 2, 3, 4, 5, 6)
@@ -478,20 +475,20 @@ def distinguished_reflections(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: W.distinguished_reflections() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: W.distinguished_reflections()
Finite family {1: (1,4)(2,3)(5,6), 2: (1,3)(2,5)(4,6), 3: (1,5)(2,4)(3,6)}
- sage: W = ReflectionGroup((1,1,3),hyperplane_index_set=['a','b','c']) # optional - gap3
- sage: W.distinguished_reflections() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3),hyperplane_index_set=['a','b','c'])
+ sage: W.distinguished_reflections()
Finite family {'a': (1,4)(2,3)(5,6), 'b': (1,3)(2,5)(4,6), 'c': (1,5)(2,4)(3,6)}
- sage: W = ReflectionGroup((3,1,1)) # optional - gap3
- sage: W.distinguished_reflections() # optional - gap3
+ sage: W = ReflectionGroup((3,1,1))
+ sage: W.distinguished_reflections()
Finite family {1: (1,2,3)}
- sage: W = ReflectionGroup((1,1,3),(3,1,2)) # optional - gap3
- sage: W.distinguished_reflections() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3),(3,1,2))
+ sage: W.distinguished_reflections()
Finite family {1: (1,6)(2,5)(7,8), 2: (1,5)(2,7)(6,8),
3: (3,9,15)(4,10,16)(12,17,23)(14,18,24)(20,25,29)(21,22,26)(27,28,30),
4: (3,11)(4,12)(9,13)(10,14)(15,19)(16,20)(17,21)(18,22)(23,27)(24,28)(25,26)(29,30),
@@ -522,7 +519,6 @@ def distinguished_reflection(self, i):
EXAMPLES::
- sage: # optional - gap3
sage: W = ReflectionGroup((1,1,3))
sage: W.distinguished_reflection(1)
(1,4)(2,3)(5,6)
@@ -531,12 +527,12 @@ def distinguished_reflection(self, i):
sage: W.distinguished_reflection(3)
(1,5)(2,4)(3,6)
- sage: W = ReflectionGroup((3,1,1),hyperplane_index_set=['a']) # optional - gap3
- sage: W.distinguished_reflection('a') # optional - gap3
+ sage: W = ReflectionGroup((3,1,1),hyperplane_index_set=['a'])
+ sage: W.distinguished_reflection('a')
(1,2,3)
- sage: W = ReflectionGroup((1,1,3),(3,1,2)) # optional - gap3
- sage: for i in range(W.number_of_reflection_hyperplanes()): # optional - gap3
+ sage: W = ReflectionGroup((1,1,3),(3,1,2))
+ sage: for i in range(W.number_of_reflection_hyperplanes()):
....: W.distinguished_reflection(i+1)
(1,6)(2,5)(7,8)
(1,5)(2,7)(6,8)
@@ -563,8 +559,8 @@ def reflection_hyperplanes(self, as_linear_functionals=False, with_order=False):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: for H in W.reflection_hyperplanes(): H # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: for H in W.reflection_hyperplanes(): H
Vector space of degree 2 and dimension 1 over Rational Field
Basis matrix:
[1 2]
@@ -575,14 +571,14 @@ def reflection_hyperplanes(self, as_linear_functionals=False, with_order=False):
Basis matrix:
[ 1 -1]
- sage: for H in W.reflection_hyperplanes(as_linear_functionals=True): H # optional - gap3
+ sage: for H in W.reflection_hyperplanes(as_linear_functionals=True): H
(1, -1/2)
(1, -2)
(1, 1)
- sage: W = ReflectionGroup((2,1,2)) # optional - gap3
- sage: for H in W.reflection_hyperplanes(): H # optional - gap3
+ sage: W = ReflectionGroup((2,1,2))
+ sage: for H in W.reflection_hyperplanes(): H
Vector space of degree 2 and dimension 1 over Rational Field
Basis matrix:
[1 1]
@@ -596,13 +592,13 @@ def reflection_hyperplanes(self, as_linear_functionals=False, with_order=False):
Basis matrix:
[0 1]
- sage: for H in W.reflection_hyperplanes(as_linear_functionals=True): H # optional - gap3
+ sage: for H in W.reflection_hyperplanes(as_linear_functionals=True): H
(1, -1)
(1, -2)
(0, 1)
(1, 0)
- sage: for H in W.reflection_hyperplanes(as_linear_functionals=True, with_order=True): H # optional - gap3
+ sage: for H in W.reflection_hyperplanes(as_linear_functionals=True, with_order=True): H
((1, -1), 2)
((1, -2), 2)
((0, 1), 2)
@@ -636,15 +632,15 @@ def reflection_hyperplane(self, i, as_linear_functional=False, with_order=False)
EXAMPLES::
- sage: W = ReflectionGroup((2,1,2)) # optional - gap3
- sage: W.reflection_hyperplane(3) # optional - gap3
+ sage: W = ReflectionGroup((2,1,2))
+ sage: W.reflection_hyperplane(3)
Vector space of degree 2 and dimension 1 over Rational Field
Basis matrix:
[1 0]
One can ask for the result as a linear form::
- sage: W.reflection_hyperplane(3, True) # optional - gap3
+ sage: W.reflection_hyperplane(3, True)
(0, 1)
"""
return self.reflection_hyperplanes(as_linear_functionals=as_linear_functional, with_order=with_order)[i]
@@ -656,7 +652,6 @@ def reflection_index_set(self):
EXAMPLES::
- sage: # optional - gap3
sage: W = ReflectionGroup((1,1,4))
sage: W.reflection_index_set()
(1, 2, 3, 4, 5, 6)
@@ -677,20 +672,20 @@ def reflections(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: W.reflections() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: W.reflections()
Finite family {1: (1,4)(2,3)(5,6), 2: (1,3)(2,5)(4,6), 3: (1,5)(2,4)(3,6)}
- sage: W = ReflectionGroup((1,1,3),reflection_index_set=['a','b','c']) # optional - gap3
- sage: W.reflections() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3),reflection_index_set=['a','b','c'])
+ sage: W.reflections()
Finite family {'a': (1,4)(2,3)(5,6), 'b': (1,3)(2,5)(4,6), 'c': (1,5)(2,4)(3,6)}
- sage: W = ReflectionGroup((3,1,1)) # optional - gap3
- sage: W.reflections() # optional - gap3
+ sage: W = ReflectionGroup((3,1,1))
+ sage: W.reflections()
Finite family {1: (1,2,3), 2: (1,3,2)}
- sage: W = ReflectionGroup((1,1,3),(3,1,2)) # optional - gap3
- sage: W.reflections() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3),(3,1,2))
+ sage: W.reflections()
Finite family {1: (1,6)(2,5)(7,8), 2: (1,5)(2,7)(6,8),
3: (3,9,15)(4,10,16)(12,17,23)(14,18,24)(20,25,29)(21,22,26)(27,28,30),
4: (3,11)(4,12)(9,13)(10,14)(15,19)(16,20)(17,21)(18,22)(23,27)(24,28)(25,26)(29,30),
@@ -714,7 +709,6 @@ def reflection(self,i):
EXAMPLES::
- sage: # optional - gap3
sage: W = ReflectionGroup((1,1,3))
sage: W.reflection(1)
(1,4)(2,3)(5,6)
@@ -723,10 +717,10 @@ def reflection(self,i):
sage: W.reflection(3)
(1,5)(2,4)(3,6)
- sage: W = ReflectionGroup((3,1,1),reflection_index_set=['a','b']) # optional - gap3
- sage: W.reflection('a') # optional - gap3
+ sage: W = ReflectionGroup((3,1,1),reflection_index_set=['a','b'])
+ sage: W.reflection('a')
(1,2,3)
- sage: W.reflection('b') # optional - gap3
+ sage: W.reflection('b')
(1,3,2)
"""
return self.reflections()[i]
@@ -737,8 +731,8 @@ def reflection_character(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: W.reflection_character() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: W.reflection_character()
[2, 0, -1]
"""
return self._gap_group.ReflectionCharacter().sage()
@@ -760,13 +754,13 @@ def discriminant(self):
EXAMPLES::
- sage: W = ReflectionGroup(['A',2]) # optional - gap3
- sage: W.discriminant() # optional - gap3
+ sage: W = ReflectionGroup(['A',2])
+ sage: W.discriminant()
x0^6 - 3*x0^5*x1 - 3/4*x0^4*x1^2 + 13/2*x0^3*x1^3
- 3/4*x0^2*x1^4 - 3*x0*x1^5 + x1^6
- sage: W = ReflectionGroup(['B',2]) # optional - gap3
- sage: W.discriminant() # optional - gap3
+ sage: W = ReflectionGroup(['B',2])
+ sage: W.discriminant()
x0^6*x1^2 - 6*x0^5*x1^3 + 13*x0^4*x1^4 - 12*x0^3*x1^5 + 4*x0^2*x1^6
"""
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
@@ -787,16 +781,16 @@ def discriminant_in_invariant_ring(self, invariants=None):
EXAMPLES::
- sage: W = ReflectionGroup(['A',3]) # optional - gap3
- sage: W.discriminant_in_invariant_ring() # optional - gap3
+ sage: W = ReflectionGroup(['A',3])
+ sage: W.discriminant_in_invariant_ring()
6*t0^3*t1^2 - 18*t0^4*t2 + 9*t1^4 - 36*t0*t1^2*t2 + 24*t0^2*t2^2 - 8*t2^3
- sage: W = ReflectionGroup(['B',3]) # optional - gap3
- sage: W.discriminant_in_invariant_ring() # optional - gap3
+ sage: W = ReflectionGroup(['B',3])
+ sage: W.discriminant_in_invariant_ring()
-t0^2*t1^2*t2 + 16*t0^3*t2^2 + 2*t1^3*t2 - 36*t0*t1*t2^2 + 108*t2^3
- sage: W = ReflectionGroup(['H',3]) # optional - gap3
- sage: W.discriminant_in_invariant_ring() # long time # optional - gap3
+ sage: W = ReflectionGroup(['H',3])
+ sage: W.discriminant_in_invariant_ring() # long time
(-829*E(5) - 1658*E(5)^2 - 1658*E(5)^3 - 829*E(5)^4)*t0^15
+ (213700*E(5) + 427400*E(5)^2 + 427400*E(5)^3 + 213700*E(5)^4)*t0^12*t1
+ (-22233750*E(5) - 44467500*E(5)^2 - 44467500*E(5)^3 - 22233750*E(5)^4)*t0^9*t1^2
@@ -872,29 +866,29 @@ def is_crystallographic(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)); W # optional - gap3
+ sage: W = ReflectionGroup((1,1,3)); W
Irreducible real reflection group of rank 2 and type A2
- sage: W.is_crystallographic() # optional - gap3
+ sage: W.is_crystallographic()
True
- sage: W = ReflectionGroup((2,1,3)); W # optional - gap3
+ sage: W = ReflectionGroup((2,1,3)); W
Irreducible real reflection group of rank 3 and type B3
- sage: W.is_crystallographic() # optional - gap3
+ sage: W.is_crystallographic()
True
- sage: W = ReflectionGroup(23); W # optional - gap3
+ sage: W = ReflectionGroup(23); W
Irreducible real reflection group of rank 3 and type H3
- sage: W.is_crystallographic() # optional - gap3
+ sage: W.is_crystallographic()
False
- sage: W = ReflectionGroup((3,1,3)); W # optional - gap3
+ sage: W = ReflectionGroup((3,1,3)); W
Irreducible complex reflection group of rank 3 and type G(3,1,3)
- sage: W.is_crystallographic() # optional - gap3
+ sage: W.is_crystallographic()
False
- sage: W = ReflectionGroup((4,2,2)); W # optional - gap3
+ sage: W = ReflectionGroup((4,2,2)); W
Irreducible complex reflection group of rank 2 and type G(4,2,2)
- sage: W.is_crystallographic() # optional - gap3
+ sage: W.is_crystallographic()
False
"""
return self.is_real() and all(t.to_matrix().base_ring() is QQ for t in self.simple_reflections())
@@ -905,12 +899,12 @@ def number_of_irreducible_components(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: W.number_of_irreducible_components() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: W.number_of_irreducible_components()
1
- sage: W = ReflectionGroup((1,1,3),(2,1,3)) # optional - gap3
- sage: W.number_of_irreducible_components() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3),(2,1,3))
+ sage: W.number_of_irreducible_components()
2
"""
return len(self._type)
@@ -922,12 +916,12 @@ def irreducible_components(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: W.irreducible_components() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: W.irreducible_components()
[Irreducible real reflection group of rank 2 and type A2]
- sage: W = ReflectionGroup((1,1,3),(2,1,3)) # optional - gap3
- sage: W.irreducible_components() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3),(2,1,3))
+ sage: W.irreducible_components()
[Irreducible real reflection group of rank 2 and type A2,
Irreducible real reflection group of rank 3 and type B3]
"""
@@ -949,21 +943,21 @@ def conjugacy_classes_representatives(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: [w.reduced_word() for w in W.conjugacy_classes_representatives()] # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: [w.reduced_word() for w in W.conjugacy_classes_representatives()]
[[], [1], [1, 2]]
- sage: W = ReflectionGroup((1,1,4)) # optional - gap3
- sage: [w.reduced_word() for w in W.conjugacy_classes_representatives()] # optional - gap3
+ sage: W = ReflectionGroup((1,1,4))
+ sage: [w.reduced_word() for w in W.conjugacy_classes_representatives()]
[[], [1], [1, 3], [1, 2], [1, 3, 2]]
- sage: W = ReflectionGroup((3,1,2)) # optional - gap3
- sage: [w.reduced_word() for w in W.conjugacy_classes_representatives()] # optional - gap3
+ sage: W = ReflectionGroup((3,1,2))
+ sage: [w.reduced_word() for w in W.conjugacy_classes_representatives()]
[[], [1], [1, 1], [2, 1, 2, 1], [2, 1, 2, 1, 1],
[2, 1, 1, 2, 1, 1], [2], [1, 2], [1, 1, 2]]
- sage: W = ReflectionGroup(23) # optional - gap3
- sage: [w.reduced_word() for w in W.conjugacy_classes_representatives()] # optional - gap3
+ sage: W = ReflectionGroup(23)
+ sage: [w.reduced_word() for w in W.conjugacy_classes_representatives()]
[[],
[1],
[1, 2],
@@ -985,22 +979,22 @@ def conjugacy_classes(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: for C in W.conjugacy_classes(): sorted(C) # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: for C in W.conjugacy_classes(): sorted(C)
[()]
[(1,3)(2,5)(4,6), (1,4)(2,3)(5,6), (1,5)(2,4)(3,6)]
[(1,2,6)(3,4,5), (1,6,2)(3,5,4)]
- sage: W = ReflectionGroup((1,1,4)) # optional - gap3
- sage: sum(len(C) for C in W.conjugacy_classes()) == W.cardinality() # optional - gap3
+ sage: W = ReflectionGroup((1,1,4))
+ sage: sum(len(C) for C in W.conjugacy_classes()) == W.cardinality()
True
- sage: W = ReflectionGroup((3,1,2)) # optional - gap3
- sage: sum(len(C) for C in W.conjugacy_classes()) == W.cardinality() # optional - gap3
+ sage: W = ReflectionGroup((3,1,2))
+ sage: sum(len(C) for C in W.conjugacy_classes()) == W.cardinality()
True
- sage: W = ReflectionGroup(23) # optional - gap3
- sage: sum(len(C) for C in W.conjugacy_classes()) == W.cardinality() # optional - gap3
+ sage: W = ReflectionGroup(23)
+ sage: sum(len(C) for C in W.conjugacy_classes()) == W.cardinality()
True
"""
return Family(self.conjugacy_classes_representatives(),
@@ -1014,7 +1008,6 @@ def rank(self):
EXAMPLES::
- sage: # optional - gap3
sage: W = ReflectionGroup((1,1,3))
sage: W.rank()
2
@@ -1038,35 +1031,35 @@ def degrees(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,4)) # optional - gap3
- sage: W.degrees() # optional - gap3
+ sage: W = ReflectionGroup((1,1,4))
+ sage: W.degrees()
(2, 3, 4)
- sage: W = ReflectionGroup((2,1,4)) # optional - gap3
- sage: W.degrees() # optional - gap3
+ sage: W = ReflectionGroup((2,1,4))
+ sage: W.degrees()
(2, 4, 6, 8)
- sage: W = ReflectionGroup((4,1,4)) # optional - gap3
- sage: W.degrees() # optional - gap3
+ sage: W = ReflectionGroup((4,1,4))
+ sage: W.degrees()
(4, 8, 12, 16)
- sage: W = ReflectionGroup((4,2,4)) # optional - gap3
- sage: W.degrees() # optional - gap3
+ sage: W = ReflectionGroup((4,2,4))
+ sage: W.degrees()
(4, 8, 8, 12)
- sage: W = ReflectionGroup((4,4,4)) # optional - gap3
- sage: W.degrees() # optional - gap3
+ sage: W = ReflectionGroup((4,4,4))
+ sage: W.degrees()
(4, 4, 8, 12)
Examples of reducible types::
- sage: W = ReflectionGroup((1,1,4), (3,1,2)); W # optional - gap3
+ sage: W = ReflectionGroup((1,1,4), (3,1,2)); W
Reducible complex reflection group of rank 5 and type A3 x G(3,1,2)
- sage: W.degrees() # optional - gap3
+ sage: W.degrees()
(2, 3, 4, 3, 6)
- sage: W = ReflectionGroup((1,1,4), (6,1,12), 23) # optional - gap3 # fails in GAP3
- sage: W.degrees() # optional - gap3
+ sage: W = ReflectionGroup((1,1,4), (6,1,12), 23)
+ sage: W.degrees()
(2, 3, 4, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 2, 6, 10)
"""
if self.is_irreducible():
@@ -1085,32 +1078,32 @@ def codegrees(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,4)) # optional - gap3
- sage: W.codegrees() # optional - gap3
+ sage: W = ReflectionGroup((1,1,4))
+ sage: W.codegrees()
(2, 1, 0)
- sage: W = ReflectionGroup((2,1,4)) # optional - gap3
- sage: W.codegrees() # optional - gap3
+ sage: W = ReflectionGroup((2,1,4))
+ sage: W.codegrees()
(6, 4, 2, 0)
- sage: W = ReflectionGroup((4,1,4)) # optional - gap3
- sage: W.codegrees() # optional - gap3
+ sage: W = ReflectionGroup((4,1,4))
+ sage: W.codegrees()
(12, 8, 4, 0)
- sage: W = ReflectionGroup((4,2,4)) # optional - gap3
- sage: W.codegrees() # optional - gap3
+ sage: W = ReflectionGroup((4,2,4))
+ sage: W.codegrees()
(12, 8, 4, 0)
- sage: W = ReflectionGroup((4,4,4)) # optional - gap3
- sage: W.codegrees() # optional - gap3
+ sage: W = ReflectionGroup((4,4,4))
+ sage: W.codegrees()
(8, 8, 4, 0)
- sage: W = ReflectionGroup((1,1,4), (3,1,2)) # optional - gap3
- sage: W.codegrees() # optional - gap3
+ sage: W = ReflectionGroup((1,1,4), (3,1,2))
+ sage: W.codegrees()
(2, 1, 0, 3, 0)
- sage: W = ReflectionGroup((1,1,4), (6,1,12), 23) # optional - gap3 # fails in GAP3
- sage: W.codegrees() # optional - gap3
+ sage: W = ReflectionGroup((1,1,4), (6,1,12), 23)
+ sage: W.codegrees()
(2, 1, 0, 66, 60, 54, 48, 42, 36, 30, 24, 18, 12, 6, 0, 8, 4, 0)
"""
if self.is_irreducible():
@@ -1135,13 +1128,13 @@ def reflection_eigenvalues_family(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: W.reflection_eigenvalues_family() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: W.reflection_eigenvalues_family()
Finite family {(): [0, 0], (1,4)(2,3)(5,6): [1/2, 0], (1,6,2)(3,5,4): [1/3, 2/3]}
- sage: W = ReflectionGroup((3,1,2)) # optional - gap3
- sage: reflection_eigenvalues = W.reflection_eigenvalues_family() # optional - gap3
- sage: for elt in sorted(reflection_eigenvalues.keys()): # optional - gap3
+ sage: W = ReflectionGroup((3,1,2))
+ sage: reflection_eigenvalues = W.reflection_eigenvalues_family()
+ sage: for elt in sorted(reflection_eigenvalues.keys()):
....: print('%s %s'%(elt, reflection_eigenvalues[elt]))
() [0, 0]
(1,3,9)(2,4,10)(6,11,17)(8,12,18)(14,19,23)(15,16,20)(21,22,24) [1/3, 0]
@@ -1153,9 +1146,9 @@ def reflection_eigenvalues_family(self):
(1,9,3)(2,24,16)(4,21,20)(5,13,7)(6,23,12)(8,17,19)(10,22,15)(11,14,18) [2/3, 2/3]
(1,13,9,7,3,5)(2,14,24,18,16,11)(4,6,21,23,20,12)(8,22,17,15,19,10) [1/3, 5/6]
- sage: W = ReflectionGroup(23) # optional - gap3
- sage: reflection_eigenvalues = W.reflection_eigenvalues_family() # optional - gap3
- sage: for elt in sorted(reflection_eigenvalues.keys()): # optional - gap3
+ sage: W = ReflectionGroup(23)
+ sage: reflection_eigenvalues = W.reflection_eigenvalues_family()
+ sage: for elt in sorted(reflection_eigenvalues.keys()):
....: print('%s %s'%(elt, reflection_eigenvalues[elt]))
() [0, 0, 0]
(1,8,4)(2,21,3)(5,10,11)(6,18,17)(7,9,12)(13,14,15)(16,23,19)(20,25,26)(22,24,27)(28,29,30) [1/3, 2/3, 0]
@@ -1187,8 +1180,8 @@ def reflection_eigenvalues(self, w, is_class_representative=False):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: for w in W: # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: for w in W:
....: print('%s %s'%(w.reduced_word(), W.reflection_eigenvalues(w)))
[] [0, 0]
[2] [1/2, 0]
@@ -1210,20 +1203,20 @@ def simple_roots(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: W.simple_roots() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: W.simple_roots()
Finite family {1: (1, 0), 2: (0, 1)}
- sage: W = ReflectionGroup((1,1,4), (2,1,2)) # optional - gap3
- sage: W.simple_roots() # optional - gap3
+ sage: W = ReflectionGroup((1,1,4), (2,1,2))
+ sage: W.simple_roots()
Finite family {1: (1, 0, 0, 0, 0), 2: (0, 1, 0, 0, 0), 3: (0, 0, 1, 0, 0), 4: (0, 0, 0, 1, 0), 5: (0, 0, 0, 0, 1)}
- sage: W = ReflectionGroup((3,1,2)) # optional - gap3
- sage: W.simple_roots() # optional - gap3
+ sage: W = ReflectionGroup((3,1,2))
+ sage: W.simple_roots()
Finite family {1: (1, 0), 2: (-1, 1)}
- sage: W = ReflectionGroup((1,1,4), (3,1,2)) # optional - gap3
- sage: W.simple_roots() # optional - gap3
+ sage: W = ReflectionGroup((1,1,4), (3,1,2))
+ sage: W.simple_roots()
Finite family {1: (1, 0, 0, 0, 0), 2: (0, 1, 0, 0, 0), 3: (0, 0, 1, 0, 0), 4: (0, 0, 0, 1, 0), 5: (0, 0, 0, -1, 1)}
"""
from sage.sets.family import Family
@@ -1235,7 +1228,6 @@ def simple_root(self, i):
EXAMPLES::
- sage: # optional - gap3
sage: W = ReflectionGroup(['A',3])
sage: W.simple_root(1)
(1, 0, 0)
@@ -1246,7 +1238,7 @@ def simple_root(self, i):
TESTS::
- sage: W.simple_root(0) # optional - gap3
+ sage: W.simple_root(0)
Traceback (most recent call last):
...
KeyError: 0
@@ -1262,20 +1254,20 @@ def simple_coroots(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: W.simple_coroots() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: W.simple_coroots()
Finite family {1: (2, -1), 2: (-1, 2)}
- sage: W = ReflectionGroup((1,1,4), (2,1,2)) # optional - gap3
- sage: W.simple_coroots() # optional - gap3
+ sage: W = ReflectionGroup((1,1,4), (2,1,2))
+ sage: W.simple_coroots()
Finite family {1: (2, -1, 0, 0, 0), 2: (-1, 2, -1, 0, 0), 3: (0, -1, 2, 0, 0), 4: (0, 0, 0, 2, -2), 5: (0, 0, 0, -1, 2)}
- sage: W = ReflectionGroup((3,1,2)) # optional - gap3
- sage: W.simple_coroots() # optional - gap3
+ sage: W = ReflectionGroup((3,1,2))
+ sage: W.simple_coroots()
Finite family {1: (-2*E(3) - E(3)^2, 0), 2: (-1, 1)}
- sage: W = ReflectionGroup((1,1,4), (3,1,2)) # optional - gap3
- sage: W.simple_coroots() # optional - gap3
+ sage: W = ReflectionGroup((1,1,4), (3,1,2))
+ sage: W.simple_coroots()
Finite family {1: (2, -1, 0, 0, 0), 2: (-1, 2, -1, 0, 0), 3: (0, -1, 2, 0, 0), 4: (0, 0, 0, -2*E(3) - E(3)^2, 0), 5: (0, 0, 0, -1, 1)}
"""
from sage.sets.family import Family
@@ -1292,8 +1284,8 @@ def simple_coroot(self, i):
EXAMPLES::
- sage: W = ReflectionGroup(['A',3]) # optional - gap3
- sage: W.simple_coroot(1) # optional - gap3
+ sage: W = ReflectionGroup(['A',3])
+ sage: W.simple_coroot(1)
(2, -1, 0)
"""
return self.simple_coroots()[i]
@@ -1310,14 +1302,14 @@ def independent_roots(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: W.independent_roots() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: W.independent_roots()
Finite family {1: (1, 0), 2: (0, 1)}
- sage: W = ReflectionGroup((4,2,3)) # optional - gap3
- sage: W.simple_roots() # optional - gap3
+ sage: W = ReflectionGroup((4,2,3))
+ sage: W.simple_roots()
Finite family {1: (1, 0, 0), 2: (-E(4), 1, 0), 3: (-1, 1, 0), 4: (0, -1, 1)}
- sage: W.independent_roots() # optional - gap3
+ sage: W.independent_roots()
Finite family {1: (1, 0, 0), 2: (-E(4), 1, 0), 4: (0, -1, 1)}
"""
Delta = self.simple_roots()
@@ -1339,12 +1331,12 @@ def roots(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: W.roots() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: W.roots()
[(1, 0), (0, 1), (1, 1), (-1, 0), (0, -1), (-1, -1)]
- sage: W = ReflectionGroup((3,1,2)) # optional - gap3
- sage: W.roots() # optional - gap3
+ sage: W = ReflectionGroup((3,1,2))
+ sage: W.roots()
[(1, 0), (-1, 1), (E(3), 0), (-E(3), 1), (0, 1), (1, -1),
(0, E(3)), (1, -E(3)), (E(3)^2, 0), (-E(3)^2, 1),
(E(3), -1), (E(3), -E(3)), (0, E(3)^2), (1, -E(3)^2),
@@ -1352,16 +1344,16 @@ def roots(self):
(E(3), -E(3)^2), (-E(3)^2, E(3)), (-1, E(3)^2),
(-E(3), E(3)^2), (E(3)^2, -E(3)^2), (-E(3)^2, E(3)^2)]
- sage: W = ReflectionGroup((4,2,2)) # optional - gap3
- sage: W.roots() # optional - gap3
+ sage: W = ReflectionGroup((4,2,2))
+ sage: W.roots()
[(1, 0), (-E(4), 1), (-1, 1), (-1, 0), (E(4), 1), (1, 1),
(0, -E(4)), (E(4), -1), (E(4), E(4)), (0, E(4)),
(E(4), -E(4)), (0, 1), (1, -E(4)), (1, -1), (0, -1),
(1, E(4)), (-E(4), 0), (-1, E(4)), (E(4), 0), (-E(4), E(4)),
(-E(4), -1), (-E(4), -E(4)), (-1, -E(4)), (-1, -1)]
- sage: W = ReflectionGroup((1,1,4), (3,1,2)) # optional - gap3
- sage: W.roots() # optional - gap3
+ sage: W = ReflectionGroup((1,1,4), (3,1,2))
+ sage: W.roots()
[(1, 0, 0, 0, 0), (0, 1, 0, 0, 0), (0, 0, 1, 0, 0),
(0, 0, 0, 1, 0), (0, 0, 0, -1, 1), (1, 1, 0, 0, 0),
(0, 1, 1, 0, 0), (1, 1, 1, 0, 0), (-1, 0, 0, 0, 0),
@@ -1390,16 +1382,16 @@ def braid_relations(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: W.braid_relations() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: W.braid_relations()
[[[1, 2, 1], [2, 1, 2]]]
- sage: W = ReflectionGroup((2,1,3)) # optional - gap3
- sage: W.braid_relations() # optional - gap3
+ sage: W = ReflectionGroup((2,1,3))
+ sage: W.braid_relations()
[[[1, 2, 1, 2], [2, 1, 2, 1]], [[1, 3], [3, 1]], [[2, 3, 2], [3, 2, 3]]]
- sage: W = ReflectionGroup((2,2,3)) # optional - gap3
- sage: W.braid_relations() # optional - gap3
+ sage: W = ReflectionGroup((2,2,3))
+ sage: W.braid_relations()
[[[1, 2, 1], [2, 1, 2]], [[1, 3], [3, 1]], [[2, 3, 2], [3, 2, 3]]]
"""
if self.is_real():
@@ -1414,12 +1406,12 @@ def fundamental_invariants(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: W.fundamental_invariants() # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: W.fundamental_invariants()
(-2*x0^2 + 2*x0*x1 - 2*x1^2, 6*x0^2*x1 - 6*x0*x1^2)
- sage: W = ReflectionGroup((3,1,2)) # optional - gap3
- sage: W.fundamental_invariants() # optional - gap3
+ sage: W = ReflectionGroup((3,1,2))
+ sage: W.fundamental_invariants()
(x0^3 + x1^3, x0^3*x1^3)
"""
import re
@@ -1455,11 +1447,11 @@ def jacobian_of_fundamental_invariants(self, invs=None):
EXAMPLES::
- sage: W = ReflectionGroup(['A',2]) # optional - gap3
- sage: W.fundamental_invariants() # optional - gap3
+ sage: W = ReflectionGroup(['A',2])
+ sage: W.fundamental_invariants()
(-2*x0^2 + 2*x0*x1 - 2*x1^2, 6*x0^2*x1 - 6*x0*x1^2)
- sage: W.jacobian_of_fundamental_invariants() # optional - gap3
+ sage: W.jacobian_of_fundamental_invariants()
[ -4*x0 + 2*x1 2*x0 - 4*x1]
[12*x0*x1 - 6*x1^2 6*x0^2 - 12*x0*x1]
"""
@@ -1484,8 +1476,8 @@ def primitive_vector_field(self, invs=None):
EXAMPLES::
- sage: W = ReflectionGroup(['A',2]) # optional - gap3
- sage: W.primitive_vector_field() # optional - gap3
+ sage: W = ReflectionGroup(['A',2])
+ sage: W.primitive_vector_field()
(3*x1/(6*x0^2 - 6*x0*x1 - 12*x1^2), 1/(6*x0^2 - 6*x0*x1 - 12*x1^2))
"""
if not self.is_irreducible():
@@ -1508,8 +1500,8 @@ def apply_vector_field(self, f, vf=None):
EXAMPLES::
- sage: W = ReflectionGroup(['A',2]) # optional - gap3
- sage: for x in W.primitive_vector_field()[0].parent().gens(): # optional - gap3
+ sage: W = ReflectionGroup(['A',2])
+ sage: for x in W.primitive_vector_field()[0].parent().gens():
....: print(W.apply_vector_field(x))
3*x1/(6*x0^2 - 6*x0*x1 - 12*x1^2)
1/(6*x0^2 - 6*x0*x1 - 12*x1^2)
@@ -1535,23 +1527,23 @@ def cartan_matrix(self):
EXAMPLES::
- sage: ReflectionGroup(['A',4]).cartan_matrix() # optional - gap3
+ sage: ReflectionGroup(['A',4]).cartan_matrix()
[ 2 -1 0 0]
[-1 2 -1 0]
[ 0 -1 2 -1]
[ 0 0 -1 2]
- sage: ReflectionGroup(['H',4]).cartan_matrix() # optional - gap3
+ sage: ReflectionGroup(['H',4]).cartan_matrix()
[ 2 E(5)^2 + E(5)^3 0 0]
[E(5)^2 + E(5)^3 2 -1 0]
[ 0 -1 2 -1]
[ 0 0 -1 2]
- sage: ReflectionGroup(4).cartan_matrix() # optional - gap3
+ sage: ReflectionGroup(4).cartan_matrix()
[-2*E(3) - E(3)^2 E(3)^2]
[ -E(3)^2 -2*E(3) - E(3)^2]
- sage: ReflectionGroup((4,2,2)).cartan_matrix() # optional - gap3
+ sage: ReflectionGroup((4,2,2)).cartan_matrix()
[ 2 -2*E(4) -2]
[ E(4) 2 1 - E(4)]
[ -1 1 + E(4) 2]
@@ -1582,19 +1574,18 @@ def invariant_form(self, brute_force=False):
EXAMPLES::
- sage: W = ReflectionGroup(['A',3]) # optional - gap3
- sage: F = W.invariant_form(); F # optional - gap3
+ sage: W = ReflectionGroup(['A',3])
+ sage: F = W.invariant_form(); F
[ 1 -1/2 0]
[-1/2 1 -1/2]
[ 0 -1/2 1]
To check that this is indeed the invariant form, see::
- sage: S = W.simple_reflections() # optional - gap3
- sage: all( F == S[i].matrix()*F*S[i].matrix().transpose() for i in W.index_set() ) # optional - gap3
+ sage: S = W.simple_reflections()
+ sage: all( F == S[i].matrix()*F*S[i].matrix().transpose() for i in W.index_set() )
True
- sage: # optional - gap3
sage: W = ReflectionGroup(['B',3])
sage: F = W.invariant_form(); F
[ 1 -1 0]
@@ -1604,44 +1595,44 @@ def invariant_form(self, brute_force=False):
sage: w * F * w.transpose().conjugate() == F
True
- sage: S = W.simple_reflections() # optional - gap3
- sage: all( F == S[i].matrix()*F*S[i].matrix().transpose() for i in W.index_set() ) # optional - gap3
+ sage: S = W.simple_reflections()
+ sage: all( F == S[i].matrix()*F*S[i].matrix().transpose() for i in W.index_set() )
True
- sage: W = ReflectionGroup((3,1,2)) # optional - gap3
- sage: F = W.invariant_form(); F # optional - gap3
+ sage: W = ReflectionGroup((3,1,2))
+ sage: F = W.invariant_form(); F
[1 0]
[0 1]
- sage: S = W.simple_reflections() # optional - gap3
- sage: all( F == S[i].matrix()*F*S[i].matrix().transpose().conjugate() for i in W.index_set() ) # optional - gap3
+ sage: S = W.simple_reflections()
+ sage: all( F == S[i].matrix()*F*S[i].matrix().transpose().conjugate() for i in W.index_set() )
True
It also worked for badly generated groups::
- sage: W = ReflectionGroup(7) # optional - gap3
- sage: W.is_well_generated() # optional - gap3
+ sage: W = ReflectionGroup(7)
+ sage: W.is_well_generated()
False
- sage: F = W.invariant_form(); F # optional - gap3
+ sage: F = W.invariant_form(); F
[1 0]
[0 1]
- sage: S = W.simple_reflections() # optional - gap3
- sage: all( F == S[i].matrix()*F*S[i].matrix().transpose().conjugate() for i in W.index_set() ) # optional - gap3
+ sage: S = W.simple_reflections()
+ sage: all( F == S[i].matrix()*F*S[i].matrix().transpose().conjugate() for i in W.index_set() )
True
And also for reducible types::
- sage: W = ReflectionGroup(['B',3],(4,2,3),4,7); W # optional - gap3
+ sage: W = ReflectionGroup(['B',3],(4,2,3),4,7); W
Reducible complex reflection group of rank 10 and type B3 x G(4,2,3) x ST4 x ST7
- sage: F = W.invariant_form(); S = W.simple_reflections() # optional - gap3
- sage: all( F == S[i].matrix()*F*S[i].matrix().transpose().conjugate() for i in W.index_set() ) # optional - gap3
+ sage: F = W.invariant_form(); S = W.simple_reflections()
+ sage: all( F == S[i].matrix()*F*S[i].matrix().transpose().conjugate() for i in W.index_set() )
True
TESTS::
- sage: tests = [['A',3],['B',3],['F',4],(4,2,2),4,7] # optional - gap3
- sage: for ty in tests: # optional - gap3
+ sage: tests = [['A',3],['B',3],['F',4],(4,2,2),4,7]
+ sage: for ty in tests:
....: W = ReflectionGroup(ty)
....: A = W.invariant_form()
....: B = W.invariant_form(brute_force=True)
@@ -1713,8 +1704,8 @@ def _invariant_form_brute_force(self):
EXAMPLES::
- sage: W = ReflectionGroup((3,1,2)) # optional - gap3
- sage: W._invariant_form_brute_force() # optional - gap3
+ sage: W = ReflectionGroup((3,1,2))
+ sage: W._invariant_form_brute_force()
[1 0]
[0 1]
"""
@@ -1774,7 +1765,6 @@ def invariant_form_standardization(self):
EXAMPLES::
- sage: # optional - gap3
sage: W = ReflectionGroup((4,2,5))
sage: I = W.invariant_form()
sage: A = W.invariant_form_standardization()
@@ -1783,7 +1773,6 @@ def invariant_form_standardization(self):
TESTS::
- sage: # optional - gap3
sage: W = ReflectionGroup(9)
sage: A = W.invariant_form_standardization()
sage: S = W.simple_reflections()
@@ -1807,8 +1796,8 @@ def set_reflection_representation(self,refl_repr=None):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: for w in W: w.to_matrix(); print("-----") # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: for w in W: w.to_matrix(); print("-----")
[1 0]
[0 1]
-----
@@ -1828,8 +1817,8 @@ def set_reflection_representation(self,refl_repr=None):
[-1 0]
-----
- sage: W.set_reflection_representation({1: matrix([[0,1,0],[1,0,0],[0,0,1]]), 2: matrix([[1,0,0],[0,0,1],[0,1,0]])}) # optional - gap3
- sage: for w in W: w.to_matrix(); print("-----") # optional - gap3
+ sage: W.set_reflection_representation({1: matrix([[0,1,0],[1,0,0],[0,0,1]]), 2: matrix([[1,0,0],[0,0,1],[0,1,0]])})
+ sage: for w in W: w.to_matrix(); print("-----")
[1 0 0]
[0 1 0]
[0 0 1]
@@ -1854,7 +1843,7 @@ def set_reflection_representation(self,refl_repr=None):
[0 1 0]
[1 0 0]
-----
- sage: W.set_reflection_representation() # optional - gap3
+ sage: W.set_reflection_representation()
"""
if refl_repr is None or set(refl_repr) == set(self.index_set()):
self._reflection_representation = refl_repr
@@ -1876,15 +1865,15 @@ def fake_degrees(self):
EXAMPLES::
- sage: W = ReflectionGroup(12) # optional - gap3
- sage: W.fake_degrees() # optional - gap3
+ sage: W = ReflectionGroup(12)
+ sage: W.fake_degrees()
[1, q^12, q^11 + q, q^8 + q^4, q^7 + q^5, q^6 + q^4 + q^2,
q^10 + q^8 + q^6, q^9 + q^7 + q^5 + q^3]
- sage: W = ReflectionGroup(["H",4]) # optional - gap3
- sage: W.cardinality() # optional - gap3
+ sage: W = ReflectionGroup(["H",4])
+ sage: W.cardinality()
14400
- sage: sum(fdeg.subs(q=1)**2 for fdeg in W.fake_degrees()) # optional - gap3
+ sage: sum(fdeg.subs(q=1)**2 for fdeg in W.fake_degrees())
14400
"""
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
@@ -1918,7 +1907,6 @@ def coxeter_number(self, chi=None):
EXAMPLES::
- sage: # optional - gap3
sage: W = ReflectionGroup(["H",4])
sage: W.coxeter_number()
30
@@ -1952,8 +1940,8 @@ def conjugacy_class_representative(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: for w in W: # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: for w in W:
....: print('%s %s'%(w.reduced_word(), w.conjugacy_class_representative().reduced_word()))
[] []
[2] [1]
@@ -1974,8 +1962,8 @@ def conjugacy_class(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: for w in W: sorted(w.conjugacy_class()) # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: for w in W: sorted(w.conjugacy_class())
[()]
[(1,3)(2,5)(4,6), (1,4)(2,3)(5,6), (1,5)(2,4)(3,6)]
[(1,3)(2,5)(4,6), (1,4)(2,3)(5,6), (1,5)(2,4)(3,6)]
@@ -2020,20 +2008,20 @@ def reflection_length(self, in_unitary_group=False):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: sorted([t.reflection_length() for t in W]) # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: sorted([t.reflection_length() for t in W])
[0, 1, 1, 1, 2, 2]
- sage: W = ReflectionGroup((2,1,2)) # optional - gap3
- sage: sorted([t.reflection_length() for t in W]) # optional - gap3
+ sage: W = ReflectionGroup((2,1,2))
+ sage: sorted([t.reflection_length() for t in W])
[0, 1, 1, 1, 1, 2, 2, 2]
- sage: W = ReflectionGroup((2,2,2)) # optional - gap3
- sage: sorted([t.reflection_length() for t in W]) # optional - gap3
+ sage: W = ReflectionGroup((2,2,2))
+ sage: sorted([t.reflection_length() for t in W])
[0, 1, 1, 2]
- sage: W = ReflectionGroup((3,1,2)) # optional - gap3
- sage: sorted([t.reflection_length() for t in W]) # optional - gap3
+ sage: W = ReflectionGroup((3,1,2))
+ sage: sorted([t.reflection_length() for t in W])
[0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
"""
W = self.parent()
@@ -2058,9 +2046,9 @@ def _repr_(self):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)); W # optional - gap3
+ sage: W = ReflectionGroup((1,1,3)); W
Irreducible real reflection group of rank 2 and type A2
- sage: W = ReflectionGroup((3,1,4)); W # optional - gap3
+ sage: W = ReflectionGroup((3,1,4)); W
Irreducible complex reflection group of rank 4 and type G(3,1,4)
"""
type_str = self._irrcomp_repr_(self._type[0])
@@ -2096,8 +2084,8 @@ def is_coxeter_element(self, which_primitive=1, is_class_representative=False):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: for w in W: # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: for w in W:
....: print('%s %s'%(w.reduced_word(), w.is_coxeter_element()))
[] False
[2] False
@@ -2124,8 +2112,8 @@ def is_h_regular(self, is_class_representative=False):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: for w in W: # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: for w in W:
....: print('%s %s'%(w.reduced_word(), w.is_h_regular()))
[] False
[2] False
@@ -2157,9 +2145,9 @@ def is_regular(self, h, is_class_representative=False):
EXAMPLES::
- sage: W = ReflectionGroup((1,1,3)) # optional - gap3
- sage: h = W.coxeter_number() # optional - gap3
- sage: for w in W: # optional - gap3
+ sage: W = ReflectionGroup((1,1,3))
+ sage: h = W.coxeter_number()
+ sage: for w in W:
....: print("{} {}".format(w.reduced_word(), w.is_regular(h)))
[] False
[2] False
@@ -2168,8 +2156,8 @@ def is_regular(self, h, is_class_representative=False):
[2, 1] True
[1, 2, 1] False
- sage: W = ReflectionGroup(23); h = W.coxeter_number() # optional - gap3
- sage: for w in W: # optional - gap3
+ sage: W = ReflectionGroup(23); h = W.coxeter_number()
+ sage: for w in W:
....: if w.is_regular(h):
....: w.reduced_word()
[1, 2, 3]
@@ -2199,7 +2187,6 @@ def is_regular(self, h, is_class_representative=False):
Check that :trac:`25478` is fixed::
- sage: # optional - gap3
sage: W = ReflectionGroup(["A",5])
sage: w = W.from_reduced_word([1,2,3,5])
sage: w.is_regular(4)
diff --git a/src/sage/combinat/root_system/reflection_group_element.pyx b/src/sage/combinat/root_system/reflection_group_element.pyx
index 6cc6c6e25a2..4f01a5a2882 100644
--- a/src/sage/combinat/root_system/reflection_group_element.pyx
+++ b/src/sage/combinat/root_system/reflection_group_element.pyx
@@ -317,6 +317,7 @@ cdef class ComplexReflectionGroupElement(PermutationGroupElement):
EXAMPLES::
+ sage: # needs sage.graphs
sage: W = WeylGroup(['A',2], prefix='s', implementation="permutation")
sage: for w in W:
....: w.reduced_word()
@@ -835,6 +836,7 @@ cdef class RealReflectionGroupElement(ComplexReflectionGroupElement):
EXAMPLES::
+ sage: # needs sage.graphs
sage: W = CoxeterGroup(['A',4], implementation="permutation")
sage: s = W.simple_reflections()
sage: w = s[2] * s[1] * s[3]
diff --git a/src/sage/combinat/root_system/reflection_group_real.py b/src/sage/combinat/root_system/reflection_group_real.py
index aee6b1d9bd9..8ae2acee1c8 100644
--- a/src/sage/combinat/root_system/reflection_group_real.py
+++ b/src/sage/combinat/root_system/reflection_group_real.py
@@ -1,3 +1,4 @@
+# sage.doctest: optional - gap3
r"""
Finite real reflection groups
-------------------------------
@@ -16,11 +17,11 @@
The point of entry to work with reflection groups is :func:`~sage.combinat.root_system.reflection_group_real.ReflectionGroup`
which can be used with finite Cartan-Killing types::
- sage: ReflectionGroup(['A',2]) # optional - gap3
+ sage: ReflectionGroup(['A',2])
Irreducible real reflection group of rank 2 and type A2
- sage: ReflectionGroup(['F',4]) # optional - gap3
+ sage: ReflectionGroup(['F',4])
Irreducible real reflection group of rank 4 and type F4
- sage: ReflectionGroup(['H',3]) # optional - gap3
+ sage: ReflectionGroup(['H',3])
Irreducible real reflection group of rank 3 and type H3
AUTHORS:
@@ -76,49 +77,49 @@ def ReflectionGroup(*args,**kwds):
Cartan-Killing classification types::
- sage: W = ReflectionGroup(['A',3]); W # optional - gap3
+ sage: W = ReflectionGroup(['A',3]); W
Irreducible real reflection group of rank 3 and type A3
- sage: W = ReflectionGroup(['H',4]); W # optional - gap3
+ sage: W = ReflectionGroup(['H',4]); W
Irreducible real reflection group of rank 4 and type H4
- sage: W = ReflectionGroup(['I',5]); W # optional - gap3
+ sage: W = ReflectionGroup(['I',5]); W
Irreducible real reflection group of rank 2 and type I2(5)
the complex infinite family `G(r,p,n)` with `p` divides `r`::
- sage: W = ReflectionGroup((1,1,4)); W # optional - gap3
+ sage: W = ReflectionGroup((1,1,4)); W
Irreducible real reflection group of rank 3 and type A3
- sage: W = ReflectionGroup((2,1,3)); W # optional - gap3
+ sage: W = ReflectionGroup((2,1,3)); W
Irreducible real reflection group of rank 3 and type B3
Chevalley-Shepard-Todd exceptional classification types::
- sage: W = ReflectionGroup(23); W # optional - gap3
+ sage: W = ReflectionGroup(23); W
Irreducible real reflection group of rank 3 and type H3
Cartan types and matrices::
- sage: ReflectionGroup(CartanType(['A',2])) # optional - gap3
+ sage: ReflectionGroup(CartanType(['A',2]))
Irreducible real reflection group of rank 2 and type A2
- sage: ReflectionGroup(CartanType((['A',2],['A',2]))) # optional - gap3
+ sage: ReflectionGroup(CartanType((['A',2],['A',2])))
Reducible real reflection group of rank 4 and type A2 x A2
- sage: C = CartanMatrix(['A',2]) # optional - gap3
- sage: ReflectionGroup(C) # optional - gap3
+ sage: C = CartanMatrix(['A',2])
+ sage: ReflectionGroup(C)
Irreducible real reflection group of rank 2 and type A2
multiples of the above::
- sage: W = ReflectionGroup(['A',2],['B',2]); W # optional - gap3
+ sage: W = ReflectionGroup(['A',2],['B',2]); W
Reducible real reflection group of rank 4 and type A2 x B2
- sage: W = ReflectionGroup(['A',2],4); W # optional - gap3
+ sage: W = ReflectionGroup(['A',2],4); W
Reducible complex reflection group of rank 4 and type A2 x ST4
- sage: W = ReflectionGroup((4,2,2),4); W # optional - gap3
+ sage: W = ReflectionGroup((4,2,2),4); W
Reducible complex reflection group of rank 4 and type G(4,2,2) x ST4
"""
if not is_chevie_available():
@@ -258,8 +259,8 @@ def __init__(self, W_types, index_set=None, hyperplane_index_set=None, reflectio
TESTS::
- sage: W = ReflectionGroup(['A',3]) # optional - gap3
- sage: TestSuite(W).run() # optional - gap3
+ sage: W = ReflectionGroup(['A',3])
+ sage: TestSuite(W).run()
"""
W_types = tuple([tuple(W_type) if isinstance(W_type, (list,tuple)) else W_type
for W_type in W_types])
@@ -283,8 +284,8 @@ def _repr_(self):
EXAMPLES::
- sage: W = ReflectionGroup(['A',3],['B',2],['I',5],['I',6]) # optional - gap3
- sage: W._repr_() # optional - gap3
+ sage: W = ReflectionGroup(['A',3],['B',2],['I',5],['I',6])
+ sage: W._repr_()
'Reducible real reflection group of rank 9 and type A3 x B2 x I2(5) x G2'
"""
type_str = ''
@@ -325,9 +326,9 @@ def iteration(self, algorithm="breadth", tracking_words=True):
EXAMPLES::
- sage: W = ReflectionGroup(["B",2]) # optional - gap3
+ sage: W = ReflectionGroup(["B",2])
- sage: for w in W.iteration("breadth",True): # optional - gap3
+ sage: for w in W.iteration("breadth",True):
....: print("%s %s"%(w, w._reduced_word))
() []
(1,3)(2,6)(5,7) [1]
@@ -338,7 +339,7 @@ def iteration(self, algorithm="breadth", tracking_words=True):
(1,7)(3,5)(4,8) [0, 1, 0]
(1,5)(2,6)(3,7)(4,8) [0, 1, 0, 1]
- sage: for w in W.iteration("depth", False): w # optional - gap3
+ sage: for w in W.iteration("depth", False): w
()
(1,3)(2,6)(5,7)
(1,5)(2,4)(6,8)
@@ -360,9 +361,9 @@ def __iter__(self):
EXAMPLES::
- sage: W = ReflectionGroup(["B",2]) # optional - gap3
+ sage: W = ReflectionGroup(["B",2])
- sage: for w in W: print("%s %s"%(w, w._reduced_word)) # optional - gap3
+ sage: for w in W: print("%s %s"%(w, w._reduced_word))
() []
(1,3)(2,6)(5,7) [1]
(1,5)(2,4)(6,8) [0]
@@ -381,12 +382,12 @@ def bipartite_index_set(self):
EXAMPLES::
- sage: W = ReflectionGroup(["A",5]) # optional - gap3
- sage: W.bipartite_index_set() # optional - gap3
+ sage: W = ReflectionGroup(["A",5])
+ sage: W.bipartite_index_set()
[[1, 3, 5], [2, 4]]
- sage: W = ReflectionGroup(["A",5],index_set=['a','b','c','d','e']) # optional - gap3
- sage: W.bipartite_index_set() # optional - gap3
+ sage: W = ReflectionGroup(["A",5],index_set=['a','b','c','d','e'])
+ sage: W.bipartite_index_set()
[['a', 'c', 'e'], ['b', 'd']]
"""
L, R = self._gap_group.BipartiteDecomposition().sage()
@@ -401,25 +402,25 @@ def cartan_type(self):
EXAMPLES::
- sage: W = ReflectionGroup(['A',3]) # optional - gap3
- sage: W.cartan_type() # optional - gap3
+ sage: W = ReflectionGroup(['A',3])
+ sage: W.cartan_type()
['A', 3]
- sage: W = ReflectionGroup(['A',3], ['B',3]) # optional - gap3
- sage: W.cartan_type() # optional - gap3
+ sage: W = ReflectionGroup(['A',3], ['B',3])
+ sage: W.cartan_type()
A3xB3 relabelled by {1: 3, 2: 2, 3: 1}
TESTS:
Check that dihedral types are handled properly::
- sage: W = ReflectionGroup(['I',3]); W # optional - gap3
+ sage: W = ReflectionGroup(['I',3]); W
Irreducible real reflection group of rank 2 and type A2
- sage: W = ReflectionGroup(['I',4]); W # optional - gap3
+ sage: W = ReflectionGroup(['I',4]); W
Irreducible real reflection group of rank 2 and type C2
- sage: W = ReflectionGroup(['I',5]); W # optional - gap3
+ sage: W = ReflectionGroup(['I',5]); W
Irreducible real reflection group of rank 2 and type I2(5)
"""
if len(self._type) == 1:
@@ -440,8 +441,8 @@ def positive_roots(self):
EXAMPLES::
- sage: W = ReflectionGroup(['A',3], ['B',2]) # optional - gap3
- sage: W.positive_roots() # optional - gap3
+ sage: W = ReflectionGroup(['A',3], ['B',2])
+ sage: W.positive_roots()
[(1, 0, 0, 0, 0),
(0, 1, 0, 0, 0),
(0, 0, 1, 0, 0),
@@ -453,8 +454,8 @@ def positive_roots(self):
(1, 1, 1, 0, 0),
(0, 0, 0, 2, 1)]
- sage: W = ReflectionGroup(['A',3]) # optional - gap3
- sage: W.positive_roots() # optional - gap3
+ sage: W = ReflectionGroup(['A',3])
+ sage: W.positive_roots()
[(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (0, 1, 1), (1, 1, 1)]
"""
return self.roots()[:self.number_of_reflections()]
@@ -465,8 +466,8 @@ def almost_positive_roots(self):
EXAMPLES::
- sage: W = ReflectionGroup(['A',3], ['B',2]) # optional - gap3
- sage: W.almost_positive_roots() # optional - gap3
+ sage: W = ReflectionGroup(['A',3], ['B',2])
+ sage: W.almost_positive_roots()
[(-1, 0, 0, 0, 0),
(0, -1, 0, 0, 0),
(0, 0, -1, 0, 0),
@@ -483,8 +484,8 @@ def almost_positive_roots(self):
(1, 1, 1, 0, 0),
(0, 0, 0, 2, 1)]
- sage: W = ReflectionGroup(['A',3]) # optional - gap3
- sage: W.almost_positive_roots() # optional - gap3
+ sage: W = ReflectionGroup(['A',3])
+ sage: W.almost_positive_roots()
[(-1, 0, 0),
(0, -1, 0),
(0, 0, -1),
@@ -503,8 +504,8 @@ def root_to_reflection(self, root):
EXAMPLES::
- sage: W = ReflectionGroup(['A',2]) # optional - gap3
- sage: for beta in W.roots(): W.root_to_reflection(beta) # optional - gap3
+ sage: W = ReflectionGroup(['A',2])
+ sage: for beta in W.roots(): W.root_to_reflection(beta)
(1,4)(2,3)(5,6)
(1,3)(2,5)(4,6)
(1,5)(2,4)(3,6)
@@ -527,8 +528,8 @@ def reflection_to_positive_root(self, r):
EXAMPLES::
- sage: W = ReflectionGroup(['A',2]) # optional - gap3
- sage: for r in W.reflections(): # optional - gap3
+ sage: W = ReflectionGroup(['A',2])
+ sage: for r in W.reflections():
....: print(W.reflection_to_positive_root(r))
(1, 0)
(0, 1)
@@ -557,15 +558,14 @@ def fundamental_weights(self):
EXAMPLES::
- sage: W = ReflectionGroup(['A',3], ['B',2]) # optional - gap3
- sage: W.fundamental_weights() # optional - gap3
+ sage: W = ReflectionGroup(['A',3], ['B',2])
+ sage: W.fundamental_weights()
Finite family {1: (3/4, 1/2, 1/4, 0, 0), 2: (1/2, 1, 1/2, 0, 0), 3: (1/4, 1/2, 3/4, 0, 0), 4: (0, 0, 0, 1, 1/2), 5: (0, 0, 0, 1, 1)}
- sage: W = ReflectionGroup(['A',3]) # optional - gap3
- sage: W.fundamental_weights() # optional - gap3
+ sage: W = ReflectionGroup(['A',3])
+ sage: W.fundamental_weights()
Finite family {1: (3/4, 1/2, 1/4), 2: (1/2, 1, 1/2), 3: (1/4, 1/2, 3/4)}
- sage: # optional - gap3
sage: W = ReflectionGroup(['A',3])
sage: S = W.simple_reflections()
sage: N = W.fundamental_weights()
@@ -598,8 +598,8 @@ def fundamental_weight(self, i):
EXAMPLES::
- sage: W = ReflectionGroup(['A',3]) # optional - gap3
- sage: [ W.fundamental_weight(i) for i in W.index_set() ] # optional - gap3
+ sage: W = ReflectionGroup(['A',3])
+ sage: [ W.fundamental_weight(i) for i in W.index_set() ]
[(3/4, 1/2, 1/4), (1/2, 1, 1/2), (1/4, 1/2, 3/4)]
"""
return self.fundamental_weights()[i]
@@ -611,8 +611,8 @@ def coxeter_diagram(self):
EXAMPLES::
- sage: G = ReflectionGroup(['B',3]) # optional - gap3
- sage: G.coxeter_diagram().edges(labels=True, sort=True) # optional - gap3
+ sage: G = ReflectionGroup(['B',3])
+ sage: G.coxeter_diagram().edges(labels=True, sort=True)
[(1, 2, 4), (2, 3, 3)]
"""
from sage.graphs.graph import Graph
@@ -634,8 +634,8 @@ def coxeter_matrix(self):
EXAMPLES::
- sage: G = ReflectionGroup(['A',3]) # optional - gap3
- sage: G.coxeter_matrix() # optional - gap3
+ sage: G = ReflectionGroup(['A',3])
+ sage: G.coxeter_matrix()
[1 3 2]
[3 1 3]
[2 3 1]
@@ -650,8 +650,8 @@ def right_coset_representatives(self, J):
EXAMPLES::
- sage: W = ReflectionGroup(["A",3]) # optional - gap3
- sage: for J in Subsets([1,2,3]): W.right_coset_representatives(J) # optional - gap3
+ sage: W = ReflectionGroup(["A",3])
+ sage: for J in Subsets([1,2,3]): W.right_coset_representatives(J)
[(), (2,5)(3,9)(4,6)(8,11)(10,12), (1,4)(2,8)(3,5)(7,10)(9,11),
(1,7)(2,4)(5,6)(8,10)(11,12), (1,2,10)(3,6,5)(4,7,8)(9,12,11),
(1,4,6)(2,3,11)(5,8,9)(7,10,12), (1,6,4)(2,11,3)(5,9,8)(7,12,10),
@@ -705,8 +705,8 @@ def simple_root_index(self, i):
EXAMPLES::
- sage: W = ReflectionGroup(['A',3]) # optional - gap3
- sage: [W.simple_root_index(i) for i in W.index_set()] # optional - gap3
+ sage: W = ReflectionGroup(['A',3])
+ sage: [W.simple_root_index(i) for i in W.index_set()]
[0, 1, 2]
"""
return self._index_set_inverse[i]
@@ -736,14 +736,12 @@ def bruhat_cone(self, x, y, side='upper', backend='cdd'):
EXAMPLES::
- sage: # optional - gap3
sage: W = ReflectionGroup(['A',2])
sage: x = W.from_reduced_word([1])
sage: y = W.w0
sage: W.bruhat_cone(x, y)
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays
- sage: # optional - gap3
sage: W = ReflectionGroup(['E',6])
sage: x = W.one()
sage: y = W.w0
@@ -752,7 +750,6 @@ def bruhat_cone(self, x, y, side='upper', backend='cdd'):
TESTS::
- sage: # optional - gap3
sage: W = ReflectionGroup(['A',2])
sage: x = W.one()
sage: y = W.w0
@@ -805,8 +802,8 @@ def right_coset_representatives(self):
EXAMPLES::
- sage: W = ReflectionGroup(['A',2]) # optional - gap3
- sage: for w in W: # optional - gap3
+ sage: W = ReflectionGroup(['A',2])
+ sage: for w in W:
....: rcr = w.right_coset_representatives()
....: print("%s %s"%(w.reduced_word(),
....: [v.reduced_word() for v in rcr]))
@@ -834,8 +831,8 @@ def left_coset_representatives(self):
EXAMPLES::
- sage: W = ReflectionGroup(['A',2]) # optional - gap3
- sage: for w in W: # optional - gap3
+ sage: W = ReflectionGroup(['A',2])
+ sage: for w in W:
....: lcr = w.left_coset_representatives()
....: print("%s %s"%(w.reduced_word(),
....: [v.reduced_word() for v in lcr]))
@@ -856,7 +853,7 @@ def _repr_(self):
EXAMPLES::
- sage: for i in [2..7]: ReflectionGroup(["I", i]) # optional - gap3
+ sage: for i in [2..7]: ReflectionGroup(["I", i])
Reducible real reflection group of rank 2 and type A1 x A1
Irreducible real reflection group of rank 2 and type A2
Irreducible real reflection group of rank 2 and type C2
diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py
index 80ed38c982f..d3e443d830b 100644
--- a/src/sage/combinat/root_system/root_lattice_realizations.py
+++ b/src/sage/combinat/root_system/root_lattice_realizations.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Root lattice realizations
"""
@@ -1117,7 +1116,7 @@ def nonnesting_partition_lattice(self, facade=False):
sage: RS = R.root_lattice()
sage: P = RS.nonnesting_partition_lattice(); P # needs sage.graphs
Finite lattice containing 14 elements
- sage: P.coxeter_transformation()**10 == 1 # needs sage.graphs
+ sage: P.coxeter_transformation()**10 == 1 # needs sage.graphs sage.libs.flint
True
sage: # needs sage.graphs
@@ -1125,7 +1124,7 @@ def nonnesting_partition_lattice(self, facade=False):
sage: RS = R.root_lattice()
sage: P = RS.nonnesting_partition_lattice(); P
Finite lattice containing 20 elements
- sage: P.coxeter_transformation()**7 == 1
+ sage: P.coxeter_transformation()**7 == 1 # needs sage.libs.flint
True
REFERENCES:
@@ -1157,7 +1156,7 @@ def generalized_nonnesting_partition_lattice(self, m, facade=False):
sage: RS = R.root_lattice()
sage: P = RS.generalized_nonnesting_partition_lattice(2); P # needs sage.graphs
Finite lattice containing 12 elements
- sage: P.coxeter_transformation()**20 == 1 # needs sage.graphs
+ sage: P.coxeter_transformation()**20 == 1 # needs sage.graphs sage.libs.flint
True
"""
Phi_plus = self.positive_roots()
@@ -1789,8 +1788,8 @@ def tau_plus_minus(self):
We explore the example of [CFZ2002]_ Eq.(1.3)::
sage: S = RootSystem(['A',2]).root_lattice()
- sage: taup, taum = S.tau_plus_minus() # needs sage.graphs
- sage: for beta in S.almost_positive_roots(): # needs sage.graphs
+ sage: taup, taum = S.tau_plus_minus() # needs sage.graphs sage.libs.gap
+ sage: for beta in S.almost_positive_roots(): # needs sage.graphs sage.libs.gap
....: print("{} , {} , {}".format(beta, taup(beta), taum(beta)))
-alpha[1] , alpha[1] , -alpha[1]
alpha[1] , -alpha[1] , alpha[1] + alpha[2]
@@ -1817,14 +1816,14 @@ def almost_positive_roots_decomposition(self):
EXAMPLES::
- sage: RootSystem(['A',2]).root_lattice().almost_positive_roots_decomposition() # needs sage.graphs
+ sage: RootSystem(['A',2]).root_lattice().almost_positive_roots_decomposition() # needs sage.graphs sage.libs.gap
[[-alpha[1], alpha[1], alpha[1] + alpha[2], alpha[2], -alpha[2]]]
- sage: RootSystem(['B',2]).root_lattice().almost_positive_roots_decomposition() # needs sage.graphs
+ sage: RootSystem(['B',2]).root_lattice().almost_positive_roots_decomposition() # needs sage.graphs sage.libs.gap
[[-alpha[1], alpha[1], alpha[1] + 2*alpha[2]],
[-alpha[2], alpha[2], alpha[1] + alpha[2]]]
- sage: RootSystem(['D',4]).root_lattice().almost_positive_roots_decomposition() # needs sage.graphs
+ sage: RootSystem(['D',4]).root_lattice().almost_positive_roots_decomposition() # needs sage.graphs sage.libs.gap
[[-alpha[1], alpha[1], alpha[1] + alpha[2], alpha[2] + alpha[3] + alpha[4]],
[-alpha[2], alpha[2], alpha[1] + alpha[2] + alpha[3] + alpha[4],
alpha[1] + 2*alpha[2] + alpha[3] + alpha[4]],
@@ -4262,8 +4261,8 @@ def weyl_action(self, element, inverse=False):
Acting by an element of the Coxeter or Weyl group on a vector in its own
lattice of definition (implemented by matrix multiplication on a vector)::
- sage: w = wl.weyl_group().from_reduced_word([1, 2]) # needs sage.graphs
- sage: mudom.weyl_action(w) # needs sage.graphs
+ sage: w = wl.weyl_group().from_reduced_word([1, 2]) # needs sage.graphs sage.libs.gap
+ sage: mudom.weyl_action(w) # needs sage.graphs sage.libs.gap
Lambda[1] - 2*Lambda[3]
Acting by an element of an isomorphic Coxeter or Weyl group (implemented by the
diff --git a/src/sage/combinat/root_system/root_space.py b/src/sage/combinat/root_system/root_space.py
index cb7fc672ac2..a375b3b8074 100644
--- a/src/sage/combinat/root_system/root_space.py
+++ b/src/sage/combinat/root_system/root_space.py
@@ -429,12 +429,13 @@ def max_quantum_element(self):
EXAMPLES::
+ sage: # needs sage.graphs sage.libs.gap
sage: Qvee = RootSystem(['C',2]).coroot_lattice()
- sage: Qvee.from_vector(vector([1,2])).max_quantum_element() # needs sage.graphs
+ sage: Qvee.from_vector(vector([1,2])).max_quantum_element()
[2, 1, 2, 1]
- sage: Qvee.from_vector(vector([1,1])).max_quantum_element() # needs sage.graphs
+ sage: Qvee.from_vector(vector([1,1])).max_quantum_element()
[1, 2, 1]
- sage: Qvee.from_vector(vector([0,2])).max_quantum_element() # needs sage.graphs
+ sage: Qvee.from_vector(vector([0,2])).max_quantum_element()
[2]
"""
diff --git a/src/sage/combinat/root_system/root_system.py b/src/sage/combinat/root_system/root_system.py
index a26b9afa75c..c80cffbdb87 100644
--- a/src/sage/combinat/root_system/root_system.py
+++ b/src/sage/combinat/root_system/root_system.py
@@ -158,7 +158,7 @@ class RootSystem(UniqueRepresentation, SageObject):
In finite type `A`, we recover the natural representation of the
symmetric group as group of permutation matrices::
- sage: RootSystem(["A",2]).ambient_space().weyl_group().simple_reflections() # needs sage.libs.pari
+ sage: RootSystem(["A",2]).ambient_space().weyl_group().simple_reflections() # needs sage.libs.gap sage.libs.pari
Finite family {1: [0 1 0]
[1 0 0]
[0 0 1],
@@ -169,7 +169,7 @@ class RootSystem(UniqueRepresentation, SageObject):
In type `B`, `C`, and `D`, we recover the natural representation
of the Weyl group as groups of signed permutation matrices::
- sage: RootSystem(["B",3]).ambient_space().weyl_group().simple_reflections() # needs sage.libs.pari
+ sage: RootSystem(["B",3]).ambient_space().weyl_group().simple_reflections() # needs sage.libs.gap sage.libs.pari
Finite family {1: [0 1 0]
[1 0 0]
[0 0 1],
@@ -203,15 +203,17 @@ class RootSystem(UniqueRepresentation, SageObject):
Here is the orbit of the identity under the action of the finite
group::
- sage: W = L.weyl_group() # needs sage.libs.pari
- sage: S3 = [ w.action(id) for w in W.classical() ] # needs sage.graphs sage.libs.pari
- sage: [L.classical()(x) for x in S3] # needs sage.graphs sage.libs.pari
+ sage: # needs sage.graphs sage.libs.gap sage.libs.pari
+ sage: W = L.weyl_group()
+ sage: S3 = [ w.action(id) for w in W.classical() ]
+ sage: [L.classical()(x) for x in S3]
[(1, 2, 3), (3, 1, 2), (2, 3, 1), (2, 1, 3), (1, 3, 2), (3, 2, 1)]
And the action of `s_0` on these yields::
- sage: s = W.simple_reflections() # needs sage.libs.pari
- sage: [L.classical()(s[0].action(x)) for x in S3] # needs sage.graphs sage.libs.pari
+ sage: # needs sage.graphs sage.libs.gap sage.libs.pari
+ sage: s = W.simple_reflections()
+ sage: [L.classical()(s[0].action(x)) for x in S3]
[(0, 2, 4), (-1, 1, 6), (-2, 3, 5), (0, 1, 5), (-1, 3, 4), (-2, 2, 6)]
We can also plot various components of the ambient spaces::
diff --git a/src/sage/combinat/root_system/type_E.py b/src/sage/combinat/root_system/type_E.py
index 5771d6d948f..7c3292d6ea7 100644
--- a/src/sage/combinat/root_system/type_E.py
+++ b/src/sage/combinat/root_system/type_E.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Root system data for type E
"""
diff --git a/src/sage/combinat/root_system/type_F.py b/src/sage/combinat/root_system/type_F.py
index 524dd1f7c35..5d699d31c5a 100644
--- a/src/sage/combinat/root_system/type_F.py
+++ b/src/sage/combinat/root_system/type_F.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Root system data for type F
"""
diff --git a/src/sage/combinat/root_system/type_relabel.py b/src/sage/combinat/root_system/type_relabel.py
index 350e290b32a..712937d08ce 100644
--- a/src/sage/combinat/root_system/type_relabel.py
+++ b/src/sage/combinat/root_system/type_relabel.py
@@ -10,7 +10,7 @@
from sage.misc.cachefunc import cached_method
from sage.misc.lazy_attribute import lazy_attribute
-from sage.sets.family import FiniteFamily
+from sage.sets.family import Family, FiniteFamily
from sage.combinat.root_system import cartan_type
from sage.combinat.root_system import ambient_space
from sage.combinat.root_system.root_lattice_realizations import RootLatticeRealizations
@@ -173,10 +173,10 @@ def __init__(self, type, relabelling):
sage: rI5 = CartanType(['I',5]).relabel({1:0,2:1})
sage: rI5.root_system().ambient_space()
"""
- assert isinstance(relabelling, FiniteFamily)
cartan_type.CartanType_decorator.__init__(self, type)
- self._relabelling = relabelling._dictionary
- self._relabelling_inverse = relabelling.inverse_family()._dictionary
+ relabelling = Family(relabelling)
+ self._relabelling = dict(relabelling.items())
+ self._relabelling_inverse = dict(relabelling.inverse_family().items())
self._index_set = tuple(sorted(relabelling[i] for i in type.index_set()))
# TODO: design an appropriate infrastructure to handle this
# automatically? Maybe using categories and axioms?
diff --git a/src/sage/combinat/root_system/weight_lattice_realizations.py b/src/sage/combinat/root_system/weight_lattice_realizations.py
index be54faa6bcb..c33299f1012 100644
--- a/src/sage/combinat/root_system/weight_lattice_realizations.py
+++ b/src/sage/combinat/root_system/weight_lattice_realizations.py
@@ -551,7 +551,7 @@ def dynkin_diagram_automorphism_of_alcove_morphism(self, f):
Translations by elements of the root lattice induce a
trivial Dynkin diagram automorphism::
- sage: # needs sage.graphs
+ sage: # needs sage.graphs sage.libs.gap
sage: R.dynkin_diagram_automorphism_of_alcove_morphism(alpha[0].translation)
{0: 0, 1: 1, 2: 2}
sage: R.dynkin_diagram_automorphism_of_alcove_morphism(alpha[1].translation)
@@ -565,19 +565,19 @@ def dynkin_diagram_automorphism_of_alcove_morphism(self, f):
sage: omega1 = Lambda[1] - Lambda[0]
sage: omega2 = Lambda[2] - Lambda[0]
- sage: # needs sage.graphs
+ sage: # needs sage.graphs sage.libs.gap
sage: R.dynkin_diagram_automorphism_of_alcove_morphism(omega1.translation)
{0: 1, 1: 2, 2: 0}
sage: R.dynkin_diagram_automorphism_of_alcove_morphism(omega2.translation)
{0: 2, 1: 0, 2: 1}
- sage: # needs sage.graphs
+ sage: # needs sage.graphs sage.libs.gap
sage: R = RootSystem(['C',2,1]).weight_lattice()
sage: alpha = R.simple_roots()
sage: R.dynkin_diagram_automorphism_of_alcove_morphism(alpha[1].translation)
{0: 2, 1: 1, 2: 0}
- sage: # needs sage.graphs
+ sage: # needs sage.graphs sage.libs.gap
sage: R = RootSystem(['D',5,1]).weight_lattice()
sage: Lambda = R.fundamental_weights()
sage: omega1 = Lambda[1] - Lambda[0]
@@ -704,9 +704,14 @@ def _test_reduced_word_of_translation(self, elements=None, **options):
# dictionary assigning a simple root to its index
rank_simple_roots = dict( (alpha[i],i) for i in self.index_set() )
+ try:
+ W = self.weyl_group()
+ except ImportError:
+ return
+
for t in elements:
t = t - self.base_ring()(t.level()/Lambda[0].level()) * Lambda[0]
- w = self.weyl_group().from_reduced_word(self.reduced_word_of_translation(t))
+ w = W.from_reduced_word(self.reduced_word_of_translation(t))
if self.null_root().is_zero():
# The following formula is only valid when the null root is zero
tester.assertEqual(w.action(rho), rho + rho.level()*t)
diff --git a/src/sage/combinat/root_system/weyl_characters.py b/src/sage/combinat/root_system/weyl_characters.py
index 51baa89b661..a42929606b1 100644
--- a/src/sage/combinat/root_system/weyl_characters.py
+++ b/src/sage/combinat/root_system/weyl_characters.py
@@ -1,4 +1,4 @@
-# sage.doctest: needs sage.groups sage.modules
+# sage.doctest: needs sage.graphs sage.groups sage.modules
"""
Weyl Character Rings
"""
@@ -691,7 +691,7 @@ def _demazure_weights(self, hwv, word="long", debug=False):
dd = {}
h = tuple(int(hwv.inner_product(alphacheck[j]))
for j in self._space.index_set())
- dd[h] = int(1)
+ dd[h] = 1
return self._demazure_helper(dd, word=word, debug=debug)
def _demazure_helper(self, dd, word="long", debug=False):
diff --git a/src/sage/combinat/rsk.py b/src/sage/combinat/rsk.py
index 2c787878768..96e5e29db5b 100644
--- a/src/sage/combinat/rsk.py
+++ b/src/sage/combinat/rsk.py
@@ -2968,7 +2968,7 @@ def _backward_format_output(self, obj1, obj2, output):
return DecreasingHeckeFactorization(df)
-class InsertionRules():
+class InsertionRules:
r"""
Catalog of rules for RSK-like insertion algorithms.
"""
diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py
index c7d5e98ea33..c08e1c7aef3 100644
--- a/src/sage/combinat/set_partition.py
+++ b/src/sage/combinat/set_partition.py
@@ -73,7 +73,7 @@ def _repr_(self):
sage: S([[1,3],[2,4]])
{{1, 3}, {2, 4}}
"""
- return '{' + ', '.join(('{' + repr(sorted(x))[1:-1] + '}' for x in self)) + '}'
+ return '{' + ', '.join('{' + repr(sorted(x))[1:-1] + '}' for x in self) + '}'
def __hash__(self):
"""
diff --git a/src/sage/combinat/set_partition_ordered.py b/src/sage/combinat/set_partition_ordered.py
index 186835f7129..a76adfa8f9f 100644
--- a/src/sage/combinat/set_partition_ordered.py
+++ b/src/sage/combinat/set_partition_ordered.py
@@ -220,7 +220,7 @@ def _repr_(self):
sage: OrderedSetPartition([[1,3],[2,4]])
[{1, 3}, {2, 4}]
"""
- return '[' + ', '.join(('{' + repr(sorted(x))[1:-1] + '}' for x in self)) + ']'
+ return '[' + ', '.join('{' + repr(sorted(x))[1:-1] + '}' for x in self) + ']'
def check(self):
"""
diff --git a/src/sage/combinat/sf/k_dual.py b/src/sage/combinat/sf/k_dual.py
index 4fa2e971e36..546695bc338 100644
--- a/src/sage/combinat/sf/k_dual.py
+++ b/src/sage/combinat/sf/k_dual.py
@@ -284,7 +284,7 @@ def _G_to_km_on_basis_single_level(self, w, m):
return 0
ans = self.zero()
for la in Partitions(m, max_part=self.k):
- ans += g.homogeneous_basis_noncommutative_variables_zero_Hecke((la)).coefficient(w) * mon(la)
+ ans += g.homogeneous_basis_noncommutative_variables_zero_Hecke(la).coefficient(w) * mon(la)
return ans
def _AffineGrothendieck(self, w, m):
diff --git a/src/sage/combinat/sf/macdonald.py b/src/sage/combinat/sf/macdonald.py
index 09a3ef98798..1358c5779df 100644
--- a/src/sage/combinat/sf/macdonald.py
+++ b/src/sage/combinat/sf/macdonald.py
@@ -1843,7 +1843,7 @@ def _creation_by_determinant_helper(self, k, part):
INPUT:
- ``self`` -- an element of the Macdonald `S` basis
- - ``k`` -- an positive integer at least as big as the
+ - ``k`` -- a positive integer at least as big as the
length of ``part``
- ``part`` -- a partition
diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py
index bca95b7f9da..2b42ebb7be6 100644
--- a/src/sage/combinat/sf/sfa.py
+++ b/src/sage/combinat/sf/sfa.py
@@ -196,7 +196,7 @@
- Darij Grinberg (2013) Sym over rings that are not characteristic 0
"""
-#*****************************************************************************
+# ****************************************************************************
# Copyright (C) 2007 Mike Hansen
# 2012 Anne Schilling
# 2012 Mike Zabrocki
@@ -210,8 +210,8 @@
#
# The full text of the GPL is available at:
#
-# http://www.gnu.org/licenses/
-#*****************************************************************************
+# https://www.gnu.org/licenses/
+# ****************************************************************************
from sage.misc.cachefunc import cached_method
from sage.rings.integer_ring import ZZ
from sage.rings.rational_field import QQ
@@ -306,7 +306,7 @@ def is_SymmetricFunction(x):
return isinstance(x, SymmetricFunctionAlgebra_generic.Element)
#####################################################################
-## Bases categories
+# Bases categories
from sage.categories.realizations import Category_realization_of_parent
@@ -1429,30 +1429,30 @@ def carlitz_shareshian_wachs(self, n, d, s, comparison=None):
# be folly.
if comparison is None:
def check_word(w):
- if sum((1 for i in range(n-1) if w[i] > w[i+1])) != d:
+ if sum(1 for i in range(n-1) if w[i] > w[i+1]) != d:
return False
- if sum((1 for i in range(n-1) if w[i] == w[i+1])) != s:
+ if sum(1 for i in range(n-1) if w[i] == w[i+1]) != s:
return False
return True
elif comparison == -1:
def check_word(w):
- if sum((1 for i in range(n-1) if w[i] > w[i+1])) != d:
+ if sum(1 for i in range(n-1) if w[i] > w[i+1]) != d:
return False
- if sum((1 for i in range(n-1) if w[i] == w[i+1])) != s:
+ if sum(1 for i in range(n-1) if w[i] == w[i+1]) != s:
return False
return w[0] < w[-1]
elif comparison == 0:
def check_word(w):
- if sum((1 for i in range(n-1) if w[i] > w[i+1])) != d:
+ if sum(1 for i in range(n-1) if w[i] > w[i+1]) != d:
return False
- if sum((1 for i in range(n-1) if w[i] == w[i+1])) != s:
+ if sum(1 for i in range(n-1) if w[i] == w[i+1]) != s:
return False
return w[0] == w[-1]
elif comparison == 1:
def check_word(w):
- if sum((1 for i in range(n-1) if w[i] > w[i+1])) != d:
+ if sum(1 for i in range(n-1) if w[i] > w[i+1]) != d:
return False
- if sum((1 for i in range(n-1) if w[i] == w[i+1])) != s:
+ if sum(1 for i in range(n-1) if w[i] == w[i+1]) != s:
return False
return w[0] > w[-1]
@@ -4619,10 +4619,10 @@ def internal_coproduct(self):
@cached_function
def hnimage(n):
- return result_parent.sum((tensor([parent(s(lam)), parent(s(lam))])
- for lam in Partitions(n)))
+ return result_parent.sum(tensor([parent(s(lam)), parent(s(lam))])
+ for lam in Partitions(n))
for lam, a in h(self):
- result += a * prod((hnimage(i) for i in lam))
+ result += a * prod(hnimage(i) for i in lam)
return result
kronecker_coproduct = internal_coproduct
@@ -5588,7 +5588,7 @@ def _is_positive(self, s):
True
"""
s_self = s(self)
- return all(( _nonnegative_coefficients(c) for c in s_self.coefficients() ))
+ return all(_nonnegative_coefficients(c) for c in s_self.coefficients())
def degree(self):
r"""
diff --git a/src/sage/combinat/shard_order.py b/src/sage/combinat/shard_order.py
index e40198fc27a..d33bc2173f6 100644
--- a/src/sage/combinat/shard_order.py
+++ b/src/sage/combinat/shard_order.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Shard intersection order
diff --git a/src/sage/combinat/shifted_primed_tableau.py b/src/sage/combinat/shifted_primed_tableau.py
index e9a320cd0ea..a05a8b0bee8 100644
--- a/src/sage/combinat/shifted_primed_tableau.py
+++ b/src/sage/combinat/shifted_primed_tableau.py
@@ -553,7 +553,7 @@ def _ascii_art_table(self, unicode=False):
else:
l1 += uh + h*width
if unicode:
- l2 += u"{}{:^{width}}".format(v, e, width=width)
+ l2 += "{}{:^{width}}".format(v, e, width=width)
else:
l2 += "{}{:^{width}}".format(v, e, width=width)
if i <= n:
diff --git a/src/sage/combinat/shuffle.py b/src/sage/combinat/shuffle.py
index 50618a6388f..9da145671bf 100644
--- a/src/sage/combinat/shuffle.py
+++ b/src/sage/combinat/shuffle.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Shuffle product of iterables
diff --git a/src/sage/combinat/skew_partition.py b/src/sage/combinat/skew_partition.py
index 484b4ceb7f3..e525c67ee39 100644
--- a/src/sage/combinat/skew_partition.py
+++ b/src/sage/combinat/skew_partition.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Skew Partitions
@@ -485,11 +484,11 @@ def _unicode_art_(self):
out, inn = self
inn = inn + [0] * (len(out) - len(inn))
if not any(self._list):
- return UnicodeArt(u'∅')
+ return UnicodeArt('∅')
if self.parent().options.convention == "French":
- s, t, b, l, r, tr, tl, br, bl, x, h = list(u' ┴┬├┤┘└┐┌┼─')
+ s, t, b, l, r, tr, tl, br, bl, x, h = list(' ┴┬├┤┘└┐┌┼─')
else:
- s, t, b, l, r, tr, tl, br, bl, x, h = list(u' ┬┴├┤┐┌┘└┼─')
+ s, t, b, l, r, tr, tl, br, bl, x, h = list(' ┬┴├┤┐┌┘└┼─')
# working with English conventions
txt = [s * inn[0] + tl + t * (out[0] - inn[0] - 1) + tr]
@@ -500,10 +499,10 @@ def _unicode_art_(self):
i1 = inn[i + 1]
if i0 == i1:
- start = u' ' * i1 + l
+ start = ' ' * i1 + l
d0 = 1
else:
- start = u' ' * i1 + tl
+ start = ' ' * i1 + tl
d0 = 0
if o0 == o1:
diff --git a/src/sage/combinat/skew_tableau.py b/src/sage/combinat/skew_tableau.py
index 4718f29f199..3019522d21e 100644
--- a/src/sage/combinat/skew_tableau.py
+++ b/src/sage/combinat/skew_tableau.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Skew Tableaux
diff --git a/src/sage/combinat/species/composition_species.py b/src/sage/combinat/species/composition_species.py
index b60e5348985..ccfe0141803 100644
--- a/src/sage/combinat/species/composition_species.py
+++ b/src/sage/combinat/species/composition_species.py
@@ -116,7 +116,7 @@ def __init__(self, F, G, min=None, max=None, weight=None):
sage: E = species.SetSpecies(); C = species.CycleSpecies()
sage: L = E(C)
sage: c = L.generating_series()[:3]
- sage: L._check() #False due to isomorphism types not being implemented # needs sage.libs.flint
+ sage: L._check() #False due to isomorphism types not being implemented # needs sage.libs.flint
False
sage: L == loads(dumps(L))
True
@@ -234,7 +234,7 @@ def _cis(self, series_ring, base_ring):
sage: E = species.SetSpecies()
sage: C = species.CycleSpecies(weight=t)
sage: S = E(C)
- sage: S.isotype_generating_series()[:5] #indirect # needs sage.modules
+ sage: S.isotype_generating_series()[:5] #indirect # needs sage.modules
[1, t, t^2 + t, t^3 + t^2 + t, t^4 + t^3 + 2*t^2 + t]
We do the same thing with set partitions weighted by the number of
diff --git a/src/sage/combinat/species/species.py b/src/sage/combinat/species/species.py
index d3f1e9d3867..705dbd22494 100644
--- a/src/sage/combinat/species/species.py
+++ b/src/sage/combinat/species/species.py
@@ -553,7 +553,7 @@ def _series_helper(self, series_ring_class, prefix, base_ring=None):
pass
# Try to return things like self._gs_callable(base_ring).
- # This is used when the subclass just provides an callable
+ # This is used when the subclass just provides a callable
# for the coefficients of the generating series. Optionally,
# the subclass can specify the order of the series.
try:
diff --git a/src/sage/combinat/symmetric_group_algebra.py b/src/sage/combinat/symmetric_group_algebra.py
index 7672c8c7649..031940f5283 100644
--- a/src/sage/combinat/symmetric_group_algebra.py
+++ b/src/sage/combinat/symmetric_group_algebra.py
@@ -19,6 +19,7 @@
from sage.combinat.partition import _Partitions, Partitions_n
from sage.combinat.tableau import Tableau, StandardTableaux_size, StandardTableaux_shape, StandardTableaux
from sage.algebras.group_algebra import GroupAlgebra_class
+from sage.algebras.cellular_basis import CellularBasis
from sage.categories.weyl_groups import WeylGroups
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
from sage.rings.rational_field import QQ
@@ -688,8 +689,7 @@ def cell_poset(self):
Finite poset containing 5 elements
"""
from sage.combinat.posets.posets import Poset
- from sage.combinat.partition import Partitions
- return Poset([Partitions(self.n), lambda x, y: y.dominates(x)])
+ return Poset([Partitions_n(self.n), lambda x, y: y.dominates(x)])
def cell_module_indices(self, la):
r"""
@@ -732,40 +732,14 @@ def _from_cellular_index(self, x):
sage: [S._from_cellular_index(i) for i in C.basis().keys()]
[[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1],
[1, 2, 3] + [2, 1, 3],
- [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [3, 1, 2],
- [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1],
- [1, 2, 3] + [1, 3, 2],
+ [1, 3, 2] + [3, 1, 2],
+ [1, 3, 2] + [2, 3, 1],
+ [1, 2, 3] + [3, 2, 1],
[1, 2, 3]]
sage: TestSuite(C).run()
"""
if ~factorial(self.n) not in self.base_ring():
- from sage.combinat.rsk import RSK_inverse
- from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet
- G = self.basis().keys()
- R = self.base_ring()
- one = R.one()
- # check if the KL polynomials can be computed using ``coxeter3``
- try:
- from sage.libs.coxeter3.coxeter_group import CoxeterGroup as Coxeter3Group
- except ImportError:
- # Falback to using the KL polynomial
- from sage.combinat.kazhdan_lusztig import KazhdanLusztigPolynomial
- from sage.groups.perm_gps.permgroup_named import SymmetricGroup
- q = PolynomialRing(R, 'q').gen()
- KLG = SymmetricGroup(self.n)
- self._cellular_KL = KazhdanLusztigPolynomial(KLG, q)
- polyfunc = self._cellular_KL.P
- else:
- self._cellular_KL = Coxeter3Group(['A', self.n+1])
- KLG = self._cellular_KL
- polyfunc = self._cellular_KL.kazhdan_lusztig_polynomial
-
- def func(S, T, mult=None):
- w = KLG.from_reduced_word(RSK_inverse(T, S, output="permutation").reduced_word())
- bruhat = RecursivelyEnumeratedSet([w], lambda u: u.bruhat_lower_covers(), structure='graded')
- return self.element_class(self, {G.from_reduced_word(v.reduced_word()): R(c(q=one))
- for v in bruhat if (c := polyfunc(v, w))})
-
+ func = self.murphy_basis_element
else:
func = self.epsilon_ik
@@ -2083,6 +2057,150 @@ def epsilon_ik(self, itab, ktab, star=0, mult='l2r'):
else:
return z.map_support(lambda x: x.inverse())
+ def murphy_basis(self):
+ r"""
+ Return the :class:`Murphy basis
+ ` of ``self``.
+
+ EXAMPLES::
+
+ sage: SGA = SymmetricGroupAlgebra(QQ, 3)
+ sage: M = SGA.murphy_basis()
+ sage: M(SGA.an_element())
+ -C([1, 1, 1], [[1], [2], [3]], [[1], [2], [3]])
+ + C([2, 1], [[1, 2], [3]], [[1, 2], [3]])
+ + C([2, 1], [[1, 2], [3]], [[1, 3], [2]])
+ + 2*C([2, 1], [[1, 3], [2]], [[1, 2], [3]])
+ + 4*C([2, 1], [[1, 3], [2]], [[1, 3], [2]])
+ - 3*C([3], [[1, 2, 3]], [[1, 2, 3]])
+ """
+ return MurphyBasis(self)
+
+ @cached_method(key=lambda s, X, Y: (StandardTableaux()(X), StandardTableaux()(Y)))
+ def murphy_basis_element(self, S, T):
+ r"""
+ Return the Murphy basis element indexed by ``S`` and ``T``.
+
+ .. SEEALSO::
+
+ :class:`~sage.combinat.symmetric_group_algebra.MurphyBasis`
+
+ EXAMPLES::
+
+ sage: import itertools
+ sage: SGA = SymmetricGroupAlgebra(QQ, 3)
+ sage: for S, T in itertools.product(StandardTableaux([2,1]), repeat=2):
+ ....: print(S, T, SGA.murphy_basis_element(S, T))
+ [[1, 3], [2]] [[1, 3], [2]] [1, 2, 3] + [2, 1, 3]
+ [[1, 3], [2]] [[1, 2], [3]] [1, 3, 2] + [3, 1, 2]
+ [[1, 2], [3]] [[1, 3], [2]] [1, 3, 2] + [2, 3, 1]
+ [[1, 2], [3]] [[1, 2], [3]] [1, 2, 3] + [3, 2, 1]
+
+ TESTS::
+
+ sage: SGA = SymmetricGroupAlgebra(QQ, 3)
+ sage: SGA.murphy_basis_element([[1,2,3,4]], [[1,2],[3,4]])
+ Traceback (most recent call last):
+ ...
+ ValueError: [[1, 2, 3, 4]] is not an element of Standard tableaux of size 3
+ sage: SGA.murphy_basis_element([[1,2,3]], [[1,2],[3]])
+ Traceback (most recent call last):
+ ...
+ ValueError: S and T must have the same shape
+ """
+ std_tab = StandardTableaux(self.n)
+ S = std_tab(S)
+ T = std_tab(T)
+ S = S.conjugate()
+ T = T.conjugate()
+
+ la = S.shape()
+ if la != T.shape():
+ raise ValueError("S and T must have the same shape")
+
+ G = self.group()
+ ds = G(list(sum((row for row in S), ())))
+ dt = G(list(sum((row for row in T), ())))
+ return self.monomial(~ds) * self._row_stabilizer(la) * self.monomial(dt)
+
+ @cached_method
+ def _row_stabilizer(self, la):
+ """
+ Return the row stabilizer element of a canonical standard tableau
+ of shape ``la``.
+
+ EXAMPLES::
+
+ sage: SGA = SymmetricGroupAlgebra(QQ, 3)
+ sage: for la in Partitions(3):
+ ....: print(la, SGA._row_stabilizer(la))
+ [3] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
+ [2, 1] [1, 2, 3] + [2, 1, 3]
+ [1, 1, 1] [1, 2, 3]
+ """
+ G = self.group()
+ return self.sum_of_monomials(G(list(w.tuple())) for w in la.young_subgroup())
+
+ def kazhdan_lusztig_cellular_basis(self):
+ r"""
+ Return the Kazhdan-Lusztig basis (at `q = 1`) of ``self``
+ as a cellular basis.
+
+ EXAMPLES::
+
+ sage: SGA = SymmetricGroupAlgebra(QQ, 3)
+ sage: KL = SGA.kazhdan_lusztig_cellular_basis()
+ sage: KL(SGA.an_element())
+ C([2, 1], [[1, 2], [3]], [[1, 2], [3]])
+ + C([2, 1], [[1, 3], [2]], [[1, 2], [3]])
+ + 2*C([2, 1], [[1, 3], [2]], [[1, 3], [2]])
+ - 3*C([3], [[1, 2, 3]], [[1, 2, 3]])
+ """
+ return KLCellularBasis(self)
+
+ @cached_method
+ def kazhdan_lusztig_basis_element(self, w):
+ r"""
+ Return the Kazhdan-Lusztig `C'_w` basis element at `q = 1`.
+
+ EXAMPLES::
+
+ sage: SGA = SymmetricGroupAlgebra(QQ, 3)
+ sage: for w in SGA.group():
+ ....: print(w, SGA.kazhdan_lusztig_basis_element(w))
+ [1, 2, 3] [1, 2, 3]
+ [1, 3, 2] [1, 2, 3] + [1, 3, 2]
+ [2, 1, 3] [1, 2, 3] + [2, 1, 3]
+ [2, 3, 1] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1]
+ [3, 1, 2] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [3, 1, 2]
+ [3, 2, 1] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
+ """
+ from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet
+ G = self.basis().keys()
+ R = self.base_ring()
+ one = R.one()
+ # check if the KL polynomials can be computed using ``coxeter3``
+ try:
+ from sage.libs.coxeter3.coxeter_group import CoxeterGroup as Coxeter3Group
+ except ImportError:
+ # Falback to using the KL polynomial
+ from sage.combinat.kazhdan_lusztig import KazhdanLusztigPolynomial
+ from sage.groups.perm_gps.permgroup_named import SymmetricGroup
+ q = PolynomialRing(R, 'q').gen()
+ self._KLG = SymmetricGroup(self.n)
+ self._cellular_KL = KazhdanLusztigPolynomial(self._KLG, q)
+ polyfunc = self._cellular_KL.P
+ else:
+ self._cellular_KL = Coxeter3Group(['A', self.n+1])
+ self._KLG = self._cellular_KL
+ polyfunc = self._cellular_KL.kazhdan_lusztig_polynomial
+
+ if w.parent() is not self._KLG:
+ w = self._KLG.from_reduced_word(w.reduced_word())
+ bruhat = RecursivelyEnumeratedSet([w], lambda u: u.bruhat_lower_covers(), structure='graded')
+ return self.element_class(self, {G.from_reduced_word(v.reduced_word()): R(c(q=one))
+ for v in bruhat if (c := polyfunc(v, w))})
+
epsilon_ik_cache = {}
@@ -2634,6 +2752,179 @@ def seminormal_test(n):
raise ValueError("3.1.20 - %s, %s" % (tab, tab2))
return True
+
+#######################
+
+
+class SGACellularBasis(CellularBasis):
+ r"""
+ A cellular basis of the symmetric group algebra.
+ """
+ def __init__(self, SGA):
+ r"""
+ Initialize ``self``.
+
+ EXAMPLES::
+
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 3)
+ sage: M = SGA.murphy_basis()
+ sage: TestSuite(M).run()
+ sage: KL = SGA.kazhdan_lusztig_cellular_basis()
+ sage: TestSuite(KL).run()
+ """
+ CellularBasis.__init__(self, SGA, self._to_sga)
+
+ def _repr_(self):
+ r"""
+ Return a string representation of ``self``.
+
+ EXAMPLES::
+
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 4)
+ sage: SGA.murphy_basis()
+ Murphy basis of Symmetric group algebra of order 4 over Finite Field of size 3
+ sage: SGA.kazhdan_lusztig_cellular_basis()
+ Kazhdan-Lusztig basis of Symmetric group algebra of order 4 over Finite Field of size 3
+ """
+ return self._name + " basis of {}".format(self._algebra)
+
+ @cached_method
+ def one_basis(self):
+ r"""
+ Return the index of the basis element for the multiplicative identity.
+
+ EXAMPLES::
+
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 4)
+ sage: M = SGA.murphy_basis()
+ sage: M.one_basis()
+ ([4], [[1, 2, 3, 4]], [[1, 2, 3, 4]])
+ """
+ la = _Partitions([self._algebra.n])
+ col = la.standard_tableaux()[0]
+ return (la, col, col)
+
+ @cached_method
+ def one(self):
+ r"""
+ Return the element `1` in ``self``.
+
+ EXAMPLES::
+
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 4)
+ sage: M = SGA.murphy_basis()
+ sage: M.one()
+ C([4], [[1, 2, 3, 4]], [[1, 2, 3, 4]])
+ """
+ return self.monomial(self.one_basis())
+
+
+class MurphyBasis(SGACellularBasis):
+ r"""
+ The Murphy basis of a symmetric group algebra.
+
+ Let `R` be a commutative ring, and let `A = R[S_n]` denote the group
+ algebra (over `R`) of `S_n`. The *Murphy basis* is the basis of `A`
+ defined as follows. Let `S, T` be standard tableaux of shape `\lambda`.
+ Define `T^{\lambda}` as the standard tableau of shape `\lambda` with
+ the first row filled with `1, \ldots, \lambda_1`, the second row
+ `\lambda_1+1, \ldots, \lambda_1+\lambda_2`, and so on. Let `d(S)` be
+ the unique permutation such that `S = T^{\lambda} d(S)` under the natural
+ action. Then the Murphy basis element indexed by `S` and `T` is
+
+ .. MATH::
+
+ M_{S'T'} = d(S)^{-1} R_{\lambda} d(T),
+
+ where `S'` denotes the conjugate tableau.
+ The Murphy basis is a :class:`cellular basis
+ ` of `A`.
+
+ EXAMPLES::
+
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 5)
+ sage: M = SGA.murphy_basis()
+ sage: for la in M.simple_module_parameterization():
+ ....: CM = M.cell_module(la)
+ ....: print(la, CM.dimension(), CM.simple_module().dimension())
+ [2, 2, 1] 5 4
+ [3, 1, 1] 6 6
+ [3, 2] 5 1
+ [4, 1] 4 4
+ [5] 1 1
+
+ REFERENCES:
+
+ - [DJM1998]_
+ - [Mathas2004]_
+ """
+ _name = "Murphy"
+
+ def _to_sga(self, ind):
+ r"""
+ Return the element in the symmetric group algebra indexed by ``ind``.
+
+ EXAMPLES::
+
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 3)
+ sage: M = SGA.murphy_basis()
+ sage: for ind in M.basis().keys():
+ ....: print(ind, M._to_sga(ind))
+ ([1, 1, 1], [[1], [2], [3]], [[1], [2], [3]]) [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
+ ([2, 1], [[1, 3], [2]], [[1, 3], [2]]) [1, 2, 3] + [2, 1, 3]
+ ([2, 1], [[1, 3], [2]], [[1, 2], [3]]) [1, 3, 2] + [3, 1, 2]
+ ([2, 1], [[1, 2], [3]], [[1, 3], [2]]) [1, 3, 2] + [2, 3, 1]
+ ([2, 1], [[1, 2], [3]], [[1, 2], [3]]) [1, 2, 3] + [3, 2, 1]
+ ([3], [[1, 2, 3]], [[1, 2, 3]]) [1, 2, 3]
+ """
+ return self._algebra.murphy_basis_element(ind[1], ind[2])
+
+
+class KLCellularBasis(SGACellularBasis):
+ """
+ The Kazhdan-Lusztig `C'` basis (at `q = 1`) of the symmetric group
+ algebra realized as a :class:`cellular basis
+ `
+
+ EXAMPLES::
+
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 5)
+ sage: KL = SGA.kazhdan_lusztig_cellular_basis()
+ sage: for la in KL.simple_module_parameterization():
+ ....: CM = KL.cell_module(la)
+ ....: print(la, CM.dimension(), CM.simple_module().dimension())
+ [2, 2, 1] 5 4
+ [3, 1, 1] 6 6
+ [3, 2] 5 1
+ [4, 1] 4 4
+ [5] 1 1
+ """
+ _name = "Kazhdan-Lusztig"
+
+ def _to_sga(self, ind):
+ r"""
+ Return the element in the symmetric group algebra indexed by ``ind``.
+
+ EXAMPLES::
+
+ sage: SGA = SymmetricGroupAlgebra(GF(3), 3)
+ sage: KL = SGA.kazhdan_lusztig_cellular_basis()
+ sage: for ind in KL.basis().keys():
+ ....: print(ind, KL._to_sga(ind))
+ ([1, 1, 1], [[1], [2], [3]], [[1], [2], [3]]) [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
+ ([2, 1], [[1, 3], [2]], [[1, 3], [2]]) [1, 2, 3] + [2, 1, 3]
+ ([2, 1], [[1, 3], [2]], [[1, 2], [3]]) [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [3, 1, 2]
+ ([2, 1], [[1, 2], [3]], [[1, 3], [2]]) [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1]
+ ([2, 1], [[1, 2], [3]], [[1, 2], [3]]) [1, 2, 3] + [1, 3, 2]
+ ([3], [[1, 2, 3]], [[1, 2, 3]]) [1, 2, 3]
+ """
+ from sage.combinat.rsk import RSK_inverse
+ S = ind[1]
+ T = ind[2]
+ w = RSK_inverse(T, S, output="permutation")
+ return self._algebra.kazhdan_lusztig_basis_element(w)
+
+
#######################
diff --git a/src/sage/combinat/tableau.py b/src/sage/combinat/tableau.py
index f716c7cd117..c4009853da6 100644
--- a/src/sage/combinat/tableau.py
+++ b/src/sage/combinat/tableau.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Tableaux
diff --git a/src/sage/combinat/tableau_tuple.py b/src/sage/combinat/tableau_tuple.py
index 96fc0f0c51c..807823a4af7 100644
--- a/src/sage/combinat/tableau_tuple.py
+++ b/src/sage/combinat/tableau_tuple.py
@@ -279,7 +279,7 @@ class TableauTuple(CombinatorialElement):
The :meth:`level` of a tableau tuple is the length of the tuples. This
corresponds to the level of the corresponding highest weight module.
- In sage a :class:`TableauTuple` looks an behaves like a real tuple of
+ In sage a :class:`TableauTuple` looks and behaves like a real tuple of
(level 1) :class:`Tableaux`. Many of the operations which are defined
on :class:`Tableau` extend to :class:`TableauTuples`. Tableau tuples of
level 1 are just ordinary :class:`Tableau`.
diff --git a/src/sage/combinat/tiling.py b/src/sage/combinat/tiling.py
index a543b50461d..723557eb9ab 100644
--- a/src/sage/combinat/tiling.py
+++ b/src/sage/combinat/tiling.py
@@ -163,7 +163,7 @@
sage: T = TilingSolver(L, box=(8,8), reflection=True)
sage: solution = next(T.solve()) # long time (7s)
sage: G = sum([piece.show2d() for piece in solution], Graphics()) # long time (<1s), needs sage.plot
- sage: G.show(aspect_ratio=1, axes=False) # long time (2s), needs sage.plot
+ sage: G.show(aspect_ratio=1, axes=False) # long time (2s), needs sage.plot
Compute the number of solutions::
@@ -199,7 +199,7 @@
sage: T = TilingSolver(L, box=(8,8,1))
sage: solution = next(T.solve()) # long time (8s)
sage: G = sum([p.show3d(size=0.85) for p in solution], Graphics()) # long time (<1s), needs sage.plot
- sage: G.show(aspect_ratio=1, viewer='tachyon') # long time (2s), needs sage.plot
+ sage: G.show(aspect_ratio=1, viewer='tachyon') # long time (2s), needs sage.plot
Let us compute the number of solutions::
diff --git a/src/sage/combinat/tutorial.py b/src/sage/combinat/tutorial.py
index a5edc7146ea..6f9fad1c5dd 100644
--- a/src/sage/combinat/tutorial.py
+++ b/src/sage/combinat/tutorial.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Introduction to combinatorics in Sage
diff --git a/src/sage/combinat/words/alphabet.py b/src/sage/combinat/words/alphabet.py
index 1de8838df00..19ac17054b8 100644
--- a/src/sage/combinat/words/alphabet.py
+++ b/src/sage/combinat/words/alphabet.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Alphabet
diff --git a/src/sage/combinat/words/finite_word.py b/src/sage/combinat/words/finite_word.py
index 35fd6e69c55..41613ed61e2 100644
--- a/src/sage/combinat/words/finite_word.py
+++ b/src/sage/combinat/words/finite_word.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Finite word
diff --git a/src/sage/combinat/words/lyndon_word.py b/src/sage/combinat/words/lyndon_word.py
index 4c978680380..209f9099f18 100644
--- a/src/sage/combinat/words/lyndon_word.py
+++ b/src/sage/combinat/words/lyndon_word.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Lyndon words
"""
diff --git a/src/sage/combinat/words/morphic.py b/src/sage/combinat/words/morphic.py
index 0db7a8db6fe..c036db8e2ec 100644
--- a/src/sage/combinat/words/morphic.py
+++ b/src/sage/combinat/words/morphic.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Morphic words
diff --git a/src/sage/combinat/words/morphism.py b/src/sage/combinat/words/morphism.py
index 279c238718e..abb99d9f685 100644
--- a/src/sage/combinat/words/morphism.py
+++ b/src/sage/combinat/words/morphism.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Word morphisms/substitutions
@@ -150,7 +149,7 @@ def get_cycles(f, domain):
return cycles
-class PeriodicPointIterator():
+class PeriodicPointIterator:
r"""
(Lazy) constructor of the periodic points of a word morphism.
@@ -3158,7 +3157,7 @@ def immortal_letters(self):
[]
"""
if not self.is_self_composable():
- raise TypeError(f'self ({self}) is not an self-composable')
+ raise TypeError(f'self ({self}) is not a self-composable')
forward = {}
backward = {letter: set() for letter in self._morph}
diff --git a/src/sage/combinat/words/paths.py b/src/sage/combinat/words/paths.py
index 5c84a784533..5106615ae9b 100644
--- a/src/sage/combinat/words/paths.py
+++ b/src/sage/combinat/words/paths.py
@@ -425,7 +425,7 @@ def __init__(self, alphabet, steps):
#Construction of the steps
from sage.structure.element import Vector
- if all((isinstance(x, Vector) for x in steps)):
+ if all(isinstance(x, Vector) for x in steps):
vsteps = steps
else:
try:
diff --git a/src/sage/combinat/words/word.py b/src/sage/combinat/words/word.py
index 132195589e9..222501a5dfd 100644
--- a/src/sage/combinat/words/word.py
+++ b/src/sage/combinat/words/word.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Word classes
@@ -197,11 +196,11 @@ def Word(data=None, alphabet=None, length=None, datatype=None, caching=True, RSK
#if a list of a semistandard and a standard tableau or a pair of lists
from sage.combinat.tableau import Tableau
if isinstance(RSK_data, (tuple, list)) and len(RSK_data) == 2 and \
- all((isinstance(x, Tableau) for x in RSK_data)):
+ all(isinstance(x, Tableau) for x in RSK_data):
from sage.combinat.rsk import RSK_inverse
return RSK_inverse(*RSK_data, output='word')
elif isinstance(RSK_data, (tuple, list)) and len(RSK_data) == 2 and \
- all((isinstance(x, (list, tuple)) for x in RSK_data)):
+ all(isinstance(x, (list, tuple)) for x in RSK_data):
from sage.combinat.rsk import RSK_inverse
P,Q = map(Tableau, RSK_data)
return RSK_inverse(P, Q, 'word')
diff --git a/src/sage/combinat/words/word_datatypes.pyx b/src/sage/combinat/words/word_datatypes.pyx
index daf21a97469..9ab88d799ba 100644
--- a/src/sage/combinat/words/word_datatypes.pyx
+++ b/src/sage/combinat/words/word_datatypes.pyx
@@ -583,7 +583,7 @@ cdef class WordDatatype_str(WordDatatype):
INPUT:
- - ``other`` - word represented by an str
+ - ``other`` - word represented by a str
OUTPUT:
diff --git a/src/sage/combinat/words/word_generators.py b/src/sage/combinat/words/word_generators.py
index 58886bd9108..641319f2ee7 100644
--- a/src/sage/combinat/words/word_generators.py
+++ b/src/sage/combinat/words/word_generators.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Common words
@@ -314,7 +313,7 @@ def __reduce__(self):
return self.__class__, (self.__p, self.__q, self.parent().alphabet())
-class WordGenerator():
+class WordGenerator:
r"""
Constructor of several famous words.
diff --git a/src/sage/combinat/words/words.py b/src/sage/combinat/words/words.py
index 0149df17598..2e3f82bede1 100644
--- a/src/sage/combinat/words/words.py
+++ b/src/sage/combinat/words/words.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Set of words
diff --git a/src/sage/crypto/lattice.py b/src/sage/crypto/lattice.py
index d24b87fe5d4..ce6c63f66f3 100644
--- a/src/sage/crypto/lattice.py
+++ b/src/sage/crypto/lattice.py
@@ -211,7 +211,7 @@ def gen_lattice(type='modular', n=4, m=8, q=11, seed=None,
[-4 -3 2 -5 0 0 0 0 0 1]
]
- sage: sage.crypto.gen_lattice(m=10, q=11, seed=42, lattice=True)
+ sage: sage.crypto.gen_lattice(m=10, q=11, seed=42, lattice=True) # needs fpylll
Free module of degree 10 and rank 10 over Integer Ring
User basis matrix:
[ 0 0 1 1 0 -1 -1 -1 1 0]
diff --git a/src/sage/databases/cremona.py b/src/sage/databases/cremona.py
index 3e1615e5fd4..7b0a3263a32 100644
--- a/src/sage/databases/cremona.py
+++ b/src/sage/databases/cremona.py
@@ -9,10 +9,11 @@
is included by default with Sage. It contains Weierstrass equations,
rank, and torsion for curves up to conductor 10000.
-The large database includes all curves in John Cremona's tables. It
-also includes data related to the BSD conjecture and modular degrees
-for all of these curves, and generators for the Mordell-Weil
-groups. To install it, run the following in the shell::
+The large database includes all curves in John Cremona's tables. It also
+includes data related to the BSD conjecture and modular degrees for all of
+these curves, and generators for the Mordell-Weil groups. To install it via the
+optional :ref:`database_cremona_ellcurve `
+package, run the following command in the shell ::
sage -i database_cremona_ellcurve
diff --git a/src/sage/databases/cubic_hecke_db.py b/src/sage/databases/cubic_hecke_db.py
index b78e582d91e..d25ef5ca630 100644
--- a/src/sage/databases/cubic_hecke_db.py
+++ b/src/sage/databases/cubic_hecke_db.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
r"""
-Cubic Hecke Database
+Cubic Hecke database
This module contains the class :class:`CubicHeckeDataBase` which serves as an
interface to `Ivan Marin's data files
@@ -31,10 +31,25 @@
of linear forms on the cubic Hecke algebra on at most four strands
satisfying the Markov trace condition for its cubic Hecke subalgebras.
+To use the database, you need to install the optional
+:ref:`database_cubic_hecke ` package by the Sage
+command ::
+
+ sage -i database_cubic_hecke
+
+EXAMPLES::
+
+ sage: # optional - database_cubic_hecke
+ sage: from sage.databases.cubic_hecke_db import CubicHeckeDataBase
+ sage: cha_db = CubicHeckeDataBase()
+ sage: cha_db
+
+
AUTHORS:
-- Sebastian Oehms (May 2020): initial version
-- Sebastian Oehms (March 2022): PyPi version and Markov trace functionality
+- Sebastian Oehms (2020-05): initial version
+- Sebastian Oehms (2022-03): PyPi version and Markov trace functionality
+
"""
##############################################################################
diff --git a/src/sage/databases/cunningham_tables.py b/src/sage/databases/cunningham_tables.py
index 9c23bf31816..94862b98561 100644
--- a/src/sage/databases/cunningham_tables.py
+++ b/src/sage/databases/cunningham_tables.py
@@ -1,5 +1,19 @@
r"""
-Cunningham table
+Cunningham tables
+
+This module provides :func:`cunningham_prime_factors`, which lists the prime
+numbers occurring in the factorization of numbers of type `b^n+1` or `b^n-1`
+with `b \in \{2,3,5,6,7,10,11,12\}`. For an introduction to Cunningham prime
+factors, see :wikipedia:`Cunningham_Project`. The data becomes available if you
+install the optional :ref:`cunningham_tables ` package by
+the command ::
+
+ sage -i cunningham_tables
+
+AUTHORS:
+
+- Yann Laigle-Chapuy (2009-10-18): initial version
+
"""
import os
@@ -16,12 +30,25 @@ def cunningham_prime_factors():
They occur in the factorization of numbers of type `b^n+1` or `b^n-1` with `b \in \{2,3,5,6,7,10,11,12\}`.
- Data from http://cage.ugent.be/~jdemeyer/cunningham/
+ EXAMPLES::
+
+ sage: # optional - cunningham_tables
+ sage: from sage.databases.cunningham_tables import cunningham_prime_factors
+ sage: cunningham_prime_factors()
+ [2,
+ 3,
+ 5,
+ 7,
+ 11,
+ 13,
+ 17,
+ ...
"""
file = os.path.join(SAGE_SHARE,'cunningham_tables','cunningham_prime_factors.sobj')
if os.path.exists(file):
return [Integer(_) for _ in load(file)]
else:
from warnings import warn
- warn("You might consider installing the optional package for factoring Cunningham numbers with the following command: ``sage -i cunningham_tables``")
+ warn("You might consider installing the optional package for factoring Cunningham numbers"
+ " with the following command: ``sage -i cunningham_tables``")
return []
diff --git a/src/sage/databases/db_class_polynomials.py b/src/sage/databases/db_class_polynomials.py
index 642865a5d63..923d3a419ee 100644
--- a/src/sage/databases/db_class_polynomials.py
+++ b/src/sage/databases/db_class_polynomials.py
@@ -1,5 +1,23 @@
"""
-Database of Hilbert Polynomials
+Database of Hilbert polynomials
+
+This module gives access to the database of Hilbert class polynomials. To use
+the database, you need to install the optional :ref:`database_kohel
+` package by the Sage command ::
+
+ sage -i database_kohel
+
+EXAMPLES::
+
+ sage: # optional - database_kohel
+ sage: db = HilbertClassPolynomialDatabase()
+ sage: db[32]
+ x^2 - 52250000*x + 12167000000
+
+AUTHORS:
+
+- David Kohel (2006-08-04): initial version
+
"""
# ****************************************************************************
# Copyright (C) 2006 David Kohel
@@ -45,8 +63,9 @@ def __getitem__(self, disc):
r"""
TESTS::
+ sage: # optional - database_kohel
sage: db = HilbertClassPolynomialDatabase()
- sage: db[32] # optional - database_kohel
+ sage: db[32]
x^2 - 52250000*x + 12167000000
sage: db[123913912]
Traceback (most recent call last):
@@ -66,16 +85,17 @@ class HilbertClassPolynomialDatabase(ClassPolynomialDatabase):
EXAMPLES::
+ sage: # optional - database_kohel
sage: db = HilbertClassPolynomialDatabase()
- sage: db[-4] # optional - database_kohel
+ sage: db[-4]
x - 1728
- sage: db[-7] # optional - database_kohel
+ sage: db[-7]
x + 3375
- sage: f = db[-23]; f # optional - database_kohel
+ sage: f = db[-23]; f
x^3 + 3491750*x^2 - 5151296875*x + 12771880859375
- sage: f.discriminant().factor() # optional - database_kohel
+ sage: f.discriminant().factor()
-1 * 5^18 * 7^12 * 11^4 * 17^2 * 19^2 * 23
- sage: db[-23] # optional - database_kohel
+ sage: db[-23]
x^3 + 3491750*x^2 - 5151296875*x + 12771880859375
"""
model = "Cls"
diff --git a/src/sage/databases/db_modular_polynomials.py b/src/sage/databases/db_modular_polynomials.py
index 4e0422539fc..025682c05ae 100644
--- a/src/sage/databases/db_modular_polynomials.py
+++ b/src/sage/databases/db_modular_polynomials.py
@@ -1,5 +1,26 @@
"""
-Database of Modular Polynomials
+Database of modular polynomials
+
+This module gives access to the database of modular polynomials. To use the
+database, you need to install the optional :ref:`database_kohel
+` package by the Sage command ::
+
+ sage -i database_kohel
+
+EXAMPLES::
+
+ sage: # optional - database_kohel
+ sage: DBMP = ClassicalModularPolynomialDatabase()
+ sage: f = DBMP[29]
+ sage: f.degree()
+ 58
+ sage: f.coefficient([28,28])
+ 400152899204646997840260839128
+
+AUTHORS:
+
+- David Kohel (2006-08-04): initial version
+
"""
# ****************************************************************************
# Copyright (C) 2006 William Stein
@@ -48,8 +69,9 @@ def _dbz_to_integer_list(name):
r"""
TESTS::
+ sage: # optional - database_kohel
sage: from sage.databases.db_modular_polynomials import _dbz_to_integer_list
- sage: _dbz_to_integer_list('PolMod/Atk/pol.002.dbz') # optional - database_kohel
+ sage: _dbz_to_integer_list('PolMod/Atk/pol.002.dbz')
[[3, 0, 1],
[2, 1, -1],
[2, 0, 744],
@@ -58,9 +80,9 @@ def _dbz_to_integer_list(name):
[0, 2, 1],
[0, 1, 7256],
[0, 0, 15252992]]
- sage: _dbz_to_integer_list('PolMod/Cls/pol.001.dbz') # optional - database_kohel
+ sage: _dbz_to_integer_list('PolMod/Cls/pol.001.dbz')
[[1, 0, 1]]
- sage: _dbz_to_integer_list('PolMod/Eta/pol.002.dbz') # optional - database_kohel
+ sage: _dbz_to_integer_list('PolMod/Eta/pol.002.dbz')
[[3, 0, 1], [2, 0, 48], [1, 1, -1], [1, 0, 768], [0, 0, 4096]]
"""
from sage.rings.integer import Integer
@@ -130,14 +152,14 @@ def __getitem__(self, level):
EXAMPLES::
+ sage: # optional - database_kohel
sage: DBMP = ClassicalModularPolynomialDatabase()
- sage: f = DBMP[29] # optional - database_kohel
- sage: f.degree() # optional - database_kohel
+ sage: f = DBMP[29]
+ sage: f.degree()
58
- sage: f.coefficient([28,28]) # optional - database_kohel
+ sage: f.coefficient([28,28])
400152899204646997840260839128
-
- sage: DBMP[50] # optional - database_kohel
+ sage: DBMP[50]
Traceback (most recent call last):
...
ValueError: file not found in the Kohel database
diff --git a/src/sage/databases/findstat.py b/src/sage/databases/findstat.py
index 5b8455a49a2..e1e33e2839c 100644
--- a/src/sage/databases/findstat.py
+++ b/src/sage/databases/findstat.py
@@ -1,38 +1,28 @@
# -*- coding: utf-8 -*-
r"""
-FindStat - the Combinatorial Statistic Finder.
+FindStat - the search engine for combinatorial statistics and maps
-The FindStat database can be found at::
+The interface to the FindStat database is ::
sage: findstat()
The Combinatorial Statistic Finder (https://www.findstat.org/)
-Fix the following three notions:
+We use the following three notions
- A *combinatorial collection* is a set `S` with interesting combinatorial properties,
- a *combinatorial map* is a combinatorially interesting map `f: S \to S'` between combinatorial collections, and
- a *combinatorial statistic* is a combinatorially interesting map `s: S \to \ZZ`.
-You can use the sage interface to FindStat to:
+You can use the FindStat interface to
- identify a combinatorial statistic or map given the values on a few small objects,
- obtain more terms, formulae, references, etc. for a given statistic or map,
- edit statistics and maps and submit new statistics.
-AUTHORS:
-
-- Martin Rubey (2015): initial version.
-- Martin Rubey (2020): rewrite, adapt to new FindStat API
-
-The main entry points
----------------------
-.. csv-table::
- :class: contentstable
- :widths: 20, 40
- :delim: |
+The main entry points to the database are
- :func:`findstat` | search for matching statistics.
- :func:`findmap` | search for matching maps.
+- :func:`findstat` to search for matching statistics,
+- :func:`findmap` to search for matching maps.
A guided tour
-------------
@@ -195,8 +185,10 @@ def mapping(sigma):
:meth:`FindStatStatistic.submit` your changes for review by the
FindStat team.
-Classes and methods
--------------------
+AUTHORS:
+
+- Martin Rubey (2015): initial version
+- Martin Rubey (2020): rewrite, adapt to new FindStat API
"""
# ****************************************************************************
@@ -910,7 +902,7 @@ def findstat(query=None, values=None, distribution=None, domain=None,
must be ``None``.
- a list of pairs of the form ``(object, value)``, or a
- dictionary from sage objects to integer values. The keyword
+ dictionary from Sage objects to integer values. The keyword
arguments ``depth`` and ``max_values`` are passed to the
finder, ``values`` and ``distribution`` must be ``None``.
@@ -1163,7 +1155,7 @@ def findmap(*args, **kwargs):
forms:
- a list of pairs of the form ``(object, value)``, or a
- dictionary from sage objects to sage objects.
+ dictionary from Sage objects to Sage objects.
- a list of pairs of the form ``(list of objects, list of
values)``, or a single pair of the form ``(list of objects,
@@ -1763,7 +1755,7 @@ def set_references_raw(self, value):
def sage_code(self):
r"""
- Return the sage code associated with the statistic or map.
+ Return the Sage code associated with the statistic or map.
OUTPUT:
@@ -1842,7 +1834,7 @@ def first_terms(self):
OUTPUT:
- A dictionary from sage objects representing an element of the
+ A dictionary from Sage objects representing an element of the
appropriate collection to integers.
This method is overridden in :class:`FindStatStatisticQuery`.
@@ -2261,7 +2253,7 @@ def set_first_terms(self, values):
INPUT:
- a list of pairs of the form ``(object, value)`` where
- ``object`` is a sage object representing an element of the
+ ``object`` is a Sage object representing an element of the
appropriate collection and ``value`` is an integer.
This information is used when submitting the statistic with
@@ -2298,7 +2290,7 @@ def code(self):
OUTPUT:
- A string. Contributors are encouraged to submit sage code in the form::
+ A string. Contributors are encouraged to submit Sage code in the form::
def statistic(x):
...
@@ -4061,9 +4053,9 @@ class FindStatCollection(Element,
- an integer designating the FindStat id of the collection, or
- - a sage object belonging to a collection, or
+ - a Sage object belonging to a collection, or
- - an iterable producing a sage object belonging to a collection.
+ - an iterable producing a Sage object belonging to a collection.
EXAMPLES::
@@ -4277,7 +4269,7 @@ def in_range(self, element):
INPUT:
- - ``element`` -- a sage object that belongs to the collection.
+ - ``element`` -- a Sage object that belongs to the collection.
OUTPUT:
@@ -4452,7 +4444,7 @@ def from_string(self):
OUTPUT:
- The function that produces the sage object given its FindStat
+ The function that produces the Sage object given its FindStat
representation as a string.
EXAMPLES::
diff --git a/src/sage/databases/jones.py b/src/sage/databases/jones.py
index 26d4dbaa373..aaab1397f0a 100644
--- a/src/sage/databases/jones.py
+++ b/src/sage/databases/jones.py
@@ -1,9 +1,10 @@
r"""
John Jones's tables of number fields
-In order to use the Jones database, the optional database package
-must be installed using the Sage command !sage -i
-database_jones_numfield
+In order to use the Jones database, the optional :ref:`database_jones_numfield
+` package must be installed using the Sage command ::
+
+ sage -i database_jones_numfield
This is a table of number fields with bounded ramification and
degree `\leq 6`. You can query the database for all number
diff --git a/src/sage/databases/knotinfo_db.py b/src/sage/databases/knotinfo_db.py
index df0b8310456..72e39796965 100644
--- a/src/sage/databases/knotinfo_db.py
+++ b/src/sage/databases/knotinfo_db.py
@@ -1,15 +1,29 @@
# -*- coding: utf-8 -*-
r"""
-KnotInfo Database
+KnotInfo database
-This module contains the class :class:`KnotInfoDataBase` and auxiliary classes
-for it which serves as an interface to the lists of named knots and links provided
+This module contains the class :class:`KnotInfoDataBase` and auxiliary classes
+for it, which serves as an interface to the lists of named knots and links provided
at the web-pages `KnotInfo `__ and
`LinkInfo `__.
+To use the database, you need to install the optional :ref:`database_knotinfo
+` package by the Sage command ::
+
+ sage -i database_knotinfo
+
+EXAMPLES::
+
+ sage: # optional - database_knotinfo
+ sage: from sage.databases.knotinfo_db import KnotInfoDataBase
+ sage: ki_db = KnotInfoDataBase()
+ sage: ki_db
+
+
AUTHORS:
-- Sebastian Oehms August 2020: initial version
+- Sebastian Oehms (2020-08): initial version
+
"""
##############################################################################
# Copyright (C) 2020 Sebastian Oehms
diff --git a/src/sage/databases/odlyzko.py b/src/sage/databases/odlyzko.py
index 547baad0625..4ee78b7de0a 100644
--- a/src/sage/databases/odlyzko.py
+++ b/src/sage/databases/odlyzko.py
@@ -1,12 +1,19 @@
"""
-Tables of zeros of the Riemann-Zeta function
+Database of the zeros of the Riemann zeta function
+
+The main access function to the database of the zeros of the Riemann zeta
+function is :func:`zeta_zeros`. In order to use ``zeta_zeros()``, you need to
+install the optional :ref:`database_odlyzko_zeta `
+package::
+
+ sage -i database_odlyzko_zeta
AUTHORS:
- William Stein: initial version
+- Jeroen Demeyer (2015-01-20): converted ``database_odlyzko_zeta`` to new-style
+ package
-- Jeroen Demeyer (2015-01-20): convert ``database_odlyzko_zeta`` to
- new-style package
"""
#*****************************************************************************
@@ -30,27 +37,20 @@ def zeta_zeros():
List of the imaginary parts of the first 2,001,052 zeros of the
Riemann zeta function, accurate to within 4e-9.
- In order to use ``zeta_zeros()``, you will need to
- install the optional Odlyzko database package::
-
- sage -i database_odlyzko_zeta
-
- You can see a list of all available optional packages with
- ``sage --optional``.
-
REFERENCES:
- http://www.dtc.umn.edu/~odlyzko/zeta_tables/index.html
EXAMPLES:
- The following example prints the imaginary part of the 13th
+ The following example shows the imaginary part of the 13th
nontrivial zero of the Riemann zeta function::
- sage: zz = zeta_zeros() # optional - database_odlyzko_zeta
- sage: zz[12] # optional - database_odlyzko_zeta
+ sage: # optional - database_odlyzko_zeta
+ sage: zz = zeta_zeros()
+ sage: zz[12]
59.347044003
- sage: len(zz) # optional - database_odlyzko_zeta
+ sage: len(zz)
2001052
"""
from sage.misc.verbose import verbose
diff --git a/src/sage/databases/oeis.py b/src/sage/databases/oeis.py
index b6eeac3499c..e40ebc7c539 100644
--- a/src/sage/databases/oeis.py
+++ b/src/sage/databases/oeis.py
@@ -8,17 +8,6 @@
- identify a sequence from its first terms.
- obtain more terms, formulae, references, etc. for a given sequence.
-AUTHORS:
-
-- Thierry Monteil (2012-02-10 -- 2013-06-21): initial version.
-
-- Vincent Delecroix (2014): modifies continued fractions because of :trac:`14567`
-
-- Moritz Firsching (2016): modifies handling of dead sequence, see :trac:`17330`
-
-- Thierry Monteil (2019): refactorization (unique representation :trac:`28480`,
- laziness :trac:`28627`)
-
EXAMPLES::
sage: oeis
@@ -134,13 +123,14 @@
- Some infinite OEIS sequences are implemented in Sage, via the
:mod:`sloane_functions ` module.
-.. TODO::
+AUTHORS:
- - in case of flood, suggest the user to install the off-line database instead.
- - interface with the off-line database (or reimplement it).
+- Thierry Monteil (2012-02-10 -- 2013-06-21): initial version.
+- Vincent Delecroix (2014): modifies continued fractions because of :trac:`14567`
+- Moritz Firsching (2016): modifies handling of dead sequence, see :trac:`17330`
+- Thierry Monteil (2019): refactorization (unique representation :trac:`28480`,
+ laziness :trac:`28627`)
-Classes and methods
--------------------
"""
# ****************************************************************************
@@ -732,7 +722,7 @@ def online_update(self):
except AttributeError:
pass
- def _field(self, key):
+ def _field(self, key, warn=True):
r"""
Return the ``key`` field of the entry of ``self``.
@@ -751,7 +741,7 @@ def _field(self, key):
for line in self.raw_entry().splitlines():
fields[line[1]].append(line[11:])
self._fields = fields
- self.is_dead(warn_only=True)
+ self.is_dead(warn_only=warn)
return self._fields[key]
def id(self, format='A'):
@@ -969,7 +959,7 @@ def author(self):
"""
return self._field('A')[0]
- def keywords(self):
+ def keywords(self, warn=True):
r"""
Return the keywords associated to the sequence ``self``.
@@ -995,7 +985,7 @@ def keywords(self):
sage: s.keywords()
('nonn', 'hard')
"""
- return tuple(self._field('K')[0].split(','))
+ return tuple(self._field('K', warn=warn)[0].split(','))
def natural_object(self):
r"""
@@ -1118,8 +1108,8 @@ def is_dead(self, warn_only=False):
EXAMPLES:
- A warn_only test is triggered as soon as some information on the
- sequence is queried::
+ A warning is triggered if any field of a dead sequence is accessed,
+ unless :meth:`is_dead` is called before::
sage: s = oeis(17)
sage: s # optional -- internet
@@ -1148,11 +1138,11 @@ def is_dead(self, warn_only=False):
True
"""
if warn_only:
- if 'dead' in self.keywords():
+ if 'dead' in self.keywords(warn_only):
from warnings import warn
warn('This sequence is dead: "{}: {}"'.format(self.id(), self.name()), RuntimeWarning)
else:
- return 'dead' in self.keywords()
+ return 'dead' in self.keywords(warn_only)
def is_finite(self):
r"""
@@ -2020,6 +2010,7 @@ def test_compile_sage_code(self):
True
"""
if self.is_dead():
+ self.is_dead(warn_only=True)
return True
filt = self.programs(language='sage')
if filt:
diff --git a/src/sage/databases/sloane.py b/src/sage/databases/sloane.py
index d5802620066..61825257470 100644
--- a/src/sage/databases/sloane.py
+++ b/src/sage/databases/sloane.py
@@ -1,8 +1,8 @@
"""
-Local copy of Sloane On-Line Encyclopedia of Integer Sequences
+Local copy of the On-Line Encyclopedia of Integer Sequences
-The SloaneEncyclopedia object provides access to a local copy of the database
-containing only the sequences and their names. To use this you must download
+The ``SloaneEncyclopedia`` object provides access to a local copy of the database
+containing only the sequences and their names. To use this, you must download
and install the database using ``SloaneEncyclopedia.install()``, or
``SloaneEncyclopedia.install_from_gz()`` if you have already downloaded the
database manually.
@@ -11,14 +11,14 @@
::
- sage: SloaneEncyclopedia[60843] # optional - sloane_database
+ sage: SloaneEncyclopedia[60843] # optional - sloane_database
[1, 6, 21, 107]
To get the name of a sequence, type
::
- sage: SloaneEncyclopedia.sequence_name(1) # optional - sloane_database
+ sage: SloaneEncyclopedia.sequence_name(1) # optional - sloane_database
'Number of groups of order n.'
To search locally for a particular subsequence, type
@@ -33,7 +33,7 @@
::
- sage: SloaneEncyclopedia.find([1,2,3,4,5], 100) # optional - sloane_database
+ sage: SloaneEncyclopedia.find([1,2,3,4,5], 100) # optional - sloane_database
[(15, [1, 2, 3, 4, 5, 7, 7, 8, 9, 11, 11, ...
Results in either case are of the form [ (number, list) ].
@@ -65,11 +65,9 @@
sequence_name() to return the description of a sequence; and changed
the data type for elements of each sequence from int to Integer.
-- Thierry Monteil (2012-02-10): deprecate dead code and update related doc and
+- Thierry Monteil (2012-02-10): deprecated dead code and update related doc and
tests.
-Classes and methods
--------------------
"""
# ****************************************************************************
@@ -265,7 +263,8 @@ def load(self):
try:
file_seq = bz2.BZ2File(self.__file__, 'r')
except IOError:
- raise IOError("The Sloane Encyclopedia database must be installed. Use e.g. 'SloaneEncyclopedia.install()' to download and install it.")
+ raise IOError("The Sloane Encyclopedia database must be installed."
+ " Use e.g. 'SloaneEncyclopedia.install()' to download and install it.")
self.__data__ = {}
@@ -295,7 +294,8 @@ def load(self):
self.__loaded_names__ = True
except KeyError:
# Some sequence in the names file is not in the database
- raise KeyError("Sloane OEIS sequence and name files do not match. Try reinstalling, e.g. SloaneEncyclopedia.install(overwrite=True).")
+ raise KeyError("Sloane OEIS sequence and name files do not match."
+ " Try reinstalling, e.g. SloaneEncyclopedia.install(overwrite=True).")
except IOError:
# The names database is not installed
self.__loaded_names__ = False
@@ -323,7 +323,8 @@ def sequence_name(self, N):
"""
self.load()
if not self.__loaded_names__:
- raise IOError("The Sloane OEIS names file is not installed. Try reinstalling, e.g. SloaneEncyclopedia.install(overwrite=True).")
+ raise IOError("The Sloane OEIS names file is not installed."
+ " Try reinstalling, e.g. SloaneEncyclopedia.install(overwrite=True).")
if N not in self.__data__: # sequence N does not exist
return ''
diff --git a/src/sage/databases/stein_watkins.py b/src/sage/databases/stein_watkins.py
index 6abf39426dd..fa5f338391a 100644
--- a/src/sage/databases/stein_watkins.py
+++ b/src/sage/databases/stein_watkins.py
@@ -1,18 +1,16 @@
r"""
The Stein-Watkins table of elliptic curves
-Sage gives access to the Stein-Watkins table of elliptic curves, via an
-optional package that you must install. This is a huge database of elliptic
-curves. You can install the database (a 2.6GB package) with the command
-
-::
+Sage gives access to the Stein-Watkins table of elliptic curves, via the
+optional :ref:`database_stein_watkins ` package
+that you must install. This is a huge database of elliptic curves. You can
+install the database (a 2.6GB package) with the command ::
sage -i database_stein_watkins
You can also automatically download a small version, which takes much less
-time, using the command
-
-::
+time, via the optional :ref:`database_stein_watkins_mini `
+package using the command ::
sage -i database_stein_watkins_mini
diff --git a/src/sage/databases/symbolic_data.py b/src/sage/databases/symbolic_data.py
index 7703a2216e5..083b3ced668 100644
--- a/src/sage/databases/symbolic_data.py
+++ b/src/sage/databases/symbolic_data.py
@@ -1,16 +1,15 @@
"""
Ideals from the Symbolic Data project
-This file implements a thin wrapper for the optional symbolic data set
-of ideals as published on http://www.symbolicdata.org . From the
-project website:
+This module implements a thin wrapper for the optional symbolic dataset of
+ideals as published on http://www.symbolicdata.org. From the project website:
- For different purposes algorithms and implementations are tested
+ For different purposes, algorithms and implementations are tested
on certified and reliable data. The development of tools and data
for such tests is usually 'orthogonal' to the main
implementation efforts, it requires different skills and
technologies and is not loved by programmers. On the other hand,
- in many cases tools and data could easily be reused - with slight
+ in many cases, tools and data could easily be reused - with slight
modifications - across similar projects. The SymbolicData Project
is set out to coordinate such efforts within the Computer Algebra
Community. Commonly collected certified and reliable data can
@@ -21,32 +20,36 @@
there are not yet well agreed aims of such a
benchmarking. Nevertheless various (often high quality) special
benchmarks are scattered through the literature. During the last
- years efforts toward collection of test data for symbolic
+ years, efforts toward collection of test data for symbolic
computations were intensified. They focused mainly on the creation
of general benchmarks for different areas of symbolic computation
and the collection of such activities on different Web site. For
- further qualification of these efforts it would be of great
+ further qualification of these efforts, it would be of great
benefit to create a commonly available digital archive of these
special benchmark data scattered through the literature. This
would provide the community with an electronic repository of
certified data that could be addressed and extended during further
development.
+In order to use this dataset, you need to install the optional
+:ref:`database_symbolic_data ` package by the Sage
+command ::
+
+ sage -i database_symbolic_data
+
EXAMPLES::
- sage: sd = SymbolicData(); sd # optional - database_symbolic_data
+ sage: # optional - database_symbolic_data
+ sage: sd = SymbolicData(); sd
SymbolicData with 372 ideals
-
- sage: sd.ZeroDim__example_1 # optional - database_symbolic_data
+ sage: sd.ZeroDim__example_1
Ideal (x1^2 + x2^2 - 10, x1^2 + x1*x2 + 2*x2^2 - 16) of Multivariate Polynomial Ring in x1, x2 over Rational Field
-
- sage: sd.Katsura_3 # optional - database_symbolic_data
+ sage: sd.Katsura_3
Ideal (u0 + 2*u1 + 2*u2 + 2*u3 - 1,
u1^2 + 2*u0*u2 + 2*u1*u3 - u2,
2*u0*u1 + 2*u1*u2 + 2*u2*u3 - u1,
u0^2 + 2*u1^2 + 2*u2^2 + 2*u3^2 - u0) of Multivariate Polynomial Ring in u0, u1, u2, u3 over Rational Field
-
- sage: sd.get_ideal('Katsura_3',GF(127),'degrevlex') # optional - database_symbolic_data
+ sage: sd.get_ideal('Katsura_3', GF(127), 'degrevlex')
Ideal (u0 + 2*u1 + 2*u2 + 2*u3 - 1,
u1^2 + 2*u0*u2 + 2*u1*u3 - u2,
2*u0*u1 + 2*u1*u2 + 2*u2*u3 - u1,
@@ -54,8 +57,20 @@
AUTHORS:
-- Martin Albrecht
+- Martin Albrecht (2007-02-19): initial version
+
"""
+
+# ****************************************************************************
+# Copyright (C) 2007 Martin Albrecht
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+# https://www.gnu.org/licenses/
+# ****************************************************************************
+
import os
from xml.dom.minidom import parse
from sage.rings.rational_field import QQ
@@ -90,13 +105,11 @@ def get_ideal(self, name, base_ring=QQ, term_order="degrevlex"):
INPUT:
- - ``name`` - name as on the symbolic data website
- - ``base_ring`` - base ring for the polynomial ring (default: ``QQ``)
- - ``term_order`` - term order for the polynomial ring (default: ``degrevlex``)
-
- OUTPUT:
+ - ``name`` -- name as on the symbolic data website
+ - ``base_ring`` -- base ring for the polynomial ring (default: ``QQ``)
+ - ``term_order`` -- term order for the polynomial ring (default: ``degrevlex``)
- ideal as given by ``name`` in ``PolynomialRing(base_ring,vars,term_order)``
+ OUTPUT: ideal as given by ``name`` in ``PolynomialRing(base_ring,vars,term_order)``
EXAMPLES::
diff --git a/src/sage/doctest/forker.py b/src/sage/doctest/forker.py
index 4315cd1ba9f..efd28d10abe 100644
--- a/src/sage/doctest/forker.py
+++ b/src/sage/doctest/forker.py
@@ -1806,12 +1806,13 @@ def parallel_dispatch(self):
job_client = None
try:
from gnumake_tokenpool import JobClient, NoJobServer
+ except ImportError:
+ pass
+ else:
try:
- job_client = JobClient()
+ job_client = JobClient(use_cysignals=True)
except NoJobServer:
pass
- except ImportError:
- pass
source_iter = iter(self.controller.sources)
diff --git a/src/sage/doctest/sources.py b/src/sage/doctest/sources.py
index 8c7b29bf1d4..cae09766f5d 100644
--- a/src/sage/doctest/sources.py
+++ b/src/sage/doctest/sources.py
@@ -238,7 +238,7 @@ def _process_doc(self, doctests, doc, namespace, start):
# Line number refers to the end of the docstring
sigon = doctest.Example(sig_on_count_doc_doctest, "0\n", lineno=docstring.count("\n"))
sigon.sage_source = sig_on_count_doc_doctest
- sigon.optional_tags = frozenset()
+ sigon.optional_tags = frozenset(self.file_optional_tags)
sigon.probed_tags = frozenset()
dt.examples.append(sigon)
doctests.append(dt)
diff --git a/src/sage/dynamics/cellular_automata/solitons.py b/src/sage/dynamics/cellular_automata/solitons.py
index 4afb3f104a2..72ec9ed0104 100644
--- a/src/sage/dynamics/cellular_automata/solitons.py
+++ b/src/sage/dynamics/cellular_automata/solitons.py
@@ -73,7 +73,7 @@ class SolitonCellularAutomata(SageObject):
current state:
34......224....2223
- We then apply an standard evolution::
+ We then apply a standard evolution::
sage: B.evolve()
sage: B
diff --git a/src/sage/env.py b/src/sage/env.py
index a221f33bb82..39d09528788 100644
--- a/src/sage/env.py
+++ b/src/sage/env.py
@@ -177,7 +177,8 @@ def var(key: str, *fallbacks: Optional[str], force: bool = False) -> Optional[st
SAGE_LOCAL = var("SAGE_LOCAL", SAGE_VENV)
SAGE_SHARE = var("SAGE_SHARE", join(SAGE_LOCAL, "share"))
SAGE_DOC = var("SAGE_DOC", join(SAGE_SHARE, "doc", "sage"))
-SAGE_SPKG_INST = var("SAGE_SPKG_INST", join(SAGE_LOCAL, "var", "lib", "sage", "installed"))
+SAGE_LOCAL_SPKG_INST = var("SAGE_LOCAL_SPKG_INST", join(SAGE_LOCAL, "var", "lib", "sage", "installed"))
+SAGE_SPKG_INST = var("SAGE_SPKG_INST", join(SAGE_LOCAL, "var", "lib", "sage", "installed")) # deprecated
# source tree of the Sage distribution
SAGE_ROOT = var("SAGE_ROOT") # no fallback for SAGE_ROOT
@@ -198,8 +199,7 @@ def var(key: str, *fallbacks: Optional[str], force: bool = False) -> Optional[st
GRAPHS_DATA_DIR = var("GRAPHS_DATA_DIR", join(SAGE_SHARE, "graphs"))
ELLCURVE_DATA_DIR = var("ELLCURVE_DATA_DIR", join(SAGE_SHARE, "ellcurves"))
POLYTOPE_DATA_DIR = var("POLYTOPE_DATA_DIR", join(SAGE_SHARE, "reflexive_polytopes"))
-GAP_LIB_DIR = var("GAP_LIB_DIR", join(SAGE_LOCAL, "lib", "gap"))
-GAP_SHARE_DIR = var("GAP_SHARE_DIR", join(SAGE_SHARE, "gap"))
+
COMBINATORIAL_DESIGN_DATA_DIR = var("COMBINATORIAL_DESIGN_DATA_DIR", join(SAGE_SHARE, "combinatorial_designs"))
CREMONA_MINI_DATA_DIR = var("CREMONA_MINI_DATA_DIR", join(SAGE_SHARE, "cremona"))
CREMONA_LARGE_DATA_DIR = var("CREMONA_LARGE_DATA_DIR", join(SAGE_SHARE, "cremona"))
@@ -243,11 +243,13 @@ def var(key: str, *fallbacks: Optional[str], force: bool = False) -> Optional[st
# GAP memory and args
SAGE_GAP_MEMORY = var('SAGE_GAP_MEMORY', None)
-_gap_cmd = "gap -r"
-if SAGE_GAP_MEMORY is not None:
- _gap_cmd += " -s " + SAGE_GAP_MEMORY + " -o " + SAGE_GAP_MEMORY
-SAGE_GAP_COMMAND = var('SAGE_GAP_COMMAND', _gap_cmd)
+SAGE_GAP_COMMAND = var('SAGE_GAP_COMMAND', None)
+# The semicolon-separated search path for GAP packages. It is passed
+# directly to GAP via the -l flag.
+GAP_ROOT_PATHS = var("GAP_ROOT_PATHS",
+ ";".join([join(SAGE_LOCAL, "lib", "gap"),
+ join(SAGE_LOCAL, "share", "gap")]))
# post process
if DOT_SAGE is not None and ' ' in DOT_SAGE:
diff --git a/src/sage/ext/fast_callable.pyx b/src/sage/ext/fast_callable.pyx
index 0a1439b7530..962b743b0c8 100644
--- a/src/sage/ext/fast_callable.pyx
+++ b/src/sage/ext/fast_callable.pyx
@@ -576,7 +576,8 @@ def function_name(fn):
Given a function, return a string giving a name for the function.
For functions we recognize, we use our standard opcode name for the
- function (so operator.add becomes 'add', and sage.all.sin becomes 'sin').
+ function (so :func:`operator.add` becomes ``'add'``, and :func:`sage.functions.trig.sin`
+ becomes ``'sin'``).
For functions we don't recognize, we try to come up with a name,
but the name will be wrapped in braces; this is a signal that
diff --git a/src/sage/ext_data/gap/sage.g b/src/sage/ext_data/gap/sage.g
index 36e131146d6..ddca6e3fb44 100644
--- a/src/sage/ext_data/gap/sage.g
+++ b/src/sage/ext_data/gap/sage.g
@@ -134,3 +134,17 @@ end;
#
# LogTo("/tmp/gapsage.log");
#
+
+
+# Load the GAP packages that GAP itself tries to autoload in the
+# default configuration (see "PackagesToLoad" in lib/package.gi). The
+# combination of passing -A to gap and these LoadPackage statements
+# allows us to load the usual set of packages, but only if they are
+# installed. So most people will get exactly the default behavior,
+# but minimal installations won't throw warnings and fail tests.
+_autoloads := [ "autpgrp", "alnuth", "crisp", "ctbllib", "factint", "fga",
+ "irredsol", "laguna", "polenta", "polycyclic", "resclasses",
+ "sophus", "tomlib" ];
+for p in _autoloads do
+ LoadPackage(p);
+od;
diff --git a/src/sage/ext_data/graphs/graph_plot_js.html b/src/sage/ext_data/graphs/graph_plot_js.html
index 75d08f91662..c56ea71e2d0 100644
--- a/src/sage/ext_data/graphs/graph_plot_js.html
+++ b/src/sage/ext_data/graphs/graph_plot_js.html
@@ -237,7 +237,7 @@
return [cx+d*nx/nn,cy+d*ny/nn]
}
- // Applies an homothety to the points of the graph respecting the
+ // Applies a homothety to the points of the graph respecting the
// aspect ratio, so that the graph takes the whole javascript
// window and is centered
function center_and_scale(graph){
diff --git a/src/sage/features/__init__.py b/src/sage/features/__init__.py
index be55d44d0c2..d5669c3c9ff 100644
--- a/src/sage/features/__init__.py
+++ b/src/sage/features/__init__.py
@@ -236,7 +236,7 @@ def require(self):
Traceback (most recent call last):
...
FeatureNotPresentError: gap_package_ve1EeThu is not available.
- `TestPackageAvailability("ve1EeThu")` evaluated to `fail` in GAP.
+ `LoadPackage("ve1EeThu")` evaluated to `fail` in GAP.
"""
presence = self.is_present()
if not presence:
@@ -393,22 +393,25 @@ def unhide(self):
EXAMPLES:
- Polycyclic is a standard GAP package since 4.10 (see :trac:`26856`). The
- following test just fails if it is hidden. Thus, in the second
- invocation no optional tag is needed::
+ PolyCyclic is an optional GAP package. The following test
+ fails if it is hidden, regardless of whether it is installed
+ or not::
sage: from sage.features.gap import GapPackage
sage: Polycyclic = GapPackage("polycyclic", spkg="gap_packages")
sage: Polycyclic.hide()
- sage: libgap(AbelianGroup(3, [0,3,4], names="abc")) # needs sage.libs.gap
+ sage: libgap(AbelianGroup(3, [0,3,4], names="abc")) # needs sage.libs.gap # optional - gap_packages_polycyclic
Traceback (most recent call last):
...
FeatureNotPresentError: gap_package_polycyclic is not available.
Feature `gap_package_polycyclic` is hidden.
Use method `unhide` to make it available again.
+ After unhiding the feature, the test should pass again if PolyCyclic
+ is installed and loaded::
+
sage: Polycyclic.unhide()
- sage: libgap(AbelianGroup(3, [0,3,4], names="abc")) # needs sage.libs.gap
+ sage: libgap(AbelianGroup(3, [0,3,4], names="abc")) # needs sage.libs.gap # optional - gap_packages_polycyclic
Pcp-group with orders [ 0, 3, 4 ]
"""
self._hidden = False
@@ -451,7 +454,7 @@ def __str__(self):
Traceback (most recent call last):
...
FeatureNotPresentError: gap_package_gapZuHoh8Uu is not available.
- `TestPackageAvailability("gapZuHoh8Uu")` evaluated to `fail` in GAP.
+ `LoadPackage("gapZuHoh8Uu")` evaluated to `fail` in GAP.
"""
lines = ["{feature} is not available.".format(feature=self.feature.name)]
if self.reason:
@@ -481,7 +484,7 @@ class FeatureTestResult():
``resolution``::
sage: presence.reason # needs sage.libs.gap
- '`TestPackageAvailability("NOT_A_PACKAGE")` evaluated to `fail` in GAP.'
+ '`LoadPackage("NOT_A_PACKAGE")` evaluated to `fail` in GAP.'
sage: bool(presence.resolution)
False
diff --git a/src/sage/features/gap.py b/src/sage/features/gap.py
index a989dcfc1fb..df5545e9c07 100644
--- a/src/sage/features/gap.py
+++ b/src/sage/features/gap.py
@@ -19,6 +19,9 @@ class GapPackage(Feature):
r"""
A :class:`~sage.features.Feature` describing the presence of a GAP package.
+ A GAP package is "present" if it *can be* loaded, not if it *has
+ been* loaded.
+
.. SEEALSO::
:class:`Feature sage.libs.gap <~sage.features.sagemath.sage__libs__gap>`
@@ -42,9 +45,10 @@ def __init__(self, package, **kwds):
def _is_present(self):
r"""
- Return whether the package is available in GAP.
+ Return whether or not the GAP package is present.
- This does not check whether this package is functional.
+ If the package is installed but not yet loaded, it is loaded
+ first. This does *not* check that the package is functional.
EXAMPLES::
@@ -57,8 +61,11 @@ def _is_present(self):
except ImportError:
return FeatureTestResult(self, False,
reason="sage.libs.gap is not available")
- command = 'TestPackageAvailability("{package}")'.format(package=self.package)
+
+ # This returns "true" even if the package is already loaded.
+ command = 'LoadPackage("{package}")'.format(package=self.package)
presence = libgap.eval(command)
+
if presence:
return FeatureTestResult(self, True,
reason="`{command}` evaluated to `{presence}` in GAP.".format(command=command, presence=presence))
diff --git a/src/sage/features/nauty.py b/src/sage/features/nauty.py
index ebd2daeb311..4a07264f927 100644
--- a/src/sage/features/nauty.py
+++ b/src/sage/features/nauty.py
@@ -24,7 +24,7 @@ class NautyExecutable(Executable):
EXAMPLES::
sage: from sage.features.nauty import NautyExecutable
- sage: NautyExecutable('converseg').is_present() # optional - nauty
+ sage: NautyExecutable('converseg').is_present() # needs nauty
FeatureTestResult('nauty_converseg', True)
"""
def __init__(self, name):
@@ -49,7 +49,7 @@ class Nauty(JoinFeature):
EXAMPLES::
sage: from sage.features.nauty import Nauty
- sage: Nauty().is_present() # optional - nauty
+ sage: Nauty().is_present() # needs nauty
FeatureTestResult('nauty', True)
"""
def __init__(self):
@@ -62,7 +62,7 @@ def __init__(self):
"""
JoinFeature.__init__(self, "nauty",
[NautyExecutable(name)
- for name in ('directg', 'gentourng', 'geng', 'genbg', 'gentreeg', 'converseg')])
+ for name in ('directg', 'gentourng', 'geng', 'genbg', 'gentreeg', 'genktreeg')])
def all_features():
diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py
index 4097d3512b9..dd48c55ee6b 100644
--- a/src/sage/features/sagemath.py
+++ b/src/sage/features/sagemath.py
@@ -311,6 +311,29 @@ def __init__(self):
spkg='sagemath_groups', type='standard')
+class sage__libs__braiding(PythonModule):
+ r"""
+ A :class:`~sage.features.Feature` describing the presence of :mod:`sage.libs.braiding`.
+
+ EXAMPLES::
+
+ sage: from sage.features.sagemath import sage__libs__braiding
+ sage: sage__libs__braiding().is_present() # needs sage.libs.braiding
+ FeatureTestResult('sage.libs.braiding', True)
+ """
+
+ def __init__(self):
+ r"""
+ TESTS::
+
+ sage: from sage.features.sagemath import sage__libs__braiding
+ sage: isinstance(sage__libs__braiding(), sage__libs__braiding)
+ True
+ """
+ PythonModule.__init__(self, 'sage.libs.braiding',
+ spkg='sagemath_libbraiding', type='standard')
+
+
class sage__libs__ecl(PythonModule):
r"""
A :class:`~sage.features.Feature` describing the presence of :mod:`sage.libs.ecl`.
@@ -330,7 +353,8 @@ def __init__(self):
sage: isinstance(sage__libs__ecl(), sage__libs__ecl)
True
"""
- PythonModule.__init__(self, 'sage.libs.ecl')
+ PythonModule.__init__(self, 'sage.libs.ecl',
+ spkg='sagemath_symbolics', type='standard')
class sage__libs__flint(JoinFeature):
@@ -1076,6 +1100,7 @@ def all_features():
sage__geometry__polyhedron(),
sage__graphs(),
sage__groups(),
+ sage__libs__braiding(),
sage__libs__ecl(),
sage__libs__flint(),
sage__libs__gap(),
diff --git a/src/sage/game_theory/gambit_docs.py b/src/sage/game_theory/gambit_docs.py
index fae37766c96..b2d8af991e9 100644
--- a/src/sage/game_theory/gambit_docs.py
+++ b/src/sage/game_theory/gambit_docs.py
@@ -115,18 +115,19 @@
converted to Python integers (due to the preparser). Here is an example
showing the Battle of the Sexes::
- sage: import gambit # optional - gambit
- sage: g = gambit.Game.new_table([2,2]) # optional - gambit
- sage: g[int(0), int(0)][int(0)] = int(2) # optional - gambit
- sage: g[int(0), int(0)][int(1)] = int(1) # optional - gambit
- sage: g[int(0), int(1)][int(0)] = int(0) # optional - gambit
- sage: g[int(0), int(1)][int(1)] = int(0) # optional - gambit
- sage: g[int(1), int(0)][int(0)] = int(0) # optional - gambit
- sage: g[int(1), int(0)][int(1)] = int(0) # optional - gambit
- sage: g[int(1), int(1)][int(0)] = int(1) # optional - gambit
- sage: g[int(1), int(1)][int(1)] = int(2) # optional - gambit
- sage: solver = gambit.nash.ExternalLCPSolver() # optional - gambit
- sage: solver.solve(g) # optional - gambit
+ sage: # optional - gambit
+ sage: import gambit
+ sage: g = gambit.Game.new_table([2,2])
+ sage: g[int(0), int(0)][int(0)] = int(2)
+ sage: g[int(0), int(0)][int(1)] = int(1)
+ sage: g[int(0), int(1)][int(0)] = int(0)
+ sage: g[int(0), int(1)][int(1)] = int(0)
+ sage: g[int(1), int(0)][int(0)] = int(0)
+ sage: g[int(1), int(0)][int(1)] = int(0)
+ sage: g[int(1), int(1)][int(0)] = int(1)
+ sage: g[int(1), int(1)][int(1)] = int(2)
+ sage: solver = gambit.nash.ExternalLCPSolver()
+ sage: solver.solve(g)
[,
,
]
diff --git a/src/sage/game_theory/normal_form_game.py b/src/sage/game_theory/normal_form_game.py
index 811e00aec62..275907d7276 100644
--- a/src/sage/game_theory/normal_form_game.py
+++ b/src/sage/game_theory/normal_form_game.py
@@ -72,7 +72,8 @@
sage: B = matrix([[2, 1], [0, 3]])
sage: battle_of_the_sexes = NormalFormGame([A, B])
sage: battle_of_the_sexes
- Normal Form Game with the following utilities: {(0, 0): [3, 2], (0, 1): [1, 1], (1, 0): [0, 0], (1, 1): [2, 3]}
+ Normal Form Game with the following utilities: {(0, 0): [3, 2],
+ (0, 1): [1, 1], (1, 0): [0, 0], (1, 1): [2, 3]}
To obtain the Nash equilibria we run the ``obtain_nash()`` method. In the
first few examples, we will use the 'support enumeration' algorithm.
@@ -159,8 +160,10 @@
sage: y = var('y')
sage: A = matrix([[1, -1], [-1, 1]])
- sage: p = plot((A * vector([y, 1 - y]))[0], y, 0, 1, color='blue', legend_label='$u_1(r_1, (y, 1-y))$', axes_labels=['$y$', ''])
- sage: p += plot((A * vector([y, 1 - y]))[1], y, 0, 1, color='red', legend_label='$u_1(r_2, (y, 1-y))$'); p
+ sage: p = plot((A * vector([y, 1 - y]))[0], y, 0, 1, color='blue',
+ ....: legend_label='$u_1(r_1, (y, 1-y))$', axes_labels=['$y$', ''])
+ sage: p += plot((A * vector([y, 1 - y]))[1], y, 0, 1, color='red',
+ ....: legend_label='$u_1(r_2, (y, 1-y))$'); p
Graphics object consisting of 2 graphics primitives
We see that the only point at which player 1 is indifferent amongst
@@ -281,7 +284,8 @@
sage: f[1,1][0] = 4
sage: f[1,1][1] = 4
sage: f
- Normal Form Game with the following utilities: {(0, 0): [1, 3], (0, 1): [2, 3], (1, 0): [3, 1], (1, 1): [4, 4]}
+ Normal Form Game with the following utilities: {(0, 0): [1, 3],
+ (0, 1): [2, 3], (1, 0): [3, 1], (1, 1): [4, 4]}
Once this game is constructed we can view the payoff matrices and solve the
game::
@@ -401,7 +405,9 @@
sage: threegame.obtain_nash()
Traceback (most recent call last):
...
- NotImplementedError: Nash equilibrium for games with more than 2 players have not been implemented yet. Please see the gambit website (http://gambit.sourceforge.net/) that has a variety of available algorithms
+ NotImplementedError: Nash equilibrium for games with more than 2 players
+ have not been implemented yet. Please see the gambit website
+ (http://gambit.sourceforge.net/) that has a variety of available algorithms
There are however a variety of such algorithms available in gambit,
further compatibility between Sage and gambit is actively being developed:
@@ -424,18 +430,18 @@
It is also possible to generate a Normal form game from a gambit Game::
- sage: from gambit import Game # optional - gambit
- sage: gambitgame= Game.new_table([2, 2]) # optional - gambit
- sage: gambitgame[int(0), int(0)][int(0)] = int(8) # optional - gambit
- sage: gambitgame[int(0), int(0)][int(1)] = int(8) # optional - gambit
- sage: gambitgame[int(0), int(1)][int(0)] = int(2) # optional - gambit
- sage: gambitgame[int(0), int(1)][int(1)] = int(10) # optional - gambit
- sage: gambitgame[int(1), int(0)][int(0)] = int(10) # optional - gambit
- sage: gambitgame[int(1), int(0)][int(1)] = int(2) # optional - gambit
- sage: gambitgame[int(1), int(1)][int(0)] = int(5) # optional - gambit
- sage: gambitgame[int(1), int(1)][int(1)] = int(5) # optional - gambit
- sage: g = NormalFormGame(gambitgame) # optional - gambit
- sage: g # optional - gambit
+ sage: # optional - gambit
+ sage: from gambit import Game
+ sage: gambitgame= Game.new_table([2, 2])
+ sage: gambitgame[int(0), int(0)][int(0)] = int(8)
+ sage: gambitgame[int(0), int(0)][int(1)] = int(8)
+ sage: gambitgame[int(0), int(1)][int(0)] = int(2)
+ sage: gambitgame[int(0), int(1)][int(1)] = int(10)
+ sage: gambitgame[int(1), int(0)][int(0)] = int(10)
+ sage: gambitgame[int(1), int(0)][int(1)] = int(2)
+ sage: gambitgame[int(1), int(1)][int(0)] = int(5)
+ sage: gambitgame[int(1), int(1)][int(1)] = int(5)
+ sage: g = NormalFormGame(gambitgame); g
Normal Form Game with the following utilities: {(0, 0): [8.0, 8.0],
(0, 1): [2.0, 10.0],
(1, 0): [10.0, 2.0],
@@ -476,9 +482,9 @@
sage: B = matrix([[min(i,j) + 2 * sign(i-j) for j in range(K, 1, -1)]
....: for i in range(K, 1, -1)])
sage: g = NormalFormGame([A, B])
- sage: g.obtain_nash(algorithm='lrs') # optional - lrslib
+ sage: g.obtain_nash(algorithm='lrs') # optional - lrslib
[[(0, 0, 0, 0, 0, 0, 0, 0, 1), (0, 0, 0, 0, 0, 0, 0, 0, 1)]]
- sage: g.obtain_nash(algorithm='LCP') # optional - gambit
+ sage: g.obtain_nash(algorithm='LCP') # optional - gambit
[[(0.0, 0.0, 0.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, 1.0)]]
@@ -564,9 +570,9 @@
sage: A = matrix([[3,3],[2,5],[0,6]])
sage: B = matrix([[3,3],[2,6],[3,1]])
sage: degenerate_game = NormalFormGame([A,B])
- sage: degenerate_game.obtain_nash(algorithm='lrs') # random, optional - lrslib
+ sage: degenerate_game.obtain_nash(algorithm='lrs') # random, optional - lrslib
[[(0, 1/3, 2/3), (1/3, 2/3)], [(1, 0, 0), (1/2, 3)], [(1, 0, 0), (1, 3)]]
- sage: degenerate_game.obtain_nash(algorithm='LCP') # optional - gambit
+ sage: degenerate_game.obtain_nash(algorithm='LCP') # optional - gambit
[[(0.0, 0.3333333333, 0.6666666667), (0.3333333333, 0.6666666667)],
[(1.0, -0.0, 0.0), (0.6666666667, 0.3333333333)],
[(1.0, 0.0, 0.0), (1.0, 0.0)]]
@@ -705,22 +711,25 @@ def __init__(self, generator=None):
sage: threegame.obtain_nash()
Traceback (most recent call last):
...
- NotImplementedError: Nash equilibrium for games with more than 2 players have not been implemented yet. Please see the gambit website (http://gambit.sourceforge.net/) that has a variety of available algorithms
+ NotImplementedError: Nash equilibrium for games with more than
+ 2 players have not been implemented yet. Please see the gambit
+ website (http://gambit.sourceforge.net/) that has a variety of
+ available algorithms
Can initialise a game from a gambit game object::
- sage: from gambit import Game # optional - gambit
- sage: gambitgame= Game.new_table([2, 2]) # optional - gambit
- sage: gambitgame[int(0), int(0)][int(0)] = int(5) # optional - gambit
- sage: gambitgame[int(0), int(0)][int(1)] = int(8) # optional - gambit
- sage: gambitgame[int(0), int(1)][int(0)] = int(2) # optional - gambit
- sage: gambitgame[int(0), int(1)][int(1)] = int(11) # optional - gambit
- sage: gambitgame[int(1), int(0)][int(0)] = int(10) # optional - gambit
- sage: gambitgame[int(1), int(0)][int(1)] = int(7) # optional - gambit
- sage: gambitgame[int(1), int(1)][int(0)] = int(5) # optional - gambit
- sage: gambitgame[int(1), int(1)][int(1)] = int(5) # optional - gambit
- sage: g = NormalFormGame(gambitgame) # optional - gambit
- sage: g # optional - gambit
+ sage: # optional - gambit
+ sage: from gambit import Game
+ sage: gambitgame= Game.new_table([2, 2])
+ sage: gambitgame[int(0), int(0)][int(0)] = int(5)
+ sage: gambitgame[int(0), int(0)][int(1)] = int(8)
+ sage: gambitgame[int(0), int(1)][int(0)] = int(2)
+ sage: gambitgame[int(0), int(1)][int(1)] = int(11)
+ sage: gambitgame[int(1), int(0)][int(0)] = int(10)
+ sage: gambitgame[int(1), int(0)][int(1)] = int(7)
+ sage: gambitgame[int(1), int(1)][int(0)] = int(5)
+ sage: gambitgame[int(1), int(1)][int(1)] = int(5)
+ sage: g = NormalFormGame(gambitgame); g
Normal Form Game with the following utilities: {(0, 0): [5.0, 8.0],
(0, 1): [2.0, 11.0],
(1, 0): [10.0, 7.0],
@@ -790,10 +799,12 @@ def __delitem__(self, key):
sage: B = matrix([[2, 0], [5, 4]])
sage: prisoners_dilemma = NormalFormGame([A, B])
sage: prisoners_dilemma
- Normal Form Game with the following utilities: {(0, 0): [2, 2], (0, 1): [5, 0], (1, 0): [0, 5], (1, 1): [4, 4]}
+ Normal Form Game with the following utilities: {(0, 0): [2, 2],
+ (0, 1): [5, 0], (1, 0): [0, 5], (1, 1): [4, 4]}
sage: del(prisoners_dilemma[(0,1)])
sage: prisoners_dilemma
- Normal Form Game with the following utilities: {(0, 0): [2, 2], (1, 0): [0, 5], (1, 1): [4, 4]}
+ Normal Form Game with the following utilities: {(0, 0): [2, 2],
+ (1, 0): [0, 5], (1, 1): [4, 4]}
"""
self.utilities.pop(key, None)
@@ -897,7 +908,8 @@ def _repr_(self):
sage: p2 = matrix([[3, 3], [1, 4]])
sage: g = NormalFormGame([p1, p2])
sage: g
- Normal Form Game with the following utilities: {(0, 0): [1, 3], (0, 1): [2, 3], (1, 0): [3, 1], (1, 1): [4, 4]}
+ Normal Form Game with the following utilities: {(0, 0): [1, 3],
+ (0, 1): [2, 3], (1, 0): [3, 1], (1, 1): [4, 4]}
"""
from pprint import pformat
base_str = "Normal Form Game with the following utilities: {}"
@@ -967,19 +979,19 @@ def _gambit_game(self, game):
TESTS::
- sage: from gambit import Game # optional - gambit
- sage: testgame = Game.new_table([2, 2]) # optional - gambit
- sage: testgame[int(0), int(0)][int(0)] = int(8) # optional - gambit
- sage: testgame[int(0), int(0)][int(1)] = int(8) # optional - gambit
- sage: testgame[int(0), int(1)][int(0)] = int(2) # optional - gambit
- sage: testgame[int(0), int(1)][int(1)] = int(10) # optional - gambit
- sage: testgame[int(1), int(0)][int(0)] = int(10) # optional - gambit
- sage: testgame[int(1), int(0)][int(1)] = int(2) # optional - gambit
- sage: testgame[int(1), int(1)][int(0)] = int(5) # optional - gambit
- sage: testgame[int(1), int(1)][int(1)] = int(5) # optional - gambit
- sage: g = NormalFormGame() # optional - gambit
- sage: g._gambit_game(testgame) # optional - gambit
- sage: g # optional - gambit
+ sage: # optional - gambit
+ sage: from gambit import Game
+ sage: testgame = Game.new_table([2, 2])
+ sage: testgame[int(0), int(0)][int(0)] = int(8)
+ sage: testgame[int(0), int(0)][int(1)] = int(8)
+ sage: testgame[int(0), int(1)][int(0)] = int(2)
+ sage: testgame[int(0), int(1)][int(1)] = int(10)
+ sage: testgame[int(1), int(0)][int(0)] = int(10)
+ sage: testgame[int(1), int(0)][int(1)] = int(2)
+ sage: testgame[int(1), int(1)][int(0)] = int(5)
+ sage: testgame[int(1), int(1)][int(1)] = int(5)
+ sage: g = NormalFormGame()
+ sage: g._gambit_game(testgame); g
Normal Form Game with the following utilities: {(0, 0): [8.0, 8.0],
(0, 1): [2.0, 10.0],
(1, 0): [10.0, 2.0],
@@ -1008,11 +1020,11 @@ def _gambit_(self, as_integer=False, maximization=True):
TESTS::
- sage: from gambit import Game # optional - gambit
+ sage: # optional - gambit
+ sage: from gambit import Game
sage: A = matrix([[2, 1], [1, 2.5]])
sage: g = NormalFormGame([A])
- sage: gg = g._gambit_() # optional - gambit
- sage: gg # optional - gambit
+ sage: gg = g._gambit_(); gg
NFG 1 R "" { "1" "2" }
{ { "1" "2" }
@@ -1028,9 +1040,7 @@ def _gambit_(self, as_integer=False, maximization=True):
}
1 2 3 4
-
- sage: gg = g._gambit_(as_integer=True) # optional - gambit
- sage: gg # optional - gambit
+ sage: gg = g._gambit_(as_integer=True); gg
NFG 1 R "" { "1" "2" }
{ { "1" "2" }
@@ -1049,11 +1059,11 @@ def _gambit_(self, as_integer=False, maximization=True):
::
+ sage: # optional - gambit
sage: A = matrix([[2, 1], [1, 2.5]])
sage: B = matrix([[3, 2], [5.5, 4]])
sage: g = NormalFormGame([A, B])
- sage: gg = g._gambit_() # optional - gambit
- sage: gg # optional - gambit
+ sage: gg = g._gambit_(); gg
NFG 1 R "" { "1" "2" }
{ { "1" "2" }
@@ -1069,9 +1079,7 @@ def _gambit_(self, as_integer=False, maximization=True):
}
1 2 3 4
-
- sage: gg = g._gambit_(as_integer = True) # optional - gambit
- sage: gg # optional - gambit
+ sage: gg = g._gambit_(as_integer = True); gg
NFG 1 R "" { "1" "2" }
{ { "1" "2" }
@@ -1090,35 +1098,36 @@ def _gambit_(self, as_integer=False, maximization=True):
::
- sage: threegame = NormalFormGame() # optional - gambit
- sage: threegame.add_player(2) # optional - gambit
- sage: threegame.add_player(2) # optional - gambit
- sage: threegame.add_player(2) # optional - gambit
- sage: threegame[0, 0, 0][0] = 3 # optional - gambit
- sage: threegame[0, 0, 0][1] = 1 # optional - gambit
- sage: threegame[0, 0, 0][2] = 4 # optional - gambit
- sage: threegame[0, 0, 1][0] = 1 # optional - gambit
- sage: threegame[0, 0, 1][1] = 5 # optional - gambit
- sage: threegame[0, 0, 1][2] = 9 # optional - gambit
- sage: threegame[0, 1, 0][0] = 2 # optional - gambit
- sage: threegame[0, 1, 0][1] = 6 # optional - gambit
- sage: threegame[0, 1, 0][2] = 5 # optional - gambit
- sage: threegame[0, 1, 1][0] = 3 # optional - gambit
- sage: threegame[0, 1, 1][1] = 5 # optional - gambit
- sage: threegame[0, 1, 1][2] = 8 # optional - gambit
- sage: threegame[1, 0, 0][0] = 9 # optional - gambit
- sage: threegame[1, 0, 0][1] = 7 # optional - gambit
- sage: threegame[1, 0, 0][2] = 9 # optional - gambit
- sage: threegame[1, 0, 1][0] = 3 # optional - gambit
- sage: threegame[1, 0, 1][1] = 2 # optional - gambit
- sage: threegame[1, 0, 1][2] = 3 # optional - gambit
- sage: threegame[1, 1, 0][0] = 8 # optional - gambit
- sage: threegame[1, 1, 0][1] = 4 # optional - gambit
- sage: threegame[1, 1, 0][2] = 6 # optional - gambit
- sage: threegame[1, 1, 1][0] = 2 # optional - gambit
- sage: threegame[1, 1, 1][1] = 6 # optional - gambit
- sage: threegame[1, 1, 1][2] = 4 # optional - gambit
- sage: threegame._gambit_(as_integer = True) # optional - gambit
+ sage: # optional - gambit
+ sage: threegame = NormalFormGame()
+ sage: threegame.add_player(2)
+ sage: threegame.add_player(2)
+ sage: threegame.add_player(2)
+ sage: threegame[0, 0, 0][0] = 3
+ sage: threegame[0, 0, 0][1] = 1
+ sage: threegame[0, 0, 0][2] = 4
+ sage: threegame[0, 0, 1][0] = 1
+ sage: threegame[0, 0, 1][1] = 5
+ sage: threegame[0, 0, 1][2] = 9
+ sage: threegame[0, 1, 0][0] = 2
+ sage: threegame[0, 1, 0][1] = 6
+ sage: threegame[0, 1, 0][2] = 5
+ sage: threegame[0, 1, 1][0] = 3
+ sage: threegame[0, 1, 1][1] = 5
+ sage: threegame[0, 1, 1][2] = 8
+ sage: threegame[1, 0, 0][0] = 9
+ sage: threegame[1, 0, 0][1] = 7
+ sage: threegame[1, 0, 0][2] = 9
+ sage: threegame[1, 0, 1][0] = 3
+ sage: threegame[1, 0, 1][1] = 2
+ sage: threegame[1, 0, 1][2] = 3
+ sage: threegame[1, 1, 0][0] = 8
+ sage: threegame[1, 1, 0][1] = 4
+ sage: threegame[1, 1, 0][2] = 6
+ sage: threegame[1, 1, 1][0] = 2
+ sage: threegame[1, 1, 1][1] = 6
+ sage: threegame[1, 1, 1][2] = 4
+ sage: threegame._gambit_(as_integer = True)
NFG 1 R "" { "1" "2" "3" }
{ { "1" "2" }
@@ -1274,7 +1283,9 @@ def add_player(self, num_strategies):
sage: g.add_player(1) # Adding second player with 1 strategy
sage: g.add_player(1) # Adding third player with 1 strategy
sage: g
- Normal Form Game with the following utilities: {(0, 0, 0): [False, False, False], (1, 0, 0): [False, False, False]}
+ Normal Form Game with the following utilities:
+ {(0, 0, 0): [False, False, False],
+ (1, 0, 0): [False, False, False]}
"""
self.players.append(_Player(num_strategies))
self._generate_utilities(True)
@@ -1350,7 +1361,8 @@ def add_strategy(self, player):
sage: t = matrix([[3, 2], [-1, 0]])
sage: example = NormalFormGame([s, t])
sage: example
- Normal Form Game with the following utilities: {(0, 0): [1, 3], (0, 1): [0, 2], (1, 0): [-2, -1], (1, 1): [3, 0]}
+ Normal Form Game with the following utilities: {(0, 0): [1, 3],
+ (0, 1): [0, 2], (1, 0): [-2, -1], (1, 1): [3, 0]}
sage: example.add_strategy(0)
sage: example
Normal Form Game with the following utilities: {(0, 0): [1, 3],
@@ -1475,10 +1487,12 @@ def obtain_nash(self, algorithm=False, maximization=True, solver=None):
....: [3, 4, 1],
....: [4, 1, 20]])
sage: g=NormalFormGame([A, B])
- sage: g.obtain_nash(algorithm='lrs') # optional - lrslib
+ sage: g.obtain_nash(algorithm='lrs') # optional - lrslib
[[(0, 0, 0, 1), (0, 0, 1)]]
- sage: g.obtain_nash(algorithm='lrs', maximization=False) # optional - lrslib
- [[(2/3, 1/12, 1/4, 0), (6333/8045, 247/8045, 293/1609)], [(3/4, 0, 1/4, 0), (0, 11/307, 296/307)], [(5/6, 1/6, 0, 0), (98/99, 1/99, 0)]]
+ sage: g.obtain_nash(algorithm='lrs', maximization=False) # optional - lrslib
+ [[(2/3, 1/12, 1/4, 0), (6333/8045, 247/8045, 293/1609)],
+ [(3/4, 0, 1/4, 0), (0, 11/307, 296/307)],
+ [(5/6, 1/6, 0, 0), (98/99, 1/99, 0)]]
This particular game has 3 Nash equilibria::
@@ -1490,7 +1504,9 @@ def obtain_nash(self, algorithm=False, maximization=True, solver=None):
....: [3,1]])
sage: g = NormalFormGame([A, B])
sage: g.obtain_nash(algorithm='enumeration')
- [[(0, 1/3, 2/3), (1/3, 2/3)], [(4/5, 1/5, 0), (2/3, 1/3)], [(1, 0, 0), (1, 0)]]
+ [[(0, 1/3, 2/3), (1/3, 2/3)],
+ [(4/5, 1/5, 0), (2/3, 1/3)],
+ [(1, 0, 0), (1, 0)]]
Here is a slightly larger game::
@@ -1525,9 +1541,9 @@ def obtain_nash(self, algorithm=False, maximization=True, solver=None):
sage: fivegame = NormalFormGame([player1, player2])
sage: fivegame.obtain_nash(algorithm='enumeration')
[[(1, 0, 0, 0, 0), (0, 1, 0, 0, 0)]]
- sage: fivegame.obtain_nash(algorithm='lrs') # optional - lrslib
+ sage: fivegame.obtain_nash(algorithm='lrs') # optional - lrslib
[[(1, 0, 0, 0, 0), (0, 1, 0, 0, 0)]]
- sage: fivegame.obtain_nash(algorithm='LCP') # optional - gambit
+ sage: fivegame.obtain_nash(algorithm='LCP') # optional - gambit
[[(1.0, 0.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0, 0.0)]]
Here are some examples of finding Nash equilibria for constant-sum games::
@@ -1536,24 +1552,24 @@ def obtain_nash(self, algorithm=False, maximization=True, solver=None):
sage: cg = NormalFormGame([A])
sage: cg.obtain_nash(algorithm='lp')
[[(0.5, 0.5), (0.5, 0.5)]]
- sage: cg.obtain_nash(algorithm='lp', solver='Coin') # optional - sage_numerical_backends_coin
+ sage: cg.obtain_nash(algorithm='lp', solver='Coin') # optional - sage_numerical_backends_coin
[[(0.5, 0.5), (0.5, 0.5)]]
sage: cg.obtain_nash(algorithm='lp', solver='PPL')
[[(1/2, 1/2), (1/2, 1/2)]]
- sage: cg.obtain_nash(algorithm='lp', solver='gambit') # optional - gambit
+ sage: cg.obtain_nash(algorithm='lp', solver='gambit') # optional - gambit
[[(0.5, 0.5), (0.5, 0.5)]]
sage: A = matrix([[2, 1], [1, 3]])
sage: cg = NormalFormGame([A])
sage: ne = cg.obtain_nash(algorithm='lp', solver='glpk')
sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne]
[[[0.666667, 0.333333], [0.666667, 0.333333]]]
- sage: ne = cg.obtain_nash(algorithm='lp', solver='Coin') # optional - sage_numerical_backends_coin
- sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - sage_numerical_backends_coin
+ sage: ne = cg.obtain_nash(algorithm='lp', solver='Coin') # optional - sage_numerical_backends_coin
+ sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - sage_numerical_backends_coin
[[[0.666667, 0.333333], [0.666667, 0.333333]]]
sage: cg.obtain_nash(algorithm='lp', solver='PPL')
[[(2/3, 1/3), (2/3, 1/3)]]
- sage: ne = cg.obtain_nash(algorithm='lp', solver='gambit') # optional - gambit
- sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - gambit
+ sage: ne = cg.obtain_nash(algorithm='lp', solver='gambit') # optional - gambit
+ sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - gambit
[[[0.666667, 0.333333], [0.666667, 0.333333]]]
sage: A = matrix([[1, 2, 1], [1, 1, 2], [2, 1, 1]])
sage: B = matrix([[2, 1, 2], [2, 2, 1], [1, 2, 2]])
@@ -1561,13 +1577,13 @@ def obtain_nash(self, algorithm=False, maximization=True, solver=None):
sage: ne = cg.obtain_nash(algorithm='lp', solver='glpk')
sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne]
[[[0.333333, 0.333333, 0.333333], [0.333333, 0.333333, 0.333333]]]
- sage: ne = cg.obtain_nash(algorithm='lp', solver='Coin') # optional - sage_numerical_backends_coin
- sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - sage_numerical_backends_coin
+ sage: ne = cg.obtain_nash(algorithm='lp', solver='Coin') # optional - sage_numerical_backends_coin
+ sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - sage_numerical_backends_coin
[[[0.333333, 0.333333, 0.333333], [0.333333, 0.333333, 0.333333]]]
sage: cg.obtain_nash(algorithm='lp', solver='PPL')
[[(1/3, 1/3, 1/3), (1/3, 1/3, 1/3)]]
- sage: ne = cg.obtain_nash(algorithm='lp', solver='gambit') # optional - gambit
- sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - gambit
+ sage: ne = cg.obtain_nash(algorithm='lp', solver='gambit') # optional - gambit
+ sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - gambit
[[[0.333333, 0.333333, 0.333333], [0.333333, 0.333333, 0.333333]]]
sage: A = matrix([[160, 205, 44],
....: [175, 180, 45],
@@ -1609,19 +1625,19 @@ def obtain_nash(self, algorithm=False, maximization=True, solver=None):
sage: gg = NormalFormGame([A])
sage: gg.obtain_nash(algorithm='enumeration')
[[(0, 1), (0, 1)], [(0, 1), (1, 0)], [(1, 0), (0, 1)], [(1, 0), (1, 0)]]
- sage: gg.obtain_nash(algorithm='lrs') # optional - lrs
+ sage: gg.obtain_nash(algorithm='lrs') # optional - lrs
[[(0, 1), (0, 1)], [(0, 1), (1, 0)], [(1, 0), (0, 1)], [(1, 0), (1, 0)]]
sage: gg.obtain_nash(algorithm='lp', solver='glpk')
[[(1.0, 0.0), (1.0, 0.0)]]
- sage: gg.obtain_nash(algorithm='LCP') # optional - gambit
+ sage: gg.obtain_nash(algorithm='LCP') # optional - gambit
[[(1.0, 0.0), (1.0, 0.0)]]
sage: gg.obtain_nash(algorithm='enumeration', maximization=False)
[[(0, 1), (0, 1)], [(0, 1), (1, 0)], [(1, 0), (0, 1)], [(1, 0), (1, 0)]]
- sage: gg.obtain_nash(algorithm='lrs', maximization=False) # optional - lrs
+ sage: gg.obtain_nash(algorithm='lrs', maximization=False) # optional - lrs
[[(0, 1), (0, 1)], [(0, 1), (1, 0)], [(1, 0), (0, 1)], [(1, 0), (1, 0)]]
sage: gg.obtain_nash(algorithm='lp', solver='glpk', maximization=False)
[[(1.0, 0.0), (1.0, 0.0)]]
- sage: gg.obtain_nash(algorithm='LCP', maximization=False) # optional - gambit
+ sage: gg.obtain_nash(algorithm='LCP', maximization=False) # optional - gambit
[[(1.0, 0.0), (1.0, 0.0)]]
Note that outputs for all algorithms are as lists of lists of
@@ -1709,7 +1725,7 @@ def _solve_lrs(self, maximization=True):
sage: A = matrix([[1, 2], [3, 4]])
sage: B = matrix([[3, 3], [1, 4]])
sage: C = NormalFormGame([A, B])
- sage: C._solve_lrs() # optional - lrslib
+ sage: C._solve_lrs() # optional - lrslib
[[(0, 1), (0, 1)]]
2 random matrices::
@@ -1725,7 +1741,7 @@ def _solve_lrs(self, maximization=True):
....: [1, 0, 0, 0, 0,],
....: [1, -3, 1, 21, -2]])
sage: biggame = NormalFormGame([p1, p2])
- sage: biggame._solve_lrs() # optional - lrslib
+ sage: biggame._solve_lrs() # optional - lrslib
[[(0, 0, 0, 20/21, 1/21), (11/12, 0, 0, 1/12, 0)]]
Another test::
@@ -1737,7 +1753,7 @@ def _solve_lrs(self, maximization=True):
....: [6, -2, -3],
....: [-4, 6, -10]])
sage: biggame = NormalFormGame([p1, p2])
- sage: biggame._solve_lrs() # optional - lrslib
+ sage: biggame._solve_lrs() # optional - lrslib
[[(0, 1, 0), (1, 0, 0)],
[(1/3, 2/3, 0), (0, 1/6, 5/6)],
[(1/3, 2/3, 0), (1/7, 0, 6/7)],
@@ -1774,7 +1790,7 @@ def _solve_LCP(self, maximization):
sage: a = matrix([[1, 0], [1, 4]])
sage: b = matrix([[2, 3], [2, 4]])
sage: c = NormalFormGame([a, b])
- sage: c._solve_LCP(maximization=True) # optional - gambit
+ sage: c._solve_LCP(maximization=True) # optional - gambit
[[(0.0, 1.0), (0.0, 1.0)]]
"""
g = self._gambit_(maximization)
@@ -1791,14 +1807,14 @@ def _solve_gambit_LP(self, maximization=True):
sage: A = matrix([[2, 1], [1, 2.5]])
sage: g = NormalFormGame([A])
- sage: g._solve_gambit_LP() # optional - gambit
+ sage: g._solve_gambit_LP() # optional - gambit
[[(0.6, 0.4), (0.6, 0.4)]]
sage: A = matrix.identity(2)
sage: g = NormalFormGame([A])
- sage: g._solve_gambit_LP() # optional - gambit
+ sage: g._solve_gambit_LP() # optional - gambit
[[(0.5, 0.5), (0.5, 0.5)]]
sage: g = NormalFormGame([A,A])
- sage: g._solve_gambit_LP() # optional - gambit
+ sage: g._solve_gambit_LP() # optional - gambit
Traceback (most recent call last):
...
RuntimeError: Method only valid for constant-sum games.
@@ -1830,9 +1846,9 @@ def _solve_LP(self, solver='glpk', maximization=True):
sage: g = NormalFormGame([A])
sage: g._solve_LP()
[[(0.5, 0.5), (0.5, 0.5)]]
- sage: g._solve_LP('gambit') # optional - gambit
+ sage: g._solve_LP('gambit') # optional - gambit
[[(0.5, 0.5), (0.5, 0.5)]]
- sage: g._solve_LP('Coin') # optional - sage_numerical_backends_coin
+ sage: g._solve_LP('Coin') # optional - sage_numerical_backends_coin
[[(0.5, 0.5), (0.5, 0.5)]]
sage: g._solve_LP('PPL')
[[(1/2, 1/2), (1/2, 1/2)]]
@@ -1841,11 +1857,11 @@ def _solve_LP(self, solver='glpk', maximization=True):
sage: ne = g._solve_LP()
sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne]
[[[0.666667, 0.333333], [0.666667, 0.333333]]]
- sage: ne = g._solve_LP('gambit') # optional - gambit
- sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - gambit
+ sage: ne = g._solve_LP('gambit') # optional - gambit
+ sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - gambit
[[[0.666667, 0.333333], [0.666667, 0.333333]]]
- sage: ne = g._solve_LP('Coin') # optional - sage_numerical_backends_coin
- sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - sage_numerical_backends_coin
+ sage: ne = g._solve_LP('Coin') # optional - sage_numerical_backends_coin
+ sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - sage_numerical_backends_coin
[[[0.666667, 0.333333], [0.666667, 0.333333]]]
sage: g._solve_LP('PPL')
[[(2/3, 1/3), (2/3, 1/3)]]
@@ -1950,7 +1966,9 @@ def _solve_enumeration(self, maximization=True):
....: [3, 2, 1, 1]])
sage: C = NormalFormGame([A, B])
sage: C._solve_enumeration()
- [[(0, 0, 0, 1), (1, 0, 0, 0)], [(2/7, 0, 0, 5/7), (5/11, 0, 6/11, 0)], [(1, 0, 0, 0), (0, 0, 1, 0)]]
+ [[(0, 0, 0, 1), (1, 0, 0, 0)],
+ [(2/7, 0, 0, 5/7), (5/11, 0, 6/11, 0)],
+ [(1, 0, 0, 0), (0, 0, 1, 0)]]
Again::
@@ -2485,11 +2503,11 @@ def is_degenerate(self, certificate=False):
....: [-17, 25, -97, -82],
....: [30, 31, -1, 50]])
sage: d_game = NormalFormGame([a, b])
- sage: d_game.obtain_nash(algorithm='lrs') # optional - lrslib
+ sage: d_game.obtain_nash(algorithm='lrs') # optional - lrslib
[[(0, 0, 1, 0), (0, 1, 0, 0)],
[(17/29, 0, 0, 12/29), (0, 0, 42/73, 31/73)],
[(122/145, 0, 23/145, 0), (0, 1, 0, 0)]]
- sage: d_game.obtain_nash(algorithm='LCP') # optional - gambit
+ sage: d_game.obtain_nash(algorithm='LCP') # optional - gambit
[[(0.5862068966, 0.0, 0.0, 0.4137931034),
(0.0, 0.0, 0.5753424658, 0.4246575342)]]
sage: d_game.obtain_nash(algorithm='enumeration')
@@ -2532,7 +2550,8 @@ def is_degenerate(self, certificate=False):
sage: g.is_degenerate()
Traceback (most recent call last):
...
- NotImplementedError: Tests for Degeneracy is not yet implemented for games with more than two players.
+ NotImplementedError: Tests for Degeneracy is not yet implemented for
+ games with more than two players.
"""
if len(self.players) > 2:
raise NotImplementedError("Tests for Degeneracy is not yet "
@@ -2607,7 +2626,7 @@ def best_responses(self, strategy, player):
sage: g.best_responses((3/4, 1/4), player=0)
[0]
- To get the best responses for Player 2 we pass the argument :code:`player=1`
+ To get the best responses for Player 2 we pass the argument :code:`player=1`::
sage: g.best_responses((4/5, 1/5, 0), player=1)
[0, 1]
@@ -2658,7 +2677,7 @@ def best_responses(self, strategy, player):
ValueError: Strategy is not of correct dimension
If the strategy is not a true probability vector then an error is
- passed:
+ passed::
sage: A = matrix([[3, 0], [0, 3], [1.5, 1.5]])
sage: B = matrix([[4, 3], [2, 6], [3, 1]])
diff --git a/src/sage/game_theory/parser.py b/src/sage/game_theory/parser.py
index 0784e4bc184..d528116f244 100644
--- a/src/sage/game_theory/parser.py
+++ b/src/sage/game_theory/parser.py
@@ -194,18 +194,19 @@ def format_gambit(self, gambit_game):
Here we construct a two by two game in gambit::
- sage: import gambit # optional - gambit
+ sage: # optional - gambit
+ sage: import gambit
sage: from sage.game_theory.parser import Parser
- sage: g = gambit.Game.new_table([2,2]) # optional - gambit
- sage: g[int(0), int(0)][int(0)] = int(2) # optional - gambit
- sage: g[int(0), int(0)][int(1)] = int(1) # optional - gambit
- sage: g[int(0), int(1)][int(0)] = int(0) # optional - gambit
- sage: g[int(0), int(1)][int(1)] = int(0) # optional - gambit
- sage: g[int(1), int(0)][int(0)] = int(0) # optional - gambit
- sage: g[int(1), int(0)][int(1)] = int(0) # optional - gambit
- sage: g[int(1), int(1)][int(0)] = int(1) # optional - gambit
- sage: g[int(1), int(1)][int(1)] = int(2) # optional - gambit
- sage: solver = gambit.nash.ExternalLCPSolver() # optional - gambit
+ sage: g = gambit.Game.new_table([2,2])
+ sage: g[int(0), int(0)][int(0)] = int(2)
+ sage: g[int(0), int(0)][int(1)] = int(1)
+ sage: g[int(0), int(1)][int(0)] = int(0)
+ sage: g[int(0), int(1)][int(1)] = int(0)
+ sage: g[int(1), int(0)][int(0)] = int(0)
+ sage: g[int(1), int(0)][int(1)] = int(0)
+ sage: g[int(1), int(1)][int(0)] = int(1)
+ sage: g[int(1), int(1)][int(1)] = int(2)
+ sage: solver = gambit.nash.ExternalLCPSolver()
Here is the output of the LCP algorithm::
@@ -218,21 +219,24 @@ def format_gambit(self, gambit_game):
The Parser class outputs the equilibrium::
sage: nasheq = Parser(LCP_output).format_gambit(g) # optional - gambit
- sage: nasheq # optional - gambit
- [[(1.0, 0.0), (1.0, 0.0)], [(0.6666666667, 0.3333333333), (0.3333333333, 0.6666666667)], [(0.0, 1.0), (0.0, 1.0)]]
+ sage: nasheq # optional - gambit
+ [[(1.0, 0.0), (1.0, 0.0)],
+ [(0.6666666667, 0.3333333333), (0.3333333333, 0.6666666667)],
+ [(0.0, 1.0), (0.0, 1.0)]]
Here is another game::
- sage: g = gambit.Game.new_table([2,2]) # optional - gambit
- sage: g[int(0), int(0)][int(0)] = int(4) # optional - gambit
- sage: g[int(0), int(0)][int(1)] = int(8) # optional - gambit
- sage: g[int(0), int(1)][int(0)] = int(0) # optional - gambit
- sage: g[int(0), int(1)][int(1)] = int(1) # optional - gambit
- sage: g[int(1), int(0)][int(0)] = int(1) # optional - gambit
- sage: g[int(1), int(0)][int(1)] = int(3) # optional - gambit
- sage: g[int(1), int(1)][int(0)] = int(1) # optional - gambit
- sage: g[int(1), int(1)][int(1)] = int(0) # optional - gambit
- sage: solver = gambit.nash.ExternalLCPSolver() # optional - gambit
+ sage: # optional - gambit
+ sage: g = gambit.Game.new_table([2,2])
+ sage: g[int(0), int(0)][int(0)] = int(4)
+ sage: g[int(0), int(0)][int(1)] = int(8)
+ sage: g[int(0), int(1)][int(0)] = int(0)
+ sage: g[int(0), int(1)][int(1)] = int(1)
+ sage: g[int(1), int(0)][int(0)] = int(1)
+ sage: g[int(1), int(0)][int(1)] = int(3)
+ sage: g[int(1), int(1)][int(0)] = int(1)
+ sage: g[int(1), int(1)][int(1)] = int(0)
+ sage: solver = gambit.nash.ExternalLCPSolver()
Here is the LCP output::
@@ -248,26 +252,27 @@ def format_gambit(self, gambit_game):
Here is a larger degenerate game::
- sage: g = gambit.Game.new_table([3,3]) # optional - gambit
- sage: g[int(0), int(0)][int(0)] = int(-7) # optional - gambit
- sage: g[int(0), int(0)][int(1)] = int(-9) # optional - gambit
- sage: g[int(0), int(1)][int(0)] = int(-5) # optional - gambit
- sage: g[int(0), int(1)][int(1)] = int(7) # optional - gambit
- sage: g[int(0), int(2)][int(0)] = int(5) # optional - gambit
- sage: g[int(0), int(2)][int(1)] = int(9) # optional - gambit
- sage: g[int(1), int(0)][int(0)] = int(5) # optional - gambit
- sage: g[int(1), int(0)][int(1)] = int(6) # optional - gambit
- sage: g[int(1), int(1)][int(0)] = int(5) # optional - gambit
- sage: g[int(1), int(1)][int(1)] = int(-2) # optional - gambit
- sage: g[int(1), int(2)][int(0)] = int(3) # optional - gambit
- sage: g[int(1), int(2)][int(1)] = int(-3) # optional - gambit
- sage: g[int(2), int(0)][int(0)] = int(1) # optional - gambit
- sage: g[int(2), int(0)][int(1)] = int(-4) # optional - gambit
- sage: g[int(2), int(1)][int(0)] = int(-6) # optional - gambit
- sage: g[int(2), int(1)][int(1)] = int(6) # optional - gambit
- sage: g[int(2), int(2)][int(0)] = int(1) # optional - gambit
- sage: g[int(2), int(2)][int(1)] = int(-10) # optional - gambit
- sage: solver = gambit.nash.ExternalLCPSolver() # optional - gambit
+ sage: # optional - gambit
+ sage: g = gambit.Game.new_table([3,3])
+ sage: g[int(0), int(0)][int(0)] = int(-7)
+ sage: g[int(0), int(0)][int(1)] = int(-9)
+ sage: g[int(0), int(1)][int(0)] = int(-5)
+ sage: g[int(0), int(1)][int(1)] = int(7)
+ sage: g[int(0), int(2)][int(0)] = int(5)
+ sage: g[int(0), int(2)][int(1)] = int(9)
+ sage: g[int(1), int(0)][int(0)] = int(5)
+ sage: g[int(1), int(0)][int(1)] = int(6)
+ sage: g[int(1), int(1)][int(0)] = int(5)
+ sage: g[int(1), int(1)][int(1)] = int(-2)
+ sage: g[int(1), int(2)][int(0)] = int(3)
+ sage: g[int(1), int(2)][int(1)] = int(-3)
+ sage: g[int(2), int(0)][int(0)] = int(1)
+ sage: g[int(2), int(0)][int(1)] = int(-4)
+ sage: g[int(2), int(1)][int(0)] = int(-6)
+ sage: g[int(2), int(1)][int(1)] = int(6)
+ sage: g[int(2), int(2)][int(0)] = int(1)
+ sage: g[int(2), int(2)][int(1)] = int(-10)
+ sage: solver = gambit.nash.ExternalLCPSolver()
Here is the LCP output::
diff --git a/src/sage/games/quantumino.py b/src/sage/games/quantumino.py
index 9f8da835585..d5646406882 100644
--- a/src/sage/games/quantumino.py
+++ b/src/sage/games/quantumino.py
@@ -253,7 +253,7 @@ class QuantuminoState(SageObject):
r"""
A state of the Quantumino puzzle.
- Used to represent an solution or a partial solution of the Quantumino
+ Used to represent a solution or a partial solution of the Quantumino
puzzle.
INPUT:
diff --git a/src/sage/geometry/cone.py b/src/sage/geometry/cone.py
index c2a9252bd72..0cebb40237c 100644
--- a/src/sage/geometry/cone.py
+++ b/src/sage/geometry/cone.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Convex rational polyhedral cones
@@ -554,7 +553,7 @@ def _ambient_space_point(body, data):
An integral, rational, real algebraic, or numeric point of the
ambient space of ``body`` is returned if ``data`` were
- successfully interpreted in such a way. A ``TypeError`` is raised
+ successfully interpreted in such a way. A :class:`TypeError` is raised
otherwise.
TESTS::
@@ -1664,7 +1663,7 @@ def _contains(self, point, region='whole cone'):
otherwise, in particular when ``point`` is incompatible with
the ambient space.
- A ``ValueError`` is raised if ``region`` is not one of the
+ A :class:`ValueError` is raised if ``region`` is not one of the
three allowed values.
TESTS::
@@ -2340,8 +2339,8 @@ def embed(self, cone):
or
:meth:`~sage.geometry.cone.ConvexRationalPolyhedralCone.facet_of`. The
cone returned by this method will have ``self`` as ambient. If ``cone``
- does not represent a valid cone of ``self``, ``ValueError`` exception
- is raised.
+ does not represent a valid cone of ``self``, :class:`ValueError`
+ exception is raised.
.. NOTE::
@@ -3017,8 +3016,8 @@ def intersection(self, other):
- :class:`cone `.
- Raises ``ValueError`` if the ambient space dimensions are not
- compatible.
+ This raises :class:`ValueError` if the ambient space dimensions
+ are not compatible.
EXAMPLES::
@@ -5349,7 +5348,7 @@ def random_element(self, ring=ZZ):
Either a lattice element or vector contained in both this cone
and its ambient vector space. If ``ring`` is ``ZZ``, a lattice
element is returned; otherwise a vector is returned. If ``ring``
- is neither ``ZZ`` nor ``QQ``, then a ``NotImplementedError`` is
+ is neither ``ZZ`` nor ``QQ``, then a :class:`NotImplementedError` is
raised.
EXAMPLES:
@@ -6267,7 +6266,7 @@ def random_cone(lattice=None, min_ambient_dim=0, max_ambient_dim=None,
A new, randomly generated cone.
- A ``ValueError`` will be thrown under the following conditions:
+ A :class:`ValueError` will be thrown under the following conditions:
* Any of ``min_ambient_dim``, ``max_ambient_dim``, ``min_rays``, or
``max_rays`` are negative.
@@ -6425,7 +6424,7 @@ def random_cone(lattice=None, min_ambient_dim=0, max_ambient_dim=None,
provided.
If the user requests too many rays in zero, one, or two dimensions,
- a ``ValueError`` is thrown::
+ a :class:`ValueError` is thrown::
sage: random_cone(max_ambient_dim=0, min_rays=1)
Traceback (most recent call last):
@@ -6513,7 +6512,7 @@ def random_cone(lattice=None, min_ambient_dim=0, max_ambient_dim=None,
sage: random_cone(lattice=L, strictly_convex=True)
0-d cone in 0-d lattice L
- A ``ValueError`` is thrown if a non-solid cone is requested in a
+ A :class:`ValueError` is thrown if a non-solid cone is requested in a
zero-dimensional lattice::
sage: L = ToricLattice(0)
@@ -6527,7 +6526,7 @@ def random_cone(lattice=None, min_ambient_dim=0, max_ambient_dim=None,
...
ValueError: all cones are solid when max_ambient_dim is zero.
- A ``ValueError`` is thrown if a solid cone is requested but the
+ A :class:`ValueError` is thrown if a solid cone is requested but the
maximum number of rays is too few::
sage: random_cone(min_ambient_dim=4, max_rays=3, solid=True)
@@ -6542,7 +6541,7 @@ def random_cone(lattice=None, min_ambient_dim=0, max_ambient_dim=None,
ValueError: max_rays must be at least 5 for a solid cone in this
lattice.
- A ``ValueError`` is thrown if a non-solid cone is requested but
+ A :class:`ValueError` is thrown if a non-solid cone is requested but
``min_rays`` guarantees a solid cone::
sage: random_cone(max_ambient_dim=4, min_rays=10, solid=False)
diff --git a/src/sage/geometry/fan.py b/src/sage/geometry/fan.py
index 3aecc84a55b..4ac1fdb497d 100644
--- a/src/sage/geometry/fan.py
+++ b/src/sage/geometry/fan.py
@@ -1956,7 +1956,7 @@ def cone_containing(self, *points):
We think of the origin as of the smallest cone containing no rays
at all. If there is no ray in ``self`` that contains all ``rays``,
- a ``ValueError`` exception will be raised.
+ a :class:`ValueError` exception will be raised.
EXAMPLES::
@@ -2352,8 +2352,8 @@ def embed(self, cone):
or
:meth:`~sage.geometry.cone.ConvexRationalPolyhedralCone.facet_of`. The
cone returned by this method will have ``self`` as ambient. If ``cone``
- does not represent a valid cone of ``self``, ``ValueError`` exception
- is raised.
+ does not represent a valid cone of ``self``, :class:`ValueError`
+ exception is raised.
.. NOTE::
@@ -3504,8 +3504,8 @@ def complex(self, base_ring=ZZ, extended=False):
OUTPUT:
The complex associated to the fan as a :class:`ChainComplex
- `. Raises a
- ``ValueError`` if the extended complex is requested for a
+ `. This raises a
+ :class:`ValueError` if the extended complex is requested for a
non-complete fan.
EXAMPLES::
diff --git a/src/sage/geometry/fan_morphism.py b/src/sage/geometry/fan_morphism.py
index 1d3cd1db886..d00e87083f7 100644
--- a/src/sage/geometry/fan_morphism.py
+++ b/src/sage/geometry/fan_morphism.py
@@ -520,8 +520,8 @@ def _ray_index_map(self):
domain fan is mapped to the origin. If it is `j`, then the `i`-th ray
of the domain fan is mapped onto the `j`-th ray of the codomain fan.
If there is a ray in the domain fan which is mapped into the relative
- interior of a higher dimensional cone, a ``ValueError`` exception is
- raised.
+ interior of a higher dimensional cone, a :class:`ValueError`
+ exception is raised.
.. NOTE::
@@ -601,8 +601,8 @@ def _subdivide_domain_fan(self, check, verbose):
OUTPUT:
- none, but the domain fan of self is replaced with its minimal
- refinement, if possible. Otherwise a ``ValueError`` exception is
- raised.
+ refinement, if possible. Otherwise a :class:`ValueError`
+ exception is raised.
TESTS::
@@ -763,11 +763,11 @@ def _subdivide_domain_fan(self, check, verbose):
def _support_error(self):
r"""
- Raise a ``ValueError`` exception due to support incompatibility.
+ Raise a :class:`ValueError` exception due to support incompatibility.
OUTPUT:
- - none, a ``ValueError`` exception is raised.
+ - none, a :class:`ValueError` exception is raised.
TESTS:
@@ -806,10 +806,10 @@ def _validate(self):
OUTPUT:
- - none, but a ``ValueError`` exception is raised if there is a cone of
- the domain fan of ``self`` which is not completely contained in a
- single cone of the codomain fan of ``self``, or if one of these fans
- does not sit in the appropriate lattice.
+ - none, but a :class:`ValueError` exception is raised if there is
+ a cone of the domain fan of ``self`` which is not completely
+ contained in a single cone of the codomain fan of ``self``,
+ or if one of these fans does not sit in the appropriate lattice.
EXAMPLES::
diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py b/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py
index fac28dfd161..ff509d0d97f 100644
--- a/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py
+++ b/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Coercion Maps Between Hyperbolic Plane Models
@@ -82,7 +81,7 @@ def _call_(self, x):
"""
C = self.codomain()
if not C.is_bounded() and self.domain().is_bounded() and x.is_boundary():
- msg = u"boundary points are not implemented for the {}"
+ msg = "boundary points are not implemented for the {}"
raise NotImplementedError(msg.format(C.name()))
y = self.image_coordinates(x.coordinates())
diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py b/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py
index 57354fad4d9..f8fb369bb39 100644
--- a/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py
+++ b/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Hyperbolic Geodesics
@@ -622,7 +621,7 @@ def is_parallel(self, other):
def ideal_endpoints(self):
r"""
Return the ideal endpoints in bounded models. Raise a
- ``NotImplementedError`` in models that are not bounded.
+ :class:`NotImplementedError` in models that are not bounded.
EXAMPLES::
@@ -660,7 +659,7 @@ def ideal_endpoints(self):
def complete(self):
r"""
Return the geodesic with ideal endpoints in bounded models. Raise a
- ``NotImplementedError`` in models that are not bounded.
+ :class:`NotImplementedError` in models that are not bounded.
In the following examples we represent complete geodesics by a dashed
line.
@@ -817,7 +816,7 @@ def common_perpendicula(self, other):
r"""
Return the unique hyperbolic geodesic perpendicular to two given
geodesics, if such a geodesic exists. If none exists, raise a
- ``ValueError``.
+ :class:`ValueError`.
INPUT:
@@ -1278,7 +1277,7 @@ def common_perpendicular(self, other):
r"""
Return the unique hyperbolic geodesic perpendicular to ``self``
and ``other``, if such a geodesic exists; otherwise raise a
- ``ValueError``.
+ :class:`ValueError`.
INPUT:
diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_interface.py b/src/sage/geometry/hyperbolic_space/hyperbolic_interface.py
index 38f6f4266af..11f4c08add9 100644
--- a/src/sage/geometry/hyperbolic_space/hyperbolic_interface.py
+++ b/src/sage/geometry/hyperbolic_space/hyperbolic_interface.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Interface to Hyperbolic Models
diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_isometry.py b/src/sage/geometry/hyperbolic_space/hyperbolic_isometry.py
index 08d68b2c518..0d9e0ec4a08 100644
--- a/src/sage/geometry/hyperbolic_space/hyperbolic_isometry.py
+++ b/src/sage/geometry/hyperbolic_space/hyperbolic_isometry.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Hyperbolic Isometries
@@ -489,7 +488,7 @@ def classification(self):
def translation_length(self):
r"""
For hyperbolic elements, return the translation length;
- otherwise, raise a ``ValueError``.
+ otherwise, raise a :class:`ValueError`.
EXAMPLES::
@@ -512,7 +511,7 @@ def translation_length(self):
def axis(self):
r"""
For a hyperbolic isometry, return the axis of the
- transformation; otherwise raise a ``ValueError``.
+ transformation; otherwise raise a :class:`ValueError`.
EXAMPLES::
@@ -593,7 +592,7 @@ def fixed_geodesic(self):
def repelling_fixed_point(self):
r"""
For a hyperbolic isometry, return the attracting fixed point;
- otherwise raise a ``ValueError``.
+ otherwise raise a :class:`ValueError`.
OUTPUT:
@@ -612,7 +611,7 @@ def repelling_fixed_point(self):
def attracting_fixed_point(self):
r"""
For a hyperbolic isometry, return the attracting fixed point;
- otherwise raise a `ValueError``.
+ otherwise raise a :class:`ValueError`.
OUTPUT:
@@ -735,7 +734,7 @@ def classification(self): #UHP
def translation_length(self): #UHP
r"""
For hyperbolic elements, return the translation length;
- otherwise, raise a ``ValueError``.
+ otherwise, raise a :class:`ValueError`.
EXAMPLES::
@@ -843,9 +842,11 @@ def fixed_point_set(self): # UHP
return self.domain().get_geodesic(*pts)
return pts
- def repelling_fixed_point(self): #UHP
+ def repelling_fixed_point(self): # UHP
r"""
- Return the repelling fixed point; otherwise raise a ``ValueError``.
+ Return the repelling fixed point.
+
+ Otherwise, this raises a :class:`ValueError`.
OUTPUT:
@@ -867,9 +868,11 @@ def repelling_fixed_point(self): #UHP
return self.domain().get_point(infinity)
return self.domain().get_point(v[0] / v[1])
- def attracting_fixed_point(self): #UHP
+ def attracting_fixed_point(self): # UHP
r"""
- Return the attracting fixed point; otherwise raise a ``ValueError``.
+ Return the attracting fixed point.
+
+ Otherwise, this raises a :class:`ValueError`.
OUTPUT:
diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_model.py b/src/sage/geometry/hyperbolic_space/hyperbolic_model.py
index 7890b222f37..33e5f0008fe 100644
--- a/src/sage/geometry/hyperbolic_space/hyperbolic_model.py
+++ b/src/sage/geometry/hyperbolic_space/hyperbolic_model.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Hyperbolic Models
@@ -156,7 +155,7 @@ def _repr_(self): # Abstract
sage: HyperbolicPlane().UHP()
Hyperbolic plane in the Upper Half Plane Model
"""
- return u'Hyperbolic plane in the {}'.format(self._name)
+ return 'Hyperbolic plane in the {}'.format(self._name)
def _element_constructor_(self, x, is_boundary=None, **graphics_options): # Abstract
"""
@@ -260,7 +259,7 @@ def point_in_model(self, p):
def point_test(self, p): # Abstract
r"""
Test whether a point is in the model. If the point is in the
- model, do nothing. Otherwise, raise a ``ValueError``.
+ model, do nothing. Otherwise, raise a :class:`ValueError`.
EXAMPLES::
@@ -298,7 +297,7 @@ def boundary_point_in_model(self, p): # Abstract
def bdry_point_test(self, p): # Abstract
r"""
Test whether a point is in the model. If the point is in the
- model, do nothing; otherwise raise a ``ValueError``.
+ model, do nothing; otherwise raise a :class:`ValueError`.
EXAMPLES::
@@ -340,7 +339,7 @@ def isometry_test(self, A): # Abstract
Test whether an isometry ``A`` is in the model.
If the isometry is in the model, do nothing. Otherwise, raise
- a ``ValueError``.
+ a :class:`ValueError`.
EXAMPLES::
@@ -1173,7 +1172,7 @@ def __init__(self, space):
# name should really be 'Poincaré Disk Model', but utf8 is not
# accepted by repr
HyperbolicModel.__init__(self, space,
- name=u'Poincare Disk Model', short_name="PD",
+ name='Poincare Disk Model', short_name="PD",
bounded=True, conformal=True, dimension=2,
isometry_group="PU(1, 1)",
isometry_group_is_projective=True)
diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_point.py b/src/sage/geometry/hyperbolic_space/hyperbolic_point.py
index 6ae2e260aac..650c90a4403 100644
--- a/src/sage/geometry/hyperbolic_space/hyperbolic_point.py
+++ b/src/sage/geometry/hyperbolic_space/hyperbolic_point.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Hyperbolic Points
diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py
index 90e620b71bc..1b429cdf804 100644
--- a/src/sage/geometry/hyperplane_arrangement/arrangement.py
+++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Hyperplane Arrangements
@@ -2723,7 +2722,7 @@ def region_containing_point(self, p):
OUTPUT:
- A polyhedron. A ``ValueError`` is raised if the point is not
+ A polyhedron. A :class:`ValueError` is raised if the point is not
interior to a region, that is, sits on a hyperplane.
EXAMPLES::
diff --git a/src/sage/geometry/hyperplane_arrangement/hyperplane.py b/src/sage/geometry/hyperplane_arrangement/hyperplane.py
index 8d4b301f8d8..18e39e286a0 100644
--- a/src/sage/geometry/hyperplane_arrangement/hyperplane.py
+++ b/src/sage/geometry/hyperplane_arrangement/hyperplane.py
@@ -484,7 +484,7 @@ def orthogonal_projection(self, point):
A vector in the ambient vector space that lies on the
hyperplane.
- In finite characteristic, a ``ValueError`` is raised if the
+ In finite characteristic, a :class:`ValueError` is raised if the
the norm of the hyperplane normal is zero.
EXAMPLES::
diff --git a/src/sage/geometry/hyperplane_arrangement/library.py b/src/sage/geometry/hyperplane_arrangement/library.py
index 4ec9f9fdbdf..cdfaca2faf0 100644
--- a/src/sage/geometry/hyperplane_arrangement/library.py
+++ b/src/sage/geometry/hyperplane_arrangement/library.py
@@ -65,7 +65,7 @@ def make_parent(base_ring, dimension, names=None):
return HyperplaneArrangements(base_ring, names=names)
-class HyperplaneArrangementLibrary():
+class HyperplaneArrangementLibrary:
"""
The library of hyperplane arrangements.
"""
diff --git a/src/sage/geometry/integral_points.pxi b/src/sage/geometry/integral_points.pxi
index 3ea46051b47..8d45f44714c 100644
--- a/src/sage/geometry/integral_points.pxi
+++ b/src/sage/geometry/integral_points.pxi
@@ -119,7 +119,7 @@ cpdef tuple parallelotope_points(spanning_points, lattice) noexcept:
sage: parallelotope_points(c.rays(), c.lattice())
(N(0, 0), N(1, 1))
- A ``ValueError`` is raised if the ``spanning_points`` are not
+ A :class:`ValueError` is raised if the ``spanning_points`` are not
linearly independent::
sage: rays = list(map(ToricLattice(2), [(1,1)]*2))
@@ -853,9 +853,9 @@ cdef class Inequality_int:
OUTPUT:
- Inequality `A x + b \geq 0`. A ``OverflowError`` is raised if a
+ Inequality `A x + b \geq 0`. A :class:`OverflowError` is raised if a
machine integer is not long enough to hold the results. A
- ``ValueError`` is raised if some of the input is not integral.
+ :class:`ValueError` is raised if some of the input is not integral.
EXAMPLES::
diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py
index 136cd370373..449143c8999 100644
--- a/src/sage/geometry/lattice_polytope.py
+++ b/src/sage/geometry/lattice_polytope.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Lattice and reflexive polytopes
@@ -5017,8 +5016,8 @@ def part_of_point(self, i):
Since a nef-partition induces a partition on the set of boundary
lattice points of `\Delta^\circ`, the value of `j` is well-defined
for all `i` but the one that corresponds to the origin, in which
- case this method will raise a ``ValueError`` exception. (The origin
- always belongs to all `\nabla_j`.)
+ case this method will raise a :class:`ValueError` exception.
+ (The origin always belongs to all `\nabla_j`.)
See :class:`nef-partition ` class documentation for
definitions and notation.
diff --git a/src/sage/geometry/point_collection.pyx b/src/sage/geometry/point_collection.pyx
index 3a67de459ed..aabb0bdcde3 100644
--- a/src/sage/geometry/point_collection.pyx
+++ b/src/sage/geometry/point_collection.pyx
@@ -756,7 +756,7 @@ cdef class PointCollection(SageObject):
OUTPUT:
- an integer if ``point`` is in ``self[start:stop]``, otherwise a
- ``ValueError`` exception is raised.
+ :class:`ValueError` exception is raised.
EXAMPLES::
diff --git a/src/sage/geometry/polyhedral_complex.py b/src/sage/geometry/polyhedral_complex.py
index d6e3b075656..09200a60be9 100644
--- a/src/sage/geometry/polyhedral_complex.py
+++ b/src/sage/geometry/polyhedral_complex.py
@@ -163,7 +163,7 @@ class PolyhedralComplex(GenericCellComplex):
- ``face_to_face_check`` -- boolean (default: ``False``);
if ``True``, then the constructor checks whether the cells
- are face-to-face, and it raises a ``ValueError`` if they are not
+ are face-to-face, and it raises a :class:`ValueError` if they are not
- ``is_mutable`` and ``is_immutable`` -- boolean (default: ``True`` and
``False`` respectively); set ``is_mutable=False`` or ``is_immutable=True``
@@ -967,7 +967,7 @@ def __contains__(self, x):
def __call__(self, x):
"""
If ``x`` is a polyhedron in this complex, return it.
- Otherwise, raise a ``ValueError``.
+ Otherwise, raise a :class:`ValueError`.
EXAMPLES::
@@ -1072,10 +1072,10 @@ def is_compact(self):
def graph(self):
"""
- The 1-skeleton of this polyhedral complex, as a graph.
+ Return the 1-skeleton of this polyhedral complex, as a graph.
- The vertices of the graph are of type ``vector``. Raises
- a ``NotImplementedError`` if the polyhedral complex is unbounded.
+ The vertices of the graph are of type ``vector``. This raises
+ a :class:`NotImplementedError` if the polyhedral complex is unbounded.
.. WARNING::
diff --git a/src/sage/geometry/polyhedron/backend_cdd.py b/src/sage/geometry/polyhedron/backend_cdd.py
index f0e7e3ada8b..e35ea92fe67 100644
--- a/src/sage/geometry/polyhedron/backend_cdd.py
+++ b/src/sage/geometry/polyhedron/backend_cdd.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
The cdd backend for polyhedral computations
"""
diff --git a/src/sage/geometry/polyhedron/backend_polymake.py b/src/sage/geometry/polyhedron/backend_polymake.py
index 089e687f3f8..a2bce697e1c 100644
--- a/src/sage/geometry/polyhedron/backend_polymake.py
+++ b/src/sage/geometry/polyhedron/backend_polymake.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
The polymake backend for polyhedral computations
diff --git a/src/sage/geometry/polyhedron/base4.py b/src/sage/geometry/polyhedron/base4.py
index 5313d64b357..2ba2a696b30 100644
--- a/src/sage/geometry/polyhedron/base4.py
+++ b/src/sage/geometry/polyhedron/base4.py
@@ -70,7 +70,7 @@ def vertex_facet_graph(self, labels=True):
This function constructs a directed bipartite graph.
The nodes of the graph correspond to the vertices of the polyhedron
- and the facets of the polyhedron. There is an directed edge
+ and the facets of the polyhedron. There is a directed edge
from a vertex to a face if and only if the vertex is incident to the face.
INPUT:
@@ -406,7 +406,7 @@ def hasse_diagram(self):
sage: D.degree_polynomial()
x^5 + x^4*y + x*y^4 + y^5 + 4*x^3*y + 8*x^2*y^2 + 4*x*y^3
- Faces of an mutable polyhedron are not hashable. Hence those are not suitable as
+ Faces of a mutable polyhedron are not hashable. Hence those are not suitable as
vertices of the hasse diagram. Use the combinatorial polyhedron instead::
sage: # needs sage.rings.number_field
diff --git a/src/sage/geometry/polyhedron/base7.py b/src/sage/geometry/polyhedron/base7.py
index c1c06b90a28..99ca1b7ebe7 100644
--- a/src/sage/geometry/polyhedron/base7.py
+++ b/src/sage/geometry/polyhedron/base7.py
@@ -133,7 +133,7 @@ def centroid(self, engine='auto', **kwds):
else:
from sage.geometry.triangulation.point_configuration import PointConfiguration
A, b = self.affine_hull_projection(as_affine_map=True, orthogonal=True, orthonormal=True, extend=True)
- pc = PointConfiguration((A(v.vector()) for v in self.Vrep_generator()))
+ pc = PointConfiguration(A(v.vector()) for v in self.Vrep_generator())
barycenters = [sum(self.Vrepresentation(i).vector() for i in simplex)/(self.dim() + 1) for simplex in triangulation]
volumes = [pc.volume(simplex) for simplex in triangulation]
diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx
index 8c23470e0e3..cd7b7316a43 100644
--- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx
+++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx
@@ -547,7 +547,7 @@ cdef tuple face_as_combinatorial_polyhedron(ListOfFaces facets, ListOfFaces Vrep
else:
delete = mem.allocarray(max(facets.n_faces(), facets.n_atoms()), sizeof(bint))
- # Set ``delete[i]`` to one if ``i`` is not an vertex of ``face``.
+ # Set ``delete[i]`` to one if ``i`` is not a vertex of ``face``.
for i in range(Vrep.n_faces()):
if face_issubset(face, Vrep.data.faces[i]):
delete[i] = 0
diff --git a/src/sage/geometry/polyhedron/library.py b/src/sage/geometry/polyhedron/library.py
index a1a59cdfe65..d48cffd5c5c 100644
--- a/src/sage/geometry/polyhedron/library.py
+++ b/src/sage/geometry/polyhedron/library.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Library of commonly used, famous, or interesting polytopes
@@ -489,7 +488,7 @@ def gale_transform_to_primal(vectors, base_ring=None, backend=None):
return m.right_kernel_matrix(basis='computed').columns()
-class Polytopes():
+class Polytopes:
"""
A class of constructors for commonly used, famous, or interesting
polytopes.
@@ -1003,7 +1002,7 @@ def rhombic_dodecahedron(self, backend=None):
sage: TestSuite(rd_norm).run() # optional - pynormaliz
"""
v = [[2,0,0],[-2,0,0],[0,2,0],[0,-2,0],[0,0,2],[0,0,-2]]
- v.extend((itertools.product([1, -1], repeat=3)))
+ v.extend(itertools.product([1, -1], repeat=3))
return Polyhedron(vertices=v, base_ring=ZZ, backend=backend)
def cuboctahedron(self, backend=None):
@@ -2552,7 +2551,7 @@ def permutahedron(self, n, project=False, backend=None):
sage: perm4.graph().is_isomorphic(graphs.BubbleSortGraph(4)) # needs sage.graphs
True
- As both Hrepresentation an Vrepresentation are known, the permutahedron can be set
+ As both Hrepresentation and Vrepresentation are known, the permutahedron can be set
up with both using the backend ``field``. The following takes very very long time
to recompute, e.g. with backend ``ppl``::
diff --git a/src/sage/geometry/polyhedron/plot.py b/src/sage/geometry/polyhedron/plot.py
index 5c2362cfdda..78767803eb0 100644
--- a/src/sage/geometry/polyhedron/plot.py
+++ b/src/sage/geometry/polyhedron/plot.py
@@ -144,7 +144,7 @@ def projection_func_identity(x):
return list(x)
-class ProjectionFuncStereographic():
+class ProjectionFuncStereographic:
"""
The stereographic (or perspective) projection onto a codimension-1 linear
subspace with respect to a sphere centered at the origin.
@@ -238,7 +238,7 @@ def __call__(self, x):
return vector(RDF, [img[i] / denom for i in range(self.dim - 1)])
-class ProjectionFuncSchlegel():
+class ProjectionFuncSchlegel:
"""
The Schlegel projection from the given input point.
diff --git a/src/sage/geometry/riemannian_manifolds/surface3d_generators.py b/src/sage/geometry/riemannian_manifolds/surface3d_generators.py
index ba8eff2ed2a..a75fdb0f2f2 100644
--- a/src/sage/geometry/riemannian_manifolds/surface3d_generators.py
+++ b/src/sage/geometry/riemannian_manifolds/surface3d_generators.py
@@ -23,7 +23,7 @@
ParametrizedSurface3D
-class SurfaceGenerators():
+class SurfaceGenerators:
"""
A class consisting of generators for several common parametrized surfaces
in 3D.
diff --git a/src/sage/geometry/toric_lattice.py b/src/sage/geometry/toric_lattice.py
index a72f31f04d2..4a34a6a510e 100644
--- a/src/sage/geometry/toric_lattice.py
+++ b/src/sage/geometry/toric_lattice.py
@@ -677,7 +677,7 @@ def quotient(self, sub, check=True,
by Sublattice
Attempting to quotient one lattice by a sublattice of another
- will result in a ``ValueError``::
+ will result in a :class:`ValueError`::
sage: N = ToricLattice(3)
sage: M = ToricLattice(3, name='M')
@@ -1467,7 +1467,7 @@ def __init__(self, V, W, check=True, positive_point=None, positive_dual_point=No
sage: ToricLattice_quotient(N, N.span([N(1,2,3)]))
2-d lattice, quotient of 3-d lattice N by Sublattice
- An ``ArithmeticError`` will be raised if ``W`` is not a
+ An :class:`ArithmeticError` will be raised if ``W`` is not a
sublattice of ``V``::
sage: N = ToricLattice(3)
diff --git a/src/sage/geometry/toric_lattice_element.pyx b/src/sage/geometry/toric_lattice_element.pyx
index bc736243642..60782a805f4 100644
--- a/src/sage/geometry/toric_lattice_element.pyx
+++ b/src/sage/geometry/toric_lattice_element.pyx
@@ -300,7 +300,7 @@ cdef class ToricLatticeElement(Vector_integer_dense):
# is wrong from our point of view.
cpdef _dot_product_(self, Vector right) noexcept:
"""
- Raise a ``TypeError`` exception.
+ Raise a :class:`TypeError` exception.
Dot product is not defined on toric lattices (there are actions of
dual lattices on each other instead).
@@ -311,7 +311,7 @@ cdef class ToricLatticeElement(Vector_integer_dense):
OUTPUT:
- - ``TypeError`` exception is raised.
+ - :class:`TypeError` exception is raised.
TESTS::
diff --git a/src/sage/geometry/toric_plotter.py b/src/sage/geometry/toric_plotter.py
index 950e3ba7ff8..2943daa49bd 100644
--- a/src/sage/geometry/toric_plotter.py
+++ b/src/sage/geometry/toric_plotter.py
@@ -746,7 +746,7 @@ def _unrecognized_option(option):
OUTPUT:
- - none, a ``KeyError`` exception is raised.
+ - none, a :class:`KeyError` exception is raised.
TESTS::
diff --git a/src/sage/geometry/triangulation/base.pyx b/src/sage/geometry/triangulation/base.pyx
index 61014429fdd..3161d19afba 100644
--- a/src/sage/geometry/triangulation/base.pyx
+++ b/src/sage/geometry/triangulation/base.pyx
@@ -588,7 +588,7 @@ cdef class PointConfiguration_base(Parent):
def _assert_is_affine(self):
"""
- Raise a ``ValueError`` if the point configuration is not
+ Raise a :class:`ValueError` if the point configuration is not
defined by affine points.
EXAMPLES::
diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py
index 68ac3119945..89d486b1e4f 100644
--- a/src/sage/geometry/triangulation/point_configuration.py
+++ b/src/sage/geometry/triangulation/point_configuration.py
@@ -733,7 +733,7 @@ def _TOPCOM_triangulate(self, verbose=True):
OUTPUT:
A :class:`~sage.geometry.triangulation.element.Triangulation`
- satisfying all restrictions imposed. Raises a ``ValueError``
+ satisfying all restrictions imposed. This raises a :class:`ValueError`
if no such triangulation exists.
EXAMPLES::
@@ -1037,7 +1037,7 @@ def triangulate(self, verbose=False):
OUTPUT:
A :class:`~sage.geometry.triangulation.element.Triangulation`
- satisfying all restrictions imposed. Raises a ``ValueError``
+ satisfying all restrictions imposed. This raises a :class:`ValueError`
if no such triangulation exists.
EXAMPLES::
diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx
index 84b048c84c5..5c7aa0b61c8 100644
--- a/src/sage/graphs/base/boost_graph.pyx
+++ b/src/sage/graphs/base/boost_graph.pyx
@@ -2298,7 +2298,7 @@ cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost,
Return the diameter of a weighted directed graph.
The ``DiFUB`` (Directed iterative Fringe Upper Bound) algorithm calculates
- the exact value of the diameter of an weighted directed graph [CGLM2012]_.
+ the exact value of the diameter of a weighted directed graph [CGLM2012]_.
This algorithm starts from a vertex found through a 2Dsweep call (a directed
version of the 2sweep method). The worst case time complexity of the DiFUB
@@ -2492,11 +2492,11 @@ cpdef diameter(G, algorithm=None, source=None,
- ``algorithm`` -- string (default: ``None``); specifies the algorithm to
use among:
- - ``'2Dsweep'`` -- Computes lower bound on the diameter of an weighted
+ - ``'2Dsweep'`` -- Computes lower bound on the diameter of a weighted
directed graph using the weighted version of the algorithm proposed in
[Broder2000]_. See the code's documentation for more details.
- - ``'DiFUB'`` -- Computes the diameter of an weighted directed graph
+ - ``'DiFUB'`` -- Computes the diameter of a weighted directed graph
using the weighted version of the algorithm proposed in [CGLM2012]_.
See the code's documentation for more details.
diff --git a/src/sage/graphs/base/c_graph.pyx b/src/sage/graphs/base/c_graph.pyx
index 7ca6c5dd124..70ce392a43c 100644
--- a/src/sage/graphs/base/c_graph.pyx
+++ b/src/sage/graphs/base/c_graph.pyx
@@ -624,8 +624,8 @@ cdef class CGraph:
OUTPUT:
- - Raise a ``NotImplementedError``. This method is not implemented in
- this base class. A child class should provide a suitable
+ - Raise a :class:`NotImplementedError`. This method is not implemented
+ in this base class. A child class should provide a suitable
implementation.
.. SEEALSO::
@@ -1267,7 +1267,7 @@ cdef class CGraph:
OUTPUT:
- - Raise ``NotImplementedError``. This method is not implemented at
+ - Raise :class:`NotImplementedError`. This method is not implemented at
the :class:`CGraph` level. A child class should provide a suitable
implementation.
diff --git a/src/sage/graphs/base/graph_backends.pyx b/src/sage/graphs/base/graph_backends.pyx
index 863f61be013..77961c33cf6 100644
--- a/src/sage/graphs/base/graph_backends.pyx
+++ b/src/sage/graphs/base/graph_backends.pyx
@@ -6,7 +6,7 @@ This module implements :class:`GenericGraphBackend` (the base class for
backends).
Any graph backend must redefine the following methods (for which
-:class:`GenericGraphBackend` raises a ``NotImplementedError``)
+:class:`GenericGraphBackend` raises a :class:`NotImplementedError`)
.. csv-table::
:class: contentstable
diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py
index 0a03affa422..6bb65e6ad33 100644
--- a/src/sage/graphs/bipartite_graph.py
+++ b/src/sage/graphs/bipartite_graph.py
@@ -1,5 +1,4 @@
# autopep8: off
-# -*- coding: utf-8 -*-
r"""
Bipartite graphs
diff --git a/src/sage/graphs/bliss.pyx b/src/sage/graphs/bliss.pyx
index eac56e21f0d..c623b5fe402 100644
--- a/src/sage/graphs/bliss.pyx
+++ b/src/sage/graphs/bliss.pyx
@@ -396,9 +396,10 @@ cpdef canonical_form(G, partition=None, return_graph=False, use_edge_labels=True
canonical graph of ``G`` or its set of edges
- ``use_edge_labels`` -- boolean (default: ``True``); whether to consider
- edge labels. The edge labels are assumed to be hashable and sortable. If
- this is not the case (ie a ``TypeError`` is raised), the algorithm will
- consider the string representations of the labels instead of the labels.
+ edge labels. The edge labels are assumed to be hashable and
+ sortable. If this is not the case (ie a :class:`TypeError` is
+ raised), the algorithm will consider the string representations
+ of the labels instead of the labels.
- ``certificate`` -- boolean (default: ``False``); when set to ``True``,
returns the labeling of G into a canonical graph
diff --git a/src/sage/graphs/connectivity.pyx b/src/sage/graphs/connectivity.pyx
index 5c8166bd540..910fcc88df8 100644
--- a/src/sage/graphs/connectivity.pyx
+++ b/src/sage/graphs/connectivity.pyx
@@ -3969,7 +3969,7 @@ cdef class TriconnectivitySPQR:
self.in_adj[eh_index] = e_virt_node
# end type-1 search
- # if an path starts at edge e, empty the tstack.
+ # if a path starts at edge e, empty the tstack.
if self.starts_path[e_index]:
while self.__tstack_not_eos():
self.t_stack_top -= 1
diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py
index 8ba57d90b3c..58f902b10cd 100644
--- a/src/sage/graphs/digraph.py
+++ b/src/sage/graphs/digraph.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Directed graphs
@@ -1195,7 +1194,7 @@ def neighbor_in_iterator(self, vertex):
"""
Return an iterator over the in-neighbors of ``vertex``.
- An vertex `u` is an in-neighbor of a vertex `v` if `uv` in an edge.
+ A vertex `u` is an in-neighbor of a vertex `v` if `uv` in an edge.
EXAMPLES::
@@ -1672,7 +1671,7 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False,
p = MixedIntegerLinearProgram(constraint_generation=True,
maximization=False, solver=solver)
- # An variable for each edge
+ # A variable for each edge
b = p.new_variable(binary=True)
# Variables are binary, and their coefficient in the objective is
@@ -3187,9 +3186,9 @@ def topological_sort(self, implementation="default"):
"""
Return a topological sort of the digraph if it is acyclic.
- If the digraph contains a directed cycle, a ``TypeError`` is raised. As
- topological sorts are not necessarily unique, different implementations
- may yield different results.
+ If the digraph contains a directed cycle, a :class:`TypeError`
+ is raised. As topological sorts are not necessarily unique,
+ different implementations may yield different results.
A topological sort is an ordering of the vertices of the digraph such
that each vertex comes before all of its successors. That is, if `u`
@@ -3269,7 +3268,8 @@ def topological_sort_generator(self):
Return an iterator over all topological sorts of the digraph if
it is acyclic.
- If the digraph contains a directed cycle, a ``TypeError`` is raised.
+ If the digraph contains a directed cycle, a :class:`TypeError`
+ is raised.
A topological sort is an ordering of the vertices of the digraph such
that each vertex comes before all of its successors. That is, if u comes
diff --git a/src/sage/graphs/digraph_generators.py b/src/sage/graphs/digraph_generators.py
index 2b29e0e73ef..d182f49afb1 100644
--- a/src/sage/graphs/digraph_generators.py
+++ b/src/sage/graphs/digraph_generators.py
@@ -74,7 +74,7 @@
from sage.graphs.graph import Graph
-class DiGraphGenerators():
+class DiGraphGenerators:
r"""
A class consisting of constructors for several common digraphs,
including orderly generation of isomorphism class representatives.
diff --git a/src/sage/graphs/domination.py b/src/sage/graphs/domination.py
index 7f631fcfe28..6323cdd29e4 100644
--- a/src/sage/graphs/domination.py
+++ b/src/sage/graphs/domination.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Domination
diff --git a/src/sage/graphs/generators/basic.py b/src/sage/graphs/generators/basic.py
index 5dbacb4de26..0dc2c00baef 100644
--- a/src/sage/graphs/generators/basic.py
+++ b/src/sage/graphs/generators/basic.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Basic graphs
@@ -400,7 +399,7 @@ def CompleteGraph(n):
G.set_pos({0: (0, 0)})
else:
G._circle_embedding(list(range(n)), angle=pi/2)
- G.add_edges(((i, j) for i in range(n) for j in range(i + 1, n)))
+ G.add_edges((i, j) for i in range(n) for j in range(i + 1, n))
return G
def CorrelationGraph(seqs, alpha, include_anticorrelation):
diff --git a/src/sage/graphs/generators/chessboard.py b/src/sage/graphs/generators/chessboard.py
index dfe5b15b273..a76d6f98de7 100644
--- a/src/sage/graphs/generators/chessboard.py
+++ b/src/sage/graphs/generators/chessboard.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Chessboard graphs
diff --git a/src/sage/graphs/generators/degree_sequence.py b/src/sage/graphs/generators/degree_sequence.py
index f5e68d89c79..05c021403b0 100644
--- a/src/sage/graphs/generators/degree_sequence.py
+++ b/src/sage/graphs/generators/degree_sequence.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Graphs with a given degree sequence
@@ -98,8 +97,8 @@ def DegreeSequenceBipartite(s1, s2):
True
Some sequences being incompatible if, for example, their sums are different,
- the functions raises a ``ValueError`` when no graph corresponding to the
- degree sequences exists::
+ the functions raises a :class:`ValueError` when no graph corresponding
+ to the degree sequences exists::
sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,1],[5,5]) # needs sage.combinat sage.modules
Traceback (most recent call last):
diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py
index 85ea52a4571..c962378cd25 100644
--- a/src/sage/graphs/generators/families.py
+++ b/src/sage/graphs/generators/families.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Various families of graphs
@@ -594,7 +593,7 @@ def BarbellGraph(n1, n2):
OUTPUT:
- A barbell graph of order ``2*n1 + n2``. A ``ValueError`` is
+ A barbell graph of order ``2*n1 + n2``. A :class:`ValueError` is
returned if ``n1 < 2`` or ``n2 < 0``.
PLOTTING:
@@ -929,7 +928,7 @@ def BubbleSortGraph(n):
OUTPUT:
The bubble sort graph `B(n)` on `n` symbols. If `n < 1`, a
- ``ValueError`` is returned.
+ :class:`ValueError` is returned.
EXAMPLES::
@@ -2714,7 +2713,7 @@ def SwitchedSquaredSkewHadamardMatrixGraph(n):
G = SquaredSkewHadamardMatrixGraph(n).complement()
G.add_vertex((4 * n - 1)**2)
G.seidel_switching(list(range((4 * n - 1) * (2 * n - 1))))
- G.name("switch skewhad^2+*_" + str((n)))
+ G.name("switch skewhad^2+*_" + str(n))
return G
@@ -3920,7 +3919,13 @@ def MathonPseudocyclicStronglyRegularGraph(t, G=None, L=None):
sage: G.is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings
(45, 22, 10, 11)
- Supplying ``G`` and ``L`` (constructed from the automorphism group of ``G``). ::
+ Supplying ``G`` and ``L`` (constructed from the automorphism group
+ of ``G``). The entries of L can't be tested directly because
+ there's some unpredictability in the way that GAP chooses a
+ representative in ``NormalSubgroups()``, the function that
+ underlies our own
+ :meth:`~sage.groups.perm_gps.permgroup.PermutationGroup_generic.normal_subgroups`
+ method::
sage: # needs sage.groups sage.libs.gap sage.rings.finite_rings
sage: G = graphs.PaleyGraph(9)
@@ -3931,18 +3936,7 @@ def MathonPseudocyclicStronglyRegularGraph(t, G=None, L=None):
....: for z in subg]
sage: ff = list(map(lambda y: (y[0]-1,y[1]-1),
....: Permutation(map(lambda x: 1+r.index(x^-1), r)).cycle_tuples()[1:]))
- sage: L = sum(i*(r[a]-r[b]) for i,(a,b) in zip(range(1,len(ff)+1), ff)); L
- [ 0 1 -1 -3 -2 -4 3 4 2]
- [-1 0 1 -4 -3 -2 2 3 4]
- [ 1 -1 0 -2 -4 -3 4 2 3]
- [ 3 4 2 0 1 -1 -3 -2 -4]
- [ 2 3 4 -1 0 1 -4 -3 -2]
- [ 4 2 3 1 -1 0 -2 -4 -3]
- [-3 -2 -4 3 4 2 0 1 -1]
- [-4 -3 -2 2 3 4 -1 0 1]
- [-2 -4 -3 4 2 3 1 -1 0]
-
- sage: # needs sage.groups sage.libs.gap sage.modules sage.rings.finite_rings
+ sage: L = sum(i*(r[a]-r[b]) for i,(a,b) in zip(range(1,len(ff)+1), ff))
sage: G.relabel(range(9))
sage: G3x3 = graphs.MathonPseudocyclicStronglyRegularGraph(2, G=G, L=L)
sage: G3x3.is_strongly_regular(parameters=True)
diff --git a/src/sage/graphs/generators/intersection.py b/src/sage/graphs/generators/intersection.py
index 0d19d30f9ea..0434806fb73 100644
--- a/src/sage/graphs/generators/intersection.py
+++ b/src/sage/graphs/generators/intersection.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Intersection graphs
diff --git a/src/sage/graphs/generators/platonic_solids.py b/src/sage/graphs/generators/platonic_solids.py
index d3bc60a9974..5a572611539 100644
--- a/src/sage/graphs/generators/platonic_solids.py
+++ b/src/sage/graphs/generators/platonic_solids.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
1-skeletons of Platonic solids
diff --git a/src/sage/graphs/generators/random.py b/src/sage/graphs/generators/random.py
index 22c1f583f6a..e0868b36e21 100644
--- a/src/sage/graphs/generators/random.py
+++ b/src/sage/graphs/generators/random.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Random graphs
diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py
index 3b47f29f2ff..bde0cafc0a8 100644
--- a/src/sage/graphs/generators/smallgraphs.py
+++ b/src/sage/graphs/generators/smallgraphs.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Various small graphs
diff --git a/src/sage/graphs/generators/world_map.py b/src/sage/graphs/generators/world_map.py
index f131aa446e2..76ec2b4f9ae 100644
--- a/src/sage/graphs/generators/world_map.py
+++ b/src/sage/graphs/generators/world_map.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Graphs from the World Map
diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py
index 0f0f995bfbd..e6677c26803 100644
--- a/src/sage/graphs/generic_graph.py
+++ b/src/sage/graphs/generic_graph.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Generic graphs (common to directed/undirected)
@@ -2933,8 +2932,8 @@ def _check_embedding_validity(self, embedding=None, boolean=True):
``_embedding``
- ``boolean`` -- boolean (default: ``True``); -- whether to return a
- boolean answer or raise a ``ValueError`` exception if the embedding is
- invalid
+ boolean answer or raise a :class:`ValueError` exception
+ if the embedding is invalid
EXAMPLES::
@@ -3443,8 +3442,8 @@ def allow_multiple_edges(self, new, check=True, keep_label='any'):
.. WARNING::
``'min'`` and ``'max'`` only works if the labels can be compared. A
- ``TypeError`` might be raised when working with non-comparable
- objects in Python 3.
+ :class:`TypeError` might be raised when working with non-comparable
+ objects.
EXAMPLES:
@@ -4092,7 +4091,7 @@ def density(self):
if n < 2:
return Rational(0)
if self._directed:
- return Rational(self.size()) / Rational((n ** 2 - n))
+ return Rational(self.size()) / Rational(n ** 2 - n)
return Rational(self.size()) / Rational((n ** 2 - n) / 2)
def is_bipartite(self, certificate=False):
@@ -8359,7 +8358,7 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False,
EXAMPLES:
- The `3 \times 3`-grid has an Hamiltonian path, an hamiltonian path
+ The `3 \times 3`-grid has a Hamiltonian path, a hamiltonian path
starting from vertex `(0, 0)` and ending at vertex `(2, 2)`, but no
Hamiltonian path starting from `(0, 0)` and ending at `(0, 1)`::
@@ -8531,7 +8530,7 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False,
g.add_edge(v, new_s, 0)
#
- # We now search for an Hamiltonian Cycle in g
+ # We now search for a Hamiltonian Cycle in g
#
from sage.categories.sets_cat import EmptySetError
try:
@@ -14065,7 +14064,7 @@ def subgraph_search_count(self, G, induced=False):
.. SEEALSO::
- - :meth:`~GenericGraph.subgraph_search` -- finds an subgraph
+ - :meth:`~GenericGraph.subgraph_search` -- finds a subgraph
isomorphic to `H` inside of a graph `G`
- :meth:`~GenericGraph.subgraph_search_iterator` -- iterator over
@@ -14174,7 +14173,7 @@ def subgraph_search_iterator(self, G, induced=False, return_graphs=True):
.. SEEALSO::
- - :meth:`~GenericGraph.subgraph_search` -- finds an subgraph
+ - :meth:`~GenericGraph.subgraph_search` -- finds a subgraph
isomorphic to `H` inside of `G`
- :meth:`~GenericGraph.subgraph_search_count` -- counts the number
@@ -18894,8 +18893,8 @@ def to_simple(self, to_undirected=True, keep_label='any', immutable=None):
.. WARNING::
``'min'`` and ``'max'`` only works if the labels can be compared. A
- ``TypeError`` might be raised when working with non-comparable
- objects in Python 3.
+ :class:`TypeError` might be raised when working with non-comparable
+ objects.
- ``immutable`` -- boolean (default: ``Non``); whether to create a
mutable/immutable copy. ``immutable=None`` (default) means that the
@@ -21634,7 +21633,7 @@ def graphviz_string(self, **options):
- a HSV sequence in a string such as ``".52,.386,.22"``
- - an hexadecimal code such as ``"#DA3305"``
+ - a hexadecimal code such as ``"#DA3305"``
- a 3-tuple of floating point (to be interpreted as RGB tuple). In
this case the 3-tuple is converted in hexadecimal code.
@@ -25341,7 +25340,7 @@ def graph_isom_equivalent_non_edge_labeled_graph(g, partition=None, standard_lab
for el, part in edge_partition:
# The multiplicity of a label is the number of edges from u to v
# it represents
- m = sum((y[1] for y in el))
+ m = sum(y[1] for y in el)
if m in tmp:
tmp[m].append(part)
else:
diff --git a/src/sage/graphs/generic_graph_pyx.pyx b/src/sage/graphs/generic_graph_pyx.pyx
index d27b3b65047..653a36d43f3 100644
--- a/src/sage/graphs/generic_graph_pyx.pyx
+++ b/src/sage/graphs/generic_graph_pyx.pyx
@@ -501,7 +501,7 @@ def length_and_string_from_graph6(s):
INPUT:
- - ``s`` -- a graph6 string describing an binary vector (and encoding its
+ - ``s`` -- a graph6 string describing a binary vector (and encoding its
length).
EXAMPLES::
@@ -1349,7 +1349,7 @@ cpdef tuple find_hamiltonian(G, long max_iter=100000, long reset_bound=30000,
find_path = (find_path > 0)
if G.is_clique(induced=False):
- # We have an hamiltonian path since n >= 2, but we have an hamiltonian
+ # We have a hamiltonian path since n >= 2, but we have a hamiltonian
# cycle only if n >= 3
return find_path or n >= 3, list(G)
diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py
index 8988765d767..0308fbca960 100644
--- a/src/sage/graphs/graph.py
+++ b/src/sage/graphs/graph.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Undirected graphs
@@ -885,7 +884,7 @@ class Graph(GenericGraph):
sage: Graph(igraph.Graph(directed=True)) # optional - python_igraph
Traceback (most recent call last):
...
- ValueError: An *undirected* igraph graph was expected. To build an directed graph, call the DiGraph constructor.
+ ValueError: An *undirected* igraph graph was expected. To build a directed graph, call the DiGraph constructor.
sage: # needs sage.modules
sage: m = matrix([[0, -1], [-1, 0]])
@@ -1206,7 +1205,7 @@ def __init__(self, data=None, pos=None, loops=None, format=None,
elif format == 'igraph':
if data.is_directed():
raise ValueError("An *undirected* igraph graph was expected. "
- "To build an directed graph, call the DiGraph "
+ "To build a directed graph, call the DiGraph "
"constructor.")
self.add_vertices(range(data.vcount()))
@@ -3285,8 +3284,8 @@ def bounded_outdegree_orientation(self, bound, solver=None, verbose=False,
OUTPUT:
- A DiGraph representing the orientation if it exists. A ``ValueError``
- exception is raised otherwise.
+ A DiGraph representing the orientation if it exists.
+ A :class:`ValueError` exception is raised otherwise.
ALGORITHM:
@@ -7985,7 +7984,7 @@ def modular_decomposition(self, algorithm=None, style='tuple'):
vertex of `C` has a neighbor outside of it.
* An anticomponent `C` (or the union of some --but not all-- of them) of
- an non-anticonnected graph `G`, for the same reason (it is just the
+ a non-anticonnected graph `G`, for the same reason (it is just the
complement of the previous graph !).
These modules being of special interest, the disjoint union of graphs is
diff --git a/src/sage/graphs/graph_decompositions/modular_decomposition.py b/src/sage/graphs/graph_decompositions/modular_decomposition.py
index 7a0c71c2fb1..c994475bd6b 100644
--- a/src/sage/graphs/graph_decompositions/modular_decomposition.py
+++ b/src/sage/graphs/graph_decompositions/modular_decomposition.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Modular Decomposition
diff --git a/src/sage/graphs/graph_decompositions/tree_decomposition.pyx b/src/sage/graphs/graph_decompositions/tree_decomposition.pyx
index 991f06efcce..803f5a09771 100644
--- a/src/sage/graphs/graph_decompositions/tree_decomposition.pyx
+++ b/src/sage/graphs/graph_decompositions/tree_decomposition.pyx
@@ -1083,37 +1083,31 @@ def label_nice_tree_decomposition(nice_TD, root, directed=False):
EXAMPLES::
sage: from sage.graphs.graph_decompositions.tree_decomposition import make_nice_tree_decomposition, label_nice_tree_decomposition
- sage: bip_one_four = graphs.CompleteBipartiteGraph(1, 4)
- sage: bip_one_four_TD = bip_one_four.treewidth(certificate=True)
- sage: nice_TD = make_nice_tree_decomposition(bip_one_four, bip_one_four_TD)
+ sage: claw = graphs.CompleteBipartiteGraph(1, 3)
+ sage: claw_TD = claw.treewidth(certificate=True)
+ sage: nice_TD = make_nice_tree_decomposition(claw, claw_TD)
sage: root = sorted(nice_TD.vertices())[0]
sage: label_TD = label_nice_tree_decomposition(nice_TD, root, directed=True)
- sage: print(label_TD.name())
- Labelled Nice tree decomposition of Tree decomposition
- sage: for node in sorted(label_TD):
+ sage: label_TD.name()
+ 'Labelled Nice tree decomposition of Tree decomposition'
+ sage: for node in sorted(label_TD): # random
....: print(node, label_TD.get_vertex(node))
(0, {}) forget
(1, {0}) forget
(2, {0, 1}) intro
(3, {0}) forget
- (4, {0, 4}) join
- (5, {0, 4}) intro
- (6, {0, 4}) intro
- (7, {0}) forget
- (8, {0}) forget
- (9, {0, 3}) intro
- (10, {0, 2}) intro
- (11, {3}) intro
- (12, {2}) intro
- (13, {}) leaf
- (14, {}) leaf
+ (4, {0, 3}) intro
+ (5, {0}) forget
+ (6, {0, 2}) intro
+ (7, {2}) intro
+ (8, {}) leaf
"""
from sage.graphs.digraph import DiGraph
from sage.graphs.graph import Graph
directed_TD = DiGraph(nice_TD.breadth_first_search(start=root, edges=True),
format='list_of_edges',
- name='Labelled {}'.format(nice_TD))
+ name='Labelled {}'.format(nice_TD.name()))
# The loop starts from the root node
# We assume the tree decomposition is valid and nice,
diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py
index 0677028e451..58a52a309f2 100644
--- a/src/sage/graphs/graph_generators.py
+++ b/src/sage/graphs/graph_generators.py
@@ -475,7 +475,7 @@ def wrap_name(x):
from . import graph
-class GraphGenerators():
+class GraphGenerators:
r"""
A class consisting of constructors for several common graphs, as well as
orderly generation of isomorphism class representatives. See the
@@ -1192,6 +1192,121 @@ def nauty_genbg(self, options="", debug=False):
G = BipartiteGraph(s[:-1], format='graph6', partition=partition)
yield G
+ def nauty_genktreeg(self, options="", debug=False):
+ r"""
+ Return a generator which creates all `k`-trees using nauty..
+
+ A `k`-tree is an undirected graph formed by starting with a complete
+ graph on `k + 1` vertices and then repeatedly add vertices in such a
+ way that each added vertex `v` has exactly `k` neighbors `U` such that,
+ together, the `k + 1` vertices formed by `v` and `U` form a clique.
+ See the :wikipedia:`K-tree` for more details.
+
+ INPUT:
+
+ - ``options`` -- string (default: ``""``); a string passed to
+ ``genktreeg`` as if it was run at a system command line. At a minimum,
+ you *must* pass the number of vertices you desire. Sage expects the
+ graphs to be in nauty's "graph6" format, do not set an option to
+ change this default or results will be unpredictable.
+
+ - ``debug`` -- boolean (default: ``False``); if ``True`` the first line
+ of ``genktreeg``'s output to standard error is captured and the first
+ call to the generator's ``next()`` function will return this line as a
+ string. A line leading with ">A" indicates a successful initiation of
+ the program with some information on the arguments, while a line
+ beginning with ">E" indicates an error with the input.
+
+ The possible options, obtained as output of ``genktreeg --help``::
+
+ n : the number of vertices
+ -k : the value of `k`(default: 2)
+ res/mod : only generate subset res out of subsets 0..mod-1
+ -l : canonically label output graphs
+
+ Options which cause ``genktreeg`` to use an output format different than
+ the graph6 format are not listed above (-u, -s, -h) as they will confuse
+ the creation of a Sage graph. The res/mod option can be useful when
+ using the output in a routine run several times in parallel.
+
+ OUTPUT:
+
+ A generator which will produce the graphs as Sage graphs.
+ These will be simple graphs: no loops, no multiple edges, no
+ directed edges.
+
+ EXAMPLES:
+
+ A `k`-tree is a maximal graph with treewidth `k`::
+
+ sage: # needs nauty
+ sage: gen = graphs.nauty_genktreeg("10 -k4")
+ sage: G = next(gen); G
+ Graph on 10 vertices
+ sage: G.treewidth()
+ 4
+
+ A list of all 2-trees with 6, 7 and 8 vertices. This agrees with
+ :oeis:`A054581`::
+
+ sage: # needs nauty
+ sage: gen = graphs.nauty_genktreeg("6")
+ sage: len(list(gen))
+ 5
+ sage: gen = graphs.nauty_genktreeg("7")
+ sage: len(list(gen))
+ 12
+ sage: gen = graphs.nauty_genktreeg("8")
+ sage: len(list(gen))
+ 39
+
+ The ``debug`` switch can be used to examine ``geng``'s reaction to the
+ input in the ``options`` string. We illustrate success. (A failure
+ will be a string beginning with ">E".) Passing the "-q" switch to
+ ``geng`` will suppress the indicator of a successful initiation, and so
+ the first returned value might be an empty string if ``debug`` is
+ ``True``::
+
+ sage: gen = graphs.nauty_genktreeg("7", debug=True) # needs nauty
+ sage: print(next(gen)) # needs nauty
+ >A ...genktreeg k=2 n=7
+
+ TESTS:
+
+ Wrong input::
+
+ sage: # needs nauty
+ sage: list(graphs.nauty_genktreeg("4 -k5", debug=True))
+ ['>E genktreeg: n cannot be less than k\n']
+ sage: list(graphs.nauty_genktreeg("10 -k 4", debug=True))
+ ['>E genktreeg -k: missing argument value\n']
+ sage: list(graphs.nauty_genktreeg("-c3", debug=False))
+ Traceback (most recent call last):
+ ...
+ ValueError: wrong format of parameter option
+ """
+ import shlex
+ from sage.features.nauty import NautyExecutable
+ geng_path = NautyExecutable("genktreeg").absolute_filename()
+ sp = subprocess.Popen(shlex.quote(geng_path) + " {0}".format(options), shell=True,
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, close_fds=True,
+ encoding='latin-1')
+ msg = sp.stderr.readline()
+ if debug:
+ yield msg
+ elif msg.startswith('>E'):
+ raise ValueError('wrong format of parameter option')
+ gen = sp.stdout
+ while True:
+ try:
+ s = next(gen)
+ except StopIteration:
+ # Exhausted list of graphs from nauty geng
+ return
+ G = graph.Graph(s[:-1], format='graph6')
+ yield G
+
def cospectral_graphs(self, vertices, matrix_function=None, graphs=None):
r"""
Find all sets of graphs on ``vertices`` vertices (with
diff --git a/src/sage/graphs/graph_input.py b/src/sage/graphs/graph_input.py
index 193afc9c4eb..4e08af6a4fc 100644
--- a/src/sage/graphs/graph_input.py
+++ b/src/sage/graphs/graph_input.py
@@ -559,7 +559,7 @@ def from_dict_of_lists(G, D, loops=False, multiedges=False, weighted=False):
for u in D:
if len(set(D[u])) != len(D[u]):
if multiedges is False:
- v = next((v for v in D[u] if D[u].count(v) > 1))
+ v = next(v for v in D[u] if D[u].count(v) > 1)
raise ValueError("non-multigraph got several edges (%s, %s)" % (u, v))
multiedges = True
break
diff --git a/src/sage/graphs/graph_latex.py b/src/sage/graphs/graph_latex.py
index 1cd878bec5a..bff200a1a86 100644
--- a/src/sage/graphs/graph_latex.py
+++ b/src/sage/graphs/graph_latex.py
@@ -625,7 +625,7 @@ def set_option(self, option_name, option_value=None):
- ``option_name`` -- a string for a latex option contained in the list
``sage.graphs.graph_latex.GraphLatex.__graphlatex_options``.
- A ``ValueError`` is raised if the option is not allowed.
+ A :class:`ValueError` is raised if the option is not allowed.
- ``option_value`` -- a value for the option. If omitted, or set to
``None``, the option will use the default value.
diff --git a/src/sage/graphs/hypergraph_generators.py b/src/sage/graphs/hypergraph_generators.py
index 4291e024001..f5218e225f1 100644
--- a/src/sage/graphs/hypergraph_generators.py
+++ b/src/sage/graphs/hypergraph_generators.py
@@ -32,7 +32,7 @@
"""
-class HypergraphGenerators():
+class HypergraphGenerators:
r"""
A class consisting of constructors for common hypergraphs.
"""
diff --git a/src/sage/graphs/lovasz_theta.py b/src/sage/graphs/lovasz_theta.py
index 49bc7e32092..5335a597ebf 100644
--- a/src/sage/graphs/lovasz_theta.py
+++ b/src/sage/graphs/lovasz_theta.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Lovász theta-function of graphs
diff --git a/src/sage/graphs/partial_cube.py b/src/sage/graphs/partial_cube.py
index 147f1acb097..79b1edc957c 100644
--- a/src/sage/graphs/partial_cube.py
+++ b/src/sage/graphs/partial_cube.py
@@ -363,7 +363,7 @@ def is_partial_cube(G, certificate=False):
# Make a digraph with edges labeled by the equivalence classes in unionfind
g = DiGraph({v: {w: unionfind.find((v, w)) for w in G[v]} for v in G})
- # Associates to a vertex the token that acts on it, an check that
+ # Associates to a vertex the token that acts on it, and check that
# no two edges on a single vertex have the same label
action = {}
for v in g:
diff --git a/src/sage/graphs/pq_trees.py b/src/sage/graphs/pq_trees.py
index 2ddd39691e8..68063bc8e73 100644
--- a/src/sage/graphs/pq_trees.py
+++ b/src/sage/graphs/pq_trees.py
@@ -558,7 +558,7 @@ def set_contiguous(self, v):
In any case, the sets containing ``v`` are contiguous when this
function ends. If there is no possibility of doing so, the function
- raises a ``ValueError`` exception.
+ raises a :class:`ValueError` exception.
EXAMPLES:
@@ -837,7 +837,7 @@ def set_contiguous(self, v):
In any case, the sets containing ``v`` are contiguous when this
function ends. If there is no possibility of doing so, the function
- raises a ``ValueError`` exception.
+ raises a :class:`ValueError` exception.
EXAMPLES:
diff --git a/src/sage/graphs/schnyder.py b/src/sage/graphs/schnyder.py
index 40f6d923656..b52dcff829a 100644
--- a/src/sage/graphs/schnyder.py
+++ b/src/sage/graphs/schnyder.py
@@ -555,7 +555,7 @@ def _compute_coordinates(g, x):
g.set_pos(coordinates) # Setting _pos attribute to store coordinates
-class TreeNode():
+class TreeNode:
"""
A class to represent each node in the trees used by ``_realizer`` and
``_compute_coordinates`` when finding a planar geometric embedding in
diff --git a/src/sage/graphs/strongly_regular_db.pyx b/src/sage/graphs/strongly_regular_db.pyx
index 4095448b606..632016b0703 100644
--- a/src/sage/graphs/strongly_regular_db.pyx
+++ b/src/sage/graphs/strongly_regular_db.pyx
@@ -2829,7 +2829,7 @@ def strongly_regular_graph(int v, int k, int l, int mu=-1, bint existence=False,
...
ValueError: There exists no (5, 5, 5, 5)-strongly regular graph
- An set of parameters proved in a paper to be infeasible::
+ A set of parameters proved in a paper to be infeasible::
sage: graphs.strongly_regular_graph(324,57,0,12,existence=True) # needs sage.combinat sage.modules
False
diff --git a/src/sage/graphs/tutte_polynomial.py b/src/sage/graphs/tutte_polynomial.py
index e82150eeb9c..4868577c892 100644
--- a/src/sage/graphs/tutte_polynomial.py
+++ b/src/sage/graphs/tutte_polynomial.py
@@ -218,7 +218,7 @@ def edge_multiplicities(G):
########
-class Ear():
+class Ear:
r"""
An ear is a sequence of vertices
@@ -372,7 +372,7 @@ def removed_from(self, G):
##################
-class EdgeSelection():
+class EdgeSelection:
pass
diff --git a/src/sage/groups/abelian_gps/abelian_group.py b/src/sage/groups/abelian_gps/abelian_group.py
index f2e79c92353..66558a9ffb0 100644
--- a/src/sage/groups/abelian_gps/abelian_group.py
+++ b/src/sage/groups/abelian_gps/abelian_group.py
@@ -581,8 +581,8 @@ def is_subgroup(left, right):
sage: G.is_subgroup(G)
True
- sage: H = G.subgroup([G.1]) # needs sage.libs.gap
- sage: H.is_subgroup(G) # needs sage.libs.gap
+ sage: H = G.subgroup([G.1]) # needs sage.libs.gap # optional - gap_package_polycyclic
+ sage: H.is_subgroup(G) # needs sage.libs.gap # optional - gap_package_polycyclic
True
sage: G. = AbelianGroup(2)
@@ -1206,7 +1206,7 @@ def subgroup(self, gensH, names="f"):
EXAMPLES::
- sage: # needs sage.libs.gap
+ sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G. = AbelianGroup(3, [2,3,4]); G
Multiplicative Abelian group isomorphic to C2 x C3 x C4
sage: H = G.subgroup([a*b,a]); H
@@ -1361,7 +1361,7 @@ def number_of_subgroups(self, order=None):
0
sage: AbelianGroup([1,3,1]).number_of_subgroups(order=2)
0
- sage: AbelianGroup([1,3,0,1]).number_of_subgroups(order=3) # needs sage.libs.gap
+ sage: AbelianGroup([1,3,0,1]).number_of_subgroups(order=3) # needs sage.libs.gap # optional - gap_package_polycyclic
1
sage: AbelianGroup([1,3,1]).number_of_subgroups(order=-2)
Traceback (most recent call last):
@@ -1451,12 +1451,12 @@ def subgroups(self, check=False):
EXAMPLES::
- sage: AbelianGroup([2,3]).subgroups() # needs sage.libs.gap
+ sage: AbelianGroup([2,3]).subgroups() # needs sage.libs.gap # optional - gap_package_polycyclic
[Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {f0*f1^2},
Multiplicative Abelian subgroup isomorphic to C2 generated by {f0},
Multiplicative Abelian subgroup isomorphic to C3 generated by {f1},
Trivial Abelian subgroup]
- sage: len(AbelianGroup([2,4,8]).subgroups()) # needs sage.libs.gap
+ sage: len(AbelianGroup([2,4,8]).subgroups()) # needs sage.libs.gap # optional - gap_package_polycyclic
81
TESTS::
@@ -1467,10 +1467,10 @@ def subgroups(self, check=False):
Check that :trac:`14196` is fixed::
sage: B = AbelianGroup([1,2])
- sage: B.subgroups() # needs sage.libs.gap
+ sage: B.subgroups() # needs sage.libs.gap # optional - gap_package_polycyclic
[Multiplicative Abelian subgroup isomorphic to C2 generated by {f1},
Trivial Abelian subgroup]
- sage: B.subgroups(check=True) # needs sage.libs.gap
+ sage: B.subgroups(check=True) # needs sage.libs.gap # optional - gap_package_polycyclic
[Multiplicative Abelian subgroup isomorphic to C2 generated by {f1},
Trivial Abelian subgroup]
"""
@@ -1534,10 +1534,10 @@ def subgroup_reduced(self, elts, verbose=False):
EXAMPLES::
sage: G = AbelianGroup([4,4])
- sage: G.subgroup( [ G([1,0]), G([1,2]) ]) # needs sage.libs.gap
+ sage: G.subgroup( [ G([1,0]), G([1,2]) ]) # needs sage.libs.gap # optional - gap_package_polycyclic
Multiplicative Abelian subgroup isomorphic to C2 x C4
generated by {f0, f0*f1^2}
- sage: AbelianGroup([4,4]).subgroup_reduced( [ [1,0], [1,2] ]) # needs sage.libs.gap
+ sage: AbelianGroup([4,4]).subgroup_reduced( [ [1,0], [1,2] ]) # needs sage.libs.gap # optional - gap_package_polycyclic
Multiplicative Abelian subgroup isomorphic to C2 x C4
generated by {f0^2*f1^2, f0^3}
"""
@@ -1568,7 +1568,7 @@ def torsion_subgroup(self, n=None):
EXAMPLES::
- sage: # needs sage.libs.gap
+ sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G = AbelianGroup([2, 3])
sage: G.torsion_subgroup()
Multiplicative Abelian subgroup isomorphic to C2 x C3 generated
@@ -1587,7 +1587,7 @@ def torsion_subgroup(self, n=None):
::
sage: G = AbelianGroup([2, 2*3, 2*3*5, 0, 2*3*5*7, 2*3*5*7*11])
- sage: G.torsion_subgroup(5) # needs sage.libs.gap
+ sage: G.torsion_subgroup(5) # needs sage.libs.gap # optional - gap_package_polycyclic
Multiplicative Abelian subgroup isomorphic to C5 x C5 x C5 generated by {f2^6, f4^42, f5^462}
"""
if n is None:
@@ -1620,7 +1620,7 @@ def __init__(self, ambient, gens, names="f", category=None):
"""
EXAMPLES::
- sage: # needs sage.libs.gap
+ sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: F = AbelianGroup(5, [30,64,729], names=list("abcde"))
sage: a,b,c,d,e = F.gens()
sage: F.subgroup([a^3,b])
@@ -1675,23 +1675,23 @@ def __init__(self, ambient, gens, names="f", category=None):
Infinite groups can also be handled::
+ sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G = AbelianGroup([3,4,0], names="abc")
sage: a,b,c = G.gens()
- sage: F = G.subgroup([a, b^2, c]); F # needs sage.libs.gap
+ sage: F = G.subgroup([a, b^2, c]); F
Multiplicative Abelian subgroup isomorphic to C2 x C3 x Z
generated by {a, b^2, c}
-
- sage: F.gens_orders() # needs sage.libs.gap
+ sage: F.gens_orders()
(2, 3, 0)
- sage: F.gens() # needs sage.libs.gap
+ sage: F.gens()
(a, b^2, c)
- sage: F.order() # needs sage.libs.gap
+ sage: F.order()
+Infinity
Testing issue :trac:`18863`::
sage: G = AbelianGroup(5,[2])
- sage: G.subgroup([prod(g^k for g,k in zip(G.gens(),[1,-2,3,-4,5]))]) # needs sage.libs.gap
+ sage: G.subgroup([prod(g^k for g,k in zip(G.gens(),[1,-2,3,-4,5]))]) # needs sage.libs.gap # optional - gap_package_polycyclic
Multiplicative Abelian subgroup isomorphic to Z
generated by {f0*f1^-2*f2^3*f3^-4*f4}
"""
@@ -1725,35 +1725,38 @@ def __contains__(self, x):
EXAMPLES::
+ sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G. = AbelianGroup(2)
- sage: A = G.subgroup([a]) # needs sage.libs.gap
+ sage: A = G.subgroup([a])
sage: a in G
True
- sage: a in A # needs sage.libs.gap
+ sage: a in A
True
TESTS:
Check that :trac:`32910` is fixed::
+ sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G. = AbelianGroup(2, [4, 576])
sage: Hgens = [a^2, a*b^2]
- sage: H = G.subgroup(Hgens) # needs sage.libs.gap
- sage: [g in H for g in (a^3, b^2, b^3, a^3*b^2, "junk")] # needs sage.libs.gap
+ sage: H = G.subgroup(Hgens)
+ sage: [g in H for g in (a^3, b^2, b^3, a^3*b^2, "junk")]
[False, False, False, True, False]
Check that :trac:`31507` is fixed::
+ sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G = AbelianGroup(2, gens_orders=[16, 16])
sage: f0, f1 = G.gens()
- sage: H = G.subgroup([f0*f1^3]) # needs sage.libs.gap
- sage: [g in H for g in (f0, f0*f1^2, f0*f1^3, f0*f1^4)] # needs sage.libs.gap
+ sage: H = G.subgroup([f0*f1^3])
+ sage: [g in H for g in (f0, f0*f1^2, f0*f1^3, f0*f1^4)]
[False, False, True, False]
sage: G. = AbelianGroup(2)
sage: Hgens = [a*b, a*b^-1]
- sage: H = G.subgroup(Hgens) # needs sage.libs.gap
- sage: b^2 in H # needs sage.libs.gap
+ sage: H = G.subgroup(Hgens) # optional - gap_package_polycyclic
+ sage: b^2 in H # optional - gap_package_polycyclic
True
"""
if not isinstance(x, AbelianGroupElement):
@@ -1781,9 +1784,10 @@ def ambient_group(self):
EXAMPLES::
+ sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G. = AbelianGroup([2,3,4])
- sage: H = G.subgroup([a, b^2]) # needs sage.libs.gap
- sage: H.ambient_group() is G # needs sage.libs.gap
+ sage: H = G.subgroup([a, b^2])
+ sage: H.ambient_group() is G
True
"""
return self._ambient_group
@@ -1805,19 +1809,17 @@ def equals(left, right):
EXAMPLES::
+ sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G = AbelianGroup(3, [2,3,4], names="abc"); G
Multiplicative Abelian group isomorphic to C2 x C3 x C4
sage: a,b,c = G.gens()
- sage: F = G.subgroup([a,b^2]); F # needs sage.libs.gap
+ sage: F = G.subgroup([a,b^2]); F
Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a, b^2}
- sage: F = AbelianGroup(2)
sage: A = G.subgroup([a])
sage: B = G.subgroup([b])
@@ -1849,8 +1851,8 @@ def _repr_(self):
sage: G. = AbelianGroup(2)
sage: G._repr_()
'Multiplicative Abelian group isomorphic to Z x Z'
- sage: A = G.subgroup([a]) # needs sage.libs.gap
- sage: A._repr_() # needs sage.libs.gap
+ sage: A = G.subgroup([a]) # needs sage.libs.gap # optional - gap_package_polycyclic
+ sage: A._repr_() # needs sage.libs.gap # optional - gap_package_polycyclic
'Multiplicative Abelian subgroup isomorphic to Z generated by {a}'
"""
eldv = self._abinvs
@@ -1872,11 +1874,12 @@ def gens(self):
EXAMPLES::
+ sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G. = AbelianGroup(2)
- sage: A = G.subgroup([a]) # needs sage.libs.gap
+ sage: A = G.subgroup([a])
sage: G.gens()
(a, b)
- sage: A.gens() # needs sage.libs.gap
+ sage: A.gens()
(a,)
"""
return self._gens
@@ -1887,9 +1890,10 @@ def gen(self, n):
EXAMPLES::
+ sage: # needs sage.libs.gap # optional - gap_package_polycyclic
sage: G. = AbelianGroup(2)
- sage: A = G.subgroup([a]) # needs sage.libs.gap
- sage: A.gen(0) # needs sage.libs.gap
+ sage: A = G.subgroup([a])
+ sage: A.gen(0)
a
"""
return self._gens[n]
diff --git a/src/sage/groups/abelian_gps/abelian_group_morphism.py b/src/sage/groups/abelian_gps/abelian_group_morphism.py
index e56b1c68afd..e4b7b82b42b 100644
--- a/src/sage/groups/abelian_gps/abelian_group_morphism.py
+++ b/src/sage/groups/abelian_gps/abelian_group_morphism.py
@@ -59,14 +59,14 @@ class AbelianGroupMorphism(Morphism):
sage: x,y = H.gens()
sage: from sage.groups.abelian_gps.abelian_group_morphism import AbelianGroupMorphism
- sage: phi = AbelianGroupMorphism(H,G,[x,y],[a,b])
+ sage: phi = AbelianGroupMorphism(H,G,[x,y],[a,b]) # optional - gap_package_polycyclic
TESTS::
sage: G. = AbelianGroup(2,[2,3])
sage: H. = AbelianGroup(3,[2,3,4])
- sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,b])
- sage: Hom(G,H) == phi.parent()
+ sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,b]) # optional - gap_package_polycyclic
+ sage: Hom(G,H) == phi.parent() # optional - gap_package_polycyclic
True
AUTHORS:
@@ -126,11 +126,11 @@ def _libgap_(self):
sage: H = AbelianGroup(2,[2,3],names="xy"); H
Multiplicative Abelian group isomorphic to C2 x C3
sage: x,y = H.gens()
- sage: phi = AbelianGroupMorphism(H,G,[x,y],[a,b])
- sage: libgap(phi)
+ sage: phi = AbelianGroupMorphism(H,G,[x,y],[a,b]) # optional - gap_package_polycyclic
+ sage: libgap(phi) # optional - gap_package_polycyclic
[ f1, f2 ] -> [ f1, f2 ]
- sage: phi = AbelianGroupMorphism(H,G,[x,y],[a*c**2,b])
- sage: libgap(phi)
+ sage: phi = AbelianGroupMorphism(H,G,[x,y],[a*c**2,b]) # optional - gap_package_polycyclic
+ sage: libgap(phi) # optional - gap_package_polycyclic
[ f1, f2 ] -> [ f1*f4, f2 ]
"""
G = libgap(self.domain())
@@ -158,16 +158,16 @@ def kernel(self):
sage: G = AbelianGroup(2,[2,3],names="xy"); G
Multiplicative Abelian group isomorphic to C2 x C3
sage: x,y = G.gens()
- sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,b])
- sage: phi.kernel()
+ sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,b]) # optional - gap_package_polycyclic
+ sage: phi.kernel() # optional - gap_package_polycyclic
Group([ ])
sage: H = AbelianGroup(3,[2,2,2],names="abc")
sage: a,b,c = H.gens()
sage: G = AbelianGroup(2,[2,2],names="x")
sage: x,y = G.gens()
- sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,a])
- sage: phi.kernel()
+ sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,a]) # optional - gap_package_polycyclic
+ sage: phi.kernel() # optional - gap_package_polycyclic
Group([ f1*f2 ])
"""
return libgap(self).Kernel()
@@ -186,11 +186,11 @@ def image(self, S):
sage: G = AbelianGroup(2,[2,3],names="xy")
sage: x,y = G.gens()
- sage: subG = G.subgroup([x])
+ sage: subG = G.subgroup([x]) # optional - gap_package_polycyclic
sage: H = AbelianGroup(3,[2,3,4],names="abc")
sage: a,b,c = H.gens()
- sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,b])
- sage: phi.image(subG)
+ sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,b]) # optional - gap_package_polycyclic
+ sage: phi.image(subG) # optional - gap_package_polycyclic
Multiplicative Abelian subgroup isomorphic to C2 generated by {a}
"""
return self.codomain().subgroup([self(g) for g in S.gens()])
@@ -206,10 +206,10 @@ def _call_(self, g):
sage: a,b,c = H.gens()
sage: G = AbelianGroup(2, [2,3], names="xy")
sage: x,y = G.gens()
- sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,b])
- sage: phi(y*x)
+ sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,b]) # optional - gap_package_polycyclic
+ sage: phi(y*x) # optional - gap_package_polycyclic
a*b
- sage: phi(y^2)
+ sage: phi(y^2) # optional - gap_package_polycyclic
b^2
"""
# g.word_problem is faster in general than word_problem(g)
diff --git a/src/sage/groups/abelian_gps/dual_abelian_group.py b/src/sage/groups/abelian_gps/dual_abelian_group.py
index 85318aa6f83..c6012254630 100644
--- a/src/sage/groups/abelian_gps/dual_abelian_group.py
+++ b/src/sage/groups/abelian_gps/dual_abelian_group.py
@@ -1,3 +1,4 @@
+# sage.doctest: needs sage.rings.number_field
r"""
Dual groups of Finite Multiplicative Abelian Groups
@@ -25,7 +26,6 @@
sage: F = AbelianGroup(5, [2,5,7,8,9], names='abcde')
sage: (a, b, c, d, e) = F.gens()
- sage: # needs sage.rings.number_field
sage: Fd = F.dual_group(names='ABCDE')
sage: Fd.base_ring()
Cyclotomic Field of order 2520 and degree 576
@@ -82,7 +82,6 @@ def is_DualAbelianGroup(x):
EXAMPLES::
- sage: # needs sage.rings.number_field
sage: from sage.groups.abelian_gps.dual_abelian_group import is_DualAbelianGroup
sage: F = AbelianGroup(5,[3,5,7,8,9], names=list("abcde"))
sage: Fd = F.dual_group()
@@ -105,7 +104,7 @@ class DualAbelianGroup_class(UniqueRepresentation, AbelianGroupBase):
EXAMPLES::
sage: F = AbelianGroup(5,[3,5,7,8,9], names="abcde")
- sage: F.dual_group() # needs sage.rings.number_field
+ sage: F.dual_group()
Dual of Abelian Group isomorphic to Z/3Z x Z/5Z x Z/7Z x Z/8Z x Z/9Z
over Cyclotomic Field of order 2520 and degree 576
@@ -123,7 +122,7 @@ def __init__(self, G, names, base_ring):
EXAMPLES::
sage: F = AbelianGroup(5,[3,5,7,8,9], names="abcde")
- sage: F.dual_group() # needs sage.rings.number_field
+ sage: F.dual_group()
Dual of Abelian Group isomorphic to Z/3Z x Z/5Z x Z/7Z x Z/8Z x Z/9Z
over Cyclotomic Field of order 2520 and degree 576
"""
@@ -180,9 +179,9 @@ def _repr_(self):
EXAMPLES::
sage: F = AbelianGroup(5, [2,5,7,8,9], names='abcde')
- sage: Fd = F.dual_group(names='ABCDE', # needs sage.rings.number_field
+ sage: Fd = F.dual_group(names='ABCDE',
....: base_ring=CyclotomicField(2*5*7*8*9))
- sage: Fd # indirect doctest # needs sage.rings.number_field
+ sage: Fd # indirect doctest
Dual of Abelian Group isomorphic to Z/2Z x Z/5Z x Z/7Z x Z/8Z x Z/9Z
over Cyclotomic Field of order 5040 and degree 1152
sage: Fd = F.dual_group(names='ABCDE', base_ring=CC) # needs sage.rings.real_mpfr
@@ -209,8 +208,8 @@ def _latex_(self):
EXAMPLES::
sage: F = AbelianGroup(3, [2]*3)
- sage: Fd = F.dual_group() # needs sage.rings.number_field
- sage: Fd._latex_() # needs sage.rings.number_field
+ sage: Fd = F.dual_group()
+ sage: Fd._latex_()
'$\\mathrm{DualAbelianGroup}( AbelianGroup ( 3, (2, 2, 2) ) )$'
"""
return r"$\mathrm{DualAbelianGroup}( AbelianGroup ( %s, %s ) )$" % (self.ngens(), self.gens_orders())
@@ -251,7 +250,6 @@ def gen(self, i=0):
EXAMPLES::
- sage: # needs sage.rings.number_field
sage: F = AbelianGroup(3, [1,2,3], names='a')
sage: Fd = F.dual_group(names="A")
sage: Fd.0
@@ -279,8 +277,8 @@ def gens(self):
EXAMPLES::
- sage: F = AbelianGroup([7,11]).dual_group() # needs sage.rings.number_field
- sage: F.gens() # needs sage.rings.number_field
+ sage: F = AbelianGroup([7,11]).dual_group()
+ sage: F.gens()
(X0, X1)
"""
n = self.group().ngens()
@@ -293,8 +291,8 @@ def ngens(self):
EXAMPLES::
sage: F = AbelianGroup([7]*100)
- sage: Fd = F.dual_group() # needs sage.rings.number_field
- sage: Fd.ngens() # needs sage.rings.number_field
+ sage: Fd = F.dual_group()
+ sage: Fd.ngens()
100
"""
return self.group().ngens()
@@ -310,8 +308,8 @@ def gens_orders(self):
EXAMPLES::
sage: F = AbelianGroup([5]*1000)
- sage: Fd = F.dual_group() # needs sage.rings.number_field
- sage: invs = Fd.gens_orders(); len(invs) # needs sage.rings.number_field
+ sage: Fd = F.dual_group()
+ sage: invs = Fd.gens_orders(); len(invs)
1000
"""
return self.group().gens_orders()
@@ -325,8 +323,8 @@ def invariants(self):
EXAMPLES::
sage: F = AbelianGroup([5]*1000)
- sage: Fd = F.dual_group() # needs sage.rings.number_field
- sage: invs = Fd.gens_orders(); len(invs) # needs sage.rings.number_field
+ sage: Fd = F.dual_group()
+ sage: invs = Fd.gens_orders(); len(invs)
1000
"""
# TODO: deprecate
@@ -340,9 +338,9 @@ def __contains__(self, X):
sage: F = AbelianGroup(5,[2, 3, 5, 7, 8], names="abcde")
sage: a,b,c,d,e = F.gens()
- sage: Fd = F.dual_group(names="ABCDE") # needs sage.rings.number_field
- sage: A,B,C,D,E = Fd.gens() # needs sage.rings.number_field
- sage: A*B^2*D^7 in Fd # needs sage.rings.number_field
+ sage: Fd = F.dual_group(names="ABCDE")
+ sage: A,B,C,D,E = Fd.gens()
+ sage: A*B^2*D^7 in Fd
True
"""
return X.parent() == self and is_DualAbelianGroupElement(X)
@@ -354,8 +352,8 @@ def order(self):
EXAMPLES::
sage: G = AbelianGroup([2,3,9])
- sage: Gd = G.dual_group() # needs sage.rings.number_field
- sage: Gd.order() # needs sage.rings.number_field
+ sage: Gd = G.dual_group()
+ sage: Gd.order()
54
"""
G = self.group()
@@ -368,10 +366,10 @@ def is_commutative(self):
EXAMPLES::
sage: G = AbelianGroup([2,3,9])
- sage: Gd = G.dual_group() # needs sage.rings.number_field
- sage: Gd.is_commutative() # needs sage.rings.number_field
+ sage: Gd = G.dual_group()
+ sage: Gd.is_commutative()
True
- sage: Gd.is_abelian() # needs sage.rings.number_field
+ sage: Gd.is_abelian()
True
"""
return True
@@ -384,8 +382,8 @@ def list(self):
EXAMPLES::
sage: G = AbelianGroup([2,3], names="ab")
- sage: Gd = G.dual_group(names="AB") # needs sage.rings.number_field
- sage: Gd.list() # needs sage.rings.number_field
+ sage: Gd = G.dual_group(names="AB")
+ sage: Gd.list()
(1, B, B^2, A, A*B, A*B^2)
"""
if not self.is_finite():
@@ -400,8 +398,8 @@ def __iter__(self):
EXAMPLES::
sage: G = AbelianGroup([2,3], names="ab")
- sage: Gd = G.dual_group(names="AB") # needs sage.rings.number_field
- sage: [X for X in Gd] # needs sage.rings.number_field
+ sage: Gd = G.dual_group(names="AB")
+ sage: [X for X in Gd]
[1, B, B^2, A, A*B, A*B^2]
sage: # needs sage.rings.real_mpfr
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 407323d4f34..6fdb8a68c4e 100644
--- a/src/sage/groups/abelian_gps/dual_abelian_group_element.py
+++ b/src/sage/groups/abelian_gps/dual_abelian_group_element.py
@@ -1,3 +1,4 @@
+# sage.doctest: needs sage.rings.number_field
"""
Elements (characters) of the dual group of a finite Abelian group
@@ -8,13 +9,12 @@
sage: F
Multiplicative Abelian group isomorphic to C2 x C3 x C5 x C7 x C8
- sage: Fd = F.dual_group(names="ABCDE"); Fd # needs sage.rings.number_field
+ sage: Fd = F.dual_group(names="ABCDE"); Fd
Dual of Abelian Group isomorphic to Z/2Z x Z/3Z x Z/5Z x Z/7Z x Z/8Z
over Cyclotomic Field of order 840 and degree 192
The elements of the dual group can be evaluated on elements of the original group::
- sage: # needs sage.rings.number_field
sage: a,b,c,d,e = F.gens()
sage: A,B,C,D,E = Fd.gens()
sage: A*B^2*D^7
@@ -71,10 +71,10 @@ def is_DualAbelianGroupElement(x) -> bool:
EXAMPLES::
sage: from sage.groups.abelian_gps.dual_abelian_group import is_DualAbelianGroupElement
- sage: F = AbelianGroup(5, [5,5,7,8,9], names=list("abcde")).dual_group() # needs sage.rings.number_field
- sage: is_DualAbelianGroupElement(F) # needs sage.rings.number_field
+ 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()) # needs sage.rings.number_field
+ sage: is_DualAbelianGroupElement(F.an_element())
True
"""
return isinstance(x, DualAbelianGroupElement)
@@ -96,7 +96,6 @@ def __call__(self, g):
EXAMPLES::
- sage: # needs sage.rings.number_field
sage: F = AbelianGroup(5, [2,3,5,7,8], names="abcde")
sage: a,b,c,d,e = F.gens()
sage: Fd = F.dual_group(names="ABCDE")
@@ -147,7 +146,6 @@ def word_problem(self, words):
EXAMPLES::
- sage: # needs sage.rings.number_field
sage: G = AbelianGroup(5,[3, 5, 5, 7, 8], names="abcde")
sage: Gd = G.dual_group(names="abcde")
sage: a,b,c,d,e = Gd.gens()
@@ -156,7 +154,7 @@ def word_problem(self, words):
sage: w = a^7*b^3*c^5*d^4*e^4
sage: x = a^3*b^2*c^2*d^3*e^5
sage: y = a^2*b^4*c^2*d^4*e^5
- sage: e.word_problem([u,v,w,x,y])
+ sage: e.word_problem([u,v,w,x,y]) # needs sage.libs.gap
[[b^2*c^2*d^3*e^5, 245]]
"""
from sage.libs.gap.libgap import libgap
diff --git a/src/sage/groups/affine_gps/affine_group.py b/src/sage/groups/affine_gps/affine_group.py
index bfcdd282df1..7b5e4695fb1 100644
--- a/src/sage/groups/affine_gps/affine_group.py
+++ b/src/sage/groups/affine_gps/affine_group.py
@@ -204,7 +204,10 @@ def __init__(self, degree, ring):
sage: G = AffineGroup(2, GF(5)); G
Affine Group of degree 2 over Finite Field of size 5
+
+ sage: # needs sage.libs.gap (for gens)
sage: TestSuite(G).run()
+
sage: G.category()
Category of finite groups
@@ -289,8 +292,10 @@ def cardinality(self):
EXAMPLES::
+ sage: # needs sage.libs.gap
sage: AffineGroup(6, GF(5)).cardinality()
172882428468750000000000000000
+
sage: AffineGroup(6, ZZ).cardinality()
+Infinity
"""
@@ -464,6 +469,7 @@ def random_element(self):
EXAMPLES::
+ sage: # needs sage.libs.gap
sage: G = AffineGroup(4, GF(3))
sage: G.random_element() # random
[2 0 1 2] [1]
@@ -498,6 +504,7 @@ def some_elements(self):
EXAMPLES::
+ sage: # needs sage.libs.gap
sage: G = AffineGroup(4,5)
sage: G.some_elements()
[ [2 0 0 0] [1]
diff --git a/src/sage/groups/affine_gps/euclidean_group.py b/src/sage/groups/affine_gps/euclidean_group.py
index 47de04c6544..59fb411b925 100644
--- a/src/sage/groups/affine_gps/euclidean_group.py
+++ b/src/sage/groups/affine_gps/euclidean_group.py
@@ -146,6 +146,8 @@ class EuclideanGroup(AffineGroup):
True
sage: G = EuclideanGroup(2, GF(5)); G
Euclidean Group of degree 2 over Finite Field of size 5
+
+ sage: # needs sage.libs.gap (for gens)
sage: TestSuite(G).run()
REFERENCES:
diff --git a/src/sage/groups/affine_gps/group_element.py b/src/sage/groups/affine_gps/group_element.py
index 52fbe9365d6..7df4dc8a69a 100644
--- a/src/sage/groups/affine_gps/group_element.py
+++ b/src/sage/groups/affine_gps/group_element.py
@@ -78,11 +78,14 @@ class AffineGroupElement(MultiplicativeGroupElement):
EXAMPLES::
sage: G = AffineGroup(2, GF(3))
+
+ sage: # needs sage.libs.gap
sage: g = G.random_element()
sage: type(g)
sage: G(g.matrix()) == g
True
+
sage: G(2)
[2 0] [0]
x |-> [0 2] x + [0]
@@ -107,6 +110,7 @@ def __init__(self, parent, A, b=0, convert=True, check=True):
TESTS::
+ sage: # needs sage.libs.gap
sage: G = AffineGroup(4, GF(5))
sage: g = G.random_element()
sage: TestSuite(g).run()
@@ -200,6 +204,7 @@ def matrix(self):
Composition of affine group elements equals multiplication of
the matrices::
+ sage: # needs sage.libs.gap
sage: g1 = G.random_element()
sage: g2 = G.random_element()
sage: g1.matrix() * g2.matrix() == (g1*g2).matrix()
diff --git a/src/sage/groups/braid.py b/src/sage/groups/braid.py
index 18d95ef86f2..bd787d3c153 100644
--- a/src/sage/groups/braid.py
+++ b/src/sage/groups/braid.py
@@ -72,7 +72,7 @@
from sage.combinat.permutation import Permutation
from sage.combinat.permutation import Permutations
from sage.combinat.subset import Subsets
-from sage.features import PythonModule
+from sage.features.sagemath import sage__libs__braiding
from sage.groups.artin import FiniteTypeArtinGroup, FiniteTypeArtinGroupElement
from sage.groups.finitely_presented import FinitelyPresentedGroup
from sage.groups.finitely_presented import GroupMorphismWithGensImages
@@ -80,7 +80,6 @@
from sage.functions.generalized import sign
from sage.groups.perm_gps.permgroup_named import SymmetricGroup
from sage.groups.perm_gps.permgroup_named import SymmetricGroupElement
-from sage.knots.knot import Knot
from sage.libs.gap.libgap import libgap
from sage.matrix.constructor import identity_matrix, matrix
from sage.misc.lazy_attribute import lazy_attribute
@@ -98,7 +97,8 @@
['leftnormalform', 'rightnormalform', 'centralizer', 'supersummitset', 'greatestcommondivisor',
'leastcommonmultiple', 'conjugatingbraid', 'ultrasummitset',
'thurston_type', 'rigidity', 'sliding_circuits'],
- feature=PythonModule('sage.libs.braiding', spkg='libbraiding', type='standard'))
+ feature=sage__libs__braiding())
+lazy_import('sage.knots.knot', 'Knot')
class Braid(FiniteTypeArtinGroupElement):
diff --git a/src/sage/groups/galois_group.py b/src/sage/groups/galois_group.py
index 5a48380eb21..a7439d18ab3 100644
--- a/src/sage/groups/galois_group.py
+++ b/src/sage/groups/galois_group.py
@@ -10,15 +10,17 @@
- David Roe (2019): initial version
"""
-from sage.groups.perm_gps.permgroup import PermutationGroup, PermutationGroup_generic, PermutationGroup_subgroup
from sage.groups.abelian_gps.abelian_group import AbelianGroup_class, AbelianGroup_subgroup
-from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
-from sage.misc.lazy_attribute import lazy_attribute
from sage.misc.abstract_method import abstract_method
from sage.misc.cachefunc import cached_method
-from sage.structure.category_object import normalize_names
+from sage.misc.lazy_attribute import lazy_attribute
+from sage.misc.lazy_import import lazy_import
from sage.rings.integer_ring import ZZ
+lazy_import('sage.groups.galois_group_perm', ['GaloisGroup_perm', 'GaloisSubgroup_perm'])
+lazy_import('sage.groups.perm_gps.permgroup', 'PermutationGroup')
+
+
def _alg_key(self, algorithm=None, recompute=False):
r"""
Return a key for use in cached_method calls.
@@ -40,6 +42,7 @@ def _alg_key(self, algorithm=None, recompute=False):
algorithm = self._get_algorithm(algorithm)
return algorithm
+
class _GMixin:
r"""
This class provides some methods for Galois groups to be used for both permutation groups
@@ -151,6 +154,7 @@ def _gc_map(self):
"""
return self._gcdata[1]
+
class _GaloisMixin(_GMixin):
"""
This class provides methods for Galois groups, allowing concrete instances
@@ -275,6 +279,7 @@ def is_galois(self):
"""
return self.order() == self._field_degree
+
class _SubGaloisMixin(_GMixin):
"""
This class provides methods for subgroups of Galois groups, allowing concrete instances
@@ -339,164 +344,6 @@ def _gcdata(self):
"""
return self._ambient_group._gcdata
-class GaloisGroup_perm(_GaloisMixin, PermutationGroup_generic):
- r"""
- The group of automorphisms of a Galois closure of a given field.
-
- INPUT:
-
- - ``field`` -- a field, separable over its base
-
- - ``names`` -- a string or tuple of length 1, giving a variable name for the splitting field
-
- - ``gc_numbering`` -- boolean, whether to express permutations in terms of the
- roots of the defining polynomial of the splitting field (versus the defining polynomial
- of the original extension). The default value may vary based on the type of field.
- """
- @abstract_method
- def transitive_number(self, algorithm=None, recompute=False):
- """
- The transitive number (as in the GAP and Magma databases of transitive groups)
- for the action on the roots of the defining polynomial of the top field.
-
- EXAMPLES::
-
- sage: R. = ZZ[]
- sage: K. = NumberField(x^3 + 2*x + 2) # needs sage.rings.number_field
- sage: G = K.galois_group() # needs sage.rings.number_field
- sage: G.transitive_number() # needs sage.rings.number_field
- 2
- """
-
- @lazy_attribute
- def _gens(self):
- """
- The generators of this Galois group as permutations of the roots. It's important that this
- be computed lazily, since it's often possible to compute other attributes (such as the order
- or transitive number) more cheaply.
-
- EXAMPLES::
-
- sage: R. = ZZ[]
- sage: K. = NumberField(x^5 - 2) # needs sage.rings.number_field
- sage: G = K.galois_group(gc_numbering=False) # needs sage.rings.number_field
- sage: G._gens # needs sage.rings.number_field
- [(1,2,3,5), (1,4,3,2,5)]
- """
- return NotImplemented
-
- def __init__(self, field, algorithm=None, names=None, gc_numbering=False):
- r"""
- EXAMPLES::
-
- sage: R. = ZZ[]
- sage: K. = NumberField(x^3 + 2*x + 2) # needs sage.rings.number_field
- sage: G = K.galois_group() # needs sage.rings.number_field
- sage: TestSuite(G).run() # needs sage.rings.number_field
- """
- self._field = field
- self._default_algorithm = algorithm
- self._base = field.base_field()
- self._gc_numbering = gc_numbering
- if names is None:
- # add a c for Galois closure
- names = field.variable_name() + 'c'
- self._gc_names = normalize_names(1, names)
- # We do only the parts of the initialization of PermutationGroup_generic
- # that don't depend on _gens
- from sage.categories.permutation_groups import PermutationGroups
- category = PermutationGroups().FinitelyGenerated().Finite()
- # Note that we DON'T call the __init__ method for PermutationGroup_generic
- # Instead, the relevant attributes are computed lazily
- super(PermutationGroup_generic, self).__init__(category=category)
-
- @lazy_attribute
- def _deg(self):
- r"""
- The number of moved points in the permutation representation.
-
- This will be the degree of the original number field if `_gc_numbering``
- is ``False``, or the degree of the Galois closure otherwise.
-
- EXAMPLES::
-
- sage: # needs sage.rings.number_field
- sage: R. = ZZ[]
- sage: K. = NumberField(x^5 - 2)
- sage: G = K.galois_group(gc_numbering=False); G
- Galois group 5T3 (5:4) with order 20 of x^5 - 2
- sage: G._deg
- 5
- sage: G = K.galois_group(gc_numbering=True); G._deg
- 20
- """
- if self._gc_numbering:
- return self.order()
- else:
- try:
- return self._field.degree()
- except NotImplementedError: # relative number fields don't support degree
- return self._field.relative_degree()
-
- @lazy_attribute
- def _domain(self):
- r"""
- The integers labeling the roots on which this Galois group acts.
-
- EXAMPLES::
-
- sage: # needs sage.rings.number_field
- sage: R. = ZZ[]
- sage: K. = NumberField(x^5 - 2)
- sage: G = K.galois_group(gc_numbering=False); G
- Galois group 5T3 (5:4) with order 20 of x^5 - 2
- sage: G._domain
- {1, 2, 3, 4, 5}
- sage: G = K.galois_group(gc_numbering=True); G._domain
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
- """
- return FiniteEnumeratedSet(range(1, self._deg+1))
-
- @lazy_attribute
- def _domain_to_gap(self):
- r"""
- Dictionary implementing the identity (used by PermutationGroup_generic).
-
- EXAMPLES::
-
- sage: R. = ZZ[]
- sage: K. = NumberField(x^5 - 2) # needs sage.rings.number_field
- sage: G = K.galois_group(gc_numbering=False) # needs sage.rings.number_field
- sage: G._domain_to_gap[5] # needs sage.rings.number_field
- 5
- """
- return {key: i+1 for i, key in enumerate(self._domain)}
-
- @lazy_attribute
- def _domain_from_gap(self):
- r"""
- Dictionary implementing the identity (used by PermutationGroup_generic).
-
- EXAMPLES::
-
- sage: R. = ZZ[]
- sage: K. = NumberField(x^5 - 2) # needs sage.rings.number_field
- sage: G = K.galois_group(gc_numbering=True) # needs sage.rings.number_field
- sage: G._domain_from_gap[20] # needs sage.rings.number_field
- 20
- """
- return {i+1: key for i, key in enumerate(self._domain)}
-
- def ngens(self):
- r"""
- Number of generators of this Galois group
-
- EXAMPLES::
-
- sage: QuadraticField(-23, 'a').galois_group().ngens() # needs sage.rings.number_field
- 1
- """
- return len(self._gens)
class GaloisGroup_ab(_GaloisMixin, AbelianGroup_class):
r"""
@@ -551,7 +398,7 @@ def permutation_group(self):
EXAMPLES::
- sage: GF(3^10).galois_group().permutation_group() # needs sage.rings.finite_rings
+ sage: GF(3^10).galois_group().permutation_group() # needs sage.libs.gap sage.rings.finite_rings
Permutation Group with generators [(1,2,3,4,5,6,7,8,9,10)]
"""
return PermutationGroup(gap_group=self._gap_().RegularActionHomomorphism().Image())
@@ -568,11 +415,12 @@ def transitive_number(self, algorithm=None, recompute=False):
sage: from sage.groups.galois_group import GaloisGroup_ab
sage: Gtest = GaloisGroup_ab(field=None, generator_orders=(2,2,4))
- sage: Gtest.transitive_number()
+ sage: Gtest.transitive_number() # needs sage.libs.gap
2
"""
return ZZ(self.permutation_group()._gap_().TransitiveIdentification())
+
class GaloisGroup_cyc(GaloisGroup_ab):
r"""
Cyclic Galois groups
@@ -614,17 +462,6 @@ def signature(self):
"""
return ZZ(1) if (self._field.degree() % 2) else ZZ(-1)
-class GaloisSubgroup_perm(PermutationGroup_subgroup, _SubGaloisMixin):
- """
- Subgroups of Galois groups (implemented as permutation groups), specified
- by giving a list of generators.
-
- Unlike ambient Galois groups, where we use a lazy ``_gens`` attribute in order
- to enable creation without determining a list of generators,
- we require that generators for a subgroup be specified during initialization,
- as specified in the ``__init__`` method of permutation subgroups.
- """
- pass
class GaloisSubgroup_ab(AbelianGroup_subgroup, _SubGaloisMixin):
"""
@@ -633,5 +470,4 @@ class GaloisSubgroup_ab(AbelianGroup_subgroup, _SubGaloisMixin):
pass
-GaloisGroup_perm.Subgroup = GaloisSubgroup_perm
GaloisGroup_ab.Subgroup = GaloisSubgroup_ab
diff --git a/src/sage/groups/galois_group_perm.py b/src/sage/groups/galois_group_perm.py
new file mode 100644
index 00000000000..162e5174143
--- /dev/null
+++ b/src/sage/groups/galois_group_perm.py
@@ -0,0 +1,186 @@
+r"""
+Galois groups of field extensions as permutation groups
+"""
+
+from sage.groups.galois_group import _GaloisMixin, _SubGaloisMixin
+from sage.groups.perm_gps.permgroup import PermutationGroup, PermutationGroup_generic, PermutationGroup_subgroup
+from sage.misc.abstract_method import abstract_method
+from sage.misc.lazy_attribute import lazy_attribute
+from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
+from sage.structure.category_object import normalize_names
+
+
+class GaloisGroup_perm(_GaloisMixin, PermutationGroup_generic):
+ r"""
+ The group of automorphisms of a Galois closure of a given field.
+
+ INPUT:
+
+ - ``field`` -- a field, separable over its base
+
+ - ``names`` -- a string or tuple of length 1, giving a variable name for the splitting field
+
+ - ``gc_numbering`` -- boolean, whether to express permutations in terms of the
+ roots of the defining polynomial of the splitting field (versus the defining polynomial
+ of the original extension). The default value may vary based on the type of field.
+ """
+ @abstract_method
+ def transitive_number(self, algorithm=None, recompute=False):
+ """
+ The transitive number (as in the GAP and Magma databases of transitive groups)
+ for the action on the roots of the defining polynomial of the top field.
+
+ EXAMPLES::
+
+ sage: R. = ZZ[]
+ sage: K. = NumberField(x^3 + 2*x + 2) # needs sage.rings.number_field
+ sage: G = K.galois_group() # needs sage.rings.number_field
+ sage: G.transitive_number() # needs sage.rings.number_field
+ 2
+ """
+
+ @lazy_attribute
+ def _gens(self):
+ """
+ The generators of this Galois group as permutations of the roots. It's important that this
+ be computed lazily, since it's often possible to compute other attributes (such as the order
+ or transitive number) more cheaply.
+
+ EXAMPLES::
+
+ sage: R. = ZZ[]
+ sage: K. = NumberField(x^5 - 2) # needs sage.rings.number_field
+ sage: G = K.galois_group(gc_numbering=False) # needs sage.rings.number_field
+ sage: G._gens # needs sage.rings.number_field
+ [(1,2,3,5), (1,4,3,2,5)]
+ """
+ return NotImplemented
+
+ def __init__(self, field, algorithm=None, names=None, gc_numbering=False):
+ r"""
+ EXAMPLES::
+
+ sage: R. = ZZ[]
+ sage: K. = NumberField(x^3 + 2*x + 2) # needs sage.rings.number_field
+ sage: G = K.galois_group() # needs sage.rings.number_field
+ sage: TestSuite(G).run() # needs sage.rings.number_field
+ """
+ self._field = field
+ self._default_algorithm = algorithm
+ self._base = field.base_field()
+ self._gc_numbering = gc_numbering
+ if names is None:
+ # add a c for Galois closure
+ names = field.variable_name() + 'c'
+ self._gc_names = normalize_names(1, names)
+ # We do only the parts of the initialization of PermutationGroup_generic
+ # that don't depend on _gens
+ from sage.categories.permutation_groups import PermutationGroups
+ category = PermutationGroups().FinitelyGenerated().Finite()
+ # Note that we DON'T call the __init__ method for PermutationGroup_generic
+ # Instead, the relevant attributes are computed lazily
+ super(PermutationGroup_generic, self).__init__(category=category)
+
+ @lazy_attribute
+ def _deg(self):
+ r"""
+ The number of moved points in the permutation representation.
+
+ This will be the degree of the original number field if `_gc_numbering``
+ is ``False``, or the degree of the Galois closure otherwise.
+
+ EXAMPLES::
+
+ sage: # needs sage.rings.number_field
+ sage: R. = ZZ[]
+ sage: K. = NumberField(x^5 - 2)
+ sage: G = K.galois_group(gc_numbering=False); G
+ Galois group 5T3 (5:4) with order 20 of x^5 - 2
+ sage: G._deg
+ 5
+ sage: G = K.galois_group(gc_numbering=True); G._deg
+ 20
+ """
+ if self._gc_numbering:
+ return self.order()
+ else:
+ try:
+ return self._field.degree()
+ except NotImplementedError: # relative number fields don't support degree
+ return self._field.relative_degree()
+
+ @lazy_attribute
+ def _domain(self):
+ r"""
+ The integers labeling the roots on which this Galois group acts.
+
+ EXAMPLES::
+
+ sage: # needs sage.rings.number_field
+ sage: R. = ZZ[]
+ sage: K. = NumberField(x^5 - 2)
+ sage: G = K.galois_group(gc_numbering=False); G
+ Galois group 5T3 (5:4) with order 20 of x^5 - 2
+ sage: G._domain
+ {1, 2, 3, 4, 5}
+ sage: G = K.galois_group(gc_numbering=True); G._domain
+ {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
+ """
+ return FiniteEnumeratedSet(range(1, self._deg+1))
+
+ @lazy_attribute
+ def _domain_to_gap(self):
+ r"""
+ Dictionary implementing the identity (used by PermutationGroup_generic).
+
+ EXAMPLES::
+
+ sage: R. = ZZ[]
+ sage: K. = NumberField(x^5 - 2) # needs sage.rings.number_field
+ sage: G = K.galois_group(gc_numbering=False) # needs sage.rings.number_field
+ sage: G._domain_to_gap[5] # needs sage.rings.number_field
+ 5
+ """
+ return {key: i+1 for i, key in enumerate(self._domain)}
+
+ @lazy_attribute
+ def _domain_from_gap(self):
+ r"""
+ Dictionary implementing the identity (used by PermutationGroup_generic).
+
+ EXAMPLES::
+
+ sage: R. = ZZ[]
+ sage: K. = NumberField(x^5 - 2) # needs sage.rings.number_field
+ sage: G = K.galois_group(gc_numbering=True) # needs sage.rings.number_field
+ sage: G._domain_from_gap[20] # needs sage.rings.number_field
+ 20
+ """
+ return {i+1: key for i, key in enumerate(self._domain)}
+
+ def ngens(self):
+ r"""
+ Number of generators of this Galois group
+
+ EXAMPLES::
+
+ sage: QuadraticField(-23, 'a').galois_group().ngens() # needs sage.rings.number_field
+ 1
+ """
+ return len(self._gens)
+
+
+class GaloisSubgroup_perm(PermutationGroup_subgroup, _SubGaloisMixin):
+ """
+ Subgroups of Galois groups (implemented as permutation groups), specified
+ by giving a list of generators.
+
+ Unlike ambient Galois groups, where we use a lazy ``_gens`` attribute in order
+ to enable creation without determining a list of generators,
+ we require that generators for a subgroup be specified during initialization,
+ as specified in the ``__init__`` method of permutation subgroups.
+ """
+ pass
+
+
+GaloisGroup_perm.Subgroup = GaloisSubgroup_perm
diff --git a/src/sage/groups/generic.py b/src/sage/groups/generic.py
index 69bffca1b9f..9ef099fa93e 100644
--- a/src/sage/groups/generic.py
+++ b/src/sage/groups/generic.py
@@ -117,10 +117,12 @@
from copy import copy
+from sage.arith.misc import integer_ceil, integer_floor, xlcm
+from sage.arith.srange import xsrange
+from sage.misc.functional import log
from sage.misc.misc_c import prod
import sage.rings.integer_ring as integer_ring
import sage.rings.integer
-from sage.arith.srange import xsrange
#
# Lists of names (as strings) which the user may use to identify one
@@ -550,10 +552,10 @@ def discrete_log_rho(a, base, ord=None, operation='*', identity=None, inverse=No
It also works with matrices::
- sage: A = matrix(GF(50021), [[10577, 23999, 28893], # needs sage.rings.finite_rings
+ sage: A = matrix(GF(50021), [[10577, 23999, 28893], # needs sage.modules sage.rings.finite_rings
....: [14601, 41019, 30188],
....: [3081, 736, 27092]])
- sage: discrete_log_rho(A^1234567, A) # needs sage.rings.finite_rings
+ sage: discrete_log_rho(A^1234567, A) # needs sage.modules sage.rings.finite_rings
1234567
Beware, the order must be prime::
@@ -1234,7 +1236,7 @@ def order_from_multiple(P, m, plist=None, factorization=None, check=True,
sage: order_from_multiple(w, 230, operation='*')
23
- sage: # needs sage.rings.finite_rings
+ sage: # needs sage.modules sage.rings.finite_rings
sage: F = GF(2^1279,'a')
sage: n = F.cardinality() - 1 # Mersenne prime
sage: order_from_multiple(F.random_element(), n,
@@ -1396,8 +1398,7 @@ def order_from_bounds(P, bounds, d=None, operation='+',
if d > 1:
Q = multiple(P, d, operation=operation)
lb, ub = bounds
- bounds = (sage.arith.all.integer_ceil(lb / d),
- sage.arith.all.integer_floor(ub / d))
+ bounds = (integer_ceil(lb / d), integer_floor(ub / d))
# Use generic bsgs to find n=d*m with lb<=n<=ub and n*P=0
@@ -1486,7 +1487,7 @@ def merge_points(P1, P2, operation='+',
if n2.divides(n1):
return (g1, n1)
- m, k1, k2 = sage.arith.all.xlcm(n1, n2)
+ m, k1, k2 = xlcm(n1, n2)
m1 = n1 // k1
m2 = n2 // k2
g1 = multiple(g1, m1, operation=operation)
diff --git a/src/sage/groups/group.pyx b/src/sage/groups/group.pyx
index cd2521e3478..ef639a0c367 100644
--- a/src/sage/groups/group.pyx
+++ b/src/sage/groups/group.pyx
@@ -35,9 +35,9 @@ def is_Group(x):
EXAMPLES::
- sage: F. = FreeGroup() # needs sage.combinat
+ sage: F. = FreeGroup() # needs sage.groups
sage: from sage.groups.group import is_Group
- sage: is_Group(F) # needs sage.combinat
+ sage: is_Group(F) # needs sage.groups
True
sage: is_Group("a string")
False
@@ -140,7 +140,7 @@ cdef class Group(Parent):
EXAMPLES::
- sage: SL(2, 7).is_commutative() # needs sage.modules sage.rings.finite_rings
+ sage: SL(2, 7).is_commutative() # needs sage.libs.gap sage.modules sage.rings.finite_rings
False
"""
return self.is_abelian()
@@ -186,6 +186,39 @@ cdef class Group(Parent):
"""
return self.order() != infinity
+ def is_trivial(self):
+ r"""
+ Return ``True`` if this group is the trivial group.
+
+ A group is trivial, if it consists only of the identity
+ element.
+
+ .. WARNING::
+
+ It is in principle undecidable whether a group is
+ trivial, for example, if the group is given by a finite
+ presentation. Thus, this method may not terminate.
+
+ EXAMPLES::
+
+ sage: groups.presentation.Cyclic(1).is_trivial()
+ True
+
+ sage: G. = FreeGroup('a, b')
+ sage: H = G / (a^2, b^3, a*b*~a*~b)
+ sage: H.is_trivial()
+ False
+
+ A non-trivial presentation of the trivial group::
+
+ sage: F. = FreeGroup()
+ sage: J = F / ((~a)*b*a*(~b)^2, (~b)*a*b*(~a)^2)
+ sage: J.is_trivial()
+ True
+ """
+ return self.order() == 1
+
+
def is_multiplicative(self):
r"""
Returns True if the group operation is given by \* (rather than
@@ -212,8 +245,8 @@ cdef class Group(Parent):
EXAMPLES::
- sage: G = AbelianGroup([2,3,4,5]) # needs sage.groups
- sage: G.an_element() # needs sage.groups
+ sage: G = AbelianGroup([2,3,4,5]) # needs sage.modules
+ sage: G.an_element() # needs sage.modules
f0*f1*f2*f3
"""
return self.prod(self.gens())
diff --git a/src/sage/groups/matrix_gps/coxeter_group.py b/src/sage/groups/matrix_gps/coxeter_group.py
index 6b865805298..d1c647f1286 100644
--- a/src/sage/groups/matrix_gps/coxeter_group.py
+++ b/src/sage/groups/matrix_gps/coxeter_group.py
@@ -79,7 +79,7 @@ class CoxeterMatrixGroup(UniqueRepresentation, FinitelyGeneratedMatrixGroup_gene
We can create Coxeter groups from Coxeter matrices::
- sage: # needs sage.rings.number_field
+ sage: # needs sage.libs.gap sage.rings.number_field
sage: W = CoxeterGroup([[1, 6, 3], [6, 1, 10], [3, 10, 1]]); W
Coxeter group over Universal Cyclotomic Field with Coxeter matrix:
[ 1 6 3]
@@ -150,7 +150,7 @@ class CoxeterMatrixGroup(UniqueRepresentation, FinitelyGeneratedMatrixGroup_gene
graphs, we can input a Coxeter graph. Following the standard convention,
edges with no label (i.e. labelled by ``None``) are treated as 3::
- sage: # needs sage.rings.number_field
+ sage: # needs sage.libs.gap sage.rings.number_field
sage: G = Graph([(0,3,None), (1,3,15), (2,3,7), (0,1,3)])
sage: W = CoxeterGroup(G); W
Coxeter group over Universal Cyclotomic Field with Coxeter matrix:
@@ -165,7 +165,7 @@ class CoxeterMatrixGroup(UniqueRepresentation, FinitelyGeneratedMatrixGroup_gene
Because there currently is no class for `\ZZ \cup \{ \infty \}`, labels
of `\infty` are given by `-1` in the Coxeter matrix::
- sage: # needs sage.rings.number_field
+ sage: # needs sage.libs.gap sage.rings.number_field
sage: G = Graph([(0,1,None), (1,2,4), (0,2,oo)])
sage: W = CoxeterGroup(G)
sage: W.coxeter_matrix()
@@ -183,7 +183,7 @@ class CoxeterMatrixGroup(UniqueRepresentation, FinitelyGeneratedMatrixGroup_gene
[2 3 1 3 3]
[2 2 3 1 2]
[2 2 3 2 1]
- sage: W = CoxeterGroup(['H',3], implementation="reflection"); W # needs sage.rings.number_field
+ sage: W = CoxeterGroup(['H',3], implementation="reflection"); W # needs sage.libs.gap sage.rings.number_field
Finite Coxeter group over
Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790?
with Coxeter matrix:
@@ -240,15 +240,15 @@ def __init__(self, coxeter_matrix, base_ring, index_set):
EXAMPLES::
sage: W = CoxeterGroup([[1,3,2],[3,1,3],[2,3,1]])
- sage: TestSuite(W).run() # long time
+ sage: TestSuite(W).run() # long time
- sage: # needs sage.rings.number_field
+ sage: # long time, needs sage.rings.number_field sage.symbolic
sage: W = CoxeterGroup([[1,3,2],[3,1,4],[2,4,1]], base_ring=QQbar)
- sage: TestSuite(W).run() # long time
+ sage: TestSuite(W).run()
sage: W = CoxeterGroup([[1,3,2],[3,1,6],[2,6,1]])
- sage: TestSuite(W).run(max_runs=30) # long time
+ sage: TestSuite(W).run(max_runs=30)
sage: W = CoxeterGroup([[1,3,2],[3,1,-1],[2,-1,1]])
- sage: TestSuite(W).run(max_runs=30) # long time
+ sage: TestSuite(W).run(max_runs=30)
We check that :trac:`16630` is fixed::
@@ -340,7 +340,7 @@ def _repr_(self):
EXAMPLES::
- sage: CoxeterGroup([[1,3,2],[3,1,4],[2,4,1]]) # needs sage.rings.number_field
+ sage: CoxeterGroup([[1,3,2],[3,1,4],[2,4,1]]) # needs sage.libs.gap sage.rings.number_field
Finite Coxeter group over Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095? with Coxeter matrix:
[1 3 2]
[3 1 4]
@@ -383,8 +383,8 @@ def coxeter_matrix(self):
sage: W.coxeter_matrix()
[1 3]
[3 1]
- sage: W = CoxeterGroup(['H',3]) # needs sage.rings.number_field
- sage: W.coxeter_matrix()
+ sage: W = CoxeterGroup(['H',3]) # needs sage.libs.gap sage.rings.number_field
+ sage: W.coxeter_matrix() # needs sage.libs.gap sage.rings.number_field
[1 3 2]
[3 1 5]
[2 5 1]
@@ -423,7 +423,7 @@ def is_finite(self):
EXAMPLES::
- sage: # needs sage.rings.number_field
+ sage: # needs sage.libs.gap sage.rings.number_field
sage: [l for l in range(2, 9) if
....: CoxeterGroup([[1,3,2],[3,1,l],[2,l,1]]).is_finite()]
[2, 3, 4, 5]
@@ -482,8 +482,8 @@ def order(self):
sage: W = CoxeterGroup([[1,3],[3,1]])
sage: W.order()
6
- sage: W = CoxeterGroup([[1,-1],[-1,1]])
- sage: W.order()
+ sage: W = CoxeterGroup([[1,-1],[-1,1]]) # needs sage.libs.gap
+ sage: W.order() # needs sage.libs.gap
+Infinity
"""
if self.is_finite():
@@ -593,7 +593,7 @@ def positive_roots(self):
sage: W.positive_roots()
((1, 0, 0), (1, 1, 0), (0, 1, 0), (1, 1, 1), (0, 1, 1), (0, 0, 1))
- sage: # needs sage.rings.number_field
+ sage: # needs sage.libs.gap sage.rings.number_field
sage: W = CoxeterGroup(['I',5], implementation='reflection')
sage: W.positive_roots()
((1, 0),
@@ -651,7 +651,7 @@ def roots(self):
(0, -1, -1),
(0, 0, -1))
- sage: # needs sage.rings.number_field
+ sage: # needs sage.libs.gap sage.rings.number_field
sage: W = CoxeterGroup(['I',5], implementation='reflection')
sage: len(W.roots())
10
diff --git a/src/sage/groups/matrix_gps/finitely_generated.py b/src/sage/groups/matrix_gps/finitely_generated.py
index c8098ad578a..ef6ba42a105 100644
--- a/src/sage/groups/matrix_gps/finitely_generated.py
+++ b/src/sage/groups/matrix_gps/finitely_generated.py
@@ -9,7 +9,7 @@
sage: F = GF(3)
sage: gens = [matrix(F, 2, [1,0, -1,1]), matrix(F, 2, [1,1,0,1])]
sage: G = MatrixGroup(gens)
- sage: G.conjugacy_classes_representatives()
+ sage: G.conjugacy_classes_representatives() # needs sage.libs.gap
(
[1 0] [0 2] [0 1] [2 0] [0 2] [0 1] [0 2]
[0 1], [1 1], [2 1], [0 2], [1 2], [2 2], [1 0]
@@ -161,6 +161,8 @@ def QuaternionMatrixGroupGF3():
is the product of `I` and `J`. ::
sage: from sage.groups.matrix_gps.finitely_generated import QuaternionMatrixGroupGF3
+
+ sage: # needs sage.libs.gap
sage: Q = QuaternionMatrixGroupGF3()
sage: Q.order()
8
@@ -176,22 +178,23 @@ def QuaternionMatrixGroupGF3():
TESTS::
- sage: groups.matrix.QuaternionGF3() # needs sage.modules sage.rings.finite_rings
+ sage: groups.matrix.QuaternionGF3()
Matrix group over Finite Field of size 3 with 2 generators (
[1 1] [2 1]
[1 2], [1 1]
)
+ sage: # needs sage.groups
sage: Q = QuaternionMatrixGroupGF3()
sage: QP = Q.as_permutation_group()
sage: QP.is_isomorphic(QuaternionGroup())
True
- sage: H = DihedralGroup(4) # needs sage.groups
- sage: H.order() # needs sage.groups
+ sage: H = DihedralGroup(4)
+ sage: H.order()
8
- sage: QP.is_abelian(), H.is_abelian() # needs sage.groups
+ sage: QP.is_abelian(), H.is_abelian()
(False, False)
- sage: QP.is_isomorphic(H) # needs sage.groups
+ sage: QP.is_isomorphic(H)
False
"""
from sage.rings.finite_rings.finite_field_constructor import FiniteField
@@ -340,6 +343,7 @@ class FinitelyGeneratedMatrixGroup_generic(MatrixGroup_generic):
sage: MatrixGroup(m1, m2) == MatrixGroup(m2, m1)
False
+ sage: # needs sage.libs.gap
sage: G = GL(2, GF(3))
sage: H = G.as_matrix_group()
sage: H == G, G == H
@@ -415,6 +419,7 @@ def gen(self, i):
EXAMPLES::
+ sage: # needs sage.libs.gap
sage: H = GL(2, GF(3))
sage: h1, h2 = H([[1,0], [2,1]]), H([[1,1], [0,1]])
sage: G = H.subgroup([h1, h2])
@@ -436,6 +441,7 @@ def ngens(self):
EXAMPLES::
+ sage: # needs sage.libs.gap
sage: H = GL(2, GF(3))
sage: h1, h2 = H([[1,0], [2,1]]), H([[1,1], [0,1]])
sage: G = H.subgroup([h1, h2])
diff --git a/src/sage/groups/matrix_gps/finitely_generated_gap.py b/src/sage/groups/matrix_gps/finitely_generated_gap.py
index af676af3673..add6875a802 100644
--- a/src/sage/groups/matrix_gps/finitely_generated_gap.py
+++ b/src/sage/groups/matrix_gps/finitely_generated_gap.py
@@ -120,16 +120,14 @@ def as_permutation_group(self, algorithm=None, seed=None):
21499084800
sage: P = G.as_permutation_group()
sage: Psmaller = G.as_permutation_group(algorithm="smaller", seed=6)
- sage: P == Psmaller
- False
sage: P.cardinality()
21499084800
sage: P.degree()
144
sage: Psmaller.cardinality()
21499084800
- sage: Psmaller.degree() # random
- 80
+ sage: Psmaller.degree() <= P.degree()
+ True
.. NOTE::
diff --git a/src/sage/groups/matrix_gps/linear.py b/src/sage/groups/matrix_gps/linear.py
index 65a8c13645c..822bd576afd 100644
--- a/src/sage/groups/matrix_gps/linear.py
+++ b/src/sage/groups/matrix_gps/linear.py
@@ -16,6 +16,8 @@
Special Linear Group of degree 2 over Integer Ring
sage: G = SL(2, GF(3)); G
Special Linear Group of degree 2 over Finite Field of size 3
+
+ sage: # needs sage.libs.gap
sage: G.is_finite()
True
sage: G.conjugacy_classes_representatives()
@@ -94,32 +96,38 @@ def GL(n, R, var='a'):
EXAMPLES::
sage: G = GL(6, GF(5))
- sage: G.order()
- 11064475422000000000000000
sage: G.base_ring()
Finite Field of size 5
sage: G.category()
Category of finite groups
+
+ sage: # needs sage.libs.gap
+ sage: G.order()
+ 11064475422000000000000000
sage: TestSuite(G).run()
sage: G = GL(6, QQ)
sage: G.category()
Category of infinite groups
+
+ sage: # needs sage.libs.gap
sage: TestSuite(G).run()
Here is the Cayley graph of (relatively small) finite General Linear Group::
+ sage: # needs sage.graphs sage.libs.gap
sage: g = GL(2,3)
- sage: d = g.cayley_graph(); d # needs sage.graphs
+ sage: d = g.cayley_graph(); d
Digraph on 48 vertices
- sage: d.plot(color_by_label=True, vertex_size=0.03, # long time # needs sage.graphs sage.plot
+ sage: d.plot(color_by_label=True, vertex_size=0.03, # long time # needs sage.plot
....: vertex_labels=False)
Graphics object consisting of 144 graphics primitives
- sage: d.plot3d(color_by_label=True) # long time # needs sage.graphs sage.plot
+ sage: d.plot3d(color_by_label=True) # long time # needs sage.plot
Graphics3d Object
::
+ sage: # needs sage.libs.gap
sage: F = GF(3); MS = MatrixSpace(F, 2, 2)
sage: gens = [MS([[2,0], [0,1]]), MS([[2,1], [2,0]])]
sage: G = MatrixGroup(gens)
@@ -213,10 +221,13 @@ def SL(n, R, var='a'):
Special Linear Group of degree 15 over Finite Field of size 7
sage: G.category()
Category of finite groups
+
+ sage: # needs sage.libs.gap
sage: G.order()
1956712595698146962015219062429586341124018007182049478916067369638713066737882363393519966343657677430907011270206265834819092046250232049187967718149558134226774650845658791865745408000000
sage: len(G.gens())
2
+
sage: G = SL(2, ZZ); G
Special Linear Group of degree 2 over Integer Ring
sage: G.category()
@@ -231,6 +242,8 @@ def SL(n, R, var='a'):
sage: G = SL(3, ZZ); G
Special Linear Group of degree 3 over Integer Ring
+
+ sage: # needs sage.libs.gap
sage: G.gens()
(
[0 1 0] [ 0 1 0] [1 1 0]
diff --git a/src/sage/groups/matrix_gps/matrix_group.py b/src/sage/groups/matrix_gps/matrix_group.py
index c0c22456320..192c4e4d4cf 100644
--- a/src/sage/groups/matrix_gps/matrix_group.py
+++ b/src/sage/groups/matrix_gps/matrix_group.py
@@ -5,10 +5,10 @@
Loading, saving, ... works::
+ sage: # needs sage.libs.gap
sage: G = GL(2,5); G
General Linear Group of degree 2 over Finite Field of size 5
sage: TestSuite(G).run()
-
sage: g = G.1; g
[4 1]
[4 0]
@@ -159,7 +159,7 @@ def as_matrix_group(self):
EXAMPLES::
sage: G = SU(4, GF(5)) # needs sage.rings.finite_rings
- sage: G.as_matrix_group() # needs sage.rings.finite_rings
+ sage: G.as_matrix_group() # needs sage.libs.gap sage.rings.finite_rings
Matrix group over Finite Field in a of size 5^2 with 2 generators (
[ a 0 0 0] [ 1 0 4*a + 3 0]
[ 0 2*a + 3 0 0] [ 1 0 0 0]
@@ -167,7 +167,8 @@ def as_matrix_group(self):
[ 0 0 0 3*a], [ 0 3*a + 1 0 0]
)
- sage: G = GO(3,GF(5))
+ sage: # needs sage.libs.gap
+ sage: G = GO(3, GF(5))
sage: G.as_matrix_group()
Matrix group over Finite Field of size 5 with 2 generators (
[2 0 0] [0 1 0]
@@ -316,8 +317,8 @@ def _repr_option(self, key):
EXAMPLES::
- sage: SO3 = groups.matrix.SO(3, QQ) # needs sage.groups sage.modules
- sage: SO3._repr_option('element_ascii_art') # needs sage.groups sage.modules
+ sage: SO3 = groups.matrix.SO(3, QQ)
+ sage: SO3._repr_option('element_ascii_art')
True
"""
if key == 'element_ascii_art':
@@ -479,6 +480,7 @@ def __richcmp__(self, other, op):
EXAMPLES::
+ sage: # needs sage.libs.gap
sage: G = GL(2,3)
sage: H = MatrixGroup(G.gens())
sage: H == G
@@ -486,6 +488,7 @@ def __richcmp__(self, other, op):
sage: G == H
True
+ sage: # needs sage.libs.gap
sage: MS = MatrixSpace(QQ, 2, 2)
sage: G = MatrixGroup([MS(1), MS([1,2,3,4])])
sage: G == G
@@ -542,3 +545,34 @@ def __richcmp__(self, other, op):
if lx != rx:
return richcmp_not_equal(lx, rx, op)
return rich_to_bool(op, 0)
+
+ def is_trivial(self):
+ r"""
+ Return ``True`` if this group is the trivial group.
+
+ A group is trivial, if it consists only of the identity
+ element, that is, if all its generators are the identity.
+
+ EXAMPLES::
+
+ sage: MatrixGroup([identity_matrix(3)]).is_trivial()
+ True
+ sage: SL(2, ZZ).is_trivial()
+ False
+ sage: CoxeterGroup(['B',3], implementation="matrix").is_trivial()
+ False
+
+ TESTS::
+
+ sage: CoxeterGroup(['A',0], implementation="matrix").is_trivial()
+ True
+ sage: MatrixGroup([matrix(SR, [[1,x], [0,1]])]).is_trivial()
+ False
+ sage: G = MatrixGroup([identity_matrix(3), identity_matrix(3)])
+ sage: G.ngens()
+ 2
+ sage: G.is_trivial()
+ True
+
+ """
+ return all(g.is_one() for g in self.gens())
diff --git a/src/sage/groups/matrix_gps/named_group.py b/src/sage/groups/matrix_gps/named_group.py
index 4568c43d326..98841d9f0af 100644
--- a/src/sage/groups/matrix_gps/named_group.py
+++ b/src/sage/groups/matrix_gps/named_group.py
@@ -10,6 +10,8 @@
Special Linear Group of degree 2 over Integer Ring
sage: G = SL(2, GF(3)); G
Special Linear Group of degree 2 over Finite Field of size 3
+
+ sage: # needs sage.libs.gap
sage: G.is_finite()
True
sage: G.conjugacy_classes_representatives()
@@ -288,12 +290,13 @@ def __richcmp__(self, other, op):
EXAMPLES::
+ sage: # needs sage.libs.gap
sage: G = GL(2,3)
sage: G == MatrixGroup(G.gens())
True
- sage: # needs sage.rings.finite_rings
- sage: G = groups.matrix.GL(4,2) # needs sage.modules
+ sage: # needs sage.libs.gap sage.rings.finite_rings
+ sage: G = groups.matrix.GL(4,2)
sage: H = MatrixGroup(G.gens())
sage: G == H
True
diff --git a/src/sage/groups/matrix_gps/orthogonal.py b/src/sage/groups/matrix_gps/orthogonal.py
index 9e90d3ac0dc..8d622f7b14f 100644
--- a/src/sage/groups/matrix_gps/orthogonal.py
+++ b/src/sage/groups/matrix_gps/orthogonal.py
@@ -39,6 +39,8 @@
sage: G = SO(4, GF(7), 1); G
Special Orthogonal Group of degree 4 and form parameter 1
over Finite Field of size 7
+
+ sage: # needs sage.libs.gap
sage: G.random_element() # random
[4 3 5 2]
[6 6 4 0]
@@ -154,7 +156,7 @@ def _OG(n, R, special, e=0, var='a', invariant_form=None):
Check that :trac:`26028` is fixed::
- sage: GO(3,25).order() # indirect doctest # needs sage.rings.finite_rings
+ sage: GO(3,25).order() # indirect doctest # needs sage.libs.gap sage.rings.finite_rings
31200
Check that :trac:`28054` is fixed::
@@ -270,6 +272,8 @@ def GO(n, R, e=0, var='a', invariant_form=None):
sage: GO(3, GF(7))
General Orthogonal Group of degree 3 over Finite Field of size 7
+
+ sage: # needs sage.libs.gap
sage: GO(3, GF(7)).order()
672
sage: GO(3, GF(7)).gens()
@@ -323,6 +327,7 @@ def GO(n, R, e=0, var='a', invariant_form=None):
TESTS::
+ sage: # needs sage.libs.gap
sage: TestSuite(GO3).run()
sage: groups.matrix.GO(2, 3, e=-1)
General Orthogonal Group of degree 2 and form parameter -1 over Finite Field of size 3
@@ -378,6 +383,7 @@ def SO(n, R, e=None, var='a', invariant_form=None):
sage: G = SO(3,GF(5)); G
Special Orthogonal Group of degree 3 over Finite Field of size 5
+ sage: # needs sage.libs.gap
sage: G = SO(3,GF(5))
sage: G.gens()
(
@@ -385,7 +391,6 @@ def SO(n, R, e=None, var='a', invariant_form=None):
[0 3 0] [0 2 0] [4 0 0]
[0 0 1], [0 3 1], [2 0 4]
)
- sage: G = SO(3,GF(5))
sage: G.as_matrix_group()
Matrix group over Finite Field of size 5 with 3 generators (
[2 0 0] [3 2 3] [1 4 4]
@@ -483,6 +488,7 @@ def invariant_bilinear_form(self):
EXAMPLES::
+ sage: # needs sage.libs.gap
sage: GO(2,3,+1).invariant_bilinear_form()
[0 1]
[1 0]
@@ -503,7 +509,7 @@ def invariant_bilinear_form(self):
TESTS::
- sage: GO3m.invariant_form()
+ sage: GO3m.invariant_form() # needs sage.libs.gap
[1 0 0]
[0 2 0]
[0 0 3]
diff --git a/src/sage/groups/matrix_gps/symplectic.py b/src/sage/groups/matrix_gps/symplectic.py
index e0f3324b645..ec61d8a0634 100644
--- a/src/sage/groups/matrix_gps/symplectic.py
+++ b/src/sage/groups/matrix_gps/symplectic.py
@@ -5,6 +5,8 @@
sage: G = Sp(4, GF(7)); G
Symplectic Group of degree 4 over Finite Field of size 7
+
+ sage: # needs sage.libs.gap
sage: g = prod(G.gens()); g
[3 0 3 0]
[1 0 0 0]
@@ -138,6 +140,7 @@ def Sp(n, R, var='a', invariant_form=None):
sage: groups.matrix.Sp(2, 3) # needs sage.modules sage.rings.finite_rings
Symplectic Group of degree 2 over Finite Field of size 3
+ sage: # needs sage.libs.gap
sage: G = Sp(4,5)
sage: TestSuite(G).run()
"""
diff --git a/src/sage/groups/matrix_gps/unitary.py b/src/sage/groups/matrix_gps/unitary.py
index ed6221cb61d..379d8276571 100644
--- a/src/sage/groups/matrix_gps/unitary.py
+++ b/src/sage/groups/matrix_gps/unitary.py
@@ -8,11 +8,11 @@
sage: # needs sage.rings.finite_rings
sage: G = SU(3,5)
- sage: G.order()
+ sage: G.order() # needs sage.libs.gap
378000
sage: G
Special Unitary Group of degree 3 over Finite Field in a of size 5^2
- sage: G.gens()
+ sage: G.gens() # needs sage.libs.gap
(
[ a 0 0] [4*a 4 1]
[ 0 2*a + 2 0] [ 4 4 0]
@@ -100,7 +100,7 @@ def _UG(n, R, special, var='a', invariant_form=None):
TESTS::
- sage: GU(3,25).order() # indirect doctest # needs sage.rings.finite_rings
+ sage: GU(3,25).order() # indirect doctest # needs sage.libs.gap sage.rings.finite_rings
3961191000000
"""
prefix = 'General'
@@ -195,7 +195,7 @@ def GU(n, R, var='a', invariant_form=None):
sage: G = GU(3, 7); G # needs sage.rings.finite_rings
General Unitary Group of degree 3 over Finite Field in a of size 7^2
- sage: G.gens() # needs sage.rings.finite_rings
+ sage: G.gens() # needs sage.libs.gap sage.rings.finite_rings
(
[ a 0 0] [6*a 6 1]
[ 0 1 0] [ 6 6 0]
@@ -207,7 +207,7 @@ def GU(n, R, var='a', invariant_form=None):
sage: G = GU(3, 5, var='beta') # needs sage.rings.finite_rings
sage: G.base_ring() # needs sage.rings.finite_rings
Finite Field in beta of size 5^2
- sage: G.gens() # needs sage.rings.finite_rings
+ sage: G.gens() # needs sage.libs.gap sage.rings.finite_rings
(
[ beta 0 0] [4*beta 4 1]
[ 0 1 0] [ 4 4 0]
diff --git a/src/sage/groups/pari_group.py b/src/sage/groups/pari_group.py
index bbcb1c0a6c9..4d1ca0bff22 100644
--- a/src/sage/groups/pari_group.py
+++ b/src/sage/groups/pari_group.py
@@ -6,8 +6,10 @@
"""
from sage.libs.pari import pari
+from sage.misc.lazy_import import lazy_import
from sage.rings.integer import Integer
-from sage.groups.perm_gps.permgroup_named import TransitiveGroup
+
+lazy_import('sage.groups.perm_gps.permgroup_named', 'TransitiveGroup')
class PariGroup():
diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py
index 8e2e6d82c10..2d73c8e7cf2 100644
--- a/src/sage/groups/perm_gps/permgroup.py
+++ b/src/sage/groups/perm_gps/permgroup.py
@@ -344,6 +344,7 @@ def PermutationGroup(gens=None, *args, **kwds):
Note that we provide generators for the acting group. The
permutation group we construct is its homomorphic image::
+ sage: # needs sage.combinat
sage: a = lambda g, x: vector(g*x, immutable=True)
sage: X = [vector(x, immutable=True) for x in GF(3)^2]
sage: G = SL(2,3); G.gens()
@@ -1365,6 +1366,38 @@ def ngens(self):
"""
return len(self.gens())
+ def is_trivial(self):
+ r"""
+ Return ``True`` if this group is the trivial group.
+
+ A permutation group is trivial, if it consists only of the
+ identity element, that is, if it has no generators or only
+ trivial generators.
+
+ EXAMPLES::
+
+ sage: G = PermutationGroup([], domain=["a", "b", "c"])
+ sage: G.is_trivial()
+ True
+ sage: SymmetricGroup(0).is_trivial()
+ True
+ sage: SymmetricGroup(1).is_trivial()
+ True
+ sage: SymmetricGroup(2).is_trivial()
+ False
+ sage: DihedralGroup(1).is_trivial()
+ False
+
+ TESTS::
+
+ sage: G = PermutationGroup([[], []], canonicalize=False)
+ sage: G.ngens()
+ 2
+ sage: G.is_trivial()
+ True
+ """
+ return all(g.is_one() for g in self._gens)
+
@cached_method
def one(self):
"""
@@ -1547,6 +1580,7 @@ def representative_action(self,x,y):
TESTS::
+ sage: # needs sage.graphs
sage: g = graphs.PetersenGraph()
sage: g.relabel(list("abcdefghik"))
sage: g.vertices(sort=True)
@@ -2337,13 +2371,14 @@ def socle(self):
EXAMPLES::
sage: G = SymmetricGroup(4)
- sage: G.socle()
+ sage: s = G.socle(); s
Subgroup generated by [(1,2)(3,4), (1,4)(2,3)] of
(Symmetric group of order 4! as a permutation group)
- sage: G.socle().socle()
- Subgroup generated by [(1,2)(3,4), (1,4)(2,3)] of
- (Subgroup generated by [(1,2)(3,4), (1,4)(2,3)]
- of (Symmetric group of order 4! as a permutation group))
+
+ The socle of the socle is, essentially, the socle::
+
+ sage: s.socle() == s.subgroup(s.gens())
+ True
"""
return self.subgroup(gap_group=self._gap_().Socle())
@@ -3706,6 +3741,7 @@ def has_regular_subgroup(self, return_group=False):
But the automorphism group of Petersen's graph does not::
+ sage: # needs sage.graphs
sage: G = graphs.PetersenGraph().automorphism_group()
sage: G.has_regular_subgroup()
False
@@ -3767,6 +3803,7 @@ def blocks_all(self, representatives=True):
Picking an interesting group::
+ sage: # needs sage.graphs
sage: g = graphs.DodecahedralGraph()
sage: g.is_vertex_transitive()
True
@@ -3776,12 +3813,12 @@ def blocks_all(self, representatives=True):
Computing its blocks representatives::
- sage: ag.blocks_all()
+ sage: ag.blocks_all() # needs sage.graphs
[[0, 15]]
Now the full block::
- sage: sorted(ag.blocks_all(representatives = False)[0])
+ sage: sorted(ag.blocks_all(representatives=False)[0]) # needs sage.graphs
[[0, 15], [1, 16], [2, 12], [3, 13], [4, 9],
[5, 10], [6, 11], [7, 18], [8, 17], [14, 19]]
@@ -3977,6 +4014,7 @@ def minimal_generating_set(self):
EXAMPLES::
+ sage: # needs sage.graphs
sage: g = graphs.CompleteGraph(4)
sage: g.relabel(['a','b','c','d'])
sage: mgs = g.automorphism_group().minimal_generating_set(); len(mgs)
diff --git a/src/sage/interfaces/gap.py b/src/sage/interfaces/gap.py
index 0a8087a20d5..26afa44edda 100644
--- a/src/sage/interfaces/gap.py
+++ b/src/sage/interfaces/gap.py
@@ -177,7 +177,7 @@
gap(...), x.[tab], and docs, e.g., gap.function? and x.function?
"""
-#*****************************************************************************
+# ****************************************************************************
# Copyright (C) 2005 William Stein
#
# Distributed under the terms of the GNU General Public License (GPL)
@@ -189,13 +189,13 @@
#
# The full text of the GPL is available at:
#
-# http://www.gnu.org/licenses/
-#*****************************************************************************
+# https://www.gnu.org/licenses/
+# ****************************************************************************
from .expect import Expect, ExpectElement, FunctionElement, ExpectFunction
from .gap_workspace import gap_workspace_file, prepare_workspace_dir
from sage.cpython.string import bytes_to_str
-from sage.env import SAGE_EXTCODE, SAGE_GAP_COMMAND, SAGE_GAP_MEMORY
+from sage.env import SAGE_EXTCODE, SAGE_GAP_COMMAND, SAGE_GAP_MEMORY, GAP_ROOT_PATHS
from sage.misc.misc import is_in_string
from sage.misc.cachefunc import cached_method
from sage.misc.instancedoc import instancedoc
@@ -217,7 +217,17 @@
first_try = True
-gap_cmd = SAGE_GAP_COMMAND
+if SAGE_GAP_COMMAND is None:
+ # Passing -A allows us to use a minimal GAP installation without
+ # producing errors at start-up. The files sage.g and sage.gaprc are
+ # used to load any additional packages that may be available.
+ gap_cmd = f'gap -A -l "{GAP_ROOT_PATHS}"'
+ if SAGE_GAP_MEMORY is not None:
+ gap_cmd += " -s " + SAGE_GAP_MEMORY + " -o " + SAGE_GAP_MEMORY
+else:
+ gap_cmd = SAGE_GAP_COMMAND
+
+
if platform.processor() == 'ia64' and os.path.exists('/usr/bin/prctl'):
# suppress unaligned access to 0x..., ip=0x... warnings
gap_cmd = 'prctl --unaligned=silent ' + gap_cmd
@@ -234,7 +244,7 @@ def gap_command(use_workspace_cache=True, local=True):
return gap_cmd, True
-############ Classes with methods for both the GAP3 and GAP4 interface
+# ########### Classes with methods for both the GAP3 and GAP4 interface
class Gap_generic(ExtraTabCompletion, Expect):
r"""
@@ -277,10 +287,10 @@ def _synchronize(self, timeout=0.5, cmd='%s;'):
E = self._expect
from sage.misc.prandom import randrange
rnd = randrange(2147483647)
- cmd = str(rnd)+';'
+ cmd = str(rnd) + ';'
try:
E.sendline(cmd)
- E.expect(r'@[nf][@J\s>]*'+str(rnd), timeout=timeout)
+ E.expect(r'@[nf][@J\s>]*' + str(rnd), timeout=timeout)
E.send(' ')
E.expect('@i', timeout=timeout)
except pexpect.TIMEOUT:
@@ -443,7 +453,7 @@ def load_package(self, pkg, verbose=False):
print("Loading GAP package {}".format(pkg))
x = self.eval('LoadPackage("{}")'.format(pkg))
if x == 'fail':
- raise RuntimeError("Error loading Gap package "+str(pkg)+". " +
+ raise RuntimeError("Error loading Gap package " + str(pkg) + ". " +
"You may want to install gap_packages SPKG.")
def eval(self, x, newlines=False, strip=True, split_lines=True, **kwds):
@@ -497,10 +507,10 @@ def eval(self, x, newlines=False, strip=True, split_lines=True, **kwds):
' -\n\\\\-'
"""
# '"
- #We remove all of the comments: On each line, we try
- #to find a pound sign. If we find it, we check to see if
- #it is occurring in a string. If it is not in a string, we
- #strip off the comment.
+ # We remove all of the comments: On each line, we try
+ # to find a pound sign. If we find it, we check to see if
+ # it is occurring in a string. If it is not in a string, we
+ # strip off the comment.
if not split_lines:
input_line = str(x)
else:
@@ -510,17 +520,17 @@ def eval(self, x, newlines=False, strip=True, split_lines=True, **kwds):
while pound_position != -1:
if not is_in_string(line, pound_position):
line = line[:pound_position]
- pound_position = line.find('#',pound_position+1)
- input_line += " "+line
+ pound_position = line.find('#', pound_position + 1)
+ input_line += " " + line
if not input_line.endswith(';'):
input_line += ';'
result = Expect.eval(self, input_line, **kwds)
if not newlines:
- result = result.replace("\\\n","")
+ result = result.replace("\\\n", "")
return result.rstrip()
def _execute_line(self, line, wait_for_prompt=True, expect_eof=False):
- if self._expect is None: # interface is down
+ if self._expect is None: # interface is down
self._start()
E = self._expect
try:
@@ -530,9 +540,9 @@ def _execute_line(self, line, wait_for_prompt=True, expect_eof=False):
except OSError:
raise RuntimeError("Error evaluating %s in %s" % (line, self))
if not wait_for_prompt:
- return (b'',b'')
+ return (b'', b'')
if len(line) == 0:
- return (b'',b'')
+ return (b'', b'')
try:
terminal_echo = [] # to be discarded
normal_outputs = [] # GAP stdout
@@ -546,43 +556,43 @@ def _execute_line(self, line, wait_for_prompt=True, expect_eof=False):
warnings.warn(
"possibly wrong version of GAP package "
"interface. Crossing fingers and continuing.")
- elif x == 1: #@@
+ elif x == 1: # @@
current_outputs.append(b'@')
- elif x == 2: #special char
+ elif x == 2: # special char
c = ord(E.after[1:2]) - ord(b'A') + 1
s = bytes([c])
current_outputs.append(s)
- elif x == 3: # garbage collection info, ignore
+ elif x == 3: # garbage collection info, ignore
pass
- elif x == 4: # @e -- break loop
+ elif x == 4: # @e -- break loop
E.sendline("quit;")
- elif x == 5: # @c completion, doesn't seem to happen when -p is in use
+ elif x == 5: # @c completion, doesn't seem to happen when -p is in use
warnings.warn("I didn't think GAP could do this")
- elif x == 6: # @f GAP error message
+ elif x == 6: # @f GAP error message
current_outputs = error_outputs
- elif x == 7: # @h help text, but this stopped happening with new help
+ elif x == 7: # @h help text, but this stopped happening with new help
warnings.warn("I didn't think GAP could do this")
- elif x == 8: # @i awaiting normal input
+ elif x == 8: # @i awaiting normal input
break
- elif x == 9: # @m finished running a child
+ elif x == 9: # @m finished running a child
pass # there is no need to do anything
- elif x == 10: #@n normal output line
+ elif x == 10: # @n normal output line
current_outputs = normal_outputs
- elif x == 11: #@r echoing input
+ elif x == 11: # @r echoing input
current_outputs = terminal_echo
- elif x == 12: #@sN shouldn't happen
+ elif x == 12: # @sN shouldn't happen
warnings.warn("this should never happen")
- elif x == 13: #@w GAP is trying to send a Window command
+ elif x == 13: # @w GAP is trying to send a Window command
warnings.warn("this should never happen")
- elif x == 14: #@x seems to be safely ignorable
+ elif x == 14: # @x seems to be safely ignorable
pass
- elif x == 15:#@z GAP starting a subprocess
+ elif x == 15: # @z GAP starting a subprocess
pass # there is no need to do anything
except pexpect.EOF:
if not expect_eof:
- raise RuntimeError("Unexpected EOF from %s executing %s" % (self,line))
+ raise RuntimeError("Unexpected EOF from %s executing %s" % (self, line))
except IOError:
- raise RuntimeError("IO Error from %s executing %s" % (self,line))
+ raise RuntimeError("IO Error from %s executing %s" % (self, line))
return (b"".join(normal_outputs), b"".join(error_outputs))
def _keyboard_interrupt(self):
@@ -687,8 +697,8 @@ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if
error += "\nRunning gap_reset_workspace()..."
self.quit()
gap_reset_workspace()
- error = error.replace('\r','')
- raise RuntimeError("%s produced error output\n%s\n executing %s" % (self, error,line))
+ error = error.replace('\r', '')
+ raise RuntimeError("%s produced error output\n%s\n executing %s" % (self, error, line))
if not normal:
return ''
@@ -762,7 +772,7 @@ def _contains(self, v1, v2):
sage: 2 in gap('Integers')
True
"""
- return self.eval('%s in %s' % (v1,v2)) == "true"
+ return self.eval('%s in %s' % (v1, v2)) == "true"
def _true_symbol(self):
"""
@@ -858,20 +868,21 @@ def function_call(self, function, args=None, kwds=None):
args, kwds = self._convert_args_kwds(args, kwds)
self._check_valid_function_name(function)
- #Here we have to do some magic because not all GAP
- #functions return a value. If you try to store their
- #results to a variable, then GAP will complain. Thus, before
- #we evaluate the function, we make it so that the marker string
- #is in the 'last' variable in GAP. If the function returns a
- #value, then that value will be in 'last', otherwise it will
- #be the marker.
+ # Here we have to do some magic because not all GAP
+ # functions return a value. If you try to store their
+ # results to a variable, then GAP will complain. Thus, before
+ # we evaluate the function, we make it so that the marker string
+ # is in the 'last' variable in GAP. If the function returns a
+ # value, then that value will be in 'last', otherwise it will
+ # be the marker.
marker = '__SAGE_LAST__:="__SAGE_LAST__";;'
cmd = "%s(%s);;" % (function, ",".join([s.name() for s in args] +
- ['%s=%s' % (key,value.name()) for key, value in kwds.items()]))
+ [f'{key}={value.name()}'
+ for key, value in kwds.items()]))
if len(marker) + len(cmd) <= self._eval_using_file_cutoff:
# We combine the two commands so we only run eval() once and the
# only output would be from the second command
- res = self.eval(marker+cmd)
+ res = self.eval(marker + cmd)
else:
self.eval(marker)
res = self.eval(cmd)
@@ -1035,7 +1046,8 @@ def _matrix_(self, R):
from sage.matrix.matrix_space import MatrixSpace
M = MatrixSpace(R, n, m)
- entries = [[R(self[r,c]) for c in range(1,m+1)] for r in range(1,n+1)]
+ entries = [[R(self[r, c]) for c in range(1, m + 1)]
+ for r in range(1, n + 1)]
return M(entries)
@@ -1089,7 +1101,7 @@ def __init__(self, max_workspace_size=None,
self.__seq = 0
self._seed = seed
- def set_seed(self,seed=None):
+ def set_seed(self, seed=None):
"""
Set the seed for gap interpreter.
@@ -1194,8 +1206,8 @@ def _start(self):
self.save_workspace()
# Now, as self._expect exists, we can compile some useful pattern:
self._compiled_full_pattern = self._expect.compile_pattern_list([
- r'@p\d+\.','@@','@[A-Z]',r'@[123456!"#$%&][^+]*\+',
- '@e','@c','@f','@h','@i','@m','@n','@r',r'@s\d',r'@w.*\+','@x','@z'])
+ r'@p\d+\.', '@@', '@[A-Z]', r'@[123456!"#$%&][^+]*\+',
+ '@e', '@c', '@f', '@h', '@i', '@m', '@n', '@r', r'@s\d', r'@w.*\+', '@x', '@z'])
# read everything up to the first "ready" prompt
self._expect.expect("@i")
@@ -1236,10 +1248,9 @@ def cputime(self, t=None):
"""
if t is not None:
return self.cputime() - t
- else:
- self.eval('_r_ := Runtimes();')
- r = sum(eval(self.eval('[_r_.user_time, _r_.system_time, _r_.user_time_children, _r_.system_time_children]')))
- return r/1000.0
+ self.eval('_r_ := Runtimes();')
+ r = sum(eval(self.eval('[_r_.user_time, _r_.system_time, _r_.user_time_children, _r_.system_time_children]')))
+ return r / 1000.0
def save_workspace(self):
r"""
@@ -1339,7 +1350,7 @@ def set(self, var, value):
sage: gap.get('x')
'2'
"""
- cmd = ('%s:=%s;;' % (var, value)).replace('\n','')
+ cmd = ('%s:=%s;;' % (var, value)).replace('\n', '')
self._eval_line(cmd, allow_use_file=True)
def get(self, var, use_file=False):
@@ -1356,10 +1367,10 @@ def get(self, var, use_file=False):
tmp = self._local_tmpfile()
if os.path.exists(tmp):
os.unlink(tmp)
- self.eval('PrintTo("%s", %s);' % (tmp,var), strip=False)
+ self.eval('PrintTo("%s", %s);' % (tmp, var), strip=False)
with open(tmp) as f:
r = f.read()
- r = r.strip().replace("\\\n","")
+ r = r.strip().replace("\\\n", "")
os.unlink(tmp)
return r
else:
@@ -1470,7 +1481,7 @@ def _tab_completion(self):
True
"""
names = eval(self.eval('NamesSystemGVars()')) + \
- eval(self.eval('NamesUserGVars()'))
+ eval(self.eval('NamesUserGVars()'))
return [n for n in names if n[0] in string.ascii_letters]
@@ -1498,20 +1509,21 @@ def gap_reset_workspace(max_workspace_size=None, verbose=False):
We temporarily need to change the worksheet filename, and to set
``first_try=True`` to ensure that the new workspace is created::
+ sage: # long time
sage: ORIGINAL_WORKSPACE = sage.interfaces.gap.WORKSPACE
sage: saved_first_try = sage.interfaces.gap.first_try
sage: sage.interfaces.gap.first_try = True
sage: sage.interfaces.gap.WORKSPACE = tmp_filename()
sage: from multiprocessing import Process
sage: import time
- sage: gap = Gap() # long time (reset GAP session)
+ sage: gap = Gap() # reset GAP session
sage: P = [Process(target=gap, args=("14242",)) for i in range(4)]
- sage: for p in P: # long time, indirect doctest
+ sage: for p in P: # indirect doctest
....: p.start()
....: time.sleep(float(0.2))
- sage: for p in P: # long time
+ sage: for p in P:
....: p.join()
- sage: os.unlink(sage.interfaces.gap.WORKSPACE) # long time
+ sage: os.unlink(sage.interfaces.gap.WORKSPACE)
sage: sage.interfaces.gap.WORKSPACE = ORIGINAL_WORKSPACE
sage: sage.interfaces.gap.first_try = saved_first_try
"""
@@ -1572,8 +1584,8 @@ def _latex_(self):
P = self._check_valid()
try:
s = P.eval('LaTeXObj(%s)' % self.name())
- s = s.replace('\\\\','\\').replace('"','')
- s = s.replace('%\\n',' ')
+ s = s.replace('\\\\', '\\').replace('"', '')
+ s = s.replace('%\\n', ' ')
return s
except RuntimeError:
return str(self)
@@ -1581,7 +1593,7 @@ def _latex_(self):
@cached_method
def _tab_completion(self):
"""
- Return additional tab completion entries
+ Return additional tab completion entries.
OUTPUT:
@@ -1595,10 +1607,11 @@ def _tab_completion(self):
"""
P = self.parent()
v = P.eval(r'\$SAGE.OperationsAdmittingFirstArgument(%s)' % self.name())
- v = v.replace('Tester(','').replace('Setter(','').replace(')','').replace('\n', '')
+ v = v.replace('Tester(', '').replace('Setter(', '').replace(')', '').replace('\n', '')
v = v.split(',')
- v = [ oper.split('"')[1] for oper in v ]
- v = [ oper for oper in v if all(ch in string.ascii_letters for ch in oper) ]
+ v = (oper.split('"')[1] for oper in v)
+ v = [oper for oper in v
+ if all(ch in string.ascii_letters for ch in oper)]
return sorted(set(v))
@@ -1708,13 +1721,13 @@ def gfq_gap_to_sage(x, F):
return F(0)
i1 = s.index("(")
i2 = s.index(")")
- q = eval(s[i1+1:i2].replace('^','**'))
+ q = eval(s[i1 + 1:i2].replace('^', '**'))
if not F.cardinality().is_power_of(q):
raise ValueError('%r has no subfield of size %r' % (F, q))
if s.find(')^') == -1:
e = 1
else:
- e = int(s[i2+2:])
+ e = int(s[i2 + 2:])
if F.degree() == 1:
g = F(gap.eval('Int(Z(%s))' % q))
elif F.is_conway():
@@ -1724,6 +1737,7 @@ def gfq_gap_to_sage(x, F):
raise ValueError('%r is not prime or defined by a Conway polynomial' % F)
return g**e
+
def intmod_gap_to_sage(x):
r"""
INPUT:
@@ -1827,5 +1841,5 @@ def gap_console():
if not get_display_manager().is_in_terminal():
raise RuntimeError('Can use the console only in the terminal. Try %%gap magics instead.')
cmd, _ = gap_command(use_workspace_cache=False)
- cmd += ' ' + os.path.join(SAGE_EXTCODE,'gap','console.g')
+ cmd += ' ' + os.path.join(SAGE_EXTCODE, 'gap', 'console.g')
os.system(cmd)
diff --git a/src/sage/interfaces/gap_workspace.py b/src/sage/interfaces/gap_workspace.py
index c104664143a..a2c97260077 100644
--- a/src/sage/interfaces/gap_workspace.py
+++ b/src/sage/interfaces/gap_workspace.py
@@ -17,7 +17,7 @@
import time
import hashlib
import subprocess
-from sage.env import DOT_SAGE, HOSTNAME, GAP_LIB_DIR, GAP_SHARE_DIR
+from sage.env import DOT_SAGE, HOSTNAME, GAP_ROOT_PATHS
def gap_workspace_file(system="gap", name="workspace", dir=None):
@@ -60,8 +60,12 @@ def gap_workspace_file(system="gap", name="workspace", dir=None):
if dir is None:
dir = os.path.join(DOT_SAGE, 'gap')
- data = f'{GAP_LIB_DIR}:{GAP_SHARE_DIR}'
- for path in GAP_LIB_DIR, GAP_SHARE_DIR:
+ data = f'{GAP_ROOT_PATHS}'
+ for path in GAP_ROOT_PATHS.split(";"):
+ if not path:
+ # If GAP_ROOT_PATHS begins or ends with a semicolon,
+ # we'll get one empty path.
+ continue
sysinfo = os.path.join(path, "sysinfo.gap")
if os.path.exists(sysinfo):
data += subprocess.getoutput(f'. "{sysinfo}" && echo ":$GAP_VERSION:$GAParch"')
diff --git a/src/sage/interfaces/jmoldata.py b/src/sage/interfaces/jmoldata.py
index 59a9a1e26a5..e7354e05c70 100644
--- a/src/sage/interfaces/jmoldata.py
+++ b/src/sage/interfaces/jmoldata.py
@@ -85,10 +85,6 @@ def jmolpath(self):
"""
jmolpath = os.path.join(JMOL_DIR, "JmolData.jar")
- if sys.platform == 'cygwin':
- import cygwin
- jmolpath = cygwin.cygpath(jmolpath, 'w')
-
return jmolpath
def is_jmol_available(self):
@@ -129,8 +125,6 @@ def export_image(self,
- datafile -- full path to the data file Jmol can read or
text of a script telling Jmol what to read or load.
- If it is a script and the platform is cygwin, the filenames in
- the script should be in native windows format.
- datafile_cmd -- (default ``'script'``) ``'load'`` or ``'script'``
should be ``"load"`` for a data file.
@@ -180,10 +174,6 @@ def export_image(self,
sage: archive = NamedTemporaryFile(suffix=".zip")
sage: D.export_jmol(archive.name) # needs sage.plot
sage: archive_native = archive.name
- sage: import sys
- sage: if sys.platform == 'cygwin':
- ....: import cygwin
- ....: archive_native = cygwin.cygpath(archive_native, 'w')
sage: script = f'set defaultdirectory "f{archive_native}"\n'
sage: script += 'script SCRIPT\n'
sage: with NamedTemporaryFile(suffix=".png") as testfile: # optional - java, needs sage.plot
@@ -198,12 +188,6 @@ def export_image(self,
jmolpath = self.jmolpath()
target_native = targetfile
- if sys.platform == 'cygwin':
- import cygwin
- target_native = cygwin.cygpath(target_native, 'w')
- if datafile_cmd != 'script':
- datafile = cygwin.cygpath(datafile, 'w')
-
launchscript = ""
if (datafile_cmd != 'script'):
launchscript = "load "
diff --git a/src/sage/interfaces/kenzo.py b/src/sage/interfaces/kenzo.py
index e403b04dab7..d6866117d57 100644
--- a/src/sage/interfaces/kenzo.py
+++ b/src/sage/interfaces/kenzo.py
@@ -131,11 +131,12 @@ def Sphere(n):
EXAMPLES::
- sage: from sage.interfaces.kenzo import Sphere # optional - kenzo
- sage: s2 = Sphere(2) # optional - kenzo
- sage: s2 # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import Sphere
+ sage: s2 = Sphere(2)
+ sage: s2
[K1 Simplicial-Set]
- sage: [s2.homology(i) for i in range(8)] # optional - kenzo
+ sage: [s2.homology(i) for i in range(8)]
[Z, 0, Z, 0, 0, 0, 0, 0]
"""
kenzosphere = __sphere__(n)
@@ -162,11 +163,12 @@ def MooreSpace(m, n):
EXAMPLES::
- sage: from sage.interfaces.kenzo import MooreSpace # optional - kenzo
- sage: m24 = MooreSpace(2,4) # optional - kenzo
- sage: m24 # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import MooreSpace
+ sage: m24 = MooreSpace(2,4)
+ sage: m24
[K10 Simplicial-Set]
- sage: [m24.homology(i) for i in range(8)] # optional - kenzo
+ sage: [m24.homology(i) for i in range(8)]
[Z, 0, 0, 0, C2, 0, 0, 0]
"""
kenzomoore = __moore__(m, n)
@@ -387,10 +389,11 @@ def table(self, p, i1, i2, j1, j2):
EXAMPLES::
- sage: from sage.interfaces.kenzo import Sphere # optional - kenzo
- sage: S2 = Sphere(2) # optional - kenzo
- sage: EMS = S2.em_spectral_sequence() # optional - kenzo
- sage: EMS.table(0, -2, 2, -2, 2) # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import Sphere
+ sage: S2 = Sphere(2)
+ sage: EMS = S2.em_spectral_sequence()
+ sage: EMS.table(0, -2, 2, -2, 2)
0 Z 0 0 0
0 0 0 0 0
0 0 Z 0 0
@@ -427,15 +430,16 @@ def homology(self, n):
OUTPUT:
- - An homology group.
+ - A homology group.
EXAMPLES::
- sage: from sage.interfaces.kenzo import Sphere # optional - kenzo
- sage: s2 = Sphere(2) # optional - kenzo
- sage: s2 # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import Sphere
+ sage: s2 = Sphere(2)
+ sage: s2
[K1 Simplicial-Set]
- sage: s2.homology(2) # optional - kenzo
+ sage: s2.homology(2)
Z
"""
echcm1 = __echcm__(self._kenzo)
@@ -490,15 +494,16 @@ def basis(self, dim):
EXAMPLES::
- sage: from sage.interfaces.kenzo import KChainComplex # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import KChainComplex
sage: m1 = matrix(ZZ, 3, 2, [-1, 1, 3, -4, 5, 6])
sage: m4 = matrix(ZZ, 2, 2, [1, 2, 3, 6])
sage: m5 = matrix(ZZ, 2, 3, [2, 2, 2, -1, -1, -1])
- sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1) # optional - kenzo
- sage: kenzo_chcm = KChainComplex(sage_chcm) # optional - kenzo
- sage: kenzo_chcm # optional - kenzo
+ sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1)
+ sage: kenzo_chcm = KChainComplex(sage_chcm)
+ sage: kenzo_chcm
[K... Chain-Complex]
- sage: for i in range(6): # optional - kenzo
+ sage: for i in range(6):
....: print("Basis in dimension %i: %s" % (i, kenzo_chcm.basis(i)))
Basis in dimension 0: ['G0G0', 'G0G1', 'G0G2']
Basis in dimension 1: ['G1G0', 'G1G1']
@@ -506,7 +511,6 @@ def basis(self, dim):
Basis in dimension 3: ['G3G0', 'G3G1']
Basis in dimension 4: ['G4G0', 'G4G1']
Basis in dimension 5: ['G5G0', 'G5G1', 'G5G2']
-
"""
return __basis_aux1__(self._kenzo, dim).python()
@@ -603,26 +607,27 @@ def differential(self, dim=None, comb=None):
EXAMPLES::
- sage: from sage.interfaces.kenzo import KChainComplex # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import KChainComplex
sage: m1 = matrix(ZZ, 3, 2, [-1, 1, 3, -4, 5, 6])
sage: m4 = matrix(ZZ, 2, 2, [1, 2, 3, 6])
sage: m5 = matrix(ZZ, 2, 3, [2, 2, 2, -1, -1, -1])
sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1)
- sage: kenzo_chcm = KChainComplex(sage_chcm) # optional - kenzo
- sage: kenzo_chcm # optional - kenzo
+ sage: kenzo_chcm = KChainComplex(sage_chcm)
+ sage: kenzo_chcm
[K... Chain-Complex]
- sage: kenzo_chcm.basis(4) # optional - kenzo
+ sage: kenzo_chcm.basis(4)
['G4G0', 'G4G1']
- sage: kenzo_chcm.differential(4, [1, 'G4G0']) # optional - kenzo
+ sage: kenzo_chcm.differential(4, [1, 'G4G0'])
----------------------------------------------------------------------{CMBN 3}
<1 * G3G0>
<3 * G3G1>
------------------------------------------------------------------------------
- sage: kenzo_chcm.basis(5) # optional - kenzo
+ sage: kenzo_chcm.basis(5)
['G5G0', 'G5G1', 'G5G2']
- sage: kenzo_chcm.differential(5, [1, 'G5G0', 2, 'G5G2']) # optional - kenzo
+ sage: kenzo_chcm.differential(5, [1, 'G5G0', 2, 'G5G2'])
----------------------------------------------------------------------{CMBN 4}
<6 * G4G0>
@@ -748,10 +753,11 @@ def homotopy_group(self, n):
EXAMPLES::
- sage: from sage.interfaces.kenzo import Sphere # optional - kenzo
- sage: s2 = Sphere(2) # optional - kenzo
- sage: p = s2.cartesian_product(s2) # optional - kenzo
- sage: p.homotopy_group(3) # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import Sphere
+ sage: s2 = Sphere(2)
+ sage: p = s2.cartesian_product(s2)
+ sage: p.homotopy_group(3)
Multiplicative Abelian group isomorphic to Z x Z
@@ -780,10 +786,11 @@ def em_spectral_sequence(self):
EXAMPLES::
- sage: from sage.interfaces.kenzo import Sphere # optional - kenzo
- sage: S2 = Sphere(2) # optional - kenzo
- sage: EMS = S2.em_spectral_sequence() # optional - kenzo
- sage: EMS.table(0, -2, 2, -2, 2) # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import Sphere
+ sage: S2 = Sphere(2)
+ sage: EMS = S2.em_spectral_sequence()
+ sage: EMS.table(0, -2, 2, -2, 2)
0 Z 0 0 0
0 0 0 0 0
0 0 Z 0 0
@@ -1090,15 +1097,16 @@ def KChainComplex(chain_complex):
EXAMPLES::
- sage: from sage.interfaces.kenzo import KChainComplex # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import KChainComplex
sage: m1 = matrix(ZZ, 3, 2, [-1, 1, 3, -4, 5, 6])
sage: m4 = matrix(ZZ, 2, 2, [1, 2, 3, 6])
sage: m5 = matrix(ZZ, 2, 3, [2, 2, 2, -1, -1, -1])
- sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1) # optional - kenzo
- sage: kenzo_chcm = KChainComplex(sage_chcm) # optional - kenzo
- sage: kenzo_chcm # optional - kenzo
+ sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1)
+ sage: kenzo_chcm = KChainComplex(sage_chcm)
+ sage: kenzo_chcm
[K... Chain-Complex]
- sage: kenzo_chcm.homology(5) # optional - kenzo
+ sage: kenzo_chcm.homology(5)
Z x Z
"""
d = chain_complex.differential()
@@ -1242,8 +1250,9 @@ def KFiniteSimplicialSet(sset):
EXAMPLES::
+ sage: # optional - kenzo
sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
- sage: from sage.interfaces.kenzo import KFiniteSimplicialSet # optional - kenzo
+ sage: from sage.interfaces.kenzo import KFiniteSimplicialSet
sage: s0 = AbstractSimplex(0, name='s0')
sage: s1 = AbstractSimplex(0, name='s1')
sage: s2 = AbstractSimplex(0, name='s2')
@@ -1253,15 +1262,15 @@ def KFiniteSimplicialSet(sset):
sage: s012 = AbstractSimplex(2, name='s012')
sage: Triangle = SimplicialSet({s01: (s1, s0),\
....: s02: (s2, s0), s12: (s2, s1)}, base_point = s0)
- sage: KTriangle = KFiniteSimplicialSet(Triangle) # optional - kenzo
- sage: KTriangle.homology(1) # optional - kenzo
+ sage: KTriangle = KFiniteSimplicialSet(Triangle)
+ sage: KTriangle.homology(1)
Z
- sage: KTriangle.basis(1) # optional - kenzo
+ sage: KTriangle.basis(1)
['CELL_1_0', 'CELL_1_1', 'CELL_1_2']
sage: S1 = simplicial_sets.Sphere(1)
sage: S3 = simplicial_sets.Sphere(3)
- sage: KS1vS3 = KFiniteSimplicialSet(S1.wedge(S3)) # optional - kenzo
- sage: KS1vS3.homology(3) # optional - kenzo
+ sage: KS1vS3 = KFiniteSimplicialSet(S1.wedge(S3))
+ sage: KS1vS3.homology(3)
Z
"""
from sage.topology.simplicial_set_constructions import ProductOfSimplicialSets
@@ -1389,18 +1398,19 @@ def source_complex(self):
EXAMPLES::
- sage: from sage.interfaces.kenzo import KChainComplex # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import KChainComplex
sage: m1 = matrix(ZZ, 3, 2, [-1, 1, 3, -4, 5, 6])
sage: m4 = matrix(ZZ, 2, 2, [1, 2, 3, 6])
sage: m5 = matrix(ZZ, 2, 3, [2, 2, 2, -1, -1, -1])
- sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1) # optional - kenzo
- sage: kenzo_chcm = KChainComplex(sage_chcm) # optional - kenzo
- sage: kenzo_chcm # optional - kenzo
+ sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1)
+ sage: kenzo_chcm = KChainComplex(sage_chcm)
+ sage: kenzo_chcm
[K... Chain-Complex]
- sage: differential_morphism = kenzo_chcm.differential() # optional - kenzo
- sage: differential_morphism # optional - kenzo
+ sage: differential_morphism = kenzo_chcm.differential()
+ sage: differential_morphism
[K... Morphism (degree -1): K... -> K...]
- sage: differential_morphism.source_complex() # optional - kenzo
+ sage: differential_morphism.source_complex()
[K... Chain-Complex]
"""
return KenzoChainComplex(__sorc_aux__(self._kenzo))
@@ -1415,18 +1425,19 @@ def target_complex(self):
EXAMPLES::
- sage: from sage.interfaces.kenzo import KChainComplex # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import KChainComplex
sage: m1 = matrix(ZZ, 3, 2, [-1, 1, 3, -4, 5, 6])
sage: m4 = matrix(ZZ, 2, 2, [1, 2, 3, 6])
sage: m5 = matrix(ZZ, 2, 3, [2, 2, 2, -1, -1, -1])
- sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1) # optional - kenzo
- sage: kenzo_chcm = KChainComplex(sage_chcm) # optional - kenzo
- sage: kenzo_chcm # optional - kenzo
+ sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1)
+ sage: kenzo_chcm = KChainComplex(sage_chcm)
+ sage: kenzo_chcm
[K... Chain-Complex]
- sage: differential_morphism = kenzo_chcm.differential() # optional - kenzo
- sage: differential_morphism # optional - kenzo
+ sage: differential_morphism = kenzo_chcm.differential()
+ sage: differential_morphism
[K... Morphism (degree -1): K... -> K...]
- sage: differential_morphism.target_complex() # optional - kenzo
+ sage: differential_morphism.target_complex()
[K... Chain-Complex]
"""
return KenzoChainComplex(__trgt_aux__(self._kenzo))
@@ -1441,22 +1452,23 @@ def degree(self):
EXAMPLES::
- sage: from sage.interfaces.kenzo import KChainComplex # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import KChainComplex
sage: m1 = matrix(ZZ, 3, 2, [-1, 1, 3, -4, 5, 6])
sage: m4 = matrix(ZZ, 2, 2, [1, 2, 3, 6])
sage: m5 = matrix(ZZ, 2, 3, [2, 2, 2, -1, -1, -1])
- sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1) # optional - kenzo
- sage: kenzo_chcm = KChainComplex(sage_chcm) # optional - kenzo
- sage: kenzo_chcm # optional - kenzo
+ sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree=-1)
+ sage: kenzo_chcm = KChainComplex(sage_chcm)
+ sage: kenzo_chcm
[K... Chain-Complex]
- sage: differential_morphism = kenzo_chcm.differential() # optional - kenzo
- sage: differential_morphism # optional - kenzo
+ sage: differential_morphism = kenzo_chcm.differential()
+ sage: differential_morphism
[K... Morphism (degree -1): K... -> K...]
- sage: differential_morphism.degree() # optional - kenzo
+ sage: differential_morphism.degree()
-1
- sage: differential_morphism.composite(differential_morphism).degree() # optional - kenzo
+ sage: differential_morphism.composite(differential_morphism).degree()
-2
- sage: kenzo_chcm.null_morphism().degree() # optional - kenzo
+ sage: kenzo_chcm.null_morphism().degree()
0
"""
return __degr_aux__(self._kenzo).python()
@@ -1485,51 +1497,52 @@ def evaluation(self, dim, comb):
EXAMPLES::
- sage: from sage.interfaces.kenzo import KChainComplex # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import KChainComplex
sage: m1 = matrix(ZZ, 3, 2, [-1, 1, 3, -4, 5, 6])
sage: m4 = matrix(ZZ, 2, 2, [1, 2, 3, 6])
sage: m5 = matrix(ZZ, 2, 3, [2, 2, 2, -1, -1, -1])
sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1)
- sage: kenzo_chcm = KChainComplex(sage_chcm) # optional - kenzo
- sage: kenzo_chcm # optional - kenzo
+ sage: kenzo_chcm = KChainComplex(sage_chcm)
+ sage: kenzo_chcm
[K... Chain-Complex]
- sage: differential_morphism = kenzo_chcm.differential() # optional - kenzo
- sage: differential_morphism # optional - kenzo
+ sage: differential_morphism = kenzo_chcm.differential()
+ sage: differential_morphism
[K... Morphism (degree -1): K... -> K...]
- sage: dif_squared = differential_morphism.composite(differential_morphism) # optional - kenzo
- sage: dif_squared # optional - kenzo
+ sage: dif_squared = differential_morphism.composite(differential_morphism)
+ sage: dif_squared
[K... Morphism (degree -2): K... -> K...]
- sage: kenzo_chcm.basis(5) # optional - kenzo
+ sage: kenzo_chcm.basis(5)
['G5G0', 'G5G1', 'G5G2']
- sage: kenzo_chcm.differential(5, [1, 'G5G0', 2, 'G5G2']) # optional - kenzo
+ sage: kenzo_chcm.differential(5, [1, 'G5G0', 2, 'G5G2'])
----------------------------------------------------------------------{CMBN 4}
<6 * G4G0>
<-3 * G4G1>
------------------------------------------------------------------------------
- sage: differential_morphism.evaluation(5, [1, 'G5G0', 2, 'G5G2']) # optional - kenzo
+ sage: differential_morphism.evaluation(5, [1, 'G5G0', 2, 'G5G2'])
----------------------------------------------------------------------{CMBN 4}
<6 * G4G0>
<-3 * G4G1>
------------------------------------------------------------------------------
- sage: dif_squared.evaluation(5, [1, 'G5G0', 2, 'G5G2']) # optional - kenzo
+ sage: dif_squared.evaluation(5, [1, 'G5G0', 2, 'G5G2'])
----------------------------------------------------------------------{CMBN 3}
------------------------------------------------------------------------------
- sage: idnt = kenzo_chcm.identity_morphism() # optional - kenzo
- sage: idx2 = idnt.sum(idnt) # optional - kenzo
- sage: idnt.evaluation(5, [1, 'G5G0', 2, 'G5G2']) # optional - kenzo
+ sage: idnt = kenzo_chcm.identity_morphism()
+ sage: idx2 = idnt.sum(idnt)
+ sage: idnt.evaluation(5, [1, 'G5G0', 2, 'G5G2'])
----------------------------------------------------------------------{CMBN 5}
<1 * G5G0>
<2 * G5G2>
------------------------------------------------------------------------------
- sage: idx2.evaluation(5, [1, 'G5G0', 2, 'G5G2']) # optional - kenzo
+ sage: idx2.evaluation(5, [1, 'G5G0', 2, 'G5G2'])
----------------------------------------------------------------------{CMBN 5}
<2 * G5G0>
@@ -1556,30 +1569,31 @@ def opposite(self):
EXAMPLES::
- sage: from sage.interfaces.kenzo import KChainComplex # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import KChainComplex
sage: m1 = matrix(ZZ, 3, 2, [-1, 1, 3, -4, 5, 6])
sage: m4 = matrix(ZZ, 2, 2, [1, 2, 3, 6])
sage: m5 = matrix(ZZ, 2, 3, [2, 2, 2, -1, -1, -1])
- sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1) # optional - kenzo
- sage: kenzo_chcm = KChainComplex(sage_chcm) # optional - kenzo
- sage: kenzo_chcm # optional - kenzo
+ sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1)
+ sage: kenzo_chcm = KChainComplex(sage_chcm)
+ sage: kenzo_chcm
[K... Chain-Complex]
- sage: idnt = kenzo_chcm.identity_morphism() # optional - kenzo
- sage: idnt # optional - kenzo
+ sage: idnt = kenzo_chcm.identity_morphism()
+ sage: idnt
[K... Morphism (degree 0): K... -> K...]
- sage: opps_id = idnt.opposite() # optional - kenzo
- sage: opps_id # optional - kenzo
+ sage: opps_id = idnt.opposite()
+ sage: opps_id
[K... Morphism (degree 0): K... -> K...]
- sage: kenzo_chcm.basis(4) # optional - kenzo
+ sage: kenzo_chcm.basis(4)
['G4G0', 'G4G1']
- sage: idnt.evaluation(4, [2, 'G4G0', -5, 'G4G1']) # optional - kenzo
+ sage: idnt.evaluation(4, [2, 'G4G0', -5, 'G4G1'])
----------------------------------------------------------------------{CMBN 4}
<2 * G4G0>
<-5 * G4G1>
------------------------------------------------------------------------------
- sage: opps_id.evaluation(4, [2, 'G4G0', -5, 'G4G1']) # optional - kenzo
+ sage: opps_id.evaluation(4, [2, 'G4G0', -5, 'G4G1'])
----------------------------------------------------------------------{CMBN 4}
<-2 * G4G0>
@@ -1653,36 +1667,37 @@ def sum(self, object=None):
EXAMPLES::
- sage: from sage.interfaces.kenzo import KChainComplex # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import KChainComplex
sage: m1 = matrix(ZZ, 3, 2, [-1, 1, 3, -4, 5, 6])
sage: m4 = matrix(ZZ, 2, 2, [1, 2, 3, 6])
sage: m5 = matrix(ZZ, 2, 3, [2, 2, 2, -1, -1, -1])
- sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1) # optional - kenzo
- sage: kenzo_chcm = KChainComplex(sage_chcm) # optional - kenzo
- sage: kenzo_chcm # optional - kenzo
+ sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1)
+ sage: kenzo_chcm = KChainComplex(sage_chcm)
+ sage: kenzo_chcm
[K... Chain-Complex]
- sage: idnt = kenzo_chcm.identity_morphism() # optional - kenzo
- sage: idnt # optional - kenzo
+ sage: idnt = kenzo_chcm.identity_morphism()
+ sage: idnt
[K... Morphism (degree 0): K... -> K...]
- sage: opps_id = idnt.opposite() # optional - kenzo
- sage: opps_id # optional - kenzo
+ sage: opps_id = idnt.opposite()
+ sage: opps_id
[K... Morphism (degree 0): K... -> K...]
- sage: null = kenzo_chcm.null_morphism() # optional - kenzo
- sage: null # optional - kenzo
+ sage: null = kenzo_chcm.null_morphism()
+ sage: null
[K... Morphism (degree 0): K... -> K...]
- sage: idx2 = idnt.sum(idnt) # optional - kenzo
- sage: idx5 = idx2.sum( # optional - kenzo
+ sage: idx2 = idnt.sum(idnt)
+ sage: idx5 = idx2.sum(
....: (opps_id, idnt, idnt, null, idx2.sum(idnt), opps_id))
- sage: kenzo_chcm.basis(4) # optional - kenzo
+ sage: kenzo_chcm.basis(4)
['G4G0', 'G4G1']
- sage: idx2.evaluation(4, [2, 'G4G0', -5, 'G4G1']) # optional - kenzo
+ sage: idx2.evaluation(4, [2, 'G4G0', -5, 'G4G1'])
----------------------------------------------------------------------{CMBN 4}
<4 * G4G0>
<-10 * G4G1>
------------------------------------------------------------------------------
- sage: idx5.evaluation(4, [2, 'G4G0', -5, 'G4G1']) # optional - kenzo
+ sage: idx5.evaluation(4, [2, 'G4G0', -5, 'G4G1'])
----------------------------------------------------------------------{CMBN 4}
<10 * G4G0>
@@ -1719,36 +1734,37 @@ def substract(self, object=None):
EXAMPLES::
- sage: from sage.interfaces.kenzo import KChainComplex # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import KChainComplex
sage: m1 = matrix(ZZ, 3, 2, [-1, 1, 3, -4, 5, 6])
sage: m4 = matrix(ZZ, 2, 2, [1, 2, 3, 6])
sage: m5 = matrix(ZZ, 2, 3, [2, 2, 2, -1, -1, -1])
- sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1) # optional - kenzo
- sage: kenzo_chcm = KChainComplex(sage_chcm) # optional - kenzo
- sage: kenzo_chcm # optional - kenzo
+ sage: sage_chcm = ChainComplex({1: m1, 4: m4, 5: m5}, degree = -1)
+ sage: kenzo_chcm = KChainComplex(sage_chcm)
+ sage: kenzo_chcm
[K... Chain-Complex]
- sage: idnt = kenzo_chcm.identity_morphism() # optional - kenzo
- sage: idnt # optional - kenzo
+ sage: idnt = kenzo_chcm.identity_morphism()
+ sage: idnt
[K... Morphism (degree 0): K... -> K...]
- sage: opps_id = idnt.opposite() # optional - kenzo
- sage: opps_id # optional - kenzo
+ sage: opps_id = idnt.opposite()
+ sage: opps_id
[K... Morphism (degree 0): K... -> K...]
- sage: null = kenzo_chcm.null_morphism() # optional - kenzo
- sage: null # optional - kenzo
+ sage: null = kenzo_chcm.null_morphism()
+ sage: null
[K... Morphism (degree 0): K... -> K...]
- sage: idx2 = idnt.substract(opps_id) # optional - kenzo
- sage: opps_idx2 = idx2.substract( # optional - kenzo
+ sage: idx2 = idnt.substract(opps_id)
+ sage: opps_idx2 = idx2.substract(
....: (opps_id, idnt, idnt, null, idx2.substract(opps_id)))
- sage: kenzo_chcm.basis(4) # optional - kenzo
+ sage: kenzo_chcm.basis(4)
['G4G0', 'G4G1']
- sage: idx2.evaluation(4, [2, 'G4G0', -5, 'G4G1']) # optional - kenzo
+ sage: idx2.evaluation(4, [2, 'G4G0', -5, 'G4G1'])
----------------------------------------------------------------------{CMBN 4}
<4 * G4G0>
<-10 * G4G1>
------------------------------------------------------------------------------
- sage: opps_idx2.evaluation(4, [2, 'G4G0', -5, 'G4G1']) # optional - kenzo
+ sage: opps_idx2.evaluation(4, [2, 'G4G0', -5, 'G4G1'])
----------------------------------------------------------------------{CMBN 4}
<-4 * G4G0>
@@ -1954,16 +1970,16 @@ def KChainComplexMorphism(morphism):
EXAMPLES::
- sage: from sage.interfaces.kenzo import KChainComplexMorphism # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import KChainComplexMorphism
sage: C = ChainComplex({0: identity_matrix(ZZ, 1)})
sage: D = ChainComplex({0: zero_matrix(ZZ, 1), 1: zero_matrix(ZZ, 1)})
sage: f = Hom(C,D)({0: identity_matrix(ZZ, 1), 1: zero_matrix(ZZ, 1)})
- sage: g = KChainComplexMorphism(f) # optional - kenzo
- sage: g # optional - kenzo
+ sage: g = KChainComplexMorphism(f); g
[K... Morphism (degree 0): K... -> K...]
- sage: g.source_complex() # optional - kenzo
+ sage: g.source_complex()
[K... Chain-Complex]
- sage: g.target_complex() # optional - kenzo
+ sage: g.target_complex()
[K... Chain-Complex]
"""
source = KChainComplex(morphism.domain())
@@ -2017,21 +2033,22 @@ def BicomplexSpectralSequence(l):
EXAMPLES::
- sage: from sage.interfaces.kenzo import BicomplexSpectralSequence # optional - kenzo
+ sage: # optional - kenzo
+ sage: from sage.interfaces.kenzo import BicomplexSpectralSequence
sage: C1 = ChainComplex({1: matrix(ZZ, 0, 2, [])}, degree_of_differential=-1)
sage: C2 = ChainComplex({1: matrix(ZZ, 1, 2, [1, 0])},degree_of_differential=-1)
sage: C3 = ChainComplex({0: matrix(ZZ, 0,2 , [])},degree_of_differential=-1)
sage: M1 = Hom(C2,C1)({1: matrix(ZZ, 2, 2, [2, 0, 0, 2])})
sage: M2 = Hom(C3,C2)({0: matrix(ZZ, 1, 2, [2, 0])})
sage: l = [M1, M2]
- sage: E = BicomplexSpectralSequence(l) # optional - kenzo
- sage: E.group(2,0,1) # optional - kenzo
+ sage: E = BicomplexSpectralSequence(l)
+ sage: E.group(2,0,1)
Additive abelian group isomorphic to Z/2 + Z
- sage: E.table(3,0,2,0,2) # optional - kenzo
+ sage: E.table(3,0,2,0,2)
0 0 0
Z/2 + Z/4 0 0
0 0 Z
- sage: E.matrix(2,2,0) # optional - kenzo
+ sage: E.matrix(2,2,0)
[ 0 0]
[-4 0]
"""
diff --git a/src/sage/interfaces/macaulay2.py b/src/sage/interfaces/macaulay2.py
index 9b11f02a85f..fde9556858d 100644
--- a/src/sage/interfaces/macaulay2.py
+++ b/src/sage/interfaces/macaulay2.py
@@ -239,7 +239,7 @@ def __init__(self, maxread=None, script_subdirectory=None,
def __reduce__(self):
"""
- Used in serializing an Macaulay2 interface.
+ Used in serializing a Macaulay2 interface.
EXAMPLES::
diff --git a/src/sage/interfaces/matlab.py b/src/sage/interfaces/matlab.py
index 74354b77412..8ecfc3447cd 100644
--- a/src/sage/interfaces/matlab.py
+++ b/src/sage/interfaces/matlab.py
@@ -300,11 +300,11 @@ def chdir(self, directory):
def sage2matlab_matrix_string(self, A):
"""
- Return an matlab matrix from a Sage matrix.
+ Return a matlab matrix from a Sage matrix.
INPUT: A Sage matrix with entries in the rationals or reals.
- OUTPUT: A string that evaluates to an Matlab matrix.
+ OUTPUT: A string that evaluates to a Matlab matrix.
EXAMPLES::
diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py
index 7efc51038ea..01ae082cca6 100644
--- a/src/sage/interfaces/qepcad.py
+++ b/src/sage/interfaces/qepcad.py
@@ -833,7 +833,7 @@ def __init__(self, formula,
x^2 + x*y + 3*x*z + 2*y*z + 2*z^2 - x - z < 0, \
-2*x + 1 < 0, -x*y - x*z - 2*y*z - 2*z^2 + z < 0, \
x + 3*y + 3*z - 1 < 0]
- sage: qepcad(conds, memcells=2000000) # optional - qepcad
+ sage: qepcad(conds, memcells=3000000) # optional - qepcad
2 x - 1 > 0 /\ z > 0 /\ z - y < 0 /\ 3 z + 3 y + x - 1 < 0
"""
self._cell_cache = {}
diff --git a/src/sage/interfaces/scilab.py b/src/sage/interfaces/scilab.py
index 3229fd3d82c..a275306dbea 100644
--- a/src/sage/interfaces/scilab.py
+++ b/src/sage/interfaces/scilab.py
@@ -249,11 +249,12 @@ def set_seed(self, seed=None):
EXAMPLES::
- sage: from sage.interfaces.scilab import Scilab # optional - scilab
- sage: s = Scilab() # optional - scilab
- sage: s.set_seed(1) # optional - scilab
+ sage: # optional - scilab
+ sage: from sage.interfaces.scilab import Scilab
+ sage: s = Scilab()
+ sage: s.set_seed(1)
1
- sage: [s.rand() for i in range(5)] # optional - scilab
+ sage: [s.rand() for i in range(5)]
[
0.6040239,
@@ -408,7 +409,7 @@ def sage2scilab_matrix_string(self, A):
A Sage matrix with entries in the rationals or reals.
OUTPUT:
- A string that evaluates to an Scilab matrix.
+ A string that evaluates to a Scilab matrix.
EXAMPLES::
@@ -535,7 +536,7 @@ def scilab_console():
EXAMPLES::
- sage: from sage.interfaces.scilab import scilab_console # optional - scilab
+ sage: from sage.interfaces.scilab import scilab_console # optional - scilab
sage: scilab_console() # optional - scilab; not tested
___________________________________________
scilab-5.0.3
@@ -569,7 +570,7 @@ def scilab_version():
EXAMPLES::
- sage: from sage.interfaces.scilab import scilab_version # optional - scilab
+ sage: from sage.interfaces.scilab import scilab_version # optional - scilab
sage: scilab_version() # optional - scilab
'scilab-...'
"""
diff --git a/src/sage/knots/knotinfo.py b/src/sage/knots/knotinfo.py
index a2f48a996ed..0ef601e124c 100644
--- a/src/sage/knots/knotinfo.py
+++ b/src/sage/knots/knotinfo.py
@@ -97,26 +97,26 @@
If you have `SnapPy `__ installed inside
-Sage you can obtain an instance of :class:`~spherogram.links.links_base.Link`,
+Sage, you can obtain an instance of :class:`~spherogram.links.links_base.Link`,
too::
+ sage: # optional - snappy
sage: L6 = KnotInfo.L6a1_0
- sage: l6s = L6.link(snappy=True); l6s # optional - snappy
+ sage: l6s = L6.link(snappy=True); l6s
Plink failed to import tkinter.
-
- sage: type(l6s) # optional - snappy
+ sage: type(l6s)
sage: l6 = L6.link()
- sage: l6 == l6s.sage_link() # optional - snappy
+ sage: l6 == l6s.sage_link()
True
- sage: L6.link(L6.items.name, snappy=True) # optional - snappy
+ sage: L6.link(L6.items.name, snappy=True)
- sage: l6sn = _ # optional - snappy
- sage: l6s == l6sn # optional - snappy
+ sage: l6sn = _
+ sage: l6s == l6sn
False
- sage: l6m = l6.mirror_image() # optional - snappy
- sage: l6sn.sage_link().is_isotopic(l6m) # optional - snappy
+ sage: l6m = l6.mirror_image()
+ sage: l6sn.sage_link().is_isotopic(l6m)
True
But observe that the name conversion to SnapPy does not distinguish orientation
@@ -238,14 +238,16 @@
from enum import Enum
from sage.misc.cachefunc import cached_method
+from sage.misc.lazy_import import lazy_import
from sage.misc.sage_eval import sage_eval
from sage.structure.sage_object import SageObject
from sage.structure.unique_representation import UniqueRepresentation
from sage.rings.integer_ring import ZZ
-from sage.groups.braid import BraidGroup
from sage.knots.knot import Knots
from sage.databases.knotinfo_db import KnotInfoColumns, db
+lazy_import('sage.groups.braid', 'BraidGroup')
+
def eval_knotinfo(string, locals={}, to_tuple=True):
r"""
@@ -694,8 +696,7 @@ def braid_length(self):
@cached_method
def braid(self):
r"""
- Return the braid notation of self as an instance of :class:`~sage.groups.braid.Braid`.
-
+ Return the braid notation of ``self`` as an instance of :class:`~sage.groups.braid.Braid`.
EXAMPLES::
diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py
index f110091f20b..eb3d51a883d 100644
--- a/src/sage/knots/link.py
+++ b/src/sage/knots/link.py
@@ -610,10 +610,17 @@ def __ne__(self, other):
"""
return not self.__eq__(other)
- def braid(self):
+ def braid(self, remove_loops=False):
r"""
Return a braid representation of ``self``.
+ INPUT:
+
+ - ``remove_loops`` -- boolean (default: ``False``). If set to ``True``
+ loops will be removed first. This can reduce the number of strands
+ needed for an ambient isotopic braid closure. However, this can lead
+ to a loss of the regular isotopy.
+
OUTPUT: an element in the braid group
.. WARNING::
@@ -634,6 +641,14 @@ def braid(self):
sage: L.braid()
(s0*s1^-1)^2*s1^-1
+ using ``remove_loops=True``::
+
+ sage: L = Link([[2, 7, 1, 1], [7, 3, 9, 2], [4, 11, 3, 9], [11, 5, 5, 4]])
+ sage: L.braid()
+ s0*s1^-1*s2*s3^-1
+ sage: L.braid(remove_loops=True)
+ 1
+
TESTS::
sage: L = Link([])
@@ -648,7 +663,20 @@ def braid(self):
sage: A = Link([[[1, 2, -2, -1, -3, -4, 4, 3]], [1, 1, 1, 1]])
sage: A.braid()
s0*s1*s2*s3
+
+ Check that :issue:`36884` is solved::
+
+ sage: L = Link([[1, 7, 2, 6], [3, 1, 4, 8], [5, 5, 6, 4], [7, 3, 8, 2]])
+ sage: L.braid()
+ s0^3*s1*s0*s1^-1
+ sage: L.braid(remove_loops=True)
+ s^3
"""
+ if remove_loops:
+ L = self.remove_loops()
+ if L != self:
+ return L.braid(remove_loops=remove_loops)
+
if self._braid is not None:
return self._braid
@@ -657,8 +685,8 @@ def braid(self):
if len(comp) > 1:
L1 = Link(comp[0])
L2 = Link(flatten(comp[1:], max_level=1))
- b1 = L1.braid()
- b2 = L2.braid()
+ b1 = L1.braid(remove_loops=remove_loops)
+ b2 = L2.braid(remove_loops=remove_loops)
n1 = b1.parent().strands()
n2 = b2.parent().strands()
t1 = list(b1.Tietze())
@@ -667,13 +695,26 @@ def braid(self):
self._braid = B(t1 + t2)
return self._braid
- # look for possible Vogel moves, perform them and call recursively to the modified link
pd_code = self.pd_code()
if not pd_code:
B = BraidGroup(2)
self._braid = B.one()
return self._braid
+ # look for possible Vogel moves, perform them and call recursively to the modified link
+ def idx(cross, edge):
+ r"""
+ Return the index of an edge in a crossing taking loops into account.
+ A loop appears as an edge which occurs twice in the crossing.
+ In all cases the second occurrence is the correct one needed in
+ the Vogel algorithm (see :issue:`36884`).
+ """
+ i = cross.index(edge)
+ if cross.count(edge) > 1:
+ return cross.index(edge, i+1)
+ else:
+ return i
+
seifert_circles = self.seifert_circles()
newedge = max(flatten(pd_code)) + 1
for region in self.regions():
@@ -702,12 +743,12 @@ def braid(self):
# C1 C2 existing crossings
# -------------------------------------------------
C1 = newPD[newPD.index(heads[a])]
- C1[C1.index(a)] = newedge + 1
+ C1[idx(C1, a)] = newedge + 1
C2 = newPD[newPD.index(tails[b])]
- C2[C2.index(b)] = newedge + 2
+ C2[idx(C2, b)] = newedge + 2
newPD.append([newedge + 3, newedge, b, a]) # D
newPD.append([newedge + 2, newedge, newedge + 3, newedge + 1]) # E
- self._braid = Link(newPD).braid()
+ self._braid = Link(newPD).braid(remove_loops=remove_loops)
return self._braid
else:
# -------------------------------------------------
@@ -723,12 +764,12 @@ def braid(self):
# / \
# -------------------------------------------------
C1 = newPD[newPD.index(heads[-a])]
- C1[C1.index(-a)] = newedge + 1
+ C1[idx(C1, -a)] = newedge + 1
C2 = newPD[newPD.index(tails[-b])]
- C2[C2.index(-b)] = newedge + 2
+ C2[idx(C2, -b)] = newedge + 2
newPD.append([newedge + 2, newedge + 1, newedge + 3, newedge]) # D
newPD.append([newedge + 3, -a, -b, newedge]) # E
- self._braid = Link(newPD).braid()
+ self._braid = Link(newPD).braid(remove_loops=remove_loops)
return self._braid
# We are in the case where no Vogel moves are necessary.
@@ -2362,6 +2403,50 @@ def regions(self):
regions.append(region)
return regions
+ def remove_loops(self):
+ r"""
+ Return an ambient isotopic link in which all loops are removed.
+
+ EXAMPLES::
+
+ sage: b = BraidGroup(4)((3, 2, -1, -1))
+ sage: L = Link(b)
+ sage: L.remove_loops()
+ Link with 2 components represented by 2 crossings
+ sage: K4 = Link([[1, 7, 2, 6], [3, 1, 4, 8], [5, 5, 6, 4], [7, 3, 8, 2]])
+ sage: K3 = K4.remove_loops()
+ sage: K3.pd_code()
+ [[1, 7, 2, 4], [3, 1, 4, 8], [7, 3, 8, 2]]
+ sage: U = Link([[1, 2, 2, 1]])
+ sage: U.remove_loops()
+ Link with 1 component represented by 0 crossings
+ """
+ pd = self.pd_code()
+ new_pd = []
+ loop_crossings = []
+ for cr in pd:
+ if len(set(cr)) == 4:
+ new_pd.append(list(cr))
+ else:
+ loop_crossings.append(cr)
+ if not loop_crossings:
+ return self
+ if not new_pd:
+ # trivial knot
+ return type(self)([])
+ new_edges = flatten(new_pd)
+ for cr in loop_crossings:
+ rem = set([e for e in cr if e in new_edges])
+ if len(rem) == 2:
+ # put remaining edges together
+ a, b = sorted(rem)
+ for ncr in new_pd:
+ if b in ncr:
+ ncr[ncr.index(b)] = a
+ break
+ res = type(self)(new_pd)
+ return res.remove_loops()
+
@cached_method
def mirror_image(self):
r"""
diff --git a/src/sage/libs/coxeter3/coxeter.pyx b/src/sage/libs/coxeter3/coxeter.pyx
index 83cd1dccaee..0ef308c7aee 100644
--- a/src/sage/libs/coxeter3/coxeter.pyx
+++ b/src/sage/libs/coxeter3/coxeter.pyx
@@ -1,6 +1,7 @@
# distutils: language = c++
# distutils: libraries = coxeter3
# sage_setup: distribution = sagemath-coxeter3
+# sage.doctest: optional - coxeter3
"""
Low level part of the interface to Fokko Ducloux's Coxeter 3 library
@@ -35,10 +36,10 @@ cdef class String:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import String # optional - coxeter3
- sage: s = String("hello"); s # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import String
+ sage: s = String("hello"); s
hello
- sage: del s # optional - coxeter3
+ sage: del s
"""
self.x = c_String(str_to_bytes(s))
@@ -46,9 +47,9 @@ cdef class String:
"""
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import String # optional - coxeter3
- sage: s = String('Hi') # optional - coxeter3
- sage: s # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import String
+ sage: s = String('Hi')
+ sage: s
Hi
"""
return bytes_to_str(self.x.ptr())
@@ -62,9 +63,9 @@ cdef class String:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import String # optional - coxeter3
- sage: s = String('hello') # optional - coxeter3
- sage: hash(s) == hash('hello') # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import String
+ sage: s = String('hello')
+ sage: hash(s) == hash('hello')
True
"""
return hash(repr(self))
@@ -73,17 +74,17 @@ cdef class String:
"""
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import String # optional - coxeter3
- sage: ta1 = String('A') # optional - coxeter3
- sage: ta2 = String('A') # optional - coxeter3
- sage: tb = String('b') # optional - coxeter3
- sage: ta1 == ta2 # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import String
+ sage: ta1 = String('A')
+ sage: ta2 = String('A')
+ sage: tb = String('b')
+ sage: ta1 == ta2
True
- sage: tb != ta1 # optional - coxeter3
+ sage: tb != ta1
True
- sage: all([ta1 < tb, ta1 <= tb, ta1 <= ta1]) # optional - coxeter3
+ sage: all([ta1 < tb, ta1 <= tb, ta1 <= ta1])
True
- sage: all([tb > ta1, tb >= ta1, tb >= tb]) # optional - coxeter3
+ sage: all([tb > ta1, tb >= ta1, tb >= tb])
True
"""
if type(other) is not type(self):
@@ -113,9 +114,9 @@ cdef class String:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import String # optional - coxeter3
- sage: s = String('Hi') # optional - coxeter3
- sage: len(s) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import String
+ sage: s = String('Hi')
+ sage: len(s)
2
"""
return self.x.length()
@@ -124,9 +125,9 @@ cdef class String:
"""
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import String # optional - coxeter3
- sage: s = String('Hi') # optional - coxeter3
- sage: TestSuite(s).run() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import String
+ sage: s = String('Hi')
+ sage: TestSuite(s).run()
"""
return (String, (repr(self),) )
@@ -138,10 +139,10 @@ cdef class Type:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import Type # optional - coxeter3
- sage: t = Type('A'); t # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import Type
+ sage: t = Type('A'); t
A
- sage: del t # optional - coxeter3
+ sage: del t
"""
self.x = c_Type(str_to_bytes(s))
@@ -149,8 +150,8 @@ cdef class Type:
"""
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import Type # optional - coxeter3
- sage: t = Type('A'); t # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import Type
+ sage: t = Type('A'); t
A
"""
return bytes_to_str(self.x.name().ptr())
@@ -159,9 +160,9 @@ cdef class Type:
"""
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import Type # optional - coxeter3
- sage: t = Type('A') # optional - coxeter3
- sage: t.name() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import Type
+ sage: t = Type('A')
+ sage: t.name()
A
"""
return String(bytes_to_str(self.x.name().ptr()))
@@ -175,12 +176,12 @@ cdef class Type:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import Type # optional - coxeter3
- sage: a = Type('A') # optional - coxeter3
- sage: b = Type('B') # optional - coxeter3
- sage: hash(a) == hash(b) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import Type
+ sage: a = Type('A')
+ sage: b = Type('B')
+ sage: hash(a) == hash(b)
False
- sage: d = {a: 1, b: 2} # optional - coxeter3
+ sage: d = {a: 1, b: 2}
"""
return hash(('Type', self.name()))
@@ -188,17 +189,17 @@ cdef class Type:
"""
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import Type # optional - coxeter3
- sage: ta1 = Type('A') # optional - coxeter3
- sage: ta2 = Type('A') # optional - coxeter3
- sage: tb = Type('b') # optional - coxeter3
- sage: ta1 == ta2 # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import Type
+ sage: ta1 = Type('A')
+ sage: ta2 = Type('A')
+ sage: tb = Type('b')
+ sage: ta1 == ta2
True
- sage: tb != ta1 # optional - coxeter3
+ sage: tb != ta1
True
- sage: all([ta1 < tb, ta1 <= tb, ta1 <= ta1]) # optional - coxeter3
+ sage: all([ta1 < tb, ta1 <= tb, ta1 <= ta1])
True
- sage: all([tb > ta1, tb >= ta1, tb >= tb]) # optional - coxeter3
+ sage: all([tb > ta1, tb >= ta1, tb >= tb])
True
"""
if type(other) is not type(self):
@@ -226,25 +227,26 @@ cdef class Type:
"""
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import Type # optional - coxeter3
- sage: t = Type('A') # optional - coxeter3
- sage: TestSuite(t).run() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import Type
+ sage: t = Type('A')
+ sage: TestSuite(t).run()
"""
return (Type, (repr(self), ))
+
cdef class CoxGroup(SageObject):
def __cinit__(self, cartan_type):
"""
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]); W # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5]); W
Coxeter group of type A and rank 5
Coxeter 3 segfault's on the trivial Coxeter group; so we catch
this and raise a not implemented error::
- sage: W = CoxGroup(['A', 0]); W # optional - coxeter3
+ sage: W = CoxGroup(['A', 0]); W
Traceback (most recent call last):
...
NotImplementedError: Coxeter group of type ['A',0] using Coxeter 3 not yet implemented
@@ -252,8 +254,8 @@ cdef class CoxGroup(SageObject):
Successfully initializes from a relabeled Cartan type::
sage: ctype = CartanType(['B', 3]).relabel({1: 3, 2: 2, 3: 1})
- sage: W = CoxGroup(ctype) # optional - coxeter3
- sage: CoxeterMatrix(W.coxeter_matrix(), ctype.index_set()) == CoxeterMatrix(ctype) # optional - coxeter3
+ sage: W = CoxGroup(ctype)
+ sage: CoxeterMatrix(W.coxeter_matrix(), ctype.index_set()) == CoxeterMatrix(ctype)
True
"""
from sage.combinat.root_system.cartan_type import CartanType
@@ -303,9 +305,9 @@ cdef class CoxGroup(SageObject):
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: W._ordering_from_cartan_type(CartanType(['A',5])) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5])
+ sage: W._ordering_from_cartan_type(CartanType(['A',5]))
[1, 2, 3, 4, 5]
"""
from sage.arith.srange import srange
@@ -340,9 +342,9 @@ cdef class CoxGroup(SageObject):
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: A4 = CoxGroup(['A', 4]) # optional - coxeter3
- sage: d = {A4: True} # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: A4 = CoxGroup(['A', 4])
+ sage: d = {A4: True}
"""
return hash((self.__class__.__name__, self.type(), self.rank()))
@@ -350,21 +352,21 @@ cdef class CoxGroup(SageObject):
"""
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: A4 = CoxGroup(['A', 4]) # optional - coxeter3
- sage: A5 = CoxGroup(['A', 5]) # optional - coxeter3
- sage: B4 = CoxGroup(['B', 4]) # optional - coxeter3
- sage: A4 == A4 # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: A4 = CoxGroup(['A', 4])
+ sage: A5 = CoxGroup(['A', 5])
+ sage: B4 = CoxGroup(['B', 4])
+ sage: A4 == A4
True
- sage: A4 != B4 # optional - coxeter3
+ sage: A4 != B4
True
- sage: A4 < B4 # optional - coxeter3
+ sage: A4 < B4
True
- sage: A5 > A4 # optional - coxeter3
+ sage: A5 > A4
True
- sage: A4 >= A4 # optional - coxeter3
+ sage: A4 >= A4
True
- sage: B4 >= A5 # optional - coxeter3
+ sage: B4 >= A5
True
"""
if type(other) is not type(self):
@@ -394,9 +396,9 @@ cdef class CoxGroup(SageObject):
"""
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: TestSuite((W)).run() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5])
+ sage: TestSuite((W)).run()
"""
return (CoxGroup, (self.cartan_type,))
@@ -406,9 +408,9 @@ cdef class CoxGroup(SageObject):
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: del W # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5])
+ sage: del W
"""
del self.x
@@ -418,8 +420,8 @@ cdef class CoxGroup(SageObject):
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]); W # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5]); W
Coxeter group of type A and rank 5
"""
return "Coxeter group of type %s and rank %s"%(self.type(), self.rank())
@@ -428,9 +430,9 @@ cdef class CoxGroup(SageObject):
"""
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 2]) # optional - coxeter3
- sage: list(iter(W)) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 2])
+ sage: list(iter(W))
[[], [1], [2], [1, 2], [2, 1], [1, 2, 1]]
"""
return CoxGroupIterator(self)
@@ -441,9 +443,9 @@ cdef class CoxGroup(SageObject):
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 2]) # optional - coxeter3
- sage: W.bruhat_interval([], [1,2]) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 2])
+ sage: W.bruhat_interval([], [1,2])
[[], [1], [2], [1, 2]]
"""
cdef CoxGroupElement ww = CoxGroupElement(self, w)
@@ -469,9 +471,9 @@ cdef class CoxGroup(SageObject):
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: W.orderings() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5])
+ sage: W.orderings()
({1: 1, 2: 2, 3: 3, 4: 4, 5: 5}, {1: 1, 2: 2, 3: 3, 4: 4, 5: 5})
"""
return self.in_ordering, self.out_ordering
@@ -484,9 +486,9 @@ cdef class CoxGroup(SageObject):
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: W.type() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5])
+ sage: W.type()
A
"""
return Type(bytes_to_str(self.x.type().name().ptr()))
@@ -497,9 +499,9 @@ cdef class CoxGroup(SageObject):
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: W.rank() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5])
+ sage: W.rank()
5
"""
return self.x.rank()
@@ -510,12 +512,12 @@ cdef class CoxGroup(SageObject):
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: W.order() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5])
+ sage: W.order()
720
- sage: W = CoxGroup(['A', 3, 1]) # optional - coxeter3
- sage: W.order() # optional - coxeter3
+ sage: W = CoxGroup(['A', 3, 1])
+ sage: W.order()
+Infinity
"""
if self.is_finite():
@@ -530,12 +532,12 @@ cdef class CoxGroup(SageObject):
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: W.is_finite() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5])
+ sage: W.is_finite()
True
- sage: W = CoxGroup(['A', 3, 1]) # optional - coxeter3
- sage: W.is_finite() # optional - coxeter3
+ sage: W = CoxGroup(['A', 3, 1])
+ sage: W.is_finite()
False
"""
return isFiniteType(self.x)
@@ -548,11 +550,11 @@ cdef class CoxGroup(SageObject):
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 2]) # optional - coxeter3
- sage: W.full_context() # optional - coxeter3
- sage: W = CoxGroup(['A', 2,1]) # optional - coxeter3
- sage: W.full_context() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 2])
+ sage: W.full_context()
+ sage: W = CoxGroup(['A', 2,1])
+ sage: W.full_context()
Traceback (most recent call last):
...
TypeError: group needs to be finite
@@ -563,20 +565,19 @@ cdef class CoxGroup(SageObject):
if not fcoxgroup.isFullContext():
fcoxgroup.fullContext()
-
def long_element(self):
"""
Return the longest word in a finite Coxeter group.
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: W.long_element() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5])
+ sage: W.long_element()
[1, 2, 1, 3, 2, 1, 4, 3, 2, 1, 5, 4, 3, 2, 1]
- sage: W = CoxGroup(['A', 3, 1]) # optional - coxeter3
- sage: W.long_element() # optional - coxeter3
+ sage: W = CoxGroup(['A', 3, 1])
+ sage: W.long_element()
Traceback (most recent call last):
...
TypeError: group needs to be finite
@@ -601,10 +602,10 @@ cdef class CoxGroup(SageObject):
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: w = [1,1,3,5,4,5,4] # optional - coxeter3
- sage: W.__call__(w) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5])
+ sage: w = [1,1,3,5,4,5,4]
+ sage: W.__call__(w)
[3, 4, 5]
"""
return CoxGroupElement(self, w).reduced()
@@ -615,9 +616,9 @@ cdef class CoxGroup(SageObject):
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: W.coxeter_matrix() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5])
+ sage: W.coxeter_matrix()
[1 3 2 2 2]
[3 1 3 2 2]
[2 3 1 3 2]
@@ -649,11 +650,11 @@ cdef class CoxGroup(SageObject):
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup# optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: W.coxeter_graph() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5])
+ sage: W.coxeter_graph()
Graph on 5 vertices
- sage: W.coxeter_graph().edges(sort=True) # optional - coxeter3
+ sage: W.coxeter_graph().edges(sort=True)
[(1, 2, None), (2, 3, None), (3, 4, None), (4, 5, None)]
"""
from sage.graphs.graph import Graph
@@ -669,26 +670,25 @@ cdef class CoxGroup(SageObject):
return g
-
cdef class CoxGroupElement:
def __init__(self, CoxGroup group, w, normal_form=True):
"""
TESTS::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupElement # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: w = CoxGroupElement(W, [2,1,2,1,1], normal_form=False); w # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupElement
+ sage: W = CoxGroup(['A', 5])
+ sage: w = CoxGroupElement(W, [2,1,2,1,1], normal_form=False); w
[2, 1, 2, 1, 1]
- sage: w = CoxGroupElement(W, [1,1,4,5,4], normal_form=False); w # optional - coxeter3
+ sage: w = CoxGroupElement(W, [1,1,4,5,4], normal_form=False); w
[1, 1, 4, 5, 4]
- sage: w = CoxGroupElement(W, [1,1,4,5,4]); w # optional - coxeter3
+ sage: w = CoxGroupElement(W, [1,1,4,5,4]); w
[4, 5, 4]
- sage: W = CoxGroup(['A', 4]) # optional - coxeter3
- sage: CoxGroupElement(W, [1,2,3,2,3]) # optional - coxeter3
+ sage: W = CoxGroup(['A', 4])
+ sage: CoxGroupElement(W, [1,2,3,2,3])
[1, 3, 2]
- sage: W = CoxGroup(['A', 4]) # optional - coxeter3
- sage: w = CoxGroupElement(W, [1,2,3,2,3]) # optional - coxeter3
- sage: del w # optional - coxeter3
+ sage: W = CoxGroup(['A', 4])
+ sage: w = CoxGroupElement(W, [1,2,3,2,3])
+ sage: del w
"""
self.group = (group).x
self._parent_group = group
@@ -705,10 +705,10 @@ cdef class CoxGroupElement:
TESTS::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupElement # optional - coxeter3
- sage: W = CoxGroup(['A', 4]) # optional - coxeter3
- sage: w = CoxGroupElement(W, [1,2,3,2,3]) # optional - coxeter3
- sage: w._coxnumber() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupElement
+ sage: W = CoxGroup(['A', 4])
+ sage: w = CoxGroupElement(W, [1,2,3,2,3])
+ sage: w._coxnumber()
7
"""
return int(self.group.extendContext(self.word))
@@ -717,10 +717,10 @@ cdef class CoxGroupElement:
"""
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A',5]) # optional - coxeter3
- sage: w = W([1,2,3]) # optional - coxeter3
- sage: TestSuite(w).run() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A',5])
+ sage: w = W([1,2,3])
+ sage: TestSuite(w).run()
"""
return (CoxGroupElement, (self._parent_group, list(self)))
@@ -730,11 +730,10 @@ cdef class CoxGroupElement:
EXAMPLES::
-
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A',5]) # optional - coxeter3
- sage: w = W([1,2,3]) # optional - coxeter3
- sage: ~w # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A',5])
+ sage: w = W([1,2,3])
+ sage: ~w
[3, 2, 1]
"""
return CoxGroupElement(self._parent_group, reversed(self))
@@ -747,10 +746,10 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A',5]) # optional - coxeter3
- sage: w = W([1,2,3]) # optional - coxeter3
- sage: w.parent_group() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A',5])
+ sage: w = W([1,2,3])
+ sage: w.parent_group()
Coxeter group of type A and rank 5
"""
@@ -762,20 +761,20 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A',5]) # optional - coxeter3
- sage: w = W([1,2,3]) # optional - coxeter3
- sage: w[0] # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A',5])
+ sage: w = W([1,2,3])
+ sage: w[0]
1
- sage: w[2] # optional - coxeter3
+ sage: w[2]
3
- sage: w[:-2] # optional - coxeter3
+ sage: w[:-2]
[1]
- sage: w[-2:] # optional - coxeter3
+ sage: w[-2:]
[2, 3]
- sage: w[3:0:-1] # optional - coxeter3
+ sage: w[3:0:-1]
[3, 2]
- sage: w[4] # optional - coxeter3
+ sage: w[4]
Traceback (most recent call last):
...
IndexError: The index (4) is out of range.
@@ -796,9 +795,9 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A',5]) # optional - coxeter3
- sage: w = W([1,2,3]); w # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A',5])
+ sage: w = W([1,2,3]); w
[1, 2, 3]
"""
@@ -813,11 +812,11 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: w = W([1,2,3]) # optional - coxeter3
- sage: v = W([2,3,4]) # optional - coxeter3
- sage: hash(w) == hash(v) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A', 5])
+ sage: w = W([1,2,3])
+ sage: v = W([2,3,4])
+ sage: hash(w) == hash(v)
False
"""
return hash((self.__class__.__name__, self.parent_group(), tuple(self)))
@@ -826,23 +825,23 @@ cdef class CoxGroupElement:
"""
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: V = CoxGroup(['A', 6]) # optional - coxeter3
- sage: w1 = W([1,2,3]) # optional - coxeter3
- sage: w2 = W([2,3,4]) # optional - coxeter3
- sage: v1 = V([1,2,3]) # optional - coxeter3
- sage: w1 == w1 # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A', 5])
+ sage: V = CoxGroup(['A', 6])
+ sage: w1 = W([1,2,3])
+ sage: w2 = W([2,3,4])
+ sage: v1 = V([1,2,3])
+ sage: w1 == w1
True
- sage: w1 != w2 # optional - coxeter3
+ sage: w1 != w2
True
- sage: all([w1 < w2, w1 <= w2, w1 <= w1]) # optional - coxeter3
+ sage: all([w1 < w2, w1 <= w2, w1 <= w1])
True
- sage: all([w2 > w1, w2 >= w1, w2 >= w2]) # optional - coxeter3
+ sage: all([w2 > w1, w2 >= w1, w2 >= w2])
True
- sage: w1 == v1 # optional - coxeter3
+ sage: w1 == v1
False
- sage: w1 != v1 # optional - coxeter3
+ sage: w1 != v1
True
"""
if type(other) is not type(self):
@@ -874,10 +873,10 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A',5]) # optional - coxeter3
- sage: w = W([1,2,3]) # optional - coxeter3
- sage: [a for a in w] # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A',5])
+ sage: w = W([1,2,3])
+ sage: [a for a in w]
[1, 2, 3]
"""
return (self[i] for i in range(len(self)))
@@ -888,10 +887,10 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A',5]) # optional - coxeter3
- sage: w = W([1,2,3]) # optional - coxeter3
- sage: len(w) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A',5])
+ sage: w = W([1,2,3])
+ sage: len(w)
3
"""
return self.word.length()
@@ -902,10 +901,10 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A',5]) # optional - coxeter3
- sage: w = W([1,2,1]) # optional - coxeter3
- sage: w.left_descents() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A',5])
+ sage: w = W([1,2,1])
+ sage: w.left_descents()
[1, 2]
"""
return LFlags_to_list(self._parent_group, self.group.ldescent(self.word))
@@ -916,10 +915,10 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A',5]) # optional - coxeter3
- sage: w = W([1,2,1]) # optional - coxeter3
- sage: w.right_descents() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A',5])
+ sage: w = W([1,2,1])
+ sage: w.right_descents()
[1, 2]
"""
return LFlags_to_list(self._parent_group, self.group.rdescent(self.word))
@@ -930,15 +929,15 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A',5]) # optional - coxeter3
- sage: w = W([1,2,3,4,5,4]) # optional - coxeter3
- sage: v = W([1,2,4,5,4]) # optional - coxeter3
- sage: v.bruhat_le(w) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A',5])
+ sage: w = W([1,2,3,4,5,4])
+ sage: v = W([1,2,4,5,4])
+ sage: v.bruhat_le(w)
True
- sage: w.bruhat_le(w) # optional - coxeter3
+ sage: w.bruhat_le(w)
True
- sage: w.bruhat_le(v) # optional - coxeter3
+ sage: w.bruhat_le(v)
False
"""
cdef CoxGroupElement ww = CoxGroupElement(self._parent_group, w)
@@ -950,10 +949,10 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A',2]) # optional - coxeter3
- sage: x = W([1,2,1]) # optional - coxeter3
- sage: x.is_two_sided_descent(1) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A',2])
+ sage: x = W([1,2,1])
+ sage: x.is_two_sided_descent(1)
True
"""
cdef Generator ss = self._parent_group.in_ordering[s]
@@ -973,11 +972,11 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A',2]) # optional - coxeter3
- sage: W([1,2,1]).coatoms() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A',2])
+ sage: W([1,2,1]).coatoms()
[[2, 1], [1, 2]]
- sage: W([]).coatoms() # optional - coxeter3
+ sage: W([]).coatoms()
[]
"""
cdef c_List_CoxWord list = c_List_CoxWord(0)
@@ -1002,11 +1001,11 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupElement # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: w = CoxGroupElement(W, [2,1,2], normal_form=False); w # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupElement
+ sage: W = CoxGroup(['A', 5])
+ sage: w = CoxGroupElement(W, [2,1,2], normal_form=False); w
[2, 1, 2]
- sage: w.normal_form() # optional - coxeter3
+ sage: w.normal_form()
[1, 2, 1]
"""
@@ -1020,11 +1019,11 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupElement # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: w = CoxGroupElement(W, [2,1,2,1,1], normal_form=False); w # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupElement
+ sage: W = CoxGroup(['A', 5])
+ sage: w = CoxGroupElement(W, [2,1,2,1,1], normal_form=False); w
[2, 1, 2, 1, 1]
- sage: w.reduced() # optional - coxeter3
+ sage: w.reduced()
[1, 2, 1]
"""
cdef CoxGroupElement res = self._new()
@@ -1035,11 +1034,11 @@ cdef class CoxGroupElement:
"""
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: W([1]) * W([1]) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5])
+ sage: W([1]) * W([1])
[]
- sage: W([1,2]) * W([1]) # optional - coxeter3
+ sage: W([1,2]) * W([1])
[1, 2, 1]
"""
cdef CoxGroupElement res = self._new()
@@ -1053,11 +1052,11 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 5]) # optional - coxeter3
- sage: W([]).poincare_polynomial() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 5])
+ sage: W([]).poincare_polynomial()
1
- sage: W([1,2,1]).poincare_polynomial() # optional - coxeter3
+ sage: W([1,2,1]).poincare_polynomial()
t^3 + 2*t^2 + 2*t + 1
"""
cdef CoxGroup W = self.parent_group()
@@ -1072,7 +1071,6 @@ cdef class CoxGroupElement:
coefficients[result[j].length()] += 1
return ZZ['t'](coefficients)
-
def kazhdan_lusztig_polynomial(self, v):
"""
Return the Kazhdan-Lusztig polynomial `P_{u,v}` where `u` is ``self``.
@@ -1082,11 +1080,11 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup # optional - coxeter3
- sage: W = CoxGroup(['A', 2]) # optional - coxeter3
- sage: W([]).kazhdan_lusztig_polynomial([1,2,1]) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup
+ sage: W = CoxGroup(['A', 2])
+ sage: W([]).kazhdan_lusztig_polynomial([1,2,1])
1
- sage: W([1,2,1]).kazhdan_lusztig_polynomial([]) # optional - coxeter3
+ sage: W([1,2,1]).kazhdan_lusztig_polynomial([])
0
"""
cdef CoxGroupElement vv
@@ -1114,15 +1112,15 @@ cdef class CoxGroupElement:
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A',5]) # optional - coxeter3
- sage: w = W([1,2,3,4,5,4]) # optional - coxeter3
- sage: v = W([1,2,4,5,4]) # optional - coxeter3
- sage: w.mu_coefficient(v) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A',5])
+ sage: w = W([1,2,3,4,5,4])
+ sage: v = W([1,2,4,5,4])
+ sage: w.mu_coefficient(v)
0
- sage: w.mu_coefficient(w) # optional - coxeter3
+ sage: w.mu_coefficient(w)
0
- sage: v.mu_coefficient(w) # optional - coxeter3
+ sage: v.mu_coefficient(w)
1
"""
cdef CoxGroupElement vv = CoxGroupElement(self._parent_group, v)
@@ -1130,16 +1128,17 @@ cdef class CoxGroupElement:
cdef CoxNbr y = self.group.extendContext(vv.word)
return ZZ(self.group.mu(x,y))
+
cdef LFlags_to_list(CoxGroup parent, LFlags f) noexcept:
"""
Return the right descent set of this element.
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import * # optional - coxeter3
- sage: W = CoxGroup(['A',5]) # optional - coxeter3
- sage: w = W([1,2,1]) # optional - coxeter3
- sage: w.right_descents() # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import *
+ sage: W = CoxGroup(['A',5])
+ sage: w = W([1,2,1])
+ sage: w.right_descents()
[1, 2]
"""
cdef Generator s
@@ -1151,6 +1150,7 @@ cdef LFlags_to_list(CoxGroup parent, LFlags f) noexcept:
f1 = f1 & (f1-1)
return l
+
class CoxGroupIterator():
def __init__(self, group):
"""
@@ -1164,10 +1164,10 @@ class CoxGroupIterator():
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupIterator # optional - coxeter3
- sage: W = CoxGroup(['A', 2]) # optional - coxeter3
- sage: it = CoxGroupIterator(W) # optional - coxeter3
- sage: [next(it) for i in range(W.order())] # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupIterator
+ sage: W = CoxGroup(['A', 2])
+ sage: it = CoxGroupIterator(W)
+ sage: [next(it) for i in range(W.order())]
[[], [1], [2], [1, 2], [2, 1], [1, 2, 1]]
"""
self.group = group
@@ -1181,10 +1181,10 @@ class CoxGroupIterator():
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupIterator # optional - coxeter3
- sage: W = CoxGroup(['A', 2]) # optional - coxeter3
- sage: it = iter(W) # optional - coxeter3
- sage: it is iter(it) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupIterator
+ sage: W = CoxGroup(['A', 2])
+ sage: it = iter(W)
+ sage: it is iter(it)
True
"""
return self
@@ -1195,10 +1195,10 @@ class CoxGroupIterator():
EXAMPLES::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupIterator # optional - coxeter3
- sage: W = CoxGroup(['A', 2]) # optional - coxeter3
- sage: it = CoxGroupIterator(W) # optional - coxeter3
- sage: next(it) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupIterator
+ sage: W = CoxGroup(['A', 2])
+ sage: it = CoxGroupIterator(W)
+ sage: next(it)
[]
"""
if self.n >= self.order:
@@ -1217,8 +1217,8 @@ def get_CoxGroup(cartan_type):
"""
TESTS::
- sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupIterator # optional - coxeter3
- sage: W = CoxGroup(['A', 2]) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupIterator
+ sage: W = CoxGroup(['A', 2])
"""
from sage.combinat.root_system.cartan_type import CartanType
cartan_type = CartanType(cartan_type)
diff --git a/src/sage/libs/coxeter3/coxeter_group.py b/src/sage/libs/coxeter3/coxeter_group.py
index bb5a3bc024a..fd5f93ad506 100644
--- a/src/sage/libs/coxeter3/coxeter_group.py
+++ b/src/sage/libs/coxeter3/coxeter_group.py
@@ -1,14 +1,15 @@
# sage_setup: distribution = sagemath-coxeter3
+# sage.doctest: optional - coxeter3
"""
Coxeter Groups implemented with Coxeter3
"""
-#*****************************************************************************
+# ****************************************************************************
# Copyright (C) 2009-2013 Mike Hansen
#
# Distributed under the terms of the GNU General Public License (GPL)
-# http://www.gnu.org/licenses/
-#*****************************************************************************
+# https://www.gnu.org/licenses/
+# ****************************************************************************
from sage.libs.coxeter3.coxeter import get_CoxGroup, CoxGroupElement
from sage.misc.cachefunc import cached_method
@@ -31,10 +32,10 @@ def __classcall__(cls, cartan_type, *args, **options):
"""
TESTS::
- sage: from sage.libs.coxeter3.coxeter_group import CoxeterGroup # optional - coxeter3
- sage: CoxeterGroup(['B',2]) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter_group import CoxeterGroup
+ sage: CoxeterGroup(['B',2])
Coxeter group of type ['B', 2] implemented by Coxeter3
- sage: CoxeterGroup(CartanType(['B', 3]).relabel({1: 3, 2: 2, 3: 1})) # optional - coxeter3
+ sage: CoxeterGroup(CartanType(['B', 3]).relabel({1: 3, 2: 2, 3: 1}))
Coxeter group of type ['B', 3] relabelled by {1: 3, 2: 2, 3: 1} implemented by Coxeter3
"""
@@ -46,15 +47,15 @@ def __init__(self, cartan_type):
"""
TESTS::
- sage: from sage.libs.coxeter3.coxeter_group import CoxeterGroup # optional - coxeter3
- sage: CoxeterGroup(['A',2]) # optional - coxeter3
+ sage: from sage.libs.coxeter3.coxeter_group import CoxeterGroup
+ sage: CoxeterGroup(['A',2])
Coxeter group of type ['A', 2] implemented by Coxeter3
As degrees and codegrees are not implemented, they are skipped in the
testsuite::
sage: to_skip = ['_test_degrees', '_test_codegrees']
- sage: TestSuite(CoxeterGroup(['A',2])).run(skip=to_skip) # optional - coxeter3
+ sage: TestSuite(CoxeterGroup(['A',2])).run(skip=to_skip)
"""
category = CoxeterGroups()
if cartan_type.is_finite():
@@ -67,9 +68,9 @@ def _repr_(self):
"""
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3'); W # optional - coxeter3 # indirect doctest
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3'); W # indirect doctest
Coxeter group of type ['A', 3] implemented by Coxeter3
- sage: W = CoxeterGroup(['A', 3, 1], implementation='coxeter3'); W # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3, 1], implementation='coxeter3'); W
Coxeter group of type ['A', 3, 1] implemented by Coxeter3
"""
return "Coxeter group of type %s implemented by Coxeter3" % (self.cartan_type())
@@ -78,8 +79,8 @@ def __iter__(self):
"""
EXAMPLES::
- sage: W = CoxeterGroup(['A', 2], implementation='coxeter3') # optional - coxeter3
- sage: list(W) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 2], implementation='coxeter3')
+ sage: list(W)
[[], [1], [2], [1, 2], [2, 1], [1, 2, 1]]
"""
for x in self._coxgroup:
@@ -91,8 +92,8 @@ def cartan_type(self):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W.cartan_type() # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W.cartan_type()
['A', 3]
"""
return self._cartan_type
@@ -103,11 +104,11 @@ def index_set(self):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W.index_set() # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W.index_set()
(1, 2, 3)
- sage: C = CoxeterGroup(['A', 3,1], implementation='coxeter3') # optional - coxeter3
- sage: C.index_set() # optional - coxeter3
+ sage: C = CoxeterGroup(['A', 3,1], implementation='coxeter3')
+ sage: C.index_set()
(0, 1, 2, 3)
"""
return self.cartan_type().index_set()
@@ -118,8 +119,8 @@ def bruhat_interval(self, u, v):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W.bruhat_interval([1],[3,1,2,3]) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W.bruhat_interval([1],[3,1,2,3])
[[1], [1, 2], [1, 3], [1, 2, 3], [1, 3, 2], [1, 2, 3, 2]]
"""
u, v = self(u), self(v)
@@ -131,8 +132,8 @@ def cardinality(self):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W.cardinality() # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W.cardinality()
24
"""
return self._coxgroup.order()
@@ -143,8 +144,8 @@ def one(self):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W.one() # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W.one()
[]
"""
@@ -156,9 +157,9 @@ def simple_reflections(self):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: s = W.simple_reflections() # optional - coxeter3
- sage: s[2]*s[1]*s[2] # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: s = W.simple_reflections()
+ sage: s[2]*s[1]*s[2]
[1, 2, 1]
"""
from sage.sets.family import Family
@@ -172,10 +173,10 @@ def from_reduced_word(self, w):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W.from_reduced_word([1, 3]) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W.from_reduced_word([1, 3])
[1, 3]
- sage: W.from_reduced_word([3, 1]) # optional - coxeter3
+ sage: W.from_reduced_word([3, 1])
[1, 3]
"""
return self.element_class(self, w)
@@ -186,8 +187,8 @@ def rank(self):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W.rank() # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W.rank()
3
"""
return self._coxgroup.rank()
@@ -198,8 +199,8 @@ def is_finite(self):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W.is_finite() # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W.is_finite()
True
"""
return self._coxgroup.is_finite()
@@ -211,10 +212,10 @@ def length(self, x):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W.length(W([1,2])) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W.length(W([1,2]))
2
- sage: W.length(W([1,1])) # optional - coxeter3
+ sage: W.length(W([1,1]))
0
"""
@@ -230,12 +231,12 @@ def coxeter_matrix(self):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: m = W.coxeter_matrix(); m # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: m = W.coxeter_matrix(); m
[1 3 2]
[3 1 3]
[2 3 1]
- sage: m.index_set() == W.index_set() # optional - coxeter3
+ sage: m.index_set() == W.index_set()
True
"""
@@ -247,11 +248,11 @@ def root_system(self):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: R = W.root_system(); R # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: R = W.root_system(); R
Root system of type ['A', 3]
- sage: alpha = R.root_space().basis() # optional - coxeter3
- sage: alpha[2] + alpha[3] # optional - coxeter3
+ sage: alpha = R.root_space().basis()
+ sage: alpha[2] + alpha[3]
alpha[2] + alpha[3]
"""
return self.cartan_type().root_system()
@@ -262,8 +263,8 @@ def _an_element_(self):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W._an_element_() # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W._an_element_()
[]
"""
@@ -275,8 +276,8 @@ def m(self, i, j):
TESTS::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W.m(1, 1) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W.m(1, 1)
doctest:warning...:
DeprecationWarning: the .m(i, j) method has been deprecated; use .coxeter_matrix()[i,j] instead.
See https://github.com/sagemath/sage/issues/30237 for details.
@@ -303,13 +304,13 @@ def kazhdan_lusztig_polynomial(self, u, v, constant_term_one=True):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W.kazhdan_lusztig_polynomial([], [1,2, 1]) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W.kazhdan_lusztig_polynomial([], [1,2, 1])
1
- sage: W.kazhdan_lusztig_polynomial([1],[3,2]) # optional - coxeter3
+ sage: W.kazhdan_lusztig_polynomial([1],[3,2])
0
- sage: W = CoxeterGroup(['A',3],implementation='coxeter3') # optional - coxeter3
- sage: W.kazhdan_lusztig_polynomial([2],[2,1,3,2]) # optional - coxeter3
+ sage: W = CoxeterGroup(['A',3],implementation='coxeter3')
+ sage: W.kazhdan_lusztig_polynomial([2],[2,1,3,2])
q + 1
.. NOTE::
@@ -325,7 +326,7 @@ def kazhdan_lusztig_polynomial(self, u, v, constant_term_one=True):
In particular, `P_{u,u}=1`::
- sage: all(W.kazhdan_lusztig_polynomial(u,u) == 1 for u in W) # optional - coxeter3
+ sage: all(W.kazhdan_lusztig_polynomial(u,u) == 1 for u in W)
True
This convention differs from Theorem 2.7 in [LT1998]_ by:
@@ -336,20 +337,20 @@ def kazhdan_lusztig_polynomial(self, u, v, constant_term_one=True):
To access the Leclerc-Thibon convention use::
- sage: W = CoxeterGroup(['A',3],implementation='coxeter3') # optional - coxeter3
- sage: W.kazhdan_lusztig_polynomial([2],[2,1,3,2],constant_term_one=False) # optional - coxeter3
+ sage: W = CoxeterGroup(['A',3],implementation='coxeter3')
+ sage: W.kazhdan_lusztig_polynomial([2],[2,1,3,2],constant_term_one=False)
q^3 + q
TESTS:
We check that Coxeter3 and Sage's implementation give the same results::
- sage: C = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3
+ sage: C = CoxeterGroup(['B', 3], implementation='coxeter3')
sage: W = WeylGroup("B3",prefix="s")
sage: [s1,s2,s3] = W.simple_reflections()
sage: R. = LaurentPolynomialRing(QQ)
sage: KL = KazhdanLusztigPolynomial(W,q)
- sage: all(KL.P(1,w) == C.kazhdan_lusztig_polynomial([],w.reduced_word()) for w in W) # optional - coxeter3 # long (15s)
+ sage: all(KL.P(1,w) == C.kazhdan_lusztig_polynomial([],w.reduced_word()) for w in W) # long (15s)
True
"""
u, v = self(u), self(v)
@@ -384,30 +385,30 @@ def parabolic_kazhdan_lusztig_polynomial(self, u, v, J, constant_term_one=True):
EXAMPLES::
- sage: W = CoxeterGroup(['A',3], implementation='coxeter3') # optional - coxeter3
- sage: W.parabolic_kazhdan_lusztig_polynomial([],[3,2],[1,3]) # optional - coxeter3
+ sage: W = CoxeterGroup(['A',3], implementation='coxeter3')
+ sage: W.parabolic_kazhdan_lusztig_polynomial([],[3,2],[1,3])
0
- sage: W.parabolic_kazhdan_lusztig_polynomial([2],[2,1,3,2],[1,3]) # optional - coxeter3
+ sage: W.parabolic_kazhdan_lusztig_polynomial([2],[2,1,3,2],[1,3])
q
- sage: C = CoxeterGroup(['A',3,1], implementation='coxeter3') # optional - coxeter3
- sage: C.parabolic_kazhdan_lusztig_polynomial([],[1],[0]) # optional - coxeter3
+ sage: C = CoxeterGroup(['A',3,1], implementation='coxeter3')
+ sage: C.parabolic_kazhdan_lusztig_polynomial([],[1],[0])
1
- sage: C.parabolic_kazhdan_lusztig_polynomial([],[1,2,1],[0]) # optional - coxeter3
+ sage: C.parabolic_kazhdan_lusztig_polynomial([],[1,2,1],[0])
1
- sage: C.parabolic_kazhdan_lusztig_polynomial([],[0,1,0,1,2,1],[0]) # optional - coxeter3
+ sage: C.parabolic_kazhdan_lusztig_polynomial([],[0,1,0,1,2,1],[0])
q
sage: w=[1, 2, 1, 3, 0, 2, 1, 0, 3, 0, 2]
sage: v=[1, 2, 1, 3, 0, 1, 2, 1, 0, 3, 0, 2, 1, 0, 3, 0, 2]
- sage: C.parabolic_kazhdan_lusztig_polynomial(w,v,[1,3]) # optional - coxeter3
+ sage: C.parabolic_kazhdan_lusztig_polynomial(w,v,[1,3])
q^2 + q
- sage: C.parabolic_kazhdan_lusztig_polynomial(w,v,[1,3],constant_term_one=False) # optional - coxeter3
+ sage: C.parabolic_kazhdan_lusztig_polynomial(w,v,[1,3],constant_term_one=False)
q^4 + q^2
TESTS::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: type(W.parabolic_kazhdan_lusztig_polynomial([2],[],[1])) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: type(W.parabolic_kazhdan_lusztig_polynomial([2],[],[1]))
"""
u = self(u)
@@ -431,19 +432,19 @@ def __init__(self, parent, x):
"""
TESTS::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W([2,1,2]) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W([2,1,2])
[1, 2, 1]
Check that :trac:`32266` is fixed::
- sage: A3 = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3
- sage: s1,s2,s3 = A3.simple_reflections() # optional - coxeter3
- sage: s1*s3 # optional - coxeter3
+ sage: A3 = CoxeterGroup('A3', implementation='coxeter3')
+ sage: s1,s2,s3 = A3.simple_reflections()
+ sage: s1*s3
[1, 3]
- sage: s3*s1 # optional - coxeter3
+ sage: s3*s1
[1, 3]
- sage: s3*s1 == s1*s3 # optional - coxeter3
+ sage: s3*s1 == s1*s3
True
"""
if not isinstance(x, CoxGroupElement):
@@ -457,9 +458,9 @@ def __iter__(self):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: w = W([1,2,1]) # optional - coxeter3
- sage: list(iter(w)) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: w = W([1,2,1])
+ sage: list(iter(w))
[1, 2, 1]
"""
return iter(self.value)
@@ -470,9 +471,9 @@ def coatoms(self):
EXAMPLES::
- sage: W = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3
- sage: w = W([1,2,3]) # optional - coxeter3
- sage: w.coatoms() # optional - coxeter3
+ sage: W = CoxeterGroup(['B', 3], implementation='coxeter3')
+ sage: w = W([1,2,3])
+ sage: w.coatoms()
[[2, 3], [3, 1], [1, 2]]
"""
W = self.parent()
@@ -484,20 +485,20 @@ def _richcmp_(self, other, op):
EXAMPLES::
- sage: W = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3
- sage: w = W([1,2,3]) # optional - coxeter3
- sage: v = W([3,1,2]) # optional - coxeter3
- sage: v < w # optional - coxeter3
+ sage: W = CoxeterGroup(['B', 3], implementation='coxeter3')
+ sage: w = W([1,2,3])
+ sage: v = W([3,1,2])
+ sage: v < w
False
- sage: w < v # optional - coxeter3
+ sage: w < v
True
Some tests for equality::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W([1,2,1]) == W([2,1,2]) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W([1,2,1]) == W([2,1,2])
True
- sage: W([1,2,1]) == W([2,1]) # optional - coxeter3
+ sage: W([1,2,1]) == W([2,1])
False
"""
return richcmp(list(self), list(other), op)
@@ -508,9 +509,9 @@ def reduced_word(self):
EXAMPLES::
- sage: W = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3
- sage: w = W([1,2,3]) # optional - coxeter3
- sage: w.reduced_word() # optional - coxeter3
+ sage: W = CoxeterGroup(['B', 3], implementation='coxeter3')
+ sage: w = W([1,2,3])
+ sage: w.reduced_word()
[1, 2, 3]
"""
return list(self)
@@ -521,9 +522,9 @@ def __invert__(self):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: w = W([1,2,3]) # optional - coxeter3
- sage: ~w # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: w = W([1,2,3])
+ sage: ~w
[3, 2, 1]
"""
return self.__class__(self.parent(), ~self.value)
@@ -534,11 +535,11 @@ def __getitem__(self, i):
"""
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: w0 = W([1,2,1]) # optional - coxeter3
- sage: w0[0] # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: w0 = W([1,2,1])
+ sage: w0[0]
1
- sage: w0[1] # optional - coxeter3
+ sage: w0[1]
2
"""
@@ -549,13 +550,13 @@ def _mul_(self, y):
"""
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: s = W.gens() # optional - coxeter3
- sage: s[1]._mul_(s[1]) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: s = W.gens()
+ sage: s[1]._mul_(s[1])
[]
- sage: s[1]*s[2]*s[1] # optional - coxeter3
+ sage: s[1]*s[2]*s[1]
[1, 2, 1]
- sage: s[2]*s[1]*s[2] # optional - coxeter3
+ sage: s[2]*s[1]*s[2]
[1, 2, 1]
"""
return self.__class__(self.parent(), self.value * y.value)
@@ -564,11 +565,11 @@ def __len__(self):
"""
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: w = W([1,2,1]) # optional - coxeter3
- sage: w.length() # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: w = W([1,2,1])
+ sage: w.length()
3
- sage: len(w) # optional - coxeter3
+ sage: len(w)
3
"""
return len(self.value)
@@ -581,8 +582,8 @@ def bruhat_le(self, v):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W([]).bruhat_le([1,2,1]) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W([]).bruhat_le([1,2,1])
True
"""
v = self.parent()(v)
@@ -594,18 +595,17 @@ def poincare_polynomial(self):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 2], implementation='coxeter3') # optional - coxeter3
- sage: W.long_element().poincare_polynomial() # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 2], implementation='coxeter3')
+ sage: W.long_element().poincare_polynomial()
t^3 + 2*t^2 + 2*t + 1
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: W([2,1,3,2]).poincare_polynomial() # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: W([2,1,3,2]).poincare_polynomial()
t^4 + 4*t^3 + 5*t^2 + 3*t + 1
- sage: W([1,2,3,2,1]).poincare_polynomial() # optional - coxeter3
+ sage: W([1,2,3,2,1]).poincare_polynomial()
t^5 + 4*t^4 + 6*t^3 + 5*t^2 + 3*t + 1
-
- sage: rw = sage.combinat.permutation.from_reduced_word # optional - coxeter3
- sage: p = [w.poincare_polynomial() for w in W] # optional - coxeter3
- sage: [rw(w.reduced_word()) for i,w in enumerate(W) if p[i] != p[i].reverse()] # optional - coxeter3
+ sage: rw = sage.combinat.permutation.from_reduced_word
+ sage: p = [w.poincare_polynomial() for w in W]
+ sage: [rw(w.reduced_word()) for i,w in enumerate(W) if p[i] != p[i].reverse()]
[[3, 4, 1, 2], [4, 2, 3, 1]]
"""
return self.value.poincare_polynomial()
@@ -616,10 +616,10 @@ def has_right_descent(self, i):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 4], implementation='coxeter3') # optional - coxeter3
- sage: W([1,2]).has_right_descent(1) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 4], implementation='coxeter3')
+ sage: W([1,2]).has_right_descent(1)
False
- sage: W([1,2]).has_right_descent(2) # optional - coxeter3
+ sage: W([1,2]).has_right_descent(2)
True
"""
return i in self.value.right_descents()
@@ -630,10 +630,10 @@ def has_left_descent(self, i):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 4], implementation='coxeter3') # optional - coxeter3
- sage: W([1,2]).has_left_descent(1) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 4], implementation='coxeter3')
+ sage: W([1,2]).has_left_descent(1)
True
- sage: W([1,2]).has_left_descent(2) # optional - coxeter3
+ sage: W([1,2]).has_left_descent(2)
False
"""
return i in self.value.left_descents()
@@ -648,15 +648,15 @@ def action(self, v):
EXAMPLES::
- sage: W = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3
- sage: R = W.root_system().root_space() # optional - coxeter3
- sage: v = R.an_element(); v # optional - coxeter3
+ sage: W = CoxeterGroup(['B', 3], implementation='coxeter3')
+ sage: R = W.root_system().root_space()
+ sage: v = R.an_element(); v
2*alpha[1] + 2*alpha[2] + 3*alpha[3]
- sage: w = W([1,2,3]) # optional - coxeter3
- sage: w.action(v) # optional - coxeter3
+ sage: w = W([1,2,3])
+ sage: w.action(v)
-alpha[1] + alpha[2] + alpha[3]
"""
- #TODO: Find a better way to do this
+ # TODO: Find a better way to do this
W = self.parent().root_system().root_space().weyl_group()
w = W.from_reduced_word(list(self))
return w.action(v)
@@ -675,14 +675,14 @@ def action_on_rational_function(self, f):
EXAMPLES::
- sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
- sage: S = PolynomialRing(QQ, 'x,y,z').fraction_field() # optional - coxeter3
- sage: x,y,z = S.gens() # optional - coxeter3
- sage: W([1]).action_on_rational_function(x+y+z) # optional - coxeter3
+ sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')
+ sage: S = PolynomialRing(QQ, 'x,y,z').fraction_field()
+ sage: x,y,z = S.gens()
+ sage: W([1]).action_on_rational_function(x+y+z)
(x^2*y + x*z + 1)/x
- sage: W([2]).action_on_rational_function(x+y+z) # optional - coxeter3
+ sage: W([2]).action_on_rational_function(x+y+z)
(x*y^2 + y^2*z + 1)/y
- sage: W([3]).action_on_rational_function(x+y+z) # optional - coxeter3
+ sage: W([3]).action_on_rational_function(x+y+z)
(y*z^2 + x*z + 1)/z
"""
Q = f.parent()
@@ -693,7 +693,9 @@ def action_on_rational_function(self, f):
n = W.rank()
if Q.ngens() != n:
- raise ValueError("the number of generators for the polynomial ring must be the same as the rank of the root system")
+ raise ValueError("the number of generators for the polynomial "
+ "ring must be the same as the rank of the "
+ "root system")
basis_elements = [alpha[i] for i in W.index_set()]
basis_to_order = {s: i for i, s in enumerate(W.index_set())}
@@ -704,7 +706,7 @@ def action_on_rational_function(self, f):
exponents = poly.exponents()
for exponent in exponents:
- #Construct something in the root lattice from the exponent vector
+ # Construct something in the root lattice from the exponent vector
exponent = sum(e*b for e, b in zip(exponent, basis_elements))
exponent = self.action(exponent)
diff --git a/src/sage/libs/gap/element.pyx b/src/sage/libs/gap/element.pyx
index e522bf5bc03..1f0f451a2c2 100644
--- a/src/sage/libs/gap/element.pyx
+++ b/src/sage/libs/gap/element.pyx
@@ -553,7 +553,7 @@ cdef class GapElement(RingElement):
INPUT:
- - ``mut`` - (boolean) whether to return an mutable copy
+ - ``mut`` - (boolean) whether to return a mutable copy
EXAMPLES::
@@ -1778,7 +1778,7 @@ cdef class GapElement_FiniteField(GapElement):
OUTPUT:
- An Sage finite field element. The isomorphism is chosen such
+ A Sage finite field element. The isomorphism is chosen such
that the Gap ``PrimitiveRoot()`` maps to the Sage
:meth:`~sage.rings.finite_rings.finite_field_prime_modn.multiplicative_generator`.
diff --git a/src/sage/libs/gap/libgap.pyx b/src/sage/libs/gap/libgap.pyx
index 3803f32b191..63400adab4c 100644
--- a/src/sage/libs/gap/libgap.pyx
+++ b/src/sage/libs/gap/libgap.pyx
@@ -46,7 +46,7 @@ equivalent::
sage: type(_)
- sage: libgap.eval('5/3 + 7*E(3)').sage()
+ sage: libgap.eval('5/3 + 7*E(3)').sage() # needs sage.rings.number_field
7*zeta3 + 5/3
sage: gens_of_group = libgap.AlternatingGroup(4).GeneratorsOfGroup()
@@ -265,7 +265,7 @@ class Gap(Parent):
sage: libgap.has_coerce_map_from(ZZ)
True
- sage: libgap.has_coerce_map_from(CyclotomicField(5)['x','y'])
+ sage: libgap.has_coerce_map_from(CyclotomicField(5)['x','y']) # needs sage.rings.number_field
True
"""
return True
@@ -362,11 +362,12 @@ class Gap(Parent):
We gracefully handle the case that the conversion fails (:trac:`18039`)::
- sage: F. = GF(9, modulus="first_lexicographic")
- sage: libgap(Matrix(F, [[a]]))
+ sage: F. = GF(9, modulus="first_lexicographic") # needs sage.rings.finite_rings
+ sage: libgap(Matrix(F, [[a]])) # needs sage.rings.finite_rings
Traceback (most recent call last):
...
- NotImplementedError: conversion of (Givaro) finite field element to GAP not implemented except for fields defined by Conway polynomials.
+ NotImplementedError: conversion of (Givaro) finite field element to GAP
+ not implemented except for fields defined by Conway polynomials.
"""
ring = M.base_ring()
try:
diff --git a/src/sage/libs/gap/sage.gaprc b/src/sage/libs/gap/sage.gaprc
index 39c878f2329..258db942a98 100644
--- a/src/sage/libs/gap/sage.gaprc
+++ b/src/sage/libs/gap/sage.gaprc
@@ -1,3 +1,31 @@
# This file is run by Sage when initializing libgap via GAP_Initialize, and may
# contain bug fixes/workarounds and/or any Sage-specific patches necessary for
# Sage's libgap interface.
+
+
+# Load the GAP packages that GAP itself tries to autoload in the
+# default configuration (see "PackagesToLoad" in lib/package.gi). The
+# combination of passing -A to gap and these LoadPackage statements
+# allows us to load the usual set of packages, but only if they are
+# installed. So most people will get exactly the default behavior,
+# but minimal installations won't throw warnings and fail tests.
+#
+# We also temporarily lower the InfoLevel of the InfoWarning class so
+# that e.g.,
+#
+# #I polycyclic package is not available. Check that the name is correct
+# #I and it is present in one of the GAP root directories (see '??RootPaths')
+#
+# is not output to the console.
+#
+_orig_warn_level := InfoLevel(InfoWarning);
+SetInfoLevel(InfoWarning, 0);
+
+_autoloads := [ "autpgrp", "alnuth", "crisp", "ctbllib", "factint", "fga",
+ "irredsol", "laguna", "polenta", "polycyclic", "resclasses",
+ "sophus", "tomlib" ];
+for p in _autoloads do
+ LoadPackage(p);
+od;
+
+SetInfoLevel(InfoWarning, _orig_warn_level);
diff --git a/src/sage/libs/gap/saved_workspace.py b/src/sage/libs/gap/saved_workspace.py
index 7636707f557..fdaf18f4644 100644
--- a/src/sage/libs/gap/saved_workspace.py
+++ b/src/sage/libs/gap/saved_workspace.py
@@ -8,7 +8,7 @@
import os
import glob
-from sage.env import GAP_LIB_DIR
+from sage.env import GAP_ROOT_PATHS
from sage.interfaces.gap_workspace import gap_workspace_file
@@ -31,7 +31,13 @@ def timestamp():
"""
libgap_dir = os.path.dirname(__file__)
libgap_files = glob.glob(os.path.join(libgap_dir, '*'))
- gap_packages = glob.glob(os.path.join(GAP_LIB_DIR, 'pkg', '*'))
+ gap_packages = []
+ for d in GAP_ROOT_PATHS.split(";"):
+ if d:
+ # If GAP_ROOT_PATHS begins or ends with a semicolon,
+ # we'll get one empty d.
+ gap_packages += glob.glob(os.path.join(d, 'pkg', '*'))
+
files = libgap_files + gap_packages
if len(files) == 0:
print('Unable to find LibGAP files.')
diff --git a/src/sage/libs/gap/util.pyx b/src/sage/libs/gap/util.pyx
index d37fe84f029..8685dc08fa5 100644
--- a/src/sage/libs/gap/util.pyx
+++ b/src/sage/libs/gap/util.pyx
@@ -217,28 +217,29 @@ cdef initialize() noexcept:
# initialize GAP.
cdef char* argv[16]
argv[0] = "sage"
- argv[1] = "-l"
- s = str_to_bytes(sage.env.GAP_LIB_DIR + ";" + sage.env.GAP_SHARE_DIR, FS_ENCODING, "surrogateescape")
- argv[2] = s
-
- argv[3] = "-m"
- argv[4] = "64m"
-
- argv[5] = "-q" # no prompt!
- argv[6] = "-E" # don't use readline as this will interfere with Python
- argv[7] = "--nointeract" # Implies -T
- argv[8] = "-x" # set the "screen" width so that GAP is less likely to
- argv[9] = "4096" # insert newlines when printing objects
+ argv[1] = "-A"
+ argv[2] = "-l"
+ s = str_to_bytes(sage.env.GAP_ROOT_PATHS, FS_ENCODING, "surrogateescape")
+ argv[3] = s
+
+ argv[4] = "-m"
+ argv[5] = "64m"
+
+ argv[6] = "-q" # no prompt!
+ argv[7] = "-E" # don't use readline as this will interfere with Python
+ argv[8] = "--nointeract" # Implies -T
+ argv[9] = "-x" # set the "screen" width so that GAP is less likely to
+ argv[10] = "4096" # insert newlines when printing objects
# 4096 unfortunately is the hard-coded max, but should
# be long enough for most cases
- cdef int argc = 10 # argv[argc] must be NULL
+ cdef int argc = 11 # argv[argc] must be NULL
gap_mem = sage.env.SAGE_GAP_MEMORY
if gap_mem is not None:
argc += 2
- argv[10] = "-s"
+ argv[11] = "-s"
s1 = str_to_bytes(gap_mem, FS_ENCODING, "surrogateescape")
- argv[11] = s1
- argv[4] = s1
+ argv[12] = s1
+ argv[5] = s1
from sage.libs.gap.saved_workspace import workspace
workspace, workspace_is_up_to_date = workspace()
diff --git a/src/sage/libs/ntl/ntl_GF2E.pyx b/src/sage/libs/ntl/ntl_GF2E.pyx
index 2e4fec38020..fa941804293 100644
--- a/src/sage/libs/ntl/ntl_GF2E.pyx
+++ b/src/sage/libs/ntl/ntl_GF2E.pyx
@@ -54,7 +54,7 @@ def ntl_GF2E_random(ntl_GF2EContext_class ctx):
INPUT:
- - ``ctx`` -- the GF2E context for which an random element should be created
+ - ``ctx`` -- the GF2E context for which a random element should be created
EXAMPLES::
diff --git a/src/sage/libs/ntl/ntl_GF2X.pyx b/src/sage/libs/ntl/ntl_GF2X.pyx
index f6781a68c7b..5e6ef736763 100644
--- a/src/sage/libs/ntl/ntl_GF2X.pyx
+++ b/src/sage/libs/ntl/ntl_GF2X.pyx
@@ -507,7 +507,7 @@ cdef class ntl_GF2X():
def hex(ntl_GF2X self):
r"""
- Return an hexadecimal representation of this element.
+ Return a hexadecimal representation of this element.
It is the same as setting \code{ntl.GF2XHexOutput(True)} and
representing this element afterwards. However it should be faster and
diff --git a/src/sage/libs/ntl/ntl_ZZ_pEX_linkage.pxi b/src/sage/libs/ntl/ntl_ZZ_pEX_linkage.pxi
index 22d15b71b45..36c87c75efa 100644
--- a/src/sage/libs/ntl/ntl_ZZ_pEX_linkage.pxi
+++ b/src/sage/libs/ntl/ntl_ZZ_pEX_linkage.pxi
@@ -332,7 +332,7 @@ cdef inline int celement_pow(ZZ_pEX_c* res, ZZ_pEX_c* x, long e, ZZ_pEX_c *modul
sage: (x+1)^(-2)
1/(x^2 + 2*x + 1)
sage: f = x+(a+1)
- sage: f**50 == sum(binomial(50,i)*(a+1)**i*x**(50-i) for i in range(51))
+ sage: f**50 == sum(binomial(50,i)*(a+1)**i*x**(50-i) for i in range(51)) # needs sage.symbolic
True
TESTS:
diff --git a/src/sage/libs/singular/decl.pxd b/src/sage/libs/singular/decl.pxd
index aa6c5515432..e36216d6395 100644
--- a/src/sage/libs/singular/decl.pxd
+++ b/src/sage/libs/singular/decl.pxd
@@ -1052,7 +1052,7 @@ cdef extern from "singular/polys/sbuckets.h":
#assumes length <= 0 || pLength(p) == length
void sBucketClearMerge(sBucket *bucket, poly **p, int *length)
- #add contents of sBucket into polynomial an clear bucket
+ #add contents of sBucket into polynomial and clear bucket
#(can handle repeated monomials)
void sBucketClearAdd(sBucket *bucket, poly **p, int *length)
diff --git a/src/sage/manifolds/differentiable/manifold.py b/src/sage/manifolds/differentiable/manifold.py
index 3a7820e01ec..4b5a793f762 100644
--- a/src/sage/manifolds/differentiable/manifold.py
+++ b/src/sage/manifolds/differentiable/manifold.py
@@ -814,7 +814,7 @@ def open_subset(self, name, latex_name=None, coord_def={}, supersets=None):
sage: U.default_chart() is X.restrict(U)
True
- An point in ``U``::
+ A point in ``U``::
sage: p = U.an_element(); p
Point on the 2-dimensional differentiable manifold M
diff --git a/src/sage/manifolds/topological_submanifold.py b/src/sage/manifolds/topological_submanifold.py
index 314a6a16a1b..9b722907152 100644
--- a/src/sage/manifolds/topological_submanifold.py
+++ b/src/sage/manifolds/topological_submanifold.py
@@ -70,7 +70,7 @@ class TopologicalSubmanifold(TopologicalManifold):
a topological embedding `\phi` from `N` to `M` (i.e. `\phi` is an
homeomorphism onto its image).
- In the case where `\phi` is only an topological immersion (i.e. is only
+ In the case where `\phi` is only a topological immersion (i.e. is only
locally an embedding), one says that `N` is an *immersed submanifold*.
The map `\phi` can also depend on one or multiple parameters.
diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx
index 4acd46db4de..0c2aa9eda4b 100644
--- a/src/sage/matrix/matrix2.pyx
+++ b/src/sage/matrix/matrix2.pyx
@@ -216,10 +216,10 @@ cdef class Matrix(Matrix1):
from sage.matrix.constructor import matrix
if self.is_sparse():
return matrix({ij: self[ij].subs(*args, **kwds) for ij in self.nonzero_positions()},
- nrows=self._nrows, ncols=self._ncols, sparse=True)
+ nrows=self._nrows, ncols=self._ncols, sparse=True)
else:
return matrix([a.subs(*args, **kwds) for a in self.list()],
- nrows=self._nrows, ncols=self._ncols, sparse=False)
+ nrows=self._nrows, ncols=self._ncols, sparse=False)
def solve_left(self, B, check=True):
"""
@@ -3183,14 +3183,12 @@ cdef class Matrix(Matrix1):
"""
# Validate assertions
- #
if not self.is_square():
raise ValueError("self must be a square matrix")
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
# Extract parameters
- #
cdef Matrix M = self
n = M._ncols
R = M._base_ring
@@ -3199,7 +3197,6 @@ cdef class Matrix(Matrix1):
# Corner cases
# N.B. We already tested for M to be square, hence we do not need to
# test for 0 x n or m x 0 matrices.
- #
if n == 0:
return S.one()
@@ -3215,7 +3212,6 @@ cdef class Matrix(Matrix1):
#
# N.B. The documentation is still 1-based, although the code, after
# having been ported from Magma to Sage, is 0-based.
- #
from sage.matrix.constructor import matrix
F = [R.zero()] * n
@@ -3226,18 +3222,15 @@ cdef class Matrix(Matrix1):
for t in range(1,n):
# Set a(1, t) to be M(<=t, t)
- #
for i in range(t+1):
a.set_unsafe(0, i, M.get_unsafe(i, t))
# Set A[1, t] to be the (t)th entry in a[1, t]
- #
A[0] = M.get_unsafe(t, t)
for p in range(1, t):
# Set a(p, t) to the product of M[<=t, <=t] * a(p-1, t)
- #
for i in range(t+1):
s = R.zero()
for j in range(t+1):
@@ -3245,11 +3238,9 @@ cdef class Matrix(Matrix1):
a.set_unsafe(p, i, s)
# Set A[p, t] to be the (t)th entry in a[p, t]
- #
A[p] = a.get_unsafe(p, t)
# Set A[t, t] to be M[t, <=t] * a(p-1, t)
- #
s = R.zero()
for j in range(t+1):
s = s + M.get_unsafe(t, j) * a.get_unsafe(t-1, j)
@@ -3262,7 +3253,7 @@ cdef class Matrix(Matrix1):
F[p] = s - A[p]
X = S.gen(0)
- f = X ** n + S(list(reversed(F)))
+ f = X**n + S(list(reversed(F)))
return f
@@ -3634,7 +3625,7 @@ cdef class Matrix(Matrix1):
# using the rows of a matrix.) Also see Cohen's first GTM,
# Algorithm 2.2.9.
- cdef Py_ssize_t i, m, n,
+ cdef Py_ssize_t i, m, n
n = self._nrows
cdef Matrix c
@@ -18607,8 +18598,8 @@ def _matrix_power_symbolic(A, n):
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)]
+ [ 1/2*2^(2*n + 1) + 1/2*kronecker_delta(0, 2*n + 1) -1/2*2^(2*n + 1) + 1/2*kronecker_delta(0, 2*n + 1)]
+ [-1/2*2^(2*n + 1) + 1/2*kronecker_delta(0, 2*n + 1) 1/2*2^(2*n + 1) + 1/2*kronecker_delta(0, 2*n + 1)]
Check if :trac:`23215` is fixed::
@@ -18618,12 +18609,25 @@ def _matrix_power_symbolic(A, n):
-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,
1/2*(a + I*b)^k + 1/2*(a - I*b)^k]
+
+ Check if :trac:`36838` is fixed:Checking symbolic power of
+ nilpotent matrix::
+
+ sage: A = matrix([[0,1],[0,0]]); A
+ [0 1]
+ [0 0]
+ sage: n = var('n'); n
+ n
+ sage: B = A^n; B
+ [ kronecker_delta(0, n) n*kronecker_delta(1, n)]
+ [ 0 kronecker_delta(0, n)]
"""
from sage.rings.qqbar import AlgebraicNumber
from sage.matrix.constructor import matrix
from sage.functions.other import binomial
from sage.symbolic.ring import SR
from sage.rings.qqbar import QQbar
+ from sage.functions.generalized import kronecker_delta
got_SR = A.base_ring() == SR
@@ -18656,8 +18660,17 @@ def _matrix_power_symbolic(A, n):
# D^i(f) / i! with f = x^n and D = differentiation wrt x
if hasattr(mk, 'radical_expression'):
mk = mk.radical_expression()
- vk = [(binomial(n, i) * mk**(n-i)).simplify_full()
- for i in range(nk)]
+
+
+ # When the variable "mk" is equal to zero, it is advisable to employ the Kronecker delta function
+ # instead of utilizing the numerical value zero. This choice is made to encompass scenarios where
+ # the power of zero is also equal to zero.
+ if mk:
+ vk = [(binomial(n, i) * mk._pow_(n-i)).simplify_full()
+ for i in range(nk)]
+ else:
+ vk = [(binomial(n, i).simplify_full() * kronecker_delta(n,i))
+ for i in range(nk)]
# Form block Mk and insert it in M
Mk = matrix(SR, [[SR.zero()]*i + vk[:nk-i] for i in range(nk)])
diff --git a/src/sage/matrix/matrix_cdv.pyx b/src/sage/matrix/matrix_cdv.pyx
index 6faf51eb6ad..73ae9d3552d 100644
--- a/src/sage/matrix/matrix_cdv.pyx
+++ b/src/sage/matrix/matrix_cdv.pyx
@@ -22,7 +22,7 @@ from sage.rings.infinity import Infinity
# We assume that H is square
cpdef hessenbergize_cdvf(Matrix_generic_dense H) noexcept:
r"""
- Replace `H` with an Hessenberg form of it.
+ Replace `H` with a Hessenberg form of it.
.. NOTE::
diff --git a/src/sage/matrix/matrix_integer_dense_hnf.py b/src/sage/matrix/matrix_integer_dense_hnf.py
index a899ae9f6e0..30db173966f 100644
--- a/src/sage/matrix/matrix_integer_dense_hnf.py
+++ b/src/sage/matrix/matrix_integer_dense_hnf.py
@@ -236,8 +236,8 @@ def double_det(A, b, c, proof):
INPUT:
- A -- an (n-1) x n matrix
- - b -- an 1 x n matrix
- - c -- an 1 x n matrix
+ - b -- a 1 x n matrix
+ - c -- a 1 x n matrix
- proof -- whether or not to compute the det modulo enough times to
provably compute the determinant.
diff --git a/src/sage/matroids/lean_matrix.pyx b/src/sage/matroids/lean_matrix.pyx
index 740864af9ce..fa1d95c9bf6 100644
--- a/src/sage/matroids/lean_matrix.pyx
+++ b/src/sage/matroids/lean_matrix.pyx
@@ -2903,7 +2903,7 @@ cdef class PlusMinusOneMatrix(LeanMatrix):
cdef LeanMatrix stack(self, LeanMatrix M) noexcept:
"""
- Warning: assumes ``M`` is an PlusMinusOneMatrix instance of right
+ Warning: assumes ``M`` is a PlusMinusOneMatrix instance of right
dimensions!
"""
cdef PlusMinusOneMatrix A
@@ -3360,7 +3360,7 @@ cdef class RationalMatrix(LeanMatrix):
cdef LeanMatrix stack(self, LeanMatrix M) noexcept:
"""
- Warning: assumes ``M`` is an RationalMatrix instance of right
+ Warning: assumes ``M`` is a RationalMatrix instance of right
dimensions!
"""
cdef RationalMatrix A
diff --git a/src/sage/matroids/set_system.pyx b/src/sage/matroids/set_system.pyx
index 1c943ed6203..ad24e104925 100644
--- a/src/sage/matroids/set_system.pyx
+++ b/src/sage/matroids/set_system.pyx
@@ -591,7 +591,7 @@ cdef class SetSystem:
cpdef _heuristic_partition(self, SetSystem P=None, EP=None) noexcept:
"""
- Return an heuristic ordered partition into singletons of the ground
+ Return a heuristic ordered partition into singletons of the ground
set of the hypergraph whose edges are the subsets in this SetSystem.
This partition obtained as follows: make an equitable
diff --git a/src/sage/misc/abstract_method.py b/src/sage/misc/abstract_method.py
index 7d8ca8edb4c..6179c5a2b8f 100644
--- a/src/sage/misc/abstract_method.py
+++ b/src/sage/misc/abstract_method.py
@@ -48,7 +48,7 @@ def abstract_method(f=None, optional=False):
sage: A.my_method
- The current policy is that a ``NotImplementedError`` is raised
+ The current policy is that a :class:`NotImplementedError` is raised
when accessing the method through an instance, even before the
method is called::
@@ -193,7 +193,7 @@ def _sage_src_lines_(self):
sage: src[0]
'def version():\n'
sage: lines
- 19
+ 18
"""
from sage.misc.sageinspect import sage_getsourcelines
return sage_getsourcelines(self._f)
diff --git a/src/sage/misc/banner.py b/src/sage/misc/banner.py
index a428de42005..9d231926705 100644
--- a/src/sage/misc/banner.py
+++ b/src/sage/misc/banner.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
SageMath version and banner info
"""
@@ -58,14 +57,14 @@ def banner_text(full=True):
if not full:
return version()
- bars = u"─" * 68
+ bars = "─" * 68
s = []
a = s.append
- a(u'┌' + bars + u'┐')
- a(u"\n│ %-66s │\n" % version())
+ a('┌' + bars + '┐')
+ a("\n│ %-66s │\n" % version())
python_version = sys.version_info[:3]
- a(u"│ %-66s │\n" % 'Using Python {}.{}.{}. Type "help()" for help.'.format(*python_version))
- a(u'└' + bars + u'┘')
+ a("│ %-66s │\n" % 'Using Python {}.{}.{}. Type "help()" for help.'.format(*python_version))
+ a('└' + bars + '┘')
pre = version_dict()['prerelease']
try:
import sage.all
@@ -75,15 +74,15 @@ def banner_text(full=True):
if pre or not have_sage_all:
red_in = '\033[31m'
red_out = '\033[0m'
- bars2 = bars.replace(u'─', u'━')
+ bars2 = bars.replace('─', '━')
a('\n')
- a(red_in + u'┏' + bars2 + u'┓' + '\n')
+ a(red_in + '┏' + bars2 + '┓' + '\n')
if pre:
- a(u"┃ %-66s ┃\n" % 'Warning: this is a prerelease version, and it may be unstable.')
+ a("┃ %-66s ┃\n" % 'Warning: this is a prerelease version, and it may be unstable.')
if not have_sage_all:
- a(u"┃ %-66s ┃\n" % 'Warning: sage.all is not available; this is a limited REPL.')
- a(u'┗' + bars2 + u'┛' + red_out)
- return u''.join(s)
+ a("┃ %-66s ┃\n" % 'Warning: sage.all is not available; this is a limited REPL.')
+ a('┗' + bars2 + '┛' + red_out)
+ return ''.join(s)
def banner():
diff --git a/src/sage/misc/call.py b/src/sage/misc/call.py
index 966ee34514b..979497b43f9 100644
--- a/src/sage/misc/call.py
+++ b/src/sage/misc/call.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Attribute and method calling
"""
diff --git a/src/sage/misc/converting_dict.py b/src/sage/misc/converting_dict.py
index 39f66c9295a..0cd7a47916e 100644
--- a/src/sage/misc/converting_dict.py
+++ b/src/sage/misc/converting_dict.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Converting Dictionary
@@ -26,7 +25,7 @@
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: # needs sage.libs.singular sage.rings.number_field
sage: K. = QQ[]
sage: I = ideal([x^2 + 2*y - 5, x + y + 3])
sage: V = sorted(I.variety(AA), key=str)
diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py
index 2af3bc65943..781e02b3191 100644
--- a/src/sage/misc/cython.py
+++ b/src/sage/misc/cython.py
@@ -370,7 +370,7 @@ def cython(filename, verbose=0, compile_message=False,
try:
with open(name + ".lis") as f:
cython_messages = f.read()
- except IOError:
+ except OSError:
cython_messages = "Error compiling Cython file"
except CompileError:
raise RuntimeError(cython_messages.strip())
diff --git a/src/sage/misc/edit_module.py b/src/sage/misc/edit_module.py
index 9b03e7237a0..82496752609 100644
--- a/src/sage/misc/edit_module.py
+++ b/src/sage/misc/edit_module.py
@@ -133,7 +133,7 @@ def template_fields(template):
"""
dict = {}
dummy = None
- while not(dummy):
+ while not dummy:
try:
dummy = template.substitute(dict)
except KeyError as inst:
@@ -168,10 +168,10 @@ def set_edit_template(template_string):
"""
global edit_template
- if not(isinstance(template_string, Template)):
+ if not isinstance(template_string, Template):
template_string = Template(template_string)
fields = set(template_fields(template_string))
- if not(fields <= set(['file', 'line']) and ('file' in fields)):
+ if not (fields <= set(['file', 'line']) and ('file' in fields)):
raise ValueError("Only ${file} and ${line} are allowed as template variables, and ${file} must occur.")
edit_template = template_string
@@ -253,7 +253,7 @@ def edit(obj, editor=None, bg=None):
if editor:
set_editor(editor)
- elif not(edit_template):
+ elif not edit_template:
try:
ED = os.environ['EDITOR']
EDITOR = ED.split()
@@ -263,7 +263,7 @@ def edit(obj, editor=None, bg=None):
except (ValueError, KeyError, IndexError):
raise ValueError("Use set_edit_template() to set a default")
- if not(edit_template):
+ if not edit_template:
raise ValueError("Use set_edit_template() to set a default")
filename, lineno = file_and_line(obj)
diff --git a/src/sage/misc/element_with_label.py b/src/sage/misc/element_with_label.py
index 831b012e31a..e7ae38264be 100644
--- a/src/sage/misc/element_with_label.py
+++ b/src/sage/misc/element_with_label.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Elements with labels.
@@ -170,4 +169,4 @@ def __ne__(self, other):
sage: a != x
False
"""
- return not(self == other)
+ return not (self == other)
diff --git a/src/sage/misc/explain_pickle.py b/src/sage/misc/explain_pickle.py
index 2fb34a2234e..a0c6323270c 100644
--- a/src/sage/misc/explain_pickle.py
+++ b/src/sage/misc/explain_pickle.py
@@ -461,8 +461,8 @@ def run_pickle(self, p):
sage: sib(pe.run_pickle('T\5\0\0\0hello.')) # py2
{atomic:'hello'}
"""
- for (op, arg, pos) in genops(p):
- assert(not(self.stopped))
+ for op, arg, pos in genops(p):
+ assert not self.stopped
try:
handler = getattr(self, op.name)
except AttributeError:
@@ -472,8 +472,8 @@ def run_pickle(self, p):
else:
handler(arg)
- assert(self.stopped)
- assert(len(self.stack) == 1)
+ assert self.stopped
+ assert len(self.stack) == 1
return self.stack[0]
def check_value(self, v):
@@ -493,7 +493,7 @@ def check_value(self, v):
AssertionError
sage: pe.check_value(sib(7))
"""
- assert(isinstance(v, (SageInputExpression, PickleObject)))
+ assert isinstance(v, (SageInputExpression, PickleObject))
def push(self, v):
r"""
@@ -2442,13 +2442,13 @@ def unpickle_build(obj, state):
slots = None
if state is not None:
- assert(isinstance(state, dict))
+ assert isinstance(state, dict)
d = obj.__dict__
for k, v in state.items():
d[k] = v
if slots is not None:
- assert(isinstance(slots, dict))
+ assert isinstance(slots, dict)
for k, v in slots.items():
setattr(obj, k, v)
@@ -2635,11 +2635,11 @@ def pers_load(s):
if cpickle_ok:
cpickle_repr = repr(cpickle_res)
- assert(current_repr == generic_repr == cpickle_repr)
+ assert current_repr == generic_repr == cpickle_repr
print("result: " + current_repr)
else:
- assert(current_repr == generic_repr)
+ assert current_repr == generic_repr
print("result: " + current_repr + " (cPickle raised an exception!)")
diff --git a/src/sage/misc/functional.py b/src/sage/misc/functional.py
index 03697f08b7c..7a2bb8c0803 100644
--- a/src/sage/misc/functional.py
+++ b/src/sage/misc/functional.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Functional notation
diff --git a/src/sage/misc/latex.py b/src/sage/misc/latex.py
index df469ca8189..f409dacbddc 100644
--- a/src/sage/misc/latex.py
+++ b/src/sage/misc/latex.py
@@ -33,10 +33,9 @@
from tempfile import TemporaryDirectory
from sage.misc.cachefunc import cached_function, cached_method
+from sage.misc.lazy_attribute import lazy_attribute
from sage.structure.sage_object import SageObject
-from sage.misc.lazy_import import lazy_import
-lazy_import('sage.misc.html', ('MathJax', 'MathJaxExpr'), deprecation=31536)
COMMON_HEADER = r'''\usepackage{amsmath}
\usepackage{amssymb}
@@ -66,111 +65,6 @@
''')
-@cached_function
-def have_latex() -> bool:
- """
- Return ``True`` if this computer has the program ``latex``.
-
- If this computer does not have LaTeX installed, you may obtain it
- from http://ctan.org/.
-
- EXAMPLES::
-
- sage: from sage.misc.latex import have_latex
- sage: have_latex() # random
- True
- """
- from .superseded import deprecation
- deprecation(32650, 'the function have_latex() is replaced by: '
- 'from sage.features.latex import latex;latex().is_present()')
- from sage.features.latex import latex
- return latex().is_present()
-
-
-@cached_function
-def have_pdflatex() -> bool:
- """
- Return ``True`` if this computer has the program ``pdflatex``.
-
- If this computer does not have pdflatex installed, you may obtain it
- from http://ctan.org/.
-
- EXAMPLES::
-
- sage: from sage.misc.latex import have_pdflatex
- sage: have_pdflatex() # random
- True
- """
- from .superseded import deprecation
- deprecation(32650, 'the function have_pdflatex() is replaced by: '
- 'from sage.features.latex import pdflatex;pdflatex().is_present()')
- from sage.features.latex import pdflatex
- return pdflatex().is_present()
-
-
-@cached_function
-def have_xelatex() -> bool:
- """
- Return ``True`` if this computer has the program ``xelatex``.
-
- If this computer does not have xelatex installed, you may obtain it
- from http://ctan.org/.
-
- EXAMPLES::
-
- sage: from sage.misc.latex import have_xelatex
- sage: have_xelatex() # random
- True
- """
- from .superseded import deprecation
- deprecation(32650, 'the function have_xelatex() is replaced by: '
- 'from sage.features.latex import xelatex;xelatex().is_present()')
- from sage.features.latex import xelatex
- return xelatex().is_present()
-
-
-@cached_function
-def have_dvipng() -> bool:
- """
- Return ``True`` if this computer has the program ``dvipng``.
-
- If this computer does not have dvipng installed, you may obtain it
- from http://sourceforge.net/projects/dvipng/
-
- EXAMPLES::
-
- sage: from sage.misc.latex import have_dvipng
- sage: have_dvipng() # random
- True
- """
- from .superseded import deprecation
- deprecation(32650, 'the function have_dvipng() is replaced by: '
- 'from sage.features.dvipng import dvipng;dvipng().is_present()')
- from sage.features.dvipng import dvipng
- return dvipng().is_present()
-
-@cached_function
-def have_convert() -> bool:
- """
- Return ``True`` if this computer has the program ``convert``.
-
- If this computer does not have convert installed, you may obtain it
- (along with the rest of the ImageMagick suite) from
- http://www.imagemagick.org
-
- EXAMPLES::
-
- sage: from sage.misc.latex import have_convert
- sage: have_convert() # random
- True
- """
- from .superseded import deprecation
- deprecation(32650, 'the function have_convert() is replaced by: '
- 'from sage.features.imagemagick import imagemagick;imagemagick().is_present()')
- from sage.features.imagemagick import ImageMagick
- return ImageMagick().is_present()
-
-
def list_function(x):
r"""
Returns the LaTeX code for a list ``x``.
@@ -207,7 +101,7 @@ def tuple_function(x, combine_all=False):
- ``x`` -- a tuple
- - ``combine_all`` -- boolean (Default: ``False``) If ``combine_all`` is
+ - ``combine_all`` -- boolean (default: ``False``) If ``combine_all`` is
``True``, then it does not return a tuple and instead returns a string
with all the elements separated by a single space. It does not collapse
tuples which are inside tuples.
@@ -315,11 +209,9 @@ def str_function(x):
INPUT:
- - ``x`` -- a string.
-
- OUTPUT:
+ - ``x`` -- a string
- A string
+ OUTPUT: A string
EXAMPLES::
@@ -436,10 +328,10 @@ class LatexExpr(str):
Normally, objects of this class are created by a :func:`latex` call. It is
also possible to generate :class:`LatexExpr` directly from a string, which
must contain valid LaTeX code for typesetting in math mode (without dollar
- signs). In the Sage notebook, use
- :func:`~sage.repl.rich_output.pretty_print.pretty_print` or the "Typeset"
- checkbox to actually see the typeset LaTeX code; alternatively, from
- either the command-line or the notebook, use the :func:`view` function.
+ signs). In the Jupyter notebook, use
+ :func:`~sage.repl.rich_output.pretty_print.pretty_print` to actually see
+ the typeset LaTeX code; alternatively, from either the command-line or the
+ notebook, use the :func:`view` function.
INPUT:
@@ -583,6 +475,30 @@ def has_latex_attr(x) -> bool:
return hasattr(x, '_latex_') and not isinstance(x, type)
+@cached_function
+def default_engine():
+ """
+ Return the default latex engine and the official name of the engine.
+
+ This is determined by availability of the popular engines on the user's
+ system. It is assumed that at least latex is available.
+
+ EXAMPLES::
+
+ sage: from sage.misc.latex import default_engine
+ sage: default_engine() # random
+ ('lualatex', 'LuaLaTeX')
+ """
+ from sage.features.latex import pdflatex, xelatex, lualatex
+ if lualatex().is_present():
+ return 'lualatex', 'LuaLaTeX'
+ if xelatex().is_present():
+ return 'xelatex', 'XeLaTeX'
+ if pdflatex().is_present():
+ return 'pdflatex', 'pdfLaTeX'
+ return 'latex', 'LaTeX'
+
+
class _Latex_prefs_object(SageObject):
"""
An object that holds LaTeX global preferences.
@@ -598,23 +514,38 @@ def __init__(self, bb=False, delimiters=["(", ")"],
sage: latex_prefs = _Latex_prefs_object()
sage: TestSuite(latex_prefs).run(skip ="_test_pickling")
"""
- self._option = {}
- self._option["blackboard_bold"] = bb
- self._option["matrix_delimiters"] = list(delimiters)
- self._option["vector_delimiters"] = list(delimiters)
- self._option["matrix_column_alignment"] = matrix_column_alignment
- self._option["macros"] = ""
- self._option["preamble"] = ""
- self._option["engine"] = "pdflatex"
- self._option["engine_name"] = "LaTeX"
+ self.__option = {}
+ self.__option["blackboard_bold"] = bb
+ self.__option["matrix_delimiters"] = list(delimiters)
+ self.__option["vector_delimiters"] = list(delimiters)
+ self.__option["matrix_column_alignment"] = matrix_column_alignment
+ self.__option["macros"] = ""
+ self.__option["preamble"] = ""
+
+ @lazy_attribute
+ def _option(self):
+ """
+ This attribute contains the preferences list.
+ EXAMPLES::
+
+ sage: from sage.misc.latex import _Latex_prefs_object
+ sage: _Latex_prefs_object()._option # random
+ {'blackboard_bold': False,
+ 'matrix_delimiters': ['(', ')'],
+ 'vector_delimiters': ['(', ')'],
+ 'matrix_column_alignment': 'r',
+ 'macros': '',
+ 'preamble': '',
+ 'engine': 'lualatex',
+ 'engine_name': 'LuaLaTeX'}
+ """
+ self.__option["engine"] = default_engine()[0]
+ self.__option["engine_name"] = default_engine()[1]
+ return self.__option
-_Latex_prefs = _Latex_prefs_object()
-##############################################################
-# The Latex class is used to make slides and LaTeX output in
-# the Sage Notebook
-#########################################
+_Latex_prefs = _Latex_prefs_object()
def latex_extra_preamble():
@@ -664,25 +595,25 @@ def latex_extra_preamble():
def _run_latex_(filename, debug=False, density=150, engine=None, png=False, do_in_background=False):
"""
This runs LaTeX on the TeX file "filename.tex". It produces files
- "filename.dvi" (or "filename.pdf"` if engine is either ``pdflatex``
- or ``xelatex``) and if ``png`` is ``True``, "filename.png". If ``png``
- is ``True`` and dvipng cannot convert the dvi file to png (because of
- postscript specials or other issues), then dvips is called, and the
- PS file is converted to a png file.
+ ``filename.dvi`` (or ``filename.pdf``` if ``engine`` is either ``'pdflatex'``,
+ ``'xelatex'``, or ``'lualatex'``) and if ``png`` is ``True``, ``filename.png``.
+ If ``png`` is ``True`` and ``dvipng`` cannot convert the dvi file to png
+ (because of postscript specials or other issues), then ``dvips`` is called, and
+ the PS file is converted to a png file.
INPUT:
- - ``filename`` -- string: file to process, including full path
+ - ``filename`` -- string; file to process, including full path
- - ``debug`` -- bool (optional, default ``False``): whether to print
+ - ``debug`` -- bool (optional, default ``False``); whether to print
verbose debugging output
- - ``density`` -- integer (optional, default 150): how big output
+ - ``density`` -- integer (optional, default 150); how big output
image is.
- ``engine`` -- string: latex engine to use.
- - ``png`` -- bool (optional, default ``False``): whether to produce a
+ - ``png`` -- bool (optional, default ``False``); whether to produce a
png file.
- ``do_in_background`` -- bool (optional, default ``False``). Unused,
@@ -690,23 +621,23 @@ def _run_latex_(filename, debug=False, density=150, engine=None, png=False, do_i
OUTPUT:
- A string which could be a string starting with 'Error' (if
- there was a problem), or it could be 'pdf' or 'dvi'. If
- engine is latex or ``None``, then a dvi file is created, but if there
- appear to be problems with it (because of PS special commands, for
- example), then a pdf file is created instead. The function
- returns 'dvi' or 'pdf' to indicate which type of file is created.
- (Detecting problems requires that dvipng be installed; if it is
- not, then the dvi file is not checked for problems and 'dvi' is
- returned.) If engine is pdflatex or xelatex and there are no errors, then
- 'pdf' is returned.
+ A string which could be a string starting with ``'Error'`` (if there was a
+ problem), or it could be ``'pdf'`` or ``'dvi'``. If ``engine`` is
+ ``'latex'`` or ``None``, then a dvi file is created, but if there appear to
+ be problems with it (because of PS special commands, for example), then a
+ pdf file is created instead. The function returns ``'dvi'`` or ``'pdf'``
+ to indicate which type of file is created. (Detecting problems requires
+ that ``dvipng`` be installed; if it is not, then the dvi file is not checked
+ for problems and ``'dvi'`` is returned.) If ``engine`` is ``'pdflatex'``,
+ ``'xelatex'`` or ``'lualatex'`` and there are no errors, then ``'pdf'`` is
+ returned.
.. WARNING::
If ``png`` is ``True``, then when using latex (the default), you
- must have 'dvipng' (or 'dvips' and 'convert') installed on your
+ must have ``dvipng`` (or ``dvips`` and ``convert``) installed on your
operating system, or this command will not work. When using
- pdflatex or xelatex, you must have 'convert' installed.
+ ``pdflatex``, ``xelatex`` or ``lualatex``, you must have ``convert`` installed.
EXAMPLES::
@@ -740,6 +671,12 @@ def _run_latex_(filename, debug=False, density=150, engine=None, png=False, do_i
command = "xelatex"
suffix = "pdf"
return_suffix = "pdf"
+ elif engine == "lualatex":
+ from sage.features.latex import lualatex
+ lualatex().require()
+ command = "lualatex"
+ suffix = "pdf"
+ return_suffix = "pdf"
else:
raise ValueError("Unsupported LaTeX engine.")
@@ -758,10 +695,8 @@ def _run_latex_(filename, debug=False, density=150, engine=None, png=False, do_i
print("Go to http://sourceforge.net/projects/dvipng/ and")
print("http://www.imagemagick.org to download these programs.")
return "Error"
- # if png output + pdflatex, check to see if convert is installed.
- elif engine == "pdflatex":
- ImageMagick().require()
- elif engine == "xelatex":
+ # if png output + [pdf|xe|lua]latex, check to see if convert is installed.
+ elif engine in ["pdflatex", "xelatex", "lualatex"]:
ImageMagick().require()
# check_validity: check to see if the dvi file is okay by trying
# to convert to a png file. if this fails, return_suffix will be
@@ -814,7 +749,7 @@ def _run_latex_(filename, debug=False, density=150, engine=None, png=False, do_i
def subpcall(x):
return not call(x, stdout=redirect,
stderr=redirect, cwd=base)
- if engine == "pdflatex" or engine == "xelatex":
+ if engine in ['pdflatex', 'xelatex', 'lualatex']:
if debug:
print(lt)
if png:
@@ -871,12 +806,17 @@ def subpcall(x):
try:
with open(base + '/' + filename + '.log') as f:
print(f.read())
- except IOError:
+ except OSError:
pass
return "Error latexing slide."
return return_suffix
+# -------------------------------------------------------
+# The Latex class is used to make slides and LaTeX output
+# -------------------------------------------------------
+
+
class LatexCall:
r"""
Typeset Sage objects via a ``__call__`` method to this class,
@@ -981,7 +921,7 @@ class Latex(LatexCall):
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):
+ def __init__(self, debug=False, slide=False, density=150, engine=None):
"""
Initialize the latex builder.
@@ -993,7 +933,6 @@ def __init__(self, debug=False, slide=False, density=150, pdflatex=None, engine=
"""
self.__debug = debug
self.__slide = slide
- self.__pdflatex = pdflatex
self.__engine = engine
self.__density = density
@@ -1046,41 +985,36 @@ def _latex_preparse(self, s, locals):
s = s[:i] + k + t[j + 1:]
def eval(self, x, globals, strip=False, filename=None, debug=None,
- density=None, pdflatex=None, engine=None, locals={}):
+ density=None, engine=None, locals={}):
r"""
Compile the formatted tex given by ``x`` as a png and writes the
output file to the directory given by ``filename``.
INPUT:
- - ``globals`` -- a globals dictionary
+ - ``globals`` -- a globals dictionary
- - ``x`` -- string to evaluate.
+ - ``x`` -- string to evaluate
- - ``strip`` -- ignored
+ - ``strip`` -- ignored
- - ``filename`` -- output filename
+ - ``filename`` -- output filename
- - ``debug`` -- whether to print verbose debugging
- output
+ - ``debug`` -- whether to print verbose debugging output
- - ``density`` -- how big output image is.
+ - ``density`` -- how big output image is
- - ``pdflatex`` -- whether to use pdflatex. This is deprecated. Use
- ``engine`` option instead.
+ - ``engine`` -- latex engine to use. Currently ``'latex'``,
+ ``'pdflatex'``, ``'xelatex'`` and ``'lualatex'`` are supported
- - ``engine`` -- latex engine to use. Currently latex, pdflatex, and
- xelatex are supported.
-
- - ``locals`` - extra local variables used when
- evaluating Sage code in ``x``.
+ - ``locals`` - extra local variables used when evaluating Sage code in ``x``
.. WARNING::
- When using latex (the default), you must have 'dvipng' (or
- 'dvips' and 'convert') installed on your operating system,
- or this command will not work. When using pdflatex or xelatex, you
- must have 'convert' installed.
+ When using ``'latex'`` (the default), you must have ``dvipng`` (or
+ ``dvips`` and ``convert``) installed on your operating system, or
+ this command will not work. When using ``'pdflatex'``, ``'xelatex'``
+ or ``'lualatex'``, you must have ``convert`` installed.
OUTPUT:
@@ -1151,7 +1085,7 @@ def eval(self, x, globals, strip=False, filename=None, debug=None,
def blackboard_bold(self, t=None):
r"""nodetex
Controls whether Sage uses blackboard bold or ordinary bold
- face for typesetting ZZ, RR, etc.
+ face for typesetting ``ZZ``, ``RR``, etc.
INPUT:
@@ -1207,18 +1141,18 @@ def matrix_delimiters(self, left=None, right=None):
Good choices for ``left`` and ``right`` are any delimiters which
LaTeX understands and knows how to resize; some examples are:
- - parentheses: '(', ')'
- - brackets: '[', ']'
- - braces: '\\{', '\\}'
- - vertical lines: '|'
- - angle brackets: '\\langle', '\\rangle'
+ - parentheses: ``'('``, ``')'``
+ - brackets: ``'['``, ``']'``
+ - braces: ``'\\{'``, ``'\\}'``
+ - vertical lines: ``'|'``
+ - angle brackets: ``'\\langle'``, ``'\\rangle'``
.. NOTE::
- Putting aside aesthetics, you may combine these in any way
- imaginable; for example, you could set ``left`` to be a
- right-hand bracket ']' and ``right`` to be a right-hand
- brace '\\}', and it will be typeset correctly.
+ Putting aside aesthetics, you may combine these in any way
+ imaginable; for example, you could set ``left`` to be a right-hand
+ bracket ``']'`` and ``right`` to be a right-hand brace ``'\\}'``,
+ and it will be typeset correctly.
EXAMPLES::
@@ -1228,12 +1162,12 @@ def matrix_delimiters(self, left=None, right=None):
\left(\begin{array}{r}
17
\end{array}\right)
- sage: latex.matrix_delimiters("[", "]")
+ sage: latex.matrix_delimiters('[', ']')
sage: latex(a)
\left[\begin{array}{r}
17
\end{array}\right]
- sage: latex.matrix_delimiters(left="\\{")
+ sage: latex.matrix_delimiters(left='\\{')
sage: latex(a)
\left\{\begin{array}{r}
17
@@ -1243,7 +1177,7 @@ def matrix_delimiters(self, left=None, right=None):
Restore defaults::
- sage: latex.matrix_delimiters("(", ")")
+ sage: latex.matrix_delimiters('(', ')')
"""
if left is None and right is None:
return _Latex_prefs._option['matrix_delimiters']
@@ -1269,18 +1203,18 @@ def vector_delimiters(self, left=None, right=None):
Good choices for ``left`` and ``right`` are any delimiters which
LaTeX understands and knows how to resize; some examples are:
- - parentheses: '(', ')'
- - brackets: '[', ']'
- - braces: '\\{', '\\}'
- - vertical lines: '|'
- - angle brackets: '\\langle', '\\rangle'
+ - parentheses: ``'('``, ``')'``
+ - brackets: ``'['``, ``']'``
+ - braces: ``'\\{'``, ``'\\}'``
+ - vertical lines: ``'|'``
+ - angle brackets: ``'\\langle'``, ``'\\rangle'``
.. NOTE::
- Putting aside aesthetics, you may combine these in any way
- imaginable; for example, you could set ``left`` to be a
- right-hand bracket ']' and ``right`` to be a right-hand
- brace '\\}', and it will be typeset correctly.
+ Putting aside aesthetics, you may combine these in any way
+ imaginable; for example, you could set ``left`` to be a right-hand
+ bracket ``']'`` and ``right`` to be a right-hand brace ``'\\}'``, and it
+ will be typeset correctly.
EXAMPLES::
@@ -1288,10 +1222,10 @@ def vector_delimiters(self, left=None, right=None):
sage: a = vector(QQ, [1,2,3])
sage: latex(a)
\left(1,\,2,\,3\right)
- sage: latex.vector_delimiters("[", "]")
+ sage: latex.vector_delimiters('[', ']')
sage: latex(a)
\left[1,\,2,\,3\right]
- sage: latex.vector_delimiters(right="\\}")
+ sage: latex.vector_delimiters(right='\\}')
sage: latex(a)
\left[1,\,2,\,3\right\}
sage: latex.vector_delimiters()
@@ -1299,7 +1233,7 @@ def vector_delimiters(self, left=None, right=None):
Restore defaults::
- sage: latex.vector_delimiters("(", ")")
+ sage: latex.vector_delimiters('(', ')')
"""
if left is None and right is None:
return _Latex_prefs._option['vector_delimiters']
@@ -1387,7 +1321,7 @@ def check_file(self, file_name, more_info=""):
- ``file_name`` -- a string
- - ``more_info`` -- a string (default: "")
+ - ``more_info`` -- a string (default: ``""``)
Emit a warning if the local LaTeX installation does not
include ``file_name``. The string ``more_info`` is appended
@@ -1417,7 +1351,7 @@ def check_file(self, file_name, more_info=""):
def extra_macros(self, macros=None):
r"""nodetex
- String containing extra LaTeX macros to use with %latex and %html.
+ String containing extra LaTeX macros to use with ``%latex`` and ``%html``.
INPUT:
@@ -1500,7 +1434,7 @@ def extra_preamble(self, s=None):
def add_to_preamble(self, s):
r"""nodetex
Append to the string ``s`` of extra LaTeX macros, for use with
- %latex.
+ ``%latex``.
EXAMPLES::
@@ -1523,7 +1457,7 @@ def add_to_preamble(self, s):
sage: latex.extra_preamble()
'\\DeclareMathOperator{\\Ext}{Ext}\\usepackage{xypic}'
- Now one can put various xypic diagrams into a %latex cell, such as
+ Now one can put various xypic diagrams into a ``%latex`` cell, such as
::
@@ -1576,7 +1510,7 @@ def engine(self, e=None):
INPUT:
- - ``e`` -- 'latex', 'pdflatex', 'xelatex' or ``None``
+ - ``e`` -- ``'latex'``, ``'pdflatex'``, ``'xelatex'``, ``'lualatex'`` or ``None``
If ``e`` is ``None``, return the current engine.
@@ -1590,14 +1524,14 @@ def engine(self, e=None):
EXAMPLES::
- sage: latex.engine()
- 'pdflatex'
+ sage: latex.engine() # random
+ 'lualatex'
sage: latex.engine("latex")
sage: latex.engine()
'latex'
- sage: latex.engine("xelatex")
+ sage: latex.engine("pdflatex")
sage: latex.engine()
- 'xelatex'
+ 'pdflatex'
"""
if e is None:
return _Latex_prefs._option["engine"]
@@ -1611,8 +1545,12 @@ def engine(self, e=None):
elif e == "xelatex":
_Latex_prefs._option["engine"] = e
_Latex_prefs._option["engine_name"] = "XeLaTeX"
+ elif e == "lualatex":
+ _Latex_prefs._option["engine"] = e
+ _Latex_prefs._option["engine_name"] = "LuaLaTeX"
else:
- raise ValueError("%s is not a supported LaTeX engine. Use latex, pdflatex, or xelatex" % e)
+ raise ValueError("%s is not a supported LaTeX engine. Use latex, pdflatex, xelatex, or lualatex" % e)
+
# Note: latex used to be a separate function, which by default was
# only loaded in command-line mode: in the old notebook,
@@ -1621,13 +1559,10 @@ def engine(self, e=None):
# function. This has been changed around so that the contents of the
# old latex function are now in Latex.__call__; thus the following
# assignment.
-
-
latex = Latex()
# Ensure that latex appear in the sphinx doc as a function
# so that the link :func:`latex` is correctly set up.
latex.__doc__ = Latex.__call__.__doc__
-#########################################
def _latex_file_(objects, title='SAGE', debug=False,
@@ -1640,22 +1575,22 @@ def _latex_file_(objects, title='SAGE', debug=False,
INPUT:
- - ``objects`` -- list (or object)
+ - ``objects`` -- list (or object)
- - ``title`` -- string (default: 'Sage'): title for the document
+ - ``title`` -- string (default: 'Sage'); title for the document
- - ``math_left`` -- string (default: '\\['), left delimiter for math mode
+ - ``math_left`` -- string (default: '\\['), left delimiter for math mode
- - ``math_right`` -- string (default: '\\]'), right delimiter for math mode
+ - ``math_right`` -- string (default: '\\]'), right delimiter for math mode
- - ``debug`` -- bool (default: False): print verbose output
+ - ``debug`` -- bool (default: False); print verbose output
- - ``sep`` -- string (default: ''): separator between math objects
+ - ``sep`` -- string (default: ``''``); separator between math objects
- - ``tiny`` -- bool (default: False): use 'tiny' font.
+ - ``tiny`` -- bool (default: False); use 'tiny' font.
- - ``extra_preamble`` -- string (default: ''): extra LaTeX commands,
- inserted before "\\begin{document}"
+ - ``extra_preamble`` -- string (default: ``''``); extra LaTeX commands,
+ inserted before ``"\\begin{document}"``
This creates a string intended to be a LaTeX file containing the
LaTeX representations of objects. It contains the following:
@@ -1674,7 +1609,7 @@ def _latex_file_(objects, title='SAGE', debug=False,
Then if ``objects`` contains more than one element, for each
remaining element:
- - the string ``sep``: you can use this, for example, to add
+ - the string ``sep``; you can use this, for example, to add
vertical space between objects with ``sep='\\vspace{15mm}'``,
or to add a horizontal line between objects with
``sep='\\hrule'``, or to insert a page break between objects
@@ -1682,7 +1617,7 @@ def _latex_file_(objects, title='SAGE', debug=False,
- the LaTeX representation of the element
- The string ends with '\\end{document}'.
+ The string ends with ``'\\end{document}'``.
EXAMPLES::
@@ -1757,7 +1692,7 @@ def _latex_file_(objects, title='SAGE', debug=False,
def view(objects, title='Sage', debug=False, sep='', tiny=False,
- pdflatex=None, engine=None, viewer=None, tightpage=True, margin=None,
+ engine=None, viewer=None, tightpage=True, margin=None,
mode='inline', combine_all=False, **kwds):
r"""nodetex
Compute a latex representation of each object in objects, compile,
@@ -1766,50 +1701,49 @@ def view(objects, title='Sage', debug=False, sep='', tiny=False,
INPUT:
- - ``objects`` -- list (or object)
+ - ``objects`` -- list (or object)
- - ``title`` -- string (default: ``'Sage'``): title for the
+ - ``title`` -- string (default: ``'Sage'``); title for the
document
- - ``debug`` -- bool (default: ``False``): print verbose
+ - ``debug`` -- bool (default: ``False``); print verbose
output
- - ``sep`` -- string (default: ''): separator between
+ - ``sep`` -- string (default: ``''``); separator between
math objects
- - ``tiny`` -- bool (default: ``False``): use tiny font.
-
- - ``pdflatex`` -- bool (default: ``False``): use pdflatex. This is
- deprecated. Use ``'engine'`` option instead.
+ - ``tiny`` -- bool (default: ``False``); use tiny font.
- - ``engine`` -- string or ``None`` (default: ``None``). Can take the
+ - ``engine`` -- string or ``None`` (default: ``None``); can take the
following values:
- - ``None`` -- the value defined in the LaTeX global preferences
- ``latex.engine()`` is used.
+ - ``None`` -- the value defined in the LaTeX global preferences
+ ``latex.engine()`` is used.
- - ``'pdflatex'`` -- compilation does tex -> pdf
+ - ``'pdflatex'`` -- compilation does ``tex`` -> ``pdf``
- - ``'xelatex'`` -- compilation does tex -> pdf
+ - ``'xelatex'`` -- compilation does ``tex`` -> ``pdf``
- - ``'latex'`` -- compilation first tries tex -> dvi -> png and if an
- error occurs then tries dvi -> ps -> pdf. This is slower than
- ``'pdflatex'`` and known to be broken when overfull hbox are detected.
+ - ``'lualatex'`` -- compilation does ``tex`` -> ``pdf``
- - ``viewer`` -- string or ``None`` (default: ``None``): specify a viewer
+ - ``'latex'`` -- compilation first tries ``tex`` -> ``dvi`` -> ``png`` and if an
+ error occurs then tries ``dvi`` -> ``ps`` -> ``pdf``. This is slower than
+ ``'pdflatex'`` and known to be broken when overfull hboxes are detected.
+
+ - ``viewer`` -- string or ``None`` (default: ``None``); specify a viewer
to use; currently the only options are ``None`` and ``'pdf'``.
- - ``tightpage`` -- bool (default: ``True``): use the LaTeX package
- 'preview' with the 'tightpage' option.
+ - ``tightpage`` -- bool (default: ``True``); use the LaTeX package
+ ``preview`` with the 'tightpage' option.
- - ``margin`` -- float or ``None`` (default: ``None``): adds a margin
+ - ``margin`` -- float or ``None`` (default: ``None``); adds a margin
of ``margin`` mm; has no affect if the option ``tightpage`` is
``False``.
- - ``mode`` -- string (default: ``'inline'``): ``'display'`` for
+ - ``mode`` -- string (default: ``'inline'``); ``'display'`` for
displaymath or ``'inline'`` for inline math
- - ``combine_all`` -- bool (default: ``False``): If ``combine_all`` is
+ - ``combine_all`` -- bool (default: ``False``); if ``combine_all`` is
``True`` and the input is a tuple, then it does not return a tuple and
instead returns a string with all the elements separated by a single
space.
@@ -1829,20 +1763,17 @@ def view(objects, title='Sage', debug=False, sep='', tiny=False,
adds a horizontal line between objects, and ``sep='\\newpage'``
inserts a page break between objects.
- If ``pdflatex`` is ``True``, then the latex engine is set to
- pdflatex.
-
- If the ``engine`` is either ``pdflatex`` or ``xelatex``, it produces
- a pdf file. Otherwise, it produces a dvi file, and if the program dvipng is
- installed, it checks the dvi file by trying to convert it to a png
- file. If this conversion fails, the dvi file probably contains
- some postscript special commands or it has other issues which
- might make displaying it a problem; in this case, the file is
- converted to a pdf file, which is then displayed.
+ If the ``engine`` is either ``'pdflatex'``, ``'xelatex'``, or ``'lualatex'``,
+ it produces a pdf file. Otherwise, it produces a dvi file, and if the program
+ ``dvipng`` is installed, it checks the dvi file by trying to convert it to a
+ png file. If this conversion fails, the dvi file probably contains some
+ postscript special commands or it has other issues which might make
+ displaying it a problem; in this case, the file is converted to a pdf file,
+ which is then displayed.
Setting ``viewer`` to ``'pdf'`` forces the use of a separate
viewer, even in notebook mode. This also sets the latex engine to be
- ``pdflatex`` if the current engine is latex.
+ ``pdflatex`` if the current engine is ``latex``.
Setting the option ``tightpage`` to ``True`` (this is the default setting)
tells LaTeX to use the package 'preview' with the 'tightpage' option.
@@ -1921,7 +1852,7 @@ def view(objects, title='Sage', debug=False, sep='', tiny=False,
s = _latex_file_(objects, title=title, sep=sep, tiny=tiny, debug=debug, **latex_options)
if engine is None:
engine = _Latex_prefs._option["engine"]
- if pdflatex or (viewer == "pdf" and engine == "latex"):
+ if viewer == "pdf" and engine == "latex":
engine = "pdflatex"
# command line or notebook with viewer
@@ -1970,42 +1901,37 @@ def run_viewer():
def png(x, filename, density=150, debug=False,
- do_in_background=False, tiny=False, pdflatex=True, engine='pdflatex'):
+ do_in_background=False, tiny=False, engine=None):
"""
Create a png image representation of ``x`` and save to the given
filename.
INPUT:
- - ``x`` -- object to be displayed
-
- - ``filename`` -- file in which to save the image
+ - ``x`` -- object to be displayed
- - ``density`` -- integer (default: 150)
+ - ``filename`` -- file in which to save the image
- - ``debug`` -- bool (default: ``False``): print verbose
- output
+ - ``density`` -- integer (default: 150)
- - ``do_in_background`` -- bool (default: ``False``): Unused,
- kept for backwards compatibility
+ - ``debug`` -- bool (default: ``False``); print verbose output
- - ``tiny`` -- bool (default: ``False``): use 'tiny' font
+ - ``do_in_background`` -- bool (default: ``False``); Unused, kept for
+ backwards compatibility
- - ``pdflatex`` -- bool (default: ``True``): use pdflatex. This option is
- deprecated. Use ``engine`` option instead. See below.
+ - ``tiny`` -- bool (default: ``False``); use tiny font
- - ``engine`` -- (default: ``'pdflatex'``) ``'latex'``, ``'pdflatex'``,
- or ``'xelatex'``
+ - ``engine`` -- (default: ``None``) ``'latex'``, ``'pdflatex'``,
+ ``'xelatex'`` or ``'lualatex'``
EXAMPLES::
+ sage: # optional - imagemagick latex, needs sage.plot
sage: from sage.misc.latex import png
sage: import tempfile
- sage: with tempfile.NamedTemporaryFile(suffix=".png") as f: # random # optional - imagemagick latex, needs sage.plot
+ sage: with tempfile.NamedTemporaryFile(suffix=".png") as f: # random
....: png(ZZ[x], f.name)
"""
- if not pdflatex:
- engine = "latex"
import sage.plot.all
if sage.plot.graphics.is_Graphics(x):
x.save(filename)
@@ -2014,6 +1940,8 @@ def png(x, filename, density=150, debug=False,
s = _latex_file_([x], math_left='$\\displaystyle', math_right='$', title='',
debug=debug, tiny=tiny,
extra_preamble='\\textheight=2\\textheight')
+ if engine is None:
+ engine = _Latex_prefs._option["engine"]
# path name for permanent png output
abs_path_to_png = os.path.abspath(filename)
# temporary directory to store stuff
@@ -2076,13 +2004,11 @@ def repr_lincomb(symbols, coeffs):
INPUT:
- - ``symbols`` -- list of symbols
+ - ``symbols`` -- list of symbols
- - ``coeffs`` -- list of coefficients of the symbols
+ - ``coeffs`` -- list of coefficients of the symbols
- OUTPUT:
-
- A string
+ OUTPUT: A string
EXAMPLES::
@@ -2213,9 +2139,7 @@ def latex_varify(a, is_fname=False):
- ``a`` -- string
- OUTPUT:
-
- A string
+ OUTPUT: A string
EXAMPLES::
@@ -2260,7 +2184,7 @@ def latex_variable_name(x, is_fname=False):
2. If the variable name is suffixed by a number, we put the number
in the subscript.
- 3. If the variable name contains an '_' we start the subscript at
+ 3. If the variable name contains an ``'_'`` we start the subscript at
the underscore. Note that #3 trumps rule #2.
4. If a component of the variable is a Greek letter, escape it
@@ -2467,7 +2391,7 @@ def _repr_(self):
make sure that you have the most recent version of the TeX package
pstricks installed. Run 'latex.add_to_preamble("\\usepackage{pstricks}")'
and try viewing it again. Call 'view' with the option `engine='latex'`
--- the default behavior is to use pdflatex, which does not work with
+-- the default behavior is to use lualatex, which does not work with
pstricks. From the command line, this should pop open a nice window
with a picture of forces acting on a mass on a pendulum."""
diff --git a/src/sage/misc/latex_standalone.py b/src/sage/misc/latex_standalone.py
index d1d9d77d864..c24b076d805 100644
--- a/src/sage/misc/latex_standalone.py
+++ b/src/sage/misc/latex_standalone.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
Standalone LaTeX Document class and TikzPicture
diff --git a/src/sage/misc/lazy_attribute.pyx b/src/sage/misc/lazy_attribute.pyx
index 1f07870b8ec..74c3756a004 100644
--- a/src/sage/misc/lazy_attribute.pyx
+++ b/src/sage/misc/lazy_attribute.pyx
@@ -77,7 +77,7 @@ cdef class _lazy_attribute():
def _sage_src_lines_(self):
r"""
- Returns the source code location for the wrapped function.
+ Return the source code location for the wrapped function.
EXAMPLES::
@@ -87,15 +87,14 @@ cdef class _lazy_attribute():
sage: src[0]
'def banner():\n'
sage: lines
- 89
+ 88
"""
from sage.misc.sageinspect import sage_getsourcelines
return sage_getsourcelines(self.f)
-
def __get__(self, a, cls):
"""
- Implements the attribute access protocol.
+ Implement the attribute access protocol.
EXAMPLES::
@@ -143,6 +142,7 @@ cdef class _lazy_attribute():
raise
return result
+
class lazy_attribute(_lazy_attribute):
r"""
A lazy attribute for an object is like a usual attribute, except
@@ -509,7 +509,7 @@ class lazy_attribute(_lazy_attribute):
class lazy_class_attribute(lazy_attribute):
"""
- A lazy class attribute for an class is like a usual class attribute,
+ A lazy class attribute for a class is like a usual class attribute,
except that, instead of being computed when the class is constructed, it
is computed on the fly the first time it is accessed, either through the
class itself or trough on of its objects.
diff --git a/src/sage/misc/mrange.py b/src/sage/misc/mrange.py
index d69b82128f1..1c93c811b2e 100644
--- a/src/sage/misc/mrange.py
+++ b/src/sage/misc/mrange.py
@@ -336,8 +336,8 @@ def __len__(self):
"""
Return the cardinality of this iterator as an int.
- Raises a ``TypeError`` if the cardinality does not fit into a Python
- int.
+ This raises a :class:`TypeError` if the cardinality does not fit
+ into a Python int.
EXAMPLES::
diff --git a/src/sage/misc/package.py b/src/sage/misc/package.py
index dcae7d0c0fc..d64c53ac3e8 100644
--- a/src/sage/misc/package.py
+++ b/src/sage/misc/package.py
@@ -152,7 +152,7 @@ def spkg_type(name):
return None
try:
f = open(os.path.join(SAGE_PKGS, name, "type"))
- except IOError:
+ except OSError:
# Probably an empty directory => ignore
return None
@@ -390,7 +390,7 @@ def _spkg_inst_dirs():
"""
Generator for the installation manifest directories as resolved paths.
- It yields first ``SAGE_SPKG_INST``, then ``SAGE_VENV_SPKG_INST``,
+ It yields first ``SAGE_LOCAL_SPKG_INST``, then ``SAGE_VENV_SPKG_INST``,
if defined; but it both resolve to the same directory, it only yields
one element.
@@ -402,7 +402,7 @@ def _spkg_inst_dirs():
"""
last_inst_dir = None
- for inst_dir in (sage.env.SAGE_SPKG_INST, sage.env.SAGE_VENV_SPKG_INST):
+ for inst_dir in (sage.env.SAGE_LOCAL_SPKG_INST, sage.env.SAGE_VENV_SPKG_INST):
if inst_dir:
inst_dir = Path(inst_dir).resolve()
if inst_dir.is_dir() and inst_dir != last_inst_dir:
diff --git a/src/sage/misc/package_dir.py b/src/sage/misc/package_dir.py
index 3749a4f2a91..7d0e14cf799 100644
--- a/src/sage/misc/package_dir.py
+++ b/src/sage/misc/package_dir.py
@@ -615,7 +615,7 @@ def handle_file(root, file):
if package in ordinary_packages:
pass
elif ((missing_all_files := distributions_per_directives - package_distributions_per_all_files[package])
- and not(missing_all_files == set(['']) and len(distributions_per_directives) < 2)):
+ and not (missing_all_files == set(['']) and len(distributions_per_directives) < 2)):
s = '' if len(missing_all_files) == 1 else 's'
print(f'{package}: missing file{s} ' + ', '.join(_all_filename(distribution)
for distribution in missing_all_files))
diff --git a/src/sage/misc/random_testing.py b/src/sage/misc/random_testing.py
index 917d8789b4d..9dfb866bbc4 100644
--- a/src/sage/misc/random_testing.py
+++ b/src/sage/misc/random_testing.py
@@ -184,7 +184,7 @@ def test_add_commutes(trials, verbose=False):
b = QQ.random_element()
if verbose:
print("a == {}, b == {} ...".format(a, b))
- assert(a + b == b + a)
+ assert a + b == b + a
if verbose:
print("Passes!")
@@ -258,6 +258,6 @@ def test_add_is_mul(trials, verbose=False):
b = QQ.random_element()
if verbose:
print("a == {}, b == {} ...".format(a, b))
- assert(a + b == a * b)
+ assert a + b == a * b
if verbose:
print("Passes!")
diff --git a/src/sage/misc/replace_dot_all.py b/src/sage/misc/replace_dot_all.py
index 3415ea83058..4f872f2691b 100644
--- a/src/sage/misc/replace_dot_all.py
+++ b/src/sage/misc/replace_dot_all.py
@@ -298,7 +298,7 @@ def process_line(location, line, replacements, row_index, verbose=False):
sage: from sage.misc.replace_dot_all import *
sage: location = os.path.join(sage.env.SAGE_SRC, 'sage/plot/arc.py')
sage: replacements = find_replacements(location, package_regex='sage[.]plot[.]all', verbose=True); replacements
- [[476, 24, 'from sage.plot.graphics import Graphics']]
+ [[477, 24, 'from sage.plot.graphics import Graphics']]
sage: with open(location, "r") as file:
....: lines = file.readlines()
sage: row_index, col_number, *_ = replacements[0]
diff --git a/src/sage/misc/sage_input.py b/src/sage/misc/sage_input.py
index 00e8d96ee9e..be38a27d683 100644
--- a/src/sage/misc/sage_input.py
+++ b/src/sage/misc/sage_input.py
@@ -3475,11 +3475,11 @@ def verify_same(a, b):
"""
from sage.structure.element import is_Element
if is_Element(a):
- assert(a.parent() == b.parent())
+ assert a.parent() == b.parent()
else:
- assert(type(a) is type(b))
+ assert type(a) is type(b)
if isinstance(a, (RealIntervalFieldElement, ComplexIntervalFieldElement)):
- assert(a.endpoints() == b.endpoints()), "Expected %s == %s" % (a, b)
+ assert a.endpoints() == b.endpoints(), "Expected %s == %s" % (a, b)
return
if not (a == b):
diff --git a/src/sage/misc/sage_timeit.py b/src/sage/misc/sage_timeit.py
index 2f9c255543b..89c813e563b 100644
--- a/src/sage/misc/sage_timeit.py
+++ b/src/sage/misc/sage_timeit.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Accurate timing information for Sage commands
@@ -90,9 +89,9 @@ def __repr__(self):
1 loop, best of 2: 3.14 ns per loop
"""
if self.stats[0] > 1:
- s = u"%d loops, best of %d: %.*g %s per loop" % self.stats
+ s = "%d loops, best of %d: %.*g %s per loop" % self.stats
else:
- s = u"%d loop, best of %d: %.*g %s per loop" % self.stats
+ s = "%d loop, best of %d: %.*g %s per loop" % self.stats
if isinstance(s, str):
return s
@@ -217,7 +216,7 @@ def sage_timeit(stmt, globals_dict=None, preparse=None, number=0, repeat=3, prec
if stmt == "":
return ''
- units = [u"s", u"ms", u"μs", u"ns"]
+ units = ["s", "ms", "μs", "ns"]
scaling = [1, 1e3, 1e6, 1e9]
timer = timeit_.Timer()
diff --git a/src/sage/misc/sageinspect.py b/src/sage/misc/sageinspect.py
index 4d7c3f9c19c..9dd1defedea 100644
--- a/src/sage/misc/sageinspect.py
+++ b/src/sage/misc/sageinspect.py
@@ -2256,7 +2256,7 @@ class ParentMethods:
if B is None:
raise AttributeError
except AttributeError:
- raise IOError("could not get source code")
+ raise OSError("could not get source code")
return sage_getsourcelines(B)
# M should just be the top-most module.
# Hence, normally it is just 'sage'
@@ -2269,14 +2269,14 @@ class ParentMethods:
if B is None:
raise AttributeError
except AttributeError:
- raise IOError("could not get source code")
+ raise OSError("could not get source code")
return sage_getsourcelines(B)
lines, base_lineno = sage_getsourcelines(M)
# the rest of the function is copied from
# inspect.findsource
if not lines:
- raise IOError('could not get source code')
+ raise OSError('could not get source code')
if inspect.ismodule(obj):
return lines, base_lineno
@@ -2301,7 +2301,7 @@ class ParentMethods:
candidates.sort()
return inspect.getblock(lines[candidates[0][1]:]), candidates[0][1]+base_lineno
else:
- raise IOError('could not find class definition')
+ raise OSError('could not find class definition')
if inspect.ismethod(obj):
obj = obj.__func__
@@ -2313,7 +2313,7 @@ class ParentMethods:
obj = obj.f_code
if inspect.iscode(obj):
if not hasattr(obj, 'co_firstlineno'):
- raise IOError('could not find function definition')
+ raise OSError('could not find function definition')
pat = re.compile(r'^(\s*def\s)|(.*(?
#include "farey.hpp"
-#include "farey_symbol.h"
+#include "sage/modular/arithgroup/farey_symbol.h"
using namespace std;
diff --git a/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py b/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py
index 47ff7c34796..bab9b856ae1 100644
--- a/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py
+++ b/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py
@@ -117,7 +117,6 @@ def __init__(self, parent, M, check=True, **kwargs):
EXAMPLES::
- sage:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup, HeckeTriangleGroupElement
sage: lam = PolynomialRing(ZZ, 'lam').gen()
sage: M = matrix([[-1, 0], [-lam^4 + 5*lam^2 + lam - 5, -1]])
diff --git a/src/sage/modular/multiple_zeta_F_algebra.py b/src/sage/modular/multiple_zeta_F_algebra.py
index 89ac3436cb2..863a369940c 100644
--- a/src/sage/modular/multiple_zeta_F_algebra.py
+++ b/src/sage/modular/multiple_zeta_F_algebra.py
@@ -563,7 +563,7 @@ def homogeneous_from_vector(self, vec, N):
OUTPUT:
- an homogeneous element of :func:`F_ring` over this base ring
+ a homogeneous element of :func:`F_ring` over this base ring
.. SEEALSO:: :meth:`F_algebra.homogeneous_to_vector`
diff --git a/src/sage/modules/fp_graded/free_module.py b/src/sage/modules/fp_graded/free_module.py
index f8f2fac3f72..ea736cc54ea 100755
--- a/src/sage/modules/fp_graded/free_module.py
+++ b/src/sage/modules/fp_graded/free_module.py
@@ -985,7 +985,7 @@ def resolution(self, k, top_dim=None, verbose=False):
INPUT:
- - ``k`` -- an non-negative integer
+ - ``k`` -- a non-negative integer
- ``top_dim`` -- stop the computation at this degree. Ignored,
for compatibility with
:meth:`sage.modules.fp_graded.module.FPModule.resolution`.
diff --git a/src/sage/modules/fp_graded/module.py b/src/sage/modules/fp_graded/module.py
index cb715523ad7..af7329820de 100755
--- a/src/sage/modules/fp_graded/module.py
+++ b/src/sage/modules/fp_graded/module.py
@@ -1155,7 +1155,7 @@ def resolution(self, k, top_dim=None, verbose=False):
INPUT:
- - ``k`` -- an non-negative integer
+ - ``k`` -- a non-negative integer
- ``top_dim`` -- stop the computation at this degree
(optional, default ``None``, but required if the algebra is
not finite-dimensional)
diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py
index 7f9679a31d2..6e01cccc82f 100644
--- a/src/sage/modules/free_module.py
+++ b/src/sage/modules/free_module.py
@@ -772,7 +772,7 @@ def span(gens, base_ring=None, check=True, already_echelonized=False):
def basis_seq(V, vecs):
"""
- This converts a list vecs of vectors in V to an Sequence of
+ This converts a list vecs of vectors in V to a Sequence of
immutable vectors.
Should it? I.e. in most ``other`` parts of the system the return type
diff --git a/src/sage/modules/torsion_quadratic_module.py b/src/sage/modules/torsion_quadratic_module.py
index b98e6f89c4b..9192c65be92 100644
--- a/src/sage/modules/torsion_quadratic_module.py
+++ b/src/sage/modules/torsion_quadratic_module.py
@@ -323,9 +323,9 @@ def _module_constructor(self, V, W, check=False):
INPUT:
- - ``V`` -- an module
+ - ``V`` -- a module
- - ``W`` -- an submodule of ``V`` over the same base ring
+ - ``W`` -- a submodule of ``V`` over the same base ring
- ``check`` -- bool (default: ``False``);
diff --git a/src/sage/modules/vector_integer_sparse.pyx b/src/sage/modules/vector_integer_sparse.pyx
index 5fe48656495..d5f2958ea59 100644
--- a/src/sage/modules/vector_integer_sparse.pyx
+++ b/src/sage/modules/vector_integer_sparse.pyx
@@ -91,7 +91,7 @@ cdef Py_ssize_t mpz_binary_search(mpz_t* v, Py_ssize_t n, mpz_t x, Py_ssize_t* i
n -- integer (length of array v)
x -- mpz_t (integer)
OUTPUT:
- position of x (as an Py_ssize_t)
+ position of x (as a Py_ssize_t)
ins -- (call be pointer), the insertion point if x is not found.
"""
cdef Py_ssize_t i, j, k, c
diff --git a/src/sage/modules/with_basis/indexed_element.pyx b/src/sage/modules/with_basis/indexed_element.pyx
index db2ff9ee4a5..f366fe1bdf1 100644
--- a/src/sage/modules/with_basis/indexed_element.pyx
+++ b/src/sage/modules/with_basis/indexed_element.pyx
@@ -27,6 +27,7 @@ from sage.misc.superseded import deprecation
from sage.typeset.ascii_art import AsciiArt, empty_ascii_art, ascii_art
from sage.typeset.unicode_art import UnicodeArt, empty_unicode_art, unicode_art
from sage.data_structures.blas_dict cimport add, negate, scal, axpy
+from sage.categories.modules import _Fields
cdef class IndexedFreeModuleElement(ModuleElement):
@@ -958,6 +959,12 @@ cdef class IndexedFreeModuleElement(ModuleElement):
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for /: 'str' and 'CombinatorialFreeModule_with_category.element_class'
+
+ sage: L = LazyPowerSeriesRing(QQ, 't')
+ sage: t = L.gen()
+ sage: F = algebras.Free(L, ['A', 'B'])
+ sage: A, B = F.gens()
+ sage: f = t*A + t**2*B/2
"""
if not isinstance(left, IndexedFreeModuleElement):
return NotImplemented
@@ -966,7 +973,7 @@ cdef class IndexedFreeModuleElement(ModuleElement):
F = self._parent
B = self.base_ring()
D = self._monomial_coefficients
- if not B.is_field():
+ if B not in _Fields:
return type(self)(F, {k: c._divide_if_possible(x)
for k, c in D.items()})
diff --git a/src/sage/numerical/mip.pxd b/src/sage/numerical/mip.pxd
index 612324a5424..e73cc408d09 100644
--- a/src/sage/numerical/mip.pxd
+++ b/src/sage/numerical/mip.pxd
@@ -3,8 +3,11 @@ cdef extern from *:
cdef int REAL = -1
cdef int INTEGER = 0
+from sage.sets.family cimport FiniteFamily
from sage.structure.sage_object cimport SageObject
from sage.numerical.backends.generic_backend cimport GenericBackend
+
+
cdef class MIPVariable
@@ -26,10 +29,8 @@ cdef class MixedIntegerLinearProgram(SageObject):
cpdef sum(self, L) noexcept
-cdef class MIPVariable(SageObject):
+cdef class MIPVariable(FiniteFamily):
cdef MixedIntegerLinearProgram _p
- cdef dict _dict
- cdef bint _dynamic_indices
cdef int _vtype
cdef str _name
cdef object _lower_bound
diff --git a/src/sage/numerical/mip.pyx b/src/sage/numerical/mip.pyx
index 1e6e6caa7bd..803724bf29b 100644
--- a/src/sage/numerical/mip.pyx
+++ b/src/sage/numerical/mip.pyx
@@ -3237,7 +3237,7 @@ class MIPSolverException(RuntimeError):
pass
-cdef class MIPVariable(SageObject):
+cdef class MIPVariable(FiniteFamily):
r"""
``MIPVariable`` is a variable used by the class
``MixedIntegerLinearProgram``.
@@ -3286,17 +3286,16 @@ cdef class MIPVariable(SageObject):
MIPVariable with 0 real components, >= 0
"""
- self._dict = {}
+ super().__init__({})
self._p = mip
self._vtype = vtype
self._lower_bound = lower_bound
self._upper_bound = upper_bound
self._name = name
- self._dynamic_indices = True
if indices is not None:
for i in indices:
self[i] # creates component
- self._dynamic_indices = False
+ self._keys = indices
def __copy__(self):
r"""
@@ -3398,9 +3397,9 @@ cdef class MIPVariable(SageObject):
"""
cdef int j
- if i in self._dict:
- return self._dict[i]
- if not self._dynamic_indices:
+ if i in self._dictionary:
+ return self._dictionary[i]
+ if self._keys is not None:
raise IndexError("{} does not index a component of {}".format(i, self))
zero = self._p._backend.zero()
name = self._name + "[" + str(i) + "]" if self._name else None
@@ -3415,7 +3414,7 @@ cdef class MIPVariable(SageObject):
name=name)
v = self._p.linear_functions_parent()({j : 1})
self._p._variables[v] = j
- self._dict[i] = v
+ self._dictionary[i] = v
return v
def copy_for_mip(self, mip):
@@ -3461,8 +3460,8 @@ cdef class MIPVariable(SageObject):
"""
cdef MIPVariable cp = type(self)(mip, self._vtype, self._name,
self._lower_bound, self._upper_bound)
- cp._dict = copy(self._dict)
- cp._dynamic_indices = self._dynamic_indices
+ cp._dictionary = copy(self._dictionary)
+ cp._keys = self._keys
return cp
def set_min(self, min):
@@ -3501,7 +3500,7 @@ cdef class MIPVariable(SageObject):
"""
self._lower_bound = min
- for v in self._dict.values():
+ for v in self._dictionary.values():
self._p.set_min(v,min)
def set_max(self, max):
@@ -3537,7 +3536,7 @@ cdef class MIPVariable(SageObject):
True
"""
self._upper_bound = max
- for v in self._dict.values():
+ for v in self._dictionary.values():
self._p.set_max(v,max)
def _repr_(self):
@@ -3570,9 +3569,9 @@ cdef class MIPVariable(SageObject):
"""
s = 'MIPVariable{0} with {1} {2} component{3}'.format(
" " + self._name if self._name else "",
- len(self._dict),
+ len(self._dictionary),
{0:"binary", -1:"real", 1:"integer"}[self._vtype],
- "s" if len(self._dict) != 1 else "")
+ "s" if len(self._dictionary) != 1 else "")
if (self._vtype != 0) and (self._lower_bound is not None):
s += ', >= {0}'.format(self._lower_bound)
if (self._vtype != 0) and (self._upper_bound is not None):
@@ -3591,11 +3590,11 @@ cdef class MIPVariable(SageObject):
sage: sorted(v.keys())
[0, 1]
"""
- return self._dict.keys()
+ return self._dictionary.keys()
def items(self):
r"""
- Return the pairs (keys,value) contained in the dictionary.
+ Return the pairs (keys, value) contained in the dictionary.
EXAMPLES::
@@ -3605,7 +3604,7 @@ cdef class MIPVariable(SageObject):
sage: sorted(v.items())
[(0, x_0), (1, x_1)]
"""
- return self._dict.items()
+ return self._dictionary.items()
def values(self):
r"""
@@ -3619,7 +3618,7 @@ cdef class MIPVariable(SageObject):
sage: sorted(v.values(), key=str)
[x_0, x_1]
"""
- return self._dict.values()
+ return self._dictionary.values()
def mip(self):
r"""
diff --git a/src/sage/parallel/map_reduce.py b/src/sage/parallel/map_reduce.py
index 66fea7f394f..097ac97c1dc 100644
--- a/src/sage/parallel/map_reduce.py
+++ b/src/sage/parallel/map_reduce.py
@@ -1786,7 +1786,7 @@ def send_partial_result(self):
r"""
Send results to the MapReduce process.
- Send the result stored in ``self._res`` to the master an reinitialize it to
+ Send the result stored in ``self._res`` to the master and reinitialize it to
``master.reduce_init``.
EXAMPLES::
diff --git a/src/sage/plot/animate.py b/src/sage/plot/animate.py
index c917452e2be..0ce77981f34 100644
--- a/src/sage/plot/animate.py
+++ b/src/sage/plot/animate.py
@@ -453,7 +453,8 @@ def make_image(self, frame, filename, **kwds):
....: floor(G.ymin()), ceil(G.ymax()))
....: G.save_image(filename, **kwds)
- sage: B = MyAnimation([graphs.CompleteGraph(n) for n in range(7,11)], figsize=5)
+ sage: B = MyAnimation([graphs.CompleteGraph(n)
+ ....: for n in range(7,11)], figsize=5)
sage: d = B.png()
sage: v = os.listdir(d); v.sort(); v
['00000000.png', '00000001.png', '00000002.png', '00000003.png']
diff --git a/src/sage/plot/arc.py b/src/sage/plot/arc.py
index 84a62554118..8da333ee12b 100644
--- a/src/sage/plot/arc.py
+++ b/src/sage/plot/arc.py
@@ -56,6 +56,7 @@ def __init__(self, x, y, r1, r2, angle, s1, s2, options):
EXAMPLES::
+ sage: # needs sage.symbolic
sage: A = arc((2,3),1,1,pi/4,(0,pi))
sage: A[0].x == 2
True
diff --git a/src/sage/plot/arrow.py b/src/sage/plot/arrow.py
index 26bb131f713..324a87bd17b 100644
--- a/src/sage/plot/arrow.py
+++ b/src/sage/plot/arrow.py
@@ -398,7 +398,7 @@ def _render_on_subplot(self, subplot):
class CheckNthSubPath():
def __init__(self, patch, n):
"""
- creates an callable object that returns True if the
+ creates a callable object that returns True if the
provided path is the n-th path from the patch.
"""
self._patch = patch
diff --git a/src/sage/plot/colors.py b/src/sage/plot/colors.py
index 3281199400b..5eeddc373fd 100644
--- a/src/sage/plot/colors.py
+++ b/src/sage/plot/colors.py
@@ -215,7 +215,7 @@ def mod_one(x):
0.0
sage: mod_one(-11/7)
0.4285714285714286
- sage: mod_one(pi) + mod_one(-pi)
+ sage: mod_one(pi) + mod_one(-pi) # needs sage.symbolic
1.0
"""
x = float(x)
@@ -361,7 +361,7 @@ def rgbcolor(c, space='rgb'):
class Color():
def __init__(self, r='#0000ff', g=None, b=None, space='rgb'):
"""
- An Red-Green-Blue (RGB) color model color object. For most
+ A Red-Green-Blue (RGB) color model color object. For most
consumer-grade devices (e.g., CRTs, LCDs, and printers), as
well as internet applications, this is a point in the sRGB
absolute color space. The Hue-Saturation-Lightness (HSL),
@@ -1146,9 +1146,10 @@ def hue(h, s=1, v=1):
This function makes it easy to sample a broad range of colors for
graphics::
+ sage: # needs sage.symbolic
sage: p = Graphics()
sage: for phi in xsrange(0, 2 * pi, 1 / pi):
- ....: p += plot(sin(x + phi), (x, -7, 7), rgbcolor = hue(phi))
+ ....: p += plot(sin(x + phi), (x, -7, 7), rgbcolor=hue(phi))
sage: p
Graphics object consisting of 20 graphics primitives
diff --git a/src/sage/plot/ellipse.py b/src/sage/plot/ellipse.py
index 821906ecf0a..788db0fd76b 100644
--- a/src/sage/plot/ellipse.py
+++ b/src/sage/plot/ellipse.py
@@ -220,7 +220,7 @@ def plot3d(self):
TESTS::
sage: from sage.plot.ellipse import Ellipse
- sage: Ellipse(0,0,2,1,pi/4,{}).plot3d()
+ sage: Ellipse(0,0,2,1,pi/4,{}).plot3d() # needs sage.symbolic
Traceback (most recent call last):
...
NotImplementedError
diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py
index adcccff059b..b6465b8f9a9 100644
--- a/src/sage/plot/graphics.py
+++ b/src/sage/plot/graphics.py
@@ -64,7 +64,7 @@ def is_Graphics(x):
sage: from sage.plot.graphics import is_Graphics
sage: is_Graphics(1)
False
- sage: is_Graphics(disk((0.0, 0.0), 1, (0, pi/2)))
+ sage: is_Graphics(disk((0.0, 0.0), 1, (0, pi/2))) # needs sage.symbolic
True
"""
return isinstance(x, Graphics)
@@ -1359,6 +1359,7 @@ def _set_scale(self, subplot, scale=None, base=None):
EXAMPLES::
+ sage: # needs sage.symbolic
sage: p = plot(x, 1, 10)
sage: fig = p.matplotlib()
sage: ax = fig.get_axes()[0]
@@ -1373,6 +1374,7 @@ def _set_scale(self, subplot, scale=None, base=None):
TESTS::
+ sage: # needs sage.symbolic
sage: p._set_scale(ax, 'log')
Traceback (most recent call last):
...
@@ -1797,7 +1799,7 @@ def show(self, **kwds):
::
- sage: G.show(scale='semilogy', base=(3,2)) # base ignored for x-axis # needs sage.symbolic
+ sage: G.show(scale='semilogy', base=(3,2)) # base ignored for x-axis # needs sage.symbolic
The scale can be also given as a 2-tuple or a 3-tuple.::
@@ -1816,7 +1818,7 @@ def show(self, **kwds):
some examples.::
sage: G = list_plot([10**i for i in range(10)]) # long time, needs sage.symbolic
- sage: G.show(scale='semilogy') # long time
+ sage: G.show(scale='semilogy') # long time, needs sage.symbolic
::
diff --git a/src/sage/plot/histogram.py b/src/sage/plot/histogram.py
index 388c2d1391d..e10229417fc 100644
--- a/src/sage/plot/histogram.py
+++ b/src/sage/plot/histogram.py
@@ -274,8 +274,8 @@ def histogram(datalist, **options):
sage: nv = normalvariate
sage: H = histogram([nv(0, 1) for _ in range(1000)], bins=20, density=True, range=[-5, 5])
- sage: P = plot(1/sqrt(2*pi)*e^(-x^2/2), (x, -5, 5), color='red', linestyle='--')
- sage: H+P
+ sage: P = plot(1/sqrt(2*pi)*e^(-x^2/2), (x, -5, 5), color='red', linestyle='--') # needs sage.symbolic
+ sage: H + P # needs sage.symbolic
Graphics object consisting of 2 graphics primitives
.. PLOT::
diff --git a/src/sage/plot/line.py b/src/sage/plot/line.py
index c945946484a..8e9cb97891f 100644
--- a/src/sage/plot/line.py
+++ b/src/sage/plot/line.py
@@ -559,6 +559,7 @@ def line2d(points, **options):
A purple plot of the Riemann zeta function `\zeta(1/2 + it)`, `0 < t < 30`::
+ sage: # needs sage.libs.pari sage.rings.complex_double
sage: i = CDF.gen()
sage: v = [zeta(0.5 + n/10 * i) for n in range(300)]
sage: L = [(z.real(), z.imag()) for z in v]
@@ -590,6 +591,7 @@ def line2d(points, **options):
A red, blue, and green "cool cat"::
+ sage: # needs sage.symbolic
sage: G = plot(-cos(x), -2, 2, thickness=5, rgbcolor=(0.5,1,0.5))
sage: P = polygon([[1,2], [5,6], [5,0]], rgbcolor=(1,0,0))
sage: Q = polygon([(-x,y) for x,y in P[0]], rgbcolor=(0,0,1))
diff --git a/src/sage/plot/matrix_plot.py b/src/sage/plot/matrix_plot.py
index f113f5aaa62..abaeb3e6fc4 100644
--- a/src/sage/plot/matrix_plot.py
+++ b/src/sage/plot/matrix_plot.py
@@ -535,7 +535,7 @@ def matrix_plot(mat, xrange=None, yrange=None, **options):
::
- sage: matrix_plot([[sin(x), cos(x)], [1, 0]])
+ sage: matrix_plot([[sin(x), cos(x)], [1, 0]]) # needs sage.symbolic
Traceback (most recent call last):
...
TypeError: mat must be a Matrix or a two dimensional array
diff --git a/src/sage/plot/plot.py b/src/sage/plot/plot.py
index b614b2ef3db..b25ba785326 100644
--- a/src/sage/plot/plot.py
+++ b/src/sage/plot/plot.py
@@ -1763,7 +1763,7 @@ def b(n): return lambda x: bessel_J(n, x) + 0.5*(n-1)
.. PLOT::
- g = plot(sin(pi*x), (x, -8, 8), ticks=[[-7,-3,0,3,7],[-1/2,0,1/2]])
+ g = plot(sin(pi*x), (x, -8, 8), ticks=[[-7,-3,0,3,7], [-1/2,0,1/2]])
sphinx_plot(g)
::
@@ -1799,7 +1799,7 @@ def b(n): return lambda x: bessel_J(n, x) + 0.5*(n-1)
.. PLOT::
- g = plot(x**2, (x,0,3), ticks=[[1,2.5],[0.5,1,2]], tick_formatter=[["$x_1$","$x_2$"],["$y_1$","$y_2$","$y_3$"]])
+ g = plot(x**2, (x,0,3), ticks=[[1,2.5],[0.5,1,2]], tick_formatter=[["$x_1$","$x_2$"], ["$y_1$","$y_2$","$y_3$"]])
sphinx_plot(g)
You can force Type 1 fonts in your figures by providing the relevant
@@ -1891,7 +1891,7 @@ def f(x): return (floor(x)+0.5) / (1-(x-0.5)**2)
sage: plot(arcsec(x/2), -2, 2) # plot should be empty; no valid points
Graphics object consisting of 0 graphics primitives
- sage: plot(sqrt(x^2-1), -2, 2) # [-1, 1] is excluded automatically
+ sage: plot(sqrt(x^2 - 1), -2, 2) # [-1, 1] is excluded automatically
Graphics object consisting of 2 graphics primitives
.. PLOT::
@@ -2573,7 +2573,7 @@ def parametric_plot(funcs, *args, **kwargs):
is 1, so that circles look like circles. ::
sage: t = var('t')
- sage: parametric_plot( (cos(t), sin(t)), (t, 0, 2*pi))
+ sage: parametric_plot((cos(t), sin(t)), (t, 0, 2*pi))
Graphics object consisting of 1 graphics primitive
.. PLOT::
@@ -2613,23 +2613,25 @@ def parametric_plot(funcs, *args, **kwargs):
.. PLOT::
- t =var('t')
+ t = var('t')
g = parametric_plot((t, t**2), (t, -4, 4), fill=True)
sphinx_plot(g)
A filled Hypotrochoid::
- sage: parametric_plot([cos(x) + 2 * cos(x/4), sin(x) - 2 * sin(x/4)], (x,0, 8*pi), fill=True)
+ sage: parametric_plot([cos(x) + 2 * cos(x/4), sin(x) - 2 * sin(x/4)],
+ ....: (x, 0, 8*pi), fill=True)
Graphics object consisting of 2 graphics primitives
.. PLOT::
- g = parametric_plot([cos(x) + 2 * cos(x/4), sin(x) - 2 * sin(x/4)], (x,0, 8*pi), fill=True)
+ g = parametric_plot([cos(x) + 2 * cos(x/4), sin(x) - 2 * sin(x/4)], (x, 0, 8*pi), fill=True)
sphinx_plot(g)
::
- sage: parametric_plot( (5*cos(x), 5*sin(x), x), (x,-12, 12), plot_points=150, color="red") # long time
+ sage: parametric_plot((5*cos(x), 5*sin(x), x), (x, -12, 12), # long time
+ ....: plot_points=150, color="red")
Graphics3d Object
.. PLOT::
@@ -2829,7 +2831,8 @@ def polar_plot(funcs, *args, **kwds):
Fill the area between two functions::
- sage: polar_plot(cos(4*x) + 1.5, 0, 2*pi, fill=0.5 * cos(4*x) + 2.5, fillcolor='orange')
+ sage: polar_plot(cos(4*x) + 1.5, 0, 2*pi, fill=0.5 * cos(4*x) + 2.5,
+ ....: fillcolor='orange')
Graphics object consisting of 2 graphics primitives
.. PLOT::
@@ -2839,7 +2842,8 @@ def polar_plot(funcs, *args, **kwds):
Fill the area between several spirals::
- sage: polar_plot([(1.2+k*0.2)*log(x) for k in range(6)], 1, 3 * pi, fill={0: [1], 2: [3], 4: [5]})
+ sage: polar_plot([(1.2+k*0.2)*log(x) for k in range(6)], 1, 3 * pi,
+ ....: fill={0: [1], 2: [3], 4: [5]})
Graphics object consisting of 9 graphics primitives
.. PLOT::
@@ -2895,7 +2899,7 @@ def list_plot(data, plotjoined=False, **kwargs):
EXAMPLES::
- sage: list_plot([i^2 for i in range(5)]) # long time
+ sage: list_plot([i^2 for i in range(5)]) # long time
Graphics object consisting of 1 graphics primitive
.. PLOT::
@@ -3008,7 +3012,9 @@ def list_plot(data, plotjoined=False, **kwargs):
sage: list_plot(x_coords, y_coords)
Traceback (most recent call last):
...
- TypeError: The second argument 'plotjoined' should be boolean (True or False). If you meant to plot two lists 'x' and 'y' against each other, use 'list_plot(list(zip(x,y)))'.
+ TypeError: The second argument 'plotjoined' should be boolean (True or False).
+ If you meant to plot two lists 'x' and 'y' against each other,
+ use 'list_plot(list(zip(x,y)))'.
Dictionaries with numeric keys and values can be plotted::
@@ -3055,12 +3061,12 @@ def list_plot(data, plotjoined=False, **kwargs):
Instead this will work. We drop the point `(0,1)`.::
- sage: list_plot(list(zip(range(1,len(yl)), yl[1:])), scale='loglog') # long time
+ sage: list_plot(list(zip(range(1,len(yl)), yl[1:])), scale='loglog') # long time
Graphics object consisting of 1 graphics primitive
We use :func:`list_plot_loglog` and plot in a different base.::
- sage: list_plot_loglog(list(zip(range(1,len(yl)), yl[1:])), base=2) # long time
+ sage: list_plot_loglog(list(zip(range(1,len(yl)), yl[1:])), base=2) # long time
Graphics object consisting of 1 graphics primitive
.. PLOT::
@@ -3267,22 +3273,22 @@ def plot_semilogy(funcs, *args, **kwds):
EXAMPLES::
- sage: plot_semilogy(exp, (1,10)) # long time # plot in semilogy scale, base 10
+ sage: plot_semilogy(exp, (1, 10)) # long time # plot in semilogy scale, base 10
Graphics object consisting of 1 graphics primitive
.. PLOT::
- g = plot_semilogy(exp, (1,10)) # long time # plot in semilogy scale, base 10
+ g = plot_semilogy(exp, (1,10)) # long time # plot in semilogy scale, base 10
sphinx_plot(g)
::
- sage: plot_semilogy(exp, (1,10), base=2) # long time # with base 2
+ sage: plot_semilogy(exp, (1, 10), base=2) # long time # with base 2
Graphics object consisting of 1 graphics primitive
.. PLOT::
- g = plot_semilogy(exp, (1,10), base=2) # long time # with base 2
+ g = plot_semilogy(exp, (1,10), base=2) # long time # with base 2
sphinx_plot(g)
"""
@@ -3505,13 +3511,14 @@ def reshape(v, n, m):
::
- sage: M = [[plot(sin(k*x),(x,-pi,pi)) for k in range(3)],[plot(cos(j*x),(x,-pi,pi)) for j in [3..5]]]
+ sage: M = [[plot(sin(k*x), (x,-pi,pi)) for k in range(3)],
+ ....: [plot(cos(j*x), (x,-pi,pi)) for j in [3..5]]]
sage: graphics_array(M,6,1) # long time (up to 4s on sage.math, 2012)
Graphics Array of size 6 x 1
TESTS::
- sage: L = [plot(sin(k*x),(x,-pi,pi)) for k in [1..3]]
+ sage: L = [plot(sin(k*x), (x,-pi,pi)) for k in [1..3]]
sage: graphics_array(L,0,-1) # indirect doctest
Traceback (most recent call last):
...
@@ -3620,6 +3627,7 @@ def h(x): return sin(4*x)
It is possible to use ``figsize`` to change the size of the plot
as a whole::
+ sage: x = var('x')
sage: L = [plot(sin(k*x), (x,-pi,pi)) for k in [1..3]]
sage: ga = graphics_array(L)
sage: ga.show(figsize=[5,3]) # smallish and compact
@@ -3860,7 +3868,8 @@ def adaptive_refinement(f, p1, p2, adaptive_tolerance=0.01,
TESTS::
sage: from sage.plot.plot import adaptive_refinement
- sage: adaptive_refinement(sin, (0,0), (pi,0), adaptive_tolerance=0.01, adaptive_recursion=0)
+ sage: adaptive_refinement(sin, (0,0), (pi,0), adaptive_tolerance=0.01,
+ ....: adaptive_recursion=0)
[]
sage: adaptive_refinement(sin, (0,0), (pi,0), adaptive_tolerance=0.01)
[(0.125*pi, 0.3826834323650898), (0.1875*pi, 0.5555702330196022),
@@ -3881,7 +3890,8 @@ def adaptive_refinement(f, p1, p2, adaptive_tolerance=0.01,
sage: f(x) = sin(1/x)
sage: n1 = len(adaptive_refinement(f, (0,0), (pi,0), adaptive_tolerance=0.01)); n1
15
- sage: n2 = len(adaptive_refinement(f, (0,0), (pi,0), adaptive_recursion=10, adaptive_tolerance=0.01)); n2
+ sage: n2 = len(adaptive_refinement(f, (0,0), (pi,0), adaptive_recursion=10,
+ ....: adaptive_tolerance=0.01)); n2
79
sage: n3 = len(adaptive_refinement(f, (0,0), (pi,0), adaptive_tolerance=0.001)); n3
26
diff --git a/src/sage/plot/plot3d/base.pyx b/src/sage/plot/plot3d/base.pyx
index 7588cde2e27..b9dc7b310ca 100644
--- a/src/sage/plot/plot3d/base.pyx
+++ b/src/sage/plot/plot3d/base.pyx
@@ -285,13 +285,8 @@ cdef class Graphics3d(SageObject):
tachyon.png.save_as(preview_png)
else:
# Java needs absolute paths
- # On cygwin, they should be native ones
scene_native = scene_zip
- if sys.platform == 'cygwin':
- import cygwin
- scene_native = cygwin.cygpath(scene_native, 'w')
-
script = '''set defaultdirectory "{0}"\nscript SCRIPT\n'''.format(scene_native)
jdata.export_image(targetfile=preview_png, datafile=script,
image_type="PNG",
@@ -2003,9 +1998,10 @@ end_scene""".format(
This works when faces have more then 3 sides::
- sage: P = polytopes.dodecahedron() # needs sage.geometry.polyhedron
- sage: Q = P.plot().all[-1] # needs sage.geometry.polyhedron
- sage: print(Q.stl_binary()[:40].decode('ascii')) # needs sage.geometry.polyhedron
+ sage: # needs sage.geometry.polyhedron sage.groups
+ sage: P = polytopes.dodecahedron()
+ sage: Q = P.plot().all[-1]
+ sage: print(Q.stl_binary()[:40].decode('ascii'))
STL binary file / made by SageMath / ###
"""
import struct
@@ -2065,9 +2061,10 @@ end_scene""".format(
Now works when faces have more then 3 sides::
- sage: P = polytopes.dodecahedron() # needs sage.geometry.polyhedron
- sage: Q = P.plot().all[-1] # needs sage.geometry.polyhedron
- sage: print(Q.stl_ascii_string().splitlines()[:7]) # needs sage.geometry.polyhedron
+ sage: # needs sage.geometry.polyhedron sage.groups
+ sage: P = polytopes.dodecahedron()
+ sage: Q = P.plot().all[-1]
+ sage: print(Q.stl_ascii_string().splitlines()[:7])
['solid surface',
'facet normal 0.0 0.5257311121191338 0.8506508083520399',
' outer loop',
diff --git a/src/sage/plot/plot3d/list_plot3d.py b/src/sage/plot/plot3d/list_plot3d.py
index b8e4ddffce6..825c140f8ea 100644
--- a/src/sage/plot/plot3d/list_plot3d.py
+++ b/src/sage/plot/plot3d/list_plot3d.py
@@ -530,7 +530,8 @@ def list_plot3d_tuples(v, interpolation_type, **kwds):
.. PLOT::
- sphinx_plot(list_plot3d([[1, 1, 1], [1, 2, 1], [0, 1, 3], [1, 0, 4]], point_list=True))
+ sphinx_plot(list_plot3d([[1, 1, 1], [1, 2, 1], [0, 1, 3], [1, 0, 4]],
+ point_list=True))
::
diff --git a/src/sage/plot/plot3d/revolution_plot3d.py b/src/sage/plot/plot3d/revolution_plot3d.py
index b140c463c29..f3220dcd1a3 100644
--- a/src/sage/plot/plot3d/revolution_plot3d.py
+++ b/src/sage/plot/plot3d/revolution_plot3d.py
@@ -1,4 +1,4 @@
-# sage.doctest: needs sage.plot
+# sage.doctest: needs sage.plot sage.symbolic
"""
Surfaces of revolution
diff --git a/src/sage/plot/plot3d/transform.pyx b/src/sage/plot/plot3d/transform.pyx
index fefbb26dede..b6d8a2f643b 100644
--- a/src/sage/plot/plot3d/transform.pyx
+++ b/src/sage/plot/plot3d/transform.pyx
@@ -174,11 +174,11 @@ def rotate_arbitrary(v, double theta):
sage: rotate_arbitrary((1,2,3), -1).det()
1.0000000000000002
- sage: rotate_arbitrary((1,1,1), 2*pi/3) * vector(RDF, (1,2,3)) # rel tol 2e-15
+ sage: rotate_arbitrary((1,1,1), 2*pi/3) * vector(RDF, (1,2,3)) # rel tol 2e-15 # needs sage.symbolic
(1.9999999999999996, 2.9999999999999996, 0.9999999999999999)
sage: rotate_arbitrary((1,2,3), 5) * vector(RDF, (1,2,3)) # rel tol 2e-15
(1.0000000000000002, 2.0, 3.000000000000001)
- sage: rotate_arbitrary((1,1,1), pi/7)^7 # rel tol 2e-15
+ sage: rotate_arbitrary((1,1,1), pi/7)^7 # rel tol 2e-15 # needs sage.symbolic
[-0.33333333333333337 0.6666666666666671 0.6666666666666665]
[ 0.6666666666666665 -0.33333333333333337 0.6666666666666671]
[ 0.6666666666666671 0.6666666666666667 -0.33333333333333326]
@@ -194,7 +194,7 @@ def rotate_arbitrary(v, double theta):
Setup some variables::
- sage: vx,vy,vz,theta = var('x y z theta')
+ sage: vx,vy,vz,theta = var('x y z theta') # needs sage.symbolic
Symbolic rotation matrices about X and Y axis::
@@ -205,37 +205,37 @@ def rotate_arbitrary(v, double theta):
way to tell Maxima that `x^2+y^2+z^2=1` which would make for
a much cleaner calculation::
- sage: vy = sqrt(1-vx^2-vz^2)
+ sage: vy = sqrt(1-vx^2-vz^2) # needs sage.symbolic
Now we rotate about the `x`-axis so `v` is in the `xy`-plane::
- sage: t = arctan(vy/vz)+pi/2
- sage: m = rotX(t)
- sage: new_y = vy*cos(t) - vz*sin(t)
+ sage: t = arctan(vy/vz)+pi/2 # needs sage.symbolic
+ sage: m = rotX(t) # needs sage.symbolic
+ sage: new_y = vy*cos(t) - vz*sin(t) # needs sage.symbolic
And rotate about the `z` axis so `v` lies on the `x` axis::
- sage: s = arctan(vx/new_y) + pi/2
- sage: m = rotZ(s) * m
+ sage: s = arctan(vx/new_y) + pi/2 # needs sage.symbolic
+ sage: m = rotZ(s) * m # needs sage.symbolic
Rotating about `v` in our old system is the same as rotating
about the `x`-axis in the new::
- sage: m = rotX(theta) * m
+ sage: m = rotX(theta) * m # needs sage.symbolic
Do some simplifying here to avoid blow-up::
- sage: m = m.simplify_rational()
+ sage: m = m.simplify_rational() # needs sage.symbolic
Now go back to the original coordinate system::
- sage: m = rotZ(-s) * m
- sage: m = rotX(-t) * m
+ sage: m = rotZ(-s) * m # needs sage.symbolic
+ sage: m = rotX(-t) * m # needs sage.symbolic
And simplify every single entry (which is more effective that simplify
the whole matrix like above)::
- sage: m.parent()([x.simplify_full() for x in m._list()]) # long time; random
+ sage: m.parent()([x.simplify_full() for x in m._list()]) # random # long time, needs sage.symbolic
[ -(cos(theta) - 1)*x^2 + cos(theta) -(cos(theta) - 1)*sqrt(-x^2 - z^2 + 1)*x + sin(theta)*abs(z) -((cos(theta) - 1)*x*z^2 + sqrt(-x^2 - z^2 + 1)*sin(theta)*abs(z))/z]
[ -(cos(theta) - 1)*sqrt(-x^2 - z^2 + 1)*x - sin(theta)*abs(z) (cos(theta) - 1)*x^2 + (cos(theta) - 1)*z^2 + 1 -((cos(theta) - 1)*sqrt(-x^2 - z^2 + 1)*z*abs(z) - x*z*sin(theta))/abs(z)]
[ -((cos(theta) - 1)*x*z^2 - sqrt(-x^2 - z^2 + 1)*sin(theta)*abs(z))/z -((cos(theta) - 1)*sqrt(-x^2 - z^2 + 1)*z*abs(z) + x*z*sin(theta))/abs(z) -(cos(theta) - 1)*z^2 + cos(theta)]
diff --git a/src/sage/quadratic_forms/binary_qf.py b/src/sage/quadratic_forms/binary_qf.py
index 880452d9430..555fe01b3ef 100755
--- a/src/sage/quadratic_forms/binary_qf.py
+++ b/src/sage/quadratic_forms/binary_qf.py
@@ -1928,7 +1928,7 @@ def BinaryQF_reduced_representatives(D, primitive_only=False, proper=True):
if D > 0: # Indefinite
if D.is_square():
b = D.sqrt()
- c = ZZ(0)
+ c = ZZ.zero()
# -b/2 < a <= b/2
for a in xsrange((-b/2).floor() + 1, (b/2).floor() + 1):
if not primitive_only or (gcd([a, b, c]) == 1):
diff --git a/src/sage/quadratic_forms/genera/genus.py b/src/sage/quadratic_forms/genera/genus.py
index d9c298f5f0a..8946683a988 100644
--- a/src/sage/quadratic_forms/genera/genus.py
+++ b/src/sage/quadratic_forms/genera/genus.py
@@ -1202,7 +1202,7 @@ def two_adic_symbol(A, val):
return [[s[0]+m0] + s[1:] for s in sym + two_adic_symbol(A, val)]
-class Genus_Symbol_p_adic_ring():
+class Genus_Symbol_p_adic_ring:
r"""
Local genus symbol over a `p`-adic ring.
@@ -2132,7 +2132,7 @@ def direct_sum(self, other):
def excess(self):
r"""
- Returns the `p`-excess of the quadratic form whose Hessian
+ Return the `p`-excess of the quadratic form whose Hessian
matrix is the symmetric matrix `A`. When `p = 2`, the `p`-excess is
called the oddity.
@@ -2242,7 +2242,7 @@ def norm(self):
sage: G = Genus(matrix(ZZ,2,[0, 1, 1, 0]))
sage: G.local_symbol(2).norm()
2
- """
+ """
if self.rank() == 0:
return ZZ(0)
p = self.prime()
@@ -2321,7 +2321,7 @@ def compartments(self):
return canonical_2_adic_compartments(symbol)
-class GenusSymbol_global_ring():
+class GenusSymbol_global_ring:
r"""
This represents a collection of local genus symbols (at primes)
and signature information which represent the genus of a
diff --git a/src/sage/quadratic_forms/qfsolve.py b/src/sage/quadratic_forms/qfsolve.py
index 85116e43f9e..ff91830874c 100644
--- a/src/sage/quadratic_forms/qfsolve.py
+++ b/src/sage/quadratic_forms/qfsolve.py
@@ -213,7 +213,7 @@ def solve(self, c=0):
if not c:
x = qfsolve(M)
if isinstance(x, Integer):
- raise ArithmeticError("no solution found (local obstruction at {})".format(x))
+ raise ArithmeticError(f"no solution found (local obstruction at {x})")
return x
# If c != 0, define a new quadratic form Q = self - c*z^2
@@ -228,7 +228,7 @@ def solve(self, c=0):
x = qfsolve(N)
# Raise an error if qfsolve() doesn't find a solution
if isinstance(x, Integer):
- raise ArithmeticError("no solution found (local obstruction at {})".format(x))
+ raise ArithmeticError(f"no solution found (local obstruction at {x})")
# Let z be the last term of x, and remove z from x
z = x[-1]
diff --git a/src/sage/quadratic_forms/quadratic_form.py b/src/sage/quadratic_forms/quadratic_form.py
index 3db01b9fe2f..c78e7badeb4 100644
--- a/src/sage/quadratic_forms/quadratic_form.py
+++ b/src/sage/quadratic_forms/quadratic_form.py
@@ -305,200 +305,200 @@ class QuadraticForm(SageObject):
# Routines to compute the p-adic local normal form
lazy_import("sage.quadratic_forms.quadratic_form__local_normal_form", [
- "find_entry_with_minimal_scale_at_prime",
- "local_normal_form",
- "jordan_blocks_by_scale_and_unimodular",
- "jordan_blocks_in_unimodular_list_by_scale_power"
- ])
+ "find_entry_with_minimal_scale_at_prime",
+ "local_normal_form",
+ "jordan_blocks_by_scale_and_unimodular",
+ "jordan_blocks_in_unimodular_list_by_scale_power"
+ ])
# Routines to perform elementary variable substitutions
from sage.quadratic_forms.quadratic_form__variable_substitutions import \
- swap_variables, \
- multiply_variable, \
- divide_variable, \
- scale_by_factor, \
- extract_variables, \
- elementary_substitution, \
- add_symmetric
+ swap_variables, \
+ multiply_variable, \
+ divide_variable, \
+ scale_by_factor, \
+ extract_variables, \
+ elementary_substitution, \
+ add_symmetric
# Routines to compute p-adic field invariants
from sage.quadratic_forms.quadratic_form__local_field_invariants import \
- rational_diagonal_form, \
- _rational_diagonal_form_and_transformation, \
- signature_vector, \
- signature, \
- hasse_invariant, \
- hasse_invariant__OMeara, \
- is_hyperbolic, \
- is_anisotropic, \
- is_isotropic, \
- anisotropic_primes, \
- compute_definiteness, \
- compute_definiteness_string_by_determinants, \
- is_positive_definite, \
- is_negative_definite, \
- is_indefinite, \
- is_definite
+ rational_diagonal_form, \
+ _rational_diagonal_form_and_transformation, \
+ signature_vector, \
+ signature, \
+ hasse_invariant, \
+ hasse_invariant__OMeara, \
+ is_hyperbolic, \
+ is_anisotropic, \
+ is_isotropic, \
+ anisotropic_primes, \
+ compute_definiteness, \
+ compute_definiteness_string_by_determinants, \
+ is_positive_definite, \
+ is_negative_definite, \
+ is_indefinite, \
+ is_definite
# Routines to compute local densities by the reduction procedure
from sage.quadratic_forms.quadratic_form__local_density_congruence import \
- count_modp_solutions__by_Gauss_sum, \
- local_good_density_congruence_odd, \
- local_good_density_congruence_even, \
- local_good_density_congruence, \
- local_zero_density_congruence, \
- local_badI_density_congruence, \
- local_badII_density_congruence, \
- local_bad_density_congruence, \
- local_density_congruence, \
- local_primitive_density_congruence
+ count_modp_solutions__by_Gauss_sum, \
+ local_good_density_congruence_odd, \
+ local_good_density_congruence_even, \
+ local_good_density_congruence, \
+ local_zero_density_congruence, \
+ local_badI_density_congruence, \
+ local_badII_density_congruence, \
+ local_bad_density_congruence, \
+ local_density_congruence, \
+ local_primitive_density_congruence
# Routines to compute local densities by counting solutions of various types
from sage.quadratic_forms.quadratic_form__count_local_2 import \
- count_congruence_solutions_as_vector, \
- count_congruence_solutions, \
- count_congruence_solutions__good_type, \
- count_congruence_solutions__zero_type, \
- count_congruence_solutions__bad_type, \
- count_congruence_solutions__bad_type_I, \
- count_congruence_solutions__bad_type_II
+ count_congruence_solutions_as_vector, \
+ count_congruence_solutions, \
+ count_congruence_solutions__good_type, \
+ count_congruence_solutions__zero_type, \
+ count_congruence_solutions__bad_type, \
+ count_congruence_solutions__bad_type_I, \
+ count_congruence_solutions__bad_type_II
# Routines to be called by the user to compute local densities
lazy_import("sage.quadratic_forms.quadratic_form__local_density_interfaces", [
- "local_density",
- "local_primitive_density"
- ])
+ "local_density",
+ "local_primitive_density"
+ ])
# Routines for computing with ternary forms
from sage.quadratic_forms.quadratic_form__ternary_Tornaria import \
- disc, \
- content, \
- adjoint, \
- antiadjoint, \
- is_adjoint, \
- reciprocal, \
- omega, \
- delta, \
- level__Tornaria, \
- discrec, \
- hasse_conductor, \
- clifford_invariant, \
- clifford_conductor, \
- basiclemma, \
- basiclemmavec, \
- xi, \
- xi_rec, \
- lll, \
- representation_number_list, \
- representation_vector_list, \
- is_zero, \
- is_zero_nonsingular, \
- is_zero_singular
+ disc, \
+ content, \
+ adjoint, \
+ antiadjoint, \
+ is_adjoint, \
+ reciprocal, \
+ omega, \
+ delta, \
+ level__Tornaria, \
+ discrec, \
+ hasse_conductor, \
+ clifford_invariant, \
+ clifford_conductor, \
+ basiclemma, \
+ basiclemmavec, \
+ xi, \
+ xi_rec, \
+ lll, \
+ representation_number_list, \
+ representation_vector_list, \
+ is_zero, \
+ is_zero_nonsingular, \
+ is_zero_singular
# Routines to compute the theta function
from sage.quadratic_forms.quadratic_form__theta import \
- theta_series, \
- theta_series_degree_2, \
- theta_by_pari, \
- theta_by_cholesky
+ theta_series, \
+ theta_series_degree_2, \
+ theta_by_pari, \
+ theta_by_cholesky
# Routines to compute the product of all local densities
lazy_import("sage.quadratic_forms.quadratic_form__siegel_product", [
- "siegel_product"
- ])
+ "siegel_product"
+ ])
# Routines to compute p-neighbors
from sage.quadratic_forms.quadratic_form__neighbors import \
- find_primitive_p_divisible_vector__random, \
- find_primitive_p_divisible_vector__next, \
- find_p_neighbor_from_vec, \
- neighbor_iteration, \
- orbits_lines_mod_p
+ find_primitive_p_divisible_vector__random, \
+ find_primitive_p_divisible_vector__next, \
+ find_p_neighbor_from_vec, \
+ neighbor_iteration, \
+ orbits_lines_mod_p
# Routines to reduce a given quadratic form
from sage.quadratic_forms.quadratic_form__reduction_theory import \
- reduced_binary_form1, \
- reduced_ternary_form__Dickson, \
- reduced_binary_form, \
- minkowski_reduction, \
- minkowski_reduction_for_4vars__SP
+ reduced_binary_form1, \
+ reduced_ternary_form__Dickson, \
+ reduced_binary_form, \
+ minkowski_reduction, \
+ minkowski_reduction_for_4vars__SP
# Wrappers for Conway-Sloane genus routines (in ./genera/)
lazy_import("sage.quadratic_forms.quadratic_form__genus", [
- "global_genus_symbol",
- "local_genus_symbol",
- "CS_genus_symbol_list"
- ])
+ "global_genus_symbol",
+ "local_genus_symbol",
+ "CS_genus_symbol_list"
+ ])
# Routines to compute local masses for ZZ.
lazy_import("sage.quadratic_forms.quadratic_form__mass", [
- "shimura_mass__maximal",
- "GHY_mass__maximal"
- ])
+ "shimura_mass__maximal",
+ "GHY_mass__maximal"
+ ])
lazy_import("sage.quadratic_forms.quadratic_form__mass__Siegel_densities", [
- "mass__by_Siegel_densities",
- "Pall_mass_density_at_odd_prime",
- "Watson_mass_at_2",
- "Kitaoka_mass_at_2",
- "mass_at_two_by_counting_mod_power"
- ])
+ "mass__by_Siegel_densities",
+ "Pall_mass_density_at_odd_prime",
+ "Watson_mass_at_2",
+ "Kitaoka_mass_at_2",
+ "mass_at_two_by_counting_mod_power"
+ ])
lazy_import("sage.quadratic_forms.quadratic_form__mass__Conway_Sloane_masses", [
- "parity",
- "is_even",
- "is_odd",
- "conway_species_list_at_odd_prime",
- "conway_species_list_at_2",
- "conway_octane_of_this_unimodular_Jordan_block_at_2",
- "conway_diagonal_factor",
- "conway_cross_product_doubled_power",
- "conway_type_factor",
- "conway_p_mass",
- "conway_standard_p_mass",
- "conway_standard_mass",
- "conway_mass"
-# conway_generic_mass, \
-# conway_p_mass_adjustment
- ])
+ "parity",
+ "is_even",
+ "is_odd",
+ "conway_species_list_at_odd_prime",
+ "conway_species_list_at_2",
+ "conway_octane_of_this_unimodular_Jordan_block_at_2",
+ "conway_diagonal_factor",
+ "conway_cross_product_doubled_power",
+ "conway_type_factor",
+ "conway_p_mass",
+ "conway_standard_p_mass",
+ "conway_standard_mass",
+ "conway_mass"
+ # conway_generic_mass, \
+ # conway_p_mass_adjustment
+ ])
# Routines to check local representability of numbers
lazy_import("sage.quadratic_forms.quadratic_form__local_representation_conditions", [
- "local_representation_conditions",
- "is_locally_universal_at_prime",
- "is_locally_universal_at_all_primes",
- "is_locally_universal_at_all_places",
- "is_locally_represented_number_at_place",
- "is_locally_represented_number"
- ])
+ "local_representation_conditions",
+ "is_locally_universal_at_prime",
+ "is_locally_universal_at_all_primes",
+ "is_locally_universal_at_all_places",
+ "is_locally_represented_number_at_place",
+ "is_locally_represented_number"
+ ])
# Routines to make a split local covering of the given quadratic form.
from sage.quadratic_forms.quadratic_form__split_local_covering import \
- cholesky_decomposition, \
- vectors_by_length, \
- complementary_subform_to_vector, \
- split_local_cover
+ cholesky_decomposition, \
+ vectors_by_length, \
+ complementary_subform_to_vector, \
+ split_local_cover
# Routines to make automorphisms of the given quadratic form.
lazy_import("sage.quadratic_forms.quadratic_form__automorphisms", [
- "basis_of_short_vectors",
- "short_vector_list_up_to_length",
- "short_primitive_vector_list_up_to_length",
- "_compute_automorphisms",
- "automorphism_group",
- "automorphisms",
- "number_of_automorphisms",
- "set_number_of_automorphisms"
- ])
+ "basis_of_short_vectors",
+ "short_vector_list_up_to_length",
+ "short_primitive_vector_list_up_to_length",
+ "_compute_automorphisms",
+ "automorphism_group",
+ "automorphisms",
+ "number_of_automorphisms",
+ "set_number_of_automorphisms"
+ ])
# Routines to test the local and global equivalence/isometry of two quadratic forms.
from sage.quadratic_forms.quadratic_form__equivalence_testing import \
- is_globally_equivalent_to, \
- is_locally_equivalent_to, \
- has_equivalent_Jordan_decomposition_at_prime, \
- is_rationally_isometric
+ is_globally_equivalent_to, \
+ is_locally_equivalent_to, \
+ has_equivalent_Jordan_decomposition_at_prime, \
+ is_rationally_isometric
# Routines for solving equations of the form Q(x) = c.
lazy_import("sage.quadratic_forms.qfsolve", [
- "solve"
- ])
+ "solve"
+ ])
# Genus
lazy_import("sage.quadratic_forms.genera.genus",
@@ -617,7 +617,7 @@ def __init__(self, R, n=None, entries=None, unsafe_initialization=False, number_
# Verify the size of the matrix is an integer >= 0
n = ZZ(n)
if n < 0:
- raise ValueError("the size must be a non-negative integer, not {}".format(n))
+ raise ValueError(f"the size must be a non-negative integer, not {n}")
# Store the relevant variables
N = n * (n + 1) // 2
@@ -738,7 +738,7 @@ def _repr_(self):
if (i > j):
out_str += "* "
else:
- out_str += str(self[i,j]) + " "
+ out_str += str(self[i, j]) + " "
out_str += "]"
return out_str
@@ -762,7 +762,7 @@ def _latex_(self):
if (i > j):
out_str += " * & "
else:
- out_str += str(self[i,j]) + " & "
+ out_str += str(self[i, j]) + " & "
# if i < (n-1):
# out_str += "\\"
out_str += "\\end{array} \\right]"
@@ -1051,7 +1051,7 @@ def __call__(self, v):
if is_Matrix(v):
# Check that v has the correct number of rows
if v.nrows() != n:
- raise TypeError("the matrix must have {} rows".format(n))
+ raise TypeError(f"the matrix must have {n} rows")
# Create the new quadratic form
m = v.ncols()
@@ -1061,7 +1061,7 @@ def __call__(self, v):
elif (is_Vector(v) or isinstance(v, (list, tuple))):
# Check the vector/tuple/list has the correct length
if not (len(v) == n):
- raise TypeError("your vector needs to have length {}".format(n))
+ raise TypeError(f"your vector needs to have length {n}")
# TO DO: Check that the elements can be coerced into the base ring of Q -- on first elt.
if len(v) > 0:
@@ -1291,7 +1291,7 @@ def gcd(self):
raise TypeError("the given quadratic form must be defined over ZZ")
return GCD(self.coefficients())
- def polynomial(self,names='x'):
+ def polynomial(self, names='x'):
r"""
Return the quadratic form as a polynomial in `n` variables.
@@ -1335,7 +1335,7 @@ def polynomial(self,names='x'):
M = matrix(B, n)
for i in range(n):
for j in range(i, n):
- M[i,j] = self[i,j]
+ M[i, j] = self[i, j]
try:
R = PolynomialRing(self.base_ring(), names, n)
except Exception:
@@ -1379,17 +1379,16 @@ def from_polynomial(poly):
raise ValueError('polynomial has monomials of degree != 2')
base = R.base_ring()
vs = R.gens()
- coeffs = []
- for i, v in enumerate(vs):
- for w in vs[i:]:
- coeffs.append(poly.monomial_coefficient(v*w))
+ coeffs = [poly.monomial_coefficient(v * w)
+ for i, v in enumerate(vs) for w in vs[i:]]
return QuadraticForm(base, len(vs), coeffs)
- def is_primitive(self):
+ def is_primitive(self) -> bool:
"""
- Determines if the given integer-valued form is primitive
- (i.e. not an integer (`> 1`) multiple of another integer-valued
- quadratic form).
+ Determine if the given integer-valued form is primitive.
+
+ This means not an integer (`> 1`) multiple of another integer-valued
+ quadratic form.
EXAMPLES::
@@ -1399,9 +1398,8 @@ def is_primitive(self):
sage: Q = QuadraticForm(ZZ, 2, [2,4,8])
sage: Q.is_primitive()
False
-
"""
- return (self.gcd() == 1)
+ return self.gcd() == 1
def primitive(self):
r"""
@@ -1630,9 +1628,9 @@ def level(self):
for i in range(self.dim()):
for j in range(i, self.dim()):
if (i == j):
- inv_denoms += [denominator(mat_inv[i,j] / 2)]
+ inv_denoms += [denominator(mat_inv[i, j] / 2)]
else:
- inv_denoms += [denominator(mat_inv[i,j])]
+ inv_denoms += [denominator(mat_inv[i, j])]
lvl = LCM(inv_denoms)
lvl = Ideal(self.base_ring()(lvl)).gen()
##############################################################
diff --git a/src/sage/quadratic_forms/quadratic_form__automorphisms.py b/src/sage/quadratic_forms/quadratic_form__automorphisms.py
index 89b2c079478..4b6e3594f83 100644
--- a/src/sage/quadratic_forms/quadratic_form__automorphisms.py
+++ b/src/sage/quadratic_forms/quadratic_form__automorphisms.py
@@ -78,10 +78,8 @@ def basis_of_short_vectors(self, show_lengths=False):
vector_list_by_length[l].append(vector([-x for x in v]))
# Make a matrix from the column vectors (in order of ascending length).
- sorted_list = []
- for i in range(len(vector_list_by_length)):
- for v in vector_list_by_length[i]:
- sorted_list.append(v)
+ sorted_list = [v for i in range(len(vector_list_by_length))
+ for v in vector_list_by_length[i]]
sorted_matrix = Matrix(sorted_list).transpose()
# Determine a basis of vectors of minimal length
@@ -205,7 +203,7 @@ def short_vector_list_up_to_length(self, len_bound, up_to_sign_flag=False):
parilens = pari(r"(M,v) -> vector(#v, i, (v[i]~ * M * v[i])\2)")(self, parilist)
# Sort the vectors into lists by their length
- vec_sorted_list = [list() for i in range(len_bound)]
+ vec_sorted_list = [[] for i in range(len_bound)]
for i in range(len(parilist)):
length = int(parilens[i])
# In certain trivial cases, PARI can sometimes return longer
@@ -349,7 +347,7 @@ def automorphisms(self):
48
sage: 2^3 * factorial(3)
48
- sage: len(Q.automorphisms())
+ sage: len(Q.automorphisms()) # needs sage.libs.gap
48
::
@@ -357,14 +355,14 @@ def automorphisms(self):
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
sage: Q.number_of_automorphisms()
16
- sage: aut = Q.automorphisms()
- sage: len(aut)
+ sage: aut = Q.automorphisms() # needs sage.libs.gap
+ sage: len(aut) # needs sage.libs.gap
16
- sage: all(Q(M) == Q for M in aut)
+ sage: all(Q(M) == Q for M in aut) # needs sage.libs.gap
True
sage: Q = QuadraticForm(ZZ, 3, [2, 1, 2, 2, 1, 3])
- sage: sorted(Q.automorphisms())
+ sage: sorted(Q.automorphisms()) # needs sage.libs.gap
[
[-1 0 0] [1 0 0]
[ 0 -1 0] [0 1 0]
diff --git a/src/sage/quadratic_forms/quadratic_form__equivalence_testing.py b/src/sage/quadratic_forms/quadratic_form__equivalence_testing.py
index 148fcbd21f2..2bd4df8f890 100644
--- a/src/sage/quadratic_forms/quadratic_form__equivalence_testing.py
+++ b/src/sage/quadratic_forms/quadratic_form__equivalence_testing.py
@@ -442,9 +442,9 @@ def is_rationally_isometric(self, other, return_matrix=False):
sage: V.is_rationally_isometric(W)
Traceback (most recent call last):
...
- NotImplementedError: This only tests regular forms
+ NotImplementedError: this only tests regular forms
- Forms must have the same base ring otherwise a `TypeError` is raised::
+ Forms must have the same base ring otherwise a :class:`TypeError` is raised::
sage: # needs sage.rings.number_field
sage: K1. = QuadraticField(5)
@@ -491,7 +491,7 @@ def is_rationally_isometric(self, other, return_matrix=False):
True
"""
if self.Gram_det() == 0 or other.Gram_det() == 0:
- raise NotImplementedError("This only tests regular forms")
+ raise NotImplementedError("this only tests regular forms")
if self.base_ring() != other.base_ring():
raise TypeError("forms must have the same base ring.")
diff --git a/src/sage/quadratic_forms/quadratic_form__genus.py b/src/sage/quadratic_forms/quadratic_form__genus.py
index 8727645b453..52468e9889a 100644
--- a/src/sage/quadratic_forms/quadratic_form__genus.py
+++ b/src/sage/quadratic_forms/quadratic_form__genus.py
@@ -133,10 +133,8 @@ def CS_genus_symbol_list(self, force_recomputation=False):
pass
# Otherwise recompute and cache the list
- list_of_CS_genus_symbols = []
-
- for p in prime_divisors(2 * self.det()):
- list_of_CS_genus_symbols.append(self.local_genus_symbol(p))
+ list_of_CS_genus_symbols = [self.local_genus_symbol(p)
+ for p in prime_divisors(2 * self.det())]
self.__CS_genus_symbol_list = list_of_CS_genus_symbols
return list_of_CS_genus_symbols
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 888f4ae2832..c337d2994a0 100644
--- a/src/sage/quadratic_forms/quadratic_form__local_representation_conditions.py
+++ b/src/sage/quadratic_forms/quadratic_form__local_representation_conditions.py
@@ -17,7 +17,7 @@
from sage.rings.rational_field import QQ
-class QuadraticFormLocalRepresentationConditions():
+class QuadraticFormLocalRepresentationConditions:
"""
A class for dealing with the local conditions of a
quadratic form, and checking local representability of numbers.
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 a99eb439e0f..9133a84b76f 100644
--- a/src/sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py
+++ b/src/sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py
@@ -197,8 +197,8 @@ def Watson_mass_at_2(self):
s_max = max(scale_list)
# Step 1: Compute dictionaries of the diagonal block and 2x2 block for each scale
- diag_dict = dict((i, Null_Form) for i in range(s_min - 2, s_max + 4)) # Initialize with the zero form
- dim2_dict = dict((i, Null_Form) for i in range(s_min, s_max + 4)) # Initialize with the zero form
+ diag_dict = {i: Null_Form for i in range(s_min - 2, s_max + 4)} # Initialize with the zero form
+ dim2_dict = {i: Null_Form for i in range(s_min, s_max + 4)} # Initialize with the zero form
for s, L in Jordan_Blocks:
i = 0
while i < L.dim() - 1 and L[i, i + 1] == 0: # Find where the 2x2 blocks start
@@ -210,8 +210,8 @@ def Watson_mass_at_2(self):
diag_dict[s] = L
# Step 2: Compute three dictionaries of invariants (for n_j, m_j, nu_j)
- n_dict = dict((j, 0) for j in range(s_min + 1, s_max + 2))
- m_dict = dict((j, 0) for j in range(s_min, s_max + 4))
+ n_dict = {j: 0 for j in range(s_min + 1, s_max + 2)}
+ m_dict = {j: 0 for j in range(s_min, s_max + 4)}
for s, L in Jordan_Blocks:
n_dict[s + 1] = L.dim()
if diag_dict[s].dim() == 0:
@@ -219,8 +219,8 @@ def Watson_mass_at_2(self):
else:
m_dict[s + 1] = ZZ(L.dim() - 1) // ZZ(2)
- nu_dict = dict((j, n_dict[j + 1] - 2 * m_dict[j + 1])
- for j in range(s_min, s_max + 1))
+ nu_dict = {j: n_dict[j + 1] - 2 * m_dict[j + 1]
+ for j in range(s_min, s_max + 1)}
nu_dict[s_max + 1] = 0
# Step 3: Compute the e_j dictionary
@@ -280,8 +280,8 @@ def Kitaoka_mass_at_2(self):
s_max = max(scale_list)
# Step 1: Compute dictionaries of the diagonal block and 2x2 block for each scale
- diag_dict = dict((i, Null_Form) for i in range(s_min - 2, s_max + 4)) # Initialize with the zero form
- dim2_dict = dict((i, Null_Form) for i in range(s_min, s_max + 4)) # Initialize with the zero form
+ diag_dict = {i: Null_Form for i in range(s_min - 2, s_max + 4)} # Initialize with the zero form
+ dim2_dict = {i: Null_Form for i in range(s_min, s_max + 4)} # Initialize with the zero form
for s, L in Jordan_Blocks:
i = 0
while i < L.dim() - 1 and L[i, i + 1] == 0: # Find where the 2x2 blocks start
diff --git a/src/sage/quadratic_forms/ternary_qf.py b/src/sage/quadratic_forms/ternary_qf.py
index 2f3a57fa713..2808c04548f 100644
--- a/src/sage/quadratic_forms/ternary_qf.py
+++ b/src/sage/quadratic_forms/ternary_qf.py
@@ -921,7 +921,7 @@ def find_p_neighbor_from_vec(self, p, v, mat=False):
Test that it works with (0, 0, 1)::
- sage: Q.find_p_neighbor_from_vec(3, (0,0,1))
+ sage: Q.find_p_neighbor_from_vec(3, (0,0,1)) # needs sage.libs.pari
Ternary quadratic form with integer coefficients:
[1 3 3]
[-2 0 -1]
diff --git a/src/sage/repl/rich_output/backend_ipython.py b/src/sage/repl/rich_output/backend_ipython.py
index 10ccdc0c2c8..ba17b9244b4 100644
--- a/src/sage/repl/rich_output/backend_ipython.py
+++ b/src/sage/repl/rich_output/backend_ipython.py
@@ -419,13 +419,6 @@ def threejs_offline_scripts(self):
script = os.path.join(THREEJS_DIR, '{}/three.min.js'.format(_required_threejs_version()))
- if sys.platform == 'cygwin':
- import cygwin
-
- def normpath(p):
- return 'file:///' + cygwin.cygpath(p, 'w').replace('\\', '/')
- script = normpath(script)
-
return '\n'.format(script)
diff --git a/src/sage/rings/asymptotic/asymptotic_expansion_generators.py b/src/sage/rings/asymptotic/asymptotic_expansion_generators.py
index 9a27c9d61eb..61d8238332d 100644
--- a/src/sage/rings/asymptotic/asymptotic_expansion_generators.py
+++ b/src/sage/rings/asymptotic/asymptotic_expansion_generators.py
@@ -604,7 +604,7 @@ def SingularityAnalysis(var, zeta=1, alpha=0, beta=0, delta=0,
precision=None, normalized=True):
r"""
Return the asymptotic expansion of the coefficients of
- an power series with specified pole and logarithmic singularity.
+ a power series with specified pole and logarithmic singularity.
More precisely, this extracts the `n`-th coefficient
diff --git a/src/sage/rings/asymptotic/growth_group_cartesian.py b/src/sage/rings/asymptotic/growth_group_cartesian.py
index 447c25fa64d..6613c5bdf32 100644
--- a/src/sage/rings/asymptotic/growth_group_cartesian.py
+++ b/src/sage/rings/asymptotic/growth_group_cartesian.py
@@ -1193,7 +1193,7 @@ def __invert__(self):
OUTPUT:
- An growth element.
+ A growth element.
.. NOTE::
diff --git a/src/sage/rings/bernoulli_mod_p.pyx b/src/sage/rings/bernoulli_mod_p.pyx
index e9bf4fbf358..ee73d6ad209 100644
--- a/src/sage/rings/bernoulli_mod_p.pyx
+++ b/src/sage/rings/bernoulli_mod_p.pyx
@@ -23,6 +23,8 @@ AUTHOR:
# https://www.gnu.org/licenses/
# ****************************************************************************
+from sage.arith.misc import is_prime, primitive_root
+
cimport sage.rings.fast_arith
import sage.rings.fast_arith
cdef sage.rings.fast_arith.arith_int arith_int
@@ -135,12 +137,12 @@ def bernoulli_mod_p(int p):
if p <= 2:
raise ValueError("p (=%s) must be a prime >= 3" % p)
- if not sage.arith.all.is_prime(p):
+ if not is_prime(p):
raise ValueError("p (=%s) must be a prime" % p)
cdef int g, gSqr, gInv, gInvSqr, isOdd
- g = sage.arith.all.primitive_root(p)
+ g = primitive_root(p)
gInv = arith_int.c_inverse_mod_int(g, p)
gSqr = (( g) * g) % p
gInvSqr = (( gInv) * gInv) % p
@@ -303,7 +305,7 @@ def bernoulli_mod_p_single(long p, long k):
if p <= 2:
raise ValueError("p (=%s) must be a prime >= 3" % p)
- if not sage.arith.all.is_prime(p):
+ if not is_prime(p):
raise ValueError("p (=%s) must be a prime" % p)
cdef long x = bernmm_bern_modp(p, k)
diff --git a/src/sage/rings/cfinite_sequence.py b/src/sage/rings/cfinite_sequence.py
index 4d9353e57b8..48d585384f6 100644
--- a/src/sage/rings/cfinite_sequence.py
+++ b/src/sage/rings/cfinite_sequence.py
@@ -89,9 +89,8 @@
from numbers import Integral
-from sage.categories.fields import Fields
+from sage.categories.rings import Rings
from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass
-from sage.rings.ring import CommutativeRing
from sage.rings.integer_ring import ZZ
from sage.rings.rational_field import QQ
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
@@ -100,6 +99,7 @@
from sage.rings.power_series_ring import PowerSeriesRing
from sage.rings.fraction_field import FractionField
from sage.structure.element import FieldElement, parent
+from sage.structure.parent import Parent
from sage.structure.unique_representation import UniqueRepresentation
from sage.interfaces.gp import Gp
@@ -110,7 +110,7 @@
def CFiniteSequences(base_ring, names=None, category=None):
r"""
- Return the ring of C-Finite sequences.
+ Return the commutative ring of C-Finite sequences.
The ring is defined over a base ring (`\ZZ` or `\QQ` )
and each element is represented by its ordinary generating function (ogf)
@@ -154,15 +154,15 @@ def CFiniteSequences(base_ring, names=None, category=None):
elif len(names) > 1:
raise NotImplementedError("Multidimensional o.g.f. not implemented.")
if category is None:
- category = Fields()
- if not (base_ring in (QQ, ZZ)):
+ category = Rings().Commutative()
+ if base_ring not in [QQ, ZZ]:
raise ValueError("O.g.f. base not rational.")
polynomial_ring = PolynomialRing(base_ring, names)
return CFiniteSequences_generic(polynomial_ring, category)
class CFiniteSequence(FieldElement,
- metaclass=InheritComparisonClasscallMetaclass):
+ metaclass=InheritComparisonClasscallMetaclass):
r"""
Create a C-finite sequence given its ordinary generating function.
@@ -174,7 +174,7 @@ class CFiniteSequence(FieldElement,
OUTPUT:
- - A CFiniteSequence object
+ A CFiniteSequence object
EXAMPLES::
@@ -247,7 +247,7 @@ class CFiniteSequence(FieldElement,
@staticmethod
def __classcall_private__(cls, ogf):
r"""
- Ensures that elements created by :class:`CFiniteSequence` have the same
+ Ensure that elements created by :class:`CFiniteSequence` have the same
parent than the ones created by the parent itself and follow the category
framework (they should be instance of :class:`CFiniteSequences` automatic
element class).
@@ -299,9 +299,8 @@ def __classcall_private__(cls, ogf):
sage: f4.parent()
The ring of C-Finite sequences in y over Rational Field
"""
-
br = ogf.base_ring()
- if not (br in (QQ, ZZ)):
+ if br not in [QQ, ZZ]:
br = QQ # if the base ring of the o.g.f is not QQ, we force it to QQ and see if the o.g.f converts nicely
# trying to figure out the ogf variables
@@ -388,7 +387,6 @@ def __init__(self, parent, ogf):
# determine start values (may be different from _get_item_ values)
alen = max(self._deg, num.degree() + 1)
R = LaurentSeriesRing(br, parent.variable_name(), default_prec=alen)
- rem = num % den
if den != 1:
self._a = R(num / den).list()
else:
@@ -400,7 +398,7 @@ def __init__(self, parent, ogf):
self._ogf = ogf
- def _repr_(self):
+ def _repr_(self) -> str:
"""
Return textual definition of sequence.
@@ -414,10 +412,8 @@ def _repr_(self):
if self._deg == 0:
if self.ogf() == 0:
return 'Constant infinite sequence 0.'
- else:
- return 'Finite sequence ' + str(self._a) + ', offset = ' + str(self._off)
- else:
- return 'C-finite sequence, generated by ' + str(self.ogf())
+ return 'Finite sequence ' + str(self._a) + ', offset = ' + str(self._off)
+ return 'C-finite sequence, generated by ' + str(self.ogf())
def __hash__(self):
r"""
@@ -656,7 +652,8 @@ def __getitem__(self, key):
if isinstance(key, slice):
m = max(key.start, key.stop)
return [self[ii] for ii in range(*key.indices(m + 1))]
- elif isinstance(key, Integral):
+
+ if isinstance(key, Integral):
n = key - self._off
if n < 0:
return 0
@@ -679,8 +676,8 @@ def __getitem__(self, key):
den = P((den * nden).list()[::2])
n //= 2
return wp + num[0] / den[0]
- else:
- raise TypeError("invalid argument type")
+
+ raise TypeError("invalid argument type")
def ogf(self):
"""
@@ -726,14 +723,14 @@ def denominator(self):
"""
return self.ogf().denominator()
- def recurrence_repr(self):
+ def recurrence_repr(self) -> str:
"""
Return a string with the recurrence representation of
the C-finite sequence.
OUTPUT:
- - A string
+ A string
EXAMPLES::
@@ -892,7 +889,7 @@ def closed_form(self, n='n'):
return expr
-class CFiniteSequences_generic(CommutativeRing, UniqueRepresentation):
+class CFiniteSequences_generic(Parent, UniqueRepresentation):
r"""
The class representing the ring of C-Finite Sequences
@@ -912,13 +909,13 @@ class CFiniteSequences_generic(CommutativeRing, UniqueRepresentation):
def __init__(self, polynomial_ring, category):
r"""
- Create the ring of CFiniteSequences over ``base_ring``
+ Create the ring of CFiniteSequences over ``base_ring``.
INPUT:
- ``base_ring`` -- the base ring for the o.g.f (either ``QQ`` or ``ZZ``)
- ``names`` -- an iterable of variables (should contain only one variable)
- - ``category`` -- the category of the ring (default: ``Fields()``)
+ - ``category`` -- the category of the ring (default: ``Rings().Commutative()``)
TESTS::
@@ -940,11 +937,14 @@ def __init__(self, polynomial_ring, category):
base_ring = polynomial_ring.base_ring()
self._polynomial_ring = polynomial_ring
self._fraction_field = FractionField(self._polynomial_ring)
- CommutativeRing.__init__(self, base_ring, self._polynomial_ring.gens(), category)
+ if category is None:
+ category = Rings().Commutative()
+ Parent.__init__(self, base_ring, names=self._polynomial_ring.gens(),
+ category=category)
def _repr_(self):
r"""
- Return the string representation of ``self``
+ Return the string representation of ``self``.
EXAMPLES::
@@ -956,7 +956,7 @@ def _repr_(self):
def _element_constructor_(self, ogf):
r"""
- Construct a C-Finite Sequence
+ Construct a C-Finite Sequence.
INPUT:
@@ -986,9 +986,9 @@ def _element_constructor_(self, ogf):
ogf = self.fraction_field()(ogf)
return self.element_class(self, ogf)
- def ngens(self):
+ def ngens(self) -> int:
r"""
- Return the number of generators of ``self``
+ Return the number of generators of ``self``.
EXAMPLES::
@@ -1026,6 +1026,18 @@ def gen(self, i=0):
raise ValueError("{} has only one generator (i=0)".format(self))
return self.polynomial_ring().gen()
+ def gens(self) -> tuple:
+ """
+ Return the generators of ``self``.
+
+ EXAMPLES::
+
+ sage: C. = CFiniteSequences(QQ)
+ sage: C.gens()
+ (x,)
+ """
+ return (self.gen(0),)
+
def an_element(self):
r"""
Return an element of C-Finite Sequences.
@@ -1043,7 +1055,7 @@ def an_element(self):
x = self.gen()
return self((2 - x) / (1 - x - x**2))
- def __contains__(self, x):
+ def __contains__(self, x) -> bool:
"""
Return ``True`` if x is an element of ``CFiniteSequences`` or
canonically coerces to this ring.
@@ -1194,7 +1206,7 @@ def guess(self, sequence, algorithm='sage'):
sage: r = C.guess([1,2,3,4,5])
Traceback (most recent call last):
...
- ValueError: Sequence too short for guessing.
+ ValueError: sequence too short for guessing
With Berlekamp-Massey, if an odd number of values is given, the last one is dropped.
So with an odd number of values the result may not generate the last value::
@@ -1205,10 +1217,11 @@ def guess(self, sequence, algorithm='sage'):
[1, 2, 4, 8, 16]
"""
S = self.polynomial_ring()
+
if algorithm == 'bm':
from sage.matrix.berlekamp_massey import berlekamp_massey
if len(sequence) < 2:
- raise ValueError('Sequence too short for guessing.')
+ raise ValueError('sequence too short for guessing')
R = PowerSeriesRing(QQ, 'x')
if len(sequence) % 2:
sequence.pop()
@@ -1217,10 +1230,11 @@ def guess(self, sequence, algorithm='sage'):
numerator = R(S(sequence) * denominator, prec=l).truncate()
return CFiniteSequence(numerator / denominator)
- elif algorithm == 'pari':
+
+ if algorithm == 'pari':
global _gp
if len(sequence) < 6:
- raise ValueError('Sequence too short for guessing.')
+ raise ValueError('sequence too short for guessing')
if _gp is None:
_gp = Gp()
_gp("ggf(v)=local(l,m,p,q,B);l=length(v);B=floor(l/2);\
@@ -1236,37 +1250,35 @@ def guess(self, sequence, algorithm='sage'):
den = S(sage_eval(_gp.eval("Vec(denominator(gf))"))[::-1])
if num == 0:
return 0
- else:
- return CFiniteSequence(num / den)
- else:
- from sage.matrix.constructor import matrix
- from sage.arith.misc import integer_ceil as ceil
- from numpy import trim_zeros
- seq = sequence[:]
- while seq and sequence[-1] == 0:
- seq.pop()
- l = len(seq)
- if l == 0:
- return 0
- if l < 6:
- raise ValueError('Sequence too short for guessing.')
-
- hl = ceil(ZZ(l) / 2)
- A = matrix([sequence[k: k + hl] for k in range(hl)])
- K = A.kernel()
- if K.dimension() == 0:
- return 0
- R = PolynomialRing(QQ, 'x')
- den = R(trim_zeros(K.basis()[-1].list()[::-1]))
- if den == 1:
- return 0
- offset = next((i for i, x in enumerate(sequence) if x), None)
- S = PowerSeriesRing(QQ, 'x', default_prec=l - offset)
- num = S(R(sequence) * den).truncate(ZZ(l) // 2 + 1)
- if num == 0 or sequence != S(num / den).list():
- return 0
- else:
- return CFiniteSequence(num / den)
+ return CFiniteSequence(num / den)
+
+ from sage.matrix.constructor import matrix
+ from sage.arith.misc import integer_ceil as ceil
+ from numpy import trim_zeros
+ seq = sequence[:]
+ while seq and sequence[-1] == 0:
+ seq.pop()
+ l = len(seq)
+ if l == 0:
+ return 0
+ if l < 6:
+ raise ValueError('sequence too short for guessing')
+
+ hl = ceil(ZZ(l) / 2)
+ A = matrix([sequence[k: k + hl] for k in range(hl)])
+ K = A.kernel()
+ if K.dimension() == 0:
+ return 0
+ R = PolynomialRing(QQ, 'x')
+ den = R(trim_zeros(K.basis()[-1].list()[::-1]))
+ if den == 1:
+ return 0
+ offset = next((i for i, x in enumerate(sequence) if x), None)
+ S = PowerSeriesRing(QQ, 'x', default_prec=l - offset)
+ num = S(R(sequence) * den).truncate(ZZ(l) // 2 + 1)
+ if num == 0 or sequence != S(num / den).list():
+ return 0
+ return CFiniteSequence(num / den)
r"""
diff --git a/src/sage/rings/complex_interval.pyx b/src/sage/rings/complex_interval.pyx
index e804964f501..4b9e7f2aefa 100644
--- a/src/sage/rings/complex_interval.pyx
+++ b/src/sage/rings/complex_interval.pyx
@@ -290,7 +290,7 @@ cdef class ComplexIntervalFieldElement(FieldElement):
Exact and nearly exact points are still visible::
- sage: # needs sage.plot
+ sage: # needs sage.plot sage.symbolic
sage: plot(CIF(pi, 1), color='red') + plot(CIF(1, e), color='purple') + plot(CIF(-1, -1))
Graphics object consisting of 6 graphics primitives
diff --git a/src/sage/rings/continued_fraction.py b/src/sage/rings/continued_fraction.py
index a813816ac50..0021dc2745d 100644
--- a/src/sage/rings/continued_fraction.py
+++ b/src/sage/rings/continued_fraction.py
@@ -208,12 +208,20 @@
import numbers
import sage.rings.abc
+
+from sage.misc.lazy_import import lazy_import
from sage.rings.infinity import Infinity
from sage.rings.integer import Integer
from sage.rings.integer_ring import ZZ
from sage.structure.richcmp import rich_to_bool, richcmp_method
from sage.structure.sage_object import SageObject
+lazy_import('sage.combinat.words.abstract_word', 'Word_class')
+lazy_import('sage.combinat.words.finite_word', 'FiniteWord_class')
+lazy_import('sage.combinat.words.infinite_word', 'InfiniteWord_class')
+lazy_import('sage.combinat.words.word', 'Word')
+
+
ZZ_0 = Integer(0)
ZZ_1 = Integer(1)
ZZ_m1 = Integer(-1)
@@ -2490,7 +2498,10 @@ def continued_fraction_list(x, type="std", partial_convergents=False,
cf = None
- from sage.rings.real_mpfr import RealLiteral
+ try:
+ from sage.rings.real_mpfr import RealLiteral
+ except ImportError:
+ RealLiteral = ()
if isinstance(x, RealLiteral):
from sage.rings.real_mpfi import RealIntervalField
x = RealIntervalField(x.prec())(x)
@@ -2661,7 +2672,6 @@ def continued_fraction(x, value=None):
pass
# input for finite or ultimately periodic partial quotient expansion
- from sage.combinat.words.finite_word import FiniteWord_class
if isinstance(x, FiniteWord_class):
x = list(x)
@@ -2675,12 +2685,10 @@ def continued_fraction(x, value=None):
return ContinuedFraction_periodic(x1, x2)
# input for infinite partial quotient expansion
- from sage.combinat.words.infinite_word import InfiniteWord_class
from sage.misc.lazy_list import lazy_list_generic
if isinstance(x, (lazy_list_generic, InfiniteWord_class)):
return ContinuedFraction_infinite(x, value)
- from sage.combinat.words.abstract_word import Word_class
if isinstance(x, Word_class):
raise ValueError("word with unknown length cannot be converted "
"to continued fractions")
diff --git a/src/sage/rings/derivation.py b/src/sage/rings/derivation.py
index 2cd1bc1b1aa..d7d4fe6ebdf 100644
--- a/src/sage/rings/derivation.py
+++ b/src/sage/rings/derivation.py
@@ -1,7 +1,7 @@
r"""
Derivations
-Let `A` be a ring and `B` be an bimodule over `A`.
+Let `A` be a ring and `B` be a bimodule over `A`.
A derivation `d : A \to B` is an additive map that satisfies
the Leibniz rule
@@ -281,7 +281,7 @@ def __init__(self, domain, codomain, twist=None):
if twist is not None:
if not (isinstance(twist, Map) and twist.category_for().is_subcategory(Rings())):
- raise TypeError("the twisting homomorphism must be an homomorphism of rings")
+ raise TypeError("the twisting homomorphism must be a homomorphism of rings")
if twist.domain() is not domain:
map = twist.domain().coerce_map_from(domain)
if map is None:
@@ -1249,7 +1249,7 @@ def precompose(self, morphism):
sage: D.precompose(D)
Traceback (most recent call last):
...
- TypeError: you must give an homomorphism of rings
+ TypeError: you must give a homomorphism of rings
TESTS::
@@ -1266,7 +1266,7 @@ def precompose(self, morphism):
else:
raise TypeError("the given ring does not coerce to the domain of the derivation")
elif not (isinstance(morphism, Map) and morphism.category_for().is_subcategory(Rings())):
- raise TypeError("you must give an homomorphism of rings")
+ raise TypeError("you must give a homomorphism of rings")
M = RingDerivationModule(morphism.domain(), parent.defining_morphism() * morphism)
arg = [ ]
for x in M.dual_basis():
@@ -1316,7 +1316,7 @@ def postcompose(self, morphism):
sage: Dx.precompose(Dy)
Traceback (most recent call last):
...
- TypeError: you must give an homomorphism of rings
+ TypeError: you must give a homomorphism of rings
"""
parent = self.parent()
@@ -1326,7 +1326,7 @@ def postcompose(self, morphism):
else:
raise TypeError("the codomain of the derivation does not coerce to the given ring")
elif not (isinstance(morphism, Map) and morphism.category_for().is_subcategory(Rings())):
- raise TypeError("you must give an homomorphism of rings")
+ raise TypeError("you must give a homomorphism of rings")
M = RingDerivationModule(parent.domain(), morphism * parent.defining_morphism())
arg = [ ]
for x in M.dual_basis():
@@ -2281,7 +2281,7 @@ def precompose(self, morphism):
else:
raise TypeError("the given ring does not coerce to the domain of the derivation")
elif not (isinstance(morphism, Map) and morphism.category_for().is_subcategory(Rings())):
- raise TypeError("you must give an homomorphism of rings")
+ raise TypeError("you must give a homomorphism of rings")
M = RingDerivationModule(morphism.domain(), parent.defining_morphism() * morphism,
parent.twisting_morphism() * morphism)
return M(self._scalar)
@@ -2324,7 +2324,7 @@ def postcompose(self, morphism):
else:
raise TypeError("the codomain of the derivation does not coerce to the given ring")
elif not (isinstance(morphism, Map) and morphism.category_for().is_subcategory(Rings())):
- raise TypeError("you must give an homomorphism of rings")
+ raise TypeError("you must give a homomorphism of rings")
M = RingDerivationModule(parent.domain(), morphism * parent.defining_morphism(),
morphism * parent.twisting_morphism())
return M(morphism(self._scalar))
diff --git a/src/sage/rings/finite_rings/element_base.pyx b/src/sage/rings/finite_rings/element_base.pyx
index 8af0867a9f5..ab029287ba6 100755
--- a/src/sage/rings/finite_rings/element_base.pyx
+++ b/src/sage/rings/finite_rings/element_base.pyx
@@ -586,8 +586,8 @@ cdef class FinitePolyExtElement(FiniteRingElement):
Finite Field in a of size 19^2
sage: b = a**20
sage: p = FinitePolyExtElement.charpoly(b, "x", algorithm="pari")
- sage: q = FinitePolyExtElement.charpoly(b, "x", algorithm="matrix") # needs sage.modules
- sage: q == p # needs sage.modules
+ sage: q = FinitePolyExtElement.charpoly(b, "x", algorithm="matrix") # needs sage.modules
+ sage: q == p # needs sage.modules
True
sage: p
x^2 + 15*x + 4
diff --git a/src/sage/rings/finite_rings/element_givaro.pyx b/src/sage/rings/finite_rings/element_givaro.pyx
index 7619ec7185f..a4727e3311d 100644
--- a/src/sage/rings/finite_rings/element_givaro.pyx
+++ b/src/sage/rings/finite_rings/element_givaro.pyx
@@ -56,10 +56,11 @@ from cysignals.signals cimport sig_on, sig_off
from cypari2.paridecl cimport *
+import sage.arith.misc
+
from sage.misc.randstate cimport current_randstate
from sage.rings.finite_rings.element_pari_ffelt cimport FiniteFieldElement_pari_ffelt
from sage.structure.richcmp cimport richcmp
-import sage.arith.all
from cypari2.gen cimport Gen
from cypari2.stack cimport clear_stack
@@ -414,9 +415,6 @@ cdef class Cache_givaro(Cache_base):
# Reduce to pari
e = e.__pari__()
- elif isinstance(e, sage.libs.gap.element.GapElement_FiniteField):
- return e.sage(ring=self.parent)
-
elif isinstance(e, GapElement):
from sage.libs.gap.libgap import libgap
return libgap(e).sage(ring=self.parent)
@@ -434,6 +432,13 @@ cdef class Cache_givaro(Cache_base):
return ret
else:
+ try:
+ from sage.libs.gap.element import GapElement_FiniteField
+ except ImportError:
+ pass
+ else:
+ if isinstance(e, GapElement_FiniteField):
+ return e.sage(ring=self.parent)
raise TypeError("unable to coerce %r" % type(e))
cdef GEN t
@@ -524,7 +529,7 @@ cdef class Cache_givaro(Cache_base):
INPUT:
- - ``n`` -- integer representation of an finite field element
+ - ``n`` -- integer representation of a finite field element
OUTPUT:
@@ -1568,7 +1573,7 @@ cdef class FiniteField_givaroElement(FinitePolyExtElement):
raise ArithmeticError("Multiplicative order of 0 not defined.")
n = (self._cache).order_c() - 1
order = Integer(1)
- for p, e in sage.arith.all.factor(n):
+ for p, e in sage.arith.misc.factor(n):
# Determine the power of p that divides the order.
a = self**(n / (p**e))
while a != 1:
diff --git a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx
index 60d275ea5ae..bb490c163a8 100644
--- a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx
+++ b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx
@@ -274,7 +274,6 @@ cdef class Cache_ntl_gf2e(Cache_base):
cdef FiniteField_ntl_gf2eElement x
cdef FiniteField_ntl_gf2eElement g
cdef Py_ssize_t i
- from sage.libs.gap.element import GapElement_FiniteField
if is_IntegerMod(e):
e = e.lift()
@@ -334,14 +333,18 @@ cdef class Cache_ntl_gf2e(Cache_base):
# Reduce to pari
e = e.__pari__()
- elif isinstance(e, GapElement_FiniteField):
- return e.sage(ring=self._parent)
-
elif isinstance(e, GapElement):
from sage.libs.gap.libgap import libgap
return libgap(e).sage(ring=self._parent)
else:
+ try:
+ from sage.libs.gap.element import GapElement_FiniteField
+ except ImportError:
+ pass
+ else:
+ if isinstance(e, GapElement_FiniteField):
+ return e.sage(ring=self._parent)
raise TypeError("unable to coerce %r" % type(e))
cdef GEN t
diff --git a/src/sage/rings/finite_rings/element_pari_ffelt.pyx b/src/sage/rings/finite_rings/element_pari_ffelt.pyx
index ca262f6f668..4f37f6c3043 100644
--- a/src/sage/rings/finite_rings/element_pari_ffelt.pyx
+++ b/src/sage/rings/finite_rings/element_pari_ffelt.pyx
@@ -611,6 +611,7 @@ cdef class FiniteFieldElement_pari_ffelt(FinitePolyExtElement):
EXAMPLES::
+ sage: # needs sage.modules
sage: k. = GF(2^20, impl='pari_ffelt')
sage: e = k.random_element()
sage: f = loads(dumps(e))
diff --git a/src/sage/rings/finite_rings/finite_field_givaro.py b/src/sage/rings/finite_rings/finite_field_givaro.py
index 2dd96beeb34..9f6abdb40b4 100644
--- a/src/sage/rings/finite_rings/finite_field_givaro.py
+++ b/src/sage/rings/finite_rings/finite_field_givaro.py
@@ -462,7 +462,7 @@ def int_to_log(self, n):
INPUT:
- - ``n`` -- integer representation of an finite field element
+ - ``n`` -- integer representation of a finite field element
OUTPUT:
diff --git a/src/sage/rings/finite_rings/galois_group.py b/src/sage/rings/finite_rings/galois_group.py
index 293803f1e98..f11b72bc681 100644
--- a/src/sage/rings/finite_rings/galois_group.py
+++ b/src/sage/rings/finite_rings/galois_group.py
@@ -1,3 +1,4 @@
+# sage.doctest: needs sage.modules sage.rings.finite_rings
r"""
Galois groups of Finite Fields
"""
@@ -109,7 +110,7 @@ def _element_constructor_(self, x, check=True):
Frob^2
sage: G(G.gens()[0])
Frob
- sage: G([(1,3,2)])
+ sage: G([(1,3,2)]) # needs sage.libs.gap
Frob^2
sage: G(k.hom(k.gen()^3, k))
Frob
diff --git a/src/sage/rings/finite_rings/integer_mod_ring.py b/src/sage/rings/finite_rings/integer_mod_ring.py
index 0bb4ce21f4b..eb35543a20e 100644
--- a/src/sage/rings/finite_rings/integer_mod_ring.py
+++ b/src/sage/rings/finite_rings/integer_mod_ring.py
@@ -617,13 +617,13 @@ def multiplicative_subgroups(self):
EXAMPLES::
sage: # needs sage.groups
- sage: Integers(5).multiplicative_subgroups()
+ sage: Integers(5).multiplicative_subgroups() # optional - gap_package_polycyclic
((2,), (4,), ())
- sage: Integers(15).multiplicative_subgroups()
+ sage: Integers(15).multiplicative_subgroups() # optional - gap_package_polycyclic
((11, 7), (11, 4), (2,), (11,), (14,), (7,), (4,), ())
- sage: Integers(2).multiplicative_subgroups()
+ sage: Integers(2).multiplicative_subgroups() # optional - gap_package_polycyclic
((),)
- sage: len(Integers(341).multiplicative_subgroups())
+ sage: len(Integers(341).multiplicative_subgroups()) # optional - gap_package_polycyclic
80
TESTS::
@@ -632,7 +632,7 @@ def multiplicative_subgroups(self):
((),)
sage: IntegerModRing(2).multiplicative_subgroups() # needs sage.groups
((),)
- sage: IntegerModRing(3).multiplicative_subgroups() # needs sage.groups
+ sage: IntegerModRing(3).multiplicative_subgroups() # needs sage.groups # optional - gap_package_polycyclic
((2,), ())
"""
return tuple(tuple(g.value() for g in H.gens())
diff --git a/src/sage/rings/finite_rings/residue_field.pyx b/src/sage/rings/finite_rings/residue_field.pyx
index e84b303769a..b79416eb1d7 100644
--- a/src/sage/rings/finite_rings/residue_field.pyx
+++ b/src/sage/rings/finite_rings/residue_field.pyx
@@ -128,7 +128,7 @@ First over a small non-prime field::
Residue field in ubar of Fractional ideal
(47, 517/55860*u^5 + 235/3724*u^4 + 9829/13965*u^3
+ 54106/13965*u^2 + 64517/27930*u + 755696/13965)
- sage: I.groebner_basis()
+ sage: I.groebner_basis() # needs sage.libs.singular
[X + (-19*ubar^2 - 5*ubar - 17)*Y]
And now over a large prime field::
@@ -144,11 +144,11 @@ And now over a large prime field::
4398046511119
sage: S. = PolynomialRing(Rf, order='lex')
sage: I = ideal([2*X - Y^2, Y + Z])
- sage: I.groebner_basis()
+ sage: I.groebner_basis() # needs sage.libs.singular
[X + 2199023255559*Z^2, Y + Z]
sage: S. = PolynomialRing(Rf, order='deglex')
sage: I = ideal([2*X - Y^2, Y + Z])
- sage: I.groebner_basis()
+ sage: I.groebner_basis() # needs sage.libs.singular
[Z^2 + 4398046511117*X, Y + Z]
"""
diff --git a/src/sage/rings/finite_rings/residue_field_pari_ffelt.pyx b/src/sage/rings/finite_rings/residue_field_pari_ffelt.pyx
index f21a3b8d9bb..e9962c3ccde 100644
--- a/src/sage/rings/finite_rings/residue_field_pari_ffelt.pyx
+++ b/src/sage/rings/finite_rings/residue_field_pari_ffelt.pyx
@@ -118,7 +118,7 @@ class ResidueFiniteField_pari_ffelt(ResidueField_generic, FiniteField_pari_ffelt
sage: R. = GF(5)[]; P = R.ideal(4*t^12 + 3*t^11 + 4*t^10 + t^9 + t^8 + 3*t^7 + 2*t^6 + 3*t^4 + t^3 + 3*t^2 + 2)
sage: k. = P.residue_field()
- sage: V = k.vector_space(map=False); v = V([1,2,3,4,5,6,7,8,9,0,1,2]); k(v) # indirect doctest # needs sage.modules
+ sage: V = k.vector_space(map=False); v = V([1,2,3,4,5,6,7,8,9,0,1,2]); k(v) # indirect doctest # needs sage.modules
2*a^11 + a^10 + 4*a^8 + 3*a^7 + 2*a^6 + a^5 + 4*a^3 + 3*a^2 + 2*a + 1
"""
try:
diff --git a/src/sage/rings/function_field/function_field_rational.py b/src/sage/rings/function_field/function_field_rational.py
index e763a673a15..226d87d084c 100644
--- a/src/sage/rings/function_field/function_field_rational.py
+++ b/src/sage/rings/function_field/function_field_rational.py
@@ -138,7 +138,7 @@ def __init__(self, constant_field, names, category=None):
sage: K. = FunctionField(CC); K # needs sage.rings.real_mpfr
Rational function field in t over Complex Field with 53 bits of precision
- sage: TestSuite(K).run() # long time (5s) # needs sage.rings.real_mpfr
+ sage: TestSuite(K).run() # long time (5s) # needs sage.rings.real_mpfr
sage: FunctionField(QQ[I], 'alpha') # needs sage.rings.number_field
Rational function field in alpha over
diff --git a/src/sage/rings/generic.py b/src/sage/rings/generic.py
index 83f923cee5c..99bf690bef6 100644
--- a/src/sage/rings/generic.py
+++ b/src/sage/rings/generic.py
@@ -20,6 +20,7 @@ class ProductTree:
(the famous *Fast* Fourier Transform) can be implemented as follows
using the :meth:`remainders` method of this class::
+ sage: # needs sage.rings.finite_rings
sage: from sage.rings.generic import ProductTree
sage: F = GF(65537)
sage: a = F(1111)
@@ -62,6 +63,7 @@ class ProductTree:
::
+ sage: # needs sage.libs.pari
sage: vs = prime_range(100)
sage: tree = ProductTree(vs)
sage: tree.root().factor()
@@ -71,7 +73,7 @@ class ProductTree:
We can access the individual layers of the tree::
- sage: tree.layers
+ sage: tree.layers # 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),
(6, 35, 143, 323, 667, 1147, 1763, 2491, 3599, 4757, 5767, 7387, 97),
(210, 46189, 765049, 4391633, 17120443, 42600829, 97),
@@ -87,8 +89,8 @@ def __init__(self, leaves):
EXAMPLES::
sage: from sage.rings.generic import ProductTree
- sage: vs = prime_range(100)
- sage: tree = ProductTree(vs)
+ sage: vs = prime_range(100) # needs sage.libs.pari
+ sage: tree = ProductTree(vs) # needs sage.libs.pari
"""
V = tuple(leaves)
self.layers = [V]
@@ -182,6 +184,7 @@ def remainders(self, x):
EXAMPLES::
+ sage: # needs sage.libs.pari
sage: from sage.rings.generic import ProductTree
sage: vs = prime_range(100)
sage: tree = ProductTree(vs)
diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx
index c990c200e57..415b0ff7d80 100644
--- a/src/sage/rings/integer.pyx
+++ b/src/sage/rings/integer.pyx
@@ -4076,7 +4076,9 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
"""
if self.is_zero():
raise ArithmeticError("support of 0 not defined")
- return sage.arith.all.prime_factors(self)
+ from sage.arith.misc import prime_factors
+
+ return prime_factors(self)
def coprime_integers(self, m):
"""
@@ -7539,7 +7541,7 @@ def _check_global_dummy_Integer():
# It operates on the following principles:
#
# - The pool starts out empty.
-# - When an new integer is needed, one from the pool is returned
+# - When a new integer is needed, one from the pool is returned
# if available, otherwise a new Integer object is created
# - When an integer is collected, it will add it to the pool
# if there is room, otherwise it will be deallocated.
diff --git a/src/sage/rings/localization.py b/src/sage/rings/localization.py
index 20c090da681..ea7534349fa 100644
--- a/src/sage/rings/localization.py
+++ b/src/sage/rings/localization.py
@@ -584,7 +584,7 @@ class Localization(IntegralDomain, UniqueRepresentation):
Accordingly, this class is inherited from :class:`IntegralDomain` and can only be used in that context.
Furthermore, the base ring should support :meth:`sage.structure.element.CommutativeRingElement.divides` and
the exact division operator `//` (:meth:`sage.structure.element.Element.__floordiv__`) in order to guarantee
- an successful application.
+ a successful application.
INPUT:
diff --git a/src/sage/rings/morphism.pyx b/src/sage/rings/morphism.pyx
index a9cb8eda29e..c65f75a248c 100644
--- a/src/sage/rings/morphism.pyx
+++ b/src/sage/rings/morphism.pyx
@@ -1255,7 +1255,7 @@ cdef class RingHomomorphism(RingMap):
Ideals in quotient rings over ``QQbar`` do not support reduction yet,
so the graph is constructed in the ambient ring instead::
- sage: # needs sage.rings.number_field
+ sage: # needs sage.libs.singular sage.rings.number_field
sage: A. = QQbar['z,w'].quotient('z*w - 1')
sage: B. = QQbar['x,y'].quotient('2*x^2 + y^2 - 1')
sage: f = A.hom([QQbar(2).sqrt()*x + QQbar(I)*y,
@@ -1447,7 +1447,7 @@ cdef class RingHomomorphism(RingMap):
An isomorphism between the algebraic torus and the circle over a number
field::
- sage: # needs sage.rings.number_field
+ sage: # needs sage.libs.singular sage.rings.number_field
sage: K. = QuadraticField(-1)
sage: A. = K['z,w'].quotient('z*w - 1')
sage: B. = K['x,y'].quotient('x^2 + y^2 - 1')
diff --git a/src/sage/rings/multi_power_series_ring.py b/src/sage/rings/multi_power_series_ring.py
index 3d96666e222..8ceaa9c5154 100644
--- a/src/sage/rings/multi_power_series_ring.py
+++ b/src/sage/rings/multi_power_series_ring.py
@@ -204,24 +204,29 @@
# http://www.gnu.org/licenses/
#*****************************************************************************
+import sage.misc.latex as latex
-from sage.rings.ring import CommutativeRing
-from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
+from sage.rings.infinity import infinity
+from sage.rings.multi_power_series_ring_element import MPowerSeries
from sage.rings.polynomial.polynomial_ring import is_PolynomialRing
+from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing
from sage.rings.polynomial.term_order import TermOrder
from sage.rings.power_series_ring import PowerSeriesRing, PowerSeriesRing_generic, is_PowerSeriesRing
-
-from sage.rings.infinity import infinity
-import sage.misc.latex as latex
+from sage.rings.ring import CommutativeRing
from sage.structure.nonexact import Nonexact
-from sage.rings.multi_power_series_ring_element import MPowerSeries
from sage.categories.commutative_rings import CommutativeRings
_CommutativeRings = CommutativeRings()
+
from sage.categories.integral_domains import IntegralDomains
_IntegralDomains = IntegralDomains()
+try:
+ from sage.rings.laurent_series_ring import LaurentSeriesRing
+except ImportError:
+ LaurentSeriesRing = ()
+
def is_MPowerSeriesRing(x):
"""
@@ -731,8 +736,8 @@ def _is_valid_homomorphism_(self, codomain, im_gens, base_map=None):
return False
if all(v == 0 for v in im_gens):
return True
- from .laurent_series_ring import is_LaurentSeriesRing
- if is_MPowerSeriesRing(codomain) or is_PowerSeriesRing(codomain) or is_LaurentSeriesRing(codomain):
+
+ if is_MPowerSeriesRing(codomain) or is_PowerSeriesRing(codomain) or isinstance(codomain, LaurentSeriesRing):
try:
B = all(v.valuation() > 0 or v.is_nilpotent() for v in im_gens)
except NotImplementedError:
diff --git a/src/sage/rings/number_field/S_unit_solver.py b/src/sage/rings/number_field/S_unit_solver.py
index 68ca166f6df..4b6b201375f 100644
--- a/src/sage/rings/number_field/S_unit_solver.py
+++ b/src/sage/rings/number_field/S_unit_solver.py
@@ -1071,7 +1071,7 @@ def reduction_step_complex_case(place, B0, list_of_gens, torsion_gen, c13):
A = A.transpose()
- # Note that l is the an lower bound on the square of the magnitude of the shortest non-zero vector in the lattice generated by A
+ # Note that l is the lower bound on the square of the magnitude of the shortest non-zero vector in the lattice generated by A
l = minimal_vector(A, zero_vector(ZZ,n+1))
# Checking hypotheses of Lemma 5.3 in our paper:
diff --git a/src/sage/rings/number_field/bdd_height.py b/src/sage/rings/number_field/bdd_height.py
index 0681aaef58e..2b3d18a6578 100644
--- a/src/sage/rings/number_field/bdd_height.py
+++ b/src/sage/rings/number_field/bdd_height.py
@@ -531,7 +531,7 @@ def packet_height(n, pair, u):
possible_norm_set.add(m * class_group_rep_norms[n])
bdd_ideals = bdd_norm_pr_ideal_gens(K, possible_norm_set)
- # Stores it in form of an dictionary and gives lambda(g)_approx for key g
+ # Stores it in form of a dictionary and gives lambda(g)_approx for key g
for norm in possible_norm_set:
gens = bdd_ideals[norm]
for g in gens:
diff --git a/src/sage/rings/number_field/galois_group.py b/src/sage/rings/number_field/galois_group.py
index 2e6b876e541..9ea602dc1aa 100644
--- a/src/sage/rings/number_field/galois_group.py
+++ b/src/sage/rings/number_field/galois_group.py
@@ -10,9 +10,9 @@
"""
from sage.structure.sage_object import SageObject
-from sage.groups.galois_group import _alg_key, GaloisGroup_perm, GaloisSubgroup_perm
+from sage.groups.galois_group import _alg_key
+from sage.groups.galois_group_perm import GaloisGroup_perm, GaloisSubgroup_perm
from sage.groups.perm_gps.permgroup import standardize_generator
-
from sage.groups.perm_gps.permgroup_element import PermutationGroupElement
from sage.misc.superseded import deprecation
from sage.misc.cachefunc import cached_method
diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py
index e34606e085b..6e6d0fc36e4 100644
--- a/src/sage/rings/number_field/number_field.py
+++ b/src/sage/rings/number_field/number_field.py
@@ -82,7 +82,6 @@
import sage.libs.ntl.all as ntl
-import sage.interfaces.gap
import sage.rings.complex_mpfr
from sage.rings.polynomial.polynomial_element import Polynomial
@@ -92,14 +91,14 @@
import sage.rings.real_double
import sage.rings.real_lazy
-from sage.rings.finite_rings.integer_mod import mod
-
-
+from sage.arith.misc import euler_phi, factor, gcd, next_prime
from sage.misc.fast_methods import WithEqualityById
from sage.misc.functional import is_odd, lift
from sage.misc.lazy_import import lazy_import
from sage.misc.misc_c import prod
+from sage.misc.sage_eval import sage_eval
from sage.rings.infinity import Infinity
+from sage.rings.finite_rings.integer_mod import mod
from sage.categories.number_fields import NumberFields
import sage.rings.ring
@@ -204,7 +203,6 @@ def proof_flag(t):
from sage.misc.latex import latex
-import sage.arith.all as arith
import sage.rings.infinity as infinity
from sage.rings.rational import Rational
from sage.rings.integer import Integer
@@ -371,18 +369,20 @@ def NumberField(polynomial, name=None, check=True, names=None, embedding=None,
One can embed into any other field::
- sage: K. = NumberField(x^3-2, embedding=CC.gen()-0.6)
+ sage: K. = NumberField(x^3 - 2, embedding=CC.gen() - 0.6)
sage: CC(a)
-0.629960524947436 + 1.09112363597172*I
- sage: L = Qp(5) # needs sage.rings.padics
+
+ sage: # needs sage.rings.padics
+ sage: L = Qp(5)
sage: f = polygen(L)^3 - 2
- sage: K. = NumberField(x^3-2, embedding=f.roots()[0][0])
+ sage: K. = NumberField(x^3 - 2, embedding=f.roots()[0][0])
sage: a + L(1)
4 + 2*5^2 + 2*5^3 + 3*5^4 + 5^5 + 4*5^6 + 2*5^8 + 3*5^9 + 4*5^12
+ 4*5^14 + 4*5^15 + 3*5^16 + 5^17 + 5^18 + 2*5^19 + O(5^20)
- sage: L. = NumberField(x^6-x^2+1/10, embedding=1)
- sage: K. = NumberField(x^3-x+1/10, embedding=b^2)
- sage: a+b
+ sage: L. = NumberField(x^6 - x^2 + 1/10, embedding=1)
+ sage: K. = NumberField(x^3 - x + 1/10, embedding=b^2)
+ sage: a + b
b^2 + b
sage: CC(a) == CC(b)^2
True
@@ -409,7 +409,7 @@ def NumberField(polynomial, name=None, check=True, names=None, embedding=None,
Note that the codomain of the embedding must be ``QQbar`` or ``AA`` for this to work
(see :trac:`20184`)::
- sage: N. = NumberField(x^3 + 2,embedding=1)
+ sage: N. = NumberField(x^3 + 2, embedding=1)
sage: 1 < g
False
sage: g > 1
@@ -493,7 +493,7 @@ def NumberField(polynomial, name=None, check=True, names=None, embedding=None,
The following has been fixed in :trac:`8800`::
sage: P. = QQ[]
- sage: K. = NumberField(x^3 - 5,embedding=0)
+ sage: K. = NumberField(x^3 - 5, embedding=0)
sage: L. = K.extension(x^2 + a)
sage: F, R = L.construction()
sage: F(R) == L # indirect doctest
@@ -1309,7 +1309,7 @@ class NumberField_generic(WithEqualityById, number_field_base.NumberField):
This example was suggested on sage-nt; see :trac:`18942`::
sage: G = DirichletGroup(80) # needs sage.modular
- sage: for chi in G: # long time # needs sage.modular
+ sage: for chi in G: # long time # needs sage.modular
....: D = ModularSymbols(chi, 2, -1).cuspidal_subspace().new_subspace().decomposition()
....: for f in D:
....: elt = f.q_eigenform(10, 'alpha')[3]
@@ -1561,7 +1561,7 @@ def construction(self):
::
sage: P. = QQ[]
- sage: K. = NumberField(x^3-5,embedding=0)
+ sage: K. = NumberField(x^3-5, embedding=0)
sage: L. = K.extension(x^2+a)
sage: a*b
a*b
@@ -1940,7 +1940,7 @@ def _convert_from_str(self, x):
sage: k('theta25^3 + (1/3)*theta25')
-1/3*theta25 - 1
"""
- w = sage.misc.all.sage_eval(x, locals=self.gens_dict())
+ w = sage_eval(x, locals=self.gens_dict())
if not (is_Element(w) and w.parent() is self):
return self(w)
else:
@@ -3317,6 +3317,7 @@ def conductor(self, check_abelian=True):
EXAMPLES::
+ sage: # needs sage.groups
sage: K = CyclotomicField(27)
sage: k = K.subfields(9)[0][0]
sage: k.conductor()
@@ -3387,27 +3388,29 @@ def dirichlet_group(self):
EXAMPLES::
+ sage: # needs sage.groups sage.modular
sage: x = polygen(QQ, 'x')
sage: K. = NumberField(x^3 + x^2 - 36*x - 4)
sage: K.conductor()
109
- sage: K.dirichlet_group()
+ sage: K.dirichlet_group() # optional - gap_package_polycyclic
[Dirichlet character modulo 109 of conductor 1 mapping 6 |--> 1,
Dirichlet character modulo 109 of conductor 109 mapping 6 |--> zeta3,
Dirichlet character modulo 109 of conductor 109 mapping 6 |--> -zeta3 - 1]
+ sage: # needs sage.modular
sage: K = CyclotomicField(44)
sage: L = K.subfields(5)[0][0]
- sage: X = L.dirichlet_group()
- sage: X
+ sage: X = L.dirichlet_group(); X # optional - gap_package_polycyclic
[Dirichlet character modulo 11 of conductor 1 mapping 2 |--> 1,
Dirichlet character modulo 11 of conductor 11 mapping 2 |--> zeta5,
Dirichlet character modulo 11 of conductor 11 mapping 2 |--> zeta5^2,
Dirichlet character modulo 11 of conductor 11 mapping 2 |--> zeta5^3,
- Dirichlet character modulo 11 of conductor 11 mapping 2 |--> -zeta5^3 - zeta5^2 - zeta5 - 1]
- sage: X[4]^2
+ Dirichlet character modulo 11 of conductor 11
+ mapping 2 |--> -zeta5^3 - zeta5^2 - zeta5 - 1]
+ sage: X[4]^2 # optional - gap_package_polycyclic
Dirichlet character modulo 11 of conductor 11 mapping 2 |--> zeta5^3
- sage: X[4]^2 in X
+ sage: X[4]^2 in X # optional - gap_package_polycyclic
True
"""
# todo : turn this into an abelian group rather than a list.
@@ -3962,10 +3965,8 @@ def primes_of_bounded_norm(self, B):
from sage.rings.fast_arith import prime_range
if self is QQ:
- # return arith.primes(B+1)
return prime_range(B + 1, algorithm="pari_isprime")
else:
- # P = [pp for p in arith.primes(B+1) for pp in self.primes_above(p)]
P = (pp for p in prime_range(B + 1, algorithm="pari_isprime")
for pp in self.primes_above(p))
P = [p for p in P if p.norm() <= B]
@@ -4016,11 +4017,9 @@ def primes_of_bounded_norm_iter(self, B):
from sage.rings.fast_arith import prime_range
if self is QQ:
- # for p in arith.primes(B+1):
for p in prime_range(B + 1, algorithm="pari_isprime"):
yield p
else:
- # for p in arith.primes(B+1):
for p in prime_range(B + 1, algorithm="pari_isprime"):
for pp in self.primes_above(p):
if pp.norm() <= B:
@@ -4133,7 +4132,7 @@ def completely_split_primes(self, B=200):
from sage.rings.fast_arith import prime_range
from sage.rings.finite_rings.finite_field_constructor import GF
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
- from sage.arith.misc import factor
+
split_primes = []
for p in prime_range(B):
Fp = GF(p)
@@ -4530,7 +4529,8 @@ def _gap_init_(self):
"""
if not self.is_absolute():
raise NotImplementedError("Currently, only simple algebraic extensions are implemented in gap")
- G = sage.interfaces.gap.gap
+ from sage.interfaces.gap import gap as G
+
q = self.polynomial()
if q.variable_name() != 'E':
return 'CallFuncList(function() local %s,E; %s:=Indeterminate(%s,"%s"); E:=AlgebraicExtension(%s,%s,"%s"); return E; end,[])' % (q.variable_name(), q.variable_name(), G(self.base_ring()).name(), q.variable_name(), G(self.base_ring()).name(), repr(self.polynomial()), str(self.gen()))
@@ -4608,6 +4608,7 @@ def class_group(self, proof=None, names='c'):
Class groups of Hecke polynomials tend to be very small::
+ sage: # needs sage.modular
sage: f = ModularForms(97, 2).T(2).charpoly()
sage: f.factor()
(x - 3) * (x^3 + 4*x^2 + 3*x - 1) * (x^4 - 3*x^3 - x^2 + 6*x - 1)
@@ -5980,7 +5981,7 @@ def decomposition_type(self, p):
sage: R. = ZZ[]
sage: K. = NumberField(x^20 + 3*x^18 + 15*x^16 + 28*x^14 + 237*x^12 + 579*x^10
....: + 1114*x^8 + 1470*x^6 + 2304*x^4 + 1296*x^2 + 729)
- sage: K.is_galois()
+ sage: K.is_galois() # needs sage.groups
True
sage: K.discriminant().factor()
2^20 * 3^10 * 53^10
@@ -6147,6 +6148,7 @@ def is_galois(self):
EXAMPLES::
+ sage: # needs sage.groups
sage: x = polygen(QQ, 'x')
sage: NumberField(x^2 + 1, 'i').is_galois()
True
@@ -6173,6 +6175,7 @@ def is_abelian(self):
EXAMPLES::
+ sage: # needs sage.groups
sage: x = polygen(QQ, 'x')
sage: NumberField(x^2 + 1, 'i').is_abelian()
True
@@ -6233,6 +6236,7 @@ def galois_group(self, type=None, algorithm='pari', names=None, gc_numbering=Non
EXAMPLES::
+ sage: # needs sage.groups
sage: x = polygen(QQ, 'x')
sage: k. = NumberField(x^2 - 14) # a Galois extension
sage: G = k.galois_group(); G
@@ -6244,13 +6248,14 @@ def galois_group(self, type=None, algorithm='pari', names=None, gc_numbering=Non
sage: G.artin_symbol(k.primes_above(3)[0])
(1,2)
- sage: k. = NumberField(x^3 - x + 1) # not Galois
+ sage: # needs sage.groups
+ sage: k. = NumberField(x^3 - x + 1) # not Galois
sage: G = k.galois_group(names='c'); G
Galois group 3T2 (S3) with order 6 of x^3 - x + 1
sage: G.gen(0)
(1,2,3)(4,5,6)
- sage: NumberField(x^3 + 2*x + 1, 'a').galois_group(algorithm='magma') # optional - magma
+ sage: NumberField(x^3 + 2*x + 1, 'a').galois_group(algorithm='magma') # optional - magma, needs sage.groups
Galois group Transitive group number 2 of degree 3
of the Number Field in a with defining polynomial x^3 + 2*x + 1
@@ -6259,6 +6264,7 @@ def galois_group(self, type=None, algorithm='pari', names=None, gc_numbering=Non
::
+ sage: # needs sage.groups
sage: K. = NumberField(x^3 - 2)
sage: L. = K.galois_closure(); L
Number Field in b1 with defining polynomial x^6 + 108
@@ -6284,6 +6290,7 @@ def galois_group(self, type=None, algorithm='pari', names=None, gc_numbering=Non
change in the future, so it's better to explicitly call :meth:`absolute_field` if that is
the desired behavior::
+ sage: # needs sage.groups
sage: x = polygen(QQ)
sage: K. = NumberField(x^2 + 1)
sage: R. = PolynomialRing(K)
@@ -6298,6 +6305,7 @@ def galois_group(self, type=None, algorithm='pari', names=None, gc_numbering=Non
We check that the changes in :trac:`28782` won't break code that used v1 Galois groups::
+ sage: # needs sage.groups
sage: G = NumberField(x^3 - 2, 'a').galois_group(type="pari")
...DeprecationWarning: the different Galois types have been merged into one class
See https://github.com/sagemath/sage/issues/28782 for details.
@@ -7427,6 +7435,7 @@ def S_unit_solutions(self, S=[], prec=106, include_exponents=False, include_boun
EXAMPLES::
+ sage: # needs sage.rings.padics
sage: x = polygen(QQ, 'x')
sage: K. = NumberField(x^2 + x + 1)
sage: S = K.primes_above(3)
@@ -7435,7 +7444,8 @@ def S_unit_solutions(self, S=[], prec=106, include_exponents=False, include_boun
You can get the exponent vectors::
- sage: K.S_unit_solutions(S, include_exponents=True) # random, due to ordering
+ sage: # needs sage.rings.padics
+ sage: K.S_unit_solutions(S, include_exponents=True) # random, due to ordering
[((2, 1), (4, 0), xi + 2, -xi - 1),
((5, -1), (4, -1), 1/3*xi + 2/3, -1/3*xi + 1/3),
((5, 0), (1, 0), -xi, xi + 1),
@@ -7443,6 +7453,7 @@ def S_unit_solutions(self, S=[], prec=106, include_exponents=False, include_boun
And the computed bound::
+ sage: # needs sage.rings.padics
sage: solutions, bound = K.S_unit_solutions(S, prec=100, include_bound=True)
sage: bound
7
@@ -7545,7 +7556,7 @@ def zeta(self, n=2, all=False):
# First check if the degree of K is compatible
# with an inclusion QQ(\zeta_n) -> K.
- if sage.arith.all.euler_phi(n).divides(K.absolute_degree()):
+ if euler_phi(n).divides(K.absolute_degree()):
w, zeta_w = self.pari_nf().nfrootsof1()
w = w.sage()
zeta_w = K(zeta_w)
@@ -7786,17 +7797,17 @@ def valuation(self, prime):
sage: x = polygen(QQ, 'x')
sage: K. = NumberField(x^2 + 1)
- sage: K.valuation(2)
+ sage: K.valuation(2) # needs sage.rings.padics
2-adic valuation
It can also be unramified in ``R``::
- sage: K.valuation(3)
+ sage: K.valuation(3) # needs sage.rings.padics
3-adic valuation
A ``prime`` that factors into pairwise distinct factors, results in an error::
- sage: K.valuation(5)
+ sage: K.valuation(5) # needs sage.rings.padics
Traceback (most recent call last):
...
ValueError: The valuation Gauss valuation induced by 5-adic valuation does not
@@ -7805,12 +7816,12 @@ def valuation(self, prime):
The valuation can also be selected by giving a valuation on the base
ring that extends uniquely::
- sage: CyclotomicField(5).valuation(ZZ.valuation(5))
+ sage: CyclotomicField(5).valuation(ZZ.valuation(5)) # needs sage.rings.padics
5-adic valuation
When the extension is not unique, this does not work::
- sage: K.valuation(ZZ.valuation(5))
+ sage: K.valuation(ZZ.valuation(5)) # needs sage.rings.padics
Traceback (most recent call last):
...
ValueError: The valuation Gauss valuation induced by 5-adic valuation does not
@@ -7821,6 +7832,7 @@ def valuation(self, prime):
`G` to infinity. This lets us specify which extension of the 5-adic
valuation we care about in the above example::
+ sage: # needs sage.rings.padics
sage: R. = QQ[]
sage: G5 = GaussValuation(R, QQ.valuation(5))
sage: v = K.valuation(G5.augmentation(x + 2, infinity))
@@ -7831,6 +7843,7 @@ def valuation(self, prime):
Note that you get the same valuation, even if you write down the
pseudo-valuation differently::
+ sage: # needs sage.rings.padics
sage: ww = K.valuation(G5.augmentation(x + 3, infinity))
sage: w is ww
True
@@ -7841,6 +7854,7 @@ def valuation(self, prime):
completion, i.e., if it is not possible to write down one of the factors
within the number field::
+ sage: # needs sage.rings.padics
sage: v = G5.augmentation(x + 3, 1)
sage: K.valuation(v)
[ 5-adic valuation, v(x + 3) = 1 ]-adic valuation
@@ -7848,7 +7862,7 @@ def valuation(self, prime):
Finally, ``prime`` can also be a fractional ideal of a number field if it
singles out an extension of a `p`-adic valuation of the base field::
- sage: K.valuation(K.fractional_ideal(a + 1))
+ sage: K.valuation(K.fractional_ideal(a + 1)) # needs sage.rings.padics
2-adic valuation
.. SEEALSO::
@@ -8224,7 +8238,7 @@ def _coerce_from_other_number_field(self, x):
The following was fixed in :trac:`8800`::
sage: P. = QQ[]
- sage: K. = NumberField(x^3 - 5,embedding=0)
+ sage: K. = NumberField(x^3 - 5, embedding=0)
sage: L. = K.extension(x^2 + a)
sage: F,R = L.construction()
sage: F(R) == L #indirect doctest
@@ -9121,6 +9135,7 @@ def _galois_closure_and_embedding(self, names=None):
For medium-sized Galois groups of fields with small discriminants,
this computation is feasible::
+ sage: # needs sage.groups
sage: x = polygen(QQ, 'x')
sage: K. = NumberField(x^6 + 4*x^2 + 2)
sage: K.galois_group().order()
@@ -9168,6 +9183,7 @@ def galois_closure(self, names=None, map=False):
EXAMPLES::
+ sage: # needs sage.groups
sage: x = polygen(QQ, 'x')
sage: K. = NumberField(x^4 - 2)
sage: M = K.galois_closure('b'); M
@@ -9179,12 +9195,14 @@ def galois_closure(self, names=None, map=False):
::
+ sage: # needs sage.groups
sage: phi = K.embeddings(L)[0]
sage: phi(K.0)
1/120*a2^5 + 19/60*a2
sage: phi(K.0).minpoly()
x^4 - 2
+ sage: # needs sage.groups
sage: L, phi = K.galois_closure('b', map=True)
sage: L
Number Field in b with defining polynomial x^8 + 28*x^4 + 2500
@@ -9196,6 +9214,7 @@ def galois_closure(self, names=None, map=False):
A cyclotomic field is already Galois::
+ sage: # needs sage.groups
sage: K. = NumberField(cyclotomic_polynomial(23))
sage: L. = K.galois_closure()
sage: L
@@ -9207,6 +9226,7 @@ def galois_closure(self, names=None, map=False):
Let's make sure we're renaming correctly::
+ sage: # needs sage.groups
sage: K. = NumberField(x^4 - 2)
sage: L, phi = K.galois_closure('cc', map=True)
sage: L
@@ -9291,6 +9311,7 @@ def embeddings(self, K):
EXAMPLES::
+ sage: # needs sage.groups
sage: x = polygen(QQ, 'x')
sage: K. = NumberField(x^3 - 2)
sage: L. = K.galois_closure(); L
@@ -10940,6 +10961,7 @@ def _gap_init_(self):
TESTS::
+ sage: # needs sage.libs.gap
sage: K = CyclotomicField(8)
sage: gap(K) # indirect doctest
CF(8)
@@ -10953,13 +10975,15 @@ def _gap_init_(self):
a genuine representation of cyclotomic fields in the
GAP interface -- see :trac:`5618`. ::
+ sage: # needs sage.groups
sage: H = AlternatingGroup(4)
sage: g = H((1,4,3))
sage: K = H.subgroup([g])
sage: z = CyclotomicField(3).an_element(); z
zeta3
sage: c = K.character([1,z,z**2]); c
- Character of Subgroup generated by [(1,4,3)] of (Alternating group of order 4!/2 as a permutation group)
+ Character of Subgroup generated by [(1,4,3)] of
+ (Alternating group of order 4!/2 as a permutation group)
sage: c(g^2); z^2
zeta3
-zeta3 - 1
@@ -10972,10 +10996,11 @@ def _libgap_(self):
TESTS::
+ sage: # needs sage.libs.gap
sage: K = CyclotomicField(8)
- sage: K._libgap_() # needs sage.libs.gap
+ sage: K._libgap_()
CF(8)
- sage: libgap(K) # indirect doctest # needs sage.libs.gap
+ sage: libgap(K) # indirect doctest
CF(8)
"""
from sage.libs.gap.libgap import libgap
@@ -11608,7 +11633,7 @@ def embeddings(self, K):
# zeta not defined
return super().embeddings(K)
else:
- X = (m for m in range(n) if arith.gcd(m, n) == 1)
+ X = (m for m in range(n) if gcd(m, n) == 1)
v = [self.hom([z**i], check=False) for i in X]
else:
v = []
@@ -11779,7 +11804,7 @@ def next_split_prime(self, p=2):
"""
n = self._n()
while True:
- p = arith.next_prime(p)
+ p = next_prime(p)
if p % n == 1:
return p
@@ -11853,7 +11878,7 @@ def _multiplicative_order_table(self):
zeta = self.zeta(n)
# todo: this desperately needs to be optimized!!!
for i in range(n):
- t[x.polynomial()] = n // arith.GCD(m, n) # multiplicative_order of (zeta_n)**m
+ t[x.polynomial()] = n // gcd(m, n) # multiplicative_order of (zeta_n)**m
x *= zeta
m += 1
self.__multiplicative_order_table = t
@@ -12276,7 +12301,7 @@ def hilbert_class_field_defining_polynomial(self, name='x'):
Note that this polynomial is not the actual Hilbert class
polynomial: see ``hilbert_class_polynomial``::
- sage: K.hilbert_class_polynomial()
+ sage: K.hilbert_class_polynomial() # needs sage.schemes
x^3 + 3491750*x^2 - 5151296875*x + 12771880859375
::
@@ -12329,11 +12354,11 @@ def hilbert_class_polynomial(self, name='x'):
EXAMPLES::
sage: K. = QuadraticField(-3)
- sage: K.hilbert_class_polynomial()
+ sage: K.hilbert_class_polynomial() # needs sage.schemes
x
sage: K. = QuadraticField(-31)
- sage: K.hilbert_class_polynomial(name='z')
+ sage: K.hilbert_class_polynomial(name='z') # needs sage.schemes
z^3 + 39491307*z^2 - 58682638134*z + 1566028350940383
"""
D = self.discriminant()
@@ -12709,14 +12734,14 @@ def _splitting_classes_gens_(K, m, d):
sage: from sage.rings.number_field.number_field import _splitting_classes_gens_
sage: K = CyclotomicField(101)
sage: L = K.subfields(20)[0][0]
- sage: L.conductor()
+ sage: L.conductor() # needs sage.groups
101
- sage: _splitting_classes_gens_(L,101,20) # needs sage.libs.gap
+ sage: _splitting_classes_gens_(L,101,20) # needs sage.libs.gap # optional - gap_package_polycyclic
[95]
sage: K = CyclotomicField(44)
sage: L = K.subfields(4)[0][0]
- sage: _splitting_classes_gens_(L,44,4) # needs sage.libs.gap
+ sage: _splitting_classes_gens_(L,44,4) # needs sage.libs.gap # optional - gap_package_polycyclic
[37]
sage: K = CyclotomicField(44)
@@ -12726,9 +12751,9 @@ def _splitting_classes_gens_(K, m, d):
sage: L
Number Field in zeta44_0 with defining polynomial x^5 - 2*x^4 - 16*x^3 + 24*x^2 + 48*x - 32
with zeta44_0 = 3.837971894457990?
- sage: L.conductor()
+ sage: L.conductor() # needs sage.groups
11
- sage: _splitting_classes_gens_(L,11,5) # needs sage.libs.gap
+ sage: _splitting_classes_gens_(L,11,5) # needs sage.libs.gap # optional - gap_package_polycyclic
[10]
"""
@@ -12746,7 +12771,7 @@ def map_Zmstar_to_Zm(h):
Hgens = []
H = Zmstar.subgroup([])
p = 0
- Horder = arith.euler_phi(m) / d
+ Horder = euler_phi(m) / d
for g in Zmstar:
if H.order() == Horder:
break
diff --git a/src/sage/rings/number_field/number_field_ideal.py b/src/sage/rings/number_field/number_field_ideal.py
index 19c9e95ed39..28105221ac7 100644
--- a/src/sage/rings/number_field/number_field_ideal.py
+++ b/src/sage/rings/number_field/number_field_ideal.py
@@ -1002,6 +1002,7 @@ def is_maximal(self):
EXAMPLES::
+ sage: x = polygen(ZZ)
sage: K. = NumberField(x^3 + 3); K
Number Field in a with defining polynomial x^3 + 3
sage: K.ideal(5).is_maximal()
@@ -1017,6 +1018,7 @@ def is_prime(self):
EXAMPLES::
+ sage: x = polygen(ZZ)
sage: K. = NumberField(x^2 - 17); K
Number Field in a with defining polynomial x^2 - 17
sage: K.ideal(5).is_prime() # inert prime
@@ -1031,7 +1033,7 @@ def is_prime(self):
Check that we do not factor the norm of the ideal, this used
to take half an hour, see :trac:`33360`::
- sage: K. = NumberField([x^2-2,x^2-3,x^2-5])
+ sage: K. = NumberField([x^2 - 2, x^2 - 3, x^2 - 5])
sage: t = (((-2611940*c + 1925290/7653)*b - 1537130/7653*c
....: + 10130950)*a + (1343014/7653*c - 8349770)*b
....: + 6477058*c - 2801449990/4002519)
@@ -1112,6 +1114,7 @@ def _cache_bnfisprincipal(self, proof=None, gens=False):
Check that no warnings are triggered from PARI/GP (see :trac:`30801`)::
+ sage: x = polygen(ZZ)
sage: K. = NumberField(x^2 - x + 112941801)
sage: I = K.ideal((112941823, a + 49942513))
sage: I.is_principal()
@@ -1494,7 +1497,7 @@ def decomposition_group(self):
EXAMPLES::
- sage: QuadraticField(-23, 'w').primes_above(7)[0].decomposition_group()
+ sage: QuadraticField(-23, 'w').primes_above(7)[0].decomposition_group() # needs sage.groups
Subgroup generated by [(1,2)] of (Galois group 2T1 (S2) with order 2 of x^2 + 23)
"""
return self.number_field().galois_group().decomposition_group(self)
@@ -1510,9 +1513,9 @@ def ramification_group(self, v):
EXAMPLES::
- sage: QuadraticField(-23, 'w').primes_above(23)[0].ramification_group(0)
+ sage: QuadraticField(-23, 'w').primes_above(23)[0].ramification_group(0) # needs sage.groups
Subgroup generated by [(1,2)] of (Galois group 2T1 (S2) with order 2 of x^2 + 23)
- sage: QuadraticField(-23, 'w').primes_above(23)[0].ramification_group(1)
+ sage: QuadraticField(-23, 'w').primes_above(23)[0].ramification_group(1) # needs sage.groups
Subgroup generated by [()] of (Galois group 2T1 (S2) with order 2 of x^2 + 23)
"""
@@ -1528,7 +1531,7 @@ def inertia_group(self):
EXAMPLES::
- sage: QuadraticField(-23, 'w').primes_above(23)[0].inertia_group()
+ sage: QuadraticField(-23, 'w').primes_above(23)[0].inertia_group() # needs sage.groups
Subgroup generated by [(1,2)] of (Galois group 2T1 (S2) with order 2 of x^2 + 23)
"""
return self.ramification_group(0)
@@ -1594,7 +1597,7 @@ def artin_symbol(self):
EXAMPLES::
- sage: QuadraticField(-23, 'w').primes_above(7)[0].artin_symbol()
+ sage: QuadraticField(-23, 'w').primes_above(7)[0].artin_symbol() # needs sage.groups
(1,2)
"""
return self.number_field().galois_group().artin_symbol(self)
diff --git a/src/sage/rings/number_field/totallyreal_rel.py b/src/sage/rings/number_field/totallyreal_rel.py
index af44569f167..9b416d2ad02 100644
--- a/src/sage/rings/number_field/totallyreal_rel.py
+++ b/src/sage/rings/number_field/totallyreal_rel.py
@@ -1,3 +1,4 @@
+# sage.doctest: needs sage.geometry.polyhedron sage.libs.linbox sage.modules sage.rings.number_field
r"""
Enumeration of totally real fields: relative extensions
@@ -51,7 +52,7 @@
sage: [ f[0] for f in ls ]
[725, 1125, 1600, 2000, 2225, 2525, 3600, 4225, 4400, 4525, 5125, 5225, 5725, 6125, 7225, 7600, 7625, 8000, 8525, 8725, 9225]
- sage: [NumberField(ZZx(x[1]), 't').is_galois() for x in ls]
+ sage: [NumberField(ZZx(x[1]), 't').is_galois() for x in ls] # needs sage.groups
[False, True, True, True, False, False, True, True, False, False, False, False, False, True, True, False, False, True, False, False, False]
Eight out of 21 such fields are Galois (with Galois group `C_4`
diff --git a/src/sage/rings/padics/padic_extension_leaves.py b/src/sage/rings/padics/padic_extension_leaves.py
index ef0ed071a2c..d63dc734097 100644
--- a/src/sage/rings/padics/padic_extension_leaves.py
+++ b/src/sage/rings/padics/padic_extension_leaves.py
@@ -303,7 +303,7 @@ class UnramifiedExtensionRingFixedMod(UnramifiedExtensionGeneric, pAdicFixedModR
TESTS::
sage: R. = ZqFM(27,1000) # needs sage.libs.flint
- sage: TestSuite(R).run(skip='_test_log',max_runs=4) # long time # needs sage.libs.flint
+ sage: TestSuite(R).run(skip='_test_log',max_runs=4) # long time # needs sage.libs.flint
"""
def __init__(self, exact_modulus, poly, prec, print_mode, shift_seed, names, implementation='FLINT'):
"""
diff --git a/src/sage/rings/padics/padic_generic_element.pyx b/src/sage/rings/padics/padic_generic_element.pyx
index 88797ddf4ed..ffafe15313c 100644
--- a/src/sage/rings/padics/padic_generic_element.pyx
+++ b/src/sage/rings/padics/padic_generic_element.pyx
@@ -3830,7 +3830,7 @@ cdef class pAdicGenericElement(LocalGenericElement):
In its simplest form, computes the inverse of
``p``-th root of this element.
- This is an helper function used in :meth:`nth_root`
+ This is a helper function used in :meth:`nth_root`
and :meth:`primitive_root_of_unity`.
INPUT:
diff --git a/src/sage/rings/padics/padic_valuation.py b/src/sage/rings/padics/padic_valuation.py
index cb0207c10d4..d1590d0391f 100644
--- a/src/sage/rings/padics/padic_valuation.py
+++ b/src/sage/rings/padics/padic_valuation.py
@@ -1360,7 +1360,7 @@ class pAdicFromLimitValuation(FiniteExtensionFromLimitValuation, pAdicValuation_
TESTS::
- sage: TestSuite(v).run(skip='_test_shift') # long time # needs sage.rings.number_field
+ sage: TestSuite(v).run(skip='_test_shift') # long time # needs sage.rings.number_field
The ``_test_shift`` test fails because the parent of the shift is
incorrect, see :trac:`23971`::
diff --git a/src/sage/rings/polynomial/complex_roots.py b/src/sage/rings/polynomial/complex_roots.py
index cbbd42c8ccf..4c66eeca40c 100644
--- a/src/sage/rings/polynomial/complex_roots.py
+++ b/src/sage/rings/polynomial/complex_roots.py
@@ -21,7 +21,11 @@
sage: x = polygen(ZZ)
sage: (x^5 - x - 1).roots(ring=CIF)
- [(1.167303978261419?, 1), (-0.764884433600585? - 0.352471546031727?*I, 1), (-0.764884433600585? + 0.352471546031727?*I, 1), (0.181232444469876? - 1.083954101317711?*I, 1), (0.181232444469876? + 1.083954101317711?*I, 1)]
+ [(1.167303978261419?, 1),
+ (-0.764884433600585? - 0.352471546031727?*I, 1),
+ (-0.764884433600585? + 0.352471546031727?*I, 1),
+ (0.181232444469876? - 1.083954101317711?*I, 1),
+ (0.181232444469876? + 1.083954101317711?*I, 1)]
"""
#*****************************************************************************
@@ -61,9 +65,13 @@ def interval_roots(p, rts, prec):
sage: rts = [CC.zeta(3)^i for i in range(0, 3)]
sage: from sage.rings.polynomial.complex_roots import interval_roots
sage: interval_roots(p, rts, 53)
- [1, -0.500000000000000? + 0.866025403784439?*I, -0.500000000000000? - 0.866025403784439?*I]
+ [1, -0.500000000000000? + 0.866025403784439?*I,
+ -0.500000000000000? - 0.866025403784439?*I]
sage: interval_roots(p, rts, 200)
- [1, -0.500000000000000000000000000000000000000000000000000000000000? + 0.866025403784438646763723170752936183471402626905190314027904?*I, -0.500000000000000000000000000000000000000000000000000000000000? - 0.866025403784438646763723170752936183471402626905190314027904?*I]
+ [1, -0.500000000000000000000000000000000000000000000000000000000000?
+ + 0.866025403784438646763723170752936183471402626905190314027904?*I,
+ -0.500000000000000000000000000000000000000000000000000000000000?
+ - 0.866025403784438646763723170752936183471402626905190314027904?*I]
"""
CIF = ComplexIntervalField(prec)
@@ -172,15 +180,19 @@ def complex_roots(p, skip_squarefree=False, retval='interval', min_prec=0):
sage: from sage.rings.polynomial.complex_roots import complex_roots
sage: x = polygen(ZZ)
sage: complex_roots(x^5 - x - 1)
- [(1.167303978261419?, 1), (-0.764884433600585? - 0.352471546031727?*I, 1), (-0.764884433600585? + 0.352471546031727?*I, 1), (0.181232444469876? - 1.083954101317711?*I, 1), (0.181232444469876? + 1.083954101317711?*I, 1)]
- sage: v=complex_roots(x^2 + 27*x + 181)
+ [(1.167303978261419?, 1),
+ (-0.764884433600585? - 0.352471546031727?*I, 1),
+ (-0.764884433600585? + 0.352471546031727?*I, 1),
+ (0.181232444469876? - 1.083954101317711?*I, 1),
+ (0.181232444469876? + 1.083954101317711?*I, 1)]
+ sage: v = complex_roots(x^2 + 27*x + 181)
Unfortunately due to numerical noise there can be a small imaginary part to each
root depending on CPU, compiler, etc, and that affects the printing order. So we
verify the real part of each root and check that the imaginary part is small in
both cases::
- sage: v # random
+ sage: v # random
[(-14.61803398874990?..., 1), (-12.3819660112501...? + 0.?e-27*I, 1)]
sage: sorted((v[0][0].real(),v[1][0].real()))
[-14.61803398874989?, -12.3819660112501...?]
@@ -227,11 +239,16 @@ def complex_roots(p, skip_squarefree=False, retval='interval', min_prec=0):
....: if tiny(x.imag()): return x.real()
....: if tiny(x.real()): return CIF(0, x.imag())
sage: rts = complex_roots(p); type(rts[0][0]), sorted(map(smash, rts))
- (, [-1.618033988749895?, -0.618033988749895?*I, 1.618033988749895?*I, 0.618033988749895?])
+ (,
+ [-1.618033988749895?, -0.618033988749895?*I,
+ 1.618033988749895?*I, 0.618033988749895?])
sage: rts = complex_roots(p, retval='algebraic'); type(rts[0][0]), sorted(map(smash, rts))
- (, [-1.618033988749895?, -0.618033988749895?*I, 1.618033988749895?*I, 0.618033988749895?])
+ (,
+ [-1.618033988749895?, -0.618033988749895?*I,
+ 1.618033988749895?*I, 0.618033988749895?])
sage: rts = complex_roots(p, retval='algebraic_real'); type(rts[0][0]), rts
- (, [(-1.618033988749895?, 1), (0.618033988749895?, 1)])
+ (,
+ [(-1.618033988749895?, 1), (0.618033988749895?, 1)])
TESTS:
diff --git a/src/sage/rings/polynomial/multi_polynomial_element.py b/src/sage/rings/polynomial/multi_polynomial_element.py
index d4e2b115e39..f5c1b0e480c 100644
--- a/src/sage/rings/polynomial/multi_polynomial_element.py
+++ b/src/sage/rings/polynomial/multi_polynomial_element.py
@@ -2075,8 +2075,9 @@ def factor(self, proof=None):
Check that we can factor over the algebraic field (:trac:`25390`)::
- sage: R. = PolynomialRing(QQbar) # needs sage.rings.number_field
- sage: factor(x^2 + y^2) # needs sage.rings.number_field
+ sage: # needs sage.libs.singular sage.rings.number_field
+ sage: R. = PolynomialRing(QQbar)
+ sage: factor(x^2 + y^2)
(x + (-1*I)*y) * (x + 1*I*y)
Check that the global proof flag for polynomials is honored::
@@ -2123,7 +2124,7 @@ def factor(self, proof=None):
sage: R. = PolynomialRing(CC,1) # needs sage.rings.real_mpfr
sage: f = z^4 - 6*z + 3 # needs sage.rings.real_mpfr
- sage: f.factor() # needs sage.rings.real_mpfr
+ sage: f.factor() # needs sage.libs.pari sage.rings.real_mpfr
(z - 1.60443920904349) * (z - 0.511399619393097)
* (z + 1.05791941421830 - 1.59281852704435*I)
* (z + 1.05791941421830 + 1.59281852704435*I)
@@ -2252,7 +2253,7 @@ def quo_rem(self, right):
((2*b + 1)*y, (2*b + 1)*y + (-a^2 + 3)*z + a)
sage: R. = Qp(5)[] # needs sage.rings.padics
- sage: x.quo_rem(y) # needs sage.rings.padics
+ sage: x.quo_rem(y) # needs sage.libs.singular sage.rings.padics
Traceback (most recent call last):
...
TypeError: no conversion of this ring to a Singular ring defined
@@ -2265,7 +2266,7 @@ def quo_rem(self, right):
sage: R. = QQbar[] # needs sage.rings.number_field
sage: f = y*x^2 + x + 1 # needs sage.rings.number_field
- sage: f.quo_rem(x) # needs sage.rings.number_field
+ sage: f.quo_rem(x) # needs sage.libs.singular sage.rings.number_field
(x*y + 1, 1)
"""
R = self.parent()
@@ -2326,7 +2327,7 @@ def resultant(self, other, variable=None):
Check that :trac:`15061` is fixed::
sage: R. = AA[] # needs sage.rings.number_field
- sage: (x^2 + 1).resultant(x^2 - y) # needs sage.rings.number_field
+ sage: (x^2 + 1).resultant(x^2 - y) # needs sage.libs.singular sage.rings.number_field
y^2 + 2*y + 1
Test for :trac:`2693`::
@@ -2334,7 +2335,7 @@ def resultant(self, other, variable=None):
sage: R. = RR[]
sage: p = x + y
sage: q = x*y
- sage: p.resultant(q) # needs sage.modules
+ sage: p.resultant(q) # needs sage.libs.singular sage.modules
-y^2
Check that this method works over QQbar (:trac:`25351`)::
@@ -2343,9 +2344,9 @@ def resultant(self, other, variable=None):
sage: P. = QQbar[]
sage: a = x + y
sage: b = x^3 - y^3
- sage: a.resultant(b)
+ sage: a.resultant(b) # needs sage.libs.singular sage.modules
(-2)*y^3
- sage: a.resultant(b, y)
+ sage: a.resultant(b, y) # needs sage.libs.singular sage.modules
2*x^3
"""
R = self.parent()
@@ -2375,7 +2376,7 @@ def subresultants(self, other, variable=None):
EXAMPLES::
- sage: # needs sage.rings.number_field
+ sage: # needs sage.libs.singular sage.rings.number_field
sage: R. = QQbar[]
sage: p = (y^2 + 6)*(x - 1) - y*(x^2 + 1)
sage: q = (x^2 + 6)*(y - 1) - x*(y^2 + 1)
@@ -2413,9 +2414,9 @@ def reduce(self, I):
sage: f3 = -x^2 + y^2
sage: F = Ideal([f1, f2, f3])
sage: g = x*y - 3*x*y^2
- sage: g.reduce(F)
+ sage: g.reduce(F) # needs sage.libs.singular
(-6)*y^2 + 2*y
- sage: g.reduce(F.gens())
+ sage: g.reduce(F.gens()) # needs sage.libs.singular
(-6)*y^2 + 2*y
::
diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx
index 561136bac6d..f519400c3c3 100644
--- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx
+++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx
@@ -3197,7 +3197,7 @@ cdef class MPolynomial_libsingular(MPolynomial_libsingular_base):
INPUT:
- ``as_ETuples`` -- (default: ``True``) if ``True`` returns the
- result as an list of ETuples, otherwise returns a list of tuples
+ result as a list of ETuples, otherwise returns a list of tuples
EXAMPLES::
diff --git a/src/sage/rings/polynomial/multi_polynomial_ring_base.pyx b/src/sage/rings/polynomial/multi_polynomial_ring_base.pyx
index 44946845b83..dc3bfdc2459 100644
--- a/src/sage/rings/polynomial/multi_polynomial_ring_base.pyx
+++ b/src/sage/rings/polynomial/multi_polynomial_ring_base.pyx
@@ -41,10 +41,11 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
sage: R. = ZZ['x,y']; R
Multivariate Polynomial Ring in x, y over Integer Ring
- sage: class CR(CommutativeRing):
+ sage: cat = Rings().Commutative()
+ sage: class CR(Parent):
....: def __init__(self):
- ....: CommutativeRing.__init__(self,self)
- ....: def __call__(self,x):
+ ....: Parent.__init__(self, self, category=cat)
+ ....: def __call__(self, x):
....: return None
sage: cr = CR()
sage: cr.is_commutative()
@@ -668,7 +669,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
def repr_long(self):
"""
- Return structured string representation of self.
+ Return structured string representation of ``self``.
EXAMPLES::
@@ -758,7 +759,6 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
Order: Graded Reverse Lexicographical
Variables: T, W
-
sage: # optional - magma
sage: magma(PolynomialRing(GF(7),4, 'x'))
Polynomial ring of rank 4 over GF(7)
@@ -797,7 +797,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
EXAMPLES::
- sage: # needs sage.rings.number_field
+ sage: # needs sage.libs.gap sage.rings.number_field
sage: F = CyclotomicField(8)
sage: P. = F[]
sage: gap(P) # indirect doctest
@@ -868,12 +868,12 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
def gen(self, n=0):
if n < 0 or n >= self._ngens:
- raise ValueError("Generator not defined.")
+ raise ValueError("generator not defined")
return self._gens[int(n)]
def variable_names_recursive(self, depth=sage.rings.infinity.infinity):
r"""
- Returns the list of variable names of this and its base rings, as if
+ Return the list of variable names of this and its base rings, as if
it were a single multi-variate polynomial.
EXAMPLES::
@@ -883,7 +883,6 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
('x', 'y', 'z', 'w')
sage: R.variable_names_recursive(3)
('y', 'z', 'w')
-
"""
if depth <= 0:
all = ()
@@ -901,7 +900,8 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
def _mpoly_base_ring(self, vars=None):
"""
- Returns the base ring if this is viewed as a polynomial ring over vars.
+ Return the base ring if this is viewed as a polynomial ring over vars.
+
See also MPolynomial._mpoly_dict_recursive.
"""
if vars is None:
@@ -1015,10 +1015,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
if not comb:
return (d,)
monomial = [comb[0]]
- res = []
- for j in range(n - 2):
- res.append(comb[j + 1] - comb[j] - 1)
- monomial += res
+ monomial.extend(comb[j + 1] - comb[j] - 1 for j in range(n - 2))
monomial.append(n + d - 1 - comb[-1] - 1)
return tuple(monomial)
@@ -1234,7 +1231,6 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
True
sage: R.random_element().parent() == R
True
-
"""
k = self.base_ring()
n = self.ngens()
@@ -1243,7 +1239,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
# Note that 'terms' could be None while 'total' is a
# nonnegative integer, so the comparison 'terms > total' could
- # fail in Python 3.
+ # fail
if terms and terms > total:
terms = total
@@ -1526,13 +1522,14 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
def macaulay_resultant(self, *args, **kwds):
r"""
- This is an implementation of the Macaulay resultant. It computes
- the resultant of universal polynomials as well as polynomials
- with constant coefficients. This is a project done in
- sage days 55. It's based on the implementation in Maple by
- Manfred Minimair, which in turn is based on the references listed below:
- It calculates the Macaulay resultant for a list of polynomials,
- up to sign!
+ Return the Macaulay resultant.
+
+ This computes the resultant of universal polynomials as well as
+ polynomials with constant coefficients. This is a project done
+ in sage days 55. It is based on the implementation in Maple by
+ Manfred Minimair, which in turn is based on the references
+ listed below. It calculates the Macaulay resultant for a list
+ of polynomials, up to sign!
REFERENCES:
@@ -1562,6 +1559,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
- the Macaulay resultant, an element of the base ring of ``self``
.. TODO::
+
Working with sparse matrices should usually give faster results,
but with the current implementation it actually works slower.
There should be a way to improve performance with regards to this.
@@ -1684,7 +1682,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
else:
flist = args
- if len(flist) <= 0:
+ if len(flist) == 0:
raise TypeError('input list should contain at least 1 polynomial')
if not all(f.is_homogeneous() for f in flist):
raise TypeError('resultant for non-homogeneous polynomials is not supported')
diff --git a/src/sage/rings/polynomial/ore_function_element.py b/src/sage/rings/polynomial/ore_function_element.py
index 3afaff91a10..a9574c6d4cb 100644
--- a/src/sage/rings/polynomial/ore_function_element.py
+++ b/src/sage/rings/polynomial/ore_function_element.py
@@ -76,6 +76,7 @@ def _repr_(self):
EXAMPLES::
+ sage: # needs sage.rings.finite_rings
sage: k. = GF(5^3)
sage: Frob = k.frobenius_endomorphism()
sage: S. = k['x', Frob]
@@ -85,6 +86,7 @@ def _repr_(self):
TESTS::
+ sage: # needs sage.rings.finite_rings
sage: f = 1/x^3; f
x^(-3)
sage: f * x^5
@@ -139,6 +141,7 @@ def __hash__(self):
TESTS::
+ sage: # needs sage.rings.finite_rings
sage: k. = GF(5^3)
sage: Frob = k.frobenius_endomorphism()
sage: S. = k['x', Frob]
@@ -156,12 +159,12 @@ def _richcmp_(self, other, op):
TESTS::
+ sage: # needs sage.rings.function_field
sage: R. = QQ[]
sage: sigma = R.hom([t+1])
sage: der = R.derivation(1, twist=sigma)
sage: S. = R['delta', der]
sage: K = S.fraction_field()
-
sage: P = K.random_element()
sage: Q = K.random_element()
sage: D = K.random_element()
@@ -197,18 +200,19 @@ def left_denominator(self):
EXAMPLES::
+ sage: # needs sage.rings.finite_rings
sage: k. = GF(5^3)
sage: Frob = k.frobenius_endomorphism()
sage: S. = k['x', Frob]
sage: s = x + a
sage: t = x^2 + a*x + a^2
-
sage: f = s^(-1) * t
sage: f.left_denominator()
x + a
In the example below, a simplification occurs::
+ sage: # needs sage.rings.finite_rings
sage: u = S.random_element(degree=2)
sage: g = (u*s)^(-1) * (u*t)
sage: g.left_denominator()
@@ -222,13 +226,13 @@ def left_denominator(self):
sage: S. = R['x', sigma]
sage: s = (x + z)^2
sage: t = (x + z) * (x^2 + z^2)
- sage: f = s^(-1) * t
- sage: f.left_denominator()
+ sage: f = s^(-1) * t # needs sage.rings.function_field
+ sage: f.left_denominator() # needs sage.rings.function_field
x^2 + (z^2 + z)*x + z^2
However, the following always holds true::
- sage: f == f.left_denominator()^(-1) * f.right_numerator()
+ sage: f == f.left_denominator()^(-1) * f.right_numerator() # needs sage.rings.function_field
True
.. SEEALSO::
@@ -258,18 +262,19 @@ def right_numerator(self):
EXAMPLES::
+ sage: # needs sage.rings.finite_rings
sage: k. = GF(5^3)
sage: Frob = k.frobenius_endomorphism()
sage: S. = k['x', Frob]
sage: s = x + a
sage: t = x^2 + a*x + a^2
-
sage: f = s^(-1) * t
sage: f.right_numerator()
x^2 + a*x + a^2
In the example below, a simplification occurs::
+ sage: # needs sage.rings.finite_rings
sage: u = S.random_element(degree=2)
sage: g = (u*s)^(-1) * (u*t)
sage: g.right_numerator()
@@ -286,15 +291,15 @@ def _reverse_fraction(self):
r"""
Return the pair `(s,t)` if this element reads `t s^{-1}`.
- This is an helper function. Do not call it directly.
+ This is a helper function. Do not call it directly.
TESTS::
+ sage: # needs sage.rings.finite_rings
sage: k. = GF(11^3)
sage: Frob = k.frobenius_endomorphism()
sage: der = k.derivation(a+1, twist=Frob)
sage: S. = k['x', der]
-
sage: P = S.random_element(degree=5)
sage: Q = S.random_element(degree=5)
sage: f = P / Q
@@ -330,18 +335,19 @@ def right_denominator(self):
EXAMPLES::
+ sage: # needs sage.rings.finite_rings
sage: k. = GF(5^3)
sage: Frob = k.frobenius_endomorphism()
sage: S. = k['x', Frob]
sage: s = x + a
sage: t = x^2 + a*x + a^2
-
sage: f = t/s
sage: f.right_denominator()
x + a
In the example below, a simplification occurs::
+ sage: # needs sage.rings.finite_rings
sage: u = S.random_element(degree=2)
sage: g = (t*u) / (s*u)
sage: g.right_denominator()
@@ -356,11 +362,12 @@ def right_denominator(self):
sage: R. = GF(11)[]
sage: sigma = R.hom([z^2])
sage: S. = R['x', sigma]
- sage: f = (x + z) / (x - z)
- sage: f.right_denominator()
+ sage: f = (x + z) / (x - z) # needs sage.rings.function_field
+ sage: f.right_denominator() # needs sage.rings.function_field
Traceback (most recent call last):
...
- NotImplementedError: inversion of the twisting morphism Ring endomorphism of Fraction Field of Univariate Polynomial Ring in z over Finite Field of size 11
+ NotImplementedError: inversion of the twisting morphism Ring endomorphism
+ of Fraction Field of Univariate Polynomial Ring in z over Finite Field of size 11
Defn: z |--> z^2
"""
return self._reverse_fraction()[1]
@@ -384,18 +391,19 @@ def left_numerator(self):
EXAMPLES::
+ sage: # needs sage.rings.finite_rings
sage: k. = GF(5^3)
sage: Frob = k.frobenius_endomorphism()
sage: S. = k['x', Frob]
sage: s = x + a
sage: t = x^2 + a*x + a^2
-
sage: f = t/s
sage: f.left_numerator()
x^2 + a*x + a^2
In the example below, a simplification occurs::
+ sage: # needs sage.rings.finite_rings
sage: u = S.random_element(degree=2)
sage: g = (t*u) / (s*u)
sage: g.left_numerator()
@@ -430,12 +438,12 @@ def _add_(self, other):
TESTS::
+ sage: # needs sage.rings.finite_rings
sage: k. = GF(5^2)
sage: Frob = k.frobenius_endomorphism()
sage: der = k.derivation(a, twist=Frob)
sage: S. = k['x', der]
sage: K = S.fraction_field()
-
sage: f = K.random_element()
sage: g = K.random_element()
sage: h = K.random_element()
@@ -458,12 +466,12 @@ def _sub_(self, other):
TESTS::
+ sage: # needs sage.rings.finite_rings
sage: k. = GF(5^2)
sage: Frob = k.frobenius_endomorphism()
sage: der = k.derivation(a, twist=Frob)
sage: S. = k['x', der]
sage: K = S.fraction_field()
-
sage: f = K.random_element()
sage: g = K.random_element()
sage: h = K.random_element()
@@ -480,12 +488,12 @@ def _neg_(self):
TESTS::
+ sage: # needs sage.rings.finite_rings
sage: k. = GF(5^2)
sage: Frob = k.frobenius_endomorphism()
sage: der = k.derivation(a, twist=Frob)
sage: S. = k['x', der]
sage: K = S.fraction_field()
-
sage: f = K.random_element()
sage: g = -f
sage: (f+g).is_zero()
@@ -503,12 +511,12 @@ def _mul_(self, other):
TESTS::
+ sage: # needs sage.rings.finite_rings
sage: k. = GF(5^2)
sage: Frob = k.frobenius_endomorphism()
sage: der = k.derivation(a, twist=Frob)
sage: S. = k['x', der]
sage: K = S.fraction_field()
-
sage: f = K.random_element()
sage: g = K.random_element()
sage: h = K.random_element()
@@ -538,18 +546,17 @@ def _div_(self, other):
TESTS::
+ sage: # needs sage.rings.finite_rings
sage: k. = GF(5^2)
sage: Frob = k.frobenius_endomorphism()
sage: der = k.derivation(a, twist=Frob)
sage: S. = k['x', der]
sage: K = S.fraction_field()
-
sage: f = K.random_element()
sage: g = K.random_element()
sage: h = K.random_element()
sage: g == 0 or h == 0 or f / (g / h) == f*h / g
True
-
sage: 0/f
0
sage: f/0
@@ -559,7 +566,7 @@ def _div_(self, other):
We check that :trac:`32109` is fixed::
- sage: K(0)/K(0)
+ sage: K(0)/K(0) # needs sage.rings.finite_rings
Traceback (most recent call last):
...
ZeroDivisionError: cannot divide by zero
@@ -579,17 +586,16 @@ def __invert__(self):
TESTS::
+ sage: # needs sage.rings.finite_rings
sage: k. = GF(5^2)
sage: Frob = k.frobenius_endomorphism()
sage: der = k.derivation(a, twist=Frob)
sage: S. = k['x', der]
sage: K = S.fraction_field()
-
sage: f = K.random_element()
sage: g = ~f
sage: f * g
1
-
sage: ~K(0)
Traceback (most recent call last):
...
@@ -629,23 +635,24 @@ def hilbert_shift(self, s, var=None):
When the twisting morphism is not trivial, the output lies
in a different Ore polynomial ring::
+ sage: # needs sage.rings.finite_rings
sage: k. = GF(5^3)
sage: Frob = k.frobenius_endomorphism()
sage: S.