From 7cce7a49f9b7227598a7e0e844e4c91cfe78baa9 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Fri, 25 Mar 2022 16:35:17 +0100 Subject: [PATCH 001/116] trac #33554: fix issues in graph_coloring.pyx --- src/sage/graphs/graph_coloring.pyx | 43 ++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/src/sage/graphs/graph_coloring.pyx b/src/sage/graphs/graph_coloring.pyx index 50cb529f95f..55ecb12ea05 100644 --- a/src/sage/graphs/graph_coloring.pyx +++ b/src/sage/graphs/graph_coloring.pyx @@ -99,6 +99,11 @@ def all_graph_colorings(G, n, count_only=False, hex_colors=False, vertex_color_d ``True``, it returns a dictionary ``{vertex: color}``, otherwise it returns a dictionary ``{color: [list of vertices]}`` + .. WARNING:: + + This method considers only colorings using exactly `n` colors, even if a + coloring using fewer colors can be found. + The construction works as follows. Columns: * The first `|V|` columns correspond to a vertex -- a `1` in this column @@ -188,7 +193,7 @@ def all_graph_colorings(G, n, count_only=False, hex_colors=False, vertex_color_d G._scream_if_not_simple(allow_multiple_edges=True) - if not n: + if not n or n > G.order(): return if n < 0: raise ValueError("n must be non-negative") @@ -229,18 +234,20 @@ def all_graph_colorings(G, n, count_only=False, hex_colors=False, vertex_color_d cdef dict color_dict = {col: i for i, col in enumerate(colors)} cdef list ones_second = [ones[i].second for i in range(len(ones))] - cdef dict coloring = {} + cdef dict coloring + cdef set used_colors try: for a in DLXCPP(ones_second): - if count_only: - yield 1 - continue coloring = {} - if vertex_color_dict: + used_colors = set() + if count_only: + used_colors = set(colormap[x][1] for x in a if x in colormap) + elif vertex_color_dict: for x in a: if x in colormap: - v,c = colormap[x] + v, c = colormap[x] + used_colors.add(c) if hex_colors: coloring[v] = colors[c] else: @@ -248,7 +255,8 @@ def all_graph_colorings(G, n, count_only=False, hex_colors=False, vertex_color_d else: for x in a: if x in colormap: - v,c = colormap[x] + v, c = colormap[x] + used_colors.add(c) if hex_colors: if colors[c] in coloring: coloring[colors[c]].append(v) @@ -259,7 +267,11 @@ def all_graph_colorings(G, n, count_only=False, hex_colors=False, vertex_color_d coloring[color_dict[colors[c]]].append(v) else: coloring[color_dict[colors[c]]] = [v] - yield coloring + if len(used_colors) == n: + if count_only: + yield 1 + else: + yield coloring except RuntimeError: raise RuntimeError("too much recursion, Graph coloring failed") @@ -268,7 +280,8 @@ cpdef first_coloring(G, n=0, hex_colors=False): Return the first vertex coloring found. If a natural number `n` is provided, returns the first found coloring with - at least `n` colors. + at least `n` colors. That is, `n` is a lower bound on the number of colors + to use. INPUT: @@ -284,6 +297,14 @@ cpdef first_coloring(G, n=0, hex_colors=False): sage: G = Graph({0: [1, 2, 3], 1: [2]}) sage: sorted(first_coloring(G, 3)) [[0], [1, 3], [2]] + + TESTS: + + :trac:`33554` is fixed:: + + sage: P3 = graphs.PathGraph(3) + sage: [len(graph_coloring.first_coloring(P3, k)) for k in range(P3.order() + 1)] + [2, 2, 2, 3] """ G._scream_if_not_simple(allow_multiple_edges=True) cdef int o = G.order() @@ -337,7 +358,7 @@ cpdef numbers_of_colorings(G): sage: from sage.graphs.graph_coloring import numbers_of_colorings sage: G = Graph({0: [1, 2, 3], 1: [2]}) sage: numbers_of_colorings(G) - [0, 0, 0, 12, 72] + [0, 0, 0, 12, 24] """ cdef int o = G.order() cdef list answer = [number_of_n_colorings(G, n) for n in range(o + 1)] From 804b062b8701604b4075037de7adc14f547bc970 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sun, 10 Apr 2022 15:41:12 +0200 Subject: [PATCH 002/116] trac #33365: add interface to nauty genbg --- src/sage/graphs/graph_generators.py | 153 ++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index 8dcceb07fe4..540cad5315c 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -262,6 +262,8 @@ def __append_to_doc(methods): "MuzychukS6Graph", "MycielskiGraph", "MycielskiStep", + "nauty_geng", + "nauty_genbg", "NKStarGraph", "NStarGraph", "OddGraph", @@ -269,6 +271,7 @@ def __append_to_doc(methods): "PasechnikGraph", "petersen_family", "planar_graphs", + "plantri_gen", "quadrangulations", "RingedTree", "SierpinskiGasketGraph", @@ -977,6 +980,156 @@ def nauty_geng(self, options="", debug=False): G = graph.Graph(s[:-1], format='graph6') yield G + def nauty_genbg(self, options="", debug=False): + r""" + Return a generator which creates bipartite graphs from nauty's ``genbg`` + program. + + INPUT: + + - ``options`` -- string (default: ``""``); a string passed to ``genbg`` + as if it was run at a system command line. At a minimum, you *must* + pass the number of vertices you desire in each side. Sage expects the + bipartite 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 ``geng``'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 ``genbg --help``:: + + n1 : the number of vertices in the first class + n2 : the number of vertices in the second class + mine:maxe : : a range for the number of edges + :0 means ' or more' except in the case 0:0 + res/mod : only generate subset res out of subsets 0..mod-1 + -c : only write connected graphs + -z : all the vertices in the second class must have + different neighbourhoods + -F : the vertices in the second class must have at least + two neighbours of degree at least 2 + -L : there is no vertex in the first class whose removal + leaves the vertices in the second class unreachable + from each other + -Y : two vertices in the second class must have at least + common neighbours + -Z : two vertices in the second class must have at most + common neighbours + -A : no vertex in the second class has a neighbourhood + which is a subset of another vertex's neighbourhood + in the second class + -D : specify an upper bound for the maximum degree + Example: -D6. You can also give separate maxima for + the two parts, for example: -D5:6 + -d : specify a lower bound for the minimum degree + Again, you can specify it separately for the two parts, + for example -d1:2 + -v : display counts by number of edges to stder + -l : canonically label output graphs + -q : suppress auxiliary output (except from -v) + + Options which cause ``genbg`` to use an output format different than the + ``graph6`` format are not listed above (-s, -a) 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 + :class:`~sage/graphs.bipartite_graph.BipartiteGraph`. These will be + simple bipartite graphs: no loops, no multiple edges, no directed edges. + + EXAMPLES: + + The generator can be used to construct biparrtite graphs for testing, + one at a time (usually inside a loop). Or it can be used to + create an entire list all at once if there is sufficient memory + to contain it:: + + sage: gen = graphs.nauty_genbg("1 1") + sage: next(gen) + Bipartite graph on 2 vertices + sage: next(gen) + Bipartite graph on 2 vertices + sage: next(gen) + Traceback (most recent call last): + ... + StopIteration + + Connected bipartite graphs of order 6 with different number of vertices + in each side:: + + sage: gen = graphs.nauty_genbg("1 5 -c") + sage: len(list(gen)) + 1 + sage: gen = graphs.nauty_genbg("2 4 -c") + sage: len(list(gen)) + 6 + sage: gen = graphs.nauty_genbg("3 3 -c") + sage: len(list(gen)) + 13 + + Use :meth:`nauty_geng` instead if you want the list of all bipartite + graphs of order `n`. For instance, the list of all connected bipartite + graphs of order 6, which agrees with :oeis:`A005142`:: + + sage: gen = graphs.nauty_geng("-b -c 6") + sage: len(list(gen)) + 17 + + The ``debug`` switch can be used to examine ``genbg``'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 + ``genbg`` 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_genbg("2 3", debug=True) + sage: print(next(gen)) + >A ...genbg n=2+3 e=0:6 d=0:0 D=3:2 + sage: gen = graphs.nauty_genbg("2 3 -q", debug=True) + sage: next(gen) + '' + + TESTS: + + Wrong input:: + + sage: list(graphs.nauty_genbg("-c1 2", debug=False)) + Traceback (most recent call last): + ... + ValueError: wrong format of parameter option + sage: list(graphs.nauty_genbg("-c1 2", debug=True)) + ['>E Usage: ...genbg [-c -ugs -vq -lzF] [-Z#] [-D#] [-A] [-d#|-d#:#] [-D#|-D#:#] n1 n2... + sage: list(graphs.nauty_genbg("-c 1 2", debug=True)) + ['>A ...genbg n=1+2 e=2:2 d=1:1 D=2:1 c\n', Bipartite graph on 3 vertices] + """ + import shlex + from sage.features.nauty import NautyExecutable + genbg_path = NautyExecutable("genbg").absolute_filename() + sp = subprocess.Popen(shlex.quote(genbg_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 + from sage.graphs.bipartite_graph import BipartiteGraph + while True: + try: + s = next(gen) + except StopIteration: + # Exhausted list of bipartite graphs from nauty genbg + return + G = BipartiteGraph(s[:-1], format='graph6') + yield G def cospectral_graphs(self, vertices, matrix_function=lambda g: g.adjacency_matrix(), graphs=None): r""" From e57e4561f3402641c366aedb4a4db38695bbad3c Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sun, 10 Apr 2022 19:22:23 +0200 Subject: [PATCH 003/116] trac #33365: ensure that the partition respects the requirement --- src/sage/graphs/graph_generators.py | 54 +++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index 540cad5315c..7a918812367 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -1028,14 +1028,19 @@ def nauty_genbg(self, options="", debug=False): -d : specify a lower bound for the minimum degree Again, you can specify it separately for the two parts, for example -d1:2 - -v : display counts by number of edges to stder + -v : display counts by number of edges to stderr -l : canonically label output graphs - -q : suppress auxiliary output (except from -v) Options which cause ``genbg`` to use an output format different than the ``graph6`` format are not listed above (-s, -a) 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. + creation of a Sage graph. Option ``-q`` which suppress auxiliary output + (except from ``-v``) should never be used as we are unable to recover + the partition of the vertices of the bipartite graph without the + auxilary output. Hence the partition of the vertices of returned + bipartite graphs might not respect the requirement. + + The res/mod option can be useful when using the output in a routine run + several times in parallel. OUTPUT: @@ -1082,18 +1087,23 @@ def nauty_genbg(self, options="", debug=False): 17 The ``debug`` switch can be used to examine ``genbg``'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 - ``genbg`` will suppress the indicator of a successful initiation, and so - the first returned value might be an empty string if ``debug`` is - ``True``:: + input in the ``options`` string. A message starting with ">A" indicates + success and a message starting with ">E" indicates a failure:: sage: gen = graphs.nauty_genbg("2 3", debug=True) sage: print(next(gen)) >A ...genbg n=2+3 e=0:6 d=0:0 D=3:2 - sage: gen = graphs.nauty_genbg("2 3 -q", debug=True) + sage: gen = graphs.nauty_genbg("-c2 3", debug=True) sage: next(gen) - '' + '>E Usage: ...genbg [-c -ugs -vq -lzF] [-Z#] [-D#] [-A] [-d#|-d#:#] [-D#|-D#:#] n1 n2... + + Check that the partition of the bipartite graph is consistent:: + + sage: gen = graphs.nauty_genbg("3 3") + sage: left = set(range(3)) + sage: for g in gen: + ....: if g.left != left: + ....: raise ValueError('wrong partition') TESTS: @@ -1102,7 +1112,7 @@ def nauty_genbg(self, options="", debug=False): sage: list(graphs.nauty_genbg("-c1 2", debug=False)) Traceback (most recent call last): ... - ValueError: wrong format of parameter option + ValueError: wrong format of parameter options sage: list(graphs.nauty_genbg("-c1 2", debug=True)) ['>E Usage: ...genbg [-c -ugs -vq -lzF] [-Z#] [-D#] [-A] [-d#|-d#:#] [-D#|-D#:#] n1 n2... sage: list(graphs.nauty_genbg("-c 1 2", debug=True)) @@ -1119,7 +1129,23 @@ def nauty_genbg(self, options="", debug=False): if debug: yield msg elif msg.startswith('>E'): - raise ValueError('wrong format of parameter option') + raise ValueError('wrong format of parameter options') + + if msg.startswith('>A'): + # We extract the partition of the vertices from the msg string + for s in msg.split(' '): + if s.startswith('n='): + from sage.rings.integer import Integer + n1, n2 = [Integer(t) for t in s[2:].split('+') if t.isdigit()] + partition = [set(range(n1)), set(range(n1, n1 + n2))] + break + else: + # should never happen + raise ValueError('unable to recover the partition') + else: + # Either msg starts with >E or option -q has been given + partition = None + gen = sp.stdout from sage.graphs.bipartite_graph import BipartiteGraph while True: @@ -1128,7 +1154,7 @@ def nauty_genbg(self, options="", debug=False): except StopIteration: # Exhausted list of bipartite graphs from nauty genbg return - G = BipartiteGraph(s[:-1], format='graph6') + G = BipartiteGraph(s[:-1], format='graph6', partition=partition) yield G def cospectral_graphs(self, vertices, matrix_function=lambda g: g.adjacency_matrix(), graphs=None): From 1124ded86b0eff3ac0b98e9a4e32c04b3d02ca7d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 8 Feb 2022 13:59:10 -0800 Subject: [PATCH 004/116] build/pkgs/gcc/spkg-configure.m4: Bump minimum version to 6.3 --- build/pkgs/gcc/spkg-configure.m4 | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/build/pkgs/gcc/spkg-configure.m4 b/build/pkgs/gcc/spkg-configure.m4 index a98cf478907..29b26c968bc 100644 --- a/build/pkgs/gcc/spkg-configure.m4 +++ b/build/pkgs/gcc/spkg-configure.m4 @@ -161,20 +161,16 @@ SAGE_SPKG_CONFIGURE_BASE([gcc], [ # Add the .0 because Debian/Ubuntu gives version numbers like # 4.6 instead of 4.6.4 (Trac #18885) AS_CASE(["$GXX_VERSION.0"], - [[[0-3]].*|4.[[0-7]].*|4.9.*], [ - # Install our own GCC if the system-provided one is older than gcc-4.8 or is 4.9.x + [[[0-5]].*|6.[[0-2]].*], [ + # Install our own GCC if the system-provided one is older than gcc-6.3 SAGE_SHOULD_INSTALL_GCC([you have $CXX version $GXX_VERSION, which is quite old]) ], [1[[3-9]].*], [ # Install our own GCC if the system-provided one is newer than 12.x. # See https://trac.sagemath.org/ticket/29456 SAGE_SHOULD_INSTALL_GCC([$CXX is g++ version $GXX_VERSION, which is too recent for this version of Sage]) - ], - [4.[[8-9]].*|5.[[0-1]].*], [ - # GCC less than 5.1 is not ready for AVX512. - sage_use_march_native=no - ]) - fi + ] + fi # The following tests check that the version of the compilers # are all the same. From 4e8b2c2771c933f7e2fac7c16fb99cc4e240238f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 8 Feb 2022 14:07:25 -0800 Subject: [PATCH 005/116] README.md, src/doc/en/installation/source.rst: Update info on GCC versions --- README.md | 4 ++-- src/doc/en/installation/source.rst | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0771a11e7ac..abfb0cf8f15 100644 --- a/README.md +++ b/README.md @@ -223,8 +223,8 @@ in the Installation Guide. 3. [Linux, Cygwin] Install the required minimal build prerequisites. - - Compilers: `gcc`, `gfortran`, `g++` (a recent enough matching - set of these three will avoid building Sage-specific compilers). + - Compilers: `gcc`, `gfortran`, `g++` (GCC 6.3 to 12.x and recent + versions of Clang (LLVM) are supported). See the Installation Manual for a discussion of suitable compilers. - Build tools: GNU `make`, GNU `m4`, `perl` (including diff --git a/src/doc/en/installation/source.rst b/src/doc/en/installation/source.rst index f06e9e0d633..ce996ec6aa4 100644 --- a/src/doc/en/installation/source.rst +++ b/src/doc/en/installation/source.rst @@ -76,11 +76,8 @@ and the :wikipedia:`bash ` shell, the following standard command-line development tools must be installed on your computer: -- A **C/C++ compiler**: Since SageMath builds its own GCC if needed, - a wide variety of C/C++ compilers is supported. - Many GCC versions work, - from as old as version 4.8 (but we recommend at least 5.1) to the most recent release. - Clang also works. +- A **C/C++ compiler**: GCC versions 6.3 to 12.x are supported. + Clang (LLVM) is also supported. See also `Using alternative compilers`_. - **make**: GNU make, version 3.80 or later. Version 3.82 or later is recommended. - **m4**: GNU m4 1.4.2 or later (non-GNU or older versions might also work). From 9b388ea6e2ab3f2690e61753182acecceef33464 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 20 Apr 2022 16:40:40 -0700 Subject: [PATCH 006/116] .github/workflows/tox*.yml: Update platforms for drop of GCC < 6.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ubuntu-trusty 14.04 is long past standard support, but ​EOL has been extended to Apr 2024. Replace by ubuntu-trusty-toolchain-gcc_11 centos-7 has EOL June 2024, gcc 4.x. Replace by centos-7-devtoolset-gcc_11 linuxmint-17 had ​EOL 2019. gcc 4.x. Drop linuxmint-18 had ​EOL 2021, gcc 5.4. Drop slackware-14.2 with gcc 5.5. Drop --- .github/workflows/tox-experimental.yml | 5 +---- .github/workflows/tox-optional.yml | 5 +---- .github/workflows/tox.yml | 2 +- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/tox-experimental.yml b/.github/workflows/tox-experimental.yml index eed55d97806..e5712591962 100644 --- a/.github/workflows/tox-experimental.yml +++ b/.github/workflows/tox-experimental.yml @@ -38,10 +38,7 @@ jobs: fail-fast: false max-parallel: 6 matrix: - # This list is different from the one in tox.yml: - # Trac #31526 switches gcc 4.x-based distributions to using the gcc_spkg configuration factor - # Trac #32281 removes gcc 4.x-based distributions whose binutils are unusable - tox_system_factor: [ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2. linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7-gcc_spkg, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-gcc_spkg] + tox_system_factor: [gitpod, ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] tox_packages_factor: [maximal] targets_pattern: [0-g, h-o, p, q-z] env: diff --git a/.github/workflows/tox-optional.yml b/.github/workflows/tox-optional.yml index 6a15b2bdbfc..9c0c3416a9c 100644 --- a/.github/workflows/tox-optional.yml +++ b/.github/workflows/tox-optional.yml @@ -38,10 +38,7 @@ jobs: fail-fast: false max-parallel: 6 matrix: - # This list is different from the one in tox.yml: - # Trac #31526 switches gcc 4.x-based distributions to using the gcc_spkg configuration factor - # Trac #32281 removes gcc 4.x-based distributions whose binutils are unusable - tox_system_factor: [ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2. linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7-gcc_spkg, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-gcc_spkg] + tox_system_factor: [ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2. linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] tox_packages_factor: [maximal] targets_pattern: [0-g, h-o, p, q-z] env: diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 3050255d228..23d0ec56b6a 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -38,7 +38,7 @@ jobs: fail-fast: false max-parallel: 20 matrix: - tox_system_factor: [gitpod, ubuntu-trusty, ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-17, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386] + tox_system_factor: [gitpod, ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] tox_packages_factor: [minimal, standard] env: TOX_ENV: docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} From e7ff2a83a3718923588f56a06c073721b2d18d8b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 20 Apr 2022 17:13:57 -0700 Subject: [PATCH 007/116] build/pkgs/gcc/spkg-configure.m4: Fixup --- build/pkgs/gcc/spkg-configure.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/gcc/spkg-configure.m4 b/build/pkgs/gcc/spkg-configure.m4 index 29b26c968bc..959e499b68a 100644 --- a/build/pkgs/gcc/spkg-configure.m4 +++ b/build/pkgs/gcc/spkg-configure.m4 @@ -169,7 +169,7 @@ SAGE_SPKG_CONFIGURE_BASE([gcc], [ # Install our own GCC if the system-provided one is newer than 12.x. # See https://trac.sagemath.org/ticket/29456 SAGE_SHOULD_INSTALL_GCC([$CXX is g++ version $GXX_VERSION, which is too recent for this version of Sage]) - ] + ]) fi # The following tests check that the version of the compilers From 0713f534c47ec586e485bd2e688fdf7fe4a80f53 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 20 Apr 2022 23:13:08 -0700 Subject: [PATCH 008/116] .github/workflows/tox*.yml: Replace ubuntu-xenial by ubuntu-xenial-toolchain-gcc_9 --- .github/workflows/tox-experimental.yml | 2 +- .github/workflows/tox-optional.yml | 2 +- .github/workflows/tox.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tox-experimental.yml b/.github/workflows/tox-experimental.yml index e5712591962..383a33dc4ec 100644 --- a/.github/workflows/tox-experimental.yml +++ b/.github/workflows/tox-experimental.yml @@ -38,7 +38,7 @@ jobs: fail-fast: false max-parallel: 6 matrix: - tox_system_factor: [gitpod, ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] + tox_system_factor: [gitpod, ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial-toolchain-gcc_9, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] tox_packages_factor: [maximal] targets_pattern: [0-g, h-o, p, q-z] env: diff --git a/.github/workflows/tox-optional.yml b/.github/workflows/tox-optional.yml index 9c0c3416a9c..37da5a4a9d8 100644 --- a/.github/workflows/tox-optional.yml +++ b/.github/workflows/tox-optional.yml @@ -38,7 +38,7 @@ jobs: fail-fast: false max-parallel: 6 matrix: - tox_system_factor: [ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2. linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] + tox_system_factor: [ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial-toolchain-gcc_9, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2. linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] tox_packages_factor: [maximal] targets_pattern: [0-g, h-o, p, q-z] env: diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 23d0ec56b6a..02f622affc2 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -38,7 +38,7 @@ jobs: fail-fast: false max-parallel: 20 matrix: - tox_system_factor: [gitpod, ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] + tox_system_factor: [gitpod, ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial-toolchain-gcc_9, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] tox_packages_factor: [minimal, standard] env: TOX_ENV: docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} From c000c8c89ed17cde730b171ef938f0c539547478 Mon Sep 17 00:00:00 2001 From: Darij Grinberg Date: Mon, 25 Apr 2022 11:03:38 +0900 Subject: [PATCH 009/116] Better normalize permutations for Schubert polynomials --- src/sage/combinat/permutation.py | 13 +++++++++++++ src/sage/combinat/schubert_polynomial.py | 18 ++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py index 8eae4b7c84c..1dce5cdfa06 100644 --- a/src/sage/combinat/permutation.py +++ b/src/sage/combinat/permutation.py @@ -4756,6 +4756,13 @@ def remove_extra_fixed_points(self): """ Return the permutation obtained by removing any fixed points at the end of ``self``. + However, return ``[1]`` rather than ``[]`` if ``self`` is the + identity permutation. + + This is mostly a helper method for + :module:`sage.combinat.schubert_polynomial`, where it is + used to normalize finitary permutations of + `\{1,2,3,\ldots\}`. EXAMPLES:: @@ -4763,11 +4770,17 @@ def remove_extra_fixed_points(self): [2, 1] sage: Permutation([1,2,3,4]).remove_extra_fixed_points() [1] + sage: Permutation([2,1]).remove_extra_fixed_points() + [2, 1] + sage: Permutation([]).remove_extra_fixed_points() + [1] .. SEEALSO:: :meth:`retract_plain` """ + if not self: + return Permutations()([1]) #Strip off all extra fixed points at the end of #the permutation. i = len(self)-1 diff --git a/src/sage/combinat/schubert_polynomial.py b/src/sage/combinat/schubert_polynomial.py index af28a8e45d7..b939754716c 100644 --- a/src/sage/combinat/schubert_polynomial.py +++ b/src/sage/combinat/schubert_polynomial.py @@ -66,9 +66,7 @@ def expand(self): TESTS: Calling .expand() should always return an element of an - MPolynomialRing - - :: + MPolynomialRing:: sage: X = SchubertPolynomialRing(ZZ) sage: f = X([1]); f @@ -83,10 +81,16 @@ def expand(self): sage: f = X([1,3,2,4]) sage: type(f.expand()) + + Now we check for correct handling of the empty + permutation (:trac:`23443`):: + + sage: X([1]).expand() * X([2,1]).expand() + x0 """ p = symmetrica.t_SCHUBERT_POLYNOM(self) if not is_MPolynomial(p): - R = PolynomialRing(self.parent().base_ring(), 1, 'x') + R = PolynomialRing(self.parent().base_ring(), 1, 'x0') p = R(p) return p @@ -361,6 +365,12 @@ def _element_constructor_(self, x): Traceback (most recent call last): ... ValueError: The input [1, 2, 1] is not a valid permutation + + Now we check for correct handling of the empty + permutation (:trac:`23443`):: + + sage: X([]) + X[1] """ if isinstance(x, list): # checking the input to avoid symmetrica crashing Sage, see trac 12924 From 8e7548b77d084a2268824c40be92f5a075f68886 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 30 Apr 2022 12:58:23 +0200 Subject: [PATCH 010/116] trac #33776: move distance_graph to graph.py --- src/sage/graphs/generic_graph.py | 161 ------------------------------- src/sage/graphs/graph.py | 161 +++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 161 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index a57e74c632a..29f6dfd7b80 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -216,7 +216,6 @@ :meth:`~GenericGraph.distance` | Return the (directed) distance from u to v in the (di)graph :meth:`~GenericGraph.distance_all_pairs` | Return the distances between all pairs of vertices. :meth:`~GenericGraph.distances_distribution` | Return the distances distribution of the (di)graph in a dictionary. - :meth:`~GenericGraph.distance_graph` | Return the graph on the same vertex set as the original graph but vertices are adjacent in the returned graph if and only if they are at specified distances in the original graph. :meth:`~GenericGraph.girth` | Return the girth of the graph. :meth:`~GenericGraph.odd_girth` | Return the odd girth of the graph. :meth:`~GenericGraph.shortest_path` | Return a list of vertices representing some shortest path from `u` to `v` @@ -14924,166 +14923,6 @@ def distance_all_pairs(self, by_weight=False, algorithm=None, weight_function=weight_function, check_weight=check_weight)[0] - def distance_graph(self, dist): - r""" - Return the graph on the same vertex set as the original graph but - vertices are adjacent in the returned graph if and only if they are at - specified distances in the original graph. - - INPUT: - - - ``dist`` -- a nonnegative integer or a list of nonnegative integers; - specified distance(s) for the connecting vertices. ``Infinity`` may - be used here to describe vertex pairs in separate components. - - OUTPUT: - - The returned value is an undirected graph. The vertex set is identical - to the calling graph, but edges of the returned graph join vertices - whose distance in the calling graph are present in the input ``dist``. - Loops will only be present if distance 0 is included. If the original - graph has a position dictionary specifying locations of vertices for - plotting, then this information is copied over to the distance graph. - In some instances this layout may not be the best, and might even be - confusing when edges run on top of each other due to symmetries chosen - for the layout. - - EXAMPLES:: - - sage: G = graphs.CompleteGraph(3) - sage: H = G.cartesian_product(graphs.CompleteGraph(2)) - sage: K = H.distance_graph(2) - sage: K.am() - [0 0 0 1 0 1] - [0 0 1 0 1 0] - [0 1 0 0 0 1] - [1 0 0 0 1 0] - [0 1 0 1 0 0] - [1 0 1 0 0 0] - - To obtain the graph where vertices are adjacent if their distance apart - is ``d`` or less use a ``range()`` command to create the input, using - ``d + 1`` as the input to ``range``. Notice that this will include - distance 0 and hence place a loop at each vertex. To avoid this, use - ``range(1, d + 1)``:: - - sage: G = graphs.OddGraph(4) - sage: d = G.diameter() - sage: n = G.num_verts() - sage: H = G.distance_graph(list(range(d+1))) - sage: H.is_isomorphic(graphs.CompleteGraph(n)) - False - sage: H = G.distance_graph(list(range(1,d+1))) - sage: H.is_isomorphic(graphs.CompleteGraph(n)) - True - - A complete collection of distance graphs will have adjacency matrices - that sum to the matrix of all ones:: - - sage: P = graphs.PathGraph(20) - sage: all_ones = sum([P.distance_graph(i).am() for i in range(20)]) - sage: all_ones == matrix(ZZ, 20, 20, [1]*400) - True - - Four-bit strings differing in one bit is the same as - four-bit strings differing in three bits:: - - sage: G = graphs.CubeGraph(4) - sage: H = G.distance_graph(3) - sage: G.is_isomorphic(H) - True - - The graph of eight-bit strings, adjacent if different in an odd number - of bits:: - - sage: G = graphs.CubeGraph(8) # long time - sage: H = G.distance_graph([1,3,5,7]) # long time - sage: degrees = [0]*sum([binomial(8,j) for j in [1,3,5,7]]) # long time - sage: degrees.append(2^8) # long time - sage: degrees == H.degree_histogram() # long time - True - - An example of using ``Infinity`` as the distance in a graph that is not - connected:: - - sage: G = graphs.CompleteGraph(3) - sage: H = G.disjoint_union(graphs.CompleteGraph(2)) - sage: L = H.distance_graph(Infinity) - sage: L.am() - [0 0 0 1 1] - [0 0 0 1 1] - [0 0 0 1 1] - [1 1 1 0 0] - [1 1 1 0 0] - - TESTS: - - Empty input, or unachievable distances silently yield empty graphs:: - - sage: G = graphs.CompleteGraph(5) - sage: G.distance_graph([]).num_edges() - 0 - sage: G = graphs.CompleteGraph(5) - sage: G.distance_graph(23).num_edges() - 0 - - It is an error to provide a distance that is not an integer type:: - - sage: G = graphs.CompleteGraph(5) - sage: G.distance_graph('junk') - Traceback (most recent call last): - ... - TypeError: unable to convert 'junk' to an integer - - It is an error to provide a negative distance:: - - sage: G = graphs.CompleteGraph(5) - sage: G.distance_graph(-3) - Traceback (most recent call last): - ... - ValueError: distance graph for a negative distance (d=-3) is not defined - - AUTHOR: - - Rob Beezer, 2009-11-25 - """ - from sage.rings.infinity import Infinity - # If input is not a list, make a list with this single object - if not isinstance(dist, list): - dist = [dist] - # Create a list of positive integer (or infinite) distances - distances = [] - for d in dist: - if d == Infinity: - distances.append(d) - else: - dint = ZZ(d) - if dint < 0: - raise ValueError('distance graph for a negative distance (d=%d) is not defined' % dint) - distances.append(dint) - # Build a graph on the same vertex set, with loops for distance 0 - vertices = {v: {} for v in self} - positions = copy(self.get_pos()) - if ZZ(0) in distances: - looped = True - else: - looped = False - from sage.graphs.graph import Graph - D = Graph(vertices, pos=positions, multiedges=False, loops=looped) - if len(distances) == 1: - dstring = "distance " + str(distances[0]) - else: - dstring = "distances " + str(sorted(distances)) - D.name("Distance graph for %s in " % dstring + self.name()) - - # Create the appropriate edges - d = self.distance_all_pairs() - for u in self: - for v in self: - if d[u].get(v, Infinity) in distances: - D.add_edge(u, v) - return D - def girth(self, certificate=False): """ Return the girth of the graph. diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index a4de61e3c0f..1d1aee130e1 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -5475,6 +5475,167 @@ def periphery(self, by_weight=False, algorithm=None, weight_function=None, return [] return [v for v in self if ecc[v] == d] + @doc_index("Distances") + def distance_graph(self, dist): + r""" + Return the graph on the same vertex set as the original graph but + vertices are adjacent in the returned graph if and only if they are at + specified distances in the original graph. + + INPUT: + + - ``dist`` -- a nonnegative integer or a list of nonnegative integers; + specified distance(s) for the connecting vertices. ``Infinity`` may + be used here to describe vertex pairs in separate components. + + OUTPUT: + + The returned value is an undirected graph. The vertex set is identical + to the calling graph, but edges of the returned graph join vertices + whose distance in the calling graph are present in the input ``dist``. + Loops will only be present if distance 0 is included. If the original + graph has a position dictionary specifying locations of vertices for + plotting, then this information is copied over to the distance graph. + In some instances this layout may not be the best, and might even be + confusing when edges run on top of each other due to symmetries chosen + for the layout. + + EXAMPLES:: + + sage: G = graphs.CompleteGraph(3) + sage: H = G.cartesian_product(graphs.CompleteGraph(2)) + sage: K = H.distance_graph(2) + sage: K.am() + [0 0 0 1 0 1] + [0 0 1 0 1 0] + [0 1 0 0 0 1] + [1 0 0 0 1 0] + [0 1 0 1 0 0] + [1 0 1 0 0 0] + + To obtain the graph where vertices are adjacent if their distance apart + is ``d`` or less use a ``range()`` command to create the input, using + ``d + 1`` as the input to ``range``. Notice that this will include + distance 0 and hence place a loop at each vertex. To avoid this, use + ``range(1, d + 1)``:: + + sage: G = graphs.OddGraph(4) + sage: d = G.diameter() + sage: n = G.num_verts() + sage: H = G.distance_graph(list(range(d+1))) + sage: H.is_isomorphic(graphs.CompleteGraph(n)) + False + sage: H = G.distance_graph(list(range(1,d+1))) + sage: H.is_isomorphic(graphs.CompleteGraph(n)) + True + + A complete collection of distance graphs will have adjacency matrices + that sum to the matrix of all ones:: + + sage: P = graphs.PathGraph(20) + sage: all_ones = sum([P.distance_graph(i).am() for i in range(20)]) + sage: all_ones == matrix(ZZ, 20, 20, [1]*400) + True + + Four-bit strings differing in one bit is the same as + four-bit strings differing in three bits:: + + sage: G = graphs.CubeGraph(4) + sage: H = G.distance_graph(3) + sage: G.is_isomorphic(H) + True + + The graph of eight-bit strings, adjacent if different in an odd number + of bits:: + + sage: G = graphs.CubeGraph(8) # long time + sage: H = G.distance_graph([1,3,5,7]) # long time + sage: degrees = [0]*sum([binomial(8,j) for j in [1,3,5,7]]) # long time + sage: degrees.append(2^8) # long time + sage: degrees == H.degree_histogram() # long time + True + + An example of using ``Infinity`` as the distance in a graph that is not + connected:: + + sage: G = graphs.CompleteGraph(3) + sage: H = G.disjoint_union(graphs.CompleteGraph(2)) + sage: L = H.distance_graph(Infinity) + sage: L.am() + [0 0 0 1 1] + [0 0 0 1 1] + [0 0 0 1 1] + [1 1 1 0 0] + [1 1 1 0 0] + + TESTS: + + Empty input, or unachievable distances silently yield empty graphs:: + + sage: G = graphs.CompleteGraph(5) + sage: G.distance_graph([]).num_edges() + 0 + sage: G = graphs.CompleteGraph(5) + sage: G.distance_graph(23).num_edges() + 0 + + It is an error to provide a distance that is not an integer type:: + + sage: G = graphs.CompleteGraph(5) + sage: G.distance_graph('junk') + Traceback (most recent call last): + ... + TypeError: unable to convert 'junk' to an integer + + It is an error to provide a negative distance:: + + sage: G = graphs.CompleteGraph(5) + sage: G.distance_graph(-3) + Traceback (most recent call last): + ... + ValueError: distance graph for a negative distance (d=-3) is not defined + + AUTHOR: + + Rob Beezer, 2009-11-25, :trac:`7533` + """ + from sage.rings.infinity import Infinity + # If input is not a list, make a list with this single object + if not isinstance(dist, list): + dist = [dist] + # Create a list of positive integer (or infinite) distances + distances = [] + for d in dist: + if d == Infinity: + distances.append(d) + else: + dint = ZZ(d) + if dint < 0: + raise ValueError('distance graph for a negative distance (d=%d) is not defined' % dint) + distances.append(dint) + # Build a graph on the same vertex set, with loops for distance 0 + vertices = {v: {} for v in self} + positions = copy(self.get_pos()) + if ZZ(0) in distances: + looped = True + else: + looped = False + from sage.graphs.graph import Graph + D = Graph(vertices, pos=positions, multiedges=False, loops=looped) + if len(distances) == 1: + dstring = "distance " + str(distances[0]) + else: + dstring = "distances " + str(sorted(distances)) + D.name("Distance graph for %s in " % dstring + self.name()) + + # Create the appropriate edges + d = self.distance_all_pairs() + for u in self: + for v in self: + if d[u].get(v, Infinity) in distances: + D.add_edge(u, v) + return D + ### Constructors @doc_index("Basic methods") From f71557684cbca2aa8792d5fbe93f342e6d4bd2bb Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 30 Apr 2022 13:04:51 +0200 Subject: [PATCH 011/116] trac #33776: speed up --- src/sage/graphs/graph.py | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 1d1aee130e1..22a1108261a 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -5605,35 +5605,47 @@ def distance_graph(self, dist): dist = [dist] # Create a list of positive integer (or infinite) distances distances = [] + s_distances = set() + b_oo = False for d in dist: if d == Infinity: - distances.append(d) + b_oo = True + distances.append(Infinity) else: dint = ZZ(d) if dint < 0: raise ValueError('distance graph for a negative distance (d=%d) is not defined' % dint) distances.append(dint) + s_distances.add(dint) # Build a graph on the same vertex set, with loops for distance 0 - vertices = {v: {} for v in self} - positions = copy(self.get_pos()) - if ZZ(0) in distances: - looped = True - else: - looped = False - from sage.graphs.graph import Graph - D = Graph(vertices, pos=positions, multiedges=False, loops=looped) if len(distances) == 1: dstring = "distance " + str(distances[0]) else: dstring = "distances " + str(sorted(distances)) - D.name("Distance graph for %s in " % dstring + self.name()) + name = "Distance graph for %s in " % dstring + self.name() + looped = ZZ(0) in s_distances + from sage.graphs.graph import Graph + D = Graph([self, []], format='vertices_and_edges', + multiedges=False, loops=looped, + pos=copy(self.get_pos()), name=name) # Create the appropriate edges - d = self.distance_all_pairs() - for u in self: - for v in self: - if d[u].get(v, Infinity) in distances: + import itertools + if self.is_connected(): + CC = [self] + else: + CC = self.connected_components_subgraphs() + if b_oo: + # add edges between connected components + for A, B in itertools.combinations(CC, 2): + D.add_edges(itertools.product(A, B)) + for g in CC: + d = g.distance_all_pairs() + for u, v in itertools.combinations(g, 2): + if d[u][v] in s_distances: D.add_edge(u, v) + if looped: + D.add_edges((u, u) for u in self) return D ### Constructors From 1edf47a2da179e8d20418c2f157af16663e462ee Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 30 Apr 2022 13:27:17 +0200 Subject: [PATCH 012/116] trac #33776: some care --- src/sage/graphs/graph.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 22a1108261a..9718a82b992 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -5485,7 +5485,7 @@ def distance_graph(self, dist): INPUT: - ``dist`` -- a nonnegative integer or a list of nonnegative integers; - specified distance(s) for the connecting vertices. ``Infinity`` may + specified distance(s) for the connecting vertices. ``Infinity`` may be used here to describe vertex pairs in separate components. OUTPUT: @@ -5493,7 +5493,7 @@ def distance_graph(self, dist): The returned value is an undirected graph. The vertex set is identical to the calling graph, but edges of the returned graph join vertices whose distance in the calling graph are present in the input ``dist``. - Loops will only be present if distance 0 is included. If the original + Loops will only be present if distance 0 is included. If the original graph has a position dictionary specifying locations of vertices for plotting, then this information is copied over to the distance graph. In some instances this layout may not be the best, and might even be @@ -5515,8 +5515,8 @@ def distance_graph(self, dist): To obtain the graph where vertices are adjacent if their distance apart is ``d`` or less use a ``range()`` command to create the input, using - ``d + 1`` as the input to ``range``. Notice that this will include - distance 0 and hence place a loop at each vertex. To avoid this, use + ``d + 1`` as the input to ``range``. Notice that this will include + distance 0 and hence place a loop at each vertex. To avoid this, use ``range(1, d + 1)``:: sage: G = graphs.OddGraph(4) @@ -5548,11 +5548,11 @@ def distance_graph(self, dist): The graph of eight-bit strings, adjacent if different in an odd number of bits:: - sage: G = graphs.CubeGraph(8) # long time - sage: H = G.distance_graph([1,3,5,7]) # long time - sage: degrees = [0]*sum([binomial(8,j) for j in [1,3,5,7]]) # long time - sage: degrees.append(2^8) # long time - sage: degrees == H.degree_histogram() # long time + sage: G = graphs.CubeGraph(8) # long time + sage: H = G.distance_graph([1,3,5,7]) # long time + sage: degrees = [0]*sum([binomial(8,j) for j in [1,3,5,7]]) # long time + sage: degrees.append(2^8) # long time + sage: degrees == H.degree_histogram() # long time True An example of using ``Infinity`` as the distance in a graph that is not @@ -5567,6 +5567,8 @@ def distance_graph(self, dist): [0 0 0 1 1] [1 1 1 0 0] [1 1 1 0 0] + sage: L.is_isomorphic(graphs.CompleteBipartiteGraph(3, 2)) + True TESTS: @@ -5605,18 +5607,15 @@ def distance_graph(self, dist): dist = [dist] # Create a list of positive integer (or infinite) distances distances = [] - s_distances = set() - b_oo = False for d in dist: if d == Infinity: - b_oo = True distances.append(Infinity) else: dint = ZZ(d) if dint < 0: raise ValueError('distance graph for a negative distance (d=%d) is not defined' % dint) distances.append(dint) - s_distances.add(dint) + s_distances = set(distances) # Build a graph on the same vertex set, with loops for distance 0 if len(distances) == 1: dstring = "distance " + str(distances[0]) @@ -5635,7 +5634,7 @@ def distance_graph(self, dist): CC = [self] else: CC = self.connected_components_subgraphs() - if b_oo: + if Infinity in s_distances: # add edges between connected components for A, B in itertools.combinations(CC, 2): D.add_edges(itertools.product(A, B)) From a0e037f4df2f303423855351c4d5fc5001cca69f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 2 May 2022 15:42:51 -0700 Subject: [PATCH 013/116] build/bin/write-dockerfile.sh [debian]: Handle EXTRA_PATH, EXTRA_SYSTEM_PACKAGES --- build/bin/write-dockerfile.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build/bin/write-dockerfile.sh b/build/bin/write-dockerfile.sh index 4e2f891d506..e61d94b8e92 100755 --- a/build/bin/write-dockerfile.sh +++ b/build/bin/write-dockerfile.sh @@ -13,7 +13,7 @@ EXTRA_SAGE_PACKAGES="${5:-_bootstrap}" STRIP_COMMENTS="sed s/#.*//;" SAGE_ROOT=. export PATH="$SAGE_ROOT"/build/bin:$PATH -SYSTEM_PACKAGES= +SYSTEM_PACKAGES=$EXTRA_SYSTEM_PACKAGES CONFIGURE_ARGS="--enable-option-checking " for PKG_BASE in $($SAGE_ROOT/sage -package list --has-file=distros/$SYSTEM.txt $SAGE_PACKAGE_LIST_ARGS) $EXTRA_SAGE_PACKAGES; do PKG_SCRIPTS="$SAGE_ROOT"/build/pkgs/$PKG_BASE @@ -60,6 +60,9 @@ RUN $UPDATE $INSTALL software-properties-common && ($INSTALL gpg gpg-agent || ec RUN $SUDO add-apt-repository $EXTRA_REPOSITORY EOF fi + if [ -n "$EXTRA_PATH" ]; then + RUN="RUN export PATH=$EXTRA_PATH:\$PATH && " + fi ;; fedora*|redhat*|centos*) cat < Date: Mon, 2 May 2022 15:43:21 -0700 Subject: [PATCH 014/116] tox.ini (ubuntu-trusty-toolchain): Use binutils-2.26 --- tox.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tox.ini b/tox.ini index 47c10c364ef..a4cb0289d61 100644 --- a/tox.ini +++ b/tox.ini @@ -192,6 +192,8 @@ setenv = ubuntu: SYSTEM=debian ubuntu: BASE_IMAGE=ubuntu ubuntu-toolchain: EXTRA_REPOSITORY=ppa:ubuntu-toolchain-r/test + ubuntu-toolchain-trusty: EXTRA_SYSTEM_PACKAGES=binutils-2.26 + ubuntu-toolchain-trusty: EXTRA_PATH=/usr/lib/binutils-2.26/bin ubuntu-trusty: BASE_TAG=trusty ubuntu-trusty: IGNORE_MISSING_SYSTEM_PACKAGES=yes ubuntu-xenial: BASE_TAG=xenial From 33ca13187c3f29b009e5e93f01d0e42fde64a713 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 2 May 2022 23:31:33 -0700 Subject: [PATCH 015/116] tox.ini, .github/workflows/tox*.yml: Add ubuntu-kinetic, linuxmint-21, fedora-37 --- .github/workflows/tox-experimental.yml | 2 +- .github/workflows/tox-optional.yml | 2 +- .github/workflows/tox.yml | 2 +- tox.ini | 9 +++++++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tox-experimental.yml b/.github/workflows/tox-experimental.yml index 383a33dc4ec..080d578c5d7 100644 --- a/.github/workflows/tox-experimental.yml +++ b/.github/workflows/tox-experimental.yml @@ -38,7 +38,7 @@ jobs: fail-fast: false max-parallel: 6 matrix: - tox_system_factor: [gitpod, ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial-toolchain-gcc_9, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] + tox_system_factor: [gitpod, ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial-toolchain-gcc_9, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, ubuntu-kinetic, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, linuxmint-20.3, linuxmint-21, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, fedora-37, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] tox_packages_factor: [maximal] targets_pattern: [0-g, h-o, p, q-z] env: diff --git a/.github/workflows/tox-optional.yml b/.github/workflows/tox-optional.yml index 37da5a4a9d8..3a451faa0b4 100644 --- a/.github/workflows/tox-optional.yml +++ b/.github/workflows/tox-optional.yml @@ -38,7 +38,7 @@ jobs: fail-fast: false max-parallel: 6 matrix: - tox_system_factor: [ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial-toolchain-gcc_9, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2. linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] + tox_system_factor: [gitpod, ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial-toolchain-gcc_9, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, ubuntu-kinetic, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, linuxmint-20.3, linuxmint-21, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, fedora-37, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] tox_packages_factor: [maximal] targets_pattern: [0-g, h-o, p, q-z] env: diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 02f622affc2..69f8450da00 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -38,7 +38,7 @@ jobs: fail-fast: false max-parallel: 20 matrix: - tox_system_factor: [gitpod, ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial-toolchain-gcc_9, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, linuxmint-20.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] + tox_system_factor: [gitpod, ubuntu-trusty-toolchain-gcc_9, ubuntu-xenial-toolchain-gcc_9, ubuntu-bionic, ubuntu-focal, ubuntu-hirsute, ubuntu-impish, ubuntu-jammy, ubuntu-kinetic, debian-stretch, debian-buster, debian-bullseye, debian-bookworm, debian-sid, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, linuxmint-20.3, linuxmint-21, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, fedora-36, fedora-37, centos-7-devtoolset-gcc_11, centos-stream-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15.3, opensuse-tumbleweed, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-devtoolset-gcc_11] tox_packages_factor: [minimal, standard] env: TOX_ENV: docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} diff --git a/tox.ini b/tox.ini index a4cb0289d61..5ee6fb94f33 100644 --- a/tox.ini +++ b/tox.ini @@ -187,7 +187,7 @@ setenv = docker: BASE_TAG=latest # # https://hub.docker.com/_/ubuntu?tab=description - # as of 2021-11, latest=focal=20.04, rolling=impish=21.10, devel=jammy=22.04 + # as of 2022-05, latest=rolling=jammy=22.04, devel=kinetic=22.10 # ubuntu: SYSTEM=debian ubuntu: BASE_IMAGE=ubuntu @@ -207,6 +207,8 @@ setenv = ubuntu-impish: IGNORE_MISSING_SYSTEM_PACKAGES=yes ubuntu-jammy: BASE_TAG=jammy ubuntu-jammy: IGNORE_MISSING_SYSTEM_PACKAGES=yes + ubuntu-kinetic: BASE_TAG=kinetic + ubuntu-kinetic: IGNORE_MISSING_SYSTEM_PACKAGES=yes # # https://hub.docker.com/_/debian # debian-bullseye does not have libgiac-dev @@ -238,9 +240,10 @@ setenv = linuxmint-20.1: BASE_IMAGE=linuxmintd/mint20.1 linuxmint-20.2: BASE_IMAGE=linuxmintd/mint20.2 linuxmint-20.3: BASE_IMAGE=linuxmintd/mint20.3 + linuxmint-21: BASE_IMAGE=linuxmintd/mint21 # # https://hub.docker.com/_/fedora - # as of 2021-11, latest=35, rawhide=36 + # as of 2021-11, latest=35, rawhide=37 fedora: SYSTEM=fedora fedora: BASE_IMAGE=fedora fedora-26: BASE_TAG=26 @@ -263,6 +266,8 @@ setenv = fedora-35: IGNORE_MISSING_SYSTEM_PACKAGES=yes fedora-36: BASE_TAG=36 fedora-36: IGNORE_MISSING_SYSTEM_PACKAGES=yes + fedora-37: BASE_TAG=37 + fedora-37: IGNORE_MISSING_SYSTEM_PACKAGES=yes # # https://hub.docker.com/r/scientificlinux/sl # From 4b52f085f8eb3fc9b81f4f37e4e5ef7f197d0248 Mon Sep 17 00:00:00 2001 From: "aram.dermenjian" Date: Tue, 29 Sep 2020 15:11:43 -0400 Subject: [PATCH 016/116] Add Nu Dyck Words and Nu Tamari Lattice --- src/doc/en/reference/combinat/module_list.rst | 2 + src/doc/en/reference/references/index.rst | 7 + src/sage/combinat/all.py | 1 + src/sage/combinat/nu_dyck_word.py | 1403 +++++++++++++++++ src/sage/combinat/nu_tamari_lattice.py | 105 ++ src/sage/combinat/words/paths.py | 38 + 6 files changed, 1556 insertions(+) create mode 100644 src/sage/combinat/nu_dyck_word.py create mode 100644 src/sage/combinat/nu_tamari_lattice.py diff --git a/src/doc/en/reference/combinat/module_list.rst b/src/doc/en/reference/combinat/module_list.rst index d1da854a364..7a97a40e30d 100644 --- a/src/doc/en/reference/combinat/module_list.rst +++ b/src/doc/en/reference/combinat/module_list.rst @@ -164,6 +164,8 @@ Comprehensive Module List sage/combinat/ncsym/ncsym sage/combinat/necklace sage/combinat/non_decreasing_parking_function + sage/combinat/nu_dyck_word + sage/combinat/nu_tamari_lattice sage/combinat/ordered_tree sage/combinat/output sage/combinat/parallelogram_polyomino diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 46e46557a02..04547fd8456 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -998,6 +998,9 @@ REFERENCES: lacunas of the Thue-Morse word*, Proc. GASCOM 2008 (June 16-20 2008, Bibbiena, Arezzo-Italia), 53--67. +.. [BMFPR] \M. Bousquet-Melou, E. Fusy, L.-F. Preville Ratelle. + *The number of intervals in the m-Tamari lattices*. :arxiv:`1106.1498` + .. [BMS2006] Bugeaud, Mignotte, and Siksek. "Classical and modular approaches to exponential Diophantine equations: I. Fibonacci and Lucas perfect powers." Annals @@ -4775,6 +4778,10 @@ REFERENCES: *PICARO - a block cipher allowing efficient higher-order side-channel resistance*; in ACNS, (2012), pp. 311-328. +.. [PRV2017] \L.-F. Préville-Ratelle and X. Viennot, + *The enumeration of generalized Tamari intervals*. + Trans. Amer. Math. Soc. 369 (2017), pp 5219--5239 + .. [Prototype_pattern] Prototype pattern, :wikipedia:`Prototype_pattern` diff --git a/src/sage/combinat/all.py b/src/sage/combinat/all.py index 953c6b29761..00153b736e5 100644 --- a/src/sage/combinat/all.py +++ b/src/sage/combinat/all.py @@ -216,6 +216,7 @@ from .subset import Subsets from .necklace import Necklaces lazy_import('sage.combinat.dyck_word', ('DyckWords', 'DyckWord')) +lazy_import('sage.combinat.nu_dyck_word', ('NuDyckWords', 'NuDyckWord')) from .sloane_functions import sloane lazy_import('sage.combinat.superpartition', ('SuperPartition', 'SuperPartitions')) diff --git a/src/sage/combinat/nu_dyck_word.py b/src/sage/combinat/nu_dyck_word.py new file mode 100644 index 00000000000..07b39d3e965 --- /dev/null +++ b/src/sage/combinat/nu_dyck_word.py @@ -0,0 +1,1403 @@ +# -*- coding: utf-8 -*- +r""" +`\nu`-Dyck Words + +A class of the `\nu`-Dyck word, see [PRV2017]_ for details. + +AUTHORS: + +- Aram Dermenjian (2020-09-26) + +This file is based off the class ``DyckWords`` written by Mke Hansen, Dan +Drake, Florent Hivert, Christian Stump, Mike Zabrocki, Jean--Baptiste Priez +and Travis Scrimshaw + +""" + +# **************************************************************************** +# Copyright (C) 2020 Aram Dermenjian , +# +# Distributed under the terms of the GNU General Public License (GPL) +# +# This code is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# The full text of the GPL is available at: +# +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.structure.element import Element +from sage.rings.integer import Integer +from sage.combinat.combinat import CombinatorialElement +from sage.structure.global_options import GlobalOptions +from sage.structure.parent import Parent +from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets +from sage.combinat.permutation import Permutations +from sage.misc.latex import latex + +from sage.combinat.words.paths import WordPaths_north_east +from sage.combinat.words.paths import FiniteWordPath_north_east + +ndw_open_symbol = 1 +ndw_close_symbol = 0 + + +def update_ndw_symbols(os, cs): + r""" + A way to alter the open and close symbols from sage + + INPUT: + + - ``os`` -- The open symbol + - ``cs`` -- The close symbol + """ + global ndw_open_symbol + global ndw_close_symbol + ndw_open_symbol = os + ndw_close_symbol = cs + + +def replace_dyck_char(x): + r""" + A map sending an opening character (``'1'``, ``'N'``, and ``'('``) to + ``ndw_open_symbol`` and a closing character (``'0'``, ``'E'``, and ``')'``) to + ``ndw_close_symbol``, and raising an error on any input other than one of the + opening or closing characters. + + This is the inverse map of :func:`replace_dyck_symbol`. + + INPUT: + + - ``x`` -- str - A ``'1'``, ``'0'``, ``'N'``, ``'E'``, ``'('`` or ``')'`` + + OUTPUT: + + - If ``x`` is an opening character, replace ``x`` with the + constant ``ndw_open_symbol``. + + - If ``x`` is a closing character, replace ``x`` with the + constant ``ndw_close_symbol``. + + - Raise a ``ValueError`` if ``x`` is neither an opening nor a + closing character. + + .. SEEALSO:: :func:`replace_dyck_symbol` + + EXAMPLES:: + + sage: from sage.combinat.nu_dyck_word import replace_dyck_char + sage: replace_dyck_char('(') + 1 + sage: replace_dyck_char(')') + 0 + sage: replace_dyck_char(1) + Traceback (most recent call last): + ... + ValueError + """ + if x == '(' or x == 'N' or x == str(ndw_open_symbol): + return ndw_open_symbol + elif x == ')' or x == 'E' or x == str(ndw_close_symbol): + return ndw_close_symbol + else: + raise ValueError + + +def replace_dyck_symbol(x, open_char='N', close_char='E'): + r""" + A map sending ``ndw_open_symbol`` to ``open_char`` and ``ndw_close_symbol`` to + ``close_char``, and raising an error on any input other than + ``ndw_open_symbol`` and ``ndw_close_symbol``. The values of the constants + ``ndw_open_symbol`` and ``ndw_close_symbol`` are subject to change. + + This is the inverse map of :func:`replace_dyck_char`. + + INPUT: + + - ``x`` -- either ``ndw_open_symbol`` or ``ndw_close_symbol``. + + - ``open_char`` -- str (optional) default ``'N'`` + + - ``close_char`` -- str (optional) default ``'E'`` + + OUTPUT: + + - If ``x`` is ``ndw_open_symbol``, replace ``x`` with ``open_char``. + + - If ``x`` is ``ndw_close_symbol``, replace ``x`` with ``close_char``. + + - If ``x`` is neither ``ndw_open_symbol`` nor ``ndw_close_symbol``, a + ``ValueError`` is raised. + + .. SEEALSO:: :func:`replace_dyck_char` + + EXAMPLES:: + + sage: from sage.combinat.nu_dyck_word import replace_dyck_symbol + sage: replace_dyck_symbol(1) + 'N' + sage: replace_dyck_symbol(0) + 'E' + sage: replace_dyck_symbol(3) + Traceback (most recent call last): + ... + ValueError + """ + if x == ndw_open_symbol: + return open_char + elif x == ndw_close_symbol: + return close_char + else: + raise ValueError + + +class NuDyckWord(CombinatorialElement): + r""" + A `\nu`-Dyck word. + + Given a lattice path `\nu` in the `\ZZ^2` grid starting at the origin + `(0,0)` consisting of North `N = (0,1)` and East `E = (1,0)` steps, a + `\nu`-Dyck path is a lattice path in the `\ZZ^2` grid starting at the + origin `(0,0)` and ending at the same coordinate as `\nu` such that it is + weakly above `\nu`. A `\nu`-Dyck word is the representation of a + `\nu`-Dyck path where a North step is represented by a 1 and an East step + is represented by a 0. + + INPUT: + + - k1 -- A path for the `\nu`-Dyck word + + - k2 -- A path for `\nu` + + EXAMPLES:: + + sage: dw = NuDyckWord([1,0,1,0],[1,0,0,1]); dw + [1, 0, 1, 0] + sage: print(dw) + NENE + sage: dw.height() + 2 + + :: + + sage: dw = NuDyckWord('1010',[1,0,0,1]); dw + [1, 0, 1, 0] + + :: + + sage: dw = NuDyckWord('NENE',[1,0,0,1]); dw + [1, 0, 1, 0] + + :: + + sage: NuDyckWord([1,0,1,0],[1,0,0,1]).pretty_print() + __ + _|x + | . . + + :: + + sage: from sage.combinat.nu_dyck_word import update_ndw_symbols + sage: update_ndw_symbols(0,1) + sage: dw = NuDyckWord('0101001','0110010'); dw + [0, 1, 0, 1, 0, 0, 1] + sage: dw.pp() + __ + |x + _| . + _|x . + | . . . + sage: update_ndw_symbols(1,0) + + """ + @staticmethod + def __classcall_private__(cls, dw=None, nu=None, **kwargs): + """ + Return an element with the appropriate parent. + + EXAMPLES:: + + sage: NuDyckWord('110100','101010') + [1, 1, 0, 1, 0, 0] + sage: NuDyckWord('010','010') + [0, 1, 0] + """ + + # if dw is none, then we might have a normal Dyck word + if dw is None: + from sage.combinat.dyck_word import DyckWord + return DyckWord(dw, kwargs) + + if isinstance(dw, NuDyckWord): + return dw + + if nu is None: + raise ValueError("nu required") + + dw = to_word_path(dw) + nu = to_word_path(nu) + + if path_weakly_above_other(dw, nu): + return NuDyckWords(nu)(dw) + + raise ValueError("invalid nu-Dyck word") + + def __init__(self, parent, dw, latex_options={}): + Element.__init__(self, parent) + self._path = to_word_path(dw) + + if parent is None: + raise ValueError("Need Parent object") + + self._nu = parent._nu + + self._latex_options = dict(latex_options) + + def _list(self): + """ + Return list of self + """ + return list(self._path) + + def __eq__(self, other): + """ + Return if two paths are equal + """ + if type(other) != type(self): + return False + return self._path == other._path and self._nu == other._nu + + def __neq__(self, other): + """ + Return if two paths are not equal + """ + return not self.__eq__(other) + + def __le__(self, other): + """ + Returns if one path is included in another + """ + if self._nu == other._nu: + return path_weakly_above_other(other._path, self._path) + return False + + def __lt__(self, other): + """ + Returns if one path is strictly included in another + """ + return self.__le__(other) and not self.__eq__(other) + + def __ge__(self, other): + """ + Returns if one path is included in another + """ + if self._nu == other._nu: + return path_weakly_above_other(self._path, other._path) + return False + + def __gt__(self, other): + """ + Returns if one path is strictly included in another + """ + return self.__ge__(other) and not self.__eq__(other) + + def _cache_key(self): + """ + Return a cache key + """ + return str(self._path) + "-" + str(self._nu) + + def __hash__(self): + return hash(''.join([str(i) for i in self._list()])) + + def set_latex_options(self, D): + r""" + Set the latex options for use in the ``_latex_`` function. + + The default values are set in the ``__init__`` function. + + - ``color`` -- (default: black) the line color. + + - ``line width`` -- (default: `2 \times` ``tikz_scale``) value representing the + line width. + + - ``nu_options`` -- (default: ``'rounded corners=1, color=red, line + width=1'``) str to indicate what the tikz options should be for path + of `\nu`. + + - ``points_color`` -- (default: ``'black'``) str to indicate color + points should be drawn with. + + - ``show_grid`` -- (default: ``True``) boolean value to indicate if + grid should be shown. + + - ``show_nu`` -- (default: ``True``) boolean value to indicate if `\nu` + should be shown. + + - ``show_points`` -- (default: ``False``) boolean value to indicate + if points should be shown on path. + + - ``tikz_scale`` -- (default: 1) scale for use with the tikz package. + + INPUT: + + - ``D`` -- a dictionary with a list of latex parameters to change + + EXAMPLES:: + + sage: NDW = NuDyckWord('010','010') + sage: NDW.set_latex_options({"tikz_scale":2}) + sage: NDW.set_latex_options({"color":"blue", "show_points":True}) + + .. TODO:: + + This should probably be merged into NuDyckWord.options. + """ + for opt in D: + self._latex_options[opt] = D[opt] + + def latex_options(self): + r""" + Return the latex options for use in the ``_latex_`` function as a + dictionary. + + The default values are set using the options. + + - ``color`` -- (default: black) the line color. + + - ``line width`` -- (default: 2*``tikz_scale``) value representing the + line width. + + - ``nu_options`` -- (default: ``'rounded corners=1, color=red, line + width=1'``) str to indicate what the tikz options should be for path + of `\nu`. + + - ``points_color`` -- (default: ``'black'``) str to indicate color + points should be drawn with. + + - ``show_grid`` -- (default: ``True``) boolean value to indicate if + grid should be shown. + + - ``show_nu`` -- (default: ``True``) boolean value to indicate if `\nu` + should be shown. + + - ``show_points`` -- (default: ``False``) boolean value to indicate + if points should be shown on path. + + - ``tikz_scale`` -- (default: 1) scale for use with the tikz package. + + EXAMPLES:: + + sage: NDW = NuDyckWord('010','010') + sage: NDW.latex_options() + {'color': black, + 'line width': 2, + 'nu_options': rounded corners=1, color=red, line width=1, + 'points_color': black, + 'show_grid': True, + 'show_nu': True, + 'show_points': False, + 'tikz_scale': 1} + + .. TODO:: + + This should probably be merged into NuDyckWord.options. + """ + d = self._latex_options.copy() + opts = self.parent().options + if "tikz_scale" not in d: + d["tikz_scale"] = opts.latex_tikz_scale + if "line width" not in d: + d["line width"] = opts.latex_line_width_scalar * d["tikz_scale"] + if "color" not in d: + d["color"] = opts.latex_color + if "show_points" not in d: + d["show_points"] = opts.latex_show_points + if "points_color" not in d: + d["points_color"] = opts.latex_points_color + if "show_grid" not in d: + d["show_grid"] = opts.latex_show_grid + if "show_nu" not in d: + d["show_nu"] = opts.latex_show_nu + if "nu_options" not in d: + d["nu_options"] = opts.latex_nu_options + return d + + def _repr_(self): + r""" + Return a string representation of ``self`` depending on + :meth:`NuDyckWords.options`. + + TESTS:: + + sage: NuDyckWord('01010','00011') + [0, 1, 0, 1, 0] + sage: NuDyckWord('10010','00011') + [1, 0, 0, 1, 0] + sage: NuDyckWords.options.display="lattice" + sage: NuDyckWord('10010','00011') + __ + ___|x + |x x x + + sage: NuDyckWords.options._reset() + """ + return self.parent().options._dispatch(self, '_repr_', 'display') + + def _repr_list(self): + r""" + Return a string representation of ``self`` as a list. + + TESTS:: + + sage: NuDyckWord([1,1,0],[1,0,1]) + [1, 1, 0] + sage: NuDyckWord('NNEE','NENE') + [1, 1, 0, 0] + """ + return str(list(self._path)) + + def _repr_lattice(self, type=None, labelling=None): + r""" + See :meth:`pretty_print()`. + + TESTS:: + + sage: print(NuDyckWord('00011001000100','00011001000100')._repr_lattice(type='N-E', labelling=[1,2,3,4])) + ____ + _____| . . 4 + ___| . . . . . 3 + | . . . . . . . 2 + ______| . . . . . . . 1 + + + sage: print(NuDyckWord('100101','010011')._repr_lattice()) + _| + ___|x + |x . . + + sage: print(NuDyckWord('110010','001011')._repr_lattice()) + __ + ___|x + |x x x + |x x . + + + """ + if type is None: + type = self.parent().options.diagram_style + if type == "grid": + type = "N-E" + + if type == "N-E": + path_length = self._path.length() + height = self._path.height() + width = self._path.width() + if path_length == 0: + return ".\n" + + # Handle right-hand side labels + if labelling is None: + labels = [" "] * height + else: + if len(labelling) != height: + raise ValueError( + "The given labelling has the wrong length. {num} needed".format(num=height)) + labels = [str(label) for label in labelling] + max_length = max(len(label) for label in labels) + labels = [lbl.rjust(max_length + 1) for lbl in labels] + + rev_path = list(self._path.reversal()) + rev_nu_path = list(self._nu.reversal()) + ts = "" + + # Grab first line + cur_pos = rev_path.index(ndw_open_symbol) + cur_nu_pos = rev_nu_path.index(ndw_open_symbol) + if cur_pos > 0: + ts += " " * (width - cur_pos) + ts += " _" + "__" * (cur_pos-1) + ts += "_\n" + + # Middle Lines + for i in range(height-1): + old_pos = cur_pos + old_nu_pos = cur_nu_pos + cur_pos = rev_path.index(ndw_open_symbol, cur_pos + 1) + cur_nu_pos = rev_nu_path.index(ndw_open_symbol, cur_nu_pos + 1) + + ts += " " * (width - cur_pos + i + 1) + if cur_pos != old_pos + 1: + ts += " _" + "__" * (cur_pos - old_pos - 2) + ts += "|" + if old_pos >= 0: + ts += "x " * (old_pos - old_nu_pos) + ts += " ." * (old_nu_pos - i) + ts += labels[height-i-1] + ts += "\n" + + # Final line + ts += "__" * (path_length - cur_pos - 1) + ts += "|" + ts += "x " * (cur_pos - cur_nu_pos) + ts += " ." * (cur_nu_pos - i - 1) + ts += labels[0] + ts += "\n" + return ts + else: + raise ValueError("The given type (=%s) is not valid." % type) + + def _ascii_art_(self): + r""" + Return an ASCII art representation of ``self``. + + TESTS:: + + sage: ascii_art(NuDyckWord('00011001000100','00011001000100')) + ____ + _____| . . + ___| . . . . . + | . . . . . . . + ______| . . . . . . . + + """ + from sage.typeset.ascii_art import AsciiArt + rep = self.parent().options.ascii_art + if rep == "pretty_output": + ret = self._repr_lattice() + return AsciiArt(ret.splitlines(), baseline=0) + + def __str__(self): + r""" + Return a string consisting of N and E steps corresponding to + the `\nu`-Dyck word. + + EXAMPLES:: + + sage: str(NuDyckWord('100101','010011')) + 'NEENEN' + sage: str(NuDyckWord('101010','100110')) + 'NENENE' + """ + return "".join(map(replace_dyck_symbol, list(self._path))) + + def pretty_print(self, type=None, labelling=None): + r""" + Display a NuDyckWord as a lattice path in the `\ZZ^2` grid. + + If the ``type`` is "N-E", then a cell below the diagonal is + indicated by a period, whereas a cell below the path but above + the diagonal is indicated by an x. If a list of labels is + included, they are displayed along the vertical edges of the + Dyck path. + + INPUT: + + - ``type`` -- (default: ``None``) can either be: + + - ``None`` to use the option default + - "N-E" to show ``self`` as a path of north and east steps, or + + - ``labelling`` -- (if type is "N-E") a list of labels assigned to + the up steps in ``self``. + + - ``underpath`` -- (if type is "N-E", default: ``True``) If ``True``, + an ``x`` to show the boxes between `\nu` and the `\nu`-Dyck Path. + + EXAMPLES:: + + sage: for ND in NuDyckWords('101010'): ND.pretty_print() + ______ + |x x . + |x . . + | . . . + ____ + _|x . + |x . . + | . . . + __ + ___| . + |x . . + | . . . + ____ + |x . + _| . . + | . . . + __ + _| . + _| . . + | . . . + + :: + + sage: ND = NuDyckWord([1,1,1,0,1,0,0,1,1,0,0,0],[1,0,1,0,1,0,1,0,1,0,1,0]) + sage: ND.pretty_print() + ______ + |x x . + ___|x . . + _|x x . . . + |x x . . . . + |x . . . . . + | . . . . . . + + :: + + sage: NuDyckWord([1,1,0,0,1,0],[1,0,1,0,1,0]).pretty_print( + ....: labelling=[1,3,2]) + __ + ___| . 2 + |x . . 3 + | . . . 1 + + :: + + sage: NuDyckWord('1101110011010010001101111000110000', + ....: '1010101010101010101010101010101010').pretty_print( + ....: labelling=list(range(1,18))) + ________ + |x x x . 17 + _____|x x . . 16 + |x x x x . . . 15 + |x x x . . . . 14 + |x x . . . . . 13 + _|x . . . . . . 12 + |x . . . . . . . 11 + _____| . . . . . . . . 10 + ___|x x . . . . . . . . . 9 + _|x x x . . . . . . . . . . 8 + |x x x . . . . . . . . . . . 7 + ___|x x . . . . . . . . . . . . 6 + |x x x . . . . . . . . . . . . . 5 + |x x . . . . . . . . . . . . . . 4 + _|x . . . . . . . . . . . . . . . 3 + |x . . . . . . . . . . . . . . . . 2 + | . . . . . . . . . . . . . . . . . 1 + + + :: + + sage: NuDyckWord().pretty_print() + . + """ + print(self._repr_lattice(type, labelling)) + + pp = pretty_print + + def _latex_(self): + r""" + A latex representation of ``self`` using the tikzpicture package. + + EXAMPLES:: + sage: NDW = NuDyckWord('010','010') + sage: NDW.set_latex_options({"show_points":True}) + sage: latex(NDW) + \vcenter{\hbox{$\begin{tikzpicture}[scale=1] + \draw[dotted] (0, 0) grid (2, 1); + \draw[line width=2,color=black,fill=black](0, 0) circle (0.21); + \draw[line width=2,color=black,fill=black](1, 0) circle (0.21); + \draw[line width=2,color=black,fill=black](1, 1) circle (0.21); + \draw[line width=2,color=black,fill=black](2, 1) circle (0.21); + \draw[rounded corners=1, color=red, line width=1] (0, 0) -- (1, 0) -- (1, 1) -- (2, 1); + \draw[rounded corners=1, color=black, line width=2] (0, 0) -- (1, 0) -- (1, 1) -- (2, 1); + \end{tikzpicture}$}} + sage: NuDyckWord('01','01')._latex_() + '\\vcenter{\\hbox{$\\begin{tikzpicture}[scale=1]\n \\draw[dotted] (0, 0) grid (1, 1);\n \\draw[rounded corners=1, color=red, line width=1] (0, 0) -- (1, 0) -- (1, 1);\n \\draw[rounded corners=1, color=black, line width=2] (0, 0) -- (1, 0) -- (1, 1);\n\\end{tikzpicture}$}}' + sage: NuDyckWord('101100','101010')._latex_() + '\\vcenter{\\hbox{$\\begin{tikzpicture}[scale=1]\n \\draw[dotted] (0, 0) grid (3, 3);\n \\draw[rounded corners=1, color=red, line width=1] (0, 0) -- (0, 1) -- (1, 1) -- (1, 2) -- (2, 2) -- (2, 3) -- (3, 3);\n \\draw[rounded corners=1, color=black, line width=2] (0, 0) -- (0, 1) -- (1, 1) -- (1, 2) -- (1, 3) -- (2, 3) -- (3, 3);\n\\end{tikzpicture}$}}' + """ + latex.add_package_to_preamble_if_available("tikz") + latex_options = self.latex_options() + + # Start setting up tikz + res = "\\vcenter{\\hbox{$\\begin{tikzpicture}" + res += "[scale=" + str(latex_options['tikz_scale']) + "]" + res += "\n" + + # Setup background grid + if latex_options['show_grid']: + grid = [((0, 0), (self.width(), self.height()))] + for v1, v2 in grid: + res += " \\draw[dotted] %s grid %s;" % (str(v1), str(v2)) + res += "\n" + + # Add points if wanted + if latex_options['show_points']: + pt_color = latex_options['points_color'] + radius = 0.15 + .03 * latex_options['line width'] + for v in self.points(): + res += " \\draw[line width=2," + res += "color=%s,fill=%s]" % (pt_color, pt_color) + res += "%s circle (%s);" % (str(v), str(radius)) + res += "\n" + + # Add nu if wanted + if latex_options['show_nu']: + res += " \\draw[%s]" % (str(latex_options['nu_options'])) + for k, p in enumerate(self._nu.points()): + if k == 0: + res += " %s" % (str(p)) + else: + res += " -- %s" % (str(p)) + res += ";\n" + + # setup Path + res += " \\draw[rounded corners=1, color=%s, line width=%s]" % ( + latex_options['color'], + str(latex_options['line width']) + ) + for k, p in enumerate(self._path.points()): + if k == 0: + res += " %s" % (str(p)) + else: + res += " -- %s" % (str(p)) + res += ";\n" + res += "\\end{tikzpicture}$}}" + return res + + def plot(self, **kwds): + r""" + Plot a `\nu`-Dyck word as a continuous path. + + EXAMPLES:: + + sage: NDW = NuDyckWord('010','010') + sage: NDW.plot() + Graphics object consisting of 1 graphics primitive + """ + from sage.plot.plot import list_plot + return list_plot(list(self.points()), plotjoined=True, **kwds) + + def path(self): + r""" + Return the underlying path object + + EXAMPLES:: + + sage: NDW = NuDyckWord('10011001000','00100101001') + sage: NDW.path() + Path: 10011001000 + """ + return self._path + + def height(self): + r""" + Return the height of ``self``. + + The height is the number of ``north`` steps. + + EXAMPLES:: + + sage: NuDyckWord('1101110011010010001101111000110000', + ....: '1010101010101010101010101010101010').height() + 17 + """ + return self._path.height() + + def width(self): + r""" + Return the width of ``self``. + + The width is the number of ``east`` steps. + + EXAMPLES:: + + sage: NuDyckWord('110111001101001000110111100011000', + ....: '101010101010101010101010101010101').width() + 16 + """ + return self._path.width() + + def length(self): + r""" + Return the length of ``self``. + + The length is the total number of steps. + + EXAMPLES:: + + sage: NDW = NuDyckWord('10011001000','00100101001') + sage: NDW.length() + 11 + """ + return self._path.length() + + def points(self): + r""" + Returns an iter with the points on the `\nu`-Dyck path. + + EXAMPLES:: + + sage: list(NuDyckWord('110111001101001000110111100011000', + ....: '101010101010101010101010101010101')._path.points()) + [(0, 0), + (0, 1), + (0, 2), + (1, 2), + (1, 3), + (1, 4), + (1, 5), + (2, 5), + (3, 5), + (3, 6), + (3, 7), + (4, 7), + (4, 8), + (5, 8), + (6, 8), + (6, 9), + (7, 9), + (8, 9), + (9, 9), + (9, 10), + (9, 11), + (10, 11), + (10, 12), + (10, 13), + (10, 14), + (10, 15), + (11, 15), + (12, 15), + (13, 15), + (13, 16), + (13, 17), + (14, 17), + (15, 17), + (16, 17)] + """ + return self._path.points() + + def heights(self): + r""" + Return the heights of each point on ``self``. + + We view the Dyck word as a Dyck path from `(0,0)` to + `(x,y)` in the first quadrant by letting ``1``'s represent + steps in the direction `(0,1)` and ``0``'s represent steps in + the direction `(1,0)`. + + The heights is the sequence of the `y`-coordinates of all + `x+y` lattice points along the path. + + EXAMPLES:: + + sage: NuDyckWord('010','010').heights() + [0, 0, 1, 1] + sage: NuDyckWord('110100','101010').heights() + [0, 1, 2, 2, 3, 3, 3] + sage: NuDyckWord('110111001101001000110111100011000', + ....: '101010101010101010101010101010101').heights() + [0, + 1, + 2, + 2, + 3, + 4, + 5, + 5, + 5, + 6, + 7, + 7, + 8, + 8, + 8, + 9, + 9, + 9, + 9, + 10, + 11, + 11, + 12, + 13, + 14, + 15, + 15, + 15, + 15, + 16, + 17, + 17, + 17, + 17] + """ + return self._path.height_vector() + + def widths(self): + r""" + Return the widths of each point on ``self``. + + We view the Dyck word as a Dyck path from `(0,0)` to + `(x,y)` in the first quadrant by letting ``1``'s represent + steps in the direction `(0,1)` and ``0``'s represent steps in + the direction `(1,0)`. + + The widths is the sequence of the `x`-coordinates of all + `x+y` lattice points along the path. + + EXAMPLES:: + + sage: NuDyckWord('010','010').widths() + [0, 1, 1, 2] + sage: NuDyckWord('110100','101010').widths() + [0, 0, 0, 1, 1, 2, 3] + sage: NuDyckWord('110111001101001000110111100011000', + ....: '101010101010101010101010101010101').widths() + [0, + 0, + 0, + 1, + 1, + 1, + 1, + 2, + 3, + 3, + 3, + 4, + 4, + 5, + 6, + 6, + 7, + 8, + 9, + 9, + 9, + 10, + 10, + 10, + 10, + 10, + 11, + 12, + 13, + 13, + 13, + 14, + 15, + 16] + """ + return self._path.width_vector() + + def horizontal_distance(self): + r""" + Return a list of how far each point is from `\nu`. + + EXAMPLES:: + + sage: NDW = NuDyckWord('10010100','00000111') + sage: NDW.horizontal_distance() + [5, 5, 4, 3, 3, 2, 2, 1, 0] + sage: NDW = NuDyckWord('10010100','00001011') + sage: NDW.horizontal_distance() + [4, 5, 4, 3, 3, 2, 2, 1, 0] + sage: NDW = NuDyckWord('10011001000','00100101001') + sage: NDW.horizontal_distance() + [2, 4, 3, 2, 3, 5, 4, 3, 3, 2, 1, 0] + + + """ + # Grab furthest east point at each height of nu + nu_points = list(self._nu.points()) + nu_easts = [max([i for i, j in nu_points if j == k]) + for k in range(self._nu.height()+1)] + + points = list(self._path.points()) + return [nu_easts[j] - i for i, j in points] + + def can_mutate(self, i): + """ + Return True/False based off if mutatable at height `i`. + + Can only mutate if an east step is followed by a north step at height + `i`. + + OUTPUT: + + - Whether we can mutate at height of `i`. + """ + if i > self.height() or i <= 0: + raise ValueError('Can\'t mutate above or below path') + + # Find the ith north step + level = 0 + ndw = self._list() + for j, k in enumerate(ndw): + if k == ndw_open_symbol: + level += 1 + if level == i: + break + if j > 0 and ndw[j-1] == ndw_close_symbol: + return j + return False + + def mutate(self, i): + r""" + return a new `\nu`-Dyck Word if possible. + + We mutate ``dEfg`` to ``dfEg`` where: + + - d is everything up until EN + + - f is everything between N and where horiz is same + + - g is everything after + """ + mutation_index = self.can_mutate(i) + if not mutation_index: + return None + + horiz = self.horizontal_distance() + # Find horiz in between East and North Step + horiz_num = horiz[mutation_index] + other_index = len(horiz) + for i in range(mutation_index + 1, len(horiz)): + if horiz[i] == horiz_num: + other_index = i + break + ndw = self._list() + d = ndw[0:mutation_index-1] + e = ndw[mutation_index:other_index] + f = ndw[other_index:] + return NuDyckWord(d + e + [ndw_close_symbol] + f, self._nu) + + +class NuDyckWords(Parent): + r""" + `\nu`-Dyck words. + + Given a lattice path `\nu` in the `\ZZ^2` grid starting at the origin + `(0,0)` consisting of North `N = (0,1)` and East `E = (1,0)` steps, a + `\nu`-Dyck path is a lattice path in the`\ZZ^2` grid starting at the + origin `(0,0)` and ending at the same coordinate as `\nu` such that it is + weakly above `\nu`. A `\nu`-Dyck word is the representation of a + `\nu`-Dyck path where a North step is represented by a 1 and an East step + is represented by a 0. + + INPUT: + + - ``nu`` -- the base lattice path. + + EXAMPLES:: + + sage: NDW = NuDyckWords('1010'); NDW + [1, 0, 1, 0] Dyck words + sage: [1,0,1,0] in NDW + True + sage: [1,1,0,0] in NDW + True + sage: [1,0,0,1] in NDW + False + sage: [0,1,0,1] in NDW + False + sage: NDW.cardinality() + 2 + """ + + Element = NuDyckWord + + def __init__(self, nu=tuple()): + """ + Intialize ``self``. + + EXAMPLES:: + + sage: TestSuite(NuDyckWords(nu=[1,0,1])).run() + """ + Parent.__init__(self, category=FiniteEnumeratedSets()) + + self._nu = to_word_path(nu) + if self._nu is None: + raise ValueError("Invalud nu supplied") + + # add options to class + class options(GlobalOptions): + r""" + Set and display the options for `\nu`-Dyck words. If no parameters + are set, then the function returns a copy of the options dictionary. + + The ``options`` to `\nu`-Dyck words can be accessed as the method + :meth:`NuDyckWords.options` of :class:`NuDyckWords` and + related parent classes. + + @OPTIONS + + EXAMPLES:: + + sage: ND = NuDyckWords('101') + sage: ND + [1, 0, 1] Dyck words + sage: ND.options + Current options for NuDyckWords + - ascii_art: pretty_output + - diagram_style: grid + - display: list + - latex_color: black + - latex_line_width_scalar: 2 + - latex_nu_options: rounded corners=1, color=red, line width=1 + - latex_points_color: black + - latex_show_grid: True + - latex_show_nu: True + - latex_show_points: False + - latex_tikz_scale: 1 + """ + NAME = 'NuDyckWords' + module = 'sage.combinat.nu_dyck_path' + display = dict(default="list", + description='Specifies how nu Dyck words should be printed', + values=dict(list='displayed as a list', + lattice='displayed on the lattice defined by ``diagram_style``'), + case_sensitive=False) + ascii_art = dict(default="pretty_output", + description='Specifies how the ascii art of nu Dyck words should be printed', + values=dict(pretty_output="Using pretty printing"), + alias=dict(pretty_print="pretty_output",), + case_sensitive=False) + diagram_style = dict(default="grid", + values=dict( + grid='printing as paths on a grid using N and E steps',), + alias={'N-E': 'grid'}, + case_sensitive=False) + latex_tikz_scale = dict(default=1, + description='The default value for the tikz scale when latexed', + checker=lambda x: True) # More trouble than it's worth to check + latex_line_width_scalar = dict(default=2, + description='The default value for the line width as a ' + 'multiple of the tikz scale when latexed', + checker=lambda x: True) # More trouble than it's worth to check + latex_color = dict(default="black", + description='The default value for the color when latexed', + checker=lambda x: isinstance(x, str)) + latex_show_points = dict(default=False, + description='The default value for showing points', + checker=lambda x: isinstance(x, bool)) + latex_points_color = dict(default='black', + description='The default value for path color.', + checker=lambda x: isinstance(x, str)) + latex_show_grid = dict(default=True, + description='The default value for showing grid', + checker=lambda x: isinstance(x, bool)) + latex_show_nu = dict(default=True, + description='The default value for showing nu', + checker=lambda x: isinstance(x, bool)) + latex_nu_options = dict(default='rounded corners=1, color=red, line width=1', + description='The default value for options for nu path', + checker=lambda x: isinstance(x, str)) + + def _element_constructor_(self, word): + """ + Construct an element of ``self``. + + EXAMPLES:: + + sage: NDW = NuDyckWords('101') + sage: elt = NDW('110'); elt + [1, 1, 0] + sage: elt.parent() is NDW + True + + """ + if isinstance(word, NuDyckWord) and word.parent() is self: + return word + return self.element_class(self, to_word_path(word)) + + def __contains__(self, x): + r""" + TESTS:: + + sage: NDW = NuDyckWords([1,0,1,1]) + sage: [1,1,0,1] in NDW + True + sage: [1,0,1,1] in NDW + True + sage: [0] in NDW + False + sage: [1, 0] in NDW + False + """ + return path_weakly_above_other(to_word_path(x), self._nu) + + def __eq__(self, other): + """ + Return equality. + """ + if type(other) != type(self): + return False + return self._nu == other._nu + + def __neq__(self, other): + """ + Return inequality. + """ + return not self.__eq__(other) + + def _repr_(self): + r""" + TESTS:: + + sage: NuDyckWords([1,0,1,1]) + [1, 0, 1, 1] Dyck words + """ + return "{nu} Dyck words".format(nu=list(self._nu)) + + def _cache_key(self): + """ + Return a cache key + """ + return str(self._nu) + + def _an_element_(self): + r""" + TESTS:: + + sage: NuDyckWords('101').an_element() + [1, 0, 1] + + """ + return self.element_class(self, self._nu) + + def __iter__(self): + """ + Iterate over ``self``. + + EXAMPLES:: + + sage: it = NuDyckWords('101010').__iter__() + sage: [i for i in it] + [[1, 1, 1, 0, 0, 0], + [1, 1, 0, 1, 0, 0], + [1, 1, 0, 0, 1, 0], + [1, 0, 1, 1, 0, 0], + [1, 0, 1, 0, 1, 0]] + + """ + P = Permutations(list(self._nu)) + for p in P: + if path_weakly_above_other(to_word_path(p), self._nu): + yield self.element_class(self, list(p)) + + def cardinality(self): + r""" + Return the number of `\nu`-Dyck words. + + EXAMPLES:: + + sage: NDW = NuDyckWords('101010'); NDW.cardinality() + 5 + sage: NDW = NuDyckWords('1010010'); NDW.cardinality() + 7 + sage: NDW = NuDyckWords('100100100'); NDW.cardinality() + 12 + """ + i = 0 + for i, j in enumerate(self): + pass + return Integer(i + 1) + + +def to_word_path(word): + r""" + Helper function which converts input into a word path over an appropriate + alphabet. + + INPUT: + + - ``word`` -- word to convert to wordpath + + OUTPUT: + + - A ``FiniteWordPath_north_east`` object. + + EXAMPLES:: + + sage: from sage.combinat.nu_dyck_word import to_word_path + sage: wp = to_word_path('NEENENEN'); wp + Path: 10010101 + sage: from sage.combinat.words.paths import FiniteWordPath_north_east + sage: isinstance(wp,FiniteWordPath_north_east) + True + sage: to_word_path('1001') + Path: 1001 + sage: to_word_path([0,1,0,0,1,0]) + Path: 010010 + """ + + # If we already have the object, don't worry + if isinstance(word, FiniteWordPath_north_east): + return word + + # If we have a Nu Dyck Path, return the path it contains + if isinstance(word, NuDyckWord): + return word.path() + + # if we have a string, convert to list + if isinstance(word, str): + word = map(replace_dyck_char, word) + + # By default "north" is first symbol, "east" is second symbol + P = WordPaths_north_east([ndw_open_symbol, ndw_close_symbol]) + + return P(word) + + +def path_weakly_above_other(path, other): + r""" + Tests if ``path`` is weakly above ``other``. + + A path `P` is wealy above another path `Q` if `P` and `Q` are the same + length and if any prefix of length `n` of `Q` contains more North steps + than the prefix of length `n` of `P`. + + INPUT: + + - ``path`` -- The path to verify is weakly above the other path. + + - ``other`` -- The other path to verify is weakly below the path. + + OUTPUT: + + - bool + + EXAMPLES:: + + sage: from sage.combinat.nu_dyck_word import path_weakly_above_other + sage: path_weakly_above_other('1001','0110') + False + sage: path_weakly_above_other('1001','0101') + True + sage: path_weakly_above_other('1111','0101') + False + sage: path_weakly_above_other('111100','0101') + False + """ + # Ensure we have word paths: + path = to_word_path(path) + other = to_word_path(other) + + # Must be same length and must have same height + if path.length() != other.length() or path.height() != other.height(): + return False + + # path is above other if height is always >= height of other + p_height = path.height_vector() + o_height = other.height_vector() + for i, j in enumerate(p_height): + if(o_height[i] > j): + return False + return True + + +def is_nu_path(path, nu): + r""" + Test if ``path`` is a `\nu`-Dyck word. + + A ``path`` is a `\nu`-Dyck word if ``path`` is weakly above the path of + `\nu`. + + .. SEEALSO:: :meth:`path_weakly_above_other` + """ + return path_weakly_above_other(path, nu) diff --git a/src/sage/combinat/nu_tamari_lattice.py b/src/sage/combinat/nu_tamari_lattice.py new file mode 100644 index 00000000000..5762ba8aae2 --- /dev/null +++ b/src/sage/combinat/nu_tamari_lattice.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +r""" +`\nu`-Tamari lattice + +A class of the `\nu`-Tamari lattice, see [PRV2017]_ for details. + +These lattices depend on one parameter `\nu` where `\nu` is a path of North +and East steps. + +The elements are :func:`\nu-Dyck paths` +which are weakly above `\nu`. + +To use the provided functionality, you should import `\nu`-Tamari lattices by +typing:: + + sage: from sage.combinat.nu_tamari_lattice import NuTamariLattice + +Then, :: + + sage: NuTamariLattice([1,1,1,0,0,1,1,0]) + Finite lattice containing 6 elements + sage: NuTamariLattice([0,0,0,1,1,0,0,1]) + Finite lattice containing 40 elements + +The classical **Tamari lattices** and the **Generalized Tamari lattices** are +special cases of this construction and are also available with this poset:: + + sage: NuTamariLattice([1,0,1,0,1,0]) + Finite lattice containing 5 elements + + sage: NuTamariLattice([1,0,0,1,0,0,1,0,0]) + Finite lattice containing 12 elements + +.. SEEALSO:: + + For more detailed information see :meth:`NuTamariLattice`. For more + information on the standard Tamari lattice see + :meth:`sage.combinat.tamari_lattices.TamariLattice`, + :meth:`sage.combinat.tamar_lattices.GeneralizedTamariLattice` +""" +# **************************************************************************** +# Copyright (C) 2020-2020 Aram Dermenjian +# +# Distributed under the terms of the GNU General Public License (GPL) +# +# This code is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# The full text of the GPL is available at: +# +# https://www.gnu.org/licenses/ +# **************************************************************************** +from sage.combinat.nu_dyck_word import NuDyckWords +from sage.combinat.posets.lattices import LatticePoset + + +def NuTamariLattice(nu): + r""" + Return the `\nu`-Tamari lattice. + + INPUT: + + - `\nu` -- a list of of 0s and 1s or a string of 0s and 1s. + + OUTPUT: + + - a finite lattice + + The elements of the lattice are + :func:`\nu-Dyck paths` weakly above + `\nu`. + + The usual :wikipedia:`Tamari lattice` is the special case + where `\nu = (NE)^h` where `h` is the height. + + Other special cases give the `m`-Tamari lattices studied in [BMFPR]_. + + EXAMPLES:: + + sage: from sage.combinat.nu_tamari_lattices import NuTamariLattice + sage: NuTamariLattice([1,0,1,0,0,1,0]) + Finite lattice containing 7 elements + sage: NuTamariLattice([1,0,1,0,1,0]) + Finite lattice containing 5 elements + sage: NuTamariLattice([1,0,1,0,1,0,1,0]) + Finite lattice containing 14 elements + sage: NuTamariLattice([1,0,1,0,1,0,0,0,1]) + Finite lattice containing 24 elements + + """ + + NDW = NuDyckWords(nu) + + covers = [] + elements = [] + height = NDW[0].height() + for ndw in NDW: + elements.append(ndw) + for i in range(1, height+1): + new_ndw = ndw.mutate(i) + if new_ndw is not None: + covers.append([ndw, new_ndw]) + return LatticePoset([elements, covers]) diff --git a/src/sage/combinat/words/paths.py b/src/sage/combinat/words/paths.py index 2a847391252..b0f0d8c1427 100644 --- a/src/sage/combinat/words/paths.py +++ b/src/sage/combinat/words/paths.py @@ -1781,6 +1781,25 @@ def height(self): """ return self.ymax() - self.ymin() + def height_vector(self): + r""" + Returns the height at each point. + """ + h_vec = [] + y_min = None + y_max = None + for (_, y) in self.points(): + if y_min is None: + y_min = y + y_max = y + else: + if y > y_max: + y_max = y + if y < y_min: + y_min = y + h_vec.append(y_max - y_min) + return h_vec + def width(self): r""" Returns the width of self. @@ -1822,6 +1841,25 @@ def width(self): """ return self.xmax() - self.xmin() + def width_vector(self): + r""" + Returns the width at each point. + """ + w_vec = [] + x_min = None + x_max = None + for (x, _) in self.points(): + if x_min is None: + x_min = x + x_max = x + else: + if x > x_max: + x_max = x + if x < x_min: + x_min = x + w_vec.append(x_max - x_min) + return w_vec + def xmin(self): r""" Returns the minimum of the x-coordinates of the path. From 1cdf03896235ad84c8b524d5d3293d20a06c763e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 7 May 2022 20:43:07 +0200 Subject: [PATCH 017/116] reviewer commit --- src/sage/combinat/nu_dyck_word.py | 177 +++++++------------------ src/sage/combinat/nu_tamari_lattice.py | 6 +- 2 files changed, 52 insertions(+), 131 deletions(-) diff --git a/src/sage/combinat/nu_dyck_word.py b/src/sage/combinat/nu_dyck_word.py index 07b39d3e965..633ddf7bd44 100644 --- a/src/sage/combinat/nu_dyck_word.py +++ b/src/sage/combinat/nu_dyck_word.py @@ -8,12 +8,12 @@ - Aram Dermenjian (2020-09-26) -This file is based off the class ``DyckWords`` written by Mke Hansen, Dan +This file is based off the class +:func:`DyckWords` written by Mike Hansen, Dan Drake, Florent Hivert, Christian Stump, Mike Zabrocki, Jean--Baptiste Priez and Travis Scrimshaw """ - # **************************************************************************** # Copyright (C) 2020 Aram Dermenjian , # @@ -100,10 +100,9 @@ def replace_dyck_char(x): """ if x == '(' or x == 'N' or x == str(ndw_open_symbol): return ndw_open_symbol - elif x == ')' or x == 'E' or x == str(ndw_close_symbol): + if x == ')' or x == 'E' or x == str(ndw_close_symbol): return ndw_close_symbol - else: - raise ValueError + raise ValueError def replace_dyck_symbol(x, open_char='N', close_char='E'): @@ -148,10 +147,9 @@ def replace_dyck_symbol(x, open_char='N', close_char='E'): """ if x == ndw_open_symbol: return open_char - elif x == ndw_close_symbol: + if x == ndw_close_symbol: return close_char - else: - raise ValueError + raise ValueError class NuDyckWord(CombinatorialElement): @@ -225,7 +223,6 @@ def __classcall_private__(cls, dw=None, nu=None, **kwargs): sage: NuDyckWord('010','010') [0, 1, 0] """ - # if dw is none, then we might have a normal Dyck word if dw is None: from sage.combinat.dyck_word import DyckWord @@ -250,7 +247,7 @@ def __init__(self, parent, dw, latex_options={}): self._path = to_word_path(dw) if parent is None: - raise ValueError("Need Parent object") + raise ValueError("need parent object") self._nu = parent._nu @@ -460,7 +457,7 @@ def _repr_list(self): """ return str(list(self._path)) - def _repr_lattice(self, type=None, labelling=None): + def _repr_lattice(self, typ=None, labelling=None): r""" See :meth:`pretty_print()`. @@ -487,12 +484,12 @@ def _repr_lattice(self, type=None, labelling=None): """ - if type is None: - type = self.parent().options.diagram_style - if type == "grid": - type = "N-E" + if typ is None: + typ = self.parent().options.diagram_style + if typ == "grid": + typ = "N-E" - if type == "N-E": + if typ == "N-E": path_length = self._path.length() height = self._path.height() width = self._path.width() @@ -505,7 +502,7 @@ def _repr_lattice(self, type=None, labelling=None): else: if len(labelling) != height: raise ValueError( - "The given labelling has the wrong length. {num} needed".format(num=height)) + "the given labelling has the wrong length: {num} needed".format(num=height)) labels = [str(label) for label in labelling] max_length = max(len(label) for label in labels) labels = [lbl.rjust(max_length + 1) for lbl in labels] @@ -519,11 +516,11 @@ def _repr_lattice(self, type=None, labelling=None): cur_nu_pos = rev_nu_path.index(ndw_open_symbol) if cur_pos > 0: ts += " " * (width - cur_pos) - ts += " _" + "__" * (cur_pos-1) + ts += " _" + "__" * (cur_pos - 1) ts += "_\n" # Middle Lines - for i in range(height-1): + for i in range(height - 1): old_pos = cur_pos old_nu_pos = cur_nu_pos cur_pos = rev_path.index(ndw_open_symbol, cur_pos + 1) @@ -536,7 +533,7 @@ def _repr_lattice(self, type=None, labelling=None): if old_pos >= 0: ts += "x " * (old_pos - old_nu_pos) ts += " ." * (old_nu_pos - i) - ts += labels[height-i-1] + ts += labels[height - i - 1] ts += "\n" # Final line @@ -547,8 +544,7 @@ def _repr_lattice(self, type=None, labelling=None): ts += labels[0] ts += "\n" return ts - else: - raise ValueError("The given type (=%s) is not valid." % type) + raise ValueError(f"the given type (={typ}) is not valid") def _ascii_art_(self): r""" @@ -691,6 +687,7 @@ def _latex_(self): A latex representation of ``self`` using the tikzpicture package. EXAMPLES:: + sage: NDW = NuDyckWord('010','010') sage: NDW.set_latex_options({"show_points":True}) sage: latex(NDW) @@ -772,7 +769,7 @@ def plot(self, **kwds): def path(self): r""" - Return the underlying path object + Return the underlying path object. EXAMPLES:: @@ -826,7 +823,7 @@ def length(self): def points(self): r""" - Returns an iter with the points on the `\nu`-Dyck path. + Return an iterator for the points on the `\nu`-Dyck path. EXAMPLES:: @@ -887,42 +884,6 @@ def heights(self): [0, 0, 1, 1] sage: NuDyckWord('110100','101010').heights() [0, 1, 2, 2, 3, 3, 3] - sage: NuDyckWord('110111001101001000110111100011000', - ....: '101010101010101010101010101010101').heights() - [0, - 1, - 2, - 2, - 3, - 4, - 5, - 5, - 5, - 6, - 7, - 7, - 8, - 8, - 8, - 9, - 9, - 9, - 9, - 10, - 11, - 11, - 12, - 13, - 14, - 15, - 15, - 15, - 15, - 16, - 17, - 17, - 17, - 17] """ return self._path.height_vector() @@ -944,42 +905,6 @@ def widths(self): [0, 1, 1, 2] sage: NuDyckWord('110100','101010').widths() [0, 0, 0, 1, 1, 2, 3] - sage: NuDyckWord('110111001101001000110111100011000', - ....: '101010101010101010101010101010101').widths() - [0, - 0, - 0, - 1, - 1, - 1, - 1, - 2, - 3, - 3, - 3, - 4, - 4, - 5, - 6, - 6, - 7, - 8, - 9, - 9, - 9, - 10, - 10, - 10, - 10, - 10, - 11, - 12, - 13, - 13, - 13, - 14, - 15, - 16] """ return self._path.width_vector() @@ -998,20 +923,18 @@ def horizontal_distance(self): sage: NDW = NuDyckWord('10011001000','00100101001') sage: NDW.horizontal_distance() [2, 4, 3, 2, 3, 5, 4, 3, 3, 2, 1, 0] - - """ # Grab furthest east point at each height of nu - nu_points = list(self._nu.points()) - nu_easts = [max([i for i, j in nu_points if j == k]) - for k in range(self._nu.height()+1)] + nu_points = self._nu.points() + nu_easts = [max(i for i, j in nu_points if j == k) + for k in range(self._nu.height() + 1)] points = list(self._path.points()) return [nu_easts[j] - i for i, j in points] - def can_mutate(self, i): + def can_mutate(self, i) -> bool: """ - Return True/False based off if mutatable at height `i`. + Return True/False based off if mutable at height `i`. Can only mutate if an east step is followed by a north step at height `i`. @@ -1021,7 +944,7 @@ def can_mutate(self, i): - Whether we can mutate at height of `i`. """ if i > self.height() or i <= 0: - raise ValueError('Can\'t mutate above or below path') + raise ValueError('cannot mutate above or below path') # Find the ith north step level = 0 @@ -1031,21 +954,26 @@ def can_mutate(self, i): level += 1 if level == i: break - if j > 0 and ndw[j-1] == ndw_close_symbol: + if j > 0 and ndw[j - 1] == ndw_close_symbol: return j return False def mutate(self, i): r""" - return a new `\nu`-Dyck Word if possible. + Return a new `\nu`-Dyck Word if possible. - We mutate ``dEfg`` to ``dfEg`` where: + If at height `i` we have an east step E meeting a north step N then we + calculate all horizontal distances from this point until we find + the first point that has the same horizontal distance to `\nu`. We let - - d is everything up until EN + - d is everything up until EN (not including EN) - - f is everything between N and where horiz is same + - f be everything between N and the point with the same horizontal + distance (including N) - - g is everything after + - g is everything after f + + .. SEEALSO:: :meth:`can_mutate` """ mutation_index = self.can_mutate(i) if not mutation_index: @@ -1060,7 +988,7 @@ def mutate(self, i): other_index = i break ndw = self._list() - d = ndw[0:mutation_index-1] + d = ndw[0:mutation_index - 1] e = ndw[mutation_index:other_index] f = ndw[other_index:] return NuDyckWord(d + e + [ndw_close_symbol] + f, self._nu) @@ -1100,7 +1028,7 @@ class NuDyckWords(Parent): Element = NuDyckWord - def __init__(self, nu=tuple()): + def __init__(self, nu=()): """ Intialize ``self``. @@ -1112,7 +1040,7 @@ def __init__(self, nu=tuple()): self._nu = to_word_path(nu) if self._nu is None: - raise ValueError("Invalud nu supplied") + raise ValueError("invalid nu supplied") # add options to class class options(GlobalOptions): @@ -1199,13 +1127,12 @@ def _element_constructor_(self, word): [1, 1, 0] sage: elt.parent() is NDW True - """ if isinstance(word, NuDyckWord) and word.parent() is self: return word return self.element_class(self, to_word_path(word)) - def __contains__(self, x): + def __contains__(self, x) -> bool: r""" TESTS:: @@ -1225,7 +1152,7 @@ def __eq__(self, other): """ Return equality. """ - if type(other) != type(self): + if not isinstance(other, NuDyckWords): return False return self._nu == other._nu @@ -1256,7 +1183,6 @@ def _an_element_(self): sage: NuDyckWords('101').an_element() [1, 0, 1] - """ return self.element_class(self, self._nu) @@ -1273,10 +1199,8 @@ def __iter__(self): [1, 1, 0, 0, 1, 0], [1, 0, 1, 1, 0, 0], [1, 0, 1, 0, 1, 0]] - """ - P = Permutations(list(self._nu)) - for p in P: + for p in Permutations(list(self._nu)): if path_weakly_above_other(to_word_path(p), self._nu): yield self.element_class(self, list(p)) @@ -1293,9 +1217,7 @@ def cardinality(self): sage: NDW = NuDyckWords('100100100'); NDW.cardinality() 12 """ - i = 0 - for i, j in enumerate(self): - pass + i = len(list(self)) return Integer(i + 1) @@ -1325,7 +1247,6 @@ def to_word_path(word): sage: to_word_path([0,1,0,0,1,0]) Path: 010010 """ - # If we already have the object, don't worry if isinstance(word, FiniteWordPath_north_east): return word @@ -1344,9 +1265,9 @@ def to_word_path(word): return P(word) -def path_weakly_above_other(path, other): +def path_weakly_above_other(path, other) -> bool: r""" - Tests if ``path`` is weakly above ``other``. + Test if ``path`` is weakly above ``other``. A path `P` is wealy above another path `Q` if `P` and `Q` are the same length and if any prefix of length `n` of `Q` contains more North steps @@ -1360,7 +1281,7 @@ def path_weakly_above_other(path, other): OUTPUT: - - bool + bool EXAMPLES:: @@ -1391,7 +1312,7 @@ def path_weakly_above_other(path, other): return True -def is_nu_path(path, nu): +def is_nu_path(path, nu) -> bool: r""" Test if ``path`` is a `\nu`-Dyck word. diff --git a/src/sage/combinat/nu_tamari_lattice.py b/src/sage/combinat/nu_tamari_lattice.py index 5762ba8aae2..f6cb83bbd5b 100644 --- a/src/sage/combinat/nu_tamari_lattice.py +++ b/src/sage/combinat/nu_tamari_lattice.py @@ -36,7 +36,7 @@ For more detailed information see :meth:`NuTamariLattice`. For more information on the standard Tamari lattice see :meth:`sage.combinat.tamari_lattices.TamariLattice`, - :meth:`sage.combinat.tamar_lattices.GeneralizedTamariLattice` + :meth:`sage.combinat.tamari_lattices.GeneralizedTamariLattice` """ # **************************************************************************** # Copyright (C) 2020-2020 Aram Dermenjian @@ -79,7 +79,7 @@ def NuTamariLattice(nu): EXAMPLES:: - sage: from sage.combinat.nu_tamari_lattices import NuTamariLattice + sage: from sage.combinat.nu_tamari_lattice import NuTamariLattice sage: NuTamariLattice([1,0,1,0,0,1,0]) Finite lattice containing 7 elements sage: NuTamariLattice([1,0,1,0,1,0]) @@ -98,7 +98,7 @@ def NuTamariLattice(nu): height = NDW[0].height() for ndw in NDW: elements.append(ndw) - for i in range(1, height+1): + for i in range(1, height + 1): new_ndw = ndw.mutate(i) if new_ndw is not None: covers.append([ndw, new_ndw]) From 45ac1d12adf984889700b52357bc1288e131d07f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 7 May 2022 21:22:13 +0200 Subject: [PATCH 018/116] adding doctests in words.paths --- src/sage/combinat/words/paths.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/words/paths.py b/src/sage/combinat/words/paths.py index b0f0d8c1427..3a6ac3ef29b 100644 --- a/src/sage/combinat/words/paths.py +++ b/src/sage/combinat/words/paths.py @@ -1783,12 +1783,19 @@ def height(self): def height_vector(self): r""" - Returns the height at each point. + Return the height at each point. + + EXAMPLES:: + + sage: Paths = WordPaths('ab', steps=[(1,0),(0,1)]) + sage: p = Paths('abbba') + sage: p.height_vector() + [0, 0, 1, 2, 3, 3] """ h_vec = [] y_min = None y_max = None - for (_, y) in self.points(): + for _, y in self.points(): if y_min is None: y_min = y y_max = y @@ -1843,12 +1850,19 @@ def width(self): def width_vector(self): r""" - Returns the width at each point. + Return the width at each point. + + EXAMPLES:: + + sage: Paths = WordPaths('ab', steps=[(1,0),(0,1)]) + sage: p = Paths('abbba') + sage: p.width_vector() + [0, 1, 1, 1, 1, 2] """ w_vec = [] x_min = None x_max = None - for (x, _) in self.points(): + for x, _ in self.points(): if x_min is None: x_min = x x_max = x From 71c60d6fb5adcfbfe29db98837bedb458ae0c776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 7 May 2022 21:38:33 +0200 Subject: [PATCH 019/116] fix back the doctests --- src/sage/combinat/nu_dyck_word.py | 53 ++++++++++++++----------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/src/sage/combinat/nu_dyck_word.py b/src/sage/combinat/nu_dyck_word.py index 633ddf7bd44..dad59c801b1 100644 --- a/src/sage/combinat/nu_dyck_word.py +++ b/src/sage/combinat/nu_dyck_word.py @@ -255,27 +255,27 @@ def __init__(self, parent, dw, latex_options={}): def _list(self): """ - Return list of self + Return list of ``self``. """ return list(self._path) def __eq__(self, other): """ - Return if two paths are equal + Return if two paths are equal. """ - if type(other) != type(self): + if not isinstance(other, NuDyckWord): return False return self._path == other._path and self._nu == other._nu def __neq__(self, other): """ - Return if two paths are not equal + Return if two paths are not equal. """ return not self.__eq__(other) def __le__(self, other): """ - Returns if one path is included in another + Return if one path is included in another. """ if self._nu == other._nu: return path_weakly_above_other(other._path, self._path) @@ -457,13 +457,13 @@ def _repr_list(self): """ return str(list(self._path)) - def _repr_lattice(self, typ=None, labelling=None): + def _repr_lattice(self, style=None, labelling=None): r""" See :meth:`pretty_print()`. TESTS:: - sage: print(NuDyckWord('00011001000100','00011001000100')._repr_lattice(type='N-E', labelling=[1,2,3,4])) + sage: print(NuDyckWord('00011001000100','00011001000100')._repr_lattice(style='N-E', labelling=[1,2,3,4])) ____ _____| . . 4 ___| . . . . . 3 @@ -481,15 +481,13 @@ def _repr_lattice(self, typ=None, labelling=None): ___|x |x x x |x x . - - """ - if typ is None: - typ = self.parent().options.diagram_style - if typ == "grid": - typ = "N-E" + if style is None: + style = self.parent().options.diagram_style + if style == "grid": + style = "N-E" - if typ == "N-E": + if style == "N-E": path_length = self._path.length() height = self._path.height() width = self._path.width() @@ -501,8 +499,7 @@ def _repr_lattice(self, typ=None, labelling=None): labels = [" "] * height else: if len(labelling) != height: - raise ValueError( - "the given labelling has the wrong length: {num} needed".format(num=height)) + raise ValueError(f"the given labelling has the wrong length: {height} needed") labels = [str(label) for label in labelling] max_length = max(len(label) for label in labels) labels = [lbl.rjust(max_length + 1) for lbl in labels] @@ -544,7 +541,7 @@ def _repr_lattice(self, typ=None, labelling=None): ts += labels[0] ts += "\n" return ts - raise ValueError(f"the given type (={typ}) is not valid") + raise ValueError(f"the given style (={style}) is not valid") def _ascii_art_(self): r""" @@ -580,11 +577,11 @@ def __str__(self): """ return "".join(map(replace_dyck_symbol, list(self._path))) - def pretty_print(self, type=None, labelling=None): + def pretty_print(self, style=None, labelling=None): r""" Display a NuDyckWord as a lattice path in the `\ZZ^2` grid. - If the ``type`` is "N-E", then a cell below the diagonal is + If the ``style`` is "N-E", then a cell below the diagonal is indicated by a period, whereas a cell below the path but above the diagonal is indicated by an x. If a list of labels is included, they are displayed along the vertical edges of the @@ -592,15 +589,15 @@ def pretty_print(self, type=None, labelling=None): INPUT: - - ``type`` -- (default: ``None``) can either be: + - ``style`` -- (default: ``None``) can either be: - ``None`` to use the option default - "N-E" to show ``self`` as a path of north and east steps, or - - ``labelling`` -- (if type is "N-E") a list of labels assigned to + - ``labelling`` -- (if style is "N-E") a list of labels assigned to the up steps in ``self``. - - ``underpath`` -- (if type is "N-E", default: ``True``) If ``True``, + - ``underpath`` -- (if style is "N-E", default: ``True``) If ``True``, an ``x`` to show the boxes between `\nu` and the `\nu`-Dyck Path. EXAMPLES:: @@ -678,7 +675,7 @@ def pretty_print(self, type=None, labelling=None): sage: NuDyckWord().pretty_print() . """ - print(self._repr_lattice(type, labelling)) + print(self._repr_lattice(style, labelling)) pp = pretty_print @@ -925,7 +922,7 @@ def horizontal_distance(self): [2, 4, 3, 2, 3, 5, 4, 3, 3, 2, 1, 0] """ # Grab furthest east point at each height of nu - nu_points = self._nu.points() + nu_points = list(self._nu.points()) nu_easts = [max(i for i, j in nu_points if j == k) for k in range(self._nu.height() + 1)] @@ -1217,8 +1214,7 @@ def cardinality(self): sage: NDW = NuDyckWords('100100100'); NDW.cardinality() 12 """ - i = len(list(self)) - return Integer(i + 1) + return Integer(len([1 for _ in self.__iter__()])) def to_word_path(word): @@ -1306,10 +1302,7 @@ def path_weakly_above_other(path, other) -> bool: # path is above other if height is always >= height of other p_height = path.height_vector() o_height = other.height_vector() - for i, j in enumerate(p_height): - if(o_height[i] > j): - return False - return True + return all(p_h >= o_h for p_h, o_h in zip(p_height, o_height)) def is_nu_path(path, nu) -> bool: From c7fa2b09d7966b13a20c84443e1d4ce3e069fbe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 8 May 2022 09:46:06 +0200 Subject: [PATCH 020/116] add some doctests and type annotations --- src/sage/combinat/nu_dyck_word.py | 86 ++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 25 deletions(-) diff --git a/src/sage/combinat/nu_dyck_word.py b/src/sage/combinat/nu_dyck_word.py index dad59c801b1..71b459c4b10 100644 --- a/src/sage/combinat/nu_dyck_word.py +++ b/src/sage/combinat/nu_dyck_word.py @@ -28,7 +28,7 @@ # # https://www.gnu.org/licenses/ # **************************************************************************** - +from __future__ import annotations from sage.structure.element import Element from sage.rings.integer import Integer from sage.combinat.combinat import CombinatorialElement @@ -105,7 +105,7 @@ def replace_dyck_char(x): raise ValueError -def replace_dyck_symbol(x, open_char='N', close_char='E'): +def replace_dyck_symbol(x, open_char='N', close_char='E') -> str: r""" A map sending ``ndw_open_symbol`` to ``open_char`` and ``ndw_close_symbol`` to ``close_char``, and raising an error on any input other than @@ -179,25 +179,17 @@ class NuDyckWord(CombinatorialElement): sage: dw.height() 2 - :: - sage: dw = NuDyckWord('1010',[1,0,0,1]); dw [1, 0, 1, 0] - :: - sage: dw = NuDyckWord('NENE',[1,0,0,1]); dw [1, 0, 1, 0] - :: - sage: NuDyckWord([1,0,1,0],[1,0,0,1]).pretty_print() __ _|x | . . - :: - sage: from sage.combinat.nu_dyck_word import update_ndw_symbols sage: update_ndw_symbols(0,1) sage: dw = NuDyckWord('0101001','0110010'); dw @@ -209,7 +201,6 @@ class NuDyckWord(CombinatorialElement): _|x . | . . . sage: update_ndw_symbols(1,0) - """ @staticmethod def __classcall_private__(cls, dw=None, nu=None, **kwargs): @@ -242,7 +233,7 @@ def __classcall_private__(cls, dw=None, nu=None, **kwargs): raise ValueError("invalid nu-Dyck word") - def __init__(self, parent, dw, latex_options={}): + def __init__(self, parent, dw, latex_options=None): Element.__init__(self, parent) self._path = to_word_path(dw) @@ -251,17 +242,36 @@ def __init__(self, parent, dw, latex_options={}): self._nu = parent._nu + if latex_options is None: + latex_options = {} self._latex_options = dict(latex_options) def _list(self): """ Return list of ``self``. + + EXAMPLES:: + + sage: w = NuDyckWord('110100','101010') + sage: w._list() + [1, 1, 0, 1, 0, 0] """ return list(self._path) def __eq__(self, other): """ Return if two paths are equal. + + EXAMPLES:: + + sage: u = NuDyckWord('010','010') + sage: w = NuDyckWord('110100','101010') + sage: w == w + True + sage: u == w + False + sage: u == 4 + False """ if not isinstance(other, NuDyckWord): return False @@ -270,6 +280,17 @@ def __eq__(self, other): def __neq__(self, other): """ Return if two paths are not equal. + + EXAMPLES:: + + sage: u = NuDyckWord('010','010') + sage: w = NuDyckWord('110100','101010') + sage: w != w + False + sage: u != w + True + sage: u != 4 + True """ return not self.__eq__(other) @@ -283,13 +304,13 @@ def __le__(self, other): def __lt__(self, other): """ - Returns if one path is strictly included in another + Return if one path is strictly included in another """ return self.__le__(other) and not self.__eq__(other) def __ge__(self, other): """ - Returns if one path is included in another + Return if one path is included in another """ if self._nu == other._nu: return path_weakly_above_other(self._path, other._path) @@ -297,18 +318,33 @@ def __ge__(self, other): def __gt__(self, other): """ - Returns if one path is strictly included in another + Return if one path is strictly included in another """ return self.__ge__(other) and not self.__eq__(other) - def _cache_key(self): + def _cache_key(self) -> tuple: """ - Return a cache key + Return a cache key for ``self``. + + EXAMPLES:: + + sage: u = NuDyckWord('010','010') + sage: u._cache_key() + (0, 1, 0, 0, 1, 0) + """ + return tuple(self._path) + tuple(self._nu) + + def __hash__(self) -> int: """ - return str(self._path) + "-" + str(self._nu) + Return a hash for ``self``. - def __hash__(self): - return hash(''.join([str(i) for i in self._list()])) + EXAMPLES:: + + sage: u = NuDyckWord('010','010') + sage: hash(u) # random + -4577085166836515071 + """ + return hash(''.join(str(i) for i in self._list())) def set_latex_options(self, D): r""" @@ -356,7 +392,7 @@ def set_latex_options(self, D): for opt in D: self._latex_options[opt] = D[opt] - def latex_options(self): + def latex_options(self) -> dict: r""" Return the latex options for use in the ``_latex_`` function as a dictionary. @@ -423,7 +459,7 @@ def latex_options(self): d["nu_options"] = opts.latex_nu_options return d - def _repr_(self): + def _repr_(self) -> str: r""" Return a string representation of ``self`` depending on :meth:`NuDyckWords.options`. @@ -444,7 +480,7 @@ def _repr_(self): """ return self.parent().options._dispatch(self, '_repr_', 'display') - def _repr_list(self): + def _repr_list(self) -> str: r""" Return a string representation of ``self`` as a list. @@ -563,7 +599,7 @@ def _ascii_art_(self): ret = self._repr_lattice() return AsciiArt(ret.splitlines(), baseline=0) - def __str__(self): + def __str__(self) -> str: r""" Return a string consisting of N and E steps corresponding to the `\nu`-Dyck word. @@ -575,7 +611,7 @@ def __str__(self): sage: str(NuDyckWord('101010','100110')) 'NENENE' """ - return "".join(map(replace_dyck_symbol, list(self._path))) + return "".join(replace_dyck_symbol(let) for let in self._path) def pretty_print(self, style=None, labelling=None): r""" From 3d170c96c918007ed6216ae7810e3341e1b4402f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 15 May 2022 08:46:34 +0200 Subject: [PATCH 021/116] adding more doctests --- src/sage/combinat/nu_dyck_word.py | 98 +++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 24 deletions(-) diff --git a/src/sage/combinat/nu_dyck_word.py b/src/sage/combinat/nu_dyck_word.py index 71b459c4b10..e8fdb669416 100644 --- a/src/sage/combinat/nu_dyck_word.py +++ b/src/sage/combinat/nu_dyck_word.py @@ -47,12 +47,20 @@ def update_ndw_symbols(os, cs): r""" - A way to alter the open and close symbols from sage + A way to alter the open and close symbols from sage. INPUT: - - ``os`` -- The open symbol - - ``cs`` -- The close symbol + - ``os`` -- the open symbol + - ``cs`` -- the close symbol + + EXAMPLES:: + + sage: from sage.combinat.nu_dyck_word import update_ndw_symbols + sage: update_ndw_symbols(0,1) + sage: dw = NuDyckWord('0101001','0110010'); dw + [0, 1, 0, 1, 0, 0, 1] + sage: update_ndw_symbols(1,0) """ global ndw_open_symbol global ndw_close_symbol @@ -234,6 +242,9 @@ def __classcall_private__(cls, dw=None, nu=None, **kwargs): raise ValueError("invalid nu-Dyck word") def __init__(self, parent, dw, latex_options=None): + """ + Initialize a nu-Dyck word. + """ Element.__init__(self, parent) self._path = to_word_path(dw) @@ -486,7 +497,7 @@ def _repr_list(self) -> str: TESTS:: - sage: NuDyckWord([1,1,0],[1,0,1]) + sage: NuDyckWord([1,1,0],[1,0,1]) # indirect doctest [1, 1, 0] sage: NuDyckWord('NNEE','NENE') [1, 1, 0, 0] @@ -965,7 +976,7 @@ def horizontal_distance(self): points = list(self._path.points()) return [nu_easts[j] - i for i, j in points] - def can_mutate(self, i) -> bool: + def can_mutate(self, i) -> bool | int: """ Return True/False based off if mutable at height `i`. @@ -974,7 +985,23 @@ def can_mutate(self, i) -> bool: OUTPUT: - - Whether we can mutate at height of `i`. + Whether we can mutate at height of `i`. + + EXAMPLES:: + + sage: NDW = NuDyckWord('10010100','00000111') + sage: NDW.can_mutate(1) + False + sage: NDW.can_mutate(3) + 5 + + TESTS:: + + sage: NDW = NuDyckWord('10010100','00000111') + sage: NDW.can_mutate(33) + Traceback (most recent call last): + ... + ValueError: cannot mutate above or below path """ if i > self.height() or i <= 0: raise ValueError('cannot mutate above or below path') @@ -991,7 +1018,7 @@ def can_mutate(self, i) -> bool: return j return False - def mutate(self, i): + def mutate(self, i) -> None | NuDyckWord: r""" Return a new `\nu`-Dyck Word if possible. @@ -1007,6 +1034,13 @@ def mutate(self, i): - g is everything after f .. SEEALSO:: :meth:`can_mutate` + + EXAMPLES:: + + sage: NDW = NuDyckWord('10010100','00000111') + sage: NDW.mutate(1) + sage: NDW.mutate(3) + [1, 0, 0, 1, 1, 0, 0, 0] """ mutation_index = self.can_mutate(i) if not mutation_index: @@ -1184,6 +1218,16 @@ def __contains__(self, x) -> bool: def __eq__(self, other): """ Return equality. + + TESTS:: + + sage: A = NuDyckWords([1,0,1,1]) + sage: B = NuDyckWords([1,0,1,1]) + sage: C = NuDyckWords([1,0,1,1,1]) + sage: A == B + True + sage: A == C + False """ if not isinstance(other, NuDyckWords): return False @@ -1192,21 +1236,36 @@ def __eq__(self, other): def __neq__(self, other): """ Return inequality. + + TESTS:: + + sage: A = NuDyckWords([1,0,1,1]) + sage: B = NuDyckWords([1,0,1,1]) + sage: C = NuDyckWords([1,0,1,1,1]) + sage: A != B + False + sage: A != C + True """ return not self.__eq__(other) - def _repr_(self): + def _repr_(self) -> str: r""" TESTS:: sage: NuDyckWords([1,0,1,1]) [1, 0, 1, 1] Dyck words """ - return "{nu} Dyck words".format(nu=list(self._nu)) + return f"{list(self._nu)} Dyck words" - def _cache_key(self): + def _cache_key(self) -> str: """ Return a cache key + + TESTS:: + + sage: NuDyckWords([1,0,1,1])._cache_key() + '1011' """ return str(self._nu) @@ -1223,6 +1282,8 @@ def __iter__(self): """ Iterate over ``self``. + .. TODO:: make a better iterator. + EXAMPLES:: sage: it = NuDyckWords('101010').__iter__() @@ -1255,8 +1316,9 @@ def cardinality(self): def to_word_path(word): r""" - Helper function which converts input into a word path over an appropriate - alphabet. + Convert input into a word path over an appropriate alphabet. + + Helper function. INPUT: @@ -1339,15 +1401,3 @@ def path_weakly_above_other(path, other) -> bool: p_height = path.height_vector() o_height = other.height_vector() return all(p_h >= o_h for p_h, o_h in zip(p_height, o_height)) - - -def is_nu_path(path, nu) -> bool: - r""" - Test if ``path`` is a `\nu`-Dyck word. - - A ``path`` is a `\nu`-Dyck word if ``path`` is weakly above the path of - `\nu`. - - .. SEEALSO:: :meth:`path_weakly_above_other` - """ - return path_weakly_above_other(path, nu) From 8f594f4dcc4b97f947d713f1a23ee5f55d2920e0 Mon Sep 17 00:00:00 2001 From: Marc Mezzarobba Date: Mon, 16 May 2022 07:28:42 +0200 Subject: [PATCH 022/116] #33804: fix NumberFieldElement._symbolic_()... ...for "complicated enough" number fields with an embedding into AA --- .../rings/number_field/number_field_element.pyx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/number_field/number_field_element.pyx b/src/sage/rings/number_field/number_field_element.pyx index 21e19618896..7c503abb7e2 100644 --- a/src/sage/rings/number_field/number_field_element.pyx +++ b/src/sage/rings/number_field/number_field_element.pyx @@ -2927,6 +2927,17 @@ cdef class NumberFieldElement(FieldElement): sage: SR(b) 1/8*(sqrt(4*(1/9*sqrt(109)*sqrt(3) + 2)^(1/3) - 4/3/(1/9*sqrt(109)*sqrt(3) + 2)^(1/3) + 17) + 5)^3 + 1/2*sqrt(4*(1/9*sqrt(109)*sqrt(3) + 2)^(1/3) - 4/3/(1/9*sqrt(109)*sqrt(3) + 2)^(1/3) + 17) + 5/2 + TESTS: + + :trac:`33804`:: + + sage: Pol. = QQ[] + sage: p = x^8 + x^7 - 9*x^6 - 3*x^5 - 6*x^4 + x^3 - 14*x^2 + 2*x + 2 + sage: rt = sorted(p.roots(AA, multiplicities=False))[1] + sage: K. = NumberField(p, embedding=rt) + sage: SR(a) + -0.3056815681115094? + """ K = self._parent.fraction_field() @@ -2952,7 +2963,7 @@ cdef class NumberFieldElement(FieldElement): return a # Once #17516 gets fixed, the next three lines can be dropped # and the remaining lines be simplified to undo df03633. - b = embedding.im_gens()[0].radical_expression() + b = embedding(K.gen()).radical_expression() if b.parent() == SR: return self.polynomial()(b) return SR(a) From b6c2839696f4bd78d7ce647e1b8c799f91fa1aff Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Tue, 17 May 2022 09:38:02 +0100 Subject: [PATCH 023/116] Add more doctests and make iterator more efficient --- src/sage/combinat/nu_dyck_word.py | 201 ++++++++++++++++++++++++------ 1 file changed, 162 insertions(+), 39 deletions(-) diff --git a/src/sage/combinat/nu_dyck_word.py b/src/sage/combinat/nu_dyck_word.py index e8fdb669416..baf5f9b830e 100644 --- a/src/sage/combinat/nu_dyck_word.py +++ b/src/sage/combinat/nu_dyck_word.py @@ -35,8 +35,8 @@ from sage.structure.global_options import GlobalOptions from sage.structure.parent import Parent from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets -from sage.combinat.permutation import Permutations from sage.misc.latex import latex +from copy import copy from sage.combinat.words.paths import WordPaths_north_east from sage.combinat.words.paths import FiniteWordPath_north_east @@ -60,6 +60,11 @@ def update_ndw_symbols(os, cs): sage: update_ndw_symbols(0,1) sage: dw = NuDyckWord('0101001','0110010'); dw [0, 1, 0, 1, 0, 0, 1] + + sage: dw = NuDyckWord('1010110','1001101'); dw + Traceback (most recent call last): + ... + ValueError: invalid nu-Dyck word sage: update_ndw_symbols(1,0) """ global ndw_open_symbol @@ -71,9 +76,9 @@ def update_ndw_symbols(os, cs): def replace_dyck_char(x): r""" A map sending an opening character (``'1'``, ``'N'``, and ``'('``) to - ``ndw_open_symbol`` and a closing character (``'0'``, ``'E'``, and ``')'``) to - ``ndw_close_symbol``, and raising an error on any input other than one of the - opening or closing characters. + ``ndw_open_symbol``, a closing character (``'0'``, ``'E'``, and ``')'``) to + ``ndw_close_symbol``, and raising an error on any input other than one of + the opening or closing characters. This is the inverse map of :func:`replace_dyck_symbol`. @@ -115,8 +120,8 @@ def replace_dyck_char(x): def replace_dyck_symbol(x, open_char='N', close_char='E') -> str: r""" - A map sending ``ndw_open_symbol`` to ``open_char`` and ``ndw_close_symbol`` to - ``close_char``, and raising an error on any input other than + A map sending ``ndw_open_symbol`` to ``open_char`` and ``ndw_close_symbol`` + to ``close_char``, and raising an error on any input other than ``ndw_open_symbol`` and ``ndw_close_symbol``. The values of the constants ``ndw_open_symbol`` and ``ndw_close_symbol`` are subject to change. @@ -244,6 +249,13 @@ def __classcall_private__(cls, dw=None, nu=None, **kwargs): def __init__(self, parent, dw, latex_options=None): """ Initialize a nu-Dyck word. + + EXAMPLES:: + + sage: NuDyckWord('010', '010') + [0, 1, 0] + sage: NuDyckWord('110100','101010') + [1, 1, 0, 1, 0, 0] """ Element.__init__(self, parent) self._path = to_word_path(dw) @@ -308,6 +320,23 @@ def __neq__(self, other): def __le__(self, other): """ Return if one path is included in another. + + EXAMPLES:: + + sage: ND1 = NuDyckWord('101', '011') + sage: ND2 = NuDyckWord('110', '011') + sage: ND3 = NuDyckWord('011', '011') + sage: ND1 <= ND1 + True + sage: ND1 <= ND2 + True + sage: ND2 <= ND1 + False + sage: ND3 <= ND2 + True + sage: ND3 <= ND1 + True + """ if self._nu == other._nu: return path_weakly_above_other(other._path, self._path) @@ -316,12 +345,44 @@ def __le__(self, other): def __lt__(self, other): """ Return if one path is strictly included in another + + EXAMPLES:: + + sage: ND1 = NuDyckWord('101', '011') + sage: ND2 = NuDyckWord('110', '011') + sage: ND3 = NuDyckWord('011', '011') + sage: ND1 < ND1 + False + sage: ND1 < ND2 + True + sage: ND2 < ND1 + False + sage: ND3 < ND2 + True + sage: ND3 < ND1 + True """ return self.__le__(other) and not self.__eq__(other) def __ge__(self, other): """ Return if one path is included in another + + EXAMPLES:: + + sage: ND1 = NuDyckWord('101', '011') + sage: ND2 = NuDyckWord('110', '011') + sage: ND3 = NuDyckWord('011', '011') + sage: ND1 >= ND1 + True + sage: ND1 >= ND2 + False + sage: ND2 >= ND1 + True + sage: ND1 >= ND3 + True + sage: ND2 >= ND3 + True """ if self._nu == other._nu: return path_weakly_above_other(self._path, other._path) @@ -330,6 +391,22 @@ def __ge__(self, other): def __gt__(self, other): """ Return if one path is strictly included in another + + EXAMPLES:: + + sage: ND1 = NuDyckWord('101', '011') + sage: ND2 = NuDyckWord('110', '011') + sage: ND3 = NuDyckWord('011', '011') + sage: ND1 > ND1 + False + sage: ND1 > ND2 + False + sage: ND2 > ND1 + True + sage: ND1 > ND3 + True + sage: ND2 > ND3 + True """ return self.__ge__(other) and not self.__eq__(other) @@ -365,8 +442,8 @@ def set_latex_options(self, D): - ``color`` -- (default: black) the line color. - - ``line width`` -- (default: `2 \times` ``tikz_scale``) value representing the - line width. + - ``line width`` -- (default: `2 \times` ``tikz_scale``) value + representing the line width. - ``nu_options`` -- (default: ``'rounded corners=1, color=red, line width=1'``) str to indicate what the tikz options should be for path @@ -510,7 +587,8 @@ def _repr_lattice(self, style=None, labelling=None): TESTS:: - sage: print(NuDyckWord('00011001000100','00011001000100')._repr_lattice(style='N-E', labelling=[1,2,3,4])) + sage: n = NuDyckWord('00011001000100','00011001000100') + sage: print(n._repr_lattice(style='N-E', labelling=[1,2,3,4])) ____ _____| . . 4 ___| . . . . . 3 @@ -650,30 +728,31 @@ def pretty_print(self, style=None, labelling=None): EXAMPLES:: sage: for ND in NuDyckWords('101010'): ND.pretty_print() - ______ - |x x . - |x . . + __ + _| . + _| . . | . . . ____ - _|x . - |x . . + |x . + _| . . | . . . __ ___| . |x . . | . . . ____ - |x . - _| . . + _|x . + |x . . | . . . - __ - _| . - _| . . + ______ + |x x . + |x . . | . . . :: - sage: ND = NuDyckWord([1,1,1,0,1,0,0,1,1,0,0,0],[1,0,1,0,1,0,1,0,1,0,1,0]) + sage: nu = [1,0,1,0,1,0,1,0,1,0,1,0] + sage: ND = NuDyckWord([1,1,1,0,1,0,0,1,1,0,0,0],nu) sage: ND.pretty_print() ______ |x x . @@ -1201,6 +1280,8 @@ def _element_constructor_(self, word): def __contains__(self, x) -> bool: r""" + Checks for containment. + TESTS:: sage: NDW = NuDyckWords([1,0,1,1]) @@ -1271,6 +1352,8 @@ def _cache_key(self) -> str: def _an_element_(self): r""" + Returns an element. + TESTS:: sage: NuDyckWords('101').an_element() @@ -1278,25 +1361,65 @@ def _an_element_(self): """ return self.element_class(self, self._nu) - def __iter__(self): + def __iter__(self, N=[], D=[], i=None, X=None): """ Iterate over ``self``. - .. TODO:: make a better iterator. + The iterator procedes by letting `N` be the locations of all the north + steps in `\nu`. Then we proceed by decreasing the locations as much as + we can from right to left. EXAMPLES:: sage: it = NuDyckWords('101010').__iter__() sage: [i for i in it] - [[1, 1, 1, 0, 0, 0], - [1, 1, 0, 1, 0, 0], - [1, 1, 0, 0, 1, 0], + [[1, 0, 1, 0, 1, 0], [1, 0, 1, 1, 0, 0], - [1, 0, 1, 0, 1, 0]] + [1, 1, 0, 0, 1, 0], + [1, 1, 0, 1, 0, 0], + [1, 1, 1, 0, 0, 0]] """ - for p in Permutations(list(self._nu)): - if path_weakly_above_other(to_word_path(p), self._nu): - yield self.element_class(self, list(p)) + # Location of all the ones + N = [k for k, v in enumerate(list(self._nu)) if v == 1] + + # Our first return element + D = copy(N) + + # Lambda function for adding a one in the appropriate spot + def X(i, N): return 1 if i in N else 0 + + # i is the final entry + i = len(N) - 1 + + # j is our iterator + j = i + + # return nu first + nu = [X(i, D) for i in range(self._nu.length())] + yield self.element_class(self, nu) + + # While we haven't reached the start of our list + while j >= 0: + # If the final number is more than 1 away from second to last + if D[i] > D[i-1] + 1: + D[i] -= 1 + DW = [X(i, D) for i in range(self._nu.length())] + yield self.element_class(self, DW) + else: + # reset j just in case + j = i + # find the last index where two numbers are more than 1 away. + while j > 0 and D[j] == D[j - 1] + 1: + j -= 1 + if j > 0 or (j == 0 and D[j] > 0): + D[j] -= 1 + # reset all the entries above j + for k in range(j + 1, len(N)): + D[k] = N[k] + DW = [X(i, D) for i in range(self._nu.length())] + yield self.element_class(self, DW) + else: + j = -1 def cardinality(self): r""" @@ -1330,16 +1453,16 @@ def to_word_path(word): EXAMPLES:: - sage: from sage.combinat.nu_dyck_word import to_word_path - sage: wp = to_word_path('NEENENEN'); wp - Path: 10010101 - sage: from sage.combinat.words.paths import FiniteWordPath_north_east - sage: isinstance(wp,FiniteWordPath_north_east) - True - sage: to_word_path('1001') - Path: 1001 - sage: to_word_path([0,1,0,0,1,0]) - Path: 010010 + sage: from sage.combinat.nu_dyck_word import to_word_path + sage: wp = to_word_path('NEENENEN'); wp + Path: 10010101 + sage: from sage.combinat.words.paths import FiniteWordPath_north_east + sage: isinstance(wp,FiniteWordPath_north_east) + True + sage: to_word_path('1001') + Path: 1001 + sage: to_word_path([0,1,0,0,1,0]) + Path: 010010 """ # If we already have the object, don't worry if isinstance(word, FiniteWordPath_north_east): From ec793fc9533278b310eeecb8fee4b5946b594be4 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Tue, 17 May 2022 11:36:58 +0100 Subject: [PATCH 024/116] Fix doc to use imperative --- src/sage/combinat/nu_dyck_word.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/nu_dyck_word.py b/src/sage/combinat/nu_dyck_word.py index baf5f9b830e..38521334568 100644 --- a/src/sage/combinat/nu_dyck_word.py +++ b/src/sage/combinat/nu_dyck_word.py @@ -1280,7 +1280,7 @@ def _element_constructor_(self, word): def __contains__(self, x) -> bool: r""" - Checks for containment. + Check for containment. TESTS:: @@ -1352,7 +1352,7 @@ def _cache_key(self) -> str: def _an_element_(self): r""" - Returns an element. + Return an element. TESTS:: From e3925245f576144eff5a546f36592ee1c83a6687 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Tue, 17 May 2022 14:41:39 +0100 Subject: [PATCH 025/116] Make iterator a recursively enumerated set --- src/sage/combinat/nu_dyck_word.py | 91 +++++++++---------------------- 1 file changed, 26 insertions(+), 65 deletions(-) diff --git a/src/sage/combinat/nu_dyck_word.py b/src/sage/combinat/nu_dyck_word.py index 38521334568..503b1e00fe5 100644 --- a/src/sage/combinat/nu_dyck_word.py +++ b/src/sage/combinat/nu_dyck_word.py @@ -32,11 +32,11 @@ from sage.structure.element import Element from sage.rings.integer import Integer from sage.combinat.combinat import CombinatorialElement +from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet from sage.structure.global_options import GlobalOptions from sage.structure.parent import Parent from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.misc.latex import latex -from copy import copy from sage.combinat.words.paths import WordPaths_north_east from sage.combinat.words.paths import FiniteWordPath_north_east @@ -259,6 +259,7 @@ def __init__(self, parent, dw, latex_options=None): """ Element.__init__(self, parent) self._path = to_word_path(dw) + self._list = list(self._path) if parent is None: raise ValueError("need parent object") @@ -269,18 +270,6 @@ def __init__(self, parent, dw, latex_options=None): latex_options = {} self._latex_options = dict(latex_options) - def _list(self): - """ - Return list of ``self``. - - EXAMPLES:: - - sage: w = NuDyckWord('110100','101010') - sage: w._list() - [1, 1, 0, 1, 0, 0] - """ - return list(self._path) - def __eq__(self, other): """ Return if two paths are equal. @@ -432,7 +421,7 @@ def __hash__(self) -> int: sage: hash(u) # random -4577085166836515071 """ - return hash(''.join(str(i) for i in self._list())) + return hash(''.join(str(i) for i in self._list)) def set_latex_options(self, D): r""" @@ -731,14 +720,14 @@ def pretty_print(self, style=None, labelling=None): __ _| . _| . . - | . . . - ____ - |x . - _| . . | . . . __ ___| . |x . . + | . . . + ____ + |x . + _| . . | . . . ____ _|x . @@ -1087,7 +1076,7 @@ def can_mutate(self, i) -> bool | int: # Find the ith north step level = 0 - ndw = self._list() + ndw = self._list for j, k in enumerate(ndw): if k == ndw_open_symbol: level += 1 @@ -1133,7 +1122,7 @@ def mutate(self, i) -> None | NuDyckWord: if horiz[i] == horiz_num: other_index = i break - ndw = self._list() + ndw = self._list d = ndw[0:mutation_index - 1] e = ndw[mutation_index:other_index] f = ndw[other_index:] @@ -1365,61 +1354,33 @@ def __iter__(self, N=[], D=[], i=None, X=None): """ Iterate over ``self``. - The iterator procedes by letting `N` be the locations of all the north - steps in `\nu`. Then we proceed by decreasing the locations as much as - we can from right to left. + The iterator interchanges a 0,1 pair whenever the 0 comes before a 1 EXAMPLES:: sage: it = NuDyckWords('101010').__iter__() sage: [i for i in it] [[1, 0, 1, 0, 1, 0], - [1, 0, 1, 1, 0, 0], [1, 1, 0, 0, 1, 0], + [1, 0, 1, 1, 0, 0], [1, 1, 0, 1, 0, 0], [1, 1, 1, 0, 0, 0]] """ - # Location of all the ones - N = [k for k, v in enumerate(list(self._nu)) if v == 1] - - # Our first return element - D = copy(N) - - # Lambda function for adding a one in the appropriate spot - def X(i, N): return 1 if i in N else 0 - - # i is the final entry - i = len(N) - 1 - - # j is our iterator - j = i - - # return nu first - nu = [X(i, D) for i in range(self._nu.length())] - yield self.element_class(self, nu) - - # While we haven't reached the start of our list - while j >= 0: - # If the final number is more than 1 away from second to last - if D[i] > D[i-1] + 1: - D[i] -= 1 - DW = [X(i, D) for i in range(self._nu.length())] - yield self.element_class(self, DW) - else: - # reset j just in case - j = i - # find the last index where two numbers are more than 1 away. - while j > 0 and D[j] == D[j - 1] + 1: - j -= 1 - if j > 0 or (j == 0 and D[j] > 0): - D[j] -= 1 - # reset all the entries above j - for k in range(j + 1, len(N)): - D[k] = N[k] - DW = [X(i, D) for i in range(self._nu.length())] - yield self.element_class(self, DW) - else: - j = -1 + # Define successor function for recursion + def transpose_close_open(N): + return [self.element_class(self, + N._list[0:k-1] + + list(reversed(N._list[k-1:k+1])) + + N._list[k+1:]) + for k, v in enumerate(N._list) + if k > 0 + and v == ndw_open_symbol + and N._list[k-1] == ndw_close_symbol + ] + + RES = RecursivelyEnumeratedSet([self.element_class(self, self._nu)], + transpose_close_open) + return RES.breadth_first_search_iterator() def cardinality(self): r""" From 956d3d2075ad7fa63c30f787139b2914dba9cb69 Mon Sep 17 00:00:00 2001 From: DavidAyotte Date: Sat, 21 May 2022 14:03:00 -0400 Subject: [PATCH 026/116] src/sage/modular/modform/ring.py: main changes --- src/sage/modular/modform/ring.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/sage/modular/modform/ring.py b/src/sage/modular/modform/ring.py index 821f9861add..52b6185b37a 100644 --- a/src/sage/modular/modform/ring.py +++ b/src/sage/modular/modform/ring.py @@ -765,13 +765,11 @@ def generators(self, maxweight=8, prec=10, start_gens=[], start_weight=2): def gen_forms(self, maxweight=8, start_gens=[], start_weight=2): r""" - This function calculates a list of modular forms generating this ring - (as an algebra over the appropriate base ring). It differs from - :meth:`generators` only in that it returns Sage modular form objects, - rather than bare `q`-expansions; and if the base ring is a finite - field, the modular forms returned will be forms in characteristic 0 - with integral `q`-expansions whose reductions modulo `p` generate the - ring of modular forms mod `p`. + Returns a list of modular forms generating this ring (as an algebra over + the appropriate base ring). + + This method differs from :meth:`generators` only in that it returns + graded modular form objects, rather than bare `q`-expansions. INPUT: @@ -796,13 +794,17 @@ def gen_forms(self, maxweight=8, start_gens=[], start_weight=2): EXAMPLES:: sage: A = ModularFormsRing(Gamma0(11), Zmod(5)).gen_forms(); A - [1 + 12*q^2 + 12*q^3 + 12*q^4 + 12*q^5 + O(q^6), q - 2*q^2 - q^3 + 2*q^4 + q^5 + O(q^6), q - 9*q^4 - 10*q^5 + O(q^6)] + [1 + 2*q^2 + 2*q^3 + 2*q^4 + 2*q^5 + O(q^6), + q + 3*q^2 + 4*q^3 + 2*q^4 + q^5 + O(q^6), + q + q^4 + O(q^6)] sage: A[0].parent() - Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field + Ring of Modular Forms for Congruence Subgroup Gamma0(11) over Ring of integers modulo 5 """ sgs = tuple( (F.weight(), None, F) for F in start_gens ) G = self._find_generators(maxweight, sgs, start_weight) - return [F for k,f,F in G] + return [self(F.parent().change_ring(self.base_ring())(F)) for k,f,F in G] + + gens = gen_forms def _find_generators(self, maxweight, start_gens, start_weight): r""" From 9a050a3e85bdd1e3eca7fcaba3e77139381ae0db Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Sun, 29 May 2022 16:07:44 -0700 Subject: [PATCH 027/116] Assume singular installation works when cross compiling --- build/pkgs/singular/spkg-configure.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/pkgs/singular/spkg-configure.m4 b/build/pkgs/singular/spkg-configure.m4 index 7cf26728368..af2eb854143 100644 --- a/build/pkgs/singular/spkg-configure.m4 +++ b/build/pkgs/singular/spkg-configure.m4 @@ -48,8 +48,8 @@ SAGE_SPKG_CONFIGURE([singular], [ ], [ AC_MSG_RESULT(no) sage_spkg_install_singular=yes - ]) - ]) + ], [AC_MSG_RESULT(yes)]) + ], [AC_MSG_RESULT(yes)]) AC_LANG_POP() LIBS="${ORIG_LIBS}" From 4789d590b621bb641be24edcd7118d6d3f37475b Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Mon, 30 May 2022 12:39:57 +0800 Subject: [PATCH 028/116] move .division_field() up to EllipticCurve_field --- src/sage/schemes/elliptic_curves/ell_field.py | 191 ++++++++++++++++++ .../elliptic_curves/ell_number_field.py | 191 ------------------ 2 files changed, 191 insertions(+), 191 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index c0f3ab5216a..25ddf2c81fd 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -764,6 +764,197 @@ def descend_to(self, K, f=None): Elist = [E.minimal_model() for E in Elist] return Elist + def division_field(self, p, names, map=False, **kwds): + r""" + Given an elliptic curve over a number field `F` and a prime number `p`, + construct the field `F(E[p])`. + + INPUT: + + - ``p`` -- a prime number (an element of `\ZZ`) + + - ``names`` -- a variable name for the number field + + - ``map`` -- (default: ``False``) also return an embedding of + the :meth:`base_field` into the resulting field. + + - ``kwds`` -- additional keywords passed to + :func:`sage.rings.number_field.splitting_field.splitting_field`. + + OUTPUT: + + If ``map`` is ``False``, the division field as an absolute number + field. If ``map`` is ``True``, a tuple ``(K, phi)`` where ``phi`` + is an embedding of the base field in the division field ``K``. + + .. WARNING:: + + This takes a very long time when the degree of the division + field is large (e.g. when `p` is large or when the Galois + representation is surjective). The ``simplify`` flag also + has a big influence on the running time: sometimes + ``simplify=False`` is faster, sometimes ``simplify=True`` + (the default) is faster. + + EXAMPLES: + + The 2-division field is the same as the splitting field of + the 2-division polynomial (therefore, it has degree 1, 2, 3 or 6):: + + sage: E = EllipticCurve('15a1') + sage: K. = E.division_field(2); K + Number Field in b with defining polynomial x + sage: E = EllipticCurve('14a1') + sage: K. = E.division_field(2); K + Number Field in b with defining polynomial x^2 + 5*x + 92 + sage: E = EllipticCurve('196b1') + sage: K. = E.division_field(2); K + Number Field in b with defining polynomial x^3 + x^2 - 114*x - 127 + sage: E = EllipticCurve('19a1') + sage: K. = E.division_field(2); K + Number Field in b with defining polynomial x^6 + 10*x^5 + 24*x^4 - 212*x^3 + 1364*x^2 + 24072*x + 104292 + + For odd primes `p`, the division field is either the splitting + field of the `p`-division polynomial, or a quadratic extension + of it. :: + + sage: E = EllipticCurve('50a1') + sage: F. = E.division_polynomial(3).splitting_field(simplify_all=True); F + Number Field in a with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3 + sage: K. = E.division_field(3, simplify_all=True); K + Number Field in b with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3 + + If we take any quadratic twist, the splitting field of the + 3-division polynomial remains the same, but the 3-division field + becomes a quadratic extension:: + + sage: E = E.quadratic_twist(5) # 50b3 + sage: F. = E.division_polynomial(3).splitting_field(simplify_all=True); F + Number Field in a with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3 + sage: K. = E.division_field(3, simplify_all=True); K + Number Field in b with defining polynomial x^12 - 3*x^11 + 8*x^10 - 15*x^9 + 30*x^8 - 63*x^7 + 109*x^6 - 144*x^5 + 150*x^4 - 120*x^3 + 68*x^2 - 24*x + 4 + + Try another quadratic twist, this time over a subfield of `F`:: + + sage: G.,_,_ = F.subfields(3)[0] + sage: E = E.base_extend(G).quadratic_twist(c); E + Elliptic Curve defined by y^2 = x^3 + 5*a0*x^2 + (-200*a0^2)*x + (-42000*a0^2+42000*a0+126000) over Number Field in a0 with defining polynomial x^3 - 3*x^2 + 3*x + 9 + sage: K. = E.division_field(3, simplify_all=True); K + Number Field in b with defining polynomial x^12 - 10*x^10 + 55*x^8 - 60*x^6 + 75*x^4 + 1350*x^2 + 2025 + + Some higher-degree examples:: + + sage: E = EllipticCurve('11a1') + sage: K. = E.division_field(2); K + Number Field in b with defining polynomial x^6 + 2*x^5 - 48*x^4 - 436*x^3 + 1668*x^2 + 28792*x + 73844 + sage: K. = E.division_field(3); K # long time (3s on sage.math, 2014) + Number Field in b with defining polynomial x^48 ... + sage: K. = E.division_field(5); K + Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1 + sage: E.division_field(5, 'b', simplify=False) + Number Field in b with defining polynomial x^4 + x^3 + 11*x^2 + 41*x + 101 + sage: E.base_extend(K).torsion_subgroup() # long time (2s on sage.math, 2014) + Torsion Subgroup isomorphic to Z/5 + Z/5 associated to the Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20) over Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1 + + sage: E = EllipticCurve('27a1') + sage: K. = E.division_field(3); K + Number Field in b with defining polynomial x^2 + 3*x + 9 + sage: K. = E.division_field(2); K + Number Field in b with defining polynomial x^6 + 6*x^5 + 24*x^4 - 52*x^3 - 228*x^2 + 744*x + 3844 + sage: K. = E.division_field(2, simplify_all=True); K + Number Field in b with defining polynomial x^6 - 3*x^5 + 5*x^3 - 3*x + 1 + sage: K. = E.division_field(5); K # long time (4s on sage.math, 2014) + Number Field in b with defining polynomial x^48 ... + sage: K. = E.division_field(7); K # long time (8s on sage.math, 2014) + Number Field in b with defining polynomial x^72 ... + + Over a number field:: + + sage: R. = PolynomialRing(QQ) + sage: K. = NumberField(x^2 + 1) + sage: E = EllipticCurve([0,0,0,0,i]) + sage: L. = E.division_field(2); L + Number Field in b with defining polynomial x^4 - x^2 + 1 + sage: L., phi = E.division_field(2, map=True); phi + Ring morphism: + From: Number Field in i with defining polynomial x^2 + 1 + To: Number Field in b with defining polynomial x^4 - x^2 + 1 + Defn: i |--> -b^3 + sage: L., phi = E.division_field(3, map=True) + sage: L + Number Field in b with defining polynomial x^24 - 6*x^22 - 12*x^21 - 21*x^20 + 216*x^19 + 48*x^18 + 804*x^17 + 1194*x^16 - 13488*x^15 + 21222*x^14 + 44196*x^13 - 47977*x^12 - 102888*x^11 + 173424*x^10 - 172308*x^9 + 302046*x^8 + 252864*x^7 - 931182*x^6 + 180300*x^5 + 879567*x^4 - 415896*x^3 + 1941012*x^2 + 650220*x + 443089 + sage: phi + Ring morphism: + From: Number Field in i with defining polynomial x^2 + 1 + To: Number Field in b with defining polynomial x^24 ... + Defn: i |--> -215621657062634529/183360797284413355040732*b^23 ... + + AUTHORS: + + - Jeroen Demeyer (2014-01-06): :trac:`11905`, use + ``splitting_field`` method, moved from ``gal_reps.py``, make + it work over number fields. + """ + from sage.misc.verbose import verbose + p = rings.Integer(p) + if not p.is_prime(): + raise ValueError("p must be a prime number") + + verbose("Adjoining X-coordinates of %s-torsion points" % p) + F = self.base_ring() + f = self.division_polynomial(p) + if p == 2: + # For p = 2, the division field is the splitting field of + # the division polynomial. + return f.splitting_field(names, map=map, **kwds) + + # Compute splitting field of X-coordinates. + # The Galois group of the division field is a subgroup of GL(2,p). + # The Galois group of the X-coordinates is a subgroup of GL(2,p)/{-1,+1}. + # We need the map to change the elliptic curve invariants to K. + deg_mult = F.degree() * p * (p+1) * (p-1) * (p-1) // 2 + K, F_to_K = f.splitting_field(names, degree_multiple=deg_mult, map=True, **kwds) + + verbose("Adjoining Y-coordinates of %s-torsion points" % p) + + # THEOREM (Cremona, http://trac.sagemath.org/ticket/11905#comment:21). + # Let K be a field, E an elliptic curve over K and p an odd + # prime number. Assume that K contains all roots of the + # p-division polynomial of E. Then either K contains all + # p-torsion points on E, or it does not contain any p-torsion + # point. + # + # PROOF. Let G be the absolute Galois group of K (every element + # in it fixes all elements of K). For any p-torsion point P + # over the algebraic closure and any sigma in G, we must have + # either sigma(P) = P or sigma(P) = -P (since K contains the + # X-coordinate of P). Now assume that K does not contain all + # p-torsion points. Then there exists a point P1 and a sigma in + # G such that sigma(P1) = -P1. Now take a different p-torsion + # point P2. Since sigma(P2) must be P2 or -P2 and + # sigma(P1+P2) = sigma(P1)+sigma(P2) = sigma(P1)-P2 must + # be P1+P2 or -(P1+P2), it follows that sigma(P2) = -sigma(P2). + # Therefore, K cannot contain any p-torsion point. + # + # This implies that it suffices to adjoin the Y-coordinate + # of just one point. + + # First factor f over F and then compute a root X of f over K. + g = f.factor()[0][0] + X = g.map_coefficients(F_to_K).roots(multiplicities=False)[0] + + # Polynomial defining the corresponding Y-coordinate + a1,a2,a3,a4,a6 = (F_to_K(ai) for ai in self.a_invariants()) + rhs = X*(X*(X + a2) + a4) + a6 + RK = rings.PolynomialRing(K, 'x') + ypol = RK([-rhs, a1*X + a3, 1]) + L = ypol.splitting_field(names, map=map, **kwds) + if map: + L, K_to_L = L + return L, F_to_K.post_compose(K_to_L) + else: + return L + def _fetch_cached_order(self, other): r""" This method copies the ``_order`` member from ``other`` diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index c2ca6bec5c4..a4d53f52890 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -306,197 +306,6 @@ def simon_two_descent(self, verbose=0, lim1=2, lim3=4, limtriv=2, if P not in self._known_points]) return t - def division_field(self, p, names, map=False, **kwds): - r""" - Given an elliptic curve over a number field `F` and a prime number `p`, - construct the field `F(E[p])`. - - INPUT: - - - ``p`` -- a prime number (an element of `\ZZ`) - - - ``names`` -- a variable name for the number field - - - ``map`` -- (default: ``False``) also return an embedding of - the :meth:`base_field` into the resulting field. - - - ``kwds`` -- additional keywords passed to - :func:`sage.rings.number_field.splitting_field.splitting_field`. - - OUTPUT: - - If ``map`` is ``False``, the division field as an absolute number - field. If ``map`` is ``True``, a tuple ``(K, phi)`` where ``phi`` - is an embedding of the base field in the division field ``K``. - - .. WARNING:: - - This takes a very long time when the degree of the division - field is large (e.g. when `p` is large or when the Galois - representation is surjective). The ``simplify`` flag also - has a big influence on the running time: sometimes - ``simplify=False`` is faster, sometimes ``simplify=True`` - (the default) is faster. - - EXAMPLES: - - The 2-division field is the same as the splitting field of - the 2-division polynomial (therefore, it has degree 1, 2, 3 or 6):: - - sage: E = EllipticCurve('15a1') - sage: K. = E.division_field(2); K - Number Field in b with defining polynomial x - sage: E = EllipticCurve('14a1') - sage: K. = E.division_field(2); K - Number Field in b with defining polynomial x^2 + 5*x + 92 - sage: E = EllipticCurve('196b1') - sage: K. = E.division_field(2); K - Number Field in b with defining polynomial x^3 + x^2 - 114*x - 127 - sage: E = EllipticCurve('19a1') - sage: K. = E.division_field(2); K - Number Field in b with defining polynomial x^6 + 10*x^5 + 24*x^4 - 212*x^3 + 1364*x^2 + 24072*x + 104292 - - For odd primes `p`, the division field is either the splitting - field of the `p`-division polynomial, or a quadratic extension - of it. :: - - sage: E = EllipticCurve('50a1') - sage: F. = E.division_polynomial(3).splitting_field(simplify_all=True); F - Number Field in a with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3 - sage: K. = E.division_field(3, simplify_all=True); K - Number Field in b with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3 - - If we take any quadratic twist, the splitting field of the - 3-division polynomial remains the same, but the 3-division field - becomes a quadratic extension:: - - sage: E = E.quadratic_twist(5) # 50b3 - sage: F. = E.division_polynomial(3).splitting_field(simplify_all=True); F - Number Field in a with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3 - sage: K. = E.division_field(3, simplify_all=True); K - Number Field in b with defining polynomial x^12 - 3*x^11 + 8*x^10 - 15*x^9 + 30*x^8 - 63*x^7 + 109*x^6 - 144*x^5 + 150*x^4 - 120*x^3 + 68*x^2 - 24*x + 4 - - Try another quadratic twist, this time over a subfield of `F`:: - - sage: G.,_,_ = F.subfields(3)[0] - sage: E = E.base_extend(G).quadratic_twist(c); E - Elliptic Curve defined by y^2 = x^3 + 5*a0*x^2 + (-200*a0^2)*x + (-42000*a0^2+42000*a0+126000) over Number Field in a0 with defining polynomial x^3 - 3*x^2 + 3*x + 9 - sage: K. = E.division_field(3, simplify_all=True); K - Number Field in b with defining polynomial x^12 - 10*x^10 + 55*x^8 - 60*x^6 + 75*x^4 + 1350*x^2 + 2025 - - Some higher-degree examples:: - - sage: E = EllipticCurve('11a1') - sage: K. = E.division_field(2); K - Number Field in b with defining polynomial x^6 + 2*x^5 - 48*x^4 - 436*x^3 + 1668*x^2 + 28792*x + 73844 - sage: K. = E.division_field(3); K # long time (3s on sage.math, 2014) - Number Field in b with defining polynomial x^48 ... - sage: K. = E.division_field(5); K - Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1 - sage: E.division_field(5, 'b', simplify=False) - Number Field in b with defining polynomial x^4 + x^3 + 11*x^2 + 41*x + 101 - sage: E.base_extend(K).torsion_subgroup() # long time (2s on sage.math, 2014) - Torsion Subgroup isomorphic to Z/5 + Z/5 associated to the Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20) over Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1 - - sage: E = EllipticCurve('27a1') - sage: K. = E.division_field(3); K - Number Field in b with defining polynomial x^2 + 3*x + 9 - sage: K. = E.division_field(2); K - Number Field in b with defining polynomial x^6 + 6*x^5 + 24*x^4 - 52*x^3 - 228*x^2 + 744*x + 3844 - sage: K. = E.division_field(2, simplify_all=True); K - Number Field in b with defining polynomial x^6 - 3*x^5 + 5*x^3 - 3*x + 1 - sage: K. = E.division_field(5); K # long time (4s on sage.math, 2014) - Number Field in b with defining polynomial x^48 ... - sage: K. = E.division_field(7); K # long time (8s on sage.math, 2014) - Number Field in b with defining polynomial x^72 ... - - Over a number field:: - - sage: R. = PolynomialRing(QQ) - sage: K. = NumberField(x^2 + 1) - sage: E = EllipticCurve([0,0,0,0,i]) - sage: L. = E.division_field(2); L - Number Field in b with defining polynomial x^4 - x^2 + 1 - sage: L., phi = E.division_field(2, map=True); phi - Ring morphism: - From: Number Field in i with defining polynomial x^2 + 1 - To: Number Field in b with defining polynomial x^4 - x^2 + 1 - Defn: i |--> -b^3 - sage: L., phi = E.division_field(3, map=True) - sage: L - Number Field in b with defining polynomial x^24 - 6*x^22 - 12*x^21 - 21*x^20 + 216*x^19 + 48*x^18 + 804*x^17 + 1194*x^16 - 13488*x^15 + 21222*x^14 + 44196*x^13 - 47977*x^12 - 102888*x^11 + 173424*x^10 - 172308*x^9 + 302046*x^8 + 252864*x^7 - 931182*x^6 + 180300*x^5 + 879567*x^4 - 415896*x^3 + 1941012*x^2 + 650220*x + 443089 - sage: phi - Ring morphism: - From: Number Field in i with defining polynomial x^2 + 1 - To: Number Field in b with defining polynomial x^24 ... - Defn: i |--> -215621657062634529/183360797284413355040732*b^23 ... - - AUTHORS: - - - Jeroen Demeyer (2014-01-06): :trac:`11905`, use - ``splitting_field`` method, moved from ``gal_reps.py``, make - it work over number fields. - """ - from sage.misc.verbose import verbose - p = Integer(p) - if not p.is_prime(): - raise ValueError("p must be a prime number") - - verbose("Adjoining X-coordinates of %s-torsion points" % p) - F = self.base_ring() - f = self.division_polynomial(p) - if p == 2: - # For p = 2, the division field is the splitting field of - # the division polynomial. - return f.splitting_field(names, map=map, **kwds) - - # Compute splitting field of X-coordinates. - # The Galois group of the division field is a subgroup of GL(2,p). - # The Galois group of the X-coordinates is a subgroup of GL(2,p)/{-1,+1}. - # We need the map to change the elliptic curve invariants to K. - deg_mult = F.degree() * p * (p+1) * (p-1) * (p-1) // 2 - K, F_to_K = f.splitting_field(names, degree_multiple=deg_mult, map=True, **kwds) - - verbose("Adjoining Y-coordinates of %s-torsion points" % p) - - # THEOREM (Cremona, http://trac.sagemath.org/ticket/11905#comment:21). - # Let K be a field, E an elliptic curve over K and p an odd - # prime number. Assume that K contains all roots of the - # p-division polynomial of E. Then either K contains all - # p-torsion points on E, or it does not contain any p-torsion - # point. - # - # PROOF. Let G be the absolute Galois group of K (every element - # in it fixes all elements of K). For any p-torsion point P - # over the algebraic closure and any sigma in G, we must have - # either sigma(P) = P or sigma(P) = -P (since K contains the - # X-coordinate of P). Now assume that K does not contain all - # p-torsion points. Then there exists a point P1 and a sigma in - # G such that sigma(P1) = -P1. Now take a different p-torsion - # point P2. Since sigma(P2) must be P2 or -P2 and - # sigma(P1+P2) = sigma(P1)+sigma(P2) = sigma(P1)-P2 must - # be P1+P2 or -(P1+P2), it follows that sigma(P2) = -sigma(P2). - # Therefore, K cannot contain any p-torsion point. - # - # This implies that it suffices to adjoin the Y-coordinate - # of just one point. - - # First factor f over F and then compute a root X of f over K. - g = f.factor()[0][0] - X = g.map_coefficients(F_to_K).roots(multiplicities=False)[0] - - # Polynomial defining the corresponding Y-coordinate - a1,a2,a3,a4,a6 = (F_to_K(ai) for ai in self.a_invariants()) - rhs = X*(X*(X + a2) + a4) + a6 - RK = PolynomialRing(K, 'x') - ypol = RK([-rhs, a1*X + a3, 1]) - L = ypol.splitting_field(names, map=map, **kwds) - if map: - L, K_to_L = L - return L, F_to_K.post_compose(K_to_L) - else: - return L - def height_pairing_matrix(self, points=None, precision=None, normalised=True): r"""Return the height pairing matrix of the given points. From 731011c1599e5bc3fd7e27438d9bd3e6d63bdda7 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Tue, 31 May 2022 13:35:39 +0800 Subject: [PATCH 029/116] support finite fields in .division_field() --- src/sage/schemes/elliptic_curves/ell_field.py | 113 ++++++++++++++---- 1 file changed, 92 insertions(+), 21 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index 25ddf2c81fd..c1d8e7a8471 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -14,6 +14,9 @@ import sage.rings.all as rings import sage.rings.abc +from sage.categories.number_fields import NumberFields +from sage.categories.finite_fields import FiniteFields + from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field from sage.schemes.curves.projective_curve import ProjectivePlaneCurve_field @@ -764,37 +767,38 @@ def descend_to(self, K, f=None): Elist = [E.minimal_model() for E in Elist] return Elist - def division_field(self, p, names, map=False, **kwds): + def division_field(self, p, names=None, map=False, **kwds): r""" - Given an elliptic curve over a number field `F` and a prime number `p`, - construct the field `F(E[p])`. + Given an elliptic curve over a number field or finite field `F` + and a prime number `p`, construct the field `F(E[p])`. INPUT: - - ``p`` -- a prime number (an element of `\ZZ`) + - ``p`` -- a prime number (an element of `\ZZ`). - - ``names`` -- a variable name for the number field + - ``names`` -- (default: ``t``) a variable name for the division field. - ``map`` -- (default: ``False``) also return an embedding of the :meth:`base_field` into the resulting field. - ``kwds`` -- additional keywords passed to - :func:`sage.rings.number_field.splitting_field.splitting_field`. + :func:`~sage.rings.polynomial.polynomial_element.Polynomial.splitting_field`. OUTPUT: If ``map`` is ``False``, the division field as an absolute number - field. If ``map`` is ``True``, a tuple ``(K, phi)`` where ``phi`` - is an embedding of the base field in the division field ``K``. + field or a finite field. + If ``map`` is ``True``, a tuple `(K, \phi)` where `\phi` is an + embedding of the base field in the division field `K`. .. WARNING:: - This takes a very long time when the degree of the division + This can take a very long time when the degree of the division field is large (e.g. when `p` is large or when the Galois representation is surjective). The ``simplify`` flag also - has a big influence on the running time: sometimes - ``simplify=False`` is faster, sometimes ``simplify=True`` - (the default) is faster. + has a big influence on the running time over number fields: + sometimes ``simplify=False`` is faster, sometimes + ``simplify=True`` (the default) is faster. EXAMPLES: @@ -889,31 +893,100 @@ def division_field(self, p, names, map=False, **kwds): To: Number Field in b with defining polynomial x^24 ... Defn: i |--> -215621657062634529/183360797284413355040732*b^23 ... + Over a finite field:: + + sage: E = EllipticCurve(GF(431^2), [1,0]) + sage: E.division_field(5, map=True) + (Finite Field in t of size 431^4, + Ring morphism: + From: Finite Field in z2 of size 431^2 + To: Finite Field in t of size 431^4 + Defn: z2 |--> 52*t^3 + 222*t^2 + 78*t + 105) + + :: + + sage: E = EllipticCurve(GF(433^2), [1,0]) + sage: K. = E.division_field(7); K + Finite Field in v of size 433^16 + + TESTS: + + Some random testing:: + + sage: def check(E, l, K): + ....: EE = E.change_ring(K) + ....: cof = EE.order().prime_to_m_part(l) + ....: pts = (cof * EE.random_point() for _ in iter(int, 1)) + ....: mul = lambda P: P if not l*P else mul(l*P) + ....: pts = map(mul, filter(bool, pts)) + ....: if l == EE.base_field().characteristic(): + ....: if EE.is_supersingular(): + ....: Ps = () + ....: else: + ....: assert l.divides(EE.order()) + ....: Ps = (next(pts),) + ....: else: + ....: assert l.divides(EE.order()) + ....: for _ in range(9999): + ....: P,Q = next(pts), next(pts) + ....: if P.weil_pairing(Q,l) != 1: + ....: Ps = (P,Q) + ....: break + ....: else: + ....: assert False + ....: deg = lcm(el.minpoly().degree() for el in sum(map(list,Ps),[])) + ....: assert max(deg, E.base_field().degree()) == K.degree() + sage: q = next_prime_power(randrange(1, 10^9)) + sage: F. = GF(q) + sage: while True: + ....: try: + ....: E = EllipticCurve([F.random_element() for _ in range(5)]) + ....: except ArithmeticError: + ....: continue + ....: break + sage: l = random_prime(8) + sage: K = E.division_field(l) + sage: n = E.cardinality(extension_degree=K.degree()//F.degree()) + sage: (l^2 if q%l else 0 + E.is_ordinary()).divides(n) + True + sage: check(E, l, K) # long time + AUTHORS: - Jeroen Demeyer (2014-01-06): :trac:`11905`, use ``splitting_field`` method, moved from ``gal_reps.py``, make it work over number fields. + - Lorenz Panny (2022): extend to finite fields """ from sage.misc.verbose import verbose p = rings.Integer(p) if not p.is_prime(): raise ValueError("p must be a prime number") + if names is None: + names = 't' + verbose("Adjoining X-coordinates of %s-torsion points" % p) F = self.base_ring() - f = self.division_polynomial(p) - if p == 2: - # For p = 2, the division field is the splitting field of + f = self.division_polynomial(l) + if l == 2 or f.is_constant(): + # For l = 2, the division field is the splitting field of # the division polynomial. + # If f is a non-zero constant, the l-torsion is trivial: + # This means the curve must be supersingular and l == p. return f.splitting_field(names, map=map, **kwds) # Compute splitting field of X-coordinates. # The Galois group of the division field is a subgroup of GL(2,p). # The Galois group of the X-coordinates is a subgroup of GL(2,p)/{-1,+1}. # We need the map to change the elliptic curve invariants to K. - deg_mult = F.degree() * p * (p+1) * (p-1) * (p-1) // 2 - K, F_to_K = f.splitting_field(names, degree_multiple=deg_mult, map=True, **kwds) + if F in NumberFields(): + deg_mult = F.degree() * p * (p+1) * (p-1)**2 // 2 + K, F_to_K = f.splitting_field(names, degree_multiple=deg_mult, map=True, **kwds) + elif F in FiniteFields(): + K, F_to_K = f.splitting_field('u', map=True, **kwds) + else: + raise NotImplementedError('only number fields and finite fields are currently supported') verbose("Adjoining Y-coordinates of %s-torsion points" % p) @@ -944,10 +1017,8 @@ def division_field(self, p, names, map=False, **kwds): X = g.map_coefficients(F_to_K).roots(multiplicities=False)[0] # Polynomial defining the corresponding Y-coordinate - a1,a2,a3,a4,a6 = (F_to_K(ai) for ai in self.a_invariants()) - rhs = X*(X*(X + a2) + a4) + a6 - RK = rings.PolynomialRing(K, 'x') - ypol = RK([-rhs, a1*X + a3, 1]) + curve = self.defining_polynomial().map_coefficients(F_to_K) + ypol = curve(X, rings.polygen(K), 1) L = ypol.splitting_field(names, map=map, **kwds) if map: L, K_to_L = L From 6b7dbcddfe0938a3d476470b59d0b69c35888b61 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Tue, 31 May 2022 13:42:27 +0800 Subject: [PATCH 030/116] rename p->l to avoid confusion with characteristic --- src/sage/schemes/elliptic_curves/ell_field.py | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index c1d8e7a8471..c2d26a80ab4 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -767,14 +767,14 @@ def descend_to(self, K, f=None): Elist = [E.minimal_model() for E in Elist] return Elist - def division_field(self, p, names=None, map=False, **kwds): + def division_field(self, l, names=None, map=False, **kwds): r""" Given an elliptic curve over a number field or finite field `F` - and a prime number `p`, construct the field `F(E[p])`. + and a prime number `\ell`, construct the field `F(E[\ell])`. INPUT: - - ``p`` -- a prime number (an element of `\ZZ`). + - ``\ell`` -- a prime number (an element of `\ZZ`). - ``names`` -- (default: ``t``) a variable name for the division field. @@ -794,7 +794,7 @@ def division_field(self, p, names=None, map=False, **kwds): .. WARNING:: This can take a very long time when the degree of the division - field is large (e.g. when `p` is large or when the Galois + field is large (e.g. when `\ell` is large or when the Galois representation is surjective). The ``simplify`` flag also has a big influence on the running time over number fields: sometimes ``simplify=False`` is faster, sometimes @@ -818,8 +818,8 @@ def division_field(self, p, names=None, map=False, **kwds): sage: K. = E.division_field(2); K Number Field in b with defining polynomial x^6 + 10*x^5 + 24*x^4 - 212*x^3 + 1364*x^2 + 24072*x + 104292 - For odd primes `p`, the division field is either the splitting - field of the `p`-division polynomial, or a quadratic extension + For odd primes `\ell`, the division field is either the splitting + field of the `\ell`-division polynomial, or a quadratic extension of it. :: sage: E = EllipticCurve('50a1') @@ -959,14 +959,14 @@ def division_field(self, p, names=None, map=False, **kwds): - Lorenz Panny (2022): extend to finite fields """ from sage.misc.verbose import verbose - p = rings.Integer(p) - if not p.is_prime(): - raise ValueError("p must be a prime number") + l = rings.Integer(l) + if not l.is_prime(): + raise ValueError("l must be a prime number") if names is None: names = 't' - verbose("Adjoining X-coordinates of %s-torsion points" % p) + verbose("Adjoining X-coordinates of %s-torsion points" % l) F = self.base_ring() f = self.division_polynomial(l) if l == 2 or f.is_constant(): @@ -977,18 +977,18 @@ def division_field(self, p, names=None, map=False, **kwds): return f.splitting_field(names, map=map, **kwds) # Compute splitting field of X-coordinates. - # The Galois group of the division field is a subgroup of GL(2,p). - # The Galois group of the X-coordinates is a subgroup of GL(2,p)/{-1,+1}. + # The Galois group of the division field is a subgroup of GL(2,l). + # The Galois group of the X-coordinates is a subgroup of GL(2,l)/{-1,+1}. # We need the map to change the elliptic curve invariants to K. if F in NumberFields(): - deg_mult = F.degree() * p * (p+1) * (p-1)**2 // 2 + deg_mult = F.degree() * l * (l+1) * (l-1)**2 // 2 K, F_to_K = f.splitting_field(names, degree_multiple=deg_mult, map=True, **kwds) elif F in FiniteFields(): K, F_to_K = f.splitting_field('u', map=True, **kwds) else: raise NotImplementedError('only number fields and finite fields are currently supported') - verbose("Adjoining Y-coordinates of %s-torsion points" % p) + verbose("Adjoining Y-coordinates of %s-torsion points" % l) # THEOREM (Cremona, http://trac.sagemath.org/ticket/11905#comment:21). # Let K be a field, E an elliptic curve over K and p an odd From e740b2279bbbf43a0c3aa313b5e9912659e5143c Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Tue, 31 May 2022 22:00:23 +0800 Subject: [PATCH 031/116] remove unused import --- src/sage/schemes/elliptic_curves/ell_number_field.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index a4d53f52890..4df3c054d4a 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -90,7 +90,6 @@ from .ell_generic import is_EllipticCurve from .ell_point import EllipticCurvePoint_number_field from .constructor import EllipticCurve -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.rings.real_mpfr import RealField From 2940e700888d1b305c8fa6061e8faed421e34ed8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 31 May 2022 16:24:58 +0200 Subject: [PATCH 032/116] conversion of maple functions --- src/sage/functions/transcendental.py | 13 ++++--- src/sage/interfaces/maple.py | 51 ++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/src/sage/functions/transcendental.py b/src/sage/functions/transcendental.py index fbbb1995c56..8579819c1aa 100644 --- a/src/sage/functions/transcendental.py +++ b/src/sage/functions/transcendental.py @@ -18,7 +18,6 @@ # **************************************************************************** import sys -import sage.rings.complex_mpfr as complex_field from sage.rings.integer_ring import ZZ from sage.rings.real_mpfr import RR @@ -147,10 +146,14 @@ def __init__(self): sage: zeta(3)._maple_init_() 'Zeta(3)' + sage: zeta(3)._maple_().sage() # optional - maple + zeta(3) """ - GinacFunction.__init__(self, 'zeta', conversions={'giac': 'Zeta', - 'maple': 'Zeta', - 'mathematica': 'Zeta'}) + GinacFunction.__init__(self, 'zeta', + conversions={'giac': 'Zeta', + 'maple': 'Zeta', + 'mathematica': 'Zeta'}) + zeta = Function_zeta() @@ -222,7 +225,7 @@ def __init__(self): """ BuiltinFunction.__init__(self, 'hurwitz_zeta', nargs=2, conversions=dict(mathematica='HurwitzZeta', - maple='Zeta', + # maple='Zeta', conflict with zeta here sympy='zeta'), latex_name=r'\zeta') diff --git a/src/sage/interfaces/maple.py b/src/sage/interfaces/maple.py index 6916024eb92..edc19e3d82a 100644 --- a/src/sage/interfaces/maple.py +++ b/src/sage/interfaces/maple.py @@ -85,7 +85,7 @@ :: sage: maple('(x^12-1)/(x-1)').simplify() # optional - maple - x^11+x^10+x^9+x^8+x^7+x^6+x^5+x^4+x^3+x^2+x+1 + (x+1)*(x^2+1)*(x^2+x+1)*(x^2-x+1)*(x^4-x^2+1) The normal command will always reduce a rational function to the @@ -1082,13 +1082,13 @@ def _latex_(self): """ return self.parent().eval('latex(%s)' % self.name()) - def op(self, i): + def op(self, i=None): """ Return the i-th operand of this expression. INPUT: - - i -- an integer + - i -- an integer or ``None`` EXAMPLES:: @@ -1098,6 +1098,8 @@ def op(self, i): sage: V.op(2) # optional - maple {1 = 4, 2 = 5, 3 = 6} """ + if i is None: + return self.parent().op(self) return self.parent().op(i, self) def _sage_(self): @@ -1170,16 +1172,34 @@ def _sage_(self): sage: sq5.parent() # optional - maple Real Field with 332 bits of precision - Functions are not yet converted back correctly:: + Functions are now sometimes converted back correctly:: sage: maple(hypergeometric([3,4],[5],x)) # optional - maple hypergeom([3, 4],[5],x) - sage: _.sage() # known bug # optional - maple + sage: _.sage() # optional - maple hypergeometric((3, 4), (5,), x) + + sage: maple(zeta(5)) # optional - maple + Zeta(5) + sage: _.sage() # optional - maple + zeta(5) + + sage: maple(psi(2,x)) # optional - maple + Psi(2,x) + sage: _.sage() # optional - maple + psi(2, x) + + sage: maple("4+6*Zeta(3)").sage() # optional - maple + 6*zeta(3) + 4 + + sage: maple("Beta(x,y)^Zeta(9)+1").sage() # optional - maple + beta(x, y)^zeta(9) + 1 """ from sage.matrix.constructor import matrix from sage.modules.free_module_element import vector from sage.rings.integer_ring import ZZ + from sage.symbolic.expression import symbol_table + symbol_maple = symbol_table["maple"] # The next few lines are a very crude excuse for a maple "parser" maple_type = repr(self.whattype()) result = repr(self) @@ -1212,15 +1232,32 @@ def _sage_(self): elif maple_type == 'fraction': return self.op(1)._sage_() / self.op(2)._sage_() elif maple_type == "function": - pass # TODO : here one should translate back function names + # TODO : better back translation of function names + fun = str(self.op(0)) + try: + sage_fun = symbol_maple[fun] + if self.nops() == 1: + args = [self.op()._sage_()] + else: + args = [arg._sage_() for arg in self.op()] + return sage_fun(*args) + except (KeyError, TypeError): + pass elif maple_type == "float": from sage.rings.real_mpfr import RealField mantissa = len(repr(self.op(1))) prec = max(53, (mantissa * 13301) // 4004) R = RealField(prec) return R(result) + elif maple_type == '`+`': + return sum(term._sage_() for term in self.op()) + elif maple_type == '`*`': + from sage.misc.misc_c import prod + return prod(term._sage_() for term in self.op()) + elif maple_type == '`^`': + return self.op(1)._sage_()**self.op(2)._sage_() elif maple_type == '`=`': # (1, 1) = 2 - return (self.op(1)._sage_() == self.op(2)._sage()) + return (self.op(1)._sage_() == self.op(2)._sage_()) try: from sage.symbolic.ring import SR return SR(result) From 9d33c1deb887d3224a4b86ad990b855db8674624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 1 Jun 2022 07:42:55 +0200 Subject: [PATCH 033/116] one more doctest --- src/sage/interfaces/maple.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/sage/interfaces/maple.py b/src/sage/interfaces/maple.py index edc19e3d82a..9b0d79ac2ed 100644 --- a/src/sage/interfaces/maple.py +++ b/src/sage/interfaces/maple.py @@ -1172,6 +1172,13 @@ def _sage_(self): sage: sq5.parent() # optional - maple Real Field with 332 bits of precision + Equations:: + + sage: maple("x=4") # optional - maple + x = 4 + sage: _.sage() # optional - maple + x == 4 + Functions are now sometimes converted back correctly:: sage: maple(hypergeometric([3,4],[5],x)) # optional - maple @@ -1192,7 +1199,7 @@ def _sage_(self): sage: maple("4+6*Zeta(3)").sage() # optional - maple 6*zeta(3) + 4 - sage: maple("Beta(x,y)^Zeta(9)+1").sage() # optional - maple + sage: maple("Beta(x,y)^Zeta(9)+1").sage() # optional - maple beta(x, y)^zeta(9) + 1 """ from sage.matrix.constructor import matrix From f307ea75caba505fbeb164faa3a991ca10c27d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 1 Jun 2022 08:51:47 +0200 Subject: [PATCH 034/116] also convert Sum and Product --- src/sage/interfaces/maple.py | 47 ++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/sage/interfaces/maple.py b/src/sage/interfaces/maple.py index 9b0d79ac2ed..16e928b6cae 100644 --- a/src/sage/interfaces/maple.py +++ b/src/sage/interfaces/maple.py @@ -433,7 +433,7 @@ def expect(self): True sage: m._start() # optional - maple sage: m.expect() # optional - maple - + Maple with PID ... sage: m.quit() # optional - maple """ return self._expect @@ -1106,8 +1106,9 @@ def _sage_(self): r""" Convert a maple expression back to a Sage expression. - This currently does not implement a parser for the Maple output language, - therefore only very simple expressions will convert successfully. + This currently does not implement a serious parser + for the Maple output language. + Therefore only very simple expressions will convert successfully. REFERENCE: @@ -1199,8 +1200,15 @@ def _sage_(self): sage: maple("4+6*Zeta(3)").sage() # optional - maple 6*zeta(3) + 4 - sage: maple("Beta(x,y)^Zeta(9)+1").sage() # optional - maple + sage: maple("Beta(x,y)^Zeta(9)+1").sage() # optional - maple beta(x, y)^zeta(9) + 1 + + Sums and products:: + + sage: maple('Sum(x-k,k=1..n)').sage() # optional - maple + sum(-k + x, k, 1, n) + sage: maple('Product(x-k,k=1..n)').sage() # optional - maple + product(-k + x, k, 1, n) """ from sage.matrix.constructor import matrix from sage.modules.free_module_element import vector @@ -1241,15 +1249,28 @@ def _sage_(self): elif maple_type == "function": # TODO : better back translation of function names fun = str(self.op(0)) - try: - sage_fun = symbol_maple[fun] - if self.nops() == 1: - args = [self.op()._sage_()] - else: - args = [arg._sage_() for arg in self.op()] - return sage_fun(*args) - except (KeyError, TypeError): - pass + if fun == 'Sum': + from sage.misc.functional import symbolic_sum + term = self.op(1)._sage_() + variable = self.op(2).op(1)._sage_() + bounds = [b._sage_() for b in self.op(2).op(2).op()] + return symbolic_sum(term, variable, *bounds, hold=True) + if fun == 'Product': + from sage.misc.functional import symbolic_prod + term = self.op(1)._sage_() + variable = self.op(2).op(1)._sage_() + bounds = [b._sage_() for b in self.op(2).op(2).op()] + return symbolic_prod(term, variable, *bounds, hold=True) + else: + try: + sage_fun = symbol_maple[fun] + if self.nops() == 1: + args = [self.op()._sage_()] + else: + args = [arg._sage_() for arg in self.op()] + return sage_fun(*args) + except (KeyError, TypeError): + pass elif maple_type == "float": from sage.rings.real_mpfr import RealField mantissa = len(repr(self.op(1))) From 9ea07376cf5bf27d3bd63fd0189090c1ef56422a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 1 Jun 2022 09:51:41 +0200 Subject: [PATCH 035/116] now for integrals too --- src/sage/interfaces/maple.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/sage/interfaces/maple.py b/src/sage/interfaces/maple.py index 16e928b6cae..224eb8bc552 100644 --- a/src/sage/interfaces/maple.py +++ b/src/sage/interfaces/maple.py @@ -1209,6 +1209,11 @@ def _sage_(self): sum(-k + x, k, 1, n) sage: maple('Product(x-k,k=1..n)').sage() # optional - maple product(-k + x, k, 1, n) + + Integrals:: + + sage: maple('Int(exp(x),x=0..y)').sage() # optional - maple + integrate(e^x, x, 0, y) """ from sage.matrix.constructor import matrix from sage.modules.free_module_element import vector @@ -1255,6 +1260,12 @@ def _sage_(self): variable = self.op(2).op(1)._sage_() bounds = [b._sage_() for b in self.op(2).op(2).op()] return symbolic_sum(term, variable, *bounds, hold=True) + if fun == 'Int': + from sage.misc.functional import integral + term = self.op(1)._sage_() + variable = self.op(2).op(1)._sage_() + bounds = [b._sage_() for b in self.op(2).op(2).op()] + return integral(term, variable, *bounds, hold=True) if fun == 'Product': from sage.misc.functional import symbolic_prod term = self.op(1)._sage_() From b454e74bb0938b4c06862ae994f2b961bc4438ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 1 Jun 2022 09:54:03 +0200 Subject: [PATCH 036/116] tweak maple parser --- src/sage/interfaces/maple.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/interfaces/maple.py b/src/sage/interfaces/maple.py index 224eb8bc552..3effc4e8b80 100644 --- a/src/sage/interfaces/maple.py +++ b/src/sage/interfaces/maple.py @@ -1254,19 +1254,19 @@ def _sage_(self): elif maple_type == "function": # TODO : better back translation of function names fun = str(self.op(0)) - if fun == 'Sum': + if fun in ['Sum', 'sum']: from sage.misc.functional import symbolic_sum term = self.op(1)._sage_() variable = self.op(2).op(1)._sage_() bounds = [b._sage_() for b in self.op(2).op(2).op()] return symbolic_sum(term, variable, *bounds, hold=True) - if fun == 'Int': + if fun in ['Int', 'int']: from sage.misc.functional import integral term = self.op(1)._sage_() variable = self.op(2).op(1)._sage_() bounds = [b._sage_() for b in self.op(2).op(2).op()] return integral(term, variable, *bounds, hold=True) - if fun == 'Product': + if fun in ['Product', 'product']: from sage.misc.functional import symbolic_prod term = self.op(1)._sage_() variable = self.op(2).op(1)._sage_() From a642e3a6b1ef82dea1cc8463a1d2cd2a34ef6283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 2 Jun 2022 10:42:01 +0200 Subject: [PATCH 037/116] fix E306 outside of combinat,graphs,rings,categories,schemes,algebras --- src/sage/calculus/desolvers.py | 16 +++++++++------- src/sage/categories/finite_posets.py | 4 +++- src/sage/coding/guruswami_sudan/gs_decoder.py | 1 + src/sage/coding/guruswami_sudan/interpolation.py | 2 ++ src/sage/coding/information_set_decoder.py | 2 ++ .../combinat/cluster_algebra_quiver/quiver.py | 1 + src/sage/crypto/sboxes.py | 1 + src/sage/databases/findstat.py | 3 +++ src/sage/databases/sql_db.py | 1 + src/sage/doctest/control.py | 2 ++ src/sage/doctest/fixtures.py | 1 + src/sage/functions/orthogonal_polys.py | 1 + .../triangulation/point_configuration.py | 1 + src/sage/groups/braid.py | 1 + src/sage/groups/cubic_braid.py | 2 ++ src/sage/homology/chain_complex.py | 1 + src/sage/homology/hochschild_complex.py | 1 + src/sage/interfaces/frobby.py | 4 +++- src/sage/knots/link.py | 1 + src/sage/libs/singular/standard_options.py | 1 + src/sage/manifolds/differentiable/vectorfield.py | 1 - src/sage/manifolds/subset.py | 3 +++ src/sage/misc/explain_pickle.py | 1 + src/sage/misc/superseded.py | 1 + src/sage/modular/modform/numerical.py | 2 ++ src/sage/modular/modsym/ambient.py | 3 ++- src/sage/modules/filtered_vector_space.py | 1 + src/sage/modules/with_basis/morphism.py | 1 + src/sage/monoids/indexed_free_monoid.py | 1 + src/sage/parallel/decorate.py | 2 ++ src/sage/plot/hyperbolic_polygon.py | 1 + src/sage/plot/plot.py | 4 +++- src/sage/plot/plot3d/plot3d.py | 10 ++++++---- .../quadratic_forms/quadratic_form__theta.py | 1 + src/sage/repl/ipython_kernel/widgets_sagenb.py | 1 + src/sage/repl/rich_output/backend_ipython.py | 1 + src/sage/rings/padics/local_generic.py | 1 + src/sage/schemes/curves/zariski_vankampen.py | 9 +++++---- .../schemes/riemann_surfaces/riemann_surface.py | 5 +++-- src/sage/sets/image_set.py | 1 + src/sage/sets/real_set.py | 1 + src/sage/tensor/modules/free_module_tensor.py | 1 + src/sage_docbuild/ext/multidocs.py | 1 + 43 files changed, 78 insertions(+), 22 deletions(-) diff --git a/src/sage/calculus/desolvers.py b/src/sage/calculus/desolvers.py index 5bf704b95eb..02e4d0562d8 100644 --- a/src/sage/calculus/desolvers.py +++ b/src/sage/calculus/desolvers.py @@ -574,6 +574,7 @@ def desolve(de, dvar, ics=None, ivar=None, show_method=False, contrib_ode=False, dvar_str=P(dvar.operator()).str() ivar_str=P(ivar).str() de00 = de00.str() + def sanitize_var(exprs): return exprs.replace("'"+dvar_str+"("+ivar_str+")",dvar_str) de0 = sanitize_var(de00) @@ -811,6 +812,7 @@ def desolve_laplace(de, dvar, ics=None, ivar=None): ## verbatim copy from desolve - end dvar_str = str(dvar) + def sanitize_var(exprs): # 'y(x) -> y(x) return exprs.replace("'"+dvar_str,dvar_str) de0=de._maxima_() @@ -1680,25 +1682,25 @@ def Dfun(y, t): variabs = dvars[:] variabs.append(ivar) for de in des: - desc.append(fast_float(de,*variabs)) + desc.append(fast_float(de, *variabs)) - def func(y,t): + def func(y, t): v = list(y[:]) v.append(t) return [dec(*v) for dec in desc] if not compute_jac: - Dfun=None + Dfun = None else: - J = jacobian(des,dvars) + J = jacobian(des, dvars) J = [list(v) for v in J] - J = fast_float(J,*variabs) - def Dfun(y,t): + J = fast_float(J, *variabs) + + def Dfun(y, t): v = list(y[:]) v.append(t) return [[element(*v) for element in row] for row in J] - sol=odeint(func, ics, times, args=args, Dfun=Dfun, rtol=rtol, atol=atol, tcrit=tcrit, h0=h0, hmax=hmax, hmin=hmin, ixpr=ixpr, mxstep=mxstep, mxhnil=mxhnil, mxordn=mxordn, mxords=mxords, printmessg=printmessg) diff --git a/src/sage/categories/finite_posets.py b/src/sage/categories/finite_posets.py index 3a537733431..1f6b49d2e15 100644 --- a/src/sage/categories/finite_posets.py +++ b/src/sage/categories/finite_posets.py @@ -1901,14 +1901,16 @@ def order_ideals_lattice(self, as_ideals=True, facade=None): else: from sage.misc.cachefunc import cached_function antichains = [tuple(a) for a in self.antichains()] + @cached_function def is_above(a, xb): return any(self.is_lequal(xa, xb) for xa in a) + def compare(a, b): return all(is_above(a, xb) for xb in b) return LatticePoset((antichains, compare), facade=facade) - @abstract_method(optional = True) + @abstract_method(optional=True) def antichains(self): r""" Return all antichains of ``self``. diff --git a/src/sage/coding/guruswami_sudan/gs_decoder.py b/src/sage/coding/guruswami_sudan/gs_decoder.py index 0cd18df579b..a18a6bb710d 100644 --- a/src/sage/coding/guruswami_sudan/gs_decoder.py +++ b/src/sage/coding/guruswami_sudan/gs_decoder.py @@ -356,6 +356,7 @@ def guruswami_sudan_decoding_radius(C = None, n_k = None, l = None, s = None): (92, (2, 6)) """ n,k = n_k_params(C, n_k) + def get_tau(s,l): "Return the decoding radius given this s and l" if s<=0 or l<=0: diff --git a/src/sage/coding/guruswami_sudan/interpolation.py b/src/sage/coding/guruswami_sudan/interpolation.py index 9c42fd0025f..1e75085fe44 100644 --- a/src/sage/coding/guruswami_sudan/interpolation.py +++ b/src/sage/coding/guruswami_sudan/interpolation.py @@ -337,11 +337,13 @@ def lee_osullivan_module(points, parameters, wy): y = PFy.gens()[0] ybasis = [(y-R)**i * G**(s-i) for i in range(0, s+1)] \ + [y**(i-s) * (y-R)**s for i in range(s+1, l+1)] + def pad(lst): return lst + [0]*(l+1-len(lst)) modbasis = [pad(yb.coefficients(sparse=False)) for yb in ybasis] return matrix(PF, modbasis) + def gs_interpolation_lee_osullivan(points, tau, parameters, wy): r""" Returns an interpolation polynomial Q(x,y) for the given input using the diff --git a/src/sage/coding/information_set_decoder.py b/src/sage/coding/information_set_decoder.py index 688966ef062..7e28e1a7aac 100644 --- a/src/sage/coding/information_set_decoder.py +++ b/src/sage/coding/information_set_decoder.py @@ -555,6 +555,7 @@ def calibrate(self): F = C.base_ring() q = F.cardinality() Fstar = F.list()[1:] + def time_information_set_steps(): before = process_time() while True: @@ -565,6 +566,7 @@ def time_information_set_steps(): except ZeroDivisionError: continue return process_time() - before + def time_search_loop(p): y = random_vector(F, n) g = random_matrix(F, p, n).rows() diff --git a/src/sage/combinat/cluster_algebra_quiver/quiver.py b/src/sage/combinat/cluster_algebra_quiver/quiver.py index 91c5a0c394e..bb46c6aa6a1 100644 --- a/src/sage/combinat/cluster_algebra_quiver/quiver.py +++ b/src/sage/combinat/cluster_algebra_quiver/quiver.py @@ -561,6 +561,7 @@ def plot(self, circular=True, center=(0, 0), directed=True, mark=None, from sage.all import e, pi, I graphs = GraphGenerators() # returns positions for graph vertices on two concentric cycles with radius 1 and 2 + def _graphs_concentric_circles(n, m): g1 = graphs.CycleGraph(n).get_pos() g2 = graphs.CycleGraph(m).get_pos() diff --git a/src/sage/crypto/sboxes.py b/src/sage/crypto/sboxes.py index c6b1933213b..056ce082b50 100644 --- a/src/sage/crypto/sboxes.py +++ b/src/sage/crypto/sboxes.py @@ -237,6 +237,7 @@ def bf(x): elif isinstance(bf, (BooleanFunction,)): bf_f2 = bf + def bf(x): xprime = map(int, x.polynomial().list()) xprime += [0]*(n-1 - len(xprime)) diff --git a/src/sage/databases/findstat.py b/src/sage/databases/findstat.py index 4a84ef1edb3..99e5e6311bd 100644 --- a/src/sage/databases/findstat.py +++ b/src/sage/databases/findstat.py @@ -645,6 +645,7 @@ def _data_from_iterable(iterable, mapping=False, domain=None, codomain = FindStatCollection(vals) all_elements = set() + def sanitize_pair(elts, vals): if domain.is_element(elts): elts = [elts] @@ -1050,6 +1051,7 @@ def findstat(query=None, values=None, distribution=None, domain=None, raise ValueError("the maximal number of values for a FindStat query must be a non-negative integer less than or equal to %i" % FINDSTAT_MAX_VALUES) check_collection = True + def get_values(raw, domain=None): if callable(raw): known_terms = _data_from_function(raw, domain) @@ -1272,6 +1274,7 @@ def findmap(*args, **kwargs): raise ValueError("the maximal number of values for a FindStat query must be a non-negative integer less than or equal to %i" % FINDSTAT_MAX_VALUES) check_collection = True + def get_values(raw, domain=None, codomain=None): if callable(raw): known_terms = _data_from_function(raw, domain) diff --git a/src/sage/databases/sql_db.py b/src/sage/databases/sql_db.py index 19d579ae38c..d13d1e83940 100644 --- a/src/sage/databases/sql_db.py +++ b/src/sage/databases/sql_db.py @@ -349,6 +349,7 @@ def _create_print_table(cur, col_titles, **kwds): continue global p p = 0 + def row_str(row, html): f = 0 global p diff --git a/src/sage/doctest/control.py b/src/sage/doctest/control.py index a9d11d0863e..bc15e851cb8 100644 --- a/src/sage/doctest/control.py +++ b/src/sage/doctest/control.py @@ -950,6 +950,7 @@ def filter_sources(self): # Filter the sources to only include those with failing doctests if the --failed option is passed if self.options.failed: self.log("Only doctesting files that failed last test.") + def is_failure(source): basename = source.basename return basename not in self.stats or self.stats[basename].get('failed') @@ -989,6 +990,7 @@ def sort_sources(self): if self.options.nthreads > 1 and len(self.sources) > self.options.nthreads: self.log("Sorting sources by runtime so that slower doctests are run first....") default = dict(walltime=0) + def sort_key(source): basename = source.basename return -self.stats.get(basename, default).get('walltime'), basename diff --git a/src/sage/doctest/fixtures.py b/src/sage/doctest/fixtures.py index 13b3fb40f19..d524899cd26 100644 --- a/src/sage/doctest/fixtures.py +++ b/src/sage/doctest/fixtures.py @@ -372,6 +372,7 @@ def trace_method(obj, meth, **kwds): from sage.cpython.getattr import raw_getattr f = raw_getattr(obj, meth) t = AttributeAccessTracerProxy(obj, **kwds) + @wraps(f) def g(*args, **kwds): arglst = [reproducible_repr(arg) for arg in args] diff --git a/src/sage/functions/orthogonal_polys.py b/src/sage/functions/orthogonal_polys.py index aace3cc767d..9e384b2bdf7 100644 --- a/src/sage/functions/orthogonal_polys.py +++ b/src/sage/functions/orthogonal_polys.py @@ -2793,6 +2793,7 @@ def eval_formula(self, n, x, b, c): + (3*b^2 + 6*b - 3*b^2/c - 3*b/c - 3*b/c^2 - 2/c^3 + 2)*x + 2*b """ from sage.misc.misc_c import prod + def P(val, k): return prod(val + j for j in range(k)) return sum((-1)**k * binomial(n, k) * binomial(x, k) * factorial(k) diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py index 0a0b17cd27a..855d6dbf4be 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -1978,6 +1978,7 @@ def placing_triangulation(self, point_order=None): (<0,2,4>, <0,3,4>, <1,2,4>, <1,3,4>) """ facet_normals = dict() + def facets_of_simplex(simplex): """ Return the facets of the simplex and store the normals in facet_normals diff --git a/src/sage/groups/braid.py b/src/sage/groups/braid.py index c2ac473b8d7..9003eb8d375 100644 --- a/src/sage/groups/braid.py +++ b/src/sage/groups/braid.py @@ -2095,6 +2095,7 @@ def reduced_word(self): in parallel. """ M = self._algebra._indices + def tuple_to_word(q_tuple): return M.prod(self._gens[i] ** exp for i, exp in enumerate(q_tuple)) diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index 846b8710604..7b235ea647c 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -1214,6 +1214,7 @@ def create_sympl_realization(self, m): # matrix. # ----------------------------------------------------------- from sage.matrix.constructor import matrix + def transvec2mat(v, bas=bas, bform=bform, fact=1): t = [x + fact*(x * bform * v) * v for x in bas] return matrix(bform.base_ring(), t) @@ -1295,6 +1296,7 @@ def create_unitary_realization(self, m): # matrix. # ----------------------------------------------------------- from sage.matrix.constructor import matrix + def transvec2mat(v, bas=bas, bform=bform, fact=a): # note x does not change under conjugation, since it belongs to standard basis t = [x + fact *(x * bform * v.conjugate()) * v for x in bas] diff --git a/src/sage/homology/chain_complex.py b/src/sage/homology/chain_complex.py index 0f8492d140f..87070944e6a 100644 --- a/src/sage/homology/chain_complex.py +++ b/src/sage/homology/chain_complex.py @@ -1337,6 +1337,7 @@ def _homology_in_degree(self, deg, base_ring, verbose, generators, algorithm): print('Computing homology of the chain complex in dimension %s...' % deg) fraction_field = base_ring.fraction_field() + def change_ring(X): if X.base_ring() is base_ring: return X diff --git a/src/sage/homology/hochschild_complex.py b/src/sage/homology/hochschild_complex.py index 478118b4274..ef68448c685 100644 --- a/src/sage/homology/hochschild_complex.py +++ b/src/sage/homology/hochschild_complex.py @@ -269,6 +269,7 @@ def boundary(self, d): Fd = self.module(d-1) Fd1 = self.module(d) mone = -one + def on_basis(k): p = self._M.monomial(k[0]) * self._A.monomial(k[1]) ret = Fd._from_dict({(m,) + k[2:]: c for m,c in p}, remove_zeros=False) diff --git a/src/sage/interfaces/frobby.py b/src/sage/interfaces/frobby.py index ed852f74efe..68be9c39d01 100644 --- a/src/sage/interfaces/frobby.py +++ b/src/sage/interfaces/frobby.py @@ -211,6 +211,7 @@ def associated_primes(self, monomial_ideal): if lines[-1]=='': lines.pop(-1) lists = [[int(_) for _ in a.split()] for a in lines] + def to_monomial(exps): return [v ** e for v, e in zip(monomial_ideal.ring().gens(), exps) if e != 0] return [monomial_ideal.ring().ideal(to_monomial(a)) for a in lists] @@ -338,8 +339,9 @@ def _parse_ideals(self, string, ring): for i in range(nrows): nmatrix+=lines.pop(0)+'\n' matrices.append(nmatrix) + def to_ideal(exps): - if len(exps)==0: + if len(exps) == 0: return ring.zero_ideal() gens = [prod([v ** e for v, e in zip(ring.gens(), expo) if e != 0]) for expo in exps] return ring.ideal(gens or ring(1)) diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index c6680df23c5..8cc24097d04 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -3918,6 +3918,7 @@ def get_knotinfo(self, mirror_version=True, unique=True): # over :class:`KnotInfo` should be returned non_unique_hint = '\nuse keyword argument `unique` to obtain more details' + def answer(L): r""" Return a single item of the KnotInfo database according to the keyword diff --git a/src/sage/libs/singular/standard_options.py b/src/sage/libs/singular/standard_options.py index 6d2d8044106..4756a6ec1db 100644 --- a/src/sage/libs/singular/standard_options.py +++ b/src/sage/libs/singular/standard_options.py @@ -132,6 +132,7 @@ def libsingular_gb_standard_options(func): does not need to use it manually. """ from sage.misc.decorators import sage_wraps + @sage_wraps(func) def wrapper(*args, **kwds): """ diff --git a/src/sage/manifolds/differentiable/vectorfield.py b/src/sage/manifolds/differentiable/vectorfield.py index 9fb6dfbef14..acf07f25aca 100644 --- a/src/sage/manifolds/differentiable/vectorfield.py +++ b/src/sage/manifolds/differentiable/vectorfield.py @@ -834,7 +834,6 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, extra_options) for ind_part in local_list] - # definition of the parallel function @parallel(p_iter='multiprocessing', ncpus=nproc) def add_point_plot(vector, dom, xx_list, chart_domain, chart, diff --git a/src/sage/manifolds/subset.py b/src/sage/manifolds/subset.py index 639567cd7e0..9e5c12d4cc7 100644 --- a/src/sage/manifolds/subset.py +++ b/src/sage/manifolds/subset.py @@ -971,6 +971,7 @@ def vertex_family(subset): def vertex_family(subset): return ManifoldSubsetFiniteFamily([subset]) subset_to_vertex = {} + def vertex(subset): try: return subset_to_vertex[subset] @@ -2307,6 +2308,7 @@ def _reduce_intersection_members(subsets): subsets = set(subsets) if not subsets: raise TypeError('input set must be nonempty') + def reduce(): # Greedily replace inclusion chains by their minimal element # and pairs with declared intersections by their intersection @@ -2531,6 +2533,7 @@ def _reduce_union_members(subsets): """ subsets = set(subsets) + def reduce(): # Greedily replace inclusion chains by their maximal element # and pairs with declared unions by their union diff --git a/src/sage/misc/explain_pickle.py b/src/sage/misc/explain_pickle.py index 946dd8057c0..cf048094575 100644 --- a/src/sage/misc/explain_pickle.py +++ b/src/sage/misc/explain_pickle.py @@ -2432,6 +2432,7 @@ def unpickle_newobj(klass, args): pickle = b"P0\nP1\n\x81." pers = [klass, args] + def pers_load(id): return pers[int(id)] diff --git a/src/sage/misc/superseded.py b/src/sage/misc/superseded.py index 0d20e025a23..d1e1601d52f 100644 --- a/src/sage/misc/superseded.py +++ b/src/sage/misc/superseded.py @@ -304,6 +304,7 @@ def __call__(self, func): (3,) {'what': 'Hello'} """ from sage.misc.decorators import sage_wraps + @sage_wraps(func) def wrapper(*args, **kwds): if not wrapper._already_issued: diff --git a/src/sage/modular/modform/numerical.py b/src/sage/modular/modform/numerical.py index 47dbdd6762b..2659fe28c14 100644 --- a/src/sage/modular/modform/numerical.py +++ b/src/sage/modular/modform/numerical.py @@ -334,6 +334,7 @@ def _eigendata(self): x = self._easy_vector() B = self._eigenvectors() + def phi(y): """ Take coefficients and a basis, and return that @@ -416,6 +417,7 @@ def eigenvalues(self, primes): raise ValueError('each element of primes must be prime.') phi_x, phi_x_inv, nzp, x_nzp = self._eigendata() B = self._eigenvectors() + def phi(y): """ Take coefficients and a basis, and return that diff --git a/src/sage/modular/modsym/ambient.py b/src/sage/modular/modsym/ambient.py index 3768e65b73f..b28de8d9d5e 100644 --- a/src/sage/modular/modsym/ambient.py +++ b/src/sage/modular/modsym/ambient.py @@ -2473,6 +2473,7 @@ def _pari_pairing(self): m = Integer(self.weight() - 2) R = PolynomialRing(QQ, 'x') x = R.gen() + def ev(s): # The Manin symbol s = X^i (c, d) corresponds to the # modular symbol (dX - bY)^i (-cX + aY)^(m - i) {b/d, a/c}. @@ -2481,7 +2482,7 @@ def ev(s): i = s.i a, b, c, d = s.lift_to_sl2z() e = [R(p) for p in P.mseval(I, matrix(2, 2, [b, a, d, c]))] - g = (d*x - b)**i * (-c*x + a)**(m - i) + g = (d * x - b)**i * (-c * x + a)**(m - i) return [sum(f[j] * g[m - j] / m.binomial(j) for j in range(m + 1)) for f in e] return matrix([ev(s) for s in self.manin_symbols_basis()]) diff --git a/src/sage/modules/filtered_vector_space.py b/src/sage/modules/filtered_vector_space.py index dd5784041eb..6caa2d2aac6 100644 --- a/src/sage/modules/filtered_vector_space.py +++ b/src/sage/modules/filtered_vector_space.py @@ -1003,6 +1003,7 @@ def direct_sum(self, other): generators = \ [ list(v) + [base_ring.zero()]*other.dimension() for v in self_gens ] + \ [ [base_ring.zero()]*self.dimension() + list(v) for v in other_gens ] + # construct the filtration dictionary def join_indices(self_indices, other_indices): self_indices = tuple(self_indices) diff --git a/src/sage/modules/with_basis/morphism.py b/src/sage/modules/with_basis/morphism.py index 7972927406d..37e541ccce7 100644 --- a/src/sage/modules/with_basis/morphism.py +++ b/src/sage/modules/with_basis/morphism.py @@ -849,6 +849,7 @@ def section(self): retract_dom = None else: on_basis = self.on_basis() + def retract_dom(i): self._dominant_item(on_basis(i))[0] diff --git a/src/sage/monoids/indexed_free_monoid.py b/src/sage/monoids/indexed_free_monoid.py index 69168f1e1bd..e6fb1c9e450 100644 --- a/src/sage/monoids/indexed_free_monoid.py +++ b/src/sage/monoids/indexed_free_monoid.py @@ -143,6 +143,7 @@ def _ascii_art_(self): ascii_art_gen = lambda m: P._ascii_art_generator(m[0]) else: pref = AsciiArt([P.prefix()]) + def ascii_art_gen(m): if m[1] != 1: r = (AsciiArt([" " * len(pref)]) + ascii_art(m[1])) diff --git a/src/sage/parallel/decorate.py b/src/sage/parallel/decorate.py index 38e4a784103..74bac3fe12b 100644 --- a/src/sage/parallel/decorate.py +++ b/src/sage/parallel/decorate.py @@ -473,10 +473,12 @@ def __call__(self, f): P = Parallel(p_iter='fork', ncpus=1, timeout=self.timeout, verbose=self.verbose) g = P(f) + def h(*args, **kwds): return list(g([(args, kwds)]))[0][1] return h + def fork(f=None, timeout=0, verbose=False): """ Decorate a function so that when called it runs in a forked diff --git a/src/sage/plot/hyperbolic_polygon.py b/src/sage/plot/hyperbolic_polygon.py index dc43a5a712d..11a090a0fad 100644 --- a/src/sage/plot/hyperbolic_polygon.py +++ b/src/sage/plot/hyperbolic_polygon.py @@ -308,6 +308,7 @@ def hyperbolic_polygon(pts, model="UHP", resolution=200, **options): xlist = [p[0] for p in pts] ylist = [p[1] for p in pts] zlist = [p[2] for p in pts] + def region(x, y, z): return _winding_number(arc_points, (x, y, z)) != 0 g = g + implicit_plot3d(x**2 + y**2 - z**2 == -1, diff --git a/src/sage/plot/plot.py b/src/sage/plot/plot.py index 89f308fa258..262948c10a9 100644 --- a/src/sage/plot/plot.py +++ b/src/sage/plot/plot.py @@ -690,7 +690,7 @@ def SelectiveFormatter(formatter, skip_values): from matplotlib.ticker import Formatter class _SelectiveFormatterClass(Formatter): - def __init__(self, formatter,skip_values): + def __init__(self, formatter, skip_values): """ Initialize a SelectiveFormatter object. @@ -717,6 +717,7 @@ def __init__(self, formatter,skip_values): """ self.formatter=formatter self.skip_values=skip_values + def set_locs(self, locs): """ Set the locations for the ticks that are not skipped. @@ -729,6 +730,7 @@ def set_locs(self, locs): sage: formatter.set_locs([i*100 for i in range(10)]) """ self.formatter.set_locs([l for l in locs if l not in self.skip_values]) + def __call__(self, x, *args, **kwds): """ Return the format for tick val *x* at position *pos* diff --git a/src/sage/plot/plot3d/plot3d.py b/src/sage/plot/plot3d/plot3d.py index 5fa37f21459..44620a0edcb 100644 --- a/src/sage/plot/plot3d/plot3d.py +++ b/src/sage/plot/plot3d/plot3d.py @@ -404,17 +404,19 @@ def to_cartesian(self, func, params=None): params = ['u', 'v'] else: raise ValueError("function is not callable") + def subs_func(t): # We use eval so that the lambda function has the same # variable names as the original function - ll="""lambda {x},{y}: t.subs({{ + ll = """lambda {x},{y}: t.subs({{ dep_var_dummy: float(func({x}, {y})), indep_var_dummies[0]: float({x}), indep_var_dummies[1]: float({y}) }})""".format(x=params[0], y=params[1]) - return eval(ll,dict(t=t, func=func, dep_var_dummy=dep_var_dummy, - indep_var_dummies=indep_var_dummies)) - return [subs_func(_) for _ in transformation] + return eval(ll, dict(t=t, func=func, + dep_var_dummy=dep_var_dummy, + indep_var_dummies=indep_var_dummies)) + return [subs_func(m) for m in transformation] def __repr__(self): """ diff --git a/src/sage/quadratic_forms/quadratic_form__theta.py b/src/sage/quadratic_forms/quadratic_form__theta.py index ba9bcebcd53..9fae946fae5 100644 --- a/src/sage/quadratic_forms/quadratic_form__theta.py +++ b/src/sage/quadratic_forms/quadratic_form__theta.py @@ -402,6 +402,7 @@ def theta_series_degree_2(Q, prec): for c in range(a, c_max + 1): for v1 in v_list[a]: v1_H = v1 * H + def B_v1(v): return v1_H * v2 for v2 in v_list[c]: diff --git a/src/sage/repl/ipython_kernel/widgets_sagenb.py b/src/sage/repl/ipython_kernel/widgets_sagenb.py index 8d49ec8c9de..2ce59d79a3b 100644 --- a/src/sage/repl/ipython_kernel/widgets_sagenb.py +++ b/src/sage/repl/ipython_kernel/widgets_sagenb.py @@ -264,6 +264,7 @@ def slider(vmin, vmax=None, step_size=None, default=None, label=None, display_va raise NotImplementedError("range_slider does not support a list of values") options = list(vmin) # Find default in options + def err(v): if v is default: return (-1, 0) diff --git a/src/sage/repl/rich_output/backend_ipython.py b/src/sage/repl/rich_output/backend_ipython.py index 2b816b96e6a..981ecdf2cb1 100644 --- a/src/sage/repl/rich_output/backend_ipython.py +++ b/src/sage/repl/rich_output/backend_ipython.py @@ -420,6 +420,7 @@ def threejs_offline_scripts(self): if sys.platform == 'cygwin': import cygwin + def normpath(p): return 'file:///' + cygwin.cygpath(p, 'w').replace('\\', '/') script = normpath(script) diff --git a/src/sage/rings/padics/local_generic.py b/src/sage/rings/padics/local_generic.py index a468efdbdec..bc2b6439f6f 100644 --- a/src/sage/rings/padics/local_generic.py +++ b/src/sage/rings/padics/local_generic.py @@ -380,6 +380,7 @@ def change(self, **kwds): for atr in ('print_mode', 'print_pos', 'print_sep', 'print_alphabet'): if atr in kwds: kwds[atr[6:]] = kwds.pop(atr) + def get_unramified_modulus(q, res_name): from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF return GF(q, res_name).modulus().change_ring(ZZ) diff --git a/src/sage/schemes/curves/zariski_vankampen.py b/src/sage/schemes/curves/zariski_vankampen.py index 46ebbbc708f..f2ab4c69307 100644 --- a/src/sage/schemes/curves/zariski_vankampen.py +++ b/src/sage/schemes/curves/zariski_vankampen.py @@ -1021,14 +1021,15 @@ def fundamental_group(f, simplified=True, projective=False): bm = braid_monodromy(f) n = bm[0].parent().strands() F = FreeGroup(n) + @parallel - def relation(x,b): - return x*b/x - relations = list(relation([(x,b) for x in F.gens() for b in bm])) + def relation(x, b): + return x * b / x + relations = list(relation([(x, b) for x in F.gens() for b in bm])) R = [r[1] for r in relations] if projective: R.append(prod(F.gens())) - G = F/R + G = F / R if simplified: return G.simplified() return G diff --git a/src/sage/schemes/riemann_surfaces/riemann_surface.py b/src/sage/schemes/riemann_surfaces/riemann_surface.py index db5017470c8..7ed22dcdd61 100644 --- a/src/sage/schemes/riemann_surfaces/riemann_surface.py +++ b/src/sage/schemes/riemann_surfaces/riemann_surface.py @@ -1808,10 +1808,11 @@ def local_N(ct, rt): ct_minus_rt = ct-rt two_rt = 2*rt + def integrand(t): - zt, wt = zwt(ct_minus_rt+t*two_rt) + zt, wt = zwt(ct_minus_rt + t * two_rt) dfdwt = self._fastcall_dfdw(zt, wt) - return V([h(zt,wt)/dfdwt for h in differentials]) + return V([h(zt, wt) / dfdwt for h in differentials]) output += two_rt*integrate_vector_N(integrand, self._prec, lN) diff --git a/src/sage/sets/image_set.py b/src/sage/sets/image_set.py index 587dd1a8014..8e9c48ce686 100644 --- a/src/sage/sets/image_set.py +++ b/src/sage/sets/image_set.py @@ -65,6 +65,7 @@ def __init__(self, map, domain_subset, *, category=None, is_injective=None): if len(map.arguments()) != 1: domain = FreeModule(domain, len(map.arguments())) function = map + def map(arg): return function(*arg) else: diff --git a/src/sage/sets/real_set.py b/src/sage/sets/real_set.py index 0cf6f27fc28..5e4c0d0cb97 100644 --- a/src/sage/sets/real_set.py +++ b/src/sage/sets/real_set.py @@ -1129,6 +1129,7 @@ def __classcall__(cls, *args, **kwds): intervals.extend(arg._intervals) elif isinstance(arg, Expression) and arg.is_relational(): from operator import eq, ne, lt, gt, le, ge + def rel_to_interval(op, val): """ Internal helper function. diff --git a/src/sage/tensor/modules/free_module_tensor.py b/src/sage/tensor/modules/free_module_tensor.py index b9bfb79eeef..bbcc1ecb2e0 100644 --- a/src/sage/tensor/modules/free_module_tensor.py +++ b/src/sage/tensor/modules/free_module_tensor.py @@ -1149,6 +1149,7 @@ class :class:`~sage.tensor.modules.comp.Components` local_list = lol(ind_list, ind_step) # list of input parameters listParalInput = [(old_comp, ppinv, pp, n_con, rank, ii) for ii in local_list] + @parallel(p_iter='multiprocessing', ncpus=nproc) def paral_newcomp(old_comp, ppinv, pp, n_con, rank, local_list_ind): partial = [] diff --git a/src/sage_docbuild/ext/multidocs.py b/src/sage_docbuild/ext/multidocs.py index f91c7753ca3..39121ef90ac 100644 --- a/src/sage_docbuild/ext/multidocs.py +++ b/src/sage_docbuild/ext/multidocs.py @@ -205,6 +205,7 @@ def fix_path_html(app, pagename, templatename, ctx, event_arg): # def pathto(otheruri, resource=False, # baseuri=self.get_target_uri(pagename)): old_pathto = ctx['pathto'] + def sage_pathto(otheruri, *args, **opts): if otheruri in mustbefixed: otheruri = os.path.join("..", otheruri) From 8091a7b01b59dbf50b3fa0563db58fed15e9464d Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Thu, 2 Jun 2022 17:03:19 +0200 Subject: [PATCH 038/116] update memory allocator to 0.1.3 --- build/pkgs/memory_allocator/checksums.ini | 6 +++--- build/pkgs/memory_allocator/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/memory_allocator/checksums.ini b/build/pkgs/memory_allocator/checksums.ini index fe48843d873..c907031eac5 100644 --- a/build/pkgs/memory_allocator/checksums.ini +++ b/build/pkgs/memory_allocator/checksums.ini @@ -1,5 +1,5 @@ tarball=memory_allocator-VERSION.tar.gz -sha1=7721219be84207f6112e118fc79af0c2729fca34 -md5=868753a09c44194cba303db89cca4396 -cksum=16627262 +sha1=1a874de2674a1948797de109adfd1f56193e153a +md5=c3a5d0f5acf896eec84266964a8aec0e +cksum=3431157422 upstream_url=https://pypi.io/packages/source/m/memory_allocator/memory_allocator-VERSION.tar.gz diff --git a/build/pkgs/memory_allocator/package-version.txt b/build/pkgs/memory_allocator/package-version.txt index 17e51c385ea..b1e80bb2480 100644 --- a/build/pkgs/memory_allocator/package-version.txt +++ b/build/pkgs/memory_allocator/package-version.txt @@ -1 +1 @@ -0.1.1 +0.1.3 From 5f5479b1f0cdfb5d2769783fe5e474dd475063bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 2 Jun 2022 19:09:27 +0200 Subject: [PATCH 039/116] fix E306 in rings/ and algebras/ --- src/sage/algebras/askey_wilson.py | 2 ++ src/sage/algebras/clifford_algebra.py | 1 + src/sage/algebras/free_algebra.py | 1 + src/sage/algebras/free_algebra_element.py | 3 ++- .../algebras/hecke_algebras/ariki_koike_algebra.py | 2 ++ src/sage/algebras/lie_algebras/heisenberg.py | 3 ++- .../algebras/lie_algebras/poincare_birkhoff_witt.py | 5 ++++- .../algebras/lie_algebras/symplectic_derivation.py | 3 +++ src/sage/algebras/lie_algebras/verma_module.py | 1 + src/sage/algebras/q_system.py | 2 ++ src/sage/algebras/quantum_groups/fock_space.py | 4 ++++ src/sage/algebras/rational_cherednik_algebra.py | 1 + src/sage/algebras/weyl_algebra.py | 4 ++++ src/sage/rings/asymptotic/asymptotic_ring.py | 5 ++++- src/sage/rings/asymptotic/misc.py | 1 + src/sage/rings/function_field/order.py | 5 +++-- src/sage/rings/function_field/place.py | 4 ++++ src/sage/rings/lazy_series.py | 12 +++++++++++- src/sage/rings/polynomial/laurent_polynomial_ring.py | 2 ++ 19 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/sage/algebras/askey_wilson.py b/src/sage/algebras/askey_wilson.py index 2ab7747322e..33014835bf0 100644 --- a/src/sage/algebras/askey_wilson.py +++ b/src/sage/algebras/askey_wilson.py @@ -300,6 +300,7 @@ def _latex_term(self, t): """ if sum(t) == 0: return '1' + def exp(l, e): if e == 0: return '' @@ -338,6 +339,7 @@ def algebra_generators(self): [A, B, C, a, b, g] """ A = self.variable_names() + def build_monomial(g): exp = [0] * 6 exp[A.index(g)] = 1 diff --git a/src/sage/algebras/clifford_algebra.py b/src/sage/algebras/clifford_algebra.py index ff0065c5fcd..4f4030c5d0e 100644 --- a/src/sage/algebras/clifford_algebra.py +++ b/src/sage/algebras/clifford_algebra.py @@ -1963,6 +1963,7 @@ def lifted_bilinear_form(self, M): back are implemented, check if this is faster. """ R = self.base_ring() + def lifted_form(x, y): result = R.zero() for mx, cx in x: diff --git a/src/sage/algebras/free_algebra.py b/src/sage/algebras/free_algebra.py index 06cc97dc106..73ee20dd595 100644 --- a/src/sage/algebras/free_algebra.py +++ b/src/sage/algebras/free_algebra.py @@ -591,6 +591,7 @@ def _element_constructor_(self, x): if self.has_coerce_map_from(P): # letterplace versus generic ngens = P.ngens() M = self._indices + def exp_to_monomial(T): out = [] for i in range(len(T)): diff --git a/src/sage/algebras/free_algebra_element.py b/src/sage/algebras/free_algebra_element.py index 2748f4b5ed2..8b7c39873c6 100644 --- a/src/sage/algebras/free_algebra_element.py +++ b/src/sage/algebras/free_algebra_element.py @@ -150,7 +150,8 @@ def __call__(self, *x, **kwds): if kwds: p = self.parent() - def extract_from(kwds,g): + + def extract_from(kwds, g): for x in g: try: return kwds[x] diff --git a/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py b/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py index 7ca1bea8c2b..3cfb9c2c1d6 100644 --- a/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py +++ b/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py @@ -1688,6 +1688,7 @@ def _product_TT(self, kp, a, k, b): T[kp] = a + b return self._from_dict({(tuple(T), self._one_perm): one}, remove_zeros=False, coerce=False) + def key(exp): if exp > 0 or kp == 0: T = list(self._zero_tuple) @@ -1715,6 +1716,7 @@ def key(exp): T[kp] = a ret = {(tuple(T), s1): one} zero = self.base_ring().zero() + def T_index(exp, ind, i, indp): T = list(self._zero_tuple) T[ind] = exp diff --git a/src/sage/algebras/lie_algebras/heisenberg.py b/src/sage/algebras/lie_algebras/heisenberg.py index fa78659c35e..b2f81946a32 100644 --- a/src/sage/algebras/lie_algebras/heisenberg.py +++ b/src/sage/algebras/lie_algebras/heisenberg.py @@ -482,8 +482,9 @@ def basis(self): sage: L.basis()[(12, 'p')] p12 """ - S = cartesian_product([PositiveIntegers(), ['p','q']]) + S = cartesian_product([PositiveIntegers(), ['p', 'q']]) I = DisjointUnionEnumeratedSets([Set(['z']), S]) + def basis_elt(x): if isinstance(x, str): return self.monomial(x) diff --git a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py index c8e313581c6..34df1d3281f 100644 --- a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py +++ b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py @@ -343,6 +343,7 @@ def inv_supp(m): if isinstance(R, PoincareBirkhoffWittBasis): if self._g == R._g: I = self._indices + def basis_function(x): return self.prod(self.monomial(I.gen(g)**e) for g,e in x._sorted_items()) # TODO: this diagonal, but with a smaller indexing set... @@ -351,8 +352,10 @@ def basis_function(x): if coerce_map: I = self._indices lift = self.coerce_map_from(self._g) + def basis_function(x): - return self.prod(lift(coerce_map(g))**e for g,e in x._sorted_items()) + return self.prod(lift(coerce_map(g))**e + for g, e in x._sorted_items()) # TODO: this diagonal, but with a smaller indexing set... return R.module_morphism(basis_function, codomain=self) diff --git a/src/sage/algebras/lie_algebras/symplectic_derivation.py b/src/sage/algebras/lie_algebras/symplectic_derivation.py index 12d79fbc04c..afaf5561b80 100644 --- a/src/sage/algebras/lie_algebras/symplectic_derivation.py +++ b/src/sage/algebras/lie_algebras/symplectic_derivation.py @@ -137,6 +137,7 @@ def _repr_term(self, m): 'a1*a2*a5*b2' """ g = self._g + def label(i): return "a{}".format(i) if i <= g else "b{}".format(i-g) return "*".join(label(i) for i in reversed(m)) @@ -152,6 +153,7 @@ def _latex_term(self, m): 'a_{1} a_{2} a_{5} b_{2}' """ g = self._g + def label(i): return "a_{{{}}}".format(i) if i <= g else "b_{{{}}}".format(i-g) return " ".join(label(i) for i in reversed(m)) @@ -168,6 +170,7 @@ def _unicode_art_term(self, m): """ from sage.typeset.unicode_art import unicode_art, unicode_subscript g = self._g + def label(i): return "a{}".format(unicode_subscript(i)) if i <= g else "b{}".format(unicode_subscript(i-g)) return unicode_art("·".join(label(i) for i in reversed(m))) diff --git a/src/sage/algebras/lie_algebras/verma_module.py b/src/sage/algebras/lie_algebras/verma_module.py index 148aeb6a59e..2ba5da72c2c 100644 --- a/src/sage/algebras/lie_algebras/verma_module.py +++ b/src/sage/algebras/lie_algebras/verma_module.py @@ -563,6 +563,7 @@ def _homogeneous_component_f(self, d): f = {i: self._pbw(g) for i,g in enumerate(self._g.f())} basis = d.parent().basis() # Standard basis vectors ret = set() + def degree(m): m = m.dict() if not m: diff --git a/src/sage/algebras/q_system.py b/src/sage/algebras/q_system.py index bbbf71e42cf..3aea736244b 100644 --- a/src/sage/algebras/q_system.py +++ b/src/sage/algebras/q_system.py @@ -213,6 +213,7 @@ def _repr_term(self, t): """ if len(t) == 0: return '1' + def repr_gen(x): ret = 'Q^({})[{}]'.format(*(x[0])) if x[1] > 1: @@ -234,6 +235,7 @@ def _latex_term(self, t): """ if len(t) == 0: return '1' + def repr_gen(x): ret = 'Q^{{({})}}_{{{}}}'.format(*(x[0])) if x[1] > 1: diff --git a/src/sage/algebras/quantum_groups/fock_space.py b/src/sage/algebras/quantum_groups/fock_space.py index 33e9eb0d686..978a996125d 100644 --- a/src/sage/algebras/quantum_groups/fock_space.py +++ b/src/sage/algebras/quantum_groups/fock_space.py @@ -744,6 +744,7 @@ def _e(self, i): |[2, 1], [1], [1]> """ P = self.parent() + def N_left(la, x, i): return (sum(1 for y in P._addable(la, i) if P._above(x, y)) - sum(1 for y in P._removable(la, i) if P._above(x, y))) @@ -839,6 +840,7 @@ def _f(self, i): + q^2*|[3, 1], [1, 1, 1], [5, 2, 2]> """ P = self.parent() + def N_right(la, x, i): return (sum(1 for y in P._addable(la, i) if P._above(y, x)) - sum(1 for y in P._removable(la, i) if P._above(y, x))) @@ -1798,6 +1800,7 @@ def _f(self, i): |5> + |3, 2> + 2*q*|3, 1, 1> + q^2*|2, 2, 1> """ P = self.parent() + def N_right(la, x, i): return (sum(1 for y in P._addable(la, i) if P._above(y, x)) - sum(1 for y in P._removable(la, i) if P._above(y, x))) @@ -2173,6 +2176,7 @@ def _G_to_fock_basis(self, la, algorithm='GW'): if len(la) == k: x = la[-1] mu = _Partitions([p - x for p in la]) + def add_cols(nu): return _Partitions([ v + x for v in list(nu) + [0]*(k - len(nu)) ]) return fock.sum_of_terms((add_cols(nu), c) for nu,c in self._G_to_fock_basis(mu)) diff --git a/src/sage/algebras/rational_cherednik_algebra.py b/src/sage/algebras/rational_cherednik_algebra.py index 93965c63878..204fcfc6020 100644 --- a/src/sage/algebras/rational_cherednik_algebra.py +++ b/src/sage/algebras/rational_cherednik_algebra.py @@ -240,6 +240,7 @@ def algebra_generators(self): keys = ['a'+str(i) for i in self._cartan_type.index_set()] keys += ['s'+str(i) for i in self._cartan_type.index_set()] keys += ['ac'+str(i) for i in self._cartan_type.index_set()] + def gen_map(k): if k[0] == 's': i = int(k[1:]) diff --git a/src/sage/algebras/weyl_algebra.py b/src/sage/algebras/weyl_algebra.py index 21cf81c0b84..c43cc7839dd 100644 --- a/src/sage/algebras/weyl_algebra.py +++ b/src/sage/algebras/weyl_algebra.py @@ -204,6 +204,7 @@ def repr_factored(w, latex_output=False): if latex_output: def exp(e): return '^{{{}}}'.format(e) if e > 1 else '' + def repr_dx(k): total = sum(k) if total == 0: @@ -215,6 +216,7 @@ def repr_dx(k): else: def exp(e): return '^{}'.format(e) if e > 1 else '' + def repr_dx(k): return ''.join('*d{}{}'.format(g, exp(e)) for e, g in zip(k, gens) if e != 0) repr_x = repr @@ -259,6 +261,7 @@ def _repr_(self): """ if self.parent().options.factor_representation: return repr_factored(self, False) + def term(m): ret = '' for i, power in enumerate(m[0] + m[1]): @@ -301,6 +304,7 @@ def exp(e): def term(m): R = self.parent()._poly_ring + def half_term(mon, polynomial): total = sum(mon) if total == 0: diff --git a/src/sage/rings/asymptotic/asymptotic_ring.py b/src/sage/rings/asymptotic/asymptotic_ring.py index 8233d1f7cc4..64a35142397 100644 --- a/src/sage/rings/asymptotic/asymptotic_ring.py +++ b/src/sage/rings/asymptotic/asymptotic_ring.py @@ -1453,6 +1453,7 @@ def truncate(self, precision=None): return self summands = self.summands.copy() + def convert_terms(element): if convert_terms.count < precision: convert_terms.count += 1 @@ -1463,7 +1464,6 @@ def convert_terms(element): summands.map(convert_terms, topological=True, reverse=True) return self.parent()(summands, simplify=True, convert=False) - def exact_part(self): r""" Return the expansion consisting of all exact terms of this @@ -1864,6 +1864,7 @@ def __pow_number__(self, exponent, precision=None, check_convergence=False): pmax = self.parent()(max_elem)**exponent import itertools + def binomials(a): P = a.parent() a = a + 1 @@ -2910,6 +2911,7 @@ def compare_with_values(self, variable, function, values, "variable".format(expr)) elif len(vars) == 1: v = vars[0] + def function(arg): return expr.subs({v: arg}) else: @@ -3707,6 +3709,7 @@ def __classcall__(cls, growth_group=None, coefficient_ring=None, raise ValueError('%s is not a ring. Cannot continue.' % (coefficient_ring,)) strgens = tuple(str(g) for g in growth_group.gens_monomial()) + def format_names(N): return ('s ' if len(N) != 1 else ' ') + ', '.join("'%s'" % n for n in N) if names and not strgens: diff --git a/src/sage/rings/asymptotic/misc.py b/src/sage/rings/asymptotic/misc.py index 32ca1e90c1e..f639cfbdeed 100644 --- a/src/sage/rings/asymptotic/misc.py +++ b/src/sage/rings/asymptotic/misc.py @@ -148,6 +148,7 @@ def parent_to_repr_short(P): from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.rings.polynomial.multi_polynomial_ring_base import is_MPolynomialRing from sage.rings.power_series_ring import is_PowerSeriesRing + def abbreviate(P): try: return P._repr_short_() diff --git a/src/sage/rings/function_field/order.py b/src/sage/rings/function_field/order.py index 7b0841e235f..745690401cd 100644 --- a/src/sage/rings/function_field/order.py +++ b/src/sage/rings/function_field/order.py @@ -1266,8 +1266,9 @@ def __init__(self, field, ideal_class=FunctionFieldIdeal_polymod): row.append(self._coordinate_vector(basis[i] * basis[j])) self._mtable.append(row) - zero = vector(R._ring,n*[0]) - def mul_vecs(f,g): + zero = vector(R._ring, n * [0]) + + def mul_vecs(f, g): s = zero for i in range(n): if f[i].is_zero(): diff --git a/src/sage/rings/function_field/place.py b/src/sage/rings/function_field/place.py index eff0c07469f..190d0329efc 100644 --- a/src/sage/rings/function_field/place.py +++ b/src/sage/rings/function_field/place.py @@ -1046,8 +1046,10 @@ def candidates(): if name is None: name='s' K = k.extension(min_poly, names=name) + def from_W(e): return K(list(e)) + def to_W(e): return vector(K(e)) else: @@ -1059,8 +1061,10 @@ def to_W(e): W, from_W, to_W = K.vector_space(k, basis=[prim**i for i in range(deg)], map=True) else: # deg == 1 K = k + def from_W(e): return K(e[0]) + def to_W(e): return vector([e]) diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index 01b55b773f7..a07327a07da 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -1522,6 +1522,7 @@ def arcsin(self): """ from .lazy_series_ring import LazyLaurentSeriesRing P = LazyLaurentSeriesRing(self.base_ring(), "z", sparse=self.parent()._sparse) + def f(n): n = ZZ(n) if n % 2: @@ -1583,6 +1584,7 @@ def arctan(self): """ from .lazy_series_ring import LazyLaurentSeriesRing P = LazyLaurentSeriesRing(self.base_ring(), "z", sparse=self.parent()._sparse) + def f(n): n = ZZ(n) if n % 4 == 1: @@ -1704,6 +1706,7 @@ def tanh(self): from sage.arith.misc import bernoulli from .lazy_series_ring import LazyLaurentSeriesRing P = LazyLaurentSeriesRing(self.base_ring(), "z", sparse=self.parent()._sparse) + def f(n): n = ZZ(n) if n % 2: @@ -1734,6 +1737,7 @@ def coth(self): from sage.arith.misc import bernoulli from .lazy_series_ring import LazyLaurentSeriesRing P = LazyLaurentSeriesRing(self.base_ring(), "z", sparse=self.parent()._sparse) + def f(n): n = ZZ(n) if n % 2: @@ -1766,6 +1770,7 @@ def sech(self): from sage.combinat.combinat import euler_number from .lazy_series_ring import LazyLaurentSeriesRing P = LazyLaurentSeriesRing(self.base_ring(), "z", sparse=self.parent()._sparse) + def f(n): n = ZZ(n) if n % 2: @@ -1797,6 +1802,7 @@ def csch(self): from sage.arith.misc import bernoulli from .lazy_series_ring import LazyLaurentSeriesRing P = LazyLaurentSeriesRing(self.base_ring(), "z", sparse=self.parent()._sparse) + def f(n): n = ZZ(n) if n % 2: @@ -1831,6 +1837,7 @@ def arcsinh(self): """ from .lazy_series_ring import LazyLaurentSeriesRing P = LazyLaurentSeriesRing(self.base_ring(), "z", sparse=self.parent()._sparse) + def f(n): n = ZZ(n) if n % 2: @@ -1894,12 +1901,13 @@ def hypergeometric(self, a, b): from .lazy_series_ring import LazyLaurentSeriesRing from sage.arith.misc import rising_factorial P = LazyLaurentSeriesRing(self.base_ring(), "z", sparse=self.parent()._sparse) + def coeff(n, c): num = 1 for term in range(len(c)): num *= rising_factorial(c[term], n) return num - f = P(lambda n: coeff(n, a)/(coeff(n, b) * factorial(ZZ(n))), + f = P(lambda n: coeff(n, a) / (coeff(n, b) * factorial(ZZ(n))), valuation=0) return f(self) @@ -2823,6 +2831,7 @@ def __call__(self, g): raise ValueError("can only compose with a positive valuation series") g._coeff_stream._approximate_order = 2 # we assume that the valuation of self[i](g) is at least i + def coefficient(n): return sum(self[i] * (g**i)[n] for i in range(n+1)) coeff_stream = Stream_function(coefficient, P._coeff_ring, P._sparse, 1) @@ -3322,6 +3331,7 @@ def __call__(self, p): b, a = p if a < 0: raise ValueError("the leading coefficient must be positive") + def coefficient(m): m = ZZ(m) try: diff --git a/src/sage/rings/polynomial/laurent_polynomial_ring.py b/src/sage/rings/polynomial/laurent_polynomial_ring.py index 399fb2838b4..9f9948bb84b 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_ring.py +++ b/src/sage/rings/polynomial/laurent_polynomial_ring.py @@ -301,8 +301,10 @@ def _split_dict_(D, indices, group_by=None): class SplitDictError(ValueError): pass + def get(T, i): return T[i] if i is not None else 0 + def extract(T, indices): return tuple(get(T, i) for i in indices) From 56d0e0eb4677bfe03524f0bfb5bf3d5eaba3a4a5 Mon Sep 17 00:00:00 2001 From: DavidAyotte Date: Thu, 2 Jun 2022 22:45:11 -0400 Subject: [PATCH 040/116] src/sage/modular/overconvergent/hecke_series.py: fix failing doctests --- src/sage/modular/overconvergent/hecke_series.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sage/modular/overconvergent/hecke_series.py b/src/sage/modular/overconvergent/hecke_series.py index 36bf374095c..5b7f9de4419 100644 --- a/src/sage/modular/overconvergent/hecke_series.py +++ b/src/sage/modular/overconvergent/hecke_series.py @@ -234,9 +234,10 @@ def low_weight_generators(N,p,m,NN): sage: low_weight_generators(11, 5, 3, 10) ([[1 + 12*q^2 + 12*q^3 + 12*q^4 + 12*q^5 + 24*q^6 + 24*q^7 + 36*q^8 + 36*q^9 + O(q^10), q + 123*q^2 + 124*q^3 + 2*q^4 + q^5 + 2*q^6 + 123*q^7 + 123*q^9 + O(q^10)], - [q + 116*q^4 + 115*q^5 + 102*q^6 + 121*q^7 + 96*q^8 + 106*q^9 + O(q^10)]], 4) + [1 + O(q^10)]], + 4) """ - M = ModularFormsRing(N, base_ring=Zmod(p)) + M = ModularFormsRing(N) b = M.gen_forms(maxweight=8) From 8dc327a72bde1a0d20cd69fce80953bde13b7edc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 3 Jun 2022 21:13:41 +0200 Subject: [PATCH 041/116] get rid of "have_ring" in singular interface --- .../multi_polynomial_libsingular.pyx | 5 ---- .../polynomial/polynomial_modn_dense_ntl.pyx | 12 ++++---- .../polynomial/polynomial_rational_flint.pyx | 6 ++-- .../polynomial_singular_interface.py | 28 +++++++------------ .../rings/polynomial/polynomial_template.pxi | 6 ++-- src/sage/structure/sage_object.pyx | 4 +-- 6 files changed, 21 insertions(+), 40 deletions(-) diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index d09ddf63c58..d015d5cab30 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -5005,9 +5005,6 @@ cdef class MPolynomial_libsingular(MPolynomial): - ``singular`` - interpreter (default: ``singular_default``) - - ``have_ring`` - should the correct ring not be set in - SINGULAR first (default: ``False``) - EXAMPLES:: sage: P. = PolynomialRing(GF(127),3) @@ -5239,8 +5236,6 @@ cdef class MPolynomial_libsingular(MPolynomial): - ``variable`` - the derivative is taken with respect to variable - - ``have_ring`` - ignored, accepted for compatibility reasons - .. NOTE:: See also :meth:`derivative` EXAMPLES:: diff --git a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx index 2519b6e598d..44b957e0da1 100644 --- a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx @@ -368,9 +368,8 @@ cdef class Polynomial_dense_mod_n(Polynomial): self.__poly = ZZ_pX(v, self.parent().modulus()) # Polynomial_singular_repr stuff, copied due to lack of multiple inheritance - def _singular_(self, singular=singular_default, have_ring=False, force=False): - if not have_ring: - self.parent()._singular_(singular,force=force).set_ring() # this is expensive + def _singular_(self, singular=singular_default, force=False): + self.parent()._singular_(singular, force=force).set_ring() # this is expensive if self.__singular is not None: try: self.__singular._check_valid() @@ -378,11 +377,10 @@ cdef class Polynomial_dense_mod_n(Polynomial): return self.__singular except (AttributeError, ValueError): pass - return self._singular_init_(singular, have_ring=have_ring) + return self._singular_init_(singular) - def _singular_init_(self, singular=singular_default, have_ring=False, force=False): - if not have_ring: - self.parent()._singular_(singular,force=force).set_ring() # this is expensive + def _singular_init_(self, singular=singular_default, force=False): + self.parent()._singular_(singular, force=force).set_ring() # this is expensive self.__singular = singular(str(self)) return self.__singular diff --git a/src/sage/rings/polynomial/polynomial_rational_flint.pyx b/src/sage/rings/polynomial/polynomial_rational_flint.pyx index cfe230ad974..f6c89d97f52 100644 --- a/src/sage/rings/polynomial/polynomial_rational_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_rational_flint.pyx @@ -332,14 +332,13 @@ cdef class Polynomial_rational_flint(Polynomial): fmpq_poly_set(res.__poly, self.__poly) return res - def _singular_(self, singular=singular_default, have_ring=False): + def _singular_(self, singular=singular_default): """ Return a Singular representation of self. INPUT: - ``singular`` - Singular interpreter (default: default interpreter) - - ``have_ring`` - set to True if the ring was already set in Singular EXAMPLES:: @@ -348,8 +347,7 @@ cdef class Polynomial_rational_flint(Polynomial): sage: singular(f) 3*x^2+2*x+5 """ - if not have_ring: - self._parent._singular_(singular).set_ring() # Expensive! + self._parent._singular_(singular).set_ring() # Expensive! return singular(self._singular_init_()) cpdef list list(self, bint copy=True): diff --git a/src/sage/rings/polynomial/polynomial_singular_interface.py b/src/sage/rings/polynomial/polynomial_singular_interface.py index 37d7e155b1f..40b77534d19 100644 --- a/src/sage/rings/polynomial/polynomial_singular_interface.py +++ b/src/sage/rings/polynomial/polynomial_singular_interface.py @@ -452,24 +452,20 @@ class Polynomial_singular_repr: Due to the incompatibility of Python extension classes and multiple inheritance, this just defers to module-level functions. """ - def _singular_(self, singular=singular, have_ring=False): - return _singular_func(self, singular, have_ring) + def _singular_(self, singular=singular): + return _singular_func(self, singular) - def _singular_init_func(self, singular=singular, have_ring=False): - return _singular_init_func(self, singular, have_ring) + def _singular_init_func(self, singular=singular): + return _singular_init_func(self, singular) -def _singular_func(self, singular=singular, have_ring=False): +def _singular_func(self, singular=singular): """ Return Singular polynomial matching this polynomial. INPUT: - ``singular`` - Singular instance to use. - - ``have_ring`` - if True we will not attempt to set this element's ring as - the current Singular ring. This is useful to speed up a batch of - ``f._singular_()`` calls. However, it's dangerous as it might lead to wrong - results if another ring is ``singular.current_ring()``. (Default: False) EXAMPLES:: @@ -494,8 +490,7 @@ def _singular_func(self, singular=singular, have_ring=False): sage: R(h^20) == f^20 True """ - if not have_ring: - self.parent()._singular_(singular).set_ring() # this is expensive + self.parent()._singular_(singular).set_ring() # this is expensive try: self.__singular._check_valid() @@ -503,19 +498,16 @@ def _singular_func(self, singular=singular, have_ring=False): return self.__singular except (AttributeError, ValueError): pass -# return self._singular_init_(singular, have_ring=have_ring) - return _singular_init_func(self, singular, have_ring=have_ring) + return _singular_init_func(self, singular) + -def _singular_init_func(self, singular=singular, have_ring=False): +def _singular_init_func(self, singular=singular): """ Return corresponding Singular polynomial but enforce that a new instance is created in the Singular interpreter. Use ``self._singular_()`` instead. """ - if not have_ring: - self.parent()._singular_(singular).set_ring() # this is expensive - + self.parent()._singular_(singular).set_ring() # this is expensive self.__singular = singular(str(self)) - return self.__singular diff --git a/src/sage/rings/polynomial/polynomial_template.pxi b/src/sage/rings/polynomial/polynomial_template.pxi index 959b5b38c8e..7b4bc755b83 100644 --- a/src/sage/rings/polynomial/polynomial_template.pxi +++ b/src/sage/rings/polynomial/polynomial_template.pxi @@ -765,14 +765,13 @@ cdef class Polynomial_template(Polynomial): celement_truncate(&r.x, &self.x, n, (self)._cparent) return r - def _singular_(self, singular=singular_default, have_ring=False): + def _singular_(self, singular=singular_default): r""" Return Singular representation of this polynomial INPUT: - ``singular`` -- Singular interpreter (default: default interpreter) - - ``have_ring`` -- set to True if the ring was already set in Singular EXAMPLES:: @@ -781,6 +780,5 @@ cdef class Polynomial_template(Polynomial): sage: singular(f) 3*x^2+2*x-2 """ - if not have_ring: - self.parent()._singular_(singular).set_ring() #this is expensive + self.parent()._singular_(singular).set_ring() # this is expensive return singular(self._singular_init_()) diff --git a/src/sage/structure/sage_object.pyx b/src/sage/structure/sage_object.pyx index c932029f9de..466b0025db2 100644 --- a/src/sage/structure/sage_object.pyx +++ b/src/sage/structure/sage_object.pyx @@ -934,13 +934,13 @@ cdef class SageObject: I = sage.interfaces.r.r return self._interface_init_(I) - def _singular_(self, G=None, have_ring=False): + def _singular_(self, G=None): if G is None: import sage.interfaces.singular G = sage.interfaces.singular.singular return self._interface_(G) - def _singular_init_(self, have_ring=False): + def _singular_init_(self): import sage.interfaces.singular I = sage.interfaces.singular.singular return self._interface_init_(I) From aa7d2e4cad01772483add28e3e6c884809b4e9ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 5 Jun 2022 16:23:12 +0200 Subject: [PATCH 042/116] some better .join with no list inside --- src/sage/databases/findstat.py | 4 ++-- src/sage/doctest/sources.py | 5 ++-- src/sage/graphs/graph_database.py | 2 +- src/sage/groups/matrix_gps/matrix_group.py | 2 +- .../groups/perm_gps/permgroup_element.pyx | 5 ++-- src/sage/schemes/curves/closed_point.py | 2 +- src/sage/schemes/curves/curve.py | 6 ++--- src/sage/schemes/curves/projective_curve.py | 2 +- .../schemes/projective/projective_space.py | 2 +- src/sage/stats/time_series.pyx | 6 ++--- src/sage/symbolic/pynac_impl.pxi | 9 +++---- src/sage/topology/simplicial_set.py | 4 ++-- .../topology/simplicial_set_constructions.py | 24 +++++++++---------- 13 files changed, 38 insertions(+), 35 deletions(-) diff --git a/src/sage/databases/findstat.py b/src/sage/databases/findstat.py index 4a84ef1edb3..0e3941aa38f 100644 --- a/src/sage/databases/findstat.py +++ b/src/sage/databases/findstat.py @@ -4594,8 +4594,8 @@ def name(self, style="singular"): "DecoratedPermutations": _SupportedFindStatCollection(lambda x: DecoratedPermutation([v if v > 0 else (i if v == 0 else -i) for i, v in enumerate(literal_eval(x.replace("+","0").replace("-","-1")), 1)]), - lambda x: "[" + ",".join([str(v) if abs(v) != i else ("+" if v > 0 else "-") - for i, v in enumerate(x, 1)]) + "]", + lambda x: "[" + ",".join((str(v) if abs(v) != i else ("+" if v > 0 else "-") + for i, v in enumerate(x, 1))) + "]", DecoratedPermutations, lambda x: x.size(), lambda x: isinstance(x, DecoratedPermutation)), diff --git a/src/sage/doctest/sources.py b/src/sage/doctest/sources.py index f9470e14d2e..21fdd3b57cc 100644 --- a/src/sage/doctest/sources.py +++ b/src/sage/doctest/sources.py @@ -1556,10 +1556,11 @@ def parse_docstring(self, docstring, namespace, start): PythonStringSource = dynamic_class("sage.doctest.sources.PythonStringSource", (StringDocTestSource, PythonSource)) min_indent = self.parser._min_indent(docstring) - pysource = '\n'.join([l[min_indent:] for l in docstring.split('\n')]) + pysource = '\n'.join(l[min_indent:] for l in docstring.split('\n')) inner_source = PythonStringSource(self.basename, pysource, self.options, - self.printpath, lineno_shift=start+1) + self.printpath, + lineno_shift=start + 1) inner_doctests, _ = inner_source._create_doctests(namespace, True) safe_docstring = inner_source._neutralize_doctests(min_indent) outer_doctest = self.parser.get_doctest(safe_docstring, namespace, diff --git a/src/sage/graphs/graph_database.py b/src/sage/graphs/graph_database.py index b0a71370dc8..9db59191da7 100644 --- a/src/sage/graphs/graph_database.py +++ b/src/sage/graphs/graph_database.py @@ -666,7 +666,7 @@ def show(self, max_field_size=20, with_picture=False): """ relabel = {} for col in valid_kwds: - relabel[col] = ' '.join([word.capitalize() for word in col.split('_')]) + relabel[col] = ' '.join(word.capitalize() for word in col.split('_')) if re.search('SELECT .*degree_sequence.* FROM', self.__query_string__): format_cols = {'degree_sequence': data_to_degseq} diff --git a/src/sage/groups/matrix_gps/matrix_group.py b/src/sage/groups/matrix_gps/matrix_group.py index f2ce966c9ed..48cf2eb1af0 100644 --- a/src/sage/groups/matrix_gps/matrix_group.py +++ b/src/sage/groups/matrix_gps/matrix_group.py @@ -348,7 +348,7 @@ def _latex_(self): 0 & 1 \end{array}\right) \right\rangle """ - gens = ', '.join([latex(x) for x in self.gens()]) + gens = ', '.join(latex(x) for x in self.gens()) return '\\left\\langle %s \\right\\rangle' % gens def sign_representation(self, base_ring=None, side="twosided"): diff --git a/src/sage/groups/perm_gps/permgroup_element.pyx b/src/sage/groups/perm_gps/permgroup_element.pyx index 31693c20e4d..2c4977a8a84 100644 --- a/src/sage/groups/perm_gps/permgroup_element.pyx +++ b/src/sage/groups/perm_gps/permgroup_element.pyx @@ -1804,9 +1804,10 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): '(1,3)(2)' """ cycles = self.cycle_tuples(singletons) - if len(cycles) == 0: + if not cycles: return '()' - return ''.join([repr(c) for c in cycles]).replace(', ',',').replace(',)',')') + text = ''.join(repr(c) for c in cycles) + return text.replace(', ', ',').replace(',)', ')') def cycle_type(self, singletons=True, as_list=False): r""" diff --git a/src/sage/schemes/curves/closed_point.py b/src/sage/schemes/curves/closed_point.py index 003d140d4b0..abda0906c92 100644 --- a/src/sage/schemes/curves/closed_point.py +++ b/src/sage/schemes/curves/closed_point.py @@ -181,7 +181,7 @@ def _repr_(self): sage: pts[0] Point (x, y) """ - return "Point ({})".format(', '.join([repr(g) for g in self.prime_ideal().gens()])) + return "Point ({})".format(', '.join(repr(g) for g in self.prime_ideal().gens())) def curve(self): """ diff --git a/src/sage/schemes/curves/curve.py b/src/sage/schemes/curves/curve.py index f9cea384986..c08183d41d5 100644 --- a/src/sage/schemes/curves/curve.py +++ b/src/sage/schemes/curves/curve.py @@ -67,9 +67,9 @@ def _repr_(self): """ if self.defining_ideal().is_zero() and self.ambient_space().dimension() == 1: return "{} Line over {}".format(self._repr_type(), self.base_ring()) - else: - return "{} Curve over {} defined by {}".format(self._repr_type(), self.base_ring(), - ', '.join([str(x) for x in self.defining_polynomials()])) + return "{} Curve over {} defined by {}".format(self._repr_type(), + self.base_ring(), + ', '.join(str(x) for x in self.defining_polynomials())) def _repr_type(self): r""" diff --git a/src/sage/schemes/curves/projective_curve.py b/src/sage/schemes/curves/projective_curve.py index 2e69efabc54..ae96943fea7 100644 --- a/src/sage/schemes/curves/projective_curve.py +++ b/src/sage/schemes/curves/projective_curve.py @@ -2038,7 +2038,7 @@ def riemann_roch_basis(self, D): Dcoeffs.append(D.coefficient(coords[x[1]])) else: Dcoeffs.append(0) - G = singular(','.join([str(x) for x in Dcoeffs]), type='intvec') + G = singular(','.join(str(x) for x in Dcoeffs), type='intvec') # call singular's brill noether routine and return T = X2[1][2] T.set_ring() diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index c0673c112e1..1bd4540983e 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -853,7 +853,7 @@ def _repr_generic_point(self, v=None): """ if v is None: v = self.gens() - return '(%s)' % (" : ".join([repr(f) for f in v])) + return '(%s)' % (" : ".join(repr(f) for f in v)) def _latex_generic_point(self, v=None): """ diff --git a/src/sage/stats/time_series.pyx b/src/sage/stats/time_series.pyx index 7045ed8b09d..d20ae2db4a4 100644 --- a/src/sage/stats/time_series.pyx +++ b/src/sage/stats/time_series.pyx @@ -310,10 +310,10 @@ cdef class TimeSeries: if len(self) > max_print: v0 = self[:max_print//2] v1 = self[-max_print//2:] - return '[' + ', '.join([format%x for x in v0]) + ' ... ' + \ - ', '.join([format%x for x in v1]) + ']' + return '[' + ', '.join(format%x for x in v0) + ' ... ' + \ + ', '.join(format%x for x in v1) + ']' else: - return '[' + ', '.join([format%x for x in self]) + ']' + return '[' + ', '.join(format%x for x in self) + ']' def __len__(self): """ diff --git a/src/sage/symbolic/pynac_impl.pxi b/src/sage/symbolic/pynac_impl.pxi index fba8c3d1495..8d0a5d93cb8 100644 --- a/src/sage/symbolic/pynac_impl.pxi +++ b/src/sage/symbolic/pynac_impl.pxi @@ -598,7 +598,7 @@ def py_latex_function_pystring(id, args, fname_paren=False): olist = [name] # print the arguments from sage.misc.latex import latex - olist.extend([r'\left(', ', '.join([latex(x) for x in args]), + olist.extend([r'\left(', ', '.join(latex(x) for x in args), r'\right)']) return ''.join(olist) @@ -646,10 +646,11 @@ cdef stdstring* py_print_fderivative(unsigned id, params, - args -- arguments of the function. """ if all(tolerant_is_symbol(a) for a in args) and len(set(args)) == len(args): - diffvarstr = ', '.join([repr(args[i]) for i in params]) - py_res = ''.join(['diff(',py_print_function_pystring(id,args,False),', ',diffvarstr,')']) + diffvarstr = ', '.join(repr(args[i]) for i in params) + py_res = ''.join(['diff(', py_print_function_pystring(id, args, False), + ', ', diffvarstr, ')']) else: - ostr = ''.join(['D[', ', '.join([repr(int(x)) for x in params]), ']']) + ostr = ''.join(['D[', ', '.join(repr(int(x)) for x in params), ']']) fstr = py_print_function_pystring(id, args, True) py_res = ostr + fstr return string_from_pystr(py_res) diff --git a/src/sage/topology/simplicial_set.py b/src/sage/topology/simplicial_set.py index 882001ebed0..f91c292700e 100644 --- a/src/sage/topology/simplicial_set.py +++ b/src/sage/topology/simplicial_set.py @@ -868,7 +868,7 @@ def _repr_(self): s_1 s_0 v """ if self.degeneracies(): - degens = ' '.join(['s_{}'.format(i) for i in self.degeneracies()]) + degens = ' '.join(f's_{i}' for i in self.degeneracies()) return degens + ' {}'.format(self.nondegenerate()) return 'Delta^{}'.format(self._dim) @@ -903,7 +903,7 @@ def _latex_(self): else: simplex = "\\Delta^{{{}}}".format(self._dim) if self.degeneracies(): - degens = ' '.join(['s_{{{}}}'.format(i) for i in self.degeneracies()]) + degens = ' '.join(f's_{{{i}}}' for i in self.degeneracies()) return degens + ' ' + simplex return simplex diff --git a/src/sage/topology/simplicial_set_constructions.py b/src/sage/topology/simplicial_set_constructions.py index 5b192d019bc..615264c0362 100644 --- a/src/sage/topology/simplicial_set_constructions.py +++ b/src/sage/topology/simplicial_set_constructions.py @@ -523,10 +523,10 @@ def __init__(self, maps=None): continue simplex_factors = tuple(zip(simplices, tuple(degens))) - s = '(' + ', '.join(['{}'.format(_[0].apply_degeneracies(*_[1])) - for _ in simplex_factors]) + ')' - ls = '(' + ', '.join(['{}'.format(latex(_[0].apply_degeneracies(*_[1]))) - for _ in simplex_factors]) + ')' + s = '(' + ', '.join('{}'.format(_[0].apply_degeneracies(*_[1])) + for _ in simplex_factors) + ')' + ls = '(' + ', '.join('{}'.format(latex(_[0].apply_degeneracies(*_[1]))) + for _ in simplex_factors) + ')' simplex = AbstractSimplex(d, name=s, latex_name=ls) translate[simplex_factors] = simplex # Now compute the faces of simplex. @@ -968,7 +968,7 @@ def _repr_(self): sage: S2.product(K, B) S^2 x Klein bottle x Classifying space of Multiplicative Abelian group isomorphic to C2 """ - return ' x '.join([str(X) for X in self._factors]) + return ' x '.join(str(X) for X in self._factors) def _latex_(self): r""" @@ -983,7 +983,7 @@ def _latex_(self): sage: latex(S2.product(RPoo, S2)) S^{2} \times RP^{\infty} \times S^{2} """ - return ' \\times '.join([latex(X) for X in self._factors]) + return ' \\times '.join(latex(X) for X in self._factors) class ProductOfSimplicialSets_finite(ProductOfSimplicialSets, PullbackOfSimplicialSets_finite): @@ -1934,7 +1934,7 @@ def _repr_(self): Smash product: (S^1 ^ RP^4 ^ S^1) """ s = 'Smash product: (' - s += ' ^ '.join([str(X) for X in self._factors]) + s += ' ^ '.join(str(X) for X in self._factors) s += ')' return s @@ -1949,7 +1949,7 @@ def _latex_(self): sage: latex(S1.smash_product(RP4, S1)) S^{1} \wedge RP^{4} \wedge S^{1} """ - return ' \\wedge '.join([latex(X) for X in self._factors]) + return ' \\wedge '.join(latex(X) for X in self._factors) class WedgeOfSimplicialSets(PushoutOfSimplicialSets, Factors): @@ -2039,7 +2039,7 @@ def _repr_(self): Wedge: (Klein bottle v Klein bottle v Klein bottle) """ s = 'Wedge: (' - s += ' v '.join([str(X) for X in self._factors]) + s += ' v '.join(str(X) for X in self._factors) s += ')' return s @@ -2054,7 +2054,7 @@ def _latex_(self): sage: latex(S1.wedge(RP4, S1)) S^{1} \vee RP^{4} \vee S^{1} """ - return ' \\vee '.join([latex(X) for X in self._factors]) + return ' \\vee '.join(latex(X) for X in self._factors) class WedgeOfSimplicialSets_finite(WedgeOfSimplicialSets, PushoutOfSimplicialSets_finite): @@ -2245,7 +2245,7 @@ def _repr_(self): Disjoint union: (Torus u Torus u RP^3) """ s = 'Disjoint union: (' - s += ' u '.join([str(X) for X in self._factors]) + s += ' u '.join(str(X) for X in self._factors) s += ')' return s @@ -2260,7 +2260,7 @@ def _latex_(self): sage: latex(S1.disjoint_union(RP4, S1)) S^{1} \amalg RP^{4} \amalg S^{1} """ - return ' \\amalg '.join([latex(X) for X in self._factors]) + return ' \\amalg '.join(latex(X) for X in self._factors) class DisjointUnionOfSimplicialSets_finite(DisjointUnionOfSimplicialSets, From b1ce8d6cb361701b388e3c2c3be7e1c831ee85ff Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 8 May 2022 17:21:34 -0700 Subject: [PATCH 043/116] sage -t: Handle --optional=!FEATURE --- src/sage/doctest/control.py | 16 +++++++++++++++- src/sage/doctest/external.py | 4 ++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/sage/doctest/control.py b/src/sage/doctest/control.py index a9d11d0863e..f4947d5edce 100644 --- a/src/sage/doctest/control.py +++ b/src/sage/doctest/control.py @@ -398,6 +398,7 @@ def __init__(self, options, args): if options.verbose: options.show_skipped = True + options.disabled_optional = set() if isinstance(options.optional, str): s = options.optional.lower() options.optional = set(s.split(',')) @@ -421,10 +422,15 @@ def __init__(self, options, args): for system in package_systems()) # Check that all tags are valid for o in options.optional: - if not optionaltag_regex.search(o): + if o.startswith('!'): + if not optionaltag_regex.search(o[1:]): + raise ValueError('invalid optional tag {!r}'.format(o)) + options.disabled_optional.add(o[1:]) + elif not optionaltag_regex.search(o): raise ValueError('invalid optional tag {!r}'.format(o)) options.optional |= auto_optional_tags + options.optional -= options.disabled_optional self.options = options @@ -1340,6 +1346,14 @@ def run(self): self.log("Using --optional=" + self._optional_tags_string()) available_software._allow_external = self.options.optional is True or 'external' in self.options.optional + for o in self.options.disabled_optional: + try: + i = available_software._indices[o] + except KeyError: + pass + else: + available_software._seen[i] = -1 + self.log("Features to be detected: " + ','.join(available_software.detectable())) self.add_files() self.expand_files_into_sources() diff --git a/src/sage/doctest/external.py b/src/sage/doctest/external.py index 546835698e2..4667c1f1fb3 100644 --- a/src/sage/doctest/external.py +++ b/src/sage/doctest/external.py @@ -471,8 +471,8 @@ def detectable(self): Return the list of names of those features for which testing their presence is allowed. """ return [feature.name - for feature in self._features - if self._allow_external or feature not in self._external_features] + for feature, seen in zip(self._features, self._seen) + if seen >= 0 and (self._allow_external or feature not in self._external_features)] def seen(self): """ From a670ae8ac34dff7c29f84744463a1c4aeb6892d4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 8 May 2022 17:38:42 -0700 Subject: [PATCH 044/116] src/bin/sage-runtests: Update documentation of --optional --- src/bin/sage-runtests | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/bin/sage-runtests b/src/bin/sage-runtests index 1976bcee5d8..c1f0aee2c18 100755 --- a/src/bin/sage-runtests +++ b/src/bin/sage-runtests @@ -43,13 +43,14 @@ if __name__ == "__main__": # By default, include all tests marked 'sagemath_doc_html' -- see # https://trac.sagemath.org/ticket/25345 and # https://trac.sagemath.org/ticket/26110: - parser.add_argument("--optional", metavar="PKGS", default=_get_optional_defaults(), - help='only run tests including one of the "# optional" tags listed in PKGS; ' + parser.add_argument("--optional", metavar="FEATURES", default=_get_optional_defaults(), + help='only run tests including one of the "# optional" tags listed in FEATURES (separated by commas); ' 'if "sage" is listed, will also run the standard doctests; ' 'if "sagemath_doc_html" is listed, will also run the tests relying on the HTML documentation; ' - 'if "optional" is listed, will also run tests for installed optional (new-style) packages; ' + 'if "optional" is listed, will also run tests for installed optional packages or detected features; ' 'if "external" is listed, will also run tests for available external software; ' - 'if set to "all", then all tests will be run') + 'if set to "all", then all tests will be run; ' + 'use "!FEATURE" to disable FEATURE') parser.add_argument("--randorder", type=int, metavar="SEED", help="randomize order of tests") parser.add_argument("--random-seed", dest="random_seed", type=int, metavar="SEED", help="random seed (integer) for fuzzing doctests", default=os.environ.get("SAGE_DOCTEST_RANDOM_SEED")) From ba86146e5a5e3308026aac49d87d2716a80c6a93 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 5 Jun 2022 11:23:43 -0700 Subject: [PATCH 045/116] src/bin/sage-runtests --help: Say that ! needs to be quoted --- src/bin/sage-runtests | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bin/sage-runtests b/src/bin/sage-runtests index c1f0aee2c18..75e2119c99a 100755 --- a/src/bin/sage-runtests +++ b/src/bin/sage-runtests @@ -50,7 +50,8 @@ if __name__ == "__main__": 'if "optional" is listed, will also run tests for installed optional packages or detected features; ' 'if "external" is listed, will also run tests for available external software; ' 'if set to "all", then all tests will be run; ' - 'use "!FEATURE" to disable FEATURE') + 'use "!FEATURE" to disable tests marked "# optional - FEATURE". ' + 'Note that "!" needs to be quoted or escaped in the shell.') parser.add_argument("--randorder", type=int, metavar="SEED", help="randomize order of tests") parser.add_argument("--random-seed", dest="random_seed", type=int, metavar="SEED", help="random seed (integer) for fuzzing doctests", default=os.environ.get("SAGE_DOCTEST_RANDOM_SEED")) From 8de8827ed0fd5a864c9e0b99da7016be8cf4e279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 6 Jun 2022 08:41:16 +0200 Subject: [PATCH 046/116] a few more tweaks in nu-Tamari --- src/sage/combinat/nu_dyck_word.py | 15 ++++++--------- src/sage/combinat/nu_tamari_lattice.py | 5 +---- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/sage/combinat/nu_dyck_word.py b/src/sage/combinat/nu_dyck_word.py index 503b1e00fe5..b319f1326fe 100644 --- a/src/sage/combinat/nu_dyck_word.py +++ b/src/sage/combinat/nu_dyck_word.py @@ -1368,15 +1368,12 @@ def __iter__(self, N=[], D=[], i=None, X=None): """ # Define successor function for recursion def transpose_close_open(N): - return [self.element_class(self, - N._list[0:k-1] - + list(reversed(N._list[k-1:k+1])) - + N._list[k+1:]) - for k, v in enumerate(N._list) - if k > 0 - and v == ndw_open_symbol - and N._list[k-1] == ndw_close_symbol - ] + for k, v in enumerate(N._list): + if k > 0 and v == ndw_open_symbol: + w = N._list[k - 1] + if w == ndw_close_symbol: + new = N._list[:k - 1] + [v, w] + N._list[k + 1:] + yield self.element_class(self, new) RES = RecursivelyEnumeratedSet([self.element_class(self, self._nu)], transpose_close_open) diff --git a/src/sage/combinat/nu_tamari_lattice.py b/src/sage/combinat/nu_tamari_lattice.py index f6cb83bbd5b..e90fc4d6791 100644 --- a/src/sage/combinat/nu_tamari_lattice.py +++ b/src/sage/combinat/nu_tamari_lattice.py @@ -66,7 +66,7 @@ def NuTamariLattice(nu): OUTPUT: - - a finite lattice + a finite lattice The elements of the lattice are :func:`\nu-Dyck paths` weakly above @@ -88,11 +88,8 @@ def NuTamariLattice(nu): Finite lattice containing 14 elements sage: NuTamariLattice([1,0,1,0,1,0,0,0,1]) Finite lattice containing 24 elements - """ - NDW = NuDyckWords(nu) - covers = [] elements = [] height = NDW[0].height() From 0f5876a1234d0465abdeb87a1384f5b023a010db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 7 Jun 2022 10:40:26 +0200 Subject: [PATCH 047/116] adding interface to Pari L-function for genus 2 curves --- src/sage/lfunctions/pari.py | 47 +++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/sage/lfunctions/pari.py b/src/sage/lfunctions/pari.py index 34959343cff..0bf997d7361 100644 --- a/src/sage/lfunctions/pari.py +++ b/src/sage/lfunctions/pari.py @@ -325,6 +325,8 @@ def lfun_eta_quotient(scalings, exponents): """ Return the L-function of an eta-quotient. + This uses :pari:`lfunetaquo`. + INPUT: - scalings -- a list of integers, the scaling factors @@ -372,6 +374,8 @@ def lfun_quadratic_form(qf): """ Return the L-function of a positive definite quadratic form. + This uses :pari:`lfunqf`. + EXAMPLES:: sage: from sage.lfunctions.pari import lfun_quadratic_form, LFunction @@ -385,6 +389,49 @@ def lfun_quadratic_form(qf): return pari.lfunqf(qf.matrix()) +def lfun_genus2(C): + """ + Return the L-function of a curve of genus 2. + + INPUT: + + - ``C`` -- hyperelliptic curve of genus 2 + + Currently, the model needs to be minimal at 2. + + This uses :pari:`lfungenus2`. + + EXAMPLES:: + + sage: from sage.lfunctions.pari import lfun_genus2, LFunction + sage: x = polygen(QQ, 'x') + sage: C = HyperellipticCurve(x^5 + x + 1) + sage: L = LFunction(lfun_genus2(C)) + ... + sage: L(3) + 0.965946926261520 + + sage: C = HyperellipticCurve(x^2+x, x^3+x^2+1) + sage: L = LFunction(lfun_genus2(C)) + sage: L(2) + 0.364286342944359 + + TESTS:: + + sage: x = polygen(QQ, 'x') + sage: H = HyperellipticCurve(x^15 + x + 1) + sage: L = LFunction(lfun_genus2(H)) + Traceback (most recent call last): + ... + ValueError: curve must be hyperelliptic of genus 2 + """ + from sage.schemes.hyperelliptic_curves.hyperelliptic_g2 import HyperellipticCurve_g2 as hyp_g2 + if not isinstance(C, hyp_g2): + raise ValueError('curve must be hyperelliptic of genus 2') + P, Q = C.hyperelliptic_polynomials() + return pari.lfungenus2(P) if not Q else pari.lfungenus2([P, Q]) + + class LFunction(SageObject): r""" Build the L-function from a PARI L-function. From c0114095a3706112f5bda36fa5b6a50ce97b9c94 Mon Sep 17 00:00:00 2001 From: Dave Witte Morris Date: Wed, 8 Jun 2022 13:07:28 -0600 Subject: [PATCH 048/116] trac 33962: fix legendre polynomial --- src/sage/functions/orthogonal_polys.py | 7 +++++++ src/sage/symbolic/ginac/inifcns_orthopoly.cpp | 13 ++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/sage/functions/orthogonal_polys.py b/src/sage/functions/orthogonal_polys.py index aace3cc767d..ade05522bdd 100644 --- a/src/sage/functions/orthogonal_polys.py +++ b/src/sage/functions/orthogonal_polys.py @@ -1290,6 +1290,13 @@ class Func_legendre_P(GinacFunction): Traceback (most recent call last): ... RuntimeError: derivative w.r.t. to the index is not supported yet + + TESTS:: + + # verify that :trac:`33962` is fixed + sage: [legendre_P(n, 0) for n in range(-10, 10)] + [0, 35/128, 0, -5/16, 0, 3/8, 0, -1/2, 0, 1, + 1, 0, -1/2, 0, 3/8, 0, -5/16, 0, 35/128, 0] """ def __init__(self): r""" diff --git a/src/sage/symbolic/ginac/inifcns_orthopoly.cpp b/src/sage/symbolic/ginac/inifcns_orthopoly.cpp index 6693a044098..a591cb4cd7c 100644 --- a/src/sage/symbolic/ginac/inifcns_orthopoly.cpp +++ b/src/sage/symbolic/ginac/inifcns_orthopoly.cpp @@ -185,10 +185,17 @@ static ex legp_eval(const ex& n_, const ex& x) if (n.info(info_flags::even)) { if (is_exactly_a(n)) { const numeric& numn = ex_to(n); - return (numn+*_num_1_p).factorial() / numn.mul(*_num1_2_p).factorial().pow_intexp(2) * numn / _num2_p->pow_intexp(numn.to_int()); + return (numn + *_num_1_p).factorial() + / numn.mul(*_num1_2_p).factorial().pow_intexp(2) + * numn + / _num2_p->pow_intexp(numn.to_int()) + * _num_1_p->pow_intexp(numn.mul(*_num1_2_p).to_int()); } - return gamma(n) / pow(gamma(n/_ex2), - _ex2) / pow(_ex2, n-_ex2) / n; + return gamma(n) + / pow(gamma(n / _ex2), _ex2) + / pow(_ex2, n - _ex2) + / n + * pow(_ex_1, n / _ex2); } } if (is_exactly_a(n) From 0b6382da3b8714b10c48f1ce55ba2ff0f55e7623 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Thu, 9 Jun 2022 09:50:15 +0800 Subject: [PATCH 049/116] more efficient algorithm for square roots modulo 2^n --- src/sage/rings/finite_rings/integer_mod.pyx | 110 +++++++++++++------- 1 file changed, 75 insertions(+), 35 deletions(-) diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index 0489e50b1bc..401bd3cd794 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -75,7 +75,7 @@ from cpython.int cimport * from cpython.list cimport * from cpython.ref cimport * -from libc.math cimport log, ceil +from libc.math cimport log2, ceil from sage.libs.gmp.all cimport * @@ -1116,9 +1116,8 @@ cdef class IntegerMod_abstract(FiniteRingElement): them `p`-adically and uses the CRT to find a square root mod `n`. - See also ``square_root_mod_prime_power`` and - ``square_root_mod_prime`` (in this module) for more - algorithmic details. + See also :meth:`square_root_mod_prime_power` and + :meth:`square_root_mod_prime` for more algorithmic details. EXAMPLES:: @@ -2900,9 +2899,8 @@ cdef class IntegerMod_int(IntegerMod_abstract): them `p`-adically and uses the CRT to find a square root mod `n`. - See also ``square_root_mod_prime_power`` and - ``square_root_mod_prime`` (in this module) for more - algorithmic details. + See also :meth:`square_root_mod_prime_power` and + :meth:`square_root_mod_prime` for more algorithmic details. EXAMPLES:: @@ -3891,66 +3889,108 @@ def square_root_mod_prime_power(IntegerMod_abstract a, p, e): Calculates the square root of `a`, where `a` is an integer mod `p^e`. - ALGORITHM: Perform `p`-adically by stripping off even - powers of `p` to get a unit and lifting - `\sqrt{unit} \bmod p` via Newton's method. + ALGORITHM: Compute `p`-adically by stripping off even powers of `p` + to get a unit and lifting `\sqrt{unit} \bmod p` via Newton's method + whenever `p` is odd and via + `\sqrt{1+y} = \sum_{k=0}^\infty \binom{1/2}{k} y^k` + for `p = 2`. AUTHORS: - Robert Bradshaw + - Lorenz Panny (2022): polynomial-time algorithm for `p = 2` EXAMPLES:: sage: from sage.rings.finite_rings.integer_mod import square_root_mod_prime_power - sage: a=Mod(17,2^20) - sage: b=square_root_mod_prime_power(a,2,20) + sage: a = Mod(17,2^20) + sage: b = square_root_mod_prime_power(a,2,20) sage: b^2 == a True :: - sage: a=Mod(72,97^10) - sage: b=square_root_mod_prime_power(a,97,10) + sage: a = Mod(72,97^10) + sage: b = square_root_mod_prime_power(a,97,10) sage: b^2 == a True sage: mod(100, 5^7).sqrt()^2 100 + + TESTS: + + A big example for the binary case (:trac:`33961`):: + + sage: y = Mod(-7, 2^777) + sage: hex(y.sqrt()^2 - y) + '0x0' + + Testing with random squares in random rings:: + + sage: p = random_prime(999) + sage: e = randrange(1, 999) + sage: x = Zmod(p^e).random_element() + sage: (x^2).sqrt()^2 == x^2 + True """ if a.is_zero() or a.is_one(): return a - if p == 2: - if e == 1: - return a - # TODO: implement something that isn't totally idiotic. - for x in a.parent(): - if x**2 == a: - return x - # strip off even powers of p cdef int i, val = a.lift().valuation(p) if val % 2 == 1: - raise ValueError("self must be a square.") + raise ValueError("self must be a square") if val > 0: unit = a._parent(a.lift() // p**val) else: unit = a - # find square root of unit mod p - x = unit.parent()(square_root_mod_prime(mod(unit, p), p)) + cdef int n + + if p == 2: + # squares in Z/2^e are of the form 4^n*(1+8*m) + if unit.lift() % 8 != 1: + raise ValueError("self must be a square") + + if unit == 1: + return a.parent()(one_Z << val//2) - # lift p-adically using Newton iteration - # this is done to higher precision than necessary except at the last step - one_half = ~(a._new_c_from_long(2)) - # need at least (e - val//2) p-adic digits of precision, which doubles - # at each step - cdef int n = ceil(log(e - val//2)/log(2)) - for i in range(n): - x = (x+unit/x) * one_half + # sqrt(1+y) = sum_{k=0}^{oo} binomial(1/2,k) y^k + y = unit - 1 + v = y.valuation(2) + y >>= v + + # 2-valuation of y^k / binomial(1/2,k) is >= (v-2)*k + n = 1 + (e + v-3) // (v-2) + + t = a.parent().one() # unit part + s = 0 # shift + + x = a.parent().one() + for i in range(1, n): + d = Integer(i) << 1 + c = 3 - d + t *= y * c.prime_to_m_part(2) / d.prime_to_m_part(2) + s += v + c.valuation(2) - d.valuation(2) +# assert t.is_unit() and s >= 0 + x += t << s + + else: + # find square root of unit mod p + x = unit.parent()(square_root_mod_prime(mod(unit, p), p)) + + # lift p-adically using Newton iteration + # this is done to higher precision than necessary except at the last step + one_half = ~(a._new_c_from_long(2)) + # need at least (e - val//2) p-adic digits of precision, which doubles + # at each step + n = ceil(log2(e - val//2)) + for i in range(n): + x = (x + unit/x) * one_half # multiply in powers of p (if any) if val > 0: - x *= p**(val // 2) + x *= p**(val//2) return x cpdef square_root_mod_prime(IntegerMod_abstract a, p=None): @@ -4010,7 +4050,7 @@ cpdef square_root_mod_prime(IntegerMod_abstract a, p=None): p = Integer(p) cdef int p_mod_16 = p % 16 - cdef double bits = log(float(p))/log(2) + cdef double bits = log2(float(p)) cdef long r, m cdef Integer resZ From 975f28a911fa54085a339255944527923453ac19 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 9 Jun 2022 08:21:39 +0200 Subject: [PATCH 050/116] 33965: initial --- src/sage/knots/link.py | 59 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index c6680df23c5..b70a6638cb6 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -1958,6 +1958,65 @@ def conway_polynomial(self): conway += coeff * t_poly**M return conway + def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ): + r""" + Return the Khovanov polynomial of ``self``. This is the Poincaré + polynomial of the Khovanov homology (in characteristic zero). + + INPUT: + + - ``var1`` -- (default: ``'q'``) the first variable. Its exponents + give the (torsion free) rank of the height of Khovanov homology + - ``var2`` -- (default: ``'t'``) the second variable. Its exponents + give the (torsion free) rank of the degree of Khovanov homology + - ``base_ring`` -- (default: ``ZZ``) the ring of the polynomial's + coefficients + + OUTPUT: + + A two variate Laurent Polynomial over the ``base_ring``, more precisely an + instance of :class:`~sage.rings.polynomial.laurent_polynomial.LaurentPolynomial`. + + EXAMPLES:: + + sage: K = Link([[[1, -2, 3, -1, 2, -3]],[-1, -1, -1]]) + sage: K.khovanov_polynomial() + q^-1 + q^-3 + q^-5*t^-2 + q^-9*t^-3 + sage: K.khovanov_polynomial(base_ring=GF(2)) + q^-1 + q^-3 + q^-5*t^-2 + q^-7*t^-2 + q^-9*t^-3 + + The figure eight knot:: + + sage: L = Link([[1, 6, 2, 7], [5, 2, 6, 3], [3, 1, 4, 8], [7, 5, 8, 4]]) + sage: L.khovanov_polynomial(var1='p') + p^5*t^2 + p*t + p + p^-1 + p^-1*t^-1 + p^-5*t^-2 + sage: L.khovanov_polynomial(var1='p', var2='s', base_ring=GF(4)) + p^5*s^2 + p^3*s^2 + p*s + p + p^-1 + p^-1*s^-1 + p^-3*s^-1 + p^-5*s^-2 + + The Hopf link:: + + sage: B = BraidGroup(2) + sage: b = B([1, 1]) + sage: K = Link(b) + sage: K.khovanov_polynomial() + q^6*t^2 + q^4*t^2 + q^2 + 1 + + .. SEEALSO:: :meth:`khovanov_homology` + """ + L = LaurentPolynomialRing(base_ring, [var1, var2]) + ch = base_ring.characteristic() + coeff = {} + kh = self.khovanov_homology() + from sage.rings.infinity import infinity + for h in kh: + for d in kh[h]: + H = kh[h][d] + gens = [g for g in H.gens() if g.order() == infinity or ch.divides(g.order())] + l = len(gens) + if l: + coeff[(h,d)]=l + return L(coeff) + def determinant(self): r""" Return the determinant of ``self``. From d6bf7a06eb15788636df3d9772b5bb57d22b1502 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 9 Jun 2022 08:32:10 +0200 Subject: [PATCH 051/116] 33965: small fix in docstring --- src/sage/knots/link.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index b70a6638cb6..f84756863fb 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -1961,7 +1961,7 @@ def conway_polynomial(self): def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ): r""" Return the Khovanov polynomial of ``self``. This is the Poincaré - polynomial of the Khovanov homology (in characteristic zero). + polynomial of the Khovanov homology. INPUT: From 99345e14d8182d09ac8da35a53af78964d77c2e8 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 9 Jun 2022 18:44:50 +0200 Subject: [PATCH 052/116] 33966: initial --- src/sage/knots/knotinfo.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/sage/knots/knotinfo.py b/src/sage/knots/knotinfo.py index 9a07897fdc0..45417f83757 100644 --- a/src/sage/knots/knotinfo.py +++ b/src/sage/knots/knotinfo.py @@ -611,6 +611,13 @@ def braid_notation(self, original=False): '{3, {-2, -2, -1, 2, -1}}' sage: L[L.items.braid_notation_old] '{4, {1, -2, 3, -2, -1, -2, -3, -2}}' + + TESTS: + + Check that :trac:`33966` is fixed:: + + sage: KnotInfo.K0_1.braid_notation() + (1,) """ braid_notation = self[self.items.braid_notation] if original: @@ -618,7 +625,7 @@ def braid_notation(self, original=False): if not braid_notation: # don't forget the unknot - return (1, -1) + return (1, ) braid_notation = eval_knotinfo(braid_notation) if type(braid_notation) is list: From 4ae68cc3cf82ab8d3ce5676044fae0fbfe3f8f38 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Jun 2022 14:38:55 -0700 Subject: [PATCH 053/116] foo From d242f96d3302bb9124dd5dc345e80b76e2f3caa3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Jun 2022 15:08:33 -0700 Subject: [PATCH 054/116] src/sage/doctest/control.py: Show also 'git describe --always --dirty' --- src/sage/doctest/control.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/sage/doctest/control.py b/src/sage/doctest/control.py index a9d11d0863e..f8e20be3016 100644 --- a/src/sage/doctest/control.py +++ b/src/sage/doctest/control.py @@ -1337,6 +1337,16 @@ def run(self): self.log("Git branch: " + branch, end="") except subprocess.CalledProcessError: pass + try: + ref = subprocess.check_output(["git", + "--git-dir=" + SAGE_ROOT_GIT, + "describe", + "--always", + "--dirty"]) + ref = ref.decode('utf-8') + self.log("Git ref: " + ref, end="") + except subprocess.CalledProcessError: + pass self.log("Using --optional=" + self._optional_tags_string()) available_software._allow_external = self.options.optional is True or 'external' in self.options.optional From f2468abaa1275cf58dd1ad5cafd111478d0df5ba Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Jun 2022 15:08:56 -0700 Subject: [PATCH 055/116] src/sage/doctest/control.py: Show SAGE_LOCAL, SAGE_VENV --- src/sage/doctest/control.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sage/doctest/control.py b/src/sage/doctest/control.py index f8e20be3016..85866a52e76 100644 --- a/src/sage/doctest/control.py +++ b/src/sage/doctest/control.py @@ -1322,7 +1322,7 @@ def run(self): return self.run_val_gdb() else: self.create_run_id() - from sage.env import SAGE_ROOT_GIT + from sage.env import SAGE_ROOT_GIT, SAGE_LOCAL, SAGE_VENV # SAGE_ROOT_GIT can be None on distributions which typically # only have the SAGE_LOCAL install tree but not SAGE_ROOT if (SAGE_ROOT_GIT is not None) and os.path.isdir(SAGE_ROOT_GIT): @@ -1348,6 +1348,8 @@ def run(self): except subprocess.CalledProcessError: pass + self.log(f"Running with {SAGE_LOCAL=} and {SAGE_VENV=}") + self.log("Using --optional=" + self._optional_tags_string()) available_software._allow_external = self.options.optional is True or 'external' in self.options.optional self.log("Features to be detected: " + ','.join(available_software.detectable())) From 94d9d75d07444fac858d9954992ccc89e6bcb349 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 10 Jun 2022 09:24:07 +0900 Subject: [PATCH 056/116] Fixing bad link in permutation.py. --- src/sage/combinat/permutation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py index 1dce5cdfa06..abfa7bd42fb 100644 --- a/src/sage/combinat/permutation.py +++ b/src/sage/combinat/permutation.py @@ -4760,7 +4760,7 @@ def remove_extra_fixed_points(self): identity permutation. This is mostly a helper method for - :module:`sage.combinat.schubert_polynomial`, where it is + :mod:`sage.combinat.schubert_polynomial`, where it is used to normalize finitary permutations of `\{1,2,3,\ldots\}`. From 4c0e7d75dbf60a415134689e9bd62c1e91042335 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Jun 2022 20:45:27 -0700 Subject: [PATCH 057/116] sage.algebras: Replace $...$ in docstrings by `...` --- src/sage/algebras/commutative_dga.py | 6 +- .../steenrod/steenrod_algebra_mult.py | 114 +++++++++--------- 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/sage/algebras/commutative_dga.py b/src/sage/algebras/commutative_dga.py index 327d7ae8f5e..ff80254caf9 100644 --- a/src/sage/algebras/commutative_dga.py +++ b/src/sage/algebras/commutative_dga.py @@ -2281,7 +2281,7 @@ def cohomology_generators(self, max_degree): ALGORITHM: - Reduce a basis of the `n`'th cohomology modulo all the degree $n$ + Reduce a basis of the `n`'th cohomology modulo all the degree `n` products of the lower degree cohomologies. EXAMPLES:: @@ -2292,12 +2292,12 @@ def cohomology_generators(self, max_degree): {1: [a], 2: [x], 3: [a*y]} The previous example has infinitely generated cohomology: - $a y^n$ is a cohomology generator for each $n$:: + `a y^n` is a cohomology generator for each `n`:: sage: B.cohomology_generators(10) {1: [a], 2: [x], 3: [a*y], 5: [a*y^2], 7: [a*y^3], 9: [a*y^4]} - In contrast, the corresponding algebra in characteristic $p$ + In contrast, the corresponding algebra in characteristic `p` has finitely generated cohomology:: sage: A3. = GradedCommutativeAlgebra(GF(3), degrees=(1,2,2)) diff --git a/src/sage/algebras/steenrod/steenrod_algebra_mult.py b/src/sage/algebras/steenrod/steenrod_algebra_mult.py index e2c1e888b66..0934c31f92d 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra_mult.py +++ b/src/sage/algebras/steenrod/steenrod_algebra_mult.py @@ -13,13 +13,13 @@ See Milnor's paper [Mil1958]_ for proofs, etc. -To multiply Milnor basis elements $\text{Sq}(r_1, r_2, ...)$ and -$\text{Sq}(s_1, s_2,...)$ at the prime 2, form all possible matrices -$M$ with rows and columns indexed starting at 0, with position (0,0) -deleted (or ignored), with $s_i$ equal to the sum of column $i$ for -each $i$, and with $r_j$ equal to the 'weighted' sum of row $j$. The -weights are as follows: elements from column $i$ are multiplied by -$2^i$. For example, to multiply $\text{Sq}(2)$ and $\text{Sq}(1,1)$, +To multiply Milnor basis elements `\text{Sq}(r_1, r_2, ...)` and +`\text{Sq}(s_1, s_2,...)` at the prime 2, form all possible matrices +`M` with rows and columns indexed starting at 0, with position (0,0) +deleted (or ignored), with `s_i` equal to the sum of column `i` for +each `i`, and with `r_j` equal to the 'weighted' sum of row `j`. The +weights are as follows: elements from column `i` are multiplied by +`2^i`. For example, to multiply `\text{Sq}(2)` and `\text{Sq}(1,1)`, form the matrices .. MATH:: @@ -34,18 +34,18 @@ 0 & 1 & 0 \end{Vmatrix} -(The $*$ is the ignored (0,0)-entry of the matrix.) For each such -matrix $M$, compute a multinomial coefficient, mod 2: for each -diagonal $\{m_{ij}: i+j=n\}$, compute $(\sum m_{i,j}!) / (m_{0,n}! -m_{1,n-1}! ... m_{n,0}!)$. Multiply these together for all $n$. (To +(The `*` is the ignored (0,0)-entry of the matrix.) For each such +matrix `M`, compute a multinomial coefficient, mod 2: for each +diagonal `\{m_{ij}: i+j=n\}`, compute `(\sum m_{i,j}!) / (m_{0,n}! +m_{1,n-1}! ... m_{n,0}!)`. Multiply these together for all `n`. (To compute this mod 2, view the entries of the matrix as their base 2 expansions; then this coefficient is zero if and only if there is some diagonal containing two numbers which have a summand in common in their base 2 expansion. For example, if 3 and 10 are in the same -diagonal, the coefficient is zero, because $3=1+2$ and $10=2+8$: they +diagonal, the coefficient is zero, because `3=1+2` and `10=2+8`: they both have a summand of 2.) -Now, for each matrix with multinomial coefficient 1, let $t_n$ be +Now, for each matrix with multinomial coefficient 1, let `t_n` be the sum of the nth diagonal in the matrix; then .. MATH:: @@ -53,12 +53,12 @@ \text{Sq}(r_1, r_2, ...) \text{Sq}(s_1, s_2, ...) = \sum \text{Sq}(t_1, t_2, ...) The function :func:`milnor_multiplication` takes as input two tuples -of non-negative integers, $r$ and $s$, which represent -$\text{Sq}(r)=\text{Sq}(r_1, r_2, ...)$ and -$\text{Sq}(s)=\text{Sq}(s_1, s_2, ...)$; it returns as output a -dictionary whose keys are tuples $t=(t_1, t_2, ...)$ of non-negative +of non-negative integers, `r` and `s`, which represent +`\text{Sq}(r)=\text{Sq}(r_1, r_2, ...)` and +`\text{Sq}(s)=\text{Sq}(s_1, s_2, ...)`; it returns as output a +dictionary whose keys are tuples `t=(t_1, t_2, ...)` of non-negative integers, and for each tuple the associated value is the coefficient -of $\text{Sq}(t)$ in the product formula. (Since we are working mod 2, +of `\text{Sq}(t)` in the product formula. (Since we are working mod 2, this coefficient is 1 -- if it is zero, the element is omitted from the dictionary altogether). @@ -66,9 +66,9 @@ As for the `p=2` case, see Milnor's paper [Mil1958]_ for proofs. -Fix an odd prime $p$. There are three steps to multiply Milnor basis -elements $Q_{f_1} Q_{f_2} ... \mathcal{P}(q_1, q_2, ...)$ and -$Q_{g_1} Q_{g_2} ... \mathcal{P}(s_1, s_2,...)$: first, use the formula +Fix an odd prime `p`. There are three steps to multiply Milnor basis +elements `Q_{f_1} Q_{f_2} ... \mathcal{P}(q_1, q_2, ...)` and +`Q_{g_1} Q_{g_2} ... \mathcal{P}(s_1, s_2,...)`: first, use the formula .. MATH:: @@ -77,9 +77,9 @@ + Q_{k+2} \mathcal{P}(q_1, q_2 - p^k, ...) + ... -Second, use the fact that the $Q_k$'s form an exterior algebra: $Q_k^2 = -0$ for all $k$, and if $i \neq j$, then $Q_i$ and $Q_j$ anticommute: -$Q_i Q_j = -Q_j Q_i$. After these two steps, the product is a linear +Second, use the fact that the `Q_k`'s form an exterior algebra: `Q_k^2 = +0` for all `k`, and if `i \neq j`, then `Q_i` and `Q_j` anticommute: +`Q_i Q_j = -Q_j Q_i`. After these two steps, the product is a linear combination of terms of the form .. MATH:: @@ -87,13 +87,13 @@ Q_{e_1} Q_{e_2} ... \mathcal{P}(r_1, r_2, ...) \mathcal{P}(s_1, s_2, ...). Finally, use Milnor matrices to multiply the pairs of -$\mathcal{P}(...)$ terms, as at the prime 2: form all possible -matrices $M$ with rows and columns indexed starting at 0, with -position (0,0) deleted (or ignored), with $s_i$ equal to the sum of -column $i$ for each $i$, and with $r_j$ equal to the weighted sum of -row $j$: elements from column $i$ are multiplied by $p^i$. For -example when $p=5$, to multiply $\mathcal{P}(5)$ and -$\mathcal{P}(1,1)$, form the matrices +`\mathcal{P}(...)` terms, as at the prime 2: form all possible +matrices `M` with rows and columns indexed starting at 0, with +position (0,0) deleted (or ignored), with `s_i` equal to the sum of +column `i` for each `i`, and with `r_j` equal to the weighted sum of +row `j`: elements from column `i` are multiplied by `p^i`. For +example when `p=5`, to multiply `\mathcal{P}(5)` and +`\mathcal{P}(1,1)`, form the matrices .. MATH:: @@ -107,30 +107,30 @@ 0 & 1 & 0 \end{Vmatrix} -For each such matrix $M$, compute a multinomial coefficient, mod $p$: -for each diagonal $\{m_{ij}: i+j=n\}$, compute $(\sum m_{i,j}!) / +For each such matrix `M`, compute a multinomial coefficient, mod `p`: +for each diagonal `\{m_{ij}: i+j=n\}`, compute `(\sum m_{i,j}!) / (m_{0,n}! m_{1,n-1}! ... m_{n,0}!)$. Multiply these together for -all $n$. +all `n`. -Now, for each matrix with nonzero multinomial coefficient $b_M$, let -$t_n$ be the sum of the $n$-th diagonal in the matrix; then +Now, for each matrix with nonzero multinomial coefficient `b_M`, let +`t_n` be the sum of the `n`-th diagonal in the matrix; then .. MATH:: \mathcal{P}(r_1, r_2, ...) \mathcal{P}(s_1, s_2, ...) = \sum b_M \mathcal{P}(t_1, t_2, ...) -For example when $p=5$, we have +For example when `p=5`, we have .. MATH:: \mathcal{P}(5) \mathcal{P}(1,1) = \mathcal{P}(6,1) + 2 \mathcal{P}(0,2). The function :func:`milnor_multiplication` takes as input two pairs of -tuples of non-negative integers, $(g,q)$ and $(f,s)$, which represent -$Q_{g_1} Q_{g_2} ... \mathcal{P}(q_1, q_2, ...)$ and -$Q_{f_1} Q_{f_2} ... \mathcal{P}(s_1, s_2, ...)$. It returns as output a -dictionary whose keys are pairs of tuples $(e,t)$ of non-negative +tuples of non-negative integers, `(g,q)` and `(f,s)`, which represent +`Q_{g_1} Q_{g_2} ... \mathcal{P}(q_1, q_2, ...)` and +`Q_{f_1} Q_{f_2} ... \mathcal{P}(s_1, s_2, ...)`. It returns as output a +dictionary whose keys are pairs of tuples `(e,t)` of non-negative integers, and for each tuple the associated value is the coefficient in the product formula. @@ -216,10 +216,10 @@ def milnor_multiplication(r,s): Dictionary of terms of the form (tuple: coeff), where 'tuple' is a tuple of non-negative integers and 'coeff' is 1. - This computes Milnor matrices for the product of $\text{Sq}(r)$ - and $\text{Sq}(s)$, computes their multinomial coefficients, and - for each matrix whose coefficient is 1, add $\text{Sq}(t)$ to the - output, where $t$ is the tuple formed by the diagonals sums from + This computes Milnor matrices for the product of `\text{Sq}(r)` + and `\text{Sq}(s)`, computes their multinomial coefficients, and + for each matrix whose coefficient is 1, add `\text{Sq}(t)` to the + output, where `t` is the tuple formed by the diagonals sums from the matrix. EXAMPLES:: @@ -327,11 +327,11 @@ def multinomial(list): None if the multinomial coefficient is 0, or sum of list if it is 1 - Given the input $[n_1, n_2, n_3, ...]$, this computes the + Given the input `[n_1, n_2, n_3, ...]`, this computes the multinomial coefficient $(n_1 + n_2 + n_3 + ...)! / (n_1! n_2! n_3! ...)$, mod 2. The method is roughly this: expand each - $n_i$ in binary. If there is a 1 in the same digit for any $n_i$ - and $n_j$ with $i\neq j$, then the coefficient is 0; otherwise, it + `n_i` in binary. If there is a 1 in the same digit for any `n_i` + and `n_j` with `i\neq j`, then the coefficient is 0; otherwise, it is 1. EXAMPLES:: @@ -387,8 +387,8 @@ def milnor_multiplication_odd(m1,m2,p): a pair of tuples, as for r and s, and 'coeff' is an integer mod p. This computes the product of the Milnor basis elements - $Q_{e_1} Q_{e_2} ... P(r_1, r_2, ...)$ and - $Q_{f_1} Q_{f_2} ... P(s_1, s_2, ...)$. + `Q_{e_1} Q_{e_2} ... P(r_1, r_2, ...)` and + `Q_{f_1} Q_{f_2} ... P(s_1, s_2, ...)`. EXAMPLES:: @@ -578,15 +578,15 @@ def multinomial_odd(list,p): Associated multinomial coefficient, mod p - Given the input $[n_1, n_2, n_3, ...]$, this computes the + Given the input `[n_1, n_2, n_3, ...]`, this computes the multinomial coefficient $(n_1 + n_2 + n_3 + ...)! / (n_1! n_2! - n_3! ...)$, mod $p$. The method is this: expand each $n_i$ in - base $p$: $n_i = \sum_j p^j n_{ij}$. Do the same for the sum of - the $n_i$'s, which we call $m$: $m = \sum_j p^j m_j$. Then the - multinomial coefficient is congruent, mod $p$, to the product of - the multinomial coefficients $m_j! / (n_{1j}! n_{2j}! ...)$. + n_3! ...)`, mod `p`. The method is this: expand each `n_i` in + base `p`: `n_i = \sum_j p^j n_{ij}`. Do the same for the sum of + the `n_i`'s, which we call `m`: `m = \sum_j p^j m_j`. Then the + multinomial coefficient is congruent, mod `p`, to the product of + the multinomial coefficients `m_j! / (n_{1j}! n_{2j}! ...)`. - Furthermore, any multinomial coefficient $m! / (n_1! n_2! ...)$ + Furthermore, any multinomial coefficient `m! / (n_1! n_2! ...)` can be computed as a product of binomial coefficients: it equals .. MATH:: From 7b6016f23cebfc749932b95945cbcf7fac7ee114 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Jun 2022 20:47:15 -0700 Subject: [PATCH 058/116] sage.calculus: Replace $...$ in docstrings by `...` --- src/sage/calculus/integration.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/calculus/integration.pyx b/src/sage/calculus/integration.pyx index da48f93de4c..f2125bbc2d7 100644 --- a/src/sage/calculus/integration.pyx +++ b/src/sage/calculus/integration.pyx @@ -111,12 +111,12 @@ def numerical_integral(func, a, b=None, EXAMPLES: - To integrate the function $x^2$ from 0 to 1, we do :: + To integrate the function `x^2` from 0 to 1, we do :: sage: numerical_integral(x^2, 0, 1, max_points=100) (0.3333333333333333, 3.700743415417188e-15) - To integrate the function $\sin(x)^3 + \sin(x)$ we do :: + To integrate the function `\sin(x)^3 + \sin(x)` we do :: sage: numerical_integral(sin(x)^3 + sin(x), 0, pi) (3.333333333333333, 3.700743415417188e-14) From 6e2d614510ae0c2236f041fbf0e3e0c4d1e5905d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Jun 2022 20:56:13 -0700 Subject: [PATCH 059/116] sage.categories, coding, databases: Replace $...$ in docstrings by `...` --- src/sage/categories/action.pyx | 2 +- src/sage/categories/algebra_modules.py | 2 +- src/sage/categories/coxeter_groups.py | 24 ++++++------- .../examples/commutative_additive_monoids.py | 2 +- .../commutative_additive_semigroups.py | 2 +- src/sage/categories/examples/semigroups.py | 2 +- .../categories/examples/semigroups_cython.pyx | 2 +- src/sage/categories/finite_monoids.py | 12 +++---- src/sage/categories/finite_semigroups.py | 10 +++--- src/sage/categories/g_sets.py | 4 +-- src/sage/categories/simplicial_sets.py | 10 +++--- src/sage/coding/binary_code.pyx | 34 +++++++++---------- src/sage/coding/guava.py | 2 +- src/sage/coding/reed_muller_code.py | 4 +-- src/sage/combinat/designs/covering_design.py | 2 +- src/sage/combinat/parallelogram_polyomino.py | 2 +- src/sage/combinat/posets/posets.py | 2 +- src/sage/combinat/words/word_generators.py | 2 +- src/sage/databases/cunningham_tables.py | 2 +- src/sage/databases/db_modular_polynomials.py | 6 ++-- 20 files changed, 64 insertions(+), 64 deletions(-) diff --git a/src/sage/categories/action.pyx b/src/sage/categories/action.pyx index 0a2085f6f52..b15cebde220 100644 --- a/src/sage/categories/action.pyx +++ b/src/sage/categories/action.pyx @@ -4,7 +4,7 @@ Group, ring, etc. actions on objects The terminology and notation used is suggestive of groups acting on sets, but this framework can be used for modules, algebras, etc. -A group action $G \times S \rightarrow S$ is a functor from $G$ to Sets. +A group action `G \times S \rightarrow S` is a functor from `G` to Sets. .. WARNING:: diff --git a/src/sage/categories/algebra_modules.py b/src/sage/categories/algebra_modules.py index d2e16148fd8..2472989723d 100644 --- a/src/sage/categories/algebra_modules.py +++ b/src/sage/categories/algebra_modules.py @@ -15,7 +15,7 @@ class AlgebraModules(Category_module): """ - The category of modules over a fixed algebra $A$. + The category of modules over a fixed algebra `A`. EXAMPLES:: diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 543f5a3763e..3f164f536a1 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -1924,8 +1924,8 @@ def canonical_matrix(self): def coset_representative(self, index_set, side='right'): r""" Return the unique shortest element of the Coxeter group - $W$ which is in the same left (resp. right) coset as - ``self``, with respect to the parabolic subgroup $W_I$. + `W` which is in the same left (resp. right) coset as + ``self``, with respect to the parabolic subgroup `W_I`. INPUT: @@ -2605,7 +2605,7 @@ def apply_demazure_product(self, element, side='right', def min_demazure_product_greater(self, element): r""" - Find the unique Bruhat-minimum element ``u`` such that ``v`` $\le$ ``w`` * ``u`` where ``v`` is ``self``, ``w`` is ``element`` and ``*`` is the Demazure product. + Find the unique Bruhat-minimum element ``u`` such that ``v`` `\le` ``w`` * ``u`` where ``v`` is ``self``, ``w`` is ``element`` and ``*`` is the Demazure product. INPUT: @@ -2651,13 +2651,13 @@ def deodhar_factor_element(self, w, index_set): - ``index_set`` is a subset of Dynkin nodes defining a parabolic subgroup ``W'`` of ``W`` It is assumed that ``v = self`` and ``w`` are minimum length coset representatives - for ``W/W'`` such that ``v`` $\le$ ``w`` in Bruhat order. + for ``W/W'`` such that ``v`` `\le` ``w`` in Bruhat order. OUTPUT: Deodhar's element ``f(v,w)`` is the unique element of ``W'`` such that, - for all ``v'`` and ``w'`` in ``W'``, ``vv'`` $\le$ ``ww'`` in ``W`` if and only if - ``v'`` $\le$ ``f(v,w) * w'`` in ``W'`` where ``*`` is the Demazure product. + for all ``v'`` and ``w'`` in ``W'``, ``vv'`` `\le` ``ww'`` in ``W`` if and only if + ``v'`` `\le` ``f(v,w) * w'`` in ``W'`` where ``*`` is the Demazure product. EXAMPLES:: @@ -2698,9 +2698,9 @@ def deodhar_factor_element(self, w, index_set): def deodhar_lift_up(self, w, index_set): r""" - Letting ``v = self``, given a Bruhat relation ``v W'`` $\le$ ``w W'`` among cosets + Letting ``v = self``, given a Bruhat relation ``v W'`` `\le` ``w W'`` among cosets with respect to the subgroup ``W'`` given by the Dynkin node subset ``index_set``, - returns the Bruhat-minimum lift ``x`` of ``wW'`` such that ``v`` $\le$ ``x``. + returns the Bruhat-minimum lift ``x`` of ``wW'`` such that ``v`` `\le` ``x``. INPUT: @@ -2710,7 +2710,7 @@ def deodhar_lift_up(self, w, index_set): OUTPUT: The unique Bruhat-minimum element ``x`` in ``W`` such that ``x W' = w W'`` - and ``v`` $\le$ ``x``. + and ``v`` `\le` ``x``. .. SEEALSO:: :meth:`sage.categories.coxeter_groups.CoxeterGroups.ElementMethods.deodhar_lift_down` @@ -2732,9 +2732,9 @@ def deodhar_lift_up(self, w, index_set): def deodhar_lift_down(self, w, index_set): r""" - Letting ``v = self``, given a Bruhat relation ``v W'`` $\ge$ ``w W'`` among cosets + Letting ``v = self``, given a Bruhat relation ``v W'`` `\ge` ``w W'`` among cosets with respect to the subgroup ``W'`` given by the Dynkin node subset ``index_set``, - returns the Bruhat-maximum lift ``x`` of ``wW'`` such that ``v`` $\ge$ ``x``. + returns the Bruhat-maximum lift ``x`` of ``wW'`` such that ``v`` `\ge` ``x``. INPUT: @@ -2744,7 +2744,7 @@ def deodhar_lift_down(self, w, index_set): OUTPUT: The unique Bruhat-maximum element ``x`` in ``W`` such that ``x W' = w W'`` - and ``v $\ge$ ``x``. + and ``v `\ge` ``x``. .. SEEALSO:: :meth:`sage.categories.coxeter_groups.CoxeterGroups.ElementMethods.deodhar_lift_up` diff --git a/src/sage/categories/examples/commutative_additive_monoids.py b/src/sage/categories/examples/commutative_additive_monoids.py index 01c2821f64f..229f66ae7e0 100644 --- a/src/sage/categories/examples/commutative_additive_monoids.py +++ b/src/sage/categories/examples/commutative_additive_monoids.py @@ -32,7 +32,7 @@ class FreeCommutativeAdditiveMonoid(FreeCommutativeAdditiveSemigroup): sage: S.additive_semigroup_generators() Family (a, b, c, d) - with product rule given by $a \times b = a$ for all $a, b$:: + with product rule given by `a \times b = a` for all `a, b`:: sage: (a,b,c,d) = S.additive_semigroup_generators() diff --git a/src/sage/categories/examples/commutative_additive_semigroups.py b/src/sage/categories/examples/commutative_additive_semigroups.py index a278d781285..88cdeeee55d 100644 --- a/src/sage/categories/examples/commutative_additive_semigroups.py +++ b/src/sage/categories/examples/commutative_additive_semigroups.py @@ -34,7 +34,7 @@ class FreeCommutativeAdditiveSemigroup(UniqueRepresentation, Parent): sage: S.additive_semigroup_generators() Family (a, b, c, d) - with product rule given by $a \times b = a$ for all $a, b$:: + with product rule given by `a \times b = a` for all `a, b`:: sage: (a,b,c,d) = S.additive_semigroup_generators() diff --git a/src/sage/categories/examples/semigroups.py b/src/sage/categories/examples/semigroups.py index 180cef37fca..4d7767a3c51 100644 --- a/src/sage/categories/examples/semigroups.py +++ b/src/sage/categories/examples/semigroups.py @@ -31,7 +31,7 @@ class LeftZeroSemigroup(UniqueRepresentation, Parent): sage: S.some_elements() [3, 42, 'a', 3.4, 'raton laveur'] - with product rule given by $a \times b = a$ for all $a, b$:: + with product rule given by `a \times b = a` for all `a, b`:: sage: S('hello') * S('world') 'hello' diff --git a/src/sage/categories/examples/semigroups_cython.pyx b/src/sage/categories/examples/semigroups_cython.pyx index c05ab880fb6..95e79315e6b 100644 --- a/src/sage/categories/examples/semigroups_cython.pyx +++ b/src/sage/categories/examples/semigroups_cython.pyx @@ -151,7 +151,7 @@ class LeftZeroSemigroup(LeftZeroSemigroupPython): sage: S.some_elements() [3, 42, 'a', 3.4, 'raton laveur'] - with product rule is given by $a \times b = a$ for all $a,b$. :: + with product rule is given by `a \times b = a` for all `a,b`. :: sage: S('hello') * S('world') 'hello' diff --git a/src/sage/categories/finite_monoids.py b/src/sage/categories/finite_monoids.py index 69e4a6bc83e..c58cfc3e4e8 100644 --- a/src/sage/categories/finite_monoids.py +++ b/src/sage/categories/finite_monoids.py @@ -35,17 +35,17 @@ def nerve(self): r""" The nerve (classifying space) of this monoid. - OUTPUT: the nerve $BG$ (if $G$ denotes this monoid), as a - simplicial set. The $k$-dimensional simplices of this - object are indexed by products of $k$ elements in the + OUTPUT: the nerve `BG` (if `G` denotes this monoid), as a + simplicial set. The `k`-dimensional simplices of this + object are indexed by products of `k` elements in the monoid: .. MATH:: a_1 * a_2 * \cdots * a_k - The 0th face of this is obtained by deleting $a_1$, and - the $k$-th face is obtained by deleting $a_k$. The other + The 0th face of this is obtained by deleting `a_1`, and + the `k`-th face is obtained by deleting `a_k`. The other faces are obtained by multiplying elements: the 1st face is @@ -58,7 +58,7 @@ def nerve(self): set. A simplex in this simplicial set will be degenerate if in - the corresponding product of $k$ elements, one of those + the corresponding product of `k` elements, one of those elements is the identity. So we only need to keep track of the products of non-identity elements. Similarly, if a product `a_{i-1} a_i` is the identity element, then the diff --git a/src/sage/categories/finite_semigroups.py b/src/sage/categories/finite_semigroups.py index 13687e6004b..a7f9b9a20a1 100644 --- a/src/sage/categories/finite_semigroups.py +++ b/src/sage/categories/finite_semigroups.py @@ -74,14 +74,14 @@ def idempotents(self): @cached_method def j_classes(self): r""" - Returns the $J$-classes of the semigroup. + Returns the `J`-classes of the semigroup. - Two elements $u$ and $v$ of a monoid are in the same $J$-class - if $u$ divides $v$ and $v$ divides $u$. + Two elements `u` and `v` of a monoid are in the same `J`-class + if `u` divides `v` and `v` divides `u`. OUTPUT: - All the $J$-classes of self, as a list of lists. + All the `J`-classes of self, as a list of lists. EXAMPLES:: @@ -117,7 +117,7 @@ def j_transversal_of_idempotents(self): sage: S = FiniteSemigroups().example(alphabet=('a','b', 'c')) - The chosen elements depend on the order of each $J$-class, + The chosen elements depend on the order of each `J`-class, and that order is random when using Python 3. :: sage: sorted(S.j_transversal_of_idempotents()) # random diff --git a/src/sage/categories/g_sets.py b/src/sage/categories/g_sets.py index f28c34a4223..b9447203e42 100644 --- a/src/sage/categories/g_sets.py +++ b/src/sage/categories/g_sets.py @@ -15,11 +15,11 @@ ############################################################# # GSets -# $G$-Sets play an important role in permutation groups. +# `G`-Sets play an important role in permutation groups. ############################################################# class GSets(Category): """ - The category of $G$-sets, for a group $G$. + The category of `G`-sets, for a group `G`. EXAMPLES:: diff --git a/src/sage/categories/simplicial_sets.py b/src/sage/categories/simplicial_sets.py index 7376e4ea721..039f7c60230 100644 --- a/src/sage/categories/simplicial_sets.py +++ b/src/sage/categories/simplicial_sets.py @@ -509,13 +509,13 @@ def unset_base_point(self): def fat_wedge(self, n): """ - Return the $n$-th fat wedge of this pointed simplicial set. + Return the `n`-th fat wedge of this pointed simplicial set. - This is the subcomplex of the $n$-fold product `X^n` + This is the subcomplex of the `n`-fold product `X^n` consisting of those points in which at least one - factor is the base point. Thus when $n=2$, this is the - wedge of the simplicial set with itself, but when $n$ - is larger, the fat wedge is larger than the $n$-fold + factor is the base point. Thus when `n=2`, this is the + wedge of the simplicial set with itself, but when `n` + is larger, the fat wedge is larger than the `n`-fold wedge. EXAMPLES:: diff --git a/src/sage/coding/binary_code.pyx b/src/sage/coding/binary_code.pyx index 11af1f7aadf..df4ce58c212 100644 --- a/src/sage/coding/binary_code.pyx +++ b/src/sage/coding/binary_code.pyx @@ -1,13 +1,13 @@ r""" Optimized low-level binary code representation -Some computations with linear binary codes. Fix a basis for $GF(2)^n$. -A linear binary code is a linear subspace of $GF(2)^n$, together with -this choice of basis. A permutation $g \in S_n$ of the fixed basis -gives rise to a permutation of the vectors, or words, in $GF(2)^n$, -sending $(w_i)$ to $(w_{g(i)})$. The permutation automorphism group of -the code $C$ is the set of permutations of the basis that bijectively -map $C$ to itself. Note that if $g$ is such a permutation, then +Some computations with linear binary codes. Fix a basis for `GF(2)^n`. +A linear binary code is a linear subspace of `GF(2)^n`, together with +this choice of basis. A permutation `g \in S_n` of the fixed basis +gives rise to a permutation of the vectors, or words, in `GF(2)^n`, +sending `(w_i)` to `(w_{g(i)})`. The permutation automorphism group of +the code `C` is the set of permutations of the basis that bijectively +map `C` to itself. Note that if `g` is such a permutation, then .. MATH:: @@ -15,7 +15,7 @@ map $C$ to itself. Note that if $g$ is such a permutation, then Over other fields, it is also required that the map be linear, which as per above boils down to scalar multiplication. However, over -$GF(2),$ the only scalars are 0 and 1, so the linearity condition has +`GF(2),` the only scalars are 0 and 1, so the linearity condition has trivial effect. AUTHOR: @@ -279,7 +279,7 @@ def test_word_perms(t_limit=5.0): cdef WordPermutation *create_word_perm(object list_perm): r""" Create a word permutation from a Python list permutation L, i.e. such that - $i \mapsto L[i]$. + `i \mapsto L[i]`. """ cdef int i, j, parity, comb, words_per_chunk, num_chunks = 1 cdef codeword *images_i @@ -426,7 +426,7 @@ cdef WordPermutation *create_id_word_perm(int degree): cdef WordPermutation *create_comp_word_perm(WordPermutation *g, WordPermutation *h): r""" - Create the composition of word permutations $g \circ h$. + Create the composition of word permutations `g \circ h`. """ cdef int i, j, parity, comb, words_per_chunk, num_chunks = 1 cdef codeword *images_i @@ -477,7 +477,7 @@ cdef WordPermutation *create_comp_word_perm(WordPermutation *g, WordPermutation cdef WordPermutation *create_inv_word_perm(WordPermutation *g): r""" - Create the inverse $g^{-1}$ of the word permutation of $g$. + Create the inverse `g^{-1}` of the word permutation of `g`. """ cdef int i, j cdef int *array = sig_malloc( g.degree * sizeof(int) ) @@ -528,9 +528,9 @@ def test_expand_to_ortho_basis(B=None): OUTPUT: - An array of codewords which represent the expansion of a basis for $B$ to a - basis for $(B^\prime)^\perp$, where $B^\prime = B$ if the all-ones vector 1 - is in $B$, otherwise $B^\prime = \text{span}(B,1)$ (note that this guarantees + An array of codewords which represent the expansion of a basis for `B` to a + basis for `(B^\prime)^\perp`, where `B^\prime = B` if the all-ones vector 1 + is in `B`, otherwise `B^\prime = \text{span}(B,1)` (note that this guarantees that all the vectors in the span of the output have even weight). TESTS:: @@ -580,9 +580,9 @@ cdef codeword *expand_to_ortho_basis(BinaryCode B, int n): OUTPUT: - An array of codewords which represent the expansion of a basis for $B$ to a - basis for $(B^\prime)^\perp$, where $B^\prime = B$ if the all-ones vector 1 - is in $B$, otherwise $B^\prime = \text{span}(B,1)$ (note that this guarantees + An array of codewords which represent the expansion of a basis for `B` to a + basis for `(B^\prime)^\perp`, where `B^\prime = B` if the all-ones vector 1 + is in `B`, otherwise `B^\prime = \text{span}(B,1)` (note that this guarantees that all the vectors in the span of the output have even weight). """ # assumes B is already in standard form diff --git a/src/sage/coding/guava.py b/src/sage/coding/guava.py index b76c980d766..e031b00af3d 100644 --- a/src/sage/coding/guava.py +++ b/src/sage/coding/guava.py @@ -62,7 +62,7 @@ def QuasiQuadraticResidueCode(p): sage: C = codes.QuasiQuadraticResidueCode(11); C # optional - gap_packages (Guava package) [22, 11] linear code over GF(2) - These are self-orthogonal in general and self-dual when $p \\equiv 3 \\pmod 4$. + These are self-orthogonal in general and self-dual when `p \\equiv 3 \\pmod 4`. AUTHOR: David Joyner (11-2005) """ diff --git a/src/sage/coding/reed_muller_code.py b/src/sage/coding/reed_muller_code.py index 653cae234f9..8eca7c8647f 100644 --- a/src/sage/coding/reed_muller_code.py +++ b/src/sage/coding/reed_muller_code.py @@ -461,7 +461,7 @@ def number_of_variables(self): def minimum_distance(self): r""" Returns the minimum distance of ``self``. - The minimum distance of a binary Reed-Muller code of order $d$ and number of variables $m$ is $q^{m-d}$ + The minimum distance of a binary Reed-Muller code of order `d` and number of variables `m` is `q^{m-d}` EXAMPLES:: @@ -663,7 +663,7 @@ def generator_matrix(self): def points(self): r""" - Returns the points of $F^m$, where $F$ is base field and $m$ is the number of variables, in order of which polynomials are evaluated on. + Returns the points of `F^m`, where `F` is base field and `m` is the number of variables, in order of which polynomials are evaluated on. EXAMPLES:: diff --git a/src/sage/combinat/designs/covering_design.py b/src/sage/combinat/designs/covering_design.py index 0fe08095880..1c0dfa47628 100644 --- a/src/sage/combinat/designs/covering_design.py +++ b/src/sage/combinat/designs/covering_design.py @@ -134,7 +134,7 @@ def trivial_covering_design(v, k, t): Cases are: * `t=0`: This could be empty, but it's a useful convention to have - one block (which is empty if $k=0$). + one block (which is empty if `k=0`). * `t=1` : This contains `\lceil v/k \rceil` blocks: `[0, ..., k-1], [k, ..., 2k-1], ...`. The last block wraps around if diff --git a/src/sage/combinat/parallelogram_polyomino.py b/src/sage/combinat/parallelogram_polyomino.py index 134fb61f4a5..5ff137f4eaf 100644 --- a/src/sage/combinat/parallelogram_polyomino.py +++ b/src/sage/combinat/parallelogram_polyomino.py @@ -4156,7 +4156,7 @@ def cardinality(self): Return the number of parallelogram polyominoes. The number of parallelogram polyominoes of size n is given by - the Catalan number $c_{n-1}$. + the Catalan number `c_{n-1}`. EXAMPLES:: diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 6b7aed790b8..096dcd0f807 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -7886,7 +7886,7 @@ def is_slender(self, certificate=False): interval contains three or four elements, as defined in [Stan2009]_. (This notion of "slender" is unrelated to the eponymous notion defined by Graetzer and Kelly in - "The Free $\mathfrak{m}$-Lattice on the Poset $H$", + "The Free `\mathfrak{m}`-Lattice on the Poset `H`", Order 1 (1984), 47--65.) This function *does not* check if the poset is graded or not. diff --git a/src/sage/combinat/words/word_generators.py b/src/sage/combinat/words/word_generators.py index 9a1ac2c4483..5cb363d248a 100644 --- a/src/sage/combinat/words/word_generators.py +++ b/src/sage/combinat/words/word_generators.py @@ -1558,7 +1558,7 @@ def _s_adic_iterator(self, sequence, letters): DEFINITION (from [Fogg]_): Let `w` be a infinite word over an alphabet `A = A_0`. A - standard representation of $w$ is obtained from a sequence of + standard representation of `w` is obtained from a sequence of substitutions `\sigma_k : A_{k+1} \to A_k` and a sequence of letters `a_k \in A_k` such that: diff --git a/src/sage/databases/cunningham_tables.py b/src/sage/databases/cunningham_tables.py index 0ffadf2ed02..9c23bf31816 100644 --- a/src/sage/databases/cunningham_tables.py +++ b/src/sage/databases/cunningham_tables.py @@ -14,7 +14,7 @@ def cunningham_prime_factors(): r""" List of all the prime numbers occurring in the so called Cunningham table. - 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\}$. + 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/ """ diff --git a/src/sage/databases/db_modular_polynomials.py b/src/sage/databases/db_modular_polynomials.py index 8b9a74ef481..d9f4b0752c2 100644 --- a/src/sage/databases/db_modular_polynomials.py +++ b/src/sage/databases/db_modular_polynomials.py @@ -207,8 +207,8 @@ class DedekindEtaModularPolynomialDatabase(ModularPolynomialDatabase): class DedekindEtaModularCorrespondenceDatabase(ModularCorrespondenceDatabase): r""" - The database of modular correspondences in $X_0(p) \times X_0(p)$, where - the model of the curves $X_0(p) = \Bold{P}^1$ are specified by quotients of + The database of modular correspondences in `X_0(p) \times X_0(p)`, where + the model of the curves `X_0(p) = \Bold{P}^1` are specified by quotients of Dedekind's eta function. """ model = "EtaCrr" @@ -216,7 +216,7 @@ class DedekindEtaModularCorrespondenceDatabase(ModularCorrespondenceDatabase): class AtkinModularPolynomialDatabase(ModularPolynomialDatabase): """ - The database of modular polynomials Phi(x,j) for $X_0(p)$, where + The database of modular polynomials Phi(x,j) for `X_0(p)`, where x is a function on invariant under the Atkin-Lehner invariant, with pole of minimal order at infinity. """ From f0f707b3c364cd2f64a530e56ca899deed18d4f1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Jun 2022 21:09:23 -0700 Subject: [PATCH 060/116] sage.geometry: Replace $...$ in docstrings by `...` --- src/sage/geometry/fan_morphism.py | 8 +- src/sage/geometry/lattice_polytope.py | 82 ++++----- .../parametrized_surface3d.py | 156 +++++++++--------- 3 files changed, 123 insertions(+), 123 deletions(-) diff --git a/src/sage/geometry/fan_morphism.py b/src/sage/geometry/fan_morphism.py index 5c1a71a488a..966947f0b22 100644 --- a/src/sage/geometry/fan_morphism.py +++ b/src/sage/geometry/fan_morphism.py @@ -1251,7 +1251,7 @@ def is_fibration(self): the linear map of vector spaces `\phi_\RR` induces a bijection between `\sigma` and `\sigma'`, and, in addition, `\phi` is :meth:`dominant ` (that is, `\phi_\RR: N_\RR \to - N'_\RR$ is surjective). + N'_\RR` is surjective). If a fan morphism `\phi: \Sigma \to \Sigma'` is a fibration, then the associated morphism between toric varieties `\tilde{\phi}: X_\Sigma \to @@ -1410,7 +1410,7 @@ def is_surjective(self): `\sigma' \in \Sigma'` there is at least one preimage cone `\sigma \in \Sigma` such that the relative interior of `\sigma` is mapped to the relative interior of `\sigma'` and, in addition, - `\phi_\RR: N_\RR \to N'_\RR$ is surjective. + `\phi_\RR: N_\RR \to N'_\RR` is surjective. If a fan morphism `\phi: \Sigma \to \Sigma'` is surjective, then the associated morphism between toric varieties `\tilde{\phi}: X_\Sigma \to @@ -1465,8 +1465,8 @@ def is_dominant(self): r""" Return whether the fan morphism is dominant. - A fan morphism $\phi$ is dominant if it is surjective as a map - of vector spaces. That is, $\phi_\RR: N_\RR \to N'_\RR$ is + A fan morphism `\phi` is dominant if it is surjective as a map + of vector spaces. That is, `\phi_\RR: N_\RR \to N'_\RR` is surjective. If the domain fan is :meth:`complete diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index 00d95c86285..89a4e9a2191 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -4209,8 +4209,8 @@ class NefPartition(SageObject, Hashable): INPUT: - - ``data`` -- a list of integers, the $i$-th element of this list must be - the part of the $i$-th vertex of ``Delta_polar`` in this nef-partition; + - ``data`` -- a list of integers, the `i`-th element of this list must be + the part of the `i`-th vertex of ``Delta_polar`` in this nef-partition; - ``Delta_polar`` -- a :class:`lattice polytope `; @@ -4224,20 +4224,20 @@ class NefPartition(SageObject, Hashable): - a nef-partition of ``Delta_polar``. - Let $M$ and $N$ be dual lattices. Let $\Delta \subset M_\RR$ be a reflexive - polytope with polar $\Delta^\circ \subset N_\RR$. Let $X_\Delta$ be the - toric variety associated to the normal fan of $\Delta$. A **nef-partition** - is a decomposition of the vertex set $V$ of $\Delta^\circ$ into a disjoint - union $V = V_0 \sqcup V_1 \sqcup \dots \sqcup V_{k-1}$ such that divisors - $E_i = \sum_{v\in V_i} D_v$ are Cartier (here $D_v$ are prime - torus-invariant Weil divisors corresponding to vertices of $\Delta^\circ$). - Equivalently, let $\nabla_i \subset N_\RR$ be the convex hull of vertices - from $V_i$ and the origin. These polytopes form a nef-partition if their - Minkowski sum $\nabla \subset N_\RR$ is a reflexive polytope. - - The **dual nef-partition** is formed by polytopes $\Delta_i \subset M_\RR$ - of $E_i$, which give a decomposition of the vertex set of $\nabla^\circ - \subset M_\RR$ and their Minkowski sum is $\Delta$, i.e. the polar duality + Let `M` and `N` be dual lattices. Let `\Delta \subset M_\RR` be a reflexive + polytope with polar `\Delta^\circ \subset N_\RR`. Let `X_\Delta` be the + toric variety associated to the normal fan of `\Delta`. A **nef-partition** + is a decomposition of the vertex set `V` of `\Delta^\circ` into a disjoint + union `V = V_0 \sqcup V_1 \sqcup \dots \sqcup V_{k-1}` such that divisors + `E_i = \sum_{v\in V_i} D_v` are Cartier (here `D_v` are prime + torus-invariant Weil divisors corresponding to vertices of `\Delta^\circ`). + Equivalently, let `\nabla_i \subset N_\RR` be the convex hull of vertices + from `V_i` and the origin. These polytopes form a nef-partition if their + Minkowski sum `\nabla \subset N_\RR` is a reflexive polytope. + + The **dual nef-partition** is formed by polytopes `\Delta_i \subset M_\RR` + of `E_i`, which give a decomposition of the vertex set of `\nabla^\circ + \subset M_\RR` and their Minkowski sum is `\Delta`, i.e. the polar duality of reflexive polytopes switches convex hull and Minkowski sum for dual nef-partitions: @@ -4259,25 +4259,25 @@ class NefPartition(SageObject, Hashable): \mathrm{Conv} \left(\Delta_0, \Delta_1, \dots, \Delta_{k-1}\right). One can also interpret the duality of nef-partitions as the duality of the - associated cones. Below $\overline{M} = M \times \ZZ^k$ and - $\overline{N} = N \times \ZZ^k$ are dual lattices. + associated cones. Below `\overline{M} = M \times \ZZ^k` and + `\overline{N} = N \times \ZZ^k` are dual lattices. - The **Cayley polytope** $P \subset \overline{M}_\RR$ of a nef-partition is + The **Cayley polytope** `P \subset \overline{M}_\RR` of a nef-partition is given by $P = \mathrm{Conv}(\Delta_0 \times e_0, \Delta_1 \times e_1, - \ldots, \Delta_{k-1} \times e_{k-1})$, where $\{e_i\}_{i=0}^{k-1}$ is the - standard basis of $\ZZ^k$. The **dual Cayley polytope** - $P^* \subset \overline{N}_\RR$ is the Cayley polytope of the dual + \ldots, \Delta_{k-1} \times e_{k-1})`, where `\{e_i\}_{i=0}^{k-1}` is the + standard basis of `\ZZ^k`. The **dual Cayley polytope** + `P^* \subset \overline{N}_\RR` is the Cayley polytope of the dual nef-partition. - The **Cayley cone** $C \subset \overline{M}_\RR$ of a nef-partition is the + The **Cayley cone** `C \subset \overline{M}_\RR` of a nef-partition is the cone spanned by its Cayley polytope. The **dual Cayley cone** - $C^\vee \subset \overline{M}_\RR$ is the usual dual cone of $C$. It turns - out, that $C^\vee$ is spanned by $P^*$. + `C^\vee \subset \overline{M}_\RR` is the usual dual cone of `C`. It turns + out, that `C^\vee` is spanned by `P^*`. It is also possible to go back from the Cayley cone to the Cayley polytope, - since $C$ is a reflexive Gorenstein cone supported by $P$: primitive - integral ray generators of $C$ are contained in an affine hyperplane and - coincide with vertices of $P$. + since `C` is a reflexive Gorenstein cone supported by `P`: primitive + integral ray generators of `C` are contained in an affine hyperplane and + coincide with vertices of `P`. See Section 4.3.1 in [CK1999]_ and references therein for further details, or [BN2008]_ for a purely combinatorial approach. @@ -4550,11 +4550,11 @@ def _sage_input_(self, sib, coerced): def Delta(self, i=None): r""" - Return the polytope $\Delta$ or $\Delta_i$ corresponding to ``self``. + Return the polytope `\Delta` or `\Delta_i` corresponding to ``self``. INPUT: - - ``i`` -- an integer. If not given, $\Delta$ will be returned. + - ``i`` -- an integer. If not given, `\Delta` will be returned. OUTPUT: @@ -4594,7 +4594,7 @@ def Delta(self, i=None): def Delta_polar(self): r""" - Return the polytope $\Delta^\circ$ corresponding to ``self``. + Return the polytope `\Delta^\circ` corresponding to ``self``. OUTPUT: @@ -4615,7 +4615,7 @@ def Delta_polar(self): def Deltas(self): r""" - Return the polytopes $\Delta_i$ corresponding to ``self``. + Return the polytopes `\Delta_i` corresponding to ``self``. OUTPUT: @@ -4749,11 +4749,11 @@ def hodge_numbers(self): def nabla(self, i=None): r""" - Return the polytope $\nabla$ or $\nabla_i$ corresponding to ``self``. + Return the polytope `\nabla` or `\nabla_i` corresponding to ``self``. INPUT: - - ``i`` -- an integer. If not given, $\nabla$ will be returned. + - ``i`` -- an integer. If not given, `\nabla` will be returned. OUTPUT: @@ -4798,7 +4798,7 @@ def nabla(self, i=None): def nabla_polar(self): r""" - Return the polytope $\nabla^\circ$ corresponding to ``self``. + Return the polytope `\nabla^\circ` corresponding to ``self``. OUTPUT: @@ -4829,7 +4829,7 @@ def nabla_polar(self): def nablas(self): r""" - Return the polytopes $\nabla_i$ corresponding to ``self``. + Return the polytopes `\nabla_i` corresponding to ``self``. OUTPUT: @@ -4904,7 +4904,7 @@ def part(self, i, all_points=False): OUTPUT: - a tuple of integers, indices of vertices (or all lattice points) of - $\Delta^\circ$ belonging to $V_i$. + `\Delta^\circ` belonging to `V_i`. See :class:`nef-partition ` class documentation for definitions and notation. @@ -4937,8 +4937,8 @@ def parts(self, all_points=False): OUTPUT: - - a tuple of tuples of integers. The $i$-th tuple contains indices of - vertices (or all lattice points) of $\Delta^\circ$ belonging to $V_i$ + - a tuple of tuples of integers. The `i`-th tuple contains indices of + vertices (or all lattice points) of `\Delta^\circ` belonging to `V_i` See :class:`nef-partition ` class documentation for definitions and notation. @@ -4977,8 +4977,8 @@ def part_of(self, i): OUTPUT: - - an integer $j$ such that the ``i``-th vertex of $\Delta^\circ$ - belongs to $V_j$. + - an integer `j` such that the ``i``-th vertex of `\Delta^\circ` + belongs to `V_j`. See :class:`nef-partition ` class documentation for definitions and notation. diff --git a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py index acd70e6bc75..c1a126b630a 100644 --- a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py +++ b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py @@ -62,8 +62,8 @@ class ParametrizedSurface3D(SageObject): - ``variables`` -- a 2-tuple of intrinsic coordinates `(u, v)` on the surface, with `u` and `v` symbolic variables, or a 2-tuple of triples - $(u, u_{min}, u_{max})$, - $(v, v_{min}, v_{max})$ when the parameter range + `(u, u_{min}, u_{max})`, + `(v, v_{min}, v_{max})` when the parameter range for the coordinates is known. - ``name`` -- name of the surface (optional). @@ -162,8 +162,8 @@ class ParametrizedSurface3D(SageObject): The first fundamental form can be used to compute the length of a curve on the surface. For example, let us find the length of the - curve $u^1 = t$, $u^2 = t$, $t \in [0,2\pi]$, on the ellipsoid - with axes $a=1$, $b=1.5$ and $c=1$. So we take the curve:: + curve `u^1 = t`, `u^2 = t`, `t \in [0,2\pi]`, on the ellipsoid + with axes `a=1`, `b=1.5` and `c=1`. So we take the curve:: sage: t = var('t', domain='real') sage: u1 = t @@ -183,7 +183,7 @@ class ParametrizedSurface3D(SageObject): sage: numerical_integral(L.substitute(a=2, b=1.5, c=1),0,1)[0] # rel tol 1e-11 2.00127905972 - We find the area of the sphere of radius $R$:: + We find the area of the sphere of radius `R`:: sage: R = var('R', domain='real') sage: u, v = var('u,v', domain='real') @@ -193,7 +193,7 @@ class ParametrizedSurface3D(SageObject): sage: integral(integral(sphere.area_form(),u,0,2*pi),v,-pi/2,pi/2) 4*pi*R^2 - We can find an orthonormal frame field $\{e_1, e_2\}$ of a surface + We can find an orthonormal frame field `\{e_1, e_2\}` of a surface and calculate its structure functions. Let us first determine the orthonormal frame field for the elliptic paraboloid:: @@ -204,7 +204,7 @@ class ParametrizedSurface3D(SageObject): We can express the orthogonal frame field both in exterior coordinates (i.e. expressed as vector field fields in the ambient - space $\RR^3$, the default) or in intrinsic coordinates + space `\RR^3`, the default) or in intrinsic coordinates (with respect to the natural frame). Here we use intrinsic coordinates:: @@ -212,9 +212,9 @@ class ParametrizedSurface3D(SageObject): {1: (1/sqrt(4*u^2 + 1), 0), 2: (-4*u*v/(sqrt(4*u^2 + 4*v^2 + 1)*sqrt(4*u^2 + 1)), sqrt(4*u^2 + 1)/sqrt(4*u^2 + 4*v^2 + 1))} Using the orthonormal frame in interior coordinates, we can calculate - the structure functions $c^k_{ij}$ of the surface, defined by - $[e_i,e_j] = c^k_{ij} e_k$, where $[e_i, e_j]$ represents the Lie - bracket of two frame vector fields $e_i, e_j$. For the + the structure functions `c^k_{ij}` of the surface, defined by + `[e_i,e_j] = c^k_{ij} e_k`, where `[e_i, e_j]` represents the Lie + bracket of two frame vector fields `e_i, e_j`. For the elliptic paraboloid, we get:: sage: EE = eparaboloid.orthonormal_frame(coordinates='int') @@ -476,7 +476,7 @@ def plot(self, urange=None, vrange=None, **kwds): the surface parameters `u` and `v`. If either of these parameters is ``None``, the method checks whether a parameter range was specified when the surface was created. If not, the default of - $(0, 2 \pi)$ is used. + `(0, 2 \pi)` is used. INPUT: @@ -597,18 +597,18 @@ def _compute_first_fundamental_form_coefficient(self, index): def first_fundamental_form_coefficient(self, index): r""" - Compute a single component $g_{ij}$ of the first fundamental form. If + Compute a single component `g_{ij}` of the first fundamental form. If the parametric representation of the surface is given by the vector - function $\vec r(u^i)$, where $u^i$, $i = 1, 2$ are curvilinear - coordinates, then $g_{ij} = \frac{\partial \vec r}{\partial u^i} \cdot \frac{\partial \vec r}{\partial u^j}$. + function `\vec r(u^i)`, where `u^i`, `i = 1, 2` are curvilinear + coordinates, then `g_{ij} = \frac{\partial \vec r}{\partial u^i} \cdot \frac{\partial \vec r}{\partial u^j}`. INPUT: - - ``index`` - tuple ``(i, j)`` specifying the index of the component $g_{ij}$. + - ``index`` - tuple ``(i, j)`` specifying the index of the component `g_{ij}`. OUTPUT: - - Component $g_{ij}$ of the first fundamental form + - Component `g_{ij}` of the first fundamental form EXAMPLES:: @@ -636,8 +636,8 @@ def first_fundamental_form_coefficient(self, index): def first_fundamental_form_coefficients(self): r""" Returns the coefficients of the first fundamental form as a dictionary. - The keys are tuples $(i, j)$, where $i$ and $j$ range over $1, 2$, - while the values are the corresponding coefficients $g_{ij}$. + The keys are tuples `(i, j)`, where `i` and `j` range over `1, 2`, + while the values are the corresponding coefficients `g_{ij}`. OUTPUT: @@ -661,9 +661,9 @@ def first_fundamental_form(self, vector1, vector2): r""" Evaluate the first fundamental form on two vectors expressed with respect to the natural coordinate frame on the surface. In other words, - if the vectors are $v = (v^1, v^2)$ and $w = (w^1, w^2)$, calculate - $g_{11} v^1 w^1 + g_{12}(v^1 w^2 + v^2 w^1) + g_{22} v^2 w^2$, with - $g_{ij}$ the coefficients of the first fundamental form. + if the vectors are `v = (v^1, v^2)` and `w = (w^1, w^2)`, calculate + `g_{11} v^1 w^1 + g_{12}(v^1 w^2 + v^2 w^1) + g_{22} v^2 w^2`, with + `g_{ij}` the coefficients of the first fundamental form. INPUT: @@ -696,9 +696,9 @@ def first_fundamental_form(self, vector1, vector2): def area_form_squared(self): """ Returns the square of the coefficient of the area form on the surface. - In terms of the coefficients $g_{ij}$ (where $i, j = 1, 2$) of the + In terms of the coefficients `g_{ij}` (where `i, j = 1, 2`) of the first fundamental form, this invariant is given by - $A^2 = g_{11}g_{22} - g_{12}^2$. + `A^2 = g_{11}g_{22} - g_{12}^2`. See also :meth:`.area_form`. @@ -722,9 +722,9 @@ def area_form_squared(self): def area_form(self): r""" Returns the coefficient of the area form on the surface. In terms of - the coefficients $g_{ij}$ (where $i, j = 1, 2$) of the first + the coefficients `g_{ij}` (where `i, j = 1, 2`) of the first fundamental form, the coefficient of the area form is given by - $A = \sqrt{g_{11}g_{22} - g_{12}^2}$. + `A = \sqrt{g_{11}g_{22} - g_{12}^2}`. See also :meth:`.area_form_squared`. @@ -746,9 +746,9 @@ def area_form(self): def first_fundamental_form_inverse_coefficients(self): r""" - Returns the coefficients $g^{ij}$ of the inverse of the fundamental + Returns the coefficients `g^{ij}` of the inverse of the fundamental form, as a dictionary. The inverse coefficients are defined by - $g^{ij} g_{jk} = \delta^i_k$ with $\delta^i_k$ the Kronecker + `g^{ij} g_{jk} = \delta^i_k` with `\delta^i_k` the Kronecker delta. OUTPUT: @@ -777,12 +777,12 @@ def first_fundamental_form_inverse_coefficients(self): def first_fundamental_form_inverse_coefficient(self, index): r""" - Returns a specific component $g^{ij}$ of the inverse of the fundamental + Returns a specific component `g^{ij}` of the inverse of the fundamental form. INPUT: - - ``index`` - tuple ``(i, j)`` specifying the index of the component $g^{ij}$. + - ``index`` - tuple ``(i, j)`` specifying the index of the component `g^{ij}`. OUTPUT: @@ -810,7 +810,7 @@ def first_fundamental_form_inverse_coefficient(self, index): @cached_method def rotation(self,theta): r""" - Gives the matrix of the rotation operator over a given angle $\theta$ + Gives the matrix of the rotation operator over a given angle `\theta` with respect to the natural frame. INPUT: @@ -823,9 +823,9 @@ def rotation(self,theta): ALGORITHM: - The operator of rotation over $\pi/2$ is $J^i_j = g^{ik}\omega_{jk}$, - where $\omega$ is the area form. The operator of rotation over an - angle $\theta$ is $\cos(\theta) I + sin(\theta) J$. + The operator of rotation over `\pi/2` is `J^i_j = g^{ik}\omega_{jk}`, + where `\omega` is the area form. The operator of rotation over an + angle `\theta` is `\cos(\theta) I + sin(\theta) J`. EXAMPLES:: @@ -833,13 +833,13 @@ def rotation(self,theta): sage: assume(cos(v)>0) sage: sphere = ParametrizedSurface3D([cos(u)*cos(v),sin(u)*cos(v),sin(v)],[u,v],'sphere') - We first compute the matrix of rotation over $\pi/3$:: + We first compute the matrix of rotation over `\pi/3`:: sage: rotation = sphere.rotation(pi/3); rotation [ 1/2 -1/2*sqrt(3)/cos(v)] [ 1/2*sqrt(3)*cos(v) 1/2] - We verify that three successive rotations over $\pi/3$ yield minus the identity:: + We verify that three successive rotations over `\pi/3` yield minus the identity:: sage: rotation^3 [-1 0] @@ -863,7 +863,7 @@ def orthonormal_frame(self, coordinates='ext'): r""" Returns the orthonormal frame field on the surface, expressed either in exterior coordinates (i.e. expressed as vector fields in the - ambient space $\mathbb{R}^3$, the default) or interior coordinates + ambient space `\mathbb{R}^3`, the default) or interior coordinates (with respect to the natural frame) INPUT: @@ -876,9 +876,9 @@ def orthonormal_frame(self, coordinates='ext'): ALGORITHM: - We normalize the first vector $\vec e_1$ of the natural frame and then - get the second frame vector as $\vec e_2 = [\vec n, \vec e_1]$, where - $\vec n$ is the unit normal to the surface. + We normalize the first vector `\vec e_1` of the natural frame and then + get the second frame vector as `\vec e_2 = [\vec n, \vec e_1]`, where + `\vec n` is the unit normal to the surface. EXAMPLES:: @@ -978,7 +978,7 @@ def lie_bracket(self, v, w): OUTPUT: - - The Lie bracket $[v, w]$. + - The Lie bracket `[v, w]`. EXAMPLES:: @@ -1006,10 +1006,10 @@ def lie_bracket(self, v, w): def frame_structure_functions(self, e1, e2): r""" - Returns the structure functions $c^k_{ij}$ for a frame field - $e_1, e_2$, i.e. a pair of vector fields on the surface which are + Returns the structure functions `c^k_{ij}` for a frame field + `e_1, e_2`, i.e. a pair of vector fields on the surface which are linearly independent at each point. The structure functions are - defined using the Lie bracket by $[e_i,e_j] = c^k_{ij}e_k$. + defined using the Lie bracket by `[e_i,e_j] = c^k_{ij}e_k`. INPUT: @@ -1020,7 +1020,7 @@ def frame_structure_functions(self, e1, e2): OUTPUT: - Dictionary of structure functions, where the key ``(i, j, k)`` refers to - the structure function $c_{i,j}^k$. + the structure function `c_{i,j}^k`. EXAMPLES:: @@ -1096,12 +1096,12 @@ def second_order_natural_frame(self): r""" Returns the second-order frame of the surface, i.e. computes the second-order derivatives (with respect to the parameters on the - surface) of the parametric expression $\vec r = \vec r(u^1,u^2)$ + surface) of the parametric expression `\vec r = \vec r(u^1,u^2)` of the surface. OUTPUT: - - Dictionary where the keys are 2-tuples ``(i, j)`` and the values are the corresponding derivatives $r_{ij}$. + - Dictionary where the keys are 2-tuples ``(i, j)`` and the values are the corresponding derivatives `r_{ij}`. EXAMPLES: @@ -1129,7 +1129,7 @@ def second_order_natural_frame_element(self, index): r""" Returns a vector in the second-order frame of the surface, i.e. computes the second-order derivatives of the parametric expression - $\vec{r}$ of the surface with respect to the parameters listed in the + `\vec{r}` of the surface with respect to the parameters listed in the argument. INPUT: @@ -1138,7 +1138,7 @@ def second_order_natural_frame_element(self, index): OUTPUT: - - The second-order derivative $r_{ij}$. + - The second-order derivative `r_{ij}`. EXAMPLES:: @@ -1179,10 +1179,10 @@ def _compute_second_fundamental_form_coefficient(self, index): def second_fundamental_form_coefficient(self, index): r""" - Returns the coefficient $h_{ij}$ of the second fundamental form - corresponding to the index $(i, j)$. If the equation of the surface - is $\vec{r}(u^1, u^2)$, then $h_{ij} = \vec{r}_{u^i u^j} \cdot \vec{n}$, - where $\vec{n}$ is the unit normal. + Returns the coefficient `h_{ij}` of the second fundamental form + corresponding to the index `(i, j)`. If the equation of the surface + is `\vec{r}(u^1, u^2)`, then `h_{ij} = \vec{r}_{u^i u^j} \cdot \vec{n}`, + where `\vec{n}` is the unit normal. INPUT: @@ -1190,7 +1190,7 @@ def second_fundamental_form_coefficient(self, index): OUTPUT: - - Component $h_{ij}$ of the second fundamental form. + - Component `h_{ij}` of the second fundamental form. EXAMPLES:: @@ -1212,9 +1212,9 @@ def second_fundamental_form_coefficient(self, index): def second_fundamental_form_coefficients(self): """ - Returns the coefficients $h_{ij}$ of the second fundamental form as - a dictionary, where the keys are the indices $(i, j)$ and the values - are the corresponding components $h_{ij}$. + Returns the coefficients `h_{ij}` of the second fundamental form as + a dictionary, where the keys are the indices `(i, j)` and the values + are the corresponding components `h_{ij}`. When only one component is needed, consider instead the function :meth:`second_fundamental_form_coefficient`. @@ -1243,8 +1243,8 @@ def second_fundamental_form_coefficients(self): def second_fundamental_form(self,vector1,vector2): r""" Evaluates the second fundamental form on two vectors on the surface. - If the vectors are given by $v=(v^1,v^2)$ and $w=(w^1,w^2)$, the - result of this function is $h_{11} v^1 w^1 + h_{12}(v^1 w^2 + v^2 w^1) + h_{22} v^2 w^2$. + If the vectors are given by `v=(v^1,v^2)` and `w=(w^1,w^2)`, the + result of this function is `h_{11} v^1 w^1 + h_{12}(v^1 w^2 + v^2 w^1) + h_{22} v^2 w^2`. INPUT: @@ -1283,8 +1283,8 @@ def second_fundamental_form(self,vector1,vector2): def gauss_curvature(self): r""" Finds the gaussian curvature of the surface, given by - $K = \frac{h_{11}h_{22} - h_{12}^2}{g_{11}g_{22} - g_{12}^2}$, - where $g_{ij}$ and $h_{ij}$ are the coefficients of the first + `K = \frac{h_{11}h_{22} - h_{12}^2}{g_{11}g_{22} - g_{12}^2}`, + where `g_{ij}` and `h_{ij}` are the coefficients of the first and second fundamental form, respectively. OUTPUT: @@ -1310,8 +1310,8 @@ def gauss_curvature(self): def mean_curvature(self): r""" Finds the mean curvature of the surface, given by - $H = \frac{1}{2}\frac{g_{22}h_{11} - 2g_{12}h_{12} + g_{11}h_{22}}{g_{11}g_{22} - g_{12}^2}$, - where $g_{ij}$ and $h_{ij}$ are the components of the first and second + `H = \frac{1}{2}\frac{g_{22}h_{11} - 2g_{12}h_{12} + g_{11}h_{22}}{g_{11}g_{22} - g_{12}^2}`, + where `g_{ij}` and `h_{ij}` are the components of the first and second fundamental forms, respectively. OUTPUT: @@ -1418,8 +1418,8 @@ def principal_directions(self): OUTPUT: For each principal curvature, returns a list of the form - $(\rho, V, n)$, where $\rho$ is the principal curvature, - $V$ is the corresponding principal direction, and $n$ is + `(\rho, V, n)`, where `\rho` is the principal curvature, + `V` is the corresponding principal direction, and `n` is the multiplicity. EXAMPLES:: @@ -1450,19 +1450,19 @@ def principal_directions(self): def connection_coefficients(self): r""" Computes the connection coefficients or Christoffel symbols - $\Gamma^k_{ij}$ of the surface. If the coefficients of the first - fundamental form are given by $g_{ij}$ (where $i, j = 1, 2$), then + `\Gamma^k_{ij}` of the surface. If the coefficients of the first + fundamental form are given by `g_{ij}` (where `i, j = 1, 2`), then $\Gamma^k_{ij} = \frac{1}{2} g^{kl} \left( \frac{\partial g_{li}}{\partial x^j} - \frac{\partial g_{ij}}{\partial x^l} + \frac{\partial g_{lj}}{\partial x^i} \right)$. - Here, $(g^{kl})$ is the inverse of the matrix $(g_{ij})$, with - $i, j = 1, 2$. + Here, `(g^{kl})` is the inverse of the matrix `(g_{ij})`, with + `i, j = 1, 2`. OUTPUT: Dictionary of connection coefficients, where the keys are 3-tuples - $(i,j,k)$ and the values are the corresponding coefficients - $\Gamma^k_{ij}$. + `(i,j,k)` and the values are the corresponding coefficients + `\Gamma^k_{ij}`. EXAMPLES:: @@ -1540,12 +1540,12 @@ def geodesics_numerical(self, p0, v0, tinterval): r""" Numerical integration of the geodesic equations. Explicitly, the geodesic equations are given by - $\frac{d^2 u^i}{dt^2} + \Gamma^i_{jk} \frac{d u^j}{dt} \frac{d u^k}{dt} = 0$. + `\frac{d^2 u^i}{dt^2} + \Gamma^i_{jk} \frac{d u^j}{dt} \frac{d u^k}{dt} = 0`. - Solving these equations gives the coordinates $(u^1, u^2)$ of + Solving these equations gives the coordinates `(u^1, u^2)` of the geodesic on the surface. The coordinates in space can - then be found by substituting $(u^1, u^2)$ into the vector - $\vec{r}(u^1, u^2)$ representing the surface. + then be found by substituting `(u^1, u^2)` into the vector + `\vec{r}(u^1, u^2)` representing the surface. ALGORITHM: @@ -1656,10 +1656,10 @@ def parallel_translation_numerical(self,curve,t,v0,tinterval): Numerically solves the equations for parallel translation of a vector along a curve on the surface. Explicitly, the equations for parallel translation are given by - $\frac{d u^i}{dt} + u^j \frac{d c^k}{dt} \Gamma^i_{jk} = 0$, - where $\Gamma^i_{jk}$ are the connection coefficients of the surface, - the vector to be transported has components $u^j$ and the curve along - which to transport has components $c^k$. + `\frac{d u^i}{dt} + u^j \frac{d c^k}{dt} \Gamma^i_{jk} = 0`, + where `\Gamma^i_{jk}` are the connection coefficients of the surface, + the vector to be transported has components `u^j` and the curve along + which to transport has components `c^k`. ALGORITHM: From 03895c086ca74afd2156051c6785d40b6109a606 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Jun 2022 21:14:36 -0700 Subject: [PATCH 061/116] sage.topology: Replace $...$ in docstrings by `...` --- .../topology/simplicial_set_constructions.py | 18 +++++++++--------- src/sage/topology/simplicial_set_examples.py | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/sage/topology/simplicial_set_constructions.py b/src/sage/topology/simplicial_set_constructions.py index 5b192d019bc..3c124b04841 100644 --- a/src/sage/topology/simplicial_set_constructions.py +++ b/src/sage/topology/simplicial_set_constructions.py @@ -728,7 +728,7 @@ def factors(self): def factor(self, i): r""" - Return the $i$-th factor of this construction of simplicial sets. + Return the `i`-th factor of this construction of simplicial sets. INPUT: @@ -902,7 +902,7 @@ def n_skeleton(self, n): def factor(self, i, as_subset=False): r""" - Return the $i$-th factor of the product. + Return the `i`-th factor of the product. INPUT: @@ -910,14 +910,14 @@ def factor(self, i, as_subset=False): - ``as_subset`` -- boolean, optional (default ``False``) - If ``as_subset`` is ``True``, return the $i$-th factor as a + If ``as_subset`` is ``True``, return the `i`-th factor as a subsimplicial set of the product, identifying it with its product with the base point in each other factor. As a subsimplicial set, it comes equipped with an inclusion map. This option will raise an error if any factor does not have a base point. - If ``as_subset`` is ``False``, return the $i$-th factor in + If ``as_subset`` is ``False``, return the `i`-th factor in its original form as a simplicial set. EXAMPLES:: @@ -1030,7 +1030,7 @@ def __init__(self, factors=None): def projection_map(self, i): """ - Return the map projecting onto the $i$-th factor. + Return the map projecting onto the `i`-th factor. INPUT: @@ -1569,7 +1569,7 @@ def __init__(self, maps=None, vertex_name=None): def structure_map(self, i): r""" - Return the $i$-th structure map of the pushout. + Return the `i`-th structure map of the pushout. INPUT: @@ -2095,7 +2095,7 @@ def __init__(self, factors=None): def inclusion_map(self, i): """ - Return the inclusion map of the $i$-th factor. + Return the inclusion map of the `i`-th factor. EXAMPLES:: @@ -2116,7 +2116,7 @@ def inclusion_map(self, i): def projection_map(self, i): """ - Return the projection map onto the $i$-th factor. + Return the projection map onto the `i`-th factor. EXAMPLES:: @@ -2300,7 +2300,7 @@ def __init__(self, factors=None): def inclusion_map(self, i): """ - Return the inclusion map of the $i$-th factor. + Return the inclusion map of the `i`-th factor. EXAMPLES:: diff --git a/src/sage/topology/simplicial_set_examples.py b/src/sage/topology/simplicial_set_examples.py index 1ddb7103447..279cf8b7c7d 100644 --- a/src/sage/topology/simplicial_set_examples.py +++ b/src/sage/topology/simplicial_set_examples.py @@ -488,10 +488,10 @@ def Point(): def Horn(n, k): r""" - Return the horn $\Lambda^n_k$. + Return the horn `\Lambda^n_k`. - This is the subsimplicial set of the $n$-simplex obtained by - removing its $k$-th face. + This is the subsimplicial set of the `n`-simplex obtained by + removing its `k`-th face. EXAMPLES:: From 9715f3fdb67a629a0ebd6ad245727d9c925e8067 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Jun 2022 21:15:40 -0700 Subject: [PATCH 062/116] sage.symbolic: Replace $...$ in docstrings by `...` --- src/sage/symbolic/expression.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index eb50443ff29..6c7fa547fd2 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -9205,7 +9205,7 @@ cdef class Expression(Expression_abc): r""" Return sinh of self. - We have $\sinh(x) = (e^{x} - e^{-x})/2$. + We have `\sinh(x) = (e^{x} - e^{-x})/2`. EXAMPLES:: @@ -9263,7 +9263,7 @@ cdef class Expression(Expression_abc): r""" Return cosh of self. - We have $\cosh(x) = (e^{x} + e^{-x})/2$. + We have `\cosh(x) = (e^{x} + e^{-x})/2`. EXAMPLES:: @@ -9319,7 +9319,7 @@ cdef class Expression(Expression_abc): r""" Return tanh of self. - We have $\tanh(x) = \sinh(x) / \cosh(x)$. + We have `\tanh(x) = \sinh(x) / \cosh(x)`. EXAMPLES:: From 73ce3e33e2a092bb16df2def931e3f60a8d30102 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Jun 2022 21:17:13 -0700 Subject: [PATCH 063/116] sage.structure: Replace $...$ in docstrings by `...` --- src/sage/structure/coerce.pyx | 2 +- src/sage/structure/coerce_maps.pyx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/structure/coerce.pyx b/src/sage/structure/coerce.pyx index 884e14b5ed7..caedace90a1 100644 --- a/src/sage/structure/coerce.pyx +++ b/src/sage/structure/coerce.pyx @@ -1291,7 +1291,7 @@ cdef class CoercionModel: sage: type(a) - We also make an exception for 0, even if $\ZZ$ does not map in:: + We also make an exception for 0, even if `\ZZ` does not map in:: sage: canonical_coercion(vector([1, 2, 3]), 0) ((1, 2, 3), (0, 0, 0)) diff --git a/src/sage/structure/coerce_maps.pyx b/src/sage/structure/coerce_maps.pyx index bd3b5575825..884ca57cabb 100644 --- a/src/sage/structure/coerce_maps.pyx +++ b/src/sage/structure/coerce_maps.pyx @@ -329,7 +329,7 @@ cdef class CallableConvertMap(Map): From: Integer Ring To: Rational Field - Create a homomorphism from $\RR$ to $\RR^+$ viewed as additive groups. + Create a homomorphism from `\RR` to `\RR^+` viewed as additive groups. :: From cdb74b4273d3241bc62b00f1ea60049b52d7bfe0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Jun 2022 21:59:33 -0700 Subject: [PATCH 064/116] src/sage/algebras/steenrod/steenrod_algebra_mult.py: Replace $...$ in docstrings by `...` (fixup) --- src/sage/algebras/steenrod/steenrod_algebra_mult.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/algebras/steenrod/steenrod_algebra_mult.py b/src/sage/algebras/steenrod/steenrod_algebra_mult.py index 0934c31f92d..ec92c86fcc5 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra_mult.py +++ b/src/sage/algebras/steenrod/steenrod_algebra_mult.py @@ -109,7 +109,7 @@ For each such matrix `M`, compute a multinomial coefficient, mod `p`: for each diagonal `\{m_{ij}: i+j=n\}`, compute `(\sum m_{i,j}!) / -(m_{0,n}! m_{1,n-1}! ... m_{n,0}!)$. Multiply these together for +(m_{0,n}! m_{1,n-1}! ... m_{n,0}!)`. Multiply these together for all `n`. Now, for each matrix with nonzero multinomial coefficient `b_M`, let @@ -328,8 +328,8 @@ def multinomial(list): None if the multinomial coefficient is 0, or sum of list if it is 1 Given the input `[n_1, n_2, n_3, ...]`, this computes the - multinomial coefficient $(n_1 + n_2 + n_3 + ...)! / (n_1! n_2! - n_3! ...)$, mod 2. The method is roughly this: expand each + multinomial coefficient `(n_1 + n_2 + n_3 + ...)! / (n_1! n_2! + n_3! ...)`, mod 2. The method is roughly this: expand each `n_i` in binary. If there is a 1 in the same digit for any `n_i` and `n_j` with `i\neq j`, then the coefficient is 0; otherwise, it is 1. @@ -579,7 +579,7 @@ def multinomial_odd(list,p): Associated multinomial coefficient, mod p Given the input `[n_1, n_2, n_3, ...]`, this computes the - multinomial coefficient $(n_1 + n_2 + n_3 + ...)! / (n_1! n_2! + multinomial coefficient `(n_1 + n_2 + n_3 + ...)! / (n_1! n_2! n_3! ...)`, mod `p`. The method is this: expand each `n_i` in base `p`: `n_i = \sum_j p^j n_{ij}`. Do the same for the sum of the `n_i`'s, which we call `m`: `m = \sum_j p^j m_j`. Then the From 8cfdab1e449b441d0bc957aa835e2a89508958b7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Jun 2022 22:24:37 -0700 Subject: [PATCH 065/116] sage.schemes: Replace $...$ in docstrings by `...` --- .../elliptic_curves/ell_rational_field.py | 2 +- .../schemes/elliptic_curves/saturation.py | 26 +++++++++---------- .../hyperelliptic_finite_field.py | 22 ++++++++-------- .../hyperelliptic_generic.py | 2 +- .../projective/projective_subscheme.py | 8 +++--- src/sage/schemes/toric/divisor.py | 2 +- src/sage/schemes/toric/homset.py | 4 +-- src/sage/schemes/toric/morphism.py | 4 +-- src/sage/schemes/toric/points.py | 2 +- src/sage/schemes/toric/sheaf/klyachko.py | 4 +-- src/sage/schemes/toric/weierstrass.py | 2 +- src/sage/schemes/toric/weierstrass_higher.py | 8 +++--- 12 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_rational_field.py b/src/sage/schemes/elliptic_curves/ell_rational_field.py index 3636a97176f..eb10937f3f0 100644 --- a/src/sage/schemes/elliptic_curves/ell_rational_field.py +++ b/src/sage/schemes/elliptic_curves/ell_rational_field.py @@ -5662,7 +5662,7 @@ def faltings_height(self, stable=False, prec=None): False If the model is changed, the Faltings height changes but the - stable height does not. It is reduced by $\log(u)$ where $u$ + stable height does not. It is reduced by `\log(u)` where `u` is the scale factor:: sage: E1 = E.change_weierstrass_model([10,0,0,0]) diff --git a/src/sage/schemes/elliptic_curves/saturation.py b/src/sage/schemes/elliptic_curves/saturation.py index aa0e25a1413..07b4738c079 100644 --- a/src/sage/schemes/elliptic_curves/saturation.py +++ b/src/sage/schemes/elliptic_curves/saturation.py @@ -601,16 +601,16 @@ def p_projections(Eq, Plist, p, debug=False): OUTPUT: - A list of $r\le2$ vectors in $\GF{p^n}$, the images of the points in - $G \otimes \GF{p}$, where $r$ is the number of vectors is the - $p$-rank of `Eq`. + A list of `r\le2` vectors in `\GF{p^n}`, the images of the points in + `G \otimes \GF{p}`, where `r` is the number of vectors is the + `p`-rank of `Eq`. ALGORITHM: - First project onto the $p$-primary part of `Eq`. If that has - $p$-rank 1 (i.e. is cyclic), use discrete logs there to define a - map to $\GF{p}$, otherwise use the Weil pairing to define two - independent maps to $\GF{p}$. + First project onto the `p`-primary part of `Eq`. If that has + `p`-rank 1 (i.e. is cyclic), use discrete logs there to define a + map to `\GF{p}`, otherwise use the Weil pairing to define two + independent maps to `\GF{p}`. EXAMPLES: @@ -618,9 +618,9 @@ def p_projections(Eq, Plist, p, debug=False): sage: E = EllipticCurve([0,0,1,-7,6]) - We reduce modulo $409$ where its order is $3^2\cdot7^2$; the - $3$-primary part is non-cyclic while the $7$-primary part is - cyclic of order $49$:: + We reduce modulo `409` where its order is `3^2\cdot7^2`; the + `3`-primary part is non-cyclic while the `7`-primary part is + cyclic of order `49`:: sage: F = GF(409) sage: EF = E.change_ring(F) @@ -630,9 +630,9 @@ def p_projections(Eq, Plist, p, debug=False): sage: G.order().factor() 3^2 * 7^2 - We construct three points and project them to the $p$-primary - parts for $p=2,3,5,7$, yielding 0,2,0,1 vectors of length 3 modulo - $p$ respectively. The exact vectors output depend on the computed + We construct three points and project them to the `p`-primary + parts for `p=2,3,5,7`, yielding 0,2,0,1 vectors of length 3 modulo + `p` respectively. The exact vectors output depend on the computed generators of `G`:: sage: Plist = [EF([-2,3]), EF([0,2]), EF([1,0])] diff --git a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py index b3d227d5d0c..3d6588e413e 100644 --- a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +++ b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py @@ -811,12 +811,12 @@ def points(self): [(0 : 6 : 1), (0 : 1 : 1), (1 : 4 : 1), (1 : 3 : 1), (2 : 4 : 1), (2 : 3 : 1), (3 : 6 : 1), (3 : 1 : 1)] The method currently lists points on the plane projective model, that - is the closure in $\mathbb{P}^2$ of the curve defined by $y^2+hy=f$. - This means that one point $(0:1:0)$ at infinity is returned if the - degree of the curve is at least 4 and $\deg(f)>\deg(h)+1$. This point + is the closure in `\mathbb{P}^2` of the curve defined by `y^2+hy=f`. + This means that one point `(0:1:0)` at infinity is returned if the + degree of the curve is at least 4 and `\deg(f)>\deg(h)+1`. This point is a singular point of the plane model. Later implementations may consider a smooth model instead since that would be a more relevant - object. Then, for a curve whose only singularity is at $(0:1:0)$, the + object. Then, for a curve whose only singularity is at `(0:1:0)`, the point at infinity would be replaced by a number of rational points of the smooth model. We illustrate this with an example of a genus 2 hyperelliptic curve:: @@ -827,13 +827,13 @@ def points(self): [(0 : 1 : 0), (0 : 0 : 1), (1 : 7 : 1), (1 : 4 : 1), (5 : 7 : 1), (5 : 4 : 1), (6 : 0 : 1), (7 : 0 : 1), (8 : 0 : 1), (9 : 0 : 1), (10 : 0 : 1)] The plane model of the genus 2 hyperelliptic curve in the above example - is the curve in $\mathbb{P}^2$ defined by $y^2z^4=g(x,z)$ where - $g(x,z)=x(x+z)(x+2z)(x+3z)(x+4z)(x+5z).$ This model has one point at - infinity $(0:1:0)$ which is also the only singular point of the plane + is the curve in `\mathbb{P}^2` defined by `y^2z^4=g(x,z)` where + `g(x,z)=x(x+z)(x+2z)(x+3z)(x+4z)(x+5z).` This model has one point at + infinity `(0:1:0)` which is also the only singular point of the plane model. In contrast, the hyperelliptic curve is smooth and imbeds via - the equation $y^2=g(x,z)$ into weighted projected space - $\mathbb{P}(1,3,1)$. The latter model has two points at infinity: - $(1:1:0)$ and $(1:-1:0)$. + the equation `y^2=g(x,z)` into weighted projected space + `\mathbb{P}(1,3,1)`. The latter model has two points at infinity: + `(1:1:0)` and `(1:-1:0)`. """ from sage.rings.finite_rings.finite_field_constructor import zech_log_bound try: @@ -1426,7 +1426,7 @@ def _Cartier_matrix_cached(self): OUTPUT: - - matrix(Fq,M)' The matrix $M = (c_(pi-j)), f(x)^((p-1)/2) = \sum c_i x^i$ + - matrix(Fq,M)' The matrix `M = (c_(pi-j)), f(x)^((p-1)/2) = \sum c_i x^i` - 'Coeff' List of Coeffs of F, this is needed for Hasse-Witt function. - 'g' genus of the curve self, this is needed by a-number. - 'Fq' is the base field of self, and it is needed for Hasse-Witt diff --git a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py index f76c6e06bac..b9d32c897b0 100644 --- a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +++ b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py @@ -393,7 +393,7 @@ def monsky_washnitzer_gens(self): def invariant_differential(self): """ - Returns $dx/2y$, as an element of the Monsky-Washnitzer cohomology + Returns `dx/2y`, as an element of the Monsky-Washnitzer cohomology of self EXAMPLES:: diff --git a/src/sage/schemes/projective/projective_subscheme.py b/src/sage/schemes/projective/projective_subscheme.py index 2087a47be82..fec6ea3558c 100644 --- a/src/sage/schemes/projective/projective_subscheme.py +++ b/src/sage/schemes/projective/projective_subscheme.py @@ -604,10 +604,10 @@ def _forward_image(self, f, check = True): The forward image is computed through elimination and ``f`` must be a morphism for this to be well defined. - In particular, let $X = V(h_1,\ldots, h_t)$ and define the ideal - $I = (h_1,\ldots,h_t,y_0-f_0(\bar{x}), \ldots, y_n-f_n(\bar{x}))$. - Then the elimination ideal $I_{n+1} = I \cap K[y_0,\ldots,y_n]$ is a homogeneous - ideal and $self(X) = V(I_{n+1})$. + In particular, let `X = V(h_1,\ldots, h_t)` and define the ideal + `I = (h_1,\ldots,h_t,y_0-f_0(\bar{x}), \ldots, y_n-f_n(\bar{x}))`. + Then the elimination ideal `I_{n+1} = I \cap K[y_0,\ldots,y_n]` is a homogeneous + ideal and `self(X) = V(I_{n+1})`. INPUT: diff --git a/src/sage/schemes/toric/divisor.py b/src/sage/schemes/toric/divisor.py index e0255c1b6ae..f0619f33dbf 100644 --- a/src/sage/schemes/toric/divisor.py +++ b/src/sage/schemes/toric/divisor.py @@ -1259,7 +1259,7 @@ def Kodaira_map(self, names='z'): Return the Kodaira map. The Kodaira map is the rational map $X_\Sigma \to - \mathbb{P}^{n-1}$, where $n$ equals the number of sections. It + \mathbb{P}^{n-1}`, where `n` equals the number of sections. It is defined by the monomial sections of the line bundle. If the divisor is ample and the toric variety smooth or of diff --git a/src/sage/schemes/toric/homset.py b/src/sage/schemes/toric/homset.py index 01e721532cd..4cc0c2e340c 100644 --- a/src/sage/schemes/toric/homset.py +++ b/src/sage/schemes/toric/homset.py @@ -472,8 +472,8 @@ class SchemeHomset_points_toric_field(SchemeHomset_points_toric_base): [1 : 3 : 6]] As for a non-compact example, the blow-up of the plane is the line - bundle $O_{\mathbf{P}^1}(-1)$. Its point set is the Cartesian - product of the points on the base $\mathbf{P}^1$ with the points + bundle `O_{\mathbf{P}^1}(-1)`. Its point set is the Cartesian + product of the points on the base `\mathbf{P}^1` with the points on the fiber:: sage: fan = Fan([Cone([(1,0), (1,1)]), Cone([(1,1), (0,1)])]) diff --git a/src/sage/schemes/toric/morphism.py b/src/sage/schemes/toric/morphism.py index 092290fa54c..ca5686eebe8 100644 --- a/src/sage/schemes/toric/morphism.py +++ b/src/sage/schemes/toric/morphism.py @@ -158,7 +158,7 @@ that is dominant over the image or its closure). For example, consider the blow-up restricted to one of the two -coordinate charts of $O_{\mathbb{P}^1}(2)$ :: +coordinate charts of `O_{\mathbb{P}^1}(2)` :: sage: O2_P1_chart = ToricVariety(Fan([O2_P1.fan().generating_cones()[0]])) @@ -230,7 +230,7 @@ So we see that the fiber over this point is an affine line. Together with another affine line in the other coordinate patch, this covers -the exceptional $\mathbb{P}^1$ of the blowup $O_{\mathbb{P}^1}(2) \to +the exceptional `\mathbb{P}^1` of the blowup `O_{\mathbb{P}^1}(2) \to \CC^2/\ZZ_2$. Here is an example with higher dimensional varieties involved:: diff --git a/src/sage/schemes/toric/points.py b/src/sage/schemes/toric/points.py index 8d79a7760c6..5da8f26a9c5 100644 --- a/src/sage/schemes/toric/points.py +++ b/src/sage/schemes/toric/points.py @@ -525,7 +525,7 @@ def _Chow_group_torsion_generators(self): OUTPUT: A tuple containing generators for - $Hom(A_{d-1,\text{tors}}, F^\times)$. + `Hom(A_{d-1,\text{tors}}, F^\times)`. EXAMPLES:: diff --git a/src/sage/schemes/toric/sheaf/klyachko.py b/src/sage/schemes/toric/sheaf/klyachko.py index 2932d9b03e5..b1304a16913 100644 --- a/src/sage/schemes/toric/sheaf/klyachko.py +++ b/src/sage/schemes/toric/sheaf/klyachko.py @@ -391,8 +391,8 @@ def E_degree(self, alpha, m): OUTPUT: - The subspace $E^\alpha(\alpha m)$ of the filtration indexed by - the ray $\alpha$ and at the filtration degree $\alpha * m$ + The subspace `E^\alpha(\alpha m)` of the filtration indexed by + the ray `\alpha` and at the filtration degree `\alpha * m` EXAMPLES:: diff --git a/src/sage/schemes/toric/weierstrass.py b/src/sage/schemes/toric/weierstrass.py index 3813cf53b80..552a91093d6 100644 --- a/src/sage/schemes/toric/weierstrass.py +++ b/src/sage/schemes/toric/weierstrass.py @@ -353,7 +353,7 @@ def Newton_polygon_embedded(polynomial, variables): def WeierstrassForm(polynomial, variables=None, transformation=False): r""" Return the Weierstrass form of an elliptic curve inside either - inside a toric surface or $\mathbb{P}^3$. + inside a toric surface or `\mathbb{P}^3`. INPUT: diff --git a/src/sage/schemes/toric/weierstrass_higher.py b/src/sage/schemes/toric/weierstrass_higher.py index d8bd20cf4f6..2f68532b48c 100644 --- a/src/sage/schemes/toric/weierstrass_higher.py +++ b/src/sage/schemes/toric/weierstrass_higher.py @@ -123,7 +123,7 @@ def _check_polynomials_P3(quadratic1, quadratic2, variables): ###################################################################### def _biquadratic_syzygy_quartic(quadratic1, quadratic2, variables=None): r""" - Helper function for the Weierstrass form of a biquadratic in $`\mathbb{P}^3$ + Helper function for the Weierstrass form of a biquadratic in `\mathbb{P}^3` The invariants and covariants of a quaternary biquadratic satisfy the relation @@ -131,9 +131,9 @@ def _biquadratic_syzygy_quartic(quadratic1, quadratic2, variables=None): which is (modulo the two quadratic equations) of the form $J^2 = p_4(T, T')$ where - * $J$, $T$, $T'$ are the covariants of the biquadratic. + * `J`, `T`, `T'` are the covariants of the biquadratic. - * $p_4$ is some quartic polynomial whose coefficients are + * `p_4` is some quartic polynomial whose coefficients are invariants of the biquadratic. INPUT: @@ -147,7 +147,7 @@ def _biquadratic_syzygy_quartic(quadratic1, quadratic2, variables=None): - The quaternary biquadratic as an algebraic form :class:`~sage.rings.invariant_theory.TwoQuaternaryQuadratics` - - The binary quartic $p_4$ as a + - The binary quartic `p_4` as a :class:`~sage.rings.invariant_theory.BinaryQuartic` - The dictionary of variable substitutions from the variables of From b215c7e23bce4166d936c9dc8aec04959fde3e00 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Jun 2022 22:28:16 -0700 Subject: [PATCH 066/116] sage.rings: Replace $...$ in docstrings by `...` --- src/sage/rings/bernmm.pyx | 8 +++--- src/sage/rings/cfinite_sequence.py | 4 +-- src/sage/rings/number_field/S_unit_solver.py | 4 +-- .../polynomial_padic_capped_relative_dense.py | 28 +++++++++---------- src/sage/rings/polynomial/pbori/fglm.py | 4 +-- src/sage/rings/power_series_poly.pyx | 4 +-- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/sage/rings/bernmm.pyx b/src/sage/rings/bernmm.pyx index 74c2aa19738..00a3da0d1ff 100644 --- a/src/sage/rings/bernmm.pyx +++ b/src/sage/rings/bernmm.pyx @@ -52,7 +52,7 @@ def bernmm_bern_rat(long k, int num_threads = 1): COMPLEXITY: - Pretty much quadratic in $k$. See the paper "A multimodular algorithm + Pretty much quadratic in `k`. See the paper "A multimodular algorithm for computing Bernoulli numbers", David Harvey, 2008, for more details. EXAMPLES:: @@ -98,9 +98,9 @@ def bernmm_bern_rat(long k, int num_threads = 1): def bernmm_bern_modp(long p, long k): r""" - Computes $B_k \mod p$, where $B_k$ is the k-th Bernoulli number. + Computes `B_k \mod p`, where `B_k` is the k-th Bernoulli number. - If $B_k$ is not $p$-integral, returns -1. + If `B_k` is not `p`-integral, returns -1. INPUT: @@ -109,7 +109,7 @@ def bernmm_bern_modp(long p, long k): COMPLEXITY: - Pretty much linear in $p$. + Pretty much linear in `p`. EXAMPLES:: diff --git a/src/sage/rings/cfinite_sequence.py b/src/sage/rings/cfinite_sequence.py index adf8cd9415b..02520ec2efb 100644 --- a/src/sage/rings/cfinite_sequence.py +++ b/src/sage/rings/cfinite_sequence.py @@ -1106,8 +1106,8 @@ def _coerce_map_from_(self, S): def from_recurrence(self, coefficients, values): r""" - Create a C-finite sequence given the coefficients $c$ and - starting values $a$ of a homogeneous linear recurrence. + Create a C-finite sequence given the coefficients `c` and + starting values `a` of a homogeneous linear recurrence. .. MATH:: diff --git a/src/sage/rings/number_field/S_unit_solver.py b/src/sage/rings/number_field/S_unit_solver.py index 4e440c36ea0..6b50b7a66b6 100644 --- a/src/sage/rings/number_field/S_unit_solver.py +++ b/src/sage/rings/number_field/S_unit_solver.py @@ -1,7 +1,7 @@ r""" Solve S-unit equation x + y = 1 -Inspired by work of Tzanakis--de Weger, Baker--Wustholz and Smart, we use the LLL methods in Sage to implement an algorithm that returns all S-unit solutions to the equation $x + y = 1$. +Inspired by work of Tzanakis--de Weger, Baker--Wustholz and Smart, we use the LLL methods in Sage to implement an algorithm that returns all S-unit solutions to the equation `x + y = 1`. REFERENCES: @@ -850,7 +850,7 @@ def K1_func(SUK, v, A, prec=106): - ``SUK`` -- a group of `S`-units - ``v`` -- an infinite place of ``K`` (element of ``SUK.number_field().places(prec)``) - - ``A`` -- a list of all products of each potential ``a``, ``b`` in the $S$-unit equation ``ax + by + 1 = 0`` with each root of unity of ``K`` + - ``A`` -- a list of all products of each potential ``a``, ``b`` in the `S`-unit equation ``ax + by + 1 = 0`` with each root of unity of ``K`` - ``prec`` -- the precision of the real field (default: 106) OUTPUT: diff --git a/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py b/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py index 6eac70126dc..42d2b9ce1db 100644 --- a/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py +++ b/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py @@ -489,19 +489,19 @@ def _mul_(self, right): ALGORITHM: We use an algorithm thought up by Joe Wetherell to find the precisions of the product. It works as follows: - Suppose $f = \sum_i a_i x^i$ and $g = \sum_j b_j x^j$. Let $N - = \max(\deg f, \deg g) + 1$ (in the actual implementation we - use $N = 2^{\lfloor \log_2\max(\deg f, \deg g)\rfloor + 1}$). + Suppose `f = \sum_i a_i x^i` and `g = \sum_j b_j x^j`. Let `N + = \max(\deg f, \deg g) + 1` (in the actual implementation we + use `N = 2^{\lfloor \log_2\max(\deg f, \deg g)\rfloor + 1}`). The valuations and absolute precisions of each coefficient contribute to the absolute precision of the kth coefficient of - the product in the following way: for each $i + j = k$, you - take the valuation of $a_i$ plus the absolute precision of - $b_j$, and then take the valuation of $b_j$ plus the absolute - precision of $a_i$, take the minimum of those two, and then - take the minimum over all $i$, $j$ summing to $k$. + the product in the following way: for each `i + j = k`, you + take the valuation of `a_i` plus the absolute precision of + `b_j`, and then take the valuation of `b_j` plus the absolute + precision of `a_i`, take the minimum of those two, and then + take the minimum over all `i`, `j` summing to `k`. You can simulate this as follows. Construct new polynomials of - degree $N$: + degree `N`: \begin{align*} A &= \sum_i N^{\mbox{valuation of $a_i$}} x^i \\ @@ -519,7 +519,7 @@ def _mul_(self, right): our implementation. Since we're working 'N-adically' we can just consider - $N^{\infty} = 0$. + `N^{\infty} = 0`. NOTE: The timing of normalization in arithmetic operations may very well change as we do more tests on the relative time @@ -762,8 +762,8 @@ def degree(self, secure=False): indistinguishable from 0), an error is raised. If ``secure`` is ``False``, the returned value is the largest - $n$ so that the coefficient of $x^n$ does not compare equal - to $0$. + `n` so that the coefficient of `x^n` does not compare equal + to `0`. EXAMPLES:: @@ -801,8 +801,8 @@ def degree(self, secure=False): def prec_degree(self): """ - Return the largest $n$ so that precision information is - stored about the coefficient of $x^n$. + Return the largest `n` so that precision information is + stored about the coefficient of `x^n`. Always greater than or equal to degree. diff --git a/src/sage/rings/polynomial/pbori/fglm.py b/src/sage/rings/polynomial/pbori/fglm.py index bbcfd33fe35..dc60adef14c 100644 --- a/src/sage/rings/polynomial/pbori/fglm.py +++ b/src/sage/rings/polynomial/pbori/fglm.py @@ -61,9 +61,9 @@ def vars_real_divisors(monomial, monomial_set): def m_k_plus_one(completed_elements, variables): r""" - Calculate $m_{k+1}$ from the FGLM algorithm. + Calculate `m_{k+1}` from the FGLM algorithm. - Calculate $m_{k+1}$ from the FGLM algorithm as described in Wichmann [Wich1997]_. + Calculate `m_{k+1}` from the FGLM algorithm as described in Wichmann [Wich1997]_. .. NOTE:: diff --git a/src/sage/rings/power_series_poly.pyx b/src/sage/rings/power_series_poly.pyx index 566b0c3d251..198c8e99438 100644 --- a/src/sage/rings/power_series_poly.pyx +++ b/src/sage/rings/power_series_poly.pyx @@ -754,8 +754,8 @@ cdef class PowerSeries_poly(PowerSeries): def truncate_powerseries(self, long prec): r""" - Given input ``prec`` = $n$, returns the power series of degree - $< n$ which is equivalent to self modulo $x^n$. + Given input ``prec`` = `n`, returns the power series of degree + `< n` which is equivalent to self modulo `x^n`. EXAMPLES:: From 3b2311ae275505f9243a64251de9d7ec8b796753 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Fri, 10 Jun 2022 17:13:24 +0900 Subject: [PATCH 067/116] Remove a period sneaked in --- src/doc/en/website/templates/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/en/website/templates/index.html b/src/doc/en/website/templates/index.html index d8895243052..cdadfb78ffd 100644 --- a/src/doc/en/website/templates/index.html +++ b/src/doc/en/website/templates/index.html @@ -33,7 +33,7 @@

{{ docstitle|e }}

. +

{% block tables %}

From aa06a211bd923aeb7ebc51b7de088a1e224646b4 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Fri, 10 Jun 2022 16:55:06 +0800 Subject: [PATCH 068/116] faster 2-adic lifting for square roots modulo 2^n --- src/sage/rings/finite_rings/integer_mod.pyx | 36 +++++++-------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index 401bd3cd794..f14ecbc5412 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -3891,9 +3891,7 @@ def square_root_mod_prime_power(IntegerMod_abstract a, p, e): ALGORITHM: Compute `p`-adically by stripping off even powers of `p` to get a unit and lifting `\sqrt{unit} \bmod p` via Newton's method - whenever `p` is odd and via - `\sqrt{1+y} = \sum_{k=0}^\infty \binom{1/2}{k} y^k` - for `p = 2`. + whenever `p` is odd and by a variant of Hensel lifting for `p = 2`. AUTHORS: @@ -3952,28 +3950,16 @@ def square_root_mod_prime_power(IntegerMod_abstract a, p, e): if unit.lift() % 8 != 1: raise ValueError("self must be a square") - if unit == 1: - return a.parent()(one_Z << val//2) - - # sqrt(1+y) = sum_{k=0}^{oo} binomial(1/2,k) y^k - y = unit - 1 - v = y.valuation(2) - y >>= v - - # 2-valuation of y^k / binomial(1/2,k) is >= (v-2)*k - n = 1 + (e + v-3) // (v-2) - - t = a.parent().one() # unit part - s = 0 # shift - - x = a.parent().one() - for i in range(1, n): - d = Integer(i) << 1 - c = 3 - d - t *= y * c.prime_to_m_part(2) / d.prime_to_m_part(2) - s += v + c.valuation(2) - d.valuation(2) -# assert t.is_unit() and s >= 0 - x += t << s + u = unit.lift() + x = next(i for i in range(1,8,2) if i*i & 31 == u & 31) + t = (x*x - u) >> 5 + for i in range(4, e-1 - val//2): + if t & 1: + x |= one_Z << i + t += x - (one_Z << i-1) + t >>= 1 +# assert t << i+2 == x*x - u + x = a.parent()(x) else: # find square root of unit mod p From 8e34f345233af19473f8b52afde5a398b5f08efc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 10 Jun 2022 12:38:16 -0700 Subject: [PATCH 069/116] Reviewer fixes to docstrings --- src/sage/categories/coxeter_groups.py | 2 +- src/sage/categories/examples/semigroups_cython.pyx | 2 +- src/sage/coding/guava.py | 2 +- .../geometry/riemannian_manifolds/parametrized_surface3d.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 3f164f536a1..11a082d2fe6 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -2744,7 +2744,7 @@ def deodhar_lift_down(self, w, index_set): OUTPUT: The unique Bruhat-maximum element ``x`` in ``W`` such that ``x W' = w W'`` - and ``v `\ge` ``x``. + and ``v`` `\ge` ``x``. .. SEEALSO:: :meth:`sage.categories.coxeter_groups.CoxeterGroups.ElementMethods.deodhar_lift_up` diff --git a/src/sage/categories/examples/semigroups_cython.pyx b/src/sage/categories/examples/semigroups_cython.pyx index 95e79315e6b..ffd8dad8342 100644 --- a/src/sage/categories/examples/semigroups_cython.pyx +++ b/src/sage/categories/examples/semigroups_cython.pyx @@ -151,7 +151,7 @@ class LeftZeroSemigroup(LeftZeroSemigroupPython): sage: S.some_elements() [3, 42, 'a', 3.4, 'raton laveur'] - with product rule is given by `a \times b = a` for all `a,b`. :: + with product rule given by `a \times b = a` for all `a,b`. :: sage: S('hello') * S('world') 'hello' diff --git a/src/sage/coding/guava.py b/src/sage/coding/guava.py index e031b00af3d..26d94e068f3 100644 --- a/src/sage/coding/guava.py +++ b/src/sage/coding/guava.py @@ -62,7 +62,7 @@ def QuasiQuadraticResidueCode(p): sage: C = codes.QuasiQuadraticResidueCode(11); C # optional - gap_packages (Guava package) [22, 11] linear code over GF(2) - These are self-orthogonal in general and self-dual when `p \\equiv 3 \\pmod 4`. + These are self-orthogonal in general and self-dual when `p \equiv 3 \pmod 4`. AUTHOR: David Joyner (11-2005) """ diff --git a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py index c1a126b630a..15285685477 100644 --- a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py +++ b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py @@ -825,7 +825,7 @@ def rotation(self,theta): The operator of rotation over `\pi/2` is `J^i_j = g^{ik}\omega_{jk}`, where `\omega` is the area form. The operator of rotation over an - angle `\theta` is `\cos(\theta) I + sin(\theta) J`. + angle `\theta` is `\cos(\theta) I + \sin(\theta) J`. EXAMPLES:: From afa5bed0f784d25343cbf9c95a680e5af1a3a61c Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Fri, 10 Jun 2022 15:10:36 -0700 Subject: [PATCH 070/116] trac 33968: more changes --- src/sage/combinat/matrices/hadamard_matrix.py | 2 +- src/sage/geometry/lattice_polytope.py | 2 +- src/sage/groups/matrix_gps/isometries.py | 8 ++++---- src/sage/rings/number_field/number_field.py | 2 +- src/sage/rings/rational_field.py | 2 +- src/sage/schemes/toric/morphism.py | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sage/combinat/matrices/hadamard_matrix.py b/src/sage/combinat/matrices/hadamard_matrix.py index d12f3e644c4..ea2d5160622 100644 --- a/src/sage/combinat/matrices/hadamard_matrix.py +++ b/src/sage/combinat/matrices/hadamard_matrix.py @@ -1156,7 +1156,7 @@ def symmetric_conference_matrix(n, check=True): A conference matrix is an `n\times n` matrix `C` with 0s on the main diagonal and 1s and -1s elsewhere, satisfying `CC^\top=(n-1)I`. - If `C=C^\top$ then `n \cong 2 \mod 4` and `C` is Seidel adjacency matrix of + If `C=C^\top` then `n \cong 2 \mod 4` and `C` is Seidel adjacency matrix of a graph, whose descendent graphs are strongly regular graphs with parameters `(n-1,(n-2)/2,(n-6)/4,(n-2)/4)`, see Sec.10.4 of [BH2012]_. Thus we build `C` from the Seidel adjacency matrix of the latter by adding row and column of 1s. diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index 89a4e9a2191..eba29281a7c 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -4263,7 +4263,7 @@ class NefPartition(SageObject, Hashable): `\overline{N} = N \times \ZZ^k` are dual lattices. The **Cayley polytope** `P \subset \overline{M}_\RR` of a nef-partition is - given by $P = \mathrm{Conv}(\Delta_0 \times e_0, \Delta_1 \times e_1, + given by `P = \mathrm{Conv}(\Delta_0 \times e_0, \Delta_1 \times e_1, \ldots, \Delta_{k-1} \times e_{k-1})`, where `\{e_i\}_{i=0}^{k-1}` is the standard basis of `\ZZ^k`. The **dual Cayley polytope** `P^* \subset \overline{N}_\RR` is the Cayley polytope of the dual diff --git a/src/sage/groups/matrix_gps/isometries.py b/src/sage/groups/matrix_gps/isometries.py index ab611b4ce7f..f9111a2c926 100644 --- a/src/sage/groups/matrix_gps/isometries.py +++ b/src/sage/groups/matrix_gps/isometries.py @@ -1,10 +1,10 @@ r""" Groups of isometries. -Let `M = \ZZ^n` or `\QQ^n`, `b: M \times M \rightarrow \QQ$ a bilinear form and -$f: M \rightarrow M$ a linear map. We say that $f$ is an isometry if for all -elements $x,y$ of $M$ we have that $b(x,y)=b(f(x),f(y))$. -A group of isometries is a subgroup of $GL(M)$ consisting of isometries. +Let `M = \ZZ^n` or `\QQ^n`, `b: M \times M \rightarrow \QQ` a bilinear form and +`f: M \rightarrow M` a linear map. We say that `f` is an isometry if for all +elements `x,y` of `M` we have that `b(x,y)=b(f(x),f(y))`. +A group of isometries is a subgroup of `GL(M)` consisting of isometries. EXAMPLES:: diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index 78e0eb50e92..e00dbe9b7d2 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -5133,7 +5133,7 @@ def selmer_space(self, S, p, proof=None): `K(S,p)`, mapping them via the inverse isomorphism to the abstract vector space ``KSp``. - The group `K(S,p)` is the finite subgroup of `K^*/(K^*)^p$ + The group `K(S,p)` is the finite subgroup of `K^*/(K^*)^p` consisting of elements whose valuation at all primes not in `S` is a multiple of `p`. It contains the subgroup of those `a\in K^*` such that `K(\sqrt[p]{a})/K` is unramified at all diff --git a/src/sage/rings/rational_field.py b/src/sage/rings/rational_field.py index 5327b921799..50710e0c13d 100644 --- a/src/sage/rings/rational_field.py +++ b/src/sage/rings/rational_field.py @@ -1405,7 +1405,7 @@ def selmer_space(self, S, p, proof=None): abstract vector space ``QSp``. The group `\QQ(S,p)` is the finite subgroup of - `\QQ^*/(\QQ^*)^p$ consisting of elements whose valuation at + `\QQ^*/(\QQ^*)^p` consisting of elements whose valuation at all primes not in `S` is a multiple of `p`. It contains the subgroup of those `a\in \QQ^*` such that `\QQ(\sqrt[p]{a})/\QQ` is unramified at all primes of `\QQ` diff --git a/src/sage/schemes/toric/morphism.py b/src/sage/schemes/toric/morphism.py index ca5686eebe8..75b683a41f7 100644 --- a/src/sage/schemes/toric/morphism.py +++ b/src/sage/schemes/toric/morphism.py @@ -231,7 +231,7 @@ So we see that the fiber over this point is an affine line. Together with another affine line in the other coordinate patch, this covers the exceptional `\mathbb{P}^1` of the blowup `O_{\mathbb{P}^1}(2) \to -\CC^2/\ZZ_2$. +\CC^2/\ZZ_2`. Here is an example with higher dimensional varieties involved:: From 8131256c2145a5645e0bb5cf33cf4eff330d0320 Mon Sep 17 00:00:00 2001 From: Dave Witte Morris Date: Fri, 10 Jun 2022 18:31:00 -0600 Subject: [PATCH 071/116] reviewer corrections --- src/sage/functions/orthogonal_polys.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/sage/functions/orthogonal_polys.py b/src/sage/functions/orthogonal_polys.py index ade05522bdd..85d8f603164 100644 --- a/src/sage/functions/orthogonal_polys.py +++ b/src/sage/functions/orthogonal_polys.py @@ -1291,12 +1291,13 @@ class Func_legendre_P(GinacFunction): ... RuntimeError: derivative w.r.t. to the index is not supported yet - TESTS:: + TESTS: + + Verify that :trac:`33962` is fixed:: - # verify that :trac:`33962` is fixed sage: [legendre_P(n, 0) for n in range(-10, 10)] [0, 35/128, 0, -5/16, 0, 3/8, 0, -1/2, 0, 1, - 1, 0, -1/2, 0, 3/8, 0, -5/16, 0, 35/128, 0] + 1, 0, -1/2, 0, 3/8, 0, -5/16, 0, 35/128, 0] """ def __init__(self): r""" From a3608a41a27c55eed9de19c40fb85c9c84db32db Mon Sep 17 00:00:00 2001 From: Dave Witte Morris Date: Wed, 8 Jun 2022 22:57:11 -0600 Subject: [PATCH 072/116] trac 33963: fix legendre polynomial --- src/sage/functions/orthogonal_polys.py | 9 +++++++++ src/sage/symbolic/ginac/mul.cpp | 2 ++ 2 files changed, 11 insertions(+) diff --git a/src/sage/functions/orthogonal_polys.py b/src/sage/functions/orthogonal_polys.py index 85d8f603164..6ea987aaa19 100644 --- a/src/sage/functions/orthogonal_polys.py +++ b/src/sage/functions/orthogonal_polys.py @@ -1298,6 +1298,15 @@ class Func_legendre_P(GinacFunction): sage: [legendre_P(n, 0) for n in range(-10, 10)] [0, 35/128, 0, -5/16, 0, 3/8, 0, -1/2, 0, 1, 1, 0, -1/2, 0, 3/8, 0, -5/16, 0, 35/128, 0] + + Verify that :trac:`33963` is fixed:: + + sage: n = var("n") + sage: assume(n, "integer") + sage: assume(n, "even") + sage: legendre_P(n, 0) + 2^(-n + 2)*(-1)^(1/2*n)*gamma(n)/(n*gamma(1/2*n)^2) + sage: forget() """ def __init__(self): r""" diff --git a/src/sage/symbolic/ginac/mul.cpp b/src/sage/symbolic/ginac/mul.cpp index c800cbf8475..6a3a8321bd2 100644 --- a/src/sage/symbolic/ginac/mul.cpp +++ b/src/sage/symbolic/ginac/mul.cpp @@ -415,6 +415,8 @@ bool mul::info(unsigned inf) const return overall_coeff.info(inf); } case info_flags::even: { + if (not overall_coeff.is_integer()) + return false; bool even_seen = false; for (const auto &elem : seq) { const ex &e = recombine_pair_to_ex(elem); From 13eced813040aab0eed0a440b9ed961c0850f492 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 10 Jun 2022 18:21:15 -0700 Subject: [PATCH 073/116] src/sage/misc/sagedoc.py (process_dollars): Emit deprecation warnings --- src/sage/misc/sagedoc.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sage/misc/sagedoc.py b/src/sage/misc/sagedoc.py index 37fd5d8b6e6..fe369cd0036 100644 --- a/src/sage/misc/sagedoc.py +++ b/src/sage/misc/sagedoc.py @@ -448,6 +448,7 @@ def process_dollars(s): """ if s.find("$") == -1: return s + from sage.misc.superseded import deprecation # find how much leading whitespace s has, for later comparison: # ignore all $ on lines which start with more whitespace. whitespace = re.match(r'\s*\S', s.lstrip('\n')) @@ -485,6 +486,9 @@ def process_dollars(s): while dollar.search(s, start, end): m = dollar.search(s, start, end) s = s[:m.end()-1] + "`" + s[m.end():] + deprecation(33973, + "using dollar signs to mark up math in Sage docstrings " + "is deprecated; use backticks instead") while slashdollar.search(s, start, end): m = slashdollar.search(s, start, end) s = s[:m.start()] + "$" + s[m.end():] From 63135495551c8cde3b267baa95f6c65c9071c78c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 10 Jun 2022 18:54:32 -0700 Subject: [PATCH 074/116] src/doc/en/developer/coding_basics.rst: No more dollar signs for math --- src/doc/en/developer/coding_basics.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/doc/en/developer/coding_basics.rst b/src/doc/en/developer/coding_basics.rst index 2b540852a61..be52a2734b3 100644 --- a/src/doc/en/developer/coding_basics.rst +++ b/src/doc/en/developer/coding_basics.rst @@ -728,10 +728,9 @@ there is not one already. That is, you can do the following: LaTeX Typesetting ----------------- -In Sage's documentation LaTeX code is allowed and is marked with **backticks or -dollar signs**: +In Sage's documentation LaTeX code is allowed and is marked with **backticks**: - ```x^2 + y^2 = 1``` and ``$x^2 + y^2 = 1$`` both yield `x^2 + y^2 = 1`. + ```x^2 + y^2 = 1``` yields `x^2 + y^2 = 1`. **Backslashes:** For LaTeX commands containing backslashes, either use double backslashes or begin the docstring with a ``r"""`` instead of ``"""``. Both of @@ -744,7 +743,7 @@ the following are valid:: def sin(x): r""" - Return $\sin(x)$. + Return `\sin(x)`. """ **MATH block:** This is similar to the LaTeX syntax ``\[\]`` From 00ef03f93178000daaf7f108d55b9bbfac811a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 11 Jun 2022 10:26:31 +0200 Subject: [PATCH 075/116] get rid of commented-out old-style print --- src/bin/sage-preparse | 3 +- src/sage/algebras/q_system.py | 8 +-- src/sage/combinat/growth.py | 5 +- .../hecke_algebra_representation.py | 5 +- .../weight_lattice_realizations.py | 2 - src/sage/geometry/voronoi_diagram.py | 2 - .../graphs/graph_decompositions/bandwidth.pyx | 3 +- src/sage/interfaces/kash.py | 18 ------ src/sage/libs/symmetrica/symmetrica.pxi | 3 - src/sage/modular/modform/half_integral.py | 6 +- .../graded_ring_element.py | 3 - src/sage/modules/fg_pid/fgp_element.py | 9 +-- src/sage/numerical/linear_functions.pyx | 2 +- src/sage/plot/bar_chart.py | 5 +- src/sage/quadratic_forms/extras.py | 18 ++---- .../quadratic_form__local_field_invariants.py | 8 --- ...c_form__local_representation_conditions.py | 5 +- ...dratic_form__mass__Conway_Sloane_masses.py | 12 ---- .../quadratic_form__mass__Siegel_densities.py | 63 ++----------------- .../quadratic_forms/quadratic_form__theta.py | 51 +-------------- .../rings/padics/padic_extension_leaves.py | 4 +- src/sage/rings/padics/pow_computer_ext.pyx | 57 ----------------- src/sage/rings/polynomial/refine_root.pyx | 3 +- src/sage/rings/tate_algebra_ideal.pyx | 1 - src/sage/schemes/elliptic_curves/BSD.py | 2 +- src/sage/schemes/elliptic_curves/height.py | 4 -- src/sage/tests/benchmark.py | 4 +- 27 files changed, 33 insertions(+), 273 deletions(-) diff --git a/src/bin/sage-preparse b/src/bin/sage-preparse index 564ef9639a6..6392909ce1c 100755 --- a/src/bin/sage-preparse +++ b/src/bin/sage-preparse @@ -278,8 +278,7 @@ def do_load_and_attach(G, file, files_before): files = z.group('files').split() lws = z.group('lws') for w in files: - name = w.replace(',','').replace('"','').replace("'","") - #print "'%s'"%name, files_before + name = w.replace(',', '').replace('"', '').replace("'", "") if name in files_before: print("WARNING: not loading {} (in {}) again since would cause circular loop" .format(name, file)) diff --git a/src/sage/algebras/q_system.py b/src/sage/algebras/q_system.py index bbbf71e42cf..e7f808af4b7 100644 --- a/src/sage/algebras/q_system.py +++ b/src/sage/algebras/q_system.py @@ -263,16 +263,14 @@ def _ascii_art_term(self, t): ret += AsciiArt(['*'], baseline=0) else: first = False - a,m = k + a, m = k var = AsciiArt([" ({})".format(a), "Q{}".format(m)], baseline=0) - #print var - #print " "*(len(str(m))+1) + "({})".format(a) + '\n' + "Q{}".format(m) if exp > 1: - var = (AsciiArt(['(','('], baseline=0) + var + var = (AsciiArt(['(', '('], baseline=0) + var + AsciiArt([')', ')'], baseline=0)) - var = AsciiArt([" "*len(var) + str(exp)], baseline=-1) * var + var = AsciiArt([" " * len(var) + str(exp)], baseline=-1) * var ret += var return ret diff --git a/src/sage/combinat/growth.py b/src/sage/combinat/growth.py index 7be7b2a877b..6d584f6dea6 100644 --- a/src/sage/combinat/growth.py +++ b/src/sage/combinat/growth.py @@ -2194,13 +2194,12 @@ def forward_rule(self, y, e, t, f, x, content): g, z = 1, _make_partition(y).add_cell(row) # black else: g, z = 2, _make_partition(y).add_cell(row) # blue - elif x == y != t and f in [1, 3]: # black or red + elif x == y != t and f in [1, 3]: # black or red c = SkewPartition([x, t]).cells()[0] col = c[0] + c[1] + 1 - # print y, t, x, c, col for i in range(len(y)): if i + y[i] == col: - z = y[:i] + [y[i]+1] + y[i+1:] + z = y[:i] + [y[i] + 1] + y[i + 1:] break g = 3 else: diff --git a/src/sage/combinat/root_system/hecke_algebra_representation.py b/src/sage/combinat/root_system/hecke_algebra_representation.py index 3eff906dc39..e146784ad98 100644 --- a/src/sage/combinat/root_system/hecke_algebra_representation.py +++ b/src/sage/combinat/root_system/hecke_algebra_representation.py @@ -611,7 +611,6 @@ def Y_lambdacheck(self, lambdacheck): alphacheck = P_check.simple_roots() c = Q_check.cartan_type().translation_factors() t = P_check.linear_combination( (alphacheck[i], c[i] * coeff) for i,coeff in lambdacheck ) - #print lambdacheck, "=", t # In type BC, c[i] may introduce rational coefficients # If we want to work in the lattice we might want to use the # following workaround after the fact ... @@ -1138,9 +1137,7 @@ def __getitem__(self, mu): muaffi = self.twist(muaff, i) mui = self.affine_retract(muaffi) E_mui = self[mui] - #print "Computing %s from E_%s=%s with T_%s"%(l, mui, E_mui, i) - q1,q2 = self.hecke_parameters(i) - #print q1, q2, self.eigenvalue(mui, -alphacheck[i]) + q1, q2 = self.hecke_parameters(i) coroot = alphacheck[i] ct = self.cartan_type() special_node = ct.special_node() diff --git a/src/sage/combinat/root_system/weight_lattice_realizations.py b/src/sage/combinat/root_system/weight_lattice_realizations.py index 07595137351..d6092d01968 100644 --- a/src/sage/combinat/root_system/weight_lattice_realizations.py +++ b/src/sage/combinat/root_system/weight_lattice_realizations.py @@ -694,7 +694,6 @@ def _test_reduced_word_of_translation(self, elements=None, **options): tester.assertIn(root, rank_simple_roots) permutation[i] = rank_simple_roots[root] tester.assertEqual(set(permutation), set(self.index_set())) - #print permutation # It could be nicer to test equality of G and its relabelling for i in self.index_set(): for j in self.index_set(): @@ -708,7 +707,6 @@ def _test_reduced_word_of_translation(self, elements=None, **options): # automorphisms, which are in bijection with the special nodes #from sage.groups.perm_gps.permgroup import PermutationGroup #P = PermutationGroup([[i+1 for i in permutation] for permutation in permutations]) - #print P, len(P) #tester.assertEqual(P, G.automorphism_group()) pass diff --git a/src/sage/geometry/voronoi_diagram.py b/src/sage/geometry/voronoi_diagram.py index 20ea56efeb3..e280a41143a 100644 --- a/src/sage/geometry/voronoi_diagram.py +++ b/src/sage/geometry/voronoi_diagram.py @@ -134,7 +134,6 @@ def __init__(self, points): enormalized.append(ineq) else: enormalized.append([i / ineq[0] for i in ineq[1:]]) - # print enormalized hlist = [list(ineq) for ineq in p.Hrepresentation()] hlistnormalized = [] for ineq in hlist: @@ -142,7 +141,6 @@ def __init__(self, points): hlistnormalized.append(ineq) else: hlistnormalized.append([i / ineq[0] for i in ineq[1:]]) - # print hlistnormalized for i in range(self._n): # for base ring RDF and AA, Polyhedron keeps the order of the diff --git a/src/sage/graphs/graph_decompositions/bandwidth.pyx b/src/sage/graphs/graph_decompositions/bandwidth.pyx index 91ffeeab130..44125b798db 100644 --- a/src/sage/graphs/graph_decompositions/bandwidth.pyx +++ b/src/sage/graphs/graph_decompositions/bandwidth.pyx @@ -392,12 +392,11 @@ cdef bint is_matching_feasible(int n, range_t * range_array, range_t * range_arr cdef int v, M, m, j for v in range(n): if range_array[v].M < range_array[v].m: - # print range_array[v].m, range_array[v].M return 0 index_array_tmp[v] = 0 # Sort the guys according to increasing value of M in O(n). - # + # Step 1: count the occurrences of each M for v in range(n): index_array_tmp[range_array[v].M] += 1 diff --git a/src/sage/interfaces/kash.py b/src/sage/interfaces/kash.py index 8cfc1dd8483..ce837b87737 100644 --- a/src/sage/interfaces/kash.py +++ b/src/sage/interfaces/kash.py @@ -558,24 +558,6 @@ def eval(self, x, newlines=False, strip=True, **kwds): else: return s.replace("\\\n", "") -# def help(self, name=None): -# """ -# Return help on KASH commands. - -# EXAMPLES:: - -# sage: X = kash.help('IntegerRing') # optional - kash - -# """ -# if name is None: -# print '\nTo use KASH help enter kash.help(s). ' -# print 'The syntax of the string s is given below.\n' -# print self.eval('?') -# elif name[0] == '?': -# print self.eval(name) -# else: -# print self.eval('?%s'%name) - def help(self, name=None): """ Return help on KASH commands. diff --git a/src/sage/libs/symmetrica/symmetrica.pxi b/src/sage/libs/symmetrica/symmetrica.pxi index e8b85194d0b..045fd8b760e 100644 --- a/src/sage/libs/symmetrica/symmetrica.pxi +++ b/src/sage/libs/symmetrica/symmetrica.pxi @@ -706,11 +706,8 @@ cdef void* _op_skew_partition(object p, OP a): cdef OP gross, klein gross = callocobject() klein = callocobject() - - #print p[0], p[1] _op_partition(p[0], gross) _op_partition(p[1], klein) - b_gk_spa(gross, klein, a) cdef object _py_skew_partition(OP a): diff --git a/src/sage/modular/modform/half_integral.py b/src/sage/modular/modform/half_integral.py index f67e1bf82df..3bef523c33b 100644 --- a/src/sage/modular/modform/half_integral.py +++ b/src/sage/modular/modform/half_integral.py @@ -128,11 +128,7 @@ def half_integral_weight_modform_basis(chi, k, prec): B = C.basis() # This computation of S below -- of course --dominates the whole function. - #from sage.misc.misc import cputime - #tm = cputime() - #print "Computing basis..." - S = [f.q_expansion(prec) for f in B] - #print "Time to compute basis", cputime(tm) + S = [f.q_expansion(prec) for f in B] T2 = theta2_qexp(prec) T3 = theta_qexp(prec) diff --git a/src/sage/modular/modform_hecketriangle/graded_ring_element.py b/src/sage/modular/modform_hecketriangle/graded_ring_element.py index b0af21809f2..4ec4b6e258b 100644 --- a/src/sage/modular/modform_hecketriangle/graded_ring_element.py +++ b/src/sage/modular/modform_hecketriangle/graded_ring_element.py @@ -1547,10 +1547,7 @@ def _q_expansion_cached(self, prec, fix_d, subs_d, d_num_prec, fix_prec = False) sage: J_inv._q_expansion_cached(prec=5, fix_d=True, subs_d=None, d_num_prec=53, fix_prec=False) == J_inv.q_expansion_fixed_d() True """ - if not fix_prec: - #if (prec <1): - # print "Warning: non-positive precision!" if ((not self.is_zero()) and prec <= self.order_at(infinity)): from warnings import warn warn("precision too low to determine any coefficient!") diff --git a/src/sage/modules/fg_pid/fgp_element.py b/src/sage/modules/fg_pid/fgp_element.py index a862cb04530..c2ed4590188 100644 --- a/src/sage/modules/fg_pid/fgp_element.py +++ b/src/sage/modules/fg_pid/fgp_element.py @@ -5,15 +5,15 @@ - William Stein, 2009 """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2009 William Stein # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.structure.element import ModuleElement from sage.structure.richcmp import richcmp @@ -233,7 +233,6 @@ def _rmul_(self, c): sage: x._rmul_(1/4) (1/4, 0) """ - # print "_rmul_" P = self.parent() return P.element_class(P, self._x._rmul_(c)) @@ -279,11 +278,9 @@ def _lmul_(self, s): sage: x._lmul_(1/4) (1/4, 0) """ - # print '_lmul_' P = self.parent() return P.element_class(P, self._x._lmul_(s)) - def _repr_(self): """ diff --git a/src/sage/numerical/linear_functions.pyx b/src/sage/numerical/linear_functions.pyx index 6aa5608c3fd..d35272b6f3f 100644 --- a/src/sage/numerical/linear_functions.pyx +++ b/src/sage/numerical/linear_functions.pyx @@ -1077,7 +1077,7 @@ cdef class LinearFunction(LinearFunctionOrConstraint): return '' try: from sage.rings.integer_ring import ZZ - coeff = ZZ(coeff) # print as integer if possible + coeff = ZZ(coeff) except (TypeError, ValueError): pass if constant_term: diff --git a/src/sage/plot/bar_chart.py b/src/sage/plot/bar_chart.py index e776d41889f..1f0d7d62cf7 100644 --- a/src/sage/plot/bar_chart.py +++ b/src/sage/plot/bar_chart.py @@ -179,11 +179,8 @@ def bar_chart(datalist, **options): sphinx_plot(bar_chart([-2,8,-7,3], rgbcolor=(1,0,0), axes=False)) """ dl = len(datalist) - # if dl > 1: - # print "WARNING, currently only 1 data set allowed" - # datalist = datalist[0] if dl == 3: - datalist = datalist+[0] + datalist = datalist + [0] # bardata = [] # cnt = 1 # for pnts in datalist: diff --git a/src/sage/quadratic_forms/extras.py b/src/sage/quadratic_forms/extras.py index 2baa4e3cfa7..ede37f6d77d 100644 --- a/src/sage/quadratic_forms/extras.py +++ b/src/sage/quadratic_forms/extras.py @@ -127,24 +127,18 @@ def extend_to_primitive(A_input): ## Extend the matrix in new coordinates, then switch back. B = A * V - B_new = matrix(R, n-k, n) - for i in range(n-k): - B_new[i, n-i-1] = 1 + B_new = matrix(R, n - k, n) + for i in range(n - k): + B_new[i, n - i - 1] = 1 C = B.stack(B_new) D = C * V**(-1) - ## DIAGNOSTIC - #print "A = ", A, "\n" - #print "B = ", B, "\n" - #print "C = ", C, "\n" - #print "D = ", D, "\n" - # Normalize for a positive determinant if D.det() < 0: - D.rescale_row(n-1, -1) + D.rescale_row(n - 1, -1) - ## Return the current information - if vec_output_flag: + # Return the current information + if vec_output_flag: return D.rows() else: return D diff --git a/src/sage/quadratic_forms/quadratic_form__local_field_invariants.py b/src/sage/quadratic_forms/quadratic_form__local_field_invariants.py index 03f74d51ed0..a78b99f3068 100644 --- a/src/sage/quadratic_forms/quadratic_form__local_field_invariants.py +++ b/src/sage/quadratic_forms/quadratic_form__local_field_invariants.py @@ -460,10 +460,6 @@ def hasse_invariant(self, p): Diag = self.rational_diagonal_form() R = Diag.base_ring() - ## DIAGNOSTIC - #print "\n Q = " + str(self) - #print "\n Q diagonalized at p = " + str(p) + " gives " + str(Diag) - hasse_temp = 1 n = Diag.dim() @@ -548,10 +544,6 @@ def hasse_invariant__OMeara(self, p): Diag = self.rational_diagonal_form() R = Diag.base_ring() - ## DIAGNOSTIC - #print "\n Q = " + str(self) - #print "\n Q diagonalized at p = " + str(p) + " gives " + str(Diag) - hasse_temp = 1 n = Diag.dim() if R == QQ: 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 df2c4fc5894..4ca4a0d0910 100644 --- a/src/sage/quadratic_forms/quadratic_form__local_representation_conditions.py +++ b/src/sage/quadratic_forms/quadratic_form__local_representation_conditions.py @@ -602,16 +602,13 @@ def is_locally_represented_at_place(self, m, p): else: ## m == 0 return True - ## Check at a finite place + # Check at a finite place sqclass = self.squareclass_vector(p) for s in sqclass: - #print "m =", m, " s =", s, " m/s =", (QQ(m)/s) if (QQ(m)/s).is_padic_square(p): nu = valuation(m//s, p) return local_vec[sqclass.index(s) + 1] <= (nu / 2) - - def is_locally_represented(self, m): """ Determines if the rational number `m` is locally represented by diff --git a/src/sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py b/src/sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py index f91857adb82..e40ba2f9e91 100644 --- a/src/sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py +++ b/src/sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py @@ -617,13 +617,6 @@ def conway_standard_mass(self): else: s = (n+1) // 2 - ## DIAGNOSTIC - #print "n = ", n - #print "s = ", s - #print "Gamma Factor = \n", prod([gamma__exact(j / ZZ(2)) for j in range(1, n+1)]) - #print "Zeta Factor = \n", prod([zeta__exact(2*k) for k in range(1, s)]) - #print "Pi Factor = \n", pi**((-1) * n * (n+1) / ZZ(4)) - generic_mass = 2 * pi**((-1) * n * (n+1) / ZZ(4)) \ * prod([gamma__exact(j / ZZ(2)) for j in range(1, n+1)]) \ * prod([zeta__exact(2*k) for k in range(1, s)]) @@ -682,11 +675,6 @@ def conway_mass(self): return self.__conway_mass -## ======================================================== - - - - #def conway_generic_mass(self): # """ # Computes the generic mass given as 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 2941df73430..9301bd2efcc 100644 --- a/src/sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py +++ b/src/sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py @@ -73,34 +73,18 @@ def mass__by_Siegel_densities(self, odd_algorithm="Pall", even_algorithm="Watson ########################################## generic_prod *= (self.det())**(ZZ(n+1)/2) ## ***** This uses the Hessian Determinant ******** ########################################## - #print "gp1 = ", generic_prod generic_prod *= prod([gamma__exact(ZZ(j)/2) for j in range(1,n+1)]) - #print "\n---", [(ZZ(j)/2, gamma__exact(ZZ(j)/2)) for j in range(1,n+1)] - #print "\n---", prod([gamma__exact(ZZ(j)/2) for j in range(1,n+1)]) - #print "gp2 = ", generic_prod generic_prod *= prod([zeta__exact(ZZ(j)) for j in range(2, 2*s+1, 2)]) - #print "\n---", [zeta__exact(ZZ(j)) for j in range(2, 2*s+1, 2)] - #print "\n---", prod([zeta__exact(ZZ(j)) for j in range(2, 2*s+1, 2)]) - #print "gp3 = ", generic_prod if (n % 2 == 0): generic_prod *= quadratic_L_function__exact(n//2, ZZ(-1)**(n//2) * char_d) - #print " NEW = ", ZZ(1) * quadratic_L_function__exact(n/2, (-1)**(n/2) * char_d) - #print - #print "gp4 = ", generic_prod - - #print "generic_prod =", generic_prod - - ## Determine the adjustment factors + # Determine the adjustment factors adj_prod = ZZ.one() for p in prime_divisors(2 * self.det()): ## Cancel out the generic factors p_adjustment = prod([1 - ZZ(p)**(-j) for j in range(2, 2*s+1, 2)]) if (n % 2 == 0): p_adjustment *= (1 - kronecker((-1)**(n//2) * char_d, p) * ZZ(p)**(-n//2)) - #print " EXTRA = ", ZZ(1) * (1 - kronecker((-1)**(n/2) * char_d, p) * ZZ(p)**(-n/2)) - #print "Factor to cancel the generic one:", p_adjustment - - ## Insert the new mass factors + # Insert the new mass factors if p == 2: if even_algorithm == "Kitaoka": p_adjustment = p_adjustment / self.Kitaoka_mass_at_2() @@ -114,24 +98,18 @@ def mass__by_Siegel_densities(self, odd_algorithm="Pall", even_algorithm="Watson else: raise TypeError("There is a problem -- your optional arguments are invalid. Try again. =(") - #print "p_adjustment for p =", p, "is", p_adjustment - - ## Put them together (cumulatively) + # Put them together (cumulatively) adj_prod *= p_adjustment - #print "Cumulative adj_prod =", adj_prod - - ## Extra adjustment for the case of a 2-dimensional form. + # Extra adjustment for the case of a 2-dimensional form. #if (n == 2): # generic_prod *= 2 - ## Return the mass mass = generic_prod * adj_prod return mass - def Pall_mass_density_at_odd_prime(self, p): """ Returns the local representation density of a form (for @@ -168,19 +146,14 @@ def Pall_mass_density_at_odd_prime(self, p): ## compute the invariants for each Jordan block. jordan_list = self.jordan_blocks_by_scale_and_unimodular(p) modified_jordan_list = [(a, Q.dim(), Q.det()) for (a,Q) in jordan_list] ## List of pairs (scale, det) - #print jordan_list - #print modified_jordan_list - ## Step 2: Compute the list of local masses for each Jordan block jordan_mass_list = [] for (s,n,d) in modified_jordan_list: generic_factor = prod([1 - p**(-2*j) for j in range(1, (n-1)//2+1)]) - #print "generic factor: ", generic_factor if (n % 2 == 0): m = n/2 generic_factor *= (1 + legendre_symbol(((-1)**m) * d, p) * p**(-m)) - #print "jordan_mass: ", generic_factor jordan_mass_list = jordan_mass_list + [generic_factor] @@ -188,7 +161,6 @@ def Pall_mass_density_at_odd_prime(self, p): MJL = modified_jordan_list s = len(modified_jordan_list) M = [sum([MJL[j][1] for j in range(i, s)]) for i in range(s-1)] ## Note: It's s-1 since we don't need the last M. - #print "M = ", M nu = sum([M[i] * MJL[i][0] * MJL[i][1] for i in range(s-1)]) - ZZ(sum([J[0] * J[1] * (J[1]-1) for J in MJL]))/ZZ(2) p_mass = prod(jordan_mass_list) p_mass *= 2**(s-1) * p**nu @@ -243,10 +215,6 @@ def Watson_mass_at_2(self): else: diag_dict[s] = L - #print "diag_dict = ", diag_dict - #print "dim2_dict = ", dim2_dict - #print "Jordan_Blocks = ", Jordan_Blocks - ## 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)) @@ -256,15 +224,10 @@ def Watson_mass_at_2(self): m_dict[s+1] = ZZ.one()/ZZ(2) * L.dim() else: m_dict[s+1] = floor(ZZ(L.dim() - 1) / ZZ(2)) - #print " ==>", ZZ(L.dim() - 1) / ZZ(2), floor(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[s_max+1] = 0 - #print "n_dict = ", n_dict - #print "m_dict = ", m_dict - #print "nu_dict = ", nu_dict - ## Step 3: Compute the e_j dictionary eps_dict = {} for j in range(s_min, s_max+3): @@ -284,9 +247,6 @@ def Watson_mass_at_2(self): else: eps_dict[j] = -1 - #print "eps_dict = ", eps_dict - - ## Step 4: Compute the quantities nu, q, P, E for the local mass at 2 nu = sum([j * n_dict[j] * (ZZ(n_dict[j] + 1) / ZZ(2) + \ sum([n_dict[r] for r in range(j+1, s_max+2)])) for j in range(s_min+1, s_max+2)]) @@ -343,11 +303,6 @@ def Kitaoka_mass_at_2(self): else: diag_dict[s] = L - #print "diag_dict = ", diag_dict - #print "dim2_dict = ", dim2_dict - #print "Jordan_Blocks = ", Jordan_Blocks - - ################## START EDITING HERE ################## ## Compute q := sum of the q_j @@ -381,14 +336,7 @@ def Kitaoka_mass_at_2(self): else: E *= 2 - ## DIAGNOSTIC - #print "\nFinal Summary:" - #print "nu =", nu - #print "q = ", q - #print "P = ", P - #print "E = ", E - - ## Compute the exponent w + # Compute the exponent w w = QQ.zero() for j in range(s_min, s_max+1): n_j = Jordan_Blocks[j][1].dim() @@ -396,7 +344,6 @@ def Kitaoka_mass_at_2(self): n_k = Jordan_Blocks[k][1].dim() w += j * n_j * (n_k + QQ(n_j + 1) / 2) - ## Step 5: Compute the local mass for the prime 2. mass_at_2 = (QQ(2)**(w - q)) * P * E return mass_at_2 diff --git a/src/sage/quadratic_forms/quadratic_form__theta.py b/src/sage/quadratic_forms/quadratic_form__theta.py index ba9bcebcd53..36594ff09d5 100644 --- a/src/sage/quadratic_forms/quadratic_form__theta.py +++ b/src/sage/quadratic_forms/quadratic_form__theta.py @@ -237,61 +237,25 @@ def theta_by_cholesky(self, q_prec): ## 3a. Main loop - - ## DIAGNOSTIC - #print - #print " L = ", L - #print " x = ", x - x[i] += 1 while (x[i] > L[i]): - - ## DIAGNOSTIC - #print " x = ", x - i += 1 x[i] += 1 - ## 3b. Main loop if (i > 0): from_step3_flag = True - - ## DIAGNOSTIC - #print " i = " + str(i) - #print " T[i] = " + str(T[i]) - #print " Q[i,i] = " + str(Q[i,i]) - #print " x[i] = " + str(x[i]) - #print " U[i] = " + str(U[i]) - #print " x[i] + U[i] = " + str(x[i] + U[i]) - #print " T[i-1] = " + str(T[i-1]) - T[i-1] = T[i] - Q[i,i] * (x[i] + U[i]) * (x[i] + U[i]) - - # DIAGNOSTIC - #print " T[i-1] = " + str(T[i-1]) - #print - i += - 1 U[i] = 0 for j in range(i+1, n): U[i] += Q[i,j] * x[j] - - ## 4. Solution found (This happens when i=0) from_step4_flag = True Q_val_double = q_prec - T[0] + Q[0,0] * (x[0] + U[0]) * (x[0] + U[0]) Q_val = floor(Q_val_double + half) ## Note: This rounds the value up, since the "round" function returns a float, but floor returns integer. - - - ## DIAGNOSTIC - #print " Q_val_double = ", Q_val_double - #print " Q_val = ", Q_val - #raise RuntimeError - - ## OPTIONAL SAFETY CHECK: eps = 0.000000001 if (abs(Q_val_double - Q_val) > eps): @@ -300,12 +264,6 @@ def theta_by_cholesky(self, q_prec): + " Q_val = " + str(Q_val) + "\n" \ + " x = " + str(x) + "\n") - - ## DIAGNOSTIC - #print " The float value is " + str(Q_val_double) - #print " The associated long value is " + str(Q_val) - #print - if (Q_val <= q_prec): theta[Q_val] += 2 @@ -315,15 +273,10 @@ def theta_by_cholesky(self, q_prec): if (x[j] != 0): done_flag = False - - ## Set the value: theta[0] = 1 + # Set the value: theta[0] = 1 theta[0] = 1 - ## DIAGNOSTIC - #print "Leaving ComputeTheta \n" - - - ## Return the series, truncated to the desired q-precision + # Return the series, truncated to the desired q-precision return PS(theta) diff --git a/src/sage/rings/padics/padic_extension_leaves.py b/src/sage/rings/padics/padic_extension_leaves.py index 5e6c9df80f1..48359ef12ab 100644 --- a/src/sage/rings/padics/padic_extension_leaves.py +++ b/src/sage/rings/padics/padic_extension_leaves.py @@ -686,8 +686,8 @@ def __init__(self, exact_modulus, poly, prec, print_mode, shift_seed, names, imp """ unram_prec = (prec + poly.degree() - 1) // poly.degree() ntl_poly = ntl_ZZ_pX([a.lift() for a in poly.list()], poly.base_ring().prime()**unram_prec) - shift_poly = ntl_ZZ_pX([a.lift() for a in shift_seed.list()], shift_seed.base_ring().prime()**unram_prec) - #print poly.base_ring().prime(), prec, poly.degree(), ntl_poly + shift_poly = ntl_ZZ_pX([a.lift() for a in shift_seed.list()], + shift_seed.base_ring().prime()**unram_prec) # deal with prec not a multiple of e better. self.prime_pow = PowComputer_ext_maker(poly.base_ring().prime(), max(min(unram_prec - 1, 30), 1), unram_prec, prec, False, ntl_poly, "FM", "e", shift_poly) self._shift_seed = shift_seed diff --git a/src/sage/rings/padics/pow_computer_ext.pyx b/src/sage/rings/padics/pow_computer_ext.pyx index 0b370efbe93..7dc2887337d 100644 --- a/src/sage/rings/padics/pow_computer_ext.pyx +++ b/src/sage/rings/padics/pow_computer_ext.pyx @@ -206,18 +206,15 @@ cdef int ZZ_pX_Eis_init(PowComputer_ZZ_pX prime_pow, ntl_ZZ_pX shift_seed) excep #ZZ_negate(a, a) ##cdef ntl_ZZ_pX printer = ntl_ZZ_pX([],prime_pow.get_context(prime_pow.prec_cap)) ##printer.x = modup - ##print printer # Note that we're losing one digit of precision here. # This is correct because right shifting does not preserve precision. # a is now the negative of the inverse of the unit part of the constant of the defining polynomial (there's a mouthful) #ZZ_pX_RightShift(tmp, modup, 1) ##printer.x = modup - ##print printer #ZZ_pX_mul_ZZ_p(tmp, tmp, ZZ_to_ZZ_p(a)) # tmp is now p/x #ZZ_pX_conv_modulus(into_multiplier, tmp, prime_pow.get_top_context().x) ##printer.x = into_multiplier - ##print printer #if multiplier: # ZZ_pX_Multiplier_construct(low_shifter_m) # ZZ_pX_Multiplier_build(low_shifter_m[0], into_multiplier, prime_pow.get_top_modulus()[0]) @@ -225,7 +222,6 @@ cdef int ZZ_pX_Eis_init(PowComputer_ZZ_pX prime_pow, ntl_ZZ_pX shift_seed) excep # ZZ_pX_construct(low_shifter_p) # low_shifter_p[0] = into_multiplier ##printer.x = (low_shifter[0]).val() - ##print printer ZZ_pX_InvMod_newton_ram(shift_seed_inv, shift_seed.x, prime_pow.get_top_modulus()[0], prime_pow.get_top_context().x) for i in range(low_length): # Currently tmp = p / x^(2^(i-1)). Squaring yields p^2 / x^(2^i) @@ -236,7 +232,6 @@ cdef int ZZ_pX_Eis_init(PowComputer_ZZ_pX prime_pow, ntl_ZZ_pX shift_seed) excep ZZ_pX_PowerXMod_long_pre(into_multiplier, prime_pow.e - (1L << i), prime_pow.get_top_modulus()[0]) ZZ_pX_MulMod_pre(into_multiplier, into_multiplier, shift_seed_inv, prime_pow.get_top_modulus()[0]) ##printer.x = into_multiplier - ##print printer if multiplier: ZZ_pX_Multiplier_build(low_shifter_m[i], into_multiplier, prime_pow.get_top_modulus()[0]) else: @@ -253,21 +248,15 @@ cdef int ZZ_pX_Eis_init(PowComputer_ZZ_pX prime_pow, ntl_ZZ_pX shift_seed) excep ###ZZ_pX_right_pshift(into_multiplier, modup, prime_pow.small_powers[1], prime_pow.get_top_context().x) ###printer.x = into_multiplier - ###print printer # into_multiplier now holds x^e/p # prime_pow.c.x should have been restored, but we make sure prime_pow.restore_top_context() - ##print "shift_seed=%s"%shift_seed ##printer.x = prime_pow.get_top_modulus()[0].val() - ##print "top_modulus=%s"%printer - ##print "top_context=%s"%prime_pow.get_top_context() into_multiplier = shift_seed_inv #ZZ_pX_InvMod_newton_ram(into_multiplier, shift_seed.x, prime_pow.get_top_modulus()[0], prime_pow.get_top_context().x) ##printer.x = into_multiplier - ##print "inverse = %s"%printer ##ZZ_pX_MulMod_pre(printer.x, into_multiplier, shift_seed.x, prime_pow.get_top_modulus()[0]) - ##print "product = %s"%printer if multiplier: ZZ_pX_Multiplier_build(high_shifter_m[0], into_multiplier, prime_pow.get_top_modulus()[0]) else: @@ -331,7 +320,6 @@ cdef int ZZ_pX_eis_shift_p(PowComputer_ZZ_pX self, ZZ_pX_c* x, ZZ_pX_c* a, long sage: f_dtr = yr*dtr; f_dtr O(a^456)*t^2 + O(a^306)*t^3 + O(a^156)*t^4 + (a^6 + 6*a^36 + 2*a^66 + 7*a^96 + 4*a^126 + O(a^156))*t^5 + O(a^158)*t^6 + (a^8 + 2*a^38 + 8*a^68 + 3*a^98 + O(a^158))*t^7 + O(a^160)*t^8 + (8*a^40 + 10*a^100 + 5*a^130 + O(a^160))*t^9 + O(a^162)*t^10 + (2*a^12 + 5*a^42 + 3*a^72 + 7*a^102 + O(a^162))*t^11 + O(a^164)*t^12 + (8*a^14 + a^44 + 6*a^74 + 4*a^104 + 7*a^134 + O(a^164))*t^13 + O(a^166)*t^14 + (2*a^16 + 8*a^46 + 5*a^106 + 4*a^136 + O(a^166))*t^15 + O(a^168)*t^16 + (a^18 + 6*a^48 + 5*a^78 + 2*a^108 + 9*a^138 + O(a^168))*t^17 + O(a^170)*t^18 + (8*a^50 + 2*a^110 + O(a^170))*t^19 + O(a^172)*t^20 + (4*a^52 + 2*a^82 + 7*a^112 + 5*a^142 + O(a^172))*t^21 + O(a^174)*t^22 + (2*a^54 + 3*a^84 + 8*a^114 + 6*a^144 + O(a^174))*t^23 + O(a^176)*t^24 + (a^26 + 6*a^56 + 4*a^86 + 9*a^116 + 3*a^146 + O(a^176))*t^25 + O(a^178)*t^26 + (10*a^28 + 5*a^58 + 4*a^88 + 10*a^118 + 6*a^148 + O(a^178))*t^27 + O(a^180)*t^28 + (5*a^30 + 5*a^60 + 4*a^90 + 9*a^120 + 3*a^150 + O(a^180))*t^29 + O(a^182)*t^30 + (4*a^32 + 10*a^62 + 5*a^92 + 7*a^122 + 3*a^152 + O(a^182))*t^31 + O(a^184)*t^32 + (5*a^34 + 9*a^94 + 3*a^124 + 6*a^154 + O(a^184))*t^33 + O(a^186)*t^34 + (4*a^36 + 3*a^66 + 10*a^96 + 2*a^126 + 6*a^156 + O(a^186))*t^35 + O(a^188)*t^36 + (6*a^38 + 9*a^68 + 7*a^128 + 10*a^158 + O(a^188))*t^37 + O(a^190)*t^38 + (7*a^40 + 3*a^70 + 4*a^100 + 4*a^130 + 8*a^160 + O(a^190))*t^39 + O(a^192)*t^40 + (a^42 + 10*a^72 + 10*a^102 + a^132 + 7*a^162 + O(a^192))*t^41 + O(a^194)*t^42 + (8*a^74 + 8*a^104 + 9*a^134 + 7*a^164 + O(a^194))*t^43 + O(a^196)*t^44 + (10*a^136 + 2*a^166 + O(a^196))*t^45 + O(a^198)*t^46 + (7*a^48 + 10*a^78 + 5*a^108 + 8*a^138 + 3*a^168 + O(a^198))*t^47 + O(a^200)*t^48 + (6*a^50 + 5*a^80 + a^110 + 6*a^170 + O(a^200))*t^49 + O(a^202)*t^50 + (a^52 + 8*a^82 + 2*a^112 + 10*a^172 + O(a^202))*t^51 + O(a^204)*t^52 + (9*a^54 + 2*a^84 + 6*a^114 + 4*a^144 + O(a^204))*t^53 + O(a^206)*t^54 + (2*a^56 + 5*a^86 + 2*a^116 + 4*a^146 + a^176 + O(a^206))*t^55 + O(a^208)*t^56 + (3*a^58 + 3*a^88 + a^118 + 5*a^148 + 2*a^178 + O(a^208))*t^57 + O(a^210)*t^58 + (5*a^60 + 10*a^90 + 9*a^120 + a^150 + 6*a^180 + O(a^210))*t^59 + O(a^212)*t^60 + (4*a^62 + 9*a^92 + 7*a^122 + 7*a^152 + 9*a^182 + O(a^212))*t^61 + O(a^214)*t^62 + (10*a^64 + 8*a^94 + 6*a^124 + 8*a^154 + 4*a^184 + O(a^214))*t^63 + O(a^216)*t^64 + (4*a^126 + 10*a^156 + 9*a^186 + O(a^216))*t^65 + O(a^218)*t^66 + (7*a^98 + 4*a^128 + 6*a^158 + 6*a^188 + O(a^218))*t^67 + O(a^220)*t^68 + (3*a^70 + 6*a^100 + 8*a^130 + 9*a^160 + 10*a^190 + O(a^220))*t^69 + O(a^222)*t^70 + (9*a^72 + 5*a^102 + 9*a^132 + 3*a^162 + 10*a^192 + O(a^222))*t^71 + O(a^224)*t^72 + (3*a^74 + 8*a^104 + 7*a^134 + 2*a^164 + O(a^224))*t^73 + O(a^226)*t^74 + (10*a^76 + a^106 + 2*a^136 + 4*a^166 + 9*a^196 + O(a^226))*t^75 + O(a^228)*t^76 + (3*a^78 + 6*a^108 + 9*a^138 + 4*a^168 + 5*a^198 + O(a^228))*t^77 + O(a^230)*t^78 + (4*a^80 + 10*a^110 + 7*a^170 + 8*a^200 + O(a^230))*t^79 + O(a^232)*t^80 + (5*a^82 + 4*a^112 + 9*a^142 + 8*a^172 + 8*a^202 + O(a^232))*t^81 + O(a^234)*t^82 + (4*a^84 + 9*a^114 + 8*a^144 + 2*a^174 + 6*a^204 + O(a^234))*t^83 + O(a^236)*t^84 + (3*a^86 + 5*a^116 + 4*a^146 + 8*a^206 + O(a^236))*t^85 + O(a^238)*t^86 + (a^118 + 7*a^148 + 6*a^208 + O(a^238))*t^87 + O(a^240)*t^88 + (4*a^90 + 9*a^120 + 9*a^150 + 6*a^180 + 6*a^210 + O(a^240))*t^89 + O(a^244)*t^90 + (10*a^122 + 3*a^152 + 8*a^182 + 4*a^212 + 2*a^242 + O(a^244))*t^91 + O(a^276)*t^92 + (9*a^154 + 10*a^184 + 10*a^214 + 7*a^244 + 9*a^274 + O(a^276))*t^93 + O(a^308)*t^94 + (9*a^186 + 4*a^216 + 5*a^246 + a^276 + 10*a^306 + O(a^308))*t^95 """ - ##print "starting..." cdef ZZ_pX_c low_part cdef ZZ_pX_c shifted_high_part cdef ZZ_pX_c powerx @@ -381,11 +369,9 @@ cdef int ZZ_pX_eis_shift_p(PowComputer_ZZ_pX self, ZZ_pX_c* x, ZZ_pX_c* a, long ##printer = ntl_ZZ_pX([],c) ZZ_pX_PowerXMod_long_pre(powerx, -n, m[0]) ##printer.x = powerx - ##print printer ZZ_pX_conv_modulus(x[0], a[0], c.x) ZZ_pX_MulMod_pre(x[0], powerx, a[0], m[0]) ##printer.x = x[0] - ##print printer return 0 elif n == 0: if x != a: @@ -396,9 +382,6 @@ cdef int ZZ_pX_eis_shift_p(PowComputer_ZZ_pX self, ZZ_pX_c* x, ZZ_pX_c* a, long ZZ_pX_conv_modulus(x[0], a[0], c.x) return 0 - ##print "eis_part: %s" %(eis_part) - ##print "pshift: %s"%(pshift) - # The following doesn't work, sadly. It should be possible to precompute and do better than what I replace this code with. # c = self.get_context(finalprec) # m = self.get_modulus(finalprec)[0] @@ -408,34 +391,27 @@ cdef int ZZ_pX_eis_shift_p(PowComputer_ZZ_pX self, ZZ_pX_c* x, ZZ_pX_c* a, long # else: # ZZ_pX_conv_modulus(x[0], a[0], c.x) # ##printer.x = a[0] -# ##print "beginning: a = %s"%(printer) # c.restore_c() # if pshift: # i = 0 # # This line restores the top context # #ZZ_pX_right_pshift(x[0], x[0], self.pow_ZZ_tmp(pshift)[0], c.x) # ##printer.x = x[0] -# ##print printer # if pshift >= self.prec_cap: # # shifter = p^(2^(high_length - 1))/x^(e*2^(high_length - 1)) # ZZ_pX_conv_modulus(shifter, high_shifter[high_length-1], c.x) # ##printer.x = shifter -# ##print printer # # if val = r + s * 2^(high_length - 1) # # then shifter = p^(s*2^(high_length - 1))/x^(e*s*2^(high_length - 1)) # ZZ_pX_PowerMod_long_pre(shifter, shifter, (pshift / (1L << (high_length - 1))), m) # ##printer.x = shifter -# ##print printer # ZZ_pX_MulMod_pre(x[0], x[0], shifter, m) # ##printer.x = shifter -# ##print printer # # Now we only need to multiply self.unit by p^r/x^(e*r) where r < 2^(high_length - 1), which is tractible. # pshift = pshift % (1L << (high_length - 1)) # while pshift > 0: # if pshift & 1: -# ##print "pshift = %s"%pshift # ##printer.x = x[0] -# ##print printer # ZZ_pX_conv_modulus(highshift, high_shifter[i], c.x) # ZZ_pX_MulMod_pre(x[0], x[0], highshift, m) # i += 1 @@ -465,32 +441,23 @@ cdef int ZZ_pX_eis_shift_p(PowComputer_ZZ_pX self, ZZ_pX_c* x, ZZ_pX_c* a, long i = 0 two_shift = 1 while eis_part > 0: - ##print "eis_part = %s"%(eis_part) if eis_part & 1: - ##print "i = %s"%(i) - ##print "two_shift = %s"%(two_shift) ##printer.x = working2 - ##print "working2 = %s"%(printer) ZZ_pX_RightShift(shifted_high_part, working2, two_shift) ##printer.x = shifted_high_part - ##print "shifted_high_part = %s"%(printer) ZZ_pX_LeftShift(low_part, shifted_high_part, two_shift) ZZ_pX_sub(low_part, working2, low_part) ##printer.x = low_part - ##print "low_part = %s"%(printer) ZZ_pX_right_pshift(low_part, low_part, self.pow_ZZ_tmp(1)[0], c.x) ##printer.x = low_part - ##print "low_part = %s"%(printer) if fm: ZZ_pX_MulMod_premul(low_part, low_part, low_shifter_fm[i], m[0]) else: ZZ_pX_conv_modulus(lowshift, low_shifter[i], c.x) ZZ_pX_MulMod_pre(low_part, low_part, lowshift, m[0]) ##printer.x = low_part - ##print "low_part = %s"%(printer) ZZ_pX_add(working2, low_part, shifted_high_part) ##printer.x = working2 - ##print "x = %s"%(printer) i += 1 two_shift = two_shift << 1 eis_part = eis_part >> 1 @@ -1016,12 +983,8 @@ cdef class PowComputer_ZZ_pX(PowComputer_ext): 4 """ if self.pow_Integer(mpz_get_si(n.value)) != Integer(a.c.p): - #print self.pow_Integer(mpz_get_si(n.value)) - #print a.c.p raise ValueError("a context mismatch") if self.pow_Integer(mpz_get_si(n.value)) != Integer(b.c.p): - #print self.pow_Integer(mpz_get_si(n.value)) - #print b.c.p raise ValueError("b context mismatch") cdef ntl_ZZ_pX r = (a)._new() cdef ntl_ZZ_pX aa = (a)._new() @@ -1504,7 +1467,6 @@ cdef class PowComputer_ZZ_pX_FM_Eis(PowComputer_ZZ_pX_FM): """ return ZZ_pX_eis_shift_p(self, x, a, n, finalprec) -# ##print "starting..." # cdef ZZ_pX_c low_part # cdef ZZ_pX_c shifted_high_part # cdef ZZ_pX_c high_shifter @@ -1515,10 +1477,8 @@ cdef class PowComputer_ZZ_pX_FM_Eis(PowComputer_ZZ_pX_FM): # ##printer = ntl_ZZ_pX([],self.get_top_context()) # ZZ_pX_PowerXMod_long_pre(high_shifter, -n, self.get_top_modulus()[0]) # ##printer.x = high_shifter -# ##print printer # ZZ_pX_MulMod_pre(x[0],high_shifter,a[0],self.get_top_modulus()[0]) # ##printer.x = x[0] -# ##print printer # return 0 # elif n == 0: # if x != a: @@ -1530,36 +1490,27 @@ cdef class PowComputer_ZZ_pX_FM_Eis(PowComputer_ZZ_pX_FM): # cdef int i # ##printer = ntl_ZZ_pX([],self.get_top_context()) -# ##print "eis_part: %s" %(eis_part) -# ##print "pshift: %s"%(pshift) # if x != a: -# ##print "copying" # x[0] = a[0] # ##printer.x = a[0] -# ##print "beginning: a = %s"%(printer) # if pshift: # i = 0 # # This line restores the top context # ZZ_pX_right_pshift(x[0], x[0], self.pow_ZZ_tmp(pshift)[0], self.get_top_context().x) # ##printer.x = x[0] -# ##print printer # if pshift >= self.prec_cap: # # high_shifter = p^(2^(high_length - 1))/x^(e*2^(high_length - 1)) # # if val = r + s * 2^(high_length - 1) # # then high_shifter = p^(s*2^(high_length - 1))/x^(e*s*2^(high_length - 1)) # ZZ_pX_PowerMod_long_pre(high_shifter, self.high_shifter[self.high_length-1].val(), (pshift / (1L << (self.high_length - 1))), self.get_top_modulus()[0]) # ##printer.x = high_shifter -# ##print printer # ZZ_pX_MulMod_pre(x[0], x[0], high_shifter, self.get_top_modulus()[0]) # ##printer.x = high_shifter -# ##print printer # # Now we only need to multiply self.unit by p^r/x^(e*r) where r < 2^(high_length - 1), which is tractible. # pshift = pshift % (1L << (self.high_length - 1)) # while pshift > 0: # if pshift & 1: -# ##print "pshift = %s"%pshift # ##printer.x = x[0] -# ##print printer # ZZ_pX_MulMod_premul(x[0], x[0], self.high_shifter[i], self.get_top_modulus()[0]) # i += 1 # pshift = pshift >> 1 @@ -1568,26 +1519,18 @@ cdef class PowComputer_ZZ_pX_FM_Eis(PowComputer_ZZ_pX_FM): # i = 0 # two_shift = 1 # while eis_part > 0: -# ##print "eis_part = %s"%(eis_part) # if eis_part & 1: -# ##print "i = %s"%(i) -# ##print "two_shift = %s"%(two_shift) # ZZ_pX_RightShift(shifted_high_part, x[0], two_shift) # ##printer.x = shifted_high_part -# ##print "shifted_high_part = %s"%(printer) # ZZ_pX_LeftShift(low_part, shifted_high_part, two_shift) # ZZ_pX_sub(low_part, x[0], low_part) # ##printer.x = low_part -# ##print "low_part = %s"%(printer) # ZZ_pX_right_pshift(low_part, low_part, self.pow_ZZ_tmp(1)[0], self.get_top_context().x) # ##printer.x = low_part -# ##print "low_part = %s"%(printer) # ZZ_pX_MulMod_premul(low_part, low_part, self.low_shifter[i], self.get_top_modulus()[0]) # ##printer.x = low_part -# ##print "low_part = %s"%(printer) # ZZ_pX_add(x[0], low_part, shifted_high_part) # ##printer.x = x[0] -# ##print "x = %s"%(printer) # i += 1 # two_shift = two_shift << 1 # eis_part = eis_part >> 1 diff --git a/src/sage/rings/polynomial/refine_root.pyx b/src/sage/rings/polynomial/refine_root.pyx index aafbeb442f3..082bf810881 100644 --- a/src/sage/rings/polynomial/refine_root.pyx +++ b/src/sage/rings/polynomial/refine_root.pyx @@ -109,11 +109,10 @@ def refine_root(ip, ipd, irt, fld): val = ip(center) nirt = center - val / slope - # print irt, nirt, (nirt in irt), nirt.diameter(), irt.diameter(), center, val, slope if nirt in irt and (nirt.diameter() >= irt.diameter() >> 3 or i >= 8): # If the new diameter is much less than the original diameter, # then we have not yet converged. (Perhaps we were asked - # for a particularly high-precision result.) So we don't + # for a particularly high-precision result.) So we do not # return yet. return nirt diff --git a/src/sage/rings/tate_algebra_ideal.pyx b/src/sage/rings/tate_algebra_ideal.pyx index 12e12ce4791..e9d8fc522ce 100644 --- a/src/sage/rings/tate_algebra_ideal.pyx +++ b/src/sage/rings/tate_algebra_ideal.pyx @@ -952,7 +952,6 @@ def groebner_basis_pote(I, prec, verbose=0): if not v or v.valuation() >= prec: # We have a new element in (I0:f) whose signature # could be useful to strengthen the syzygy criterium - #print ("| add signature for syzygy criterium: %s" % s) gb0.append(s) else: # We update the current strong Grobner basis diff --git a/src/sage/schemes/elliptic_curves/BSD.py b/src/sage/schemes/elliptic_curves/BSD.py index 16734687c15..a9a42ebd84b 100644 --- a/src/sage/schemes/elliptic_curves/BSD.py +++ b/src/sage/schemes/elliptic_curves/BSD.py @@ -907,7 +907,7 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5, BSD.primes.remove(p) break - # print some extra information + # some extra information if verbosity > 1: if BSD.primes: print('Remaining primes:') diff --git a/src/sage/schemes/elliptic_curves/height.py b/src/sage/schemes/elliptic_curves/height.py index 0770e3284bc..21403a196de 100644 --- a/src/sage/schemes/elliptic_curves/height.py +++ b/src/sage/schemes/elliptic_curves/height.py @@ -1574,12 +1574,8 @@ def wp(z): pole_approx = abs(z) ** -2 else: pole_approx = z ** -2 - # print "pole approx", pole_approx + eps(err, abs_only) - # print approx in approx.intersection(pole_approx + eps(err, abs_only)) approx = approx.intersection(pole_approx + eps(err, abs_only)) - return approx - return wp @cached_method diff --git a/src/sage/tests/benchmark.py b/src/sage/tests/benchmark.py index 3649a81f4f8..3612f941168 100644 --- a/src/sage/tests/benchmark.py +++ b/src/sage/tests/benchmark.py @@ -1,7 +1,6 @@ """ Benchmarks - COMMENTS: Taken as a whole these benchmarks suggest that by far the fastest math @@ -85,7 +84,6 @@ def run(self, systems=None, timeout=60, trials=1, sort=False, optional=False): if sort: systems.sort() print('\n\n\n' + str(self)) - #print "Timeout: %s seconds"%timeout print(' %-12s%-12s%-12s%-12s%-12s%15s' % ('System', 'min', 'avg', 'max', 'trials', 'cpu or wall')) @@ -142,6 +140,7 @@ def __repr__(self): except AttributeError: return 'sage.tests.benchmark.Benchmark instance' + class Divpoly(Benchmark): def __init__(self, n): """ @@ -582,7 +581,6 @@ def __init__(self, nvars=2, base=QQ, allow_singular=True): ## z1 = gp(str(z1)) ## gp.eval('gettime') ## f = z0*z1 -## print f ## return float(gp.eval('gettime/1000.0')) def maxima(self): From 017c3a28645dc708f4187fa5debf56e012f416d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 11 Jun 2022 11:36:27 +0200 Subject: [PATCH 076/116] some pep fixes in pxi files --- .../libs/linkages/padics/Polynomial_ram.pxi | 3 +- .../libs/linkages/padics/fmpz_poly_unram.pxi | 30 ++++++--- src/sage/libs/linkages/padics/mpz.pxi | 3 +- src/sage/libs/ntl/ntl_GF2X_linkage.pxi | 13 ++-- src/sage/libs/symmetrica/sb.pxi | 63 +++++++++++++------ src/sage/libs/symmetrica/symmetrica.pxi | 3 +- .../matrix/matrix_modn_dense_template.pxi | 52 +++++++++------ src/sage/rings/padics/CA_template.pxi | 9 ++- src/sage/rings/padics/CR_template.pxi | 13 ++-- src/sage/rings/padics/FM_template.pxi | 6 +- src/sage/rings/padics/FP_template.pxi | 10 ++- 11 files changed, 138 insertions(+), 67 deletions(-) diff --git a/src/sage/libs/linkages/padics/Polynomial_ram.pxi b/src/sage/libs/linkages/padics/Polynomial_ram.pxi index 3742ffd567d..1ac51f1211f 100644 --- a/src/sage/libs/linkages/padics/Polynomial_ram.pxi +++ b/src/sage/libs/linkages/padics/Polynomial_ram.pxi @@ -319,7 +319,8 @@ _expansion_zero = [] # the expansion_mode enum is defined in padic_template_element_header.pxi cdef inline cexpansion_next(celement value, expansion_mode mode, long curpower, PowComputer_ prime_pow): - if mode == teichmuller_mode: raise NotImplementedError + if mode == teichmuller_mode: + raise NotImplementedError # This is not very efficient, but there's no clear better way. # We assume this is only called on two-step extensions (for more general # extensions, convert to the absolute field). diff --git a/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi b/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi index b797782c657..60fb9439388 100644 --- a/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi +++ b/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi @@ -87,20 +87,25 @@ cdef inline int ccmp(celement a, celement b, long prec, bint reduce_a, bint redu if prec == 0: return 0 - if ciszero(prime_pow.poly_ccmp, prime_pow): return 0 + if ciszero(prime_pow.poly_ccmp, prime_pow): + return 0 cdef long da = fmpz_poly_degree(a) cdef long db = fmpz_poly_degree(b) - if da < db: return -1 - elif da > db: return 1 + if da < db: + return -1 + elif da > db: + return 1 cdef long cmp cdef long i for i in range(da+1): fmpz_poly_get_coeff_fmpz(prime_pow.fmpz_ccmp, prime_pow.poly_ccmp, i) cmp = fmpz_cmp_si(prime_pow.fmpz_ccmp, 0) - if cmp < 0: return -1 - elif cmp > 0: return 1 + if cmp < 0: + return -1 + elif cmp > 0: + return 1 assert False cdef inline int cneg(celement out, celement a, long prec, PowComputer_ prime_pow) except -1: @@ -238,7 +243,8 @@ cdef inline long cvaluation(celement a, long prec, PowComputer_ prime_pow) excep if fmpz_is_zero(prime_pow.fmpz_cval): continue val = fmpz_remove(prime_pow.fmpz_cval, prime_pow.fmpz_cval, prime_pow.fprime) - if val < ret: ret = val + if val < ret: + ret = val return ret cdef inline bint cisunit(celement a, PowComputer_ prime_pow) except -1: @@ -354,10 +360,12 @@ cdef inline int cinvert(celement out, celement a, long prec, PowComputer_ prime_ fmpz_poly_scalar_divexact_fmpz(out, a, prime_pow.fmpz_cinv) fmpz_poly_xgcd(prime_pow.fmpz_cinv2, out, prime_pow.poly_cinv2, out, prime_pow.poly_cinv) - if fmpz_is_zero(prime_pow.fmpz_cinv2): raise ValueError("polynomials are not coprime") + if fmpz_is_zero(prime_pow.fmpz_cinv2): + raise ValueError("polynomials are not coprime") fmpz_mul(prime_pow.fmpz_cinv2, prime_pow.fmpz_cinv, prime_pow.fmpz_cinv2) - if not fmpz_invmod(prime_pow.fmpz_cinv2, prime_pow.fmpz_cinv2, prime_pow.pow_fmpz_t_tmp(prec)[0]): raise ValueError("content or xgcd is not a unit") + if not fmpz_invmod(prime_pow.fmpz_cinv2, prime_pow.fmpz_cinv2, prime_pow.pow_fmpz_t_tmp(prec)[0]): + raise ValueError("content or xgcd is not a unit") fmpz_poly_scalar_mul_fmpz(out, out, prime_pow.fmpz_cinv2) creduce(out, out, prec, prime_pow) @@ -581,7 +589,8 @@ cdef inline cexpansion_next(fmpz_poly_t value, expansion_mode mode, long curpowe is being found. Only used in ``smallest_mode``. - ``prime_pow`` -- A ``PowComputer`` holding `p`-adic data. """ - if mode == teichmuller_mode: raise NotImplementedError + if mode == teichmuller_mode: + raise NotImplementedError ans = [] cdef fmpz* c cdef long i @@ -728,7 +737,8 @@ cdef int cconv(celement out, x, long prec, long valshift, PowComputer_ prime_pow for i in range(len(x)): cconv(prime_pow.poly_cconv, x[i], prec, valshift, prime_pow) degree = fmpz_poly_degree(prime_pow.poly_cconv) - if degree == -1: continue + if degree == -1: + continue elif degree == 0: fmpz_poly_get_coeff_fmpz(prime_pow.fmpz_cconv, prime_pow.poly_cconv, 0) fmpz_poly_set_coeff_fmpz(out, i, prime_pow.fmpz_cconv) diff --git a/src/sage/libs/linkages/padics/mpz.pxi b/src/sage/libs/linkages/padics/mpz.pxi index a766ce99bb1..a7200b0c4fa 100644 --- a/src/sage/libs/linkages/padics/mpz.pxi +++ b/src/sage/libs/linkages/padics/mpz.pxi @@ -505,7 +505,8 @@ cdef inline cexpansion_next(mpz_t value, expansion_mode mode, long curpower, Pow is being found. Only used in ``smallest_mode``. - ``prime_pow`` -- A ``PowComputer`` holding `p`-adic data. """ - if mode == teichmuller_mode: raise NotImplementedError + if mode == teichmuller_mode: + raise NotImplementedError cdef Integer ans = PY_NEW(Integer) cdef bint neg mpz_mod(ans.value, value, prime_pow.prime.value) diff --git a/src/sage/libs/ntl/ntl_GF2X_linkage.pxi b/src/sage/libs/ntl/ntl_GF2X_linkage.pxi index bccdbc15bad..91d52652cd5 100644 --- a/src/sage/libs/ntl/ntl_GF2X_linkage.pxi +++ b/src/sage/libs/ntl/ntl_GF2X_linkage.pxi @@ -347,16 +347,21 @@ cdef inline int celement_pow(GF2X_c* res, GF2X_c* x, long e, GF2X_c *modulus, lo GF2X_LeftShift(res[0], x[0], e - 1) else: do_sig = GF2X_deg(x[0]) > 1e5 - if do_sig: sig_on() + if do_sig: + sig_on() GF2X_power(res[0], x[0], e) - if do_sig: sig_off() + if do_sig: + sig_off() else: GF2XModulus_build(mod, modulus[0]) do_sig = GF2X_deg(x[0]) > 1e5 - if do_sig: sig_on() + if do_sig: + sig_on() GF2X_PowerMod_long_pre(res[0], x[0], e, mod) - if do_sig: sig_off() + if do_sig: + sig_off() + cdef inline int celement_gcd(GF2X_c* res, GF2X_c* a, GF2X_c *b, long parent) except -2: """ diff --git a/src/sage/libs/symmetrica/sb.pxi b/src/sage/libs/symmetrica/sb.pxi index 2a7b7ed6a5c..732d9811901 100644 --- a/src/sage/libs/symmetrica/sb.pxi +++ b/src/sage/libs/symmetrica/sb.pxi @@ -12,8 +12,6 @@ cdef extern from 'symmetrica/def.h': INT mult_schubert_polynom(OP a,OP b,OP c) - - cdef object _check_schubert(object a, OP ca): if a in Permutations(): if isinstance(a, builtinlist): @@ -48,7 +46,9 @@ def mult_schubert_schubert_symmetrica(a, b): max_a = _check_schubert(a, ca) max_b = _check_schubert(b, cb) except (ValueError, TypeError), err: - freeall(ca); freeall(cb); freeall(cres) + freeall(ca) + freeall(cb) + freeall(cres) raise err @@ -81,7 +81,8 @@ def t_SCHUBERT_POLYNOM_symmetrica(a): try: max_a = _check_schubert(a, ca) except (ValueError, TypeError), err: - freeall(ca); freeall(cres) + freeall(ca) + freeall(cres) raise err sig_on() @@ -111,12 +112,14 @@ def t_POLYNOM_SCHUBERT_symmetrica(a): cdef OP ca = callocobject(), cres = callocobject() if not is_MPolynomial(a): - freeall(ca); freeall(cres) + freeall(ca) + freeall(cres) raise TypeError("a (= %s) must be a multivariate polynomial") else: br = a.parent().base_ring() if br != QQ and br != ZZ: - freeall(ca); freeall(cres) + freeall(ca) + freeall(cres) raise ValueError("a's base ring must be either ZZ or QQ") else: _op_polynom(a, ca) @@ -151,7 +154,9 @@ def mult_schubert_variable_symmetrica(a, i): try: max_a = _check_schubert(a, ca) except (ValueError, TypeError), err: - freeall(ca); freeall(ci); freeall(cres) + freeall(ca) + freeall(ci) + freeall(cres) raise err _op_integer(i, ci) @@ -162,7 +167,9 @@ def mult_schubert_variable_symmetrica(a, i): res = _py(cres) - freeall(ca); freeall(ci); freeall(cres) + freeall(ca) + freeall(ci) + freeall(cres) return res @@ -191,11 +198,15 @@ def divdiff_perm_schubert_symmetrica(perm, a): try: max_a = _check_schubert(a, ca) except (ValueError, TypeError), err: - freeall(ca); freeall(cperm); freeall(cres) + freeall(ca) + freeall(cperm) + freeall(cres) raise err if perm not in Permutations(): - freeall(ca); freeall(cperm); freeall(cres) + freeall(ca) + freeall(cperm) + freeall(cres) raise TypeError("perm must be a permutation") else: perm = Permutation(perm) @@ -204,7 +215,9 @@ def divdiff_perm_schubert_symmetrica(perm, a): _op_permutation(perm, cperm) if max_perm > max_a: - freeall(ca); freeall(cperm); freeall(cres) + freeall(ca) + freeall(cperm) + freeall(cres) raise ValueError(r"cannot apply \delta_{%s} to a (= %s)" % (perm, a)) sig_on() @@ -213,7 +226,9 @@ def divdiff_perm_schubert_symmetrica(perm, a): res = _py(cres) - freeall(ca); freeall(cperm); freeall(cres) + freeall(ca) + freeall(cperm) + freeall(cres) return res @@ -235,7 +250,9 @@ def scalarproduct_schubert_symmetrica(a, b): max_a = _check_schubert(a, ca) max_b = _check_schubert(b, cb) except (ValueError, TypeError), err: - freeall(ca); freeall(cb); freeall(cres) + freeall(ca) + freeall(cb) + freeall(cres) raise err sig_on() @@ -247,7 +264,9 @@ def scalarproduct_schubert_symmetrica(a, b): else: res = _py(cres) - freeall(ca); freeall(cb); freeall(cres) + freeall(ca) + freeall(cb) + freeall(cres) return res @@ -275,17 +294,23 @@ def divdiff_schubert_symmetrica(i, a): try: max_a = _check_schubert(a, ca) except (ValueError, TypeError), err: - freeall(ca); freeall(ci); freeall(cres) + freeall(ca) + freeall(ci) + freeall(cres) raise err if not isinstance(i, (int, Integer)): - freeall(ca); freeall(ci); freeall(cres) + freeall(ca) + freeall(ci) + freeall(cres) raise TypeError("i must be an integer") else: _op_integer(i, ci) if i > max_a or i <= 0: - freeall(ca); freeall(ci); freeall(cres) + freeall(ca) + freeall(ci) + freeall(cres) raise ValueError(r"cannot apply \delta_{%s} to a (= %s)" % (i, a)) sig_on() @@ -294,6 +319,8 @@ def divdiff_schubert_symmetrica(i, a): res = _py(cres) - freeall(ca); freeall(ci); freeall(cres) + freeall(ca) + freeall(ci) + freeall(cres) return res diff --git a/src/sage/libs/symmetrica/symmetrica.pxi b/src/sage/libs/symmetrica/symmetrica.pxi index e8b85194d0b..75fce1b8220 100644 --- a/src/sage/libs/symmetrica/symmetrica.pxi +++ b/src/sage/libs/symmetrica/symmetrica.pxi @@ -667,8 +667,7 @@ cdef object _py_sq_radical(OP a): else: res += _py(S_PO_K(ptr))*sqrt(_py(S_PO_S(ptr))) - - ptr = S_L_N(ptr); + ptr = S_L_N(ptr) return res.radical_simplify() diff --git a/src/sage/matrix/matrix_modn_dense_template.pxi b/src/sage/matrix/matrix_modn_dense_template.pxi index 11859c6bda1..77339965aa4 100644 --- a/src/sage/matrix/matrix_modn_dense_template.pxi +++ b/src/sage/matrix/matrix_modn_dense_template.pxi @@ -189,12 +189,14 @@ cdef inline linbox_echelonize(celement modulus, celement* entries, Py_ssize_t nr cdef size_t nbthreads nbthreads = Parallelism().get('linbox') cdef bool transform = False - if nrows*ncols > 1000: sig_on() + if nrows * ncols > 1000: + sig_on() if nbthreads > 1 : r = pReducedRowEchelonForm(F[0], nrows, ncols, entries, ncols, P, Q, transform, nbthreads) else : r = ReducedRowEchelonForm(F[0], nrows, ncols, entries, ncols, P, Q) - if nrows*ncols > 1000: sig_off() + if nrows * ncols > 1000: + sig_off() for i in range(nrows): for j in range(r): @@ -257,12 +259,14 @@ cdef inline int linbox_rank(celement modulus, celement* entries, Py_ssize_t nrow cdef Py_ssize_t r cdef size_t nbthreads nbthreads = Parallelism().get('linbox') - if nrows*ncols > 1000: sig_on() + if nrows * ncols > 1000: + sig_on() if nbthreads > 1: r = pRank(F[0], nrows, ncols, cpy, ncols, nbthreads) else: r = Rank(F[0], nrows, ncols, cpy, ncols) - if nrows*ncols > 1000: sig_off() + if nrows * ncols > 1000: + sig_off() sig_free(cpy) del F return r @@ -278,12 +282,14 @@ cdef inline celement linbox_det(celement modulus, celement* entries, Py_ssize_t cdef size_t nbthreads nbthreads = Parallelism().get('linbox') - if n*n > 1000: sig_on() + if n*n > 1000: + sig_on() if nbthreads > 1 : pDet(F[0], d, n, cpy, n, nbthreads) else : Det(F[0], d, n, cpy, n) - if n*n > 1000: sig_off() + if n*n > 1000: + sig_off() sig_free(cpy) del F return d @@ -300,7 +306,8 @@ cdef inline celement linbox_matrix_matrix_multiply(celement modulus, celement* a cdef size_t nbthreads nbthreads = Parallelism().get('linbox') - if m*n*k > 100000: sig_on() + if m*n*k > 100000: + sig_on() if nbthreads > 1 : pfgemm(F[0], FflasNoTrans, FflasNoTrans, m, n, k, one, A, k, B, n, zero, @@ -310,7 +317,8 @@ cdef inline celement linbox_matrix_matrix_multiply(celement modulus, celement* a A, k, B, n, zero, ans, n) - if m*n*k > 100000: sig_off() + if m*n*k > 100000: + sig_off() del F @@ -323,12 +331,14 @@ cdef inline int linbox_matrix_vector_multiply(celement modulus, celement* C, cel F.init(one, 1) F.init(zero, 0) - if m*n > 100000: sig_on() + if m*n > 100000: + sig_on() fgemv(F[0], trans, m, n, one, A, n, b, 1, zero, C, 1) - if m*n > 100000: sig_off() + if m*n > 100000: + sig_off() del F @@ -340,9 +350,11 @@ cdef inline linbox_minpoly(celement modulus, Py_ssize_t nrows, celement* entries cdef ModField *F = new ModField(modulus) cdef vector[ModField.Element] *minP = new vector[ModField.Element]() - if nrows*nrows > 1000: sig_on() + if nrows*nrows > 1000: + sig_on() MinPoly(F[0], minP[0], nrows, entries, nrows) - if nrows*nrows > 1000: sig_off() + if nrows*nrows > 1000: + sig_off() l = [] for i in range(minP.size()): @@ -362,9 +374,11 @@ cdef inline linbox_charpoly(celement modulus, Py_ssize_t nrows, celement* entrie cdef celement *cpy = linbox_copy(modulus, entries, nrows, nrows) - if nrows*nrows > 1000: sig_on() + if nrows * nrows > 1000: + sig_on() CharPoly(R[0], P, nrows, cpy, nrows) - if nrows*nrows > 1000: sig_off() + if nrows * nrows > 1000: + sig_off() sig_free(cpy) @@ -1704,7 +1718,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): ....: A.echelonize(algorithm='all') """ x = self.fetch('in_echelon_form') - if not x is None: + if x is not None: return # already known to be in echelon form if not self.base_ring().is_field(): @@ -1941,8 +1955,8 @@ cdef class Matrix_modn_dense_template(Matrix_dense): """ self.check_mutability() x = self.fetch('in_hessenberg_form') - if not x is None and x: return # already known to be in Hessenberg form - + if x is not None and x: + return # already known to be in Hessenberg form if self._nrows != self._ncols: raise ArithmeticError("Matrix must be square to compute Hessenberg form.") @@ -2134,7 +2148,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): cdef Matrix_modn_dense_template A if self.p > 2 and is_prime(self.p): x = self.fetch('rank') - if not x is None: + if x is not None: return x r = Integer(linbox_rank(self.p, self._entries, self._nrows, self._ncols)) self.cache('rank', r) @@ -2237,7 +2251,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): if self.p > 2 and is_prime(self.p): x = self.fetch('det') - if not x is None: + if x is not None: return x d = linbox_det(self.p, self._entries, self._nrows) d2 = self._coerce_element(d) diff --git a/src/sage/rings/padics/CA_template.pxi b/src/sage/rings/padics/CA_template.pxi index 257aa09036b..8f1c4c7795c 100644 --- a/src/sage/rings/padics/CA_template.pxi +++ b/src/sage/rings/padics/CA_template.pxi @@ -860,7 +860,8 @@ cdef class CAElement(pAdicTemplateElement): :meth:`sage.misc.cachefunc._cache_key` """ - tuple_recursive = lambda l: tuple(tuple_recursive(x) for x in l) if isinstance(l, Iterable) else l + def tuple_recursive(l): + return tuple(tuple_recursive(x) for x in l) if isinstance(l, Iterable) else l return (self.parent(), tuple_recursive(trim_zeros(list(self.expansion()))), self.precision_absolute()) def _teichmuller_set_unsafe(self): @@ -1671,7 +1672,8 @@ cdef class pAdicConvert_CA_frac_field(Morphism): a + O(3^20) """ cdef CRElement x = _x - if x.ordp < 0: raise ValueError("negative valuation") + if x.ordp < 0: + raise ValueError("negative valuation") cdef CAElement ans = self._zero._new_c() cdef bint reduce = (x.prime_pow.e > 1) ans.absprec = x.relprec + x.ordp @@ -1721,7 +1723,8 @@ cdef class pAdicConvert_CA_frac_field(Morphism): """ cdef long aprec, rprec cdef CRElement x = _x - if x.ordp < 0: raise ValueError("negative valuation") + if x.ordp < 0: + raise ValueError("negative valuation") cdef CAElement ans = self._zero._new_c() cdef bint reduce = False _process_args_and_kwds(&aprec, &rprec, args, kwds, True, ans.prime_pow) diff --git a/src/sage/rings/padics/CR_template.pxi b/src/sage/rings/padics/CR_template.pxi index e8080c29856..602a756a2a9 100644 --- a/src/sage/rings/padics/CR_template.pxi +++ b/src/sage/rings/padics/CR_template.pxi @@ -358,7 +358,9 @@ cdef class CRElement(pAdicTemplateElement): else: if self.ordp > right.ordp: # Addition is commutative, swap so self.ordp < right.ordp - ans = right; right = self; self = ans + ans = right + right = self + self = ans tmpL = right.ordp - self.ordp if tmpL > self.relprec: return self @@ -1249,7 +1251,8 @@ cdef class CRElement(pAdicTemplateElement): :meth:`sage.misc.cachefunc._cache_key` """ - tuple_recursive = lambda l: tuple(tuple_recursive(x) for x in l) if isinstance(l, list) else l + def tuple_recursive(l): + return tuple(tuple_recursive(x) for x in l) if isinstance(l, list) else l return (self.parent(), tuple_recursive(trim_zeros(list(self.expansion()))), self.valuation(), self.precision_relative()) def _teichmuller_set_unsafe(self): @@ -2392,7 +2395,8 @@ cdef class pAdicConvert_CR_frac_field(Morphism): a + O(3^20) """ cdef CRElement x = _x - if x.ordp < 0: raise ValueError("negative valuation") + if x.ordp < 0: + raise ValueError("negative valuation") cdef CRElement ans = self._zero._new_c() ans.relprec = x.relprec ans.ordp = x.ordp @@ -2436,7 +2440,8 @@ cdef class pAdicConvert_CR_frac_field(Morphism): """ cdef long aprec, rprec cdef CRElement x = _x - if x.ordp < 0: raise ValueError("negative valuation") + if x.ordp < 0: + raise ValueError("negative valuation") cdef CRElement ans = self._zero._new_c() cdef bint reduce = False _process_args_and_kwds(&aprec, &rprec, args, kwds, False, ans.prime_pow) diff --git a/src/sage/rings/padics/FM_template.pxi b/src/sage/rings/padics/FM_template.pxi index c940f131464..df7bd8bdf38 100644 --- a/src/sage/rings/padics/FM_template.pxi +++ b/src/sage/rings/padics/FM_template.pxi @@ -1426,7 +1426,8 @@ cdef class pAdicConvert_FM_frac_field(Morphism): a """ cdef FPElement x = _x - if x.ordp < 0: raise ValueError("negative valuation") + if x.ordp < 0: + raise ValueError("negative valuation") if x.ordp >= self._zero.prime_pow.ram_prec_cap: return self._zero cdef FMElement ans = self._zero._new_c() @@ -1470,7 +1471,8 @@ cdef class pAdicConvert_FM_frac_field(Morphism): """ cdef long aprec, rprec cdef FPElement x = _x - if x.ordp < 0: raise ValueError("negative valuation") + if x.ordp < 0: + raise ValueError("negative valuation") if x.ordp >= self._zero.prime_pow.ram_prec_cap: return self._zero cdef FMElement ans = self._zero._new_c() diff --git a/src/sage/rings/padics/FP_template.pxi b/src/sage/rings/padics/FP_template.pxi index 6c70c8a1c75..65485cdc0ad 100644 --- a/src/sage/rings/padics/FP_template.pxi +++ b/src/sage/rings/padics/FP_template.pxi @@ -359,7 +359,9 @@ cdef class FPElement(pAdicTemplateElement): else: if self.ordp > right.ordp: # Addition is commutative, swap so self.ordp < right.ordp - ans = right; right = self; self = ans + ans = right + right = self + self = ans tmpL = right.ordp - self.ordp if tmpL > self.prime_pow.ram_prec_cap: return self @@ -2015,7 +2017,8 @@ cdef class pAdicConvert_FP_frac_field(Morphism): a """ cdef FPElement x = _x - if x.ordp < 0: raise ValueError("negative valuation") + if x.ordp < 0: + raise ValueError("negative valuation") cdef FPElement ans = self._zero._new_c() ans.ordp = x.ordp cshift_notrunc(ans.unit, x.unit, 0, ans.prime_pow.ram_prec_cap, ans.prime_pow, False) @@ -2058,7 +2061,8 @@ cdef class pAdicConvert_FP_frac_field(Morphism): """ cdef long aprec, rprec cdef FPElement x = _x - if x.ordp < 0: raise ValueError("negative valuation") + if x.ordp < 0: + raise ValueError("negative valuation") cdef FPElement ans = self._zero._new_c() cdef bint reduce = False _process_args_and_kwds(&aprec, &rprec, args, kwds, False, ans.prime_pow) From 88e71c553a6e7579a4d66fd4cf5a2d4f44193db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 11 Jun 2022 11:42:05 +0200 Subject: [PATCH 077/116] some pep fixes for E7 in pxd files --- .../perm_gps/partn_ref/data_structures.pxd | 9 +- src/sage/libs/flint/padic.pxd | 120 +++++++++--------- src/sage/libs/flint/thread_pool.pxd | 2 +- src/sage/libs/gmp/randomize.pxd | 6 +- src/sage/libs/singular/decl.pxd | 30 ++--- 5 files changed, 86 insertions(+), 81 deletions(-) diff --git a/src/sage/groups/perm_gps/partn_ref/data_structures.pxd b/src/sage/groups/perm_gps/partn_ref/data_structures.pxd index b6af8190d51..b469d09c2b5 100644 --- a/src/sage/groups/perm_gps/partn_ref/data_structures.pxd +++ b/src/sage/groups/perm_gps/partn_ref/data_structures.pxd @@ -151,7 +151,8 @@ cdef inline int OP_merge_list_perm(OrbitPartition *OP, int *gamma): """ cdef int i, i_root, gamma_i_root, changed = 0 for i from 0 <= i < OP.degree: - if gamma[i] == i: continue + if gamma[i] == i: + continue i_root = OP_find(OP, i) gamma_i_root = OP_find(OP, gamma[i]) if i_root != gamma_i_root: @@ -508,8 +509,10 @@ cdef inline bint SC_contains(StabilizerChain *SC, int level, int *pi, bint modif for i from level <= i < SC.base_size: b = SC.base_orbits[i][0] x = perm[b] - if x == b: continue - if SC.parents[i][x] == -1: return 0 + if x == b: + continue + if SC.parents[i][x] == -1: + return 0 SC_compose_up_to_base(SC, i, x, perm) return SC_perm_is_identity(perm, n) diff --git a/src/sage/libs/flint/padic.pxd b/src/sage/libs/flint/padic.pxd index 831d8746920..e155ddabfd8 100644 --- a/src/sage/libs/flint/padic.pxd +++ b/src/sage/libs/flint/padic.pxd @@ -15,40 +15,40 @@ cdef extern from "flint_wrap.h": #* Context *******************************************************************/ void padic_ctx_init(padic_ctx_t ctx, const fmpz_t p, slong min, slong max, - padic_print_mode mode); - void padic_ctx_clear(padic_ctx_t ctx); + padic_print_mode mode) + void padic_ctx_clear(padic_ctx_t ctx) int _padic_ctx_pow_ui(fmpz_t rop, ulong e, const padic_ctx_t ctx) void padic_ctx_pow_ui(fmpz_t rop, ulong e, const padic_ctx_t ctx) #* Memory management *********************************************************/ - void padic_init(padic_t rop); - void padic_init2(padic_t rop, slong N); - void padic_clear(padic_t rop); + void padic_init(padic_t rop) + void padic_init2(padic_t rop, slong N) + void padic_clear(padic_t rop) void _padic_canonicalise(padic_t rop, const padic_ctx_t ctx) - void _padic_reduce(padic_t rop, const padic_ctx_t ctx); - void padic_reduce(padic_t rop, const padic_ctx_t ctx); + void _padic_reduce(padic_t rop, const padic_ctx_t ctx) + void padic_reduce(padic_t rop, const padic_ctx_t ctx) #* Randomisation *************************************************************/ - void padic_randtest(padic_t rop, flint_rand_t state, const padic_ctx_t ctx); + void padic_randtest(padic_t rop, flint_rand_t state, const padic_ctx_t ctx) void padic_randtest_not_zero(padic_t rop, flint_rand_t state, - const padic_ctx_t ctx); + const padic_ctx_t ctx) void padic_randtest_int(padic_t rop, flint_rand_t state, - const padic_ctx_t ctx); + const padic_ctx_t ctx) #* Assignments and conversions ***********************************************/ - void padic_set(padic_t rop, const padic_t op, const padic_ctx_t ctx); - void padic_set_si(padic_t rop, slong op, const padic_ctx_t ctx); - void padic_set_ui(padic_t rop, ulong op, const padic_ctx_t ctx); - void padic_set_fmpz(padic_t rop, const fmpz_t op, const padic_ctx_t ctx); - void padic_set_fmpq(padic_t rop, const fmpq_t op, const padic_ctx_t ctx); - void padic_set_mpz(padic_t rop, const mpz_t op, const padic_ctx_t ctx); - void padic_set_mpq(padic_t rop, const mpq_t op, const padic_ctx_t ctx); - void padic_get_fmpz(fmpz_t rop, const padic_t op, const padic_ctx_t ctx); - void padic_get_fmpq(fmpq_t rop, const padic_t op, const padic_ctx_t ctx); - void padic_get_mpz(mpz_t rop, const padic_t op, const padic_ctx_t ctx); - void padic_get_mpq(mpq_t rop, const padic_t op, const padic_ctx_t ctx); + void padic_set(padic_t rop, const padic_t op, const padic_ctx_t ctx) + void padic_set_si(padic_t rop, slong op, const padic_ctx_t ctx) + void padic_set_ui(padic_t rop, ulong op, const padic_ctx_t ctx) + void padic_set_fmpz(padic_t rop, const fmpz_t op, const padic_ctx_t ctx) + void padic_set_fmpq(padic_t rop, const fmpq_t op, const padic_ctx_t ctx) + void padic_set_mpz(padic_t rop, const mpz_t op, const padic_ctx_t ctx) + void padic_set_mpq(padic_t rop, const mpq_t op, const padic_ctx_t ctx) + void padic_get_fmpz(fmpz_t rop, const padic_t op, const padic_ctx_t ctx) + void padic_get_fmpq(fmpq_t rop, const padic_t op, const padic_ctx_t ctx) + void padic_get_mpz(mpz_t rop, const padic_t op, const padic_ctx_t ctx) + void padic_get_mpq(mpq_t rop, const padic_t op, const padic_ctx_t ctx) void padic_swap(padic_t op1, padic_t op2) void padic_zero(padic_t rop) void padic_one(padic_t rop) @@ -59,58 +59,58 @@ cdef extern from "flint_wrap.h": int padic_equal(const padic_t op1, const padic_t op2) #* Arithmetic operations *****************************************************/ - slong * _padic_lifts_exps(slong *n, slong N); - void _padic_lifts_pows(fmpz *pow, const slong *a, slong n, const fmpz_t p); + slong * _padic_lifts_exps(slong *n, slong N) + void _padic_lifts_pows(fmpz *pow, const slong *a, slong n, const fmpz_t p) void padic_add(padic_t rop, const padic_t op1, const padic_t op2, - const padic_ctx_t ctx); + const padic_ctx_t ctx) void padic_sub(padic_t rop, const padic_t op1, const padic_t op2, - const padic_ctx_t ctx); - void padic_neg(padic_t rop, const padic_t op, const padic_ctx_t ctx); + const padic_ctx_t ctx) + void padic_neg(padic_t rop, const padic_t op, const padic_ctx_t ctx) void padic_mul(padic_t rop, const padic_t op1, const padic_t op2, - const padic_ctx_t ctx); - void padic_shift(padic_t rop, const padic_t op, slong v, const padic_ctx_t ctx); + const padic_ctx_t ctx) + void padic_shift(padic_t rop, const padic_t op, slong v, const padic_ctx_t ctx) void padic_div(padic_t rop, const padic_t op1, const padic_t op2, - const padic_ctx_t ctx); - void _padic_inv_precompute(padic_inv_t S, const fmpz_t p, slong N); - void _padic_inv_clear(padic_inv_t S); - void _padic_inv_precomp(fmpz_t rop, const fmpz_t op, const padic_inv_t S); - void _padic_inv(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N); - void padic_inv(padic_t rop, const padic_t op, const padic_ctx_t ctx); - int padic_sqrt(padic_t rop, const padic_t op, const padic_ctx_t ctx); + const padic_ctx_t ctx) + void _padic_inv_precompute(padic_inv_t S, const fmpz_t p, slong N) + void _padic_inv_clear(padic_inv_t S) + void _padic_inv_precomp(fmpz_t rop, const fmpz_t op, const padic_inv_t S) + void _padic_inv(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N) + void padic_inv(padic_t rop, const padic_t op, const padic_ctx_t ctx) + int padic_sqrt(padic_t rop, const padic_t op, const padic_ctx_t ctx) void padic_pow_si(padic_t rop, const padic_t op, slong e, - const padic_ctx_t ctx); + const padic_ctx_t ctx) #* Exponential ***************************************************************/ - slong _padic_exp_bound(slong v, slong N, const fmpz_t p); - void _padic_exp(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N); - void _padic_exp_rectangular(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N); - void _padic_exp_balanced(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N); - int padic_exp(padic_t rop, const padic_t op, const padic_ctx_t ctx); - int padic_exp_rectangular(padic_t rop, const padic_t op, const padic_ctx_t ctx); - int padic_exp_balanced(padic_t rop, const padic_t op, const padic_ctx_t ctx); + slong _padic_exp_bound(slong v, slong N, const fmpz_t p) + void _padic_exp(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N) + void _padic_exp_rectangular(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N) + void _padic_exp_balanced(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N) + int padic_exp(padic_t rop, const padic_t op, const padic_ctx_t ctx) + int padic_exp_rectangular(padic_t rop, const padic_t op, const padic_ctx_t ctx) + int padic_exp_balanced(padic_t rop, const padic_t op, const padic_ctx_t ctx) #* Logarithm *****************************************************************/ - slong _padic_log_bound(slong v, slong N, const fmpz_t p); - void _padic_log(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N); - void _padic_log_rectangular(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N); - void _padic_log_satoh(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N); - void _padic_log_balanced(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N); - int padic_log(padic_t rop, const padic_t op, const padic_ctx_t ctx); - int padic_log_rectangular(padic_t rop, const padic_t op, const padic_ctx_t ctx); - int padic_log_satoh(padic_t rop, const padic_t op, const padic_ctx_t ctx); - int padic_log_balanced(padic_t rop, const padic_t op, const padic_ctx_t ctx); + slong _padic_log_bound(slong v, slong N, const fmpz_t p) + void _padic_log(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N) + void _padic_log_rectangular(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N) + void _padic_log_satoh(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N) + void _padic_log_balanced(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N) + int padic_log(padic_t rop, const padic_t op, const padic_ctx_t ctx) + int padic_log_rectangular(padic_t rop, const padic_t op, const padic_ctx_t ctx) + int padic_log_satoh(padic_t rop, const padic_t op, const padic_ctx_t ctx) + int padic_log_balanced(padic_t rop, const padic_t op, const padic_ctx_t ctx) #* Special functions *********************************************************/ - void _padic_teichmuller(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N); - void padic_teichmuller(padic_t rop, const padic_t op, const padic_ctx_t ctx); - ulong padic_val_fac_ui_2(ulong N); - ulong padic_val_fac_ui(ulong N, const fmpz_t p); - void padic_val_fac(fmpz_t rop, const fmpz_t op, const fmpz_t p); + void _padic_teichmuller(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N) + void padic_teichmuller(padic_t rop, const padic_t op, const padic_ctx_t ctx) + ulong padic_val_fac_ui_2(ulong N) + ulong padic_val_fac_ui(ulong N, const fmpz_t p) + void padic_val_fac(fmpz_t rop, const fmpz_t op, const fmpz_t p) #* Input and output **********************************************************/ - char * padic_get_str(char * str, const padic_t op, const padic_ctx_t ctx); - int _padic_fprint(FILE * file, const fmpz_t u, slong v, const padic_ctx_t ctx); - int padic_fprint(FILE * file, const padic_t op, const padic_ctx_t ctx); + char * padic_get_str(char * str, const padic_t op, const padic_ctx_t ctx) + int _padic_fprint(FILE * file, const fmpz_t u, slong v, const padic_ctx_t ctx) + int padic_fprint(FILE * file, const padic_t op, const padic_ctx_t ctx) int _padic_print(const fmpz_t u, slong v, const padic_ctx_t ctx) int padic_print(const padic_t op, const padic_ctx_t ctx) diff --git a/src/sage/libs/flint/thread_pool.pxd b/src/sage/libs/flint/thread_pool.pxd index b773695d2de..a2cd915de79 100644 --- a/src/sage/libs/flint/thread_pool.pxd +++ b/src/sage/libs/flint/thread_pool.pxd @@ -18,7 +18,7 @@ cdef extern from "flint/thread_pool.h": ctypedef struct thread_pool_entry_struct: pass - ctypedef thread_pool_entry_struct thread_pool_entry_t[1]; + ctypedef thread_pool_entry_struct thread_pool_entry_t[1] ctypedef struct thread_pool_struct: pass diff --git a/src/sage/libs/gmp/randomize.pxd b/src/sage/libs/gmp/randomize.pxd index b2ddb55f555..51087eaa02e 100644 --- a/src/sage/libs/gmp/randomize.pxd +++ b/src/sage/libs/gmp/randomize.pxd @@ -43,10 +43,12 @@ cdef inline void mpq_randomize_entry_recip_uniform(mpq_t x): # probability distribution is $X = \mbox{trunc}(1/R)$, where R # varies uniformly between 0 and 1.) cdef int den = rstate.c_random() - SAGE_RAND_MAX/2 - if den == 0: den = 1 + if den == 0: + den = 1 mpz_set_si(mpq_numref(x), (SAGE_RAND_MAX/5*2) / den) den = rstate.c_random() - if den == 0: den = 1 + if den == 0: + den = 1 mpz_set_si(mpq_denref(x), SAGE_RAND_MAX / den) mpq_canonicalize(x) diff --git a/src/sage/libs/singular/decl.pxd b/src/sage/libs/singular/decl.pxd index d5cf0444119..d6b2f28bf2a 100644 --- a/src/sage/libs/singular/decl.pxd +++ b/src/sage/libs/singular/decl.pxd @@ -159,8 +159,8 @@ cdef extern from "singular/Singular/libsingular.h": ring *extRing int ch - mpz_ptr modBase; - unsigned long modExponent; + mpz_ptr modBase + unsigned long modExponent #n_coeffType type int type @@ -475,9 +475,9 @@ cdef extern from "singular/Singular/libsingular.h": # see coeffs.h ctypedef struct GFInfo: - int GFChar; - int GFDegree; - const char* GFPar_name; + int GFChar + int GFDegree + const char* GFPar_name # parameter is pointer to gGFInfo # @@ -1008,8 +1008,8 @@ cdef extern from "singular/coeffs/rmodulon.h": # see rmodulon.h ctypedef struct ZnmInfo: - mpz_ptr base; - unsigned long exp; + mpz_ptr base + unsigned long exp cdef extern from "singular/coeffs/rintegers.h": @@ -1035,7 +1035,7 @@ cdef extern from "singular/polys/sbuckets.h": sBucket *sBucketCreate(ring *r) #destroy an sBucket (note: pointer to pointer) - void sBucketDestroy(sBucket **bucket); + void sBucketDestroy(sBucket **bucket) #merge contents of sBucket into polynomial and clear bucket #(use when monomials are distinct). @@ -1051,29 +1051,29 @@ cdef extern from "singular/polys/sbuckets.h": void sBucketDestroyAdd(sBucket *bucket, poly *p, int *length) #delete bucket constant and clear pointer - void sBucketDeleteAndDestroy(sBucket **bucket_pt); + void sBucketDeleteAndDestroy(sBucket **bucket_pt) #merge p into bucket (distinct monomials assumed) #destroys poly in the process - void sBucket_Merge_p(sBucket *bucket, poly *p, int lp); + void sBucket_Merge_p(sBucket *bucket, poly *p, int lp) #merge p into bucket (distinct monomials assumed) #destroys poly in the process - void sBucket_Merge_m(sBucket *bucket, poly *p); + void sBucket_Merge_m(sBucket *bucket, poly *p) #adds p into bucket (distinct monomials assumed) #destroys poly in the process - void sBucket_Add_p(sBucket *bucket, poly *p, int lp); + void sBucket_Add_p(sBucket *bucket, poly *p, int lp) #adds p into bucket (distinct monomials assumed) #destroys poly in the process - void sBucket_Add_m(sBucket *bucket, poly *p); + void sBucket_Add_m(sBucket *bucket, poly *p) #sorts p with bucketSort: assumes all monomials of p are different - poly *sBucketSortMerge(poly *p, const ring *r); + poly *sBucketSortMerge(poly *p, const ring *r) #sorts p with bucketSort: p may have equal monomials - poly *sBucketSortAdd(poly *p, const ring *r); + poly *sBucketSortAdd(poly *p, const ring *r) cdef extern from "singular/polys/nc/nc.h": # Non-commutative functions From e49f0d2a90d870423c2ba78dc6b17fe6955389ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 11 Jun 2022 17:15:16 +0200 Subject: [PATCH 078/116] fix pycodestyle E306 in geometry and schemes --- .../geometry/hyperbolic_space/hyperbolic_geodesic.py | 4 +++- .../geometry/hyperplane_arrangement/arrangement.py | 3 ++- src/sage/geometry/polyhedron/base.py | 4 +++- src/sage/geometry/polyhedron/base_ZZ.py | 3 ++- .../polyhedron/double_description_inhomogeneous.py | 3 ++- src/sage/geometry/polyhedron/library.py | 3 ++- src/sage/schemes/elliptic_curves/ell_rational_field.py | 6 ++++-- .../schemes/elliptic_curves/gal_reps_number_field.py | 3 +++ src/sage/schemes/elliptic_curves/heegner.py | 10 ++++++---- src/sage/schemes/elliptic_curves/height.py | 4 +++- 10 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py b/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py index 76de0b72983..6168e033670 100644 --- a/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +++ b/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py @@ -2325,12 +2325,14 @@ def plot(self, boundary=True, **options): opts = {'axes': False, 'aspect_ratio': 1} opts.update(self.graphics_options()) opts.update(options) + def map_pt(pt): if pt in CC: return CC(pt) return CC(*pt) end_1, end_2 = [map_pt(k.coordinates()) for k in self.endpoints()] - pic = bezier_path([[(real(end_1), imag(end_1)), (real(end_2), imag(end_2))]], **opts) + pic = bezier_path([[(real(end_1), imag(end_1)), + (real(end_2), imag(end_2))]], **opts) if boundary: pic += self._model.get_background_graphic() return pic diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index fa979354148..e83b6aeacd7 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -846,8 +846,9 @@ def update(mapping, val, I): mapping[val] = len(mapping) elif element_label == "subset": from sage.sets.set import Set + def update(mapping, val, I): - mapping[val] = Set(val) + mapping[val] = Set(val) elif element_label == "subspace": def update(mapping, val, I): mapping[val] = I diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 338c9ca0700..576e073a825 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -1024,8 +1024,10 @@ def permutations_to_matrices(self, conj_class_reps, acting_group=None, additiona G = acting_group group_dict = {} + def permutation_to_matrix(permutation, V, Vplus, W): - A = sum(V[permutation(i)].column() * Vplus[i].row() for i in range(len(V))) + A = sum(V[permutation(i)].column() * Vplus[i].row() + for i in range(len(V))) return A + W for perm in G.gens(): diff --git a/src/sage/geometry/polyhedron/base_ZZ.py b/src/sage/geometry/polyhedron/base_ZZ.py index 8cda8150e79..cfb62d03834 100644 --- a/src/sage/geometry/polyhedron/base_ZZ.py +++ b/src/sage/geometry/polyhedron/base_ZZ.py @@ -812,6 +812,7 @@ def minkowski_decompositions(self): if self.dim() > 2 or not self.is_compact(): raise NotImplementedError('only implemented for bounded polygons') summands = [] + def is_known_summand(poly): for summand in summands: try: @@ -825,7 +826,7 @@ def is_known_summand(poly): continue Y = self - X Y = Y.change_ring(ZZ) # Minkowski difference returns QQ-polyhedron - if X+Y != self: + if X + Y != self: continue decompositions.append((X, Y)) summands += [X, Y] diff --git a/src/sage/geometry/polyhedron/double_description_inhomogeneous.py b/src/sage/geometry/polyhedron/double_description_inhomogeneous.py index 369697dc63c..068c3317434 100644 --- a/src/sage/geometry/polyhedron/double_description_inhomogeneous.py +++ b/src/sage/geometry/polyhedron/double_description_inhomogeneous.py @@ -508,10 +508,11 @@ def _extract_Hrep(self, DD): sage: V2H._extract_Hrep(DD) """ zero = self.base_ring.zero() + def is_trivial(ray): # trivial Hrep output 1 >= 0 return ray[0] > zero and all(r == zero for r in ray[1:]) - ieqs = [self._unpivot_ray(_) for _ in DD.R] + ieqs = (self._unpivot_ray(ra) for ra in DD.R) self.inequalities = [r for r in ieqs if not is_trivial(r)] self.equations = self._linear_subspace.matrix().rows() diff --git a/src/sage/geometry/polyhedron/library.py b/src/sage/geometry/polyhedron/library.py index 95ecc6aac9c..b71e1e29d2b 100644 --- a/src/sage/geometry/polyhedron/library.py +++ b/src/sage/geometry/polyhedron/library.py @@ -2558,8 +2558,9 @@ def permutahedron(self, n, project=False, backend=None): return Polyhedron(vertices=verts, backend=backend) else: parent = Polyhedra(ZZ, n, backend=backend) + def tri(m): - return (m*(m+1))//2 + return (m * (m + 1)) // 2 # Each proper `S \subset [n]` corresponds exactly to # a facet that minimizes the coordinates in `S`. diff --git a/src/sage/schemes/elliptic_curves/ell_rational_field.py b/src/sage/schemes/elliptic_curves/ell_rational_field.py index 3636a97176f..5586b8bc07b 100644 --- a/src/sage/schemes/elliptic_curves/ell_rational_field.py +++ b/src/sage/schemes/elliptic_curves/ell_rational_field.py @@ -1349,11 +1349,11 @@ def modular_symbol_numerical(self, sign=1, prec=20): """ from sage.schemes.elliptic_curves.mod_sym_num import ModularSymbolNumerical M = ModularSymbolNumerical(self, sign=sign) + def f(r): return M.approximative_value(r, prec=prec) return f - def pollack_stevens_modular_symbol(self, sign=0, implementation='eclib'): """ Create the modular symbol attached to the elliptic curve, @@ -2743,10 +2743,12 @@ def silverman_height_bound(self, algorithm='default'): b2 = self.b2() twostar = 2 if b2 else 1 from math import log + def h(x): return log(max(abs(x.numerator()), abs(x.denominator()))) + def h_oo(x): - return log(max(abs(x),1)) + return log(max(abs(x), 1)) mu = h(Delta)/12 + h_oo(j)/12 + h_oo(b2/12)/2 + log(twostar)/2 lower = 2*(-h(j)/24 - mu - 0.961) upper = 2*(mu + 1.07) diff --git a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py index 0692e1e9217..cc950676c6d 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py +++ b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py @@ -540,6 +540,7 @@ def Frobenius_filter(E, L, patience=100): K_is_Q = (K==QQ) from sage.arith.misc import primes from sage.rings.infinity import infinity + def primes_iter(): for p in primes(start=2, stop=infinity): if K_is_Q: @@ -1306,6 +1307,7 @@ def Billerey_B_bound(E, max_l=200, num_l=8, small_prime_bound=0, debug=False): DK = K.discriminant() ED = E.discriminant().norm() B0 = ZZ(6*DK*ED) + def remove_primes(B): B1 = B.prime_to_m_part(B0) for p in primes(small_prime_bound): @@ -1413,6 +1415,7 @@ def Billerey_R_bound(E, max_l=200, num_l=8, small_prime_bound=None, debug=False) DK = K.discriminant() ED = E.discriminant().norm() B0 = ZZ(6*DK*ED) + def remove_primes(B): B1 = B.prime_to_m_part(B0) for p in primes(small_prime_bound): diff --git a/src/sage/schemes/elliptic_curves/heegner.py b/src/sage/schemes/elliptic_curves/heegner.py index 8548c4cbdb7..7c9e4cb0193 100644 --- a/src/sage/schemes/elliptic_curves/heegner.py +++ b/src/sage/schemes/elliptic_curves/heegner.py @@ -5054,11 +5054,12 @@ def modp_splitting_map(self, p): [10 5] """ I, J = self.modp_splitting_data(p) - K = I*J + K = I * J F = I.base_ring() + def phi(q): v = [F(a) for a in q.coefficient_tuple()] - return v[0] + I*v[1] + J*v[2] + K*v[3] + return v[0] + I * v[1] + J * v[2] + K * v[3] return phi def cyclic_subideal_p1(self, I, c): @@ -5739,12 +5740,13 @@ def best_heegner_D(ell_1, ell_2): raise ValueError("if first_only is not True, then the curve E must have rank 1 or 2") P, Q = E.gens() + def kernel_of_reduction(ell): # return list of reps for the kernel as a subgroup of the map # E(Q) / q E(Q) ----> E(F_ell) / q E(F_ell) m = ZZ(E.Np(ell) / q) - A = [a*P + b*Q for a in range(q) for b in range(q)] - return [z for z in A if red(z,ell) * m == 0] + A = (a * P + b * Q for a in range(q) for b in range(q)) + return [z for z in A if red(z, ell) * m == 0] # compute first good odd prime ell_1 = ZZ(3) diff --git a/src/sage/schemes/elliptic_curves/height.py b/src/sage/schemes/elliptic_curves/height.py index 0770e3284bc..1edda0bc949 100644 --- a/src/sage/schemes/elliptic_curves/height.py +++ b/src/sage/schemes/elliptic_curves/height.py @@ -943,8 +943,9 @@ def pair_max(f, g): g = g.change_ring(CDF) dfn = [fast_callable(f.derivative(n)/factorial(n), CDF) for n in range(f.degree()+1)] dgn = [fast_callable(g.derivative(n)/factorial(n), CDF) for n in range(g.degree()+1)] + def max_f_g(s): - (a,b),(c,d) = s.real().endpoints(), s.imag().endpoints() + (a,b), (c,d) = s.real().endpoints(), s.imag().endpoints() dx = a - b dy = c - d eta = RDF(dx*dx + dy*dy).sqrt() @@ -1728,6 +1729,7 @@ def complex_intersection_is_empty(self, Bk, v, verbose=False, use_half=True): T = PeriodicRegion(CDF(1), CDF(tau), vals < B, full=not use_half).expand().refine() B = RIF(B) leaning_right = tau.real() / tau.imag() >= 0 + def check_line(z): wpz = wp(z) if wpz > B: From 56ee208e59725b45e06d4d0f0bd0e90811e03664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 11 Jun 2022 19:03:59 +0200 Subject: [PATCH 079/116] latex for elements of quotient rings --- src/sage/rings/quotient_ring_element.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/sage/rings/quotient_ring_element.py b/src/sage/rings/quotient_ring_element.py index 7a3790f744b..69df8d3319e 100644 --- a/src/sage/rings/quotient_ring_element.py +++ b/src/sage/rings/quotient_ring_element.py @@ -224,6 +224,31 @@ def _repr_(self): with localvars(R, P.variable_names(), normalize=False): return str(self.__rep) + def _latex_(self): + """ + Return the LaTeX representation as a string. + + EXAMPLES:: + + sage: R = PolynomialRing(QQ, 'a, b, c') + sage: a = R.gen(0) + sage: I = R.ideal(a**2 + a + 1) + sage: S = R.quotient(I, names=R.variable_names()) + sage: a = S.gen(0) + sage: latex(a) + a + """ + from sage.structure.parent_gens import localvars + P = self.parent() + R = P.cover_ring() + # see _repr_ above for the idea + try: + P.variable_names() + except ValueError: + return self.__rep._latex_() + with localvars(R, P.variable_names(), normalize=False): + return self.__rep._latex_() + def __pari__(self): """ The Pari representation of this quotient element. From c9167d13c98daabe345a90e84b2bb40ab34904dc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 14:24:52 -0700 Subject: [PATCH 080/116] src/sage/interfaces/tachyon.py: Convert help from latex to rst using pandoc --- src/sage/interfaces/tachyon.py | 1261 +++++++++++++++++--------------- 1 file changed, 669 insertions(+), 592 deletions(-) diff --git a/src/sage/interfaces/tachyon.py b/src/sage/interfaces/tachyon.py index 3f1dcdb5385..c796bc4241c 100644 --- a/src/sage/interfaces/tachyon.py +++ b/src/sage/interfaces/tachyon.py @@ -24,7 +24,7 @@ class TachyonRT(SageObject): - """ + r""" The Tachyon Ray Tracer tachyon_rt(model, outfile='sage.png', verbose=1, block=True, extra_opts='') @@ -71,6 +71,673 @@ class TachyonRT(SageObject): - The file outfile is created. + This help, which was written by John Stone, describes how to create + scene files. + + At the present time, scene description files are very simple. The parser + can’t handle multiple file scene descriptions, although they may be + added in the future. Most of the objects and their scene description are + closely related to the RAY API *(See the API docs for additional info.)* + + Basic Scene Requirements + ------------------------ + + Unlike some other ray tracers out there, RAY requires that you specify + most of the scene parameters in the scene description file itself. If + users would rather specify some of these parameters at the command line, + then I may add that feature in the future. A scene description file + contains keywords, and values associated or grouped with a keyword. All + keywords can be in caps, lower case, or mixed case for the convenience + of the user. File names and texture names are normally case-sensitive, + although the behavior for file names is operating system-dependent. All + values are either character strings, or floating point numbers. In some + cases, the presence of one keyword will require additional keyword / + value pairs. + + At the moment there are several keywords with values, that must appear + in every scene description file. Every scene description file must begin + with the **BEGIN_SCENE** keyword, and end with the **END_SCENE** + keyword. All definitions and declarations of any kind must be inside the + **BEGIN_SCENE**, **END_SCENE** pair. The **RESOLUTION** keyword is + followed by an x resolution and a y resolution in terms of pixels on + each axis. There are currently no limits placed on the resolution of an + output image other than the computer’s available memory and reasonable + execution time. An example of a simple scene description skeleton is + show below: + + :: + + BEGIN_SCENE + RESOLUTION 1024 1024 + ... + ... Camera definition.. + ... + ... Other objects, etc.. + ... + + END_SCENE + + Camera and viewing parameters + ----------------------------- + + One of the most important parts of any scene, is the camera position and + orientation. Having a good angle on a scene can make the difference + between an average looking scene and a strikingly interesting one. There + may be multiple camera definitions in a scene file, but the last camera + definition overrides all previous definitions. There are several + parameters that control the camera in , **PROJECTION**, **ZOOM**, + **ASPECTRATIO**, **ANTIALIASING**, **CENTER**, **RAYDEPTH**, + **VIEWDIR**, and **UPDIR**. + + The first and last keywords required in the definition of a camera are + the **CAMERA** and **END_CAMERA** keywords. The **PROJECTION** keyword + is optional, the remaining camera keywords are required, and must be + written in the sequence they are listed in the examples in this section. + + Camera projection modes + ~~~~~~~~~~~~~~~~~~~~~~~ + + The **PROJECTION** keyword must be followed by one of the supported + camera projection mode identifiers **PERSPECTIVE**, **PERSPECTIVE_DOF**, + **ORTHOGRAPHIC**, or **FISHEYE**. The **FISHEYE** projection mode + requires two extra parameters **FOCALLENGTH** and **APERTURE** which + precede the regular camera options. + + :: + + Camera + projection perspective_dof + focallength 0.75 + aperture 0.02 + Zoom 0.666667 + Aspectratio 1.000000 + Antialiasing 128 + Raydepth 30 + Center 0.000000 0.000000 -2.000000 + Viewdir -0.000000 -0.000000 2.000000 + Updir 0.000000 1.000000 -0.000000 + End_Camera + + Common camera parameters + ~~~~~~~~~~~~~~~~~~~~~~~~ + + The **ZOOM** parameter controls the camera in a way similar to a + telephoto lens on a 35mm camera. A zoom value of 1.0 is standard, with a + 90 degree field of view. By changing the zoom factor to 2.0, the + relative size of any feature in the frame is twice as big, while the + field of view is decreased slightly. The zoom effect is implemented as a + scaling factor on the height and width of the image plane relative to + the world. + + The **ASPECTRATIO** parameter controls the aspect ratio of the resulting + image. By using the aspect ratio parameter, one can produce images which + look correct on any screen. Aspect ratio alters the relative width of + the image plane, while keeping the height of the image plane constant. + In general, most workstation displays have an aspect ratio of 1.0. To + see what aspect ratio your display has, you can render a simple sphere, + at a resolution of 512x512 and measure the ratio of its width to its + height. + + The **ANTIALIASING** parameter controls the maximum level of + supersampling used to obtain higher image quality. The parameter given + sets the number of additional rays to trace per-pixel to attain higher + image quality. + + The **RAYDEPTH** parameter tells RAY what the maximum level of + reflections, refraction, or in general the maximum recursion depth to + trace rays to. A value between 4 and 12 is usually good. A value of 1 + will disable rendering of reflective or transmissive objects (they’ll be + black). + + The remaining three camera parameters are the most important, because + they define the coordinate system of the camera, and its position in the + scene. The **CENTER** parameter is an X, Y, Z coordinate defining the + center of the camera *(also known as the Center of Projection)*. Once + you have determined where the camera will be placed in the scene, you + need to tell RAY what the camera should be looking at. The **VIEWDIR** + parameter is a vector indicating the direction the camera is facing. It + may be useful for me to add a "Look At" type keyword in the future to + make camera aiming easier. If people want or need the "Look At" style + camera, let me know. The last parameter needed to completely define a + camera is the "up" direction. The **UPDIR** parameter is a vector which + points in the direction of the "sky". I wrote the camera so that + **VIEWDIR** and **UPDIR** don’t have to be perpendicular, and there + shouldn’t be a need for a "right" vector although some other ray tracers + require it. Here’s a snippet of a camera definition: + + :: + + CAMERA + ZOOM 1.0 + ASPECTRATIO 1.0 + ANTIALIASING 0 + RAYDEPTH 12 + CENTER 0.0 0.0 2.0 + VIEWDIR 0 0 -1 + UPDIR 0 1 0 + END_CAMERA + + Viewing frustum + ~~~~~~~~~~~~~~~ + + An optional **FRUSTUM** parameter provides a means for rendering + sub-images in a larger frame, and correct stereoscopic images. The + **FRUSTUM** keyword must be followed by four floating parameters, which + indicate the top, bottom, left and right coordinates of the image plane + in eye coordinates. When the projection mode is set to **FISHEYE**, the + frustum parameters correspond to spherical coordinates specified in + radians. + + :: + + CAMERA + ZOOM 1.0 + ASPECTRATIO 1.0 + ANTIALIASING 0 + RAYDEPTH 4 + CENTER 0.0 0.0 -6.0 + VIEWDIR 0.0 0.0 1.0 + UPDIR 0.0 1.0 0.0 + FRUSTUM -0.5 0.5 -0.5 0.5 + END_CAMERA + + Including Files + --------------- + + The **INCLUDE** keyword is used anywhere after the camera description, + and is immediately followed by a valid filename, for a file containing + additional scene description information. The included file is opened, + and processing continues as if it were part of the current file, until + the end of the included file is reached. Parsing of the current file + continues from where it left off prior to the included file. + + Scene File Comments + ------------------- + + The **:math:`\#`** keyword is used anywhere after the camera + description, and will cause RAY to ignore all characters from the + **:math:`\#`** to the end of the input line. The **:math:`\#`** + character must be surrounded by whitespace in order to be recognized. A + sequence such as **:math:`\#\#\#`** will not be recognized as a comment. + + Lights + ------ + + The most frequently used type of lights provided by RAY are positional + point light sources. The lights are actually small spheres, which are + visible. A point light is composed of three pieces of information, a + center, a radius (since its a sphere), and a color. To define a light, + simply write the **LIGHT** keyword, followed by its **CENTER** (a X, Y, + Z coordinate), its **RAD** (radius, a scalar), and its **COLOR** (a Red + Green Blue triple). The radius parameter will accept any value of 0.0 or + greater. Lights of radius 0.0 will not be directly visible in the + rendered scene, but contribute light to the scene normally. For a light, + the color values range from 0.0 to 1.0, any values outside this range + may yield unpredictable results. A simple light definition looks like + this: + + :: + + LIGHT CENTER 4.0 3.0 2.0 + RAD 0.2 + COLOR 0.5 0.5 0.5 + + This light would be gray colored if seen directly, and would be 50% + intensity in each RGB color component. + + RAY supports simple directional lighting, commonly used in CAD and + scientific visualization programs for its performance advantages over + positional lights. Directional lights cannot be seen directly in scenes + rendered by , only their illumination contributes to the final image. + + :: + + DIRECTIONAL_LIGHT + DIRECTION 0.0 -1.0 0.0 + COLOR 1.0 0.0 0.0 + + RAY supports spotlights, which are described very similarly to a point + light, but they are attenuated by angle from the direction vector, based + on a “falloff start” angle and “falloff end”angle. Between the starting + and ending angles, the illumination is attenuated linearly. The syntax + for a spotlight description in a scene file is as follows. + + :: + + SPOTLIGHT + CENTER 0.0 3.0 17.0 + RAD 0.2 + DIRECTION 0.0 -1.0 0.0 + FALLOFF_START 20.0 + FALLOFF_END 45.0 + COLOR 1.0 0.0 0.0 + + The lighting system implemented by RAY provides various levels of + distance-based lighting attenuation. By default, a light is not + attenuated by distance. If the *attenuation* keywords is present + immediately prior to the light’s color, RAY will accept coefficients + which are used to calculate distance-based attenuation, which is applied + the light by multiplying with the resulting value. The attenuation + factor is calculated from the equation + + .. math:: 1/(K_c + K_l d + k_q d^2) + + This attenuation equation should be familiar to some as it is the same + lighting attenuation equation used by OpenGL. The constant, linear, and + quadratic terms are specified in a scene file as shown in the following + example. + + :: + + LIGHT + CENTER -5.0 0.0 10.0 + RAD 1.0 + ATTENUATION CONSTANT 1.0 LINEAR 0.2 QUADRATIC 0.05 + COLOR 1.0 0.0 0.0 + + Atmospheric effects + ------------------- + + RAY currently only implements one atmospheric effect, simple + distance-based fog. + + Fog + ~~~ + + RAY provides a simple distance-based fog effect intended to provide + functionality similar to that found in OpenGL, for compatibility with + software that requires an OpenGL-like fog implementation. Much like + OpenGL, RAY provides linear, exponential, and exponential-squared fog. + + :: + + FOG + LINEAR START 0.0 END 50.0 DENSITY 1.0 COLOR 1.0 1.0 1.0 + + :: + + FOG + EXP START 0.0 END 50.0 DENSITY 1.0 COLOR 1.0 1.0 1.0 + + :: + + FOG + EXP2 START 0.0 END 50.0 DENSITY 1.0 COLOR 1.0 1.0 1.0 + + Objects + ------- + + Spheres + ~~~~~~~ + + Spheres are the simplest object supported by RAY and they are also the + fastest object to render. Spheres are defined as one would expect, with + a **CENTER**, **RAD** (radius), and a texture. The texture may be + defined along with the object as discussed earlier, or it may be + declared and assigned a name. Here’s a sphere definition using a + previously defined "NitrogenAtom" texture: + + :: + + SPHERE CENTER 26.4 27.4 -2.4 RAD 1.0 NitrogenAtom + + A sphere with an inline texture definition is declared like this: + + :: + + Sphere center 1.0 0.0 10.0 + Rad 1.0 + Texture Ambient 0.2 Diffuse 0.8 Specular 0.0 Opacity 1.0 + Color 1.0 0.0 0.5 + TexFunc 0 + + Notice that in this example I used mixed case for the keywords, this is + allowable... Review the section on textures if the texture definitions + are confusing. + + Triangles + ~~~~~~~~~ + + Triangles are also fairly simple objects, constructed by listing the + three vertices of the triangle, and its texture. The order of the + vertices isn’t important, the triangle object is "double sided", so the + surface normal is always pointing back in the direction of the incident + ray. The triangle vertices are listed as **V1**, **V2**, and **V3** each + one is an X, Y, Z coordinate. An example of a triangle is shown below: + + :: + + TRI + V0 0.0 -4.0 12.0 + V1 4.0 -4.0 8.0 + V2 -4.0 -4.0 8.0 + TEXTURE + AMBIENT 0.1 DIFFUSE 0.2 SPECULAR 0.7 OPACITY 1.0 + COLOR 1.0 1.0 1.0 + TEXFUNC 0 + + Smoothed Triangles + ~~~~~~~~~~~~~~~~~~ + + Smoothed triangles are just like regular triangles, except that the + surface normal for each of the three vertices is used to determine the + surface normal across the triangle by linear interpolation. Smoothed + triangles yield curved looking objects and have nice reflections. + + :: + + STRI + V0 1.4 0.0 2.4 + V1 1.35 -0.37 2.4 + V2 1.36 -0.32 2.45 + N0 -0.9 -0.0 -0.4 + N1 -0.8 0.23 -0.4 + N2 -0.9 0.27 -0.15 + TEXTURE + AMBIENT 0.1 DIFFUSE 0.2 SPECULAR 0.7 OPACITY 1.0 + COLOR 1.0 1.0 1.0 + TEXFUNC 0 + + Infinite Planes + ~~~~~~~~~~~~~~~ + + Useful for things like desert floors, backgrounds, skies etc, the + infinite plane is pretty easy to use. An infinite plane only consists of + two pieces of information, the **CENTER** of the plane, and a **NORMAL** + to the plane. The center of the plane is just any point on the plane + such that the point combined with the surface normal define the equation + for the plane. As with triangles, planes are double sided. Here is an + example of an infinite plane: + + :: + + PLANE + CENTER 0.0 -5.0 0.0 + NORMAL 0.0 1.0 0.0 + TEXTURE + AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 + COLOR 1.0 1.0 1.0 + TEXFUNC 1 + CENTER 0.0 -5.0 0.0 + ROTATE 0. 0.0 0.0 + SCALE 1.0 1.0 1.0 + + Rings + ~~~~~ + + Rings are a simple object, they are really a not-so-infinite plane. + Rings are simply an infinite plane cut into a washer shaped ring, + infinitely thing just like a plane. A ring only requires two more pieces + of information than an infinite plane does, an inner and outer radius. + Here’s an example of a ring: + + :: + + Ring + Center 1.0 1.0 1.0 + Normal 0.0 1.0 0.0 + Inner 1.0 + Outer 5.0 + MyNewRedTexture + + Infinite Cylinders + ~~~~~~~~~~~~~~~~~~ + + Infinite cylinders are quite simple. They are defined by a center, an + axis, and a radius. An example of an infinite cylinder is: + + :: + + Cylinder + Center 0.0 0.0 0.0 + Axis 0.0 1.0 0.0 + Rad 1.0 + SomeRandomTexture + + Finite Cylinders + ~~~~~~~~~~~~~~~~ + + Finite cylinders are almost the same as infinite ones, but the center + and length of the axis determine the extents of the cylinder. The finite + cylinder is also really a shell, it doesn’t have any caps. If you need + to close off the ends of the cylinder, use two ring objects, with the + inner radius set to 0.0 and the normal set to be the axis of the + cylinder. Finite cylinders are built this way to enhance speed. + + :: + + FCylinder + Center 0.0 0.0 0.0 + Axis 0.0 9.0 0.0 + Rad 1.0 + SomeRandomTexture + + This defines a finite cylinder with radius 1.0, going from 0.0 0.0 0.0, + to 0.0 9.0 0.0 along the Y axis. The main difference between an infinite + cylinder and a finite cylinder is in the interpretation of the **AXIS** + parameter. In the case of the infinite cylinder, the length of the axis + vector is ignored. In the case of the finite cylinder, the axis + parameter is used to determine the length of the overall cylinder. + + Axis Aligned Boxes + ~~~~~~~~~~~~~~~~~~ + + Axis aligned boxes are fast, but of limited usefulness. As such, I’m not + going to waste much time explaining ’em. An axis aligned box is defined + by a **MIN** point, and a **MAX** point. The volume between the min and + max points is the box. Here’s a simple box: + + :: + + BOX + MIN -1.0 -1.0 -1.0 + MAX 1.0 1.0 1.0 + Boxtexture1 + + Fractal Landscapes + ~~~~~~~~~~~~~~~~~~ + + Currently fractal landscapes are a built-in function. In the near future + I’ll allow the user to load an image map for use as a heightfield. + Fractal landscapes are currently forced to be axis aligned. Any + suggestion on how to make them more appealing to users is welcome. A + fractal landscape is defined by its "resolution" which is the number of + grid points along each axis, and by its scale and center. The "scale" is + how large the landscape is along the X, and Y axes in world coordinates. + Here’s a simple landscape: + + :: + + SCAPE + RES 30 30 + SCALE 80.0 80.0 + CENTER 0.0 -4.0 20.0 + TEXTURE + AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 + COLOR 1.0 1.0 1.0 + TEXFUNC 0 + + The landscape shown above generates a square landscape made of 1,800 + triangles. When time permits, the heightfield code will be rewritten to + be more general and to increase rendering speed. + + Arbitrary Quadric Surfaces + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Docs soon. I need to add these into the parser, must have forgotten + before ;-) + + Volume Rendered Scalar Voxels + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + These are a little trickier than the average object :-) These are likely + to change substantially in the very near future so I’m not going to get + too detailed yet. A volume rendered data set is described by its axis + aligned bounding box, and its resolution along each axis. The final + parameter is the voxel data file. If you are seriously interested in + messing with these, get hold of me and I’ll give you more info. Here’s a + quick example: + + :: + + SCALARVOL + MIN -1.0 -1.0 -0.4 + MAX 1.0 1.0 0.4 + DIM 256 256 100 + FILE /cfs/johns/vol/engine.256x256x110 + TEXTURE + AMBIENT 1.0 DIFFUSE 0.0 SPECULAR 0.0 OPACITY 8.1 + COLOR 1.0 1.0 1.0 + TEXFUNC 0 + + Texture and Color + ----------------- + + Simple Texture Characteristics + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + The surface textures applied to an object drastically alter its overall + appearance, making textures and color one of the most important topics + in this manual. As with many other renderers, textures can be declared + and associated with a name so that they may be used over and over again + in a scene definition with less typing. If a texture is only need once, + or it is unique to a particular object in the scene, then it may be + declared along with the object it is applied to, and does not need a + name. + + The simplest texture definition is a solid color with no image mapping + or procedural texture mapping. A solid color texture is defined by the + **AMBIENT**, **DIFFUSE**, **SPECULAR**, **OPACITY** and **COLOR** + parameters. The **AMBIENT** parameter defines the ambient lighting + coefficient to be used when shading the object. Similarly, the + **DIFFUSE** parameter is the relative contribution of the diffuse + shading to the surface appearance. The **SPECULAR** parameter is the + contribution from perfectly reflected rays, as if on a mirrored surface. + **OPACITY** defines how transparent a surface is. An **OPACITY** value + of 0.0 renders the object completely invisible. An **OPACITY** value of + 1.0 makes the object completely solid, and non-transmissive. In general, + the values for the ambient, diffuse, and specular parameters should add + up to 1.0, if they don’t then pixels may be over or underexposed quite + easily. These parameters function in a manner similar to that of other + ray tracers. The **COLOR** parameter is an RGB triple with each value + ranging from 0.0 to 1.0 inclusive. If the RGB values stray from 0.0 to + 1.0, results are undefined. In the case of solid textures, a final + parameter, **TEXFUNC** is set to zero (integer). + + Texture Declaration and Aliasing + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + To define a simple texture for use on several objects in a scene, the + **TEXDEF** keyword is used. The **TEXDEF** keyword is followed by a case + sensitive texture name, which will subsequently be used while defining + objects. If many objects in a scene use the same texture through texture + definition, a significant amount of memory may be saved since only one + copy of the texture is present in memory, and its shared by all of the + objects. Here is an example of a solid texture definition: + + :: + + TEXDEF MyNewRedTexture + AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 + COLOR 1.0 0.0 0.0 TEXFUNC 0 + + When this texture is used in an object definition, it is referenced only + by name. Be careful not to use one of the other keywords as a defined + texture, this will probably cause the parser to explode, as I don’t + check for use of keywords as texture names. + + When a texture is declared within an object definition, it appears in an + identical format to the **TEXDEF** declaration, but the **TEXTURE** + keyword is used instead of **TEXDEF**. If it is useful to have several + names for the same texture (when you are too lazy to actually finish + defining different variations of a wood texture for example, and just + want to be approximately correct for example) aliases can be constructed + using the **TEXALIAS** keyword, along with the alias name, and the + original name. An example of a texture alias is: + + :: + + TEXALIAS MyNewestRedTexture MyNewRedTexture + + This line would alias MyNewestRedTexture to be the same thing as the + previously declared MyNewRedTexture. Note that the source texture must + be declared before any aliases that use it. + + Image Maps and Procedural Textures + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Image maps and procedural textures very useful in making realistic + looking scenes. A good image map can do as much for the realism of a + wooden table as any amount of sophisticated geometry or lighting. Image + maps are made by wrapping an image on to an object in one of three ways, + a spherical map, a cylindrical map, and a planar map. Procedural + textures are used in a way similar to the image maps, but they are on + the fly and do not use much memory compared to the image maps. The main + disadvantage of the procedural maps is that they must be hard-coded into + RAY when it is compiled. + + The syntax used for all texture maps is fairly simple to learn. The + biggest problem with the way that the parser is written now is that the + different mappings are selected by an integer, which is not very user + friendly. I expect to rewrite this section of the parser sometime in the + near future to alleviate this problem. When I rewrite the parser, I may + also end up altering the parameters that are used to describe a texture + map, and some of them may become optional rather than required. + + .. container:: center + + +---------------------------+-----------------------------------------+ + | Texture Mapping Functions | | + +===========================+=========================================+ + | Value for TEXFUNC | Mapping and Texture Description | + +---------------------------+-----------------------------------------+ + | 0 | No special texture, plain shading | + +---------------------------+-----------------------------------------+ + | 1 | 3D checkerboard function, like a | + | | Rubik’s cube | + +---------------------------+-----------------------------------------+ + | 2 | Grit Texture, randomized surface color | + +---------------------------+-----------------------------------------+ + | 3 | 3D marble texture, uses object’s base | + | | color | + +---------------------------+-----------------------------------------+ + | 4 | 3D wood texture, light and dark brown, | + | | not very good yet | + +---------------------------+-----------------------------------------+ + | 5 | 3D gradient noise function (can’t | + | | remember what it look like | + +---------------------------+-----------------------------------------+ + | 6 | Don’t remember | + +---------------------------+-----------------------------------------+ + | 7 | Cylindrical Image Map, requires ppm | + | | filename | + +---------------------------+-----------------------------------------+ + | 8 | Spherical Image Map, requires ppm | + | | filename | + +---------------------------+-----------------------------------------+ + | 9 | Planar Image Map, requires ppm filename | + +---------------------------+-----------------------------------------+ + + Here’s an example of a sphere, with a spherical image map applied to its + surface: + + :: + + SPHERE + CENTER 2.0 0.0 5.0 + RAD 2.0 + TEXTURE + AMBIENT 0.4 DIFFUSE 0.8 SPECULAR 0.0 OPACITY 1.0 + COLOR 1.0 1.0 1.0 + TEXFUNC 7 /cfs/johns/imaps/fire644.ppm + CENTER 2.0 0.0 5.0 + ROTATE 0.0 0.0 0.0 + SCALE 2.0 -2.0 1.0 + + Basically, the image maps require the center, rotate and scale + parameters so that you can position the image map on the object + properly. + EXAMPLES: @@ -196,598 +863,8 @@ def help(self, use_pager=True): sage: t.help(use_pager=False) This help, which was written by John Stone, describes ... """ - s = r""" -This help, which was written by John Stone, describes how to create -scene files. - -At the present time, scene description files are very simple. -The parser can't handle multiple file scene descriptions, although they -may be added in the future. Most of the objects and their scene description -are closely related to the RAY API -\emph{(See the API docs for additional info.)} - -\subsection{Basic Scene Requirements} - Unlike some other ray tracers out there, RAY requires that you -specify most of the scene parameters in the scene description file itself. -If users would rather specify some of these parameters at the command line, -then I may add that feature in the future. -A scene description file contains keywords, and values associated or grouped -with a keyword. All keywords can be in caps, lower case, or mixed case -for the convenience of the user. File names and texture names are -normally case-sensitive, although the behavior for file names is -operating system-dependent. All values are either character strings, or -floating point numbers. In some cases, the presence of one keyword will -require additional keyword / value pairs. - - At the moment there are several keywords with values, -that must appear in every scene description file. -Every scene description file must begin with the -{\bf BEGIN\_SCENE} keyword, and end with the {\bf END\_SCENE} keyword. -All definitions and declarations of any kind must be inside the -{\bf BEGIN\_SCENE}, {\bf END\_SCENE} pair. -The {\bf RESOLUTION} keyword is followed by an x resolution -and a y resolution in terms of pixels on each axis. There are currently -no limits placed on the resolution of an output image other than the -computer's available memory and reasonable execution time. -An example of a simple scene description skeleton is show below: -\begin{verbatim} -BEGIN_SCENE - RESOLUTION 1024 1024 -... -... Camera definition.. -... -... Other objects, etc.. -... - -END_SCENE -\end{verbatim} - -\subsection{Camera and viewing parameters} - One of the most important parts of any scene, is the camera position and -orientation. Having a good angle on a scene can make the difference between -an average looking scene and a strikingly interesting one. There may be -multiple camera definitions in a scene file, but the last camera definition -overrides all previous definitions. -There are several parameters that control the camera in \RAY, -{\bf PROJECTION}, {\bf ZOOM}, {\bf ASPECTRATIO}, {\bf ANTIALIASING}, - {\bf CENTER}, {\bf RAYDEPTH}, {\bf VIEWDIR}, and {\bf UPDIR}. - -The first and last keywords required in the definition of a camera are the -{\bf CAMERA} and {\bf END\_CAMERA} keywords. The {\bf PROJECTION} keyword -is optional, the remaining camera keywords are required, and must be -written in the sequence they are listed in the examples in this section. - -\subsubsection{Camera projection modes} - The {\bf PROJECTION} keyword must be followed by one of the supported -camera projection mode identifiers {\bf PERSPECTIVE}, {\bf PERSPECTIVE_DOF}, -{\bf ORTHOGRAPHIC}, or {\bf FISHEYE}. The {\bf FISHEYE} projection mode -requires two extra parameters {\bf FOCALLENGTH} and {\bf APERTURE} -which precede the regular camera options. - -\begin{verbatim} -Camera - projection perspective_dof - focallength 0.75 - aperture 0.02 - Zoom 0.666667 - Aspectratio 1.000000 - Antialiasing 128 - Raydepth 30 - Center 0.000000 0.000000 -2.000000 - Viewdir -0.000000 -0.000000 2.000000 - Updir 0.000000 1.000000 -0.000000 -End_Camera -\end{verbatim} - -\subsubsection{Common camera parameters} - The {\bf ZOOM} parameter controls the camera in a way similar to a -telephoto lens on a 35mm camera. A zoom value of 1.0 is standard, -with a 90 degree field of view. By changing the zoom factor to 2.0, -the relative size of any feature in the frame is twice as big, while -the field of view is decreased slightly. The zoom effect is -implemented as a scaling factor on the height and width of the image -plane relative to the world. - - The {\bf ASPECTRATIO} parameter controls the aspect ratio of the resulting -image. By using the aspect ratio parameter, one can produce images which -look correct on any screen. Aspect ratio alters the relative width of the -image plane, while keeping the height of the image plane constant. In -general, most workstation displays have an aspect ratio of 1.0. To see -what aspect ratio your display has, you can render a simple sphere, at -a resolution of 512x512 and measure the ratio of its width to its height. - -The {\bf ANTIALIASING} parameter controls the maximum level of supersampling -used to obtain higher image quality. The parameter given sets the number of -additional rays to trace per-pixel to attain higher image quality. - - The {\bf RAYDEPTH} parameter tells RAY what the maximum -level of reflections, refraction, or in general the maximum recursion -depth to trace rays to. A value between 4 and 12 is usually good. A -value of 1 will disable rendering of reflective or transmissive -objects (they'll be black). - - The remaining three camera parameters are the most important, because -they define the coordinate system of the camera, and its position in the -scene. The {\bf CENTER} parameter is an X, Y, Z coordinate defining the -center of the camera \emph{(also known as the Center of Projection)}. -Once you have determined where the camera will be placed in the scene, you -need to tell RAY what the camera should be looking at. The -{\bf VIEWDIR} parameter is a vector indicating the direction the camera -is facing. It may be useful for me to add a "Look At" type keyword in -the future to make camera aiming easier. If people want or need the -"Look At" style camera, let me know. The last parameter needed to completely -define a camera is the "up" direction. The {\bf UPDIR} parameter is a vector -which points in the direction of the "sky". I wrote the camera so that -{\bf VIEWDIR} and {\bf UPDIR} don't have to be perpendicular, and there -shouldn't be a need for a "right" vector although some other ray tracers -require it. Here's a snippet of a camera definition: -\begin{verbatim} -CAMERA - ZOOM 1.0 - ASPECTRATIO 1.0 - ANTIALIASING 0 - RAYDEPTH 12 - CENTER 0.0 0.0 2.0 - VIEWDIR 0 0 -1 - UPDIR 0 1 0 -END_CAMERA -\end{verbatim} - - -\subsubsection{Viewing frustum} -An optional {\bf FRUSTUM} parameter provides a means for rendering sub-images -in a larger frame, and correct stereoscopic images. The {\bf FRUSTUM} -keyword must be followed by four floating parameters, which indicate -the top, bottom, left and right coordinates of the image plane in -eye coordinates. When the projection mode is set to {\bf FISHEYE}, -the frustum parameters correspond to spherical coordinates specified -in radians. - -\begin{verbatim} -CAMERA - ZOOM 1.0 - ASPECTRATIO 1.0 - ANTIALIASING 0 - RAYDEPTH 4 - CENTER 0.0 0.0 -6.0 - VIEWDIR 0.0 0.0 1.0 - UPDIR 0.0 1.0 0.0 - FRUSTUM -0.5 0.5 -0.5 0.5 -END_CAMERA -\end{verbatim} - - -\subsection{Including Files} -The {\bf INCLUDE} keyword is used anywhere after the camera description, -and is immediately followed by a valid filename, for a file containing -additional scene description information. The included file is opened, -and processing continues as if it were part of the current file, until -the end of the included file is reached. Parsing of the current file -continues from where it left off prior to the included file. - -\subsection{Scene File Comments} -The {\bf $\#$} keyword is used anywhere after the camera description, and -will cause RAY to ignore all characters from the {\bf $\#$} to the end -of the input line. The {\bf $\#$} character must be surrounded by whitespace -in order to be recognized. A sequence such as {\bf $\#\#\#$} will not be -recognized as a comment. - -\subsection{Lights} -The most frequently used type of lights provided by RAY are positional -point light sources. The lights are actually small spheres, which are -visible. A point light is composed of three pieces of -information, a center, a radius (since its a sphere), and a color. -To define a light, simply write the {\bf LIGHT} keyword, followed by -its {\bf CENTER} (a X, Y, Z coordinate), its {\bf RAD} (radius, a scalar), -and its {\bf COLOR} (a Red Green Blue triple). The radius parameter will -accept any value of 0.0 or greater. Lights of radius 0.0 will not be -directly visible in the rendered scene, but contribute light to the scene -normally. -For a light, the color values -range from 0.0 to 1.0, any values outside this range may yield unpredictable -results. A simple light definition looks like this: -\begin{verbatim} - LIGHT CENTER 4.0 3.0 2.0 - RAD 0.2 - COLOR 0.5 0.5 0.5 -\end{verbatim} -This light would be gray colored if seen directly, and would be 50\% -intensity in each RGB color component. - - -RAY supports simple directional lighting, commonly used in -CAD and scientific visualization programs for its performance -advantages over positional lights. Directional lights cannot be -seen directly in scenes rendered by \RAY, only their illumination -contributes to the final image. - -\begin{verbatim} -DIRECTIONAL_LIGHT - DIRECTION 0.0 -1.0 0.0 - COLOR 1.0 0.0 0.0 -\end{verbatim} - -RAY supports spotlights, which are described very similarly to a -point light, but they are attenuated by angle from the direction vector, -based on a ``falloff start'' angle and ``falloff end''angle. Between -the starting and ending angles, the illumination is attenuated linearly. -The syntax for a spotlight description in a scene file is as follows. -\begin{verbatim} -SPOTLIGHT - CENTER 0.0 3.0 17.0 - RAD 0.2 - DIRECTION 0.0 -1.0 0.0 - FALLOFF_START 20.0 - FALLOFF_END 45.0 - COLOR 1.0 0.0 0.0 -\end{verbatim} - -The lighting system implemented by RAY provides various levels of -distance-based lighting attenuation. By default, a light is not attenuated -by distance. If the \emph{attenuation} keywords is present immediately -prior to the light's color, RAY will accept coefficients which are used -to calculate distance-based attenuation, which is applied the light by -multiplying with the resulting value. The attenuation factor is calculated -from the equation -$$ - 1/(K_c + K_l d + k_q d^2) -$$ - -This attenuation equation should be familiar to some as it -is the same lighting attenuation equation used by OpenGL. -The constant, linear, and quadratic terms are specified in a scene file -as shown in the following example. -\begin{verbatim} -LIGHT - CENTER -5.0 0.0 10.0 - RAD 1.0 - ATTENUATION CONSTANT 1.0 LINEAR 0.2 QUADRATIC 0.05 - COLOR 1.0 0.0 0.0 -\end{verbatim} - - - -\subsection{Atmospheric effects} -RAY currently only implements one atmospheric effect, -simple distance-based fog. - -\subsubsection{Fog} -RAY provides a simple distance-based fog effect intended to provide -functionality similar to that found in OpenGL, for compatibility with -software that requires an OpenGL-like fog implementation. Much like -OpenGL, RAY provides linear, exponential, and exponential-squared fog. - -\begin{verbatim} - FOG - LINEAR START 0.0 END 50.0 DENSITY 1.0 COLOR 1.0 1.0 1.0 -\end{verbatim} - -\begin{verbatim} - FOG - EXP START 0.0 END 50.0 DENSITY 1.0 COLOR 1.0 1.0 1.0 -\end{verbatim} - -\begin{verbatim} - FOG - EXP2 START 0.0 END 50.0 DENSITY 1.0 COLOR 1.0 1.0 1.0 -\end{verbatim} - - -\subsection{Objects} - -\subsubsection{Spheres} - Spheres are the simplest object supported by RAY and they are -also the fastest object to render. Spheres are defined as one would expect, -with a {\bf CENTER}, {\bf RAD} (radius), and a texture. The texture may -be defined along with the object as discussed earlier, or it may be declared -and assigned a name. -Here's a sphere definition using a previously defined "NitrogenAtom" texture: -\begin{verbatim} - SPHERE CENTER 26.4 27.4 -2.4 RAD 1.0 NitrogenAtom -\end{verbatim} -A sphere with an inline texture definition is declared like this: -\begin{verbatim} - Sphere center 1.0 0.0 10.0 - Rad 1.0 - Texture Ambient 0.2 Diffuse 0.8 Specular 0.0 Opacity 1.0 - Color 1.0 0.0 0.5 - TexFunc 0 -\end{verbatim} -Notice that in this example I used mixed case for the keywords, this is -allowable... -Review the section on textures if the texture definitions are confusing. - -\subsubsection{Triangles} - Triangles are also fairly simple objects, constructed by listing the -three vertices of the triangle, and its texture. The order of the -vertices isn't important, the triangle object is "double sided", so the -surface normal is always pointing back in the direction of the incident ray. -The triangle vertices are listed as {\bf V1}, {\bf V2}, and {\bf V3} each one -is an X, Y, Z coordinate. An example of a triangle is shown below: -\begin{verbatim} -TRI - V0 0.0 -4.0 12.0 - V1 4.0 -4.0 8.0 - V2 -4.0 -4.0 8.0 - TEXTURE - AMBIENT 0.1 DIFFUSE 0.2 SPECULAR 0.7 OPACITY 1.0 - COLOR 1.0 1.0 1.0 - TEXFUNC 0 -\end{verbatim} - -\subsubsection{Smoothed Triangles} - Smoothed triangles are just like regular triangles, except that the - surface normal for each of the three vertices is used to determine the - surface normal across the triangle by linear interpolation. - Smoothed triangles yield curved looking objects and have nice - reflections. -\begin{verbatim} -STRI - V0 1.4 0.0 2.4 - V1 1.35 -0.37 2.4 - V2 1.36 -0.32 2.45 - N0 -0.9 -0.0 -0.4 - N1 -0.8 0.23 -0.4 - N2 -0.9 0.27 -0.15 - TEXTURE - AMBIENT 0.1 DIFFUSE 0.2 SPECULAR 0.7 OPACITY 1.0 - COLOR 1.0 1.0 1.0 - TEXFUNC 0 -\end{verbatim} - -\subsubsection{Infinite Planes} - - Useful for things like desert floors, backgrounds, skies etc, the infinite -plane is pretty easy to use. An infinite plane only consists of two pieces -of information, the {\bf CENTER} of the plane, and a {\bf NORMAL} to the plane. -The center of the plane is just any point on the plane such that the point -combined with the surface normal define the equation for the plane. -As with triangles, planes are double sided. Here is an example of an -infinite plane: -\begin{verbatim} -PLANE - CENTER 0.0 -5.0 0.0 - NORMAL 0.0 1.0 0.0 - TEXTURE - AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 - COLOR 1.0 1.0 1.0 - TEXFUNC 1 - CENTER 0.0 -5.0 0.0 - ROTATE 0. 0.0 0.0 - SCALE 1.0 1.0 1.0 -\end{verbatim} - -\subsubsection{Rings} - Rings are a simple object, they are really a not-so-infinite plane. -Rings are simply an infinite plane cut into a washer shaped ring, infinitely -thing just like a plane. A ring only requires two more pieces of information -than an infinite plane does, an inner and outer radius. Here's an example -of a ring: -\begin{verbatim} - Ring - Center 1.0 1.0 1.0 - Normal 0.0 1.0 0.0 - Inner 1.0 - Outer 5.0 - MyNewRedTexture -\end{verbatim} - -\subsubsection{Infinite Cylinders} - Infinite cylinders are quite simple. They are defined by a center, an -axis, and a radius. An example of an infinite cylinder is: -\begin{verbatim} - Cylinder - Center 0.0 0.0 0.0 - Axis 0.0 1.0 0.0 - Rad 1.0 - SomeRandomTexture -\end{verbatim} - -\subsubsection{Finite Cylinders} - Finite cylinders are almost the same as infinite ones, but the - center and length of the axis determine the extents of the cylinder. - The finite cylinder is also really a shell, it doesn't have any - caps. If you need to close off the ends of the cylinder, use two - ring objects, with the inner radius set to 0.0 and the normal set - to be the axis of the cylinder. Finite cylinders are built this - way to enhance speed. - -\begin{verbatim} - FCylinder - Center 0.0 0.0 0.0 - Axis 0.0 9.0 0.0 - Rad 1.0 - SomeRandomTexture -\end{verbatim} -This defines a finite cylinder with radius 1.0, going from 0.0 0.0 0.0, to -0.0 9.0 0.0 along the Y axis. The main difference between an infinite cylinder -and a finite cylinder is in the interpretation of the {\bf AXIS} parameter. -In the case of the infinite cylinder, the length of the axis vector is -ignored. In the case of the finite cylinder, the axis parameter is used -to determine the length of the overall cylinder. - -\subsubsection{Axis Aligned Boxes} - Axis aligned boxes are fast, but of limited usefulness. As such, I'm -not going to waste much time explaining 'em. An axis aligned box is -defined by a {\bf MIN} point, and a {\bf MAX} point. The volume between -the min and max points is the box. Here's a simple box: -\begin{verbatim} - BOX - MIN -1.0 -1.0 -1.0 - MAX 1.0 1.0 1.0 - Boxtexture1 -\end{verbatim} - -\subsubsection{Fractal Landscapes} - Currently fractal landscapes are a built-in function. In the near future -I'll allow the user to load an image map for use as a heightfield. -Fractal landscapes are currently forced to be axis aligned. Any suggestion -on how to make them more appealing to users is welcome. A fractal landscape -is defined by its "resolution" which is the number of grid points along -each axis, and by its scale and center. The "scale" is how large the -landscape is along the X, and Y axes in world coordinates. Here's a simple -landscape: -\begin{verbatim} -SCAPE - RES 30 30 - SCALE 80.0 80.0 - CENTER 0.0 -4.0 20.0 - TEXTURE - AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 - COLOR 1.0 1.0 1.0 - TEXFUNC 0 -\end{verbatim} -The landscape shown above generates a square landscape made of 1,800 triangles. -When time permits, the heightfield code will be rewritten to be more -general and to increase rendering speed. - -\subsubsection{Arbitrary Quadric Surfaces} - Docs soon. I need to add these into the parser, must have forgotten -before ;-) - -\subsubsection{Volume Rendered Scalar Voxels} -These are a little trickier than the average object :-) -These are likely to change substantially in the very near future so I'm not -going to get too detailed yet. -A volume rendered data set is described by its axis aligned bounding box, and -its resolution along each axis. The final parameter is the voxel data -file. If you are seriously interested in messing with these, get hold of -me and I'll give you more info. Here's a quick example: -\begin{verbatim} -SCALARVOL - MIN -1.0 -1.0 -0.4 - MAX 1.0 1.0 0.4 - DIM 256 256 100 - FILE /cfs/johns/vol/engine.256x256x110 - TEXTURE - AMBIENT 1.0 DIFFUSE 0.0 SPECULAR 0.0 OPACITY 8.1 - COLOR 1.0 1.0 1.0 - TEXFUNC 0 -\end{verbatim} - -\subsection{Texture and Color} -\subsubsection{Simple Texture Characteristics} - The surface textures applied to an object drastically alter its overall -appearance, making textures and color one of the most important topics in -this manual. As with many other renderers, textures can be declared and -associated with a name so that they may be used over and over again in -a scene definition with less typing. If a texture is only need once, or it -is unique to a particular object in the scene, then it may be declared along -with the object it is applied to, and does not need a name. - - The simplest texture definition is a solid color with no image mapping -or procedural texture mapping. A solid color texture is defined by the -{\bf AMBIENT}, {\bf DIFFUSE}, {\bf SPECULAR}, {\bf OPACITY} and {\bf COLOR} -parameters. The {\bf AMBIENT} parameter defines the ambient lighting -coefficient to be used when shading the object. Similarly, the {\bf DIFFUSE} -parameter is the relative contribution of the diffuse shading to the surface -appearance. The {\bf SPECULAR} parameter is the contribution from perfectly -reflected rays, as if on a mirrored surface. {\bf OPACITY} defines how -transparent a surface is. An {\bf OPACITY} value of 0.0 renders the object -completely invisible. An {\bf OPACITY} value of 1.0 makes the object -completely solid, and non-transmissive. In general, the values for the -ambient, diffuse, and specular parameters should add up to 1.0, if they don't -then pixels may be over or underexposed quite easily. These parameters -function in a manner similar to that of other ray tracers. The {\bf COLOR} -parameter is an RGB triple with each value ranging from 0.0 to 1.0 inclusive. -If the RGB values stray from 0.0 to 1.0, results are undefined. -In the case of solid textures, a final parameter, {\bf TEXFUNC} is set to -zero (integer). - -\subsubsection{Texture Declaration and Aliasing} - To define a simple texture for use on several objects in a scene, the -{\bf TEXDEF} keyword is used. The {\bf TEXDEF} keyword is followed by -a case sensitive texture name, which will subsequently be used while -defining objects. If many objects in a scene use the same texture through -texture definition, a significant amount of memory may be saved since only -one copy of the texture is present in memory, and its shared by all -of the objects. Here is an example of a solid texture definition: -\begin{verbatim} - TEXDEF MyNewRedTexture - AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 - COLOR 1.0 0.0 0.0 TEXFUNC 0 -\end{verbatim} -When this texture is used in an object definition, it is referenced only by -name. Be careful not to use one of the other keywords as a defined texture, -this will probably cause the parser to explode, as I don't check for use -of keywords as texture names. - - When a texture is declared within an object definition, it appears in -an identical format to the {\bf TEXDEF} declaration, but the {\bf TEXTURE} -keyword is used instead of {\bf TEXDEF}. If it is useful to have several -names for the same texture (when you are too lazy to actually finish defining -different variations of a wood texture for example, and just want to be -approximately correct for example) aliases can be constructed using the -{\bf TEXALIAS} keyword, along with the alias name, and the original name. -An example of a texture alias is: -\begin{verbatim} - TEXALIAS MyNewestRedTexture MyNewRedTexture -\end{verbatim} -This line would alias MyNewestRedTexture to be the same thing as the -previously declared MyNewRedTexture. Note that the source texture must -be declared before any aliases that use it. - -\subsubsection{Image Maps and Procedural Textures} Image maps and -procedural textures very useful in making realistic looking scenes. A -good image map can do as much for the realism of a wooden table as any -amount of sophisticated geometry or lighting. Image maps are made by -wrapping an image on to an object in one of three ways, a spherical -map, a cylindrical map, and a planar map. Procedural textures are -used in a way similar to the image maps, but they are on the fly and -do not use much memory compared to the image maps. The main -disadvantage of the procedural maps is that they must be hard-coded -into RAY when it is compiled. - - The syntax used for all texture maps is fairly simple to learn. The biggest -problem with the way that the parser is written now is that the different -mappings are selected by an integer, which is not very user friendly. I -expect to rewrite this section of the parser sometime in the near future to -alleviate this problem. When I rewrite the parser, I may also end up altering -the parameters that are used to describe a texture map, and some of them may -become optional rather than required. - -\begin{center} -\begin{tabular}{|c|c|} -\multicolumn{2}{c}{Texture Mapping Functions} \\ -\hline -{Value for TEXFUNC} & {Mapping and Texture Description}\\ -\hline -{0} & {No special texture, plain shading} \\ -{1} & {3D checkerboard function, like a Rubik's cube} \\ -{2} & {Grit Texture, randomized surface color} \\ -{3} & {3D marble texture, uses object's base color} \\ -{4} & {3D wood texture, light and dark brown, not very good yet} \\ -{5} & {3D gradient noise function (can't remember what it look like} \\ -{6} & {Don't remember} \\ -{7} & {Cylindrical Image Map, requires ppm filename} \\ -{8} & {Spherical Image Map, requires ppm filename} \\ -{9} & {Planar Image Map, requires ppm filename} \\ -\hline -\end{tabular} -\end{center} - -Here's an example of a sphere, with a spherical image map applied to its -surface: -\begin{verbatim} -SPHERE - CENTER 2.0 0.0 5.0 - RAD 2.0 - TEXTURE - AMBIENT 0.4 DIFFUSE 0.8 SPECULAR 0.0 OPACITY 1.0 - COLOR 1.0 1.0 1.0 - TEXFUNC 7 /cfs/johns/imaps/fire644.ppm - CENTER 2.0 0.0 5.0 - ROTATE 0.0 0.0 0.0 - SCALE 2.0 -2.0 1.0 -\end{verbatim} - -Basically, the image maps require the center, rotate and scale -parameters so that you can position the image map on the object -properly. -""" from sage.misc.sagedoc import format - f = format(s) - f = f.replace('{ ','').replace('}','').replace('{','') + f = format(self.__doc__) if use_pager: pager()(f) else: From cc07fc0bb4f7b512344d8899117432384fc1de02 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 14:27:51 -0700 Subject: [PATCH 081/116] src/sage/interfaces/tachyon.py: Mark up tachyon keywords with double backticks --- src/sage/interfaces/tachyon.py | 80 +++++++++++++++++----------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/sage/interfaces/tachyon.py b/src/sage/interfaces/tachyon.py index c796bc4241c..444f22e9357 100644 --- a/src/sage/interfaces/tachyon.py +++ b/src/sage/interfaces/tachyon.py @@ -96,9 +96,9 @@ class TachyonRT(SageObject): At the moment there are several keywords with values, that must appear in every scene description file. Every scene description file must begin - with the **BEGIN_SCENE** keyword, and end with the **END_SCENE** + with the ``BEGIN_SCENE`` keyword, and end with the ``END_SCENE`` keyword. All definitions and declarations of any kind must be inside the - **BEGIN_SCENE**, **END_SCENE** pair. The **RESOLUTION** keyword is + ``BEGIN_SCENE``, ``END_SCENE`` pair. The ``RESOLUTION`` keyword is followed by an x resolution and a y resolution in terms of pixels on each axis. There are currently no limits placed on the resolution of an output image other than the computer’s available memory and reasonable @@ -125,22 +125,22 @@ class TachyonRT(SageObject): between an average looking scene and a strikingly interesting one. There may be multiple camera definitions in a scene file, but the last camera definition overrides all previous definitions. There are several - parameters that control the camera in , **PROJECTION**, **ZOOM**, - **ASPECTRATIO**, **ANTIALIASING**, **CENTER**, **RAYDEPTH**, - **VIEWDIR**, and **UPDIR**. + parameters that control the camera in , ``PROJECTION``, ``ZOOM``, + ``ASPECTRATIO``, ``ANTIALIASING``, ``CENTER``, ``RAYDEPTH``, + ``VIEWDIR``, and ``UPDIR``. The first and last keywords required in the definition of a camera are - the **CAMERA** and **END_CAMERA** keywords. The **PROJECTION** keyword + the ``CAMERA`` and ``END_CAMERA`` keywords. The ``PROJECTION`` keyword is optional, the remaining camera keywords are required, and must be written in the sequence they are listed in the examples in this section. Camera projection modes ~~~~~~~~~~~~~~~~~~~~~~~ - The **PROJECTION** keyword must be followed by one of the supported - camera projection mode identifiers **PERSPECTIVE**, **PERSPECTIVE_DOF**, - **ORTHOGRAPHIC**, or **FISHEYE**. The **FISHEYE** projection mode - requires two extra parameters **FOCALLENGTH** and **APERTURE** which + The ``PROJECTION`` keyword must be followed by one of the supported + camera projection mode identifiers ``PERSPECTIVE``, ``PERSPECTIVE_DOF``, + ``ORTHOGRAPHIC``, or ``FISHEYE``. The ``FISHEYE`` projection mode + requires two extra parameters ``FOCALLENGTH`` and ``APERTURE`` which precede the regular camera options. :: @@ -161,7 +161,7 @@ class TachyonRT(SageObject): Common camera parameters ~~~~~~~~~~~~~~~~~~~~~~~~ - The **ZOOM** parameter controls the camera in a way similar to a + The ``ZOOM`` parameter controls the camera in a way similar to a telephoto lens on a 35mm camera. A zoom value of 1.0 is standard, with a 90 degree field of view. By changing the zoom factor to 2.0, the relative size of any feature in the frame is twice as big, while the @@ -169,7 +169,7 @@ class TachyonRT(SageObject): scaling factor on the height and width of the image plane relative to the world. - The **ASPECTRATIO** parameter controls the aspect ratio of the resulting + The ``ASPECTRATIO`` parameter controls the aspect ratio of the resulting image. By using the aspect ratio parameter, one can produce images which look correct on any screen. Aspect ratio alters the relative width of the image plane, while keeping the height of the image plane constant. @@ -178,12 +178,12 @@ class TachyonRT(SageObject): at a resolution of 512x512 and measure the ratio of its width to its height. - The **ANTIALIASING** parameter controls the maximum level of + The ``ANTIALIASING`` parameter controls the maximum level of supersampling used to obtain higher image quality. The parameter given sets the number of additional rays to trace per-pixel to attain higher image quality. - The **RAYDEPTH** parameter tells RAY what the maximum level of + The ``RAYDEPTH`` parameter tells RAY what the maximum level of reflections, refraction, or in general the maximum recursion depth to trace rays to. A value between 4 and 12 is usually good. A value of 1 will disable rendering of reflective or transmissive objects (they’ll be @@ -191,17 +191,17 @@ class TachyonRT(SageObject): The remaining three camera parameters are the most important, because they define the coordinate system of the camera, and its position in the - scene. The **CENTER** parameter is an X, Y, Z coordinate defining the + scene. The ``CENTER`` parameter is an X, Y, Z coordinate defining the center of the camera *(also known as the Center of Projection)*. Once you have determined where the camera will be placed in the scene, you - need to tell RAY what the camera should be looking at. The **VIEWDIR** + need to tell RAY what the camera should be looking at. The ``VIEWDIR`` parameter is a vector indicating the direction the camera is facing. It may be useful for me to add a "Look At" type keyword in the future to make camera aiming easier. If people want or need the "Look At" style camera, let me know. The last parameter needed to completely define a - camera is the "up" direction. The **UPDIR** parameter is a vector which + camera is the "up" direction. The ``UPDIR`` parameter is a vector which points in the direction of the "sky". I wrote the camera so that - **VIEWDIR** and **UPDIR** don’t have to be perpendicular, and there + ``VIEWDIR`` and ``UPDIR`` don’t have to be perpendicular, and there shouldn’t be a need for a "right" vector although some other ray tracers require it. Here’s a snippet of a camera definition: @@ -220,11 +220,11 @@ class TachyonRT(SageObject): Viewing frustum ~~~~~~~~~~~~~~~ - An optional **FRUSTUM** parameter provides a means for rendering + An optional ``FRUSTUM`` parameter provides a means for rendering sub-images in a larger frame, and correct stereoscopic images. The - **FRUSTUM** keyword must be followed by four floating parameters, which + ``FRUSTUM`` keyword must be followed by four floating parameters, which indicate the top, bottom, left and right coordinates of the image plane - in eye coordinates. When the projection mode is set to **FISHEYE**, the + in eye coordinates. When the projection mode is set to ``FISHEYE``, the frustum parameters correspond to spherical coordinates specified in radians. @@ -244,7 +244,7 @@ class TachyonRT(SageObject): Including Files --------------- - The **INCLUDE** keyword is used anywhere after the camera description, + The ``INCLUDE`` keyword is used anywhere after the camera description, and is immediately followed by a valid filename, for a file containing additional scene description information. The included file is opened, and processing continues as if it were part of the current file, until @@ -267,8 +267,8 @@ class TachyonRT(SageObject): point light sources. The lights are actually small spheres, which are visible. A point light is composed of three pieces of information, a center, a radius (since its a sphere), and a color. To define a light, - simply write the **LIGHT** keyword, followed by its **CENTER** (a X, Y, - Z coordinate), its **RAD** (radius, a scalar), and its **COLOR** (a Red + simply write the ``LIGHT`` keyword, followed by its ``CENTER`` (a X, Y, + Z coordinate), its ``RAD`` (radius, a scalar), and its ``COLOR`` (a Red Green Blue triple). The radius parameter will accept any value of 0.0 or greater. Lights of radius 0.0 will not be directly visible in the rendered scene, but contribute light to the scene normally. For a light, @@ -372,7 +372,7 @@ class TachyonRT(SageObject): Spheres are the simplest object supported by RAY and they are also the fastest object to render. Spheres are defined as one would expect, with - a **CENTER**, **RAD** (radius), and a texture. The texture may be + a ``CENTER``, ``RAD`` (radius), and a texture. The texture may be defined along with the object as discussed earlier, or it may be declared and assigned a name. Here’s a sphere definition using a previously defined "NitrogenAtom" texture: @@ -443,7 +443,7 @@ class TachyonRT(SageObject): Useful for things like desert floors, backgrounds, skies etc, the infinite plane is pretty easy to use. An infinite plane only consists of - two pieces of information, the **CENTER** of the plane, and a **NORMAL** + two pieces of information, the ``CENTER`` of the plane, and a ``NORMAL`` to the plane. The center of the plane is just any point on the plane such that the point combined with the surface normal define the equation for the plane. As with triangles, planes are double sided. Here is an @@ -514,7 +514,7 @@ class TachyonRT(SageObject): This defines a finite cylinder with radius 1.0, going from 0.0 0.0 0.0, to 0.0 9.0 0.0 along the Y axis. The main difference between an infinite - cylinder and a finite cylinder is in the interpretation of the **AXIS** + cylinder and a finite cylinder is in the interpretation of the ``AXIS`` parameter. In the case of the infinite cylinder, the length of the axis vector is ignored. In the case of the finite cylinder, the axis parameter is used to determine the length of the overall cylinder. @@ -524,7 +524,7 @@ class TachyonRT(SageObject): Axis aligned boxes are fast, but of limited usefulness. As such, I’m not going to waste much time explaining ’em. An axis aligned box is defined - by a **MIN** point, and a **MAX** point. The volume between the min and + by a ``MIN`` point, and a ``MAX`` point. The volume between the min and max points is the box. Here’s a simple box: :: @@ -607,28 +607,28 @@ class TachyonRT(SageObject): The simplest texture definition is a solid color with no image mapping or procedural texture mapping. A solid color texture is defined by the - **AMBIENT**, **DIFFUSE**, **SPECULAR**, **OPACITY** and **COLOR** - parameters. The **AMBIENT** parameter defines the ambient lighting + ``AMBIENT``, ``DIFFUSE``, ``SPECULAR``, ``OPACITY`` and ``COLOR`` + parameters. The ``AMBIENT`` parameter defines the ambient lighting coefficient to be used when shading the object. Similarly, the - **DIFFUSE** parameter is the relative contribution of the diffuse - shading to the surface appearance. The **SPECULAR** parameter is the + ``DIFFUSE`` parameter is the relative contribution of the diffuse + shading to the surface appearance. The ``SPECULAR`` parameter is the contribution from perfectly reflected rays, as if on a mirrored surface. - **OPACITY** defines how transparent a surface is. An **OPACITY** value - of 0.0 renders the object completely invisible. An **OPACITY** value of + ``OPACITY`` defines how transparent a surface is. An ``OPACITY`` value + of 0.0 renders the object completely invisible. An ``OPACITY`` value of 1.0 makes the object completely solid, and non-transmissive. In general, the values for the ambient, diffuse, and specular parameters should add up to 1.0, if they don’t then pixels may be over or underexposed quite easily. These parameters function in a manner similar to that of other - ray tracers. The **COLOR** parameter is an RGB triple with each value + ray tracers. The ``COLOR`` parameter is an RGB triple with each value ranging from 0.0 to 1.0 inclusive. If the RGB values stray from 0.0 to 1.0, results are undefined. In the case of solid textures, a final - parameter, **TEXFUNC** is set to zero (integer). + parameter, ``TEXFUNC`` is set to zero (integer). Texture Declaration and Aliasing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To define a simple texture for use on several objects in a scene, the - **TEXDEF** keyword is used. The **TEXDEF** keyword is followed by a case + ``TEXDEF`` keyword is used. The ``TEXDEF`` keyword is followed by a case sensitive texture name, which will subsequently be used while defining objects. If many objects in a scene use the same texture through texture definition, a significant amount of memory may be saved since only one @@ -647,12 +647,12 @@ class TachyonRT(SageObject): check for use of keywords as texture names. When a texture is declared within an object definition, it appears in an - identical format to the **TEXDEF** declaration, but the **TEXTURE** - keyword is used instead of **TEXDEF**. If it is useful to have several + identical format to the ``TEXDEF`` declaration, but the ``TEXTURE`` + keyword is used instead of ``TEXDEF``. If it is useful to have several names for the same texture (when you are too lazy to actually finish defining different variations of a wood texture for example, and just want to be approximately correct for example) aliases can be constructed - using the **TEXALIAS** keyword, along with the alias name, and the + using the ``TEXALIAS`` keyword, along with the alias name, and the original name. An example of a texture alias is: :: From bcff99fbab52a9bafe61edf95ee2b8b6355adb38 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 14:31:01 -0700 Subject: [PATCH 082/116] src/sage/interfaces/tachyon.py: More fixes to mark up --- src/sage/interfaces/tachyon.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/interfaces/tachyon.py b/src/sage/interfaces/tachyon.py index 444f22e9357..875f3551602 100644 --- a/src/sage/interfaces/tachyon.py +++ b/src/sage/interfaces/tachyon.py @@ -254,11 +254,11 @@ class TachyonRT(SageObject): Scene File Comments ------------------- - The **:math:`\#`** keyword is used anywhere after the camera + The ``#`` keyword is used anywhere after the camera description, and will cause RAY to ignore all characters from the - **:math:`\#`** to the end of the input line. The **:math:`\#`** + ``#`` to the end of the input line. The ``#`` character must be surrounded by whitespace in order to be recognized. A - sequence such as **:math:`\#\#\#`** will not be recognized as a comment. + sequence such as ``###`` will not be recognized as a comment. Lights ------ @@ -402,7 +402,7 @@ class TachyonRT(SageObject): three vertices of the triangle, and its texture. The order of the vertices isn’t important, the triangle object is "double sided", so the surface normal is always pointing back in the direction of the incident - ray. The triangle vertices are listed as **V1**, **V2**, and **V3** each + ray. The triangle vertices are listed as ``V1``, ``V2``, and ``V3`` each one is an X, Y, Z coordinate. An example of a triangle is shown below: :: From fc788853aee37573c9667e137a863e351b110c4a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 14:32:51 -0700 Subject: [PATCH 083/116] src/sage/interfaces/tachyon.py: Update doctest --- src/sage/interfaces/tachyon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/interfaces/tachyon.py b/src/sage/interfaces/tachyon.py index 875f3551602..a5b11f4cfab 100644 --- a/src/sage/interfaces/tachyon.py +++ b/src/sage/interfaces/tachyon.py @@ -861,7 +861,7 @@ def help(self, use_pager=True): sage: from sage.interfaces.tachyon import TachyonRT sage: t = TachyonRT() sage: t.help(use_pager=False) - This help, which was written by John Stone, describes ... + The Tachyon Ray Tracer... This help, which was written by John Stone, describes ... """ from sage.misc.sagedoc import format f = format(self.__doc__) From b24b06c98dfe9b570862d072c3a729399665296a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 14:36:01 -0700 Subject: [PATCH 084/116] src/sage/misc/sagedoc.py: Update doctest output --- src/sage/misc/sagedoc.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sage/misc/sagedoc.py b/src/sage/misc/sagedoc.py index fe369cd0036..d2c1bac6b05 100644 --- a/src/sage/misc/sagedoc.py +++ b/src/sage/misc/sagedoc.py @@ -418,6 +418,10 @@ def process_dollars(s): sage: process_dollars('hello') 'hello' sage: process_dollars('some math: $x=y$') + doctest:warning... + DeprecationWarning: using dollar signs to mark up math in Sage docstrings + is deprecated; use backticks instead + See https://trac.sagemath.org/33973 for details. 'some math: `x=y`' Replace \\$ with $, and don't do anything when backticks are involved:: From 903e44ad3ac592275a455cbfc6beca557ea7f62b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 14:55:59 -0700 Subject: [PATCH 085/116] sage.schemes: Replace $...$ in docstrings by `...` (fixup) --- src/sage/schemes/toric/divisor.py | 2 +- src/sage/schemes/toric/weierstrass_higher.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/schemes/toric/divisor.py b/src/sage/schemes/toric/divisor.py index f0619f33dbf..ec5ea7db889 100644 --- a/src/sage/schemes/toric/divisor.py +++ b/src/sage/schemes/toric/divisor.py @@ -1258,7 +1258,7 @@ def Kodaira_map(self, names='z'): r""" Return the Kodaira map. - The Kodaira map is the rational map $X_\Sigma \to + The Kodaira map is the rational map `X_\Sigma \to \mathbb{P}^{n-1}`, where `n` equals the number of sections. It is defined by the monomial sections of the line bundle. diff --git a/src/sage/schemes/toric/weierstrass_higher.py b/src/sage/schemes/toric/weierstrass_higher.py index 2f68532b48c..034d3ead9e4 100644 --- a/src/sage/schemes/toric/weierstrass_higher.py +++ b/src/sage/schemes/toric/weierstrass_higher.py @@ -16,8 +16,8 @@ sage: WeierstrassForm([quadratic1, quadratic2]) (-1/4, 0) -Hence, the Weierstrass form of this complete intersection is $Y^2 = -X^3 - \frac{1}{4} X Z^4$. +Hence, the Weierstrass form of this complete intersection is `Y^2 = +X^3 - \frac{1}{4} X Z^4`. """ #***************************************************************************** @@ -128,8 +128,8 @@ def _biquadratic_syzygy_quartic(quadratic1, quadratic2, variables=None): The invariants and covariants of a quaternary biquadratic satisfy the relation :meth:`sage.rings.invariant_theory.TwoQuaternaryQuadratics.syzygy`, - which is (modulo the two quadratic equations) of the form $J^2 = - p_4(T, T')$ where + which is (modulo the two quadratic equations) of the form `J^2 = + p_4(T, T')` where * `J`, `T`, `T'` are the covariants of the biquadratic. From a5adc4806f97d46facb88dfb572e17511d0e7a2c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 14:56:13 -0700 Subject: [PATCH 086/116] sage.plot: Replace $...$ in docstrings by `...` --- src/sage/plot/line.py | 2 +- src/sage/plot/plot3d/transform.pyx | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/sage/plot/line.py b/src/sage/plot/line.py index 511f9640943..e4b3b4ddc82 100644 --- a/src/sage/plot/line.py +++ b/src/sage/plot/line.py @@ -200,7 +200,7 @@ def __setitem__(self, i, point): EXAMPLES: - We create a line graphics object $L$ and get ahold of the + We create a line graphics object ``L`` and get ahold of the corresponding line graphics primitive:: sage: L = line([(1,2), (3,-4), (2, 5), (1,2)]) diff --git a/src/sage/plot/plot3d/transform.pyx b/src/sage/plot/plot3d/transform.pyx index aba8fa69598..7e91d30823b 100644 --- a/src/sage/plot/plot3d/transform.pyx +++ b/src/sage/plot/plot3d/transform.pyx @@ -199,25 +199,25 @@ def rotate_arbitrary(v, double theta): sage: def rotX(theta): return matrix(SR, 3, 3, [1, 0, 0, 0, cos(theta), -sin(theta), 0, sin(theta), cos(theta)]) sage: def rotZ(theta): return matrix(SR, 3, 3, [cos(theta), -sin(theta), 0, sin(theta), cos(theta), 0, 0, 0, 1]) - Normalizing $y$ so that $|v|=1$. Perhaps there is a better - way to tell Maxima that $x^2+y^2+z^2=1$ which would make for + Normalizing `y` so that `|v|=1`. Perhaps there is a better + 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) - Now we rotate about the $x$-axis so $v$ is in the $xy$-plane:: + 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) - And rotate about the $z$ axis so $v$ lies on the $x$ axis:: + 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 - Rotating about $v$ in our old system is the same as rotating - about the $x$-axis in the new:: + Rotating about `v` in our old system is the same as rotating + about the `x`-axis in the new:: sage: m = rotX(theta) * m From eb98d68fc7f3f0ff47a61ff0c4ee8a0fd6cea941 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 14:56:25 -0700 Subject: [PATCH 087/116] sage.sets: Replace $...$ in docstrings by `...` --- src/sage/sets/real_set.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/sets/real_set.py b/src/sage/sets/real_set.py index 0cf6f27fc28..ce849c612e2 100644 --- a/src/sage/sets/real_set.py +++ b/src/sage/sets/real_set.py @@ -1350,7 +1350,7 @@ def get_interval(self, i): OUTPUT: - The $i$-th connected component as a :class:`RealInterval`. + The ``i``-th connected component as a :class:`RealInterval`. EXAMPLES:: From 8ff93695bf341c8aff86ecff3eb25476b84dc96c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 14:58:10 -0700 Subject: [PATCH 088/116] sage.modules: Replace $...$ in docstrings by `...` --- src/sage/modules/filtered_vector_space.py | 8 ++++---- src/sage/modules/multi_filtered_vector_space.py | 8 ++++---- src/sage/modules/tensor_operations.py | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/sage/modules/filtered_vector_space.py b/src/sage/modules/filtered_vector_space.py index dd5784041eb..b56a64e111a 100644 --- a/src/sage/modules/filtered_vector_space.py +++ b/src/sage/modules/filtered_vector_space.py @@ -544,8 +544,8 @@ def is_exhaustive(self): r""" Return whether the filtration is exhaustive. - A filtration $\{F_d\}$ in an ambient vector space $V$ is - exhaustive if $\cup F_d = V$. See also :meth:`is_separating`. + A filtration `\{F_d\}` in an ambient vector space `V` is + exhaustive if `\cup F_d = V`. See also :meth:`is_separating`. OUTPUT: @@ -569,8 +569,8 @@ def is_separating(self): r""" Return whether the filtration is separating. - A filtration $\{F_d\}$ in an ambient vector space $V$ is - exhaustive if $\cap F_d = 0$. See also :meth:`is_exhaustive`. + A filtration `\{F_d\}` in an ambient vector space `V` is + exhaustive if `\cap F_d = 0`. See also :meth:`is_exhaustive`. OUTPUT: diff --git a/src/sage/modules/multi_filtered_vector_space.py b/src/sage/modules/multi_filtered_vector_space.py index 61e4754452e..18d87cc1197 100644 --- a/src/sage/modules/multi_filtered_vector_space.py +++ b/src/sage/modules/multi_filtered_vector_space.py @@ -238,8 +238,8 @@ def is_exhaustive(self): r""" Return whether the multi-filtration is exhaustive. - A filtration $\{F_d\}$ in an ambient vector space $V$ is - exhaustive if $\cup F_d = V$. See also :meth:`is_separating`. + A filtration `\{F_d\}` in an ambient vector space `V` is + exhaustive if `\cup F_d = V`. See also :meth:`is_separating`. OUTPUT: @@ -260,8 +260,8 @@ def is_separating(self): r""" Return whether the multi-filtration is separating. - A filtration $\{F_d\}$ in an ambient vector space $V$ is - exhaustive if $\cap F_d = 0$. See also :meth:`is_exhaustive`. + A filtration `\{F_d\}` in an ambient vector space `V` is + exhaustive if `\cap F_d = 0`. See also :meth:`is_exhaustive`. OUTPUT: diff --git a/src/sage/modules/tensor_operations.py b/src/sage/modules/tensor_operations.py index ce3bd555434..d6f2144a61d 100644 --- a/src/sage/modules/tensor_operations.py +++ b/src/sage/modules/tensor_operations.py @@ -25,7 +25,7 @@ (1, -1) In a convenient choice of basis, the tensor product is -$(a,b)\otimes(c,d)=(ac,ad,bc,bd)$. In this example, it is one of the +`(a,b)\otimes(c,d)=(ac,ad,bc,bd)`. In this example, it is one of the vectors of the vector collection ``VW`` :: sage: VW.index_map(0, 1) @@ -308,9 +308,9 @@ def _init_product_vectors(self, i): INPUT: - `i` -- list/tuple of integers. Multi-index of length equal - to the number of constituent vector collections. The $j$-th - entry $i[j]$ indexes a ray in the $j$-th vector - collection. Hence, $i$ specifies one element in each vector + to the number of constituent vector collections. The `j`-th + entry `i[j]` indexes a ray in the `j`-th vector + collection. Hence, `i` specifies one element in each vector collection. OUTPUT: @@ -326,7 +326,7 @@ def _init_product_vectors(self, i): .. NOTE:: In a convenient choice of coordinates the tensor product - of, say, two vectors $(a,b)$ and $(c,d)$, is $(ac, ad, bc, + of, say, two vectors `(a,b)` and `(c,d)`, is `(ac, ad, bc, bd)$. EXAMPLES:: @@ -370,7 +370,7 @@ def _init_power_operation_vectors(self, i, linear_combinations): :meth:`_init_product_vector`. - ``linear_combination`` -- formal linear combination of - vector indices in the vectors specified by $i$. + vector indices in the vectors specified by `i`. EXAMPLES:: From 47b9894fcf30327a57b5ad4649b572d278070806 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 14:59:54 -0700 Subject: [PATCH 089/116] src/sage/probability/probability_distribution.pyx: Fix math markup --- src/sage/probability/probability_distribution.pyx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sage/probability/probability_distribution.pyx b/src/sage/probability/probability_distribution.pyx index 22fcc0c0090..a76518b7969 100644 --- a/src/sage/probability/probability_distribution.pyx +++ b/src/sage/probability/probability_distribution.pyx @@ -986,7 +986,7 @@ cdef class GeneralDiscreteDistribution(ProbabilityDistribution): EXAMPLES: Constructs a ``GeneralDiscreteDistribution`` with the probability - distribution `$P$` where `$P(0) = 0.3$`, `$P(1) = 0.4$`, `$P(2) = 0.3$`:: + distribution `P` where `P(0) = 0.3`, `P(1) = 0.4`, `P(2) = 0.3`:: sage: P = [0.3, 0.4, 0.3] sage: X = GeneralDiscreteDistribution(P) @@ -1004,7 +1004,6 @@ cdef class GeneralDiscreteDistribution(ProbabilityDistribution): sage: [1.0*x/nr_samples for x in counts] # abs tol 3e-2 [0.3, 0.4, 0.3] - The distribution probabilities will automatically be normalised:: sage: P = [0.1, 0.3] From 089d6fb57d7a527a5bf0789dab742b500edb7f1a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 15:02:46 -0700 Subject: [PATCH 090/116] sage.modular: Replace $...$ in docstrings by `...` --- src/sage/modular/abvar/abvar.py | 6 +++--- src/sage/modular/arithgroup/congroup.pyx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/modular/abvar/abvar.py b/src/sage/modular/abvar/abvar.py index c0834b3b804..80467d9b5b0 100644 --- a/src/sage/modular/abvar/abvar.py +++ b/src/sage/modular/abvar/abvar.py @@ -2871,9 +2871,9 @@ def _ambient_cuspidal_subgroup(self, rational_only=False, rational_subgroup=Fals def shimura_subgroup(self): r""" Return the Shimura subgroup of this modular abelian variety. This is - the kernel of $J_0(N) \rightarrow J_1(N)$ under the natural map. + the kernel of `J_0(N) \rightarrow J_1(N)` under the natural map. Here we compute the Shimura subgroup as the kernel of - $J_0(N) \rightarrow J_0(Np)$ where the map is the difference between the + `J_0(N) \rightarrow J_0(Np)` where the map is the difference between the two degeneracy maps. EXAMPLES:: @@ -3623,7 +3623,7 @@ def _isogeny_to_product_of_powers(self): `\phi: A \rightarrow B_1 \times \cdots \times B_n`, where each `B_i` is a power of a simple abelian variety. These factors will be exactly those returned by - self.decomposition(simple=False).Note that this isogeny is not + ``self.decomposition(simple=False)``. Note that this isogeny is not unique. EXAMPLES:: diff --git a/src/sage/modular/arithgroup/congroup.pyx b/src/sage/modular/arithgroup/congroup.pyx index 3cb2a84b334..1f20ebfb478 100644 --- a/src/sage/modular/arithgroup/congroup.pyx +++ b/src/sage/modular/arithgroup/congroup.pyx @@ -70,7 +70,7 @@ def degeneracy_coset_representatives_gamma0(int N, int M, int t): ALGORITHM: - 1. Compute representatives for $\Gamma_0(N/t,t)$ inside of $\Gamma_0(M)$: + 1. Compute representatives for `\Gamma_0(N/t,t)` inside of `\Gamma_0(M)`: + COSET EQUIVALENCE: Two right cosets represented by `[a,b;c,d]` and `[a',b';c',d']` of `\Gamma_0(N/t,t)` in `\SL_2(\ZZ)` are equivalent if From b18479b647983ddb2a1467eb828063076a238618 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 15:05:12 -0700 Subject: [PATCH 091/116] src/sage/interfaces/qepcad.py: Replace $...$ in docstrings by `...` --- src/sage/interfaces/qepcad.py | 122 +++++++++++++++++----------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py index c2e6c00ec48..e83f5dedeeb 100644 --- a/src/sage/interfaces/qepcad.py +++ b/src/sage/interfaces/qepcad.py @@ -3,31 +3,31 @@ =================== The basic function of QEPCAD is to construct cylindrical algebraic -decompositions (CADs) of $\RR^k$, given a list of polynomials. Using +decompositions (CADs) of `\RR^k`, given a list of polynomials. Using this CAD, it is possible to perform quantifier elimination and formula simplification. -A CAD for a set $A$ of $k$-variate polynomials decomposes $\RR^j$ into -disjoint cells, for each $j$ in $0 \leq j \leq k$. The sign of each -polynomial in $A$ is constant in each cell of $\RR^k$, and for each -cell in $\RR^j$ ($j > 1$), the projection of that cell into -$\RR^{j-1}$ is a cell of $\RR^{j-1}$. (This property makes the +A CAD for a set `A` of `k`-variate polynomials decomposes `\RR^j` into +disjoint cells, for each `j` in `0 \leq j \leq k`. The sign of each +polynomial in `A` is constant in each cell of `\RR^k`, and for each +cell in `\RR^j` (`j > 1`), the projection of that cell into +`\RR^{j-1}` is a cell of `\RR^{j-1}`. (This property makes the decomposition 'cylindrical'.) -Given a formula $\exists x. P(a,b,x) = 0$ (for a polynomial $P$), and -a cylindrical algebraic decomposition for $P$, we can eliminate the -quantifier (find an equivalent formula in the two variables $a$, $b$ -without the quantifier $\exists$) as follows. For each cell $C$ in -$\RR^2$, find the cells of $\RR^3$ which project to $C$. (This -collection is called the ``stack`` over $C$.) Mark $C$ as true if -some member of the stack has sign $= 0$; otherwise, mark $C$ as false. -Then, construct a polynomial formula in $a$, $b$ which specifies +Given a formula `\exists x. P(a,b,x) = 0` (for a polynomial `P`), and +a cylindrical algebraic decomposition for `P`, we can eliminate the +quantifier (find an equivalent formula in the two variables `a`, `b` +without the quantifier `\exists`) as follows. For each cell `C` in +`\RR^2`, find the cells of `\RR^3` which project to `C`. (This +collection is called the ``stack`` over `C`.) Mark `C` as true if +some member of the stack has sign `= 0`; otherwise, mark `C` as false. +Then, construct a polynomial formula in `a`, `b` which specifies exactly the true cells (this is always possible). The same technique works if the body of the quantifier is any boolean combination of polynomial equalities and inequalities. Formula simplification is a similar technique. Given a formula which -describes a simple set of $\RR^k$ in a complicated way as a boolean +describes a simple set of `\RR^k` in a complicated way as a boolean combination of polynomial equalities and inequalities, QEPCAD can construct a CAD for the polynomials and recover a simple equivalent formula. @@ -64,7 +64,7 @@ sage: ellipse = 3*x^2 + 2*x*y + y^2 - x + y - 7 -What is the projection onto the $x$ axis of this ellipse? First we +What is the projection onto the `x` axis of this ellipse? First we construct a formula asking this question. :: sage: F = qf.exists(y, ellipse == 0); F @@ -75,7 +75,7 @@ sage: qepcad(F) # optional - qepcad 8 x^2 - 8 x - 29 <= 0 -How about the projection onto the $y$ axis? :: +How about the projection onto the `y` axis? :: sage: qepcad(qf.exists(x, ellipse == 0)) # optional - qepcad 8 y^2 + 16 y - 85 <= 0 @@ -90,7 +90,7 @@ sage: circle = x^2 + y^2 - 3 -For what values $k$ does a vertical line $x=k$ intersect the combined +For what values `k` does a vertical line `x=k` intersect the combined figure of the circle and ellipse exactly three times? :: sage: F = qf.exactly_k(3, y, circle * ellipse == 0); F @@ -98,7 +98,7 @@ sage: qepcad(F) # not tested (random order) x^2 - 3 <= 0 /\ 8 x^2 - 8 x - 29 <= 0 /\ 8 x^4 - 26 x^2 - 4 x + 13 >= 0 /\ [ 8 x^4 - 26 x^2 - 4 x + 13 = 0 \/ x^2 - 3 = 0 \/ 8 x^2 - 8 x - 29 = 0 ] -Here we see that the solutions are among the eight ($4 + 2 + 2$) roots +Here we see that the solutions are among the eight (`4 + 2 + 2`) roots of the three polynomials inside the brackets, but not all of these roots are solutions; the polynomial inequalities outside the brackets are needed to select those roots that are solutions. @@ -168,7 +168,7 @@ There is another reason to prefer output using _root_ expressions; not only does it sometimes give added insight into the geometric structure, it also can be more efficient to construct. Consider this -formula for the projection of a particular semicircle onto the $x$ +formula for the projection of a particular semicircle onto the `x` axis:: sage: F = qf.exists(y, qf.and_(circle == 0, x + y > 0)); F @@ -176,9 +176,9 @@ sage: qepcad(F) # not tested (random order) x^2 - 3 <= 0 /\ [ x > 0 \/ 2 x^2 - 3 < 0 ] -Here, the formula $x > 0$ had to be introduced in order to get a +Here, the formula `x > 0` had to be introduced in order to get a solution formula; the original CAD of F did not include the -polynomial $x$. To avoid having QEPCAD do the extra work to come up +polynomial `x`. To avoid having QEPCAD do the extra work to come up with a solution formula, we can tell it to use the extended language; it is always possible to construct a solution formula in the extended language without introducing new polynomials. :: @@ -251,7 +251,7 @@ sage: pts = qepcad(F, solution='all-points'); pts # optional - qepcad [{'x': 1.732050807568878?}, {'x': 1.731054913462534?}, {'x': 0.678911384208004?}, {'x': -0.9417727377417167?}, {'x': -1.468193559928821?}, {'x': -1.468501968502953?}] -Since $y$ is bound by the quantifier, the solutions only refer to $x$. +Since `y` is bound by the quantifier, the solutions only refer to `x`. We can substitute one of these solutions into the original equation:: @@ -339,19 +339,19 @@ We said before that QEPCAD creates 'cylindrical algebraic decompositions'; since we have a bivariate polynomial, we get -decompositions of $\RR^0$, $\RR^1$, and $\RR^2$. In this case, where -our example is a circle of radius $\sqrt{3}$ centered on the origin, +decompositions of `\RR^0`, `\RR^1`, and `\RR^2`. In this case, where +our example is a circle of radius `\sqrt{3}` centered on the origin, these decompositions are as follows: -The decomposition of $\RR^0$ is trivial (of course). The -decomposition of $\RR^1$ has five cells: $x < -\sqrt{3}$, $x = --\sqrt{3}$, $-\sqrt{3} < x < \sqrt{3}$, $x = \sqrt{3}$, and $x > -\sqrt{3}$. These five cells comprise the ``stack`` over the single -cell in the trivial decomposition of $\RR^0$. +The decomposition of `\RR^0` is trivial (of course). The +decomposition of `\RR^1` has five cells: `x < -\sqrt{3}`, `x = +-\sqrt{3}`, `-\sqrt{3} < x < \sqrt{3}`, `x = \sqrt{3}`, and `x > +\sqrt{3}`. These five cells comprise the ``stack`` over the single +cell in the trivial decomposition of `\RR^0`. -These five cells give rise to five stacks in $\RR^2$. The first and +These five cells give rise to five stacks in `\RR^2`. The first and fifth stack have just one cell apiece. The second and fourth stacks -have three cells: $y < 0$, $y = 0$, and $y > 0$. The third stack has +have three cells: `y < 0`, `y = 0`, and `y > 0`. The third stack has five cells: below the circle, the lower semicircle, the interior of the circle, the upper semicircle, and above the circle. @@ -359,7 +359,7 @@ starting with 1. Each cell has an ``index``, which is a tuple of integers describing the path to the cell in the tree of all cells. For example, the cell 'below the circle' has index (3,1) (the first -cell in the stack over the third cell of $\RR^1$) and the interior of +cell in the stack over the third cell of `\RR^1`) and the interior of the circle has index (3,3). We can view these cells with the QEPCAD command ``d_cell``. For @@ -389,7 +389,7 @@ ---------------------------------------------------- We see that, the level of this cell is 2, meaning that it is part of -the decomposition of $\RR^2$. The dimension is 1, meaning that the +the decomposition of `\RR^2`. The dimension is 1, meaning that the cell is homeomorphic to a line (rather than a plane or a point). The sample point gives the coordinates of one point in the cell, both symbolically and numerically. @@ -482,8 +482,8 @@ QEPCAD object has moved to phase 'Before Choice' QEPCAD object has moved to phase 'Before Solution' -Now we want to find all cells $c$ in the decomposition of $\RR^1$ such -that the stack over $c$ contains exactly two cells on the ellipse, and +Now we want to find all cells `c` in the decomposition of `\RR^1` such +that the stack over `c` contains exactly two cells on the ellipse, and also contains exactly two cells on the circle. Our input polynomials are 'level-2 projection factors', we see:: @@ -792,7 +792,7 @@ def __init__(self, formula, Requires a formula, which may be a :class:`qformula` as returned by the methods of ``qepcad_formula``, a symbolic equality or inequality, a - polynomial $p$ (meaning $p = 0$), or a string, which is passed + polynomial `p` (meaning `p = 0`), or a string, which is passed straight to QEPCAD. ``vars`` specifies the variables to use; this gives the variable @@ -1470,7 +1470,7 @@ def qepcad(formula, assume=None, interact=False, solution=None, sage: qepcad(qf.exists(x, a*x^2 + b*x + c == 0), assume=(a != 0)) # optional - qepcad 4 a c - b^2 <= 0 - For which values of $a$, $b$, $c$ does $a x^2 + b x + c$ have + For which values of `a`, `b`, `c` does `a x^2 + b x + c` have 2 real zeroes? :: sage: exact2 = qepcad(qf.exactly_k(2, x, a*x^2 + b*x + c == 0)); exact2 # not tested (random order) @@ -1486,7 +1486,7 @@ def qepcad(formula, assume=None, interact=False, solution=None, sage: exact0 = qepcad(qf.forall(x, a*x^2 + b*x + c != 0)); exact0 # not tested (random order) 4 a c - b^2 >= 0 /\ c /= 0 /\ [ b = 0 \/ 4 a c - b^2 > 0 ] - $3^{75}$ real zeroes? :: + `3^{75}` real zeroes? :: sage: qepcad(qf.exactly_k(3^75, x, a*x^2 + b*x + c == 0)) # optional - qepcad FALSE @@ -1505,7 +1505,7 @@ def qepcad(formula, assume=None, interact=False, solution=None, sage: qepcad(r'[[%s] \/ [%s] \/ [%s]]' % (exact0, exact1, exact2), vars=(a,b,c)) # not tested (random order) b /= 0 \/ a /= 0 \/ c /= 0 - So we have finitely many zeroes if $a$, $b$, or $c$ is nonzero; + So we have finitely many zeroes if `a`, `b`, or `c` is nonzero; which means we should have infinitely many zeroes if they are all zero. :: @@ -1532,7 +1532,7 @@ def qepcad(formula, assume=None, interact=False, solution=None, sage: qepcad(r'[[%s] \/ [%s] \/ [a = 0 /\ b = 0 /\ c = 0]]' % (exact0, exact1), vars='a,b,c') # not tested (random order) a = 0 \/ 4 a c - b^2 >= 0 - Since polynomials are continuous and $y > 0$ is an open set, + Since polynomials are continuous and `y > 0` is an open set, they are positive infinitely often iff they are positive at least once. :: @@ -1541,9 +1541,9 @@ def qepcad(formula, assume=None, interact=False, solution=None, sage: qepcad(qf.exists(x, a*x^2 + b*x + c > 0)) # not tested (random order) c > 0 \/ a > 0 \/ 4 a c - b^2 < 0 - However, since $y >= 0$ is not open, the equivalence does not + However, since `y >= 0` is not open, the equivalence does not hold if you replace 'positive' with 'nonnegative'. - (We assume $a \neq 0$ to get simpler formulas.) :: + (We assume `a \neq 0` to get simpler formulas.) :: sage: qepcad(qf.infinitely_many(x, a*x^2 + b*x + c >= 0), assume=(a != 0)) # not tested (random order) a > 0 \/ 4 a c - b^2 < 0 @@ -1944,7 +1944,7 @@ def formula(self, formula): - ``formula`` -- a polynomial, a symbolic equality or inequality, or a list of polynomials, equalities, or inequalities - A polynomial $p$ is interpreted as the equation $p = 0$. + A polynomial `p` is interpreted as the equation `p = 0`. A list is interpreted as the conjunction ('and') of the elements. EXAMPLES:: @@ -1971,7 +1971,7 @@ def and_(self, *formulas): Each input formula may be a :class:`qformula` as returned by the methods of ``qepcad_formula``, a symbolic equality or - inequality, or a polynomial $p$ (meaning $p = 0$). + inequality, or a polynomial `p` (meaning `p = 0`). EXAMPLES:: @@ -1997,7 +1997,7 @@ def or_(self, *formulas): Each input formula may be a :class:`qformula` as returned by the methods of ``qepcad_formula``, a symbolic equality or - inequality, or a polynomial $p$ (meaning $p = 0$). + inequality, or a polynomial `p` (meaning `p = 0`). EXAMPLES:: @@ -2023,7 +2023,7 @@ def not_(self, formula): The input formula may be a :class:`qformula` as returned by the methods of ``qepcad_formula``, a symbolic equality or - inequality, or a polynomial $p$ (meaning $p = 0$). + inequality, or a polynomial `p` (meaning `p = 0`). EXAMPLES:: @@ -2044,11 +2044,11 @@ def not_(self, formula): def implies(self, f1, f2): r""" Return the implication of its input formulas (that is, given - formulas $P$ and $Q$, returns '$P$ implies $Q$'). + formulas `P` and `Q`, returns '`P` implies `Q`'). The input formulas may be a :class:`qformula` as returned by the methods of ``qepcad_formula``, a symbolic equality or - inequality, or a polynomial $p$ (meaning $p = 0$). + inequality, or a polynomial `p` (meaning `p = 0`). EXAMPLES:: @@ -2070,11 +2070,11 @@ def implies(self, f1, f2): def iff(self, f1, f2): r""" Return the equivalence of its input formulas (that is, given - formulas $P$ and $Q$, returns '$P$ iff $Q$'). + formulas `P` and `Q`, returns '`P` iff `Q`'). The input formulas may be a :class:`qformula` as returned by the methods of ``qepcad_formula``, a symbolic equality or - inequality, or a polynomial $p$ (meaning $p = 0$). + inequality, or a polynomial `p` (meaning `p = 0`). EXAMPLES:: @@ -2100,7 +2100,7 @@ def exists(self, v, formula): The input formula may be a :class:`qformula` as returned by the methods of ``qepcad_formula``, a symbolic equality or - inequality, or a polynomial $p$ (meaning $p = 0$). + inequality, or a polynomial `p` (meaning `p = 0`). EXAMPLES:: @@ -2127,7 +2127,7 @@ def forall(self, v, formula): The input formula may be a :class:`qformula` as returned by the methods of ``qepcad_formula``, a symbolic equality or - inequality, or a polynomial $p$ (meaning $p = 0$). + inequality, or a polynomial `p` (meaning `p = 0`). EXAMPLES:: @@ -2155,7 +2155,7 @@ def infinitely_many(self, v, formula): The input formula may be a :class:`qformula` as returned by the methods of ``qepcad_formula``, a symbolic equality or - inequality, or a polynomial $p$ (meaning $p = 0$). + inequality, or a polynomial `p` (meaning `p = 0`). EXAMPLES:: @@ -2181,7 +2181,7 @@ def all_but_finitely_many(self, v, formula): The input formula may be a :class:`qformula` as returned by the methods of ``qepcad_formula``, a symbolic equality or - inequality, or a polynomial $p$ (meaning $p = 0$). + inequality, or a polynomial `p` (meaning `p = 0`). EXAMPLES:: @@ -2208,7 +2208,7 @@ def connected_subset(self, v, formula, allow_multi=False): The input formula may be a :class:`qformula` as returned by the methods of ``qepcad_formula``, a symbolic equality or - inequality, or a polynomial $p$ (meaning $p = 0$). + inequality, or a polynomial `p` (meaning `p = 0`). EXAMPLES:: @@ -2225,20 +2225,20 @@ def connected_subset(self, v, formula, allow_multi=False): def exactly_k(self, k, v, formula, allow_multi=False): r""" - Given a nonnegative integer $k$, a variable, and a formula, + Given a nonnegative integer `k`, a variable, and a formula, returns a new formula which is true iff the original formula - is true for exactly $k$ values of the variable. + is true for exactly `k` values of the variable. This method is available both as :meth:`exactly_k` and :meth:`X` (the QEPCAD name for this quantifier). - (Note that QEPCAD does not support $k=0$ with this syntax, so if - $k=0$ is requested we implement it with :meth:`forall` and + (Note that QEPCAD does not support `k=0` with this syntax, so if + `k=0` is requested we implement it with :meth:`forall` and :meth:`not_`.) The input formula may be a :class:`qformula` as returned by the methods of ``qepcad_formula``, a symbolic equality or - inequality, or a polynomial $p$ (meaning $p = 0$). + inequality, or a polynomial `p` (meaning `p = 0`). EXAMPLES:: From 65d1b6832d96cea235caf0670e4b0d4336991fdf Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 15:06:11 -0700 Subject: [PATCH 092/116] src/sage/interfaces/r.py: Replace $...$ in docstrings by `...` --- src/sage/interfaces/r.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/interfaces/r.py b/src/sage/interfaces/r.py index 1e0d6ff73b1..6b1f601b563 100644 --- a/src/sage/interfaces/r.py +++ b/src/sage/interfaces/r.py @@ -22,7 +22,7 @@ The simplest data structure in R is the numeric vector which consists of an ordered collection of numbers. To create a -vector named $x$ using the R interface in Sage, you pass the +vector named `x` using the R interface in Sage, you pass the R interpreter object a list or tuple of numbers:: sage: x = r([10.4,5.6,3.1,6.4,21.7]); x # optional - rpy2 @@ -36,16 +36,16 @@ sage: 1/x # optional - rpy2 [1] 0.09615385 0.17857143 0.32258065 0.15625000 0.04608295 -The following assignment creates a vector $y$ with 11 entries which -consists of two copies of $x$ with a 0 in between:: +The following assignment creates a vector `y` with 11 entries which +consists of two copies of `x` with a 0 in between:: sage: y = r([x,0,x]); y # optional - rpy2 [1] 10.4 5.6 3.1 6.4 21.7 0.0 10.4 5.6 3.1 6.4 21.7 Vector Arithmetic -The following command generates a new vector $v$ of length 11 constructed -by adding together (element by element) $2x$ repeated 2.2 times, $y$ +The following command generates a new vector `v` of length 11 constructed +by adding together (element by element) `2x` repeated 2.2 times, `y` repeated just once, and 1 repeated 11 times:: sage: v = 2*x+y+1; v # optional - rpy2 From 91885fafc48cd4c7fdc9a4b8a11889b63f645284 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 15:08:16 -0700 Subject: [PATCH 093/116] src/sage/lfunctions/zero_sums.pyx: Replace $...$ in docstrings by `...` --- src/sage/lfunctions/zero_sums.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/lfunctions/zero_sums.pyx b/src/sage/lfunctions/zero_sums.pyx index 4a71c1e84eb..a67ad9d8ebb 100644 --- a/src/sage/lfunctions/zero_sums.pyx +++ b/src/sage/lfunctions/zero_sums.pyx @@ -1002,7 +1002,7 @@ cdef class LFunctionZeroSum_EllipticCurve(LFunctionZeroSum_abstract): The returned value is zero if `n` is not a perfect prime power; when `n=p^e` for `p` a prime of bad reduction it is `-a_p^e log(p)/p^e`, - where `a_p` is `+1, -1` or `0` according to the reduction type of $p$; + where `a_p` is `+1, -1` or `0` according to the reduction type of `p`; and when `n=p^e` for a prime `p` of good reduction, the value is `-(\alpha_p^e + \beta_p^e) \log(p)/p^e`, where `\alpha_p` and `\beta_p` are the two complex roots of the characteristic equation From ce9e3647b7805f178cedb866ec2f5edf0a02f3fd Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 15:10:15 -0700 Subject: [PATCH 094/116] src/sage/manifolds/differentiable/examples/euclidean.py: Replace $...$ in docstrings by `...` --- src/sage/manifolds/differentiable/examples/euclidean.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/manifolds/differentiable/examples/euclidean.py b/src/sage/manifolds/differentiable/examples/euclidean.py index d508003d301..8b3cb23531d 100644 --- a/src/sage/manifolds/differentiable/examples/euclidean.py +++ b/src/sage/manifolds/differentiable/examples/euclidean.py @@ -2480,7 +2480,7 @@ def scalar_triple_product(self, name=None, latex_name=None): \epsilon(u,v,w) = u \cdot (v \times w). - The scalar triple product operator $\epsilon$ is a *3-form*, i.e. a + The scalar triple product operator `\epsilon` is a *3-form*, i.e. a field of fully antisymmetric trilinear forms; it is also called the *volume form* of `E` or the *Levi-Civita tensor* of `E`. @@ -2494,7 +2494,7 @@ def scalar_triple_product(self, name=None, latex_name=None): OUTPUT: - - the scalar triple product operator $\epsilon$, as an instance of + - the scalar triple product operator `\epsilon`, as an instance of :class:`~sage.manifolds.differentiable.diff_form.DiffFormParal` EXAMPLES:: From 53d36469831f0ad0460b0a5e0f824ab6b2ba8d54 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 15:11:26 -0700 Subject: [PATCH 095/116] sage.quadratic_forms: Replace $...$ in docstrings by `...` --- src/sage/quadratic_forms/genera/normal_form.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/quadratic_forms/genera/normal_form.py b/src/sage/quadratic_forms/genera/normal_form.py index 51bf5a64b45..4744e3d079e 100644 --- a/src/sage/quadratic_forms/genera/normal_form.py +++ b/src/sage/quadratic_forms/genera/normal_form.py @@ -159,7 +159,7 @@ def p_adic_normal_form(G, p, precision=None, partial=False, debug=False): [1 2] For `p=2` the partial normal form is a block diagonal matrix with blocks - `2^k G_k` such that $G_k$ is a block diagonal matrix of the form + `2^k G_k` such that `G_k` is a block diagonal matrix of the form `[U`, ... , `U`, `V`, `Wa`, `Wb]` where we allow `V`, `Wa`, `Wb` to be `0 \times 0` matrices. From b72f0f9458bef5cd6fb3d632596374bd7b304d20 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jun 2022 15:19:34 -0700 Subject: [PATCH 096/116] sage.libs: Replace $...$ in docstrings by `...` --- src/sage/libs/eclib/homspace.pyx | 2 +- src/sage/libs/eclib/newforms.pyx | 6 +++--- src/sage/libs/flint/fmpz_poly.pyx | 4 ++-- src/sage/libs/ntl/ntl_GF2X.pyx | 4 ++-- src/sage/libs/ntl/ntl_ZZX.pyx | 24 ++++++++++++------------ src/sage/libs/ntl/ntl_ZZ_p.pyx | 6 +++--- src/sage/libs/ntl/ntl_ZZ_pE.pyx | 6 +++--- src/sage/libs/ntl/ntl_ZZ_pEX.pyx | 10 +++++----- src/sage/libs/ntl/ntl_lzz_p.pyx | 2 +- src/sage/libs/ntl/ntl_lzz_pX.pyx | 14 +++++++------- src/sage/libs/ntl/ntl_mat_GF2.pyx | 8 ++++---- src/sage/libs/ntl/ntl_mat_GF2E.pyx | 4 ++-- src/sage/libs/ntl/ntl_mat_ZZ.pyx | 20 ++++++++++---------- src/sage/libs/symmetrica/sb.pxi | 4 ++-- 14 files changed, 57 insertions(+), 57 deletions(-) diff --git a/src/sage/libs/eclib/homspace.pyx b/src/sage/libs/eclib/homspace.pyx index 5f284139363..9868795ab20 100644 --- a/src/sage/libs/eclib/homspace.pyx +++ b/src/sage/libs/eclib/homspace.pyx @@ -108,7 +108,7 @@ cdef class ModularSymbols: def number_of_cusps(self): r""" - Return the number of cusps for $\Gamma_0(N)$, where $N$ is the + Return the number of cusps for `\Gamma_0(N)`, where `N` is the level. EXAMPLES:: diff --git a/src/sage/libs/eclib/newforms.pyx b/src/sage/libs/eclib/newforms.pyx index 82364945a0d..d30ac0e3758 100644 --- a/src/sage/libs/eclib/newforms.pyx +++ b/src/sage/libs/eclib/newforms.pyx @@ -32,18 +32,18 @@ cdef class ECModularSymbol: sage: M = ECModularSymbol(E,1); M Modular symbol with sign 1 over Rational Field attached to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field - By default, symbols are based at the cusp $\infty$, i.e. we evaluate $\{\infty,r\}$:: + By default, symbols are based at the cusp `\infty`, i.e. we evaluate `\{\infty,r\}`:: sage: [M(1/i) for i in range(1,11)] [2/5, -8/5, -3/5, 7/5, 12/5, 12/5, 7/5, -3/5, -8/5, 2/5] - We can also switch the base point to the cusp $0$:: + We can also switch the base point to the cusp `0`:: sage: [M(1/i, base_at_infinity=False) for i in range(1,11)] [0, -2, -1, 1, 2, 2, 1, -1, -2, 0] For the minus symbols this makes no difference since - $\{0,\infty\}$ is in the plus space. Note that to evaluate minus + `\{0,\infty\}` is in the plus space. Note that to evaluate minus symbols the space must be defined with sign 0, which makes both signs available:: diff --git a/src/sage/libs/flint/fmpz_poly.pyx b/src/sage/libs/flint/fmpz_poly.pyx index ba7f81d7143..d894478ba60 100644 --- a/src/sage/libs/flint/fmpz_poly.pyx +++ b/src/sage/libs/flint/fmpz_poly.pyx @@ -74,7 +74,7 @@ cdef class Fmpz_poly(SageObject): def __setitem__(self, i, value): """ - Set the $i$-th item of self, which is the coefficient of the $x^i$ term. + Set the `i`-th item of self, which is the coefficient of the `x^i` term. EXAMPLES:: @@ -93,7 +93,7 @@ cdef class Fmpz_poly(SageObject): def __getitem__(self, i): """ - Return the $i$-th item of self, which is the coefficient of the $x^i$ term. + Return the `i`-th item of self, which is the coefficient of the `x^i` term. EXAMPLES:: diff --git a/src/sage/libs/ntl/ntl_GF2X.pyx b/src/sage/libs/ntl/ntl_GF2X.pyx index 8aa4c43d348..101f36bb895 100644 --- a/src/sage/libs/ntl/ntl_GF2X.pyx +++ b/src/sage/libs/ntl/ntl_GF2X.pyx @@ -368,7 +368,7 @@ cdef class ntl_GF2X(object): def __lshift__(ntl_GF2X self, int i): """ Return left shift of self by i bits ( == multiplication by - $X^i$). + `X^i`). INPUT: i -- offset/power of X @@ -387,7 +387,7 @@ cdef class ntl_GF2X(object): def __rshift__(ntl_GF2X self, int offset): """ Return right shift of self by i bits ( == floor division by - $X^i$). + `X^i`). INPUT: i -- offset/power of X diff --git a/src/sage/libs/ntl/ntl_ZZX.pyx b/src/sage/libs/ntl/ntl_ZZX.pyx index 8c596bd23a6..7f4d7a6366d 100644 --- a/src/sage/libs/ntl/ntl_ZZX.pyx +++ b/src/sage/libs/ntl/ntl_ZZX.pyx @@ -81,7 +81,7 @@ cdef proof_flag(t): cdef class ntl_ZZX(object): r""" - The class \class{ZZX} implements polynomials in $\Z[X]$, i.e., + The class \class{ZZX} implements polynomials in `\Z[X]`, i.e., univariate polynomials with integer coefficients. Polynomial multiplication is very fast, and is implemented using @@ -703,11 +703,11 @@ cdef class ntl_ZZX(object): function computes s and t such that: a*s + b*t = r; otherwise s and t are both 0. If proof = False (*not* the default), then resultant computation may use a randomized strategy that - errors with probability no more than $2^{-80}$. The default is + errors with probability no more than `2^{-80}`. The default is default is proof=None, see proof.polynomial or sage.structure.proof, but the global default is True), then this function may use a randomized strategy that errors with probability no more than - $2^{-80}$. + `2^{-80}`. EXAMPLES:: @@ -929,7 +929,7 @@ cdef class ntl_ZZX(object): def invert_and_truncate(self, long m): """ - Compute and return the inverse of self modulo $x^m$. + Compute and return the inverse of self modulo `x^m`. The constant term of self must be 1 or -1. EXAMPLES:: @@ -983,7 +983,7 @@ cdef class ntl_ZZX(object): def trace_list(self): """ - Return the list of traces of the powers $x^i$ of the + Return the list of traces of the powers `x^i` of the monomial x modulo this polynomial for i = 0, ..., deg(f)-1. This polynomial must be monic. @@ -1016,7 +1016,7 @@ cdef class ntl_ZZX(object): default is proof=None, see proof.polynomial or sage.structure.proof, but the global default is True), then this function may use a randomized strategy that errors with probability no more than - $2^{-80}$. + `2^{-80}`. EXAMPLES:: @@ -1041,7 +1041,7 @@ cdef class ntl_ZZX(object): is proof=None, see proof.polynomial or sage.structure.proof, but the global default is proof=True) then it may use a randomized strategy that errors with probability no more than - $2^{-80}$. + `2^{-80}`. EXAMPLES:: @@ -1070,7 +1070,7 @@ cdef class ntl_ZZX(object): proof.polynomial or sage.structure.proof, but the global default is proof=True), then this function may use a randomized strategy that errors with probability no more than - $2^{-80}$. + `2^{-80}`. EXAMPLES:: @@ -1096,7 +1096,7 @@ cdef class ntl_ZZX(object): proof.polynomial or sage.structure.proof, but the global default is proof=True), then this function may use a randomized strategy that errors with probability no more than - $2^{-80}$. + `2^{-80}`. EXAMPLES:: @@ -1115,7 +1115,7 @@ cdef class ntl_ZZX(object): Return the minimal polynomial of this polynomial modulo the modulus. The modulus must be monic of degree bigger than self. In all cases, this function may use a randomized - strategy that errors with probability no more than $2^{-80}$. + strategy that errors with probability no more than `2^{-80}`. EXAMPLES:: @@ -1124,8 +1124,8 @@ cdef class ntl_ZZX(object): sage: f.charpoly_mod(g) [0 0 0 0 1] - However, since $f^2 = 0$ modulo $g$, its minimal polynomial - is of degree $2$:: + However, since `f^2 = 0` modulo `g`, its minimal polynomial + is of degree `2`:: sage: f.minpoly_mod_noproof(g) [0 0 1] diff --git a/src/sage/libs/ntl/ntl_ZZ_p.pyx b/src/sage/libs/ntl/ntl_ZZ_p.pyx index 114963b1882..dcb13030882 100644 --- a/src/sage/libs/ntl/ntl_ZZ_p.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_p.pyx @@ -76,11 +76,11 @@ def ntl_ZZ_p_random_element(v): ############################################################################## cdef class ntl_ZZ_p(object): r""" - The \class{ZZ_p} class is used to represent integers modulo $p$. - The modulus $p$ may be any positive integer, not necessarily prime. + The \class{ZZ_p} class is used to represent integers modulo `p`. + The modulus `p` may be any positive integer, not necessarily prime. Objects of the class \class{ZZ_p} are represented as a \code{ZZ} in the - range $0, \ldots, p-1$. + range `0, \ldots, p-1`. Each \class{ZZ_p} contains a pointer of a \class{ZZ_pContext} which contains pre-computed data for NTL. These can be explicitly constructed diff --git a/src/sage/libs/ntl/ntl_ZZ_pE.pyx b/src/sage/libs/ntl/ntl_ZZ_pE.pyx index 6e3684521de..b809099baa8 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pE.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pE.pyx @@ -56,12 +56,12 @@ ZZ_sage = IntegerRing() ############################################################################## cdef class ntl_ZZ_pE(object): r""" - The \class{ZZ_pE} class is used to model $\Z / p\Z [x] / (f(x))$. - The modulus $p$ may be any positive integer, not necessarily prime, + The \class{ZZ_pE} class is used to model `\Z / p\Z [x] / (f(x))`. + The modulus `p` may be any positive integer, not necessarily prime, and the modulus f is not required to be irreducible. Objects of the class \class{ZZ_pE} are represented as a \code{ZZ_pX} of - degree less than the degree of $f$. + degree less than the degree of `f`. Each \class{ZZ_pE} contains a pointer of a \class{ZZ_pEContext} which contains pre-computed data for NTL. These can be explicitly constructed diff --git a/src/sage/libs/ntl/ntl_ZZ_pEX.pyx b/src/sage/libs/ntl/ntl_ZZ_pEX.pyx index a23d84bd4ad..b2ea533a15c 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pEX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pEX.pyx @@ -6,7 +6,7 @@ # distutils: language = c++ """ -Wrapper for NTL's polynomials over finite ring extensions of $\Z / p\Z.$ +Wrapper for NTL's polynomials over finite ring extensions of `\Z / p\Z.` AUTHORS: -- David Roe (2007-10-10) @@ -53,9 +53,9 @@ from sage.arith.power cimport generic_power_pos cdef class ntl_ZZ_pEX(object): r""" - The class \class{ZZ_pEX} implements polynomials over finite ring extensions of $\Z / p\Z$. + The class \class{ZZ_pEX} implements polynomials over finite ring extensions of `\Z / p\Z`. - It can be used, for example, for arithmetic in $GF(p^n)[X]$. + It can be used, for example, for arithmetic in `GF(p^n)[X]`. However, except where mathematically necessary (e.g., GCD computations), ZZ_pE need not be a field. """ @@ -449,7 +449,7 @@ cdef class ntl_ZZ_pEX(object): def square(self): """ - Return $f^2$. + Return `f^2`. EXAMPLES:: @@ -997,7 +997,7 @@ cdef class ntl_ZZ_pEX(object): def invert_and_truncate(self, long m): """ - Compute and return the inverse of self modulo $x^m$. + Compute and return the inverse of self modulo `x^m`. The constant term of self must be invertible. EXAMPLES:: diff --git a/src/sage/libs/ntl/ntl_lzz_p.pyx b/src/sage/libs/ntl/ntl_lzz_p.pyx index 2152f299967..9e787aaf6cd 100644 --- a/src/sage/libs/ntl/ntl_lzz_p.pyx +++ b/src/sage/libs/ntl/ntl_lzz_p.pyx @@ -61,7 +61,7 @@ ZZ_sage = IntegerRing() cdef class ntl_zz_p(object): r""" - The class \class{zz_p} implements arithmetic modulo $p$, + The class \class{zz_p} implements arithmetic modulo `p`, for p smaller than a machine word. NOTE: This type is provided mostly for completeness, and diff --git a/src/sage/libs/ntl/ntl_lzz_pX.pyx b/src/sage/libs/ntl/ntl_lzz_pX.pyx index d7a88da82fd..0941c68460c 100644 --- a/src/sage/libs/ntl/ntl_lzz_pX.pyx +++ b/src/sage/libs/ntl/ntl_lzz_pX.pyx @@ -54,7 +54,7 @@ ZZ_sage = IntegerRing() cdef class ntl_zz_pX(object): r""" - The class \class{zz_pX} implements polynomial arithmetic modulo $p$, + The class \class{zz_pX} implements polynomial arithmetic modulo `p`, for p smaller than a machine word. Polynomial arithmetic is implemented using the FFT, combined with @@ -409,7 +409,7 @@ cdef class ntl_zz_pX(object): """ Returns the quotient and remainder when self is divided by right. - Specifically, this return r, q such that $self = q * right + r$ + Specifically, this return r, q such that `self = q * right + r` EXAMPLES:: @@ -434,7 +434,7 @@ cdef class ntl_zz_pX(object): def __floordiv__(ntl_zz_pX self, ntl_zz_pX right): """ - Returns the whole part of $self / right$. + Returns the whole part of `self / right`. EXAMPLES:: @@ -452,7 +452,7 @@ cdef class ntl_zz_pX(object): def __lshift__(ntl_zz_pX self, long n): """ - Shifts this polynomial to the left, which is multiplication by $x^n$. + Shifts this polynomial to the left, which is multiplication by `x^n`. EXAMPLES:: @@ -467,7 +467,7 @@ cdef class ntl_zz_pX(object): def __rshift__(ntl_zz_pX self, long n): """ - Shifts this polynomial to the right, which is division by $x^n$ (and truncation). + Shifts this polynomial to the right, which is division by `x^n` (and truncation). EXAMPLES:: @@ -497,7 +497,7 @@ cdef class ntl_zz_pX(object): def reverse(self): """ - Returns self with coefficients reversed, i.e. $x^n self(x^{-n})$. + Returns self with coefficients reversed, i.e. `x^n self(x^{-n})`. EXAMPLES:: @@ -722,7 +722,7 @@ cdef class ntl_zz_pX(object): def invert_and_truncate(self, long m): """ - Compute and return the inverse of self modulo $x^m$. + Compute and return the inverse of self modulo `x^m`. The constant term of self must be 1 or -1. EXAMPLES:: diff --git a/src/sage/libs/ntl/ntl_mat_GF2.pyx b/src/sage/libs/ntl/ntl_mat_GF2.pyx index 6967d469cef..bd87dd9984c 100644 --- a/src/sage/libs/ntl/ntl_mat_GF2.pyx +++ b/src/sage/libs/ntl/ntl_mat_GF2.pyx @@ -6,10 +6,10 @@ # distutils: language = c++ """ -Matrices over the $\GF{2}$ via NTL +Matrices over the `\GF{2}` via NTL This class is only provided to have a complete NTL interface and for -comparison purposes. Sage's native matrices over $F_2$ are much faster +comparison purposes. Sage's native matrices over `F_2` are much faster for many problems like matrix multiplication and Gaussian elimination. AUTHORS: @@ -47,7 +47,7 @@ from sage.libs.ntl.ntl_ZZ import unpickle_class_args cdef class ntl_mat_GF2(object): r""" - The \class{mat_GF2} class implements arithmetic with matrices over $F_2$. + The \class{mat_GF2} class implements arithmetic with matrices over `F_2`. """ def __init__(self, nrows=0, ncols=0, v=None): """ @@ -498,7 +498,7 @@ cdef class ntl_mat_GF2(object): def __invert__(self): """ - Return $X = A^{-1}$; an error is raised if A is singular. + Return `X = A^{-1}`; an error is raised if A is singular. EXAMPLES:: diff --git a/src/sage/libs/ntl/ntl_mat_GF2E.pyx b/src/sage/libs/ntl/ntl_mat_GF2E.pyx index 85fd9d6d46f..b3b98b4d266 100644 --- a/src/sage/libs/ntl/ntl_mat_GF2E.pyx +++ b/src/sage/libs/ntl/ntl_mat_GF2E.pyx @@ -47,7 +47,7 @@ from sage.libs.ntl.ntl_ZZ import unpickle_class_args cdef class ntl_mat_GF2E(object): r""" - The \class{mat_GF2E} class implements arithmetic with matrices over $GF(2**x)$. + The \class{mat_GF2E} class implements arithmetic with matrices over `GF(2**x)`. """ def __init__(self, modulus = None, nrows=0, ncols=0, v=None): """ @@ -571,7 +571,7 @@ cdef class ntl_mat_GF2E(object): def __invert__(self): """ - Return $X = A^{-1}$; an error is raised if A is singular. + Return `X = A^{-1}`; an error is raised if A is singular. EXAMPLES:: diff --git a/src/sage/libs/ntl/ntl_mat_ZZ.pyx b/src/sage/libs/ntl/ntl_mat_ZZ.pyx index c9f054602e8..00db7a54c64 100644 --- a/src/sage/libs/ntl/ntl_mat_ZZ.pyx +++ b/src/sage/libs/ntl/ntl_mat_ZZ.pyx @@ -70,11 +70,11 @@ cdef inline ntl_mat_ZZ make_mat_ZZ_sig_off(mat_ZZ_c* x): cdef class ntl_mat_ZZ(object): # see ntl_mat_ZZ.pxd for data members r""" - The \class{mat_ZZ} class implements arithmetic with matrices over $\Z$. + The \class{mat_ZZ} class implements arithmetic with matrices over `\Z`. """ def __init__(self, nrows=0, ncols=0, v=None): """ - The \class{mat_ZZ} class implements arithmetic with matrices over $\Z$. + The \class{mat_ZZ} class implements arithmetic with matrices over `\Z`. EXAMPLES:: @@ -1167,19 +1167,19 @@ cdef class ntl_mat_ZZ(object): r""" Performs LLL reduction of self (puts \code{self} in an LLL form). - \code{self} is an $m x n$ matrix, viewed as $m$ rows of - $n$-vectors. $m$ may be less than, equal to, or greater than $n$, + \code{self} is an `m x n` matrix, viewed as `m` rows of + `n`-vectors. `m` may be less than, equal to, or greater than `n`, and the rows need not be linearly independent. self is transformed into an LLL-reduced basis, and the return value is - the rank r of self so as det2 (see below). The first $m-r$ rows + the rank r of self so as det2 (see below). The first `m-r` rows of self are zero. More specifically, elementary row transformations are performed on \code{self} so that the non-zero rows of new-\code{self} form an LLL-reduced basis for the lattice spanned by the rows of old-\code{self}. The default reduction - parameter is $\delta=3/4$, which means that the squared length - of the first non-zero basis vector is no more than $2^{r-1}$ + parameter is `\delta=3/4`, which means that the squared length + of the first non-zero basis vector is no more than `2^{r-1}` times that of the shortest vector in the lattice. det2 is calculated as the \emph{square} of the determinant of @@ -1193,10 +1193,10 @@ cdef class ntl_mat_ZZ(object): of old-B. The parameters a and b allow an arbitrary reduction parameter - $\delta=a/b$, where $1/4 < a/b \leq 1$, where a and b are positive + `\delta=a/b`, where `1/4 < a/b \leq 1`, where a and b are positive integers. For a basis reduced with parameter delta, the squared length of the first non-zero basis vector is no more - than $1/(delta-1/4)^{r-1}$ times that of the shortest vector in + than `1/(delta-1/4)^{r-1}` times that of the shortest vector in the lattice. The algorithm employed here is essentially the one in Cohen's @@ -1280,7 +1280,7 @@ cdef class ntl_mat_ZZ(object): different, improving both stability and performance. If return_U is True, then also U is returned which is - the transition matrix: $U * self_{old} = self_{new}$ + the transition matrix: `U * self_{old} = self_{new}` The optional argument 'delta' is the reduction parameter, and may be set so that 0.50 <= delta < 1. Setting it close to 1 diff --git a/src/sage/libs/symmetrica/sb.pxi b/src/sage/libs/symmetrica/sb.pxi index 2a7b7ed6a5c..73a5b61c64d 100644 --- a/src/sage/libs/symmetrica/sb.pxi +++ b/src/sage/libs/symmetrica/sb.pxi @@ -170,7 +170,7 @@ def mult_schubert_variable_symmetrica(a, i): def divdiff_perm_schubert_symmetrica(perm, a): r""" Returns the result of applying the divided difference operator - $\delta_i$ to $a$ where $a$ is either a permutation or a + `\delta_i` to `a` where `a` is either a permutation or a Schubert polynomial over QQ. EXAMPLES:: @@ -254,7 +254,7 @@ def scalarproduct_schubert_symmetrica(a, b): def divdiff_schubert_symmetrica(i, a): r""" Returns the result of applying the divided difference operator - $\delta_i$ to $a$ where $a$ is either a permutation or a + `\delta_i` to `a` where `a` is either a permutation or a Schubert polynomial over QQ. EXAMPLES:: From 997689644971cd75c1a074efbc6348165adf181c Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sun, 12 Jun 2022 10:12:20 +0200 Subject: [PATCH 097/116] trac #33980: typos in graphs --- src/sage/graphs/bliss.pyx | 2 +- src/sage/graphs/chrompoly.pyx | 2 +- src/sage/graphs/comparability.pyx | 2 +- src/sage/graphs/generators/distance_regular.pyx | 6 +++--- src/sage/graphs/generators/families.py | 6 +++--- src/sage/graphs/graph_decompositions/cutwidth.pyx | 4 ++-- .../graphs/graph_decompositions/modular_decomposition.py | 2 +- src/sage/graphs/graph_decompositions/tree_decomposition.pyx | 4 ++-- src/sage/graphs/spanning_tree.pyx | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/sage/graphs/bliss.pyx b/src/sage/graphs/bliss.pyx index 921bc6a7659..140b83b4e3b 100644 --- a/src/sage/graphs/bliss.pyx +++ b/src/sage/graphs/bliss.pyx @@ -525,7 +525,7 @@ cpdef canonical_form(G, partition=None, return_graph=False, use_edge_labels=True if partition: from itertools import chain int2vert = list(chain(*partition)) - # We check that the partition constains only vertices of the graph + # We check that the partition contains only vertices of the graph # and that it is actually a partition seen = set() for u in int2vert: diff --git a/src/sage/graphs/chrompoly.pyx b/src/sage/graphs/chrompoly.pyx index 221caa5431a..4fb9f382894 100644 --- a/src/sage/graphs/chrompoly.pyx +++ b/src/sage/graphs/chrompoly.pyx @@ -402,7 +402,7 @@ def chromatic_polynomial_with_cache(G, cache=None): sage: chromatic_polynomial_with_cache(graphs.CompleteBipartiteGraph(3,3)) x^6 - 9*x^5 + 36*x^4 - 75*x^3 + 78*x^2 - 31*x - If a cache is provided, it is feeded:: + If a cache is provided, it is fed:: sage: cache = {} sage: G = graphs.CycleGraph(4) diff --git a/src/sage/graphs/comparability.pyx b/src/sage/graphs/comparability.pyx index 9c6e0d68f9b..d81887a2b12 100644 --- a/src/sage/graphs/comparability.pyx +++ b/src/sage/graphs/comparability.pyx @@ -161,7 +161,7 @@ Implementation details This is done by a call to :meth:`Graph.is_bipartite`, and here is how : Around a vertex `u`, any two edges `uv, uv'` such that `vv'\not\in G` are - equivalent. Hence, the equivalence classe of edges around a vertex are + equivalent. Hence, the equivalence class of edges around a vertex are precisely the connected components of the complement of the graph induced by the neighbors of `u`. diff --git a/src/sage/graphs/generators/distance_regular.pyx b/src/sage/graphs/generators/distance_regular.pyx index e8a731b6824..8d047a19191 100644 --- a/src/sage/graphs/generators/distance_regular.pyx +++ b/src/sage/graphs/generators/distance_regular.pyx @@ -1871,7 +1871,7 @@ def is_classical_parameters_graph(list array): from sage.combinat.q_analogues import q_binomial def integral_log(const int x, const int b): - # compute log_b(x) if is not a positive iteger, return -1 + # compute log_b(x) if is not a positive integer, return -1 if x <= 0: return -1 k = log(x, b) @@ -2358,7 +2358,7 @@ def is_near_polygon(array): sage: _.is_distance_regular(True) ([7, 6, 6, 5, 5, 4, None], [None, 1, 1, 2, 2, 3, 3]) - REFERECES: + REFERENCES: See [BCN1989]_ pp. 198-206 for some theory about near polygons as well as a list of known examples. @@ -2481,7 +2481,7 @@ def near_polygon_graph(family, params): - ``family`` -- int; an element of the enum ``NearPolygonGraph``. - - ``params`` -- int or tuple; the paramters needed to construct a graph + - ``params`` -- int or tuple; the parameters needed to construct a graph of the family ``family``. EXAMPLES:: diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index 4e8ad05527b..c6220e32eba 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -1851,10 +1851,10 @@ def RoseWindowGraph(n, a, r): - ``n`` -- the number of nodes is `2 * n` - - ``a`` -- integer such that `1 \leq a < n` determing a-spoke edges + - ``a`` -- integer such that `1 \leq a < n` determining a-spoke edges - - ``r`` -- integer such that `1 \leq r < n` and `r \neq n / 2` determing how - inner vertices are connected + - ``r`` -- integer such that `1 \leq r < n` and `r \neq n / 2` determining + how inner vertices are connected PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the rose window graphs are diff --git a/src/sage/graphs/graph_decompositions/cutwidth.pyx b/src/sage/graphs/graph_decompositions/cutwidth.pyx index 9b1711107e9..7a38495c0f1 100644 --- a/src/sage/graphs/graph_decompositions/cutwidth.pyx +++ b/src/sage/graphs/graph_decompositions/cutwidth.pyx @@ -117,7 +117,7 @@ optimal layout for the cutwidth of `G`. - `z` -- Objective value to minimize. It is equal to the maximum over all position `k` of the number of edges with one extremity at position at most `k` - and the other at position stricly more than `k`, that is `\sum_{uv\in + and the other at position strictly more than `k`, that is `\sum_{uv\in E}y_{u,v}^{k}`. @@ -142,7 +142,7 @@ optimal layout for the cutwidth of `G`. Constraints (1)-(3) ensure that all vertices have a distinct position. Constraints (4)-(5) force variable `y_{u,v}^k` to 1 if the edge is in the cut. Constraint (6) count the number of edges starting at position at most `k` and -ending at a position stricly larger than `k`. +ending at a position strictly larger than `k`. This formulation corresponds to method :meth:`cutwidth_MILP`. diff --git a/src/sage/graphs/graph_decompositions/modular_decomposition.py b/src/sage/graphs/graph_decompositions/modular_decomposition.py index 941aaa26b29..ebb66d3fc21 100644 --- a/src/sage/graphs/graph_decompositions/modular_decomposition.py +++ b/src/sage/graphs/graph_decompositions/modular_decomposition.py @@ -2962,7 +2962,7 @@ def test_module(module, graph): # Function implemented for testing def children_node_type(module, node_type): """ - Check whether the node type of the childrens of ``module`` is ``node_type``. + Check whether the node type of the children of ``module`` is ``node_type``. INPUT: diff --git a/src/sage/graphs/graph_decompositions/tree_decomposition.pyx b/src/sage/graphs/graph_decompositions/tree_decomposition.pyx index 22f041f0b94..872d0d9ffe3 100644 --- a/src/sage/graphs/graph_decompositions/tree_decomposition.pyx +++ b/src/sage/graphs/graph_decompositions/tree_decomposition.pyx @@ -5,7 +5,7 @@ Tree decompositions This module implements tree-decomposition methods. A tree-decomposition of a graph `G = (V, E)` is a pair `(X, T)`, where `X=\{X_1, -X_2, \ldots, X_t\}` is a familly of subsets of `V`, usually called *bags*, and +X_2, \ldots, X_t\}` is a family of subsets of `V`, usually called *bags*, and `T` is a tree of order `t` whose nodes are the subsets `X_i` satisfying the following properties: @@ -33,7 +33,7 @@ dist_G(u, v)`). The *treelength* `tl(G)` of a graph `G` is the minimum length among all possible tree decompositions of `G`. While deciding whether a graph has treelength 1 can be done in linear time -(equivalant to deciding if the graph is chordal), deciding if it has treelength +(equivalent to deciding if the graph is chordal), deciding if it has treelength at most `k` for any fixed constant `k \leq 2` is NP-complete [Lokshtanov2009]_. Treewidth and treelength are different measures of tree-likeness. In particular, diff --git a/src/sage/graphs/spanning_tree.pyx b/src/sage/graphs/spanning_tree.pyx index 7a2a9153b90..2054cd975bc 100644 --- a/src/sage/graphs/spanning_tree.pyx +++ b/src/sage/graphs/spanning_tree.pyx @@ -1305,7 +1305,7 @@ def edge_disjoint_spanning_trees(G, k, by_weight=False, weight_function=None, ch # Initialization of data structures - # - partition[0] is used to maitain known clumps. + # - partition[0] is used to maintain known clumps. # - partition[i], 1 <= i <= k, is used to check if a given edge has both its # endpoints in the same tree of forest Fi. partition = [DisjointSet_of_hashables(G) for _ in range(k + 1)] From d490b8f8b2e22edb74e225e2d8878aa0f47dcac7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 3 Jun 2022 22:29:41 -0700 Subject: [PATCH 098/116] build/pkgs/sage_setup/dependencies: Add jinja2 --- build/pkgs/sage_setup/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/sage_setup/dependencies b/build/pkgs/sage_setup/dependencies index fb4de797d36..dc512520b14 100644 --- a/build/pkgs/sage_setup/dependencies +++ b/build/pkgs/sage_setup/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) cython pkgconfig $(SAGE_ROOT)/pkgs/sage-setup/sage_setup/autogen/interpreters/specs/*.py $(SAGE_ROOT)/pkgs/sage-setup/sage_setup/command/*.py | $(PYTHON_TOOLCHAIN) +$(PYTHON) cython pkgconfig jinja2 $(SAGE_ROOT)/pkgs/sage-setup/sage_setup/autogen/interpreters/specs/*.py $(SAGE_ROOT)/pkgs/sage-setup/sage_setup/command/*.py | $(PYTHON_TOOLCHAIN) ---------- All lines of this file are ignored except the first. From c53de989a77e0d2c4858c3011ab59057cb1aedaa Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Sun, 12 Jun 2022 13:41:06 -0700 Subject: [PATCH 099/116] trac 33973: remove more dollar signs --- src/sage/combinat/words/suffix_trees.py | 2 +- .../parametrized_surface3d.py | 4 +- src/sage/geometry/toric_plotter.py | 2 +- .../graphs/generators/classical_geometries.py | 2 +- .../abelian_gps/dual_abelian_group_element.py | 2 +- src/sage/groups/braid.py | 10 ++-- src/sage/groups/perm_gps/permgroup_named.py | 48 +++++++++---------- src/sage/interfaces/frobby.py | 4 +- src/sage/matrix/matrix_cyclo_dense.pyx | 10 ++-- src/sage/matrix/matrix_double_dense.pyx | 12 ++--- .../matrix/matrix_integer_dense_saturation.py | 2 +- src/sage/matrix/matrix_mpolynomial_dense.pyx | 2 +- src/sage/matrix/special.py | 2 +- src/sage/matrix/symplectic_basis.py | 18 +++---- src/sage/media/wav.py | 6 +-- src/sage/modular/arithgroup/congroup_sl2z.py | 4 +- src/sage/modular/modform/numerical.py | 2 +- 17 files changed, 66 insertions(+), 66 deletions(-) diff --git a/src/sage/combinat/words/suffix_trees.py b/src/sage/combinat/words/suffix_trees.py index a70eb02f7ff..1cfdb629213 100644 --- a/src/sage/combinat/words/suffix_trees.py +++ b/src/sage/combinat/words/suffix_trees.py @@ -1570,7 +1570,7 @@ class DecoratedSuffixTree(ImplicitSuffixTree): A *decorated suffix tree* of a word `w` is the suffix tree of `w` marked with the end point of all squares in the `w`. - The symbol ``"$"`` is appended to ``w`` to ensure that each final + The symbol ``$`` is appended to ``w`` to ensure that each final state is a leaf of the suffix tree. INPUT: diff --git a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py index 15285685477..e1021f66a97 100644 --- a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py +++ b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py @@ -1452,9 +1452,9 @@ def connection_coefficients(self): Computes the connection coefficients or Christoffel symbols `\Gamma^k_{ij}` of the surface. If the coefficients of the first fundamental form are given by `g_{ij}` (where `i, j = 1, 2`), then - $\Gamma^k_{ij} = \frac{1}{2} g^{kl} \left( \frac{\partial g_{li}}{\partial x^j} + `\Gamma^k_{ij} = \frac{1}{2} g^{kl} \left( \frac{\partial g_{li}}{\partial x^j} - \frac{\partial g_{ij}}{\partial x^l} - + \frac{\partial g_{lj}}{\partial x^i} \right)$. + + \frac{\partial g_{lj}}{\partial x^i} \right)`. Here, `(g^{kl})` is the inverse of the matrix `(g_{ij})`, with `i, j = 1, 2`. diff --git a/src/sage/geometry/toric_plotter.py b/src/sage/geometry/toric_plotter.py index 17e7730fbae..923fb43440d 100644 --- a/src/sage/geometry/toric_plotter.py +++ b/src/sage/geometry/toric_plotter.py @@ -836,7 +836,7 @@ def label_list(label, n, math_mode, index_set=None): If ``label`` was a list of ``n`` entries, it is returned without changes. If ``label`` is ``None``, a list of ``n`` ``None``'s is returned. If - ``label`` is a string, a list of strings of the form "$label_{i}$" is + ``label`` is a string, a list of strings of the form ``$label_{i}$`` is returned, where `i` ranges over ``index_set``. (If ``math_mode=False``, the form "label_i" is used instead.) If ``n=1``, there is no subscript added, unless ``index_set`` was specified explicitly. diff --git a/src/sage/graphs/generators/classical_geometries.py b/src/sage/graphs/generators/classical_geometries.py index 6290002cc1b..4e049f44a6d 100644 --- a/src/sage/graphs/generators/classical_geometries.py +++ b/src/sage/graphs/generators/classical_geometries.py @@ -1433,7 +1433,7 @@ def Nowhere0WordsTwoWeightCodeGraph(q, hyperoval=None, field=None, check_hyperov def OrthogonalDualPolarGraph(e, d, q): r""" - Return the dual polar graph on $GO^e(n,q)$ of diameter `d`. + Return the dual polar graph on `GO^e(n,q)` of diameter `d`. The value of `n` is determined by `d` and `e`. 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 31f132c7b73..174d1435b68 100644 --- a/src/sage/groups/abelian_gps/dual_abelian_group_element.py +++ b/src/sage/groups/abelian_gps/dual_abelian_group_element.py @@ -200,7 +200,7 @@ def word_problem(self, words, display=True): [[b^2*c^2*d^3*e^5, 245]] The command e.word_problem([u,v,w,x,y],display=True) returns - the same list but also prints $e = (b^2*c^2*d^3*e^5)^245$. + the same list but also prints `e = (b^2*c^2*d^3*e^5)^245`. """ ## First convert the problem to one using AbelianGroups import copy diff --git a/src/sage/groups/braid.py b/src/sage/groups/braid.py index c2ac473b8d7..8144aa7b9d6 100644 --- a/src/sage/groups/braid.py +++ b/src/sage/groups/braid.py @@ -628,8 +628,8 @@ def LKB_matrix(self, variables='x,y'): r""" Return the Lawrence-Krammer-Bigelow representation matrix. - The matrix is expressed in the basis $\{e_{i, j} \mid 1\leq i - < j \leq n\}$, where the indices are ordered + The matrix is expressed in the basis `\{e_{i, j} \mid 1\leq i + < j \leq n\}`, where the indices are ordered lexicographically. It is a matrix whose entries are in the ring of Laurent polynomials on the given variables. By default, the variables are ``'x'`` and ``'y'``. @@ -1345,7 +1345,7 @@ def _left_normal_form_coxeter(self): OUTPUT: - A tuple whose first element is the power of $\Delta$, and the + A tuple whose first element is the power of `\Delta`, and the rest are the permutations corresponding to the simple factors. EXAMPLES:: @@ -3080,8 +3080,8 @@ class group of the punctured disk. x_{j} & \text{otherwise} \end{cases}, - where $\sigma_i$ are the generators of the braid group on $n$ - strands, and $x_j$ the generators of the free group of rank $n$. + where `\sigma_i` are the generators of the braid group on `n` + strands, and `x_j` the generators of the free group of rank `n`. You should left multiplication of the free group element by the braid to compute the action. Alternatively, use the diff --git a/src/sage/groups/perm_gps/permgroup_named.py b/src/sage/groups/perm_gps/permgroup_named.py index cc780adc4dc..deb7e9c4657 100644 --- a/src/sage/groups/perm_gps/permgroup_named.py +++ b/src/sage/groups/perm_gps/permgroup_named.py @@ -3,34 +3,34 @@ You can construct the following permutation groups: --- SymmetricGroup, $S_n$ of order $n!$ (n can also be a list $X$ of distinct - positive integers, in which case it returns $S_X$) +-- SymmetricGroup, `S_n` of order `n!` (n can also be a list `X` of distinct + positive integers, in which case it returns `S_X`) --- AlternatingGroup, $A_n$ of order $n!/2$ (n can also be a list $X$ +-- AlternatingGroup, `A_n` of order `n!/2` (n can also be a list `X` of distinct positive integers, in which case it returns - $A_X$) + `A_X`) --- DihedralGroup, $D_n$ of order $2n$ +-- DihedralGroup, `D_n` of order `2n` --- GeneralDihedralGroup, $Dih(G)$, where G is an abelian group +-- GeneralDihedralGroup, `Dih(G)`, where G is an abelian group --- CyclicPermutationGroup, $C_n$ of order $n$ +-- CyclicPermutationGroup, `C_n` of order `n` -- DiCyclicGroup, nonabelian groups of order `4m` with a unique element of order 2 --- TransitiveGroup, $n^{th}$ transitive group of degree $d$ +-- TransitiveGroup, `n^{th}` transitive group of degree `d` from the GAP tables of transitive groups -- TransitiveGroups(d), TransitiveGroups(), set of all of the above --- PrimitiveGroup, $n^{th}$ primitive group of degree $d$ +-- PrimitiveGroup, `n^{th}` primitive group of degree `d` from the GAP tables of primitive groups -- PrimitiveGroups(d), PrimitiveGroups(), set of all of the above -- MathieuGroup(degree), Mathieu group of degree 9, 10, 11, 12, 21, 22, 23, or 24. --- KleinFourGroup, subgroup of $S_4$ of order $4$ which is not $C_2 \times C_2$ +-- KleinFourGroup, subgroup of `S_4` of order `4` which is not `C_2 \times C_2` -- QuaternionGroup, non-abelian group of order `8`, `\{\pm 1, \pm I, \pm J, \pm K\}` @@ -39,24 +39,24 @@ -- SemidihedralGroup, nonabelian 2-groups with cyclic subgroups of index 2 --- PGL(n,q), projective general linear group of $n\times n$ matrices over +-- PGL(n,q), projective general linear group of `n\times n` matrices over the finite field GF(q) --- PSL(n,q), projective special linear group of $n\times n$ matrices over +-- PSL(n,q), projective special linear group of `n\times n` matrices over the finite field GF(q) --- PSp(2n,q), projective symplectic linear group of $2n\times 2n$ matrices +-- PSp(2n,q), projective symplectic linear group of `2n\times 2n` matrices over the finite field GF(q) --- PSU(n,q), projective special unitary group of $n \times n$ matrices having - coefficients in the finite field $GF(q^2)$ that respect a +-- PSU(n,q), projective special unitary group of `n \times n` matrices having + coefficients in the finite field `GF(q^2)` that respect a fixed nondegenerate sesquilinear form, of determinant 1. --- PGU(n,q), projective general unitary group of $n\times n$ matrices having - coefficients in the finite field $GF(q^2)$ that respect a +-- PGU(n,q), projective general unitary group of `n\times n` matrices having + coefficients in the finite field `GF(q^2)` that respect a fixed nondegenerate sesquilinear form, modulo the centre. --- SuzukiGroup(q), Suzuki group over GF(q), $^2 B_2(2^{2k+1}) = Sz(2^{2k+1})$. +-- SuzukiGroup(q), Suzuki group over GF(q), `^2 B_2(2^{2k+1}) = Sz(2^{2k+1})`. -- ComplexReflectionGroup, the complex reflection group `G(m, p, n)` or the exceptional complex reflection group `G_m` @@ -622,7 +622,7 @@ def algebra(self, base_ring, category=None): class AlternatingGroup(PermutationGroup_symalt): def __init__(self, domain=None): """ - The alternating group of order $n!/2$, as a permutation group. + The alternating group of order `n!/2`, as a permutation group. INPUT: @@ -968,8 +968,8 @@ def is_abelian(self): class KleinFourGroup(PermutationGroup_unique): def __init__(self): r""" - The Klein 4 Group, which has order $4$ and exponent $2$, viewed - as a subgroup of $S_4$. + The Klein 4 Group, which has order `4` and exponent `2`, viewed + as a subgroup of `S_4`. OUTPUT: @@ -1703,7 +1703,7 @@ def _repr_(self): class MathieuGroup(PermutationGroup_unique): def __init__(self, n): """ - The Mathieu group of degree $n$. + The Mathieu group of degree `n`. INPUT: @@ -2777,7 +2777,7 @@ def ramification_module_decomposition_modular_curve(self): REFERENCE: D. Joyner and A. Ksir, 'Modular representations on some Riemann-Roch spaces of modular curves - $X(N)$', Computational Aspects of Algebraic Curves, + `X(N)`', Computational Aspects of Algebraic Curves, (Editor: T. Shaska) Lecture Notes in Computing, WorldScientific, 2005.) @@ -2990,7 +2990,7 @@ class SuzukiGroup(PermutationGroup_unique): def __init__(self, q, name='a'): r""" The Suzuki group over GF(q), - $^2 B_2(2^{2k+1}) = Sz(2^{2k+1})$. + `^2 B_2(2^{2k+1}) = Sz(2^{2k+1})`. A wrapper for the GAP function SuzukiGroup. diff --git a/src/sage/interfaces/frobby.py b/src/sage/interfaces/frobby.py index ed852f74efe..58f2ebbb51d 100644 --- a/src/sage/interfaces/frobby.py +++ b/src/sage/interfaces/frobby.py @@ -144,8 +144,8 @@ def hilbert(self, monomial_ideal): The Hilbert-Poincaré series of a monomial ideal is the sum of all monomials not in the ideal. This sum can be written as a (finite) - rational function with $(x_1-1)(x_2-1)...(x_n-1)$ in the denominator, - assuming the variables of the ring are $x_1,x2,...,x_n$. This action + rational function with `(x_1-1)(x_2-1)...(x_n-1)` in the denominator, + assuming the variables of the ring are `x_1,x2,...,x_n`. This action computes the polynomial in the numerator of this fraction. INPUT: diff --git a/src/sage/matrix/matrix_cyclo_dense.pyx b/src/sage/matrix/matrix_cyclo_dense.pyx index 1845be41cbd..ba9c043f25f 100644 --- a/src/sage/matrix/matrix_cyclo_dense.pyx +++ b/src/sage/matrix/matrix_cyclo_dense.pyx @@ -922,7 +922,7 @@ cdef class Matrix_cyclo_dense(Matrix_dense): sage: A.coefficient_bound() 16 - The above bound is just $9 + 7$, coming from the lower left entry. + The above bound is just `9 + 7`, coming from the lower left entry. A better bound would be the following:: sage: (A[1,0]).abs() @@ -1309,7 +1309,7 @@ cdef class Matrix_cyclo_dense(Matrix_dense): def _charpoly_mod(self, p): """ Return the characteristic polynomial of self*denom modulo all - primes over $p$. + primes over `p`. This is used internally by the multimodular charpoly algorithm. @@ -1356,9 +1356,9 @@ cdef class Matrix_cyclo_dense(Matrix_dense): INPUT: proof -- bool (default: global flag); if False, compute - using primes $p_i$ until the lift modulo all - primes up to $p_i$ is the same as the lift modulo - all primes up to $p_{i+3}$ or the bound is + using primes `p_i` until the lift modulo all + primes up to `p_i` is the same as the lift modulo + all primes up to `p_{i+3}` or the bound is reached. EXAMPLES:: diff --git a/src/sage/matrix/matrix_double_dense.pyx b/src/sage/matrix/matrix_double_dense.pyx index d62c2f2c14b..7e799e30993 100644 --- a/src/sage/matrix/matrix_double_dense.pyx +++ b/src/sage/matrix/matrix_double_dense.pyx @@ -1108,7 +1108,7 @@ cdef class Matrix_double_dense(Matrix_numpy_dense): OUTPUT: - Default output for a square matrix of size $n$ is a list of $n$ + Default output for a square matrix of size `n` is a list of `n` eigenvalues from the complex double field, :class:`~sage.rings.complex_double.CDF`. If the ``'symmetric'`` or ``'hermitian'`` algorithms are chosen, the returned eigenvalues @@ -1120,11 +1120,11 @@ cdef class Matrix_double_dense(Matrix_numpy_dense): where each pair is an eigenvalue followed by its multiplicity. The eigenvalue reported is the mean of the eigenvalues computed, and these eigenvalues are contained in an interval (or disk) whose - radius is less than ``5*tol`` for $n < 10,000$ in the worst case. + radius is less than ``5*tol`` for `n < 10,000` in the worst case. - More precisely, for an $n\times n$ matrix, the diameter of the + More precisely, for an `n\times n` matrix, the diameter of the interval containing similar eigenvalues could be as large as sum - of the reciprocals of the first $n$ integers times ``tol``. + of the reciprocals of the first `n` integers times ``tol``. .. WARNING:: @@ -1875,7 +1875,7 @@ cdef class Matrix_double_dense(Matrix_numpy_dense): OUTPUT: - - U, S, V -- immutable matrices such that $A = U*S*V.conj().transpose()$ + - U, S, V -- immutable matrices such that `A = U*S*V.conj().transpose()` where U and V are orthogonal and S is zero off of the diagonal. Note that if self is m-by-n, then the dimensions of the @@ -3604,7 +3604,7 @@ cdef class Matrix_double_dense(Matrix_numpy_dense): def _hadamard_row_bound(self): r""" Return an integer n such that the absolute value of the - determinant of this matrix is at most $10^n$. + determinant of this matrix is at most `10^n`. EXAMPLES:: diff --git a/src/sage/matrix/matrix_integer_dense_saturation.py b/src/sage/matrix/matrix_integer_dense_saturation.py index b88e7b23472..9ac854ea2d1 100644 --- a/src/sage/matrix/matrix_integer_dense_saturation.py +++ b/src/sage/matrix/matrix_integer_dense_saturation.py @@ -118,7 +118,7 @@ def random_sublist_of_size(k, n): def solve_system_with_difficult_last_row(B, A): """ - Solve the matrix equation B*Z = A when the last row of $B$ + Solve the matrix equation B*Z = A when the last row of `B` contains huge entries. INPUT: diff --git a/src/sage/matrix/matrix_mpolynomial_dense.pyx b/src/sage/matrix/matrix_mpolynomial_dense.pyx index 5ceb931ee36..ee700a93148 100644 --- a/src/sage/matrix/matrix_mpolynomial_dense.pyx +++ b/src/sage/matrix/matrix_mpolynomial_dense.pyx @@ -437,7 +437,7 @@ cdef class Matrix_mpolynomial_dense(Matrix_generic_dense): of the Gauss-Bareiss algorithm (see :meth:`echelon_form` for details). The tuple as length equal to the rank of self and the value at the - $i$-th position indicates the source column which was put as the $i$-th + `i`-th position indicates the source column which was put as the `i`-th column. If no Gauss-Bareiss reduction was performed yet, None is diff --git a/src/sage/matrix/special.py b/src/sage/matrix/special.py index 37840617e31..619d5d7c892 100644 --- a/src/sage/matrix/special.py +++ b/src/sage/matrix/special.py @@ -1486,7 +1486,7 @@ def circulant(v, sparse=None): Return the circulant matrix specified by its 1st row `v` A circulant `n \times n` matrix specified by the 1st row `v=(v_0...v_{n-1})` is - the matrix $(c_{ij})_{0 \leq i,j\leq n-1}$, where $c_{ij}=v_{j-i \mod b}$. + the matrix `(c_{ij})_{0 \leq i,j\leq n-1}`, where `c_{ij}=v_{j-i \mod b}`. INPUT: diff --git a/src/sage/matrix/symplectic_basis.py b/src/sage/matrix/symplectic_basis.py index 29e04edd6e2..4caee7a6da6 100644 --- a/src/sage/matrix/symplectic_basis.py +++ b/src/sage/matrix/symplectic_basis.py @@ -145,17 +145,17 @@ def symplectic_basis_over_field(M): Returns a pair (F, C) such that the rows of C form a symplectic basis for M and ``F = C * M * C.transpose()``. - Anti-symmetric means that $M = -M^t$. Alternating means that the - diagonal of $M$ is identically zero. + Anti-symmetric means that `M = -M^t`. Alternating means that the + diagonal of `M` is identically zero. - A symplectic basis is a basis of the form $e_1, - \ldots, e_j, f_1, \ldots f_j, z_1, \ldots, z_k$ such that + A symplectic basis is a basis of the form `e_1, + \ldots, e_j, f_1, \ldots f_j, z_1, \ldots, z_k` such that - * $z_i M v^t$ = 0 for all vectors $v$; - * $e_i M {e_j}^t = 0$ for all $i, j$; - * $f_i M {f_j}^t = 0$ for all $i, j$; - * $e_i M {f_i}^t = 1$ for all $i$; - * $e_i M {f_j}^t = 0$ for all $i$ not equal $j$. + * `z_i M v^t` = 0 for all vectors `v`; + * `e_i M {e_j}^t = 0` for all `i, j`; + * `f_i M {f_j}^t = 0` for all `i, j`; + * `e_i M {f_i}^t = 1` for all `i`; + * `e_i M {f_j}^t = 0` for all `i` not equal `j`. See the examples for a pictorial description of such a basis. diff --git a/src/sage/media/wav.py b/src/sage/media/wav.py index cbe77237003..6252c6080e1 100644 --- a/src/sage/media/wav.py +++ b/src/sage/media/wav.py @@ -70,8 +70,8 @@ class Wave(SageObject): Indexing: - Getting the $n$th item in a Wave object will give you the value - of the $n$th frame. + Getting the `n^{th}` item in a Wave object will give you the value + of the `n^{th}` frame. """ def __init__(self, data=None, **kwds): if data is not None: @@ -197,7 +197,7 @@ def getnframes(self): def readframes(self, n): """ - Read out the raw data for the first $n$ frames of this wave object. + Read out the raw data for the first `n` frames of this wave object. INPUT: diff --git a/src/sage/modular/arithgroup/congroup_sl2z.py b/src/sage/modular/arithgroup/congroup_sl2z.py index ce8a4a80f2c..062f835517c 100644 --- a/src/sage/modular/arithgroup/congroup_sl2z.py +++ b/src/sage/modular/arithgroup/congroup_sl2z.py @@ -48,7 +48,7 @@ class SL2Z_class(Gamma0_class): def __init__(self): r""" - The modular group $\SL_2(\Z)$. + The modular group `\SL_2(\Z)`. EXAMPLES:: @@ -165,7 +165,7 @@ def reduce_cusp(self, c): r""" Return the unique reduced cusp equivalent to c under the action of self. Always returns Infinity, since there is only - one equivalence class of cusps for $SL_2(Z)$. + one equivalence class of cusps for `SL_2(Z)`. EXAMPLES:: diff --git a/src/sage/modular/modform/numerical.py b/src/sage/modular/modform/numerical.py index 47dbdd6762b..eb66a1ab69b 100644 --- a/src/sage/modular/modform/numerical.py +++ b/src/sage/modular/modform/numerical.py @@ -53,7 +53,7 @@ class NumericalEigenforms(SageObject): A numerical eigenforms object, with the following useful methods: - - :meth:`ap` - return all eigenvalues of $T_p$ + - :meth:`ap` - return all eigenvalues of `T_p` - :meth:`eigenvalues` - list of eigenvalues corresponding to the given list of primes, e.g.,:: From 1176758659e48a56fe3cf8e5a871a212f5a5f8a9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 12 Jun 2022 14:00:44 -0700 Subject: [PATCH 100/116] pkgs/sage-setup: Add jinja2 dep to requirements.txt, setup.cfg --- pkgs/sage-setup/requirements.txt | 1 + pkgs/sage-setup/setup.cfg | 1 + 2 files changed, 2 insertions(+) diff --git a/pkgs/sage-setup/requirements.txt b/pkgs/sage-setup/requirements.txt index e92efbdfa0e..3853e7d55b7 100644 --- a/pkgs/sage-setup/requirements.txt +++ b/pkgs/sage-setup/requirements.txt @@ -1,2 +1,3 @@ Cython pkgconfig +jinja2 diff --git a/pkgs/sage-setup/setup.cfg b/pkgs/sage-setup/setup.cfg index 79fd069f7c0..05f152ef60b 100644 --- a/pkgs/sage-setup/setup.cfg +++ b/pkgs/sage-setup/setup.cfg @@ -35,3 +35,4 @@ python_requires = >=3.8, <3.11 install_requires = pkgconfig + jinja2 From 25228977a73b100d8179fdb6d2662989deb993c6 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Sun, 12 Jun 2022 13:41:26 -0700 Subject: [PATCH 101/116] trac 33973: remove dollar signs in matrix_polynomial_dense.pyx --- src/sage/matrix/matrix_polynomial_dense.pyx | 242 ++++++++++---------- 1 file changed, 121 insertions(+), 121 deletions(-) diff --git a/src/sage/matrix/matrix_polynomial_dense.pyx b/src/sage/matrix/matrix_polynomial_dense.pyx index 6f2969d91c8..0c7ad5e4aa8 100644 --- a/src/sage/matrix/matrix_polynomial_dense.pyx +++ b/src/sage/matrix/matrix_polynomial_dense.pyx @@ -47,29 +47,29 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): r""" Dense matrix over a univariate polynomial ring over a field. - For a field $\Bold{K}$, we consider matrices over the univariate - polynomial ring $\Bold{K}[x]$. + For a field `\Bold{K}`, we consider matrices over the univariate + polynomial ring `\Bold{K}[x]`. - They are often used to represent bases of some $\Bold{K}[x]$-modules. In + They are often used to represent bases of some `\Bold{K}[x]`-modules. In this context, there are two possible representations which are both commonly used in the literature. - Working column-wise: each column of the matrix is a vector in the basis; - then, a $\\Bold{K}[x]$-submodule of $\\Bold{K}[x]^{m}$ of rank $n$ is - represented by an $m \\times n$ matrix, whose columns span the module - (via $\\Bold{K}[x]$-linear combinations). This matrix has full rank, - and $n \\leq m$. + then, a `\Bold{K}[x]`-submodule of `\Bold{K}[x]^{m}` of rank `n` is + represented by an `m \times n` matrix, whose columns span the module + (via `\Bold{K}[x]`-linear combinations). This matrix has full rank, + and `n \leq m`. - Working row-wise: each row of the matrix is a vector in the basis; then, - a $\\Bold{K}[x]$-submodule of $\\Bold{K}[x]^{n}$ of rank $m$ is - represented by an $m \\times n$ matrix, whose rows span the module (via - $\\Bold{K}[x]$-linear combinations). This matrix has full rank, and $m - \\leq n$. + a `\Bold{K}[x]`-submodule of `\Bold{K}[x]^{n}` of rank `m` is + represented by an `m \times n` matrix, whose rows span the module (via + `\Bold{K}[x]`-linear combinations). This matrix has full rank, and `m + \leq n`. For the rest of this class description, we assume that one is working row-wise. For a given such module, all its bases are equivalent under left-multiplication by a unimodular matrix, that is, a square matrix which - has determinant in $\Bold{K}\setminus\{0\}$. + has determinant in `\Bold{K}\setminus\{0\}`. There are bases which are called reduced or minimal: their rows have the minimal degree possible among all bases of this module; here the degree of @@ -82,17 +82,17 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): These notions can be extended via a more general degree measure, involving a tuple of integers which is called shift and acts as column degree shifts - in the definition of row degree. Precisely, for given $s_1,\ldots,s_n \in - \ZZ$ and a row vector $[p_1 \; \cdots \; p_n] \in \Bold{K}[x]^{1 \times - n}$, its shifted row degree is the maximum of $\deg(p_j) + s_j$ for $1 \leq - j \leq n$ (see :meth:`row_degrees`). Then, reduced bases and Popov bases + in the definition of row degree. Precisely, for given `s_1,\ldots,s_n \in + \ZZ` and a row vector `[p_1 \; \cdots \; p_n] \in \Bold{K}[x]^{1 \times + n}`, its shifted row degree is the maximum of `\deg(p_j) + s_j` for `1 \leq + j \leq n` (see :meth:`row_degrees`). Then, reduced bases and Popov bases are defined similarly, with respect to this notion of degree. Another important canonical basis is the Hermite basis, which is an upper triangular matrix satisfying a normalization condition similar to that for - the Popov basis. In fact, if $d$ is the largest degree appearing in the + the Popov basis. In fact, if `d` is the largest degree appearing in the Hermite basis, then the Hermite basis coincide with the shifted Popov basis - with the shifts $((n-1)d,\ldots,2d,d,0)$. + with the shifts `((n-1)d,\ldots,2d,d,0)`. """ def _check_shift_dimension(self, shifts, row_wise=True): @@ -100,9 +100,9 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): Raises an exception if the ``shifts`` argument does not have the right length. - For an $m \times n$ polynomial matrix, if working row-wise then - ``shifts`` should have $n$ entries; if working column-wise, it should - have $m$ entries. + For an `m \times n` polynomial matrix, if working row-wise then + ``shifts`` should have `n` entries; if working column-wise, it should + have `m` entries. INPUT: @@ -168,17 +168,17 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): r""" Return the matrix of the (shifted) degrees in this matrix. - For a given polynomial matrix $M = (M_{i,j})_{i,j}$, its degree matrix - is the matrix $(\deg(M_{i,j}))_{i,j}$ formed by the degrees of its - entries. Here, the degree of the zero polynomial is $-1$. + For a given polynomial matrix `M = (M_{i,j})_{i,j}`, its degree matrix + is the matrix `(\deg(M_{i,j}))_{i,j}` formed by the degrees of its + entries. Here, the degree of the zero polynomial is `-1`. - For given shifts $s_1,\ldots,s_m \in \ZZ$, the shifted degree - matrix of $M$ is either $(\deg(M_{i,j})+s_j)_{i,j}$ if working - row-wise, or $(\deg(M_{i,j})+s_i)_{i,j}$ if working column-wise. In the - former case, $m$ has to be the number of columns of $M$; in the latter - case, the number of its rows. Here, if $M_{i,j}=0$ then the + For given shifts `s_1,\ldots,s_m \in \ZZ`, the shifted degree + matrix of `M` is either `(\deg(M_{i,j})+s_j)_{i,j}` if working + row-wise, or `(\deg(M_{i,j})+s_i)_{i,j}` if working column-wise. In the + former case, `m` has to be the number of columns of `M`; in the latter + case, the number of its rows. Here, if `M_{i,j}=0` then the corresponding entry in the shifted degree matrix is - $\min(s_1,\ldots,s_m)-1$. For more on shifts and working row-wise + `\min(s_1,\ldots,s_m)-1`. For more on shifts and working row-wise versus column-wise, see the class documentation. INPUT: @@ -295,12 +295,12 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): - if `d` is an integer, this selects the coefficient of `d` for all entries; - - if `d` is a list $(d_1,\ldots,d_m)$ and ``row_wise`` is ``True``, - this selects the coefficient of degree $d_i$ for all entries of the - $i$th row for each $i$; - - if `d` is a list $(d_1,\ldots,d_n)$ and ``row_wise`` is ``False``, - this selects the coefficient of degree $d_i$ for all entries of the - $j$th column for each $j$. + - if `d` is a list `(d_1,\ldots,d_m)` and ``row_wise`` is ``True``, + this selects the coefficient of degree `d_i` for all entries of the + `i`th row for each `i`; + - if `d` is a list `(d_1,\ldots,d_n)` and ``row_wise`` is ``False``, + this selects the coefficient of degree `d_i` for all entries of the + `j`th column for each `j`. INPUT: @@ -388,12 +388,12 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): - if `d` is an integer, the truncation is at precision `d` for all entries; - - if `d` is a list $(d_1,\ldots,d_m)$ and ``row_wise`` is ``True``, all - entries of the $i$th row are truncated at precision $d_i$ for each - $i$; - - if `d` is a list $(d_1,\ldots,d_n)$ and ``row_wise`` is ``False``, - all entries of the $j$th column are truncated at precision $d_j$ for - each $j$. + - if `d` is a list `(d_1,\ldots,d_m)` and ``row_wise`` is ``True``, all + entries of the `i`th row are truncated at precision `d_i` for each + `i`; + - if `d` is a list `(d_1,\ldots,d_n)` and ``row_wise`` is ``False``, + all entries of the `j`th column are truncated at precision `d_j` for + each `j`. Here the convention for univariate polynomials is to take zero for the truncation for a negative `d`. @@ -480,10 +480,10 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): all its entries as specified by `d`. - if `d` is an integer, the shift is by `d` for all entries; - - if `d` is a list $(d_1,\ldots,d_m)$ and ``row_wise`` is ``True``, all - entries of the $i$th row are shifted by $d_i$ for each $i$; - - if `d` is a list $(d_1,\ldots,d_n)$ and ``row_wise`` is ``False``, - all entries of the $j$th column are shifted by $d_j$ for each $j$. + - if `d` is a list `(d_1,\ldots,d_m)` and ``row_wise`` is ``True``, all + entries of the `i`th row are shifted by `d_i` for each `i`; + - if `d` is a list `(d_1,\ldots,d_n)` and ``row_wise`` is ``False``, + all entries of the `j`th column are shifted by `d_j` for each `j`. Shifting by `d` means multiplying by the variable to the power `d`; if `d` is negative then terms of negative degree after shifting are @@ -586,12 +586,12 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): it; - if ``degree`` is not provided, then all entries are reversed with respect to the degree of the whole matrix; - - if ``degree`` is a list $(d_1,\ldots,d_m)$ and ``row_wise`` is - ``True``, all entries of the $i$th row are reversed with respect to - $d_i$ for each $i$; - - if ``degree`` is a list $(d_1,\ldots,d_n)$ and ``row_wise`` is - ``False``, all entries of the $j$th column are reversed with respect - to $d_j$ for each $j$. + - if ``degree`` is a list `(d_1,\ldots,d_m)` and ``row_wise`` is + ``True``, all entries of the `i`th row are reversed with respect to + `d_i` for each `i`; + - if ``degree`` is a list `(d_1,\ldots,d_n)` and ``row_wise`` is + ``False``, all entries of the `j`th column are reversed with respect + to `d_j` for each `j`. INPUT: @@ -733,7 +733,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): INPUT: a positive integer `d` . - OUTPUT: the unique polynomial matrix $B$ of degree less than `d` such + OUTPUT: the unique polynomial matrix `B` of degree less than `d` such that `AB` and `BA` are the identity matrix modulo `x^d`, where `A` is ``self``. @@ -1069,15 +1069,15 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): r""" Return the (shifted) row degrees of this matrix. - For a given polynomial matrix $M = (M_{i,j})_{i,j}$ with $m$ rows and - $n$ columns, its row degrees is the tuple $(d_1,\ldots,d_m)$ where $d_i - = \max_j(\deg(M_{i,j}))$ for $1\leq i \leq m$. Thus, $d_i=-1$ if - the $i$-th row of $M$ is zero, and $d_i \geq 0$ otherwise. + For a given polynomial matrix `M = (M_{i,j})_{i,j}` with `m` rows and + `n` columns, its row degrees is the tuple `(d_1,\ldots,d_m)` where `d_i + = \max_j(\deg(M_{i,j}))` for `1\leq i \leq m`. Thus, `d_i=-1` if + the `i`-th row of `M` is zero, and `d_i \geq 0` otherwise. - For given shifts $s_1,\ldots,s_n \in \ZZ$, the shifted row degrees of - $M$ is $(d_1,\ldots,d_m)$ where $d_i = \max_j(\deg(M_{i,j})+s_j)$. - Here, if the $i$-th row of $M$ is zero then $d_i - =\min(s_1,\ldots,s_n)-1$; otherwise, $d_i$ is larger than this value. + For given shifts `s_1,\ldots,s_n \in \ZZ`, the shifted row degrees of + `M` is `(d_1,\ldots,d_m)` where `d_i = \max_j(\deg(M_{i,j})+s_j)`. + Here, if the `i`-th row of `M` is zero then `d_i + =\min(s_1,\ldots,s_n)-1`; otherwise, `d_i` is larger than this value. INPUT: @@ -1114,7 +1114,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): sage: M.row_degrees(shifts=[-2,1,2]) [2, 1, -3] - The row degrees of an empty matrix ($0\times n$ or $m\times 0$) is + The row degrees of an empty matrix (`0\times n` or `m\times 0`) is not defined:: sage: M = Matrix( pR, 0, 3 ) @@ -1144,15 +1144,15 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): r""" Return the (shifted) column degrees of this matrix. - For a given polynomial matrix $M = (M_{i,j})_{i,j}$ with $m$ rows and - $n$ columns, its column degrees is the tuple $(d_1,\ldots,d_n)$ where - $d_j = \max_i(\deg(M_{i,j}))$ for $1\leq j \leq n$. Thus, $d_j=-1$ if - the $j$-th column of $M$ is zero, and $d_j \geq 0$ otherwise. + For a given polynomial matrix `M = (M_{i,j})_{i,j}` with `m` rows and + `n` columns, its column degrees is the tuple `(d_1,\ldots,d_n)` where + `d_j = \max_i(\deg(M_{i,j}))` for `1\leq j \leq n`. Thus, `d_j=-1` if + the `j`-th column of `M` is zero, and `d_j \geq 0` otherwise. - For given shifts $s_1,\ldots,s_m \in \ZZ$, the shifted column degrees of - $M$ is $(d_1,\ldots,d_n)$ where $d_j = \max_i(\deg(M_{i,j})+s_i)$. - Here, if the $j$-th column of $M$ is zero then $d_j = - \min(s_1,\ldots,s_m)-1$; otherwise $d_j$ is larger than this value. + For given shifts `s_1,\ldots,s_m \in \ZZ`, the shifted column degrees of + `M` is `(d_1,\ldots,d_n)` where `d_j = \max_i(\deg(M_{i,j})+s_i)`. + Here, if the `j`-th column of `M` is zero then `d_j = + \min(s_1,\ldots,s_m)-1`; otherwise `d_j` is larger than this value. INPUT: @@ -1177,7 +1177,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): sage: M.column_degrees(shifts=[-2,1]) [4, -3, -2] - The column degrees of an empty matrix ($0\times n$ or $m\times 0$) is + The column degrees of an empty matrix (`0\times n` or `m\times 0`) is not defined:: sage: M = Matrix( pR, 0, 3 ) @@ -1211,22 +1211,22 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): r""" Return the (shifted) leading matrix of this matrix. - Let $M$ be a univariate polynomial matrix in $\Bold{K}[x]^{m \times - n}$. Working row-wise and without shifts, its leading matrix is the - matrix in $\Bold{K}^{m \times n}$ formed by the leading coefficients of - the entries of $M$ which reach the degree of the corresponding row. + Let `M` be a univariate polynomial matrix in `\Bold{K}[x]^{m \times + n}`. Working row-wise and without shifts, its leading matrix is the + matrix in `\Bold{K}^{m \times n}` formed by the leading coefficients of + the entries of `M` which reach the degree of the corresponding row. - More precisely, if working row-wise, let $s_1,\ldots,s_n \in \ZZ$ - be a shift, and let $(d_1,\ldots,d_m)$ denote the shifted row degrees of - $M$. Then, the shifted leading matrix of $M$ is the matrix in - $\Bold{K}^{m \times n}$ whose entry $i,j$ is the coefficient of degree - $d_i-s_j$ of the entry $i,j$ of $M$. - - If working column-wise, let $s_1,\ldots,s_m \in \ZZ$ be a shift, - and let $(d_1,\ldots,d_n)$ denote the shifted column degrees of $M$. - Then, the shifted leading matrix of $M$ is the matrix in $\Bold{K}^{m - \times n}$ whose entry $i,j$ is the coefficient of degree $d_j-s_i$ of - the entry $i,j$ of $M$. + More precisely, if working row-wise, let `s_1,\ldots,s_n \in \ZZ` + be a shift, and let `(d_1,\ldots,d_m)` denote the shifted row degrees of + `M`. Then, the shifted leading matrix of `M` is the matrix in + `\Bold{K}^{m \times n}` whose entry `i,j` is the coefficient of degree + `d_i-s_j` of the entry `i,j` of `M`. + + If working column-wise, let `s_1,\ldots,s_m \in \ZZ` be a shift, + and let `(d_1,\ldots,d_n)` denote the shifted column degrees of `M`. + Then, the shifted leading matrix of `M` is the matrix in `\Bold{K}^{m + \times n}` whose entry `i,j` is the coefficient of degree `d_j-s_i` of + the entry `i,j` of `M`. INPUT: @@ -1296,12 +1296,12 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): def _is_empty_popov(self, row_wise=True, include_zero_vectors=True): r""" - Assuming that this matrix is empty, that is, of dimensions $0\times n$ - or $m\times 0$, return a boolean indicating if it is in shifted Popov + Assuming that this matrix is empty, that is, of dimensions `0\times n` + or `m\times 0`, return a boolean indicating if it is in shifted Popov form. If zero vectors are allowed in shifted reduced forms, this always returns true. Otherwise, by convention and if working row-wise, for - $n\geq 0$ the $0\times n$ matrix is in shifted Popov form for all - shifts, and for $m>0$ the $m \times 0$ matrix is not in shifted Popov + `n\geq 0` the `0\times n` matrix is in shifted Popov form for all + shifts, and for `m>0` the `m \times 0` matrix is not in shifted Popov form for any shift. The convention is similar if working column-wise. The behaviour of this method for non-empty matrices is not defined. @@ -1355,18 +1355,18 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): Return a boolean indicating whether this matrix is in (shifted) reduced form. - An $m \times n$ univariate polynomial matrix $M$ is said to be in - shifted row reduced form if it has $k$ nonzero rows with $k \leq n$ and - its shifted leading matrix has rank $k$. Equivalently, when considering - all the matrices obtained by left-multiplying $M$ by a unimodular - matrix, then the shifted row degrees of $M$ -- once sorted in + An `m \times n` univariate polynomial matrix `M` is said to be in + shifted row reduced form if it has `k` nonzero rows with `k \leq n` and + its shifted leading matrix has rank `k`. Equivalently, when considering + all the matrices obtained by left-multiplying `M` by a unimodular + matrix, then the shifted row degrees of `M` -- once sorted in nondecreasing order -- is lexicographically minimal. - Similarly, $M$ is said to be in shifted column reduced form if it has - $k$ nonzero columns with $k \leq m$ and its shifted leading matrix has - rank $k$. + Similarly, `M` is said to be in shifted column reduced form if it has + `k` nonzero columns with `k \leq m` and its shifted leading matrix has + rank `k`. - Sometimes, one forbids $M$ to have zero rows (resp. columns) in the + Sometimes, one forbids `M` to have zero rows (resp. columns) in the above definitions; an optional parameter allows one to adopt this more restrictive setting. @@ -1435,15 +1435,15 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): Return the (shifted) leading positions (also known as the pivot indices), and optionally the (shifted) pivot degrees of this matrix. - If working row-wise, for a given shift $s_1,\ldots,s_n \in - \ZZ$, taken as $(0,\ldots,0)$ by default, and a row vector of - univariate polynomials $[p_1,\ldots,p_n]$, the leading position of - this vector is the index $j$ of the rightmost nonzero entry $p_j$ such - that $\deg(p_j) + s_j$ is equal to the shifted row degree of the vector. - Then the pivot degree of the vector is the degree $\deg(p_j)$. + If working row-wise, for a given shift `s_1,\ldots,s_n \in + \ZZ`, taken as `(0,\ldots,0)` by default, and a row vector of + univariate polynomials `[p_1,\ldots,p_n]`, the leading position of + this vector is the index `j` of the rightmost nonzero entry `p_j` such + that `\deg(p_j) + s_j` is equal to the shifted row degree of the vector. + Then the pivot degree of the vector is the degree `\deg(p_j)`. - For the zero row, both the leading positions and degree are $-1$. For - a $m \times n$ polynomial matrix, the leading positions and pivot + For the zero row, both the leading positions and degree are `-1`. For + a `m \times n` polynomial matrix, the leading positions and pivot degrees are the two lists containing the leading positions and the pivot degrees of its rows. @@ -1498,8 +1498,8 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): sage: M.leading_positions(shifts=[2,0], row_wise=False,return_degree=True) ([1, -1, 0], [3, -1, 0]) - The leading positions and pivot degrees of an empty matrix ($0\times n$ - or $m\times 0$) is not defined:: + The leading positions and pivot degrees of an empty matrix (`0\times n` + or `m\times 0`) is not defined:: sage: M = Matrix( pR, 0, 3 ) sage: M.leading_positions() @@ -1834,9 +1834,9 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): the matrix, and in each nonzero row the pivot (leftmost nonzero entry) is strictly to the right of the pivot of the row just above this row. - Note that, for any integer $d$ strictly greater than all degrees + Note that, for any integer `d` strictly greater than all degrees appearing in the Hermite form, then the Hermite form coincides with the - shifted Popov form with the shifts $((n-1)d,\ldots,2d,d,0)$, where $n$ + shifted Popov form with the shifts `((n-1)d,\ldots,2d,d,0)`, where `n` is the column dimension. If working column-wise, a polynomial matrix is said to be in Hermite @@ -1932,8 +1932,8 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): Return a (shifted) (ordered) weak Popov form of this matrix. See :meth:`is_weak_popov` for a definition of weak Popov forms. If the - input matrix is $A$, a weak Popov form of $A$ is any matrix $P$ in weak - Popov form and such that $UA = P$ for some unimodular matrix $U$. The + input matrix is `A`, a weak Popov form of `A` is any matrix `P` in weak + Popov form and such that `UA = P` for some unimodular matrix `U`. The latter matrix is called the transformation, and the first optional argument allows one to specify whether to return this transformation. @@ -2230,9 +2230,9 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): Return the (shifted) Popov form of this matrix. See :meth:`is_popov` for a definition of Popov forms. If the input - matrix is $A$, the (shifted) Popov form of $A$ is the unique matrix $P$ - in (shifted) Popov form and such that $UA = P$ for some unimodular - matrix $U$. The latter matrix is called the transformation, and the + matrix is `A`, the (shifted) Popov form of `A` is the unique matrix `P` + in (shifted) Popov form and such that `UA = P` for some unimodular + matrix `U`. The latter matrix is called the transformation, and the first optional argument allows one to specify whether to return this transformation. We refer to the description of :meth:`weak_popov_form` for an explanation of the option ``include_zero_vectors`` . @@ -2424,9 +2424,9 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): Return a row reduced form of this matrix (resp. a column reduced form if the optional parameter ``row_wise`` is set to ``False``). - An $m \times n$ univariate polynomial matrix $M$ is said to be in - (shifted) row reduced form if it has $k$ nonzero rows with $k \leq n$ - and its (shifted) leading matrix has rank $k$. See :meth:`is_reduced` + An `m \times n` univariate polynomial matrix `M` is said to be in + (shifted) row reduced form if it has `k` nonzero rows with `k \leq n` + and its (shifted) leading matrix has rank `k`. See :meth:`is_reduced` for more information. Currently, the implementation of this method is a direct call to @@ -2548,8 +2548,8 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): Return the Hermite form of this matrix. See :meth:`is_hermite` for a definition of Hermite forms. If the input - is a matrix $A$, then its Hermite form is the unique matrix $H$ in Hermite - form such that $UA = H$ for some unimodular matrix $U$. + is a matrix `A`, then its Hermite form is the unique matrix `H` in Hermite + form such that `UA = H` for some unimodular matrix `U`. INPUT: From 9fa71012bd6bb05fef4d5e53acb95f64a612c7f2 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Mon, 13 Jun 2022 09:30:58 +0900 Subject: [PATCH 102/116] Add missing title to conf.py --- .gitignore | 1 + src/sage_docbuild/conf.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/.gitignore b/.gitignore index 1c92edd7e12..59b7fb8b9e4 100644 --- a/.gitignore +++ b/.gitignore @@ -187,6 +187,7 @@ build/bin/sage-build-env-config # Generated by docbuild /src/doc/en/reference/*/sage +/src/doc/en/reference/*/sage_docbuild /src/doc/en/reference/sage /src/doc/en/reference/spkg/*.rst /src/doc/output diff --git a/src/sage_docbuild/conf.py b/src/sage_docbuild/conf.py index c0866c0af75..f8268444f4f 100644 --- a/src/sage_docbuild/conf.py +++ b/src/sage_docbuild/conf.py @@ -1,3 +1,20 @@ +r""" +Sphinx build configuration + +This file contains configuration needed to customize Sphinx input and output +behavior. +""" + +# **************************************************************************** +# Copyright (C) 2022 Kwankyu Lee +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + import importlib import sys import os From 818410f0f4c4b14e14741e0c7b4fe2aabac8ba61 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 13 Feb 2022 16:11:29 -0500 Subject: [PATCH 103/116] Trac #33213: replace SAGE_TMP in the isgci database download routine. ...and make it work on python3. The database download requires internet access and isn't tested by default. As a result, it lay broken for a while -- the local file needs to be opened in binary mode to write the bytes returned by urlopen(). --- src/sage/graphs/isgci.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/sage/graphs/isgci.py b/src/sage/graphs/isgci.py index 69858727ee7..ac6b3d15605 100644 --- a/src/sage/graphs/isgci.py +++ b/src/sage/graphs/isgci.py @@ -826,22 +826,20 @@ def _download_db(self): sage: graph_classes._download_db() # Not tested -- requires internet """ - from sage.misc.misc import SAGE_TMP + import tempfile u = urlopen('https://www.graphclasses.org/data.zip', - context=default_context()) - localFile = open(os.path.join(SAGE_TMP, 'isgci.zip'), 'w') - localFile.write(u.read()) - localFile.close() - z = zipfile.ZipFile(os.path.join(SAGE_TMP, 'isgci.zip')) - - # Save a systemwide updated copy whenever possible - - try: - z.extract(_XML_FILE, GRAPHS_DATA_DIR) - z.extract(_SMALLGRAPHS_FILE, GRAPHS_DATA_DIR) - except IOError: - z.extract(_XML_FILE, SAGE_TMP) - z.extract(_SMALLGRAPHS_FILE, GRAPHS_DATA_DIR) + context=SSLContext()) + with tempfile.NamedTemporaryFile(suffix=".zip") as f: + f.write(u.read()) + z = zipfile.ZipFile(f.name) + + # Save a systemwide updated copy whenever possible + try: + z.extract(_XML_FILE, GRAPHS_DATA_DIR) + z.extract(_SMALLGRAPHS_FILE, GRAPHS_DATA_DIR) + except IOError: + z.extract(_XML_FILE, d) + z.extract(_SMALLGRAPHS_FILE, GRAPHS_DATA_DIR) def _parse_db(self, directory): r""" From 71c93257a890243480177145bfad474e3a94e1de Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 13 Feb 2022 20:11:04 -0500 Subject: [PATCH 104/116] Trac #33213: replace SAGE_TMP in GLPK graph backend doctests. --- .../numerical/backends/glpk_graph_backend.pyx | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/sage/numerical/backends/glpk_graph_backend.pyx b/src/sage/numerical/backends/glpk_graph_backend.pyx index 564c108fdf4..877b45c2ed3 100644 --- a/src/sage/numerical/backends/glpk_graph_backend.pyx +++ b/src/sage/numerical/backends/glpk_graph_backend.pyx @@ -160,11 +160,12 @@ cdef class GLPKGraphBackend(): sage: gbe.add_vertices([None, None]) ['0', '1'] sage: a = gbe.add_edge('0', '1') - sage: gbe.write_graph(SAGE_TMP+"/graph.txt") + sage: import tempfile + sage: with tempfile.NamedTemporaryFile() as f: + ....: _ = gbe.write_graph(f.name) + ....: gbe1 = GLPKGraphBackend(f.name, "plain") Writing graph to ... 4 lines were written - 0 - sage: gbe1 = GLPKGraphBackend(SAGE_TMP+"/graph.txt", "plain") Reading graph from ... Graph has 2 vertices and 1 edge 3 lines were read @@ -1048,7 +1049,9 @@ cdef class GLPKGraphBackend(): sage: from sage.numerical.backends.glpk_graph_backend import GLPKGraphBackend sage: gbe = GLPKGraphBackend() sage: a = gbe.add_edge("0", "1") - sage: gbe.write_graph(SAGE_TMP+"/graph.txt") + sage: import tempfile + sage: with tempfile.NamedTemporaryFile() as f: + ....: gbe.write_graph(f.name) Writing graph to ... 4 lines were written 0 @@ -1078,7 +1081,9 @@ cdef class GLPKGraphBackend(): sage: from sage.numerical.backends.glpk_graph_backend import GLPKGraphBackend sage: gbe = GLPKGraphBackend() sage: a = gbe.add_edge("0", "1") - sage: gbe.write_ccdata(SAGE_TMP+"/graph.dat") + sage: import tempfile + sage: with tempfile.NamedTemporaryFile() as f: + ....: gbe.write_ccdata(f.name) Writing graph to ... 6 lines were written 0 @@ -1104,7 +1109,9 @@ cdef class GLPKGraphBackend(): sage: from sage.numerical.backends.glpk_graph_backend import GLPKGraphBackend sage: gbe = GLPKGraphBackend() sage: a = gbe.add_edge("0", "1") - sage: gbe.write_mincost(SAGE_TMP+"/graph.min") + sage: import tempfile + sage: with tempfile.NamedTemporaryFile() as f: + ....: gbe.write_mincost(f.name) Writing min-cost flow problem data to ... 4 lines were written 0 @@ -1200,20 +1207,23 @@ cdef class GLPKGraphBackend(): sage: from sage.numerical.backends.glpk_graph_backend import GLPKGraphBackend sage: gbe = GLPKGraphBackend() + sage: import tempfile + sage: with tempfile.NamedTemporaryFile() as f: + ....: gbe.write_maxflow(f.name) + Traceback (most recent call last): + ... + OSError: Cannot write empty graph sage: gbe.add_vertices([None for i in range(2)]) ['0', '1'] sage: a = gbe.add_edge('0', '1') sage: gbe.maxflow_ffalg('0', '1') 0.0 - sage: gbe.write_maxflow(SAGE_TMP+"/graph.max") + sage: with tempfile.NamedTemporaryFile() as f: + ....: gbe.write_maxflow(f.name) Writing maximum flow problem data to ... 6 lines were written 0 - sage: gbe = GLPKGraphBackend() - sage: gbe.write_maxflow(SAGE_TMP+"/graph.max") - Traceback (most recent call last): - ... - OSError: Cannot write empty graph + """ if self.graph.nv <= 0: From 08213fa71416b2f41936097bcb7379dc1e1c4ff0 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 13 Feb 2022 12:50:45 -0500 Subject: [PATCH 105/116] Trac #33213: replace SAGE_TMP in graph doctests. --- src/sage/graphs/bipartite_graph.py | 53 ++++++++++++++++-------------- src/sage/graphs/generic_graph.py | 6 ++-- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index 2ec92b073a1..2d421accf32 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -245,14 +245,15 @@ class BipartiteGraph(Graph): #. From an alist file:: - sage: file_name = os.path.join(SAGE_TMP, 'deleteme.alist.txt') - sage: fi = open(file_name, 'w') - sage: _ = fi.write("7 4 \n 3 4 \n 3 3 1 3 1 1 1 \n 3 3 3 4 \n\ - 1 2 4 \n 1 3 4 \n 1 0 0 \n 2 3 4 \n\ - 2 0 0 \n 3 0 0 \n 4 0 0 \n\ - 1 2 3 0 \n 1 4 5 0 \n 2 4 6 0 \n 1 2 4 7 \n") - sage: fi.close() - sage: B = BipartiteGraph(file_name) + sage: import tempfile + sage: with tempfile.NamedTemporaryFile(mode="w+t") as f: + ....: _ = f.write("7 4 \n 3 4 \n 3 3 1 3 1 1 1 \n\ + ....: 3 3 3 4 \n 1 2 4 \n 1 3 4 \n 1 0 0 \n\ + ....: 2 3 4 \n 2 0 0 \n 3 0 0 \n 4 0 0 \n\ + ....: 1 2 3 0 \n 1 4 5 0 \n 2 4 6 0 \n\ + ....: 1 2 4 7 \n") + ....: f.flush() + ....: B = BipartiteGraph(f.name) sage: B.is_isomorphic(H) True @@ -1487,15 +1488,17 @@ def load_afile(self, fname): EXAMPLES:: - sage: file_name = os.path.join(SAGE_TMP, 'deleteme.alist.txt') - sage: fi = open(file_name, 'w') - sage: _ = fi.write("7 4 \n 3 4 \n 3 3 1 3 1 1 1 \n 3 3 3 4 \n\ - 1 2 4 \n 1 3 4 \n 1 0 0 \n 2 3 4 \n\ - 2 0 0 \n 3 0 0 \n 4 0 0 \n\ - 1 2 3 0 \n 1 4 5 0 \n 2 4 6 0 \n 1 2 4 7 \n") - sage: fi.close() - sage: B = BipartiteGraph() - sage: B.load_afile(file_name) + sage: import tempfile + sage: with tempfile.NamedTemporaryFile(mode="w+t") as f: + ....: _ = f.write("7 4 \n 3 4 \n 3 3 1 3 1 1 1 \n\ + ....: 3 3 3 4 \n 1 2 4 \n 1 3 4 \n\ + ....: 1 0 0 \n 2 3 4 \n 2 0 0 \n 3 0 0 \n\ + ....: 4 0 0 \n 1 2 3 0 \n 1 4 5 0 \n\ + ....: 2 4 6 0 \n 1 2 4 7 \n") + ....: f.flush() + ....: B = BipartiteGraph() + ....: B2 = BipartiteGraph(f.name) + ....: B.load_afile(f.name) Bipartite graph on 11 vertices sage: B.edges() [(0, 7, None), @@ -1511,7 +1514,6 @@ def load_afile(self, fname): (4, 8, None), (5, 9, None), (6, 10, None)] - sage: B2 = BipartiteGraph(file_name) sage: B2 == B True """ @@ -1582,15 +1584,17 @@ def save_afile(self, fname): [0 1 0 1 0 1 0] [1 1 0 1 0 0 1] sage: b = BipartiteGraph(M) - sage: file_name = os.path.join(SAGE_TMP, 'deleteme.alist.txt') - sage: b.save_afile(file_name) - sage: b2 = BipartiteGraph(file_name) + sage: import tempfile + sage: with tempfile.NamedTemporaryFile() as f: + ....: b.save_afile(f.name) + ....: b2 = BipartiteGraph(f.name) sage: b.is_isomorphic(b2) True TESTS:: - sage: file_name = os.path.join(SAGE_TMP, 'deleteme.alist.txt') + sage: import tempfile + sage: f = tempfile.NamedTemporaryFile() sage: for order in range(3, 13, 3): ....: num_chks = int(order / 3) ....: num_vars = order - num_chks @@ -1599,8 +1603,8 @@ def save_afile(self, fname): ....: g = graphs.RandomGNP(order, 0.5) ....: try: ....: b = BipartiteGraph(g, partition, check=False) - ....: b.save_afile(file_name) - ....: b2 = BipartiteGraph(file_name) + ....: b.save_afile(f.name) + ....: b2 = BipartiteGraph(f.name) ....: if not b.is_isomorphic(b2): ....: print("Load/save failed for code with edges:") ....: print(b.edges()) @@ -1610,6 +1614,7 @@ def save_afile(self, fname): ....: print("with edges: ") ....: g.edges() ....: raise + sage: f.close() # this removes the file """ # open the file try: diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 5cc9122c7f0..6f282621c46 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -21514,9 +21514,9 @@ def graphviz_to_file_named(self, filename, **options): EXAMPLES:: sage: G = Graph({0: {1: None, 2: None}, 1: {0: None, 2: None}, 2: {0: None, 1: None, 3: 'foo'}, 3: {2: 'foo'}}, sparse=True) - sage: tempfile = os.path.join(SAGE_TMP, 'temp_graphviz') - sage: G.graphviz_to_file_named(tempfile, edge_labels=True) - sage: with open(tempfile) as f: + sage: import tempfile + sage: with tempfile.NamedTemporaryFile(mode="a+t") as f: + ....: G.graphviz_to_file_named(f.name, edge_labels=True) ....: print(f.read()) graph { node_0 [label="0"]; From 976f0d686ee5375ed3894009a13b2cd54fcd89f2 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Fri, 10 Jun 2022 23:24:55 +0100 Subject: [PATCH 106/116] remove crud after except, make it pass --- src/sage/graphs/isgci.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sage/graphs/isgci.py b/src/sage/graphs/isgci.py index ac6b3d15605..811ce322156 100644 --- a/src/sage/graphs/isgci.py +++ b/src/sage/graphs/isgci.py @@ -838,8 +838,7 @@ def _download_db(self): z.extract(_XML_FILE, GRAPHS_DATA_DIR) z.extract(_SMALLGRAPHS_FILE, GRAPHS_DATA_DIR) except IOError: - z.extract(_XML_FILE, d) - z.extract(_SMALLGRAPHS_FILE, GRAPHS_DATA_DIR) + pass def _parse_db(self, directory): r""" From 4610b1c97f8c09e9b0a502491102d0e52448a19e Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 13 Feb 2022 20:33:45 -0500 Subject: [PATCH 107/116] Trac #33213: replace ECL_TMP (based on SAGE_TMP) in maxima/ecl interfaces. We have historically massaged TMPDIR and TMP when interfacing with ECL to ensure that SAGE_TMP was used consistently for temporary files. Simply removing this code seems to do the trick, since ECL wants to use the system location by default. The existing ECL_TMP path is marked with a deprecation warning. --- src/sage/interfaces/maxima.py | 2 -- src/sage/interfaces/maxima_abstract.py | 2 -- src/sage/libs/ecl.pyx | 6 ------ src/sage/misc/misc.py | 17 +++++++++++++---- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/sage/interfaces/maxima.py b/src/sage/interfaces/maxima.py index 5044771eb7d..a05b4995cac 100644 --- a/src/sage/interfaces/maxima.py +++ b/src/sage/interfaces/maxima.py @@ -496,7 +496,6 @@ from random import randrange from sage.env import MAXIMA -from sage.misc.misc import ECL_TMP from .expect import (Expect, ExpectElement, gc_disabled) @@ -570,7 +569,6 @@ def __init__(self, script_subdirectory=None, logfile=None, server=None, name = 'maxima', prompt = r'\(\%i[0-9]+\) ', command = '{0} -p {1}'.format(MAXIMA, shlex.quote(STARTUP)), - env = {'TMPDIR': str(ECL_TMP)}, script_subdirectory = script_subdirectory, restart_on_ctrlc = False, verbose_start = False, diff --git a/src/sage/interfaces/maxima_abstract.py b/src/sage/interfaces/maxima_abstract.py index 14cf31e9b98..3c563149393 100644 --- a/src/sage/interfaces/maxima_abstract.py +++ b/src/sage/interfaces/maxima_abstract.py @@ -59,7 +59,6 @@ from sage.cpython.string import bytes_to_str -from sage.misc.misc import ECL_TMP from sage.misc.multireplace import multiple_replace from sage.structure.richcmp import richcmp, rich_to_bool @@ -166,7 +165,6 @@ def _command_runner(self, command, s, redirect=True): """ cmd = '{} --very-quiet --batch-string="{}({});" '.format(MAXIMA, command, s) env = os.environ.copy() - env['TMPDIR'] = str(ECL_TMP) if redirect: res = bytes_to_str(subprocess.check_output(cmd, shell=True, diff --git a/src/sage/libs/ecl.pyx b/src/sage/libs/ecl.pyx index 22730718183..2cfac57f544 100644 --- a/src/sage/libs/ecl.pyx +++ b/src/sage/libs/ecl.pyx @@ -21,7 +21,6 @@ from posix.signal cimport sigaction, sigaction_t cimport cysignals.signals from sage.libs.gmp.types cimport mpz_t -from sage.misc.misc import ECL_TMP from sage.cpython.string cimport str_to_bytes, char_to_str from sage.rings.integer cimport Integer from sage.rings.rational cimport Rational @@ -273,11 +272,6 @@ def init_ecl(): list_of_objects=cl_cons(ECL_NIL,cl_cons(ECL_NIL,ECL_NIL)) cl_set(string_to_object(b"*SAGE-LIST-OF-OBJECTS*"), list_of_objects) - cl_eval(string_to_object(b""" - (setf (logical-pathname-translations "TMP") - '(("**;*.*" "%s/**/*.*"))) - """ % str_to_bytes(str(ECL_TMP)))) - # We define our own error catching eval, apply and funcall/ # Presently these routines are only converted to byte-code. If they # ever turn out to be a bottle neck, it should be easy to properly diff --git a/src/sage/misc/misc.py b/src/sage/misc/misc.py index da354511413..5c6504e39b7 100644 --- a/src/sage/misc/misc.py +++ b/src/sage/misc/misc.py @@ -239,11 +239,20 @@ def ECL_TMP(): sage: from sage.misc.misc import ECL_TMP sage: ECL_TMP - l'.../temp/.../ecl' + doctest:warning... + DeprecationWarning: ECL_TMP is deprecated and is no longer used + by the ECL interface in sage + See https://trac.sagemath.org/33213 for details. + ... + """ - d = os.path.join(str(SAGE_TMP), 'ecl') - os.makedirs(d, exist_ok=True) - return d + from sage.misc.superseded import deprecation + deprecation(33213, "ECL_TMP is deprecated and is no longer used by the ECL interface in sage") + import atexit, tempfile + d = tempfile.TemporaryDirectory() + result = os.path.join(d.name, 'ecl') + atexit.register(lambda: d.cleanup()) + return result @lazy_string From c79c24d9006b01319f15967c43949f2977057d59 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Mon, 13 Jun 2022 08:04:41 -0700 Subject: [PATCH 108/116] trac 33973: reviewer comments --- src/sage/groups/abelian_gps/dual_abelian_group_element.py | 2 +- src/sage/media/wav.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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 174d1435b68..aaabe107781 100644 --- a/src/sage/groups/abelian_gps/dual_abelian_group_element.py +++ b/src/sage/groups/abelian_gps/dual_abelian_group_element.py @@ -200,7 +200,7 @@ def word_problem(self, words, display=True): [[b^2*c^2*d^3*e^5, 245]] The command e.word_problem([u,v,w,x,y],display=True) returns - the same list but also prints `e = (b^2*c^2*d^3*e^5)^245`. + the same list but also prints ``e = (b^2*c^2*d^3*e^5)^245``. """ ## First convert the problem to one using AbelianGroups import copy diff --git a/src/sage/media/wav.py b/src/sage/media/wav.py index 6252c6080e1..7be09afdf41 100644 --- a/src/sage/media/wav.py +++ b/src/sage/media/wav.py @@ -70,8 +70,8 @@ class Wave(SageObject): Indexing: - Getting the `n^{th}` item in a Wave object will give you the value - of the `n^{th}` frame. + Getting the `n`-th item in a Wave object will give you the value + of the `n`-th frame. """ def __init__(self, data=None, **kwds): if data is not None: From 247381bda6edd12de83b91fd4415a52300b1961d Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Thu, 16 Jun 2022 12:53:57 +0800 Subject: [PATCH 109/116] doc tweaks --- src/sage/schemes/elliptic_curves/ell_field.py | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index c2d26a80ab4..6cd458b0dbf 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -770,24 +770,25 @@ def descend_to(self, K, f=None): def division_field(self, l, names=None, map=False, **kwds): r""" Given an elliptic curve over a number field or finite field `F` - and a prime number `\ell`, construct the field `F(E[\ell])`. + and a prime number `\ell`, construct the `\ell`-division field + `F(E[\ell])`. - INPUT: - - - ``\ell`` -- a prime number (an element of `\ZZ`). + The `\ell`-division field is the smallest extension of `F` over + which all `\ell`-torsion points of `E` are defined. - - ``names`` -- (default: ``t``) a variable name for the division field. - - - ``map`` -- (default: ``False``) also return an embedding of - the :meth:`base_field` into the resulting field. + INPUT: - - ``kwds`` -- additional keywords passed to - :func:`~sage.rings.polynomial.polynomial_element.Polynomial.splitting_field`. + - `\ell` -- a prime number (an element of `\ZZ`) + - ``names`` -- (default: ``t``) a variable name for the division field + - ``map`` -- (default: ``False``) also return an embedding of the + :meth:`base_field` into the resulting field + - ``kwds`` -- additional keyword arguments passed to + :func:`~sage.rings.polynomial.polynomial_element.Polynomial.splitting_field` OUTPUT: - If ``map`` is ``False``, the division field as an absolute number - field or a finite field. + If ``map`` is ``False``, the division field `K` as an absolute + number field or a finite field. If ``map`` is ``True``, a tuple `(K, \phi)` where `\phi` is an embedding of the base field in the division field `K`. @@ -797,8 +798,8 @@ def division_field(self, l, names=None, map=False, **kwds): field is large (e.g. when `\ell` is large or when the Galois representation is surjective). The ``simplify`` flag also has a big influence on the running time over number fields: - sometimes ``simplify=False`` is faster, sometimes - ``simplify=True`` (the default) is faster. + sometimes ``simplify=False`` is faster, sometimes the default + ``simplify=True`` is faster. EXAMPLES: From 3be7fe8c681169cbc9d0e0e9efe1db6ff87d5863 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Thu, 16 Jun 2022 12:55:37 +0800 Subject: [PATCH 110/116] move default value to argument list, where it belongs --- src/sage/schemes/elliptic_curves/ell_field.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index 6cd458b0dbf..d7801e940be 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -767,7 +767,7 @@ def descend_to(self, K, f=None): Elist = [E.minimal_model() for E in Elist] return Elist - def division_field(self, l, names=None, map=False, **kwds): + def division_field(self, l, names='t', map=False, **kwds): r""" Given an elliptic curve over a number field or finite field `F` and a prime number `\ell`, construct the `\ell`-division field @@ -779,7 +779,7 @@ def division_field(self, l, names=None, map=False, **kwds): INPUT: - `\ell` -- a prime number (an element of `\ZZ`) - - ``names`` -- (default: ``t``) a variable name for the division field + - ``names`` -- (default: ``'t'``) a variable name for the division field - ``map`` -- (default: ``False``) also return an embedding of the :meth:`base_field` into the resulting field - ``kwds`` -- additional keyword arguments passed to @@ -964,9 +964,6 @@ def division_field(self, l, names=None, map=False, **kwds): if not l.is_prime(): raise ValueError("l must be a prime number") - if names is None: - names = 't' - verbose("Adjoining X-coordinates of %s-torsion points" % l) F = self.base_ring() f = self.division_polynomial(l) From 9a82ed8168794501d7979c5f94c86b8c8d36072a Mon Sep 17 00:00:00 2001 From: DavidAyotte Date: Thu, 16 Jun 2022 11:08:34 -0400 Subject: [PATCH 111/116] sage/modular/modform/ring.py: fix mistake and format docstrings --- src/sage/modular/modform/ring.py | 78 ++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 28 deletions(-) diff --git a/src/sage/modular/modform/ring.py b/src/sage/modular/modform/ring.py index 52b6185b37a..e6fc11c739e 100644 --- a/src/sage/modular/modform/ring.py +++ b/src/sage/modular/modform/ring.py @@ -161,19 +161,19 @@ class ModularFormsRing(Parent): True sage: m.generators() [(2, 1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^10)), - (2, q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10))] + (2, q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10))] sage: m.q_expansion_basis(2,10) [1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^10), - q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10)] + q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10)] sage: m.q_expansion_basis(3,10) [] sage: m.q_expansion_basis(10,10) [1 + 10560*q^6 + 3960*q^8 + O(q^10), - q - 8056*q^7 - 30855*q^9 + O(q^10), - q^2 - 796*q^6 - 8192*q^8 + O(q^10), - q^3 + 66*q^7 + 832*q^9 + O(q^10), - q^4 + 40*q^6 + 528*q^8 + O(q^10), - q^5 + 20*q^7 + 190*q^9 + O(q^10)] + q - 8056*q^7 - 30855*q^9 + O(q^10), + q^2 - 796*q^6 - 8192*q^8 + O(q^10), + q^3 + 66*q^7 + 832*q^9 + O(q^10), + q^4 + 40*q^6 + 528*q^8 + O(q^10), + q^5 + 20*q^7 + 190*q^9 + O(q^10)] Elements of modular forms ring can be initiated via multivariate polynomials (see :meth:`from_polynomial`):: @@ -250,7 +250,7 @@ def some_elements(self): sage: ModularFormsRing(1).some_elements() [1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6), - 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)] + 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)] """ return [self(f) for f in self.gen_forms()] @@ -365,8 +365,8 @@ def _generators_variables_dictionnary(self, poly_parent, gens): sage: P = QQ['x, y, z'] sage: M._generators_variables_dictionnary(P, M.gen_forms()) {z: q^2 - 2*q^3 + 3*q^4 + O(q^6), - y: q + 5*q^3 - 2*q^4 + 6*q^5 + O(q^6), - x: 1 + 24*q^3 + O(q^6)} + y: q + 5*q^3 - 2*q^4 + 6*q^5 + O(q^6), + x: 1 + 24*q^3 + O(q^6)} """ if poly_parent.base_ring() != self.base_ring(): raise ValueError('the base ring of `poly_parent` must be the same as the base ring of the modular forms ring') @@ -675,18 +675,22 @@ def generators(self, maxweight=8, prec=10, start_gens=[], start_weight=2): EXAMPLES:: sage: ModularFormsRing(SL2Z).generators() - [(4, 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + 60480*q^6 + 82560*q^7 + 140400*q^8 + 181680*q^9 + O(q^10)), (6, 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 - 4058208*q^6 - 8471232*q^7 - 17047800*q^8 - 29883672*q^9 + O(q^10))] + [(4, 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + 60480*q^6 + 82560*q^7 + 140400*q^8 + 181680*q^9 + O(q^10)), + (6, 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 - 4058208*q^6 - 8471232*q^7 - 17047800*q^8 - 29883672*q^9 + O(q^10))] sage: s = ModularFormsRing(SL2Z).generators(maxweight=5, prec=3); s [(4, 1 + 240*q + 2160*q^2 + O(q^3))] sage: s[0][1].parent() Power Series Ring in q over Rational Field sage: ModularFormsRing(1).generators(prec=4) - [(4, 1 + 240*q + 2160*q^2 + 6720*q^3 + O(q^4)), (6, 1 - 504*q - 16632*q^2 - 122976*q^3 + O(q^4))] + [(4, 1 + 240*q + 2160*q^2 + 6720*q^3 + O(q^4)), + (6, 1 - 504*q - 16632*q^2 - 122976*q^3 + O(q^4))] sage: ModularFormsRing(2).generators(prec=12) - [(2, 1 + 24*q + 24*q^2 + 96*q^3 + 24*q^4 + 144*q^5 + 96*q^6 + 192*q^7 + 24*q^8 + 312*q^9 + 144*q^10 + 288*q^11 + O(q^12)), (4, 1 + 240*q^2 + 2160*q^4 + 6720*q^6 + 17520*q^8 + 30240*q^10 + O(q^12))] + [(2, 1 + 24*q + 24*q^2 + 96*q^3 + 24*q^4 + 144*q^5 + 96*q^6 + 192*q^7 + 24*q^8 + 312*q^9 + 144*q^10 + 288*q^11 + O(q^12)), + (4, 1 + 240*q^2 + 2160*q^4 + 6720*q^6 + 17520*q^8 + 30240*q^10 + O(q^12))] sage: ModularFormsRing(4).generators(maxweight=2, prec=20) - [(2, 1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + 144*q^10 + 96*q^12 + 192*q^14 + 24*q^16 + 312*q^18 + O(q^20)), (2, q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + 12*q^11 + 14*q^13 + 24*q^15 + 18*q^17 + 20*q^19 + O(q^20))] + [(2, 1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + 144*q^10 + 96*q^12 + 192*q^14 + 24*q^16 + 312*q^18 + O(q^20)), + (2, q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + 12*q^11 + 14*q^13 + 24*q^15 + 18*q^17 + 20*q^19 + O(q^20))] Here we see that for ``\Gamma_0(11)`` taking a basis of forms in weights 2 and 4 is enough to generate everything up to weight 12 (and probably @@ -709,16 +713,27 @@ def generators(self, maxweight=8, prec=10, start_gens=[], start_weight=2): sage: ModularFormsRing(Gamma1(4)).generators(prec=10, maxweight=10) [(2, 1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^10)), - (2, q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10)), - (3, 1 + 12*q^2 + 64*q^3 + 60*q^4 + 160*q^6 + 384*q^7 + 252*q^8 + O(q^10)), - (3, q + 4*q^2 + 8*q^3 + 16*q^4 + 26*q^5 + 32*q^6 + 48*q^7 + 64*q^8 + 73*q^9 + O(q^10))] + (2, q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10)), + (3, 1 + 12*q^2 + 64*q^3 + 60*q^4 + 160*q^6 + 384*q^7 + 252*q^8 + O(q^10)), + (3, q + 4*q^2 + 8*q^3 + 16*q^4 + 26*q^5 + 32*q^6 + 48*q^7 + 64*q^8 + 73*q^9 + O(q^10))] Using different base rings will change the generators:: sage: ModularFormsRing(Gamma0(13)).generators(maxweight=12, prec=4) - [(2, 1 + 2*q + 6*q^2 + 8*q^3 + O(q^4)), (4, 1 + O(q^4)), (4, q + O(q^4)), (4, q^2 + O(q^4)), (4, q^3 + O(q^4)), (6, 1 + O(q^4)), (6, q + O(q^4))] + [(2, 1 + 2*q + 6*q^2 + 8*q^3 + O(q^4)), + (4, 1 + O(q^4)), (4, q + O(q^4)), + (4, q^2 + O(q^4)), (4, q^3 + O(q^4)), + (6, 1 + O(q^4)), + (6, q + O(q^4))] sage: ModularFormsRing(Gamma0(13),base_ring=ZZ).generators(maxweight=12, prec=4) - [(2, 1 + 2*q + 6*q^2 + 8*q^3 + O(q^4)), (4, q + 4*q^2 + 10*q^3 + O(q^4)), (4, 2*q^2 + 5*q^3 + O(q^4)), (4, q^2 + O(q^4)), (4, -2*q^3 + O(q^4)), (6, O(q^4)), (6, O(q^4)), (12, O(q^4))] + [(2, 1 + 2*q + 6*q^2 + 8*q^3 + O(q^4)), + (4, q + 4*q^2 + 10*q^3 + O(q^4)), + (4, 2*q^2 + 5*q^3 + O(q^4)), + (4, q^2 + O(q^4)), + (4, -2*q^3 + O(q^4)), + (6, O(q^4)), + (6, O(q^4)), + (12, O(q^4))] sage: [k for k,f in ModularFormsRing(1, QQ).generators(maxweight=12)] [4, 6] sage: [k for k,f in ModularFormsRing(1, ZZ).generators(maxweight=12)] @@ -738,7 +753,9 @@ def generators(self, maxweight=8, prec=10, start_gens=[], start_weight=2): sage: f = (M.0 + M.1).qexp(10); f 1 + 17/5*q + 26/5*q^2 + 43/5*q^3 + 94/5*q^4 + 77/5*q^5 + 154/5*q^6 + 86/5*q^7 + 36*q^8 + 146/5*q^9 + O(q^10) sage: ModularFormsRing(11).generators(start_gens = [(2, f)]) - [(2, 1 + 17/5*q + 26/5*q^2 + 43/5*q^3 + 94/5*q^4 + 77/5*q^5 + 154/5*q^6 + 86/5*q^7 + 36*q^8 + 146/5*q^9 + O(q^10)), (2, 1 + 12*q^2 + 12*q^3 + 12*q^4 + 12*q^5 + 24*q^6 + 24*q^7 + 36*q^8 + 36*q^9 + O(q^10)), (4, 1 + O(q^10))] + [(2, 1 + 17/5*q + 26/5*q^2 + 43/5*q^3 + 94/5*q^4 + 77/5*q^5 + 154/5*q^6 + 86/5*q^7 + 36*q^8 + 146/5*q^9 + O(q^10)), + (2, 1 + 12*q^2 + 12*q^3 + 12*q^4 + 12*q^5 + 24*q^6 + 24*q^7 + 36*q^8 + 36*q^9 + O(q^10)), + (4, 1 + O(q^10))] """ sgs = [] for x in start_gens: @@ -765,7 +782,7 @@ def generators(self, maxweight=8, prec=10, start_gens=[], start_weight=2): def gen_forms(self, maxweight=8, start_gens=[], start_weight=2): r""" - Returns a list of modular forms generating this ring (as an algebra over + Return a list of modular forms generating this ring (as an algebra over the appropriate base ring). This method differs from :meth:`generators` only in that it returns @@ -795,8 +812,8 @@ def gen_forms(self, maxweight=8, start_gens=[], start_weight=2): sage: A = ModularFormsRing(Gamma0(11), Zmod(5)).gen_forms(); A [1 + 2*q^2 + 2*q^3 + 2*q^4 + 2*q^5 + O(q^6), - q + 3*q^2 + 4*q^3 + 2*q^4 + q^5 + O(q^6), - q + q^4 + O(q^6)] + q + 3*q^2 + 4*q^3 + 2*q^4 + q^5 + O(q^6), + q + q^4 + O(q^6)] sage: A[0].parent() Ring of Modular Forms for Congruence Subgroup Gamma0(11) over Ring of integers modulo 5 """ @@ -830,7 +847,10 @@ def _find_generators(self, maxweight, start_gens, start_weight): sage: R = ModularFormsRing(Gamma1(4)) sage: R._find_generators(8, (), 2) - [(2, 1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^9), 1 + 24*q^2 + 24*q^4 + O(q^6)), (2, q + 4*q^3 + 6*q^5 + 8*q^7 + O(q^9), q + 4*q^3 + 6*q^5 + O(q^6)), (3, 1 + 12*q^2 + 64*q^3 + 60*q^4 + 160*q^6 + 384*q^7 + 252*q^8 + O(q^9), 1 + 12*q^2 + 64*q^3 + 60*q^4 + O(q^6)), (3, q + 4*q^2 + 8*q^3 + 16*q^4 + 26*q^5 + 32*q^6 + 48*q^7 + 64*q^8 + O(q^9), q + 4*q^2 + 8*q^3 + 16*q^4 + 26*q^5 + O(q^6))] + [(2, 1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^9), 1 + 24*q^2 + 24*q^4 + O(q^6)), + (2, q + 4*q^3 + 6*q^5 + 8*q^7 + O(q^9), q + 4*q^3 + 6*q^5 + O(q^6)), + (3, 1 + 12*q^2 + 64*q^3 + 60*q^4 + 160*q^6 + 384*q^7 + 252*q^8 + O(q^9), 1 + 12*q^2 + 64*q^3 + 60*q^4 + O(q^6)), + (3, q + 4*q^2 + 8*q^3 + 16*q^4 + 26*q^5 + 32*q^6 + 48*q^7 + 64*q^8 + O(q^9), q + 4*q^2 + 8*q^3 + 16*q^4 + 26*q^5 + O(q^6))] """ default_params = (start_gens == () and start_weight == 2) @@ -949,14 +969,14 @@ def q_expansion_basis(self, weight, prec=None, use_random=True): sage: m = ModularFormsRing(Gamma0(4)) sage: m.q_expansion_basis(2,10) [1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^10), - q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10)] + q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10)] sage: m.q_expansion_basis(3,10) [] sage: X = ModularFormsRing(SL2Z) sage: X.q_expansion_basis(12, 10) [1 + 196560*q^2 + 16773120*q^3 + 398034000*q^4 + 4629381120*q^5 + 34417656000*q^6 + 187489935360*q^7 + 814879774800*q^8 + 2975551488000*q^9 + O(q^10), - q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 - 6048*q^6 - 16744*q^7 + 84480*q^8 - 113643*q^9 + O(q^10)] + q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 - 6048*q^6 - 16744*q^7 + 84480*q^8 - 113643*q^9 + O(q^10)] We calculate a basis of a massive modular forms space, in two ways. Using this module is about twice as fast as Sage's generic code. :: @@ -969,7 +989,8 @@ def q_expansion_basis(self, weight, prec=None, use_random=True): Check that absurdly small values of ``prec`` don't mess things up:: sage: ModularFormsRing(11).q_expansion_basis(10, prec=5) - [1 + O(q^5), q + O(q^5), q^2 + O(q^5), q^3 + O(q^5), q^4 + O(q^5), O(q^5), O(q^5), O(q^5), O(q^5), O(q^5)] + [1 + O(q^5), q + O(q^5), q^2 + O(q^5), q^3 + O(q^5), + q^4 + O(q^5), O(q^5), O(q^5), O(q^5), O(q^5), O(q^5)] """ d = self.modular_forms_of_weight(weight).dimension() if d == 0: @@ -1097,7 +1118,8 @@ def cuspidal_submodule_q_expansion_basis(self, weight, prec=None): sage: R = ModularFormsRing(Gamma0(3)) sage: R.cuspidal_submodule_q_expansion_basis(20) - [q - 8532*q^6 - 88442*q^7 + O(q^8), q^2 + 207*q^6 + 24516*q^7 + O(q^8), q^3 + 456*q^6 + O(q^8), q^4 - 135*q^6 - 926*q^7 + O(q^8), q^5 + 18*q^6 + 135*q^7 + O(q^8)] + [q - 8532*q^6 - 88442*q^7 + O(q^8), q^2 + 207*q^6 + 24516*q^7 + O(q^8), + q^3 + 456*q^6 + O(q^8), q^4 - 135*q^6 - 926*q^7 + O(q^8), q^5 + 18*q^6 + 135*q^7 + O(q^8)] We compute a basis of a space of very large weight, quickly (using this module) and slowly (using modular symbols), and verify that the answers From 7ea68acb2dcdd5db3921681d7dd5d2d58decbad2 Mon Sep 17 00:00:00 2001 From: DavidAyotte Date: Thu, 16 Jun 2022 11:30:21 -0400 Subject: [PATCH 112/116] sage/modular/modform/element.py: remove blank newlines --- src/sage/modular/modform/element.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/sage/modular/modform/element.py b/src/sage/modular/modform/element.py index 74f2ceb3697..3344e9aff95 100644 --- a/src/sage/modular/modform/element.py +++ b/src/sage/modular/modform/element.py @@ -491,8 +491,6 @@ def __bool__(self): """ return not self.element().is_zero() - - def prec(self): """ Return the precision to which self.q_expansion() is @@ -1743,8 +1741,6 @@ def __bool__(self): """ return True - - def character(self): r""" The nebentypus character of this newform (as a Dirichlet character with From 7873c83ce4417f7e59b39c510d74dcdc4f4115e0 Mon Sep 17 00:00:00 2001 From: DavidAyotte Date: Thu, 16 Jun 2022 11:36:02 -0400 Subject: [PATCH 113/116] sage/modular/modform/ring.py: add change_ring method --- src/sage/modular/modform/ring.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/sage/modular/modform/ring.py b/src/sage/modular/modform/ring.py index e6fc11c739e..e07300439ba 100644 --- a/src/sage/modular/modform/ring.py +++ b/src/sage/modular/modform/ring.py @@ -242,6 +242,27 @@ def __init__(self, group, base_ring=QQ): self.__cached_cusp_gens = [] Parent.__init__(self, base=base_ring, category=GradedAlgebras(base_ring)) + def change_ring(self, base_ring): + r""" + Return the ring of modular forms over the given base ring and the same + group as ``self``. + + INPUT: + + - ``base_ring`` - a base ring, which should be `\QQ`, `\ZZ`, or the + integers mod `p` for some prime `p`. + + EXAMPLES:: + + sage: M = ModularFormsRing(11); M + Ring of Modular Forms for Congruence Subgroup Gamma0(11) over Rational Field + sage: M.change_ring(Zmod(7)) + Ring of Modular Forms for Congruence Subgroup Gamma0(11) over Ring of integers modulo 7 + sage: M.change_ring(ZZ) + Ring of Modular Forms for Congruence Subgroup Gamma0(11) over Integer Ring + """ + return ModularFormsRing(self.group(), base_ring=base_ring) + def some_elements(self): r""" Return a list of generators of ``self``. From b1ebc84736ec0a89a1cf7021e55ccb7fd28fc5de Mon Sep 17 00:00:00 2001 From: DavidAyotte Date: Thu, 16 Jun 2022 21:09:45 -0400 Subject: [PATCH 114/116] sage/modular/modform/: little doc tweak --- src/sage/modular/modform/element.py | 25 ++++++++++++++++--------- src/sage/modular/modform/ring.py | 24 +++++++++++++----------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/sage/modular/modform/element.py b/src/sage/modular/modform/element.py index 3344e9aff95..c8dc792e139 100644 --- a/src/sage/modular/modform/element.py +++ b/src/sage/modular/modform/element.py @@ -3197,9 +3197,10 @@ def __init__(self, parent, forms_datum): r""" INPUT: - - ``parent`` - an object of the class ``ModularFormsRing`` - - ``forms_datum`` - a dictionary ``{k_1:f_1, k_2:f_2, ..., k_n:f_n}`` or a list ``[f_1, f_2,..., f_n]`` - where `f_i` is a modular form of weight `k_i` + - ``parent`` -- an object of the class ``ModularFormsRing`` + - ``forms_datum`` -- a dictionary ``{k_1:f_1, k_2:f_2, ..., k_n:f_n}`` + or a list ``[f_1, f_2,..., f_n]`` where `f_i` is a modular form of + weight `k_i` OUTPUT: @@ -3344,7 +3345,8 @@ def group(self): def q_expansion(self, prec=None): r""" - Compute the `q`-expansion of the graded modular form up to precision ``prec`` (default: 6). + Return the `q`-expansion of the graded modular form up to precision + ``prec`` (default: 6). An alias of this method is ``qexp``. @@ -3389,8 +3391,12 @@ def _repr_(self): def __getitem__(self, weight): r""" - Given a graded form `F = f_1 + ... + f_r`, return the modular form of the given weight corresponding to - the homogeneous component. + Return the homogeneous component of the given graded modular form. + + INPUT: + + - ``weight`` -- An integer corresponding to the weight of the + homogeneous component of the given graded modular form. EXAMPLES:: @@ -3500,9 +3506,10 @@ def _mul_(self, other): INPUT: - - ``other`` - a ```GradedModularForm`` + - ``other`` -- a ``GradedModularFormElement`` - OUTPUT: the ```GradedModularForm`` corresponding to the multiplication of ```self`` and ``other``. + OUTPUT: the ``GradedModularFormElement`` corresponding to the + multiplication of ``self`` and ``other``. TESTS:: @@ -3811,7 +3818,7 @@ def derivative(self, name='E2'): INPUT: - - ``name`` (str, default: 'E2') - the name of the weight 2 Eisenstein + - ``name`` (str, default: 'E2') -- the name of the weight 2 Eisenstein series generating the graded algebra of quasimodular forms over the ring of modular forms. diff --git a/src/sage/modular/modform/ring.py b/src/sage/modular/modform/ring.py index e07300439ba..bd3f6640ad9 100644 --- a/src/sage/modular/modform/ring.py +++ b/src/sage/modular/modform/ring.py @@ -249,8 +249,8 @@ def change_ring(self, base_ring): INPUT: - - ``base_ring`` - a base ring, which should be `\QQ`, `\ZZ`, or the - integers mod `p` for some prime `p`. + - ``base_ring`` -- a base ring, which should be `\QQ`, `\ZZ`, or the + integers mod `p` for some prime `p`. EXAMPLES:: @@ -293,7 +293,8 @@ def gen(self, i): INPUT: - - ``i`` (Integer) - correspond to the `i`-th modular form generating the ``ModularFormsRing``. + - ``i`` (Integer) -- correspond to the `i`-th modular form generating + the ring of modular forms. OUTPUT: A ``GradedModularFormElement`` @@ -470,8 +471,9 @@ def _element_constructor_(self, forms_datum): INPUT: - - ``forms_datum`` (dict, list, ModularFormElement, GradedModularFormElement, RingElement, Multivariate polynomial) - Try to coerce - ``forms_datum`` into self. + - ``forms_datum`` (dict, list, ModularFormElement, + GradedModularFormElement, RingElement, Multivariate polynomial) -- Try + to coerce ``forms_datum`` into self. TESTS:: @@ -853,12 +855,12 @@ def _find_generators(self, maxweight, start_gens, start_weight): INPUT: - - maxweight: maximum weight to try - - start_weight: minimum weight to try - - start_gens: a sequence of tuples of the form `(k, f, F)`, where `F` is a - modular form of weight `k` and `f` is its `q`-expansion coerced into - ``self.base_ring()`. Either (but not both) of `f` and `F` may be - None. + - ``maxweight`` -- maximum weight to try + - ``start_weight`` -- minimum weight to try + - ``start_gens`` -- a sequence of tuples of the form `(k, f, F)`, where + `F` is a modular form of weight `k` and `f` is its `q`-expansion + coerced into ``self.base_ring()`. Either (but not both) of `f` and `F` + may be ``None``. OUTPUT: From 695a66741f4eb2377d6a158ddade89e335b57e2e Mon Sep 17 00:00:00 2001 From: dcoudert Date: Fri, 17 Jun 2022 16:32:39 +0200 Subject: [PATCH 115/116] trac #33365: formatting --- src/sage/graphs/graph_generators.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index fcfa6bce198..8a98b0ddc99 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -1033,12 +1033,12 @@ def nauty_genbg(self, options="", debug=False): -l : canonically label output graphs Options which cause ``genbg`` to use an output format different than the - ``graph6`` format are not listed above (-s, -a) as they will confuse the - creation of a Sage graph. Option ``-q`` which suppress auxiliary output - (except from ``-v``) should never be used as we are unable to recover - the partition of the vertices of the bipartite graph without the - auxilary output. Hence the partition of the vertices of returned - bipartite graphs might not respect the requirement. + ``graph6`` format are not listed above (``-s``, ``-a``) as they will + confuse the creation of a Sage graph. Option ``-q`` which suppress + auxiliary output (except from ``-v``) should never be used as we are + unable to recover the partition of the vertices of the bipartite graph + without the auxilary output. Hence the partition of the vertices of + returned bipartite graphs might not respect the requirement. The res/mod option can be useful when using the output in a routine run several times in parallel. From f8df80820dc7321dc9b18c9644c3b8315999670b Mon Sep 17 00:00:00 2001 From: Release Manager Date: Sun, 19 Jun 2022 17:25:55 +0200 Subject: [PATCH 116/116] Updated SageMath version to 9.7.beta3 --- .zenodo.json | 8 ++++---- VERSION.txt | 2 +- build/pkgs/configure/checksums.ini | 6 +++--- build/pkgs/configure/package-version.txt | 2 +- pkgs/sage-conf/VERSION.txt | 2 +- pkgs/sage-conf_pypi/VERSION.txt | 2 +- pkgs/sage-docbuild/VERSION.txt | 2 +- pkgs/sage-setup/VERSION.txt | 2 +- pkgs/sage-sws2rst/VERSION.txt | 2 +- pkgs/sagemath-categories/VERSION.txt | 2 +- pkgs/sagemath-environment/VERSION.txt | 2 +- pkgs/sagemath-objects/VERSION.txt | 2 +- pkgs/sagemath-repl/VERSION.txt | 2 +- src/VERSION.txt | 2 +- src/bin/sage-version.sh | 6 +++--- src/sage/version.py | 6 +++--- 16 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index f05573e690c..9818adbfe11 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -1,10 +1,10 @@ { "description": "Mirror of the Sage https://sagemath.org/ source tree", "license": "other-open", - "title": "sagemath/sage: 9.7.beta2", - "version": "9.7.beta2", + "title": "sagemath/sage: 9.7.beta3", + "version": "9.7.beta3", "upload_type": "software", - "publication_date": "2022-06-12", + "publication_date": "2022-06-19", "creators": [ { "affiliation": "SageMath.org", @@ -15,7 +15,7 @@ "related_identifiers": [ { "scheme": "url", - "identifier": "https://github.com/sagemath/sage/tree/9.7.beta2", + "identifier": "https://github.com/sagemath/sage/tree/9.7.beta3", "relation": "isSupplementTo" }, { diff --git a/VERSION.txt b/VERSION.txt index 8f5b1728548..07f40386ec2 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 9.7.beta2, Release Date: 2022-06-12 +SageMath version 9.7.beta3, Release Date: 2022-06-19 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index bea6fb69123..6759e5bee67 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=c250372aafc7d27ce8ae02fda5a70ea12ce2464a -md5=973d69177ce8ce4b12cc4f50349fdd42 -cksum=466625133 +sha1=b6a462ba966439bb0cbd460d2bd1cb02d3343fba +md5=95d6ce767184d6ee956feaf65494b4e8 +cksum=2637324690 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 2013ad087c0..9ad842adb86 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -08609a40ad9848c14b71daa9a27f0853e7494fc6 +b466c8ae02c04d287d28d2d669e1d111df3724ff diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt index 4cd5a231c54..3f1358a4f1f 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -9.7.beta2 +9.7.beta3 diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt index 4cd5a231c54..3f1358a4f1f 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -9.7.beta2 +9.7.beta3 diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index 4cd5a231c54..3f1358a4f1f 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -9.7.beta2 +9.7.beta3 diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt index 4cd5a231c54..3f1358a4f1f 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -9.7.beta2 +9.7.beta3 diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt index 4cd5a231c54..3f1358a4f1f 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -9.7.beta2 +9.7.beta3 diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index 4cd5a231c54..3f1358a4f1f 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -9.7.beta2 +9.7.beta3 diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index 4cd5a231c54..3f1358a4f1f 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -9.7.beta2 +9.7.beta3 diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index 4cd5a231c54..3f1358a4f1f 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -9.7.beta2 +9.7.beta3 diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt index 4cd5a231c54..3f1358a4f1f 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -9.7.beta2 +9.7.beta3 diff --git a/src/VERSION.txt b/src/VERSION.txt index 4cd5a231c54..3f1358a4f1f 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -9.7.beta2 +9.7.beta3 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index 3dc222edd01..c33cbfefeb8 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -1,5 +1,5 @@ # Sage version information for shell scripts # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='9.7.beta2' -SAGE_RELEASE_DATE='2022-06-12' -SAGE_VERSION_BANNER='SageMath version 9.7.beta2, Release Date: 2022-06-12' +SAGE_VERSION='9.7.beta3' +SAGE_RELEASE_DATE='2022-06-19' +SAGE_VERSION_BANNER='SageMath version 9.7.beta3, Release Date: 2022-06-19' diff --git a/src/sage/version.py b/src/sage/version.py index 3ea94539369..79bc5e851bd 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '9.7.beta2' -date = '2022-06-12' -banner = 'SageMath version 9.7.beta2, Release Date: 2022-06-12' +version = '9.7.beta3' +date = '2022-06-19' +banner = 'SageMath version 9.7.beta3, Release Date: 2022-06-19'

This is documentation for Sage {{ release }}. Documentations in other languages are available here. -