From 042d29a5bf258d65d2b80f47c4fddf04cd414b27 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Thu, 26 Oct 2023 15:58:06 +0200 Subject: [PATCH 001/155] First implementation of twisted chain complex --- src/sage/topology/simplicial_set.py | 165 ++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/src/sage/topology/simplicial_set.py b/src/sage/topology/simplicial_set.py index 3ee14ae2da8..646522510e7 100644 --- a/src/sage/topology/simplicial_set.py +++ b/src/sage/topology/simplicial_set.py @@ -3772,6 +3772,171 @@ def chain_complex(self, dimensions=None, base_ring=ZZ, augmented=False, return ChainComplex(differentials, degree_of_differential=-1, check=check) + + def twisted_chain_complex(self, twisting_operator, dimensions=None, augmented=False, + cochain=False, verbose=False, subcomplex=None, + check=False): + r""" + Return the normalized chain complex twisted by some operator. + + A twisting operator is a map from the set of simplices to some algebra. + The differentials are then twisted by this operator. + + INPUT: + + - ``twisting_operator`` -- a dictionary, associating the twist of each + simplex. + + - ``dimensions`` -- if ``None``, compute the chain complex in all + dimensions. If a list or tuple of integers, compute the + chain complex in those dimensions, setting the chain groups + in all other dimensions to zero. + + - ``augmented`` (optional, default ``False``) -- if ``True``, + return the augmented chain complex (that is, include a class + in dimension `-1` corresponding to the empty cell). + + - ``cochain`` (optional, default ``False``) -- if ``True``, + return the cochain complex (that is, the dual of the chain + complex). + + - ``verbose`` (optional, default ``False``) -- ignored. + + - ``subcomplex`` (optional, default ``None``) -- if present, + compute the chain complex relative to this subcomplex. + + - ``check`` (optional, default ``False``) -- If ``True``, make + sure that the chain complex is actually a chain complex: + the differentials are composable and their product is zero. + + The normalized chain complex of a simplicial set is isomorphic + to the chain complex obtained by modding out by degenerate + simplices, and the latter is what is actually constructed + here. + + EXAMPLES:: + + sage: W = simplicial_sets.Sphere(1).wedge(simplicial_sets.Sphere(2)) + sage: W.nondegenerate_simplices() + [*, sigma_1, sigma_2] + sage: s1 = W.nondegenerate_simplices()[1] + sage: L. = LaurentPolynomialRing(QQ) + sage: tw = {s1:t} + sage: ChC = W.twisted_chain_complex(tw) + sage: ChC.differential(1) + [-1 + t] + sage: ChC.differential(2) + [0] + + """ + from sage.homology.chain_complex import ChainComplex + from sage.structure.element import get_coercion_model + cm = get_coercion_model() + + def twist(s): + if s in twisting_operator: + return twisting_operator[s] + if s.dimension() > 1: + return twist(self.face_data()[s][-1]) + return 1 + base_ring = cm.common_parent(*twisting_operator.values()) + + if dimensions is None: + if not self.cells(): # Empty + if cochain: + return ChainComplex({-1: matrix(base_ring, 0, 0)}, + degree_of_differential=1) + return ChainComplex({0: matrix(base_ring, 0, 0)}, + degree_of_differential=-1) + dimensions = list(range(self.dimension() + 1)) + else: + if not isinstance(dimensions, (list, tuple, range)): + dimensions = list(range(dimensions - 1, dimensions + 2)) + else: + dimensions = [n for n in dimensions if n >= 0] + if not dimensions: + # Return the empty chain complex. + if cochain: + return ChainComplex(base_ring=base_ring, degree=1) + else: + return ChainComplex(base_ring=base_ring, degree=-1) + + differentials = {} + # Convert the tuple self._data to a dictionary indexed by the + # non-degenerate simplices. + if subcomplex: + X = self.quotient(subcomplex) + face_data = X.face_data() + nondegens = X.nondegenerate_simplices() + else: + face_data = self.face_data() + nondegens = self.nondegenerate_simplices() + # simplices: dictionary indexed by dimension, values the list + # of non-degenerate simplices in that dimension. + simplices = {} + for sigma in nondegens: + if sigma.dimension() in simplices: + simplices[sigma.dimension()].append(sigma) + else: + simplices[sigma.dimension()] = [sigma] + first = dimensions.pop(0) + if first in simplices: + rank = len(simplices[first]) + current = sorted(simplices[first]) + else: + rank = 0 + current = [] + if augmented and first == 0: + differentials[first-1] = matrix(base_ring, 0, 1) + differentials[first] = matrix(base_ring, 1, rank, + [1] * rank) + else: + differentials[first] = matrix(base_ring, 0, rank) + + for d in dimensions: + old_rank = rank + faces = {_[1]: _[0] for _ in enumerate(current)} + if d in simplices: + current = sorted(simplices[d]) + rank = len(current) + # old_rank: number of simplices in dimension d-1. + # faces: list of simplices in dimension d-1. + # rank: number of simplices in dimension d. + # current: list of simplices in dimension d. + if not faces: + differentials[d] = matrix(base_ring, old_rank, rank) + else: + matrix_data = {} + for col, sigma in enumerate(current): + sign = 1 + twists = len(face_data[sigma]) * [1] + twists[0] = twist(sigma) + for (ch,tau) in zip(twists,face_data[sigma]): + if tau.is_nondegenerate(): + row = faces[tau] + if (row, col) in matrix_data: + matrix_data[(row, col)] += sign*ch + else: + matrix_data[(row, col)] = sign*ch + sign *= -1 + + differentials[d] = matrix(base_ring, old_rank, + rank, matrix_data) + + else: + rank = 0 + current = [] + differentials[d] = matrix(base_ring, old_rank, rank) + + if cochain: + new_diffs = {} + for d in differentials: + new_diffs[d-1] = differentials[d].transpose() + return ChainComplex(new_diffs, degree_of_differential=1, + check=check) + return ChainComplex(differentials, degree_of_differential=-1, + check=check) + @cached_method def algebraic_topological_model(self, base_ring=None): r""" From 93e5f28b1a3e9a1413961cf025fb6396b1702e1d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 28 Oct 2023 13:40:29 -0700 Subject: [PATCH 002/155] pkgs/sagemath-bliss/pyproject.toml.m4: Move metadata here from setup.cfg.m4 --- pkgs/sagemath-bliss/pyproject.toml.m4 | 22 ++++++++++++++++++++++ pkgs/sagemath-bliss/setup.cfg.m4 | 17 ----------------- 2 files changed, 22 insertions(+), 17 deletions(-) delete mode 100644 pkgs/sagemath-bliss/setup.cfg.m4 diff --git a/pkgs/sagemath-bliss/pyproject.toml.m4 b/pkgs/sagemath-bliss/pyproject.toml.m4 index 1cbcdf7e162..6e2fb0b8d6b 100644 --- a/pkgs/sagemath-bliss/pyproject.toml.m4 +++ b/pkgs/sagemath-bliss/pyproject.toml.m4 @@ -10,3 +10,25 @@ requires = [ SPKG_INSTALL_REQUIRES_cysignals ] build-backend = "setuptools.build_meta" + +[project] +name = "sagemath-bliss" +description = "Sage: Open Source Mathematics Software: Graph (iso/auto)morphisms with bliss" +dependencies = [ + SPKG_INSTALL_REQUIRES_cysignals +] +dynamic = ["version"] +include(`pyproject_toml_metadata.m4`) + +[project.readme] +file = "README.rst" +content-type = "text/x-rst" + +[project.optional-dependencies] +test = [SPKG_INSTALL_REQUIRES_sagemath_repl] + +[tool.setuptools] +include-package-data = false + +[tool.setuptools.dynamic] +version = {file = ["VERSION.txt"]} diff --git a/pkgs/sagemath-bliss/setup.cfg.m4 b/pkgs/sagemath-bliss/setup.cfg.m4 deleted file mode 100644 index d1faa96a563..00000000000 --- a/pkgs/sagemath-bliss/setup.cfg.m4 +++ /dev/null @@ -1,17 +0,0 @@ -include(`sage_spkg_versions.m4')dnl' -*- conf-unix -*- -[metadata] -name = sagemath-bliss -version = file: VERSION.txt -description = Sage: Open Source Mathematics Software: Graph (iso/auto)morphisms with bliss -long_description = file: README.rst -long_description_content_type = text/x-rst -include(`setup_cfg_metadata.m4')dnl' - -[options] -python_requires = >=3.8, <3.12 -install_requires = - SPKG_INSTALL_REQUIRES_cysignals - -[options.extras_require] -test = - SPKG_INSTALL_REQUIRES_sagemath_repl From 4bf48e696ab5b304a0e82ed0428b928ca4aba645 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 28 Oct 2023 13:50:37 -0700 Subject: [PATCH 003/155] pkgs/sagemath-coxeter3/pyproject.toml.m4: Move metadata here from setup.cfg.m4 --- pkgs/sagemath-coxeter3/pyproject.toml.m4 | 24 ++++++++++++++++++++++++ pkgs/sagemath-coxeter3/setup.cfg.m4 | 20 -------------------- 2 files changed, 24 insertions(+), 20 deletions(-) delete mode 100644 pkgs/sagemath-coxeter3/setup.cfg.m4 diff --git a/pkgs/sagemath-coxeter3/pyproject.toml.m4 b/pkgs/sagemath-coxeter3/pyproject.toml.m4 index a7d65382b21..6b43b7049b0 100644 --- a/pkgs/sagemath-coxeter3/pyproject.toml.m4 +++ b/pkgs/sagemath-coxeter3/pyproject.toml.m4 @@ -9,3 +9,27 @@ requires = [ SPKG_INSTALL_REQUIRES_cysignals ] build-backend = "setuptools.build_meta" + +[project] +name = "sagemath-coxeter3" +description = "Sage: Open Source Mathematics Software: Coxeter groups, Bruhat ordering, Kazhdan-Lusztig polynomials with coxeter3" +dependencies = [] +dynamic = ["version"] +include(`pyproject_toml_metadata.m4`) + +[project.readme] +file = "README.rst" +content-type = "text/x-rst" + +[tool.setuptools] +packages = ["sage.libs.coxeter3"] +include-package-data = false + +[tool.setuptools.dynamic] +version = {file = ["VERSION.txt"]} + +[tool.setuptools.package-data] +"sage.libs.coxeter3" = [ + "coxeter.pxd", + "decl.pxd", +] diff --git a/pkgs/sagemath-coxeter3/setup.cfg.m4 b/pkgs/sagemath-coxeter3/setup.cfg.m4 deleted file mode 100644 index ab3288d89ab..00000000000 --- a/pkgs/sagemath-coxeter3/setup.cfg.m4 +++ /dev/null @@ -1,20 +0,0 @@ -include(`sage_spkg_versions.m4')dnl' -*- conf-unix -*- -[metadata] -name = sagemath-coxeter3 -version = file: VERSION.txt -description = Sage: Open Source Mathematics Software: Coxeter groups, Bruhat ordering, Kazhdan-Lusztig polynomials with coxeter3 -long_description = file: README.rst -long_description_content_type = text/x-rst -include(`setup_cfg_metadata.m4')dnl' - -[options] -python_requires = >=3.8, <3.12 -install_requires = - -packages = - sage.libs.coxeter3 - -[options.package_data] -sage.libs.coxeter3 = - coxeter.pxd - decl.pxd From f7ca4892c7d7f3a31b4caa10edf832d807a3204a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 28 Oct 2023 13:50:44 -0700 Subject: [PATCH 004/155] pkgs/sagemath-meataxe/pyproject.toml.m4: Move metadata here from setup.cfg.m4 --- pkgs/sagemath-meataxe/pyproject.toml.m4 | 25 +++++++++++++++++++++++++ pkgs/sagemath-meataxe/setup.cfg.m4 | 22 ---------------------- 2 files changed, 25 insertions(+), 22 deletions(-) delete mode 100644 pkgs/sagemath-meataxe/setup.cfg.m4 diff --git a/pkgs/sagemath-meataxe/pyproject.toml.m4 b/pkgs/sagemath-meataxe/pyproject.toml.m4 index a7d65382b21..93b7fc89ac0 100644 --- a/pkgs/sagemath-meataxe/pyproject.toml.m4 +++ b/pkgs/sagemath-meataxe/pyproject.toml.m4 @@ -9,3 +9,28 @@ requires = [ SPKG_INSTALL_REQUIRES_cysignals ] build-backend = "setuptools.build_meta" + +[project] +name = "sagemath-meataxe" +description = "Sage: Open Source Mathematics Software: Matrices over small finite fields with meataxe" +dependencies = [] +dynamic = ["version"] +include(`pyproject_toml_metadata.m4`) + +[project.readme] +file = "README.rst" +content-type = "text/x-rst" + +[tool.setuptools] +packages = [ + "sage.libs", + "sage.matrix", +] +include-package-data = false + +[tool.setuptools.dynamic] +version = {file = ["VERSION.txt"]} + +[tool.setuptools.package-data] +"sage.libs" = ["meataxe.pxd"] +"sage.matrix" = ["matrix_gfpn_dense.pxd"] diff --git a/pkgs/sagemath-meataxe/setup.cfg.m4 b/pkgs/sagemath-meataxe/setup.cfg.m4 deleted file mode 100644 index a558825e120..00000000000 --- a/pkgs/sagemath-meataxe/setup.cfg.m4 +++ /dev/null @@ -1,22 +0,0 @@ -include(`sage_spkg_versions.m4')dnl' -*- conf-unix -*- -[metadata] -name = sagemath-meataxe -version = file: VERSION.txt -description = Sage: Open Source Mathematics Software: Matrices over small finite fields with meataxe -long_description = file: README.rst -long_description_content_type = text/x-rst -include(`setup_cfg_metadata.m4')dnl' - -[options] -python_requires = >=3.8, <3.12 - -packages = - sage.libs - sage.matrix - -[options.package_data] -sage.libs = - meataxe.pxd - -sage.matrix = - matrix_gfpn_dense.pxd From 5c6b4f190ceee52e658e0e07a8f62656a6ba3a81 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 28 Oct 2023 13:52:52 -0700 Subject: [PATCH 005/155] pkgs/sagemath-mcqd/pyproject.toml.m4: Move metadata here from setup.cfg.m4 --- pkgs/sagemath-mcqd/pyproject.toml.m4 | 24 ++++++++++++++++++++++++ pkgs/sagemath-mcqd/setup.cfg.m4 | 21 --------------------- 2 files changed, 24 insertions(+), 21 deletions(-) delete mode 100644 pkgs/sagemath-mcqd/setup.cfg.m4 diff --git a/pkgs/sagemath-mcqd/pyproject.toml.m4 b/pkgs/sagemath-mcqd/pyproject.toml.m4 index 7e651119193..f18f13b4acc 100644 --- a/pkgs/sagemath-mcqd/pyproject.toml.m4 +++ b/pkgs/sagemath-mcqd/pyproject.toml.m4 @@ -10,3 +10,27 @@ requires = [ SPKG_INSTALL_REQUIRES_cysignals ] build-backend = "setuptools.build_meta" + +[project] +name = "sagemath-mcqd" +description = "Sage: Open Source Mathematics Software: Finding maximum cliques with mcqd" +dependencies = [ + SPKG_INSTALL_REQUIRES_memory_allocator + SPKG_INSTALL_REQUIRES_cysignals +] +dynamic = ["version"] +include(`pyproject_toml_metadata.m4`) + +[project.readme] +file = "README.rst" +content-type = "text/x-rst" + +[tool.setuptools] +packages = ["sage.graphs"] +include-package-data = false + +[tool.setuptools.dynamic] +version = {file = ["VERSION.txt"]} + +[tool.setuptools.package-data] +"sage.graphs" = ["mcqd.pxd"] diff --git a/pkgs/sagemath-mcqd/setup.cfg.m4 b/pkgs/sagemath-mcqd/setup.cfg.m4 deleted file mode 100644 index fff8f2805ef..00000000000 --- a/pkgs/sagemath-mcqd/setup.cfg.m4 +++ /dev/null @@ -1,21 +0,0 @@ -include(`sage_spkg_versions.m4')dnl' -*- conf-unix -*- -[metadata] -name = sagemath-mcqd -version = file: VERSION.txt -description = Sage: Open Source Mathematics Software: Finding maximum cliques with mcqd -long_description = file: README.rst -long_description_content_type = text/x-rst -include(`setup_cfg_metadata.m4')dnl' - -[options] -python_requires = >=3.8, <3.12 -install_requires = - SPKG_INSTALL_REQUIRES_memory_allocator - SPKG_INSTALL_REQUIRES_cysignals - -packages = - sage.graphs - -[options.package_data] -sage.graphs = - mcqd.pxd From a095eb5e79d5b7a709b9f5832f18d3d992fbaa5c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 28 Oct 2023 13:54:58 -0700 Subject: [PATCH 006/155] pkgs/sagemath-sirocco/pyproject.toml.m4: Move metadata here from setup.cfg.m4 --- pkgs/sagemath-sirocco/pyproject.toml.m4 | 20 ++++++++++++++++++++ pkgs/sagemath-sirocco/setup.cfg.m4 | 14 -------------- 2 files changed, 20 insertions(+), 14 deletions(-) delete mode 100644 pkgs/sagemath-sirocco/setup.cfg.m4 diff --git a/pkgs/sagemath-sirocco/pyproject.toml.m4 b/pkgs/sagemath-sirocco/pyproject.toml.m4 index 99894dd5e5e..009a2b8e41a 100644 --- a/pkgs/sagemath-sirocco/pyproject.toml.m4 +++ b/pkgs/sagemath-sirocco/pyproject.toml.m4 @@ -10,3 +10,23 @@ requires = [ SPKG_INSTALL_REQUIRES_cysignals ] build-backend = "setuptools.build_meta" + +[project] +name = "sagemath-sirocco" +description = "Sage: Open Source Mathematics Software: Certified root continuation with sirocco" +dependencies = [ + SPKG_INSTALL_REQUIRES_cypari + SPKG_INSTALL_REQUIRES_cysignals +] +dynamic = ["version"] +include(`pyproject_toml_metadata.m4`) + +[project.readme] +file = "README.rst" +content-type = "text/x-rst" + +[tool.setuptools] +include-package-data = false + +[tool.setuptools.dynamic] +version = {file = ["VERSION.txt"]} diff --git a/pkgs/sagemath-sirocco/setup.cfg.m4 b/pkgs/sagemath-sirocco/setup.cfg.m4 deleted file mode 100644 index 4f1e0f03d95..00000000000 --- a/pkgs/sagemath-sirocco/setup.cfg.m4 +++ /dev/null @@ -1,14 +0,0 @@ -include(`sage_spkg_versions.m4')dnl' -*- conf-unix -*- -[metadata] -name = sagemath-sirocco -version = file: VERSION.txt -description = Sage: Open Source Mathematics Software: Certified root continuation with sirocco -long_description = file: README.rst -long_description_content_type = text/x-rst -include(`setup_cfg_metadata.m4')dnl' - -[options] -python_requires = >=3.8, <3.12 -install_requires = - SPKG_INSTALL_REQUIRES_cypari - SPKG_INSTALL_REQUIRES_cysignals From f8558b091ed75526efa368adad7ee2fdd627fa59 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 28 Oct 2023 13:57:29 -0700 Subject: [PATCH 007/155] pkgs/sagemath-tdlib/pyproject.toml.m4: Move metadata here from setup.cfg.m4 --- pkgs/sagemath-tdlib/pyproject.toml.m4 | 19 +++++++++++++++++++ pkgs/sagemath-tdlib/setup.cfg.m4 | 12 ------------ 2 files changed, 19 insertions(+), 12 deletions(-) delete mode 100644 pkgs/sagemath-tdlib/setup.cfg.m4 diff --git a/pkgs/sagemath-tdlib/pyproject.toml.m4 b/pkgs/sagemath-tdlib/pyproject.toml.m4 index a7d65382b21..aa63d428b25 100644 --- a/pkgs/sagemath-tdlib/pyproject.toml.m4 +++ b/pkgs/sagemath-tdlib/pyproject.toml.m4 @@ -9,3 +9,22 @@ requires = [ SPKG_INSTALL_REQUIRES_cysignals ] build-backend = "setuptools.build_meta" + +[project] +name = "sagemath-tdlib" +description = "Sage: Open Source Mathematics Software: Tree decompositions with tdlib" +dependencies = [ + SPKG_INSTALL_REQUIRES_cysignals +] +dynamic = ["version"] +include(`pyproject_toml_metadata.m4`) + +[project.readme] +file = "README.rst" +content-type = "text/x-rst" + +[tool.setuptools] +include-package-data = false + +[tool.setuptools.dynamic] +version = {file = ["VERSION.txt"]} diff --git a/pkgs/sagemath-tdlib/setup.cfg.m4 b/pkgs/sagemath-tdlib/setup.cfg.m4 deleted file mode 100644 index 62833bbe6f6..00000000000 --- a/pkgs/sagemath-tdlib/setup.cfg.m4 +++ /dev/null @@ -1,12 +0,0 @@ -include(`sage_spkg_versions.m4')dnl' -*- conf-unix -*- -[metadata] -name = sagemath-tdlib -version = file: VERSION.txt -description = Sage: Open Source Mathematics Software: Tree decompositions with tdlib -long_description = file: README.rst -long_description_content_type = text/x-rst -include(`setup_cfg_metadata.m4')dnl' - -[options] -python_requires = >=3.8, <3.12 -install_requires = SPKG_INSTALL_REQUIRES_cysignals From 375796ced3dab8286359588eccfcad2b1b6a095d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 28 Oct 2023 14:27:46 -0700 Subject: [PATCH 008/155] Fix m4 syntax --- pkgs/sagemath-bliss/pyproject.toml.m4 | 2 +- pkgs/sagemath-coxeter3/pyproject.toml.m4 | 2 +- pkgs/sagemath-mcqd/pyproject.toml.m4 | 2 +- pkgs/sagemath-meataxe/pyproject.toml.m4 | 2 +- pkgs/sagemath-sirocco/pyproject.toml.m4 | 2 +- pkgs/sagemath-tdlib/pyproject.toml.m4 | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgs/sagemath-bliss/pyproject.toml.m4 b/pkgs/sagemath-bliss/pyproject.toml.m4 index 6e2fb0b8d6b..f43eb3b8052 100644 --- a/pkgs/sagemath-bliss/pyproject.toml.m4 +++ b/pkgs/sagemath-bliss/pyproject.toml.m4 @@ -18,7 +18,7 @@ dependencies = [ SPKG_INSTALL_REQUIRES_cysignals ] dynamic = ["version"] -include(`pyproject_toml_metadata.m4`) +include(`pyproject_toml_metadata.m4')dnl' [project.readme] file = "README.rst" diff --git a/pkgs/sagemath-coxeter3/pyproject.toml.m4 b/pkgs/sagemath-coxeter3/pyproject.toml.m4 index 6b43b7049b0..b9e51ff9c09 100644 --- a/pkgs/sagemath-coxeter3/pyproject.toml.m4 +++ b/pkgs/sagemath-coxeter3/pyproject.toml.m4 @@ -15,7 +15,7 @@ name = "sagemath-coxeter3" description = "Sage: Open Source Mathematics Software: Coxeter groups, Bruhat ordering, Kazhdan-Lusztig polynomials with coxeter3" dependencies = [] dynamic = ["version"] -include(`pyproject_toml_metadata.m4`) +include(`pyproject_toml_metadata.m4')dnl' [project.readme] file = "README.rst" diff --git a/pkgs/sagemath-mcqd/pyproject.toml.m4 b/pkgs/sagemath-mcqd/pyproject.toml.m4 index f18f13b4acc..8d590b5c9a6 100644 --- a/pkgs/sagemath-mcqd/pyproject.toml.m4 +++ b/pkgs/sagemath-mcqd/pyproject.toml.m4 @@ -19,7 +19,7 @@ dependencies = [ SPKG_INSTALL_REQUIRES_cysignals ] dynamic = ["version"] -include(`pyproject_toml_metadata.m4`) +include(`pyproject_toml_metadata.m4')dnl' [project.readme] file = "README.rst" diff --git a/pkgs/sagemath-meataxe/pyproject.toml.m4 b/pkgs/sagemath-meataxe/pyproject.toml.m4 index 93b7fc89ac0..40421296ef2 100644 --- a/pkgs/sagemath-meataxe/pyproject.toml.m4 +++ b/pkgs/sagemath-meataxe/pyproject.toml.m4 @@ -15,7 +15,7 @@ name = "sagemath-meataxe" description = "Sage: Open Source Mathematics Software: Matrices over small finite fields with meataxe" dependencies = [] dynamic = ["version"] -include(`pyproject_toml_metadata.m4`) +include(`pyproject_toml_metadata.m4')dnl' [project.readme] file = "README.rst" diff --git a/pkgs/sagemath-sirocco/pyproject.toml.m4 b/pkgs/sagemath-sirocco/pyproject.toml.m4 index 009a2b8e41a..ed3a732db3a 100644 --- a/pkgs/sagemath-sirocco/pyproject.toml.m4 +++ b/pkgs/sagemath-sirocco/pyproject.toml.m4 @@ -19,7 +19,7 @@ dependencies = [ SPKG_INSTALL_REQUIRES_cysignals ] dynamic = ["version"] -include(`pyproject_toml_metadata.m4`) +include(`pyproject_toml_metadata.m4')dnl' [project.readme] file = "README.rst" diff --git a/pkgs/sagemath-tdlib/pyproject.toml.m4 b/pkgs/sagemath-tdlib/pyproject.toml.m4 index aa63d428b25..140515d827c 100644 --- a/pkgs/sagemath-tdlib/pyproject.toml.m4 +++ b/pkgs/sagemath-tdlib/pyproject.toml.m4 @@ -17,7 +17,7 @@ dependencies = [ SPKG_INSTALL_REQUIRES_cysignals ] dynamic = ["version"] -include(`pyproject_toml_metadata.m4`) +include(`pyproject_toml_metadata.m4')dnl' [project.readme] file = "README.rst" From ac24cc05db36716f5bfb6f2295ab0b38b19bcc53 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 17 May 2023 13:20:30 -0700 Subject: [PATCH 009/155] Massive modularization fixes --- src/sage/libs/pari/tests.py | 106 ++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/src/sage/libs/pari/tests.py b/src/sage/libs/pari/tests.py index 97d1ec95893..d71eab73818 100644 --- a/src/sage/libs/pari/tests.py +++ b/src/sage/libs/pari/tests.py @@ -405,12 +405,12 @@ -1 sage: pari(3/4).ceil() 1 - sage: x = SR.symbol('x') - sage: pari(x).ceil() + sage: x = SR.symbol('x') # optional - sage.symbolic + sage: pari(x).ceil() # optional - sage.symbolic x - sage: pari((x^2+x+1)/x).ceil() + sage: pari((x^2+x+1)/x).ceil() # optional - sage.symbolic x + 1 - sage: pari(x^2+5*x+2.5).ceil() + sage: pari(x^2+5*x+2.5).ceil() # optional - sage.symbolic x^2 + 5*x + 2.50000000000000 sage: x = pari(-2).Mod(5) @@ -493,12 +493,12 @@ [1, 2, 4] sage: pari([[1.1,2.2],[3.3,4.4]]).floor() [[1, 2], [3, 4]] - sage: x = SR.symbol('x') - sage: pari(x).floor() + sage: x = SR.symbol('x') # optional - sage.symbolic + sage: pari(x).floor() # optional - sage.symbolic x - sage: pari((x^2+x+1)/x).floor() + sage: pari((x^2+x+1)/x).floor() # optional - sage.symbolic x + 1 - sage: pari(x^2+5*x+2.5).floor() + sage: pari(x^2+5*x+2.5).floor() # optional - sage.symbolic x^2 + 5*x + 2.50000000000000 sage: pari('"hello world"').floor() Traceback (most recent call last): @@ -507,7 +507,7 @@ sage: pari(1.75).frac() 0.750000000000000 - sage: pari(sqrt(2)).frac() + sage: pari(sqrt(2)).frac() # optional - sage.symbolic 0.414213562373095 sage: pari('sqrt(-2)').frac() Traceback (most recent call last): @@ -516,7 +516,7 @@ sage: pari('1+2*I').imag() 2 - sage: pari(sqrt(-2)).imag() + sage: pari(sqrt(-2)).imag() # optional - sage.symbolic 1.41421356237310 sage: pari('x+I').imag() 1 @@ -536,13 +536,13 @@ sage: b.lift() -17*x^2 - 3*x - sage: pari(pi).sign() + sage: pari(pi).sign() # optional - sage.symbolic 1 sage: pari(0).sign() 0 sage: pari(-1/2).sign() -1 - sage: pari(SR(I)).sign() + sage: pari(SR(I)).sign() # optional - sage.symbolic Traceback (most recent call last): ... PariError: incorrect type in gsigne (t_COMPLEX) @@ -788,8 +788,8 @@ sage: pari(5).cotan() -0.295812915532746 - sage: x = RR(pi) - sage: pari(x).cotan() # random + sage: x = RR(pi) # optional - sage.symbolic + sage: pari(x).cotan() # random # optional - sage.symbolic -8.17674825 E15 sage: pari(1).dilog() @@ -1087,18 +1087,18 @@ sage: pari(10).eulerphi() 4 - sage: x = SR.symbol('x') + sage: x = SR.symbol('x') # optional - sage.symbolic sage: pari(10).gcd(15) 5 sage: pari([5, 'y']).gcd() 1 - sage: pari([x, x^2]).gcd() + sage: pari([x, x^2]).gcd() # optional - sage.symbolic x sage: pari(10).lcm(15) 30 sage: pari([5, 'y']).lcm() 5*y - sage: pari([10, x, x^2]).lcm() + sage: pari([10, x, x^2]).lcm() # optional - sage.symbolic 10*x^2 sage: pari(20).numbpart() @@ -1201,10 +1201,10 @@ [0, 1/2, 0, -3/4, 0, 2, -3/2, 0, -9/16, 40, -116, 117/4, 256000/117, Vecsmall([1]), [Vecsmall([64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]] sage: pari([0,0.5,0,-0.75,0]).ellinit() [0, 0.500000000000000, 0, -0.750000000000000, 0, 2.00000000000000, -1.50000000000000, 0, -0.562500000000000, 40.0000000000000, -116.000000000000, 29.2500000000000, 2188.03418803419, Vecsmall([0]), [Vecsmall([64, 1])], [0, 0, 0, 0]] - sage: pari([0,SR(I),0,1,0]).ellinit() + sage: pari([0,SR(I),0,1,0]).ellinit() # optional - sage.symbolic [0, I, 0, 1, 0, 4*I, 2, 0, -1, -64, 352*I, -80, 16384/5, Vecsmall([0]), [Vecsmall([64, 0])], [0, 0, 0, 0]] - sage: x = SR.symbol('x') - sage: pari([0,x,0,2*x,1]).ellinit() + sage: x = SR.symbol('x') # optional - sage.symbolic + sage: pari([0,x,0,2*x,1]).ellinit() # optional - sage.symbolic [0, x, 0, 2*x, 1, 4*x, 4*x, 4, -4*x^2 + 4*x, 16*x^2 - 96*x, -64*x^3 + 576*x^2 - 864, 64*x^4 - 576*x^3 + 576*x^2 - 432, (256*x^6 - 4608*x^5 + 27648*x^4 - 55296*x^3)/(4*x^4 - 36*x^3 + 36*x^2 - 27), Vecsmall([0]), [Vecsmall([64, 0])], [0, 0, 0, 0]] sage: e = pari([0,1,1,-2,0]).ellinit() @@ -1365,9 +1365,9 @@ [0] sage: e.ellmul(p, 2) [1/4, -7/8] - sage: q = e.ellmul(p, SR(1+I)); q + sage: q = e.ellmul(p, SR(1+I)); q # optional - sage.symbolic [-2*I, 1 + I] - sage: e.ellmul(q, SR(1-I)) + sage: e.ellmul(q, SR(1-I)) # optional - sage.symbolic [1/4, -7/8] sage: for D in [-7, -8, -11, -12, -16, -19, -27, -28]: # long time (1s) ....: hcpol = hilbert_class_polynomial(D) @@ -1507,50 +1507,50 @@ sage: K.pari_bnf().bnrclassno(p._pari_bid_()) 3 - sage: x = SR.symbol('x') - sage: P = pari(x^6 + 108) - sage: G = P.galoisinit() - sage: G[0] == P + sage: x = SR.symbol('x') # optional - sage.symbolic + sage: P = pari(x^6 + 108) # optional - sage.symbolic + sage: G = P.galoisinit() # optional - sage.symbolic + sage: G[0] == P # optional - sage.symbolic True - sage: len(G[5]) == prod(G[7]) + sage: len(G[5]) == prod(G[7]) # optional - sage.symbolic True - sage: G = pari(x^6 + 108).galoisinit() - sage: G.galoispermtopol(G[5]) + sage: G = pari(x^6 + 108).galoisinit() # optional - sage.symbolic + sage: G.galoispermtopol(G[5]) # optional - sage.symbolic [x, 1/12*x^4 - 1/2*x, -1/12*x^4 - 1/2*x, 1/12*x^4 + 1/2*x, -1/12*x^4 + 1/2*x, -x] - sage: G.galoispermtopol(G[5][1]) + sage: G.galoispermtopol(G[5][1]) # optional - sage.symbolic 1/12*x^4 - 1/2*x - sage: G.galoispermtopol(G[5][1:4]) + sage: G.galoispermtopol(G[5][1:4]) # optional - sage.symbolic [1/12*x^4 - 1/2*x, -1/12*x^4 - 1/2*x, 1/12*x^4 + 1/2*x] - sage: G = pari(x^4 + 1).galoisinit() - sage: G.galoisfixedfield(G[5][1], flag=2) + sage: G = pari(x^4 + 1).galoisinit() # optional - sage.symbolic + sage: G.galoisfixedfield(G[5][1], flag=2) # optional - sage.symbolic [y^2 - 2, Mod(-x^3 + x, x^4 + 1), [x^2 - y*x + 1, x^2 + y*x + 1]] - sage: G.galoisfixedfield(G[5][5:7]) + sage: G.galoisfixedfield(G[5][5:7]) # optional - sage.symbolic [x^4 + 1, Mod(x, x^4 + 1)] - sage: L = G.galoissubgroups() - sage: G.galoisfixedfield(L[3], flag=2, v='z') + sage: L = G.galoissubgroups() # optional - sage.symbolic + sage: G.galoisfixedfield(L[3], flag=2, v='z') # optional - sage.symbolic [z^2 + 2, Mod(x^3 + x, x^4 + 1), [x^2 - z*x - 1, x^2 + z*x - 1]] - sage: G = pari(x^6 + 108).galoisinit() - sage: L = G.galoissubgroups() - sage: list(L[0][1]) + sage: G = pari(x^6 + 108).galoisinit() # optional - sage.symbolic + sage: L = G.galoissubgroups() # optional - sage.symbolic + sage: list(L[0][1]) # optional - sage.symbolic [3, 2] - sage: G = pari(x^6 + 108).galoisinit() - sage: G.galoisisabelian() + sage: G = pari(x^6 + 108).galoisinit() # optional - sage.symbolic + sage: G.galoisisabelian() # optional - sage.symbolic 0 - sage: H = G.galoissubgroups()[2] - sage: H.galoisisabelian() + sage: H = G.galoissubgroups()[2] # optional - sage.symbolic + sage: H.galoisisabelian() # optional - sage.symbolic Mat(2) - sage: H.galoisisabelian(flag=1) + sage: H.galoisisabelian(flag=1) # optional - sage.symbolic 1 - sage: G = pari(x^6 + 108).galoisinit() - sage: L = G.galoissubgroups() - sage: G.galoisisnormal(L[0]) + sage: G = pari(x^6 + 108).galoisinit() # optional - sage.symbolic + sage: L = G.galoissubgroups() # optional - sage.symbolic + sage: G.galoisisnormal(L[0]) # optional - sage.symbolic 1 - sage: G.galoisisnormal(L[2]) + sage: G.galoisisnormal(L[2]) # optional - sage.symbolic 0 sage: F = QuadraticField(5, 'alpha') @@ -1565,11 +1565,11 @@ sage: (b-1).valuation(Q) >= 2 True - sage: F = NumberField(x^3-2, 'alpha') - sage: nf = F.__pari__() - sage: x = pari('[1, -1, 2]~') - sage: y = pari('[1, -1, 3]~') - sage: nf.idealcoprime(x, y) + sage: F = NumberField(x^3-2, 'alpha') # optional - sage.symbolic + sage: nf = F.__pari__() # optional - sage.symbolic + sage: x = pari('[1, -1, 2]~') # optional - sage.symbolic + sage: y = pari('[1, -1, 3]~') # optional - sage.symbolic + sage: nf.idealcoprime(x, y) # optional - sage.symbolic 1 sage: y = pari('[2, -2, 4]~') From d424e68e21389da66c20f582f8e08e653f0022e6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 20 May 2023 15:38:10 -0700 Subject: [PATCH 010/155] More # optional --- src/sage/libs/pari/tests.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/libs/pari/tests.py b/src/sage/libs/pari/tests.py index d71eab73818..e2ffddb65eb 100644 --- a/src/sage/libs/pari/tests.py +++ b/src/sage/libs/pari/tests.py @@ -911,8 +911,8 @@ sage: pari(2).zeta() 1.64493406684823 - sage: x = RR(pi)^2/6 - sage: pari(x) + sage: x = RR(pi)^2/6 # optional - sage.symbolic + sage: pari(x) # optional - sage.symbolic 1.64493406684823 sage: pari(3).zeta() 1.20205690315959 @@ -1340,9 +1340,9 @@ sage: e = pari([0,1,1,-2,0]).ellinit() sage: e.ellordinate(0) [0, -1] - sage: e.ellordinate(SR(I)) + sage: e.ellordinate(SR(I)) # optional - sage.symbolic [0.582203589721741 - 1.38606082464177*I, -1.58220358972174 + 1.38606082464177*I] - sage: e.ellordinate(SR(I), precision=128)[0].sage() + sage: e.ellordinate(SR(I), precision=128)[0].sage() # optional - sage.symbolic 0.58220358972174117723338947874993600727 - 1.3860608246417697185311834209833653345*I sage: e.ellordinate(1+3*5^1+O(5^3)) [4*5 + 5^2 + O(5^3), 4 + 3*5^2 + O(5^3)] From 3112c8ca4f213196e9c0eb00f766739b745e8262 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 31 May 2023 14:48:18 -0700 Subject: [PATCH 011/155] sage.rings.*_mpfr: Modularization fixes --- src/sage/libs/pari/convert_sage_real_mpfr.pxd | 6 + src/sage/libs/pari/convert_sage_real_mpfr.pyx | 99 ++++++++++++++++ src/sage/rings/complex_mpfr.pyx | 9 +- src/sage/rings/real_lazy.pyx | 11 +- src/sage/rings/real_mpfr.pxd | 5 +- src/sage/rings/real_mpfr.pyx | 106 ++---------------- 6 files changed, 130 insertions(+), 106 deletions(-) create mode 100644 src/sage/libs/pari/convert_sage_real_mpfr.pxd create mode 100644 src/sage/libs/pari/convert_sage_real_mpfr.pyx diff --git a/src/sage/libs/pari/convert_sage_real_mpfr.pxd b/src/sage/libs/pari/convert_sage_real_mpfr.pxd new file mode 100644 index 00000000000..a00e0ec1cb5 --- /dev/null +++ b/src/sage/libs/pari/convert_sage_real_mpfr.pxd @@ -0,0 +1,6 @@ +from cypari2.gen cimport Gen + +from sage.rings.real_mpfr cimport RealNumber + +cpdef Gen new_gen_from_real_mpfr_element(RealNumber self) +cpdef set_real_mpfr_element_from_gen(RealNumber self, Gen x) diff --git a/src/sage/libs/pari/convert_sage_real_mpfr.pyx b/src/sage/libs/pari/convert_sage_real_mpfr.pyx new file mode 100644 index 00000000000..1d93ab930d5 --- /dev/null +++ b/src/sage/libs/pari/convert_sage_real_mpfr.pyx @@ -0,0 +1,99 @@ +from cypari2.stack cimport new_gen +from cypari2.paridecl cimport * + + +cpdef Gen new_gen_from_real_mpfr_element(RealNumber self): + + # This uses interfaces of MPFR and PARI which are documented + # (and not marked subject-to-change). It could be faster + # by using internal interfaces of MPFR, which are documented + # as subject-to-change. + + if mpfr_nan_p(self.value) or mpfr_inf_p(self.value): + raise ValueError('cannot convert NaN or infinity to Pari float') + + # wordsize for PARI + cdef unsigned long wordsize = sizeof(long)*8 + + cdef mpfr_prec_t prec + prec = (self._parent).__prec + + # We round up the precision to the nearest multiple of wordsize. + cdef int rounded_prec + rounded_prec = (self.prec() + wordsize - 1) & ~(wordsize - 1) + + # Yes, assigning to self works fine, even in Cython. + if rounded_prec > prec: + self = RealField(rounded_prec)(self) + + cdef mpz_t mantissa + cdef mp_exp_t exponent + cdef GEN pari_float + + sig_on() + if mpfr_zero_p(self.value): + pari_float = real_0_bit(-rounded_prec) + else: + # Now we can extract the mantissa, and it will be normalized + # (the most significant bit of the most significant word will be 1). + mpz_init(mantissa) + exponent = mpfr_get_z_exp(mantissa, self.value) + + # Create a PARI REAL + pari_float = cgetr(2 + rounded_prec / wordsize) + pari_float[1] = evalexpo(exponent + rounded_prec - 1) + evalsigne(mpfr_sgn(self.value)) + mpz_export(&pari_float[2], NULL, 1, wordsize // 8, 0, 0, mantissa) + mpz_clear(mantissa) + + return new_gen(pari_float) + + +cpdef bint set_real_mpfr_element_from_gen(RealNumber self, Gen x): + r""" + EXAMPLES:: + + sage: rt2 = sqrt(pari('2.0')) + sage: rt2 + 1.41421356237310 + sage: rt2.sage() + 1.41421356237309505 + sage: rt2.sage().prec() + 64 + sage: pari(rt2.sage()) == rt2 + True + sage: for i in range(100, 200): + ....: assert(sqrt(pari(i)) == pari(sqrt(pari(i)).sage())) + sage: (-3.1415).__pari__().sage() + -3.14150000000000000 + """ + cdef GEN g = x.g + + if typ((x).g) != t_REAL: + return False + + cdef int sgn + sgn = signe(g) + + if sgn == 0: + mpfr_set_ui(self.value, 0, MPFR_RNDN) + return True + + cdef int wordsize = 8 * sizeof(long) + + cdef mpz_t mantissa + mpz_init(mantissa) + mpz_import(mantissa, lg(g) - 2, 1, wordsize/8, 0, 0, &g[2]) + + cdef mp_exp_t exponent = expo(g) + + # Round to nearest for best results when setting a low-precision + # MPFR from a high-precision GEN + mpfr_set_z(self.value, mantissa, MPFR_RNDN) + mpfr_mul_2si(self.value, self.value, exponent - wordsize * (lg(g) - 2) + 1, MPFR_RNDN) + + if sgn < 0: + mpfr_neg(self.value, self.value, MPFR_RNDN) + + mpz_clear(mantissa) + + return True diff --git a/src/sage/rings/complex_mpfr.pyx b/src/sage/rings/complex_mpfr.pyx index d6f92bb2fee..dc57c30383f 100644 --- a/src/sage/rings/complex_mpfr.pyx +++ b/src/sage/rings/complex_mpfr.pyx @@ -59,7 +59,12 @@ from sage.rings.integer_ring import ZZ cimport gmpy2 gmpy2.import_gmpy2() -# Some objects that are note imported at startup in order to break +try: + from sage.libs.pari.all import pari_gen +except ImportError: + pari_gen = () + +# Some objects that are not imported at startup in order to break # circular imports NumberFieldElement_quadratic = None AlgebraicNumber_base = None @@ -929,7 +934,7 @@ cdef class ComplexNumber(sage.structure.element.FieldElement): if isinstance(real, ComplexNumber): real, imag = (real).real(), (real).imag() - elif isinstance(real, sage.libs.pari.all.pari_gen): + elif isinstance(real, pari_gen): real, imag = real.real(), real.imag() elif isinstance(real, (list, tuple)): re, imag = real diff --git a/src/sage/rings/real_lazy.pyx b/src/sage/rings/real_lazy.pyx index 54a84e4920a..e765cdfe801 100644 --- a/src/sage/rings/real_lazy.pyx +++ b/src/sage/rings/real_lazy.pyx @@ -49,9 +49,13 @@ from sage.rings.integer import Integer cdef QQ, RR, CC, RealField, ComplexField from sage.rings.rational_field import QQ -from sage.rings.real_mpfr import RR, RealField -from sage.rings.complex_mpfr import ComplexField -from sage.rings.cc import CC + +try: + from sage.rings.real_mpfr import RR, RealField + from sage.rings.complex_mpfr import ComplexField + from sage.rings.cc import CC +except ImportError: + pass cdef _QQx = None @@ -814,7 +818,6 @@ cdef class LazyFieldElement(FieldElement): try: return self.eval(complex) except Exception: - from .complex_mpfr import ComplexField return complex(self.eval(ComplexField(53))) cpdef eval(self, R) noexcept: diff --git a/src/sage/rings/real_mpfr.pxd b/src/sage/rings/real_mpfr.pxd index 5d44208f339..f89ec9557fd 100644 --- a/src/sage/rings/real_mpfr.pxd +++ b/src/sage/rings/real_mpfr.pxd @@ -1,10 +1,8 @@ -from sage.libs.mpfr.types cimport mpfr_rnd_t, mpfr_t +from sage.libs.mpfr.types cimport mpfr_rnd_t, mpfr_t, mpfr_prec_t cimport sage.rings.ring cimport sage.rings.abc cimport sage.structure.element -from cypari2.types cimport GEN -from sage.libs.mpfr.types cimport mpfr_prec_t cdef class RealNumber(sage.structure.element.RingElement) # forward decl @@ -26,7 +24,6 @@ cdef class RealNumber(sage.structure.element.RingElement): cpdef _mul_(self, other) noexcept cpdef _mod_(self, right) noexcept cdef _set(self, x, int base) noexcept - cdef _set_from_GEN_REAL(self, GEN g) noexcept cdef RealNumber abs(RealNumber self) noexcept cpdef RealField(mpfr_prec_t prec=*, int sci_not=*, rnd=*) noexcept diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 4a091fd9191..4b1250adac1 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -142,10 +142,6 @@ import sage.misc.weak_dict import operator -from cypari2.paridecl cimport * -from cypari2.gen cimport Gen -from cypari2.stack cimport new_gen - from sage.libs.mpmath.utils cimport mpfr_to_mpfval from .integer cimport Integer @@ -155,6 +151,7 @@ from sage.categories.map cimport Map from .real_double cimport RealDoubleElement +import sage.rings.abc import sage.rings.rational_field import sage.rings.infinity @@ -164,6 +161,11 @@ from sage.arith.numerical_approx cimport digits_to_bits from sage.arith.constants cimport M_LN2_LN10 from sage.arith.long cimport is_small_python_int +try: + from cypari2 import Gen + from sage.libs.pari.convert_sage_real_mpfr import new_gen_from_real_mpfr_element, set_real_mpfr_element_from_gen +except ImportError: + Gen = () cimport gmpy2 gmpy2.import_gmpy2() @@ -743,9 +745,8 @@ cdef class RealField_class(sage.rings.abc.RealField): return RRtoRR(S, self) elif QQ.has_coerce_map_from(S): return QQtoRR(QQ, self) * QQ._internal_coerce_map_from(S) - from sage.rings.qqbar import AA from sage.rings.real_lazy import RLF - if S is AA or S is RLF: + if isinstance(S, sage.rings.abc.AlgebraicRealField) or S is RLF: return self.convert_method_map(S, "_mpfr_") return self._coerce_map_via([RLF], S) @@ -1456,7 +1457,6 @@ cdef class RealNumber(sage.structure.element.RingElement): # This should not be called except when the number is being created. # Real Numbers are supposed to be immutable. cdef RealField_class parent - cdef Gen _gen parent = self._parent if isinstance(x, RealNumber): if isinstance(x, RealLiteral): @@ -1470,9 +1470,8 @@ cdef class RealNumber(sage.structure.element.RingElement): mpfr_set_z(self.value, (x).value, parent.rnd) elif isinstance(x, Rational): mpfr_set_q(self.value, (x).value, parent.rnd) - elif isinstance(x, Gen) and typ((x).g) == t_REAL: - _gen = x - self._set_from_GEN_REAL(_gen.g) + elif isinstance(x, Gen) and set_real_mpfr_element_from_gen(self, x): + pass elif isinstance(x, int): x = Integer(x) mpfr_set_z(self.value, (x).value, parent.rnd) @@ -1504,49 +1503,6 @@ cdef class RealNumber(sage.structure.element.RingElement): else: raise TypeError("unable to convert {!r} to a real number".format(s)) - cdef _set_from_GEN_REAL(self, GEN g) noexcept: - """ - EXAMPLES:: - - sage: rt2 = sqrt(pari('2.0')) - sage: rt2 - 1.41421356237310 - sage: rt2.sage() - 1.41421356237309505 - sage: rt2.sage().prec() - 64 - sage: pari(rt2.sage()) == rt2 - True - sage: for i in range(100, 200): - ....: assert(sqrt(pari(i)) == pari(sqrt(pari(i)).sage())) - sage: (-3.1415).__pari__().sage() - -3.14150000000000000 - """ - cdef int sgn - sgn = signe(g) - - if sgn == 0: - mpfr_set_ui(self.value, 0, MPFR_RNDN) - return - - cdef int wordsize = 8 * sizeof(long) - - cdef mpz_t mantissa - mpz_init(mantissa) - mpz_import(mantissa, lg(g) - 2, 1, wordsize/8, 0, 0, &g[2]) - - cdef mp_exp_t exponent = expo(g) - - # Round to nearest for best results when setting a low-precision - # MPFR from a high-precision GEN - mpfr_set_z(self.value, mantissa, MPFR_RNDN) - mpfr_mul_2si(self.value, self.value, exponent - wordsize * (lg(g) - 2) + 1, MPFR_RNDN) - - if sgn < 0: - mpfr_neg(self.value, self.value, MPFR_RNDN) - - mpz_clear(mantissa) - def __reduce__(self): """ EXAMPLES:: @@ -3370,48 +3326,7 @@ cdef class RealNumber(sage.structure.element.RingElement): sage: RR(a) << (sys.maxsize-3)/4 0.500000000000000 """ - # This uses interfaces of MPFR and PARI which are documented - # (and not marked subject-to-change). It could be faster - # by using internal interfaces of MPFR, which are documented - # as subject-to-change. - - if mpfr_nan_p(self.value) or mpfr_inf_p(self.value): - raise ValueError('cannot convert NaN or infinity to Pari float') - - # wordsize for PARI - cdef unsigned long wordsize = sizeof(long)*8 - - cdef mpfr_prec_t prec - prec = (self._parent)._prec - - # We round up the precision to the nearest multiple of wordsize. - cdef int rounded_prec - rounded_prec = (self.prec() + wordsize - 1) & ~(wordsize - 1) - - # Yes, assigning to self works fine, even in Cython. - if rounded_prec > prec: - self = RealField(rounded_prec)(self) - - cdef mpz_t mantissa - cdef mp_exp_t exponent - cdef GEN pari_float - - sig_on() - if mpfr_zero_p(self.value): - pari_float = real_0_bit(-rounded_prec) - else: - # Now we can extract the mantissa, and it will be normalized - # (the most significant bit of the most significant word will be 1). - mpz_init(mantissa) - exponent = mpfr_get_z_exp(mantissa, self.value) - - # Create a PARI REAL - pari_float = cgetr(2 + rounded_prec / wordsize) - pari_float[1] = evalexpo(exponent + rounded_prec - 1) + evalsigne(mpfr_sgn(self.value)) - mpz_export(&pari_float[2], NULL, 1, wordsize // 8, 0, 0, mantissa) - mpz_clear(mantissa) - - return new_gen(pari_float) + return new_gen_from_real_mpfr_element(self) def _mpmath_(self, prec=None, rounding=None): """ @@ -3431,7 +3346,6 @@ cdef class RealNumber(sage.structure.element.RingElement): from sage.libs.mpmath.all import make_mpf return make_mpf(mpfr_to_mpfval(self.value)) - def sign_mantissa_exponent(self): r""" Return the sign, mantissa, and exponent of ``self``. From eb9d1e75fe56cb78237cede93e62c8f943b14c0b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Jun 2023 23:52:17 -0700 Subject: [PATCH 012/155] src/sage/libs/pari/convert_sage_real_mpfr.pyx: Add missing imports --- src/sage/libs/pari/convert_sage_real_mpfr.pyx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sage/libs/pari/convert_sage_real_mpfr.pyx b/src/sage/libs/pari/convert_sage_real_mpfr.pyx index 1d93ab930d5..d019cc0d5b9 100644 --- a/src/sage/libs/pari/convert_sage_real_mpfr.pyx +++ b/src/sage/libs/pari/convert_sage_real_mpfr.pyx @@ -1,6 +1,8 @@ from cypari2.stack cimport new_gen from cypari2.paridecl cimport * +from sage.libs.mpfr cimport * +from sage.libs.mpfr.types cimport mpfr_t, mpfr_prec_t cpdef Gen new_gen_from_real_mpfr_element(RealNumber self): From 99368cf9ee2ed49fc7e91bd06c76eb848f6823c9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 12 Jun 2023 09:06:53 -0700 Subject: [PATCH 013/155] src/sage/libs/pari/convert_sage_real_mpfr.pyx: Add missing cimport --- src/sage/libs/pari/convert_sage_real_mpfr.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/libs/pari/convert_sage_real_mpfr.pyx b/src/sage/libs/pari/convert_sage_real_mpfr.pyx index d019cc0d5b9..7be868fcc95 100644 --- a/src/sage/libs/pari/convert_sage_real_mpfr.pyx +++ b/src/sage/libs/pari/convert_sage_real_mpfr.pyx @@ -1,6 +1,7 @@ from cypari2.stack cimport new_gen from cypari2.paridecl cimport * +from sage.libs.gmp.mpz cimport * from sage.libs.mpfr cimport * from sage.libs.mpfr.types cimport mpfr_t, mpfr_prec_t From df08ebeda782332b7f76fed787a2f0147a3e48cb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 12 Jun 2023 22:21:03 -0700 Subject: [PATCH 014/155] sage.libs.pari.convert_sage_real_mpfr: Add missing imports --- src/sage/libs/pari/convert_sage_real_mpfr.pxd | 2 +- src/sage/libs/pari/convert_sage_real_mpfr.pyx | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sage/libs/pari/convert_sage_real_mpfr.pxd b/src/sage/libs/pari/convert_sage_real_mpfr.pxd index a00e0ec1cb5..a7674309255 100644 --- a/src/sage/libs/pari/convert_sage_real_mpfr.pxd +++ b/src/sage/libs/pari/convert_sage_real_mpfr.pxd @@ -3,4 +3,4 @@ from cypari2.gen cimport Gen from sage.rings.real_mpfr cimport RealNumber cpdef Gen new_gen_from_real_mpfr_element(RealNumber self) -cpdef set_real_mpfr_element_from_gen(RealNumber self, Gen x) +cpdef bint set_real_mpfr_element_from_gen(RealNumber self, Gen x) diff --git a/src/sage/libs/pari/convert_sage_real_mpfr.pyx b/src/sage/libs/pari/convert_sage_real_mpfr.pyx index 7be868fcc95..5a45ccff0ae 100644 --- a/src/sage/libs/pari/convert_sage_real_mpfr.pyx +++ b/src/sage/libs/pari/convert_sage_real_mpfr.pyx @@ -1,9 +1,12 @@ from cypari2.stack cimport new_gen from cypari2.paridecl cimport * +from cysignals.signals cimport sig_on, sig_off from sage.libs.gmp.mpz cimport * from sage.libs.mpfr cimport * from sage.libs.mpfr.types cimport mpfr_t, mpfr_prec_t +from sage.rings.real_mpfr cimport RealField_class, RealField + cpdef Gen new_gen_from_real_mpfr_element(RealNumber self): From b72ad6f57b62475946f8d72bb4cca0280fe74c7f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 15 Jul 2023 16:10:45 -0700 Subject: [PATCH 015/155] sage.libs.pari: Split out .convert_sage_matrix and other modularization fixes --- src/sage/interfaces/gp.py | 15 +- src/sage/libs/pari/__init__.py | 2 + src/sage/libs/pari/convert_gmp.pyx | 2 +- src/sage/libs/pari/convert_sage.pyx | 130 ++------ .../libs/pari/convert_sage_complex_double.pyx | 2 +- src/sage/libs/pari/convert_sage_matrix.pyx | 105 +++++++ src/sage/libs/pari/tests.py | 293 ++++++++++-------- src/sage/matrix/args.pyx | 2 +- 8 files changed, 317 insertions(+), 234 deletions(-) create mode 100644 src/sage/libs/pari/convert_sage_matrix.pyx diff --git a/src/sage/interfaces/gp.py b/src/sage/interfaces/gp.py index e5c77833cca..ddd55423487 100644 --- a/src/sage/interfaces/gp.py +++ b/src/sage/interfaces/gp.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sage.libs.pari r""" Interface to the GP calculator of PARI/GP @@ -140,14 +141,18 @@ ########################################################################## import os +import sage.interfaces.abc + from sage.env import DOT_SAGE -from .expect import Expect, ExpectElement, ExpectFunction, FunctionElement -from sage.misc.verbose import verbose from sage.interfaces.tab_completion import ExtraTabCompletion from sage.libs.pari.all import pari -import sage.rings.complex_mpfr from sage.misc.instancedoc import instancedoc -import sage.interfaces.abc +from sage.misc.lazy_import import lazy_import +from sage.misc.verbose import verbose + +lazy_import('sage.rings.cc', 'CC') + +from .expect import Expect, ExpectElement, ExpectFunction, FunctionElement class Gp(ExtraTabCompletion, Expect): @@ -982,7 +987,7 @@ def _complex_double_(self, CDF): """ # Retrieving values from another computer algebra system is # slow anyway, right? - cc_val = self._complex_mpfr_field_(sage.rings.complex_mpfr.ComplexField()) + cc_val = self._complex_mpfr_field_(CC) return CDF(cc_val) def __len__(self): diff --git a/src/sage/libs/pari/__init__.py b/src/sage/libs/pari/__init__.py index 95b93560892..44d159ef3c1 100644 --- a/src/sage/libs/pari/__init__.py +++ b/src/sage/libs/pari/__init__.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.rings.real_mpfr """ Interface between Sage and PARI @@ -51,6 +52,7 @@ functions). For instance, if we want to use the PARI library to compute ``sqrt(pi)`` with a precision of 100 bits:: + sage: # needs sage.symbolic sage: R = RealField(100) sage: s = R(pi); s 3.1415926535897932384626433833 diff --git a/src/sage/libs/pari/convert_gmp.pyx b/src/sage/libs/pari/convert_gmp.pyx index 4a38bd5f527..8be1dad5cb9 100644 --- a/src/sage/libs/pari/convert_gmp.pyx +++ b/src/sage/libs/pari/convert_gmp.pyx @@ -172,7 +172,7 @@ cdef Gen rational_matrix(mpq_t** B, long nr, long nc) noexcept: EXAMPLES:: - sage: matrix(QQ,2,[1..6]).__pari__() # indirect doctest + sage: matrix(QQ,2,[1..6]).__pari__() # indirect doctest # needs sage.modules [1, 2, 3; 4, 5, 6] """ sig_on() diff --git a/src/sage/libs/pari/convert_sage.pyx b/src/sage/libs/pari/convert_sage.pyx index 500ed520312..da75e9595e1 100644 --- a/src/sage/libs/pari/convert_sage.pyx +++ b/src/sage/libs/pari/convert_sage.pyx @@ -27,16 +27,30 @@ from .convert_gmp cimport INT_to_mpz, new_gen_from_mpz_t, new_gen_from_mpq_t, IN from sage.ext.stdsage cimport PY_NEW from sage.libs.gmp.mpz cimport mpz_fits_slong_p, mpz_sgn, mpz_get_ui, mpz_set, mpz_set_si, mpz_set_ui from sage.libs.gmp.mpq cimport mpq_denref, mpq_numref +from sage.misc.lazy_import import LazyImport from sage.rings.integer cimport smallInteger -from sage.rings.real_mpfr import RealField -from sage.rings.complex_mpfr import ComplexField -from sage.rings.number_field.number_field import QuadraticField -from sage.matrix.args cimport (MatrixArgs, MA_ENTRIES_SEQ_SEQ, - MA_ENTRIES_SEQ_FLAT, MA_ENTRIES_CALLABLE, - MA_ENTRIES_UNKNOWN, MA_ENTRIES_SCALAR) -from sage.rings.padics.factory import Qp from sage.rings.infinity import Infinity +try: + from sage.rings.real_mpfr import RealField + from sage.rings.complex_mpfr import ComplexField +except ImportError: + pass + +try: + from sage.rings.number_field.number_field import QuadraticField +except ImportError: + pass +else: + QQi = QuadraticField(-1, 'i') + +try: + from sage.rings.padics.factory import Qp +except ImportError: + pass + +pari_typ_to_entries_type = LazyImport('sage.libs.pari.convert_sage_matrix', 'pari_typ_to_entries_type') + cpdef gen_to_sage(Gen z, locals=None) noexcept: """ @@ -179,6 +193,7 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept: sage: parent(gen_to_sage(f, {'x': x, 'y': y})) Multivariate Polynomial Ring in x, y over Rational Field + sage: # needs sage.symbolic sage: x,y = SR.var('x,y') sage: gen_to_sage(f, {'x': x, 'y': y}) 2/3*x^3 + x + y - 5/7 @@ -224,7 +239,9 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept: sage: z = pari('[1,2;3,4]') sage: z.type() 't_MAT' - sage: a = gen_to_sage(z); a + + sage: # needs sage.modules + sage: a = gen_to_sage(z); a # needs sage.modules [1 2] [3 4] sage: a.parent() @@ -232,6 +249,7 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept: Conversion of p-adics:: + sage: # needs sage.rings.padics sage: z = pari('569 + O(7^8)'); z 2 + 4*7 + 4*7^2 + 7^3 + O(7^8) sage: a = gen_to_sage(z); a @@ -294,20 +312,14 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept: C = ComplexField(sage_prec) return C(R(real), R(imag)) else: - K = QuadraticField(-1, 'i') - return K([gen_to_sage(real), gen_to_sage(imag)]) + return QQi([gen_to_sage(real), gen_to_sage(imag)]) elif t == t_VEC or t == t_COL: return [gen_to_sage(x, locals) for x in z.python_list()] elif t == t_VECSMALL: return z.python_list_small() elif t == t_MAT: - nc = lg(g) - 1 - nr = 0 if nc == 0 else lg(gel(g,1)) - 1 - ma = MatrixArgs.__new__(MatrixArgs) - ma.nrows = nr - ma.ncols = nc - ma.entries = [gen_to_sage(z[i,j], locals) for i in range(nr) for j in range(nc)] - return ma.matrix() + from .convert_sage_matrix import gen_to_sage_matrix + return gen_to_sage_matrix(z, locals) elif t == t_PADIC: p = z.padicprime() K = Qp(Integer(p), precp(g)) @@ -330,7 +342,7 @@ cpdef set_integer_from_gen(Integer self, Gen x) noexcept: r""" EXAMPLES:: - sage: [Integer(pari(x)) for x in [1, 2^60, 2., GF(3)(1), GF(9,'a')(2)]] + sage: [Integer(pari(x)) for x in [1, 2^60, 2., GF(3)(1), GF(9,'a')(2)]] # needs sage.rings.finite_rings [1, 1152921504606846976, 2, 1, 2] sage: Integer(pari(2.1)) # indirect doctest Traceback (most recent call last): @@ -390,7 +402,7 @@ cpdef set_rational_from_gen(Rational self, Gen x) noexcept: r""" EXAMPLES:: - sage: [Rational(pari(x)) for x in [1, 1/2, 2^60, 2., GF(3)(1), GF(9,'a')(2)]] + sage: [Rational(pari(x)) for x in [1, 1/2, 2^60, 2., GF(3)(1), GF(9,'a')(2)]] # needs sage.rings.finite_rings [1, 1/2, 1152921504606846976, 2, 1, 2] sage: Rational(pari(2.1)) # indirect doctest Traceback (most recent call last): @@ -576,83 +588,3 @@ cpdef list pari_prime_range(long c_start, long c_stop, bint py_ints=False) noexc res.append(z) NEXT_PRIME_VIADIFF(p, pari_prime_ptr) return res - - -def pari_typ_to_entries_type(MatrixArgs self): - """ - Determine the ``entries_type`` of a :class:`sage.matrix.args.MatrixArgs` - with PARI entries. - - This will modify the entries. - - TESTS: - - ``MA_ENTRIES_SEQ_SEQ``:: - - sage: from sage.libs.pari.convert_sage import pari_typ_to_entries_type - sage: from sage.matrix.args import MatrixArgs - sage: ma = MatrixArgs(QQ, entries=pari("[1,2;3,4]")) - sage: 0x10_03 == pari_typ_to_entries_type(ma) - True - - ``MA_ENTRIES_SEQ_FLAT``:: - - sage: ma = MatrixArgs(QQ, entries=pari("[1,2]")) - sage: 0x10_04 == pari_typ_to_entries_type(ma) - True - sage: ma = MatrixArgs(QQ, entries=pari(vector([1,2]))) - sage: 0x10_04 == pari_typ_to_entries_type(ma) - True - sage: ma = MatrixArgs(QQ, entries=pari(matrix(2, range(4))[0])) - sage: 0x10_04 == pari_typ_to_entries_type(ma) - True - - ``MA_ENTRIES_CALLABLE``:: - - sage: ma = MatrixArgs(QQ, entries=pari(lambda x: x)) - sage: 0x13_06 == pari_typ_to_entries_type(ma) - True - - ``MA_ENTRIES_SCALAR``:: - - sage: ma = MatrixArgs(QQ, entries=pari(1/2)) - sage: 0x17_02 == pari_typ_to_entries_type(ma) - True - - ``MA_ENTRIES_UNKNOWN``:: - - sage: ma = MatrixArgs(QQ, entries=pari('"2"')) - sage: 0 == pari_typ_to_entries_type(ma) - True - - A second call gives an error:: - - sage: ma = MatrixArgs(QQ, entries=pari("[1,2]")) - sage: 0x10_04 == pari_typ_to_entries_type(ma) - True - sage: 0x10_04 == pari_typ_to_entries_type(ma) - Traceback (most recent call last): - ... - ValueError: entries are not a PARI generator - """ - if not isinstance(self.entries, Gen): - raise ValueError("entries are not a PARI generator") - cdef long t = typ((self.entries).g) - if t == t_MAT: - R = self.base - if R is None: - self.entries = self.entries.Col().sage() - else: - self.entries = [[R(x) for x in v] - for v in self.entries.mattranspose()] - return MA_ENTRIES_SEQ_SEQ - elif t in [t_VEC, t_COL, t_VECSMALL, t_LIST]: - self.entries = self.entries.sage() - return MA_ENTRIES_SEQ_FLAT - elif t == t_CLOSURE: - return MA_ENTRIES_CALLABLE - elif t == t_STR: - return MA_ENTRIES_UNKNOWN - else: - self.entries = self.entries.sage() - return MA_ENTRIES_SCALAR diff --git a/src/sage/libs/pari/convert_sage_complex_double.pyx b/src/sage/libs/pari/convert_sage_complex_double.pyx index d4022c62a0f..c2ee7bec586 100644 --- a/src/sage/libs/pari/convert_sage_complex_double.pyx +++ b/src/sage/libs/pari/convert_sage_complex_double.pyx @@ -25,7 +25,7 @@ cpdef ComplexDoubleElement pari_to_cdf(Gen g) noexcept: Traceback (most recent call last): ... PariError: overflow in t_REAL->double conversion - sage: CDF(pari(x^2 + 5)) + sage: CDF(pari(x^2 + 5)) # needs sage.symbolic Traceback (most recent call last): ... PariError: incorrect type in gtofp (t_POL) diff --git a/src/sage/libs/pari/convert_sage_matrix.pyx b/src/sage/libs/pari/convert_sage_matrix.pyx new file mode 100644 index 00000000000..dd14eb17abf --- /dev/null +++ b/src/sage/libs/pari/convert_sage_matrix.pyx @@ -0,0 +1,105 @@ +# sage_setup: distribution = sagemath-pari +# sage.doctest: needs sage.modules + +from cypari2.gen cimport Gen +from cypari2.types cimport (GEN, typ, t_INT, t_FRAC, t_REAL, t_COMPLEX, + t_INTMOD, t_PADIC, t_INFINITY, t_VEC, t_COL, + t_VECSMALL, t_MAT, t_STR, + lg, precp) +from cypari2.paridecl cimport * + +from sage.matrix.args cimport (MatrixArgs, MA_ENTRIES_SEQ_SEQ, + MA_ENTRIES_SEQ_FLAT, MA_ENTRIES_CALLABLE, + MA_ENTRIES_UNKNOWN, MA_ENTRIES_SCALAR) + +from .convert_sage cimport gen_to_sage + +def gen_to_sage_matrix(Gen z, locals=None): + cdef GEN g = z.g + nc = lg(g) - 1 + nr = 0 if nc == 0 else lg(gel(g,1)) - 1 + ma = MatrixArgs.__new__(MatrixArgs) + ma.nrows = nr + ma.ncols = nc + ma.entries = [gen_to_sage(z[i,j], locals) for i in range(nr) for j in range(nc)] + return ma.matrix() + + +def pari_typ_to_entries_type(MatrixArgs self): + """ + Determine the ``entries_type`` of a :class:`sage.matrix.args.MatrixArgs` + with PARI entries. + + This will modify the entries. + + TESTS: + + ``MA_ENTRIES_SEQ_SEQ``:: + + sage: from sage.libs.pari.convert_sage import pari_typ_to_entries_type + sage: from sage.matrix.args import MatrixArgs + sage: ma = MatrixArgs(QQ, entries=pari("[1,2;3,4]")) + sage: 0x10_03 == pari_typ_to_entries_type(ma) + True + + ``MA_ENTRIES_SEQ_FLAT``:: + + sage: ma = MatrixArgs(QQ, entries=pari("[1,2]")) + sage: 0x10_04 == pari_typ_to_entries_type(ma) + True + sage: ma = MatrixArgs(QQ, entries=pari(vector([1,2]))) + sage: 0x10_04 == pari_typ_to_entries_type(ma) + True + sage: ma = MatrixArgs(QQ, entries=pari(matrix(2, range(4))[0])) + sage: 0x10_04 == pari_typ_to_entries_type(ma) + True + + ``MA_ENTRIES_CALLABLE``:: + + sage: ma = MatrixArgs(QQ, entries=pari(lambda x: x)) + sage: 0x13_06 == pari_typ_to_entries_type(ma) + True + + ``MA_ENTRIES_SCALAR``:: + + sage: ma = MatrixArgs(QQ, entries=pari(1/2)) + sage: 0x17_02 == pari_typ_to_entries_type(ma) + True + + ``MA_ENTRIES_UNKNOWN``:: + + sage: ma = MatrixArgs(QQ, entries=pari('"2"')) + sage: 0 == pari_typ_to_entries_type(ma) + True + + A second call gives an error:: + + sage: ma = MatrixArgs(QQ, entries=pari("[1,2]")) + sage: 0x10_04 == pari_typ_to_entries_type(ma) + True + sage: 0x10_04 == pari_typ_to_entries_type(ma) + Traceback (most recent call last): + ... + ValueError: entries are not a PARI generator + """ + if not isinstance(self.entries, Gen): + raise ValueError("entries are not a PARI generator") + cdef long t = typ((self.entries).g) + if t == t_MAT: + R = self.base + if R is None: + self.entries = self.entries.Col().sage() + else: + self.entries = [[R(x) for x in v] + for v in self.entries.mattranspose()] + return MA_ENTRIES_SEQ_SEQ + elif t in [t_VEC, t_COL, t_VECSMALL, t_LIST]: + self.entries = self.entries.sage() + return MA_ENTRIES_SEQ_FLAT + elif t == t_CLOSURE: + return MA_ENTRIES_CALLABLE + elif t == t_STR: + return MA_ENTRIES_UNKNOWN + else: + self.entries = self.entries.sage() + return MA_ENTRIES_SCALAR diff --git a/src/sage/libs/pari/tests.py b/src/sage/libs/pari/tests.py index e2ffddb65eb..293e53b002f 100644 --- a/src/sage/libs/pari/tests.py +++ b/src/sage/libs/pari/tests.py @@ -10,16 +10,16 @@ Creating PARI objects:: - sage: pari(Matrix(2,2,range(4))) + sage: pari(Matrix(2,2,range(4))) # needs sage.modules [0, 1; 2, 3] - sage: pari(x^2-3) + sage: pari(x^2-3) # needs sage.symbolic x^2 - 3 The following example caused Sage to crash before :trac:`20630`:: sage: R. = QQ[] - sage: K. = NumberField(theta^2 + 1) + sage: K. = NumberField(theta^2 + 1) # needs sage.rings.number_field sage: K.absolute_polynomial().galois_group(pari_group=True) PARI group [2, -1, 1, "S2"] of degree 2 @@ -28,7 +28,7 @@ sage: pari.allocatemem(200000) PARI stack size set to 200000 bytes, maximum size set to ... - sage: x = polygen(ZpFM(3,10)) + sage: x = polygen(ZpFM(3,10)) # needs sage.rings.padics sage: pol = ((x-1)^50 + x) sage: pari(pol).poldisc() 2*3 + 3^4 + 2*3^6 + 3^7 + 2*3^8 + 2*3^9 + O(3^10) @@ -60,7 +60,7 @@ Number fields:: sage: x = polygen(QQ) - sage: K. = NumberField(x^4 - 4*x^2 + 1) + sage: K. = NumberField(x^4 - 4*x^2 + 1) # needs sage.rings.number_field sage: pari(K).nf_get_pol() y^4 - 4*y^2 + 1 sage: L. = K.extension(x^2 - 5) @@ -74,7 +74,7 @@ sage: K.pari_bnf().nf_get_pol() y^4 - 4*y^2 + 1 - sage: K. = QuadraticField(-65) + sage: K. = QuadraticField(-65) # needs sage.rings.number_field sage: G = K.pari_bnf().bnf_get_gen(); G [[3, 2; 0, 1], [2, 1; 0, 1]] sage: [K.ideal(J) for J in G] @@ -82,24 +82,24 @@ Conversions:: - sage: K. = QuadraticField(-1) + sage: K. = QuadraticField(-1) # needs sage.rings.number_field sage: F = pari(K).idealfactor(K.ideal(5)); F [[5, [-2, 1]~, 1, 1, [2, -1; 1, 2]], 1; [5, [2, 1]~, 1, 1, [-2, -1; 1, -2]], 1] sage: F[0,0].pr_get_p() 5 - sage: K. = QuadraticField(-1) + sage: K. = QuadraticField(-1) # needs sage.rings.number_field sage: J = pari(K).idealstar(K.ideal(4*i + 2)) sage: J.bid_get_cyc() [4, 2] - sage: int(pari(RealField(63)(2^63-1))) + sage: int(pari(RealField(63)(2^63-1))) # needs sage.rings.real_mpfr 9223372036854775807 # 32-bit 9223372036854775807 # 64-bit - sage: int(pari(RealField(63)(2^63+2))) + sage: int(pari(RealField(63)(2^63+2))) # needs sage.rings.real_mpfr 9223372036854775810 - sage: K = Qp(11,5) + sage: K = Qp(11,5) # needs sage.rings.padics sage: x = K(11^-10 + 5*11^-7 + 11^-6) sage: y = pari(x) sage: y.padicprime() @@ -125,20 +125,21 @@ Conversion from matrices and vectors is supported:: - sage: a = pari(matrix(2,3,[1,2,3,4,5,6])); a, a.type() + sage: a = pari(matrix(2,3,[1,2,3,4,5,6])); a, a.type() # needs sage.modules ([1, 2, 3; 4, 5, 6], 't_MAT') - sage: v = vector([1.2, 3.4, 5.6]) + sage: v = vector([1.2, 3.4, 5.6]) # needs sage.modules sage: pari(v) [1.20000000000000, 3.40000000000000, 5.60000000000000] Some more exotic examples:: + sage: # needs sage.rings.number_field sage: K. = NumberField(polygen(QQ)^3 - 2) sage: pari(K) [y^3 - 2, [1, 1], -108, 1, [[1, 1.25992104989487, 1.58740105196820; 1, -0.629960524947437 + 1.09112363597172*I, -0.793700525984100 - 1.37472963699860*I], [1, 1.25992104989487, 1.58740105196820; 1, 0.461163111024285, -2.16843016298270; 1, -1.72108416091916, 0.581029111014503], [16, 20, 25; 16, 7, -35; 16, -28, 9], [3, 0, 0; 0, 0, 6; 0, 6, 0], [6, 0, 0; 0, 6, 0; 0, 0, 3], [2, 0, 0; 0, 0, 1; 0, 1, 0], [2, [0, 0, 2; 1, 0, 0; 0, 1, 0]], [2, 3]], [1.25992104989487, -0.629960524947437 + 1.09112363597172*I], [1, y, y^2], [1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0, 0, 0, 2, 0, 2, 0; 0, 1, 0, 1, 0, 0, 0, 0, 2; 0, 0, 1, 0, 1, 0, 1, 0, 0]] - sage: E = EllipticCurve('37a1') - sage: pari(E) + sage: E = EllipticCurve('37a1') # needs sage.schemes + sage: pari(E) # needs sage.schemes [0, 0, 1, -1, 0, 0, -2, 1, -1, 48, -216, 37, 110592/37, Vecsmall([1]), [Vecsmall([64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]] Deprecation checks:: @@ -405,12 +406,14 @@ -1 sage: pari(3/4).ceil() 1 - sage: x = SR.symbol('x') # optional - sage.symbolic - sage: pari(x).ceil() # optional - sage.symbolic + + sage: # needs sage.symbolic + sage: x = SR.symbol('x') + sage: pari(x).ceil() x - sage: pari((x^2+x+1)/x).ceil() # optional - sage.symbolic + sage: pari((x^2+x+1)/x).ceil() x + 1 - sage: pari(x^2+5*x+2.5).ceil() # optional - sage.symbolic + sage: pari(x^2+5*x+2.5).ceil() x^2 + 5*x + 2.50000000000000 sage: x = pari(-2).Mod(5) @@ -493,12 +496,13 @@ [1, 2, 4] sage: pari([[1.1,2.2],[3.3,4.4]]).floor() [[1, 2], [3, 4]] - sage: x = SR.symbol('x') # optional - sage.symbolic - sage: pari(x).floor() # optional - sage.symbolic + + sage: x = SR.symbol('x') # needs sage.symbolic + sage: pari(x).floor() # needs sage.symbolic x - sage: pari((x^2+x+1)/x).floor() # optional - sage.symbolic + sage: pari((x^2+x+1)/x).floor() # needs sage.symbolic x + 1 - sage: pari(x^2+5*x+2.5).floor() # optional - sage.symbolic + sage: pari(x^2+5*x+2.5).floor() # needs sage.symbolic x^2 + 5*x + 2.50000000000000 sage: pari('"hello world"').floor() Traceback (most recent call last): @@ -507,7 +511,7 @@ sage: pari(1.75).frac() 0.750000000000000 - sage: pari(sqrt(2)).frac() # optional - sage.symbolic + sage: pari(sqrt(2)).frac() # needs sage.symbolic 0.414213562373095 sage: pari('sqrt(-2)').frac() Traceback (most recent call last): @@ -516,7 +520,7 @@ sage: pari('1+2*I').imag() 2 - sage: pari(sqrt(-2)).imag() # optional - sage.symbolic + sage: pari(sqrt(-2)).imag() # needs sage.symbolic 1.41421356237310 sage: pari('x+I').imag() 1 @@ -536,13 +540,13 @@ sage: b.lift() -17*x^2 - 3*x - sage: pari(pi).sign() # optional - sage.symbolic + sage: pari(pi).sign() # needs sage.symbolic 1 sage: pari(0).sign() 0 sage: pari(-1/2).sign() -1 - sage: pari(SR(I)).sign() # optional - sage.symbolic + sage: pari(SR(I)).sign() # needs sage.symbolic Traceback (most recent call last): ... PariError: incorrect type in gsigne (t_COMPLEX) @@ -705,16 +709,16 @@ 1.04719755119660 sage: pari(1.1).acos() 0.443568254385115*I - sage: C. = ComplexField() - sage: pari(1.1+i).acos() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(1.1+i).acos() # needs sage.rings.real_mpfr 0.849343054245252 - 1.09770986682533*I sage: pari(2).acosh() 1.31695789692482 sage: pari(0).acosh() 1.57079632679490*I - sage: C. = ComplexField() - sage: pari(i).acosh() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(i).acosh() # needs sage.rings.real_mpfr 0.881373587019543 + 1.57079632679490*I sage: pari(2).agm(2) @@ -723,12 +727,12 @@ 0 sage: pari(1).agm(2) 1.45679103104691 - sage: C. = ComplexField() - sage: pari(1+i).agm(-3) + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(1+i).agm(-3) # needs sage.rings.real_mpfr -0.964731722290876 + 1.15700282952632*I - sage: C. = ComplexField() - sage: pari(2+i).arg() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(2+i).arg() # needs sage.rings.real_mpfr 0.463647609000806 sage: pari(pari(0.5).sin()).asin() @@ -738,14 +742,14 @@ sage: pari(2).asinh() 1.44363547517881 - sage: C. = ComplexField() - sage: pari(2+i).asinh() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(2+i).asinh() # needs sage.rings.real_mpfr 1.52857091948100 + 0.427078586392476*I sage: pari(1).atan() 0.785398163397448 - sage: C. = ComplexField() - sage: pari(1.5+i).atan() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(1.5+i).atan() # needs sage.rings.real_mpfr 1.10714871779409 + 0.255412811882995*I sage: pari(0).atanh() @@ -763,46 +767,46 @@ 0.412710032209716 sage: pari(2).besseli(3) 2.24521244092995 - sage: C. = ComplexField() - sage: pari(2).besseli(3+i) + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(2).besseli(3+i) # needs sage.rings.real_mpfr 1.12539407613913 + 2.08313822670661*I - sage: C. = ComplexField() - sage: pari(2+i).bessely(3) + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(2+i).bessely(3) # needs sage.rings.real_mpfr -0.280775566958244 - 0.486708533223726*I sage: pari(1.5).cos() 0.0707372016677029 - sage: C. = ComplexField() - sage: pari(1+i).cos() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(1+i).cos() # needs sage.rings.real_mpfr 0.833730025131149 - 0.988897705762865*I sage: pari('x+O(x^8)').cos() 1 - 1/2*x^2 + 1/24*x^4 - 1/720*x^6 + 1/40320*x^8 + O(x^9) sage: pari(1.5).cosh() 2.35240961524325 - sage: C. = ComplexField() - sage: pari(1+i).cosh() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(1+i).cosh() # needs sage.rings.real_mpfr 0.833730025131149 + 0.988897705762865*I sage: pari('x+O(x^8)').cosh() 1 + 1/2*x^2 + 1/24*x^4 + 1/720*x^6 + ...O(...) sage: pari(5).cotan() -0.295812915532746 - sage: x = RR(pi) # optional - sage.symbolic - sage: pari(x).cotan() # random # optional - sage.symbolic + sage: x = RR(pi) # needs sage.symbolic + sage: pari(x).cotan() # random -8.17674825 E15 sage: pari(1).dilog() 1.64493406684823 - sage: C. = ComplexField() - sage: pari(1+i).dilog() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(1+i).dilog() # needs sage.rings.real_mpfr 0.616850275068085 + 1.46036211675312*I sage: pari(1).erfc() 0.157299207050285 - sage: C. = ComplexField() - sage: pari(i).eta() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(i).eta() # needs sage.rings.real_mpfr 0.998129069925959 sage: pari(0).exp() @@ -816,8 +820,8 @@ 1.00000000000000 sage: pari(5).gamma() 24.0000000000000 - sage: C. = ComplexField() - sage: pari(1+i).gamma() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(1+i).gamma() # needs sage.rings.real_mpfr 0.498015668118356 - 0.154949828301811*I sage: pari(-1).gamma() Traceback (most recent call last): @@ -828,23 +832,23 @@ 1.32934038817914 sage: pari(5).gammah() 52.3427777845535 - sage: C. = ComplexField() - sage: pari(1+i).gammah() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(1+i).gammah() # needs sage.rings.real_mpfr 0.575315188063452 + 0.0882106775440939*I sage: pari(1).hyperu(2,3) 0.333333333333333 - sage: C. = ComplexField() - sage: pari(1+i).incgam(3-i) + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(1+i).incgam(3-i) # needs sage.rings.real_mpfr -0.0458297859919946 + 0.0433696818726677*I sage: pari(1).incgamc(2) 0.864664716763387 sage: pari(5).log() 1.60943791243410 - sage: C. = ComplexField() - sage: pari(i).log() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(i).log() # needs sage.rings.real_mpfr 0.E-19 + 1.57079632679490*I sage: pari(100).lngamma() @@ -857,14 +861,14 @@ sage: pari(1).sin() 0.841470984807897 - sage: C. = ComplexField() - sage: pari(1+i).sin() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(1+i).sin() # needs sage.rings.real_mpfr 1.29845758141598 + 0.634963914784736*I sage: pari(0).sinh() 0.E-19 - sage: C. = ComplexField() - sage: pari(1+i).sinh() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(1+i).sinh() # needs sage.rings.real_mpfr 0.634963914784736 + 1.29845758141598*I sage: pari(2).sqrt() @@ -877,14 +881,14 @@ sage: pari(2).tan() -2.18503986326152 - sage: C. = ComplexField() - sage: pari(i).tan() + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: pari(i).tan() # needs sage.rings.real_mpfr 0.761594155955765*I sage: pari(1).tanh() 0.761594155955765 - sage: C. = ComplexField() - sage: z = pari(i); z + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: z = pari(i); z # needs sage.rings.real_mpfr 1.00000000000000*I sage: result = z.tanh() sage: result.real() <= 1e-18 @@ -901,6 +905,7 @@ sage: pari(0.5).thetanullk(1) 0.548978532560341 + sage: # needs sage.rings.real_mpfr sage: C. = ComplexField() sage: pari(i).weber() 1.18920711500272 @@ -911,8 +916,8 @@ sage: pari(2).zeta() 1.64493406684823 - sage: x = RR(pi)^2/6 # optional - sage.symbolic - sage: pari(x) # optional - sage.symbolic + sage: x = RR(pi)^2/6 # needs sage.symbolic + sage: pari(x) # needs sage.symbolic 1.64493406684823 sage: pari(3).zeta() 1.20205690315959 @@ -966,6 +971,7 @@ sage: pari('[1,2,3; 4,5,6; 7,8,9]').mathnf() [6, 1; 3, 1; 0, 1] + sage: # needs sage.modules sage: M = matrix([[1,2,3],[4,5,6],[7,8,11]]) sage: d = M.det() sage: pari(M).mathnfmod(d) @@ -976,6 +982,7 @@ sage: pari(M).mathnfmod(12) [1, 0, 0; 0, 2, 0; 0, 0, 6] + sage: # needs sage.modules sage: M = matrix([[1,0,0],[0,2,0],[0,0,6]]) sage: pari(M).mathnfmodid(6) [1, 0, 0; 0, 2, 0; 0, 0, 6] @@ -1007,6 +1014,7 @@ Quadratic forms:: + sage: # needs sage.modules sage: A = Matrix(3,3,[1,2,3,2,5,5,3,5,11]) sage: A.is_positive_definite() True @@ -1029,6 +1037,7 @@ 10, 5.00000000000000000, [ 1 2 0 1 -1] ] + sage: # needs sage.modules sage: M = diagonal_matrix([1,1,-1]) sage: P = M.__pari__().qfparam([0,1,-1]); P [0, -2, 0; 1, 0, -1; -1, 0, -1] @@ -1042,6 +1051,7 @@ sage: 48^2 + 55^2 == 73^2 True + sage: # needs sage.modules sage: M = diagonal_matrix([1,2,3,4,-5]) sage: M.__pari__().qfsolve() [0, 1, -1, 0, -1]~ @@ -1087,18 +1097,19 @@ sage: pari(10).eulerphi() 4 - sage: x = SR.symbol('x') # optional - sage.symbolic + sage: # needs sage.symbolic + sage: x = SR.symbol('x') sage: pari(10).gcd(15) 5 sage: pari([5, 'y']).gcd() 1 - sage: pari([x, x^2]).gcd() # optional - sage.symbolic + sage: pari([x, x^2]).gcd() x sage: pari(10).lcm(15) 30 sage: pari([5, 'y']).lcm() 5*y - sage: pari([10, x, x^2]).lcm() # optional - sage.symbolic + sage: pari([10, x, x^2]).lcm() 10*x^2 sage: pari(20).numbpart() @@ -1153,6 +1164,7 @@ sage: pari(2003).ffinit(3) Mod(1, 2003)*x^3 + Mod(1, 2003)*x^2 + Mod(1993, 2003)*x + Mod(1995, 2003) + sage: # needs sage.rings.finite_rings sage: k. = GF(2^12) sage: g = pari(a).ffprimroot() sage: (g^1234).fflog(g) @@ -1167,6 +1179,7 @@ sage: (b^555).fflog(b, (ord, ord.factor()) ) 555 + sage: # needs sage.rings.finite_rings sage: k. = GF(5^80) sage: g = pari(a).ffprimroot() sage: g.fforder() @@ -1178,6 +1191,7 @@ p-adic functions:: + sage: # needs sage.rings.padics sage: K = Qp(11,5) sage: x = K(11^-10 + 5*11^-7 + 11^-6) sage: y = pari(x) @@ -1201,10 +1215,10 @@ [0, 1/2, 0, -3/4, 0, 2, -3/2, 0, -9/16, 40, -116, 117/4, 256000/117, Vecsmall([1]), [Vecsmall([64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]] sage: pari([0,0.5,0,-0.75,0]).ellinit() [0, 0.500000000000000, 0, -0.750000000000000, 0, 2.00000000000000, -1.50000000000000, 0, -0.562500000000000, 40.0000000000000, -116.000000000000, 29.2500000000000, 2188.03418803419, Vecsmall([0]), [Vecsmall([64, 1])], [0, 0, 0, 0]] - sage: pari([0,SR(I),0,1,0]).ellinit() # optional - sage.symbolic + sage: pari([0,SR(I),0,1,0]).ellinit() # needs sage.symbolic [0, I, 0, 1, 0, 4*I, 2, 0, -1, -64, 352*I, -80, 16384/5, Vecsmall([0]), [Vecsmall([64, 0])], [0, 0, 0, 0]] - sage: x = SR.symbol('x') # optional - sage.symbolic - sage: pari([0,x,0,2*x,1]).ellinit() # optional - sage.symbolic + sage: x = SR.symbol('x') # needs sage.symbolic + sage: pari([0,x,0,2*x,1]).ellinit() # needs sage.symbolic [0, x, 0, 2*x, 1, 4*x, 4*x, 4, -4*x^2 + 4*x, 16*x^2 - 96*x, -64*x^3 + 576*x^2 - 864, 64*x^4 - 576*x^3 + 576*x^2 - 432, (256*x^6 - 4608*x^5 + 27648*x^4 - 55296*x^3)/(4*x^4 - 36*x^3 + 36*x^2 - 27), Vecsmall([0]), [Vecsmall([64, 0])], [0, 0, 0, 0]] sage: e = pari([0,1,1,-2,0]).ellinit() @@ -1233,6 +1247,8 @@ sage: e = pari([0, 5, 2, -1, 1]).ellinit() sage: e.ellglobalred() [20144, [1, -2, 0, -1], 1, [2, 4; 1259, 1], [[4, 2, 0, 1], [1, 5, 0, 1]]] + + sage: # needs sage.schemes sage: e = pari(EllipticCurve('17a').a_invariants()).ellinit() sage: e.ellglobalred() [17, [1, 0, 0, 0], 4, Mat([17, 1]), [[1, 8, 0, 4]]] @@ -1251,8 +1267,9 @@ sage: e.ellak(0) 0 + sage: # needs sage.schemes sage: E = EllipticCurve('389a1') - sage: pari(E).ellanalyticrank() + sage: pari(E).ellanalyticrank() # needs sage.rings.number_field [2, 1.51863300057685] sage: e = pari([0, -1, 1, -10, -20]).ellinit() @@ -1291,6 +1308,7 @@ sage: om.elleisnum(100) 2.15314248576078 E50 + sage: # needs sage.schemes sage: e = pari([0,0,0,0,1]).ellinit() sage: e.elllocalred(7) [0, 1, [1, 0, 0, 0], 1] @@ -1331,6 +1349,7 @@ sage: e.elllocalred(3) [2, -10, [1, 0, 0, 0], 4] + sage: # needs sage.schemes sage: e = pari(EllipticCurve('65a1').a_invariants()).ellinit() sage: e.ellorder([0,0]) 2 @@ -1340,11 +1359,11 @@ sage: e = pari([0,1,1,-2,0]).ellinit() sage: e.ellordinate(0) [0, -1] - sage: e.ellordinate(SR(I)) # optional - sage.symbolic + sage: e.ellordinate(SR(I)) # needs sage.symbolic [0.582203589721741 - 1.38606082464177*I, -1.58220358972174 + 1.38606082464177*I] - sage: e.ellordinate(SR(I), precision=128)[0].sage() # optional - sage.symbolic + sage: e.ellordinate(SR(I), precision=128)[0].sage() # needs sage.symbolic 0.58220358972174117723338947874993600727 - 1.3860608246417697185311834209833653345*I - sage: e.ellordinate(1+3*5^1+O(5^3)) + sage: e.ellordinate(1+3*5^1+O(5^3)) # needs sage.rings.padics [4*5 + 5^2 + O(5^3), 4 + 3*5^2 + O(5^3)] sage: e.ellordinate('z+2*z^2+O(z^4)') [-2*z - 7*z^2 - 23*z^3 + O(z^4), -1 + 2*z + 7*z^2 + 23*z^3 + O(z^4)] @@ -1365,9 +1384,9 @@ [0] sage: e.ellmul(p, 2) [1/4, -7/8] - sage: q = e.ellmul(p, SR(1+I)); q # optional - sage.symbolic + sage: q = e.ellmul(p, SR(1+I)); q # needs sage.symbolic [-2*I, 1 + I] - sage: e.ellmul(q, SR(1-I)) # optional - sage.symbolic + sage: e.ellmul(q, SR(1-I)) # needs sage.symbolic [1/4, -7/8] sage: for D in [-7, -8, -11, -12, -16, -19, -27, -28]: # long time (1s) ....: hcpol = hilbert_class_polynomial(D) @@ -1397,6 +1416,7 @@ sage: e.ellrootno(1009) 1 + sage: # needs sage.rings.real_mpfr sage: e = pari([0,0,0,1,0]).ellinit() sage: C. = ComplexField() sage: e.ellsigma(2+i) @@ -1409,26 +1429,26 @@ sage: e = pari([0,0,0,1,0]).ellinit() sage: e.ellzeta(1) 1.06479841295883 - sage: C. = ComplexField() - sage: e.ellzeta(i-1) + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: e.ellzeta(i-1) # needs sage.rings.real_mpfr -0.350122658523049 - 0.350122658523049*I sage: e = pari([0,0,0,1,0]).ellinit() - sage: C. = ComplexField() - sage: e.ellztopoint(1+i) + sage: C. = ComplexField() # needs sage.rings.real_mpfr + sage: e.ellztopoint(1+i) # needs sage.rings.real_mpfr [0.E-... - 1.02152286795670*I, -0.149072813701096 - 0.149072813701096*I] sage: e.ellztopoint(0) [0] - sage: pari(SR(I)).ellj() + sage: pari(SR(I)).ellj() # needs sage.symbolic 1728.00000000000 - sage: pari(SR(3*I)).ellj() + sage: pari(SR(3*I)).ellj() # needs sage.symbolic 153553679.396729 sage: pari('quadgen(-3)').ellj() 0.E-54 sage: pari('quadgen(-7)').ellj(precision=256).sage() -3375.000000000000000000000000000000000000000000000000000000000000000000000000 - sage: pari(SR(-I)).ellj() + sage: pari(SR(-I)).ellj() # needs sage.symbolic Traceback (most recent call last): ... PariError: domain error in modular function: Im(argument) <= 0 @@ -1497,93 +1517,102 @@ General number fields:: sage: x = polygen(QQ) - sage: K. = NumberField(x^2 - 1/8) + sage: K. = NumberField(x^2 - 1/8) # needs sage.rings.number_field sage: pari(x^2 - 2).factornf(K.pari_polynomial("a")) doctest:...: DeprecationWarning: the PARI/GP function factornf is obsolete (2016-08-08) [x + Mod(-a, a^2 - 2), 1; x + Mod(a, a^2 - 2), 1] - sage: K. = QuadraticField(-23) + sage: K. = QuadraticField(-23) # needs sage.rings.number_field sage: p = K.primes_above(3)[0] sage: K.pari_bnf().bnrclassno(p._pari_bid_()) 3 - sage: x = SR.symbol('x') # optional - sage.symbolic - sage: P = pari(x^6 + 108) # optional - sage.symbolic - sage: G = P.galoisinit() # optional - sage.symbolic - sage: G[0] == P # optional - sage.symbolic + sage: # needs sage.symbolic + sage: x = SR.symbol('x') + sage: P = pari(x^6 + 108) + sage: G = P.galoisinit() + sage: G[0] == P True - sage: len(G[5]) == prod(G[7]) # optional - sage.symbolic + sage: len(G[5]) == prod(G[7]) True - sage: G = pari(x^6 + 108).galoisinit() # optional - sage.symbolic - sage: G.galoispermtopol(G[5]) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: G = pari(x^6 + 108).galoisinit() + sage: G.galoispermtopol(G[5]) [x, 1/12*x^4 - 1/2*x, -1/12*x^4 - 1/2*x, 1/12*x^4 + 1/2*x, -1/12*x^4 + 1/2*x, -x] - sage: G.galoispermtopol(G[5][1]) # optional - sage.symbolic + sage: G.galoispermtopol(G[5][1]) 1/12*x^4 - 1/2*x - sage: G.galoispermtopol(G[5][1:4]) # optional - sage.symbolic + sage: G.galoispermtopol(G[5][1:4]) [1/12*x^4 - 1/2*x, -1/12*x^4 - 1/2*x, 1/12*x^4 + 1/2*x] - sage: G = pari(x^4 + 1).galoisinit() # optional - sage.symbolic - sage: G.galoisfixedfield(G[5][1], flag=2) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: G = pari(x^4 + 1).galoisinit() + sage: G.galoisfixedfield(G[5][1], flag=2) [y^2 - 2, Mod(-x^3 + x, x^4 + 1), [x^2 - y*x + 1, x^2 + y*x + 1]] - sage: G.galoisfixedfield(G[5][5:7]) # optional - sage.symbolic + sage: G.galoisfixedfield(G[5][5:7]) [x^4 + 1, Mod(x, x^4 + 1)] - sage: L = G.galoissubgroups() # optional - sage.symbolic - sage: G.galoisfixedfield(L[3], flag=2, v='z') # optional - sage.symbolic + sage: L = G.galoissubgroups() + sage: G.galoisfixedfield(L[3], flag=2, v='z') [z^2 + 2, Mod(x^3 + x, x^4 + 1), [x^2 - z*x - 1, x^2 + z*x - 1]] - sage: G = pari(x^6 + 108).galoisinit() # optional - sage.symbolic - sage: L = G.galoissubgroups() # optional - sage.symbolic - sage: list(L[0][1]) # optional - sage.symbolic + sage: G = pari(x^6 + 108).galoisinit() + sage: L = G.galoissubgroups() + sage: list(L[0][1]) [3, 2] - sage: G = pari(x^6 + 108).galoisinit() # optional - sage.symbolic - sage: G.galoisisabelian() # optional - sage.symbolic + sage: # needs sage.symbolic + sage: G = pari(x^6 + 108).galoisinit() + sage: G.galoisisabelian() 0 - sage: H = G.galoissubgroups()[2] # optional - sage.symbolic - sage: H.galoisisabelian() # optional - sage.symbolic + sage: H = G.galoissubgroups()[2] + sage: H.galoisisabelian() Mat(2) - sage: H.galoisisabelian(flag=1) # optional - sage.symbolic + sage: H.galoisisabelian(flag=1) 1 - sage: G = pari(x^6 + 108).galoisinit() # optional - sage.symbolic - sage: L = G.galoissubgroups() # optional - sage.symbolic - sage: G.galoisisnormal(L[0]) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: G = pari(x^6 + 108).galoisinit() + sage: L = G.galoissubgroups() + sage: G.galoisisnormal(L[0]) 1 - sage: G.galoisisnormal(L[2]) # optional - sage.symbolic + sage: G.galoisisnormal(L[2]) 0 + sage: # needs sage.rings.number_field sage: F = QuadraticField(5, 'alpha') sage: nf = F.__pari__() sage: P = F.ideal(F.gen()) sage: Q = F.ideal(2) - sage: moduli = pari.matrix(2,2,[P.pari_prime(),4,Q.pari_prime(),4]) + sage: moduli = pari.matrix(2,2,[P.pari_prime(),4,Q.pari_prime(),4]) # needs sage.symbolic sage: residues = pari.vector(2,[0,1]) sage: b = F(nf.idealchinese(moduli,residues)) - sage: b.valuation(P) >= 4 + sage: b.valuation(P) >= 4 # needs sage.symbolic True sage: (b-1).valuation(Q) >= 2 True - sage: F = NumberField(x^3-2, 'alpha') # optional - sage.symbolic - sage: nf = F.__pari__() # optional - sage.symbolic - sage: x = pari('[1, -1, 2]~') # optional - sage.symbolic - sage: y = pari('[1, -1, 3]~') # optional - sage.symbolic - sage: nf.idealcoprime(x, y) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: F = NumberField(x^3-2, 'alpha') + sage: nf = F.__pari__() + sage: x = pari('[1, -1, 2]~') + sage: y = pari('[1, -1, 3]~') + sage: nf.idealcoprime(x, y) 1 sage: y = pari('[2, -2, 4]~') sage: nf.idealcoprime(x, y) [5/43, 9/43, -1/43]~ + sage: # needs sage.rings.number_field sage: R. = PolynomialRing(QQ) sage: K. = NumberField(x^2 + 1) sage: L = K.pari_nf().ideallist(100) - sage: L[0] # One ideal of norm 1. + sage: L[0] # One ideal of norm 1. # needs sage.symbolic [[1, 0; 0, 1]] - sage: L[64] # 4 ideals of norm 65. + sage: L[64] # 4 ideals of norm 65. # needs sage.symbolic [[65, 8; 0, 1], [65, 47; 0, 1], [65, 18; 0, 1], [65, 57; 0, 1]] + sage: # needs sage.rings.number_field sage: F = NumberField(x^3-2, 'alpha') sage: nf = F.__pari__() sage: I = pari('[1, -1, 2]~') @@ -1591,12 +1620,14 @@ sage: nf.ideallog(5, bid) [25]~ + sage: # needs sage.rings.number_field sage: K. = QuadraticField(-1) sage: F = pari(K).idealprimedec(5); F [[5, [-2, 1]~, 1, 1, [2, -1; 1, 2]], [5, [2, 1]~, 1, 1, [-2, -1; 1, -2]]] sage: F[0].pr_get_p() 5 + sage: # needs sage.rings.number_field sage: x = polygen(ZZ) sage: F = NumberField(x^3 - 2, 'alpha') sage: nf = F.__pari__() @@ -1604,6 +1635,7 @@ sage: nf.idealstar(I) [[[43, 9, 5; 0, 1, 0; 0, 0, 1], [0]], [42, [42]], [Mat([[43, [9, 1, 0]~, 1, 1, [-5, 2, -18; -9, -5, 2; 1, -9, -5]], 1]), Mat([[43, [9, 1, 0]~, 1, 1, [-5, 2, -18; -9, -5, 2; 1, -9, -5]], 1])], [[[[42], [3], [43, 9, 5; 0, 1, 0; 0, 0, 1], [[[-14, -8, 20]~, [1, 34, 38], [43, [9, 1, 0]~, 1, 1, [-5, 2, -18; -9, -5, 2; 1, -9, -5]]]~, 3, [42, [2, 1; 3, 1; 7, 1]]]]], [[], Vecsmall([])]], [Mat(1)]] + sage: # needs sage.rings.number_field sage: x = polygen(QQ) sage: K. = NumberField(x^3 - 17) sage: Kpari = K.pari_nf() @@ -1616,12 +1648,14 @@ sage: Kpari.getattr('zk') * pari("[3/2, -5, 0]~") -5/3*y^2 + 5/3*y - 1/6 + sage: # needs sage.rings.number_field sage: k. = NumberField(x^2 + 5) sage: x = 10 sage: y = a + 1 sage: pari(k).nfeltdiveuc(x, y) [2, -2]~ + sage: # needs sage.rings.number_field sage: x = polygen(ZZ) sage: k. = NumberField(x^2 + 5) sage: I = k.ideal(a) @@ -1641,6 +1675,7 @@ sage: nf.nfgaloisconj() [-x, x]~ + sage: # needs sage.rings.number_field sage: x = polygen(QQ) sage: K. = NumberField(x^3 - x + 1) sage: pari(K).nfhilbert(t, t + 2) @@ -1652,6 +1687,7 @@ sage: pari(K).nfhilbert(t, t + 2, P.pari_prime()) 1 + sage: # needs sage.rings.number_field sage: F. = NumberField(x^2-x-1) sage: Fp = pari(F) sage: A = matrix(F,[[1,2,a,3],[3,0,a+2,0],[0,0,a,2],[3+a,a,0,1]]) @@ -1684,6 +1720,7 @@ ... PariError: incorrect type in checknf [please apply nfinit()] (t_REAL) + sage: # needs sage.rings.number_field sage: F = NumberField(x^3-2,'alpha') sage: G = NumberField(x^3-2,'beta') sage: F.__pari__().nfisisom(G.__pari__()) @@ -1743,6 +1780,7 @@ ... PariError: domain error in quadray: isfundamental(D) = 0 + sage: # needs sage.rings.number_field sage.symbolic sage: x = SR.symbol('x') sage: F = NumberField(x^3-2,'alpha') sage: F.__pari__()[0].nfdisc() @@ -1771,6 +1809,7 @@ sage: from cypari2 import Pari sage: pari = Pari() + sage: # needs sage.symbolic sage: f = pari('(2/3)*x^3 + x - 5/7 + y'); f 2/3*x^3 + x + (y - 5/7) sage: var('x,y') diff --git a/src/sage/matrix/args.pyx b/src/sage/matrix/args.pyx index bdb6eb796dd..f1a4c587962 100644 --- a/src/sage/matrix/args.pyx +++ b/src/sage/matrix/args.pyx @@ -1304,7 +1304,7 @@ cdef class MatrixArgs: return MA_ENTRIES_NDARRAY return MA_ENTRIES_SCALAR if isinstance(self.entries, Gen): # PARI object - from sage.libs.pari.convert_sage import pari_typ_to_entries_type + from sage.libs.pari.convert_sage_matrix import pari_typ_to_entries_type return pari_typ_to_entries_type(self) if isinstance(self.entries, MatrixArgs): # Prevent recursion From 3458fbf65e3637a8236eee9eaa478d82e01d8ba4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 16 Jul 2023 21:11:58 -0700 Subject: [PATCH 016/155] Update # needs --- src/sage/libs/pari/convert_sage.pyx | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/sage/libs/pari/convert_sage.pyx b/src/sage/libs/pari/convert_sage.pyx index da75e9595e1..b3726548fb4 100644 --- a/src/sage/libs/pari/convert_sage.pyx +++ b/src/sage/libs/pari/convert_sage.pyx @@ -131,15 +131,15 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept: 15 sage: z = pari('1.234'); z 1.234000000000000000000000000000000000000000000000000000000000000000000 - sage: a = gen_to_sage(z); a + sage: a = gen_to_sage(z); a # needs sage.rings.real_mpfr 1.234000000000000000000000000000000000000000000000000000000000000000000000000 - sage: a.parent() + sage: a.parent() # needs sage.rings.real_mpfr Real Field with 256 bits of precision sage: pari.set_real_precision(15) 70 - sage: a = gen_to_sage(pari('1.234')); a + sage: a = gen_to_sage(pari('1.234')); a # needs sage.rings.real_mpfr 1.23400000000000000 - sage: a.parent() + sage: a.parent() # needs sage.rings.real_mpfr Real Field with 64 bits of precision For complex numbers, the parent depends on the PARI type:: @@ -148,37 +148,37 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept: 3 + I sage: z.type() 't_COMPLEX' - sage: a = gen_to_sage(z); a + sage: a = gen_to_sage(z); a # needs sage.rings.number_field i + 3 - sage: a.parent() + sage: a.parent() # needs sage.rings.number_field Number Field in i with defining polynomial x^2 + 1 with i = 1*I sage: z = pari('(3+I)/2'); z 3/2 + 1/2*I - sage: a = gen_to_sage(z); a + sage: a = gen_to_sage(z); a # needs sage.rings.number_field 1/2*i + 3/2 - sage: a.parent() + sage: a.parent() # needs sage.rings.number_field Number Field in i with defining polynomial x^2 + 1 with i = 1*I sage: z = pari('1.0 + 2.0*I'); z 1.00000000000000 + 2.00000000000000*I - sage: a = gen_to_sage(z); a + sage: a = gen_to_sage(z); a # needs sage.rings.real_mpfr 1.00000000000000000 + 2.00000000000000000*I - sage: a.parent() + sage: a.parent() # needs sage.rings.real_mpfr Complex Field with 64 bits of precision sage: z = pari('1 + 1.0*I'); z 1 + 1.00000000000000*I - sage: a = gen_to_sage(z); a + sage: a = gen_to_sage(z); a # needs sage.rings.real_mpfr 1.00000000000000000 + 1.00000000000000000*I - sage: a.parent() + sage: a.parent() # needs sage.rings.real_mpfr Complex Field with 64 bits of precision sage: z = pari('1.0 + 1*I'); z 1.00000000000000 + I - sage: a = gen_to_sage(z); a + sage: a = gen_to_sage(z); a # needs sage.rings.real_mpfr 1.00000000000000000 + 1.00000000000000000*I - sage: a.parent() + sage: a.parent() # needs sage.rings.real_mpfr Complex Field with 64 bits of precision Converting polynomials:: @@ -241,7 +241,7 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept: 't_MAT' sage: # needs sage.modules - sage: a = gen_to_sage(z); a # needs sage.modules + sage: a = gen_to_sage(z); a [1 2] [3 4] sage: a.parent() From 7c9924a65adb89d69acef681f97d9719e910c20d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 7 Aug 2023 22:44:17 -0700 Subject: [PATCH 017/155] src/sage/libs: sage -fixdoctests --only-tags --- src/sage/libs/pari/tests.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/sage/libs/pari/tests.py b/src/sage/libs/pari/tests.py index 293e53b002f..dd3b3b61c9c 100644 --- a/src/sage/libs/pari/tests.py +++ b/src/sage/libs/pari/tests.py @@ -20,7 +20,7 @@ sage: R. = QQ[] sage: K. = NumberField(theta^2 + 1) # needs sage.rings.number_field - sage: K.absolute_polynomial().galois_group(pari_group=True) + sage: K.absolute_polynomial().galois_group(pari_group=True) # needs sage.rings.number_field PARI group [2, -1, 1, "S2"] of degree 2 Before :trac:`15654`, this used to take a very long time. @@ -29,7 +29,7 @@ sage: pari.allocatemem(200000) PARI stack size set to 200000 bytes, maximum size set to ... sage: x = polygen(ZpFM(3,10)) # needs sage.rings.padics - sage: pol = ((x-1)^50 + x) + sage: pol = ((x-1)^50 + x) # needs sage.rings.padics sage: pari(pol).poldisc() 2*3 + 3^4 + 2*3^6 + 3^7 + 2*3^8 + 2*3^9 + O(3^10) @@ -61,35 +61,35 @@ sage: x = polygen(QQ) sage: K. = NumberField(x^4 - 4*x^2 + 1) # needs sage.rings.number_field - sage: pari(K).nf_get_pol() + sage: pari(K).nf_get_pol() # needs sage.rings.number_field y^4 - 4*y^2 + 1 - sage: L. = K.extension(x^2 - 5) + sage: L. = K.extension(x^2 - 5) # needs sage.rings.number_field sage: pari(L).nf_get_pol() # Absolute y^8 - 28*y^6 + 208*y^4 - 408*y^2 + 36 sage: L.pari_rnf().nf_get_pol() # Relative x^2 - 5 - sage: K.pari_nf().nf_get_pol() + sage: K.pari_nf().nf_get_pol() # needs sage.rings.number_field y^4 - 4*y^2 + 1 - sage: K.pari_bnf().nf_get_pol() + sage: K.pari_bnf().nf_get_pol() # needs sage.rings.number_field y^4 - 4*y^2 + 1 sage: K. = QuadraticField(-65) # needs sage.rings.number_field - sage: G = K.pari_bnf().bnf_get_gen(); G + sage: G = K.pari_bnf().bnf_get_gen(); G # needs sage.rings.number_field [[3, 2; 0, 1], [2, 1; 0, 1]] - sage: [K.ideal(J) for J in G] + sage: [K.ideal(J) for J in G] # needs sage.rings.number_field [Fractional ideal (3, a + 2), Fractional ideal (2, a + 1)] Conversions:: sage: K. = QuadraticField(-1) # needs sage.rings.number_field - sage: F = pari(K).idealfactor(K.ideal(5)); F + sage: F = pari(K).idealfactor(K.ideal(5)); F # needs sage.rings.number_field [[5, [-2, 1]~, 1, 1, [2, -1; 1, 2]], 1; [5, [2, 1]~, 1, 1, [-2, -1; 1, -2]], 1] sage: F[0,0].pr_get_p() 5 sage: K. = QuadraticField(-1) # needs sage.rings.number_field - sage: J = pari(K).idealstar(K.ideal(4*i + 2)) + sage: J = pari(K).idealstar(K.ideal(4*i + 2)) # needs sage.rings.number_field sage: J.bid_get_cyc() [4, 2] @@ -100,7 +100,7 @@ 9223372036854775810 sage: K = Qp(11,5) # needs sage.rings.padics - sage: x = K(11^-10 + 5*11^-7 + 11^-6) + sage: x = K(11^-10 + 5*11^-7 + 11^-6) # needs sage.rings.number_field sage: y = pari(x) sage: y.padicprime() 11 @@ -128,7 +128,7 @@ sage: a = pari(matrix(2,3,[1,2,3,4,5,6])); a, a.type() # needs sage.modules ([1, 2, 3; 4, 5, 6], 't_MAT') sage: v = vector([1.2, 3.4, 5.6]) # needs sage.modules - sage: pari(v) + sage: pari(v) # needs sage.modules [1.20000000000000, 3.40000000000000, 5.60000000000000] Some more exotic examples:: @@ -1518,13 +1518,13 @@ sage: x = polygen(QQ) sage: K. = NumberField(x^2 - 1/8) # needs sage.rings.number_field - sage: pari(x^2 - 2).factornf(K.pari_polynomial("a")) + sage: pari(x^2 - 2).factornf(K.pari_polynomial("a")) # needs sage.rings.number_field doctest:...: DeprecationWarning: the PARI/GP function factornf is obsolete (2016-08-08) [x + Mod(-a, a^2 - 2), 1; x + Mod(a, a^2 - 2), 1] sage: K. = QuadraticField(-23) # needs sage.rings.number_field - sage: p = K.primes_above(3)[0] - sage: K.pari_bnf().bnrclassno(p._pari_bid_()) + sage: p = K.primes_above(3)[0] # needs sage.rings.number_field + sage: K.pari_bnf().bnrclassno(p._pari_bid_()) # needs sage.rings.number_field 3 sage: # needs sage.symbolic @@ -1585,7 +1585,7 @@ sage: Q = F.ideal(2) sage: moduli = pari.matrix(2,2,[P.pari_prime(),4,Q.pari_prime(),4]) # needs sage.symbolic sage: residues = pari.vector(2,[0,1]) - sage: b = F(nf.idealchinese(moduli,residues)) + sage: b = F(nf.idealchinese(moduli,residues)) # needs sage.symbolic sage: b.valuation(P) >= 4 # needs sage.symbolic True sage: (b-1).valuation(Q) >= 2 @@ -1600,7 +1600,7 @@ 1 sage: y = pari('[2, -2, 4]~') - sage: nf.idealcoprime(x, y) + sage: nf.idealcoprime(x, y) # needs sage.rings.number_field [5/43, 9/43, -1/43]~ sage: # needs sage.rings.number_field From 4a7ba1fc03a840bfc59f207c37b02e129f54557b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 1 Sep 2023 17:14:18 -0700 Subject: [PATCH 018/155] src/sage/libs/pari/convert_sage_real_mpfr.pyx: Fix up merge --- src/sage/libs/pari/convert_sage_real_mpfr.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/libs/pari/convert_sage_real_mpfr.pyx b/src/sage/libs/pari/convert_sage_real_mpfr.pyx index 5a45ccff0ae..49b1d6d1b9b 100644 --- a/src/sage/libs/pari/convert_sage_real_mpfr.pyx +++ b/src/sage/libs/pari/convert_sage_real_mpfr.pyx @@ -22,7 +22,7 @@ cpdef Gen new_gen_from_real_mpfr_element(RealNumber self): cdef unsigned long wordsize = sizeof(long)*8 cdef mpfr_prec_t prec - prec = (self._parent).__prec + prec = (self._parent)._prec # We round up the precision to the nearest multiple of wordsize. cdef int rounded_prec From 8af2686e2309e869de35f325e1c703b3aebfe036 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Sep 2023 20:04:01 -0700 Subject: [PATCH 019/155] sage.libs.pari: Update # needs --- .../libs/pari/convert_sage_complex_double.pyx | 2 + src/sage/libs/pari/convert_sage_real_mpfr.pyx | 2 + src/sage/libs/pari/tests.py | 66 ++++++++++--------- 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/sage/libs/pari/convert_sage_complex_double.pyx b/src/sage/libs/pari/convert_sage_complex_double.pyx index c2ee7bec586..b97c3831c75 100644 --- a/src/sage/libs/pari/convert_sage_complex_double.pyx +++ b/src/sage/libs/pari/convert_sage_complex_double.pyx @@ -1,3 +1,5 @@ +# sage.doctest: needs sage.rings.complex_double + from cysignals.signals cimport sig_on, sig_off from sage.libs.gsl.complex cimport * diff --git a/src/sage/libs/pari/convert_sage_real_mpfr.pyx b/src/sage/libs/pari/convert_sage_real_mpfr.pyx index 49b1d6d1b9b..119944a5209 100644 --- a/src/sage/libs/pari/convert_sage_real_mpfr.pyx +++ b/src/sage/libs/pari/convert_sage_real_mpfr.pyx @@ -1,3 +1,5 @@ +# sage.doctest: needs sage.rings.real_mpfr + from cypari2.stack cimport new_gen from cypari2.paridecl cimport * from cysignals.signals cimport sig_on, sig_off diff --git a/src/sage/libs/pari/tests.py b/src/sage/libs/pari/tests.py index dd3b3b61c9c..af5d4b4c367 100644 --- a/src/sage/libs/pari/tests.py +++ b/src/sage/libs/pari/tests.py @@ -30,7 +30,7 @@ PARI stack size set to 200000 bytes, maximum size set to ... sage: x = polygen(ZpFM(3,10)) # needs sage.rings.padics sage: pol = ((x-1)^50 + x) # needs sage.rings.padics - sage: pari(pol).poldisc() + sage: pari(pol).poldisc() # needs sage.rings.padics 2*3 + 3^4 + 2*3^6 + 3^7 + 2*3^8 + 2*3^9 + O(3^10) This used to give the wrong answer before :trac:`23259`:: @@ -59,56 +59,58 @@ Number fields:: + sage: # needs sage.rings.number_field sage: x = polygen(QQ) - sage: K. = NumberField(x^4 - 4*x^2 + 1) # needs sage.rings.number_field - sage: pari(K).nf_get_pol() # needs sage.rings.number_field + sage: K. = NumberField(x^4 - 4*x^2 + 1) + sage: pari(K).nf_get_pol() y^4 - 4*y^2 + 1 - sage: L. = K.extension(x^2 - 5) # needs sage.rings.number_field - sage: pari(L).nf_get_pol() # Absolute + sage: L. = K.extension(x^2 - 5) + sage: pari(L).nf_get_pol() # Absolute y^8 - 28*y^6 + 208*y^4 - 408*y^2 + 36 - sage: L.pari_rnf().nf_get_pol() # Relative + sage: L.pari_rnf().nf_get_pol() # Relative x^2 - 5 - - sage: K.pari_nf().nf_get_pol() # needs sage.rings.number_field + sage: K.pari_nf().nf_get_pol() y^4 - 4*y^2 + 1 - sage: K.pari_bnf().nf_get_pol() # needs sage.rings.number_field + sage: K.pari_bnf().nf_get_pol() y^4 - 4*y^2 + 1 - sage: K. = QuadraticField(-65) # needs sage.rings.number_field - sage: G = K.pari_bnf().bnf_get_gen(); G # needs sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(-65) + sage: G = K.pari_bnf().bnf_get_gen(); G [[3, 2; 0, 1], [2, 1; 0, 1]] - sage: [K.ideal(J) for J in G] # needs sage.rings.number_field + sage: [K.ideal(J) for J in G] [Fractional ideal (3, a + 2), Fractional ideal (2, a + 1)] Conversions:: - sage: K. = QuadraticField(-1) # needs sage.rings.number_field - sage: F = pari(K).idealfactor(K.ideal(5)); F # needs sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(-1) + sage: F = pari(K).idealfactor(K.ideal(5)); F [[5, [-2, 1]~, 1, 1, [2, -1; 1, 2]], 1; [5, [2, 1]~, 1, 1, [-2, -1; 1, -2]], 1] sage: F[0,0].pr_get_p() 5 - - sage: K. = QuadraticField(-1) # needs sage.rings.number_field - sage: J = pari(K).idealstar(K.ideal(4*i + 2)) # needs sage.rings.number_field + sage: J = pari(K).idealstar(K.ideal(4*i + 2)) sage: J.bid_get_cyc() [4, 2] - sage: int(pari(RealField(63)(2^63-1))) # needs sage.rings.real_mpfr + sage: int(pari(RealField(63)(2^63 - 1))) # needs sage.rings.real_mpfr 9223372036854775807 # 32-bit 9223372036854775807 # 64-bit - sage: int(pari(RealField(63)(2^63+2))) # needs sage.rings.real_mpfr + sage: int(pari(RealField(63)(2^63 + 2))) # needs sage.rings.real_mpfr 9223372036854775810 - sage: K = Qp(11,5) # needs sage.rings.padics - sage: x = K(11^-10 + 5*11^-7 + 11^-6) # needs sage.rings.number_field + sage: # needs sage.rings.padics + sage: K = Qp(11,5) + sage: x = K(11^-10 + 5*11^-7 + 11^-6) sage: y = pari(x) sage: y.padicprime() 11 sage: y.padicprime().type() 't_INT' + sage: # needs sage.rings.finite_rings sage: x = polygen(GF(3)) - sage: k. = GF(9, modulus=x^2+1) + sage: k. = GF(9, modulus=x^2 + 1) sage: b = pari(a).ffprimroot() sage: b # random a + 1 @@ -497,13 +499,15 @@ sage: pari([[1.1,2.2],[3.3,4.4]]).floor() [[1, 2], [3, 4]] - sage: x = SR.symbol('x') # needs sage.symbolic - sage: pari(x).floor() # needs sage.symbolic + sage: # needs sage.symbolic + sage: x = SR.symbol('x') + sage: pari(x).floor() x - sage: pari((x^2+x+1)/x).floor() # needs sage.symbolic + sage: pari((x^2+x+1)/x).floor() x + 1 - sage: pari(x^2+5*x+2.5).floor() # needs sage.symbolic + sage: pari(x^2+5*x+2.5).floor() x^2 + 5*x + 2.50000000000000 + sage: pari('"hello world"').floor() Traceback (most recent call last): ... @@ -767,11 +771,13 @@ 0.412710032209716 sage: pari(2).besseli(3) 2.24521244092995 - sage: C. = ComplexField() # needs sage.rings.real_mpfr - sage: pari(2).besseli(3+i) # needs sage.rings.real_mpfr + + sage: # needs sage.rings.real_mpfr + sage: C. = ComplexField() + sage: pari(2).besseli(3+i) 1.12539407613913 + 2.08313822670661*I - sage: C. = ComplexField() # needs sage.rings.real_mpfr - sage: pari(2+i).bessely(3) # needs sage.rings.real_mpfr + sage: C. = ComplexField() + sage: pari(2+i).bessely(3) -0.280775566958244 - 0.486708533223726*I sage: pari(1.5).cos() From 4f9b1095fdbbb29b58eb7fb4e545c377ec57674e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 12 Sep 2023 13:28:10 -0700 Subject: [PATCH 020/155] sage.libs: Update # needs --- src/sage/libs/pari/convert_sage.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/libs/pari/convert_sage.pyx b/src/sage/libs/pari/convert_sage.pyx index b3726548fb4..fd9346915ae 100644 --- a/src/sage/libs/pari/convert_sage.pyx +++ b/src/sage/libs/pari/convert_sage.pyx @@ -207,6 +207,7 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept: Converting vectors:: + sage: # needs sage.rings.number_field sage.rings.real_mpfr sage: z1 = pari('[-3, 2.1, 1+I]'); z1 [-3, 2.10000000000000, 1 + I] sage: z2 = pari('[1.0*I, [1,2]]~'); z2 From bc3c285a4f80f2ed5ab35afe5b20a342785f1886 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 23 Sep 2023 19:55:56 -0700 Subject: [PATCH 021/155] Add # needs --- src/sage/libs/pari/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/libs/pari/tests.py b/src/sage/libs/pari/tests.py index af5d4b4c367..5605d232d9e 100644 --- a/src/sage/libs/pari/tests.py +++ b/src/sage/libs/pari/tests.py @@ -20,7 +20,7 @@ sage: R. = QQ[] sage: K. = NumberField(theta^2 + 1) # needs sage.rings.number_field - sage: K.absolute_polynomial().galois_group(pari_group=True) # needs sage.rings.number_field + sage: K.absolute_polynomial().galois_group(pari_group=True) # needs sage.groups sage.rings.number_field PARI group [2, -1, 1, "S2"] of degree 2 Before :trac:`15654`, this used to take a very long time. From 3c47c556ea5c91232e42a6cc90f3869636cdec88 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 5 Mar 2023 21:38:40 -0800 Subject: [PATCH 022/155] Add # optional - numpy etc. --- src/sage/interfaces/sympy.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/interfaces/sympy.py b/src/sage/interfaces/sympy.py index a334c241127..c380731f8b7 100644 --- a/src/sage/interfaces/sympy.py +++ b/src/sage/interfaces/sympy.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sympy """ SymPy --> Sage conversion From 68f3e3fea2f9fd0b063dcb4849395a4d3b471463 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 13 May 2023 15:58:37 -0700 Subject: [PATCH 023/155] src/sage/interfaces/tides.py: pycodestyle fix --- src/sage/interfaces/tides.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sage/interfaces/tides.py b/src/sage/interfaces/tides.py index f70a2357cd3..1b00f52df54 100644 --- a/src/sage/interfaces/tides.py +++ b/src/sage/interfaces/tides.py @@ -37,8 +37,10 @@ - [TIDES]_ """ + from sage.rings.real_mpfr import RealField -from sage.calculus.all import symbolic_expression +from sage.misc.lazy_import import lazy_import +lazy_import("sage.calculus.all", "symbolic_expression") from sage.misc.flatten import flatten from sage.ext.fast_callable import fast_callable from sage.rings.semirings.non_negative_integer_semiring import NN From 58c324f130d0935040410f93c1956a3ed949f329 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 17 May 2023 13:20:30 -0700 Subject: [PATCH 024/155] Massive modularization fixes --- src/sage/interfaces/expect.py | 2 +- src/sage/interfaces/gp.py | 28 ++++++++++++++-------------- src/sage/interfaces/interface.py | 1 + src/sage/interfaces/jmoldata.py | 6 +++--- src/sage/interfaces/quit.py | 14 +++++++------- src/sage/interfaces/tests.py | 2 +- 6 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/sage/interfaces/expect.py b/src/sage/interfaces/expect.py index 17ad63cfbac..9c38a8c1cba 100644 --- a/src/sage/interfaces/expect.py +++ b/src/sage/interfaces/expect.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: optional - sage.libs.gap sage.libs.pari sage.libs.singular sage.symbolic """ Common Interface Functionality through Pexpect diff --git a/src/sage/interfaces/gp.py b/src/sage/interfaces/gp.py index e5c77833cca..c777bc6bd40 100644 --- a/src/sage/interfaces/gp.py +++ b/src/sage/interfaces/gp.py @@ -787,26 +787,26 @@ def new_with_bits_prec(self, s, precision=0): EXAMPLES:: - sage: pi_def = gp(pi); pi_def + sage: pi_def = gp(pi); pi_def # optional - sage.symbolic 3.141592653589793238462643383 # 32-bit 3.1415926535897932384626433832795028842 # 64-bit - sage: pi_def.precision() + sage: pi_def.precision() # optional - sage.symbolic 28 # 32-bit 38 # 64-bit - sage: pi_150 = gp.new_with_bits_prec(pi, 150) - sage: new_prec = pi_150.precision(); new_prec + sage: pi_150 = gp.new_with_bits_prec(pi, 150) # optional - sage.symbolic + sage: new_prec = pi_150.precision(); new_prec # optional - sage.symbolic 48 # 32-bit 57 # 64-bit - sage: old_prec = gp.set_precision(new_prec); old_prec + sage: old_prec = gp.set_precision(new_prec); old_prec # optional - sage.symbolic 28 # 32-bit 38 # 64-bit - sage: pi_150 + sage: pi_150 # optional - sage.symbolic 3.14159265358979323846264338327950288419716939938 # 32-bit 3.14159265358979323846264338327950288419716939937510582098 # 64-bit - sage: gp.set_precision(old_prec) + sage: gp.set_precision(old_prec) # optional - sage.symbolic 48 # 32-bit 57 # 64-bit - sage: gp.get_precision() + sage: gp.get_precision() # optional - sage.symbolic 28 # 32-bit 38 # 64-bit """ @@ -877,9 +877,9 @@ def _sage_(self): EXAMPLES:: - sage: gp(SR(I)).sage() + sage: gp(SR(I)).sage() # optional - sage.symbolic i - sage: gp(SR(I)).sage().parent() + sage: gp(SR(I)).sage().parent() # optional - sage.symbolic Number Field in i with defining polynomial x^2 + 1 with i = 1*I :: @@ -955,11 +955,11 @@ def _complex_mpfr_field_(self, CC): EXAMPLES:: - sage: z = gp(SR(1+15*I)); z + sage: z = gp(SR(1+15*I)); z # optional - sage.symbolic 1 + 15*I - sage: z._complex_mpfr_field_(CC) + sage: z._complex_mpfr_field_(CC) # optional - sage.symbolic 1.00000000000000 + 15.0000000000000*I - sage: CC(z) # CC(gp(1+15*I)) + sage: CC(z) # CC(gp(1+15*I)) # optional - sage.symbolic 1.00000000000000 + 15.0000000000000*I sage: CC(gp(11243.9812+15*I)) 11243.9812000000 + 15.0000000000000*I @@ -977,7 +977,7 @@ def _complex_double_(self, CDF): EXAMPLES:: - sage: CDF(gp(pi+I*e)) + sage: CDF(gp(pi+I*e)) # optional - sage.symbolic 3.141592653589793 + 2.718281828459045*I """ # Retrieving values from another computer algebra system is diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index 78f94269ff4..4c0f1205092 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sage.libs.gap sage.libs.pari sage.libs.singular sage.symbolic r""" Common Interface Functionality diff --git a/src/sage/interfaces/jmoldata.py b/src/sage/interfaces/jmoldata.py index a68e53e2d85..2890a8a7a76 100644 --- a/src/sage/interfaces/jmoldata.py +++ b/src/sage/interfaces/jmoldata.py @@ -134,10 +134,10 @@ def export_image(self, sage: from sage.interfaces.jmoldata import JmolData sage: JData = JmolData() - sage: D = dodecahedron() + sage: D = dodecahedron() # optional - sage.plot sage: from tempfile import NamedTemporaryFile sage: archive = NamedTemporaryFile(suffix=".zip") - sage: D.export_jmol(archive.name) + sage: D.export_jmol(archive.name) # optional - sage.plot sage: archive_native = archive.name sage: import sys sage: if sys.platform == 'cygwin': @@ -145,7 +145,7 @@ def export_image(self, ....: archive_native = cygwin.cygpath(archive_native, 'w') sage: script = f'set defaultdirectory "f{archive_native}"\n' sage: script += 'script SCRIPT\n' - sage: with NamedTemporaryFile(suffix=".png") as testfile: # optional -- java + sage: with NamedTemporaryFile(suffix=".png") as testfile: # optional -- java sage.plot ....: JData.export_image(targetfile=testfile.name, ....: datafile=script, ....: image_type="PNG") diff --git a/src/sage/interfaces/quit.py b/src/sage/interfaces/quit.py index 575646f2365..afc87aed1a7 100644 --- a/src/sage/interfaces/quit.py +++ b/src/sage/interfaces/quit.py @@ -140,19 +140,19 @@ def invalidate_all(): EXAMPLES:: - sage: a = maxima(2); b = gp(3) - sage: a, b + sage: a = maxima(2); b = gp(3) # optional - sage.libs.pari sage.symbolic + sage: a, b # optional - sage.libs.pari sage.symbolic (2, 3) - sage: sage.interfaces.quit.invalidate_all() - sage: a + sage: sage.interfaces.quit.invalidate_all() # optional - sage.libs.pari sage.symbolic + sage: a # optional - sage.libs.pari sage.symbolic (invalid Maxima object -- The maxima session in which this object was defined is no longer running.) - sage: b + sage: b # optional - sage.libs.pari sage.symbolic (invalid PARI/GP interpreter object -- The pari session in which this object was defined is no longer running.) However the maxima and gp sessions should still work out, though with their state reset:: - sage: a = maxima(2); b = gp(3) - sage: a, b + sage: a = maxima(2); b = gp(3) # optional - sage.libs.pari sage.symbolic + sage: a, b # optional - sage.libs.pari sage.symbolic (2, 3) """ for I in expect_objects: diff --git a/src/sage/interfaces/tests.py b/src/sage/interfaces/tests.py index 8c760c2a2c0..6c0942e04f4 100644 --- a/src/sage/interfaces/tests.py +++ b/src/sage/interfaces/tests.py @@ -13,7 +13,7 @@ 4 sage: parent(a) Gap - sage: a = 2 * maxima('2'); a + sage: a = 2 * maxima('2'); a # optional - sage.symbolic 4 sage: parent(a) Maxima From dc83a6fc45f6d206569e896ba1f30d3359e60df8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 20 May 2023 15:38:10 -0700 Subject: [PATCH 025/155] More # optional --- src/sage/interfaces/axiom.py | 20 ++++++++++---------- src/sage/interfaces/tests.py | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/sage/interfaces/axiom.py b/src/sage/interfaces/axiom.py index 5df8d2e184a..b00e9fc68a0 100644 --- a/src/sage/interfaces/axiom.py +++ b/src/sage/interfaces/axiom.py @@ -796,12 +796,12 @@ def _sage_(self): 2.12340000000000 sage: _.parent() #optional - axiom Real Field with 53 bits of precision - sage: a = RealField(100)(pi) - sage: axiom(a)._sage_() #optional - axiom + sage: a = RealField(100)(pi) # optional - sage.symbolic + sage: axiom(a)._sage_() #optional - axiom # optional - sage.symbolic 3.1415926535897932384626433833 - sage: _.parent() #optional - axiom + sage: _.parent() #optional - axiom # optional - sage.symbolic Real Field with 100 bits of precision - sage: axiom(a)._sage_() == a #optional - axiom + sage: axiom(a)._sage_() == a #optional - axiom # optional - sage.symbolic True sage: axiom(2.0)._sage_() #optional - axiom 2.00000000000000 @@ -810,16 +810,16 @@ def _sage_(self): We can also convert Axiom's polynomials to Sage polynomials. - sage: a = axiom(x^2 + 1) #optional - axiom - sage: a.type() #optional - axiom + sage: a = axiom(x^2 + 1) #optional - axiom # optional - sage.symbolic + sage: a.type() #optional - axiom # optional - sage.symbolic Polynomial Integer - sage: a.sage() #optional - axiom + sage: a.sage() #optional - axiom # optional - sage.symbolic x^2 + 1 - sage: _.parent() #optional - axiom + sage: _.parent() #optional - axiom # optional - sage.symbolic Univariate Polynomial Ring in x over Integer Ring - sage: axiom('x^2 + y^2 + 1/2').sage() #optional - axiom + sage: axiom('x^2 + y^2 + 1/2').sage() #optional - axiom # optional - sage.symbolic y^2 + x^2 + 1/2 - sage: _.parent() #optional - axiom + sage: _.parent() #optional - axiom # optional - sage.symbolic Multivariate Polynomial Ring in y, x over Rational Field diff --git a/src/sage/interfaces/tests.py b/src/sage/interfaces/tests.py index 6c0942e04f4..a77a66e7876 100644 --- a/src/sage/interfaces/tests.py +++ b/src/sage/interfaces/tests.py @@ -15,7 +15,7 @@ Gap sage: a = 2 * maxima('2'); a # optional - sage.symbolic 4 - sage: parent(a) + sage: parent(a) # optional - sage.symbolic Maxima sage: a = 2 * singular('2'); a 4 From 890561498a5d2c8dbabc90f3b8ebfc1944cd21e8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 31 May 2023 23:15:29 -0700 Subject: [PATCH 026/155] sage.interfaces: Modularization fixes --- src/sage/interfaces/gp.py | 1 + src/sage/interfaces/interface.py | 20 +++++++------- src/sage/interfaces/maxima_abstract.py | 37 +++++++++++++++----------- src/sage/interfaces/sympy_wrapper.py | 1 + 4 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/sage/interfaces/gp.py b/src/sage/interfaces/gp.py index c777bc6bd40..974ef82a406 100644 --- a/src/sage/interfaces/gp.py +++ b/src/sage/interfaces/gp.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sage.libs.pari r""" Interface to the GP calculator of PARI/GP diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index 4c0f1205092..3774d033e0f 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -349,14 +349,14 @@ def _coerce_impl(self, x, use_special=True): if isinstance(x, bool): return self(self._true_symbol() if x else self._false_symbol()) elif isinstance(x, int): - import sage.rings.all - return self(sage.rings.all.Integer(x)) + from sage.rings.integer import Integer + return self(Integer(x)) elif isinstance(x, float): - import sage.rings.all - return self(sage.rings.all.RDF(x)) + from sage.rings.real_double import RDF + return self(RDF(x)) elif isinstance(x, complex): - import sage.rings.all - return self(sage.rings.all.CDF(x)) + from sage.rings.complex_double import CDF + return self(CDF(x)) if use_special: try: return self._coerce_from_special_method(x) @@ -1374,8 +1374,8 @@ def _integer_(self, ZZ=None): sage: QQ(m) 1 """ - import sage.rings.all - return sage.rings.all.Integer(repr(self)) + from sage.rings.integer import Integer + return Integer(repr(self)) def _rational_(self): """ @@ -1389,8 +1389,8 @@ def _rational_(self): sage: QQ(m) 1/2 """ - import sage.rings.all - return sage.rings.all.Rational(repr(self)) + from sage.rings.rational import Rational + return Rational(repr(self)) def name(self, new_name=None): """ diff --git a/src/sage/interfaces/maxima_abstract.py b/src/sage/interfaces/maxima_abstract.py index 9fe624a7f02..bdb4494edf9 100644 --- a/src/sage/interfaces/maxima_abstract.py +++ b/src/sage/interfaces/maxima_abstract.py @@ -1020,11 +1020,13 @@ def plot_list(self, ptsx, ptsy, options=None): EXAMPLES:: - sage: zeta_ptsx = [ (pari(1/2 + i*I/10).zeta().real()).precision(1) for i in range(70,150)] - sage: zeta_ptsy = [ (pari(1/2 + i*I/10).zeta().imag()).precision(1) for i in range(70,150)] - sage: maxima.plot_list(zeta_ptsx, zeta_ptsy) # not tested + sage: zeta_ptsx = [(pari(1/2 + i*I/10).zeta().real()).precision(1) # optional - sage.libs.pari + ....: for i in range(70,150)] + sage: zeta_ptsy = [(pari(1/2 + i*I/10).zeta().imag()).precision(1) # optional - sage.libs.pari + ....: for i in range(70,150)] + sage: maxima.plot_list(zeta_ptsx, zeta_ptsy) # not tested # optional - sage.libs.pari sage: opts='[gnuplot_preamble, "set nokey"], [gnuplot_term, ps], [gnuplot_out_file, "zeta.eps"]' - sage: maxima.plot_list(zeta_ptsx, zeta_ptsy, opts) # not tested + sage: maxima.plot_list(zeta_ptsx, zeta_ptsy, opts) # not tested # optional - sage.libs.pari """ cmd = 'plot2d([discrete,%s, %s]' % (ptsx, ptsy) if options is None: @@ -1056,18 +1058,23 @@ def plot_multilist(self, pts_list, options=None): EXAMPLES:: - sage: xx = [ i/10.0 for i in range(-10,10)] - sage: yy = [ i/10.0 for i in range(-10,10)] - sage: x0 = [ 0 for i in range(-10,10)] - sage: y0 = [ 0 for i in range(-10,10)] - sage: zeta_ptsx1 = [ (pari(1/2+i*I/10).zeta().real()).precision(1) for i in range(10)] - sage: zeta_ptsy1 = [ (pari(1/2+i*I/10).zeta().imag()).precision(1) for i in range(10)] - sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1],[xx,y0],[x0,yy]]) # not tested - sage: zeta_ptsx1 = [ (pari(1/2+i*I/10).zeta().real()).precision(1) for i in range(10,150)] - sage: zeta_ptsy1 = [ (pari(1/2+i*I/10).zeta().imag()).precision(1) for i in range(10,150)] - sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1],[xx,y0],[x0,yy]]) # not tested + sage: xx = [i/10.0 for i in range(-10,10)] + sage: yy = [i/10.0 for i in range(-10,10)] + sage: x0 = [0 for i in range(-10,10)] + sage: y0 = [0 for i in range(-10,10)] + sage: zeta_ptsx1 = [(pari(1/2+i*I/10).zeta().real()).precision(1) # optional - sage.libs.pari + ....: for i in range(10)] + sage: zeta_ptsy1 = [(pari(1/2+i*I/10).zeta().imag()).precision(1) # optional - sage.libs.pari + ....: for i in range(10)] + sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1], [xx,y0], [x0,yy]]) # not tested + sage: zeta_ptsx1 = [(pari(1/2+i*I/10).zeta().real()).precision(1) # optional - sage.libs.pari + ....: for i in range(10,150)] + sage: zeta_ptsy1 = [(pari(1/2+i*I/10).zeta().imag()).precision(1) # optional - sage.libs.pari + ....: for i in range(10,150)] + sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1], [xx,y0], [x0,yy]]) # not tested sage: opts='[gnuplot_preamble, "set nokey"]' - sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1],[xx,y0],[x0,yy]],opts) # not tested + sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1], [xx,y0], [x0,yy]], # not tested + ....: opts) """ n = len(pts_list) cmd = '[' diff --git a/src/sage/interfaces/sympy_wrapper.py b/src/sage/interfaces/sympy_wrapper.py index 7f49cb76923..792d1eaee99 100644 --- a/src/sage/interfaces/sympy_wrapper.py +++ b/src/sage/interfaces/sympy_wrapper.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sympy """ Wrapper Class for Sage Sets as SymPy Sets """ From 12c0bb4d05f534aebe9cbf13ad350a091253594c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 11 Jun 2023 23:47:37 -0700 Subject: [PATCH 027/155] More # optional --- src/sage/interfaces/quit.py | 18 +++++++++--------- src/sage/interfaces/sagespawn.pyx | 1 + 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/sage/interfaces/quit.py b/src/sage/interfaces/quit.py index afc87aed1a7..720ea3f080a 100644 --- a/src/sage/interfaces/quit.py +++ b/src/sage/interfaces/quit.py @@ -63,14 +63,14 @@ def expect_quitall(verbose=False): EXAMPLES:: sage: sage.interfaces.quit.expect_quitall() - sage: gp.eval('a=10') + sage: gp.eval('a=10') # optional - sage.libs.pari '10' - sage: gp('a') + sage: gp('a') # optional - sage.libs.pari 10 sage: sage.interfaces.quit.expect_quitall() - sage: gp('a') + sage: gp('a') # optional - sage.libs.pari a - sage: sage.interfaces.quit.expect_quitall(verbose=True) + sage: sage.interfaces.quit.expect_quitall(verbose=True) # optional - sage.libs.pari Exiting PARI/GP interpreter with PID ... running .../gp --fast --emacs --quiet --stacksize 10000000 """ for P in expect_objects: @@ -87,18 +87,18 @@ def kill_spawned_jobs(verbose=False): """ INPUT: - - ``verbose`` -- bool (default: False); if True, display a - message each time a process is sent a kill signal + - ``verbose`` -- bool (default: ``False``); if ``True``, display a + message each time a process is sent a kill signal EXAMPLES:: - sage: gp.eval('a=10') + sage: gp.eval('a=10') # optional - sage.libs.pari '10' sage: sage.interfaces.quit.kill_spawned_jobs(verbose=False) sage: sage.interfaces.quit.expect_quitall() - sage: gp.eval('a=10') + sage: gp.eval('a=10') # optional - sage.libs.pari '10' - sage: sage.interfaces.quit.kill_spawned_jobs(verbose=True) + sage: sage.interfaces.quit.kill_spawned_jobs(verbose=True) # optional - sage.libs.pari Killing spawned job ... After doing the above, we do the following to avoid confusion in other doctests:: diff --git a/src/sage/interfaces/sagespawn.pyx b/src/sage/interfaces/sagespawn.pyx index 6bb9b90e580..497efc74bba 100644 --- a/src/sage/interfaces/sagespawn.pyx +++ b/src/sage/interfaces/sagespawn.pyx @@ -1,3 +1,4 @@ +# sage.doctest: optional - ptyprocess """ Sage wrapper around pexpect's ``spawn`` class and the ptyprocess's ``PtyProcess`` class. From 520b3e1c2924add211894f19f2c30377fce1bfa6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 19 Jun 2023 00:11:47 -0700 Subject: [PATCH 028/155] More # optional --- src/sage/interfaces/sage0.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/interfaces/sage0.py b/src/sage/interfaces/sage0.py index 9eddb7019f7..a8bb27975c3 100644 --- a/src/sage/interfaces/sage0.py +++ b/src/sage/interfaces/sage0.py @@ -506,9 +506,9 @@ def _sage_(self): EXAMPLES:: - sage: sr = mq.SR(allow_zero_inversions=True) - sage: F,s = sr.polynomial_system() - sage: F == sage0(F)._sage_() + sage: sr = mq.SR(allow_zero_inversions=True) # optional - sage.modules + sage: F,s = sr.polynomial_system() # optional - sage.modules + sage: F == sage0(F)._sage_() # optional - sage.modules True """ P = self.parent() From 5fab34b7d43e19cbdb030d206353153d52fb6dc0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 19 Jun 2023 23:43:13 -0700 Subject: [PATCH 029/155] More # optional --- src/sage/interfaces/sage0.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/interfaces/sage0.py b/src/sage/interfaces/sage0.py index a8bb27975c3..0d43f2bd6b9 100644 --- a/src/sage/interfaces/sage0.py +++ b/src/sage/interfaces/sage0.py @@ -506,9 +506,9 @@ def _sage_(self): EXAMPLES:: - sage: sr = mq.SR(allow_zero_inversions=True) # optional - sage.modules - sage: F,s = sr.polynomial_system() # optional - sage.modules - sage: F == sage0(F)._sage_() # optional - sage.modules + sage: sr = mq.SR(allow_zero_inversions=True) # optional - sage.modules sage.rings.finite_rings + sage: F,s = sr.polynomial_system() # optional - sage.modules sage.rings.finite_rings + sage: F == sage0(F)._sage_() # optional - sage.modules sage.rings.finite_rings True """ P = self.parent() From 962eeacad3728fe7bd8640205879808dbdb14df7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 12 Jul 2023 17:25:38 -0700 Subject: [PATCH 030/155] ./sage -fixdoctests --no-test src/sage/interfaces --- src/sage/interfaces/axiom.py | 20 +++++++++--------- src/sage/interfaces/gfan.py | 4 ++-- src/sage/interfaces/gp.py | 28 +++++++++++++------------- src/sage/interfaces/jmoldata.py | 6 +++--- src/sage/interfaces/maxima_abstract.py | 16 +++++++-------- src/sage/interfaces/quit.py | 28 +++++++++++++------------- src/sage/interfaces/sage0.py | 6 +++--- src/sage/interfaces/tests.py | 4 ++-- 8 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/sage/interfaces/axiom.py b/src/sage/interfaces/axiom.py index b00e9fc68a0..f61fcc638f9 100644 --- a/src/sage/interfaces/axiom.py +++ b/src/sage/interfaces/axiom.py @@ -796,12 +796,12 @@ def _sage_(self): 2.12340000000000 sage: _.parent() #optional - axiom Real Field with 53 bits of precision - sage: a = RealField(100)(pi) # optional - sage.symbolic - sage: axiom(a)._sage_() #optional - axiom # optional - sage.symbolic + sage: a = RealField(100)(pi) # needs sage.symbolic + sage: axiom(a)._sage_() # optional - axiom # needs sage.symbolic 3.1415926535897932384626433833 - sage: _.parent() #optional - axiom # optional - sage.symbolic + sage: _.parent() # optional - axiom # needs sage.symbolic Real Field with 100 bits of precision - sage: axiom(a)._sage_() == a #optional - axiom # optional - sage.symbolic + sage: axiom(a)._sage_() == a # optional - axiom # needs sage.symbolic True sage: axiom(2.0)._sage_() #optional - axiom 2.00000000000000 @@ -810,16 +810,16 @@ def _sage_(self): We can also convert Axiom's polynomials to Sage polynomials. - sage: a = axiom(x^2 + 1) #optional - axiom # optional - sage.symbolic - sage: a.type() #optional - axiom # optional - sage.symbolic + sage: a = axiom(x^2 + 1) # optional - axiom # needs sage.symbolic + sage: a.type() # optional - axiom # needs sage.symbolic Polynomial Integer - sage: a.sage() #optional - axiom # optional - sage.symbolic + sage: a.sage() # optional - axiom # needs sage.symbolic x^2 + 1 - sage: _.parent() #optional - axiom # optional - sage.symbolic + sage: _.parent() # optional - axiom # needs sage.symbolic Univariate Polynomial Ring in x over Integer Ring - sage: axiom('x^2 + y^2 + 1/2').sage() #optional - axiom # optional - sage.symbolic + sage: axiom('x^2 + y^2 + 1/2').sage() # optional - axiom # needs sage.symbolic y^2 + x^2 + 1/2 - sage: _.parent() #optional - axiom # optional - sage.symbolic + sage: _.parent() # optional - axiom # needs sage.symbolic Multivariate Polynomial Ring in y, x over Rational Field diff --git a/src/sage/interfaces/gfan.py b/src/sage/interfaces/gfan.py index ffb75c39b35..01429c5cde6 100644 --- a/src/sage/interfaces/gfan.py +++ b/src/sage/interfaces/gfan.py @@ -63,7 +63,7 @@ def __call__(self, input, cmd='', verbose=False, format=None): EXAMPLES:: - sage: print(gfan('Q[x,y]{x^2-y-1,y^2-xy-2/3}', cmd='bases')) # optional - gfan + sage: print(gfan('Q[x,y]{x^2-y-1,y^2-xy-2/3}', cmd='bases')) # needs gfan Q[x,y] {{ y^4+4/9-7/3*y^2-y^3, @@ -85,7 +85,7 @@ def __call__(self, input, cmd='', verbose=False, format=None): TESTS:: - sage: _ = gfan(I='Q[x,y]{x^2-y-1,y^2-xy-2/3}', cmd='bases') # optional - gfan + sage: _ = gfan(I='Q[x,y]{x^2-y-1,y^2-xy-2/3}', cmd='bases') # needs gfan doctest:...: DeprecationWarning: use the option 'input' instead of 'I' See https://github.com/sagemath/sage/issues/33468 for details. diff --git a/src/sage/interfaces/gp.py b/src/sage/interfaces/gp.py index 974ef82a406..d1085562828 100644 --- a/src/sage/interfaces/gp.py +++ b/src/sage/interfaces/gp.py @@ -788,26 +788,26 @@ def new_with_bits_prec(self, s, precision=0): EXAMPLES:: - sage: pi_def = gp(pi); pi_def # optional - sage.symbolic + sage: pi_def = gp(pi); pi_def # needs sage.symbolic 3.141592653589793238462643383 # 32-bit 3.1415926535897932384626433832795028842 # 64-bit - sage: pi_def.precision() # optional - sage.symbolic + sage: pi_def.precision() # needs sage.symbolic 28 # 32-bit 38 # 64-bit - sage: pi_150 = gp.new_with_bits_prec(pi, 150) # optional - sage.symbolic - sage: new_prec = pi_150.precision(); new_prec # optional - sage.symbolic + sage: pi_150 = gp.new_with_bits_prec(pi, 150) # needs sage.symbolic + sage: new_prec = pi_150.precision(); new_prec # needs sage.symbolic 48 # 32-bit 57 # 64-bit - sage: old_prec = gp.set_precision(new_prec); old_prec # optional - sage.symbolic + sage: old_prec = gp.set_precision(new_prec); old_prec # needs sage.symbolic 28 # 32-bit 38 # 64-bit - sage: pi_150 # optional - sage.symbolic + sage: pi_150 # needs sage.symbolic 3.14159265358979323846264338327950288419716939938 # 32-bit 3.14159265358979323846264338327950288419716939937510582098 # 64-bit - sage: gp.set_precision(old_prec) # optional - sage.symbolic + sage: gp.set_precision(old_prec) # needs sage.symbolic 48 # 32-bit 57 # 64-bit - sage: gp.get_precision() # optional - sage.symbolic + sage: gp.get_precision() # needs sage.symbolic 28 # 32-bit 38 # 64-bit """ @@ -878,9 +878,9 @@ def _sage_(self): EXAMPLES:: - sage: gp(SR(I)).sage() # optional - sage.symbolic + sage: gp(SR(I)).sage() # needs sage.symbolic i - sage: gp(SR(I)).sage().parent() # optional - sage.symbolic + sage: gp(SR(I)).sage().parent() # needs sage.symbolic Number Field in i with defining polynomial x^2 + 1 with i = 1*I :: @@ -956,11 +956,11 @@ def _complex_mpfr_field_(self, CC): EXAMPLES:: - sage: z = gp(SR(1+15*I)); z # optional - sage.symbolic + sage: z = gp(SR(1+15*I)); z # needs sage.symbolic 1 + 15*I - sage: z._complex_mpfr_field_(CC) # optional - sage.symbolic + sage: z._complex_mpfr_field_(CC) # needs sage.symbolic 1.00000000000000 + 15.0000000000000*I - sage: CC(z) # CC(gp(1+15*I)) # optional - sage.symbolic + sage: CC(z) # CC(gp(1+15*I)) # needs sage.symbolic 1.00000000000000 + 15.0000000000000*I sage: CC(gp(11243.9812+15*I)) 11243.9812000000 + 15.0000000000000*I @@ -978,7 +978,7 @@ def _complex_double_(self, CDF): EXAMPLES:: - sage: CDF(gp(pi+I*e)) # optional - sage.symbolic + sage: CDF(gp(pi+I*e)) # needs sage.symbolic 3.141592653589793 + 2.718281828459045*I """ # Retrieving values from another computer algebra system is diff --git a/src/sage/interfaces/jmoldata.py b/src/sage/interfaces/jmoldata.py index 2890a8a7a76..3e83043d747 100644 --- a/src/sage/interfaces/jmoldata.py +++ b/src/sage/interfaces/jmoldata.py @@ -134,10 +134,10 @@ def export_image(self, sage: from sage.interfaces.jmoldata import JmolData sage: JData = JmolData() - sage: D = dodecahedron() # optional - sage.plot + sage: D = dodecahedron() # needs sage.plot sage: from tempfile import NamedTemporaryFile sage: archive = NamedTemporaryFile(suffix=".zip") - sage: D.export_jmol(archive.name) # optional - sage.plot + sage: D.export_jmol(archive.name) # needs sage.plot sage: archive_native = archive.name sage: import sys sage: if sys.platform == 'cygwin': @@ -145,7 +145,7 @@ def export_image(self, ....: archive_native = cygwin.cygpath(archive_native, 'w') sage: script = f'set defaultdirectory "f{archive_native}"\n' sage: script += 'script SCRIPT\n' - sage: with NamedTemporaryFile(suffix=".png") as testfile: # optional -- java sage.plot + sage: with NamedTemporaryFile(suffix=".png") as testfile: # optional - java, needs sage.plot ....: JData.export_image(targetfile=testfile.name, ....: datafile=script, ....: image_type="PNG") diff --git a/src/sage/interfaces/maxima_abstract.py b/src/sage/interfaces/maxima_abstract.py index bdb4494edf9..abc43baf127 100644 --- a/src/sage/interfaces/maxima_abstract.py +++ b/src/sage/interfaces/maxima_abstract.py @@ -1020,13 +1020,13 @@ def plot_list(self, ptsx, ptsy, options=None): EXAMPLES:: - sage: zeta_ptsx = [(pari(1/2 + i*I/10).zeta().real()).precision(1) # optional - sage.libs.pari + sage: zeta_ptsx = [(pari(1/2 + i*I/10).zeta().real()).precision(1) # needs sage.libs.pari ....: for i in range(70,150)] - sage: zeta_ptsy = [(pari(1/2 + i*I/10).zeta().imag()).precision(1) # optional - sage.libs.pari + sage: zeta_ptsy = [(pari(1/2 + i*I/10).zeta().imag()).precision(1) # needs sage.libs.pari ....: for i in range(70,150)] - sage: maxima.plot_list(zeta_ptsx, zeta_ptsy) # not tested # optional - sage.libs.pari + sage: maxima.plot_list(zeta_ptsx, zeta_ptsy) # not tested # needs sage.libs.pari sage: opts='[gnuplot_preamble, "set nokey"], [gnuplot_term, ps], [gnuplot_out_file, "zeta.eps"]' - sage: maxima.plot_list(zeta_ptsx, zeta_ptsy, opts) # not tested # optional - sage.libs.pari + sage: maxima.plot_list(zeta_ptsx, zeta_ptsy, opts) # not tested # needs sage.libs.pari """ cmd = 'plot2d([discrete,%s, %s]' % (ptsx, ptsy) if options is None: @@ -1062,14 +1062,14 @@ def plot_multilist(self, pts_list, options=None): sage: yy = [i/10.0 for i in range(-10,10)] sage: x0 = [0 for i in range(-10,10)] sage: y0 = [0 for i in range(-10,10)] - sage: zeta_ptsx1 = [(pari(1/2+i*I/10).zeta().real()).precision(1) # optional - sage.libs.pari + sage: zeta_ptsx1 = [(pari(1/2+i*I/10).zeta().real()).precision(1) # needs sage.libs.pari ....: for i in range(10)] - sage: zeta_ptsy1 = [(pari(1/2+i*I/10).zeta().imag()).precision(1) # optional - sage.libs.pari + sage: zeta_ptsy1 = [(pari(1/2+i*I/10).zeta().imag()).precision(1) # needs sage.libs.pari ....: for i in range(10)] sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1], [xx,y0], [x0,yy]]) # not tested - sage: zeta_ptsx1 = [(pari(1/2+i*I/10).zeta().real()).precision(1) # optional - sage.libs.pari + sage: zeta_ptsx1 = [(pari(1/2+i*I/10).zeta().real()).precision(1) # needs sage.libs.pari ....: for i in range(10,150)] - sage: zeta_ptsy1 = [(pari(1/2+i*I/10).zeta().imag()).precision(1) # optional - sage.libs.pari + sage: zeta_ptsy1 = [(pari(1/2+i*I/10).zeta().imag()).precision(1) # needs sage.libs.pari ....: for i in range(10,150)] sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1], [xx,y0], [x0,yy]]) # not tested sage: opts='[gnuplot_preamble, "set nokey"]' diff --git a/src/sage/interfaces/quit.py b/src/sage/interfaces/quit.py index 720ea3f080a..99e5aa018f3 100644 --- a/src/sage/interfaces/quit.py +++ b/src/sage/interfaces/quit.py @@ -63,14 +63,14 @@ def expect_quitall(verbose=False): EXAMPLES:: sage: sage.interfaces.quit.expect_quitall() - sage: gp.eval('a=10') # optional - sage.libs.pari + sage: gp.eval('a=10') # needs sage.libs.pari '10' - sage: gp('a') # optional - sage.libs.pari + sage: gp('a') # needs sage.libs.pari 10 sage: sage.interfaces.quit.expect_quitall() - sage: gp('a') # optional - sage.libs.pari + sage: gp('a') # needs sage.libs.pari a - sage: sage.interfaces.quit.expect_quitall(verbose=True) # optional - sage.libs.pari + sage: sage.interfaces.quit.expect_quitall(verbose=True) # needs sage.libs.pari Exiting PARI/GP interpreter with PID ... running .../gp --fast --emacs --quiet --stacksize 10000000 """ for P in expect_objects: @@ -92,13 +92,13 @@ def kill_spawned_jobs(verbose=False): EXAMPLES:: - sage: gp.eval('a=10') # optional - sage.libs.pari + sage: gp.eval('a=10') # needs sage.libs.pari '10' sage: sage.interfaces.quit.kill_spawned_jobs(verbose=False) sage: sage.interfaces.quit.expect_quitall() - sage: gp.eval('a=10') # optional - sage.libs.pari + sage: gp.eval('a=10') # needs sage.libs.pari '10' - sage: sage.interfaces.quit.kill_spawned_jobs(verbose=True) # optional - sage.libs.pari + sage: sage.interfaces.quit.kill_spawned_jobs(verbose=True) # needs sage.libs.pari Killing spawned job ... After doing the above, we do the following to avoid confusion in other doctests:: @@ -140,19 +140,19 @@ def invalidate_all(): EXAMPLES:: - sage: a = maxima(2); b = gp(3) # optional - sage.libs.pari sage.symbolic - sage: a, b # optional - sage.libs.pari sage.symbolic + sage: a = maxima(2); b = gp(3) # needs sage.libs.pari sage.symbolic + sage: a, b # needs sage.libs.pari sage.symbolic (2, 3) - sage: sage.interfaces.quit.invalidate_all() # optional - sage.libs.pari sage.symbolic - sage: a # optional - sage.libs.pari sage.symbolic + sage: sage.interfaces.quit.invalidate_all() # needs sage.libs.pari sage.symbolic + sage: a # needs sage.libs.pari sage.symbolic (invalid Maxima object -- The maxima session in which this object was defined is no longer running.) - sage: b # optional - sage.libs.pari sage.symbolic + sage: b # needs sage.libs.pari sage.symbolic (invalid PARI/GP interpreter object -- The pari session in which this object was defined is no longer running.) However the maxima and gp sessions should still work out, though with their state reset:: - sage: a = maxima(2); b = gp(3) # optional - sage.libs.pari sage.symbolic - sage: a, b # optional - sage.libs.pari sage.symbolic + sage: a = maxima(2); b = gp(3) # needs sage.libs.pari sage.symbolic + sage: a, b # needs sage.libs.pari sage.symbolic (2, 3) """ for I in expect_objects: diff --git a/src/sage/interfaces/sage0.py b/src/sage/interfaces/sage0.py index 0d43f2bd6b9..1505d1f2f69 100644 --- a/src/sage/interfaces/sage0.py +++ b/src/sage/interfaces/sage0.py @@ -506,9 +506,9 @@ def _sage_(self): EXAMPLES:: - sage: sr = mq.SR(allow_zero_inversions=True) # optional - sage.modules sage.rings.finite_rings - sage: F,s = sr.polynomial_system() # optional - sage.modules sage.rings.finite_rings - sage: F == sage0(F)._sage_() # optional - sage.modules sage.rings.finite_rings + sage: sr = mq.SR(allow_zero_inversions=True) # needs sage.modules sage.rings.finite_rings + sage: F,s = sr.polynomial_system() # needs sage.modules sage.rings.finite_rings + sage: F == sage0(F)._sage_() # needs sage.modules sage.rings.finite_rings True """ P = self.parent() diff --git a/src/sage/interfaces/tests.py b/src/sage/interfaces/tests.py index a77a66e7876..13f755b4d11 100644 --- a/src/sage/interfaces/tests.py +++ b/src/sage/interfaces/tests.py @@ -13,9 +13,9 @@ 4 sage: parent(a) Gap - sage: a = 2 * maxima('2'); a # optional - sage.symbolic + sage: a = 2 * maxima('2'); a # needs sage.symbolic 4 - sage: parent(a) # optional - sage.symbolic + sage: parent(a) # needs sage.symbolic Maxima sage: a = 2 * singular('2'); a 4 From be49efe987d7b7a39734c5386955183560d90782 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 13 Jul 2023 22:30:42 -0700 Subject: [PATCH 031/155] sage.interfaces: Update # needs --- src/sage/interfaces/interface.py | 18 ++++++++++-------- src/sage/interfaces/quit.py | 11 ++++++----- src/sage/interfaces/sage0.py | 1 + 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index 3774d033e0f..94b8307cea4 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -882,11 +882,12 @@ def _reduce(self): by the doctests because the original identifier was reused. This test makes sure that does not happen again:: - sage: a = r("'abc'") # optional - rpy2 - sage: b = dumps(a) # optional - rpy2 - sage: r.set(a.name(), 0) # make sure that identifier reuse # optional - rpy2 + sage: # optional - rpy2 + sage: a = r("'abc'") + sage: b = dumps(a) + sage: r.set(a.name(), 0) # make sure that identifier reuse ....: # does not accidentally lead to success - sage: loads(b) # optional - rpy2 + sage: loads(b) [1] "abc" """ @@ -1402,13 +1403,14 @@ def name(self, new_name=None): EXAMPLES:: - sage: x = r([1,2,3]); x # optional - rpy2 + sage: # optional - rpy2 + sage: x = r([1,2,3]); x [1] 1 2 3 - sage: x.name() # optional - rpy2 + sage: x.name() 'sage...' - sage: x = r([1,2,3]).name('x'); x # optional - rpy2 + sage: x = r([1,2,3]).name('x'); x [1] 1 2 3 - sage: x.name() # optional - rpy2 + sage: x.name() 'x' :: diff --git a/src/sage/interfaces/quit.py b/src/sage/interfaces/quit.py index 99e5aa018f3..c10b1414dde 100644 --- a/src/sage/interfaces/quit.py +++ b/src/sage/interfaces/quit.py @@ -140,13 +140,14 @@ def invalidate_all(): EXAMPLES:: - sage: a = maxima(2); b = gp(3) # needs sage.libs.pari sage.symbolic - sage: a, b # needs sage.libs.pari sage.symbolic + sage: # needs sage.libs.pari sage.symbolic + sage: a = maxima(2); b = gp(3) + sage: a, b (2, 3) - sage: sage.interfaces.quit.invalidate_all() # needs sage.libs.pari sage.symbolic - sage: a # needs sage.libs.pari sage.symbolic + sage: sage.interfaces.quit.invalidate_all() + sage: a (invalid Maxima object -- The maxima session in which this object was defined is no longer running.) - sage: b # needs sage.libs.pari sage.symbolic + sage: b (invalid PARI/GP interpreter object -- The pari session in which this object was defined is no longer running.) However the maxima and gp sessions should still work out, though with their state reset:: diff --git a/src/sage/interfaces/sage0.py b/src/sage/interfaces/sage0.py index 1505d1f2f69..11ece30ac56 100644 --- a/src/sage/interfaces/sage0.py +++ b/src/sage/interfaces/sage0.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.all r""" Interface to Sage From 7fb10c60d8487f232c57ebb1670703e6f1f60ee0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 6 Aug 2023 20:45:08 -0700 Subject: [PATCH 032/155] src/sage/interfaces: Update file-level doctest tag --- src/sage/interfaces/expect.py | 2 +- src/sage/interfaces/gp.py | 3 ++- src/sage/interfaces/interface.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/sage/interfaces/expect.py b/src/sage/interfaces/expect.py index 9c38a8c1cba..a5ba8f09f4e 100644 --- a/src/sage/interfaces/expect.py +++ b/src/sage/interfaces/expect.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.libs.gap sage.libs.pari sage.libs.singular sage.symbolic +# sage.doctest: needs sage.libs.gap sage.libs.pari sage.libs.singular sage.symbolic """ Common Interface Functionality through Pexpect diff --git a/src/sage/interfaces/gp.py b/src/sage/interfaces/gp.py index d1085562828..6e12504e829 100644 --- a/src/sage/interfaces/gp.py +++ b/src/sage/interfaces/gp.py @@ -1,4 +1,5 @@ -# sage.doctest: optional - sage.libs.pari +# sage_setup: distribution = sagemath-pari +# sage.doctest: needs sage.libs.pari r""" Interface to the GP calculator of PARI/GP diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index 94b8307cea4..8e89aa65c1e 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.libs.gap sage.libs.pari sage.libs.singular sage.symbolic +# sage.doctest: needs sage.libs.gap sage.libs.pari sage.libs.singular sage.symbolic r""" Common Interface Functionality From c2b63b2f88e6a9fdb654eafbb7c29250c2ee62bd Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 7 Aug 2023 22:44:16 -0700 Subject: [PATCH 033/155] src/sage/interfaces: sage -fixdoctests --only-tags --- src/sage/interfaces/axiom.py | 97 +++---- src/sage/interfaces/fricas.py | 137 +++++----- src/sage/interfaces/frobby.py | 85 ++++--- src/sage/interfaces/kash.py | 139 +++++----- src/sage/interfaces/kenzo.py | 396 +++++++++++++++-------------- src/sage/interfaces/lie.py | 80 +++--- src/sage/interfaces/macaulay2.py | 10 +- src/sage/interfaces/magma.py | 298 ++++++++++++---------- src/sage/interfaces/maple.py | 16 ++ src/sage/interfaces/mathematica.py | 88 ++++--- src/sage/interfaces/mathics.py | 160 ++++++------ src/sage/interfaces/matlab.py | 77 +++--- src/sage/interfaces/mupad.py | 80 +++--- src/sage/interfaces/octave.py | 126 ++++----- src/sage/interfaces/polymake.py | 164 ++++++------ src/sage/interfaces/qepcad.py | 70 ++--- src/sage/interfaces/rubik.py | 57 +++-- src/sage/interfaces/scilab.py | 134 +++++----- 18 files changed, 1209 insertions(+), 1005 deletions(-) diff --git a/src/sage/interfaces/axiom.py b/src/sage/interfaces/axiom.py index f61fcc638f9..5933e633d38 100644 --- a/src/sage/interfaces/axiom.py +++ b/src/sage/interfaces/axiom.py @@ -304,12 +304,13 @@ def _commands(self): EXAMPLES:: - sage: cmds = axiom._commands() #optional - axiom - sage: len(cmds) > 100 #optional - axiom + sage: # optional - axiom + sage: cmds = axiom._commands() + sage: len(cmds) > 100 True - sage: '<' in cmds #optional - axiom + sage: '<' in cmds True - sage: 'factor' in cmds #optional - axiom + sage: 'factor' in cmds True """ s = self.eval(")what things") @@ -327,18 +328,19 @@ def _tab_completion(self, verbose=True, use_disk_cache=True): EXAMPLES:: - sage: c = axiom._tab_completion(use_disk_cache=False, verbose=False) #optional - axiom - sage: len(c) > 100 #optional - axiom + sage: # optional - axiom + sage: c = axiom._tab_completion(use_disk_cache=False, verbose=False) + sage: len(c) > 100 True - sage: 'factor' in c #optional - axiom + sage: 'factor' in c True - sage: '**' in c #optional - axiom + sage: '**' in c False - sage: 'upperCase?' in c #optional - axiom + sage: 'upperCase?' in c False - sage: 'upperCase_q' in c #optional - axiom + sage: 'upperCase_q' in c True - sage: 'upperCase_e' in c #optional - axiom + sage: 'upperCase_e' in c True """ try: @@ -396,11 +398,12 @@ def get(self, var): EXAMPLES:: - sage: axiom.set('xx', '2') #optional - axiom - sage: axiom.get('xx') #optional - axiom + sage: # optional - axiom + sage: axiom.set('xx', '2') + sage: axiom.get('xx') '2' - sage: a = axiom('(1 + sqrt(2))^5') #optional - axiom - sage: axiom.get(a.name()) #optional - axiom + sage: a = axiom('(1 + sqrt(2))^5') + sage: axiom.get(a.name()) ' +-+\r\r\n 29\\|2 + 41' """ s = self._eval_line(str(var)) @@ -571,26 +574,28 @@ def _richcmp_(self, other, op): """ EXAMPLES:: - sage: two = axiom(2) #optional - axiom - sage: two == 2 #optional - axiom + sage: # optional - axiom + sage: two = axiom(2) + sage: two == 2 True - sage: two == 3 #optional - axiom + sage: two == 3 False - sage: two < 3 #optional - axiom + sage: two < 3 True - sage: two > 1 #optional - axiom + sage: two > 1 True - sage: a = axiom(1); b = axiom(2) #optional - axiom - sage: a == b #optional - axiom + sage: # optional - axiom + sage: a = axiom(1); b = axiom(2) + sage: a == b False - sage: a < b #optional - axiom + sage: a < b True - sage: a > b #optional - axiom + sage: a > b False - sage: b < a #optional - axiom + sage: b < a False - sage: b > a #optional - axiom + sage: b > a True We can also compare more complicated object such as functions:: @@ -649,15 +654,16 @@ def __getitem__(self, n): EXAMPLES:: - sage: v = axiom('[i*x^i for i in 0..5]'); v # optional - axiom + sage: # optional - axiom + sage: v = axiom('[i*x^i for i in 0..5]'); v 2 3 4 5 [0,x,2x ,3x ,4x ,5x ] - sage: v[4] # optional - axiom + sage: v[4] 3 3x - sage: v[1] # optional - axiom + sage: v[1] 0 - sage: v[10] # optional - axiom + sage: v[10] Traceback (most recent call last): ... IndexError: index out of range @@ -677,12 +683,13 @@ def comma(self, *args): EXAMPLES:: - sage: two = axiom(2) #optional - axiom - sage: two.comma(3) #optional - axiom + sage: # optional - axiom + sage: two = axiom(2) + sage: two.comma(3) [2,3] - sage: two.comma(3,4) #optional - axiom + sage: two.comma(3,4) [2,3,4] - sage: _.type() #optional - axiom + sage: _.type() Tuple PositiveInteger """ P = self._check_valid() @@ -810,16 +817,17 @@ def _sage_(self): We can also convert Axiom's polynomials to Sage polynomials. - sage: a = axiom(x^2 + 1) # optional - axiom # needs sage.symbolic - sage: a.type() # optional - axiom # needs sage.symbolic + sage: # optional - axiom, needs sage.symbolic + sage: a = axiom(x^2 + 1) + sage: a.type() Polynomial Integer - sage: a.sage() # optional - axiom # needs sage.symbolic + sage: a.sage() x^2 + 1 - sage: _.parent() # optional - axiom # needs sage.symbolic + sage: _.parent() Univariate Polynomial Ring in x over Integer Ring - sage: axiom('x^2 + y^2 + 1/2').sage() # optional - axiom # needs sage.symbolic + sage: axiom('x^2 + y^2 + 1/2').sage() y^2 + x^2 + 1/2 - sage: _.parent() # optional - axiom # needs sage.symbolic + sage: _.parent() Multivariate Polynomial Ring in y, x over Rational Field @@ -902,12 +910,13 @@ def __init__(self, object, name): """ TESTS:: - sage: a = axiom('"Hello"') #optional - axiom - sage: a.upperCase_q #optional - axiom + sage: # optional - axiom + sage: a = axiom('"Hello"') + sage: a.upperCase_q upperCase? - sage: a.upperCase_e #optional - axiom + sage: a.upperCase_e upperCase! - sage: a.upperCase_e() #optional - axiom + sage: a.upperCase_e() "HELLO" """ if name.endswith("_q"): diff --git a/src/sage/interfaces/fricas.py b/src/sage/interfaces/fricas.py index c771aea716c..c19feb3a7e5 100644 --- a/src/sage/interfaces/fricas.py +++ b/src/sage/interfaces/fricas.py @@ -313,13 +313,14 @@ def _start(self): EXAMPLES:: - sage: a = FriCAS() # optional - fricas - sage: a.is_running() # optional - fricas + sage: # optional - fricas + sage: a = FriCAS() + sage: a.is_running() False - sage: a._start() # optional - fricas - sage: a.is_running() # optional - fricas + sage: a._start() + sage: a.is_running() True - sage: a.quit() # optional - fricas + sage: a.quit() """ # setting the prompt properly is necessary for restarting FriCAS self._prompt = FRICAS_FIRST_PROMPT @@ -356,16 +357,17 @@ def _quit_string(self): EXAMPLES:: - sage: fricas._quit_string() # optional - fricas + sage: # optional - fricas + sage: fricas._quit_string() ')quit' - sage: a = FriCAS() # optional - fricas - sage: a.is_running() # optional - fricas + sage: a = FriCAS() + sage: a.is_running() False - sage: a._start() # optional - fricas - sage: a.is_running() # optional - fricas + sage: a._start() + sage: a.is_running() True - sage: a.quit() # optional - fricas - sage: a.is_running() # optional - fricas + sage: a.quit() + sage: a.is_running() False TESTS: @@ -387,12 +389,13 @@ def _commands(self): EXAMPLES:: - sage: cmds = fricas._commands() # optional - fricas - sage: len(cmds) > 100 # optional - fricas + sage: # optional - fricas + sage: cmds = fricas._commands() + sage: len(cmds) > 100 True - sage: '<' in cmds # optional - fricas + sage: '<' in cmds True - sage: 'factor' in cmds # optional - fricas + sage: 'factor' in cmds True """ output = self.eval(")what operations", reformat=False) @@ -408,18 +411,19 @@ def _tab_completion(self, verbose=True, use_disk_cache=True): EXAMPLES:: - sage: c = fricas._tab_completion(use_disk_cache=False, verbose=False) # optional - fricas - sage: len(c) > 100 # optional - fricas + sage: # optional - fricas + sage: c = fricas._tab_completion(use_disk_cache=False, verbose=False) + sage: len(c) > 100 True - sage: 'factor' in c # optional - fricas + sage: 'factor' in c True - sage: '**' in c # optional - fricas + sage: '**' in c False - sage: 'upperCase?' in c # optional - fricas + sage: 'upperCase?' in c False - sage: 'upperCase_q' in c # optional - fricas + sage: 'upperCase_q' in c True - sage: 'upperCase_e' in c # optional - fricas + sage: 'upperCase_e' in c True """ try: @@ -676,15 +680,16 @@ def get(self, var): EXAMPLES:: - sage: fricas.set('xx', '2') # optional - fricas - sage: fricas.get('xx') # optional - fricas + sage: # optional - fricas + sage: fricas.set('xx', '2') + sage: fricas.get('xx') '2' - sage: a = fricas('(1 + sqrt(2))^5') # optional - fricas - sage: fricas.get(a.name()) # optional - fricas + sage: a = fricas('(1 + sqrt(2))^5') + sage: fricas.get(a.name()) ' +-+\n29 \\|2 + 41' - sage: fricas.get('(1 + sqrt(2))^5') # optional - fricas + sage: fricas.get('(1 + sqrt(2))^5') ' +-+\n29 \\|2 + 41' - sage: fricas.new('(1 + sqrt(2))^5') # optional - fricas + sage: fricas.new('(1 + sqrt(2))^5') +-+ 29 \|2 + 41 """ @@ -728,19 +733,20 @@ def get_string(self, var): Check that :trac:`25628` is fixed:: - sage: var("a b"); f = 1/(1+a*cos(x)) # optional - fricas + sage: # optional - fricas + sage: var("a b"); f = 1/(1+a*cos(x)) (a, b) - sage: lF = integrate(f, x, algorithm="fricas") # optional - fricas - sage: (diff(lF[0], x) - f).simplify_trig() # optional - fricas + sage: lF = integrate(f, x, algorithm="fricas") + sage: (diff(lF[0], x) - f).simplify_trig() 0 - sage: (diff(lF[1], x) - f).simplify_trig() # optional - fricas + sage: (diff(lF[1], x) - f).simplify_trig() 0 - sage: f = 1/(b*x^2+a); lF = integrate(f, x, algorithm="fricas"); lF # optional - fricas + sage: f = 1/(b*x^2+a); lF = integrate(f, x, algorithm="fricas"); lF [1/2*log((2*a*b*x + (b*x^2 - a)*sqrt(-a*b))/(b*x^2 + a))/sqrt(-a*b), arctan(sqrt(a*b)*x/a)/sqrt(a*b)] - sage: (diff(lF[0], x) - f).simplify_trig() # optional - fricas + sage: (diff(lF[0], x) - f).simplify_trig() 0 - sage: (diff(lF[1], x) - f).simplify_trig() # optional - fricas + sage: (diff(lF[1], x) - f).simplify_trig() 0 """ @@ -1613,13 +1619,14 @@ def _sage_expression(fricas_InputForm): Check conversions of sums and products:: - sage: var("k, m, n") # optional - fricas + sage: # optional - fricas + sage: var("k, m, n") (k, m, n) - sage: fricas("sum(1/factorial(k), k=1..n)").sage() # optional - fricas + sage: fricas("sum(1/factorial(k), k=1..n)").sage() sum(1/factorial(_...), _..., 1, n) - sage: fricas("eval(sum(x/k, k=1..n), x=k)").sage() # optional - fricas + sage: fricas("eval(sum(x/k, k=1..n), x=k)").sage() k*harmonic_number(n) - sage: fricas("product(1/factorial(k), k=1..n)").sage() # optional - fricas + sage: fricas("product(1/factorial(k), k=1..n)").sage() 1/product(factorial(_...), _..., 1, n) sage: f = fricas.guess([sum(1/k, k,1,n) for n in range(10)])[0]; f # optional - fricas @@ -1772,20 +1779,21 @@ def _sage_(self): Floats:: - sage: fricas(2.1234).sage() # optional - fricas + sage: # optional - fricas + sage: fricas(2.1234).sage() 2.12340000000000 - sage: _.parent() # optional - fricas + sage: _.parent() Real Field with 53 bits of precision - sage: a = RealField(100)(pi) # optional - fricas - sage: fricas(a).sage() # optional - fricas + sage: a = RealField(100)(pi) + sage: fricas(a).sage() 3.1415926535897932384626433833 - sage: _.parent() # optional - fricas + sage: _.parent() Real Field with 100 bits of precision - sage: fricas(a).sage() == a # optional - fricas + sage: fricas(a).sage() == a True - sage: fricas(2.0).sage() # optional - fricas + sage: fricas(2.0).sage() 2.00000000000000 - sage: _.parent() # optional - fricas + sage: _.parent() Real Field with 53 bits of precision Algebraic numbers:: @@ -1810,15 +1818,16 @@ def _sage_(self): We can also convert FriCAS's polynomials to Sage polynomials:: - sage: a = fricas("x^2 + 1"); a.typeOf() # optional - fricas + sage: # optional - fricas + sage: a = fricas("x^2 + 1"); a.typeOf() Polynomial(Integer) - sage: a.sage() # optional - fricas + sage: a.sage() x^2 + 1 - sage: _.parent() # optional - fricas + sage: _.parent() Univariate Polynomial Ring in x over Integer Ring - sage: fricas('x^2 + y^2 + 1/2').sage() # optional - fricas + sage: fricas('x^2 + y^2 + 1/2').sage() y^2 + x^2 + 1/2 - sage: _.parent() # optional - fricas + sage: _.parent() Multivariate Polynomial Ring in y, x over Rational Field sage: fricas("1$Polynomial Integer").sage() # optional - fricas @@ -2067,12 +2076,13 @@ def __init__(self, object, name): TESTS:: - sage: a = fricas('"Hello"') # optional - fricas - sage: a.upperCase_q # optional - fricas + sage: # optional - fricas + sage: a = fricas('"Hello"') + sage: a.upperCase_q upperCase? - sage: a.upperCase_e # optional - fricas + sage: a.upperCase_e upperCase! - sage: a.upperCase_e() # optional - fricas + sage: a.upperCase_e() "HELLO" """ @@ -2167,13 +2177,14 @@ def __doctest_cleanup(): """ EXAMPLES:: - sage: from sage.interfaces.fricas import __doctest_cleanup # optional - fricas - sage: a = FriCAS() # optional - fricas - sage: two = a(2) # optional - fricas - sage: a.is_running() # optional - fricas + sage: # optional - fricas + sage: from sage.interfaces.fricas import __doctest_cleanup + sage: a = FriCAS() + sage: two = a(2) + sage: a.is_running() True - sage: __doctest_cleanup() # optional - fricas - sage: a.is_running() # optional - fricas + sage: __doctest_cleanup() + sage: a.is_running() False """ import sage.interfaces.quit diff --git a/src/sage/interfaces/frobby.py b/src/sage/interfaces/frobby.py index aab3bd9b58f..7eb5e53becd 100644 --- a/src/sage/interfaces/frobby.py +++ b/src/sage/interfaces/frobby.py @@ -115,20 +115,22 @@ def alexander_dual(self, monomial_ideal): This is a simple example of computing irreducible decomposition. :: - sage: (a, b, c, d) = QQ['a,b,c,d'].gens() # optional - frobby - sage: id = ideal(a * b, b * c, c * d, d * a) # optional - frobby - sage: alexander_dual = frobby.alexander_dual(id) # optional - frobby - sage: true_alexander_dual = ideal(b * d, a * c) # optional - frobby - sage: alexander_dual == true_alexander_dual # use sets to ignore order # optional - frobby + sage: # optional - frobby + sage: (a, b, c, d) = QQ['a,b,c,d'].gens() + sage: id = ideal(a * b, b * c, c * d, d * a) + sage: alexander_dual = frobby.alexander_dual(id) + sage: true_alexander_dual = ideal(b * d, a * c) + sage: alexander_dual == true_alexander_dual # use sets to ignore order True We see how it is much faster to compute this with frobby than the built-in procedure for simplicial complexes:: - sage: t=simplicial_complexes.PoincareHomologyThreeSphere() # optional - frobby - sage: R=PolynomialRing(QQ,16,'x') # optional - frobby - sage: I=R.ideal([prod([R.gen(i-1) for i in a]) for a in t.facets()]) # optional - frobby - sage: len(frobby.alexander_dual(I).gens()) # optional - frobby + sage: # optional - frobby + sage: t=simplicial_complexes.PoincareHomologyThreeSphere() + sage: R=PolynomialRing(QQ,16,'x') + sage: I=R.ideal([prod([R.gen(i-1) for i in a]) for a in t.facets()]) + sage: len(frobby.alexander_dual(I).gens()) 643 @@ -261,11 +263,12 @@ def irreducible_decomposition(self, monomial_ideal): This is a simple example of computing irreducible decomposition. :: - sage: (x, y, z) = QQ['x,y,z'].gens() # optional - frobby - sage: id = ideal(x ** 2, y ** 2, x * z, y * z) # optional - frobby - sage: decom = frobby.irreducible_decomposition(id) # optional - frobby - sage: true_decom = [ideal(x, y), ideal(x ** 2, y ** 2, z)] # optional - frobby - sage: set(decom) == set(true_decom) # use sets to ignore order # optional - frobby + sage: # optional - frobby + sage: (x, y, z) = QQ['x,y,z'].gens() + sage: id = ideal(x ** 2, y ** 2, x * z, y * z) + sage: decom = frobby.irreducible_decomposition(id) + sage: true_decom = [ideal(x, y), ideal(x ** 2, y ** 2, z)] + sage: set(decom) == set(true_decom) # use sets to ignore order True We now try the special case of the zero ideal in different rings. @@ -273,25 +276,27 @@ def irreducible_decomposition(self, monomial_ideal): We should also try PolynomialRing(QQ, names=[]), but it has a bug which makes that impossible (see :trac:`3028`). :: - sage: rings = [ZZ['x'], CC['x,y']] # optional - frobby - sage: allOK = True # optional - frobby - sage: for ring in rings: # optional - frobby + sage: # optional - frobby + sage: rings = [ZZ['x'], CC['x,y']] + sage: allOK = True + sage: for ring in rings: ....: id0 = ring.ideal(0) ....: decom0 = frobby.irreducible_decomposition(id0) ....: allOK = allOK and decom0 == [id0] - sage: allOK # optional - frobby + sage: allOK True Finally, we try the ideal that is all of the ring in different rings. :: - sage: rings = [ZZ['x'], CC['x,y']] # optional - frobby - sage: allOK = True # optional - frobby - sage: for ring in rings: # optional - frobby + sage: # optional - frobby + sage: rings = [ZZ['x'], CC['x,y']] + sage: allOK = True + sage: for ring in rings: ....: id1 = ring.ideal(1) ....: decom1 = frobby.irreducible_decomposition(id1) ....: allOK = allOK and decom1 == [id1] - sage: allOK # optional - frobby + sage: allOK True """ frobby_input = self._ideal_to_string(monomial_ideal) @@ -316,10 +321,11 @@ def _parse_ideals(self, string, ring): EXAMPLES:: - sage: ring = QQ['x,y,z'] # optional - frobby - sage: (x, y, z) = ring.gens() # optional - frobby - sage: string = '2 3\n1 2 3\n0 5 0\n2 3\n1 2 3\n4 5 6' # optional - frobby - sage: frobby._parse_ideals(string, ring) # optional - frobby + sage: # optional - frobby + sage: ring = QQ['x,y,z'] + sage: (x, y, z) = ring.gens() + sage: string = '2 3\n1 2 3\n0 5 0\n2 3\n1 2 3\n4 5 6' + sage: frobby._parse_ideals(string, ring) [Ideal (x*y^2*z^3, y^5) of Multivariate Polynomial Ring in x, y, z over Rational Field, Ideal (x*y^2*z^3, x^4*y^5*z^6) of Multivariate Polynomial Ring in x, y, z over Rational Field] @@ -365,10 +371,11 @@ def _parse_4ti2_matrix(self, string): The format is straight-forward, as this example shows. :: - sage: string = '2 3\n1 2 3\n 0 5 0' # optional - frobby - sage: parsed_matrix = frobby._parse_4ti2_matrix(string) # optional - frobby - sage: reference_matrix = [[1, 2, 3], [0, 5, 0]] # optional - frobby - sage: parsed_matrix == reference_matrix # optional - frobby + sage: # optional - frobby + sage: string = '2 3\n1 2 3\n 0 5 0' + sage: parsed_matrix = frobby._parse_4ti2_matrix(string) + sage: reference_matrix = [[1, 2, 3], [0, 5, 0]] + sage: parsed_matrix == reference_matrix True A number of syntax errors lead to exceptions. :: @@ -414,10 +421,11 @@ def _ideal_to_string(self, monomial_ideal): EXAMPLES:: - sage: ring = QQ['x,y,z'] # optional - frobby - sage: (x, y, z) = ring.gens() # optional - frobby - sage: id = ring.ideal(x ** 2, x * y * z) # optional - frobby - sage: frobby._ideal_to_string(id) == "2 3\n2 0 0\n1 1 1\n" # optional - frobby + sage: # optional - frobby + sage: ring = QQ['x,y,z'] + sage: (x, y, z) = ring.gens() + sage: id = ring.ideal(x ** 2, x * y * z) + sage: frobby._ideal_to_string(id) == "2 3\n2 0 0\n1 1 1\n" True """ # There is no exponent vector that represents zero as a generator, so @@ -447,10 +455,11 @@ def _monomial_to_string(self, monomial): EXAMPLES:: - sage: ring = QQ['x,y,z'] # optional - frobby - sage: (x, y, z) = ring.gens() # optional - frobby - sage: monomial = x * x * z # optional - frobby - sage: frobby._monomial_to_string(monomial) == '2 0 1\n' # optional - frobby + sage: # optional - frobby + sage: ring = QQ['x,y,z'] + sage: (x, y, z) = ring.gens() + sage: monomial = x * x * z + sage: frobby._monomial_to_string(monomial) == '2 0 1\n' True """ exponents = monomial.exponents() diff --git a/src/sage/interfaces/kash.py b/src/sage/interfaces/kash.py index ebfd9178c70..aecddae452b 100644 --- a/src/sage/interfaces/kash.py +++ b/src/sage/interfaces/kash.py @@ -89,11 +89,12 @@ :: - sage: a = kash(12345) # optional -- kash - sage: b = kash(25) # optional -- kash - sage: a/b # optional -- kash + sage: # optional - kash + sage: a = kash(12345) + sage: b = kash(25) + sage: a/b 2469/5 - sage: a**b # optional -- kash + sage: a**b 1937659030411463935651167391656422626577614411586152317674869233464019922771432158872187137603759765625 Variable assignment @@ -130,12 +131,13 @@ :: - sage: F = kash.Factorization(4352) # optional -- kash - sage: F[1] # optional -- kash + sage: # optional - kash + sage: F = kash.Factorization(4352) + sage: F[1] <2, 8> - sage: F[2] # optional -- kash + sage: F[2] <17, 1> - sage: F # optional -- kash + sage: F [ <2, 8>, <17, 1> ], extended by: ext1 := 1, ext2 := Unassign @@ -147,17 +149,18 @@ :: - sage: kash.GCD(15,25) # optional -- kash + sage: # optional - kash + sage: kash.GCD(15,25) 5 - sage: kash.LCM(15,25) # optional -- kash + sage: kash.LCM(15,25) 75 - sage: kash.Div(25,15) # optional -- kash + sage: kash.Div(25,15) 1 - sage: kash(17) % kash(5) # optional -- kash + sage: kash(17) % kash(5) 2 - sage: kash.IsPrime(10007) # optional -- kash + sage: kash.IsPrime(10007) TRUE - sage: kash.IsPrime(2005) # optional -- kash + sage: kash.IsPrime(2005) FALSE sage: kash.NextPrime(10007) # optional -- kash @@ -168,18 +171,19 @@ :: - sage: kash.Precision() # optional -- kash + sage: # optional - kash + sage: kash.Precision() 30 - sage: kash('R') # optional -- kash + sage: kash('R') Real field of precision 30 - sage: kash.Precision(40) # optional -- kash + sage: kash.Precision(40) 40 - sage: kash('R') # optional -- kash + sage: kash('R') Real field of precision 40 - sage: z = kash('1 + 2*I') # optional -- kash - sage: z # optional -- kash + sage: z = kash('1 + 2*I') + sage: z 1.000000000000000000000000000000000000000 + 2.000000000000000000000000000000000000000*I - sage: z*z # optional -- kash + sage: z*z -3.000000000000000000000000000000000000000 + 4.000000000000000000000000000000000000000*I sage: kash.Cos('1.24') # optional -- kash @@ -222,40 +226,42 @@ :: - sage: v = kash([1,2,3]); v # optional -- kash + sage: # optional - kash + sage: v = kash([1,2,3]); v [ 1, 2, 3 ] - sage: v[1] # optional -- kash + sage: v[1] 1 - sage: v[3] # optional -- kash + sage: v[3] 3 - sage: v.Append([5]) # optional -- kash + sage: v.Append([5]) [ 1, 2, 3, 5 ] - sage: v # optional -- kash + sage: v [ 1, 2, 3 ] - sage: v.Append_([5, 6]) # optional -- kash + sage: v.Append_([5, 6]) SUCCESS - sage: v # optional -- kash + sage: v [ 1, 2, 3, 5, 6 ] - sage: v.Add(5) # optional -- kash + sage: v.Add(5) [ 1, 2, 3, 5, 6, 5 ] - sage: v # optional -- kash + sage: v [ 1, 2, 3, 5, 6 ] - sage: v.Add_(5) # optional -- kash + sage: v.Add_(5) SUCCESS - sage: v # optional -- kash + sage: v [ 1, 2, 3, 5, 6, 5 ] The ``Apply`` command applies a function to each element of a list:: - sage: L = kash([1,2,3,4]) # optional -- kash - sage: L.Apply('i -> 3*i') # optional -- kash + sage: # optional - kash + sage: L = kash([1,2,3,4]) + sage: L.Apply('i -> 3*i') [ 3, 6, 9, 12 ] - sage: L # optional -- kash + sage: L [ 1, 2, 3, 4 ] - sage: L.Apply('IsEven') # optional -- kash + sage: L.Apply('IsEven') [ FALSE, TRUE, FALSE, TRUE ] - sage: L # optional -- kash + sage: L [ 1, 2, 3, 4 ] Ranges @@ -265,11 +271,12 @@ :: - sage: L = kash('[1..10]') # optional -- kash - sage: L # optional -- kash + sage: # optional - kash + sage: L = kash('[1..10]') + sage: L [ 1 .. 10 ] - sage: L = kash('[2,4..100]') # optional -- kash - sage: L # optional -- kash + sage: L = kash('[2,4..100]') + sage: L [ 2, 4 .. 100 ] Sequences @@ -283,15 +290,16 @@ :: - sage: f = kash('X^3 + X + 1') # optional -- kash - sage: f + f # optional -- kash + sage: # optional - kash + sage: f = kash('X^3 + X + 1') + sage: f + f 2*X^3 + 2*X + 2 - sage: f * f # optional -- kash + sage: f * f X^6 + 2*X^4 + 2*X^3 + X^2 + 2*X + 1 - sage: f.Evaluate(10) # optional -- kash + sage: f.Evaluate(10) 1011 - sage: Qx = kash.PolynomialAlgebra('Q') # optional -- kash - sage: Qx.gen(1)**5 + kash('7/3') # sage1 below somewhat random; optional -- kash + sage: Qx = kash.PolynomialAlgebra('Q') + sage: Qx.gen(1)**5 + kash('7/3') sage1.1^5 + 7/3 Number Fields @@ -308,12 +316,13 @@ :: - sage: f = kash('X^5 + 4*X^4 - 56*X^2 -16*X + 192') # optional -- kash - sage: O = f.EquationOrder() # optional -- kash - sage: a = O.gen(2) # optional -- kash - sage: a # optional -- kash + sage: # optional - kash + sage: f = kash('X^5 + 4*X^4 - 56*X^2 -16*X + 192') + sage: O = f.EquationOrder() + sage: a = O.gen(2) + sage: a [0, 1, 0, 0, 0] - sage: O.Basis() # output somewhat random; optional -- kash + sage: O.Basis() [ _NG.1, _NG.2, @@ -321,9 +330,9 @@ _NG.4, _NG.5 ] - sage: O.Discriminant() # optional -- kash + sage: O.Discriminant() 1364202618880 - sage: O.MaximalOrder() # name sage2 below somewhat random; optional -- kash + sage: O.MaximalOrder() Maximal Order of sage2 sage: O = kash.MaximalOrder('X^3 - 77') # optional -- kash @@ -353,10 +362,11 @@ Computation of class groups and unit groups:: - sage: f = kash('X^5 + 4*X^4 - 56*X^2 -16*X + 192') # optional -- kash - sage: O = kash.EquationOrder(f) # optional -- kash - sage: OK = O.MaximalOrder() # optional -- kash - sage: OK.ClassGroup() # name sage32 below random; optional -- kash + sage: # optional - kash + sage: f = kash('X^5 + 4*X^4 - 56*X^2 -16*X + 192') + sage: O = kash.EquationOrder(f) + sage: OK = O.MaximalOrder() + sage: OK.ClassGroup() Abelian Group isomorphic to Z/6 Defined on 1 generator Relations: @@ -381,12 +391,13 @@ :: - sage: k = kash.FiniteField(25) # optional -- kash - sage: kT = k.RationalFunctionField() # optional -- kash - sage: kTy = kT.PolynomialAlgebra() # optional -- kash - sage: T = kT.gen(1) # optional -- kash - sage: y = kTy.gen(1) # optional -- kash - sage: f = y**3 + T**4 + 1 # optional -- kash + sage: # optional - kash + sage: k = kash.FiniteField(25) + sage: kT = k.RationalFunctionField() + sage: kTy = kT.PolynomialAlgebra() + sage: T = kT.gen(1) + sage: y = kTy.gen(1) + sage: f = y**3 + T**4 + 1 Long Input ---------- diff --git a/src/sage/interfaces/kenzo.py b/src/sage/interfaces/kenzo.py index 3607dd7879e..e403b04dab7 100644 --- a/src/sage/interfaces/kenzo.py +++ b/src/sage/interfaces/kenzo.py @@ -193,12 +193,13 @@ def EilenbergMacLaneSpace(G, n): EXAMPLES:: - sage: from sage.interfaces.kenzo import EilenbergMacLaneSpace # optional - kenzo - sage: e3 = EilenbergMacLaneSpace(ZZ, 3) # optional - kenzo - sage: [e3.homology(i) for i in range(8)] # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import EilenbergMacLaneSpace + sage: e3 = EilenbergMacLaneSpace(ZZ, 3) + sage: [e3.homology(i) for i in range(8)] [Z, 0, 0, Z, 0, C2, 0, C3] - sage: f3 = EilenbergMacLaneSpace(AdditiveAbelianGroup([2]), 3) # optional - kenzo - sage: [f3.homology(i) for i in range(8)] # optional - kenzo + sage: f3 = EilenbergMacLaneSpace(AdditiveAbelianGroup([2]), 3) + sage: [f3.homology(i) for i in range(8)] [Z, 0, 0, C2, 0, C2, C2, C2] """ if G == ZZ: @@ -230,15 +231,16 @@ def __init__(self, kenzo_object): TESTS:: - sage: from sage.interfaces.kenzo import KenzoObject # optional -kenzo - sage: from sage.interfaces.kenzo import __sphere__ # optional -kenzo - sage: ks = __sphere__(2) # optional -kenzo - sage: ks # optional -kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import KenzoObject + sage: from sage.interfaces.kenzo import __sphere__ + sage: ks = __sphere__(2) + sage: ks - sage: s2 = KenzoObject(ks) # optional -kenzo - sage: s2 # optional -kenzo + sage: s2 = KenzoObject(ks) + sage: s2 [K1 Simplicial-Set] - sage: TestSuite(s2).run(skip='_test_pickling') # optional -kenzo + sage: TestSuite(s2).run(skip='_test_pickling') """ self._kenzo = kenzo_object @@ -280,12 +282,13 @@ def group(self, p, i, j): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: S2 = Sphere(2) # optional - kenzo - sage: EMS = S2.em_spectral_sequence() # optional - kenzo - sage: EMS.group(0, -1, 2) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: S2 = Sphere(2) + sage: EMS = S2.em_spectral_sequence() + sage: EMS.group(0, -1, 2) Additive abelian group isomorphic to Z - sage: EMS.group(0, -1, 3) # optional - kenzo + sage: EMS.group(0, -1, 3) Trivial group """ invs = __spectral_sequence_group__(self._kenzo, p, i, j).python() @@ -308,16 +311,17 @@ def matrix(self, p, i, j): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: S3 = Sphere(3) # optional - kenzo - sage: L = S3.loop_space() # optional - kenzo - sage: EMS = L.em_spectral_sequence() # optional - kenzo - sage: EMS.table(1, -5, -2, 5, 8) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: S3 = Sphere(3) + sage: L = S3.loop_space() + sage: EMS = L.em_spectral_sequence() + sage: EMS.table(1, -5, -2, 5, 8) 0 Z Z + Z + Z Z + Z + Z 0 0 0 0 0 0 Z Z + Z 0 0 0 0 - sage: EMS.matrix(1, -2 ,8) # optional - kenzo + sage: EMS.matrix(1, -2 ,8) [ 3 -2 0] [ 3 0 -3] [ 0 2 -3] @@ -344,18 +348,19 @@ def differential(self, p, i, j): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: S3 = Sphere(3) # optional - kenzo - sage: L = S3.loop_space() # optional - kenzo - sage: EMS = L.em_spectral_sequence() # optional - kenzo - sage: EMS.table(1,-5,-2,5,8) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: S3 = Sphere(3) + sage: L = S3.loop_space() + sage: EMS = L.em_spectral_sequence() + sage: EMS.table(1,-5,-2,5,8) 0 Z Z + Z + Z Z + Z + Z 0 0 0 0 0 0 Z Z + Z 0 0 0 0 - sage: EMS.matrix(1, -3, 8) # optional - kenzo + sage: EMS.matrix(1, -3, 8) [ 2 -2 2] - sage: EMS.differential(1, -3, 8) # optional - kenzo + sage: EMS.differential(1, -3, 8) Morphism from module over Integer Ring with invariants (0, 0, 0) to module with invariants (0,) that sends the generators to [(2), (-2), (2)] """ domain = self.group(p, i, j) @@ -458,13 +463,14 @@ def tensor_product(self, other): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: p = s2.tensor_product(s3) # optional - kenzo - sage: type(p) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: p = s2.tensor_product(s3) + sage: type(p) - sage: [p.homology(i) for i in range(8)] # optional - kenzo + sage: [p.homology(i) for i in range(8)] [Z, 0, Z, Z, 0, Z, 0, 0] """ return KenzoChainComplex(__tnsr_prdc__(self._kenzo, other._kenzo)) @@ -514,11 +520,12 @@ def identity_morphism(self): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: tp = s2.tensor_product(s2) # optional - kenzo - sage: idnt = tp.identity_morphism() # optional - kenzo - sage: type(idnt) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: tp = s2.tensor_product(s2) + sage: idnt = tp.identity_morphism() + sage: type(idnt) """ return KenzoChainComplexMorphism(__idnt_mrph__(self._kenzo)) @@ -542,20 +549,21 @@ def null_morphism(self, target=None, degree=None): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: tp22 = s2.tensor_product(s2) # optional - kenzo - sage: tp22 # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: tp22 = s2.tensor_product(s2) + sage: tp22 [K... Chain-Complex] - sage: tp23 = s2.tensor_product(s3) # optional - kenzo - sage: tp23 # optional - kenzo + sage: tp23 = s2.tensor_product(s3) + sage: tp23 [K... Chain-Complex] - sage: null1 = tp22.null_morphism() # optional - kenzo - sage: null1 # optional - kenzo + sage: null1 = tp22.null_morphism() + sage: null1 [K... Morphism (degree 0): K... -> K...] - sage: null2 = tp22.null_morphism(target = tp23, degree = -3) # optional - kenzo - sage: null2 # optional - kenzo + sage: null2 = tp22.null_morphism(target = tp23, degree = -3) + sage: null2 [K... Morphism (degree -3): K... -> K...] """ if target is None: @@ -634,13 +642,14 @@ def orgn(self): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: l2 = s2.loop_space() # optional - kenzo - sage: l2.orgn() # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: l2 = s2.loop_space() + sage: l2.orgn() '(LOOP-SPACE [K... Simplicial-Set])' - sage: A = l2.cartesian_product(s2) # optional - kenzo - sage: A.orgn() # optional - kenzo + sage: A = l2.cartesian_product(s2) + sage: A.orgn() '(CRTS-PRDC [K... Simplicial-Group] [K... Simplicial-Set])' """ return str(__orgn_aux1__(self._kenzo)) @@ -669,13 +678,14 @@ def loop_space(self, n=1): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: l2 = s2.loop_space() # optional - kenzo - sage: type(l2) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: l2 = s2.loop_space() + sage: type(l2) - sage: l2 = s2.loop_space() # optional - kenzo - sage: [l2.homology(i) for i in range(8)] # optional - kenzo + sage: l2 = s2.loop_space() + sage: [l2.homology(i) for i in range(8)] [Z, Z, Z, Z, Z, Z, Z, Z] """ return KenzoSimplicialGroup(__loop_space__(self._kenzo, n)) @@ -694,13 +704,14 @@ def cartesian_product(self, other): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: p = s2.cartesian_product(s3) # optional - kenzo - sage: type(p) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: p = s2.cartesian_product(s3) + sage: type(p) - sage: [p.homology(i) for i in range(6)] # optional - kenzo + sage: [p.homology(i) for i in range(6)] [Z, 0, Z, Z, 0, Z] """ prod_kenzo = __crts_prdc__(self._kenzo, other._kenzo) @@ -716,12 +727,13 @@ def suspension(self): EXAMPLES:: - sage: from sage.interfaces.kenzo import EilenbergMacLaneSpace # optional - kenzo - sage: e3 = EilenbergMacLaneSpace(ZZ, 3) # optional - kenzo - sage: s = e3.suspension() # optional - kenzo - sage: type(s) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import EilenbergMacLaneSpace + sage: e3 = EilenbergMacLaneSpace(ZZ, 3) + sage: s = e3.suspension() + sage: type(s) - sage: [s.homology(i) for i in range(6)] # optional - kenzo + sage: [s.homology(i) for i in range(6)] [Z, 0, 0, 0, Z, 0] """ return KenzoSimplicialSet(__suspension__(self._kenzo)) @@ -799,11 +811,12 @@ def sw_spectral_sequence(self): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: S3 = Sphere(3) # optional - kenzo - sage: E = S3.sw_spectral_sequence() # optional - kenzo - sage: T = E.table(0, 0, 4, 0, 4) # optional - kenzo - sage: T # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: S3 = Sphere(3) + sage: E = S3.sw_spectral_sequence() + sage: T = E.table(0, 0, 4, 0, 4) + sage: T Z 0 0 Z 0 0 0 0 0 0 Z 0 0 Z 0 @@ -827,12 +840,13 @@ def serre_spectral_sequence(self): EXAMPLES:: + sage: # optional - kenzo sage: from sage.interfaces.kenzo import Sphere - sage: S2 = Sphere(2) # optional - kenzo - sage: S3 = Sphere(3) # optional - kenzo - sage: P = S2.cartesian_product(S3) # optional - kenzo - sage: E = P.serre_spectral_sequence() # optional - kenzo - sage: E.table(0, 0, 2, 0, 3) # optional - kenzo + sage: S2 = Sphere(2) + sage: S3 = Sphere(3) + sage: P = S2.cartesian_product(S3) + sage: E = P.serre_spectral_sequence() + sage: E.table(0, 0, 2, 0, 3) Z 0 Z 0 0 0 0 0 0 @@ -862,13 +876,14 @@ def wedge(self, other): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: w = s2.wedge(s3) # optional - kenzo - sage: type(w) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: w = s2.wedge(s3) + sage: type(w) - sage: [w.homology(i) for i in range(6)] # optional - kenzo + sage: [w.homology(i) for i in range(6)] [Z, 0, Z, Z, 0, 0] """ wedge_kenzo = __wedge__(self._kenzo, other._kenzo) @@ -888,13 +903,14 @@ def join(self, other): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: j = s2.join(s3) # optional - kenzo - sage: type(j) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: j = s2.join(s3) + sage: type(j) - sage: [j.homology(i) for i in range(6)] # optional - kenzo + sage: [j.homology(i) for i in range(6)] [Z, 0, 0, 0, 0, 0] """ join_kenzo = __join__(self._kenzo, other._kenzo) @@ -914,13 +930,14 @@ def smash_product(self, other): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: s = s2.smash_product(s3) # optional - kenzo - sage: type(s) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: s = s2.smash_product(s3) + sage: type(s) - sage: [s.homology(i) for i in range(6)] # optional - kenzo + sage: [s.homology(i) for i in range(6)] [Z, 0, 0, 0, 0, Z] """ smash_kenzo = __smash_product__(self._kenzo, other._kenzo) @@ -942,13 +959,14 @@ def classifying_space(self): EXAMPLES:: - sage: from sage.interfaces.kenzo import MooreSpace # optional - kenzo - sage: m2 = MooreSpace(2,4) # optional - kenzo - sage: l2 = m2.loop_space() # optional - kenzo - sage: c = l2.classifying_space() # optional - kenzo - sage: type(c) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import MooreSpace + sage: m2 = MooreSpace(2,4) + sage: l2 = m2.loop_space() + sage: c = l2.classifying_space() + sage: type(c) - sage: [c.homology(i) for i in range(8)] # optional - kenzo + sage: [c.homology(i) for i in range(8)] [Z, 0, 0, 0, C2, 0, 0, 0] """ return KenzoSimplicialGroup(__classifying_space__(self._kenzo)) @@ -1118,14 +1136,15 @@ def SChainComplex(kchaincomplex, start=0, end=15): :: - sage: from sage.interfaces.kenzo import SChainComplex, Sphere # optional - kenzo - sage: S4 = Sphere(4) # optional - kenzo - sage: C = SChainComplex(S4) # optional - kenzo - sage: C # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import SChainComplex, Sphere + sage: S4 = Sphere(4) + sage: C = SChainComplex(S4) + sage: C Chain complex with at most 3 nonzero terms over Integer Ring - sage: C._ascii_art_() # optional - kenzo + sage: C._ascii_art_() 0 <-- C_4 <-- 0 ... 0 <-- C_0 <-- 0 - sage: [C.homology(i) for i in range(6)] # optional - kenzo + sage: [C.homology(i) for i in range(6)] [Z, 0, 0, 0, Z, 0] """ matrices = {} @@ -1156,17 +1175,18 @@ def SAbstractSimplex(simplex, dim): EXAMPLES:: + sage: # optional - kenzo sage: from sage.libs.ecl import EclObject, ecl_eval - sage: from sage.interfaces.kenzo import ( # optional - kenzo + sage: from sage.interfaces.kenzo import ( ....: KenzoObject, SAbstractSimplex) - sage: KAbSm = KenzoObject(ecl_eval("(ABSM 15 'K)")) # optional - kenzo - sage: SAbSm1 = SAbstractSimplex(KAbSm, 2) # optional - kenzo - sage: SAbSm2 = SAbstractSimplex(KAbSm, 7) # optional - kenzo - sage: SAbSm1.degeneracies() # optional - kenzo + sage: KAbSm = KenzoObject(ecl_eval("(ABSM 15 'K)")) + sage: SAbSm1 = SAbstractSimplex(KAbSm, 2) + sage: SAbSm2 = SAbstractSimplex(KAbSm, 7) + sage: SAbSm1.degeneracies() [3, 2, 1, 0] - sage: SAbSm1.dimension() # optional - kenzo + sage: SAbSm1.dimension() 6 - sage: SAbSm2.dimension() # optional - kenzo + sage: SAbSm2.dimension() 11 """ degeneracies = __dgop_int_ext__(__dgop__(simplex._kenzo)).python() @@ -1192,15 +1212,16 @@ def KAbstractSimplex(simplex): EXAMPLES:: + sage: # optional - kenzo sage: from sage.topology.simplicial_set import AbstractSimplex - sage: from sage.interfaces.kenzo import ( # optional - kenzo + sage: from sage.interfaces.kenzo import ( ....: KAbstractSimplex, SAbstractSimplex) - sage: SAbSm = AbstractSimplex(1, (2,0,3,2,1), name = 'SAbSm') # optional - kenzo - sage: KAbSm = KAbstractSimplex(SAbSm) # optional - kenzo - sage: SAbSm2 = SAbstractSimplex(KAbSm, 1) # optional - kenzo - sage: SAbSm.degeneracies() == SAbSm2.degeneracies() # optional - kenzo + sage: SAbSm = AbstractSimplex(1, (2,0,3,2,1), name = 'SAbSm') + sage: KAbSm = KAbstractSimplex(SAbSm) + sage: SAbSm2 = SAbstractSimplex(KAbSm, 1) + sage: SAbSm.degeneracies() == SAbSm2.degeneracies() True - sage: SAbSm.dimension() == SAbSm2.dimension() # optional - kenzo + sage: SAbSm.dimension() == SAbSm2.dimension() True """ return KenzoObject(__kabstractsimplex_aux1__(simplex.degeneracies(), @@ -1289,30 +1310,31 @@ def SFiniteSimplicialSet(ksimpset, limit): EXAMPLES:: + sage: # optional - kenzo sage: from sage.topology.simplicial_set import SimplicialSet - sage: from sage.interfaces.kenzo import ( # optional - kenzo + sage: from sage.interfaces.kenzo import ( ....: AbstractSimplex, KFiniteSimplicialSet, ....: SFiniteSimplicialSet, Sphere) - sage: s0 = AbstractSimplex(0, name='s0') # optional - kenzo - sage: s1 = AbstractSimplex(0, name='s1') # optional - kenzo - sage: s2 = AbstractSimplex(0, name='s2') # optional - kenzo - sage: s01 = AbstractSimplex(1, name='s01') # optional - kenzo - sage: s02 = AbstractSimplex(1, name='s02') # optional - kenzo - sage: s12 = AbstractSimplex(1, name='s12') # optional - kenzo - sage: s012 = AbstractSimplex(2, name='s012') # optional - kenzo - sage: Triangle = SimplicialSet({s01: (s1, s0), # optional - kenzo + sage: s0 = AbstractSimplex(0, name='s0') + sage: s1 = AbstractSimplex(0, name='s1') + sage: s2 = AbstractSimplex(0, name='s2') + sage: s01 = AbstractSimplex(1, name='s01') + sage: s02 = AbstractSimplex(1, name='s02') + sage: s12 = AbstractSimplex(1, name='s12') + sage: s012 = AbstractSimplex(2, name='s012') + sage: Triangle = SimplicialSet({s01: (s1, s0), ....: s02: (s2, s0), ....: s12: (s2, s1)}, ....: base_point = s0) - sage: KTriangle = KFiniteSimplicialSet(Triangle) # optional - kenzo - sage: STriangle = SFiniteSimplicialSet(KTriangle, 1) # optional - kenzo - sage: STriangle.homology() # optional - kenzo + sage: KTriangle = KFiniteSimplicialSet(Triangle) + sage: STriangle = SFiniteSimplicialSet(KTriangle, 1) + sage: STriangle.homology() {0: 0, 1: Z} - sage: S1 = simplicial_sets.Sphere(1) # optional - kenzo - sage: S3 = simplicial_sets.Sphere(3) # optional - kenzo - sage: KS1vS3 = KFiniteSimplicialSet(S1.wedge(S3)) # optional - kenzo - sage: SS1vS3 = SFiniteSimplicialSet(KS1vS3, 3) # optional - kenzo - sage: SS1vS3.homology() # optional - kenzo + sage: S1 = simplicial_sets.Sphere(1) + sage: S3 = simplicial_sets.Sphere(3) + sage: KS1vS3 = KFiniteSimplicialSet(S1.wedge(S3)) + sage: SS1vS3 = SFiniteSimplicialSet(KS1vS3, 3) + sage: SS1vS3.homology() {0: 0, 1: Z, 2: 0, 3: Z} """ list_orgn = __orgn_aux1__(ksimpset._kenzo).python() @@ -1587,18 +1609,19 @@ def composite(self, object=None): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: tp22 = s2.tensor_product(s2) # optional - kenzo - sage: tp23 = s2.tensor_product(s3) # optional - kenzo - sage: idnt = tp22.identity_morphism() # optional - kenzo - sage: idnt # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: tp22 = s2.tensor_product(s2) + sage: tp23 = s2.tensor_product(s3) + sage: idnt = tp22.identity_morphism() + sage: idnt [K... Morphism (degree 0): K... -> K...] - sage: null = tp23.null_morphism(target = tp22, degree = 4) # optional - kenzo - sage: null # optional - kenzo + sage: null = tp23.null_morphism(target = tp22, degree = 4) + sage: null [K... Morphism (degree 4): K... -> K...] - sage: idnt.composite((tp22, null)) # optional - kenzo + sage: idnt.composite((tp22, null)) [K... Morphism (degree 3): K... -> K...] """ if object is None: @@ -1765,25 +1788,26 @@ def change_source_target_complex(self, source=None, target=None): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere, KenzoChainComplex # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere, KenzoChainComplex sage: from sage.libs.ecl import ecl_eval - sage: ZCC = KenzoChainComplex(ecl_eval("(z-chcm)")) # optional - kenzo - sage: ZCC # optional - kenzo + sage: ZCC = KenzoChainComplex(ecl_eval("(z-chcm)")) + sage: ZCC [K... Chain-Complex] - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: tp = s2.tensor_product(s3) # optional - kenzo - sage: tp # optional - kenzo + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: tp = s2.tensor_product(s3) + sage: tp [K... Filtered-Chain-Complex] - sage: null = ZCC.null_morphism(tp) # optional - kenzo - sage: null # optional - kenzo + sage: null = ZCC.null_morphism(tp) + sage: null [K... Morphism (degree 0): K... -> K...] - sage: null.source_complex() # optional - kenzo + sage: null.source_complex() [K... Chain-Complex] - sage: null2 = null.change_source_target_complex(source = tp) # optional - kenzo - sage: null2 # optional - kenzo + sage: null2 = null.change_source_target_complex(source = tp) + sage: null2 [K... Morphism (degree 0): K... -> K...] - sage: null2.source_complex() # optional - kenzo + sage: null2.source_complex() [K... Filtered-Chain-Complex] """ source = source or self.source_complex() @@ -1810,24 +1834,25 @@ def destructive_change_source_target_complex(self, source=None, target=None): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere, KenzoChainComplex # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere, KenzoChainComplex sage: from sage.libs.ecl import ecl_eval - sage: ZCC = KenzoChainComplex(ecl_eval("(z-chcm)")) # optional - kenzo - sage: ZCC # optional - kenzo + sage: ZCC = KenzoChainComplex(ecl_eval("(z-chcm)")) + sage: ZCC [K... Chain-Complex] - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: tp = s2.tensor_product(s3) # optional - kenzo - sage: tp # optional - kenzo + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: tp = s2.tensor_product(s3) + sage: tp [K... Filtered-Chain-Complex] - sage: null = ZCC.null_morphism(tp) # optional - kenzo - sage: null # optional - kenzo + sage: null = ZCC.null_morphism(tp) + sage: null [K... Morphism (degree 0): K... -> K...] - sage: null.target_complex() # optional - kenzo + sage: null.target_complex() [K... Filtered-Chain-Complex] - sage: null.destructive_change_source_target_complex(target = ZCC) # optional - kenzo + sage: null.destructive_change_source_target_complex(target = ZCC) [K... Cohomology-Class on K... of degree 0] - sage: null.target_complex() # optional - kenzo + sage: null.target_complex() [K... Chain-Complex] """ source = source or self.source_complex() @@ -1864,19 +1889,20 @@ def build_morphism(source_complex, target_complex, degree, algorithm, strategy, EXAMPLES:: + sage: # optional - kenzo sage: from sage.interfaces.kenzo import (KenzoChainComplex, ....: build_morphism) sage: from sage.libs.ecl import ecl_eval - sage: ZCC = KenzoChainComplex(ecl_eval("(z-chcm)")) # optional - kenzo - sage: A = build_morphism( # optional - kenzo + sage: ZCC = KenzoChainComplex(ecl_eval("(z-chcm)")) + sage: A = build_morphism( ....: ZCC, ZCC, -1, ....: ecl_eval("#'(lambda (comb) (cmbn (1- (degr comb))))"), ....: "cmbn", ["zero morphism on ZCC"]) - sage: A.target_complex() # optional - kenzo + sage: A.target_complex() [K... Chain-Complex] - sage: A.degree() # optional - kenzo + sage: A.degree() -1 - sage: type(A) # optional - kenzo + sage: type(A) """ return KenzoChainComplexMorphism( diff --git a/src/sage/interfaces/lie.py b/src/sage/interfaces/lie.py index 84aee7d7259..2866dfbb828 100644 --- a/src/sage/interfaces/lie.py +++ b/src/sage/interfaces/lie.py @@ -53,36 +53,38 @@ You can perform basic arithmetic operations in LiE. :: - sage: lie.eval('19+68') # optional - lie + sage: # optional - lie + sage: lie.eval('19+68') '87' - sage: a = lie('1111111111*1111111111') # optional - lie - sage: a # optional - lie + sage: a = lie('1111111111*1111111111') + sage: a 1234567900987654321 - sage: a/1111111111 # optional - lie + sage: a/1111111111 1111111111 - sage: a = lie('345') # optional - lie - sage: a^2+3*a-5 # optional - lie + sage: a = lie('345') + sage: a^2+3*a-5 120055 - sage: _ / 7*a # optional - lie + sage: _ / 7*a 5916750 Vectors in LiE are created using square brackets. Notice that the indexing in LiE is 1-based, unlike Python/Sage which is 0-based. :: - sage: v = lie('[3,2,6873,-38]') # optional - lie - sage: v # optional - lie + sage: # optional - lie + sage: v = lie('[3,2,6873,-38]') + sage: v [3,2,6873,-38] - sage: v[3] # optional - lie + sage: v[3] 6873 - sage: v+v # optional - lie + sage: v+v [6,4,13746,-76] - sage: v*v # optional - lie + sage: v*v 47239586 - sage: v+234786 # optional - lie + sage: v+234786 [3,2,6873,-38,234786] - sage: v-3 # optional - lie + sage: v-3 [3,2,-38] - sage: v^v # optional - lie + sage: v^v [3,2,6873,-38,3,2,6873,-38] You can also work with matrices in LiE. :: @@ -101,19 +103,20 @@ ,[3, 7, 0, 9] ] - sage: m^3 # optional - lie + sage: # optional - lie + sage: m^3 [[ 220, 87, 81, 375] ,[-168,-1089, 13,1013] ,[1550, 357,-55,1593] ,[-854, -652, 98,-170] ] - sage: v*m # optional - lie + sage: v*m [-6960,62055,55061,-319] - sage: m*v # optional - lie + sage: m*v [20508,-27714,54999,-14089] - sage: v*m*v # optional - lie + sage: v*m*v 378549605 - sage: m+v # optional - lie + sage: m+v [[ 1, 0, 3, 3] ,[12, 4, -4, 7] ,[-1, 9, 8, 0] @@ -130,17 +133,18 @@ LiE handles multivariate (Laurent) polynomials. :: - sage: lie('X[1,2]') # optional - lie + sage: # optional - lie + sage: lie('X[1,2]') 1X[1,2] - sage: -3*_ # optional - lie + sage: -3*_ -3X[1,2] - sage: _ + lie('4X[-1,4]') # optional - lie + sage: _ + lie('4X[-1,4]') 4X[-1,4] - 3X[ 1,2] - sage: _^2 # optional - lie + sage: _^2 16X[-2,8] - 24X[ 0,6] + 9X[ 2,4] - sage: lie('(4X[-1,4]-3X[1,2])*(X[2,0]-X[0,-4])') # optional - lie + sage: lie('(4X[-1,4]-3X[1,2])*(X[2,0]-X[0,-4])') -4X[-1, 0] + 3X[ 1,-2] + 4X[ 1, 4] - 3X[ 3, 2] - sage: _ - _ # optional - lie + sage: _ - _ 0X[0,0] @@ -172,15 +176,16 @@ a function (say f), you can call it using lie.f ; however, user-defined functions do not show up when using tab-completion. :: - sage: lie.eval('f(int x) = 2*x') # optional - lie + sage: # optional - lie + sage: lie.eval('f(int x) = 2*x') '' - sage: lie.f(984) # optional - lie + sage: lie.f(984) 1968 - sage: lie.eval('f(int n) = a=3*n-7; if a < 0 then a = -a fi; 7^a+a^3-4*a-57') # optional - lie + sage: lie.eval('f(int n) = a=3*n-7; if a < 0 then a = -a fi; 7^a+a^3-4*a-57') '' - sage: lie.f(2) # optional - lie + sage: lie.f(2) -53 - sage: lie.f(5) # optional - lie + sage: lie.f(5) 5765224 @@ -250,7 +255,8 @@ which evaluates a polynomial at a point. Below is a (roughly) direct translation of that program into Python / Sage. :: - sage: def eval_pol(p, pt): # optional - lie + sage: # optional - lie + sage: def eval_pol(p, pt): ....: s = 0 ....: for i in range(1,p.length().sage()+1): ....: m = 1 @@ -258,12 +264,12 @@ ....: m *= pt[j]^p.expon(i)[j] ....: s += p.coef(i)*m ....: return s - sage: a = lie('X[1,2]') # optional - lie - sage: b1 = lie('[1,2]') # optional - lie - sage: b2 = lie('[2,3]') # optional - lie - sage: eval_pol(a, b1) # optional - lie + sage: a = lie('X[1,2]') + sage: b1 = lie('[1,2]') + sage: b2 = lie('[2,3]') + sage: eval_pol(a, b1) 4 - sage: eval_pol(a, b2) # optional - lie + sage: eval_pol(a, b2) 18 diff --git a/src/sage/interfaces/macaulay2.py b/src/sage/interfaces/macaulay2.py index 4ed5ab46542..e8a4d94d2dc 100644 --- a/src/sage/interfaces/macaulay2.py +++ b/src/sage/interfaces/macaulay2.py @@ -496,7 +496,11 @@ def _contains(self, v1, v2): sage: 0 in a, 2 in a, 3 in a (True, True, False) sage: b = macaulay2('hashTable {"x" => 1, "y" => 2}') +<<<<<<< HEAD sage: 'x' in b, '"x"' in b # indirect doctest +======= + sage: 'x' in b, '"x"' in b +>>>>>>> a24a77aaaa1 (src/sage/interfaces: sage -fixdoctests --only-tags) (False, True) """ return self.eval("%s#?%s" % (v2, v1)) == self._true_symbol() @@ -645,7 +649,11 @@ def cputime(self, t=None): sage: R = macaulay2("QQ[x,y]") sage: x,y = R.gens() sage: a = (x+y+1)^20 +<<<<<<< HEAD sage: macaulay2.cputime() # random +======= + sage: macaulay2.cputime() +>>>>>>> a24a77aaaa1 (src/sage/interfaces: sage -fixdoctests --only-tags) 0.48393700000000001 """ _t = float(self.cpuTime()._sage_()) @@ -958,7 +966,7 @@ def _repr_(self): Sequence sage: str(macaulay2('1..25')) (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25) - sage: macaulay2.options.after_print = False # optional - macaulay2 + sage: macaulay2.options.after_print = False """ from sage.typeset.ascii_art import empty_ascii_art P = self.parent() diff --git a/src/sage/interfaces/magma.py b/src/sage/interfaces/magma.py index 529bfbc349b..7d66375f25f 100644 --- a/src/sage/interfaces/magma.py +++ b/src/sage/interfaces/magma.py @@ -47,23 +47,25 @@ how many you get using the ``nvals`` named parameter to a function call:: - sage: n = magma(100) # optional - magma - sage: n.IsSquare(nvals = 1) # optional - magma + sage: # optional - magma + sage: n = magma(100) + sage: n.IsSquare(nvals = 1) true - sage: n.IsSquare(nvals = 2) # optional - magma + sage: n.IsSquare(nvals = 2) (true, 10) - sage: n = magma(-2006) # optional - magma - sage: n.Factorization() # optional - magma + sage: n = magma(-2006) + sage: n.Factorization() [ <2, 1>, <17, 1>, <59, 1> ] - sage: n.Factorization(nvals=2) # optional - magma + sage: n.Factorization(nvals=2) ([ <2, 1>, <17, 1>, <59, 1> ], -1) We verify that an obviously principal ideal is principal:: - sage: _ = magma.eval('R := PolynomialRing(RationalField())') # optional - magma - sage: O = magma.NumberField('x^2+23').MaximalOrder() # optional - magma - sage: I = magma('ideal<%s|%s.1>'%(O.name(),O.name())) # optional - magma - sage: I.IsPrincipal(nvals=2) # optional - magma + sage: # optional - magma + sage: _ = magma.eval('R := PolynomialRing(RationalField())') + sage: O = magma.NumberField('x^2+23').MaximalOrder() + sage: I = magma('ideal<%s|%s.1>'%(O.name(),O.name())) + sage: I.IsPrincipal(nvals=2) (true, [1, 0]) Long Input @@ -142,14 +144,15 @@ structure S is denoted by S(x). This also works for the Magma interface:: - sage: G = magma.DirichletGroup(20) # optional - magma - sage: G.AssignNames(['a', 'b']) # optional - magma - sage: (G.1).Modulus() # optional - magma + sage: # optional - magma + sage: G = magma.DirichletGroup(20) + sage: G.AssignNames(['a', 'b']) + sage: (G.1).Modulus() 20 - sage: e = magma.DirichletGroup(40)(G.1) # optional - magma - sage: print(e) # optional - magma + sage: e = magma.DirichletGroup(40)(G.1) + sage: print(e) Kronecker character -4 in modulus 40 - sage: print(e.Modulus()) # optional - magma + sage: print(e.Modulus()) 40 We coerce some polynomial rings into Magma:: @@ -713,13 +716,14 @@ def __call__(self, x, gens=None): EXAMPLES:: - sage: magma(EllipticCurve('37a')) # optional - magma + sage: # optional - magma + sage: magma(EllipticCurve('37a')) Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field - sage: magma('EllipticCurve([GF(5)|1,2,3,4,1])') # optional - magma + sage: magma('EllipticCurve([GF(5)|1,2,3,4,1])') Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 1 over GF(5) - sage: magma('PowerSeriesRing(Rationals())', 't') # optional - magma + sage: magma('PowerSeriesRing(Rationals())', 't') Power series ring in t over Rational Field - sage: magma('PolynomialRing(RationalField(), 3)', 'x,y,z') # optional - magma + sage: magma('PolynomialRing(RationalField(), 3)', 'x,y,z') Polynomial ring of rank 3 over Rational Field Order: Lexicographical Variables: x, y, z @@ -736,25 +740,27 @@ def __call__(self, x, gens=None): We test caching:: - sage: R. = ZZ[] # optional - magma - sage: magma(R) is magma(R) # optional - magma + sage: # optional - magma + sage: R. = ZZ[] + sage: magma(R) is magma(R) True - sage: m = Magma() # optional - magma - sage: m(R) # optional - magma + sage: m = Magma() + sage: m(R) Univariate Polynomial Ring in x over Integer Ring - sage: m(R) is magma(R) # optional - magma + sage: m(R) is magma(R) False - sage: R._magma_cache # optional - magma + sage: R._magma_cache {Magma: Univariate Polynomial Ring in x over Integer Ring, Magma: Univariate Polynomial Ring in x over Integer Ring} - sage: P. = PolynomialRing(GF(127)) # optional - magma - sage: m = Magma() # optional - magma - sage: m(P) # optional - magma + sage: # optional - magma + sage: P. = PolynomialRing(GF(127)) + sage: m = Magma() + sage: m(P) Polynomial ring of rank 2 over GF(127) Order: Graded Reverse Lexicographical Variables: x, y - sage: P._magma_cache # optional - magma + sage: P._magma_cache {Magma: Polynomial ring of rank 2 over GF(127) Order: Graded Reverse Lexicographical Variables: x, y} @@ -891,16 +897,17 @@ def clear(self, var): :: - sage: magma = Magma() # optional - magma - sage: a = magma('100') # optional - magma - sage: a.name() # optional - magma + sage: # optional - magma + sage: magma = Magma() + sage: a = magma('100') + sage: a.name() '_sage_[1]' - sage: del a # optional - magma - sage: b = magma('257') # optional - magma - sage: b.name() # optional - magma + sage: del a + sage: b = magma('257') + sage: b.name() '_sage_[1]' - sage: del b # optional - magma - sage: magma('_sage_[1]') # optional - magma + sage: del b + sage: magma('_sage_[1]') 0 """ self.__available_var.insert(0, var) # adds var to front of list @@ -931,12 +938,13 @@ def cputime(self, t=None): EXAMPLES:: - sage: type(magma.cputime()) # optional - magma + sage: # optional - magma + sage: type(magma.cputime()) <... 'float'> - sage: magma.cputime() # random, optional - magma + sage: magma.cputime() 1.9399999999999999 - sage: t = magma.cputime() # optional - magma - sage: magma.cputime(t) # random, optional - magma + sage: t = magma.cputime() + sage: magma.cputime(t) 0.02 """ if t: @@ -1251,15 +1259,16 @@ def bar_call(self, left, name, gens, nvals=1): methods of Magma elements. Here we illustrate directly using bar_call to create quotients:: - sage: V = magma.RModule(ZZ,3) # optional - magma - sage: V # optional - magma + sage: # optional - magma + sage: V = magma.RModule(ZZ,3) + sage: V RModule(IntegerRing(), 3) - sage: magma.bar_call(V, 'quo', [[1,2,3]], nvals=1) # optional - magma + sage: magma.bar_call(V, 'quo', [[1,2,3]], nvals=1) RModule(IntegerRing(), 2) - sage: magma.bar_call(V, 'quo', [[1,2,3]], nvals=2) # optional - magma + sage: magma.bar_call(V, 'quo', [[1,2,3]], nvals=2) (RModule(IntegerRing(), 2), Mapping from: RModule(IntegerRing(), 3) to RModule(IntegerRing(), 2)) - sage: magma.bar_call(V, 'quo', V, nvals=2) # optional - magma + sage: magma.bar_call(V, 'quo', V, nvals=2) (RModule(IntegerRing(), 0), Mapping from: RModule(IntegerRing(), 3) to RModule(IntegerRing(), 0)) """ @@ -1644,11 +1653,12 @@ def __call__(self, *args, **kwds): EXAMPLES: We create a MagmaFunctionElement:: - sage: n = magma(-15) # optional - magma - sage: f = n.Factorisation # optional - magma - sage: type(f) # optional - magma + sage: # optional - magma + sage: n = magma(-15) + sage: f = n.Factorisation + sage: type(f) - sage: f() # optional - magma + sage: f() [ <3, 1>, <5, 1> ] We verify that the nvals argument works. @@ -1686,12 +1696,13 @@ def _instancedoc_(self): EXAMPLES:: - sage: n = magma(-15) # optional - magma - sage: f = n.Factorisation # optional - magma - sage: print(f.__doc__) # optional - magma + sage: # optional - magma + sage: n = magma(-15) + sage: f = n.Factorisation + sage: print(f.__doc__) (n::RngIntElt) -> RngIntEltFact, RngIntElt, SeqEnum ... - sage: print(n.Factorisation.__doc__) # optional - magma + sage: print(n.Factorisation.__doc__) (n::RngIntElt) -> RngIntEltFact, RngIntElt, SeqEnum ... """ @@ -1728,13 +1739,14 @@ def _repr_(self): :: - sage: V = magma('VectorSpace(RationalField(),2)') # optional - magma - sage: V.set_magma_attribute('M', 290398) # optional - magma - sage: V.M # optional - magma + sage: # optional - magma + sage: V = magma('VectorSpace(RationalField(),2)') + sage: V.set_magma_attribute('M', 290398) + sage: V.M 290398 - sage: type(V.M) # optional - magma + sage: type(V.M) - sage: type(V.M.__repr__()) # optional - magma + sage: type(V.M.__repr__()) <... 'str'> Displaying a non-attribute function works as above. @@ -1898,13 +1910,14 @@ def __getattr__(self, attrname): EXAMPLES:: - sage: n = magma(-15) # optional - magma - sage: type(n) # optional - magma + sage: # optional - magma + sage: n = magma(-15) + sage: type(n) - sage: f = n.__getattr__('Factorization') # optional - magma - sage: type(f) # optional - magma + sage: f = n.__getattr__('Factorization') + sage: type(f) - sage: f # optional - magma + sage: f Partially evaluated Magma function or intrinsic 'Factorization' ... """ @@ -1921,24 +1934,25 @@ def _sage_(self): EXAMPLES: Enumerated Sets:: - sage: a = magma('{1,2/3,-5/9}') # optional - magma - sage: a.sage() # optional - magma + sage: # optional - magma + sage: a = magma('{1,2/3,-5/9}') + sage: a.sage() {1, -5/9, 2/3} - sage: a._sage_() # optional - magma + sage: a._sage_() {1, -5/9, 2/3} - sage: type(a.sage()) # optional - magma + sage: type(a.sage()) - sage: a = magma('{1,2/3,-5/9}'); a # optional - magma + sage: a = magma('{1,2/3,-5/9}'); a { -5/9, 2/3, 1 } - sage: a.Type() # optional - magma + sage: a.Type() SetEnum - sage: b = a.sage(); b # optional - magma + sage: b = a.sage(); b {1, -5/9, 2/3} - sage: type(b) # optional - magma + sage: type(b) - sage: c = magma(b); c # optional - magma + sage: c = magma(b); c { -5/9, 2/3, 1 } - sage: c.Type() # optional - magma + sage: c.Type() SetEnum Multisets are converted to lists:: @@ -1986,20 +2000,22 @@ def _sage_(self): Multivariate polynomials:: - sage: R. = QQ[] # optional - magma - sage: f = x^2+3*y # optional - magma - sage: g = magma(f).sage(); g # optional - magma + sage: # optional - magma + sage: R. = QQ[] + sage: f = x^2+3*y + sage: g = magma(f).sage(); g x^2 + 3*y - sage: parent(f) == parent(g) # optional - magma + sage: parent(f) == parent(g) True Real and complex numbers:: - sage: m = magma(RealField(200)(1/3)) # optional - magma - sage: m.sage() # indirect doctest, optional - magma + sage: # optional - magma + sage: m = magma(RealField(200)(1/3)) + sage: m.sage() 0.33333333333333333333333333333333333333333333333333333333333 - sage: m = magma(RealField(1000)(1/3)) # optional - magma - sage: m.sage() # indirect doctest, optional - magma + sage: m = magma(RealField(1000)(1/3)) + sage: m.sage() 0.333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 sage: m = magma(ComplexField(200)).1; m # optional - magma @@ -2041,14 +2057,15 @@ def _sage_(self): to relative number fields. Conversion of their elements has not yet been implemented.:: - sage: magma.eval('P := PolynomialRing(Rationals());') # optional - magma + sage: # optional - magma + sage: magma.eval('P := PolynomialRing(Rationals());') '' - sage: K = magma('NumberField([x^2-2,x^2-3]:Abs);') # optional - magma - sage: L = K.sage(); L # optional - magma + sage: K = magma('NumberField([x^2-2,x^2-3]:Abs);') + sage: L = K.sage(); L Number Field in K1 with defining polynomial x^2 - 2 over its base field - sage: L.base_field() # optional - magma + sage: L.base_field() Number Field in K2 with defining polynomial x^2 - 3 - sage: K.GeneratorsSequence()[1].sage() # optional - magma + sage: K.GeneratorsSequence()[1].sage() Traceback (most recent call last): ... NameError: name 'K' is not defined @@ -2083,11 +2100,12 @@ def AssignNames(self, names): """ EXAMPLES:: - sage: S = magma.PolynomialRing(magma.Integers(), 2) # optional - magma - sage: S.AssignNames(['a', 'b']) # optional - magma - sage: S.1 # optional - magma + sage: # optional - magma + sage: S = magma.PolynomialRing(magma.Integers(), 2) + sage: S.AssignNames(['a', 'b']) + sage: S.1 a - sage: S.1^2 + S.2 # optional - magma + sage: S.1^2 + S.2 a^2 + b """ P = self._check_valid() @@ -2214,13 +2232,14 @@ def evaluate(self, *args): EXAMPLES:: - sage: f = magma('Factorization') # optional - magma - sage: f.evaluate(15) # optional - magma + sage: # optional - magma + sage: f = magma('Factorization') + sage: f.evaluate(15) [ <3, 1>, <5, 1> ] - sage: f(15) # optional - magma + sage: f(15) [ <3, 1>, <5, 1> ] - sage: f = magma('GCD') # optional - magma - sage: f.evaluate(15,20) # optional - magma + sage: f = magma('GCD') + sage: f.evaluate(15,20) 5 sage: m = matrix(QQ, 2, 2, [2,3,5,7]) # optional - magma @@ -2242,13 +2261,14 @@ def __call__(self, *args): EXAMPLES:: - sage: M = magma.RMatrixSpace(magma.IntegerRing(), 2, 2) # optional - magma - sage: A = M([1,2,3,4]); A # optional - magma + sage: # optional - magma + sage: M = magma.RMatrixSpace(magma.IntegerRing(), 2, 2) + sage: A = M([1,2,3,4]); A [1 2] [3 4] - sage: type(A) # optional - magma + sage: type(A) - sage: A.Type() # optional - magma + sage: A.Type() ModMatRngElt """ if len(args) > 1: @@ -2274,16 +2294,17 @@ def __iter__(self): EXAMPLES:: - sage: V = magma('VectorSpace(GF(3),2)') # optional - magma - sage: V # optional - magma + sage: # optional - magma + sage: V = magma('VectorSpace(GF(3),2)') + sage: V Full Vector space of degree 2 over GF(3) - sage: w = V.__iter__(); w # optional - magma + sage: w = V.__iter__(); w - sage: next(w) # optional - magma + sage: next(w) (0 0) - sage: next(w) # optional - magma + sage: next(w) (1 0) - sage: list(w) # optional - magma + sage: list(w) [(2 0), (0 1), (1 1), (2 1), (0 2), (1 2), (2 2)] """ P = self._check_valid() @@ -2299,12 +2320,13 @@ def __len__(self): EXAMPLES:: - sage: V = magma('VectorSpace(GF(3),2)') # optional - magma - sage: V # optional - magma + sage: # optional - magma + sage: V = magma('VectorSpace(GF(3),2)') + sage: V Full Vector space of degree 2 over GF(3) - sage: len(V) # optional - magma + sage: len(V) 9 - sage: V.__len__() # optional - magma + sage: V.__len__() 9 """ P = self._check_valid() @@ -2431,11 +2453,12 @@ def _latex_(self): Power Series:: - sage: _=magma.eval('R := PowerSeriesRing(RationalField())') # optional - magma - sage: latex(magma('(1/(1+x))')) # optional - magma + sage: # optional - magma + sage: _=magma.eval('R := PowerSeriesRing(RationalField())') + sage: latex(magma('(1/(1+x))')) 1-x+x^{2}-x^{3}+x^{4}-x^{5}+x^{6}-x^{7}+x^{8}-x^{9}+x^{10}-x^{11}+x^{12}-x^{13}+x^{14}-x^{15}+x^{16}-x^{17}+x^{18}-x^{19}+O(x^{20}) - sage: _=magma.eval('R := PowerSeriesRing(RationalField())') # optional - magma - sage: latex(magma('(-1/(2+x + O(x^3)))')) # optional - magma + sage: _=magma.eval('R := PowerSeriesRing(RationalField())') + sage: latex(magma('(-1/(2+x + O(x^3)))')) \frac{-1}{2}+\frac{1}{4}x-\frac{1}{8}x^{2}+O(x^{3}) p-adic Numbers:: @@ -2457,11 +2480,12 @@ def set_magma_attribute(self, attrname, value): EXAMPLES:: - sage: V = magma("VectorSpace(RationalField(),2)") # optional - magma - sage: V.set_magma_attribute('M',10) # optional - magma - sage: V.get_magma_attribute('M') # optional - magma + sage: # optional - magma + sage: V = magma("VectorSpace(RationalField(),2)") + sage: V.set_magma_attribute('M',10) + sage: V.get_magma_attribute('M') 10 - sage: V.M # optional - magma + sage: V.M 10 """ P = self.parent() # instance of Magma that contains this element. @@ -2478,11 +2502,12 @@ def get_magma_attribute(self, attrname): EXAMPLES:: - sage: V = magma("VectorSpace(RationalField(),10)") # optional - magma - sage: V.set_magma_attribute('M','"hello"') # optional - magma - sage: V.get_magma_attribute('M') # optional - magma + sage: # optional - magma + sage: V = magma("VectorSpace(RationalField(),10)") + sage: V.set_magma_attribute('M','"hello"') + sage: V.get_magma_attribute('M') hello - sage: V.M # optional - magma + sage: V.M hello """ P = self.parent() @@ -2620,13 +2645,14 @@ def __bool__(self): Test use in bool conversions of bools:: - sage: bool(magma(False)) # optional - magma + sage: # optional - magma + sage: bool(magma(False)) False - sage: bool(magma(True)) # optional - magma + sage: bool(magma(True)) True - sage: bool(magma(1)) # optional - magma + sage: bool(magma(1)) True - sage: bool(magma(0)) # optional - magma + sage: bool(magma(0)) False TESTS: @@ -2713,12 +2739,13 @@ def quo(self, gens, **args): :: - sage: V = magma.RModule(ZZ,3); V # optional - magma + sage: # optional - magma + sage: V = magma.RModule(ZZ,3); V RModule(IntegerRing(), 3) - sage: W, phi = V.quo([[1,2,3]]) # optional - magma - sage: W # optional - magma + sage: W, phi = V.quo([[1,2,3]]) + sage: W RModule(IntegerRing(), 2) - sage: phi # optional - magma + sage: phi Mapping from: RModule(IntegerRing(), 3) to RModule(IntegerRing(), 2) """ return self.parent().bar_call(self, 'quo', gens, nvals=2) @@ -2741,10 +2768,11 @@ def ideal(self, gens): EXAMPLES:: - sage: R = magma('PolynomialRing(RationalField())') # optional - magma - sage: R.assign_names(['x']) # optional - magma - sage: x = R.1 # optional - magma - sage: R.ideal([x^2 - 1, x^3 - 1]) # optional - magma + sage: # optional - magma + sage: R = magma('PolynomialRing(RationalField())') + sage: R.assign_names(['x']) + sage: x = R.1 + sage: R.ideal([x^2 - 1, x^3 - 1]) Ideal of Univariate Polynomial Ring in x over Rational Field generated by x - 1 """ return self.parent().bar_call(self, 'ideal', gens, nvals=1) diff --git a/src/sage/interfaces/maple.py b/src/sage/interfaces/maple.py index 7ba21a66cf6..1f4f209f127 100644 --- a/src/sage/interfaces/maple.py +++ b/src/sage/interfaces/maple.py @@ -605,12 +605,20 @@ def cputime(self, t=None): sage: # optional - maple sage: t = maple.cputime() +<<<<<<< HEAD sage: t # random +======= + sage: t +>>>>>>> a24a77aaaa1 (src/sage/interfaces: sage -fixdoctests --only-tags) 0.02 sage: x = maple('x') sage: maple.diff(x^2, x) 2*x +<<<<<<< HEAD sage: maple.cputime(t) # random +======= + sage: maple.cputime(t) +>>>>>>> a24a77aaaa1 (src/sage/interfaces: sage -fixdoctests --only-tags) 0.0 """ if t is None: @@ -810,7 +818,11 @@ def with_package(self, package): :: sage: # optional - maple +<<<<<<< HEAD sage: maple.quit() # reset maple +======= + sage: maple.quit() +>>>>>>> a24a77aaaa1 (src/sage/interfaces: sage -fixdoctests --only-tags) sage: maple('partition(10)') partition(10) sage: maple('bell(10)') @@ -947,7 +959,11 @@ def __hash__(self): sage: # optional - maple sage: m = maple('x^2+y^2') +<<<<<<< HEAD sage: m.__hash__() # random +======= + sage: m.__hash__() +>>>>>>> a24a77aaaa1 (src/sage/interfaces: sage -fixdoctests --only-tags) 188724254834261060184983038723355865733 sage: hash(m) # random 5035731711831192733 diff --git a/src/sage/interfaces/mathematica.py b/src/sage/interfaces/mathematica.py index 9c6e3ca86e9..9c64e9f4286 100644 --- a/src/sage/interfaces/mathematica.py +++ b/src/sage/interfaces/mathematica.py @@ -31,14 +31,15 @@ call the Mathematica wrapper object's ``sage()`` method. This method returns a native Sage object:: - sage: mobj = mathematica(x^2-1) # optional - mathematica - sage: mobj2 = mobj.Factor(); mobj2 # optional - mathematica + sage: # optional - mathematica + sage: mobj = mathematica(x^2-1) + sage: mobj2 = mobj.Factor(); mobj2 (-1 + x)*(1 + x) - sage: mobj2.parent() # optional - mathematica + sage: mobj2.parent() Mathematica - sage: sobj = mobj2.sage(); sobj # optional - mathematica + sage: sobj = mobj2.sage(); sobj (x + 1)*(x - 1) - sage: sobj.parent() # optional - mathematica + sage: sobj.parent() Symbolic Ring @@ -122,16 +123,17 @@ We solve an equation and a system of two equations:: - sage: eqn = mathematica('3x + 5 == 14') # optional - mathematica - sage: eqn # optional - mathematica + sage: # optional - mathematica + sage: eqn = mathematica('3x + 5 == 14') + sage: eqn 5 + 3*x == 14 - sage: eqn.Solve('x') # optional - mathematica + sage: eqn.Solve('x') {{x -> 3}} - sage: sys = mathematica('{x^2 - 3y == 3, 2x - y == 1}') # optional - mathematica - sage: print(sys) # optional - mathematica + sage: sys = mathematica('{x^2 - 3y == 3, 2x - y == 1}') + sage: print(sys) 2 {x - 3 y == 3, 2 x - y == 1} - sage: sys.Solve('{x, y}') # optional - mathematica + sage: sys.Solve('{x, y}') {{x -> 0, y -> -1}, {x -> 6, y -> 11}} Assignments and definitions @@ -227,15 +229,16 @@ We factor an integer:: - sage: n = mathematica(2434500) # optional - mathematica - sage: n.FactorInteger() # optional - mathematica + sage: # optional - mathematica + sage: n = mathematica(2434500) + sage: n.FactorInteger() {{2, 2}, {3, 2}, {5, 3}, {541, 1}} - sage: n = mathematica(2434500) # optional - mathematica - sage: F = n.FactorInteger(); F # optional - mathematica + sage: n = mathematica(2434500) + sage: F = n.FactorInteger(); F {{2, 2}, {3, 2}, {5, 3}, {541, 1}} - sage: F[1] # optional - mathematica + sage: F[1] {2, 2} - sage: F[4] # optional - mathematica + sage: F[4] {541, 1} Mathematica's ECM package is no longer available. @@ -261,17 +264,18 @@ :: - sage: x = mathematica(pi/2) # optional - mathematica - sage: print(x) # optional - mathematica + sage: # optional - mathematica + sage: x = mathematica(pi/2) + sage: print(x) Pi -- 2 - sage: loads(dumps(x)) == x # optional - mathematica + sage: loads(dumps(x)) == x True - sage: n = x.N(50) # optional - mathematica - sage: print(n) # optional - mathematica + sage: n = x.N(50) + sage: print(n) 1.5707963267948966192313216916397514420985846996876 - sage: loads(dumps(n)) == n # optional - mathematica + sage: loads(dumps(n)) == n True Complicated translations @@ -351,13 +355,14 @@ Check that numerical approximations via Mathematica's `N[]` function work correctly (:trac:`18888`, :trac:`28907`):: - sage: mathematica('Pi/2').N(10) # optional -- mathematica + sage: # optional - mathematica + sage: mathematica('Pi/2').N(10) 1.5707963268 - sage: mathematica('Pi').N(10) # optional -- mathematica + sage: mathematica('Pi').N(10) 3.1415926536 - sage: mathematica('Pi').N(50) # optional -- mathematica + sage: mathematica('Pi').N(50) 3.14159265358979323846264338327950288419716939937511 - sage: str(mathematica('Pi*x^2-1/2').N()) # optional -- mathematica + sage: str(mathematica('Pi*x^2-1/2').N()) 2 -0.5 + 3.14159 x @@ -373,13 +378,14 @@ Check that all trig/hyperbolic functions and their reciprocals are correctly translated to Mathematica (:trac:`34087`):: - sage: x=var('x') # optional - mathematica - sage: FL=[sin, cos, tan, csc, sec, cot, # optional - mathematica + sage: # optional - mathematica + sage: x=var('x') + sage: FL=[sin, cos, tan, csc, sec, cot, ....: sinh, cosh, tanh, csch, sech, coth] - sage: IFL=[arcsin, arccos, arctan, arccsc, # optional - mathematica + sage: IFL=[arcsin, arccos, arctan, arccsc, ....: arcsec, arccot, arcsinh, arccosh, ....: arctanh, arccsch, arcsech, arccoth] - sage: [mathematica.TrigToExp(u(x)).sage() # optional - mathematica + sage: [mathematica.TrigToExp(u(x)).sage() ....: for u in FL] [-1/2*I*e^(I*x) + 1/2*I*e^(-I*x), 1/2*e^(I*x) + 1/2*e^(-I*x), @@ -393,7 +399,7 @@ -2/(e^(-x) - e^x), 2/(e^(-x) + e^x), -(e^(-x) + e^x)/(e^(-x) - e^x)] - sage: [mathematica.TrigToExp(u(x)).sage() # optional - mathematica + sage: [mathematica.TrigToExp(u(x)).sage() ....: for u in IFL] [-I*log(I*x + sqrt(-x^2 + 1)), 1/2*pi + I*log(I*x + sqrt(-x^2 + 1)), @@ -789,12 +795,13 @@ def _sage_(self, locals={}): Mathematica lists of numbers/constants become Sage lists of numbers/constants:: - sage: m = mathematica('{{1., 4}, Pi, 3.2e100, I}') # optional - mathematica - sage: s = m.sage(); s # optional - mathematica + sage: # optional - mathematica + sage: m = mathematica('{{1., 4}, Pi, 3.2e100, I}') + sage: s = m.sage(); s [[1.00000000000000, 4], pi, 3.20000000000000*e100, I] - sage: s[1].n() # optional - mathematica + sage: s[1].n() 3.14159265358979 - sage: s[3]^2 # optional - mathematica + sage: s[3]^2 -1 :: @@ -825,11 +832,12 @@ def _sage_(self, locals={}): :: - sage: m = mathematica('bla^2') # optional - mathematica - sage: mb = m.sage() # optional - mathematica - sage: var('bla') # optional - mathematica + sage: # optional - mathematica + sage: m = mathematica('bla^2') + sage: mb = m.sage() + sage: var('bla') bla - sage: bla^2 - mb # optional - mathematica + sage: bla^2 - mb 0 diff --git a/src/sage/interfaces/mathics.py b/src/sage/interfaces/mathics.py index 0bf0bc78829..aec033d3173 100644 --- a/src/sage/interfaces/mathics.py +++ b/src/sage/interfaces/mathics.py @@ -47,14 +47,15 @@ call the Mathics wrapper object's ``sage()`` method. This method returns a native Sage object:: - sage: mobj = mathics(x^2-1) # optional - mathics - sage: mobj2 = mobj.Factor(); mobj2 # optional - mathics + sage: # optional - mathics + sage: mobj = mathics(x^2-1) + sage: mobj2 = mobj.Factor(); mobj2 (-1 + x) (1 + x) - sage: mobj2.parent() # optional - mathics + sage: mobj2.parent() Mathics - sage: sobj = mobj2.sage(); sobj # optional - mathics + sage: sobj = mobj2.sage(); sobj (x + 1)*(x - 1) - sage: sobj.parent() # optional - mathics + sage: sobj.parent() Symbolic Ring @@ -132,15 +133,16 @@ We solve an equation and a system of two equations:: - sage: eqn = mathics('3x + 5 == 14') # optional - mathics - sage: eqn # optional - mathics + sage: # optional - mathics + sage: eqn = mathics('3x + 5 == 14') + sage: eqn 5 + 3 x == 14 - sage: eqn.Solve('x') # optional - mathics + sage: eqn.Solve('x') {{x -> 3}} - sage: sys = mathics('{x^2 - 3y == 3, 2x - y == 1}') # optional - mathics - sage: print(sys) # optional - mathics + sage: sys = mathics('{x^2 - 3y == 3, 2x - y == 1}') + sage: print(sys) {x ^ 2 - 3 y == 3, 2 x - y == 1} - sage: sys.Solve('{x, y}') # optional - mathics + sage: sys.Solve('{x, y}') {{x -> 0, y -> -1}, {x -> 6, y -> 11}} Assignments and definitions @@ -233,15 +235,16 @@ We factor an integer:: - sage: n = mathics(2434500) # optional - mathics - sage: n.FactorInteger() # optional - mathics + sage: # optional - mathics + sage: n = mathics(2434500) + sage: n.FactorInteger() {{2, 2}, {3, 2}, {5, 3}, {541, 1}} - sage: n = mathics(2434500) # optional - mathics - sage: F = n.FactorInteger(); F # optional - mathics + sage: n = mathics(2434500) + sage: F = n.FactorInteger(); F {{2, 2}, {3, 2}, {5, 3}, {541, 1}} - sage: F[1] # optional - mathics + sage: F[1] {2, 2} - sage: F[4] # optional - mathics + sage: F[4] {541, 1} @@ -266,15 +269,16 @@ :: - sage: x = mathics(pi/2) # optional - mathics - sage: print(x) # optional - mathics + sage: # optional - mathics + sage: x = mathics(pi/2) + sage: print(x) Pi / 2 - sage: loads(dumps(x)) == x # optional - mathics + sage: loads(dumps(x)) == x True - sage: n = x.N(50) # optional - mathics - sage: print(n) # optional - mathics + sage: n = x.N(50) + sage: print(n) 1.5707963267948966192313216916397514420985846996876 - sage: loads(dumps(n)) == n # optional - mathics + sage: loads(dumps(n)) == n True Complicated translations @@ -356,13 +360,14 @@ Check that numerical approximations via Mathics's `N[]` function work correctly (:trac:`18888`, :trac:`28907`):: - sage: mathics('Pi/2').N(10) # optional -- mathics + sage: # optional - mathics + sage: mathics('Pi/2').N(10) 1.570796327 - sage: mathics('Pi').N(10) # optional -- mathics + sage: mathics('Pi').N(10) 3.141592654 - sage: mathics('Pi').N(50) # optional -- mathics + sage: mathics('Pi').N(50) 3.1415926535897932384626433832795028841971693993751 - sage: str(mathics('Pi*x^2-1/2').N()) # optional -- mathics + sage: str(mathics('Pi*x^2-1/2').N()) '-0.5 + 3.14159 x ^ 2.' Check that Mathics's `E` exponential symbol is correctly backtranslated @@ -405,15 +410,16 @@ def _mathics_sympysage_symbol(self): EXAMPLES:: + sage: # optional - mathics sage: from sage.interfaces.mathics import _mathics_sympysage_symbol - sage: mt = mathics('t') # optional - mathics - sage: st = mt.to_sympy(); st # optional - mathics + sage: mt = mathics('t') + sage: st = mt.to_sympy(); st _Mathics_User_Global`t - sage: _mathics_sympysage_symbol(st) # optional - mathics + sage: _mathics_sympysage_symbol(st) t - sage: bool(_ == st._sage_()) # optional - mathics + sage: bool(_ == st._sage_()) True - sage: type(st._sage_()) # optional - mathics + sage: type(st._sage_()) """ from sage.symbolic.ring import SR @@ -442,20 +448,21 @@ class Mathics(Interface): EXAMPLES:: - sage: t = mathics('Tan[I + 0.5]') # optional - mathics - sage: t.parent() # optional - mathics + sage: # optional - mathics + sage: t = mathics('Tan[I + 0.5]') + sage: t.parent() Mathics - sage: ts = t.sage() # optional - mathics - sage: ts.parent() # optional - mathics + sage: ts = t.sage() + sage: ts.parent() Complex Field with 53 bits of precision - sage: t == mathics(ts) # optional - mathics + sage: t == mathics(ts) True - sage: mtan = mathics.Tan # optional - mathics - sage: mt = mtan(I+1/2) # optional - mathics - sage: mt == t # optional - mathics + sage: mtan = mathics.Tan + sage: mt = mtan(I+1/2) + sage: mt == t True - sage: u = mathics(I+1/2) # optional - mathics - sage: u.Tan() == mt # optional - mathics + sage: u = mathics(I+1/2) + sage: u.Tan() == mt True @@ -829,34 +836,37 @@ class MathicsElement(ExtraTabCompletion, InterfaceElement): EXAMPLES:: - sage: me=mathics(e); me # optional - mathics + sage: # optional - mathics + sage: me=mathics(e); me E - sage: type(me) # optional - mathics + sage: type(me) - sage: P = me.parent(); P # optional - mathics + sage: P = me.parent(); P Mathics - sage: type(P) # optional - mathics + sage: type(P) Access to the Mathics expression objects:: - sage: res = me._mathics_result # optional - mathics - sage: type(res) # optional - mathics + sage: # optional - mathics + sage: res = me._mathics_result + sage: type(res) - sage: expr = res.last_eval; expr # optional - mathics + sage: expr = res.last_eval; expr - sage: type(expr) # optional - mathics + sage: type(expr) Applying Mathics methods:: - sage: me.to_sympy() # optional - mathics + sage: # optional - mathics + sage: me.to_sympy() E - sage: me.get_name() # optional - mathics + sage: me.get_name() 'System`E' - sage: me.is_inexact() # optional - mathics + sage: me.is_inexact() False - sage: me.is_symbol() # optional - mathics + sage: me.is_symbol() True Conversion to Sage:: @@ -900,12 +910,13 @@ def __getattr__(self, attrname): r""" EXAMPLES:: - sage: a = mathics(5*x) # optional - mathics - sage: res = a._mathics_result # optional - mathics - sage: str(a) == res.result # optional - mathics + sage: # optional - mathics + sage: a = mathics(5*x) + sage: res = a._mathics_result + sage: str(a) == res.result True - sage: t = mathics._eval('5*x') # optional - mathics - sage: t.last_eval == res.last_eval # optional - mathics + sage: t = mathics._eval('5*x') + sage: t.last_eval == res.last_eval True """ P = self._check_valid() @@ -1004,12 +1015,13 @@ def _sage_(self, locals={}): Mathics lists of numbers/constants become Sage lists of numbers/constants:: - sage: m = mathics('{{1., 4}, Pi, 3.2e100, I}') # optional - mathics - sage: s = m.sage(); s # optional - mathics + sage: # optional - mathics + sage: m = mathics('{{1., 4}, Pi, 3.2e100, I}') + sage: s = m.sage(); s [[1.00000000000000, 4], pi, 3.20000000000000*e100, 1.00000000000000*I] - sage: s[1].n() # optional - mathics + sage: s[1].n() 3.14159265358979 - sage: s[3]^2 # optional - mathics + sage: s[3]^2 -1.00000000000000 :: @@ -1040,11 +1052,12 @@ def _sage_(self, locals={}): :: - sage: m = mathics('bla^2') # optional - mathics - sage: mb = m.sage() # optional - mathics - sage: var('bla') # optional - mathics + sage: # optional - mathics + sage: m = mathics('bla^2') + sage: mb = m.sage() + sage: var('bla') bla - sage: bla^2 - mb # optional - mathics + sage: bla^2 - mb 0 """ @@ -1203,14 +1216,15 @@ def _richcmp_(self, other, op): r""" EXAMPLES:: - sage: mobj1 = mathics([x^2-1, 2]) # optional - mathics - sage: mobj2 = mathics('{x^2-1, 2}') # optional - mathics - sage: mobj3 = mathics('5*x + y') # optional - mathics - sage: mobj1 == mobj2 # optional - mathics + sage: # optional - mathics + sage: mobj1 = mathics([x^2-1, 2]) + sage: mobj2 = mathics('{x^2-1, 2}') + sage: mobj3 = mathics('5*x + y') + sage: mobj1 == mobj2 True - sage: mobj1 < mobj2 # optional - mathics + sage: mobj1 < mobj2 False - sage: mobj1 == mobj3 # optional - mathics + sage: mobj1 == mobj3 False """ P = self.parent() diff --git a/src/sage/interfaces/matlab.py b/src/sage/interfaces/matlab.py index 24c40a3647c..74354b77412 100644 --- a/src/sage/interfaces/matlab.py +++ b/src/sage/interfaces/matlab.py @@ -30,53 +30,57 @@ EXAMPLES:: - sage: matlab('4+10') # optional - matlab + sage: # optional - matlab + sage: matlab('4+10') 14 - sage: matlab('date') # optional - matlab; random output + sage: matlab('date') 18-Oct-2006 - sage: matlab('5*10 + 6') # optional - matlab + sage: matlab('5*10 + 6') 56 - sage: matlab('(6+6)/3') # optional - matlab + sage: matlab('(6+6)/3') 4 - sage: matlab('9')^2 # optional - matlab + sage: matlab('9')^2 81 - sage: a = matlab(10); b = matlab(20); c = matlab(30) # optional - matlab - sage: avg = (a+b+c)/3 ; avg # optional - matlab + sage: a = matlab(10); b = matlab(20); c = matlab(30) + sage: avg = (a+b+c)/3 ; avg 20 - sage: parent(avg) # optional - matlab + sage: parent(avg) Matlab :: - sage: my_scalar = matlab('3.1415') # optional - matlab - sage: my_scalar # optional - matlab + sage: # optional - matlab + sage: my_scalar = matlab('3.1415') + sage: my_scalar 3.1415 - sage: my_vector1 = matlab('[1,5,7]') # optional - matlab - sage: my_vector1 # optional - matlab + sage: my_vector1 = matlab('[1,5,7]') + sage: my_vector1 1 5 7 - sage: my_vector2 = matlab('[1;5;7]') # optional - matlab - sage: my_vector2 # optional - matlab + sage: my_vector2 = matlab('[1;5;7]') + sage: my_vector2 1 5 7 - sage: my_vector1 * my_vector2 # optional - matlab + sage: my_vector1 * my_vector2 75 :: - sage: row_vector1 = matlab('[1 2 3]') # optional - matlab - sage: row_vector2 = matlab('[3 2 1]') # optional - matlab - sage: matrix_from_row_vec = matlab('[%s; %s]'%(row_vector1.name(), row_vector2.name())) # optional - matlab - sage: matrix_from_row_vec # optional - matlab + sage: # optional - matlab + sage: row_vector1 = matlab('[1 2 3]') + sage: row_vector2 = matlab('[3 2 1]') + sage: matrix_from_row_vec = matlab('[%s; %s]'%(row_vector1.name(), row_vector2.name())) + sage: matrix_from_row_vec 1 2 3 3 2 1 :: - sage: column_vector1 = matlab('[1;3]') # optional - matlab - sage: column_vector2 = matlab('[2;8]') # optional - matlab - sage: matrix_from_col_vec = matlab('[%s %s]'%(column_vector1.name(), column_vector2.name())) # optional - matlab - sage: matrix_from_col_vec # optional - matlab + sage: # optional - matlab + sage: column_vector1 = matlab('[1;3]') + sage: column_vector2 = matlab('[2;8]') + sage: matrix_from_col_vec = matlab('[%s %s]'%(column_vector1.name(), column_vector2.name())) + sage: matrix_from_col_vec 1 2 3 8 @@ -106,12 +110,13 @@ :: - sage: my_vector1 = matlab('[1,5,7]') # optional - matlab - sage: my_vector1(1) # optional - matlab + sage: # optional - matlab + sage: my_vector1 = matlab('[1,5,7]') + sage: my_vector1(1) 1 - sage: my_vector1(2) # optional - matlab + sage: my_vector1(2) 5 - sage: my_vector1(3) # optional - matlab + sage: my_vector1(3) 7 Matrix indexing works as follows:: @@ -159,10 +164,11 @@ class Matlab(Expect): EXAMPLES:: - sage: a = matlab('[ 1, 1, 2; 3, 5, 8; 13, 21, 33 ]') # optional - matlab - sage: b = matlab('[ 1; 3; 13]') # optional - matlab - sage: c = a * b # optional - matlab - sage: print(c) # optional - matlab + sage: # optional - matlab + sage: a = matlab('[ 1, 1, 2; 3, 5, 8; 13, 21, 33 ]') + sage: b = matlab('[ 1; 3; 13]') + sage: c = a * b + sage: print(c) 30 122 505 @@ -328,12 +334,13 @@ def _matrix_(self, R): EXAMPLES:: - sage: A = matlab('[1,2;3,4]') # optional - matlab - sage: matrix(ZZ, A) # optional - matlab + sage: # optional - matlab + sage: A = matlab('[1,2;3,4]') + sage: matrix(ZZ, A) [1 2] [3 4] - sage: A = matlab('[1,2;3,4.5]') # optional - matlab - sage: matrix(RR, A) # optional - matlab + sage: A = matlab('[1,2;3,4.5]') + sage: matrix(RR, A) [1.00000000000000 2.00000000000000] [3.00000000000000 4.50000000000000] diff --git a/src/sage/interfaces/mupad.py b/src/sage/interfaces/mupad.py index 956de696806..82920a9edaa 100644 --- a/src/sage/interfaces/mupad.py +++ b/src/sage/interfaces/mupad.py @@ -13,23 +13,25 @@ TESTS:: - sage: mupad.package('"MuPAD-Combinat"') # optional - mupad - sage: combinat = mupad.combinat # optional - mupad - sage: examples = mupad.examples # optional - mupad - sage: S = examples.SymmetricFunctions() # optional - mupad - sage: S.s[2,1]^2 # optional - mupad + sage: # optional - mupad + sage: mupad.package('"MuPAD-Combinat"') + sage: combinat = mupad.combinat + sage: examples = mupad.examples + sage: S = examples.SymmetricFunctions() + sage: S.s[2,1]^2 s[3, 3] + s[4, 2] + s[2, 2, 1, 1] + s[2, 2, 2] + 2 s[3, 2, 1] + s[4, 1, 1] + s[3, 1, 1, 1] - sage: S.omega( S.s[3] ) # optional - mupad + sage: S.omega( S.s[3] ) s[1, 1, 1] - sage: s = S.s # optional - mupad - sage: p = S.p # optional - mupad - sage: s(s[2,1] + p[2,1]) # optional - mupad + sage: s = S.s + sage: p = S.p + sage: s(s[2,1] + p[2,1]) s[2, 1] + s[3] - s[1, 1, 1] - sage: s(_) # optional - mupad + sage: s(_) s[2, 1] + s[3] - s[1, 1, 1] - sage: combinat.tableaux.list(3) # optional - mupad # note: the order of the result seems to depend on the version of MuPAD / MuPAD-Combinat + sage: # optional - mupad + sage: combinat.tableaux.list(3) -- +---+ -- | | 3 | | | +---+ +---+ +---+ | @@ -37,8 +39,8 @@ | +---+---+---+ +---+---+ +---+---+ +---+ | | | 1 | 2 | 3 |, | 1 | 2 |, | 1 | 3 |, | 1 | | -- +---+---+---+ +---+---+ +---+---+ +---+ -- - sage: three = mupad(3) # optional - mupad - sage: three.combinat.tableaux.list() # optional - mupad + sage: three = mupad(3) + sage: three.combinat.tableaux.list() -- +---+ -- | | 3 | | | +---+ +---+ +---+ | @@ -46,12 +48,12 @@ | +---+---+---+ +---+---+ +---+---+ +---+ | | | 1 | 2 | 3 |, | 1 | 2 |, | 1 | 3 |, | 1 | | -- +---+---+---+ +---+---+ +---+---+ +---+ -- - sage: t = _[1] # optional - mupad - sage: t # optional - mupad + sage: t = _[1] + sage: t +---+---+---+ | 1 | 2 | 3 | +---+---+---+ - sage: combinat.tableaux.conjugate(t) # optional - mupad + sage: combinat.tableaux.conjugate(t) +---+ | 3 | +---+ @@ -60,21 +62,22 @@ | 1 | +---+ - sage: combinat.ribbonsTableaux.list([2,2],[1,1],2) # optional - mupad + sage: # optional - mupad + sage: combinat.ribbonsTableaux.list([2,2],[1,1],2) -- +---+---+ +---+---+ -- | | | 2 | | 2 | | | + + +, +---+---+ | | | 1 | | | 1 | | -- +---+---+ +---+---+ -- - sage: combinat.tableaux.kAtom([2,1],3) # optional - mupad + sage: combinat.tableaux.kAtom([2,1],3) -- +---+ -- | | 2 | | | +---+---+ | | | 1 | 1 | | -- +---+---+ -- - sage: M = S.Macdonald() # optional - mupad - sage: a = M.P[1]^2 # optional - mupad - sage: mupad.mapcoeffs(a, 'normal') # optional - mupad + sage: M = S.Macdonald() + sage: a = M.P[1]^2 + sage: mupad.mapcoeffs(a, 'normal') q - t + q t - 1 P[2] + --------------- P[1, 1] q t - 1 @@ -491,13 +494,14 @@ def __getattr__(self, attrname): """ EXAMPLES:: - sage: mupad.package('"MuPAD-Combinat"') # optional - mupad-Combinat - sage: combinat = mupad.combinat # optional - mupad-Combinat - sage: three = mupad(3) # optional - mupad-Combinat - sage: type(three.combinat) # optional - mupad-Combinat + sage: # optional - mupad + sage: mupad.package('"MuPAD-Combinat"') + sage: combinat = mupad.combinat + sage: three = mupad(3) + sage: type(three.combinat) - sage: tableaux = three.combinat.tableaux # optional - mupad-Combinat - sage: type(tableaux) # optional - mupad-Combinat + sage: tableaux = three.combinat.tableaux + sage: type(tableaux) """ P = self._obj.parent() @@ -528,13 +532,14 @@ def __call__(self, *args): """ EXAMPLES:: - sage: mupad.package('"MuPAD-Combinat"') # optional - mupad-Combinat - sage: combinat = mupad.combinat # optional - mupad-Combinat - sage: examples = mupad.examples # optional - mupad-Combinat - sage: S = examples.SymmetricFunctions() # optional - mupad-Combinat - sage: type(S.omega) # optional - mupad-Combinat + sage: # optional - mupad + sage: mupad.package('"MuPAD-Combinat"') + sage: combinat = mupad.combinat + sage: examples = mupad.examples + sage: S = examples.SymmetricFunctions() + sage: type(S.omega) - sage: S.omega(S.s[3]) # optional - mupad-Combinat + sage: S.omega(S.s[3]) s[1, 1, 1] """ P = self._obj.parent() @@ -551,11 +556,12 @@ def __getattr__(self, attrname): """ EXAMPLES:: - sage: mupad.package('"MuPAD-Combinat"') # optional - mupad-Combinat - sage: S = mupad.examples.SymmetricFunctions() # optional - mupad-Combinat - sage: type(S) # optional - mupad-Combinat + sage: # optional - mupad + sage: mupad.package('"MuPAD-Combinat"') + sage: S = mupad.examples.SymmetricFunctions() + sage: type(S) - sage: S.s # optional - mupad-Combinat + sage: S.s (examples::SymmetricFunctions(Dom::ExpressionField()))::s sage: x = mupad('x') # optional - mupad-Combinat diff --git a/src/sage/interfaces/octave.py b/src/sage/interfaces/octave.py index d0f5694c8bc..10e8457aa0f 100644 --- a/src/sage/interfaces/octave.py +++ b/src/sage/interfaces/octave.py @@ -60,31 +60,32 @@ :: - sage: octave("airy(3,2)") # optional - octave + sage: # optional - octave + sage: octave("airy(3,2)") 4.10068 - sage: octave("beta(2,2)") # optional - octave + sage: octave("beta(2,2)") 0.166667 - sage: octave("betainc(0.2,2,2)") # optional - octave + sage: octave("betainc(0.2,2,2)") 0.104 - sage: octave("besselh(0,2)") # optional - octave + sage: octave("besselh(0,2)") (0.223891,0.510376) - sage: octave("besselh(0,1)") # optional - octave + sage: octave("besselh(0,1)") (0.765198,0.088257) - sage: octave("besseli(1,2)") # optional - octave + sage: octave("besseli(1,2)") 1.59064 - sage: octave("besselj(1,2)") # optional - octave + sage: octave("besselj(1,2)") 0.576725 - sage: octave("besselk(1,2)") # optional - octave + sage: octave("besselk(1,2)") 0.139866 - sage: octave("erf(0)") # optional - octave + sage: octave("erf(0)") 0 - sage: octave("erf(1)") # optional - octave + sage: octave("erf(1)") 0.842701 - sage: octave("erfinv(0.842)") # optional - octave + sage: octave("erfinv(0.842)") 0.998315 - sage: octave("gamma(1.5)") # optional - octave + sage: octave("gamma(1.5)") 0.886227 - sage: octave("gammainc(1.5,1)") # optional - octave + sage: octave("gammainc(1.5,1)") 0.77687 Tutorial @@ -92,37 +93,39 @@ EXAMPLES:: - sage: octave('4+10') # optional - octave + sage: # optional - octave + sage: octave('4+10') 14 - sage: octave('date') # optional - octave; random output + sage: octave('date') 18-Oct-2007 - sage: octave('5*10 + 6') # optional - octave + sage: octave('5*10 + 6') 56 - sage: octave('(6+6)/3') # optional - octave + sage: octave('(6+6)/3') 4 - sage: octave('9')^2 # optional - octave + sage: octave('9')^2 81 - sage: a = octave(10); b = octave(20); c = octave(30) # optional - octave - sage: avg = (a+b+c)/3 # optional - octave - sage: avg # optional - octave + sage: a = octave(10); b = octave(20); c = octave(30) + sage: avg = (a+b+c)/3 + sage: avg 20 - sage: parent(avg) # optional - octave + sage: parent(avg) Octave :: - sage: my_scalar = octave('3.1415') # optional - octave - sage: my_scalar # optional - octave + sage: # optional - octave + sage: my_scalar = octave('3.1415') + sage: my_scalar 3.1415 - sage: my_vector1 = octave('[1,5,7]') # optional - octave - sage: my_vector1 # optional - octave + sage: my_vector1 = octave('[1,5,7]') + sage: my_vector1 1 5 7 - sage: my_vector2 = octave('[1;5;7]') # optional - octave - sage: my_vector2 # optional - octave + sage: my_vector2 = octave('[1;5;7]') + sage: my_vector2 1 5 7 - sage: my_vector1 * my_vector2 # optional - octave + sage: my_vector1 * my_vector2 75 """ @@ -356,11 +359,12 @@ def _start(self): EXAMPLES:: - sage: o = Octave() # optional - octave - sage: o.is_running() # optional - octave + sage: # optional - octave + sage: o = Octave() + sage: o.is_running() False - sage: o._start() # optional - octave - sage: o.is_running() # optional - octave + sage: o._start() + sage: o.is_running() True """ Expect._start(self) @@ -647,13 +651,14 @@ def __bool__(self): EXAMPLES:: - sage: bool(octave('0')) # optional - octave + sage: # optional - octave + sage: bool(octave('0')) False - sage: bool(octave('[]')) # optional - octave + sage: bool(octave('[]')) False - sage: bool(octave('[0,0]')) # optional - octave + sage: bool(octave('[0,0]')) False - sage: bool(octave('[0,0,0;0,0,0]')) # optional - octave + sage: bool(octave('[0,0,0;0,0,0]')) False sage: bool(octave('0.1')) # optional - octave @@ -685,12 +690,13 @@ def _matrix_(self, R=None): sage: _.base_ring() # optional - octave Complex Double Field - sage: A = octave('[1,2;3,4]') # optional - octave - sage: matrix(ZZ, A) # optional - octave + sage: # optional - octave + sage: A = octave('[1,2;3,4]') + sage: matrix(ZZ, A) [1 2] [3 4] - sage: A = octave('[1,2;3,4.5]') # optional - octave - sage: matrix(RR, A) # optional - octave + sage: A = octave('[1,2;3,4.5]') + sage: matrix(RR, A) [1.00000000000000 2.00000000000000] [3.00000000000000 4.50000000000000] """ @@ -716,14 +722,15 @@ def _vector_(self, R=None): EXAMPLES:: - sage: A = octave('[1,2,3,4]') # optional - octave - sage: vector(ZZ, A) # optional - octave + sage: # optional - octave + sage: A = octave('[1,2,3,4]') + sage: vector(ZZ, A) (1, 2, 3, 4) - sage: A = octave('[1,2.3,4.5]') # optional - octave - sage: vector(A) # optional - octave + sage: A = octave('[1,2.3,4.5]') + sage: vector(A) (1.0, 2.3, 4.5) - sage: A = octave('[1,I]') # optional - octave - sage: vector(A) # optional - octave + sage: A = octave('[1,I]') + sage: vector(A) (1.0, 1.0*I) """ from sage.modules.free_module import FreeModule @@ -780,23 +787,24 @@ def _sage_(self): EXAMPLES:: - sage: A = octave('2833') # optional - octave - sage: A.sage() # optional - octave + sage: # optional - octave + sage: A = octave('2833') + sage: A.sage() 2833.0 - sage: B = sqrt(A) # optional - octave - sage: B.sage() # optional - octave + sage: B = sqrt(A) + sage: B.sage() 53.2259 - sage: C = sqrt(-A) # optional - octave - sage: C.sage() # optional - octave + sage: C = sqrt(-A) + sage: C.sage() 53.2259*I - sage: A = octave('[1,2,3,4]') # optional - octave - sage: A.sage() # optional - octave + sage: A = octave('[1,2,3,4]') + sage: A.sage() (1.0, 2.0, 3.0, 4.0) - sage: A = octave('[1,2.3,4.5]') # optional - octave - sage: A.sage() # optional - octave + sage: A = octave('[1,2.3,4.5]') + sage: A.sage() (1.0, 2.3, 4.5) - sage: A = octave('[1,2.3+I,4.5]') # optional - octave - sage: A.sage() # optional - octave + sage: A = octave('[1,2.3+I,4.5]') + sage: A.sage() (1.0, 2.3 + 1.0*I, 4.5) """ if self.isscalar(): diff --git a/src/sage/interfaces/polymake.py b/src/sage/interfaces/polymake.py index 9161ebd5377..3875ff7962e 100644 --- a/src/sage/interfaces/polymake.py +++ b/src/sage/interfaces/polymake.py @@ -243,15 +243,16 @@ def _function_call_string(self, function, args, kwds): EXAMPLES:: - sage: polymake._function_call_string('cube', ['2','7','3'], ['group=>1']) # optional - jupymake + sage: # optional - jupymake + sage: polymake._function_call_string('cube', ['2','7','3'], ['group=>1']) 'cube(2,7,3, group=>1);' - sage: c = polymake('cube(2,7,3, group=>1)') # optional - jupymake - sage: c.VERTICES # optional - jupymake + sage: c = polymake('cube(2,7,3, group=>1)') + sage: c.VERTICES 1 3 3 1 7 3 1 3 7 1 7 7 - sage: c.GROUP # optional - jupymake + sage: c.GROUP full combinatorial group """ @@ -461,13 +462,14 @@ def clear(self, var): TESTS:: - sage: c = polymake.cube(15) # optional - jupymake - sage: polymake._available_vars = [] # optional - jupymake - sage: old = c._name # optional - jupymake - sage: del c # optional - jupymake # indirect doctest - sage: len(polymake._available_vars) # optional - jupymake + sage: # optional - jupymake + sage: c = polymake.cube(15) + sage: polymake._available_vars = [] + sage: old = c._name + sage: del c + sage: len(polymake._available_vars) 1 - sage: polymake._next_var_name() in old # optional - jupymake + sage: polymake._next_var_name() in old True """ @@ -500,13 +502,14 @@ def _create(self, value, name=None): EXAMPLES:: - sage: polymake._create("('foo', 'bar')", name="my_array") # optional - jupymake + sage: # optional - jupymake + sage: polymake._create("('foo', 'bar')", name="my_array") '@my_array' - sage: print(polymake.eval('print join(", ", @my_array);')) # optional - jupymake + sage: print(polymake.eval('print join(", ", @my_array);')) foo, bar - sage: polymake._create('"foobar"', name="my_string") # optional - jupymake + sage: polymake._create('"foobar"', name="my_string") '$my_string[0]' - sage: print(polymake.eval('print $my_string[0];')) # optional - jupymake + sage: print(polymake.eval('print $my_string[0];')) foobar """ @@ -743,20 +746,22 @@ def application(self, app): terms of inequalities. Polymake knows to compute the f- and h-vector and finds that the polytope is very ample:: - sage: q = polymake.new_object("Polytope", INEQUALITIES=[[5,-4,0,1],[-3,0,-4,1],[-2,1,0,0],[-4,4,4,-1],[0,0,1,0],[8,0,0,-1],[1,0,-1,0],[3,-1,0,0]]) # optional - jupymake - sage: q.H_VECTOR # optional - jupymake + sage: # optional - jupymake + sage: q = polymake.new_object("Polytope", INEQUALITIES=[[5,-4,0,1],[-3,0,-4,1],[-2,1,0,0],[-4,4,4,-1],[0,0,1,0],[8,0,0,-1],[1,0,-1,0],[3,-1,0,0]]) + sage: q.H_VECTOR 1 5 5 1 - sage: q.F_VECTOR # optional - jupymake + sage: q.F_VECTOR 8 14 8 - sage: q.VERY_AMPLE # optional - jupymake + sage: q.VERY_AMPLE true In the application 'fan', polymake can now compute the normal fan of `q` and its (primitive) rays:: - sage: polymake.application('fan') # optional - jupymake - sage: g = q.normal_fan() # optional - jupymake - sage: g.RAYS # optional - jupymake + sage: # optional - jupymake + sage: polymake.application('fan') + sage: g = q.normal_fan() + sage: g.RAYS -1 0 1/4 0 -1 1/4 1 0 0 @@ -765,7 +770,7 @@ def application(self, app): 0 0 -1 0 -1 0 -1 0 0 - sage: g.RAYS.primitive() # optional - jupymake + sage: g.RAYS.primitive() -4 0 1 0 -4 1 1 0 0 @@ -784,14 +789,15 @@ def application(self, app): but only in 'tropical', the following shows the effect of changing the application. :: - sage: polymake.application('polytope') # optional - jupymake - sage: 'trop_witness' in dir(polymake) # optional - jupymake + sage: # optional - jupymake + sage: polymake.application('polytope') + sage: 'trop_witness' in dir(polymake) False - sage: polymake.application('tropical') # optional - jupymake - sage: 'trop_witness' in dir(polymake) # optional - jupymake + sage: polymake.application('tropical') + sage: 'trop_witness' in dir(polymake) True - sage: polymake.application('polytope') # optional - jupymake - sage: 'trop_witness' in dir(polymake) # optional - jupymake + sage: polymake.application('polytope') + sage: 'trop_witness' in dir(polymake) False For completeness, we show what happens when asking for an application @@ -827,17 +833,18 @@ def new_object(self, name, *args, **kwds): EXAMPLES:: - sage: q = polymake.new_object("Polytope", INEQUALITIES=[[4,-4,0,1],[-4,0,-4,1],[-2,1,0,0],[-4,4,4,-1],[0,0,1,0],[8,0,0,-1]]) # optional - jupymake - sage: q.N_VERTICES # optional - jupymake + sage: # optional - jupymake + sage: q = polymake.new_object("Polytope", INEQUALITIES=[[4,-4,0,1],[-4,0,-4,1],[-2,1,0,0],[-4,4,4,-1],[0,0,1,0],[8,0,0,-1]]) + sage: q.N_VERTICES 4 - sage: q.BOUNDED # optional - jupymake + sage: q.BOUNDED true - sage: q.VERTICES # optional - jupymake + sage: q.VERTICES 1 2 0 4 1 3 0 8 1 2 1 8 1 3 1 8 - sage: q.full_typename() # optional - jupymake + sage: q.full_typename() 'Polytope' """ @@ -885,11 +892,12 @@ def _repr_(self): of the object that is not longer than single line, it is used for printing:: - sage: p = polymake.rand_sphere(3, 12, seed=15) # optional - jupymake - sage: p # optional - jupymake + sage: # optional - jupymake + sage: p = polymake.rand_sphere(3, 12, seed=15) + sage: p Random spherical polytope of dimension 3; seed=15... - sage: c = polymake.cube(4) # optional - jupymake - sage: c # optional - jupymake + sage: c = polymake.cube(4) + sage: c cube of dimension 4 We use the print representation of scalars to display scalars:: @@ -924,11 +932,12 @@ def _repr_(self): Similarly, polymake matrices and vectors are explicitly listed:: - sage: c.VERTICES.typename() # optional - jupymake + sage: # optional - jupymake + sage: c.VERTICES.typename() 'Matrix' - sage: c.VERTICES[0].typename() # optional - jupymake + sage: c.VERTICES[0].typename() 'Vector' - sage: c.VERTICES # optional - jupymake # random + sage: c.VERTICES 1 -1 -1 -1 -1 1 1 -1 -1 -1 1 -1 1 -1 -1 @@ -945,7 +954,7 @@ def _repr_(self): 1 1 -1 1 1 1 -1 1 1 1 1 1 1 1 1 - sage: c.VERTICES[0] # optional - jupymake + sage: c.VERTICES[0] 1 -1 -1 -1 -1 For other types, we simply use the print representation offered @@ -1225,34 +1234,37 @@ def __getattr__(self, attrname): A property:: - sage: c = polymake.cube(3) # optional - jupymake - sage: c.H_VECTOR # optional - jupymake + sage: # optional - jupymake + sage: c = polymake.cube(3) + sage: c.H_VECTOR 1 5 5 1 - sage: c.N_VERTICES # optional - jupymake + sage: c.N_VERTICES 8 - sage: d = polymake.cross(3) # optional - jupymake - sage: d.N_VERTICES # optional - jupymake + sage: d = polymake.cross(3) + sage: d.N_VERTICES 6 A function:: - sage: c.minkowski_sum_fukuda # optional - jupymake + sage: # optional - jupymake + sage: c.minkowski_sum_fukuda minkowski_sum_fukuda (bound to Polymake::polytope::Polytope__Rational object) - sage: s = c.minkowski_sum_fukuda(d) # optional - jupymake - sage: s.N_VERTICES # optional - jupymake + sage: s = c.minkowski_sum_fukuda(d) + sage: s.N_VERTICES 24 - sage: s # optional - jupymake + sage: s Polytope[SAGE...] A member function:: - sage: c = polymake.cube(2) # optional - jupymake - sage: V = polymake.new_object('Vector', [1,0,0]) # optional - jupymake - sage: V # optional - jupymake + sage: # optional - jupymake + sage: c = polymake.cube(2) + sage: V = polymake.new_object('Vector', [1,0,0]) + sage: V 1 0 0 - sage: c.contains # optional - jupymake + sage: c.contains Member function 'contains' of Polymake::polytope::Polytope__Rational object - sage: c.contains(V) # optional - jupymake + sage: c.contains(V) true """ @@ -1281,13 +1293,14 @@ def get_member_function(self, attrname): EXAMPLES:: - sage: c = polymake.cube(2) # optional - jupymake - sage: c.contains # optional - jupymake + sage: # optional - jupymake + sage: c = polymake.cube(2) + sage: c.contains Member function 'contains' of Polymake::polytope::Polytope__Rational object - sage: V = polymake.new_object('Vector', [1,0,0]) # optional - jupymake - sage: V # optional - jupymake + sage: V = polymake.new_object('Vector', [1,0,0]) + sage: V 1 0 0 - sage: c.contains(V) # optional - jupymake + sage: c.contains(V) true Whether a member function of the given name actually exists for that @@ -1438,12 +1451,13 @@ def typeof(self): EXAMPLES:: - sage: p = polymake.rand_sphere(3, 13, seed=12) # optional - jupymake - sage: p.typeof() # optional - jupymake + sage: # optional - jupymake + sage: p = polymake.rand_sphere(3, 13, seed=12) + sage: p.typeof() ('Polymake::polytope::Polytope__Rational', 'ARRAY') - sage: p.VERTICES.typeof() # optional - jupymake + sage: p.VERTICES.typeof() ('Polymake::common::Matrix_A_Rational_I_NonSymmetric_Z', 'ARRAY') - sage: p.get_schedule('"F_VECTOR"').typeof() # optional - jupymake + sage: p.get_schedule('"F_VECTOR"').typeof() ('Polymake::Core::Scheduler::RuleChain', 'ARRAY') On "small" objects, it just returns empty strings:: @@ -1666,13 +1680,14 @@ class PolymakeFunctionElement(InterfaceFunctionElement): EXAMPLES:: - sage: c = polymake.cube(2) # optional - jupymake - sage: V = polymake.new_object('Vector', [1,0,0]) # optional - jupymake - sage: V # optional - jupymake + sage: # optional - jupymake + sage: c = polymake.cube(2) + sage: V = polymake.new_object('Vector', [1,0,0]) + sage: V 1 0 0 - sage: c.contains # optional - jupymake + sage: c.contains Member function 'contains' of Polymake::polytope::Polytope__Rational object - sage: c.contains(V) # optional - jupymake + sage: c.contains(V) true """ @@ -1840,16 +1855,17 @@ class PolymakeJuPyMake(PolymakeAbstract): :: - sage: L = polymake.db_query({'"_id"': '"F.4D.0047"'}, # long time, optional - jupymake internet perl_mongodb + sage: # long time, optional - internet jupymake perl_mongodb + sage: L = polymake.db_query({'"_id"': '"F.4D.0047"'}, ....: db='"LatticePolytopes"', ....: collection='"SmoothReflexive"'); L BigObjectArray - sage: len(L) # long time, optional - jupymake internet perl_mongodb + sage: len(L) 1 - sage: P = L[0] # long time, optional - jupymake internet perl_mongodb - sage: sorted(P.list_properties(), key=str) # long time, optional - jupymake internet perl_mongodb + sage: P = L[0] + sage: sorted(P.list_properties(), key=str) [..., LATTICE_POINTS_GENERATORS, ..., POINTED, ...] - sage: P.F_VECTOR # long time, optional - jupymake internet perl_mongodb + sage: P.F_VECTOR 20 40 29 9 """ diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py index b6b657515bc..5a69861eec8 100644 --- a/src/sage/interfaces/qepcad.py +++ b/src/sage/interfaces/qepcad.py @@ -404,13 +404,14 @@ A :class:`QepcadCell` has accessor methods for the important state held within a cell. For instance:: - sage: c.level() # optional - qepcad + sage: # optional - qepcad + sage: c.level() 2 - sage: c.index() # optional - qepcad + sage: c.index() (3, 4) - sage: qe.cell(3).number_of_children() # optional - qepcad + sage: qe.cell(3).number_of_children() 5 - sage: len(qe.cell(3)) # optional - qepcad + sage: len(qe.cell(3)) 5 One particularly useful thing we can get from a cell is its sample point, @@ -574,19 +575,20 @@ sage: _qepcad_atoms(qepcad(F, solution='extended')) # optional - qepcad {'x > _root_1 2 x^2 - 3', 'x^2 - 3 <= 0'} - sage: qe = qepcad(qf.and_(ellipse == 0, circle == 0), interact=True) # optional - qepcad - sage: qe.go(); qe.go(); qe.go() # optional - qepcad + sage: # optional - qepcad + sage: qe = qepcad(qf.and_(ellipse == 0, circle == 0), interact=True) + sage: qe.go(); qe.go(); qe.go() QEPCAD object has moved to phase 'Before Projection (y)' QEPCAD object has moved to phase 'Before Choice' QEPCAD object has moved to phase 'Before Solution' - sage: for c in qe.cell(): # optional - qepcad + sage: for c in qe.cell(): ....: count_ellipse = 0 ....: count_circle = 0 ....: for c2 in c: ....: count_ellipse += (c2.signs()[1][0] == 0) ....: count_circle += (c2.signs()[1][1] == 0) ....: c.set_truth(count_ellipse == 2 and count_circle == 2) - sage: _qepcad_atoms(qe.solution_extension('G')) # optional - qepcad + sage: _qepcad_atoms(qe.solution_extension('G')) {'8 x^2 - 8 x - 29 < 0', 'x^2 - 3 < 0'} @@ -1044,24 +1046,25 @@ def phase(self): EXAMPLES:: - sage: qe = qepcad(x > 2/3, interact=True) # optional - qepcad - sage: qe.phase() # optional - qepcad + sage: # optional - qepcad + sage: qe = qepcad(x > 2/3, interact=True) + sage: qe.phase() 'Before Normalization' - sage: qe.go() # optional - qepcad + sage: qe.go() QEPCAD object has moved to phase 'At the end of projection phase' - sage: qe.phase() # optional - qepcad + sage: qe.phase() 'At the end of projection phase' - sage: qe.go() # optional - qepcad + sage: qe.go() QEPCAD object has moved to phase 'Before Choice' - sage: qe.phase() # optional - qepcad + sage: qe.phase() 'Before Choice' - sage: qe.go() # optional - qepcad + sage: qe.go() QEPCAD object has moved to phase 'Before Solution' - sage: qe.phase() # optional - qepcad + sage: qe.phase() 'Before Solution' - sage: qe.go() # optional - qepcad + sage: qe.go() 3 x - 2 > 0 - sage: qe.phase() # optional - qepcad + sage: qe.phase() 'EXITED' """ match = self._qex.expect().match @@ -1079,13 +1082,14 @@ def _parse_answer_stats(self): EXAMPLES:: - sage: qe = qepcad(x^2 > 2, interact=True) # optional - qepcad - sage: qe.finish() # optional - qepcad + sage: # optional - qepcad + sage: qe = qepcad(x^2 > 2, interact=True) + sage: qe.finish() x^2 - 2 > 0 - sage: (ans, stats) = qe._parse_answer_stats() # optional - qepcad - sage: ans # optional - qepcad + sage: (ans, stats) = qe._parse_answer_stats() + sage: ans 'x^2 - 2 > 0' - sage: stats # random, optional - qepcad + sage: stats '-----------------------------------------------------------------------------\r\n0 Garbage collections, 0 Cells and 0 Arrays reclaimed, in 0 milliseconds.\r\n492514 Cells in AVAIL, 500000 Cells in SPACE.\r\n\r\nSystem time: 16 milliseconds.\r\nSystem time after the initialization: 4 milliseconds.\r\n-----------------------------------------------------------------------------\r\n' """ if self.phase() != 'EXITED': @@ -1168,14 +1172,15 @@ def cell(self, *index): EXAMPLES:: - sage: qe = qepcad(x + 3 == 42, interact=True) # optional - qepcad - sage: qe.go(); qe.go(); qe.go() # optional - qepcad + sage: # optional - qepcad + sage: qe = qepcad(x + 3 == 42, interact=True) + sage: qe.go(); qe.go(); qe.go() QEPCAD object has moved to phase 'At the end of projection phase' QEPCAD object has moved to phase 'Before Choice' QEPCAD object has moved to phase 'Before Solution' - sage: qe.cell(2) # optional - qepcad + sage: qe.cell(2) QEPCAD cell (2) - sage: qe.cell(2) is qe.cell(2) # optional - qepcad + sage: qe.cell(2) is qe.cell(2) True """ index_str = _format_cell_index(index) @@ -2696,16 +2701,17 @@ def sample_point(self): EXAMPLES:: - sage: qe = qepcad(x^2 - x - 1 == 0, interact=True) # optional - qepcad - sage: qe.go(); qe.go(); qe.go() # optional - qepcad + sage: # optional - qepcad + sage: qe = qepcad(x^2 - x - 1 == 0, interact=True) + sage: qe.go(); qe.go(); qe.go() QEPCAD object has moved to phase 'At the end of projection phase' QEPCAD object has moved to phase 'Before Choice' QEPCAD object has moved to phase 'Before Solution' - sage: v1 = qe.cell(2).sample_point()[0]; v1 # optional - qepcad + sage: v1 = qe.cell(2).sample_point()[0]; v1 -0.618033988749895? - sage: v2 = qe.cell(4).sample_point()[0]; v2 # optional - qepcad + sage: v2 = qe.cell(4).sample_point()[0]; v2 1.618033988749895? - sage: v1 + v2 == 1 # optional - qepcad + sage: v1 + v2 == 1 True """ try: diff --git a/src/sage/interfaces/rubik.py b/src/sage/interfaces/rubik.py index 109a2623c95..767c440715d 100644 --- a/src/sage/interfaces/rubik.py +++ b/src/sage/interfaces/rubik.py @@ -137,19 +137,20 @@ def solve(self, facets): EXAMPLES:: - sage: from sage.interfaces.rubik import * # optional - rubiks - sage: solver = DikSolver() # optional - rubiks - sage: solver = OptimalSolver() # optional - rubiks # long time (28s on sage.math, 2012) + sage: # optional - rubiks + sage: from sage.interfaces.rubik import * + sage: solver = DikSolver() + sage: solver = OptimalSolver() # long time (28s on sage.math, 2012) Initializing tables... Done. - sage: C = RubiksCube("R U") # optional - rubiks - sage: solver.solve(C.facets()) # optional - rubiks + sage: C = RubiksCube("R U") + sage: solver.solve(C.facets()) 'R U' - sage: C = RubiksCube("R U F L B D") # optional - rubiks - sage: solver.solve(C.facets()) # optional - rubiks + sage: C = RubiksCube("R U F L B D") + sage: solver.solve(C.facets()) 'R U F L B D' - sage: C = RubiksCube("R2 D2") # optional - rubiks - sage: solver.solve(C.facets()) # optional - rubiks + sage: C = RubiksCube("R2 D2") + sage: solver.solve(C.facets()) 'R2 D2' """ self.ready() @@ -193,21 +194,22 @@ def solve(self, facets): """ EXAMPLES:: - sage: from sage.interfaces.rubik import * # optional - rubiks - sage: C = RubiksCube("R U") # optional - rubiks - sage: CubexSolver().solve(C.facets()) # optional - rubiks + sage: # optional - rubiks + sage: from sage.interfaces.rubik import * + sage: C = RubiksCube("R U") + sage: CubexSolver().solve(C.facets()) 'R U' - sage: C = RubiksCube("R U F L B D") # optional - rubiks - sage: sol = CubexSolver().solve(C.facets()); sol # optional - rubiks + sage: C = RubiksCube("R U F L B D") + sage: sol = CubexSolver().solve(C.facets()); sol "U' L' L' U L U' L U D L L D' L' D L' D' L D L' U' L D' L' U L' B' U' L' U B L D L D' U' L' U L B L B' L' U L U' L' F' L' F L' F L F' L' D' L' D D L D' B L B' L B' L B F' L F F B' L F' B D' D' L D B' B' L' D' B U' U' L' B' D' F' F' L D F'" - sage: RubiksCube(sol) == C # optional - rubiks + sage: RubiksCube(sol) == C True - sage: C = RubiksCube("R2 F'") # optional - rubiks - sage: CubexSolver().solve(C.facets()) # optional - rubiks + sage: C = RubiksCube("R2 F'") + sage: CubexSolver().solve(C.facets()) "R' R' F'" - sage: C = RubiksCube().scramble() # optional - rubiks - sage: sol = CubexSolver().solve(C.facets()) # optional - rubiks - sage: C == RubiksCube(sol) # optional - rubiks + sage: C = RubiksCube().scramble() + sage: sol = CubexSolver().solve(C.facets()) + sage: C == RubiksCube(sol) True """ s = self.format_cube(facets) @@ -245,15 +247,16 @@ def solve(self, facets, timeout=10, extra_time=2): """ EXAMPLES:: - sage: from sage.interfaces.rubik import * # optional - rubiks - sage: C = RubiksCube().move("R U") # optional - rubiks - sage: DikSolver().solve(C.facets()) # optional - rubiks + sage: # optional - rubiks + sage: from sage.interfaces.rubik import * + sage: C = RubiksCube().move("R U") + sage: DikSolver().solve(C.facets()) 'R U' - sage: C = RubiksCube().move("R U F L B D") # optional - rubiks - sage: DikSolver().solve(C.facets()) # optional - rubiks + sage: C = RubiksCube().move("R U F L B D") + sage: DikSolver().solve(C.facets()) 'R U F L B D' - sage: C = RubiksCube().move("R2 F'") # optional - rubiks - sage: DikSolver().solve(C.facets()) # optional - rubiks + sage: C = RubiksCube().move("R2 F'") + sage: DikSolver().solve(C.facets()) "R2 F'" """ cube_str = self.format_cube(facets) diff --git a/src/sage/interfaces/scilab.py b/src/sage/interfaces/scilab.py index 54c28f55598..b1fd5c1d983 100644 --- a/src/sage/interfaces/scilab.py +++ b/src/sage/interfaces/scilab.py @@ -15,60 +15,65 @@ EXAMPLES:: - sage: scilab.eval('2+2') # optional - scilab + sage: # optional - scilab + sage: scilab.eval('2+2') 'ans =\n \n 4.' - sage: scilab('2+2') # optional - scilab + sage: scilab('2+2') 4. - sage: a = scilab(10) # optional - scilab - sage: a**10 # optional - scilab + sage: a = scilab(10) + sage: a**10 1.000D+10 Tutorial based the MATLAB interface tutorial: EXAMPLES:: - sage: scilab('4+10') # optional - scilab + sage: # optional - scilab + sage: scilab('4+10') 14. - sage: scilab('date') # optional - scilab; random output + sage: scilab('date') 15-Feb-2010 - sage: scilab('5*10 + 6') # optional - scilab + sage: scilab('5*10 + 6') 56. - sage: scilab('(6+6)/3') # optional - scilab + sage: scilab('(6+6)/3') 4. - sage: scilab('9')^2 # optional - scilab + sage: scilab('9')^2 81. - sage: a = scilab(10); b = scilab(20); c = scilab(30) # optional - scilab - sage: avg = (a+b+c)/3 # optional - scilab - sage: avg # optional - scilab + sage: a = scilab(10); b = scilab(20); c = scilab(30) + sage: avg = (a+b+c)/3 + sage: avg 20. - sage: parent(avg) # optional - scilab + sage: parent(avg) Scilab - sage: my_scalar = scilab('3.1415') # optional - scilab - sage: my_scalar # optional - scilab + sage: # optional - scilab + sage: my_scalar = scilab('3.1415') + sage: my_scalar 3.1415 - sage: my_vector1 = scilab('[1,5,7]') # optional - scilab - sage: my_vector1 # optional - scilab + sage: my_vector1 = scilab('[1,5,7]') + sage: my_vector1 1. 5. 7. - sage: my_vector2 = scilab('[1;5;7]') # optional - scilab - sage: my_vector2 # optional - scilab + sage: my_vector2 = scilab('[1;5;7]') + sage: my_vector2 1. 5. 7. - sage: my_vector1 * my_vector2 # optional - scilab + sage: my_vector1 * my_vector2 75. - sage: row_vector1 = scilab('[1 2 3]') # optional - scilab - sage: row_vector2 = scilab('[3 2 1]') # optional - scilab - sage: matrix_from_row_vec = scilab('[%s; %s]'%(row_vector1.name(), row_vector2.name())) # optional - scilab - sage: matrix_from_row_vec # optional - scilab + sage: # optional - scilab + sage: row_vector1 = scilab('[1 2 3]') + sage: row_vector2 = scilab('[3 2 1]') + sage: matrix_from_row_vec = scilab('[%s; %s]'%(row_vector1.name(), row_vector2.name())) + sage: matrix_from_row_vec 1. 2. 3. 3. 2. 1. - sage: column_vector1 = scilab('[1;3]') # optional - scilab - sage: column_vector2 = scilab('[2;8]') # optional - scilab - sage: matrix_from_col_vec = scilab('[%s %s]'%(column_vector1.name(), column_vector2.name())) # optional - scilab - sage: matrix_from_col_vec # optional - scilab + sage: # optional - scilab + sage: column_vector1 = scilab('[1;3]') + sage: column_vector2 = scilab('[2;8]') + sage: matrix_from_col_vec = scilab('[%s %s]'%(column_vector1.name(), column_vector2.name())) + sage: matrix_from_col_vec 1. 2. 3. 8. @@ -90,12 +95,13 @@ sage: tm # optional - scilab 0.5 2.5 4.5 6.5 8.5 - sage: my_vector1 = scilab('[1,5,7]') # optional - scilab - sage: my_vector1(1) # optional - scilab + sage: # optional - scilab + sage: my_vector1 = scilab('[1,5,7]') + sage: my_vector1(1) 1. - sage: my_vector1(2) # optional - scilab + sage: my_vector1(2) 5. - sage: my_vector1(3) # optional - scilab + sage: my_vector1(3) 7. Matrix indexing works as follows:: @@ -113,15 +119,16 @@ Setting using parenthesis cannot work (because of how the Python language works). Use square brackets or the set function:: - sage: my_matrix = scilab('[8, 12, 19; 7, 3, 2; 12, 4, 23; 8, 1, 1]') # optional - scilab - sage: my_matrix.set(2,3, 1999) # optional - scilab - sage: my_matrix # optional - scilab + sage: # optional - scilab + sage: my_matrix = scilab('[8, 12, 19; 7, 3, 2; 12, 4, 23; 8, 1, 1]') + sage: my_matrix.set(2,3, 1999) + sage: my_matrix 8. 12. 19. 7. 3. 1999. 12. 4. 23. 8. 1. 1. - sage: my_matrix[2,3] = -126 # optional - scilab - sage: my_matrix # optional - scilab + sage: my_matrix[2,3] = -126 + sage: my_matrix 8. 12. 19. 7. 3. - 126. 12. 4. 23. @@ -129,39 +136,40 @@ TESTS:: - sage: M = scilab(x) # optional - scilab + sage: # optional - scilab + sage: M = scilab(x) Traceback (most recent call last): ... TypeError: ..._interface_init_() takes exactly one argument (0 given) - sage: M = scilab(matrix(3,range(9))); M # optional - scilab + sage: M = scilab(matrix(3,range(9))); M 0. 1. 2. 3. 4. 5. 6. 7. 8. - sage: M(10) # optional - scilab + sage: M(10) Traceback (most recent call last): ... TypeError: Error executing code in Scilab ... Invalid index. - sage: M[10] # optional - scilab + sage: M[10] Traceback (most recent call last): ... TypeError: Error executing code in Scilab ... Invalid index. - sage: M(4,2) # optional - scilab + sage: M(4,2) Traceback (most recent call last): ... TypeError: Error executing code in Scilab ... Invalid index. - sage: M[2,4] # optional - scilab + sage: M[2,4] Traceback (most recent call last): ... TypeError: Error executing code in Scilab ... Invalid index. - sage: M(9) = x # optional - scilab + sage: M(9) = x Traceback (most recent call last): ... SyntaxError: can...t assign to function call (..., line 1) @@ -199,10 +207,11 @@ class Scilab(Expect): EXAMPLES:: - sage: a = scilab('[ 1, 1, 2; 3, 5, 8; 13, 21, 33 ]') # optional - scilab - sage: b = scilab('[ 1; 3; 13]') # optional - scilab - sage: c = a * b # optional - scilab - sage: print(c) # optional - scilab + sage: # optional - scilab + sage: a = scilab('[ 1, 1, 2; 3, 5, 8; 13, 21, 33 ]') + sage: b = scilab('[ 1; 3; 13]') + sage: c = a * b + sage: print(c) 30. 122. 505. @@ -433,12 +442,13 @@ def __getitem__(self, n): EXAMPLES:: - sage: M = scilab('[1,2,3;4,5,6;7,8,9]') # optional - scilab - sage: M[1] # optional - scilab + sage: # optional - scilab + sage: M = scilab('[1,2,3;4,5,6;7,8,9]') + sage: M[1] 1. - sage: M[7] # optional - scilab + sage: M[7] 3. - sage: M[3,2] # optional - scilab + sage: M[3,2] 8. """ if isinstance(n, tuple): @@ -453,14 +463,15 @@ def __setitem__(self, n, value): EXAMPLES:: - sage: M = scilab('[1,2,3;4,5,6;7,8,9]') # optional - scilab - sage: M[6] = 0 # optional - scilab - sage: M # optional - scilab + sage: # optional - scilab + sage: M = scilab('[1,2,3;4,5,6;7,8,9]') + sage: M[6] = 0 + sage: M 1. 2. 3. 4. 5. 6. 7. 0. 9. - sage: M[3,2] = 10 # optional - scilab - sage: M # optional - scilab + sage: M[3,2] = 10 + sage: M 1. 2. 3. 4. 5. 6. 7. 10. 9. @@ -477,12 +488,13 @@ def _matrix_(self, R): EXAMPLES:: - sage: A = scilab('[1,2;3,4]') # optional - scilab - sage: matrix(ZZ, A) # optional - scilab + sage: # optional - scilab + sage: A = scilab('[1,2;3,4]') + sage: matrix(ZZ, A) [1 2] [3 4] - sage: A = scilab('[1,2;3,4.5]') # optional - scilab - sage: matrix(RR, A) # optional - scilab + sage: A = scilab('[1,2;3,4.5]') + sage: matrix(RR, A) [1.00000000000000 2.00000000000000] [3.00000000000000 4.50000000000000] """ From 8c9b1e60712ff80fe9313f19729abc577d787719 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Sep 2023 15:31:22 -0700 Subject: [PATCH 034/155] Fix # needs for sagemath-pari --- src/sage/interfaces/gp.py | 24 +++++++++++++----------- src/sage/interfaces/macaulay2.py | 8 -------- src/sage/interfaces/maple.py | 16 ---------------- 3 files changed, 13 insertions(+), 35 deletions(-) diff --git a/src/sage/interfaces/gp.py b/src/sage/interfaces/gp.py index 6e12504e829..cfea368fc02 100644 --- a/src/sage/interfaces/gp.py +++ b/src/sage/interfaces/gp.py @@ -789,26 +789,27 @@ def new_with_bits_prec(self, s, precision=0): EXAMPLES:: - sage: pi_def = gp(pi); pi_def # needs sage.symbolic + sage: # needs sage.symbolic + sage: pi_def = gp(pi); pi_def 3.141592653589793238462643383 # 32-bit 3.1415926535897932384626433832795028842 # 64-bit - sage: pi_def.precision() # needs sage.symbolic + sage: pi_def.precision() 28 # 32-bit 38 # 64-bit - sage: pi_150 = gp.new_with_bits_prec(pi, 150) # needs sage.symbolic - sage: new_prec = pi_150.precision(); new_prec # needs sage.symbolic + sage: pi_150 = gp.new_with_bits_prec(pi, 150) + sage: new_prec = pi_150.precision(); new_prec 48 # 32-bit 57 # 64-bit - sage: old_prec = gp.set_precision(new_prec); old_prec # needs sage.symbolic + sage: old_prec = gp.set_precision(new_prec); old_prec 28 # 32-bit 38 # 64-bit - sage: pi_150 # needs sage.symbolic + sage: pi_150 3.14159265358979323846264338327950288419716939938 # 32-bit 3.14159265358979323846264338327950288419716939937510582098 # 64-bit - sage: gp.set_precision(old_prec) # needs sage.symbolic + sage: gp.set_precision(old_prec) 48 # 32-bit 57 # 64-bit - sage: gp.get_precision() # needs sage.symbolic + sage: gp.get_precision() 28 # 32-bit 38 # 64-bit """ @@ -957,11 +958,12 @@ def _complex_mpfr_field_(self, CC): EXAMPLES:: - sage: z = gp(SR(1+15*I)); z # needs sage.symbolic + sage: # needs sage.symbolic + sage: z = gp(SR(1+15*I)); z 1 + 15*I - sage: z._complex_mpfr_field_(CC) # needs sage.symbolic + sage: z._complex_mpfr_field_(CC) 1.00000000000000 + 15.0000000000000*I - sage: CC(z) # CC(gp(1+15*I)) # needs sage.symbolic + sage: CC(z) # CC(gp(1+15*I)) 1.00000000000000 + 15.0000000000000*I sage: CC(gp(11243.9812+15*I)) 11243.9812000000 + 15.0000000000000*I diff --git a/src/sage/interfaces/macaulay2.py b/src/sage/interfaces/macaulay2.py index e8a4d94d2dc..9b11f02a85f 100644 --- a/src/sage/interfaces/macaulay2.py +++ b/src/sage/interfaces/macaulay2.py @@ -496,11 +496,7 @@ def _contains(self, v1, v2): sage: 0 in a, 2 in a, 3 in a (True, True, False) sage: b = macaulay2('hashTable {"x" => 1, "y" => 2}') -<<<<<<< HEAD sage: 'x' in b, '"x"' in b # indirect doctest -======= - sage: 'x' in b, '"x"' in b ->>>>>>> a24a77aaaa1 (src/sage/interfaces: sage -fixdoctests --only-tags) (False, True) """ return self.eval("%s#?%s" % (v2, v1)) == self._true_symbol() @@ -649,11 +645,7 @@ def cputime(self, t=None): sage: R = macaulay2("QQ[x,y]") sage: x,y = R.gens() sage: a = (x+y+1)^20 -<<<<<<< HEAD sage: macaulay2.cputime() # random -======= - sage: macaulay2.cputime() ->>>>>>> a24a77aaaa1 (src/sage/interfaces: sage -fixdoctests --only-tags) 0.48393700000000001 """ _t = float(self.cpuTime()._sage_()) diff --git a/src/sage/interfaces/maple.py b/src/sage/interfaces/maple.py index 1f4f209f127..7ba21a66cf6 100644 --- a/src/sage/interfaces/maple.py +++ b/src/sage/interfaces/maple.py @@ -605,20 +605,12 @@ def cputime(self, t=None): sage: # optional - maple sage: t = maple.cputime() -<<<<<<< HEAD sage: t # random -======= - sage: t ->>>>>>> a24a77aaaa1 (src/sage/interfaces: sage -fixdoctests --only-tags) 0.02 sage: x = maple('x') sage: maple.diff(x^2, x) 2*x -<<<<<<< HEAD sage: maple.cputime(t) # random -======= - sage: maple.cputime(t) ->>>>>>> a24a77aaaa1 (src/sage/interfaces: sage -fixdoctests --only-tags) 0.0 """ if t is None: @@ -818,11 +810,7 @@ def with_package(self, package): :: sage: # optional - maple -<<<<<<< HEAD sage: maple.quit() # reset maple -======= - sage: maple.quit() ->>>>>>> a24a77aaaa1 (src/sage/interfaces: sage -fixdoctests --only-tags) sage: maple('partition(10)') partition(10) sage: maple('bell(10)') @@ -959,11 +947,7 @@ def __hash__(self): sage: # optional - maple sage: m = maple('x^2+y^2') -<<<<<<< HEAD sage: m.__hash__() # random -======= - sage: m.__hash__() ->>>>>>> a24a77aaaa1 (src/sage/interfaces: sage -fixdoctests --only-tags) 188724254834261060184983038723355865733 sage: hash(m) # random 5035731711831192733 From b3ebde679b9ca28bc811e85841206ff9ebae0370 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Sep 2023 23:46:22 -0700 Subject: [PATCH 035/155] Add # needs --- src/sage/interfaces/sympy_wrapper.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sage/interfaces/sympy_wrapper.py b/src/sage/interfaces/sympy_wrapper.py index 792d1eaee99..5ad6095a787 100644 --- a/src/sage/interfaces/sympy_wrapper.py +++ b/src/sage/interfaces/sympy_wrapper.py @@ -97,6 +97,7 @@ def is_finite_set(self): EXAMPLES:: + sage: # needs sage.graphs sage: W = WeylGroup(["A",1,1]) sage: sW = W._sympy_(); sW SageSet(Weyl Group of type ['A', 1, 1] (as a matrix group acting on the root space)) @@ -112,6 +113,7 @@ def is_iterable(self): EXAMPLES:: + sage: # needs sage.graphs sage: W = WeylGroup(["A",1,1]) sage: sW = W._sympy_(); sW SageSet(Weyl Group of type ['A', 1, 1] (as a matrix group acting on the root space)) @@ -168,6 +170,7 @@ def __len__(self): EXAMPLES:: + sage: # needs sage.graphs sage: sB3 = WeylGroup(["B", 3])._sympy_(); sB3 SageSet(Weyl Group of type ['B', 3] (as a matrix group acting on the ambient space)) sage: len(sB3) From 5e10e574fa82a6f8f06e00f7afb17451f0ecbd96 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 23 Sep 2023 11:21:51 -0700 Subject: [PATCH 036/155] Update # needs --- src/sage/interfaces/gp.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/interfaces/gp.py b/src/sage/interfaces/gp.py index cfea368fc02..4cff85207e2 100644 --- a/src/sage/interfaces/gp.py +++ b/src/sage/interfaces/gp.py @@ -887,6 +887,7 @@ def _sage_(self): :: + sage: # needs sage.modules sage: M = Matrix(ZZ,2,2,[1,2,3,4]); M [1 2] [3 4] From dd5fefdcb99ed69941c8e107ee0fa13526b59895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 7 Nov 2023 16:03:04 +0100 Subject: [PATCH 037/155] capitals to Hopf, Lie, Coxeter by appropriate mechanism --- src/sage/algebras/clifford_algebra.py | 2 +- .../algebras/lie_algebras/free_lie_algebra.py | 2 +- src/sage/algebras/lie_algebras/lie_algebra.py | 8 +++--- src/sage/algebras/lie_algebras/morphism.py | 4 +-- .../lie_algebras/nilpotent_lie_algebra.py | 2 +- src/sage/algebras/lie_algebras/quotient.py | 2 +- .../algebras/steenrod/steenrod_algebra.py | 4 +-- src/sage/categories/category.py | 23 ++++++++-------- .../categories/complex_reflection_groups.py | 6 ++--- ...eflection_or_generalized_coxeter_groups.py | 6 ++--- src/sage/categories/coxeter_groups.py | 15 ++--------- .../examples/hopf_algebras_with_basis.py | 2 +- .../filtered_hopf_algebras_with_basis.py | 6 ++--- src/sage/categories/finite_coxeter_groups.py | 4 +-- ...ensional_graded_lie_algebras_with_basis.py | 8 +++--- ...te_dimensional_hopf_algebras_with_basis.py | 13 +++++----- ...itely_generated_lambda_bracket_algebras.py | 2 +- ...nitely_generated_lie_conformal_algebras.py | 17 ++++++------ .../categories/generalized_coxeter_groups.py | 4 +-- src/sage/categories/graded_hopf_algebras.py | 7 ++--- .../graded_hopf_algebras_with_basis.py | 6 ++--- .../graded_lie_algebras_with_basis.py | 5 ++-- src/sage/categories/group_algebras.py | 6 ++--- src/sage/categories/hopf_algebras.py | 26 +++++++++---------- .../categories/hopf_algebras_with_basis.py | 18 ++++++------- .../categories/lambda_bracket_algebras.py | 4 +-- src/sage/categories/lie_algebras.py | 2 +- src/sage/categories/lie_conformal_algebras.py | 4 +-- src/sage/categories/primer.py | 2 +- src/sage/categories/realizations.py | 8 +++--- src/sage/categories/shephard_groups.py | 2 +- .../super_hopf_algebras_with_basis.py | 8 +++--- src/sage/categories/super_modules.py | 2 +- .../triangular_kac_moody_algebras.py | 2 +- src/sage/categories/weyl_groups.py | 11 -------- src/sage/categories/with_realizations.py | 8 +++--- src/sage/combinat/chas/fsym.py | 4 +-- src/sage/combinat/chas/wqsym.py | 8 +++--- src/sage/combinat/fqsym.py | 4 +-- .../combinat/ncsf_qsym/generic_basis_code.py | 6 ++--- src/sage/combinat/ncsf_qsym/ncsf.py | 4 +-- src/sage/combinat/ncsf_qsym/qsym.py | 2 +- src/sage/combinat/ncsym/bases.py | 4 +-- src/sage/combinat/sf/k_dual.py | 2 +- src/sage/combinat/sf/sf.py | 4 +-- src/sage/combinat/sf/sfa.py | 14 +++++----- src/sage/misc/c3_controlled.pyx | 2 +- src/sage/rings/derivation.py | 2 +- src/sage/rings/ring.pyx | 2 +- 49 files changed, 146 insertions(+), 163 deletions(-) diff --git a/src/sage/algebras/clifford_algebra.py b/src/sage/algebras/clifford_algebra.py index 220a2eb27a5..009c753539e 100644 --- a/src/sage/algebras/clifford_algebra.py +++ b/src/sage/algebras/clifford_algebra.py @@ -1369,7 +1369,7 @@ def __init__(self, R, names): sage: E. = ExteriorAlgebra(QQ) sage: E.category() Category of finite dimensional supercommutative supercocommutative - super hopf algebras with basis over Rational Field + super Hopf algebras with basis over Rational Field sage: TestSuite(E).run() sage: TestSuite(ExteriorAlgebra(GF(3), ['a', 'b'])).run() diff --git a/src/sage/algebras/lie_algebras/free_lie_algebra.py b/src/sage/algebras/lie_algebras/free_lie_algebra.py index 60d49a174b6..c07a99e9e44 100644 --- a/src/sage/algebras/lie_algebras/free_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/free_lie_algebra.py @@ -933,7 +933,7 @@ def super_categories(self): sage: L. = LieAlgebra(QQ) sage: bases = FreeLieAlgebraBases(L) sage: bases.super_categories() - [Category of lie algebras with basis over Rational Field, + [Category of Lie algebras with basis over Rational Field, Category of realizations of Free Lie algebra generated by (x, y) over Rational Field] """ return [LieAlgebras(self.base().base_ring()).WithBasis(), Realizations(self.base())] diff --git a/src/sage/algebras/lie_algebras/lie_algebra.py b/src/sage/algebras/lie_algebras/lie_algebra.py index 5e1d44813ac..0013413d6a4 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra.py +++ b/src/sage/algebras/lie_algebras/lie_algebra.py @@ -322,7 +322,7 @@ class LieAlgebra(Parent, UniqueRepresentation): # IndexedGenerators): sage: L Nilpotent Lie algebra on 3 generators (X, Y, Z) over Rational Field sage: L.category() - Category of finite dimensional nilpotent lie algebras with basis over Rational Field + Category of finite dimensional nilpotent Lie algebras with basis over Rational Field A second example defining the Engel Lie algebra:: @@ -530,7 +530,7 @@ def __init__(self, R, names=None, category=None): sage: L. = LieAlgebra(QQ, abelian=True) sage: L.category() - Category of finite dimensional nilpotent lie algebras with basis over Rational Field + Category of finite dimensional nilpotent Lie algebras with basis over Rational Field """ category = LieAlgebras(R).or_subcategory(category) Parent.__init__(self, base=R, names=names, category=category) @@ -805,7 +805,7 @@ def __init__(self, R, names=None, index_set=None, category=None, prefix='L', **k sage: L. = LieAlgebra(QQ, abelian=True) sage: L.category() - Category of finite dimensional nilpotent lie algebras with basis over Rational Field + Category of finite dimensional nilpotent Lie algebras with basis over Rational Field """ self._indices = index_set LieAlgebra.__init__(self, R, names, category) @@ -890,7 +890,7 @@ def __init__(self, R, names=None, index_set=None, category=None): sage: L. = LieAlgebra(QQ, abelian=True) sage: L.category() - Category of finite dimensional nilpotent lie algebras with basis over Rational Field + Category of finite dimensional nilpotent Lie algebras with basis over Rational Field """ LieAlgebraWithGenerators.__init__(self, R, names, index_set, category) self.__ngens = len(self._indices) diff --git a/src/sage/algebras/lie_algebras/morphism.py b/src/sage/algebras/lie_algebras/morphism.py index f71001ce98f..a70555416c3 100644 --- a/src/sage/algebras/lie_algebras/morphism.py +++ b/src/sage/algebras/lie_algebras/morphism.py @@ -43,7 +43,7 @@ class LieAlgebraHomomorphism_im_gens(Morphism): It should be a map from the base ring of the domain to the base ring of the codomain. Note that if base_map is nontrivial then the result will - not be a morphism in the category of lie algebras over + not be a morphism in the category of Lie algebras over the base ring. - ``check`` -- whether to run checks on the validity of the defining data @@ -380,7 +380,7 @@ class LieAlgebraMorphism_from_generators(LieAlgebraHomomorphism_im_gens): It should be a map from the base ring of the domain to the base ring of the codomain. Note that if base_map is nontrivial then the result will - not be a morphism in the category of lie algebras over + not be a morphism in the category of Lie algebras over the base ring. - ``check`` -- (default: ``True``) boolean; if ``False`` the values on the Lie brackets implied by ``on_generators`` will diff --git a/src/sage/algebras/lie_algebras/nilpotent_lie_algebra.py b/src/sage/algebras/lie_algebras/nilpotent_lie_algebra.py index a97e422e54b..13b368ad889 100644 --- a/src/sage/algebras/lie_algebras/nilpotent_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/nilpotent_lie_algebra.py @@ -243,7 +243,7 @@ class FreeNilpotentLieAlgebra(NilpotentLieAlgebra_dense): sage: L = LieAlgebra(QQ, 3, step=3) sage: L.category() - Category of finite dimensional stratified lie algebras with basis over Rational Field + Category of finite dimensional stratified Lie algebras with basis over Rational Field sage: L in LieAlgebras(QQ).Nilpotent() True diff --git a/src/sage/algebras/lie_algebras/quotient.py b/src/sage/algebras/lie_algebras/quotient.py index 7fe6b29677f..2b494f3cc2a 100644 --- a/src/sage/algebras/lie_algebras/quotient.py +++ b/src/sage/algebras/lie_algebras/quotient.py @@ -51,7 +51,7 @@ class LieQuotient_finite_dimensional_with_basis(LieAlgebraWithStructureCoefficie L: Free Nilpotent Lie algebra on 5 generators (X_1, X_2, X_12, X_112, X_122) over Rational Field I: Ideal (X_122) sage: E.category() - Join of Category of finite dimensional nilpotent lie algebras with basis + Join of Category of finite dimensional nilpotent Lie algebras with basis over Rational Field and Category of subquotients of sets sage: E.basis().list() [X_1, X_2, X_12, X_112] diff --git a/src/sage/algebras/steenrod/steenrod_algebra.py b/src/sage/algebras/steenrod/steenrod_algebra.py index 7c4d444f81c..c0511aa0641 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra.py +++ b/src/sage/algebras/steenrod/steenrod_algebra.py @@ -556,7 +556,7 @@ def __init__(self, p=2, basis='milnor', **kwds): sage: TestSuite(SteenrodAlgebra(basis='woody')).run() # long time sage: A3 = SteenrodAlgebra(3) sage: A3.category() - Category of supercocommutative super hopf algebras + Category of supercocommutative super Hopf algebras with basis over Finite Field of size 3 sage: TestSuite(A3).run() # long time sage: TestSuite(SteenrodAlgebra(basis='adem', p=3)).run() @@ -3836,7 +3836,7 @@ def SteenrodAlgebra(p=2, basis='milnor', generic='auto', **kwds): sage: A.is_division_algebra() False sage: A.category() - Category of supercocommutative super hopf algebras + Category of supercocommutative super Hopf algebras with basis over Finite Field of size 2 There are methods for constructing elements of the Steenrod diff --git a/src/sage/categories/category.py b/src/sage/categories/category.py index b200f1a7283..1dd39bfc7d6 100644 --- a/src/sage/categories/category.py +++ b/src/sage/categories/category.py @@ -119,6 +119,9 @@ _join_cache = WeakValueDictionary() +HALL_OF_FAME = ['Coxeter', 'Hopf', 'Weyl', 'Lie', 'Hecke'] + + class Category(UniqueRepresentation, SageObject): r""" The base class for modeling mathematical categories, like for example: @@ -513,14 +516,10 @@ def _repr_object_names(self): sage: PrincipalIdealDomains()._repr_object_names() 'principal ideal domains' """ - i = -1 - s = self._label - while i < len(s) - 1: - for i in range(len(s)): - if s[i].isupper(): - s = s[:i] + " " + s[i].lower() + s[i + 1:] - break - return s.lstrip() + words = "".join(letter if not letter.isupper() else ";" + letter + for letter in self._label).split(";") + return " ".join(w if w in HALL_OF_FAME else w.lower() + for w in words).lstrip() def _short_name(self): """ @@ -1235,7 +1234,7 @@ def structure(self): Category of right modules over Rational Field, Category of left modules over Rational Field) sage: structure(HopfAlgebras(QQ).Graded().WithBasis().Connected()) - (Category of hopf algebras over Rational Field, + (Category of Hopf algebras over Rational Field, Category of graded modules over Rational Field) This method is used in :meth:`is_full_subcategory` for @@ -2018,7 +2017,7 @@ def _with_axiom_as_tuple(self, axiom): Category of commutative magmas, Category of finite additive groups) sage: HopfAlgebras(QQ)._with_axiom_as_tuple('FiniteDimensional') - (Category of hopf algebras over Rational Field, + (Category of Hopf algebras over Rational Field, Category of finite dimensional vector spaces over Rational Field) """ if axiom in self.axioms(): @@ -2595,11 +2594,13 @@ def category_sample(): [Category of Coxeter groups, Category of G-sets for Symmetric group of order 8! as a permutation group, Category of Hecke modules over Rational Field, + Category of Hopf algebras over Rational Field, + Category of Hopf algebras with basis over Rational Field, Category of Lie algebras over Rational Field, Category of Weyl groups, Category of additive magmas, ..., Category of fields, ..., - Category of graded hopf algebras with basis over Rational Field, ..., + Category of graded Hopf algebras with basis over Rational Field, ..., Category of modular abelian varieties over Rational Field, ..., Category of simplicial complexes, ..., Category of vector spaces over Rational Field, ... diff --git a/src/sage/categories/complex_reflection_groups.py b/src/sage/categories/complex_reflection_groups.py index fbc04ff329c..925ee1c228e 100644 --- a/src/sage/categories/complex_reflection_groups.py +++ b/src/sage/categories/complex_reflection_groups.py @@ -45,10 +45,10 @@ class ComplexReflectionGroups(Category_singleton): sage: ComplexReflectionGroups() Category of complex reflection groups sage: ComplexReflectionGroups().super_categories() - [Category of complex reflection or generalized coxeter groups] + [Category of complex reflection or generalized Coxeter groups] sage: ComplexReflectionGroups().all_super_categories() [Category of complex reflection groups, - Category of complex reflection or generalized coxeter groups, + Category of complex reflection or generalized Coxeter groups, Category of groups, Category of monoids, Category of finitely generated semigroups, @@ -87,7 +87,7 @@ def super_categories(self): sage: from sage.categories.complex_reflection_groups import ComplexReflectionGroups sage: ComplexReflectionGroups().super_categories() - [Category of complex reflection or generalized coxeter groups] + [Category of complex reflection or generalized Coxeter groups] """ return [ComplexReflectionOrGeneralizedCoxeterGroups()] diff --git a/src/sage/categories/complex_reflection_or_generalized_coxeter_groups.py b/src/sage/categories/complex_reflection_or_generalized_coxeter_groups.py index d3908a8db03..ca2f1e09235 100644 --- a/src/sage/categories/complex_reflection_or_generalized_coxeter_groups.py +++ b/src/sage/categories/complex_reflection_or_generalized_coxeter_groups.py @@ -82,7 +82,7 @@ class ComplexReflectionOrGeneralizedCoxeterGroups(Category_singleton): sage: from sage.categories.complex_reflection_or_generalized_coxeter_groups import ComplexReflectionOrGeneralizedCoxeterGroups sage: C = ComplexReflectionOrGeneralizedCoxeterGroups(); C - Category of complex reflection or generalized coxeter groups + Category of complex reflection or generalized Coxeter groups sage: C.super_categories() [Category of finitely generated enumerated groups] @@ -108,7 +108,7 @@ def super_categories(self): sage: from sage.categories.complex_reflection_groups import ComplexReflectionGroups sage: ComplexReflectionGroups().super_categories() - [Category of complex reflection or generalized coxeter groups] + [Category of complex reflection or generalized Coxeter groups] """ return [Groups().FinitelyGenerated()] @@ -117,7 +117,7 @@ def Irreducible(self): r""" Return the full subcategory of irreducible objects of ``self``. - A complex reflection group, or generalized coxeter group + A complex reflection group, or generalized Coxeter group is *reducible* if its simple reflections can be split in two sets `X` and `Y` such that the elements of `X` commute with that of `Y`. In particular, the group is then direct diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 71285521a5e..c4725a11a5e 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -43,7 +43,7 @@ class CoxeterGroups(Category_singleton): sage: C = CoxeterGroups(); C Category of Coxeter groups sage: C.super_categories() - [Category of generalized coxeter groups] + [Category of generalized Coxeter groups] sage: W = C.example(); W The symmetric group on {0, ..., 3} @@ -105,7 +105,7 @@ def super_categories(self): EXAMPLES:: sage: CoxeterGroups().super_categories() - [Category of generalized coxeter groups] + [Category of generalized Coxeter groups] """ return [GeneralizedCoxeterGroups()] @@ -128,17 +128,6 @@ def additional_structure(self): Finite = LazyImport('sage.categories.finite_coxeter_groups', 'FiniteCoxeterGroups') Algebras = LazyImport('sage.categories.coxeter_group_algebras', 'CoxeterGroupAlgebras') - def _repr_object_names(self): - """ - Return the name of the objects of this category. - - EXAMPLES:: - - sage: CoxeterGroups().Finite() - Category of finite Coxeter groups - """ - return "Coxeter groups" - class ParentMethods: @abstract_method def coxeter_matrix(self): diff --git a/src/sage/categories/examples/hopf_algebras_with_basis.py b/src/sage/categories/examples/hopf_algebras_with_basis.py index 10c89b0f9ad..7f05827c28a 100644 --- a/src/sage/categories/examples/hopf_algebras_with_basis.py +++ b/src/sage/categories/examples/hopf_algebras_with_basis.py @@ -29,7 +29,7 @@ def __init__(self, R, G): sage: from sage.categories.examples.hopf_algebras_with_basis import MyGroupAlgebra sage: A = MyGroupAlgebra(QQ, DihedralGroup(6)) sage: A.category() - Category of finite dimensional hopf algebras with basis over Rational Field + Category of finite dimensional Hopf algebras with basis over Rational Field sage: TestSuite(A).run() """ self._group = G diff --git a/src/sage/categories/filtered_hopf_algebras_with_basis.py b/src/sage/categories/filtered_hopf_algebras_with_basis.py index 0310744d9e1..dadd10dd70e 100644 --- a/src/sage/categories/filtered_hopf_algebras_with_basis.py +++ b/src/sage/categories/filtered_hopf_algebras_with_basis.py @@ -31,9 +31,9 @@ class FilteredHopfAlgebrasWithBasis(FilteredModulesCategory): EXAMPLES:: sage: C = HopfAlgebrasWithBasis(ZZ).Filtered(); C - Category of filtered hopf algebras with basis over Integer Ring + Category of filtered Hopf algebras with basis over Integer Ring sage: C.super_categories() - [Category of hopf algebras with basis over Integer Ring, + [Category of Hopf algebras with basis over Integer Ring, Category of filtered algebras with basis over Integer Ring, Category of filtered coalgebras with basis over Integer Ring] @@ -53,7 +53,7 @@ def super_categories(self): EXAMPLES:: sage: HopfAlgebrasWithBasis(QQ).Filtered().WithRealizations().super_categories() - [Join of Category of hopf algebras over Rational Field + [Join of Category of Hopf algebras over Rational Field and Category of filtered algebras over Rational Field and Category of filtered coalgebras over Rational Field] diff --git a/src/sage/categories/finite_coxeter_groups.py b/src/sage/categories/finite_coxeter_groups.py index 4d422a7541f..9d1b8f6cf68 100644 --- a/src/sage/categories/finite_coxeter_groups.py +++ b/src/sage/categories/finite_coxeter_groups.py @@ -27,7 +27,7 @@ class FiniteCoxeterGroups(CategoryWithAxiom): sage: CoxeterGroups.Finite() Category of finite Coxeter groups sage: FiniteCoxeterGroups().super_categories() - [Category of finite generalized coxeter groups, + [Category of finite generalized Coxeter groups, Category of Coxeter groups] sage: G = CoxeterGroups().Finite().example() @@ -54,7 +54,7 @@ def extra_super_categories(self): EXAMPLES:: sage: CoxeterGroups().Finite().super_categories() - [Category of finite generalized coxeter groups, + [Category of finite generalized Coxeter groups, Category of Coxeter groups] """ from sage.categories.complex_reflection_groups import ComplexReflectionGroups diff --git a/src/sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py b/src/sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py index c5554a2f094..5377122d3f6 100644 --- a/src/sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +++ b/src/sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py @@ -29,10 +29,10 @@ class FiniteDimensionalGradedLieAlgebrasWithBasis(CategoryWithAxiom_over_base_ri EXAMPLES:: sage: C = LieAlgebras(ZZ).WithBasis().FiniteDimensional().Graded(); C - Category of finite dimensional graded lie algebras with basis over Integer Ring + Category of finite dimensional graded Lie algebras with basis over Integer Ring sage: C.super_categories() - [Category of graded lie algebras with basis over Integer Ring, - Category of finite dimensional lie algebras with basis over Integer Ring] + [Category of graded Lie algebras with basis over Integer Ring, + Category of finite dimensional Lie algebras with basis over Integer Ring] sage: C is LieAlgebras(ZZ).WithBasis().FiniteDimensional().Graded() True @@ -120,7 +120,7 @@ class Stratified(CategoryWithAxiom_over_base_ring): sage: C = LieAlgebras(QQ).WithBasis().Graded().Stratified().FiniteDimensional() sage: C - Category of finite dimensional stratified lie algebras with basis over Rational Field + Category of finite dimensional stratified Lie algebras with basis over Rational Field A finite-dimensional stratified Lie algebra is nilpotent:: diff --git a/src/sage/categories/finite_dimensional_hopf_algebras_with_basis.py b/src/sage/categories/finite_dimensional_hopf_algebras_with_basis.py index ffa3655fb9b..da3f1365584 100644 --- a/src/sage/categories/finite_dimensional_hopf_algebras_with_basis.py +++ b/src/sage/categories/finite_dimensional_hopf_algebras_with_basis.py @@ -1,16 +1,17 @@ r""" Finite dimensional Hopf algebras with basis """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) # 2011 Nicolas M. Thiery # # Distributed under the terms of the GNU General Public License (GPL) -# http://www.gnu.org/licenses/ -#****************************************************************************** +# https://www.gnu.org/licenses/ +# ***************************************************************************** from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring + class FiniteDimensionalHopfAlgebrasWithBasis(CategoryWithAxiom_over_base_ring): """ The category of finite dimensional Hopf algebras with a @@ -18,10 +19,10 @@ class FiniteDimensionalHopfAlgebrasWithBasis(CategoryWithAxiom_over_base_ring): EXAMPLES:: - sage: FiniteDimensionalHopfAlgebrasWithBasis(QQ) # fixme: Hopf should be capitalized - Category of finite dimensional hopf algebras with basis over Rational Field + sage: FiniteDimensionalHopfAlgebrasWithBasis(QQ) + Category of finite dimensional Hopf algebras with basis over Rational Field sage: FiniteDimensionalHopfAlgebrasWithBasis(QQ).super_categories() - [Category of hopf algebras with basis over Rational Field, + [Category of Hopf algebras with basis over Rational Field, Category of finite dimensional algebras with basis over Rational Field] TESTS:: diff --git a/src/sage/categories/finitely_generated_lambda_bracket_algebras.py b/src/sage/categories/finitely_generated_lambda_bracket_algebras.py index c997118a3bc..5ff1634ca43 100644 --- a/src/sage/categories/finitely_generated_lambda_bracket_algebras.py +++ b/src/sage/categories/finitely_generated_lambda_bracket_algebras.py @@ -95,7 +95,7 @@ class Graded(GradedModulesCategory): EXAMPLES:: sage: LieConformalAlgebras(QQbar).FinitelyGenerated().Graded() # needs sage.rings.number_field - Category of H-graded finitely generated lie conformal algebras + Category of H-graded finitely generated Lie conformal algebras over Algebraic Field """ def _repr_object_names(self): diff --git a/src/sage/categories/finitely_generated_lie_conformal_algebras.py b/src/sage/categories/finitely_generated_lie_conformal_algebras.py index 53d5ed4ccf6..90b18df668f 100644 --- a/src/sage/categories/finitely_generated_lie_conformal_algebras.py +++ b/src/sage/categories/finitely_generated_lie_conformal_algebras.py @@ -6,21 +6,22 @@ - Reimundo Heluani (2019-10-05): Initial implementation. """ -#****************************************************************************** +# ***************************************************************************** # Copyright (C) 2019 Reimundo Heluani # # 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.categories.category_with_axiom import CategoryWithAxiom_over_base_ring from sage.categories.graded_modules import GradedModulesCategory from sage.categories.super_modules import SuperModulesCategory from sage.categories.lie_conformal_algebras import LieConformalAlgebras + class FinitelyGeneratedLieConformalAlgebras(CategoryWithAxiom_over_base_ring): """ The category of finitely generated Lie conformal algebras. @@ -28,7 +29,7 @@ class FinitelyGeneratedLieConformalAlgebras(CategoryWithAxiom_over_base_ring): EXAMPLES:: sage: LieConformalAlgebras(QQbar).FinitelyGenerated() # needs sage.rings.number_field - Category of finitely generated lie conformal algebras over Algebraic Field + Category of finitely generated Lie conformal algebras over Algebraic Field """ _base_category_class_and_axiom = (LieConformalAlgebras, "FinitelyGeneratedAsLambdaBracketAlgebra") @@ -63,7 +64,7 @@ class Super(SuperModulesCategory): EXAMPLES:: sage: LieConformalAlgebras(AA).FinitelyGenerated().Super() # needs sage.rings.number_field - Category of super finitely generated lie conformal algebras + Category of super finitely generated Lie conformal algebras over Algebraic Real Field """ class Graded(GradedModulesCategory): @@ -73,7 +74,7 @@ class Graded(GradedModulesCategory): EXAMPLES:: sage: LieConformalAlgebras(QQbar).FinitelyGenerated().Super().Graded() # needs sage.rings.number_field - Category of H-graded super finitely generated lie conformal algebras + Category of H-graded super finitely generated Lie conformal algebras over Algebraic Field """ def _repr_object_names(self): @@ -85,7 +86,7 @@ def _repr_object_names(self): sage: C = LieConformalAlgebras(QQbar).FinitelyGenerated() # needs sage.rings.number_field sage: C.Super().Graded() # needs sage.rings.number_field Category of H-graded super finitely generated - lie conformal algebras over Algebraic Field + Lie conformal algebras over Algebraic Field """ return "H-graded {}".format(self.base_category()._repr_object_names()) @@ -96,7 +97,7 @@ class Graded(GradedModulesCategory): EXAMPLES:: sage: LieConformalAlgebras(QQbar).FinitelyGenerated().Graded() # needs sage.rings.number_field - Category of H-graded finitely generated lie conformal algebras + Category of H-graded finitely generated Lie conformal algebras over Algebraic Field """ def _repr_object_names(self): diff --git a/src/sage/categories/generalized_coxeter_groups.py b/src/sage/categories/generalized_coxeter_groups.py index a59da41b3f1..844472ba6be 100644 --- a/src/sage/categories/generalized_coxeter_groups.py +++ b/src/sage/categories/generalized_coxeter_groups.py @@ -34,7 +34,7 @@ class GeneralizedCoxeterGroups(Category_singleton): sage: from sage.categories.generalized_coxeter_groups import GeneralizedCoxeterGroups sage: C = GeneralizedCoxeterGroups(); C - Category of generalized coxeter groups + Category of generalized Coxeter groups TESTS:: @@ -47,7 +47,7 @@ def super_categories(self): sage: from sage.categories.generalized_coxeter_groups import GeneralizedCoxeterGroups sage: GeneralizedCoxeterGroups().super_categories() - [Category of complex reflection or generalized coxeter groups] + [Category of complex reflection or generalized Coxeter groups] """ return [ComplexReflectionOrGeneralizedCoxeterGroups()] diff --git a/src/sage/categories/graded_hopf_algebras.py b/src/sage/categories/graded_hopf_algebras.py index c4d5a24e3fe..60d5befd6f5 100644 --- a/src/sage/categories/graded_hopf_algebras.py +++ b/src/sage/categories/graded_hopf_algebras.py @@ -1,13 +1,14 @@ r""" Graded Hopf algebras """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) # 2008-2011 Nicolas M. Thiery # # Distributed under the terms of the GNU General Public License (GPL) # https://www.gnu.org/licenses/ -#****************************************************************************** +# ***************************************************************************** + def GradedHopfAlgebras(base_ring): r""" @@ -16,7 +17,7 @@ def GradedHopfAlgebras(base_ring): EXAMPLES:: sage: C = GradedHopfAlgebras(QQ); C - Join of Category of hopf algebras over Rational Field + Join of Category of Hopf algebras over Rational Field and Category of graded algebras over Rational Field and Category of graded coalgebras over Rational Field sage: C is HopfAlgebras(QQ).Graded() diff --git a/src/sage/categories/graded_hopf_algebras_with_basis.py b/src/sage/categories/graded_hopf_algebras_with_basis.py index 41beadad8a4..60cf4977eae 100644 --- a/src/sage/categories/graded_hopf_algebras_with_basis.py +++ b/src/sage/categories/graded_hopf_algebras_with_basis.py @@ -22,9 +22,9 @@ class GradedHopfAlgebrasWithBasis(GradedModulesCategory): EXAMPLES:: sage: C = GradedHopfAlgebrasWithBasis(ZZ); C - Category of graded hopf algebras with basis over Integer Ring + Category of graded Hopf algebras with basis over Integer Ring sage: C.super_categories() - [Category of filtered hopf algebras with basis over Integer Ring, + [Category of filtered Hopf algebras with basis over Integer Ring, Category of graded algebras with basis over Integer Ring, Category of graded coalgebras with basis over Integer Ring] @@ -64,7 +64,7 @@ def super_categories(self): EXAMPLES:: sage: GradedHopfAlgebrasWithBasis(QQ).WithRealizations().super_categories() - [Join of Category of hopf algebras over Rational Field + [Join of Category of Hopf algebras over Rational Field and Category of graded algebras over Rational Field and Category of graded coalgebras over Rational Field] diff --git a/src/sage/categories/graded_lie_algebras_with_basis.py b/src/sage/categories/graded_lie_algebras_with_basis.py index 885a4dfb8cd..8552218e074 100644 --- a/src/sage/categories/graded_lie_algebras_with_basis.py +++ b/src/sage/categories/graded_lie_algebras_with_basis.py @@ -15,6 +15,7 @@ from sage.categories.graded_modules import GradedModulesCategory from sage.misc.lazy_import import LazyImport + class GradedLieAlgebrasWithBasis(GradedModulesCategory): """ The category of graded Lie algebras with a distinguished basis. @@ -22,10 +23,10 @@ class GradedLieAlgebrasWithBasis(GradedModulesCategory): EXAMPLES:: sage: C = LieAlgebras(ZZ).WithBasis().Graded(); C - Category of graded lie algebras with basis over Integer Ring + Category of graded Lie algebras with basis over Integer Ring sage: C.super_categories() [Category of graded modules with basis over Integer Ring, - Category of lie algebras with basis over Integer Ring, + Category of Lie algebras with basis over Integer Ring, Category of graded Lie algebras over Integer Ring] sage: C is LieAlgebras(ZZ).WithBasis().Graded() diff --git a/src/sage/categories/group_algebras.py b/src/sage/categories/group_algebras.py index 1f68c28c3b4..7a41d4877fd 100644 --- a/src/sage/categories/group_algebras.py +++ b/src/sage/categories/group_algebras.py @@ -40,7 +40,7 @@ class GroupAlgebras(AlgebrasCategory): sage: C = Groups().Algebras(ZZ); C Category of group algebras over Integer Ring sage: C.super_categories() - [Category of hopf algebras with basis over Integer Ring, + [Category of Hopf algebras with basis over Integer Ring, Category of monoid algebras over Integer Ring] We can also construct this category with:: @@ -92,9 +92,9 @@ def extra_super_categories(self): sage: C = Groups().Algebras(QQ) sage: C.extra_super_categories() - [Category of hopf algebras over Rational Field] + [Category of Hopf algebras over Rational Field] sage: sorted(C.super_categories(), key=str) - [Category of hopf algebras with basis over Rational Field, + [Category of Hopf algebras with basis over Rational Field, Category of monoid algebras over Rational Field] """ from sage.categories.hopf_algebras import HopfAlgebras diff --git a/src/sage/categories/hopf_algebras.py b/src/sage/categories/hopf_algebras.py index 41e349690fe..12b9ff48063 100644 --- a/src/sage/categories/hopf_algebras.py +++ b/src/sage/categories/hopf_algebras.py @@ -25,7 +25,7 @@ class HopfAlgebras(Category_over_base_ring): EXAMPLES:: sage: HopfAlgebras(QQ) - Category of hopf algebras over Rational Field + Category of Hopf algebras over Rational Field sage: HopfAlgebras(QQ).super_categories() [Category of bialgebras over Rational Field] @@ -53,11 +53,11 @@ def dual(self): sage: C = HopfAlgebras(QQ) sage: C.dual() - Category of hopf algebras over Rational Field + Category of Hopf algebras over Rational Field """ return self - WithBasis = LazyImport('sage.categories.hopf_algebras_with_basis', 'HopfAlgebrasWithBasis') + WithBasis = LazyImport('sage.categories.hopf_algebras_with_basis', 'HopfAlgebrasWithBasis') class ElementMethods: @@ -89,12 +89,12 @@ def antipode(self): # return operator.antipode(self) class ParentMethods: - #def __setup__(self): # Check the conventions for _setup_ or __setup__ + # def __setup__(self): # Check the conventions for _setup_ or __setup__ # if self.implements("antipode"): # coercion.declare(operator.antipode, [self], self.antipode) # - #@lazy_attribute - #def antipode(self): + # @lazy_attribute + # def antipode(self): # # delegates to the overloading mechanism but # # guarantees that the result is in self # compose(self, operator.antipode, domain=self) @@ -126,7 +126,7 @@ def dual(self): sage: C = HopfAlgebras(QQ).Super() sage: C.dual() - Category of super hopf algebras over Rational Field + Category of super Hopf algebras over Rational Field """ return self @@ -155,9 +155,9 @@ def extra_super_categories(self): sage: C = HopfAlgebras(QQ).TensorProducts() sage: C.extra_super_categories() - [Category of hopf algebras over Rational Field] + [Category of Hopf algebras over Rational Field] sage: sorted(C.super_categories(), key=str) - [Category of hopf algebras over Rational Field, + [Category of Hopf algebras over Rational Field, Category of tensor products of algebras over Rational Field, Category of tensor products of coalgebras over Rational Field] """ @@ -165,8 +165,8 @@ def extra_super_categories(self): class ParentMethods: # TODO: enable when tensor product of morphisms will be implemented - #@lazy_attribute - #def antipode(self): + # @lazy_attribute + # def antipode(self): # return tensor([module.antipode for module in self.modules]) pass @@ -179,8 +179,8 @@ class DualCategory(Category_over_base_ring): """ class ParentMethods: - #@lazy_attribute - #def antipode(self): + # @lazy_attribute + # def antipode(self): # self.dual().antipode.dual() # Check that this is the correct formula pass diff --git a/src/sage/categories/hopf_algebras_with_basis.py b/src/sage/categories/hopf_algebras_with_basis.py index 615fc4eae06..d56adc36eb1 100644 --- a/src/sage/categories/hopf_algebras_with_basis.py +++ b/src/sage/categories/hopf_algebras_with_basis.py @@ -25,9 +25,9 @@ class HopfAlgebrasWithBasis(CategoryWithAxiom_over_base_ring): sage: C = HopfAlgebrasWithBasis(QQ) sage: C - Category of hopf algebras with basis over Rational Field + Category of Hopf algebras with basis over Rational Field sage: C.super_categories() - [Category of hopf algebras over Rational Field, + [Category of Hopf algebras over Rational Field, Category of bialgebras with basis over Rational Field] We now show how to use a simple Hopf algebra, namely the group algebra of the dihedral group @@ -38,7 +38,7 @@ class HopfAlgebrasWithBasis(CategoryWithAxiom_over_base_ring): Dihedral group of order 6 as a permutation group over Rational Field sage: A.rename("A") # needs sage.groups sage: A.category() # needs sage.groups - Category of finite dimensional hopf algebras with basis over Rational Field + Category of finite dimensional Hopf algebras with basis over Rational Field sage: A.one_basis() # needs sage.groups () @@ -149,7 +149,7 @@ def example(self, G=None): # sage: C = HopfAlgebrasWithBasis(QQ) # sage: C.dual() -# Category of hopf algebras with basis over Rational Field +# Category of Hopf algebras with basis over Rational Field # """ # return self @@ -283,7 +283,7 @@ class ElementMethods: class TensorProducts(TensorProductsCategory): """ - The category of hopf algebras with basis constructed by tensor product of hopf algebras with basis + The category of Hopf algebras with basis constructed by tensor product of Hopf algebras with basis """ @cached_method @@ -293,11 +293,11 @@ def extra_super_categories(self): sage: C = HopfAlgebrasWithBasis(QQ).TensorProducts() sage: C.extra_super_categories() - [Category of hopf algebras with basis over Rational Field] + [Category of Hopf algebras with basis over Rational Field] sage: sorted(C.super_categories(), key=str) - [Category of hopf algebras with basis over Rational Field, - Category of tensor products of algebras with basis over Rational Field, - Category of tensor products of hopf algebras over Rational Field] + [Category of Hopf algebras with basis over Rational Field, + Category of tensor products of Hopf algebras over Rational Field, + Category of tensor products of algebras with basis over Rational Field] """ return [self.base_category()] diff --git a/src/sage/categories/lambda_bracket_algebras.py b/src/sage/categories/lambda_bracket_algebras.py index 40cb5ed70c4..3891b42c3ed 100644 --- a/src/sage/categories/lambda_bracket_algebras.py +++ b/src/sage/categories/lambda_bracket_algebras.py @@ -91,7 +91,7 @@ def FinitelyGeneratedAsLambdaBracketAlgebra(self): EXAMPLES:: sage: LieConformalAlgebras(QQ).FinitelyGenerated() - Category of finitely generated lie conformal algebras over Rational Field + Category of finitely generated Lie conformal algebras over Rational Field """ return self._with_axiom("FinitelyGeneratedAsLambdaBracketAlgebra") @@ -102,7 +102,7 @@ def FinitelyGenerated(self): EXAMPLES:: sage: LieConformalAlgebras(QQ).FinitelyGenerated() - Category of finitely generated lie conformal algebras over Rational Field + Category of finitely generated Lie conformal algebras over Rational Field """ return self._with_axiom("FinitelyGeneratedAsLambdaBracketAlgebra") diff --git a/src/sage/categories/lie_algebras.py b/src/sage/categories/lie_algebras.py index 7244eab161b..32aa9f00041 100644 --- a/src/sage/categories/lie_algebras.py +++ b/src/sage/categories/lie_algebras.py @@ -108,7 +108,7 @@ def Nilpotent(self): sage: LieAlgebras(QQ).Nilpotent() Category of nilpotent Lie algebras over Rational Field sage: LieAlgebras(QQ).WithBasis().Nilpotent() - Category of nilpotent lie algebras with basis over Rational Field + Category of nilpotent Lie algebras with basis over Rational Field """ return self._with_axiom("Nilpotent") diff --git a/src/sage/categories/lie_conformal_algebras.py b/src/sage/categories/lie_conformal_algebras.py index ee48889dd0b..cb5a944ce59 100644 --- a/src/sage/categories/lie_conformal_algebras.py +++ b/src/sage/categories/lie_conformal_algebras.py @@ -185,12 +185,12 @@ def super_categories(self): sage: C.super_categories() [Category of Lambda bracket algebras over Rational Field] sage: C = LieConformalAlgebras(QQ).FinitelyGenerated(); C - Category of finitely generated lie conformal algebras over Rational Field + Category of finitely generated Lie conformal algebras over Rational Field sage: C.super_categories() [Category of finitely generated lambda bracket algebras over Rational Field, Category of Lie conformal algebras over Rational Field] sage: C.all_super_categories() - [Category of finitely generated lie conformal algebras over Rational Field, + [Category of finitely generated Lie conformal algebras over Rational Field, Category of finitely generated lambda bracket algebras over Rational Field, Category of Lie conformal algebras over Rational Field, Category of Lambda bracket algebras over Rational Field, diff --git a/src/sage/categories/primer.py b/src/sage/categories/primer.py index 14f8d5fbbe5..0aff713bd94 100644 --- a/src/sage/categories/primer.py +++ b/src/sage/categories/primer.py @@ -159,7 +159,7 @@ Category of fields sage: HopfAlgebras(QQ) - Category of hopf algebras over Rational Field + Category of Hopf algebras over Rational Field Each of the above is called a *category*. It typically specifies what are the operations on the elements, as well as the axioms satisfied by diff --git a/src/sage/categories/realizations.py b/src/sage/categories/realizations.py index 1c40e597676..d22b6f6a80a 100644 --- a/src/sage/categories/realizations.py +++ b/src/sage/categories/realizations.py @@ -78,11 +78,11 @@ def Realizations(self): The subset algebra of {1, 2, 3} over Rational Field sage: C = GradedHopfAlgebrasWithBasis(QQ).Realizations(); C - Join of Category of graded hopf algebras with basis over Rational Field - and Category of realizations of hopf algebras over Rational Field + Join of Category of graded Hopf algebras with basis over Rational Field + and Category of realizations of Hopf algebras over Rational Field sage: C.super_categories() - [Category of graded hopf algebras with basis over Rational Field, - Category of realizations of hopf algebras over Rational Field] + [Category of graded Hopf algebras with basis over Rational Field, + Category of realizations of Hopf algebras over Rational Field] sage: TestSuite(C).run() diff --git a/src/sage/categories/shephard_groups.py b/src/sage/categories/shephard_groups.py index 5e5c8089f87..945274bcd84 100644 --- a/src/sage/categories/shephard_groups.py +++ b/src/sage/categories/shephard_groups.py @@ -36,6 +36,6 @@ def super_categories(self): sage: from sage.categories.shephard_groups import ShephardGroups sage: ShephardGroups().super_categories() - [Category of finite generalized coxeter groups] + [Category of finite generalized Coxeter groups] """ return [GeneralizedCoxeterGroups().Finite()] diff --git a/src/sage/categories/super_hopf_algebras_with_basis.py b/src/sage/categories/super_hopf_algebras_with_basis.py index afaafc2b8f7..b3b86d0973d 100644 --- a/src/sage/categories/super_hopf_algebras_with_basis.py +++ b/src/sage/categories/super_hopf_algebras_with_basis.py @@ -18,11 +18,11 @@ class SuperHopfAlgebrasWithBasis(SuperModulesCategory): EXAMPLES:: sage: C = HopfAlgebras(ZZ).WithBasis().Super(); C - Category of super hopf algebras with basis over Integer Ring + Category of super Hopf algebras with basis over Integer Ring sage: sorted(C.super_categories(), key=str) - [Category of super algebras with basis over Integer Ring, - Category of super coalgebras with basis over Integer Ring, - Category of super hopf algebras over Integer Ring] + [Category of super Hopf algebras over Integer Ring, + Category of super algebras with basis over Integer Ring, + Category of super coalgebras with basis over Integer Ring] TESTS:: diff --git a/src/sage/categories/super_modules.py b/src/sage/categories/super_modules.py index 0fbd94fbf31..a6d17ea32b0 100644 --- a/src/sage/categories/super_modules.py +++ b/src/sage/categories/super_modules.py @@ -46,7 +46,7 @@ def default_super_categories(cls, category, *args): EXAMPLES:: sage: HopfAlgebras(ZZ).WithBasis().FiniteDimensional().Super() # indirect doctest - Category of finite dimensional super hopf algebras with basis over Integer Ring + Category of finite dimensional super Hopf algebras with basis over Integer Ring """ axioms = axiom_whitelist.intersection(category.axioms()) C = super().default_super_categories(category, *args) diff --git a/src/sage/categories/triangular_kac_moody_algebras.py b/src/sage/categories/triangular_kac_moody_algebras.py index e9c3f1ad167..f5730707d36 100644 --- a/src/sage/categories/triangular_kac_moody_algebras.py +++ b/src/sage/categories/triangular_kac_moody_algebras.py @@ -37,7 +37,7 @@ def super_categories(self): sage: from sage.categories.triangular_kac_moody_algebras import TriangularKacMoodyAlgebras sage: TriangularKacMoodyAlgebras(QQ).super_categories() - [Join of Category of graded lie algebras with basis over Rational Field + [Join of Category of graded Lie algebras with basis over Rational Field and Category of kac moody algebras over Rational Field] """ diff --git a/src/sage/categories/weyl_groups.py b/src/sage/categories/weyl_groups.py index 79db1d40001..5a52c10e04b 100644 --- a/src/sage/categories/weyl_groups.py +++ b/src/sage/categories/weyl_groups.py @@ -74,17 +74,6 @@ def additional_structure(self): """ return None - def _repr_object_names(self): - """ - Return the name of the objects of this category. - - EXAMPLES:: - - sage: WeylGroups().Finite() - Category of finite Weyl groups - """ - return "Weyl groups" - Finite = LazyImport('sage.categories.finite_weyl_groups', 'FiniteWeylGroups') class ParentMethods: diff --git a/src/sage/categories/with_realizations.py b/src/sage/categories/with_realizations.py index d0dc8d148bd..eaabcdaf04a 100644 --- a/src/sage/categories/with_realizations.py +++ b/src/sage/categories/with_realizations.py @@ -271,9 +271,9 @@ def WithRealizations(self): sage: Semigroups().WithRealizations() Join of Category of semigroups and Category of sets with realizations sage: C = GradedHopfAlgebrasWithBasis(QQ).WithRealizations(); C - Category of graded hopf algebras with basis over Rational Field with realizations + Category of graded Hopf algebras with basis over Rational Field with realizations sage: C.super_categories() - [Join of Category of hopf algebras over Rational Field + [Join of Category of Hopf algebras over Rational Field and Category of graded algebras over Rational Field and Category of graded coalgebras over Rational Field] sage: TestSuite(Semigroups().WithRealizations()).run() @@ -303,7 +303,7 @@ def _repr_(self): EXAMPLES:: sage: C = GradedHopfAlgebrasWithBasis(QQ).WithRealizations(); C #indirect doctest - Category of graded hopf algebras with basis over Rational Field with realizations + Category of graded Hopf algebras with basis over Rational Field with realizations """ s = repr(self.base_category()) - return s+" with realizations" + return s + " with realizations" diff --git a/src/sage/combinat/chas/fsym.py b/src/sage/combinat/chas/fsym.py index f1c149c66f1..7f63a24c798 100644 --- a/src/sage/combinat/chas/fsym.py +++ b/src/sage/combinat/chas/fsym.py @@ -214,10 +214,10 @@ def super_categories(self): sage: bases = FSymBases(FSym) sage: bases.super_categories() [Category of realizations of Hopf algebra of standard tableaux over the Integer Ring, - Join of Category of realizations of hopf algebras over Integer Ring + Join of Category of realizations of Hopf algebras over Integer Ring and Category of graded algebras over Integer Ring and Category of graded coalgebras over Integer Ring, - Category of graded connected hopf algebras with basis over Integer Ring] + Category of graded connected Hopf algebras with basis over Integer Ring] """ R = self.base().base_ring() return [self.base().Realizations(), diff --git a/src/sage/combinat/chas/wqsym.py b/src/sage/combinat/chas/wqsym.py index 57b90761c88..567e1f1b9f5 100644 --- a/src/sage/combinat/chas/wqsym.py +++ b/src/sage/combinat/chas/wqsym.py @@ -1945,18 +1945,18 @@ def super_categories(self): sage: bases = WQSymBases(WQSym, True) sage: bases.super_categories() [Category of realizations of Word Quasi-symmetric functions over Integer Ring, - Join of Category of realizations of hopf algebras over Integer Ring + Join of Category of realizations of Hopf algebras over Integer Ring and Category of graded algebras over Integer Ring and Category of graded coalgebras over Integer Ring, - Category of graded connected hopf algebras with basis over Integer Ring] + Category of graded connected Hopf algebras with basis over Integer Ring] sage: bases = WQSymBases(WQSym, False) sage: bases.super_categories() [Category of realizations of Word Quasi-symmetric functions over Integer Ring, - Join of Category of realizations of hopf algebras over Integer Ring + Join of Category of realizations of Hopf algebras over Integer Ring and Category of graded algebras over Integer Ring and Category of graded coalgebras over Integer Ring, - Join of Category of filtered connected hopf algebras with basis over Integer Ring + Join of Category of filtered connected Hopf algebras with basis over Integer Ring and Category of graded algebras over Integer Ring and Category of graded coalgebras over Integer Ring] """ diff --git a/src/sage/combinat/fqsym.py b/src/sage/combinat/fqsym.py index 48780725faa..fbfbf7b54bc 100644 --- a/src/sage/combinat/fqsym.py +++ b/src/sage/combinat/fqsym.py @@ -1276,10 +1276,10 @@ def super_categories(self): sage: bases = FQSymBases(FQSym) sage: bases.super_categories() [Category of realizations of Free Quasi-symmetric functions over Integer Ring, - Join of Category of realizations of hopf algebras over Integer Ring + Join of Category of realizations of Hopf algebras over Integer Ring and Category of graded algebras over Integer Ring and Category of graded coalgebras over Integer Ring, - Category of graded connected hopf algebras with basis over Integer Ring] + Category of graded connected Hopf algebras with basis over Integer Ring] """ R = self.base().base_ring() return [self.base().Realizations(), diff --git a/src/sage/combinat/ncsf_qsym/generic_basis_code.py b/src/sage/combinat/ncsf_qsym/generic_basis_code.py index bbf4d7af76c..4fe908d727c 100644 --- a/src/sage/combinat/ncsf_qsym/generic_basis_code.py +++ b/src/sage/combinat/ncsf_qsym/generic_basis_code.py @@ -69,8 +69,8 @@ def super_categories(self): sage: QSym = QuasiSymmetricFunctions(QQ) sage: BasesOfQSymOrNCSF(QSym).super_categories() [Category of realizations of Quasisymmetric functions over the Rational Field, - Category of graded hopf algebras with basis over Rational Field, - Join of Category of realizations of hopf algebras over Rational Field + Category of graded Hopf algebras with basis over Rational Field, + Join of Category of realizations of Hopf algebras over Rational Field and Category of graded algebras over Rational Field and Category of graded coalgebras over Rational Field] """ @@ -1051,7 +1051,7 @@ def __init__(self, domain, on_generators, position=0, codomain=None, category=No sage: f(2*Psi[[]] + 3 * Psi[1,3,2] + Psi[2,4] ) 2*Psi[] - 3*Psi[1, 3, 2] + Psi[2, 4] sage: f.category() - Category of endsets of hopf algebras over Rational Field and graded modules over Rational Field + Category of endsets of Hopf algebras over Rational Field and graded modules over Rational Field If ``anti`` is true, this returns an anti-algebra morphism:: diff --git a/src/sage/combinat/ncsf_qsym/ncsf.py b/src/sage/combinat/ncsf_qsym/ncsf.py index f8d3fb64844..0d91379f408 100644 --- a/src/sage/combinat/ncsf_qsym/ncsf.py +++ b/src/sage/combinat/ncsf_qsym/ncsf.py @@ -66,7 +66,7 @@ class NonCommutativeSymmetricFunctions(UniqueRepresentation, Parent): one generator in each degree:: sage: NCSF.category() - Join of Category of hopf algebras over Rational Field + Join of Category of Hopf algebras over Rational Field and Category of graded algebras over Rational Field and Category of monoids with realizations and Category of graded coalgebras over Rational Field @@ -2134,7 +2134,7 @@ def algebra_morphism(self, on_generators, **keywords): sage: f(2*Psi[[]] + 3 * Psi[1,3,2] + Psi[2,4] ) 2*Psi[] - 3*Psi[1, 3, 2] + Psi[2, 4] sage: f.category() - Category of endsets of hopf algebras over Rational Field and graded modules over Rational Field + Category of endsets of Hopf algebras over Rational Field and graded modules over Rational Field If ``anti`` is true, this returns an anti-algebra morphism:: diff --git a/src/sage/combinat/ncsf_qsym/qsym.py b/src/sage/combinat/ncsf_qsym/qsym.py index 527724e95b6..75b60c617a5 100644 --- a/src/sage/combinat/ncsf_qsym/qsym.py +++ b/src/sage/combinat/ncsf_qsym/qsym.py @@ -185,7 +185,7 @@ class QuasiSymmetricFunctions(UniqueRepresentation, Parent): sage: QSym = QuasiSymmetricFunctions(QQ) sage: QSym.category() - Join of Category of hopf algebras over Rational Field + Join of Category of Hopf algebras over Rational Field and Category of graded algebras over Rational Field and Category of commutative algebras over Rational Field and Category of monoids with realizations diff --git a/src/sage/combinat/ncsym/bases.py b/src/sage/combinat/ncsym/bases.py index 9d4aac2cdf1..466d1ad42e5 100644 --- a/src/sage/combinat/ncsym/bases.py +++ b/src/sage/combinat/ncsym/bases.py @@ -74,8 +74,8 @@ def super_categories(self): sage: NCSymOrNCSymDualBases(NCSym).super_categories() [Category of realizations of Symmetric functions in non-commuting variables over the Rational Field, - Category of graded hopf algebras with basis over Rational Field, - Join of Category of realizations of hopf algebras over Rational Field + Category of graded Hopf algebras with basis over Rational Field, + Join of Category of realizations of Hopf algebras over Rational Field and Category of graded algebras over Rational Field and Category of graded coalgebras over Rational Field] """ diff --git a/src/sage/combinat/sf/k_dual.py b/src/sage/combinat/sf/k_dual.py index be19a9fd413..4fa2e971e36 100644 --- a/src/sage/combinat/sf/k_dual.py +++ b/src/sage/combinat/sf/k_dual.py @@ -490,7 +490,7 @@ def super_categories(self): sage: KQB = KBoundedQuotientBases(Q) sage: KQB.super_categories() [Category of realizations of 3-Bounded Quotient of Symmetric Functions over Univariate Polynomial Ring in t over Rational Field with t=1, - Join of Category of graded hopf algebras with basis over Univariate Polynomial Ring in t over Rational Field + Join of Category of graded Hopf algebras with basis over Univariate Polynomial Ring in t over Rational Field and Category of quotients of algebras over Univariate Polynomial Ring in t over Rational Field and Category of quotients of graded modules with basis over Univariate Polynomial Ring in t over Rational Field] """ diff --git a/src/sage/combinat/sf/sf.py b/src/sage/combinat/sf/sf.py index 16999699f42..ad86bfd6c7f 100644 --- a/src/sage/combinat/sf/sf.py +++ b/src/sage/combinat/sf/sf.py @@ -73,7 +73,7 @@ class SymmetricFunctions(UniqueRepresentation, Parent): Sage knows certain categorical information about this algebra:: sage: Sym.category() - Join of Category of hopf algebras over Rational Field + Join of Category of Hopf algebras over Rational Field and Category of unique factorization domains and Category of graded algebras over Rational Field and Category of commutative algebras over Rational Field @@ -165,7 +165,7 @@ class SymmetricFunctions(UniqueRepresentation, Parent): [Category of graded bases of Symmetric Functions over Rational Field, Category of filtered bases of Symmetric Functions over Rational Field, Category of bases of Symmetric Functions over Rational Field, - Category of graded hopf algebras with basis over Rational Field, + Category of graded Hopf algebras with basis over Rational Field, ...] To start with, ``p`` is a graded algebra, the grading being induced diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index 9a5d8fb70a3..f8288701e5d 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -360,8 +360,8 @@ def super_categories(self): sage: bases = SymmetricFunctionsBases(Sym) sage: bases.super_categories() [Category of realizations of Symmetric Functions over Rational Field, - Category of commutative hopf algebras with basis over Rational Field, - Join of Category of realizations of hopf algebras over Rational Field + Category of commutative Hopf algebras with basis over Rational Field, + Join of Category of realizations of Hopf algebras over Rational Field and Category of graded algebras over Rational Field and Category of graded coalgebras over Rational Field, Category of unique factorization domains] @@ -370,8 +370,8 @@ def super_categories(self): sage: bases = SymmetricFunctionsBases(Sym) sage: bases.super_categories() [Category of realizations of Symmetric Functions over Univariate Polynomial Ring in x over Integer Ring, - Category of commutative hopf algebras with basis over Univariate Polynomial Ring in x over Integer Ring, - Join of Category of realizations of hopf algebras over Univariate Polynomial Ring in x over Integer Ring + Category of commutative Hopf algebras with basis over Univariate Polynomial Ring in x over Integer Ring, + Join of Category of realizations of Hopf algebras over Univariate Polynomial Ring in x over Integer Ring and Category of graded algebras over Univariate Polynomial Ring in x over Integer Ring and Category of graded coalgebras over Univariate Polynomial Ring in x over Integer Ring] """ @@ -1532,7 +1532,7 @@ def super_categories(self): sage: bases = FilteredSymmetricFunctionsBases(Sym) sage: bases.super_categories() [Category of bases of Symmetric Functions over Rational Field, - Category of commutative filtered hopf algebras with basis over Rational Field] + Category of commutative filtered Hopf algebras with basis over Rational Field] """ cat = HopfAlgebras(self.base().base_ring()).Commutative().WithBasis().Filtered() return [SymmetricFunctionsBases(self.base()), cat] @@ -1582,7 +1582,7 @@ def super_categories(self): sage: bases = GradedSymmetricFunctionsBases(Sym) sage: bases.super_categories() [Category of filtered bases of Symmetric Functions over Rational Field, - Category of commutative graded hopf algebras with basis over Rational Field] + Category of commutative graded Hopf algebras with basis over Rational Field] """ cat = HopfAlgebras(self.base().base_ring()).Commutative().WithBasis().Graded() return [FilteredSymmetricFunctionsBases(self.base()), cat] @@ -3540,7 +3540,7 @@ def inner_plethysm(self, x): .. [SchaThi1994] Thomas Scharf, Jean-Yves Thibon. *A Hopf-algebra approach to inner plethysm*. Advances in Mathematics 104 (1994), pp. 30-58. - ftp://ftp.mathe2.uni-bayreuth.de/axel/papers/scharf:a_hopf_algebra_approach_to_inner_plethysm.ps.gz + ftp://ftp.mathe2.uni-bayreuth.de/axel/papers/scharf:a_Hopf_algebra_approach_to_inner_plethysm.ps.gz INPUT: diff --git a/src/sage/misc/c3_controlled.pyx b/src/sage/misc/c3_controlled.pyx index 4a4c51cbfe7..b32d493659f 100644 --- a/src/sage/misc/c3_controlled.pyx +++ b/src/sage/misc/c3_controlled.pyx @@ -346,8 +346,8 @@ doctest:: [Category of affine Weyl groups, Category of fields, Category of finite Weyl groups, + Category of finite dimensional Hopf algebras with basis over Rational Field, Category of finite dimensional algebras with basis over Rational Field, - Category of finite dimensional hopf algebras with basis over Rational Field, Category of finite enumerated permutation groups, Category of number fields] diff --git a/src/sage/rings/derivation.py b/src/sage/rings/derivation.py index 44182627cfc..2cd1bc1b1aa 100644 --- a/src/sage/rings/derivation.py +++ b/src/sage/rings/derivation.py @@ -78,7 +78,7 @@ sage: M.category() Join of - Category of lie algebras with basis over Rational Field and + Category of Lie algebras with basis over Rational Field and Category of modules with basis over Multivariate Polynomial Ring in x, y, z over Rational Field diff --git a/src/sage/rings/ring.pyx b/src/sage/rings/ring.pyx index 75f58656385..b91205037a6 100644 --- a/src/sage/rings/ring.pyx +++ b/src/sage/rings/ring.pyx @@ -150,7 +150,7 @@ cdef class Ring(ParentWithGens): Category of infinite algebras over (finite dimensional algebras with basis over (number fields and quotient fields and metric spaces) and infinite sets) sage: PolynomialRing(SteenrodAlgebra(2),'x').category() # needs sage.combinat sage.modules - Category of infinite algebras over (super hopf algebras with basis + Category of infinite algebras over (super Hopf algebras with basis over Finite Field of size 2 and supercocommutative super coalgebras over Finite Field of size 2) From 6193042a988883f73b27f4b434bf11e0b7469ddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 7 Nov 2023 16:19:11 +0100 Subject: [PATCH 038/155] fix wrong change --- src/sage/combinat/sf/sfa.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index f8288701e5d..bca95b7f9da 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -3540,7 +3540,7 @@ def inner_plethysm(self, x): .. [SchaThi1994] Thomas Scharf, Jean-Yves Thibon. *A Hopf-algebra approach to inner plethysm*. Advances in Mathematics 104 (1994), pp. 30-58. - ftp://ftp.mathe2.uni-bayreuth.de/axel/papers/scharf:a_Hopf_algebra_approach_to_inner_plethysm.ps.gz + ftp://ftp.mathe2.uni-bayreuth.de/axel/papers/scharf:a_hopf_algebra_approach_to_inner_plethysm.ps.gz INPUT: From fbd035b2831d1df7f9ab992935679d88f9b2c12f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 14 May 2023 21:14:46 -0700 Subject: [PATCH 039/155] src/doc: Add sage.doctest: optional --- src/doc/de/tutorial/tour_plotting.rst | 2 ++ src/doc/en/prep/Calculus.rst | 2 +- src/doc/en/prep/Quickstarts/Differential-Equations.rst | 2 +- src/doc/en/prep/Symbolics-and-Basic-Plotting.rst | 2 +- .../thematic_tutorials/vector_calculus/vector_calc_advanced.rst | 2 +- .../vector_calculus/vector_calc_cartesian.rst | 2 +- .../thematic_tutorials/vector_calculus/vector_calc_change.rst | 2 +- .../vector_calculus/vector_calc_curvilinear.rst | 2 +- .../en/thematic_tutorials/vector_calculus/vector_calc_plane.rst | 2 +- src/doc/en/tutorial/tour_plotting.rst | 2 ++ src/doc/fr/tutorial/tour_plotting.rst | 2 ++ src/doc/ja/tutorial/tour_plotting.rst | 2 ++ src/doc/pt/tutorial/tour_plotting.rst | 2 ++ src/doc/ru/tutorial/tour_plotting.rst | 2 ++ 14 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/doc/de/tutorial/tour_plotting.rst b/src/doc/de/tutorial/tour_plotting.rst index e7dc377193f..c91403bc937 100644 --- a/src/doc/de/tutorial/tour_plotting.rst +++ b/src/doc/de/tutorial/tour_plotting.rst @@ -1,3 +1,5 @@ +.. sage-doctest: optional - sage.plot sage.symbolic + .. _section-plot: Plotten diff --git a/src/doc/en/prep/Calculus.rst b/src/doc/en/prep/Calculus.rst index af6902b9e04..77821db1e57 100644 --- a/src/doc/en/prep/Calculus.rst +++ b/src/doc/en/prep/Calculus.rst @@ -1,4 +1,4 @@ -.. -*- coding: utf-8 -*- +.. sage-doctest: optional - sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/prep/Quickstarts/Differential-Equations.rst b/src/doc/en/prep/Quickstarts/Differential-Equations.rst index 3c023424db8..7c6d4c93d73 100644 --- a/src/doc/en/prep/Quickstarts/Differential-Equations.rst +++ b/src/doc/en/prep/Quickstarts/Differential-Equations.rst @@ -1,4 +1,4 @@ -.. -*- coding: utf-8 -*- +.. sage-doctest: optional - sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst b/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst index 6e0ab69765a..89036f5a0e0 100644 --- a/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst +++ b/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst @@ -1,4 +1,4 @@ -.. -*- coding: utf-8 -*- +.. sage-doctest: optional - sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_advanced.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_advanced.rst index 104933d7bc8..ca7d466ad98 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_advanced.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_advanced.rst @@ -1,4 +1,4 @@ -.. -*- coding: utf-8 -*- +.. sage-doctest: optional - sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst index 978aa129395..24c2f8a5e46 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst @@ -1,4 +1,4 @@ -.. -*- coding: utf-8 -*- +.. sage-doctest: optional - sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst index d7164e7c363..970a7364b97 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst @@ -1,4 +1,4 @@ -.. -*- coding: utf-8 -*- +.. .. sage-doctest: optional - sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst index bdcff4b9af8..6eea195f37b 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst @@ -1,4 +1,4 @@ -.. -*- coding: utf-8 -*- +.. sage-doctest: optional - sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst index 59c4270badb..ecffbcce490 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst @@ -1,4 +1,4 @@ -.. -*- coding: utf-8 -*- +.. sage-doctest: optional - sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/tutorial/tour_plotting.rst b/src/doc/en/tutorial/tour_plotting.rst index a218f70ff1e..860bd614cb9 100644 --- a/src/doc/en/tutorial/tour_plotting.rst +++ b/src/doc/en/tutorial/tour_plotting.rst @@ -1,3 +1,5 @@ +.. sage-doctest: optional - sage.plot sage.symbolic + .. _section-plot: Plotting diff --git a/src/doc/fr/tutorial/tour_plotting.rst b/src/doc/fr/tutorial/tour_plotting.rst index 6233d33db53..4bf29282fa6 100644 --- a/src/doc/fr/tutorial/tour_plotting.rst +++ b/src/doc/fr/tutorial/tour_plotting.rst @@ -1,3 +1,5 @@ +.. sage-doctest: optional - sage.plot sage.symbolic + .. _section-plot: Graphiques diff --git a/src/doc/ja/tutorial/tour_plotting.rst b/src/doc/ja/tutorial/tour_plotting.rst index 07f65fc3fdf..66b28798152 100644 --- a/src/doc/ja/tutorial/tour_plotting.rst +++ b/src/doc/ja/tutorial/tour_plotting.rst @@ -1,3 +1,5 @@ +.. sage-doctest: optional - sage.plot sage.symbolic + .. _section-plot: プロットする diff --git a/src/doc/pt/tutorial/tour_plotting.rst b/src/doc/pt/tutorial/tour_plotting.rst index 1fb3d910dfc..ee0a6a1992a 100644 --- a/src/doc/pt/tutorial/tour_plotting.rst +++ b/src/doc/pt/tutorial/tour_plotting.rst @@ -1,3 +1,5 @@ +.. sage-doctest: optional - sage.plot sage.symbolic + .. _section-plot: Gráficos diff --git a/src/doc/ru/tutorial/tour_plotting.rst b/src/doc/ru/tutorial/tour_plotting.rst index 76f6c1ef6a3..cb388c9edc5 100644 --- a/src/doc/ru/tutorial/tour_plotting.rst +++ b/src/doc/ru/tutorial/tour_plotting.rst @@ -1,3 +1,5 @@ +.. sage-doctest: optional - sage.plot sage.symbolic + .. _section-plot: Построение графиков From a76ce800b30706cd951de2cfe866de35c0465edb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 8 Jul 2023 17:56:46 -0700 Subject: [PATCH 040/155] src/doc/en/thematic_tutorials/steenrod_algebra_modules.rst: Doctest cosmetics --- .../steenrod_algebra_modules.rst | 139 ++++++++++-------- 1 file changed, 81 insertions(+), 58 deletions(-) diff --git a/src/doc/en/thematic_tutorials/steenrod_algebra_modules.rst b/src/doc/en/thematic_tutorials/steenrod_algebra_modules.rst index f038ff7acaa..6a096608c68 100644 --- a/src/doc/en/thematic_tutorials/steenrod_algebra_modules.rst +++ b/src/doc/en/thematic_tutorials/steenrod_algebra_modules.rst @@ -41,7 +41,8 @@ with relations, the coefficients for each relation is given:: sage: r1 = [Sq(8), Sq(7), 0] # First relation sage: r2 = [Sq(7), 0, 1] # Second relation sage: M = SteenrodFPModule(A, [0, 1, 7], relations=[r1, r2]); M - Finitely presented left module on 3 generators and 2 relations over mod 2 Steenrod algebra, milnor basis + Finitely presented left module on 3 generators and 2 relations + over mod 2 Steenrod algebra, milnor basis The resulting module will have three generators in the degrees we gave them:: @@ -156,8 +157,8 @@ A vector space presentation can be produced:: Vector space quotient V/W of dimension 4 over Finite Field of size 2 where V: Vector space of dimension 4 over Finite Field of size 2 W: Vector space of degree 4 and dimension 0 over Finite Field of size 2 - Basis matrix: - [] + Basis matrix: + [] Given any element, its coordinates with respect to this basis can be computed:: @@ -188,11 +189,13 @@ such homomorphisms using the function ``Hom``:: sage: Hko = SteenrodFPModule(A, [0], [[Sq(2)], [Sq(1)]]) sage: homspace = Hom(Hko, Hko); homspace - Set of Morphisms from Finitely presented left module on 1 generator and 2 relations - over mod 2 Steenrod algebra, milnor basis - to Finitely presented left module on 1 generator and 2 relations - over mod 2 Steenrod algebra, milnor basis - in Category of finitely presented graded modules over mod 2 Steenrod algebra, milnor basis + Set of Morphisms + from Finitely presented left module on 1 generator and 2 relations + over mod 2 Steenrod algebra, milnor basis + to Finitely presented left module on 1 generator and 2 relations + over mod 2 Steenrod algebra, milnor basis + in Category of finitely presented graded modules + over mod 2 Steenrod algebra, milnor basis Just as with module elements, homomorphisms are created using the homspace. The only argument is a list of elements in the codomain, giving the @@ -207,7 +210,8 @@ The resulting homomorphism is the one sending the `i`-th generator of the domain to the `i`-th codomain value given:: sage: f - Module endomorphism of Finitely presented left module on 1 generator and 2 relations over mod 2 Steenrod algebra, milnor basis + Module endomorphism of Finitely presented left module on 1 generator + and 2 relations over mod 2 Steenrod algebra, milnor basis Defn: g[0] |--> Sq(0,0,1)*g[0] Homomorphisms can be evaluated on elements of the domain module:: @@ -232,7 +236,8 @@ Convenience methods exist for creating the trivial morphism:: sage: x == 0 False sage: zero_map = homspace.zero(); zero_map - Module endomorphism of Finitely presented left module on 1 generator and 2 relations over mod 2 Steenrod algebra, milnor basis + Module endomorphism of Finitely presented left module on 1 generator + and 2 relations over mod 2 Steenrod algebra, milnor basis Defn: g[0] |--> 0 sage: zero_map(x) 0 @@ -242,7 +247,8 @@ Convenience methods exist for creating the trivial morphism:: as well as the identity endomorphism:: sage: one = Hom(Hko, Hko).identity(); one - Module endomorphism of Finitely presented left module on 1 generator and 2 relations over mod 2 Steenrod algebra, milnor basis + Module endomorphism of Finitely presented left module on 1 generator + and 2 relations over mod 2 Steenrod algebra, milnor basis Defn: g[0] |--> g[0] sage: one.is_endomorphism() True @@ -271,7 +277,8 @@ Any two homomorphisms can be added as long as they are of the same degree:: sage: (f1 + f2).is_zero() False sage: f1 + f2 - Module endomorphism of Finitely presented left module on 1 generator and 2 relations over mod 2 Steenrod algebra, milnor basis + Module endomorphism of Finitely presented left module on 1 generator + and 2 relations over mod 2 Steenrod algebra, milnor basis Defn: g[0] |--> (Sq(0,0,3)+Sq(0,2,0,1)+Sq(8,2,1))*g[0] or when at least one of them is zero:: @@ -302,32 +309,32 @@ elements is a linear transformation:: [1 0 0 0 0 0] [0 0 0 0 0 0] [1 0 0 0 0 0] - Domain: Vector space quotient V/W of dimension 3 over Finite Field of size 2 where - V: Vector space of dimension 20 over Finite Field of size 2 - W: Vector space of degree 20 and dimension 17 over Finite Field of size 2 - Basis matrix: - [1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] - [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] - [0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] - [0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1] - [0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1] - [0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 1] - [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 1] - [0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 1] - [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] - [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1] - [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] - [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1] - [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1] - [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1] - [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1] - [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] - [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1] + Domain: Vector space quotient V/W of dimension 3 over Finite Field of size 2 where + V: Vector space of dimension 20 over Finite Field of size 2 + W: Vector space of degree 20 and dimension 17 over Finite Field of size 2 + Basis matrix: + [1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] + [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] + [0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] + [0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1] + [0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1] + [0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 1] + [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 1] + [0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 1] + [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1] + [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1] + [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1] + [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1] + [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1] + [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] + [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1] Codomain: Vector space quotient V/W of dimension 6 over Finite Field of size 2 where - V: Vector space of dimension 35 over Finite Field of size 2 - W: Vector space of degree 35 and dimension 29 over Finite Field of size 2 - Basis matrix: - 29 x 35 dense matrix over Finite Field of size 2 + V: Vector space of dimension 35 over Finite Field of size 2 + W: Vector space of degree 35 and dimension 29 over Finite Field of size 2 + Basis matrix: + 29 x 35 dense matrix over Finite Field of size 2 This is compatible with the vector presentations of its domain and codomain modules:: @@ -352,13 +359,13 @@ Elements in the preimage of a homomorphism can be found:: Homomorphisms can be composed as expected:: sage: g = homspace([Sq(0, 0, 0, 1)*gen]); g - Module endomorphism of Finitely presented left module on 1 generator and 2 relations - over mod 2 Steenrod algebra, milnor basis + Module endomorphism of Finitely presented left module on 1 generator + and 2 relations over mod 2 Steenrod algebra, milnor basis Defn: g[0] |--> Sq(0,0,0,1)*g[0] sage: g*f - Module endomorphism of Finitely presented left module on 1 generator and 2 relations - over mod 2 Steenrod algebra, milnor basis + Module endomorphism of Finitely presented left module on 1 generator + and 2 relations over mod 2 Steenrod algebra, milnor basis Defn: g[0] |--> Sq(0,0,1,1)*g[0] sage: one = homspace.identity() @@ -412,13 +419,15 @@ homomorphism of free modules. We then construct a candidate for an isomorphism and check that it is both injective and surjective:: sage: HZ = SteenrodFPModule(A, [0], [[Sq(1)]]); HZ - Finitely presented left module on 1 generator and 1 relation over mod 2 Steenrod algebra, milnor basis + Finitely presented left module on 1 generator and 1 relation + over mod 2 Steenrod algebra, milnor basis sage: F = SteenrodFPModule(A, [0]) sage: j = Hom(F, F)([Sq(1)*F.generator(0)]) - sage: coker = j.cokernel_projection() # the natural quotient homomorphism onto the cokernel. + sage: coker = j.cokernel_projection() # the natural quotient homomorphism onto the cokernel. sage: hz = coker.codomain(); hz - Finitely presented left module on 1 generator and 1 relation over mod 2 Steenrod algebra, milnor basis + Finitely presented left module on 1 generator and 1 relation + over mod 2 Steenrod algebra, milnor basis sage: a = Hom(HZ, hz)([hz.generator(0)]) sage: a.is_injective() @@ -435,8 +444,10 @@ injective homomorphism into the domain of `f`:: sage: k = f.kernel_inclusion(); k Module morphism: - From: Finitely presented left module on 1 generator and 3 relations over mod 2 Steenrod algebra, milnor basis - To: Finitely presented left module on 1 generator and 2 relations over mod 2 Steenrod algebra, milnor basis + From: Finitely presented left module on 1 generator and 3 relations + over mod 2 Steenrod algebra, milnor basis + To: Finitely presented left module on 1 generator and 2 relations + over mod 2 Steenrod algebra, milnor basis Defn: g[7] |--> Sq(0,0,1)*g[0] sage: k.codomain() == f.domain() True @@ -445,7 +456,8 @@ injective homomorphism into the domain of `f`:: sage: ker = k.domain() sage: ker - Finitely presented left module on 1 generator and 3 relations over mod 2 Steenrod algebra, milnor basis + Finitely presented left module on 1 generator and 3 relations + over mod 2 Steenrod algebra, milnor basis We can check that the injective image of `k` is the kernel of `f` by showing that `f` factors as `h\circ c`, where `c` is the quotient map @@ -470,8 +482,10 @@ equal to the submodule `\operatorname{im}(f)`:: sage: i = f.image(); i Module morphism: - From: Finitely presented left module on 1 generator and 3 relations over mod 2 Steenrod algebra, milnor basis - To: Finitely presented left module on 1 generator and 2 relations over mod 2 Steenrod algebra, milnor basis + From: Finitely presented left module on 1 generator and 3 relations + over mod 2 Steenrod algebra, milnor basis + To: Finitely presented left module on 1 generator and 2 relations + over mod 2 Steenrod algebra, milnor basis Defn: g[7] |--> Sq(0,0,1)*g[0] sage: i.codomain() == f.codomain() True @@ -483,8 +497,10 @@ lifting `f` over `i`, and showing that the lift is surjective:: sage: f_ = f.lift(i); f_ Module morphism: - From: Finitely presented left module on 1 generator and 2 relations over mod 2 Steenrod algebra, milnor basis - To: Finitely presented left module on 1 generator and 3 relations over mod 2 Steenrod algebra, milnor basis + From: Finitely presented left module on 1 generator and 2 relations + over mod 2 Steenrod algebra, milnor basis + To: Finitely presented left module on 1 generator and 3 relations + over mod 2 Steenrod algebra, milnor basis Defn: g[0] |--> g[7] sage: i*f_ == f # Is im(i) contained in im(f) ? True @@ -501,7 +517,8 @@ domain `\ker(g)`:: sage: K = f.kernel_inclusion() # k: ker(f) -> Hko sage: h = f.homology(f) # h: ker(f) -> ker(f) / im(f) sage: h.codomain() # This is the homology module. - Finitely presented left module on 1 generator and 4 relations over mod 2 Steenrod algebra, milnor basis + Finitely presented left module on 1 generator and 4 relations + over mod 2 Steenrod algebra, milnor basis Free resolutions @@ -632,8 +649,10 @@ The projection:: sage: q = Hom(HZ, Hko)([Hko.generator(0)]) sage: q Module morphism: - From: Finitely presented left module on 1 generator and 1 relation over mod 2 Steenrod algebra, milnor basis - To: Finitely presented left module on 1 generator and 2 relations over mod 2 Steenrod algebra, milnor basis + From: Finitely presented left module on 1 generator and 1 relation + over mod 2 Steenrod algebra, milnor basis + To: Finitely presented left module on 1 generator and 2 relations + over mod 2 Steenrod algebra, milnor basis Defn: g[0] |--> g[0] The map to lift over `q`:: @@ -641,8 +660,10 @@ The map to lift over `q`:: sage: f = Hom(L, Hko)([Sq(0,2,1,1)*Hko.generator(0)]) sage: f Module morphism: - From: Finitely presented left module on 1 generator and 2 relations over mod 2 Steenrod algebra, milnor basis - To: Finitely presented left module on 1 generator and 2 relations over mod 2 Steenrod algebra, milnor basis + From: Finitely presented left module on 1 generator and 2 relations + over mod 2 Steenrod algebra, milnor basis + To: Finitely presented left module on 1 generator and 2 relations + over mod 2 Steenrod algebra, milnor basis Defn: g[28] |--> Sq(0,2,1,1)*g[0] sage: f.is_zero() # f is non-trivial. @@ -703,8 +724,10 @@ Start by finding a single lift of `f` over the projection `q`:: sage: fl = f.lift(q); fl Module morphism: - From: Finitely presented left module on 1 generator and 2 relations over mod 2 Steenrod algebra, milnor basis - To: Finitely presented left module on 1 generator and 1 relation over mod 2 Steenrod algebra, milnor basis + From: Finitely presented left module on 1 generator and 2 relations + over mod 2 Steenrod algebra, milnor basis + To: Finitely presented left module on 1 generator and 1 relation + over mod 2 Steenrod algebra, milnor basis Defn: g[28] |--> (Sq(4,3,0,1)+Sq(6,0,1,1)+Sq(7,2,0,1)+Sq(10,1,0,1))*g[0] We verify that ``fl`` is indeed a lift:: From 6251ad50895c8af97c3306bc2b622a02c701f49f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 8 Nov 2023 14:05:56 -0800 Subject: [PATCH 041/155] sage -fixdoctests --no-test src/doc --- .../geometry/polyhedra_tutorial.rst | 58 ++++++++--------- .../numerical_sage/cvxopt.rst | 64 +++++++++---------- src/doc/es/tutorial/tour_rings.rst | 2 +- 3 files changed, 62 insertions(+), 62 deletions(-) diff --git a/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst b/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst index b7d689e5ca3..78c75616f49 100644 --- a/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst +++ b/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst @@ -163,22 +163,22 @@ The following example demonstrates the limitations of :code:`RDF`. :: - sage: D = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: D # optional - sage.rings.number_field + sage: D = polytopes.dodecahedron() # needs sage.rings.number_field + sage: D # needs sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^3 defined as the convex hull of 20 vertices - sage: vertices_RDF = [n(v.vector(),digits=6) for v in D.vertices()] # optional - sage.rings.number_field - sage: D_RDF = Polyhedron(vertices=vertices_RDF, base_ring=RDF) # optional - sage.rings.number_field + sage: vertices_RDF = [n(v.vector(),digits=6) for v in D.vertices()] # needs sage.rings.number_field + sage: D_RDF = Polyhedron(vertices=vertices_RDF, base_ring=RDF) # needs sage.rings.number_field doctest:warning ... UserWarning: This polyhedron data is numerically complicated; cdd could not convert between the inexact V and H representation without loss of data. The resulting object might show inconsistencies. - sage: D_RDF = Polyhedron(vertices=sorted(vertices_RDF), base_ring=RDF) # optional - sage.rings.number_field + sage: D_RDF = Polyhedron(vertices=sorted(vertices_RDF), base_ring=RDF) # needs sage.rings.number_field Traceback (most recent call last): ... ValueError: *Error: Numerical inconsistency is found. Use the GMP exact arithmetic. @@ -199,11 +199,11 @@ It is also possible to define a polyhedron over algebraic numbers. :: - sage: sqrt_2 = AA(2)^(1/2) # optional - sage.rings.number_field - sage: cbrt_2 = AA(2)^(1/3) # optional - sage.rings.number_field - sage: timeit('Polyhedron(vertices = [[sqrt_2, 0], [0, cbrt_2]])') # optional - sage.rings.number_field # random + sage: sqrt_2 = AA(2)^(1/2) # needs sage.rings.number_field + sage: cbrt_2 = AA(2)^(1/3) # needs sage.rings.number_field + sage: timeit('Polyhedron(vertices = [[sqrt_2, 0], [0, cbrt_2]])') # needs sage.rings.number_field 5 loops, best of 3: 43.2 ms per loop - sage: P4 = Polyhedron(vertices = [[sqrt_2, 0], [0, cbrt_2]]); P4 # optional - sage.rings.number_field + sage: P4 = Polyhedron(vertices = [[sqrt_2, 0], [0, cbrt_2]]); P4 # needs sage.rings.number_field A 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices .. end of output @@ -212,11 +212,11 @@ There is another way to create a polyhedron over algebraic numbers: :: - sage: K. = NumberField(x^2 - 2, embedding=AA(2)**(1/2)) # optional - sage.rings.number_field - sage: L. = NumberField(x^3 - 2, embedding=AA(2)**(1/3)) # optional - sage.rings.number_field - sage: timeit('Polyhedron(vertices = [[a, 0], [0, b]])') # optional - sage.rings.number_field # random + sage: K. = NumberField(x^2 - 2, embedding=AA(2)**(1/2)) # needs sage.rings.number_field + sage: L. = NumberField(x^3 - 2, embedding=AA(2)**(1/3)) # needs sage.rings.number_field + sage: timeit('Polyhedron(vertices = [[a, 0], [0, b]])') # needs sage.rings.number_field 5 loops, best of 3: 39.9 ms per loop - sage: P5 = Polyhedron(vertices = [[a, 0], [0, b]]); P5 # optional - sage.rings.number_field + sage: P5 = Polyhedron(vertices = [[a, 0], [0, b]]); P5 # needs sage.rings.number_field A 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices .. end of output @@ -225,10 +225,10 @@ If the base ring is known it may be a good option to use the proper :meth:`sage. :: - sage: J = K.composite_fields(L)[0] # optional - sage.rings.number_field - sage: timeit('Polyhedron(vertices = [[J(a), 0], [0, J(b)]])') # optional - sage.rings.number_field # random + sage: J = K.composite_fields(L)[0] # needs sage.rings.number_field + sage: timeit('Polyhedron(vertices = [[J(a), 0], [0, J(b)]])') # needs sage.rings.number_field 25 loops, best of 3: 9.8 ms per loop - sage: P5_comp = Polyhedron(vertices = [[J(a), 0], [0, J(b)]]); P5_comp # optional - sage.rings.number_field + sage: P5_comp = Polyhedron(vertices = [[J(a), 0], [0, J(b)]]); P5_comp # needs sage.rings.number_field A 1-dimensional polyhedron in (Number Field in ab with defining polynomial x^6 - 6*x^4 - 4*x^3 + 12*x^2 - 24*x - 4 @@ -242,9 +242,9 @@ It is not possible to define a polyhedron over it: :: - sage: sqrt_2s = sqrt(2) # optional - sage.symbolic - sage: cbrt_2s = 2^(1/3) # optional - sage.symbolic - sage: Polyhedron(vertices = [[sqrt_2s, 0], [0, cbrt_2s]]) # optional - sage.symbolic + sage: sqrt_2s = sqrt(2) # needs sage.symbolic + sage: cbrt_2s = 2^(1/3) # needs sage.symbolic + sage: Polyhedron(vertices = [[sqrt_2s, 0], [0, cbrt_2s]]) # needs sage.symbolic Traceback (most recent call last): ... ValueError: no default backend for computations with Symbolic Ring @@ -577,12 +577,12 @@ but not algebraic or symbolic values: :: - sage: P4_cdd = Polyhedron(vertices = [[sqrt_2, 0], [0, cbrt_2]], backend='cdd') # optional - sage.rings.number_field + sage: P4_cdd = Polyhedron(vertices = [[sqrt_2, 0], [0, cbrt_2]], backend='cdd') # needs sage.rings.number_field Traceback (most recent call last): ... ValueError: No such backend (=cdd) implemented for given basering (=Algebraic Real Field). - sage: P5_cdd = Polyhedron(vertices = [[sqrt_2s, 0], [0, cbrt_2s]], backend='cdd') # optional - sage.symbolic + sage: P5_cdd = Polyhedron(vertices = [[sqrt_2s, 0], [0, cbrt_2s]], backend='cdd') # needs sage.symbolic Traceback (most recent call last): ... ValueError: No such backend (=cdd) implemented for given basering (=Symbolic Ring). @@ -656,8 +656,8 @@ An example with quadratic field: :: - sage: V = polytopes.dodecahedron().vertices_list() # optional - sage.rings.number_field - sage: Polyhedron(vertices=V, backend='polymake') # optional - jupymake # optional - sage.rings.number_field + sage: V = polytopes.dodecahedron().vertices_list() # needs sage.rings.number_field + sage: Polyhedron(vertices=V, backend='polymake') # optional - jupymake # needs sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^3 @@ -681,7 +681,7 @@ examples. :: - sage: type(D) # optional - sage.rings.number_field + sage: type(D) # needs sage.rings.number_field .. end of output @@ -691,13 +691,13 @@ backend :code:`field` is called. :: - sage: P4.parent() # optional - sage.rings.number_field + sage: P4.parent() # needs sage.rings.number_field Polyhedra in AA^2 - sage: P5.parent() # optional - sage.rings.number_field + sage: P5.parent() # needs sage.rings.number_field Polyhedra in AA^2 - sage: type(P4) # optional - sage.rings.number_field + sage: type(P4) # needs sage.rings.number_field - sage: type(P5) # optional - sage.rings.number_field + sage: type(P5) # needs sage.rings.number_field .. end of output @@ -788,7 +788,7 @@ polytope is already defined! :: - sage: A = polytopes.buckyball(); A # can take long # optional - sage.rings.number_field + sage: A = polytopes.buckyball(); A # can take long # needs sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^3 diff --git a/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst b/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst index ba6cfb5fb86..c79469010e9 100644 --- a/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst +++ b/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst @@ -28,15 +28,15 @@ by :: - sage: import numpy # optional - cvxopt - sage: from cvxopt.base import spmatrix # optional - cvxopt - sage: from cvxopt.base import matrix as m # optional - cvxopt - sage: from cvxopt import umfpack # optional - cvxopt - sage: Integer = int # optional - cvxopt - sage: V = [2,3, 3,-1,4, 4,-3,1,2, 2, 6,1] # optional - cvxopt - sage: I = [0,1, 0, 2,4, 1, 2,3,4, 2, 1,4] # optional - cvxopt - sage: J = [0,0, 1, 1,1, 2, 2,2,2, 3, 4,4] # optional - cvxopt - sage: A = spmatrix(V,I,J) # optional - cvxopt + sage: import numpy # needs cvxopt + sage: from cvxopt.base import spmatrix # needs cvxopt + sage: from cvxopt.base import matrix as m # needs cvxopt + sage: from cvxopt import umfpack # needs cvxopt + sage: Integer = int # needs cvxopt + sage: V = [2,3, 3,-1,4, 4,-3,1,2, 2, 6,1] # needs cvxopt + sage: I = [0,1, 0, 2,4, 1, 2,3,4, 2, 1,4] # needs cvxopt + sage: J = [0,0, 1, 1,1, 2, 2,2,2, 3, 4,4] # needs cvxopt + sage: A = spmatrix(V,I,J) # needs cvxopt To solve an equation :math:`AX=B`, with :math:`B=[1,1,1,1,1]`, we could do the following. @@ -45,9 +45,9 @@ we could do the following. :: - sage: B = numpy.array([1.0]*5) # optional - cvxopt - sage: B.shape=(5,1) # optional - cvxopt - sage: print(B) # optional - cvxopt + sage: B = numpy.array([1.0]*5) # needs cvxopt + sage: B.shape=(5,1) # needs cvxopt + sage: print(B) # needs cvxopt [[1.] [1.] [1.] @@ -55,15 +55,15 @@ we could do the following. [1.]] - sage: print(A) # optional - cvxopt + sage: print(A) # needs cvxopt [ 2.00e+00 3.00e+00 0 0 0 ] [ 3.00e+00 0 4.00e+00 0 6.00e+00] [ 0 -1.00e+00 -3.00e+00 2.00e+00 0 ] [ 0 0 1.00e+00 0 0 ] [ 0 4.00e+00 2.00e+00 0 1.00e+00] - sage: C = m(B) # optional - cvxopt - sage: umfpack.linsolve(A,C) # optional - cvxopt - sage: print(C) # optional - cvxopt + sage: C = m(B) # needs cvxopt + sage: umfpack.linsolve(A,C) # needs cvxopt + sage: print(C) # needs cvxopt [ 5.79e-01] [-5.26e-02] [ 1.00e+00] @@ -81,13 +81,13 @@ We could compute the approximate minimum degree ordering by doing :: - sage: RealNumber = float # optional - cvxopt - sage: Integer = int # optional - cvxopt - sage: from cvxopt.base import spmatrix # optional - cvxopt - sage: from cvxopt import amd # optional - cvxopt - sage: A = spmatrix([10,3,5,-2,5,2],[0,2,1,2,2,3],[0,0,1,1,2,3]) # optional - cvxopt - sage: P = amd.order(A) # optional - cvxopt - sage: print(P) # optional - cvxopt + sage: RealNumber = float # needs cvxopt + sage: Integer = int # needs cvxopt + sage: from cvxopt.base import spmatrix # needs cvxopt + sage: from cvxopt import amd # needs cvxopt + sage: A = spmatrix([10,3,5,-2,5,2],[0,2,1,2,2,3],[0,0,1,1,2,3]) # needs cvxopt + sage: P = amd.order(A) # needs cvxopt + sage: print(P) # needs cvxopt [ 1] [ 0] [ 2] @@ -108,14 +108,14 @@ For a simple linear programming example, if we want to solve :: - sage: RealNumber = float # optional - cvxopt - sage: Integer = int # optional - cvxopt - sage: from cvxopt.base import matrix as m # optional - cvxopt - sage: from cvxopt import solvers # optional - cvxopt - sage: c = m([-4., -5.]) # optional - cvxopt - sage: G = m([[2., 1., -1., 0.], [1., 2., 0., -1.]]) # optional - cvxopt - sage: h = m([3., 3., 0., 0.]) # optional - cvxopt - sage: sol = solvers.lp(c,G,h) # random # optional - cvxopt + sage: RealNumber = float # needs cvxopt + sage: Integer = int # needs cvxopt + sage: from cvxopt.base import matrix as m # needs cvxopt + sage: from cvxopt import solvers # needs cvxopt + sage: c = m([-4., -5.]) # needs cvxopt + sage: G = m([[2., 1., -1., 0.], [1., 2., 0., -1.]]) # needs cvxopt + sage: h = m([3., 3., 0., 0.]) # needs cvxopt + sage: sol = solvers.lp(c,G,h) # random # needs cvxopt pcost dcost gap pres dres k/t 0: -8.1000e+00 -1.8300e+01 4e+00 0e+00 8e-01 1e+00 1: -8.8055e+00 -9.4357e+00 2e-01 1e-16 4e-02 3e-02 @@ -127,6 +127,6 @@ For a simple linear programming example, if we want to solve :: - sage: print(sol['x']) # optional - cvxopt # ... below since can get -00 or +00 depending on architecture + sage: print(sol['x']) # needs cvxopt [ 1.00e...00] [ 1.00e+00] diff --git a/src/doc/es/tutorial/tour_rings.rst b/src/doc/es/tutorial/tour_rings.rst index 1bdee618525..fd7af3f72d2 100644 --- a/src/doc/es/tutorial/tour_rings.rst +++ b/src/doc/es/tutorial/tour_rings.rst @@ -131,7 +131,7 @@ y anillos de matrices. Veamos algunos de estos anillos:: sage: GF(3) Finite Field of size 3 sage: # es necesario dar un nombre al generador si el número - sage: GF(27, 'a') # de elementos no es primo + sage: GF(27, 'a') # de elementos no es primo Finite Field in a of size 3^3 sage: Zp(5) 5-adic Ring with capped relative precision 20 From 77a3544aed27887e6dd81302462309b5f2d96e45 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 8 Nov 2023 14:12:14 -0800 Subject: [PATCH 042/155] sage -fixdoctests --only-tags src/doc --- .../Statistics-and-Distributions.rst | 13 ++-- .../geometry/polyhedra_tutorial.rst | 45 +++++++------- .../numerical_sage/cvxopt.rst | 60 ++++++++++--------- 3 files changed, 64 insertions(+), 54 deletions(-) diff --git a/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst b/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst index ed7eed79dfc..0a76a3024ec 100644 --- a/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst +++ b/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst @@ -142,13 +142,14 @@ the examples in ``r.kruskal_test?`` in the notebook. :: - sage: x=r([2.9, 3.0, 2.5, 2.6, 3.2]) # normal subjects # optional - rpy2 - sage: y=r([3.8, 2.7, 4.0, 2.4]) # with obstructive airway disease # optional - rpy2 - sage: z=r([2.8, 3.4, 3.7, 2.2, 2.0]) # with asbestosis # optional - rpy2 - sage: a = r([x,y,z]) # make a long R vector of all the data # optional - rpy2 - sage: b = r.factor(5*[1]+4*[2]+5*[3]) # create something for R to tell # optional - rpy2 + sage: # optional - rpy2 + sage: x=r([2.9, 3.0, 2.5, 2.6, 3.2]) # normal subjects + sage: y=r([3.8, 2.7, 4.0, 2.4]) # with obstructive airway disease + sage: z=r([2.8, 3.4, 3.7, 2.2, 2.0]) # with asbestosis + sage: a = r([x,y,z]) # make a long R vector of all the data + sage: b = r.factor(5*[1]+4*[2]+5*[3]) # create something for R to tell ....: # which subjects are which - sage: a; b # show them # optional - rpy2 + sage: a; b # show them [1] 2.9 3.0 2.5 2.6 3.2 3.8 2.7 4.0 2.4 2.8 3.4 3.7 2.2 2.0 [1] 1 1 1 1 1 2 2 2 2 3 3 3 3 3 Levels: 1 2 3 diff --git a/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst b/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst index 78c75616f49..8d3a137c2c0 100644 --- a/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst +++ b/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst @@ -199,11 +199,12 @@ It is also possible to define a polyhedron over algebraic numbers. :: - sage: sqrt_2 = AA(2)^(1/2) # needs sage.rings.number_field - sage: cbrt_2 = AA(2)^(1/3) # needs sage.rings.number_field - sage: timeit('Polyhedron(vertices = [[sqrt_2, 0], [0, cbrt_2]])') # needs sage.rings.number_field + sage: # needs sage.rings.number_field + sage: sqrt_2 = AA(2)^(1/2) + sage: cbrt_2 = AA(2)^(1/3) + sage: timeit('Polyhedron(vertices = [[sqrt_2, 0], [0, cbrt_2]])') 5 loops, best of 3: 43.2 ms per loop - sage: P4 = Polyhedron(vertices = [[sqrt_2, 0], [0, cbrt_2]]); P4 # needs sage.rings.number_field + sage: P4 = Polyhedron(vertices = [[sqrt_2, 0], [0, cbrt_2]]); P4 A 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices .. end of output @@ -212,11 +213,12 @@ There is another way to create a polyhedron over algebraic numbers: :: - sage: K. = NumberField(x^2 - 2, embedding=AA(2)**(1/2)) # needs sage.rings.number_field - sage: L. = NumberField(x^3 - 2, embedding=AA(2)**(1/3)) # needs sage.rings.number_field - sage: timeit('Polyhedron(vertices = [[a, 0], [0, b]])') # needs sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = NumberField(x^2 - 2, embedding=AA(2)**(1/2)) + sage: L. = NumberField(x^3 - 2, embedding=AA(2)**(1/3)) + sage: timeit('Polyhedron(vertices = [[a, 0], [0, b]])') 5 loops, best of 3: 39.9 ms per loop - sage: P5 = Polyhedron(vertices = [[a, 0], [0, b]]); P5 # needs sage.rings.number_field + sage: P5 = Polyhedron(vertices = [[a, 0], [0, b]]); P5 A 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices .. end of output @@ -691,13 +693,14 @@ backend :code:`field` is called. :: - sage: P4.parent() # needs sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P4.parent() Polyhedra in AA^2 - sage: P5.parent() # needs sage.rings.number_field + sage: P5.parent() Polyhedra in AA^2 - sage: type(P4) # needs sage.rings.number_field + sage: type(P4) - sage: type(P5) # needs sage.rings.number_field + sage: type(P5) .. end of output @@ -709,13 +712,14 @@ The fourth backend is :code:`normaliz` and is an optional Sage package. :: - sage: P1_normaliz = Polyhedron(vertices = [[1, 0], [0, 1]], rays = [[1, 1]], backend='normaliz') # optional - pynormaliz - sage: type(P1_normaliz) # optional - pynormaliz + sage: # optional - pynormaliz + sage: P1_normaliz = Polyhedron(vertices = [[1, 0], [0, 1]], rays = [[1, 1]], backend='normaliz') + sage: type(P1_normaliz) - sage: P2_normaliz = Polyhedron(vertices = [[1/2, 0, 0], [0, 1/2, 0]], # optional - pynormaliz + sage: P2_normaliz = Polyhedron(vertices = [[1/2, 0, 0], [0, 1/2, 0]], ....: rays = [[1, 1, 0]], ....: lines = [[0, 0, 1]], backend='normaliz') - sage: type(P2_normaliz) # optional - pynormaliz + sage: type(P2_normaliz) .. end of output @@ -753,12 +757,13 @@ The backend :code:`normaliz` provides other methods such as :: - sage: P6 = Polyhedron(vertices = [[0, 0], [3/2, 0], [3/2, 3/2], [0, 3]], backend='normaliz') # optional - pynormaliz - sage: IH = P6.integral_hull(); IH # optional - pynormaliz + sage: # optional - pynormaliz + sage: P6 = Polyhedron(vertices = [[0, 0], [3/2, 0], [3/2, 3/2], [0, 3]], backend='normaliz') + sage: IH = P6.integral_hull(); IH A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices - sage: P6.plot(color='blue')+IH.plot(color='red') # optional - pynormaliz + sage: P6.plot(color='blue')+IH.plot(color='red') Graphics object consisting of 12 graphics primitives - sage: P1_normaliz.integral_hull() # optional - pynormaliz + sage: P1_normaliz.integral_hull() A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 1 ray .. end of output diff --git a/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst b/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst index c79469010e9..c71f2445a5e 100644 --- a/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst +++ b/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst @@ -28,15 +28,16 @@ by :: - sage: import numpy # needs cvxopt - sage: from cvxopt.base import spmatrix # needs cvxopt - sage: from cvxopt.base import matrix as m # needs cvxopt - sage: from cvxopt import umfpack # needs cvxopt - sage: Integer = int # needs cvxopt - sage: V = [2,3, 3,-1,4, 4,-3,1,2, 2, 6,1] # needs cvxopt - sage: I = [0,1, 0, 2,4, 1, 2,3,4, 2, 1,4] # needs cvxopt - sage: J = [0,0, 1, 1,1, 2, 2,2,2, 3, 4,4] # needs cvxopt - sage: A = spmatrix(V,I,J) # needs cvxopt + sage: # needs cvxopt + sage: import numpy + sage: from cvxopt.base import spmatrix + sage: from cvxopt.base import matrix as m + sage: from cvxopt import umfpack + sage: Integer = int + sage: V = [2,3, 3,-1,4, 4,-3,1,2, 2, 6,1] + sage: I = [0,1, 0, 2,4, 1, 2,3,4, 2, 1,4] + sage: J = [0,0, 1, 1,1, 2, 2,2,2, 3, 4,4] + sage: A = spmatrix(V,I,J) To solve an equation :math:`AX=B`, with :math:`B=[1,1,1,1,1]`, we could do the following. @@ -55,15 +56,16 @@ we could do the following. [1.]] - sage: print(A) # needs cvxopt + sage: # needs cvxopt + sage: print(A) [ 2.00e+00 3.00e+00 0 0 0 ] [ 3.00e+00 0 4.00e+00 0 6.00e+00] [ 0 -1.00e+00 -3.00e+00 2.00e+00 0 ] [ 0 0 1.00e+00 0 0 ] [ 0 4.00e+00 2.00e+00 0 1.00e+00] - sage: C = m(B) # needs cvxopt - sage: umfpack.linsolve(A,C) # needs cvxopt - sage: print(C) # needs cvxopt + sage: C = m(B) + sage: umfpack.linsolve(A,C) + sage: print(C) [ 5.79e-01] [-5.26e-02] [ 1.00e+00] @@ -81,13 +83,14 @@ We could compute the approximate minimum degree ordering by doing :: - sage: RealNumber = float # needs cvxopt - sage: Integer = int # needs cvxopt - sage: from cvxopt.base import spmatrix # needs cvxopt - sage: from cvxopt import amd # needs cvxopt - sage: A = spmatrix([10,3,5,-2,5,2],[0,2,1,2,2,3],[0,0,1,1,2,3]) # needs cvxopt - sage: P = amd.order(A) # needs cvxopt - sage: print(P) # needs cvxopt + sage: # needs cvxopt + sage: RealNumber = float + sage: Integer = int + sage: from cvxopt.base import spmatrix + sage: from cvxopt import amd + sage: A = spmatrix([10,3,5,-2,5,2],[0,2,1,2,2,3],[0,0,1,1,2,3]) + sage: P = amd.order(A) + sage: print(P) [ 1] [ 0] [ 2] @@ -108,14 +111,15 @@ For a simple linear programming example, if we want to solve :: - sage: RealNumber = float # needs cvxopt - sage: Integer = int # needs cvxopt - sage: from cvxopt.base import matrix as m # needs cvxopt - sage: from cvxopt import solvers # needs cvxopt - sage: c = m([-4., -5.]) # needs cvxopt - sage: G = m([[2., 1., -1., 0.], [1., 2., 0., -1.]]) # needs cvxopt - sage: h = m([3., 3., 0., 0.]) # needs cvxopt - sage: sol = solvers.lp(c,G,h) # random # needs cvxopt + sage: # needs cvxopt + sage: RealNumber = float + sage: Integer = int + sage: from cvxopt.base import matrix as m + sage: from cvxopt import solvers + sage: c = m([-4., -5.]) + sage: G = m([[2., 1., -1., 0.], [1., 2., 0., -1.]]) + sage: h = m([3., 3., 0., 0.]) + sage: sol = solvers.lp(c,G,h) # random pcost dcost gap pres dres k/t 0: -8.1000e+00 -1.8300e+01 4e+00 0e+00 8e-01 1e+00 1: -8.8055e+00 -9.4357e+00 2e-01 1e-16 4e-02 3e-02 From e0b5177babed3c2cfb7b34356b6af4a0b1b464f7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 8 Nov 2023 14:15:55 -0800 Subject: [PATCH 043/155] src/doc: Update file-level doctest tags --- src/doc/de/tutorial/tour_plotting.rst | 2 +- src/doc/en/developer/packaging_sage_library.rst | 2 +- src/doc/en/prep/Calculus.rst | 2 +- src/doc/en/prep/Quickstarts/Differential-Equations.rst | 2 +- src/doc/en/prep/Symbolics-and-Basic-Plotting.rst | 2 +- .../thematic_tutorials/vector_calculus/vector_calc_advanced.rst | 2 +- .../vector_calculus/vector_calc_cartesian.rst | 2 +- .../thematic_tutorials/vector_calculus/vector_calc_change.rst | 2 +- .../vector_calculus/vector_calc_curvilinear.rst | 2 +- .../en/thematic_tutorials/vector_calculus/vector_calc_plane.rst | 2 +- src/doc/en/tutorial/tour_plotting.rst | 2 +- src/doc/fr/tutorial/tour_plotting.rst | 2 +- src/doc/ja/tutorial/tour_plotting.rst | 2 +- src/doc/pt/tutorial/tour_plotting.rst | 2 +- src/doc/ru/tutorial/tour_plotting.rst | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/doc/de/tutorial/tour_plotting.rst b/src/doc/de/tutorial/tour_plotting.rst index c91403bc937..495c5a6943b 100644 --- a/src/doc/de/tutorial/tour_plotting.rst +++ b/src/doc/de/tutorial/tour_plotting.rst @@ -1,4 +1,4 @@ -.. sage-doctest: optional - sage.plot sage.symbolic +.. sage-doctest: needs sage.plot sage.symbolic .. _section-plot: diff --git a/src/doc/en/developer/packaging_sage_library.rst b/src/doc/en/developer/packaging_sage_library.rst index 0244d96e5ac..44d169c9518 100644 --- a/src/doc/en/developer/packaging_sage_library.rst +++ b/src/doc/en/developer/packaging_sage_library.rst @@ -423,7 +423,7 @@ Apparently it does not in a very substantial way: merely a heuristic. Looking at the source of "entropy", through ``log`` from :mod:`sage.misc.functional`, a runtime dependency on symbolics comes in. In fact, for this reason, two doctests there are - already marked as ``# optional - sage.symbolic``. + already marked as ``# needs sage.symbolic``. So if packaged as **sagemath-coding**, now a domain expert would have to decide whether these dependencies on symbolics are strong enough to diff --git a/src/doc/en/prep/Calculus.rst b/src/doc/en/prep/Calculus.rst index 77821db1e57..c2f636be558 100644 --- a/src/doc/en/prep/Calculus.rst +++ b/src/doc/en/prep/Calculus.rst @@ -1,4 +1,4 @@ -.. sage-doctest: optional - sage.plot sage.symbolic +.. sage-doctest: needs sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/prep/Quickstarts/Differential-Equations.rst b/src/doc/en/prep/Quickstarts/Differential-Equations.rst index 7c6d4c93d73..94964ccc0a7 100644 --- a/src/doc/en/prep/Quickstarts/Differential-Equations.rst +++ b/src/doc/en/prep/Quickstarts/Differential-Equations.rst @@ -1,4 +1,4 @@ -.. sage-doctest: optional - sage.plot sage.symbolic +.. sage-doctest: needs sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst b/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst index 89036f5a0e0..3bc9308669b 100644 --- a/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst +++ b/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst @@ -1,4 +1,4 @@ -.. sage-doctest: optional - sage.plot sage.symbolic +.. sage-doctest: needs sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_advanced.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_advanced.rst index ca7d466ad98..7bd9934cffd 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_advanced.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_advanced.rst @@ -1,4 +1,4 @@ -.. sage-doctest: optional - sage.plot sage.symbolic +.. sage-doctest: needs sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst index 24c2f8a5e46..51300f93bc1 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst @@ -1,4 +1,4 @@ -.. sage-doctest: optional - sage.plot sage.symbolic +.. sage-doctest: needs sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst index 970a7364b97..029c5727435 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst @@ -1,4 +1,4 @@ -.. .. sage-doctest: optional - sage.plot sage.symbolic +.. .. sage-doctest: needs sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst index 6eea195f37b..af11769e274 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst @@ -1,4 +1,4 @@ -.. sage-doctest: optional - sage.plot sage.symbolic +.. sage-doctest: needs sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst index ecffbcce490..921724105a0 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst @@ -1,4 +1,4 @@ -.. sage-doctest: optional - sage.plot sage.symbolic +.. sage-doctest: needs sage.plot sage.symbolic .. linkall diff --git a/src/doc/en/tutorial/tour_plotting.rst b/src/doc/en/tutorial/tour_plotting.rst index 860bd614cb9..ad861c3ca56 100644 --- a/src/doc/en/tutorial/tour_plotting.rst +++ b/src/doc/en/tutorial/tour_plotting.rst @@ -1,4 +1,4 @@ -.. sage-doctest: optional - sage.plot sage.symbolic +.. sage-doctest: needs sage.plot sage.symbolic .. _section-plot: diff --git a/src/doc/fr/tutorial/tour_plotting.rst b/src/doc/fr/tutorial/tour_plotting.rst index 4bf29282fa6..3815125ed19 100644 --- a/src/doc/fr/tutorial/tour_plotting.rst +++ b/src/doc/fr/tutorial/tour_plotting.rst @@ -1,4 +1,4 @@ -.. sage-doctest: optional - sage.plot sage.symbolic +.. sage-doctest: needs sage.plot sage.symbolic .. _section-plot: diff --git a/src/doc/ja/tutorial/tour_plotting.rst b/src/doc/ja/tutorial/tour_plotting.rst index 66b28798152..baf450fd6eb 100644 --- a/src/doc/ja/tutorial/tour_plotting.rst +++ b/src/doc/ja/tutorial/tour_plotting.rst @@ -1,4 +1,4 @@ -.. sage-doctest: optional - sage.plot sage.symbolic +.. sage-doctest: needs sage.plot sage.symbolic .. _section-plot: diff --git a/src/doc/pt/tutorial/tour_plotting.rst b/src/doc/pt/tutorial/tour_plotting.rst index ee0a6a1992a..dacf25e063b 100644 --- a/src/doc/pt/tutorial/tour_plotting.rst +++ b/src/doc/pt/tutorial/tour_plotting.rst @@ -1,4 +1,4 @@ -.. sage-doctest: optional - sage.plot sage.symbolic +.. sage-doctest: needs sage.plot sage.symbolic .. _section-plot: diff --git a/src/doc/ru/tutorial/tour_plotting.rst b/src/doc/ru/tutorial/tour_plotting.rst index cb388c9edc5..f4a755e412e 100644 --- a/src/doc/ru/tutorial/tour_plotting.rst +++ b/src/doc/ru/tutorial/tour_plotting.rst @@ -1,4 +1,4 @@ -.. sage-doctest: optional - sage.plot sage.symbolic +.. sage-doctest: needs sage.plot sage.symbolic .. _section-plot: From 886aec18932b374ae714e9e82c9168adc8bb87b8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 8 Nov 2023 14:27:52 -0800 Subject: [PATCH 044/155] src/doc: Doctest cosmetics --- .../Statistics-and-Distributions.rst | 14 +++++----- .../geometry/polyhedra_tutorial.rst | 28 +++++++++++-------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst b/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst index 0a76a3024ec..e83516d6833 100644 --- a/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst +++ b/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst @@ -143,13 +143,13 @@ the examples in ``r.kruskal_test?`` in the notebook. :: sage: # optional - rpy2 - sage: x=r([2.9, 3.0, 2.5, 2.6, 3.2]) # normal subjects - sage: y=r([3.8, 2.7, 4.0, 2.4]) # with obstructive airway disease - sage: z=r([2.8, 3.4, 3.7, 2.2, 2.0]) # with asbestosis - sage: a = r([x,y,z]) # make a long R vector of all the data - sage: b = r.factor(5*[1]+4*[2]+5*[3]) # create something for R to tell - ....: # which subjects are which - sage: a; b # show them + sage: x = r([2.9, 3.0, 2.5, 2.6, 3.2]) # normal subjects + sage: y = r([3.8, 2.7, 4.0, 2.4]) # with obstructive airway disease + sage: z = r([2.8, 3.4, 3.7, 2.2, 2.0]) # with asbestosis + sage: a = r([x,y,z]) # make a long R vector of all the data + sage: b = r.factor(5*[1] + 4*[2] + 5*[3]) # create something for R to tell + ....: # which subjects are which + sage: a; b # show them [1] 2.9 3.0 2.5 2.6 3.2 3.8 2.7 4.0 2.4 2.8 3.4 3.7 2.2 2.0 [1] 1 1 1 1 1 2 2 2 2 3 3 3 3 3 Levels: 1 2 3 diff --git a/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst b/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst index 8d3a137c2c0..a311b4699be 100644 --- a/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst +++ b/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst @@ -713,12 +713,13 @@ The fourth backend is :code:`normaliz` and is an optional Sage package. :: sage: # optional - pynormaliz - sage: P1_normaliz = Polyhedron(vertices = [[1, 0], [0, 1]], rays = [[1, 1]], backend='normaliz') + sage: P1_normaliz = Polyhedron(vertices=[[1, 0], [0, 1]], rays=[[1, 1]], + ....: backend='normaliz') sage: type(P1_normaliz) - sage: P2_normaliz = Polyhedron(vertices = [[1/2, 0, 0], [0, 1/2, 0]], - ....: rays = [[1, 1, 0]], - ....: lines = [[0, 0, 1]], backend='normaliz') + sage: P2_normaliz = Polyhedron(vertices=[[1/2, 0, 0], [0, 1/2, 0]], + ....: rays=[[1, 1, 0]], + ....: lines=[[0, 0, 1]], backend='normaliz') sage: type(P2_normaliz) @@ -728,7 +729,7 @@ This backend does not work with :code:`RDF` or other inexact fields. :: - sage: P3_normaliz = Polyhedron(vertices = [[0.5, 0], [0, 0.5]], backend='normaliz') # optional - pynormaliz + sage: P3_normaliz = Polyhedron(vertices=[[0.5, 0], [0, 0.5]], backend='normaliz') # optional - pynormaliz Traceback (most recent call last): ... ValueError: No such backend (=normaliz) implemented for given basering (=Real Double Field). @@ -742,12 +743,14 @@ the computation is done using an embedded number field. :: - sage: P4_normaliz = Polyhedron(vertices = [[sqrt_2, 0], [0, cbrt_2]], backend='normaliz') # optional - pynormaliz - sage: P4_normaliz # optional - pynormaliz + sage: # optional - pynormaliz + sage: P4_normaliz = Polyhedron(vertices=[[sqrt_2, 0], [0, cbrt_2]], + ....: backend='normaliz') + sage: P4_normaliz A 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices - - sage: P5_normaliz = Polyhedron(vertices = [[sqrt_2s, 0], [0, cbrt_2s]], backend='normaliz') # optional - pynormaliz - sage: P5_normaliz # optional - pynormaliz + sage: P5_normaliz = Polyhedron(vertices=[[sqrt_2s, 0], [0, cbrt_2s]], + ....: backend='normaliz') + sage: P5_normaliz A 1-dimensional polyhedron in (Symbolic Ring)^2 defined as the convex hull of 2 vertices .. end of output @@ -758,10 +761,11 @@ The backend :code:`normaliz` provides other methods such as :: sage: # optional - pynormaliz - sage: P6 = Polyhedron(vertices = [[0, 0], [3/2, 0], [3/2, 3/2], [0, 3]], backend='normaliz') + sage: P6 = Polyhedron(vertices=[[0, 0], [3/2, 0], [3/2, 3/2], [0, 3]], + ....: backend='normaliz') sage: IH = P6.integral_hull(); IH A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices - sage: P6.plot(color='blue')+IH.plot(color='red') + sage: P6.plot(color='blue') + IH.plot(color='red') Graphics object consisting of 12 graphics primitives sage: P1_normaliz.integral_hull() A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 1 ray From ef731b5d01fdfc156744c7b47220f3dc5d2b1436 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 8 Nov 2023 14:28:04 -0800 Subject: [PATCH 045/155] src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst: Restore lost comment --- src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst b/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst index c71f2445a5e..56ffac780ad 100644 --- a/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst +++ b/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst @@ -131,6 +131,6 @@ For a simple linear programming example, if we want to solve :: - sage: print(sol['x']) # needs cvxopt + sage: print(sol['x']) # ... below since can get -00 or +00 depending on architecture # needs cvxopt [ 1.00e...00] [ 1.00e+00] From 3f24ab33220caec78102d9940313e09f08548623 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 8 Nov 2023 16:16:07 -0800 Subject: [PATCH 046/155] src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst: Restore lost # random --- .../thematic_tutorials/geometry/polyhedra_tutorial.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst b/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst index a311b4699be..ad0422ca484 100644 --- a/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst +++ b/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst @@ -216,7 +216,7 @@ There is another way to create a polyhedron over algebraic numbers: sage: # needs sage.rings.number_field sage: K. = NumberField(x^2 - 2, embedding=AA(2)**(1/2)) sage: L. = NumberField(x^3 - 2, embedding=AA(2)**(1/3)) - sage: timeit('Polyhedron(vertices = [[a, 0], [0, b]])') + sage: timeit('Polyhedron(vertices=[[a, 0], [0, b]])') # random 5 loops, best of 3: 39.9 ms per loop sage: P5 = Polyhedron(vertices = [[a, 0], [0, b]]); P5 A 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices @@ -227,10 +227,11 @@ If the base ring is known it may be a good option to use the proper :meth:`sage. :: - sage: J = K.composite_fields(L)[0] # needs sage.rings.number_field - sage: timeit('Polyhedron(vertices = [[J(a), 0], [0, J(b)]])') # needs sage.rings.number_field + sage: # needs sage.rings.number_field + sage: J = K.composite_fields(L)[0] + sage: timeit('Polyhedron(vertices=[[J(a), 0], [0, J(b)]])') # random 25 loops, best of 3: 9.8 ms per loop - sage: P5_comp = Polyhedron(vertices = [[J(a), 0], [0, J(b)]]); P5_comp # needs sage.rings.number_field + sage: P5_comp = Polyhedron(vertices=[[J(a), 0], [0, J(b)]]); P5_comp A 1-dimensional polyhedron in (Number Field in ab with defining polynomial x^6 - 6*x^4 - 4*x^3 + 12*x^2 - 24*x - 4 From 55efc14d74683f79bd3a0a79677e598201004253 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 8 Nov 2023 16:16:16 -0800 Subject: [PATCH 047/155] src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst: Doctest cosmetics --- .../geometry/polyhedra_tutorial.rst | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst b/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst index ad0422ca484..d083abf8859 100644 --- a/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst +++ b/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst @@ -91,7 +91,7 @@ and some rays. :: - sage: P1 = Polyhedron(vertices = [[1, 0], [0, 1]], rays = [[1, 1]]) + sage: P1 = Polyhedron(vertices=[[1, 0], [0, 1]], rays=[[1, 1]]) sage: P1 A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 1 ray @@ -118,9 +118,9 @@ We can also add a lineality space. :: - sage: P2 = Polyhedron(vertices = [[1/2, 0, 0], [0, 1/2, 0]], - ....: rays = [[1, 1, 0]], - ....: lines = [[0, 0, 1]]) + sage: P2 = Polyhedron(vertices=[[1/2, 0, 0], [0, 1/2, 0]], + ....: rays=[[1, 1, 0]], + ....: lines=[[0, 0, 1]]) sage: P2 A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 2 vertices, 1 ray, 1 line sage: P2.plot() @@ -144,7 +144,7 @@ The chosen ring depends on the input format. :: - sage: P3 = Polyhedron(vertices = [[0.5, 0], [0, 0.5]]) + sage: P3 = Polyhedron(vertices=[[0.5, 0], [0, 0.5]]) sage: P3 A 1-dimensional polyhedron in RDF^2 defined as the convex hull of 2 vertices sage: P3.parent() @@ -202,9 +202,9 @@ It is also possible to define a polyhedron over algebraic numbers. sage: # needs sage.rings.number_field sage: sqrt_2 = AA(2)^(1/2) sage: cbrt_2 = AA(2)^(1/3) - sage: timeit('Polyhedron(vertices = [[sqrt_2, 0], [0, cbrt_2]])') + sage: timeit('Polyhedron(vertices=[[sqrt_2, 0], [0, cbrt_2]])') 5 loops, best of 3: 43.2 ms per loop - sage: P4 = Polyhedron(vertices = [[sqrt_2, 0], [0, cbrt_2]]); P4 + sage: P4 = Polyhedron(vertices=[[sqrt_2, 0], [0, cbrt_2]]); P4 A 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices .. end of output @@ -218,7 +218,7 @@ There is another way to create a polyhedron over algebraic numbers: sage: L. = NumberField(x^3 - 2, embedding=AA(2)**(1/3)) sage: timeit('Polyhedron(vertices=[[a, 0], [0, b]])') # random 5 loops, best of 3: 39.9 ms per loop - sage: P5 = Polyhedron(vertices = [[a, 0], [0, b]]); P5 + sage: P5 = Polyhedron(vertices=[[a, 0], [0, b]]); P5 A 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices .. end of output @@ -247,7 +247,7 @@ It is not possible to define a polyhedron over it: sage: sqrt_2s = sqrt(2) # needs sage.symbolic sage: cbrt_2s = 2^(1/3) # needs sage.symbolic - sage: Polyhedron(vertices = [[sqrt_2s, 0], [0, cbrt_2s]]) # needs sage.symbolic + sage: Polyhedron(vertices=[[sqrt_2s, 0], [0, cbrt_2s]]) # needs sage.symbolic Traceback (most recent call last): ... ValueError: no default backend for computations with Symbolic Ring @@ -392,7 +392,7 @@ inequalities and equalities as objects. :: - sage: P3_QQ = Polyhedron(vertices = [[0.5, 0], [0, 0.5]], base_ring=QQ) + sage: P3_QQ = Polyhedron(vertices=[[0.5, 0], [0, 0.5]], base_ring=QQ) sage: HRep = P3_QQ.Hrepresentation() sage: H1 = HRep[0]; H1 An equation (2, 2) x - 1 == 0 @@ -530,7 +530,7 @@ In order to use a specific backend, we specify the :code:`backend` parameter. :: - sage: P1_cdd = Polyhedron(vertices = [[1, 0], [0, 1]], rays = [[1, 1]], backend='cdd') + sage: P1_cdd = Polyhedron(vertices=[[1, 0], [0, 1]], rays=[[1, 1]], backend='cdd') sage: P1_cdd A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 1 ray @@ -570,7 +570,7 @@ The :code:`cdd` backend accepts also entries in :code:`RDF`: :: - sage: P3_cdd = Polyhedron(vertices = [[0.5, 0], [0, 0.5]], backend='cdd') + sage: P3_cdd = Polyhedron(vertices=[[0.5, 0], [0, 0.5]], backend='cdd') sage: P3_cdd A 1-dimensional polyhedron in RDF^2 defined as the convex hull of 2 vertices @@ -580,12 +580,12 @@ but not algebraic or symbolic values: :: - sage: P4_cdd = Polyhedron(vertices = [[sqrt_2, 0], [0, cbrt_2]], backend='cdd') # needs sage.rings.number_field + sage: P4_cdd = Polyhedron(vertices=[[sqrt_2, 0], [0, cbrt_2]], backend='cdd') # needs sage.rings.number_field Traceback (most recent call last): ... ValueError: No such backend (=cdd) implemented for given basering (=Algebraic Real Field). - sage: P5_cdd = Polyhedron(vertices = [[sqrt_2s, 0], [0, cbrt_2s]], backend='cdd') # needs sage.symbolic + sage: P5_cdd = Polyhedron(vertices=[[sqrt_2s, 0], [0, cbrt_2s]], backend='cdd') # needs sage.symbolic Traceback (most recent call last): ... ValueError: No such backend (=cdd) implemented for given basering (=Symbolic Ring). From e449ad1f9c44b6a16d290c5a5ae0d7361e36b840 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Thu, 9 Nov 2023 13:57:13 +0100 Subject: [PATCH 048/155] alignment of optional tags in digraph.py --- src/sage/graphs/digraph.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index c57224eba22..8ba57d90b3c 100644 --- a/src/sage/graphs/digraph.py +++ b/src/sage/graphs/digraph.py @@ -444,9 +444,9 @@ class DiGraph(GenericGraph): #. An igraph directed Graph (see also :meth:`~sage.graphs.generic_graph.GenericGraph.igraph_graph`):: - sage: import igraph # optional - python_igraph - sage: g = igraph.Graph([(0,1),(0,2)], directed=True) # optional - python_igraph - sage: DiGraph(g) # optional - python_igraph + sage: import igraph # optional - python_igraph + sage: g = igraph.Graph([(0,1),(0,2)], directed=True) # optional - python_igraph + sage: DiGraph(g) # optional - python_igraph Digraph on 3 vertices If ``vertex_labels`` is ``True``, the names of the vertices are given by @@ -462,8 +462,9 @@ class DiGraph(GenericGraph): If the igraph Graph has edge attributes, they are used as edge labels:: - sage: g = igraph.Graph([(0,1),(0,2)], directed=True, edge_attrs={'name':['a','b'], 'weight':[1,3]}) # optional - python_igraph - sage: DiGraph(g).edges(sort=True) # optional - python_igraph + sage: g = igraph.Graph([(0, 1), (0, 2)], directed=True, # optional - python_igraph + ....: edge_attrs={'name':['a', 'b'], 'weight':[1, 3]}) + sage: DiGraph(g).edges(sort=True) # optional - python_igraph [(0, 1, {'name': 'a', 'weight': 1}), (0, 2, {'name': 'b', 'weight': 3})] @@ -621,8 +622,8 @@ def __init__(self, data=None, pos=None, loops=None, format=None, Sage DiGraph from igraph undirected graph:: - sage: import igraph # optional - python_igraph - sage: DiGraph(igraph.Graph()) # optional - python_igraph + sage: import igraph # optional - python_igraph + sage: DiGraph(igraph.Graph()) # optional - python_igraph Traceback (most recent call last): ... ValueError: a *directed* igraph graph was expected. To build an undirected graph, call the Graph constructor From c9a3bb9f75e00df6817549a4f8576d821ecb2daf Mon Sep 17 00:00:00 2001 From: dcoudert Date: Thu, 9 Nov 2023 13:57:55 +0100 Subject: [PATCH 049/155] alignment of optional tags in dot2tex_utils.py --- src/sage/graphs/dot2tex_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/graphs/dot2tex_utils.py b/src/sage/graphs/dot2tex_utils.py index ce2cd873c8b..f8eb55485ac 100644 --- a/src/sage/graphs/dot2tex_utils.py +++ b/src/sage/graphs/dot2tex_utils.py @@ -21,7 +21,7 @@ def have_dot2tex(): EXAMPLES:: - sage: sage.graphs.dot2tex_utils.have_dot2tex() # optional - dot2tex graphviz + sage: sage.graphs.dot2tex_utils.have_dot2tex() # optional - dot2tex graphviz True sage: sage.graphs.dot2tex_utils.have_dot2tex() in [True, False] True @@ -41,7 +41,7 @@ def assert_have_dot2tex(): EXAMPLES:: - sage: sage.graphs.dot2tex_utils.assert_have_dot2tex() # optional - dot2tex graphviz + sage: sage.graphs.dot2tex_utils.assert_have_dot2tex() # optional - dot2tex graphviz """ check_error_string = """ An error occurs while testing the dot2tex installation. From 9dcec8e48a43955463dd75aa53717eb9a44ca3ff Mon Sep 17 00:00:00 2001 From: dcoudert Date: Thu, 9 Nov 2023 14:02:35 +0100 Subject: [PATCH 050/155] alignment of optional tags in generic_graph.py --- src/sage/graphs/generic_graph.py | 68 ++++++++++++++++---------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index c3039f68968..4ff71648f42 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -1622,8 +1622,8 @@ def igraph_graph(self, vertex_list=None, vertex_attrs={}, edge_attrs={}): sage: G = Graph([(1, 2, 'a'), (2, 3, 'b')]) sage: E = list(G.edge_iterator()) - sage: H = G.igraph_graph(edge_attrs={'label': [e[2] for e in E]}) # optional - python_igraph - sage: H.es['label'] # optional - python_igraph + sage: H = G.igraph_graph(edge_attrs={'label': [e[2] for e in E]}) # optional - python_igraph + sage: H.es['label'] # optional - python_igraph ['a', 'b'] @@ -1632,84 +1632,86 @@ def igraph_graph(self, vertex_list=None, vertex_attrs={}, edge_attrs={}): sage: G = Graph([(1, 2, {'weight': 1}), (2, 3, {'weight': 2})]) sage: E = list(G.edge_iterator()) - sage: H = G.igraph_graph(edge_attrs={'weight': [e[2]['weight'] for e in E]}) # optional - python_igraph - sage: H.is_weighted() # optional - python_igraph + sage: H = G.igraph_graph(edge_attrs={'weight': [e[2]['weight'] for e in E]}) # optional - python_igraph + sage: H.is_weighted() # optional - python_igraph True - sage: H.es['weight'] # optional - python_igraph + sage: H.es['weight'] # optional - python_igraph [1, 2] Adding vertex attributes:: sage: G = graphs.GridGraph([2, 2]) - sage: H = G.igraph_graph(vertex_attrs={'name': G.vertices(sort=True)}) # optional - python_igraph - sage: H.vs()['name'] # optional - python_igraph + sage: H = G.igraph_graph(vertex_attrs={'name': G.vertices(sort=True)}) # optional - python_igraph + sage: H.vs()['name'] # optional - python_igraph [(0, 0), (0, 1), (1, 0), (1, 1)] Providing a mapping from vertices to consecutive integers:: sage: G = graphs.GridGraph([2, 2]) sage: V = list(G) - sage: H = G.igraph_graph(vertex_list=V, vertex_attrs={'name': V}) # optional - python_igraph - sage: H.vs()['name'] == V # optional - python_igraph + sage: H = G.igraph_graph(vertex_list=V, vertex_attrs={'name': V}) # optional - python_igraph + sage: H.vs()['name'] == V # optional - python_igraph True Sometimes, Sage integer/floats are not compatible with igraph:: sage: G = Graph([(0, 1, 2)]) sage: E = list(G.edge_iterator()) - sage: H = G.igraph_graph(edge_attrs={'capacity': [e[2] for e in E]}) # optional - python_igraph - sage: H.maxflow_value(0, 1, 'capacity') # optional - python_igraph + sage: H = G.igraph_graph(edge_attrs={'capacity': [e[2] for e in E]}) # optional - python_igraph + sage: H.maxflow_value(0, 1, 'capacity') # optional - python_igraph 1.0 - sage: H = G.igraph_graph(edge_attrs={'capacity': [float(e[2]) for e in E]}) # optional - python_igraph - sage: H.maxflow_value(0, 1, 'capacity') # optional - python_igraph + sage: H = G.igraph_graph(edge_attrs={'capacity': [float(e[2]) for e in E]}) # optional - python_igraph + sage: H.maxflow_value(0, 1, 'capacity') # optional - python_igraph 2.0 TESTS: Converting a DiGraph back and forth:: + sage: # optional - python_igraph sage: G = DiGraph([('a', 'b', {'w': 1}), ('b', 'c', {'w': 2})]) sage: vertex_attrs = {'name': G.vertices(sort=False)} sage: E = list(G.edge_iterator()) sage: edge_attrs = {'w': [e[2]['w'] for e in E]} - sage: H = DiGraph(G.igraph_graph(vertex_attrs=vertex_attrs, edge_attrs=edge_attrs)) # optional - python_igraph - sage: G == H # optional - python_igraph + sage: H = DiGraph(G.igraph_graph(vertex_attrs=vertex_attrs, edge_attrs=edge_attrs)) + sage: G == H True - sage: G.edges(sort=True) == H.edges(sort=True) # optional - python_igraph + sage: G.edges(sort=True) == H.edges(sort=True) True - sage: H = DiGraph(G.igraph_graph(edge_attrs=edge_attrs)) # optional - python_igraph - sage: G == H # optional - python_igraph + sage: H = DiGraph(G.igraph_graph(edge_attrs=edge_attrs)) + sage: G == H False When checking for equality, edge labels are not taken into account:: - sage: H = DiGraph(G.igraph_graph(vertex_attrs=vertex_attrs)) # optional - python_igraph - sage: G == H # optional - python_igraph + sage: H = DiGraph(G.igraph_graph(vertex_attrs=vertex_attrs)) # optional - python_igraph + sage: G == H # optional - python_igraph True - sage: G.edges(sort=True) == H.edges(sort=True) # optional - python_igraph + sage: G.edges(sort=True) == H.edges(sort=True) # optional - python_igraph False Converting a Graph back and forth:: + sage: # optional - python_igraph sage: G = Graph([('a', 'b', {'w': 1}), ('b', 'c', {'w': 2})]) sage: vertex_attrs = {'name': G.vertices(sort=False)} sage: E = list(G.edge_iterator()) sage: edge_attrs = {'w': [e[2]['w'] for e in E]} - sage: H = Graph(G.igraph_graph(vertex_attrs=vertex_attrs, edge_attrs=edge_attrs)) # optional - python_igraph - sage: G == H # optional - python_igraph + sage: H = Graph(G.igraph_graph(vertex_attrs=vertex_attrs, edge_attrs=edge_attrs)) + sage: G == H True - sage: G.edges(sort=True) == H.edges(sort=True) # optional - python_igraph + sage: G.edges(sort=True) == H.edges(sort=True) True - sage: H = Graph(G.igraph_graph(edge_attrs=edge_attrs)) # optional - python_igraph - sage: G == H # optional - python_igraph + sage: H = Graph(G.igraph_graph(edge_attrs=edge_attrs)) + sage: G == H False When checking for equality, edge labels are not taken into account:: - sage: H = Graph(G.igraph_graph(vertex_attrs=vertex_attrs)) # optional - python_igraph - sage: G == H # optional - python_igraph + sage: H = Graph(G.igraph_graph(vertex_attrs=vertex_attrs)) # optional - python_igraph + sage: G == H # optional - python_igraph True - sage: G.edges(sort=True) == H.edges(sort=True) # optional - python_igraph + sage: G.edges(sort=True) == H.edges(sort=True) # optional - python_igraph False Check input parameter ``vertex_list``:: @@ -7331,7 +7333,7 @@ def edge_cut(self, s, t, value_only=True, use_edge_labels=False, vertices=False, ....: g.set_edge_label(u,v,round(random(),5)) sage: g.edge_cut(0, 1, algorithm="FF") == g.edge_cut(0, 1, algorithm="LP") # needs sage.numerical.mip True - sage: g.edge_cut(0, 1, algorithm="FF") == g.edge_cut(0, 1, algorithm="igraph") # optional - python_igraph + sage: g.edge_cut(0, 1, algorithm="FF") == g.edge_cut(0, 1, algorithm="igraph") # optional - python_igraph True Rounded return value when using the LP method:: @@ -9544,8 +9546,8 @@ def flow(self, x, y, value_only=True, integer=False, use_edge_labels=True, sage: flow_lp = g.flow(0, 1, algorithm="LP") # needs sage.numerical.mip sage: abs(flow_ff - flow_lp) < 0.01 # needs sage.numerical.mip True - sage: flow_igraph = g.flow(0, 1, algorithm="igraph") # optional python_igraph - sage: abs(flow_ff - flow_igraph) < 0.00001 # optional python_igraph + sage: flow_igraph = g.flow(0, 1, algorithm="igraph") # optional - python_igraph + sage: abs(flow_ff - flow_igraph) < 0.00001 # optional - python_igraph True """ self._scream_if_not_simple(allow_loops=True) @@ -23140,7 +23142,7 @@ def automorphism_group(self, partition=None, verbosity=0, sage: G.automorphism_group(edge_labels=True) # needs sage.groups Permutation Group with generators [(1,4)(2,3)] - sage: G.automorphism_group(edge_labels=True, algorithm="bliss") # optional - bliss + sage: G.automorphism_group(edge_labels=True, algorithm="bliss") # optional - bliss Permutation Group with generators [(1,4)(2,3)] sage: G.automorphism_group(edge_labels=True, algorithm="sage") # needs sage.groups From 9db848bd2319d60a1d7c2cdea381c28ebeafc768 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Thu, 9 Nov 2023 14:03:46 +0100 Subject: [PATCH 051/155] alignment of optional tags in graph.py --- src/sage/graphs/graph.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index b3c845af376..2505ac59f41 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -213,9 +213,9 @@ - an igraph Graph:: - sage: import igraph # optional - python_igraph - sage: g = Graph(igraph.Graph([(1,3),(3,2),(0,2)])) # optional - python_igraph - sage: g # optional - python_igraph + sage: import igraph # optional - python_igraph + sage: g = Graph(igraph.Graph([(1,3),(3,2),(0,2)])) # optional - python_igraph + sage: g # optional - python_igraph Graph on 4 vertices Generators @@ -820,9 +820,9 @@ class Graph(GenericGraph): #. An igraph Graph (see also :meth:`~sage.graphs.generic_graph.GenericGraph.igraph_graph`):: - sage: import igraph # optional - python_igraph - sage: g = igraph.Graph([(0, 1), (0, 2)]) # optional - python_igraph - sage: Graph(g) # optional - python_igraph + sage: import igraph # optional - python_igraph + sage: g = igraph.Graph([(0, 1), (0, 2)]) # optional - python_igraph + sage: Graph(g) # optional - python_igraph Graph on 3 vertices If ``vertex_labels`` is ``True``, the names of the vertices are given by @@ -838,8 +838,8 @@ class Graph(GenericGraph): If the igraph Graph has edge attributes, they are used as edge labels:: - sage: g = igraph.Graph([(0,1),(0,2)], edge_attrs={'name':['a','b'], 'weight':[1,3]}) # optional - python_igraph - sage: Graph(g).edges(sort=True) # optional - python_igraph + sage: g = igraph.Graph([(0,1),(0,2)], edge_attrs={'name':['a','b'], 'weight':[1,3]}) # optional - python_igraph + sage: Graph(g).edges(sort=True) # optional - python_igraph [(0, 1, {'name': 'a', 'weight': 1}), (0, 2, {'name': 'b', 'weight': 3})] @@ -883,7 +883,7 @@ class Graph(GenericGraph): ... ValueError: Unknown input format 'HeyHeyHey' - sage: Graph(igraph.Graph(directed=True)) # optional - python_igraph + sage: Graph(igraph.Graph(directed=True)) # optional - python_igraph Traceback (most recent call last): ... ValueError: An *undirected* igraph graph was expected. To build an directed graph, call the DiGraph constructor. @@ -7175,7 +7175,7 @@ def vertex_cover(self, algorithm="Cliquer", value_only=False, Testing mcqd:: - sage: graphs.PetersenGraph().vertex_cover(algorithm="mcqd", value_only=True) # optional - mcqd + sage: graphs.PetersenGraph().vertex_cover(algorithm="mcqd", value_only=True) # optional - mcqd 6 Given a wrong algorithm:: From 9016c14c0f8779e44f54f840f9cb578dc4967e60 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Thu, 9 Nov 2023 14:11:11 +0100 Subject: [PATCH 052/155] alignment of optional tags in graph_generators.py --- src/sage/graphs/graph_generators.py | 91 +++++++++++++++-------------- 1 file changed, 48 insertions(+), 43 deletions(-) diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index 7e2a2341a46..6c998c664f5 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -1450,17 +1450,17 @@ def fullerenes(self, order, ipr=False): There are 1812 isomers of `\textrm{C}_{60}`, i.e., 1812 fullerene graphs on 60 vertices:: - sage: gen = graphs.fullerenes(60) # optional buckygen - sage: len(list(gen)) # optional buckygen + sage: gen = graphs.fullerenes(60) # optional - buckygen + sage: len(list(gen)) # optional - buckygen 1812 However, there is only one IPR fullerene graph on 60 vertices: the famous Buckminster Fullerene:: - sage: gen = graphs.fullerenes(60, ipr=True) # optional buckygen - sage: next(gen) # optional buckygen + sage: gen = graphs.fullerenes(60, ipr=True) # optional - buckygen + sage: next(gen) # optional - buckygen Graph on 60 vertices - sage: next(gen) # optional buckygen + sage: next(gen) # optional - buckygen Traceback (most recent call last): ... StopIteration @@ -1557,26 +1557,26 @@ def fusenes(self, hexagon_count, benzenoids=False): There is a unique fusene with 2 hexagons:: - sage: gen = graphs.fusenes(2) # optional benzene - sage: len(list(gen)) # optional benzene + sage: gen = graphs.fusenes(2) # optional - benzene + sage: len(list(gen)) # optional - benzene 1 This fusene is naphthalene (`\textrm{C}_{10}\textrm{H}_{8}`). In the fusene graph the H-atoms are not stored, so this is a graph on just 10 vertices:: - sage: gen = graphs.fusenes(2) # optional benzene - sage: next(gen) # optional benzene + sage: gen = graphs.fusenes(2) # optional - benzene + sage: next(gen) # optional - benzene Graph on 10 vertices - sage: next(gen) # optional benzene + sage: next(gen) # optional - benzene Traceback (most recent call last): ... StopIteration There are 6505 benzenoids with 9 hexagons:: - sage: gen = graphs.fusenes(9, benzenoids=True) # optional benzene - sage: len(list(gen)) # optional benzene + sage: gen = graphs.fusenes(9, benzenoids=True) # optional - benzene + sage: len(list(gen)) # optional - benzene 6505 """ if hexagon_count < 0: @@ -1760,7 +1760,7 @@ def plantri_gen(self, options=""): An overview of the number of quadrangulations on up to 12 vertices. This agrees with :oeis:`A113201`:: - sage: for i in range(4, 13): # optional plantri + sage: for i in range(4, 13): # optional - plantri ....: cmd = '-qm2c2 {}'.format(i) ....: L = len(list(graphs.plantri_gen(cmd))) ....: print("{:2d} {:3d}".format(i, L)) @@ -1778,9 +1778,9 @@ def plantri_gen(self, options=""): Wrong input, ``"-c=3"`` instead of ``"-c3"``:: - sage: list(graphs.plantri_gen("6 -c3")) # optional plantri + sage: list(graphs.plantri_gen("6 -c3")) # optional - plantri [Graph on 6 vertices, Graph on 6 vertices] - sage: list(graphs.plantri_gen("6 -c=3")) # optional plantri + sage: list(graphs.plantri_gen("6 -c=3")) # optional - plantri Traceback (most recent call last): ... AttributeError: invalid options '6 -c=3' @@ -1879,20 +1879,20 @@ def planar_graphs(self, order, minimum_degree=None, There are 6 planar graphs on 4 vertices:: - sage: gen = graphs.planar_graphs(4) # optional plantri - sage: len(list(gen)) # optional plantri + sage: gen = graphs.planar_graphs(4) # optional - plantri + sage: len(list(gen)) # optional - plantri 6 Three of these planar graphs are bipartite:: - sage: gen = graphs.planar_graphs(4, only_bipartite=True) # optional plantri - sage: len(list(gen)) # optional plantri + sage: gen = graphs.planar_graphs(4, only_bipartite=True) # optional - plantri + sage: len(list(gen)) # optional - plantri 3 Setting ``dual=True`` gives the planar dual graphs:: - sage: gen = graphs.planar_graphs(4, dual=True) # optional plantri - sage: [u for u in list(gen)] # optional plantri + sage: gen = graphs.planar_graphs(4, dual=True) # optional - plantri + sage: [u for u in list(gen)] # optional - plantri [Graph on 4 vertices, Multi-graph on 3 vertices, Multi-graph on 2 vertices, @@ -1903,8 +1903,8 @@ def planar_graphs(self, order, minimum_degree=None, The cycle of length 4 is the only 2-connected bipartite planar graph on 4 vertices:: - sage: l = list(graphs.planar_graphs(4, minimum_connectivity=2, only_bipartite=True)) # optional plantri - sage: l[0].get_embedding() # optional plantri + sage: l = list(graphs.planar_graphs(4, minimum_connectivity=2, only_bipartite=True)) # optional - plantri + sage: l[0].get_embedding() # optional - plantri {1: [2, 3], 2: [1, 4], 3: [1, 4], @@ -1913,9 +1913,9 @@ def planar_graphs(self, order, minimum_degree=None, There is one planar graph with one vertex. This graph obviously has minimum degree equal to 0:: - sage: list(graphs.planar_graphs(1)) # optional plantri + sage: list(graphs.planar_graphs(1)) # optional - plantri [Graph on 1 vertex] - sage: list(graphs.planar_graphs(1, minimum_degree=1)) # optional plantri + sage: list(graphs.planar_graphs(1, minimum_degree=1)) # optional - plantri [] Specifying lower and upper bounds on the number of edges:: @@ -1932,9 +1932,9 @@ def planar_graphs(self, order, minimum_degree=None, Specifying the maximum size of a face:: - sage: len(list(graphs.planar_graphs(4, maximum_face_size=3))) # optional plantri + sage: len(list(graphs.planar_graphs(4, maximum_face_size=3))) # optional - plantri 1 - sage: len(list(graphs.planar_graphs(4, maximum_face_size=4))) # optional plantri + sage: len(list(graphs.planar_graphs(4, maximum_face_size=4))) # optional - plantri 3 TESTS: @@ -2102,28 +2102,28 @@ def triangulations(self, order, minimum_degree=None, minimum_connectivity=None, The unique planar embedding of the `K_4` is the only planar triangulations on 4 vertices:: - sage: gen = graphs.triangulations(4) # optional plantri - sage: [g.get_embedding() for g in gen] # optional plantri + sage: gen = graphs.triangulations(4) # optional - plantri + sage: [g.get_embedding() for g in gen] # optional - plantri [{1: [2, 3, 4], 2: [1, 4, 3], 3: [1, 2, 4], 4: [1, 3, 2]}] but, of course, this graph is not Eulerian:: - sage: gen = graphs.triangulations(4, only_eulerian=True) # optional plantri - sage: len(list(gen)) # optional plantri + sage: gen = graphs.triangulations(4, only_eulerian=True) # optional - plantri + sage: len(list(gen)) # optional - plantri 0 The unique Eulerian triangulation on 6 vertices is isomorphic to the octahedral graph. :: - sage: gen = graphs.triangulations(6, only_eulerian=True) # optional plantri - sage: g = next(gen) # optional plantri - sage: g.is_isomorphic(graphs.OctahedralGraph()) # optional plantri + sage: gen = graphs.triangulations(6, only_eulerian=True) # optional - plantri + sage: g = next(gen) # optional - plantri + sage: g.is_isomorphic(graphs.OctahedralGraph()) # optional - plantri True An overview of the number of 5-connected triangulations on up to 22 vertices. This agrees with :oeis:`A081621`:: - sage: for i in range(12, 23): # optional plantri + sage: for i in range(12, 23): # optional - plantri ....: L = len(list(graphs.triangulations(i, minimum_connectivity=5))) ....: print("{} {:3d}".format(i,L)) 12 1 @@ -2140,7 +2140,8 @@ def triangulations(self, order, minimum_degree=None, minimum_connectivity=None, The minimum connectivity can be at most the minimum degree:: - sage: gen = next(graphs.triangulations(10, minimum_degree=3, minimum_connectivity=5)) # optional plantri + sage: gen = next(graphs.triangulations(10, minimum_degree=3, # optional - plantri + ....: minimum_connectivity=5)) Traceback (most recent call last): ... ValueError: Minimum connectivity can be at most the minimum degree. @@ -2148,19 +2149,23 @@ def triangulations(self, order, minimum_degree=None, minimum_connectivity=None, There are 5 triangulations with 9 vertices and minimum degree equal to 4 that are 3-connected, but only one of them is not 4-connected:: - sage: len([g for g in graphs.triangulations(9, minimum_degree=4, minimum_connectivity=3)]) # optional plantri + sage: len([g for g in graphs.triangulations(9, minimum_degree=4, # optional - plantri + ....: minimum_connectivity=3)]) 5 - sage: len([g for g in graphs.triangulations(9, minimum_degree=4, minimum_connectivity=3, exact_connectivity=True)]) # optional plantri + sage: len([g for g in graphs.triangulations(9, minimum_degree=4, # optional - plantri + ....: minimum_connectivity=3, + ....: exact_connectivity=True)]) 1 Setting ``dual=True`` gives the planar dual graphs:: - sage: [len(g) for g in graphs.triangulations(9, minimum_degree=4, minimum_connectivity=3, dual=True)] # optional plantri + sage: [len(g) for g in graphs.triangulations(9, minimum_degree=4, # optional plantri + ....: minimum_connectivity=3, dual=True)] [14, 14, 14, 14, 14] TESTS:: - sage: [g.size() for g in graphs.triangulations(6, minimum_connectivity=3)] # optional plantri + sage: [g.size() for g in graphs.triangulations(6, minimum_connectivity=3)] # optional - plantri [12, 12] """ if order < 0: @@ -2282,7 +2287,7 @@ def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None An overview of the number of quadrangulations on up to 12 vertices. This agrees with :oeis:`A113201`:: - sage: for i in range(4,13): # optional plantri + sage: for i in range(4,13): # optional - plantri ....: L = len(list(graphs.quadrangulations(i))) ....: print("{:2d} {:3d}".format(i,L)) 4 1 @@ -2298,12 +2303,12 @@ def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None There are 2 planar quadrangulation on 12 vertices that do not have a non-facial quadrangle:: - sage: len([g for g in graphs.quadrangulations(12, no_nonfacial_quadrangles=True)]) # optional plantri + sage: len([g for g in graphs.quadrangulations(12, no_nonfacial_quadrangles=True)]) # optional - plantri 2 Setting ``dual=True`` gives the planar dual graphs:: - sage: [len(g) for g in graphs.quadrangulations(12, no_nonfacial_quadrangles=True, dual=True)] # optional plantri + sage: [len(g) for g in graphs.quadrangulations(12, no_nonfacial_quadrangles=True, dual=True)] # optional - plantri [10, 10] """ if order < 0: From 64264723ab30056bb529b7f31940fd7698c2e61d Mon Sep 17 00:00:00 2001 From: dcoudert Date: Thu, 9 Nov 2023 14:12:09 +0100 Subject: [PATCH 053/155] alignment of optional tags in graph_latex.py --- src/sage/graphs/graph_latex.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/graphs/graph_latex.py b/src/sage/graphs/graph_latex.py index 76db076502c..1cd878bec5a 100644 --- a/src/sage/graphs/graph_latex.py +++ b/src/sage/graphs/graph_latex.py @@ -1329,8 +1329,8 @@ def latex(self): sage: C = [[0,1], [2]] sage: kwds = dict(subgraph_clusters=C,color_by_label=True,prog='dot',format='dot2tex') sage: opts = G_with_labels.latex_options() - sage: opts.set_options(edge_labels=True, **kwds) # optional - dot2tex graphviz - sage: latex(G_with_labels) # optional - dot2tex graphviz + sage: opts.set_options(edge_labels=True, **kwds) # optional - dot2tex graphviz + sage: latex(G_with_labels) # optional - dot2tex graphviz \begin{tikzpicture}[>=latex,line join=bevel,] %% \begin{scope} @@ -1388,7 +1388,7 @@ def dot2tex_picture(self): sage: G = DiGraph() sage: G.add_edge(3333, 88, 'my_label') sage: G.set_latex_options(edge_labels=True) - sage: print(G.latex_options().dot2tex_picture()) # optional - dot2tex graphviz + sage: print(G.latex_options().dot2tex_picture()) # optional - dot2tex graphviz \begin{tikzpicture}[>=latex,line join=bevel,] %% \node (node_...) at (...bp,...bp) [draw,draw=none] {$...$}; @@ -1404,7 +1404,7 @@ def dot2tex_picture(self): sage: G = Graph([(0,1)]) sage: G.set_latex_options(edge_colors = {(0,1): 'red'}) - sage: print(G.latex_options().dot2tex_picture()) # optional - dot2tex graphviz + sage: print(G.latex_options().dot2tex_picture()) # optional - dot2tex graphviz \begin{tikzpicture}[>=latex,line join=bevel,] ... \draw [red,] (node_0) ... (node_1); From 67c6957438c167037810375aa7bd83356db3badc Mon Sep 17 00:00:00 2001 From: dcoudert Date: Thu, 9 Nov 2023 14:12:45 +0100 Subject: [PATCH 054/155] alignment of optional tags in lovasz_theta.py --- src/sage/graphs/lovasz_theta.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/graphs/lovasz_theta.py b/src/sage/graphs/lovasz_theta.py index bd18dcb944e..49bc7e32092 100644 --- a/src/sage/graphs/lovasz_theta.py +++ b/src/sage/graphs/lovasz_theta.py @@ -46,9 +46,9 @@ def lovasz_theta(graph): EXAMPLES:: sage: C = graphs.PetersenGraph() - sage: C.lovasz_theta() # optional csdp + sage: C.lovasz_theta() # optional - csdp 4.0 - sage: graphs.CycleGraph(5).lovasz_theta() # optional csdp + sage: graphs.CycleGraph(5).lovasz_theta() # optional - csdp 2.236068 TESTS:: From 00827742c4b9cd264868843a73e34a2e2515cfef Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Thu, 9 Nov 2023 14:38:28 +0100 Subject: [PATCH 055/155] first prototype --- src/sage/topology/simplicial_set.py | 93 +++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/src/sage/topology/simplicial_set.py b/src/sage/topology/simplicial_set.py index 646522510e7..f707c9407fa 100644 --- a/src/sage/topology/simplicial_set.py +++ b/src/sage/topology/simplicial_set.py @@ -258,8 +258,10 @@ import copy +from sage.matrix.special import identity_matrix from sage.misc.cachefunc import cached_method from sage.misc.fast_methods import WithEqualityById +from sage.misc.flatten import flatten from sage.misc.lazy_import import lazy_import from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ @@ -3937,6 +3939,97 @@ def twist(s): return ChainComplex(differentials, degree_of_differential=-1, check=check) + def twisted_homology(self, n): + r""" + The `n`-th twisted homology module of the simplicial set with respect to + the abelianization of the fundamental_group. + + It is a module over a Laurent + polynomial ring, that, if the fundamental group is abelian, coincides + with the homology of the universal cover. + + INPUT: + + - ``n`` - a positive integer. + """ + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing + G, d = self._universal_cover_dict() + abelG = G.abelianization_map().codomain() + abelinv = abelG.abelian_invariants() + RP = PolynomialRing(ZZ, 'x', 2 * len(abelinv)) + I = RP.ideal([RP.gen(i)**j-1 for i,j in enumerate(abelinv)]) + J = RP.ideal([RP.gen(2*a)*RP.gen(2*a+1) - 1 for a in range(RP.ngens()//2)]) + GB = (I+J).groebner_basis() + GBI = RP.ideal(GB) + def reduce_laurent(a): + return a._singular_().reduce(GBI)._sage_() + def group_to_polynomial(el, RP): + res = RP.one() + for a in el.Tietze(): + if a > 0: + res *= RP.gen(2*a-2) + else: + res*= RP.gen(-2*a-1) + return res + nd = {a:group_to_polynomial(G.abelianization_map()(b), RP) for a,b in d.items()} + CC = self.twisted_chain_complex(nd) + def mkernel(M): + if M.nrows() == 0 or M.ncols() == 0: + return M + res = M + n = res.ncols() + for g in (I+J).gens(): + res = res.stack(g*identity_matrix(n)) + syz = res.T._singular_().syz()._sage_() + trimmed = syz.T.submatrix(0,0,syz.ncols(),M.nrows()) + trimmed = trimmed.apply_map(reduce_laurent) + to_delete = [i for (i,r) in enumerate(trimmed.rows()) if not r] + return trimmed.delete_rows(to_delete) + def lift_to_submodule(S, M): + if S.nrows() == 0 or S.ncols() == 0: + return S + res = M + for g in GB: + res = res.stack(g*identity_matrix(M.ncols())) + singres = res.T._singular_().lift(S.T._singular_())._sage_() + return singres.submatrix(0,0,M.nrows(),S.nrows()) + def mgb(M): + if M.nrows() == 0 or M.ncols() == 0: + return M + res = M + for g in GB: + res = res.stack(g*identity_matrix(M.ncols())) + sres = res.T._singular_().std()._sage_().T + to_delete = [i for i, r in enumerate(sres.apply_map(reduce_laurent)) if not r] + return sres.delete_rows(to_delete) + M2 = border_matrix(n+1) + M1 = CC.differential(n).T + M2 = CC.differential(n + 1).T + if M1.nrows() == 0: + return (RP**0).quotient_module([]) + K = mkernel(M1) + DK = mkernel(K) + if M2.nrows() > 0: + S = lift_to_submodule(M2, K) + if S.nrows() > 0 and S.ncols() > 0: + res = mgb(DK.stack(S.T)) + else: + res = DK + else: + res = mgb(DK.T) + resmat = mgb(res.apply_map(reduce_laurent)) + L = LaurentPolynomialRing(ZZ, 'x', len(abelinv)) + h = RP.hom(flatten([[g, g**-1] for g in L.gens()]),codomain = L) + laumat = resmat.apply_map(h) + laumat = laumat.change_ring(L) + if laumat.ncols() > 0: + for g in I.gens(): + laumat = laumat.stack(h(g)*identity_matrix(L, laumat.ncols())) + AM = L ** K.nrows() + SM = AM.submodule(laumat) + return AM.quotient_module(SM) + @cached_method def algebraic_topological_model(self, base_ring=None): r""" From 7e015d38f56768321a4f23e2a22d1779b3ac6dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 9 Nov 2023 14:39:40 +0100 Subject: [PATCH 056/155] refresh the file plural.pyx --- src/sage/rings/polynomial/plural.pyx | 256 +++++++++++++-------------- 1 file changed, 120 insertions(+), 136 deletions(-) diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index 90e3663da5c..17a95c52618 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -37,8 +37,7 @@ The underlying libSINGULAR interface was implemented by - Martin Albrecht (2009-05): added `\ZZ/n\ZZ` support, refactoring - - Martin Albrecht (2009-06): refactored the code to allow better - re-use + - Martin Albrecht (2009-06): refactored the code to allow better re-use .. TODO:: @@ -100,7 +99,6 @@ TESTS:: sage: TestSuite(P).run() sage: loads(dumps(P)) is P True - """ from cysignals.memory cimport sig_malloc, sig_free @@ -128,12 +126,11 @@ from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomialRing_ from sage.rings.polynomial.multi_polynomial_ideal import NCPolynomialIdeal from sage.rings.polynomial.polydict import ETuple -from sage.rings.ring import check_default_category +from sage.rings.ring import check_default_category, Ring from sage.structure.element cimport CommutativeRingElement, Element, RingElement from sage.structure.factory import UniqueFactory from sage.structure.richcmp cimport rich_to_bool from sage.structure.parent cimport Parent -from sage.structure.parent_gens cimport ParentWithGens from sage.rings.polynomial.term_order import TermOrder from sage.misc.functional import coerce @@ -149,7 +146,6 @@ class G_AlgFactory(UniqueFactory): sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) sage: H is A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) # indirect doctest True - """ def create_object(self, version, key, **extra_args): """ @@ -157,15 +153,15 @@ class G_AlgFactory(UniqueFactory): INPUT: - - ``key`` - a 6-tuple, formed by a base ring, a tuple of names, two + - ``key`` -- a 6-tuple, formed by a base ring, a tuple of names, two matrices over a polynomial ring over the base ring with the given variable names, a term order, and a category - - ``extra_args`` - a dictionary, whose only relevant key is 'check'. + - ``extra_args`` -- a dictionary, whose only relevant key is 'check'. TESTS:: sage: A. = FreeAlgebra(QQ, 3) - sage: H=A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) + sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) sage: sorted(H.relations().items(), key=str) [(y*x, x*y - z), (z*x, x*z + 2*x), (z*y, y*z - 2*y)] """ @@ -183,12 +179,12 @@ class G_AlgFactory(UniqueFactory): INPUT: - - ``base_ring`` - a ring - - ``c,d`` - two matrices - - ``names`` - a tuple or list of names - - ``order`` - (optional) term order - - ``category`` - (optional) category - - ``check`` - optional bool + - ``base_ring`` -- a ring + - ``c,d`` -- two matrices + - ``names`` -- a tuple or list of names + - ``order`` -- (optional) term order + - ``category`` -- (optional) category + - ``check`` -- optional bool TESTS:: @@ -196,7 +192,6 @@ class G_AlgFactory(UniqueFactory): sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) sage: H is A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) # indirect doctest True - """ if names is None: raise ValueError("The generator names must be provided") @@ -255,9 +250,9 @@ cdef class NCPolynomialRing_plural(Ring): INPUT: - - ``base_ring`` - base ring (must be either `\GF{q}`, `\ZZ`, `\ZZ/n\ZZ`, `\QQ` or absolute number field) + - ``base_ring`` -- base ring (must be either `\GF{q}`, `\ZZ`, `\ZZ/n\ZZ`, `\QQ` or absolute number field) - ``names`` - a tuple of names of ring variables - - ``c``, ``d``- upper triangular matrices of coefficients, + - ``c``, ``d`` -- upper triangular matrices of coefficients, resp. commutative polynomials, satisfying the nondegeneracy conditions, which are to be tested if ``check`` is ``True``. These matrices describe the noncommutative relations: @@ -266,8 +261,8 @@ cdef class NCPolynomialRing_plural(Ring): where ``0 <= i < j < self.ngens()``. Note that two variables commute if they are not part of one of these relations. - - ``order`` - term order - - ``check`` - check the noncommutative conditions (default: ``True``) + - ``order`` -- term order + - ``check`` -- check the noncommutative conditions (default: ``True``) TESTS: @@ -339,17 +334,15 @@ cdef class NCPolynomialRing_plural(Ring): self._ngens = n self._term_order = order - Ring.__init__(self, base_ring, names, category=category) + Ring.__init__(self, base_ring, names, category=category, + normalize=False) self._populate_coercion_lists_() - #MPolynomialRing_generic.__init__(self, base_ring, n, names, order) - #self._has_singular = True - assert(n == len(self._names)) + assert n == len(self._names) self._one_element = new_NCP(self, p_ISet(1, self._ring)) self._zero_element = new_NCP(self, NULL) - if check: from sage.libs.singular.function_factory import ff test = ff.nctools__lib.ndcond(ring = self) @@ -378,9 +371,9 @@ cdef class NCPolynomialRing_plural(Ring): True """ return g_Algebra, (self.base_ring(), self._c, self._d, - self.variable_names(), - self.term_order(), - self.category()) + self.variable_names(), + self.term_order(), + self.category()) def __dealloc__(self): r""" @@ -420,7 +413,7 @@ cdef class NCPolynomialRing_plural(Ring): def _element_constructor_(self, element): """ - Make sure element is a valid member of self, and return the constructed element. + Make sure element is a valid member of ``self``, and return the constructed element. EXAMPLES:: @@ -441,7 +434,7 @@ cdef class NCPolynomialRing_plural(Ring): TESTS: - Check conversion from self:: + Check conversion from ``self``:: sage: A. = FreeAlgebra(QQ, 3) sage: P. = A.g_algebra(relations={y*x:-x*y}, order = 'lex') @@ -496,9 +489,7 @@ cdef class NCPolynomialRing_plural(Ring): sage: B = A.g_algebra({y*x:-x*y}) sage: B(2) 2 - """ - if element == 0: return self._zero_element if element == 1: @@ -517,7 +508,8 @@ cdef class NCPolynomialRing_plural(Ring): except Exception: pass - if(_ring != currRing): rChangeCurrRing(_ring) + if _ring != currRing: + rChangeCurrRing(_ring) if isinstance(element, NCPolynomial_plural): @@ -592,7 +584,7 @@ cdef class NCPolynomialRing_plural(Ring): def free_algebra(self): """ - The free algebra of which this is the quotient. + Return the free algebra of which this is the quotient. EXAMPLES:: @@ -607,7 +599,9 @@ cdef class NCPolynomialRing_plural(Ring): def __hash__(self): """ - Return a hash for this noncommutative ring, that is, a hash of the string + Return a hash for this noncommutative ring. + + This is a hash of the string representation of this polynomial ring. NOTE: @@ -624,7 +618,6 @@ cdef class NCPolynomialRing_plural(Ring): sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') sage: {P:2}[P] # indirect doctest 2 - """ return self @@ -632,10 +625,10 @@ cdef class NCPolynomialRing_plural(Ring): """ Return the free module of rank `n` over this ring. - NOTE: + .. NOTE:: - This is not properly implemented yet. Thus, there is - a warning. + This is not properly implemented yet. Thus, there is + a warning. EXAMPLES:: @@ -653,7 +646,6 @@ cdef class NCPolynomialRing_plural(Ring): It's also not guaranteed that all multiplications are done from the right side. Ambient free module of rank 3 over Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y} - """ from sage.modules.free_module import FreeModule return FreeModule(self, n) @@ -758,8 +750,7 @@ cdef class NCPolynomialRing_plural(Ring): rChangeCurrRing(_ring) from sage.libs.singular.function import singular_function ringlist = singular_function('ringlist') - result = ringlist(self, ring=self) - return result + return ringlist(self, ring=self) def relations(self, add_commutative=False): """ @@ -786,7 +777,6 @@ cdef class NCPolynomialRing_plural(Ring): {z*x: x*z + 2*x, z*y: y*z - 2*y} sage: H.relations(add_commutative=True) {y*x: x*y, z*x: x*z + 2*x, z*y: y*z - 2*y} - """ if add_commutative: if self._relations_commutative is not None: @@ -799,7 +789,7 @@ cdef class NCPolynomialRing_plural(Ring): n = self.ngens() for r in range(0, n-1, 1): for c in range(r+1, n, 1): - res[ A.gen(c) * A.gen(r) ] = self.gen(c) * self.gen(r) # C[r, c] * P.gen(r) * P.gen(c) + D[r, c] + res[A.gen(c) * A.gen(r)] = self.gen(c) * self.gen(r) # C[r, c] * P.gen(r) * P.gen(c) + D[r, c] self._relations_commutative = res return res @@ -814,14 +804,14 @@ cdef class NCPolynomialRing_plural(Ring): for r in range(0, n-1, 1): for c in range(r+1, n, 1): if (self.gen(c) * self.gen(r) != self.gen(r) * self.gen(c)): - res[ A.gen(c) * A.gen(r) ] = self.gen(c) * self.gen(r) # C[r, c] * P.gen(r) * P.gen(c) + D[r, c] + res[A.gen(c) * A.gen(r)] = self.gen(c) * self.gen(r) # C[r, c] * P.gen(r) * P.gen(c) + D[r, c] self._relations = res return self._relations def ngens(self): """ - Returns the number of variables in this noncommutative polynomial ring. + Return the number of variables in this noncommutative polynomial ring. EXAMPLES:: @@ -834,7 +824,7 @@ cdef class NCPolynomialRing_plural(Ring): def gen(self, int n=0): """ - Returns the ``n``-th generator of this noncommutative polynomial + Return the ``n``-th generator of this noncommutative polynomial ring. INPUT: @@ -890,15 +880,14 @@ cdef class NCPolynomialRing_plural(Ring): Left Ideal (x + 2*y + 2*z - 1, 2*x*y + 2*y*z - y, x^2 - x + 2*y^2 + 2*z^2) of Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y} sage: P.ideal([x + 2*y + 2*z-1, 2*x*y + 2*y*z-y, x^2 + 2*y^2 + 2*z^2-x], side="twosided") Twosided Ideal (x + 2*y + 2*z - 1, 2*x*y + 2*y*z - y, x^2 - x + 2*y^2 + 2*z^2) of Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y} - """ coerce = kwds.get('coerce', True) if len(gens) == 1: gens = gens[0] - #if is_SingularElement(gens): + # if is_SingularElement(gens): # gens = list(gens) # coerce = True - #elif is_Macaulay2Element(gens): + # elif is_Macaulay2Element(gens): # gens = list(gens) # coerce = True if not isinstance(gens, (list, tuple)): @@ -920,9 +909,9 @@ cdef class NCPolynomialRing_plural(Ring): sage: Q # indirect doctest """ - cdef ring* _ring = self._ring - if(_ring != currRing): rChangeCurrRing(_ring) + if _ring != currRing: + rChangeCurrRing(_ring) from sage.libs.singular.function import singular_function ring = singular_function('ring') @@ -977,9 +966,9 @@ cdef class NCPolynomialRing_plural(Ring): INPUT: - - ``f`` - monomial - - ``g`` - monomial - - ``coeff`` - divide coefficients as well (default: ``False``) + - ``f`` -- monomial + - ``g`` -- monomial + - ``coeff`` -- divide coefficients as well (default: ``False``) EXAMPLES:: @@ -1050,7 +1039,8 @@ cdef class NCPolynomialRing_plural(Ring): if self is not g._parent: g = self.coerce(g) - if(r != currRing): rChangeCurrRing(r) + if r != currRing: + rChangeCurrRing(r) if not f._poly: return self._zero_element @@ -1060,7 +1050,8 @@ cdef class NCPolynomialRing_plural(Ring): res = pMDivide(f._poly, g._poly) if coeff: if (r.cf.type == n_unknown) or r.cf.cfDivBy(p_GetCoeff(f._poly, r), p_GetCoeff(g._poly, r), r.cf): - n = r.cf.cfDiv( p_GetCoeff(f._poly, r) , p_GetCoeff(g._poly, r), r.cf) + n = r.cf.cfDiv(p_GetCoeff(f._poly, r), + p_GetCoeff(g._poly, r), r.cf) p_SetCoeff0(res, n, r) else: raise ArithmeticError("Cannot divide these coefficients.") @@ -1130,7 +1121,6 @@ cdef class NCPolynomialRing_plural(Ring): else: return True - def monomial_lcm(self, NCPolynomial_plural f, NCPolynomial_plural g): """ LCM for monomials. Coefficients are ignored. @@ -1187,7 +1177,8 @@ cdef class NCPolynomialRing_plural(Ring): if g._poly == NULL: raise ArithmeticError("Cannot compute LCM of zero and nonzero element.") - if(self._ring != currRing): rChangeCurrRing(self._ring) + if self._ring != currRing: + rChangeCurrRing(self._ring) pLcm(f._poly, g._poly, m) p_Setm(m, self._ring) @@ -1318,18 +1309,18 @@ cdef class NCPolynomialRing_plural(Ring): if p == NULL: if q == NULL: - return False #GCD(0,0) = 0 + return False # GCD(0,0) = 0 else: - return True #GCD(x,0) = 1 + return True # GCD(x,0) = 1 elif q == NULL: - return True # GCD(0,x) = 1 + return True # GCD(0,x) = 1 - elif p_IsConstant(p,r) or p_IsConstant(q,r): # assuming a base field + elif p_IsConstant(p, r) or p_IsConstant(q, r): # assuming a base field return False for i from 1 <= i <= r.N: - if p_GetExp(p,i,r) and p_GetExp(q,i,r): + if p_GetExp(p, i, r) and p_GetExp(q, i, r): return False return True @@ -1540,8 +1531,8 @@ cdef class NCPolynomial_plural(RingElement): """ cdef poly *_p singular_polynomial_add(&_p, left._poly, - (right)._poly, - (left._parent)._ring) + (right)._poly, + (left._parent)._ring) return new_NCP((left._parent), _p) cpdef _sub_(left, right) noexcept: @@ -1623,8 +1614,8 @@ cdef class NCPolynomial_plural(RingElement): # all currently implemented rings are commutative cdef poly *_p singular_polynomial_mul(&_p, left._poly, - (right)._poly, - (left._parent)._ring) + (right)._poly, + (left._parent)._ring) return new_NCP((left._parent),_p) cpdef _div_(left, right) noexcept: @@ -1764,7 +1755,8 @@ cdef class NCPolynomial_plural(RingElement): cdef ring *r = parent._ring cdef poly *res - if(r != currRing): rChangeCurrRing(r) + if r != currRing: + rChangeCurrRing(r) if isinstance(I, NCPolynomialIdeal): try: @@ -1777,7 +1769,7 @@ cdef class NCPolynomial_plural(RingElement): _I = idInit(len(I),1) for f in I: if not (isinstance(f, NCPolynomial_plural) - and (f)._parent is parent): + and (f)._parent is parent): try: f = parent.coerce(f) except TypeError as msg: @@ -1787,9 +1779,9 @@ cdef class NCPolynomial_plural(RingElement): _I.m[i] = p_Copy((f)._poly, r) i+=1 - #the second parameter would be qring! + # the second parameter would be qring! res = kNF(_I, NULL, self._poly) - id_Delete(&_I,r) + id_Delete(&_I, r) return new_NCP(parent,res) def _repr_(self): @@ -1971,8 +1963,10 @@ cdef class NCPolynomial_plural(RingElement): def degrees(self): """ - Returns a tuple with the maximal degree of each variable in - this polynomial. The list of degrees is ordered by the order + Return a tuple with the maximal degree of each variable in + this polynomial. + + The list of degrees is ordered by the order of the generators. EXAMPLES:: @@ -1998,7 +1992,6 @@ cdef class NCPolynomial_plural(RingElement): p = pNext(p) return tuple(d) - def coefficient(self, degrees): """ Return the coefficient of the variables with the degrees @@ -2208,18 +2201,19 @@ cdef class NCPolynomial_plural(RingElement): cdef int n cdef int v r = (self._parent)._ring - if r!=currRing: rChangeCurrRing(r) + if r != currRing: + rChangeCurrRing(r) base = (self._parent)._base p = self._poly pd = dict() while p: d = dict() for v from 1 <= v <= r.N: - n = p_GetExp(p,v,r) - if n!=0: + n = p_GetExp(p, v, r) + if n != 0: d[v-1] = n - pd[ETuple(d,r.N)] = si2sa(p_GetCoeff(p, r), r, base) + pd[ETuple(d, r.N)] = si2sa(p_GetCoeff(p, r), r, base) p = pNext(p) return pd @@ -2273,7 +2267,6 @@ cdef class NCPolynomial_plural(RingElement): base_map = codomain return sum(prod(im_gens[i]**val for i, val in enumerate(t))*base_map(d[t]) for t in d) - cdef long _hash_c(self) noexcept: """ See :meth:`__hash__` @@ -2283,16 +2276,17 @@ cdef class NCPolynomial_plural(RingElement): cdef int n cdef int v r = (self._parent)._ring - if r!=currRing: rChangeCurrRing(r) + if r != currRing: + rChangeCurrRing(r) base = (self._parent)._base p = self._poly - cdef long result = 0 # store it in a c-int and just let the overflowing additions wrap + cdef long result = 0 # store it in a c-int and just let the overflowing additions wrap cdef long result_mon var_name_hash = [hash(vn) for vn in self._parent.variable_names()] cdef long c_hash while p: c_hash = hash(si2sa(p_GetCoeff(p, r), r, base)) - if c_hash != 0: # this is always going to be true, because we are sparse (correct?) + if c_hash != 0: # this is always going to be true, because we are sparse (correct?) # Hash (self[i], gen_a, exp_a, gen_b, exp_b, gen_c, exp_c, ...) as a tuple according to the algorithm. # I omit gen,exp pairs where the exponent is zero. result_mon = c_hash @@ -2440,10 +2434,10 @@ cdef class NCPolynomial_plural(RingElement): True """ cdef ring *_ring = (self._parent)._ring - if(_ring != currRing): rChangeCurrRing(_ring) + if _ring != currRing: + rChangeCurrRing(_ring) return bool(p_IsHomogeneous(self._poly,_ring)) - def is_monomial(self): """ Return ``True`` if this polynomial is a monomial. @@ -2474,7 +2468,8 @@ cdef class NCPolynomial_plural(RingElement): if self._poly == NULL: return True - if(_ring != currRing): rChangeCurrRing(_ring) + if _ring != currRing: + rChangeCurrRing(_ring) _p = p_Head(self._poly, _ring) _n = p_GetCoeff(_p, _ring) @@ -2538,7 +2533,8 @@ cdef class NCPolynomial_plural(RingElement): l = list() cdef NCPolynomialRing_plural parent = self._parent cdef ring *_ring = parent._ring - if(_ring != currRing): rChangeCurrRing(_ring) + if _ring != currRing: + rChangeCurrRing(_ring) cdef poly *p = p_Copy(self._poly, _ring) cdef poly *t @@ -2550,7 +2546,7 @@ cdef class NCPolynomial_plural(RingElement): p.next = NULL p_SetCoeff(p, n_Init(1,_ring.cf), _ring) p_Setm(p, _ring) - l.append( new_NCP(parent,p) ) + l.append(new_NCP(parent, p)) p = t return l @@ -2582,9 +2578,9 @@ cdef class NCPolynomial_plural(RingElement): p = pNext(p) if p_LmIsConstant(p, r): - return si2sa( p_GetCoeff(p, r), r, (self._parent)._base ) - else: - return (self._parent)._base._zero_element + return si2sa(p_GetCoeff(p, r), r, + (self._parent)._base) + return (self._parent)._base._zero_element cpdef is_constant(self) noexcept: """ @@ -2605,10 +2601,10 @@ cdef class NCPolynomial_plural(RingElement): def lm(NCPolynomial_plural self): """ - Returns the lead monomial of ``self`` with respect to the term + Return the lead monomial of ``self`` with respect to the term order of ``self.parent()``. - In Sage a monomial is a product of variables in some power + In Sage, a monomial is a product of variables in some power without a coefficient. EXAMPLES:: @@ -2645,7 +2641,6 @@ cdef class NCPolynomial_plural(RingElement): sage: f = x^4*y^7*z^1 + x^4*y^2*z^3 sage: f.lm() x^4*y^7*z - """ cdef poly *_p cdef ring *_ring @@ -2677,7 +2672,6 @@ cdef class NCPolynomial_plural(RingElement): sage: f.lc() 5 """ - cdef poly *_p cdef ring *_ring cdef number *_n @@ -2686,20 +2680,21 @@ cdef class NCPolynomial_plural(RingElement): if self._poly == NULL: return (self._parent)._base._zero_element - if(_ring != currRing): rChangeCurrRing(_ring) + if _ring != currRing: + rChangeCurrRing(_ring) _p = p_Head(self._poly, _ring) _n = p_GetCoeff(_p, _ring) - ret = si2sa(_n, _ring, (self._parent)._base) + ret = si2sa(_n, _ring, (self._parent)._base) p_Delete(&_p, _ring) return ret def lt(NCPolynomial_plural self): """ - Leading term of this polynomial. + Return the leading term of this polynomial. - In Sage a term is a product of variables in some power and a + In Sage, a term is a product of variables in some power and a coefficient. EXAMPLES:: @@ -2721,7 +2716,7 @@ cdef class NCPolynomial_plural(RingElement): return (self._parent)._zero_element return new_NCP((self._parent), - p_Head(self._poly,(self._parent)._ring)) + p_Head(self._poly,(self._parent)._ring)) def is_zero(self): """ @@ -2739,10 +2734,7 @@ cdef class NCPolynomial_plural(RingElement): sage: (x-x).is_zero() True """ - if self._poly is NULL: - return True - else: - return False + return self._poly is NULL def __bool__(self): """ @@ -2758,10 +2750,7 @@ cdef class NCPolynomial_plural(RingElement): sage: bool(x-x) False """ - if self._poly: - return True - else: - return False + return True if self._poly else False def __call__(self, *x, **kwds): """ @@ -2809,9 +2798,8 @@ cdef class NCPolynomial_plural(RingElement): ##################################################################### - cdef inline NCPolynomial_plural new_NCP(NCPolynomialRing_plural parent, - poly *juice) noexcept: + poly *juice) noexcept: """ Construct NCPolynomial_plural from parent and SINGULAR poly. @@ -2821,7 +2809,6 @@ cdef inline NCPolynomial_plural new_NCP(NCPolynomialRing_plural parent, sage: H = A.g_algebra({z*x:x*z+2*x, z*y:y*z-2*y}) sage: H.gen(2) # indirect doctest z - """ cdef NCPolynomial_plural p = NCPolynomial_plural.__new__(NCPolynomial_plural) p._parent = parent @@ -2830,8 +2817,6 @@ cdef inline NCPolynomial_plural new_NCP(NCPolynomialRing_plural parent, return p - - cpdef MPolynomialRing_libsingular new_CRing(RingWrap rw, base_ring) noexcept: """ Construct MPolynomialRing_libsingular from ringWrap, assuming the ground field to be base_ring @@ -2876,7 +2861,7 @@ cpdef MPolynomialRing_libsingular new_CRing(RingWrap rw, base_ring) noexcept: sage: C.one() 1 """ - assert( rw.is_commutative() ) + assert rw.is_commutative() cdef MPolynomialRing_libsingular self = MPolynomialRing_libsingular.__new__(MPolynomialRing_libsingular) @@ -2891,15 +2876,13 @@ cpdef MPolynomialRing_libsingular new_CRing(RingWrap rw, base_ring) noexcept: self._ring.ShortOut = 0 self._ngens = rw.ngens() - self._term_order = TermOrder(rw.ordering_string(), force=True) + self._term_order = TermOrder(rw.ordering_string(), force=True) - ParentWithGens.__init__(self, base_ring, tuple(rw.var_names()), - normalize=False) -# self._populate_coercion_lists_() # ??? + names = tuple(rw.var_names()) + Ring.__init__(self, base_ring, names, category=Algebras(base_ring), + normalize=False) - #MPolynomialRing_generic.__init__(self, base_ring, n, names, order) self._has_singular = True -# self._relations = self.relations() return self @@ -2951,8 +2934,7 @@ cpdef NCPolynomialRing_plural new_NRing(RingWrap rw, base_ring) noexcept: Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: x*y - 1} """ - - assert( not rw.is_commutative() ) + assert not rw.is_commutative() cdef NCPolynomialRing_plural self = NCPolynomialRing_plural.__new__(NCPolynomialRing_plural) self._ring = rw._ring @@ -2963,12 +2945,10 @@ cpdef NCPolynomialRing_plural new_NRing(RingWrap rw, base_ring) noexcept: self._ring.ShortOut = 0 self._ngens = rw.ngens() - self._term_order = TermOrder(rw.ordering_string(), force=True) + self._term_order = TermOrder(rw.ordering_string(), force=True) - ParentWithGens.__init__(self, base_ring, rw.var_names()) -# self._populate_coercion_lists_() # ??? + Ring.__init__(self, base_ring, rw.var_names(), category=Algebras(base_ring)) - #MPolynomialRing_generic.__init__(self, base_ring, n, names, order) self._has_singular = True self._relations = self.relations() @@ -3029,6 +3009,7 @@ def new_Ring(RingWrap rw, base_ring): return new_CRing(rw, base_ring) return new_NRing(rw, base_ring) + def SCA(base_ring, names, alt_vars, order='degrevlex'): """ Return a free graded-commutative algebra @@ -3067,24 +3048,25 @@ def SCA(base_ring, names, alt_vars, order='degrevlex'): n = len(names) alt_start = min(alt_vars) alt_end = max(alt_vars) - assert( alt_start >= 0 ) - assert( (alt_end >= alt_start) and (alt_end < n) ) + assert 0 <= alt_start <= alt_end < n - relations = {} # {y*x:-x*y} + relations = {} # {y*x:-x*y} from sage.algebras.free_algebra import FreeAlgebra A = FreeAlgebra(base_ring, n, names) for r in range(0, n-1, 1): for c in range(r+1, n, 1): - if (r in alt_vars) and (c in alt_vars): - relations[ A.gen(c) * A.gen(r) ] = - A.gen(r) * A.gen(c) + if r in alt_vars and c in alt_vars: + relations[A.gen(c) * A.gen(r)] = - A.gen(r) * A.gen(c) - cdef NCPolynomialRing_plural H = A.g_algebra(relations=relations, order=order) + cdef NCPolynomialRing_plural H = A.g_algebra(relations=relations, + order=order) I = H.ideal([H.gen(i) * H.gen(i) for i in alt_vars]).twostd() return H.quotient(I) + def ExteriorAlgebra(base_ring, names,order='degrevlex'): """ - Return the exterior algebra on some generators + Return the exterior algebra on some generators. This is also known as a Grassmann algebra. This is a finite dimensional algebra, where all generators anti-commute. @@ -3116,17 +3098,19 @@ def ExteriorAlgebra(base_ring, names,order='degrevlex'): 1 """ n = len(names) - relations = {} # {y*x:-x*y} + relations = {} # {y*x:-x*y} from sage.algebras.free_algebra import FreeAlgebra A = FreeAlgebra(base_ring, n, names) for r in range(n-1): for c in range(r+1, n): - relations[ A.gen(c) * A.gen(r) ] = - A.gen(r) * A.gen(c) + relations[A.gen(c) * A.gen(r)] = - A.gen(r) * A.gen(c) - cdef NCPolynomialRing_plural H = A.g_algebra(relations=relations,order=order) + cdef NCPolynomialRing_plural H = A.g_algebra(relations=relations, + order=order) I = H.ideal([H.gen(i) * H.gen(i) for i in range(n)]).twostd() return H.quotient(I) + cdef poly *addwithcarry(poly *tempvector, poly *maxvector, int pos, ring *_ring) noexcept: if p_GetExp(tempvector, pos, _ring) < p_GetExp(maxvector, pos, _ring): p_SetExp(tempvector, pos, p_GetExp(tempvector, pos, _ring)+1, _ring) From e5333f877c423da1b8dd931b26d69e1d99acb8fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 9 Nov 2023 15:23:37 +0100 Subject: [PATCH 057/155] get rid of some ParentWithGens in real and complex fields --- src/sage/rings/complex_double.pyx | 4 ++-- src/sage/rings/complex_mpc.pyx | 4 ++-- src/sage/rings/complex_mpfr.pyx | 4 ++-- src/sage/rings/real_mpfr.pyx | 16 ++++++++-------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index 8f1e8205817..d72298657fe 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -81,10 +81,10 @@ cdef extern from "": import sage.rings.abc cimport sage.rings.ring cimport sage.rings.integer +from sage.rings.ring import Ring from sage.structure.element cimport Element, FieldElement from sage.structure.parent cimport Parent -from sage.structure.parent_gens import ParentWithGens from sage.structure.richcmp cimport rich_to_bool from sage.categories.morphism cimport Morphism from sage.structure.coerce cimport is_numpy_type @@ -149,7 +149,7 @@ cdef class ComplexDoubleField_class(sage.rings.abc.ComplexDoubleField): (-1.0, -1.0 + 1.2246...e-16*I, False) """ from sage.categories.fields import Fields - ParentWithGens.__init__(self, self, ('I',), normalize=False, category=Fields().Infinite().Metric().Complete()) + Ring.__init__(self, self, ('I',), normalize=False, category=Fields().Infinite().Metric().Complete()) self._populate_coercion_lists_() def __reduce__(self): diff --git a/src/sage/rings/complex_mpc.pyx b/src/sage/rings/complex_mpc.pyx index 562286db44e..e584c9b72c9 100644 --- a/src/sage/rings/complex_mpc.pyx +++ b/src/sage/rings/complex_mpc.pyx @@ -68,11 +68,11 @@ from sage.cpython.string cimport str_to_bytes from sage.libs.mpfr cimport * from sage.libs.mpc cimport * from sage.structure.parent cimport Parent -from sage.structure.parent_gens cimport ParentWithGens from sage.structure.element cimport Element from sage.structure.richcmp cimport rich_to_bool from sage.categories.map cimport Map from sage.libs.pari.all import pari +from sage.rings.ring import Ring from .integer cimport Integer from .complex_mpfr cimport ComplexNumber @@ -319,7 +319,7 @@ cdef class MPComplexField_class(sage.rings.ring.Field): self.__real_field = real_mpfr.RealField(prec, rnd=_mpfr_rounding_modes[rnd_re(n)]) self.__imag_field = real_mpfr.RealField(prec, rnd=_mpfr_rounding_modes[rnd_im(n)]) - ParentWithGens.__init__(self, self._real_field(), ('I',), False, category=Fields().Infinite()) + Ring.__init__(self, self._real_field(), ('I',), False, category=Fields().Infinite()) self._populate_coercion_lists_(coerce_list=[MPFRtoMPC(self._real_field(), self)]) cdef MPComplexNumber _new(self) noexcept: diff --git a/src/sage/rings/complex_mpfr.pyx b/src/sage/rings/complex_mpfr.pyx index d6f92bb2fee..cf6d41cda32 100644 --- a/src/sage/rings/complex_mpfr.pyx +++ b/src/sage/rings/complex_mpfr.pyx @@ -40,7 +40,7 @@ from sage.structure.element cimport RingElement, Element from sage.structure.richcmp cimport rich_to_bool from sage.categories.map cimport Map from sage.structure.parent import Parent -from sage.structure.parent_gens import ParentWithGens +from sage.rings.ring import Ring from sage.misc.sage_eval import sage_eval @@ -277,7 +277,7 @@ class ComplexField_class(sage.rings.abc.ComplexField): """ self._prec = int(prec) from sage.categories.fields import Fields - ParentWithGens.__init__(self, self._real_field(), ('I',), False, category=Fields().Infinite().Metric().Complete()) + Ring.__init__(self, self._real_field(), ('I',), False, category=Fields().Infinite().Metric().Complete()) self._populate_coercion_lists_(coerce_list=[RRtoCC(self._real_field(), self)], convert_method_name='_complex_mpfr_') diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 4a091fd9191..65621002288 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -107,7 +107,7 @@ Make sure we don't have a new field for every new literal:: True """ -#***************************************************************************** +# ***************************************************************************** # Copyright (C) 2005-2006 William Stein # # This program is free software: you can redistribute it and/or modify @@ -115,7 +115,7 @@ Make sure we don't have a new field for every new literal:: # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # https://www.gnu.org/licenses/ -#***************************************************************************** +# ***************************************************************************** import math # for log import sys @@ -158,8 +158,8 @@ from .real_double cimport RealDoubleElement import sage.rings.rational_field import sage.rings.infinity +from sage.rings.ring import Ring -from sage.structure.parent_gens cimport ParentWithGens from sage.arith.numerical_approx cimport digits_to_bits from sage.arith.constants cimport M_LN2_LN10 from sage.arith.long cimport is_small_python_int @@ -169,11 +169,11 @@ cimport gmpy2 gmpy2.import_gmpy2() -#***************************************************************************** +# **************************************************************************** # # Implementation # -#***************************************************************************** +# **************************************************************************** _re_skip_zeroes = re.compile(r'^(.+?)0*$') @@ -356,11 +356,11 @@ def mpfr_get_exp_max_max(): mpfr_set_exp_min(mpfr_get_emin_min()) mpfr_set_exp_max(mpfr_get_emax_max()) -#***************************************************************************** +# ***************************************************************************** # # Real Field # -#***************************************************************************** +# ***************************************************************************** # The real field is in Cython, so mpfr elements will have access to # their parent via direct C calls, which will be faster. @@ -534,7 +534,7 @@ cdef class RealField_class(sage.rings.abc.RealField): self.rnd_str = char_to_str(rnd_str + 5) # Strip "MPFR_" from sage.categories.fields import Fields - ParentWithGens.__init__(self, self, tuple(), False, category=Fields().Infinite().Metric().Complete()) + Ring.__init__(self, self, tuple(), False, category=Fields().Infinite().Metric().Complete()) # Initialize zero and one cdef RealNumber rn From f43552ef2b44e2c7eec235929d9253975db47a02 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Nov 2023 08:11:34 -0800 Subject: [PATCH 058/155] src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst: Restore lost # random --- src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst b/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst index d083abf8859..ca7fdac7197 100644 --- a/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst +++ b/src/doc/en/thematic_tutorials/geometry/polyhedra_tutorial.rst @@ -202,7 +202,7 @@ It is also possible to define a polyhedron over algebraic numbers. sage: # needs sage.rings.number_field sage: sqrt_2 = AA(2)^(1/2) sage: cbrt_2 = AA(2)^(1/3) - sage: timeit('Polyhedron(vertices=[[sqrt_2, 0], [0, cbrt_2]])') + sage: timeit('Polyhedron(vertices=[[sqrt_2, 0], [0, cbrt_2]])') # random 5 loops, best of 3: 43.2 ms per loop sage: P4 = Polyhedron(vertices=[[sqrt_2, 0], [0, cbrt_2]]); P4 A 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices From d745084f9cc2b65b930d8ce69001b0e8daaab925 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Thu, 9 Nov 2023 10:17:32 -0800 Subject: [PATCH 059/155] Incidental edits from #36372 (Fix/ignore all remaining test failures when run under conda) --- src/sage/crypto/mq/sr.py | 20 ++-- .../matrix_gps/finitely_generated_gap.py | 7 +- src/sage/parallel/map_reduce.py | 10 +- src/sage/repl/ipython_kernel/install.py | 8 +- .../polynomial/multi_polynomial_ideal.py | 92 +++++++++++-------- .../polynomial/multi_polynomial_sequence.py | 32 ++++--- src/sage/rings/polynomial/pbori/fglm.py | 4 +- src/sage_setup/clean.py | 4 +- 8 files changed, 104 insertions(+), 73 deletions(-) diff --git a/src/sage/crypto/mq/sr.py b/src/sage/crypto/mq/sr.py index c4293c5a0e2..49b7d67374d 100644 --- a/src/sage/crypto/mq/sr.py +++ b/src/sage/crypto/mq/sr.py @@ -308,23 +308,21 @@ - [MR2002]_ """ -from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF -from sage.rings.integer_ring import ZZ -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing, BooleanPolynomialRing_constructor as BooleanPolynomialRing - -from sage.structure.element import is_Matrix from sage.matrix.constructor import Matrix, random_matrix from sage.matrix.matrix_space import MatrixSpace - -from sage.misc.verbose import get_verbose from sage.misc.flatten import flatten - +from sage.misc.verbose import get_verbose from sage.modules.vector_modn_dense import Vector_modn_dense - +from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF +from sage.rings.integer_ring import ZZ from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence -from .mpolynomialsystemgenerator import MPolynomialSystemGenerator - +from sage.rings.polynomial.polynomial_ring_constructor import \ + BooleanPolynomialRing_constructor as BooleanPolynomialRing +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.polynomial.term_order import TermOrder +from sage.structure.element import is_Matrix + +from .mpolynomialsystemgenerator import MPolynomialSystemGenerator def SR(n=1, r=1, c=1, e=4, star=False, **kwargs): diff --git a/src/sage/groups/matrix_gps/finitely_generated_gap.py b/src/sage/groups/matrix_gps/finitely_generated_gap.py index fcfb223b58d..af676af3673 100644 --- a/src/sage/groups/matrix_gps/finitely_generated_gap.py +++ b/src/sage/groups/matrix_gps/finitely_generated_gap.py @@ -34,9 +34,9 @@ from sage.modules.free_module_element import vector from sage.rings.fraction_field import FractionField from sage.rings.integer_ring import ZZ +from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.power_series_ring import PowerSeriesRing -from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence class FinitelyGeneratedMatrixGroup_gap(MatrixGroup_gap): @@ -313,8 +313,9 @@ def invariant_generators(self): - S. King, "Minimal Generating Sets of non-modular invariant rings of finite groups", :arxiv:`math/0703035`. """ - from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.interfaces.singular import singular + from sage.rings.polynomial.polynomial_ring_constructor import \ + PolynomialRing gens = self.gens() singular.LIB("finvar.lib") n = self.degree() # len((gens[0].matrix()).rows()) @@ -755,6 +756,7 @@ def reynolds_operator(self, poly, chi=None): if chi is None: # then this is the trivial character if R.characteristic() == 0: from sage.rings.qqbar import QQbar + # non-modular case if C == QQbar or R == QQbar: L = QQbar @@ -788,6 +790,7 @@ def reynolds_operator(self, poly, chi=None): K = chi.values()[0].parent() if R.characteristic() == 0: from sage.rings.qqbar import QQbar + # extend base_ring to compositum if C == QQbar or K == QQbar or R == QQbar: L = QQbar diff --git a/src/sage/parallel/map_reduce.py b/src/sage/parallel/map_reduce.py index a7b610b10e1..66fea7f394f 100644 --- a/src/sage/parallel/map_reduce.py +++ b/src/sage/parallel/map_reduce.py @@ -548,17 +548,17 @@ # https://www.gnu.org/licenses/ # **************************************************************************** import copy -import sys -import random -import queue import ctypes import logging import multiprocessing as mp +import queue +import random +import sys from collections import deque from threading import Thread -from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet # _generic from sage.misc.lazy_attribute import lazy_attribute +from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet # _generic logger = logging.getLogger(__name__) logger.__doc__ = (""" @@ -1895,8 +1895,8 @@ def __init__(self, maxl=9): """ RESetMapReduce.__init__(self) - from sage.rings.polynomial.polynomial_ring import polygen from sage.rings.integer_ring import ZZ + from sage.rings.polynomial.polynomial_ring import polygen self.x = polygen(ZZ, 'x') self.maxl = maxl diff --git a/src/sage/repl/ipython_kernel/install.py b/src/sage/repl/ipython_kernel/install.py index 081599b3452..0adeab04bcd 100644 --- a/src/sage/repl/ipython_kernel/install.py +++ b/src/sage/repl/ipython_kernel/install.py @@ -14,12 +14,14 @@ """ -import os import errno +import os import warnings from sage.env import ( - SAGE_DOC, SAGE_VENV, SAGE_EXTCODE, + SAGE_DOC, + SAGE_EXTCODE, + SAGE_VENV, SAGE_VERSION, THREEJS_DIR, ) @@ -257,7 +259,7 @@ def check(cls): sage: from sage.repl.ipython_kernel.install import SageKernelSpec sage: SageKernelSpec.check() # random """ - from jupyter_client.kernelspec import get_kernel_spec, NoSuchKernel + from jupyter_client.kernelspec import NoSuchKernel, get_kernel_spec ident = cls.identifier() try: spec = get_kernel_spec(ident) diff --git a/src/sage/rings/polynomial/multi_polynomial_ideal.py b/src/sage/rings/polynomial/multi_polynomial_ideal.py index a752af29e75..4b460f244d6 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ideal.py +++ b/src/sage/rings/polynomial/multi_polynomial_ideal.py @@ -238,33 +238,34 @@ import sage.rings.abc import sage.rings.polynomial.toy_buchberger as toy_buchberger -import sage.rings.polynomial.toy_variety as toy_variety import sage.rings.polynomial.toy_d_basis as toy_d_basis - +import sage.rings.polynomial.toy_variety as toy_variety from sage.misc.cachefunc import cached_method from sage.misc.method_decorator import MethodDecorator from sage.misc.misc_c import prod -from sage.misc.verbose import verbose, get_verbose +from sage.misc.verbose import get_verbose, verbose from sage.rings.ideal import Ideal_generic from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.noncommutative_ideals import Ideal_nc from sage.rings.qqbar_decorators import handle_AA_and_QQbar +from sage.structure.richcmp import (op_EQ, op_GE, op_GT, op_LE, op_LT, op_NE, + rich_to_bool, richcmp_method) from sage.structure.sequence import Sequence -from sage.structure.richcmp import (richcmp_method, op_EQ, op_NE, - op_LT, op_GT, op_LE, op_GE, rich_to_bool) - try: from sage.interfaces.expect import StdOutContext - from sage.interfaces.singular import singular as singular_default, singular_gb_standard_options - from sage.libs.singular.standard_options import libsingular_gb_standard_options + from sage.interfaces.singular import singular as singular_default + from sage.interfaces.singular import singular_gb_standard_options + from sage.libs.singular.standard_options import \ + libsingular_gb_standard_options except ImportError: singular_default = None singular_gb_standard_options = libsingular_gb_standard_options = MethodDecorator try: - from sage.interfaces.magma import magma as magma_default, magma_gb_standard_options + from sage.interfaces.magma import magma as magma_default + from sage.interfaces.magma import magma_gb_standard_options except ImportError: magma_default = None magma_gb_standard_options = MethodDecorator @@ -439,7 +440,8 @@ def _groebner_basis_magma(self, deg_bound=None, prot=False, magma=magma_default) a = str(R.base_ring().gen()) mgb = [e.replace("$.1",a) for e in mgb] - from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence + from sage.rings.polynomial.multi_polynomial_sequence import \ + PolynomialSequence B = PolynomialSequence([R(e) for e in mgb], R, immutable=True) return B @@ -531,11 +533,11 @@ def _groebner_basis_libsingular(self, algorithm="groebner", *args, **kwds): sage: len(gI.gens()) 3 """ - from sage.rings.polynomial.multi_polynomial_ideal_libsingular import std_libsingular, slimgb_libsingular from sage.libs.singular.function import singular_function - from sage.libs.singular.option import opt - from sage.libs.singular.function_factory import ff + from sage.libs.singular.option import opt + from sage.rings.polynomial.multi_polynomial_ideal_libsingular import ( + slimgb_libsingular, std_libsingular) groebner = ff.groebner if get_verbose() >= 2: @@ -592,14 +594,15 @@ def _groebner_cover(self): [[1], [1], [[[(2*a + 3)], [[1]]]]]] """ from sage.rings.fraction_field import FractionField_generic - from sage.rings.polynomial.multi_polynomial_ring_base import is_MPolynomialRing + from sage.rings.polynomial.multi_polynomial_ring_base import \ + is_MPolynomialRing from sage.rings.polynomial.polynomial_ring import is_PolynomialRing F = self.base_ring() if (not isinstance(F, FractionField_generic) or (not is_MPolynomialRing(F.ring()) and not is_PolynomialRing(F.ring()))): raise TypeError("the base ring must be a field with parameters") - from sage.libs.singular.function import singular_function, lib from sage.arith.functions import lcm + from sage.libs.singular.function import lib, singular_function lib("grobcov.lib") grobcov = singular_function("grobcov") polynomials = [] @@ -1142,8 +1145,8 @@ def triangular_decomposition(self, algorithm=None, singular=singular_default): if I.dimension() != 0: raise TypeError("dimension must be zero") - from sage.libs.singular.function import singular_function from sage.libs.singular.function import lib as singular_lib + from sage.libs.singular.function import singular_function singular_lib('triang.lib') @@ -1471,7 +1474,8 @@ def _groebner_basis_singular(self, algorithm="groebner", *args, **kwds): This method is called by the :meth:`.groebner_basis` method and the user usually doesn't need to bother with this one. """ - from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence + from sage.rings.polynomial.multi_polynomial_sequence import \ + PolynomialSequence R = self.ring() S = self._groebner_basis_singular_raw(algorithm=algorithm, *args, **kwds) @@ -1806,7 +1810,8 @@ def integral_closure(self, p=0, r=True, singular=singular_default): Uses libSINGULAR. """ - from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence + from sage.rings.polynomial.multi_polynomial_sequence import \ + PolynomialSequence R = self.ring() from sage.libs.singular.function_factory import ff @@ -1895,9 +1900,11 @@ def free_resolution(self, *args, **kwds): ... NotImplementedError: the ring must be a polynomial ring using Singular """ - from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular + from sage.rings.polynomial.multi_polynomial_libsingular import \ + MPolynomialRing_libsingular if isinstance(self.ring(), MPolynomialRing_libsingular): - from sage.homology.free_resolution import FiniteFreeResolution_singular + from sage.homology.free_resolution import \ + FiniteFreeResolution_singular return FiniteFreeResolution_singular(self, *args, **kwds) raise NotImplementedError("the ring must be a polynomial ring using Singular") @@ -1934,9 +1941,11 @@ def graded_free_resolution(self, *args, **kwds): ... NotImplementedError: the ring must be a polynomial ring using Singular """ - from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular + from sage.rings.polynomial.multi_polynomial_libsingular import \ + MPolynomialRing_libsingular if isinstance(self.ring(), MPolynomialRing_libsingular): - from sage.homology.graded_resolution import GradedFiniteFreeResolution_singular + from sage.homology.graded_resolution import \ + GradedFiniteFreeResolution_singular return GradedFiniteFreeResolution_singular(self, *args, **kwds) raise NotImplementedError("the ring must be a polynomial ring using Singular") @@ -2110,9 +2119,9 @@ def basis_is_groebner(self, singular=singular_default): sage: I2.basis_is_groebner() True """ - from sage.matrix.constructor import matrix - from sage.libs.singular.option import opt_verb_ctx from sage.libs.singular.function_factory import ff + from sage.libs.singular.option import opt_verb_ctx + from sage.matrix.constructor import matrix sing_reduce = ff.reduce syz = ff.syz @@ -2220,7 +2229,8 @@ def transformed_basis(self, algorithm="gwalk", other_ring=None, singular=singula sage: J = Ideal(I.transformed_basis('fglm', other_ring=S)) # known bug sage: J # known bug """ - from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence + from sage.rings.polynomial.multi_polynomial_sequence import \ + PolynomialSequence R = self.ring() if self.basis_is_groebner(): @@ -2229,8 +2239,7 @@ def transformed_basis(self, algorithm="gwalk", other_ring=None, singular=singula I = R.ideal(self.groebner_basis()) if algorithm in ("gwalk","awalk1","awalk2","twalk","fwalk"): - from sage.libs.singular.function import lib - from sage.libs.singular.function import singular_function + from sage.libs.singular.function import lib, singular_function lib("grwalk.lib") gb = singular_function(algorithm)(I) return PolynomialSequence(R, sorted(gb,reverse=True), immutable=True) @@ -2468,6 +2477,7 @@ def saturation(self, other): (Ideal (y, x^5) of Multivariate Polynomial Ring in x, y, z over Algebraic Field, 4) """ from sage.libs.singular.function_factory import ff + # function renamed in singular > 4.3.2p4, see issue #35980 try: sat = ff.elim__lib.sat_with_exp @@ -3242,8 +3252,10 @@ def _normal_basis_libsingular(self, degree, weights=None): sage: I.normal_basis() [k, 1] """ - from sage.rings.polynomial.multi_polynomial_ideal_libsingular import kbase_libsingular - from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence + from sage.rings.polynomial.multi_polynomial_ideal_libsingular import \ + kbase_libsingular + from sage.rings.polynomial.multi_polynomial_sequence import \ + PolynomialSequence gb = self._groebner_basis_libsingular() J = self.ring().ideal(gb) if weights is None or degree is None: @@ -3330,7 +3342,8 @@ def normal_basis(self, degree=None, algorithm='libsingular', sage: S.ideal(x^6 + y^3 + z^2).normal_basis(6, algorithm='singular') # needs sage.rings.finite_rings [x^4*y, x^2*y^2, y^3, x^3*z, x*y*z, z^2] """ - from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence + from sage.rings.polynomial.multi_polynomial_sequence import \ + PolynomialSequence weights = tuple(x.degree() for x in self.ring().gens()) if all(w == 1 for w in weights): @@ -3427,7 +3440,8 @@ def _groebner_basis_macaulay2(self, strategy=None): ... ValueError: unsupported Macaulay2 strategy """ - from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence + from sage.rings.polynomial.multi_polynomial_sequence import \ + PolynomialSequence I = self._macaulay2_() if strategy == "gb" or strategy is None: @@ -3904,7 +3918,8 @@ def gens(self): sage: I.gens() [x, y + 1] """ - from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence + from sage.rings.polynomial.multi_polynomial_sequence import \ + PolynomialSequence return PolynomialSequence(self.ring(), Ideal_generic.gens(self), immutable=True) @property @@ -4636,8 +4651,10 @@ def groebner_basis(self, algorithm='', deg_bound=None, mult_bound=None, prot=Fal ... NotImplementedError: msolve only supports the degrevlex order (use transformed_basis()) """ - from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence - from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + from sage.rings.polynomial.multi_polynomial_sequence import \ + PolynomialSequence + from sage.rings.polynomial.polynomial_ring_constructor import \ + PolynomialRing if algorithm.lower() == "magma": algorithm = "magma:GroebnerBasis" @@ -5144,9 +5161,9 @@ def degree_of_semi_regularity(self): if m <= n: raise ValueError("This function requires an overdefined system of polynomials.") - from sage.rings.rational_field import QQ from sage.misc.misc_c import prod from sage.rings.power_series_ring import PowerSeriesRing + from sage.rings.rational_field import QQ z = PowerSeriesRing(QQ, 'z', default_prec=sum(degs)).gen() s = prod([1-z**d for d in degs]) / (1-z)**n @@ -5220,8 +5237,8 @@ def plot(self, *args, **kwds): Graphics object consisting of 1 graphics primitive """ - from sage.rings.real_mpfr import RR from sage.plot.all import implicit_plot + from sage.rings.real_mpfr import RR K = self.base_ring() if not RR.has_coerce_map_from(K): @@ -5538,7 +5555,8 @@ def weil_restriction(self): Based on a Singular implementation by Michael Brickenstein """ - from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + from sage.rings.polynomial.polynomial_ring_constructor import \ + PolynomialRing R = self.ring() nvars = R.ngens() diff --git a/src/sage/rings/polynomial/multi_polynomial_sequence.py b/src/sage/rings/polynomial/multi_polynomial_sequence.py index b52fb34f721..9f0c7712d58 100644 --- a/src/sage/rings/polynomial/multi_polynomial_sequence.py +++ b/src/sage/rings/polynomial/multi_polynomial_sequence.py @@ -173,10 +173,10 @@ from sage.rings.quotient_ring import is_QuotientRing from sage.structure.sequence import Sequence_generic - try: from sage.interfaces.singular import singular, singular_gb_standard_options - from sage.libs.singular.standard_options import libsingular_gb_standard_options + from sage.libs.singular.standard_options import \ + libsingular_gb_standard_options except ImportError: singular = None singular_gb_standard_options = libsingular_gb_standard_options = MethodDecorator @@ -1151,8 +1151,10 @@ def reduced(self): [y^3 + z, x*y + (1 + 2 + O(2^20))*z, x*z - z] """ - from sage.rings.polynomial.multi_polynomial_ideal_libsingular import interred_libsingular - from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular + from sage.rings.polynomial.multi_polynomial_ideal_libsingular import \ + interred_libsingular + from sage.rings.polynomial.multi_polynomial_libsingular import \ + MPolynomialRing_libsingular R = self.ring() @@ -1169,7 +1171,8 @@ def reduced(self): ret.append(f.lc()**(-1)*f) # lead coeffs are not reduced by interred s.option("set",o) except TypeError: - from sage.rings.polynomial.toy_buchberger import inter_reduction + from sage.rings.polynomial.toy_buchberger import \ + inter_reduction ret = inter_reduction(self) ret = sorted(ret, reverse=True) @@ -1327,15 +1330,17 @@ def eliminate_linear_variables(self, maxlength=Infinity, skip=None, return_reduc This is called "massaging" in [BCJ2007]_. """ - from sage.rings.polynomial.multi_polynomial_ring_base import BooleanPolynomialRing_base + from sage.rings.polynomial.multi_polynomial_ring_base import \ + BooleanPolynomialRing_base R = self.ring() if not isinstance(R, BooleanPolynomialRing_base): raise NotImplementedError("Only BooleanPolynomialRing's are supported.") + from sage.rings.polynomial.pbori.ll import (eliminate, ll_encode, + ll_red_nf_redsb) from sage.rings.polynomial.pbori.pbori import gauss_on_polys - from sage.rings.polynomial.pbori.ll import eliminate, ll_encode, ll_red_nf_redsb F = self reductors = [] @@ -1413,7 +1418,8 @@ def _groebner_strategy(self): sage: F._groebner_strategy() """ - from sage.rings.polynomial.multi_polynomial_ring_base import BooleanPolynomialRing_base + from sage.rings.polynomial.multi_polynomial_ring_base import \ + BooleanPolynomialRing_base R = self.ring() @@ -1537,7 +1543,8 @@ def solve(self, algorithm='polybori', n=1, eliminate_linear_variables=True, ver if eliminate_linear_variables: T, reductors = self.eliminate_linear_variables(return_reductors=True) if T.variables() != (): - from sage.rings.polynomial.pbori.pbori import BooleanPolynomialRing + from sage.rings.polynomial.pbori.pbori import \ + BooleanPolynomialRing R_solving = BooleanPolynomialRing( T.nvariables(), [str(_) for _ in list(T.variables())] ) S = PolynomialSequence( R_solving, [ R_solving(f) for f in T] ) @@ -1621,12 +1628,14 @@ def reduced(self): ....: assert g[i].lt() not in t.divisors() """ - from sage.rings.polynomial.multi_polynomial_ring_base import BooleanPolynomialRing_base + from sage.rings.polynomial.multi_polynomial_ring_base import \ + BooleanPolynomialRing_base R = self.ring() if isinstance(R, BooleanPolynomialRing_base): - from sage.rings.polynomial.pbori.interred import interred as inter_red + from sage.rings.polynomial.pbori.interred import \ + interred as inter_red l = [p for p in self if not p == 0] l = sorted(inter_red(l, completely=True), reverse=True) @@ -1683,5 +1692,6 @@ def weil_restriction(self): from sage.misc.persist import register_unpickle_override + register_unpickle_override("sage.crypto.mq.mpolynomialsystem","MPolynomialSystem_generic", PolynomialSequence_generic) register_unpickle_override("sage.crypto.mq.mpolynomialsystem","MPolynomialRoundSystem_generic", PolynomialSequence_generic) diff --git a/src/sage/rings/polynomial/pbori/fglm.py b/src/sage/rings/polynomial/pbori/fglm.py index dc60adef14c..60559b31b85 100644 --- a/src/sage/rings/polynomial/pbori/fglm.py +++ b/src/sage/rings/polynomial/pbori/fglm.py @@ -1,5 +1,5 @@ -from .PyPolyBoRi import Polynomial, BoolePolynomialVector -from .pbori import FGLMStrategy, BooleSet +from .pbori import BooleSet, FGLMStrategy +from .PyPolyBoRi import BoolePolynomialVector, Polynomial def _fglm(I, from_ring, to_ring): diff --git a/src/sage_setup/clean.py b/src/sage_setup/clean.py index 3cf0d08a353..e9c81c9ed1a 100644 --- a/src/sage_setup/clean.py +++ b/src/sage_setup/clean.py @@ -15,11 +15,11 @@ #***************************************************************************** -import os import importlib.util +import os from sage.misc.package_dir import SourceDistributionFilter -from sage_setup.find import installed_files_by_module, get_extensions +from sage_setup.find import get_extensions, installed_files_by_module def _remove(file_set, module_base, to_remove): From a29689ec51655c2e69e8b7cc95640078a3fec861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 10 Nov 2023 08:40:59 +0100 Subject: [PATCH 060/155] suggested details --- src/sage/rings/polynomial/plural.pyx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index 17a95c52618..f06b8241e9c 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -334,8 +334,7 @@ cdef class NCPolynomialRing_plural(Ring): self._ngens = n self._term_order = order - Ring.__init__(self, base_ring, names, category=category, - normalize=False) + Ring.__init__(self, base_ring, names, category=category) self._populate_coercion_lists_() assert n == len(self._names) @@ -2716,7 +2715,7 @@ cdef class NCPolynomial_plural(RingElement): return (self._parent)._zero_element return new_NCP((self._parent), - p_Head(self._poly,(self._parent)._ring)) + p_Head(self._poly, (self._parent)._ring)) def is_zero(self): """ From b23f4cea97812c51dfbaa51e48e3a16dc99b7061 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 10 Nov 2023 09:15:41 +0100 Subject: [PATCH 061/155] free_space_on_docker_hub_workflow initial --- .ci/describe-system.sh | 23 --- .ci/protect-secrets.sh | 40 ----- .github/workflows/docker_hub.yml | 91 +++++++++++ .github/workflows/push_to_docker_hub.yml | 112 ++----------- .gitlab-ci.yml | 195 ----------------------- 5 files changed, 107 insertions(+), 354 deletions(-) delete mode 100755 .ci/describe-system.sh delete mode 100755 .ci/protect-secrets.sh create mode 100644 .github/workflows/docker_hub.yml delete mode 100644 .gitlab-ci.yml diff --git a/.ci/describe-system.sh b/.ci/describe-system.sh deleted file mode 100755 index 6bd3b0efd4a..00000000000 --- a/.ci/describe-system.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh - -# **************************************************************************** -# Copyright (C) 2018 Julian Rüth -# -# 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/ -# **************************************************************************** - -set +e -x - -docker info -docker run docker sh -c " - set -x - uname -a - df -h - cat /proc/cpuinfo - cat /proc/meminfo - cat /proc/sys/vm/overcommit_memory - cat /proc/sys/vm/overcommit_ratio" diff --git a/.ci/protect-secrets.sh b/.ci/protect-secrets.sh deleted file mode 100755 index 527604106ca..00000000000 --- a/.ci/protect-secrets.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh - -# This script protects all environment variables that start with "SECRET_". -# It puts them in a temporary file. The name of the variable contains the path -# of that file. This filename can then safely be used in `cat` even if `set -# -x` has been turned on. Also you can run "export" to understand the -# environment without danger. -# Be careful, however, not to use this like the following: -# docker login $DOCKER_USER $(cat $SECRET_DOCKER_PASS) -# as this would expose the password if `set -x` has been turned on. - -# **************************************************************************** -# Copyright (C) 2018 Julian Rüth -# -# 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/ -# **************************************************************************** - -set -eo pipefail -set +x - -function encrypt { - RET=`mktemp` - eval " echo \$$1" > "$RET" - echo $RET -} - -for name in `awk 'END { for (name in ENVIRON) { print name; } }' < /dev/null`; do -case "$name" in - SECRET_*) - export $name="$(encrypt $name)" - echo "Protected $name" - ;; -esac -done - -unset encrypt diff --git a/.github/workflows/docker_hub.yml b/.github/workflows/docker_hub.yml new file mode 100644 index 00000000000..694cd51762f --- /dev/null +++ b/.github/workflows/docker_hub.yml @@ -0,0 +1,91 @@ +name: Reusable workflow for Docker Hub images + +on: + workflow_call: + inputs: + dockerhub_repository: + default: sagemath-dev + type: string + dockerfile_target: + default: make-build + type: string + +jobs: + build-and-push: + name: Build Docker image and push to DockerHub + runs-on: ubuntu-latest + steps: + - name: Maximize build disk space + uses: easimon/maximize-build-space@v8 + with: + # need space in /var for Docker images + root-reserve-mb: 40000 + remove-dotnet: true + remove-android: true + remove-haskell: true + remove-codeql: true + remove-docker-images: true + + - name: Checkout + uses: actions/checkout@v4 + + - name: Set tag + # docker/metadata-action@v4 is not used since we need to distinguish + # between latest and develop tags + id: set_tag + run: | + git fetch --depth=1 origin +refs/tags/*:refs/tags/* + TAG_NAME=$(git tag --sort=creatordate | tail -1) + REPO=${{ inputs.dockerhub_repository }} + # see if the tag has already been pushed + # if yes then skip following steps + URL="https://registry.hub.docker.com/v2/repositories/sagemath/$REPO/tags?page_size=32" + LATEST_TAGS=$(curl -L -s $URL | jq '."results"[]["name"]') + JOB_DONE=false + for i in $LATEST_TAGS; do if [[ $i == \"$TAG_NAME\" ]]; then JOB_DONE=true; break; fi done + echo "JOB_DONE=$JOB_DONE" >> $GITHUB_ENV + + if [[ $JOB_DONE == 'false' ]] + then + TAG="sagemath/$REPO:$TAG_NAME" + TAG_LIST="$TAG, sagemath/$REPO:develop" + BASE="sagemath/sagemath-dev:$TAG_NAME" + echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV + echo "TAG=$TAG" >> $GITHUB_ENV + echo "TAG_LIST=$TAG_LIST" >> $GITHUB_ENV + echo "BASE=$BASE" >> $GITHUB_ENV + fi + df -h + + - name: Update Tag List + id: upd_tag_list + run: | + REPO=${{ inputs.dockerhub_repository }} + TAG_LIST="${{ env.TAG_LIST }}, sagemath/$REPO:latest" + echo "TAG_LIST=$TAG_LIST" >> $GITHUB_ENV + if: "env.JOB_DONE == 'false' && !contains(env.TAG_NAME, 'beta') && !contains(env.TAG_NAME, 'rc')" + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + if: env.JOB_DONE == 'false' + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + if: env.JOB_DONE == 'false' + + - name: Build and push make-build + uses: docker/build-push-action@v5 + with: + context: . + file: docker/Dockerfile + target: ${{ inputs.dockerfile_target }} + build-args: | + MAKE_BUILD=${{ env.BASE }} + push: true + tags: ${{ env.TAG_LIST }} + cache-from: type=gha + cache-to: type=gha,mode=max + if: env.JOB_DONE == 'false' diff --git a/.github/workflows/push_to_docker_hub.yml b/.github/workflows/push_to_docker_hub.yml index 77a9f819d70..0ae58b7b13b 100644 --- a/.github/workflows/push_to_docker_hub.yml +++ b/.github/workflows/push_to_docker_hub.yml @@ -7,106 +7,26 @@ on: - 'develop' push: tags: - # Just create image on pushing a tag + # Create images on pushing a tag - '*' + schedule: + # Recover failed runs each Tuesday and Thursday at one o'clock + - cron: '0 1 * * 2,4' jobs: sagemath-dev: - name: Build Docker image on target make-build and push to DockerHub sagemath-dev - # target make-build replaces former sagemath-dev, see https://github.com/sagemath/sage/pull/36047 - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set tag - # docker/metadata-action@v4 is not used since we need to distinguish - # between latest and develop tags - id: set_tag - run: | - git fetch --depth=1 origin +refs/tags/*:refs/tags/* - TAG_NAME=$(git tag --sort=creatordate | tail -1) - TAG="sagemath/sagemath-dev:$TAG_NAME" - TAG_LIST="$TAG, sagemath/sagemath-dev:develop" - echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV - echo "TAG=$TAG" >> $GITHUB_ENV - echo "TAG_LIST=$TAG_LIST" >> $GITHUB_ENV - - - name: Update Tag List - id: upd_tag_list - run: | - TAG_LIST="${{ env.TAG_LIST }}, sagemath/sagemath-dev:latest" - echo "TAG_LIST=$TAG_LIST" >> $GITHUB_ENV - if: "!contains(env.TAG_NAME, 'beta') && !contains(env.TAG_NAME, 'rc')" - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Build and push make-build - uses: docker/build-push-action@v5 - with: - context: . - file: docker/Dockerfile - target: make-build # see the corresponding header-note - push: true - tags: ${{ env.TAG_LIST }} - cache-from: type=gha - cache-to: type=gha,mode=max + uses: ./.github/workflows/docker_hub.yml + with: + # Build from scratch + dockerhub_repository: sagemath-dev + dockerfile_target: make-build + secrets: inherit sagemath: needs: sagemath-dev - name: Build Docker image on target sagemath and push to DockerHub sagemath - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set tag - # docker/metadata-action@v4 is not used since we need to distinguish - # between latest and develop tags - id: set_tag - run: | - git fetch --depth=1 origin +refs/tags/*:refs/tags/* - TAG_NAME=$(git tag --sort=creatordate | tail -1) - TAG="sagemath/sagemath:$TAG_NAME" - TAG_LIST="$TAG, sagemath/sagemath:develop" - BASE="sagemath/sagemath-dev:$TAG_NAME" - echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV - echo "TAG=$TAG" >> $GITHUB_ENV - echo "TAG_LIST=$TAG_LIST" >> $GITHUB_ENV - echo "BASE=$BASE" >> $GITHUB_ENV - - - name: Update Tag List - id: upd_tag_list - run: | - TAG_LIST="${{ env.TAG_LIST }}, sagemath/sagemath:latest" - echo "TAG_LIST=$TAG_LIST" >> $GITHUB_ENV - if: "!contains(env.TAG_NAME, 'beta') && !contains(env.TAG_NAME, 'rc')" - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Build and push sagemath - uses: docker/build-push-action@v5 - with: - context: . - file: docker/Dockerfile - build-args: | - MAKE_BUILD=${{ env.BASE }} - target: sagemath - push: true - tags: ${{ env.TAG_LIST }} - cache-from: type=gha - cache-to: type=gha,mode=max + uses: ./.github/workflows/docker_hub.yml + with: + # Build from sagemath-dev + dockerhub_repository: sagemath + dockerfile_target: sagemath + secrets: inherit diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index e80a04b422b..00000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,195 +0,0 @@ -# This file configures automatic builds of Sage on [GitLab](https://gitlab.com). -# To make the build time not too excessive, we seed the build cache with -# sagemath/sagemath-dev:develop. When basic SPKGs changed, this does not help -# much and the full build might exceed the set time limit in GitLab. You can -# increase that limit in Settings → CI/CD. -# You can also provision your own private more powerful runner in the same -# place -# https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker-executor; -# or set up your favourite cloud service to provide an on-demand autoscale -# runner. More details below. - -# As of early 2018 a run on GitLab CI takes about 45 minutes. We could probably -# save 10 minutes by not building/pushing/testing dev images for branches other -# than master/develop. - -# Note that most of the time during CI is spent with pulling and pushing of -# docker images and copying files locally as part of the docker build. At the -# moment there is no reliable way of passing the docker images to the following -# stages without explicit pushing/pulling or similar: -# https://gitlab.com/gitlab-org/gitlab-runner/issues/1107 - -# The timings mentioned above are typical values. The shared runners provided -# on gitlab.com are sometimes much slower depending on the runner you are -# scheduled on. Sometimes it's slower for no apparent reason, probably just an -# overcommittment of virtual machines on hardware. - -# GitLab provides several flavours of shared runners (as of early 2018): -# * runners tagged as "do" (digitalocean.com) provide about 60GB of HDD, two -# cores, but only 2GB of RAM. The RAM is sometimes not sufficient to build -# the documentation. -# * runners tagged as "gce" (Google Compute Engine) provide about 22GB of HDD, -# a single core, 4GB of RAM. Since we are relying on OverlayFS, the disk -# space is not sufficient to build sage from scratch. -# The shared runners are terminated after three hours. Currently, this is often -# insufficient to build sage from scratch. - -# If you want to provide your own runners, make sure to tag them as follows: -# * "big" (60GB of disk space are available) to make build-from-clean pass. - -image: docker:stable - -stages: - - build - - test - - release - -variables: - DOCKER_TAG: $CI_COMMIT_REF_NAME - # Builds are very I/O intensive; make sure we have a fast file system. - DOCKER_DRIVER: overlay2 - DEFAULT_ARTIFACT_BASE: sagemath/sagemath-dev:develop - -before_script: - # GitLab has no mechanism yet to hide secret variables: https://gitlab.com/gitlab-org/gitlab-ce/issues/13784 - # So we roll our own which protects all variables that start with SECRET_ - - . .ci/protect-secrets.sh - # Collect debug infos about the system we are running on - - .ci/describe-system.sh - # Set DOCKER_TAG according to the current branch/tag - - . .ci/update-env.sh - # Set MAKEFLAGS and SAGE_NUM_THREADS according to the machine we are running on - - . .ci/setup-make-parallelity.sh - -# We use docker-in-docker to build our docker images, i.e., we run a -# docker:dind "service" container and link to it from the container running the -# actual scripts below. -# Our scripts automatically connect to this service (unless you override it by -# setting DOCKER_HOST.) For example, each RUN statement in the Dockerfile -# spawns a docker container inside the docker:dind container to perform the RUN -# command there. -# It can be faster to expose your outer docker daemon by mounting -# /var/run/docker.sock to /var/run/docker.sock and setting DOCKER_HOST in -# Settings -> CI/CD -> Secret variable to unix:///var/run/docker.sock. (The -# speedup is mostly due to sharing layers of intermediate images.) However, -# this is only possible if you provision your own runners. Shared gitlab -# runners, do not bind mount /var/run/docker.sock. Also, docker:dind provides -# better isolation. If you expect many builds to run simultaneously on a host, -# conflicting tags can cause issues with a mounted DOCKER_HOST. -services: -- docker:stable-dind - -# Build Sage and its documentation. -# The build starts from the build artifacts of DEFAULT_ARTIFACT_BASE which is -# usually much faster than building from a clean checkout of Sage. -build-from-latest: - stage: build - artifacts: - when: always - paths: - - gitlab-build-docker.log - - html - expire_in: 1 month - script: - - apk --update add coreutils rsync - # The output of the build can get larger than gitlab.com's limit; only - # print the first 1MB (and the last 80 lines.) GitLab's limit is 4MB, - # however, the list of all branches and tags that shows up in the initial - # checkout takes already 1.5 MB: - # https://gitlab.com/gitlab-org/gitlab-runner/issues/4142 - - .ci/build-docker.sh | tee gitlab-build-docker.log | .ci/head-tail.sh 1048576 - - .ci/push-gitlab.sh sagemath-dev - - .ci/push-gitlab.sh sagemath - - DOCKER_TAG=$CI_COMMIT_SHA .ci/push-gitlab.sh sagemath - except: - - master - - develop - - tags - - web - -# Build Sage and its documentation from a clean checkout of Sage. -# Note that this takes several hours. You probably want to run this on your own -# gitlab-runner and increase the standard GitLab time limit for CI runs. -# Some of the shared runners provided by GitLab for free do not have enough -# disk space for this to work. If a build fails with "no space left on device", -# you could just retry it and hope to be scheduled on a machine with more disk -# space, or provision your own runner. -build-from-clean: - extends: - - build-from-latest - artifacts: - when: always - paths: - - gitlab-build-docker.log - - html - expire_in: 99 years - variables: - ARTIFACT_BASE: "source-clean" - only: - - master - - develop - - tags - # Run build-from-clean for a pipeline that has been explicitly created - # through GitLab's web interface. - - web - except: [] - tags: - # 60 GB of HDD are available - - big - # This build takes several CPU hours. It is very unlikely that there are any - # actual build errors for a tagged release but the (discounted) cloud - # machines this is running on might be preempted during the long build time. - # So let's try three times before we give up. - retry: 2 - -test-dev: - stage: test - dependencies: [] - script: - - . .ci/pull-gitlab.sh sagemath-dev - - sh .ci/test-dev.sh "$DOCKER_IMAGE" - -test-cli: - stage: test - dependencies: [] - script: - - . .ci/pull-gitlab.sh sagemath - - sh .ci/test-cli.sh "$DOCKER_IMAGE" - -test-jupyter: - stage: test - dependencies: [] - script: - - . .ci/pull-gitlab.sh sagemath - - sh .ci/test-jupyter.sh "$DOCKER_IMAGE" docker - -# Pushes the built images to Docker Hub if the Settings -> CI/CD -> Secret -# variables DOCKER_USER and SECRET_DOCKER_PASS have been set up. -push-dockerhub: - stage: release - dependencies: [] - only: - refs: - - branches - - tags - variables: - - $SECRET_DOCKER_PASS - script: - - . .ci/pull-gitlab.sh sagemath - - sh .ci/push-dockerhub.sh sagemath - -# Pushes the built dev images to Docker Hub if the Settings -> CI/CD -> Secret -# variables DOCKER_USER and SECRET_DOCKER_PASS have been set up. -push-dockerhub-dev: - stage: release - dependencies: [] - only: - refs: - - master - - develop - - tags - variables: - - $SECRET_DOCKER_PASS - script: - - . .ci/pull-gitlab.sh sagemath-dev - - sh .ci/push-dockerhub.sh sagemath-dev From 50c9a3886f2ffe5e4d1e7231a3e316369ef5f6b7 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Fri, 10 Nov 2023 09:55:31 +0100 Subject: [PATCH 062/155] start integration with twisted chain complex --- src/sage/topology/simplicial_set.py | 117 ++++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 15 deletions(-) diff --git a/src/sage/topology/simplicial_set.py b/src/sage/topology/simplicial_set.py index f707c9407fa..667a60bb6b9 100644 --- a/src/sage/topology/simplicial_set.py +++ b/src/sage/topology/simplicial_set.py @@ -258,11 +258,13 @@ import copy +from sage.functions.generalized import sign from sage.matrix.special import identity_matrix from sage.misc.cachefunc import cached_method from sage.misc.fast_methods import WithEqualityById from sage.misc.flatten import flatten from sage.misc.lazy_import import lazy_import +from sage.misc.misc_c import prod from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ @@ -296,6 +298,7 @@ class AbstractSimplex_class(SageObject): Users should not call this directly, but instead use :func:`AbstractSimplex`. See that function for more documentation. """ + def __init__(self, dim, degeneracies=(), underlying=None, name=None, latex_name=None): """ @@ -3204,6 +3207,7 @@ class SimplicialSet_finite(SimplicialSet_arbitrary, GenericCellComplex): sage: X Y """ + def __init__(self, data, base_point=None, name=None, check=True, category=None, latex_name=None): r""" @@ -3774,10 +3778,44 @@ def chain_complex(self, dimensions=None, base_ring=ZZ, augmented=False, return ChainComplex(differentials, degree_of_differential=-1, check=check) + def _canonical_twisting_operator(self): + r""" + The canonical twisting operator corresponds to the abelianization of the fundamental + group. It assigns each edge to the corresponding element in the algebra of the + abelianization of the fundamental group, which is a quotient of a Laurent polynomial + ring. - def twisted_chain_complex(self, twisting_operator, dimensions=None, augmented=False, - cochain=False, verbose=False, subcomplex=None, - check=False): + EXAMPLES:: + + sage: X = simplicial_sets.Torus() + sage: d = X._canonical_twisting_operator() + sage: d + {(sigma_1, sigma_1): f2, (sigma_1, s_0 v_0): f3, (s_0 v_0, sigma_1): f2*f3^-1} + sage: list(d.values())[0].parent() + Multivariate Laurent Polynomial Ring in f2, f3 over Rational Field + sage: Y = simplicial_sets.RealProjectiveSpace(2) + sage: Y._canonical_twisting_operator() + {f: F1bar} + sage: d2 = Y._canonical_twisting_operator() + sage: d2 + {f: F1bar} + sage: list(d2.values())[0].parent() + Quotient of Univariate Laurent Polynomial Ring in F1 over Rational Field by the ideal (-1 + F1^2) + + """ + from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing + G, d = self._universal_cover_dict() + phi = G.abelianization_map() + abelG, R, I, images = G.abelianization_to_algebra(ZZ) + QRP = R.quotient_ring(I) + res = dict() + for s, el in d.items(): + res[s] = QRP(prod(images[abs(a)-1]**sign(a) for a in phi(el).Tietze())) + return res + + def twisted_chain_complex(self, twisting_operator=None, dimensions=None, augmented=False, + cochain=False, verbose=False, subcomplex=None, + check=False): r""" Return the normalized chain complex twisted by some operator. @@ -3787,7 +3825,9 @@ def twisted_chain_complex(self, twisting_operator, dimensions=None, augmented=Fa INPUT: - ``twisting_operator`` -- a dictionary, associating the twist of each - simplex. + simplex. If it is not given, the canonical one (associated to the + laurent polynomial ring abelianization of the fundamental group, ignoring + torsion) is used. - ``dimensions`` -- if ``None``, compute the chain complex in all dimensions. If a list or tuple of integers, compute the @@ -3830,18 +3870,51 @@ def twisted_chain_complex(self, twisting_operator, dimensions=None, augmented=Fa sage: ChC.differential(2) [0] + :: + + sage: X = simplicial_sets.Torus() + sage: C = X.twisted_chain_complex() + sage: C.differential(1) + [f2*f3^-1 - 1 f3 - 1 f2 - 1] + sage: C.differential(2) + [ 1 f3] + [f2*f3^-1 1] + [ -1 -1] + sage: C.differential(3) + [] + + :: + + sage: Y = simplicial_sets.RealProjectiveSpace(2) + sage: C = Y.twisted_chain_complex() + sage: C.differential(1) + [-1 + F1] + sage: C.differential(2) + [1 + F1] + sage: C.differential(3) + [] + """ from sage.homology.chain_complex import ChainComplex from sage.structure.element import get_coercion_model cm = get_coercion_model() + if twisting_operator: + twop = twisting_operator + else: + di = self._canonical_twisting_operator() + if hasattr(list(di.values())[0], "lift"): + twop = {a: b.lift() for a, b in di.items()} + else: + twop = di + def twist(s): - if s in twisting_operator: - return twisting_operator[s] + if s in twop: + return twop[s] if s.dimension() > 1: return twist(self.face_data()[s][-1]) return 1 - base_ring = cm.common_parent(*twisting_operator.values()) + base_ring = cm.common_parent(*twop.values()) if dimensions is None: if not self.cells(): # Empty @@ -3913,7 +3986,7 @@ def twist(s): sign = 1 twists = len(face_data[sigma]) * [1] twists[0] = twist(sigma) - for (ch,tau) in zip(twists,face_data[sigma]): + for (ch, tau) in zip(twists, face_data[sigma]): if tau.is_nondegenerate(): row = faces[tau] if (row, col) in matrix_data: @@ -3952,28 +4025,40 @@ def twisted_homology(self, n): - ``n`` - a positive integer. """ + CC = self.twisted_chain_complex(ZZ) + M1 = CC.differential(n).T + M2 = CC.differential(n + 1).T + RL = CC.base_ring() + RP = PolynomialRing(ZZ, 'x', 2 * RL.ngens()) + def convert_to_polynomial(p): + + D = self._canonical_twisting_operator() + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing G, d = self._universal_cover_dict() abelG = G.abelianization_map().codomain() abelinv = abelG.abelian_invariants() RP = PolynomialRing(ZZ, 'x', 2 * len(abelinv)) - I = RP.ideal([RP.gen(i)**j-1 for i,j in enumerate(abelinv)]) + I = RP.ideal([RP.gen(i)**j-1 for i, j in enumerate(abelinv)]) J = RP.ideal([RP.gen(2*a)*RP.gen(2*a+1) - 1 for a in range(RP.ngens()//2)]) GB = (I+J).groebner_basis() GBI = RP.ideal(GB) + def reduce_laurent(a): return a._singular_().reduce(GBI)._sage_() + def group_to_polynomial(el, RP): res = RP.one() for a in el.Tietze(): if a > 0: res *= RP.gen(2*a-2) else: - res*= RP.gen(-2*a-1) + res *= RP.gen(-2*a-1) return res - nd = {a:group_to_polynomial(G.abelianization_map()(b), RP) for a,b in d.items()} + nd = {a: group_to_polynomial(G.abelianization_map()(b), RP) for a, b in d.items()} CC = self.twisted_chain_complex(nd) + def mkernel(M): if M.nrows() == 0 or M.ncols() == 0: return M @@ -3982,10 +4067,11 @@ def mkernel(M): for g in (I+J).gens(): res = res.stack(g*identity_matrix(n)) syz = res.T._singular_().syz()._sage_() - trimmed = syz.T.submatrix(0,0,syz.ncols(),M.nrows()) + trimmed = syz.T.submatrix(0, 0, syz.ncols(), M.nrows()) trimmed = trimmed.apply_map(reduce_laurent) - to_delete = [i for (i,r) in enumerate(trimmed.rows()) if not r] + to_delete = [i for (i, r) in enumerate(trimmed.rows()) if not r] return trimmed.delete_rows(to_delete) + def lift_to_submodule(S, M): if S.nrows() == 0 or S.ncols() == 0: return S @@ -3993,7 +4079,8 @@ def lift_to_submodule(S, M): for g in GB: res = res.stack(g*identity_matrix(M.ncols())) singres = res.T._singular_().lift(S.T._singular_())._sage_() - return singres.submatrix(0,0,M.nrows(),S.nrows()) + return singres.submatrix(0, 0, M.nrows(), S.nrows()) + def mgb(M): if M.nrows() == 0 or M.ncols() == 0: return M @@ -4020,7 +4107,7 @@ def mgb(M): res = mgb(DK.T) resmat = mgb(res.apply_map(reduce_laurent)) L = LaurentPolynomialRing(ZZ, 'x', len(abelinv)) - h = RP.hom(flatten([[g, g**-1] for g in L.gens()]),codomain = L) + h = RP.hom(flatten([[g, g**-1] for g in L.gens()]), codomain=L) laumat = resmat.apply_map(h) laumat = laumat.change_ring(L) if laumat.ncols() > 0: From 13098aa85e4234a5e33df6bd1c80c0986cad72da Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Fri, 10 Nov 2023 13:00:19 +0100 Subject: [PATCH 063/155] First fully working implementation of twisted_homology --- .../rings/polynomial/laurent_polynomial.pyx | 23 ++++ .../polynomial/laurent_polynomial_mpair.pyx | 28 +++++ .../laurent_polynomial_ring_base.py | 8 ++ src/sage/topology/simplicial_set.py | 110 ++++++++++++------ 4 files changed, 136 insertions(+), 33 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index cf92b0e43d1..b61fb1024c3 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -1988,3 +1988,26 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): 0 """ return self.__u[-self.__n] + + def _as_extended_polynomial(self): + """ + This Laurent polynomial seen as a polynomial in twice as many variables, + where half of the variables are the inverses of the other half. + + EXAMPLES:: + + sage: L. = LaurentPolynomialRing(QQ) + sage: f = t-t^-2 + sage: f._as_extended_polynomial() + -tinv^2 + t + sage: _.parent() + Multivariate Polynomial Ring in t, tinv over Rational Field + + """ + dres = {} + for (e, c) in self.dict().items(): + if e > 0 : + dres[(e,0)] = c + else: + dres[(0,-e)] = c + return self.parent()._extended_ring(dres) diff --git a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx index e14f1b36ce5..b428560c1ae 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx @@ -555,6 +555,34 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): for exp, coeff in self._poly.iterator_exp_coeff(): yield (coeff, P.element_class(P, one, exp.eadd(self._mon))) + def _as_extended_polynomial(self): + """ + This Laurent polynomial seen as a polynomial in twice as many variables, + where half of the variables are the inverses of the other half. + + EXAMPLES:: + + sage: L. = LaurentPolynomialRing(QQ) + sage: f = t1-t2^-2 + sage: f + t1 - t2^-2 + sage: f._as_extended_polynomial() + -t2inv^2 + t1 + sage: _.parent() + Multivariate Polynomial Ring in t1, t1inv, t2, t2inv over Rational Field + + """ + dres = {} + for (e, c) in self.dict().items(): + exps = [] + for t in e: + if t > 0 : + exps += [t, 0] + else: + exps += [0, -t] + dres [tuple(exps)] = c + return self.parent()._extended_ring(dres) + def iterator_exp_coeff(self): """ Iterate over ``self`` as pairs of (ETuple, coefficient). diff --git a/src/sage/rings/polynomial/laurent_polynomial_ring_base.py b/src/sage/rings/polynomial/laurent_polynomial_ring_base.py index 0c9022c492c..302476381a5 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_ring_base.py +++ b/src/sage/rings/polynomial/laurent_polynomial_ring_base.py @@ -25,6 +25,7 @@ from sage.rings.infinity import infinity +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.ring import CommutativeRing from sage.structure.parent import Parent @@ -61,6 +62,13 @@ def __init__(self, R): self._one_element = self.element_class(self, R.one()) CommutativeRing.__init__(self, R.base_ring(), names=names, category=R.category()) + ernames = [] + for n in names: + ernames.append(n) + ernames.append(n + "inv") + ER = PolynomialRing(R.base_ring(), ernames) + self._extended_ring = ER + self._extended_ring_ideal = ER.ideal([ER.gen(2*i)*ER.gen(2*i+1)-1 for i in range(self._n)]) def ngens(self): """ diff --git a/src/sage/topology/simplicial_set.py b/src/sage/topology/simplicial_set.py index 667a60bb6b9..0dc1a64fcb0 100644 --- a/src/sage/topology/simplicial_set.py +++ b/src/sage/topology/simplicial_set.py @@ -4012,37 +4012,85 @@ def twist(s): return ChainComplex(differentials, degree_of_differential=-1, check=check) - def twisted_homology(self, n): + def twisted_homology(self, n, reduced=False): r""" The `n`-th twisted homology module of the simplicial set with respect to the abelianization of the fundamental_group. - It is a module over a Laurent - polynomial ring, that, if the fundamental group is abelian, coincides - with the homology of the universal cover. + It is a module over a polynomial ring, including relations to make some + variables the multiplicative inverses of others. INPUT: - ``n`` - a positive integer. + + - ``reduced`` - (default: False) if set to True, the presentation matrix + will be reduced. + + EXAMPLES:: + + sage: X = simplicial_sets.Sphere(1).wedge(simplicial_sets.Sphere(2)) + sage: X.twisted_homology(1) + Quotient module by Submodule of Ambient free module of rank 1 over the integral domain Multivariate Polynomial Ring in f1, f1inv over Integer Ring + Generated by the rows of the matrix: + [f1*f1inv - 1] + sage: X.twisted_homology(2) + Quotient module by Submodule of Ambient free module of rank 1 over the integral domain Multivariate Polynomial Ring in f1, f1inv over Integer Ring + Generated by the rows of the matrix: + [] + + :: + + sage: Y = simplicial_sets.Torus() + sage: Y.twisted_homology(1) + Quotient module by Submodule of Ambient free module of rank 5 over the integral domain Multivariate Polynomial Ring in f2, f2inv, f3, f3inv over Integer Ring + Generated by the rows of the matrix: + [ 1 0 0 0 0] + [ 0 1 0 0 0] + [ 0 0 1 0 0] + [ 0 0 0 1 0] + [ 0 0 0 0 1] + [f2*f2inv - 1 0 0 0 0] + [ 0 f2*f2inv - 1 0 0 0] + [ 0 0 f2*f2inv - 1 0 0] + [ 0 0 0 f2*f2inv - 1 0] + [ 0 0 0 0 f2*f2inv - 1] + [f3*f3inv - 1 0 0 0 0] + [ 0 f3*f3inv - 1 0 0 0] + [ 0 0 f3*f3inv - 1 0 0] + [ 0 0 0 f3*f3inv - 1 0] + [ 0 0 0 0 f3*f3inv - 1] + sage: Y.twisted_homology(2) + Quotient module by Submodule of Ambient free module of rank 0 over the integral domain Multivariate Polynomial Ring in f2, f2inv, f3, f3inv over Integer Ring + Generated by the rows of the matrix: + [] + sage: Y.twisted_homology(1, reduced=True) + Quotient module by Submodule of Ambient free module of rank 5 over the integral domain Multivariate Polynomial Ring in f2, f2inv, f3, f3inv over Integer Ring + Generated by the rows of the matrix: + [1 0 0 0 0] + [0 1 0 0 0] + [0 0 1 0 0] + [0 0 0 1 0] + [0 0 0 0 1] + """ - CC = self.twisted_chain_complex(ZZ) + G, d = self._universal_cover_dict() + phi = G.abelianization_map() + abelG, R, I, images = G.abelianization_to_algebra(ZZ) + CC = self.twisted_chain_complex() M1 = CC.differential(n).T M2 = CC.differential(n + 1).T - RL = CC.base_ring() - RP = PolynomialRing(ZZ, 'x', 2 * RL.ngens()) def convert_to_polynomial(p): - - D = self._canonical_twisting_operator() - - from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing - from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing - G, d = self._universal_cover_dict() - abelG = G.abelianization_map().codomain() - abelinv = abelG.abelian_invariants() - RP = PolynomialRing(ZZ, 'x', 2 * len(abelinv)) - I = RP.ideal([RP.gen(i)**j-1 for i, j in enumerate(abelinv)]) - J = RP.ideal([RP.gen(2*a)*RP.gen(2*a+1) - 1 for a in range(RP.ngens()//2)]) - GB = (I+J).groebner_basis() + if hasattr(p, "lift"): + return p.lift()._as_extended_polynomial() + else: + return p._as_extended_polynomial() + M1 = M1.apply_map(convert_to_polynomial) + M2 = M2.apply_map(convert_to_polynomial) + RP = R._extended_ring + IP = RP.ideal([convert_to_polynomial(g) for g in I]) + JP = R._extended_ring_ideal + GB = (IP+JP).groebner_basis() GBI = RP.ideal(GB) def reduce_laurent(a): @@ -4056,15 +4104,13 @@ def group_to_polynomial(el, RP): else: res *= RP.gen(-2*a-1) return res - nd = {a: group_to_polynomial(G.abelianization_map()(b), RP) for a, b in d.items()} - CC = self.twisted_chain_complex(nd) def mkernel(M): if M.nrows() == 0 or M.ncols() == 0: return M res = M n = res.ncols() - for g in (I+J).gens(): + for g in (IP+JP).gens(): res = res.stack(g*identity_matrix(n)) syz = res.T._singular_().syz()._sage_() trimmed = syz.T.submatrix(0, 0, syz.ncols(), M.nrows()) @@ -4091,8 +4137,6 @@ def mgb(M): to_delete = [i for i, r in enumerate(sres.apply_map(reduce_laurent)) if not r] return sres.delete_rows(to_delete) M2 = border_matrix(n+1) - M1 = CC.differential(n).T - M2 = CC.differential(n + 1).T if M1.nrows() == 0: return (RP**0).quotient_module([]) K = mkernel(M1) @@ -4106,15 +4150,15 @@ def mgb(M): else: res = mgb(DK.T) resmat = mgb(res.apply_map(reduce_laurent)) - L = LaurentPolynomialRing(ZZ, 'x', len(abelinv)) - h = RP.hom(flatten([[g, g**-1] for g in L.gens()]), codomain=L) - laumat = resmat.apply_map(h) - laumat = laumat.change_ring(L) - if laumat.ncols() > 0: - for g in I.gens(): - laumat = laumat.stack(h(g)*identity_matrix(L, laumat.ncols())) - AM = L ** K.nrows() - SM = AM.submodule(laumat) + AM = RP ** K.nrows() + if resmat.ncols() == 0: + SM = AM.submodule([]) + return AM.quotient_module(SM) + for g in (IP+JP).gens(): + resmat = resmat.stack(g * identity_matrix(resmat.ncols())) + if reduced: + resmat = resmat.T._singular_().std()._sage_().T + SM = AM.submodule(resmat) return AM.quotient_module(SM) @cached_method From bae71ff398ea99a500684f80cebe20e245dac7aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 10 Nov 2023 14:58:19 +0100 Subject: [PATCH 064/155] less use of _an_element_impl --- src/sage/combinat/free_module.py | 14 -------------- src/sage/interfaces/gap.py | 9 +++++++++ src/sage/interfaces/lie.py | 4 ++-- src/sage/interfaces/lisp.py | 6 +++--- src/sage/interfaces/r.py | 4 ++-- src/sage/modular/hecke/algebra.py | 6 ++++-- 6 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 3c77ac6ef16..d8092f4bea1 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -777,20 +777,6 @@ def _convert_map_from_(self, S): lambda x: self.sum_of_terms((G(g), K(c)) for c, g in x)) - def _an_element_impl(self): # TODO: REMOVE? - """ - Return an element of ``self``, namely the zero element. - - EXAMPLES:: - - sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) - sage: F._an_element_impl() - 0 - sage: _.parent() is F - True - """ - return self.element_class(self, {}) - def _first_ngens(self, n): """ Used by the preparser for ``F. = ...``. diff --git a/src/sage/interfaces/gap.py b/src/sage/interfaces/gap.py index 3a2ed434091..0a8087a20d5 100644 --- a/src/sage/interfaces/gap.py +++ b/src/sage/interfaces/gap.py @@ -1428,6 +1428,15 @@ def _object_class(self): """ return GapElement + def _an_element_(self): + """ + EXAMPLES:: + + sage: gap._an_element_() + 0 + """ + return self(0) + def _function_element_class(self): """ Returns the GapFunctionElement class. diff --git a/src/sage/interfaces/lie.py b/src/sage/interfaces/lie.py index 84aee7d7259..6c3da736cc0 100644 --- a/src/sage/interfaces/lie.py +++ b/src/sage/interfaces/lie.py @@ -530,11 +530,11 @@ def _tab_completion(self, type=None, verbose=False, use_disk_cache=True): else: return self._tab_completion_list - def _an_element_impl(self): + def _an_element_(self): """ EXAMPLES:: - sage: lie._an_element_impl() # optional - lie + sage: lie._an_element_() # optional - lie 0 """ return self(0) diff --git a/src/sage/interfaces/lisp.py b/src/sage/interfaces/lisp.py index 3d6e620c4d1..58b7ab685f0 100644 --- a/src/sage/interfaces/lisp.py +++ b/src/sage/interfaces/lisp.py @@ -136,14 +136,14 @@ def eval(self, code, strip=True, **kwds): x.append(M.strip()) self.__in_seq = s except TypeError as s: - return 'error evaluating "%s":\n%s' % (code,s) + return 'error evaluating "%s":\n%s' % (code, s) return '\n'.join(x) - def _an_element_impl(self): + def _an_element_(self): """ EXAMPLES:: - sage: lisp._an_element_impl() + sage: lisp._an_element_() 0 """ return self(0) diff --git a/src/sage/interfaces/r.py b/src/sage/interfaces/r.py index bdf50dbfed9..80a6ea27c74 100644 --- a/src/sage/interfaces/r.py +++ b/src/sage/interfaces/r.py @@ -1085,7 +1085,7 @@ def call(self, function_name, *args, **kwds): """ return self.function_call(function_name, args=args, kwds=kwds) - def _an_element_impl(self): + def _an_element_(self): """ Returns an element belonging to the R interpreter. This is used behind the scenes when doing things like comparisons, etc. @@ -1094,7 +1094,7 @@ def _an_element_impl(self): EXAMPLES:: - sage: r._an_element_impl() # optional - rpy2 + sage: r._an_element_() # optional - rpy2 [1] 0 sage: type(_) # optional - rpy2 diff --git a/src/sage/modular/hecke/algebra.py b/src/sage/modular/hecke/algebra.py index 4ccc6d0b1bf..e0f539a507b 100644 --- a/src/sage/modular/hecke/algebra.py +++ b/src/sage/modular/hecke/algebra.py @@ -181,9 +181,11 @@ def __init__(self, M): self.__M = M CommutativeAlgebra.__init__(self, M.base_ring()) - def _an_element_impl(self): + def _an_element_(self): r""" - Return an element of this algebra. Used by the coercion machinery. + Return an element of this algebra. + + Used by the coercion machinery. EXAMPLES:: From 7d5ad2b2a16d26c3decb0378b53bb56788917971 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Fri, 10 Nov 2023 15:21:44 +0100 Subject: [PATCH 065/155] moved to pointed category and fixed issue with universal_cover_dict --- src/sage/categories/simplicial_sets.py | 405 ++++++++++++++++++++++++- src/sage/topology/simplicial_set.py | 387 ----------------------- 2 files changed, 399 insertions(+), 393 deletions(-) diff --git a/src/sage/categories/simplicial_sets.py b/src/sage/categories/simplicial_sets.py index c07871402fd..72dd3b6220c 100644 --- a/src/sage/categories/simplicial_sets.py +++ b/src/sage/categories/simplicial_sets.py @@ -8,13 +8,22 @@ # https://www.gnu.org/licenses/ # ***************************************************************************** +from sage.functions.generalized import sign +from sage.matrix.special import identity_matrix from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import from sage.categories.category_singleton import Category_singleton from sage.categories.category_with_axiom import CategoryWithAxiom from sage.categories.sets_cat import Sets from sage.categories.homsets import HomsetsCategory +from sage.matrix.constructor import matrix +from sage.misc.flatten import flatten +from sage.misc.misc_c import prod from sage.rings.infinity import Infinity from sage.rings.integer import Integer +from sage.rings.integer_ring import ZZ + +lazy_import('sage.matrix.constructor', 'matrix') class SimplicialSets(Category_singleton): @@ -360,10 +369,9 @@ def _universal_cover_dict(self): [1, f, f * f] """ from sage.groups.free_group import FreeGroup - skel = self.n_skeleton(2) - graph = skel.graph() - if not skel.is_connected(): - graph = graph.subgraph(skel.base_point()) + graph = self.graph() + if not self.is_connected(): + graph = graph.subgraph(self.base_point()) edges = [e[2] for e in graph.edges(sort=False)] spanning_tree = [e[2] for e in graph.min_spanning_tree()] gens = [e for e in edges if e not in spanning_tree] @@ -371,9 +379,9 @@ def _universal_cover_dict(self): FG = FreeGroup(len(gens), 'e') rels = [] - for f in skel.n_cells(2): + for f in self.n_cells(2): z = dict() - for i, sigma in enumerate(skel.faces(f)): + for i, sigma in enumerate(self.faces(f)): if sigma in spanning_tree: z[i] = FG.one() elif sigma.is_degenerate(): @@ -574,6 +582,391 @@ def universal_cover(self): """ return self.universal_cover_map().domain() + def _canonical_twisting_operator(self): + r""" + The canonical twisting operator corresponds to the abelianization of the fundamental + group. It assigns each edge to the corresponding element in the algebra of the + abelianization of the fundamental group, which is a quotient of a Laurent polynomial + ring. + + EXAMPLES:: + + sage: X = simplicial_sets.Torus() + sage: d = X._canonical_twisting_operator() + sage: d + {(s_0 v_0, sigma_1): f2*f3^-1, (sigma_1, s_0 v_0): f3, (sigma_1, sigma_1): f2} + sage: list(d.values())[0].parent() + Multivariate Laurent Polynomial Ring in f2, f3 over Integer Ring + sage: Y = simplicial_sets.RealProjectiveSpace(2) + sage: Y._canonical_twisting_operator() + {f: F1bar} + sage: d2 = Y._canonical_twisting_operator() + sage: d2 + {f: F1bar} + sage: list(d2.values())[0].parent() + Quotient of Univariate Laurent Polynomial Ring in F1 over Integer Ring by the ideal (-1 + F1^2) + + """ + from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing + G, d = self._universal_cover_dict() + phi = G.abelianization_map() + abelG, R, I, images = G.abelianization_to_algebra(ZZ) + QRP = R.quotient_ring(I) + res = dict() + for s, el in d.items(): + res[s] = QRP(prod(images[abs(a)-1]**sign(a) for a in phi(el).Tietze())) + return res + + def twisted_chain_complex(self, twisting_operator=None, dimensions=None, augmented=False, + cochain=False, verbose=False, subcomplex=None, + check=False): + r""" + Return the normalized chain complex twisted by some operator. + + A twisting operator is a map from the set of simplices to some algebra. + The differentials are then twisted by this operator. + + INPUT: + + - ``twisting_operator`` -- a dictionary, associating the twist of each + simplex. If it is not given, the canonical one (associated to the + laurent polynomial ring abelianization of the fundamental group, ignoring + torsion) is used. + + - ``dimensions`` -- if ``None``, compute the chain complex in all + dimensions. If a list or tuple of integers, compute the + chain complex in those dimensions, setting the chain groups + in all other dimensions to zero. + + - ``augmented`` (optional, default ``False``) -- if ``True``, + return the augmented chain complex (that is, include a class + in dimension `-1` corresponding to the empty cell). + + - ``cochain`` (optional, default ``False``) -- if ``True``, + return the cochain complex (that is, the dual of the chain + complex). + + - ``verbose`` (optional, default ``False``) -- ignored. + + - ``subcomplex`` (optional, default ``None``) -- if present, + compute the chain complex relative to this subcomplex. + + - ``check`` (optional, default ``False``) -- If ``True``, make + sure that the chain complex is actually a chain complex: + the differentials are composable and their product is zero. + + The normalized chain complex of a simplicial set is isomorphic + to the chain complex obtained by modding out by degenerate + simplices, and the latter is what is actually constructed + here. + + EXAMPLES:: + + sage: W = simplicial_sets.Sphere(1).wedge(simplicial_sets.Sphere(2)) + sage: W.nondegenerate_simplices() + [*, sigma_1, sigma_2] + sage: s1 = W.nondegenerate_simplices()[1] + sage: L. = LaurentPolynomialRing(QQ) + sage: tw = {s1:t} + sage: ChC = W.twisted_chain_complex(tw) + sage: ChC.differential(1) + [-1 + t] + sage: ChC.differential(2) + [0] + + :: + + sage: X = simplicial_sets.Torus() + sage: C = X.twisted_chain_complex() + sage: C.differential(1) + [f2*f3^-1 - 1 f3 - 1 f2 - 1] + sage: C.differential(2) + [ 1 f3] + [f2*f3^-1 1] + [ -1 -1] + sage: C.differential(3) + [] + + :: + + sage: Y = simplicial_sets.RealProjectiveSpace(2) + sage: C = Y.twisted_chain_complex() + sage: C.differential(1) + [-1 + F1] + sage: C.differential(2) + [1 + F1] + sage: C.differential(3) + [] + + """ + from sage.homology.chain_complex import ChainComplex + from sage.structure.element import get_coercion_model + cm = get_coercion_model() + + if twisting_operator: + twop = twisting_operator + else: + di = self._canonical_twisting_operator() + if hasattr(list(di.values())[0], "lift"): + twop = {a: b.lift() for a, b in di.items()} + else: + twop = di + + def twist(s): + if s in twop: + return twop[s] + if s.dimension() > 1: + return twist(self.face_data()[s][-1]) + return 1 + base_ring = cm.common_parent(*twop.values()) + + if dimensions is None: + if not self.cells(): # Empty + if cochain: + return ChainComplex({-1: matrix(base_ring, 0, 0)}, + degree_of_differential=1) + return ChainComplex({0: matrix(base_ring, 0, 0)}, + degree_of_differential=-1) + dimensions = list(range(self.dimension() + 1)) + else: + if not isinstance(dimensions, (list, tuple, range)): + dimensions = list(range(dimensions - 1, dimensions + 2)) + else: + dimensions = [n for n in dimensions if n >= 0] + if not dimensions: + # Return the empty chain complex. + if cochain: + return ChainComplex(base_ring=base_ring, degree=1) + else: + return ChainComplex(base_ring=base_ring, degree=-1) + + differentials = {} + # Convert the tuple self._data to a dictionary indexed by the + # non-degenerate simplices. + if subcomplex: + X = self.quotient(subcomplex) + face_data = X.face_data() + nondegens = X.nondegenerate_simplices() + else: + face_data = self.face_data() + nondegens = self.nondegenerate_simplices() + # simplices: dictionary indexed by dimension, values the list + # of non-degenerate simplices in that dimension. + simplices = {} + for sigma in nondegens: + if sigma.dimension() in simplices: + simplices[sigma.dimension()].append(sigma) + else: + simplices[sigma.dimension()] = [sigma] + first = dimensions.pop(0) + if first in simplices: + rank = len(simplices[first]) + current = sorted(simplices[first]) + else: + rank = 0 + current = [] + if augmented and first == 0: + differentials[first-1] = matrix(base_ring, 0, 1) + differentials[first] = matrix(base_ring, 1, rank, + [1] * rank) + else: + differentials[first] = matrix(base_ring, 0, rank) + + for d in dimensions: + old_rank = rank + faces = {_[1]: _[0] for _ in enumerate(current)} + if d in simplices: + current = sorted(simplices[d]) + rank = len(current) + # old_rank: number of simplices in dimension d-1. + # faces: list of simplices in dimension d-1. + # rank: number of simplices in dimension d. + # current: list of simplices in dimension d. + if not faces: + differentials[d] = matrix(base_ring, old_rank, rank) + else: + matrix_data = {} + for col, sigma in enumerate(current): + sign = 1 + twists = len(face_data[sigma]) * [1] + twists[0] = twist(sigma) + for (ch, tau) in zip(twists, face_data[sigma]): + if tau.is_nondegenerate(): + row = faces[tau] + if (row, col) in matrix_data: + matrix_data[(row, col)] += sign*ch + else: + matrix_data[(row, col)] = sign*ch + sign *= -1 + + differentials[d] = matrix(base_ring, old_rank, + rank, matrix_data) + + else: + rank = 0 + current = [] + differentials[d] = matrix(base_ring, old_rank, rank) + + if cochain: + new_diffs = {} + for d in differentials: + new_diffs[d-1] = differentials[d].transpose() + return ChainComplex(new_diffs, degree_of_differential=1, + check=check) + return ChainComplex(differentials, degree_of_differential=-1, + check=check) + + def twisted_homology(self, n, reduced=False): + r""" + The `n`-th twisted homology module of the simplicial set with respect to + the abelianization of the fundamental_group. + + It is a module over a polynomial ring, including relations to make some + variables the multiplicative inverses of others. + + INPUT: + + - ``n`` - a positive integer. + + - ``reduced`` - (default: False) if set to True, the presentation matrix + will be reduced. + + EXAMPLES:: + + sage: X = simplicial_sets.Sphere(1).wedge(simplicial_sets.Sphere(2)) + sage: X.twisted_homology(1) + Quotient module by Submodule of Ambient free module of rank 0 over the integral domain Multivariate Polynomial Ring in f1, f1inv over Integer Ring + Generated by the rows of the matrix: + [] + sage: X.twisted_homology(2) + Quotient module by Submodule of Ambient free module of rank 1 over the integral domain Multivariate Polynomial Ring in f1, f1inv over Integer Ring + Generated by the rows of the matrix: + [f1*f1inv - 1] + + :: + + sage: Y = simplicial_sets.Torus() + sage: Y.twisted_homology(1) + Quotient module by Submodule of Ambient free module of rank 5 over the integral domain Multivariate Polynomial Ring in f2, f2inv, f3, f3inv over Integer Ring + Generated by the rows of the matrix: + [ 1 0 0 0 0] + [ 0 1 0 0 0] + [ 0 0 1 0 0] + [ 0 0 0 1 0] + [ 0 0 0 0 1] + [f2*f2inv - 1 0 0 0 0] + [ 0 f2*f2inv - 1 0 0 0] + [ 0 0 f2*f2inv - 1 0 0] + [ 0 0 0 f2*f2inv - 1 0] + [ 0 0 0 0 f2*f2inv - 1] + [f3*f3inv - 1 0 0 0 0] + [ 0 f3*f3inv - 1 0 0 0] + [ 0 0 f3*f3inv - 1 0 0] + [ 0 0 0 f3*f3inv - 1 0] + [ 0 0 0 0 f3*f3inv - 1] + sage: Y.twisted_homology(2) + Quotient module by Submodule of Ambient free module of rank 0 over the integral domain Multivariate Polynomial Ring in f2, f2inv, f3, f3inv over Integer Ring + Generated by the rows of the matrix: + [] + sage: Y.twisted_homology(1, reduced=True) + Quotient module by Submodule of Ambient free module of rank 5 over the integral domain Multivariate Polynomial Ring in f2, f2inv, f3, f3inv over Integer Ring + Generated by the rows of the matrix: + [1 0 0 0 0] + [0 1 0 0 0] + [0 0 1 0 0] + [0 0 0 1 0] + [0 0 0 0 1] + + """ + G, d = self._universal_cover_dict() + phi = G.abelianization_map() + abelG, R, I, images = G.abelianization_to_algebra(ZZ) + CC = self.twisted_chain_complex() + M1 = CC.differential(n).T + M2 = CC.differential(n + 1).T + def convert_to_polynomial(p): + if hasattr(p, "lift"): + return p.lift()._as_extended_polynomial() + else: + return p._as_extended_polynomial() + M1 = M1.apply_map(convert_to_polynomial) + M2 = M2.apply_map(convert_to_polynomial) + RP = R._extended_ring + IP = RP.ideal([convert_to_polynomial(g) for g in I]) + JP = R._extended_ring_ideal + GB = (IP+JP).groebner_basis() + GBI = RP.ideal(GB) + + def reduce_laurent(a): + return a._singular_().reduce(GBI)._sage_() + + def group_to_polynomial(el, RP): + res = RP.one() + for a in el.Tietze(): + if a > 0: + res *= RP.gen(2*a-2) + else: + res *= RP.gen(-2*a-1) + return res + + def mkernel(M): + if M.nrows() == 0: + return matrix(M.base_ring(), 0, 0) + if M.ncols() == 0: + return M.T + res = M + n = res.ncols() + for g in (IP+JP).gens(): + res = res.stack(g*identity_matrix(n)) + syz = res.T._singular_().syz()._sage_() + trimmed = syz.T.submatrix(0, 0, syz.ncols(), M.nrows()) + trimmed = trimmed.apply_map(reduce_laurent) + to_delete = [i for (i, r) in enumerate(trimmed.rows()) if not r] + return trimmed.delete_rows(to_delete) + + def lift_to_submodule(S, M): + if S.nrows() == 0 or S.ncols() == 0: + return S + res = M + for g in GB: + res = res.stack(g*identity_matrix(M.ncols())) + singres = res.T._singular_().lift(S.T._singular_())._sage_() + return singres.submatrix(0, 0, M.nrows(), S.nrows()) + + def mgb(M): + if M.nrows() == 0 or M.ncols() == 0: + return M + res = M + for g in GB: + res = res.stack(g*identity_matrix(M.ncols())) + sres = res.T._singular_().std()._sage_().T + to_delete = [i for i, r in enumerate(sres.apply_map(reduce_laurent)) if not r] + return sres.delete_rows(to_delete) + M2 = border_matrix(n+1) + if M1.nrows() == 0: + return (RP**0).quotient_module([]) + K = mkernel(M1) + DK = mkernel(K) + if M2.nrows() > 0: + S = lift_to_submodule(M2, K) + if S.nrows() > 0 and S.ncols() > 0: + res = mgb(DK.stack(S.T)) + else: + res = DK + else: + res = mgb(DK) + resmat = mgb(res.apply_map(reduce_laurent)) + AM = RP ** K.nrows() + if resmat.ncols() == 0: + SM = AM.submodule([]) + return AM.quotient_module(SM) + for g in (IP+JP).gens(): + resmat = resmat.stack(g * identity_matrix(resmat.ncols())) + if reduced: + resmat = resmat.T._singular_().std()._sage_().T + SM = AM.submodule(resmat) + return AM.quotient_module(SM) + def is_simply_connected(self): """ Return ``True`` if this pointed simplicial set is simply connected. diff --git a/src/sage/topology/simplicial_set.py b/src/sage/topology/simplicial_set.py index 0dc1a64fcb0..e33465f1153 100644 --- a/src/sage/topology/simplicial_set.py +++ b/src/sage/topology/simplicial_set.py @@ -258,13 +258,9 @@ import copy -from sage.functions.generalized import sign -from sage.matrix.special import identity_matrix from sage.misc.cachefunc import cached_method from sage.misc.fast_methods import WithEqualityById -from sage.misc.flatten import flatten from sage.misc.lazy_import import lazy_import -from sage.misc.misc_c import prod from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ @@ -3778,389 +3774,6 @@ def chain_complex(self, dimensions=None, base_ring=ZZ, augmented=False, return ChainComplex(differentials, degree_of_differential=-1, check=check) - def _canonical_twisting_operator(self): - r""" - The canonical twisting operator corresponds to the abelianization of the fundamental - group. It assigns each edge to the corresponding element in the algebra of the - abelianization of the fundamental group, which is a quotient of a Laurent polynomial - ring. - - EXAMPLES:: - - sage: X = simplicial_sets.Torus() - sage: d = X._canonical_twisting_operator() - sage: d - {(sigma_1, sigma_1): f2, (sigma_1, s_0 v_0): f3, (s_0 v_0, sigma_1): f2*f3^-1} - sage: list(d.values())[0].parent() - Multivariate Laurent Polynomial Ring in f2, f3 over Rational Field - sage: Y = simplicial_sets.RealProjectiveSpace(2) - sage: Y._canonical_twisting_operator() - {f: F1bar} - sage: d2 = Y._canonical_twisting_operator() - sage: d2 - {f: F1bar} - sage: list(d2.values())[0].parent() - Quotient of Univariate Laurent Polynomial Ring in F1 over Rational Field by the ideal (-1 + F1^2) - - """ - from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing - G, d = self._universal_cover_dict() - phi = G.abelianization_map() - abelG, R, I, images = G.abelianization_to_algebra(ZZ) - QRP = R.quotient_ring(I) - res = dict() - for s, el in d.items(): - res[s] = QRP(prod(images[abs(a)-1]**sign(a) for a in phi(el).Tietze())) - return res - - def twisted_chain_complex(self, twisting_operator=None, dimensions=None, augmented=False, - cochain=False, verbose=False, subcomplex=None, - check=False): - r""" - Return the normalized chain complex twisted by some operator. - - A twisting operator is a map from the set of simplices to some algebra. - The differentials are then twisted by this operator. - - INPUT: - - - ``twisting_operator`` -- a dictionary, associating the twist of each - simplex. If it is not given, the canonical one (associated to the - laurent polynomial ring abelianization of the fundamental group, ignoring - torsion) is used. - - - ``dimensions`` -- if ``None``, compute the chain complex in all - dimensions. If a list or tuple of integers, compute the - chain complex in those dimensions, setting the chain groups - in all other dimensions to zero. - - - ``augmented`` (optional, default ``False``) -- if ``True``, - return the augmented chain complex (that is, include a class - in dimension `-1` corresponding to the empty cell). - - - ``cochain`` (optional, default ``False``) -- if ``True``, - return the cochain complex (that is, the dual of the chain - complex). - - - ``verbose`` (optional, default ``False``) -- ignored. - - - ``subcomplex`` (optional, default ``None``) -- if present, - compute the chain complex relative to this subcomplex. - - - ``check`` (optional, default ``False``) -- If ``True``, make - sure that the chain complex is actually a chain complex: - the differentials are composable and their product is zero. - - The normalized chain complex of a simplicial set is isomorphic - to the chain complex obtained by modding out by degenerate - simplices, and the latter is what is actually constructed - here. - - EXAMPLES:: - - sage: W = simplicial_sets.Sphere(1).wedge(simplicial_sets.Sphere(2)) - sage: W.nondegenerate_simplices() - [*, sigma_1, sigma_2] - sage: s1 = W.nondegenerate_simplices()[1] - sage: L. = LaurentPolynomialRing(QQ) - sage: tw = {s1:t} - sage: ChC = W.twisted_chain_complex(tw) - sage: ChC.differential(1) - [-1 + t] - sage: ChC.differential(2) - [0] - - :: - - sage: X = simplicial_sets.Torus() - sage: C = X.twisted_chain_complex() - sage: C.differential(1) - [f2*f3^-1 - 1 f3 - 1 f2 - 1] - sage: C.differential(2) - [ 1 f3] - [f2*f3^-1 1] - [ -1 -1] - sage: C.differential(3) - [] - - :: - - sage: Y = simplicial_sets.RealProjectiveSpace(2) - sage: C = Y.twisted_chain_complex() - sage: C.differential(1) - [-1 + F1] - sage: C.differential(2) - [1 + F1] - sage: C.differential(3) - [] - - """ - from sage.homology.chain_complex import ChainComplex - from sage.structure.element import get_coercion_model - cm = get_coercion_model() - - if twisting_operator: - twop = twisting_operator - else: - di = self._canonical_twisting_operator() - if hasattr(list(di.values())[0], "lift"): - twop = {a: b.lift() for a, b in di.items()} - else: - twop = di - - def twist(s): - if s in twop: - return twop[s] - if s.dimension() > 1: - return twist(self.face_data()[s][-1]) - return 1 - base_ring = cm.common_parent(*twop.values()) - - if dimensions is None: - if not self.cells(): # Empty - if cochain: - return ChainComplex({-1: matrix(base_ring, 0, 0)}, - degree_of_differential=1) - return ChainComplex({0: matrix(base_ring, 0, 0)}, - degree_of_differential=-1) - dimensions = list(range(self.dimension() + 1)) - else: - if not isinstance(dimensions, (list, tuple, range)): - dimensions = list(range(dimensions - 1, dimensions + 2)) - else: - dimensions = [n for n in dimensions if n >= 0] - if not dimensions: - # Return the empty chain complex. - if cochain: - return ChainComplex(base_ring=base_ring, degree=1) - else: - return ChainComplex(base_ring=base_ring, degree=-1) - - differentials = {} - # Convert the tuple self._data to a dictionary indexed by the - # non-degenerate simplices. - if subcomplex: - X = self.quotient(subcomplex) - face_data = X.face_data() - nondegens = X.nondegenerate_simplices() - else: - face_data = self.face_data() - nondegens = self.nondegenerate_simplices() - # simplices: dictionary indexed by dimension, values the list - # of non-degenerate simplices in that dimension. - simplices = {} - for sigma in nondegens: - if sigma.dimension() in simplices: - simplices[sigma.dimension()].append(sigma) - else: - simplices[sigma.dimension()] = [sigma] - first = dimensions.pop(0) - if first in simplices: - rank = len(simplices[first]) - current = sorted(simplices[first]) - else: - rank = 0 - current = [] - if augmented and first == 0: - differentials[first-1] = matrix(base_ring, 0, 1) - differentials[first] = matrix(base_ring, 1, rank, - [1] * rank) - else: - differentials[first] = matrix(base_ring, 0, rank) - - for d in dimensions: - old_rank = rank - faces = {_[1]: _[0] for _ in enumerate(current)} - if d in simplices: - current = sorted(simplices[d]) - rank = len(current) - # old_rank: number of simplices in dimension d-1. - # faces: list of simplices in dimension d-1. - # rank: number of simplices in dimension d. - # current: list of simplices in dimension d. - if not faces: - differentials[d] = matrix(base_ring, old_rank, rank) - else: - matrix_data = {} - for col, sigma in enumerate(current): - sign = 1 - twists = len(face_data[sigma]) * [1] - twists[0] = twist(sigma) - for (ch, tau) in zip(twists, face_data[sigma]): - if tau.is_nondegenerate(): - row = faces[tau] - if (row, col) in matrix_data: - matrix_data[(row, col)] += sign*ch - else: - matrix_data[(row, col)] = sign*ch - sign *= -1 - - differentials[d] = matrix(base_ring, old_rank, - rank, matrix_data) - - else: - rank = 0 - current = [] - differentials[d] = matrix(base_ring, old_rank, rank) - - if cochain: - new_diffs = {} - for d in differentials: - new_diffs[d-1] = differentials[d].transpose() - return ChainComplex(new_diffs, degree_of_differential=1, - check=check) - return ChainComplex(differentials, degree_of_differential=-1, - check=check) - - def twisted_homology(self, n, reduced=False): - r""" - The `n`-th twisted homology module of the simplicial set with respect to - the abelianization of the fundamental_group. - - It is a module over a polynomial ring, including relations to make some - variables the multiplicative inverses of others. - - INPUT: - - - ``n`` - a positive integer. - - - ``reduced`` - (default: False) if set to True, the presentation matrix - will be reduced. - - EXAMPLES:: - - sage: X = simplicial_sets.Sphere(1).wedge(simplicial_sets.Sphere(2)) - sage: X.twisted_homology(1) - Quotient module by Submodule of Ambient free module of rank 1 over the integral domain Multivariate Polynomial Ring in f1, f1inv over Integer Ring - Generated by the rows of the matrix: - [f1*f1inv - 1] - sage: X.twisted_homology(2) - Quotient module by Submodule of Ambient free module of rank 1 over the integral domain Multivariate Polynomial Ring in f1, f1inv over Integer Ring - Generated by the rows of the matrix: - [] - - :: - - sage: Y = simplicial_sets.Torus() - sage: Y.twisted_homology(1) - Quotient module by Submodule of Ambient free module of rank 5 over the integral domain Multivariate Polynomial Ring in f2, f2inv, f3, f3inv over Integer Ring - Generated by the rows of the matrix: - [ 1 0 0 0 0] - [ 0 1 0 0 0] - [ 0 0 1 0 0] - [ 0 0 0 1 0] - [ 0 0 0 0 1] - [f2*f2inv - 1 0 0 0 0] - [ 0 f2*f2inv - 1 0 0 0] - [ 0 0 f2*f2inv - 1 0 0] - [ 0 0 0 f2*f2inv - 1 0] - [ 0 0 0 0 f2*f2inv - 1] - [f3*f3inv - 1 0 0 0 0] - [ 0 f3*f3inv - 1 0 0 0] - [ 0 0 f3*f3inv - 1 0 0] - [ 0 0 0 f3*f3inv - 1 0] - [ 0 0 0 0 f3*f3inv - 1] - sage: Y.twisted_homology(2) - Quotient module by Submodule of Ambient free module of rank 0 over the integral domain Multivariate Polynomial Ring in f2, f2inv, f3, f3inv over Integer Ring - Generated by the rows of the matrix: - [] - sage: Y.twisted_homology(1, reduced=True) - Quotient module by Submodule of Ambient free module of rank 5 over the integral domain Multivariate Polynomial Ring in f2, f2inv, f3, f3inv over Integer Ring - Generated by the rows of the matrix: - [1 0 0 0 0] - [0 1 0 0 0] - [0 0 1 0 0] - [0 0 0 1 0] - [0 0 0 0 1] - - """ - G, d = self._universal_cover_dict() - phi = G.abelianization_map() - abelG, R, I, images = G.abelianization_to_algebra(ZZ) - CC = self.twisted_chain_complex() - M1 = CC.differential(n).T - M2 = CC.differential(n + 1).T - def convert_to_polynomial(p): - if hasattr(p, "lift"): - return p.lift()._as_extended_polynomial() - else: - return p._as_extended_polynomial() - M1 = M1.apply_map(convert_to_polynomial) - M2 = M2.apply_map(convert_to_polynomial) - RP = R._extended_ring - IP = RP.ideal([convert_to_polynomial(g) for g in I]) - JP = R._extended_ring_ideal - GB = (IP+JP).groebner_basis() - GBI = RP.ideal(GB) - - def reduce_laurent(a): - return a._singular_().reduce(GBI)._sage_() - - def group_to_polynomial(el, RP): - res = RP.one() - for a in el.Tietze(): - if a > 0: - res *= RP.gen(2*a-2) - else: - res *= RP.gen(-2*a-1) - return res - - def mkernel(M): - if M.nrows() == 0 or M.ncols() == 0: - return M - res = M - n = res.ncols() - for g in (IP+JP).gens(): - res = res.stack(g*identity_matrix(n)) - syz = res.T._singular_().syz()._sage_() - trimmed = syz.T.submatrix(0, 0, syz.ncols(), M.nrows()) - trimmed = trimmed.apply_map(reduce_laurent) - to_delete = [i for (i, r) in enumerate(trimmed.rows()) if not r] - return trimmed.delete_rows(to_delete) - - def lift_to_submodule(S, M): - if S.nrows() == 0 or S.ncols() == 0: - return S - res = M - for g in GB: - res = res.stack(g*identity_matrix(M.ncols())) - singres = res.T._singular_().lift(S.T._singular_())._sage_() - return singres.submatrix(0, 0, M.nrows(), S.nrows()) - - def mgb(M): - if M.nrows() == 0 or M.ncols() == 0: - return M - res = M - for g in GB: - res = res.stack(g*identity_matrix(M.ncols())) - sres = res.T._singular_().std()._sage_().T - to_delete = [i for i, r in enumerate(sres.apply_map(reduce_laurent)) if not r] - return sres.delete_rows(to_delete) - M2 = border_matrix(n+1) - if M1.nrows() == 0: - return (RP**0).quotient_module([]) - K = mkernel(M1) - DK = mkernel(K) - if M2.nrows() > 0: - S = lift_to_submodule(M2, K) - if S.nrows() > 0 and S.ncols() > 0: - res = mgb(DK.stack(S.T)) - else: - res = DK - else: - res = mgb(DK.T) - resmat = mgb(res.apply_map(reduce_laurent)) - AM = RP ** K.nrows() - if resmat.ncols() == 0: - SM = AM.submodule([]) - return AM.quotient_module(SM) - for g in (IP+JP).gens(): - resmat = resmat.stack(g * identity_matrix(resmat.ncols())) - if reduced: - resmat = resmat.T._singular_().std()._sage_().T - SM = AM.submodule(resmat) - return AM.quotient_module(SM) - @cached_method def algebraic_topological_model(self, base_ring=None): r""" From 2748c2adfc9154f013543483d0634a1990501248 Mon Sep 17 00:00:00 2001 From: Devi Charan Date: Sat, 11 Nov 2023 02:13:50 +0530 Subject: [PATCH 066/155] Fixed crystals in the dark mode. --- .../en/thematic_tutorials/media/stand-a.png | Bin 1337 -> 4404 bytes .../en/thematic_tutorials/media/stand-b.png | Bin 1592 -> 3215 bytes .../en/thematic_tutorials/media/stand-c.png | Bin 1504 -> 2617 bytes .../en/thematic_tutorials/media/stand-d.png | Bin 3569 -> 4711 bytes .../en/thematic_tutorials/media/stand-g.png | Bin 1508 -> 2789 bytes .../en/thematic_tutorials/media/standard1.png | Bin 11222 -> 11422 bytes .../en/thematic_tutorials/media/tableau1.png | Bin 604 -> 672 bytes .../en/thematic_tutorials/media/tableau2.png | Bin 1117 -> 1453 bytes .../en/thematic_tutorials/media/tableau3.png | Bin 902 -> 914 bytes .../en/thematic_tutorials/media/tableau4.png | Bin 1301 -> 1417 bytes .../en/thematic_tutorials/media/tableaux.png | Bin 5704 -> 7224 bytes .../en/thematic_tutorials/media/tensor.png | Bin 1496 -> 5614 bytes 12 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/doc/en/thematic_tutorials/media/stand-a.png b/src/doc/en/thematic_tutorials/media/stand-a.png index e2c973a337157dde40a4d779840de3ada38842fd..5b51eae50ff0fad9d9681e4c1c496e1f4ddb38a8 100644 GIT binary patch literal 4404 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 ZtY=_g#P!mRuMDVz!PC{xWt~$(699^sQJw$* diff --git a/src/doc/en/thematic_tutorials/media/stand-b.png b/src/doc/en/thematic_tutorials/media/stand-b.png index 21db8f321a618ffef7c65d89b91eab5a00e648f9..bc270abde8cb52e428477f5bdc8adc99233358c4 100644 GIT binary patch literal 3215 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 B8OHzs literal 1592 zcma)6doQfW#uxvhgntYk8YWL$Tq{n@ko$NsVB>^a~2J@50K_j%s;e1E(dM-O|b!FAyP z0H}F+;_v_fLqNHK`fBLbHayq|0W9K>2k!fKt#Z^Gh^?o22GSw){43mFopxS%WYI9B zf3$!DDH<|dv(^iT@r@gplwe}7J8G#;&ksz&X4kbfA{wVkKCJ8Twg@+DafVeqiiNl{ zwmyZ#fn88XOW0xBmbwl%55cUk*gul2i+0^=okkX?U((uY1a(S2*|gzj2m#<;ya(?2 zV~JJPLK695@sWif?iR)g+q4E`9naB8ZCSYIICo0~Q?c0Chml(18aQ79Us;vhomtGo z`SGVljcLcWzV(eD5|*86Zq5hk=G@lkpTvbY3*+<4V~qT{y~5Drs^fd*tZCs}6@y58ey5#X@kO=p^+#1(wp`9l)mWS!8QU7kEij!u^HB7B%`VFlOGQF^`A+Q$3^tnG1-hK_M{zf|monO%69NY|W;SX{Wn zX3A`8B&_|&k;5LNU#OXLi#;uT8(g!V5qr7G^rOg_KKKIkaTy9&Oh-$P@Fv5x^J9MV z;ss{ZBMG~1Kp*+J?we#?L#x?qZsyY$ zZkl-|;T_eNGO#?sLRpaGPha~$zQ(zijtSHeN(Y!Za^g8ZmsJBv53LEPnHvT9nIGWB`Gq$B$UWJ zPMkTUcz%CR|G0Qbt}K!&!}1Zz8MhDP;xltp)!N40h_dGgMKdAJrJo0?gbAFk1;5_Q z5%Q$c-1Os!1om0-XwIpML{AfcD!Zw#&NEcj&Q}bXzI1I1LJOYC&C}4^90N1NH(hX3 z?==-lpIKSowuGK4U&Zw;#bQcGm0*Iiac*E#aJOK-zTj(H?p#+LnI|q0q0Z`i=Lc7$ zg=XP(Hu9iRpGA%(kPC-jWjYJh2paniDHn32gLWnN2%=N#K3fx(jZk`{jZ?l6d^Rbc zeKK@V&Q^RmiqGm5W;@8OB>_x1tbQKH*DJ4@7i4^$Mmd)~hxe5?j}Nm~Ob;S!X=;dY zs=bLhYpq{VDHz@AQGp-Z?ax}%Q_IswJhDR4iw0Zj#y1Gw^fQ<=rL1L`(@SU<#DhrKzD-u4f>GNYM_jEEjqjGHMC09ZFa3}z5fGs<57Ha#%DtC z?6)qLu6^HgjWrO{tH$60Y(==mZOh}x%}cjbAg{&|lsW{sNz1xRdvt>_$}OEkMu;{>gn43sL}HZijJI*zlA;0a*IbZ~y=R diff --git a/src/doc/en/thematic_tutorials/media/stand-c.png b/src/doc/en/thematic_tutorials/media/stand-c.png index fe480d5f7f45a3dfb9f2c3a370efde2159036af5..3874783ae7bdbfb0cfdbd9675acaafc3c4b38748 100644 GIT binary patch literal 2617 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 bm$vvX-5NTQr@^xg00000NkvXXu0mjfc!ux7 literal 1504 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 diff --git a/src/doc/en/thematic_tutorials/media/stand-g.png b/src/doc/en/thematic_tutorials/media/stand-g.png index b817da8f1add62fdfb066d35092f868c089b9c3d..aeb401483fda095882a4720e246e40d648486174 100644 GIT binary patch literal 2789 zcmVB$|S% zAQXy3R1nISv@uN_2iHFPUcS5Co%!+Mp1U`*cXM{ce6Vyo{=c8|-&umgN-@F1BuwEy zo4}IbF)Qp!mJV>p0av`Z+NKTzx-yY+W{ui8UV==)V%jMuWCX-AlD&*v9wz>GrogjV zVqq15l5$~|#gF3>8}qoD)G(1yV3j*NYs|q}xSB^u4HyFm(e|AUBwAaV=7nr05f=v{ zmRr}CVR2I((WVV)nX%?2?oQp!B;u=eoy@`!Kxlx4wjDzGXh++EP{1@6Wht$-MS!P) zn!8D2UIr6PL`Ohc&22P2$dgjG(k@$XkmmW)sE}TPG=IOa#HR0&)Tf2~&yEs%?zziUIVVaL;|eiAy*1T2Kku<=P`0pg-%Y!&SW+ zgqZ*VWM;RG`>V=&Q&u)_eEzy{t4WFqx~R)zt7~~lhv$+(G>KDJ0{E!?hLpH|{~XoG z$w3ZGH_CM^Sq-ucDGhwDA89pTx$mLv;43a=8hH8zRV8v&8jTL@QXY;0sp=IIU%4td zz>xlZKzy=bYROPQLofUx+i@c5#4dxuZ5tUY4a0W!NdbV1OAc*EU)04X?k3q;MSO#?NfQoUTMVF%D z+$?RdSnfzg!gC`cXOE|GR~Iylob2vy<|3?Wwd?YYxX{4tpT9iRR)s2;w=7g(!NjLS z+QjoW9Z(qn;#0rl_*=5n6PE1|Nz5M|dv0%KuAbZHO}Kn}>mGpFwm^sk6EJcz9&*B_{zFwk+F6ZUU}!z&w5AE3q;I za{yrR2Pzskb;3)*GtA;gEJxuj#qoK{)wiTa*kOid=rNbP0C4@v{&PUC?@nFR3i4@wuRrYbkB;mM zhQ|l`g1*4eVBgRrQJw3#c!7ATv<%Gc>n*bT>yg1wPzwg~==uUd|HQ~ZfByG@gZ1RD z`(cTpO50lE)kp9Jk0%`R4-^zP?DGVD-hu)``^Kq`>h=~PSkAj&xN1jr&Z89=4hDSw zP|&Xp`}dFag?&MPIHdItQ9~;|V`n4-?D?iOf{oL50|)yjdWZdE-u&-Dx2utUY(qtt zfOiRcE~v5_XAcDYgZ_fzMhC)uhdc#7eW3#ZYM|yl28=93;&5LmJmC46FYCXz>;71X z$BW*ggK1&^K)|Q@v=Q&Hcg&~xy`gbWps~Km)yH9E5Z&34H0l*qpR)cL#=fgFD}DQy-myY(;OiHF^G`BGRMCxJJ8K9b#<~F0?XM1% z2_W9_jZ+M!Xb`Ud_85%m>bXjEKYmsyM@a|cvK!c3Y)e--CJHJ{#-e=ln9 z#M>|TdVaE?9KprriE{k~keE1m`d~y66$g;X2q9wQqrJ~eDxlKy#nL`4!|`>ro_Zp+ zs@=lX)CBpiEr}vn2LK}pr+0j^(?AKO6vt8)nW-2nFiZnr228T3C8bB&i!Y`3#3Cyzn?}nzDD5OhG_#GT=ZOF+_6x3e_@^EVr&bspoHEaTQc~Z(yu! zl7|`$T+USq8Lo&bT0$;=hURW=({oL-9}nCptFl(wa;R;y&> zs#HqRx&%U3Oi@hq3WV2|?c@*%Afu=&qZR|h=>m>p_91}frrO|4o+X`iU~=2*LZfup zq$Iy2gK_&&tj27w%vCy%jF&@Xlv*ENGA40)cTNDw?(n)++Rha_ks2FvISsZ#uG9<1 z>Y*w?=&OXvB`ed#2o~zgZ7LFC(n{oFtKloP$)A>^O8@`3GF>t+t>>z!+_GwrweDug z{mtoZije|ygXBG`_=2kAdPsZ~6p>C<`LW}c`1!3JD$WZ4=#t!+p53V|V5dawOC3r& zX8^WMi}z+W0fcm0CsFx*ZkKyoeN;7q-JRvvuh$UK#wPU$-Xy$aPVKF#m?G_6!khgK zUF{K70h=BWVQOmGtQ^6-se{~Z0b^Zm)vsQn_1oO8GCa*hoo#85^cxBjQK)@HVTe&N zWWPF4T`AePE2fBOQF%kMlCn=%QZr*n- r2CKqXV8$w;QWwu5a+sRGI2-AIwQo~5-hF5}00000NkvXXu0mjf??@%R literal 1508 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 diff --git a/src/doc/en/thematic_tutorials/media/tableau1.png b/src/doc/en/thematic_tutorials/media/tableau1.png index 98d034a0840cb7121f05dd666ce6ad0fed3b1117..52e7c1703c9fecc4de488cc416bd70e533a43987 100644 GIT binary patch delta 660 zcmV;F0&D%;1fT_w7=H)=0001#I)wxP000SaNLh0L01op201op398;M(0000HbVXQn zRB3cV=-00^1OC@Cqh($_C9FV`zbNq^HV$XN?eaoJ=Bd7Va|yjGS@W}Rk>wD2@tU)zieIdPa%@k+B6fN90%eBo5cP%c;(v*!e uUMk)SW{P`^x|Ei#E!Q@%m??Ea`Tx+03*>PYctjQh zX%8@VJDF_<5-cllOb60ny$q}M*q9g?7>zw$978H@y}hl?cgR7)_2KDc?X4x!88Y&l~8j~u!)#^K+{?>i{O7qv;iw!+&DJBYw86|m7WH`7n8%a$d zPw3XU`G*5+kLlk3xHK_FFJJuhAK$I_CT%-YlSzrGXwJD`-e~sr#@k81_g49Qu28ug zvUkzWyOS=jtZMytfLq8}W22#c+8SV3s+PD$l%ynqk2 RnStsUJYD@<);T3K0RYzR&R_rl diff --git a/src/doc/en/thematic_tutorials/media/tableau2.png b/src/doc/en/thematic_tutorials/media/tableau2.png index ba142fa1408a363c0cbec3955adf52f45f914ced..9dae9ebe93d5bb3517c3be1fa54a7533adb77be2 100644 GIT binary patch delta 1447 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 diff --git a/src/doc/en/thematic_tutorials/media/tableau3.png b/src/doc/en/thematic_tutorials/media/tableau3.png index 63f8894bdb74788e4cdab0b54676cfcd11126f4b..bce84867d4ad19f83d14fa9a883719ca9324bd96 100644 GIT binary patch delta 904 zcmV;319$v}2a*Sn7=H)=0000vyPd57000SaNLh0L01op201op398;M(0000HbVXQn zRB3cV=-00^1OC@Cqh($_C9FV`zbNq^HV$j2o&Z5al|{U|a;;_SaDEa5LB%?X60??s5eR4k0NPYn46GcDA-Y2JE7`klz-l`WGhr=SCw{>@)}$>qcQ+% zPN$zEN9abF#R9HYj zNw_%f9h#yps*Bnt>ecn~;P_V`sCO;k`}o069#CXB1zwXI9#BI=fKrDBeaz|`>iDv2 z*v}W-z%8=m1*P!*duSNmDf=Hl}Pu<8T#`Ar6B<^lC~YO)%X!iopf zfq&j!vYYIE>H*b2mcr4hxgD9hHID2?(^@MBvNIx8Enn=oPo8 zZHr<&FeQnxVfUSbe?(QfTo!qt5iu?^&!(k?rd~5i(|mgV=+>m25mRm^F$|ST+xW46K9?mFVLtn^LzUEDXT^9qf^qS%eXUK z{~ju{&gr}|%VUu!x)!hrMTMel5~o~JXP$CVWQb+gnQr*4_8n){!=UTdy26ZUvw1)K z&HeVJM0=Br-rlpv)@1q}x3jzSYSrsI!e0(KUdbz8b4D%c&8{zNbc+2iaJPGX{QUXn zjGGGY%=D}uWZka{ohr9~UlCBIJTTMrs_BNf;~Ihg6SsP)@BVC-Q}K9`JMWUo%(3QW zyU$DPSgWyl71OVOU%oipQ=QsE)RDJ3rPJQH` z=&^C)v)Sv{027;PiEBhjN@7W>RdP`(kYX@0Ff`CLumqwI19K}ALn}iIT_D52;Qb@_ zQWOoj`6-!cmAEy`+yDP0P=g}KhJs=%kIbOdVyFDlyp+tmbf^3Z26K}Na}#YNGfQnV z6Z55Wj<5n1t3eg}q?V=TFgT{KRxmIQs?}8YmbT80#4r7;(LH<0}K| OVDNPHb6Mw<&;$Va-)1xb diff --git a/src/doc/en/thematic_tutorials/media/tableau4.png b/src/doc/en/thematic_tutorials/media/tableau4.png index df31775840662b24e101ad5149f80e71fc01c54f..1857acc6cb8652bd7ab9a34a2dcc1c2f6730f9db 100644 GIT binary patch delta 1410 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 diff --git a/src/doc/en/thematic_tutorials/media/tableaux.png b/src/doc/en/thematic_tutorials/media/tableaux.png index 6dc74d77ccda3464c35310961b85b12b4e4a0329..5d6ad183e602538a3de6e9e53bdf68abc6a698c6 100644 GIT binary patch literal 7224 zcmai(cRbr|^!LAF6;)j*T6!z38LEgqTC>!sO;CGPjEGgMv|6Lorb4JvHESm|YSdmW zB}OO-V(&eF(fj^A&-35&N0RUBoaE%n_d3_-yw6F5j+QDtEh{Ym0QBl=N>2d*BuBd5 zzCd~c8miz?q!$`@H4``hT-rK+kloZvlOh?fcqtou={tEnw*z#PRBk`=w6pSZ^Hj8` z;~_b(ojVl~UXE^_f4%x{ZqMPj6;;{#eS}GFL4SQ?FC{y;ji-~lmy;U|04}6;^YHS1 z9l#0+31Ruw)CUDS`}=u^HTwD~0T}ASMoOsw8UWZ3>Pm|GzGEvHFA}e}*0<9|@XX&= zQqD1oV1E)_E(7La(AC{$b-U^re-r*&X*OHQ{dHi^wu`+nlZi3(CxPGSzVlU4m1{e! zKLIl3={Cm_Oj{vV;lkYX9cwR2Z*StSiJki3o@LE`O`qOv7w_7dAR<@WarM&R_YZC- z1>e3Ed;nMl-c1)Y@r?Iknuu3rs&$+UU%k?|_tZ?p|FVOZnzI`y=_YrdJXVSjIGYSm zE*CB{!8noA^K_a;G%8(dn@60ITrx}9O+6z;M+4X3Ms@28~MBu;@+f%_VBxG6ZzD+!l< z#wxG^Z*`vv8&zX3_Apk}q_sV*IFuB$w^Ow+{)PeFPMftRf_A7G zj|+j*aOHVpQl^KRe;90?^^8q3%?_4+XE4W^GI)(+{hI`TSjfX-M%Y+k;%6v!GhF%d z;F03E9|zlO!}S87GSJ+nC~S4S2LC(k68BVSdH}4-eW$8)IOE9B%&d~PK~4awQ{|(Y z;@;a#Tz1!(-FkC`E#^#KhYX*zZ(0pcipiTGUbS4rho<`-`ehL_Z7jY#U>;MHll1pk^}95tyDGE^T!}PkXhBye=K?lAK|bESK`#u!b>N16*Dk^p)AG!u0@6Xz-hBRbXTP6|FS!@!DF&k&UzMd$sJ!#@%D_h_jNNI;}c<%*A{eJxt%GQ_EDQZzjpX5&I8r3 zJ?>)tE`oBdg0aCPq3oSPUf}QU-QYIG&fG>lW{X z)|AMjCJIkZ$@rU28&j|@F?$Z#(k{8eQ?_FZ6d_W@@blk(Kf1KdNUXVAF^yz%FX8;wBS$Ok z8W~hY+jol#`qVC6mC-jU%CHGTMtlsqVBG^6iORjxle7=g8%45tmGHcD1XZ|2i_ke* zm2Nn=iV$#(aBeaRex+eax{Qn>kRc+^xXZ$#I=ude1Y{lOeYr>Wg@OKMf@fMpBv0$d z40`&EU#VPt))>pni5&$V*NnQD?uwT>r*?l6>!TMndh0C)r4BtHNauXKz9l1&eK6O~ zlD;Jgxd;tSDqqy|w7JCw>Z2#G8LNv;&t@DySC&xp6gKSE-%HSFFVZe*>+4^^(FJ9h z?!?0GR*klilrEm{4IRcW*DzQ6T%k^&U#IQW+A%Mum}YYxKJp%P-uSS#@-<}dc|^C7 zWqo%c>G$Vx-`m(jU%ir!B^LvSuql9fM|pPV-9j3Mh%y=Dj(Sgl-l+&8S&;->wYZzh ztBBo=muBy^gXwAs1>e(J2Gz)y8V=PH?u zd*o1xu}e?%skVDLsb$MY_w!}S>Nxc$*vf{4K%bbeo^L`l`PblmyBo*2f#t3FWj4s(2@xV<}ftgf)<-_ZF2 zHhWJONR>Nq;RCqHKFN~2E(YZ_TXGHVPlk`?JEm^e0z>1Ux-cbj1)?EPkfhaO7DmdZ z$Y3z!)x3;AA3a%$LZpf1WUyQqY#MQmi5MQDaoMiKy9!sJ_|iFDVdOkBuU3L>4$RU} z*03lEhJP!q((t7Pgn3bH2VLa9$sF3I?x}f2=?l(Q{komqv9DtMt9<>1*tTn%KU9cT z9+G0pE=Vz4QoyC-aU$36O;Yaf8#VunREzK)vOf2kZb{9 zG6*c@UH2Qd6b1;G0|u4Dp##t!gw5%;*_Qvz|7$#O|IhsYd2c{+ENp+xpOr`z-d(`} z@!9mKBTpXw1k)g#V*$H~fW~7@-ankBZ$I8v87rx+HczBTAitp`c~>x9`ume|Vaa&o z;|u?i2~Jd!kM?ov&V5O~3!cl%H22lxDZk(;sFdH2{n)s6)vz^6*J{8zd0p}xF4Fuc zbR3vlzD!nsKoq}!=67xkwcj1}5fmtG-d0IdO+UX!C!_6rC+aHvC;?#Ejw!1wN`8i?$QkP1>OmOv>ukh7 zAeC%($Rld^W{BWS4zW$&j7B7!%xbjQ^`?EG3kxvu#@q!`w1|sH0G^&4_`8G;?Zv^m4CM>Lk(%F63Y`iK%Lp2wg? z<)6zf>DQN#K2ta0vFp*-t3WQQDG4^)pQ*)es>7m}!x=Vpv#s~y;_%l#GegDhWnHvj z8P(T@Da?k2DbT)%XwKa8U^iU5v&4ivjmBE(ehRs`{!Zg`QP8N{0o8*vInvCd4Fn0wh!YEmYb@U6g1(z<@vhVL zW3Kz|O!|a;Uh1L$7$Ev=Ty_ogefQo`ow9xIOWF2-Zo*eDKpS`V&wC4-L-ayuAz8l{ z_e-B)Cd*oE7~9W2mnC!56fhRqUzF)>VN_51Y$yL#)(N?8Y4e!JubmpfB)5!lqNEQo zx~;lHu%^Ed0(raXXM_6~(`MJTx0TV57T_;!Y9E6sKXKgxJ*|OQ2JP?MVw&vf%KshE z%OBHh?J18`Q@N?qap9j?G04H|mJ9#PIC2|UmK6GH6+dtA{T(_lulM?sG4pCRFG-Na zLn{%??0VfK!j)ARFwIa`cpctcr#pJ&G?OAcf;zEtM@$VK3uCQIezO>nhpZk$18-qg zmn7-7XJ8+g?1PsYWtEOpe-^Zk+>@8q{<4^*{Hs~BVZ|j4+6#eE<%j$ZTPn$<&l^vO z<%iw>=@p#Am&71;YS&ihTfgllYjW3w+z4SPGFX`MRTom?vr{yh5bIJxr8A$^(Oqi2 zoWpqfMKb?uBB6`@cFCMEh@4djpnZ&xJ$r$DqrrcgqANEVP-bHOzz?u@Xn6G0A50*W!iC;wXvdE!x}@ z3+`$@#+0a!0yKiR2yMkMr=;tOJbS8%zJyKqXVWAwZ`=r;zUVJFh1$`yZ9J^ZNkF)C zr&;W7JVdgAz%MV`oJ2Ir*ks3HUT3@vq^m%z(S2!;9^r$jh^y<<-KnL{=P}`Jbtse5@OkAxwlE`ooZ81Kf&=mT=eBmTE8>&wQ4OLY44tEMTOgKOYTq?ZtI)s4 z3I&8ep?MXkhn0M?`)zwjN*objA;0j)-;uQ?Muf$b%njw$qzZJDP1svNO(Vhb65vIC)JaZLark%TCvivh`(y{ zXJmZ$#(Pu$VYyTd;MG}Zq-|c-aWRLG2BEcqBnTKBG5L!`h1hyR5P;R zg@OGVwqQh}olpxN*XW_1ByS~Tggt0%nd?zgA4zymN_guY z`G_(fnpWhS)^oyo@@&`bSH8A31(J;l+(fHuvoCEju5W;8@%wj#F_&4-$M@C))1#!E zX#J}%JiO0Q^D1K*u2jvs5`G-;zl0?OOXSuq;IW9eEki8y)`%)A>n8G@gz^YE1>pRQ z&kx04qSEof7HSF2;Dp`%cBkj=9-(WYIppwhq_hN@LU=;Tl9_-bZSgw_DTO$X)vURA zzFFP7lW(3$Le!vgUUTB^j~xDDm&gBsE)t^sKY&Iu|6f4+kK6q2p^7}x>J7h3<8gpT z#BAE~A)s@Uvo6S?Q*0ma~ zV;fVt&mQ-R_RRAiR!gsX0h83L5rUJAq40CSjOve4`Cw!H+LGyNF->l^VoVMA+H9mX zr>7oN(g#Odi2o}%jDI2bC*S>YJ?GZqz+r8~Leer^k{}>-4!>RUs>b$=?FkD!LGG_T zd`+0VW03Y96$T}}hSzmCN-Q@H_4`eCYCRjdlPtZgnM(~N!_2V=!S7`abBnefV)fx! zV!d$zP!Ml+XMPe-4Ofjm_Ay5XwJjOR8f{2T zB?r8%Ws-Q^O05(vndU4GtD{XZtmPLZ6gA^K10%6D{^1Nz>;1_DlU9~-$zBJDo?9?{ z;7i`@S#cg)X8##;4q~sr?{jS2wpw3j&1Q;K`t591r1eP0;q#9DroyA`!#g#=E0vn zgv(olpR(F36qn^~YW+6k4{n7dp~fc?j-DnLFWP!;m>$*N8lJ4NVJPOh^x_2s`Uk&L zn#tfgMx}5#K$q#k-;iI?`>k0;8werv3E3;=?0p&}d)D*(O<1+-4~$Q(-T`|0khxTQ z2T2(tc@5~hvBrW8516N9&IO7}2P1E|Yhq>3t)$C7TeS-<+S%u^mYf6UC)7eh4A)3sm~THdIG6v;t(0j>OS>7#wt zQu&>tm!Qri@K_6am>ruOz$3z7d3rDZbp&~s5#@j}y!9yDDNLukz2Enw$iXY?9519PYa{1<|kr~xt z_ajxg)7GU&vc#RuqiUFKwO?DYxt!Cp@s)ZYDRNEuammE#&wGGUX*)>jeOpv=Qt_Rz zUP+-LUdMWL!+8=oyr=Z8BJj&@0mrL`@at$f6rdOeGb4P3kEtsX7N*C79Z>1?K` zv`Wb3>fG!n7}3ENE_OR9$UAy^BMa|mwN)0VRsir6vtes|0}F{4*GGz4yKOYg8r<-R zHo-1c^7UUCaVA`z?df+*e|sIH1MyihpK)n@us+6m4|@&Yh1Xav*6v z{ekKJ3_FU{Khq2EOjwB2%*~b4E}06_3Hq3QTN&~JqvihQyJ2W<9U&QPIK=1Nvpg*N z!0p?*b*_6wmC&TE2c4k4UT?DTE>r0*M7qu8zj;}fse2{e49x47s}g4*7}aklXkJk# zRvgX-*)Sx0c;&h{gm@vuKsxi0*i!%SOLNT@_n_8#wR}eo`bSmj(;J*!0rSZd37Kr- zE<3Y_Or?Kziu_x+a~Jgy-Ww-pkRcO;hhk>(HuSi$Alh^rj(+rH`;vw%cB-nI+tCUp zl3Z|972rmMffcvsMVLV_fGOX&eKYStTf z@`H_$X4)mF4CbRo8B%m?fA)jFlPh@++}|-3(`Wi4%W1ow&q)KjpFfQlR%;G)bz{QP zTx2-^(OXu1Vu=6zY>y}LL-Rl(WiKWy)oi1W-%dBgDp+=>&Olge9FJ@2;pSfIJtV8Q zr{p4|-JW?N<(A;A44cI%xT|-9f6PR=qy+d(GU@p;9T`?eSRa#-%J#+GAFpN~9)nvN zqu}ICf-7}F-&k~vw1Wnovs6cJX_K#4B(Pf}qlsS)df4e~#bW|HdPs{(HRD8WN9d6S z$jm*3?^mh=3JnVf*Ax%yA^?#YHYA%cY{4G|w+GZUIg-SM6dqAg$E2`ajlGKnTA9m~DwuSc6WOp(CS^6)-6b4i2Nvj3(9?4O-x{XDK-EAE_ z{!*ka(m8IZNcKq&I91eouz-;C5r%hvciLF2Ujww$nZ7#o6vYCU<98*#3_!F}X&i6A zf|Iw2k&a^K!eh`{k=PT)Vv?=Ou2}USG%rYGMFk#7Nhh3FyAv-h|J7$mttFFfWtFoo0Be)KX;&gmhto8LD zwz?sETURJqw|ZFnZUx{z26#OhD0muD@O07Km|L?8L!vr8MEUF^gHne_Q5;ctoPtNU zyo!2Z=RM2nIRoQSs1s?Z6Q^;LT^;XQ$kUbV344#$nt4P=;1_Css%!kY*d-B8-pc*< z$Bos7m>9WmX(kWS6q8i)e@Z;LYHID-%CwKZ5z93bP9=FIB5LDtaFO!+JTa+%2VTBY zD%>Br__U1Q&#Dy}I9h(qGIxBZJQIm;eRWkA7SQ-FT=AZ4mOp`e@Djsc9-Rr-zjMsu T59B2Ma|fs^YbljHd=~mY8Ezm9 literal 5704 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 diff --git a/src/doc/en/thematic_tutorials/media/tensor.png b/src/doc/en/thematic_tutorials/media/tensor.png index a15989a1075dcdf0901eae5aa22b76a6559df93e..c7287e2d0daeec5ce75b7296fc8a1ffdc10edd00 100644 GIT binary patch literal 5614 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 mb$Ms%)G5(^9{PXCSRk?h literal 1496 zcmai!c|6p47{`BFSx2EsLu(tF==95Pj3TUaTn&n-j5O;QM>)e_nwggEaI~&A3L!${ z%rRzj%+Q!9X%Z1~WgBM0(m2OVcG}nOzFzyszV?sj`Fy|6>v_MP=bz`3c+$ystNb_e z003;Yx5KyqfRvf!y-!(Ml7H;>*e#Jw-dJ1A#)e8cs$24t3$t^Nkf`0CVe{;w>6aog z%)J#lyuq|Av9eGMG20MlT0a`ooNTeZhwGq7Aqgvr^< z{c^R%Y&nvwc3EaYyJ#in*_KSDg*mxOEiEs&WCPh010<4XvM;HS&e_k%>7=q6RlO9g(=jP>wn{TZ^|=A5C-sVO;Ejmb*x zoNZ`0y82#Yo^u6%XY%Z?q~Ow>MZHipc?b~2&T1L-K-m76_%Vy4FeTVQ>4 zn%E0CJQ#f!g4EC`qVzBt6B4Eu(##5LwS;SdrP_&zVwy)Dn?6nb&IfTtqXTn;4Z|&( z__&_R44fR##({$S*L}>6j=D|S`bHdJ-2#S!iddnPwy?J<>+YZ6fkVCY$5MI82G2rvy`TVAjQ3$o={;9w{gWU@3QPceA zmpUWp%4C|rIDb7aUGa^c)qLG{#H=(cmL)u2II69f?MR2SY*CpbWSX2 zJTZ}_D~|h}jM%=~FpV{41@4W{WiU|c>~n4}2!nI>Lv91a`#kd7i+tpZLd~Js>~iK( z3}eqhdC#zSeGE_0B1aABb0@iQt#quIM(w{=@3rPq)Od5-ny7;Q@?#>G31txsn0*dm zl$A`Al%d&nV>Y@qkV8OCad37K@JC@%9n_E8GGRMdCF|_rQFihr? zMeVMHssSSTSp>z#eI><{e)IEE18LeD<@eKfiKMxD_1e+}&ZuEW5%Eo`ZTbXy!egO$ zHg)7f_~VBq6QeCy$ zE#|)hq~-qajyLdrB$ne=<+d!_)-38c*34A+sd{RvHz(@8#3DB1cmq#_*{Tv}NoIv} z>O0w~j$(<6X-8V0jr8@3BpCTzB1i<#gHR|CLW3xjD|E!@h=CDW4}=VjAjl`p)c0RN zaHwyfU+jMau?ivgs=!ByFeF0gk@+{h;Lwszh!6)fJPmQK_5GW(lciggaGWVoiJ6F H-^c#}utK$c From ccac65c3cce90ef01cdd51af3415dcac0c042902 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 8 Sep 2023 15:15:50 -0700 Subject: [PATCH 067/155] Replace relative cimports --- .../quatalg/quaternion_algebra_cython.pyx | 2 +- src/sage/arith/power.pyx | 2 +- src/sage/categories/action.pxd | 6 +++--- src/sage/categories/action.pyx | 6 +++--- src/sage/categories/morphism.pxd | 2 +- src/sage/cpython/debug.pyx | 2 +- src/sage/cpython/getattr.pyx | 2 +- src/sage/data_structures/bitset.pxd | 2 +- src/sage/data_structures/bitset.pyx | 2 +- src/sage/misc/cachefunc.pxd | 2 +- src/sage/modular/modsym/heilbronn.pyx | 2 +- src/sage/rings/abc.pxd | 2 +- src/sage/rings/complex_conversion.pyx | 4 ++-- src/sage/rings/complex_double.pyx | 4 ++-- src/sage/rings/complex_interval.pxd | 2 +- src/sage/rings/complex_interval.pyx | 6 +++--- src/sage/rings/complex_mpc.pyx | 6 +++--- src/sage/rings/complex_mpfr.pxd | 2 +- src/sage/rings/complex_mpfr.pyx | 6 +++--- src/sage/rings/convert/mpfi.pyx | 16 ++++++++-------- src/sage/rings/finite_rings/element_givaro.pyx | 2 +- .../rings/finite_rings/element_pari_ffelt.pyx | 2 +- .../finite_rings/hom_finite_field_givaro.pyx | 12 ++++++------ .../finite_rings/hom_prime_finite_field.pxd | 2 +- .../finite_rings/hom_prime_finite_field.pyx | 6 +++--- src/sage/rings/integer_ring.pxd | 4 ++-- src/sage/rings/laurent_series_ring_element.pyx | 2 +- .../number_field_element_quadratic.pxd | 2 +- src/sage/rings/polynomial/evaluation.pxd | 4 ++-- src/sage/rings/polynomial/multi_polynomial.pxd | 2 +- src/sage/rings/polynomial/polynomial_element.pxd | 4 ++-- src/sage/rings/polynomial/polynomial_element.pyx | 2 +- .../polynomial/polynomial_real_mpfr_dense.pyx | 2 +- src/sage/rings/power_series_mpoly.pxd | 2 +- src/sage/rings/power_series_mpoly.pyx | 2 +- src/sage/rings/power_series_pari.pxd | 2 +- src/sage/rings/power_series_poly.pxd | 2 +- src/sage/rings/power_series_poly.pyx | 2 +- src/sage/rings/rational.pyx | 2 +- src/sage/rings/real_double_element_gsl.pxd | 2 +- src/sage/rings/real_mpfi.pxd | 4 ++-- src/sage/rings/real_mpfi.pyx | 6 +++--- src/sage/rings/real_mpfr.pyx | 6 +++--- 43 files changed, 77 insertions(+), 77 deletions(-) diff --git a/src/sage/algebras/quatalg/quaternion_algebra_cython.pyx b/src/sage/algebras/quatalg/quaternion_algebra_cython.pyx index 983e2515c04..130c9f5d43a 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra_cython.pyx +++ b/src/sage/algebras/quatalg/quaternion_algebra_cython.pyx @@ -35,7 +35,7 @@ from sage.matrix.matrix_space import MatrixSpace from sage.matrix.matrix_integer_dense cimport Matrix_integer_dense from sage.matrix.matrix_rational_dense cimport Matrix_rational_dense -from .quaternion_algebra_element cimport QuaternionAlgebraElement_rational_field +from sage.algebras.quatalg.quaternion_algebra_element cimport QuaternionAlgebraElement_rational_field from sage.libs.gmp.mpz cimport mpz_t, mpz_lcm, mpz_init, mpz_set, mpz_clear, mpz_init_set, mpz_mul, mpz_fdiv_q, mpz_cmp_si diff --git a/src/sage/arith/power.pyx b/src/sage/arith/power.pyx index 65090f23c23..2b4cbd099d1 100644 --- a/src/sage/arith/power.pyx +++ b/src/sage/arith/power.pyx @@ -17,7 +17,7 @@ square-and-multiply algorithm. from cysignals.signals cimport sig_check -from .long cimport integer_check_long +from sage.arith.long cimport integer_check_long cpdef generic_power(a, n) noexcept: diff --git a/src/sage/categories/action.pxd b/src/sage/categories/action.pxd index 444fcc1f38f..a22a37cc22a 100644 --- a/src/sage/categories/action.pxd +++ b/src/sage/categories/action.pxd @@ -1,7 +1,7 @@ from sage.structure.element cimport Element -from .morphism cimport Morphism -from .map cimport Map -from .functor cimport Functor +from sage.categories.morphism cimport Morphism +from sage.categories.map cimport Map +from sage.categories.functor cimport Functor cdef class Action(Functor): cdef readonly G diff --git a/src/sage/categories/action.pyx b/src/sage/categories/action.pyx index 46effeecc42..86711311133 100644 --- a/src/sage/categories/action.pyx +++ b/src/sage/categories/action.pyx @@ -56,9 +56,9 @@ AUTHOR: from cpython.tuple cimport PyTuple_GET_ITEM -from .functor cimport Functor -from .morphism cimport Morphism -from .map cimport Map +from sage.categories.functor cimport Functor +from sage.categories.morphism cimport Morphism +from sage.categories.map cimport Map from sage.structure.element cimport parent from sage.structure.parent cimport Parent diff --git a/src/sage/categories/morphism.pxd b/src/sage/categories/morphism.pxd index 1a941b62b33..e5befc8207e 100644 --- a/src/sage/categories/morphism.pxd +++ b/src/sage/categories/morphism.pxd @@ -1,5 +1,5 @@ from sage.structure.element cimport Element -from .map cimport Map +from sage.categories.map cimport Map cdef class Morphism(Map): diff --git a/src/sage/cpython/debug.pyx b/src/sage/cpython/debug.pyx index cdaca3a4854..0cfc1fc2388 100644 --- a/src/sage/cpython/debug.pyx +++ b/src/sage/cpython/debug.pyx @@ -21,7 +21,7 @@ cdef extern from "Python.h": cdef extern from "sage/cpython/debugimpl.c": void _type_debug(PyTypeObject*) -from .getattr cimport AttributeErrorMessage +from sage.cpython.getattr cimport AttributeErrorMessage # Determine subtype_traverse, subtype_clear, subtype_dealloc functions diff --git a/src/sage/cpython/getattr.pyx b/src/sage/cpython/getattr.pyx index 3a06167ea99..e4982020879 100644 --- a/src/sage/cpython/getattr.pyx +++ b/src/sage/cpython/getattr.pyx @@ -4,7 +4,7 @@ Variants of getattr() from cpython.object cimport PyObject, PyTypeObject, Py_TYPE, descrgetfunc -from .string cimport bytes_to_str +from sage.cpython.string cimport bytes_to_str cdef extern from "Python.h": r""" diff --git a/src/sage/data_structures/bitset.pxd b/src/sage/data_structures/bitset.pxd index d8122c05165..0d72f7eb6ed 100644 --- a/src/sage/data_structures/bitset.pxd +++ b/src/sage/data_structures/bitset.pxd @@ -7,7 +7,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from .bitset_base cimport bitset_t +from sage.data_structures.bitset_base cimport bitset_t # Python layer over bitset_t cdef class FrozenBitset: diff --git a/src/sage/data_structures/bitset.pyx b/src/sage/data_structures/bitset.pyx index 0e3f6e3d640..5c341c8a003 100644 --- a/src/sage/data_structures/bitset.pyx +++ b/src/sage/data_structures/bitset.pyx @@ -31,7 +31,7 @@ linear in ``capacity``. # http://www.gnu.org/licenses/ #***************************************************************************** -from .bitset_base cimport * +from sage.data_structures.bitset_base cimport * from cpython.object cimport Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE diff --git a/src/sage/misc/cachefunc.pxd b/src/sage/misc/cachefunc.pxd index 747e9b60df0..5590c41f4d3 100644 --- a/src/sage/misc/cachefunc.pxd +++ b/src/sage/misc/cachefunc.pxd @@ -1,4 +1,4 @@ -from .function_mangling cimport ArgumentFixer +from sage.misc.function_mangling cimport ArgumentFixer cpdef dict_key(o) noexcept cpdef cache_key(o) noexcept diff --git a/src/sage/modular/modsym/heilbronn.pyx b/src/sage/modular/modsym/heilbronn.pyx index ba42d70aa9e..36134d94d14 100644 --- a/src/sage/modular/modsym/heilbronn.pyx +++ b/src/sage/modular/modsym/heilbronn.pyx @@ -38,7 +38,7 @@ from . import p1list cdef p1list.export export export = p1list.export() -from .apply cimport Apply +from sage.modular.modsym.apply cimport Apply cdef Apply PolyApply= Apply() from sage.matrix.matrix_rational_dense cimport Matrix_rational_dense diff --git a/src/sage/rings/abc.pxd b/src/sage/rings/abc.pxd index a53b512d62f..a2d2e3f0ce4 100644 --- a/src/sage/rings/abc.pxd +++ b/src/sage/rings/abc.pxd @@ -1,4 +1,4 @@ -from .ring cimport CommutativeRing, Field +from sage.rings.ring cimport CommutativeRing, Field cdef class RealField(Field): diff --git a/src/sage/rings/complex_conversion.pyx b/src/sage/rings/complex_conversion.pyx index e7e53724f9c..39c8b63eb55 100644 --- a/src/sage/rings/complex_conversion.pyx +++ b/src/sage/rings/complex_conversion.pyx @@ -1,5 +1,5 @@ -from .complex_double cimport ComplexDoubleElement -from .complex_mpfr cimport ComplexNumber +from sage.rings.complex_double cimport ComplexDoubleElement +from sage.rings.complex_mpfr cimport ComplexNumber from sage.libs.mpfr cimport mpfr_get_d, MPFR_RNDN from sage.libs.gsl.complex cimport GSL_SET_COMPLEX diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index 8f1e8205817..12deffcc9b2 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -105,9 +105,9 @@ complex_double_element_gamma = None complex_double_element_gamma_inc = None complex_double_element_zeta = None -from .complex_conversion cimport CCtoCDF +from sage.rings.complex_conversion cimport CCtoCDF -from .real_double cimport RealDoubleElement, double_repr +from sage.rings.real_double cimport RealDoubleElement, double_repr from .real_double import RDF from sage.rings.integer_ring import ZZ from sage.structure.richcmp cimport rich_to_bool diff --git a/src/sage/rings/complex_interval.pxd b/src/sage/rings/complex_interval.pxd index 56513b65747..60d8c010cd8 100644 --- a/src/sage/rings/complex_interval.pxd +++ b/src/sage/rings/complex_interval.pxd @@ -2,7 +2,7 @@ from sage.libs.mpfr.types cimport mpfr_prec_t from sage.libs.mpfi.types cimport mpfi_t cimport sage.structure.element -from .real_mpfi cimport RealIntervalFieldElement, RealIntervalField_class +from sage.rings.real_mpfi cimport RealIntervalFieldElement, RealIntervalField_class cdef class ComplexIntervalFieldElement(sage.structure.element.FieldElement): diff --git a/src/sage/rings/complex_interval.pyx b/src/sage/rings/complex_interval.pyx index c38261d136d..b35d4d6db1a 100644 --- a/src/sage/rings/complex_interval.pyx +++ b/src/sage/rings/complex_interval.pyx @@ -66,11 +66,11 @@ from sage.arith.constants cimport LOG_TEN_TWO_PLUS_EPSILON from sage.structure.element cimport FieldElement from sage.structure.parent cimport Parent -from .complex_mpfr cimport ComplexNumber +from sage.rings.complex_mpfr cimport ComplexNumber from sage.rings.integer cimport Integer cimport sage.rings.real_mpfi as real_mpfi -from .real_mpfr cimport RealNumber -from .convert.mpfi cimport mpfi_set_sage +from sage.rings.real_mpfr cimport RealNumber +from sage.rings.convert.mpfi cimport mpfi_set_sage from .infinity import infinity diff --git a/src/sage/rings/complex_mpc.pyx b/src/sage/rings/complex_mpc.pyx index 562286db44e..3a5667b5f58 100644 --- a/src/sage/rings/complex_mpc.pyx +++ b/src/sage/rings/complex_mpc.pyx @@ -74,12 +74,12 @@ from sage.structure.richcmp cimport rich_to_bool from sage.categories.map cimport Map from sage.libs.pari.all import pari -from .integer cimport Integer -from .complex_mpfr cimport ComplexNumber +from sage.rings.integer cimport Integer +from sage.rings.complex_mpfr cimport ComplexNumber from .complex_mpfr import ComplexField_class from sage.misc.randstate cimport randstate, current_randstate -from .real_mpfr cimport RealField_class, RealNumber +from sage.rings.real_mpfr cimport RealField_class, RealNumber from .real_mpfr import mpfr_prec_min, mpfr_prec_max from sage.structure.richcmp cimport rich_to_bool, richcmp from sage.categories.fields import Fields diff --git a/src/sage/rings/complex_mpfr.pxd b/src/sage/rings/complex_mpfr.pxd index 4aa6de62a69..95972c52bb5 100644 --- a/src/sage/rings/complex_mpfr.pxd +++ b/src/sage/rings/complex_mpfr.pxd @@ -1,7 +1,7 @@ from sage.libs.mpfr.types cimport mpfr_t, mpfr_prec_t cimport sage.structure.element -from .real_mpfr cimport RealNumber +from sage.rings.real_mpfr cimport RealNumber cdef class ComplexNumber(sage.structure.element.FieldElement): cdef mpfr_t __re diff --git a/src/sage/rings/complex_mpfr.pyx b/src/sage/rings/complex_mpfr.pyx index d6f92bb2fee..fc93ba366dd 100644 --- a/src/sage/rings/complex_mpfr.pyx +++ b/src/sage/rings/complex_mpfr.pyx @@ -47,10 +47,10 @@ from sage.misc.sage_eval import sage_eval import sage.rings.abc from sage.arith.constants cimport LOG_TEN_TWO_PLUS_EPSILON from . import infinity -from .integer cimport Integer +from sage.rings.integer cimport Integer -from .complex_double cimport ComplexDoubleElement -from .real_mpfr cimport RealNumber +from sage.rings.complex_double cimport ComplexDoubleElement +from sage.rings.real_mpfr cimport RealNumber from sage.libs.gsl.complex cimport * from sage.libs.mpmath.utils cimport mpfr_to_mpfval diff --git a/src/sage/rings/convert/mpfi.pyx b/src/sage/rings/convert/mpfi.pyx index abef4963bcf..0d42927740a 100644 --- a/src/sage/rings/convert/mpfi.pyx +++ b/src/sage/rings/convert/mpfi.pyx @@ -23,14 +23,14 @@ from sage.cpython.string cimport bytes_to_str from sage.structure.element cimport Element import sage.rings.abc -from ..integer cimport Integer -from ..rational cimport Rational -from ..real_mpfi cimport RealIntervalFieldElement, RealIntervalField_class -from ..real_mpfr cimport RealNumber -from ..real_double cimport RealDoubleElement -from ..complex_mpfr cimport ComplexNumber -from ..complex_interval cimport ComplexIntervalFieldElement -from ..complex_double cimport ComplexDoubleElement +from sage.rings.integer cimport Integer +from sage.rings.rational cimport Rational +from sage.rings.real_mpfi cimport RealIntervalFieldElement, RealIntervalField_class +from sage.rings.real_mpfr cimport RealNumber +from sage.rings.real_double cimport RealDoubleElement +from sage.rings.complex_mpfr cimport ComplexNumber +from sage.rings.complex_interval cimport ComplexIntervalFieldElement +from sage.rings.complex_double cimport ComplexDoubleElement from cypari2.gen cimport Gen diff --git a/src/sage/rings/finite_rings/element_givaro.pyx b/src/sage/rings/finite_rings/element_givaro.pyx index 0483b4949e7..7619ec7185f 100644 --- a/src/sage/rings/finite_rings/element_givaro.pyx +++ b/src/sage/rings/finite_rings/element_givaro.pyx @@ -57,7 +57,7 @@ from cysignals.signals cimport sig_on, sig_off from cypari2.paridecl cimport * from sage.misc.randstate cimport current_randstate -from .element_pari_ffelt cimport FiniteFieldElement_pari_ffelt +from sage.rings.finite_rings.element_pari_ffelt cimport FiniteFieldElement_pari_ffelt from sage.structure.richcmp cimport richcmp import sage.arith.all diff --git a/src/sage/rings/finite_rings/element_pari_ffelt.pyx b/src/sage/rings/finite_rings/element_pari_ffelt.pyx index 9beb505cae3..e5bf41429e0 100644 --- a/src/sage/rings/finite_rings/element_pari_ffelt.pyx +++ b/src/sage/rings/finite_rings/element_pari_ffelt.pyx @@ -24,7 +24,7 @@ from sage.libs.pari.convert_gmp cimport _new_GEN_from_mpz_t from cypari2.stack cimport new_gen, new_gen_noclear, clear_stack from cypari2.gen cimport Gen as pari_gen, objtogen -from .element_base cimport FinitePolyExtElement +from sage.rings.finite_rings.element_base cimport FinitePolyExtElement from .integer_mod import IntegerMod_abstract import sage.rings.integer diff --git a/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx b/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx index 21036266df1..bc685731610 100644 --- a/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx +++ b/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx @@ -33,21 +33,21 @@ AUTHOR: from sage.rings.finite_rings.finite_field_constructor import FiniteField -from .hom_finite_field cimport SectionFiniteFieldHomomorphism_generic -from .hom_finite_field cimport FiniteFieldHomomorphism_generic -from .hom_finite_field cimport FrobeniusEndomorphism_finite_field +from sage.rings.finite_rings.hom_finite_field cimport SectionFiniteFieldHomomorphism_generic +from sage.rings.finite_rings.hom_finite_field cimport FiniteFieldHomomorphism_generic +from sage.rings.finite_rings.hom_finite_field cimport FrobeniusEndomorphism_finite_field -from .hom_prime_finite_field cimport FiniteFieldHomomorphism_prime +from sage.rings.finite_rings.hom_prime_finite_field cimport FiniteFieldHomomorphism_prime from sage.categories.homset import Hom from sage.structure.element cimport Element from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro -from .element_givaro cimport FiniteField_givaroElement +from sage.rings.finite_rings.element_givaro cimport FiniteField_givaroElement #from element_givaro cimport make_FiniteField_givaroElement from sage.structure.parent cimport Parent -from .element_givaro cimport Cache_givaro +from sage.rings.finite_rings.element_givaro cimport Cache_givaro cdef class SectionFiniteFieldHomomorphism_givaro(SectionFiniteFieldHomomorphism_generic): diff --git a/src/sage/rings/finite_rings/hom_prime_finite_field.pxd b/src/sage/rings/finite_rings/hom_prime_finite_field.pxd index c0da361fb42..b146b0c9169 100644 --- a/src/sage/rings/finite_rings/hom_prime_finite_field.pxd +++ b/src/sage/rings/finite_rings/hom_prime_finite_field.pxd @@ -1,4 +1,4 @@ -from .hom_finite_field cimport (SectionFiniteFieldHomomorphism_generic, +from sage.rings.finite_rings.hom_finite_field cimport (SectionFiniteFieldHomomorphism_generic, FiniteFieldHomomorphism_generic, FrobeniusEndomorphism_finite_field) diff --git a/src/sage/rings/finite_rings/hom_prime_finite_field.pyx b/src/sage/rings/finite_rings/hom_prime_finite_field.pyx index 6bc38546612..2ff550aa1b1 100644 --- a/src/sage/rings/finite_rings/hom_prime_finite_field.pyx +++ b/src/sage/rings/finite_rings/hom_prime_finite_field.pyx @@ -27,9 +27,9 @@ AUTHOR: from sage.categories.homset import Hom from sage.structure.element cimport Element -from .hom_finite_field cimport SectionFiniteFieldHomomorphism_generic -from .hom_finite_field cimport FiniteFieldHomomorphism_generic -from .hom_finite_field cimport FrobeniusEndomorphism_finite_field +from sage.rings.finite_rings.hom_finite_field cimport SectionFiniteFieldHomomorphism_generic +from sage.rings.finite_rings.hom_finite_field cimport FiniteFieldHomomorphism_generic +from sage.rings.finite_rings.hom_finite_field cimport FrobeniusEndomorphism_finite_field from sage.rings.finite_rings.finite_field_base import FiniteField diff --git a/src/sage/rings/integer_ring.pxd b/src/sage/rings/integer_ring.pxd index 41afccaa514..d0af1bc068f 100644 --- a/src/sage/rings/integer_ring.pxd +++ b/src/sage/rings/integer_ring.pxd @@ -1,5 +1,5 @@ -from .ring cimport PrincipalIdealDomain -from .integer cimport Integer +from sage.rings.ring cimport PrincipalIdealDomain +from sage.rings.integer cimport Integer from sage.libs.gmp.types cimport mpz_t cdef class IntegerRing_class(PrincipalIdealDomain): diff --git a/src/sage/rings/laurent_series_ring_element.pyx b/src/sage/rings/laurent_series_ring_element.pyx index b15e6cbdcf0..58f65513270 100644 --- a/src/sage/rings/laurent_series_ring_element.pyx +++ b/src/sage/rings/laurent_series_ring_element.pyx @@ -71,7 +71,7 @@ from .infinity import infinity from sage.rings.rational_field import QQ import sage.misc.latex from sage.rings.polynomial.laurent_polynomial import LaurentPolynomial_univariate -from .power_series_ring_element cimport PowerSeries +from sage.rings.power_series_ring_element cimport PowerSeries from sage.structure.element cimport Element, AlgebraElement from sage.structure.richcmp cimport richcmp_not_equal, rich_to_bool from sage.misc.derivative import multi_derivative diff --git a/src/sage/rings/number_field/number_field_element_quadratic.pxd b/src/sage/rings/number_field/number_field_element_quadratic.pxd index 76661971848..b9fbb294a54 100644 --- a/src/sage/rings/number_field/number_field_element_quadratic.pxd +++ b/src/sage/rings/number_field/number_field_element_quadratic.pxd @@ -2,7 +2,7 @@ from sage.libs.gmp.types cimport mpz_t from sage.libs.arb.types cimport arb_t from sage.rings.integer cimport Integer from sage.rings.rational cimport Rational -from .number_field_element cimport NumberFieldElement, NumberFieldElement_absolute +from sage.rings.number_field.number_field_element cimport NumberFieldElement, NumberFieldElement_absolute cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): diff --git a/src/sage/rings/polynomial/evaluation.pxd b/src/sage/rings/polynomial/evaluation.pxd index 4978e83a831..bbd1ba97b4b 100644 --- a/src/sage/rings/polynomial/evaluation.pxd +++ b/src/sage/rings/polynomial/evaluation.pxd @@ -1,2 +1,2 @@ -from .evaluation_flint cimport * -from .evaluation_ntl cimport * +from sage.rings.polynomial.evaluation_flint cimport * +from sage.rings.polynomial.evaluation_ntl cimport * diff --git a/src/sage/rings/polynomial/multi_polynomial.pxd b/src/sage/rings/polynomial/multi_polynomial.pxd index 73bde26ab51..3f4fe16888c 100644 --- a/src/sage/rings/polynomial/multi_polynomial.pxd +++ b/src/sage/rings/polynomial/multi_polynomial.pxd @@ -1,4 +1,4 @@ -from .commutative_polynomial cimport CommutativePolynomial +from sage.rings.polynomial.commutative_polynomial cimport CommutativePolynomial cdef class MPolynomial(CommutativePolynomial): diff --git a/src/sage/rings/polynomial/polynomial_element.pxd b/src/sage/rings/polynomial/polynomial_element.pxd index b337919a807..9b8bf41fa06 100644 --- a/src/sage/rings/polynomial/polynomial_element.pxd +++ b/src/sage/rings/polynomial/polynomial_element.pxd @@ -2,8 +2,8 @@ from sage.structure.element import Element from sage.structure.element cimport Element, CommutativeAlgebraElement, ModuleElement from sage.structure.parent cimport Parent from sage.rings.integer cimport Integer -from .commutative_polynomial cimport CommutativePolynomial -from .polynomial_compiled cimport CompiledPolynomialFunction +from sage.rings.polynomial.commutative_polynomial cimport CommutativePolynomial +from sage.rings.polynomial.polynomial_compiled cimport CompiledPolynomialFunction cdef class Polynomial(CommutativePolynomial): diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 8e9c4822a7b..44c86cb84cb 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -182,7 +182,7 @@ cpdef is_Polynomial(f) noexcept: return isinstance(f, Polynomial) -from .polynomial_compiled cimport CompiledPolynomialFunction +from sage.rings.polynomial.polynomial_compiled cimport CompiledPolynomialFunction from sage.rings.polynomial.polydict cimport ETuple diff --git a/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx b/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx index 15c65081cd9..8bd5bd00a67 100644 --- a/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +++ b/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx @@ -30,7 +30,7 @@ from cpython.long cimport PyLong_AsLong from cpython.float cimport PyFloat_AS_DOUBLE from sage.structure.parent cimport Parent -from .polynomial_element cimport Polynomial, _dict_to_list +from sage.rings.polynomial.polynomial_element cimport Polynomial, _dict_to_list from sage.rings.real_mpfr cimport RealField_class, RealNumber from sage.rings.integer cimport Integer, smallInteger from sage.rings.rational cimport Rational diff --git a/src/sage/rings/power_series_mpoly.pxd b/src/sage/rings/power_series_mpoly.pxd index d358ada1356..d8816e694b7 100644 --- a/src/sage/rings/power_series_mpoly.pxd +++ b/src/sage/rings/power_series_mpoly.pxd @@ -1,5 +1,5 @@ from sage.structure.element cimport ModuleElement -from .power_series_ring_element cimport PowerSeries +from sage.rings.power_series_ring_element cimport PowerSeries cdef class PowerSeries_mpoly(PowerSeries): cdef ModuleElement __f diff --git a/src/sage/rings/power_series_mpoly.pyx b/src/sage/rings/power_series_mpoly.pyx index fa62a7ef6d6..b65bda0dc81 100644 --- a/src/sage/rings/power_series_mpoly.pyx +++ b/src/sage/rings/power_series_mpoly.pyx @@ -1,6 +1,6 @@ # NOT ready to be used -- possibly should be deleted. -from .power_series_ring_element cimport PowerSeries +from sage.rings.power_series_ring_element cimport PowerSeries from sage.structure.element cimport Element from .infinity import infinity from .polynomial.multi_polynomial_ring_base import is_MPolynomialRing diff --git a/src/sage/rings/power_series_pari.pxd b/src/sage/rings/power_series_pari.pxd index fadf7f0fd08..35b37929c33 100644 --- a/src/sage/rings/power_series_pari.pxd +++ b/src/sage/rings/power_series_pari.pxd @@ -1,5 +1,5 @@ from cypari2.gen cimport Gen as pari_gen -from .power_series_ring_element cimport PowerSeries +from sage.rings.power_series_ring_element cimport PowerSeries cdef class PowerSeries_pari(PowerSeries): cdef pari_gen g diff --git a/src/sage/rings/power_series_poly.pxd b/src/sage/rings/power_series_poly.pxd index 80c441798a1..e37e1fb26cf 100644 --- a/src/sage/rings/power_series_poly.pxd +++ b/src/sage/rings/power_series_poly.pxd @@ -1,4 +1,4 @@ -from .power_series_ring_element cimport PowerSeries +from sage.rings.power_series_ring_element cimport PowerSeries from sage.rings.polynomial.polynomial_element cimport Polynomial from sage.categories.action cimport Action diff --git a/src/sage/rings/power_series_poly.pyx b/src/sage/rings/power_series_poly.pyx index 519e13c1226..894d05c787b 100644 --- a/src/sage/rings/power_series_poly.pyx +++ b/src/sage/rings/power_series_poly.pyx @@ -4,7 +4,7 @@ Power Series Methods The class ``PowerSeries_poly`` provides additional methods for univariate power series. """ -from .power_series_ring_element cimport PowerSeries +from sage.rings.power_series_ring_element cimport PowerSeries from sage.structure.element cimport Element from .infinity import infinity from sage.libs.pari.all import pari_gen, PariError diff --git a/src/sage/rings/rational.pyx b/src/sage/rings/rational.pyx index 0b398428006..09ff7be6a29 100644 --- a/src/sage/rings/rational.pyx +++ b/src/sage/rings/rational.pyx @@ -72,7 +72,7 @@ from sage.structure.richcmp cimport rich_to_bool_sgn import sage.rings.rational_field cimport sage.rings.integer as integer -from .integer cimport Integer +from sage.rings.integer cimport Integer from .integer_ring import ZZ diff --git a/src/sage/rings/real_double_element_gsl.pxd b/src/sage/rings/real_double_element_gsl.pxd index 39c36999ec4..1762c5f944b 100644 --- a/src/sage/rings/real_double_element_gsl.pxd +++ b/src/sage/rings/real_double_element_gsl.pxd @@ -1,4 +1,4 @@ -from .real_double cimport RealDoubleElement +from sage.rings.real_double cimport RealDoubleElement cdef class RealDoubleElement_gsl(RealDoubleElement): diff --git a/src/sage/rings/real_mpfi.pxd b/src/sage/rings/real_mpfi.pxd index 32332d81e3e..f9fc7a1969c 100644 --- a/src/sage/rings/real_mpfi.pxd +++ b/src/sage/rings/real_mpfi.pxd @@ -5,8 +5,8 @@ from sage.rings.ring cimport Field cimport sage.rings.abc from sage.structure.element cimport RingElement -from .rational cimport Rational -from .real_mpfr cimport RealField_class +from sage.rings.rational cimport Rational +from sage.rings.real_mpfr cimport RealField_class cdef class RealIntervalFieldElement(RingElement) # forward decl diff --git a/src/sage/rings/real_mpfi.pyx b/src/sage/rings/real_mpfi.pyx index 6e389b53ac2..d0ab92e3f8d 100644 --- a/src/sage/rings/real_mpfi.pyx +++ b/src/sage/rings/real_mpfi.pyx @@ -269,9 +269,9 @@ from sage.structure.element cimport have_same_parent from sage.structure.parent cimport Parent from sage.structure.richcmp cimport richcmp -from .convert.mpfi cimport mpfi_set_sage -from .real_mpfr cimport RealField_class, RealNumber, RealField -from .integer cimport Integer +from sage.rings.convert.mpfi cimport mpfi_set_sage +from sage.rings.real_mpfr cimport RealField_class, RealNumber, RealField +from sage.rings.integer cimport Integer from .integer_ring import ZZ from .rational_field import QQ diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 4a091fd9191..9117dfcd4ce 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -148,12 +148,12 @@ from cypari2.stack cimport new_gen from sage.libs.mpmath.utils cimport mpfr_to_mpfval -from .integer cimport Integer -from .rational cimport Rational +from sage.rings.integer cimport Integer +from sage.rings.rational cimport Rational from sage.categories.map cimport Map -from .real_double cimport RealDoubleElement +from sage.rings.real_double cimport RealDoubleElement import sage.rings.rational_field From 920a221c2d8ca182a49c6a6fc98e04c7b1d2f6f2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Sep 2023 20:25:37 -0700 Subject: [PATCH 068/155] Replace relative imports in Cython files --- src/sage/categories/action.pyx | 4 +-- src/sage/categories/functor.pyx | 2 +- src/sage/categories/map.pyx | 2 +- src/sage/categories/morphism.pyx | 2 +- src/sage/cpython/wrapperdescr.pyx | 2 +- src/sage/misc/lazy_import.pyx | 6 ++-- src/sage/misc/persist.pyx | 6 ++-- src/sage/misc/sage_timeit_class.pyx | 2 +- src/sage/modular/modsym/heilbronn.pyx | 2 +- src/sage/modular/pollack_stevens/dist.pyx | 2 +- src/sage/rings/complex_double.pyx | 34 +++++++++---------- src/sage/rings/complex_interval.pyx | 6 ++-- src/sage/rings/complex_mpc.pyx | 10 +++--- src/sage/rings/complex_mpfr.pyx | 10 +++--- .../rings/finite_rings/element_ntl_gf2e.pyx | 4 +-- .../rings/finite_rings/element_pari_ffelt.pyx | 2 +- .../rings/finite_rings/finite_field_base.pyx | 12 +++---- .../rings/finite_rings/hom_finite_field.pyx | 2 +- src/sage/rings/finite_rings/integer_mod.pyx | 14 ++++---- src/sage/rings/finite_rings/residue_field.pyx | 12 +++---- src/sage/rings/fraction_field_element.pyx | 2 +- src/sage/rings/function_field/element.pyx | 2 +- .../rings/function_field/element_polymod.pyx | 2 +- .../rings/function_field/element_rational.pyx | 2 +- src/sage/rings/integer.pyx | 6 ++-- src/sage/rings/integer_ring.pyx | 2 +- .../rings/laurent_series_ring_element.pyx | 2 +- src/sage/rings/morphism.pyx | 34 +++++++++---------- .../number_field/number_field_element.pyx | 20 +++++------ .../number_field_element_quadratic.pyx | 6 ++-- .../number_field/number_field_morphisms.pyx | 2 +- .../rings/number_field/totallyreal_data.pyx | 2 +- src/sage/rings/padics/morphism.pyx | 2 +- src/sage/rings/padics/padic_printing.pyx | 2 +- src/sage/rings/padics/pow_computer.pyx | 8 ++--- src/sage/rings/padics/pow_computer_flint.pyx | 8 ++--- .../multi_polynomial_libsingular.pyx | 2 +- .../polynomial/multi_polynomial_ring_base.pyx | 24 ++++++------- .../rings/polynomial/polynomial_element.pyx | 2 +- .../polynomial/polynomial_number_field.pyx | 2 +- src/sage/rings/power_series_mpoly.pyx | 6 ++-- src/sage/rings/power_series_poly.pyx | 2 +- src/sage/rings/power_series_ring_element.pyx | 6 ++-- src/sage/rings/rational.pyx | 10 +++--- src/sage/rings/real_double.pyx | 14 ++++---- src/sage/rings/real_double_element_gsl.pyx | 4 +-- src/sage/rings/real_mpfi.pyx | 4 +-- src/sage/rings/real_mpfr.pyx | 22 ++++++------ src/sage/rings/ring.pyx | 2 +- src/sage/rings/sum_of_squares.pyx | 2 +- src/sage/sat/solvers/satsolver.pyx | 8 ++--- src/sage/structure/parent.pyx | 2 +- src/sage/symbolic/expression.pyx | 8 ++--- src/sage/symbolic/function.pyx | 10 +++--- src/sage/symbolic/pynac_impl.pxi | 12 +++---- src/sage/symbolic/ring.pyx | 4 +-- 56 files changed, 192 insertions(+), 192 deletions(-) diff --git a/src/sage/categories/action.pyx b/src/sage/categories/action.pyx index 86711311133..0e54ceffa27 100644 --- a/src/sage/categories/action.pyx +++ b/src/sage/categories/action.pyx @@ -62,7 +62,7 @@ from sage.categories.map cimport Map from sage.structure.element cimport parent from sage.structure.parent cimport Parent -from . import homset +from sage.categories import homset from weakref import ref @@ -91,7 +91,7 @@ cdef class Action(Functor): :class:`Action` itself, but other classes may use it """ def __init__(self, G, S, is_left=True, op=None): - from .groupoid import Groupoid + from sage.categories.groupoid import Groupoid Functor.__init__(self, Groupoid(G), category(S)) self.G = G self.US = ref(S) diff --git a/src/sage/categories/functor.pyx b/src/sage/categories/functor.pyx index c25e99f2164..32bd079fc73 100644 --- a/src/sage/categories/functor.pyx +++ b/src/sage/categories/functor.pyx @@ -33,7 +33,7 @@ AUTHORS: # https://www.gnu.org/licenses/ # **************************************************************************** -from . import category +from sage.categories import category def _Functor_unpickle(Cl, D, domain, codomain): diff --git a/src/sage/categories/map.pyx b/src/sage/categories/map.pyx index 8f09e3aa00d..fadd066d7f4 100644 --- a/src/sage/categories/map.pyx +++ b/src/sage/categories/map.pyx @@ -21,7 +21,7 @@ AUTHORS: # https://www.gnu.org/licenses/ # **************************************************************************** -from . import homset +from sage.categories import homset import weakref from sage.ext.stdsage cimport HAS_DICTIONARY from sage.arith.power cimport generic_power diff --git a/src/sage/categories/morphism.pyx b/src/sage/categories/morphism.pyx index 32fcd565e34..a30cf52e5c9 100644 --- a/src/sage/categories/morphism.pyx +++ b/src/sage/categories/morphism.pyx @@ -467,7 +467,7 @@ cdef class CallMorphism(Morphism): cdef class IdentityMorphism(Morphism): def __init__(self, parent): - from .homset import Homset, Hom + from sage.categories.homset import Homset, Hom if not isinstance(parent, Homset): parent = Hom(parent, parent) Morphism.__init__(self, parent) diff --git a/src/sage/cpython/wrapperdescr.pyx b/src/sage/cpython/wrapperdescr.pyx index 108ca690b8d..5738a87af46 100644 --- a/src/sage/cpython/wrapperdescr.pyx +++ b/src/sage/cpython/wrapperdescr.pyx @@ -30,7 +30,7 @@ Pure Python classes have normal methods, not slot wrappers:: # https://www.gnu.org/licenses/ # **************************************************************************** -from .string import bytes_to_str +from sage.cpython.string import bytes_to_str def wrapperdescr_call(slotwrapper, self, *args, **kwds): diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index 0ac9fb03d95..c9b09dc1ef5 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -66,7 +66,7 @@ import os import pickle from warnings import warn import inspect -from . import sageinspect +from sage.misc import sageinspect # LazyImport.__repr__ uses try... except FeatureNotPresentError. @@ -1137,7 +1137,7 @@ def save_cache_file(): sage: sage.misc.lazy_import.save_cache_file() """ from sage.misc.temporary_file import atomic_write - from .lazy_import_cache import get_cache_file + from sage.misc.lazy_import_cache import get_cache_file global star_imports if star_imports is None: @@ -1180,7 +1180,7 @@ def get_star_imports(module_name): """ global star_imports if star_imports is None: - from .lazy_import_cache import get_cache_file + from sage.misc.lazy_import_cache import get_cache_file star_imports = {} try: with open(get_cache_file(), "rb") as cache_file: diff --git a/src/sage/misc/persist.pyx b/src/sage/misc/persist.pyx index 670a9a6ac17..5bbc32a239a 100644 --- a/src/sage/misc/persist.pyx +++ b/src/sage/misc/persist.pyx @@ -42,7 +42,7 @@ import bz2 comp = zlib comp_other = bz2 -from .sage_unittest import TestSuite +from sage.misc.sage_unittest import TestSuite # We define two global dictionaries `already_pickled` and @@ -1237,7 +1237,7 @@ def db(name): The database directory is ``$HOME/.sage/db``. """ - from .misc import SAGE_DB + from sage.misc.misc import SAGE_DB return load('%s/%s'%(SAGE_DB,name)) @@ -1250,5 +1250,5 @@ def db_save(x, name=None): try: x.db(name) except AttributeError: - from .misc import SAGE_DB + from sage.misc.misc import SAGE_DB save(x, '%s/%s'%(SAGE_DB,name)) diff --git a/src/sage/misc/sage_timeit_class.pyx b/src/sage/misc/sage_timeit_class.pyx index 5537148e358..f568886574f 100644 --- a/src/sage/misc/sage_timeit_class.pyx +++ b/src/sage/misc/sage_timeit_class.pyx @@ -6,7 +6,7 @@ The ``timeit`` command This uses the function :func:`~sage.misc.sage_timeit.sage_timeit`. """ -from . import sage_timeit +from sage.misc import sage_timeit class SageTimeit: diff --git a/src/sage/modular/modsym/heilbronn.pyx b/src/sage/modular/modsym/heilbronn.pyx index 36134d94d14..7fc8ed28055 100644 --- a/src/sage/modular/modsym/heilbronn.pyx +++ b/src/sage/modular/modsym/heilbronn.pyx @@ -34,7 +34,7 @@ cdef extern from "": float roundf(float x) cimport sage.modular.modsym.p1list as p1list -from . import p1list +from sage.modular.modsym import p1list cdef p1list.export export export = p1list.export() diff --git a/src/sage/modular/pollack_stevens/dist.pyx b/src/sage/modular/pollack_stevens/dist.pyx index fe1f5583cd5..3f67bbf8ecb 100644 --- a/src/sage/modular/pollack_stevens/dist.pyx +++ b/src/sage/modular/pollack_stevens/dist.pyx @@ -44,7 +44,7 @@ from sage.rings.infinity import Infinity #from sage.libs.flint.ulong_extras cimport * -from .sigma0 import Sigma0 +from sage.modular.pollack_stevens.sigma0 import Sigma0 cdef long overflow = 1 << (4 * sizeof(long) - 1) cdef long underflow = -overflow diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index 12deffcc9b2..f101960aab8 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -108,7 +108,7 @@ complex_double_element_zeta = None from sage.rings.complex_conversion cimport CCtoCDF from sage.rings.real_double cimport RealDoubleElement, double_repr -from .real_double import RDF +from sage.rings.real_double import RDF from sage.rings.integer_ring import ZZ from sage.structure.richcmp cimport rich_to_bool @@ -213,7 +213,7 @@ cdef class ComplexDoubleField_class(sage.rings.abc.ComplexDoubleField): sage: CDF.characteristic() 0 """ - from .integer import Integer + from sage.rings.integer import Integer return Integer(0) def random_element(self, double xmin=-1, double xmax=1, double ymin=-1, double ymax=1): @@ -351,7 +351,7 @@ cdef class ComplexDoubleField_class(sage.rings.abc.ComplexDoubleField): sage: CDF((1,2)) # indirect doctest 1.0 + 2.0*I """ - from . import complex_mpfr + from sage.rings import complex_mpfr if isinstance(x, ComplexDoubleElement): return x elif isinstance(x, tuple): @@ -417,10 +417,10 @@ cdef class ComplexDoubleField_class(sage.rings.abc.ComplexDoubleField): """ if S is int or S is float: return FloatToCDF(S) - from .rational_field import QQ - from .real_lazy import RLF - from .real_mpfr import RR - from .cc import CC + from sage.rings.rational_field import QQ + from sage.rings.real_lazy import RLF + from sage.rings.real_mpfr import RR + from sage.rings.cc import CC if S is ZZ or S is QQ or S is RDF or S is RLF: return FloatToCDF(S) @@ -502,7 +502,7 @@ cdef class ComplexDoubleField_class(sage.rings.abc.ComplexDoubleField): if prec == 53: return self else: - from .complex_mpfr import ComplexField + from sage.rings.complex_mpfr import ComplexField return ComplexField(prec) @@ -621,7 +621,7 @@ cdef class ComplexDoubleField_class(sage.rings.abc.ComplexDoubleField): ... ValueError: n must be a positive integer """ - from .integer import Integer + from sage.rings.integer import Integer try: n = Integer(n) except TypeError: @@ -968,7 +968,7 @@ cdef class ComplexDoubleElement(FieldElement): True """ # Sending to another computer algebra system is slow anyway, right? - from .complex_mpfr import ComplexField + from sage.rings.complex_mpfr import ComplexField return ComplexField()(self)._interface_init_(I) def _mathematica_init_(self): @@ -980,7 +980,7 @@ cdef class ComplexDoubleElement(FieldElement): sage: mathematica(CDF(1e-25, 1e25)) # optional - mathematica 1.*^-25 + 1.*^25*I """ - from .complex_mpfr import ComplexField + from sage.rings.complex_mpfr import ComplexField return ComplexField()(self)._mathematica_init_() def _maxima_init_(self, I=None): @@ -995,7 +995,7 @@ cdef class ComplexDoubleElement(FieldElement): sage: CDF(.5 + I)._maxima_init_() # needs sage.symbolic '0.50000000000000000 + 1.0000000000000000*%i' """ - from .complex_mpfr import ComplexField + from sage.rings.complex_mpfr import ComplexField return ComplexField()(self)._maxima_init_(I) def _sympy_(self): @@ -1097,7 +1097,7 @@ cdef class ComplexDoubleElement(FieldElement): sage: format(CDF(0, 0), '+#.4') '+0.000' """ - from .complex_mpfr import _format_complex_number + from sage.rings.complex_mpfr import _format_complex_number return _format_complex_number(GSL_REAL(self._complex), GSL_IMAG(self._complex), format_spec) @@ -2382,12 +2382,12 @@ cdef class ComplexDoubleElement(FieldElement): """ if not GSL_IMAG(self._complex): if GSL_REAL(self._complex) == 0: - from .infinity import unsigned_infinity + from sage.rings.infinity import unsigned_infinity return unsigned_infinity try: - from .integer import Integer + from sage.rings.integer import Integer if Integer(GSL_REAL(self._complex)) < 0: - from .cc import CC + from sage.rings.cc import CC return CC(self).gamma() except TypeError: pass @@ -2429,7 +2429,7 @@ cdef class ComplexDoubleElement(FieldElement): Infinity """ if GSL_REAL(self._complex) == 1 and GSL_IMAG(self._complex) == 0: - from .infinity import unsigned_infinity + from sage.rings.infinity import unsigned_infinity return unsigned_infinity global complex_double_element_zeta diff --git a/src/sage/rings/complex_interval.pyx b/src/sage/rings/complex_interval.pyx index b35d4d6db1a..e804964f501 100644 --- a/src/sage/rings/complex_interval.pyx +++ b/src/sage/rings/complex_interval.pyx @@ -71,7 +71,7 @@ from sage.rings.integer cimport Integer cimport sage.rings.real_mpfi as real_mpfi from sage.rings.real_mpfr cimport RealNumber from sage.rings.convert.mpfi cimport mpfi_set_sage -from .infinity import infinity +from sage.rings.infinity import infinity def is_ComplexIntervalFieldElement(x): @@ -1914,7 +1914,7 @@ cdef class ComplexIntervalFieldElement(FieldElement): 0.500000000000000? + 3.39927010637040?*I """ if not self: - from .real_mpfi import RIF + from sage.rings.real_mpfi import RIF return RIF(0).log() re = abs(self).log() im = self.argument() @@ -2291,6 +2291,6 @@ def create_ComplexIntervalFieldElement(s_real, s_imag=None, int pad=0, min_prec= #else: # bits = max(int(math.log(base,2)*len(s_imag)),int(math.log(base,2)*len(s_imag))) - from .complex_interval_field import ComplexIntervalField + from sage.rings.complex_interval_field import ComplexIntervalField C = ComplexIntervalField(prec=max(bits+pad, min_prec)) return ComplexIntervalFieldElement(C, s_real, s_imag) diff --git a/src/sage/rings/complex_mpc.pyx b/src/sage/rings/complex_mpc.pyx index 3a5667b5f58..6f727bb4c59 100644 --- a/src/sage/rings/complex_mpc.pyx +++ b/src/sage/rings/complex_mpc.pyx @@ -59,7 +59,7 @@ EXAMPLES:: # **************************************************************************** import re -from . import real_mpfr +from sage.rings import real_mpfr import weakref from cpython.object cimport Py_NE @@ -76,11 +76,11 @@ from sage.libs.pari.all import pari from sage.rings.integer cimport Integer from sage.rings.complex_mpfr cimport ComplexNumber -from .complex_mpfr import ComplexField_class +from sage.rings.complex_mpfr import ComplexField_class from sage.misc.randstate cimport randstate, current_randstate from sage.rings.real_mpfr cimport RealField_class, RealNumber -from .real_mpfr import mpfr_prec_min, mpfr_prec_max +from sage.rings.real_mpfr import mpfr_prec_min, mpfr_prec_max from sage.structure.richcmp cimport rich_to_bool, richcmp from sage.categories.fields import Fields @@ -105,8 +105,8 @@ def late_import(): import sage.rings.qqbar AA = sage.rings.qqbar.AA QQbar = sage.rings.qqbar.QQbar - from .real_lazy import CLF, RLF - from .complex_double import CDF + from sage.rings.real_lazy import CLF, RLF + from sage.rings.complex_double import CDF _mpfr_rounding_modes = ['RNDN', 'RNDZ', 'RNDU', 'RNDD'] diff --git a/src/sage/rings/complex_mpfr.pyx b/src/sage/rings/complex_mpfr.pyx index fc93ba366dd..40fe9debdb5 100644 --- a/src/sage/rings/complex_mpfr.pyx +++ b/src/sage/rings/complex_mpfr.pyx @@ -46,7 +46,7 @@ from sage.misc.sage_eval import sage_eval import sage.rings.abc from sage.arith.constants cimport LOG_TEN_TWO_PLUS_EPSILON -from . import infinity +from sage.rings import infinity from sage.rings.integer cimport Integer from sage.rings.complex_double cimport ComplexDoubleElement @@ -97,8 +97,8 @@ def late_import(): QQbar = sage.rings.qqbar.QQbar import sage.symbolic.ring SR = sage.symbolic.ring.SR - from .real_lazy import CLF, RLF - from .complex_double import CDF + from sage.rings.real_lazy import CLF, RLF + from sage.rings.complex_double import CDF cdef object numpy_complex_interface = {'typestr': '=c16'} cdef object numpy_object_interface = {'typestr': '|O'} @@ -367,7 +367,7 @@ class ComplexField_class(sage.rings.abc.ComplexField): try: return self.__real_field except AttributeError: - from .real_mpfr import RealField + from sage.rings.real_mpfr import RealField self.__real_field = RealField(self._prec) return self.__real_field @@ -2926,7 +2926,7 @@ cdef class ComplexNumber(sage.structure.element.FieldElement): if base is None: return ComplexNumber(self._parent, rho.log(), theta) else: - from .real_mpfr import RealField + from sage.rings.real_mpfr import RealField return ComplexNumber(self._parent, rho.log()/RealNumber(RealField(self.prec()),base).log(), theta/RealNumber(RealField(self.prec()),base).log()) def additive_order(self): diff --git a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx index 61e7b05048c..60d275ea5ae 100644 --- a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx +++ b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx @@ -44,8 +44,8 @@ from sage.libs.pari.all import pari from cypari2.gen cimport Gen from cypari2.stack cimport clear_stack -from .element_pari_ffelt import FiniteFieldElement_pari_ffelt -from .finite_field_ntl_gf2e import FiniteField_ntl_gf2e +from sage.rings.finite_rings.element_pari_ffelt import FiniteFieldElement_pari_ffelt +from sage.rings.finite_rings.finite_field_ntl_gf2e import FiniteField_ntl_gf2e from sage.interfaces.abc import GapElement diff --git a/src/sage/rings/finite_rings/element_pari_ffelt.pyx b/src/sage/rings/finite_rings/element_pari_ffelt.pyx index e5bf41429e0..ca262f6f668 100644 --- a/src/sage/rings/finite_rings/element_pari_ffelt.pyx +++ b/src/sage/rings/finite_rings/element_pari_ffelt.pyx @@ -25,7 +25,7 @@ from cypari2.stack cimport new_gen, new_gen_noclear, clear_stack from cypari2.gen cimport Gen as pari_gen, objtogen from sage.rings.finite_rings.element_base cimport FinitePolyExtElement -from .integer_mod import IntegerMod_abstract +from sage.rings.finite_rings.integer_mod import IntegerMod_abstract import sage.rings.integer from sage.rings.integer cimport Integer diff --git a/src/sage/rings/finite_rings/finite_field_base.pyx b/src/sage/rings/finite_rings/finite_field_base.pyx index cc2d1b65dd0..dd79b0d90b9 100644 --- a/src/sage/rings/finite_rings/finite_field_base.pyx +++ b/src/sage/rings/finite_rings/finite_field_base.pyx @@ -1045,7 +1045,7 @@ cdef class FiniteField(Field): pass from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing - from .finite_field_constructor import GF + from sage.rings.finite_rings.finite_field_constructor import GF R = PolynomialRing(GF(self.characteristic()), 'x') self._modulus = R((-1,1)) # Polynomial x - 1 return self._modulus @@ -1288,7 +1288,7 @@ cdef class FiniteField(Field): inclusion_map = self.coerce_map_from(base) from sage.matrix.constructor import matrix - from .maps_finite_field import ( + from sage.rings.finite_rings.maps_finite_field import ( MorphismVectorSpaceToFiniteField, MorphismFiniteFieldToVectorSpace) E = self @@ -1379,7 +1379,7 @@ cdef class FiniteField(Field): if isinstance(R, FiniteField): if R is self: return True - from .residue_field import ResidueField_generic + from sage.rings.finite_rings.residue_field import ResidueField_generic if isinstance(R, ResidueField_generic): return False if R.characteristic() == self.characteristic(): @@ -1543,7 +1543,7 @@ cdef class FiniteField(Field): sage: L(u).minpoly() == u.minpoly() True """ - from .finite_field_constructor import GF + from sage.rings.finite_rings.finite_field_constructor import GF from sage.rings.polynomial.polynomial_element import Polynomial from sage.rings.integer import Integer if name is None and names is not None: @@ -1719,7 +1719,7 @@ cdef class FiniteField(Field): sage: GF(3^8, 'a').subfield(4) Finite Field in a4 of size 3^4 """ - from .finite_field_constructor import GF + from sage.rings.finite_rings.finite_field_constructor import GF p = self.characteristic() n = self.degree() if not n % degree == 0: @@ -1926,7 +1926,7 @@ cdef class FiniteField(Field): sage: GF(next_prime(2^16, 2), 'a').is_conway() False """ - from .conway_polynomials import conway_polynomial, exists_conway_polynomial + from sage.rings.finite_rings.conway_polynomials import conway_polynomial, exists_conway_polynomial p = self.characteristic() n = self.degree() return (exists_conway_polynomial(p, n) diff --git a/src/sage/rings/finite_rings/hom_finite_field.pyx b/src/sage/rings/finite_rings/hom_finite_field.pyx index 5f54c04dd36..85dadd6fb2c 100644 --- a/src/sage/rings/finite_rings/hom_finite_field.pyx +++ b/src/sage/rings/finite_rings/hom_finite_field.pyx @@ -763,7 +763,7 @@ cdef class FrobeniusEndomorphism_finite_field(FrobeniusEndomorphism_generic): """ if self._degree_fixed == 1: k = FiniteField(self.domain().characteristic()) - from .hom_prime_finite_field import FiniteFieldHomomorphism_prime + from sage.rings.finite_rings.hom_prime_finite_field import FiniteFieldHomomorphism_prime f = FiniteFieldHomomorphism_prime(Hom(k, self.domain())) else: k = FiniteField(self.domain().characteristic()**self._degree_fixed, diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index d715cec1493..d687c4bf50c 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -153,7 +153,7 @@ def Mod(n, m, parent=None): # m is non-zero, so return n mod m if parent is None: - from .integer_mod_ring import IntegerModRing + from sage.rings.finite_rings.integer_mod_ring import IntegerModRing parent = IntegerModRing(m) return IntegerMod(parent, n) @@ -493,7 +493,7 @@ cdef class IntegerMod_abstract(FiniteRingElement): if not isinstance(self, IntegerMod_abstract): # something % Mod(x,y) makes no sense return NotImplemented - from .integer_mod_ring import IntegerModRing + from sage.rings.finite_rings.integer_mod_ring import IntegerModRing R = IntegerModRing(modulus) if (self)._parent._IntegerModRing_generic__order % R.order(): raise ArithmeticError(f"reduction modulo {modulus!r} not defined") @@ -1227,7 +1227,7 @@ cdef class IntegerMod_abstract(FiniteRingElement): R = self.parent()['x'] modulus = R.gen()**2 - R(self) if self._parent.is_field(): - from .finite_field_constructor import FiniteField + from sage.rings.finite_rings.finite_field_constructor import FiniteField Q = FiniteField(self._modulus.sageInteger**2, y, modulus) else: R = self.parent()['x'] @@ -1437,7 +1437,7 @@ cdef class IntegerMod_abstract(FiniteRingElement): ....: if (y^41).nth_root(41*r)**(41*r) != y^41: raise RuntimeError ....: if (y^307).nth_root(307*r)**(307*r) != y^307: raise RuntimeError - sage: for t in range(200): # needs sage.libs.pari + sage: for t in range(200): # needs sage.libs.pari sage.rings.padics ....: n = randint(1,2^63) ....: K = Integers(n) ....: b = K.random_element() @@ -2137,7 +2137,7 @@ cdef class IntegerMod_gmp(IntegerMod_abstract): modulus = self._modulus.sageInteger other_modulus = other._modulus.sageInteger - from .integer_mod_ring import IntegerModRing + from sage.rings.finite_rings.integer_mod_ring import IntegerModRing lift = IntegerMod_gmp(IntegerModRing(modulus*other_modulus)) try: if mpz_cmp(self.value, other.value) > 0: @@ -2541,7 +2541,7 @@ cdef class IntegerMod_int(IntegerMod_abstract): cdef IntegerMod_int lift cdef int_fast32_t x - from .integer_mod_ring import IntegerModRing + from sage.rings.finite_rings.integer_mod_ring import IntegerModRing lift = IntegerMod_int(IntegerModRing(self._modulus.int32 * other._modulus.int32)) try: @@ -3377,7 +3377,7 @@ cdef class IntegerMod_int64(IntegerMod_abstract): cdef IntegerMod_int64 lift cdef int_fast64_t x - from .integer_mod_ring import IntegerModRing + from sage.rings.finite_rings.integer_mod_ring import IntegerModRing lift = IntegerMod_int64(IntegerModRing(self._modulus.int64 * other._modulus.int64)) try: diff --git a/src/sage/rings/finite_rings/residue_field.pyx b/src/sage/rings/finite_rings/residue_field.pyx index 9845266870a..e84b303769a 100644 --- a/src/sage/rings/finite_rings/residue_field.pyx +++ b/src/sage/rings/finite_rings/residue_field.pyx @@ -386,7 +386,7 @@ class ResidueFieldFactory(UniqueFactory): q = characteristic**(f.degree()) if q < zech_log_bound and (impl is None or impl == 'givaro'): try: - from .residue_field_givaro import ResidueFiniteField_givaro + from sage.rings.finite_rings.residue_field_givaro import ResidueFiniteField_givaro except ImportError: if impl is not None: raise @@ -394,7 +394,7 @@ class ResidueFieldFactory(UniqueFactory): return ResidueFiniteField_givaro(p, q, names, f, None, None, None) if q % 2 == 0 and (impl is None or impl == 'ntl'): try: - from .residue_field_ntl_gf2e import ResidueFiniteField_ntl_gf2e + from sage.rings.finite_rings.residue_field_ntl_gf2e import ResidueFiniteField_ntl_gf2e except ImportError: if impl is not None: raise @@ -402,7 +402,7 @@ class ResidueFieldFactory(UniqueFactory): return ResidueFiniteField_ntl_gf2e(q, names, f, "poly", p, None, None, None) if impl is None or impl == 'pari': try: - from .residue_field_pari_ffelt import ResidueFiniteField_pari_ffelt + from sage.rings.finite_rings.residue_field_pari_ffelt import ResidueFiniteField_pari_ffelt except ImportError: if impl is not None: raise @@ -462,7 +462,7 @@ class ResidueFieldFactory(UniqueFactory): q = characteristic**(f.degree()) if q < zech_log_bound and (impl is None or impl == 'givaro'): try: - from .residue_field_givaro import ResidueFiniteField_givaro + from sage.rings.finite_rings.residue_field_givaro import ResidueFiniteField_givaro except ImportError: if impl is not None: raise @@ -470,7 +470,7 @@ class ResidueFieldFactory(UniqueFactory): return ResidueFiniteField_givaro(p, q, names, f, to_vs, to_order, PB) elif q % 2 == 0 and (impl is None or impl == 'ntl'): try: - from .residue_field_ntl_gf2e import ResidueFiniteField_ntl_gf2e + from sage.rings.finite_rings.residue_field_ntl_gf2e import ResidueFiniteField_ntl_gf2e except ImportError: if impl is not None: raise @@ -478,7 +478,7 @@ class ResidueFieldFactory(UniqueFactory): return ResidueFiniteField_ntl_gf2e(q, names, f, "poly", p, to_vs, to_order, PB) if impl is None or impl == 'pari': try: - from .residue_field_pari_ffelt import ResidueFiniteField_pari_ffelt + from sage.rings.finite_rings.residue_field_pari_ffelt import ResidueFiniteField_pari_ffelt except ImportError: if impl is not None: raise diff --git a/src/sage/rings/fraction_field_element.pyx b/src/sage/rings/fraction_field_element.pyx index cb0bbce912f..5b6cfa2e29f 100644 --- a/src/sage/rings/fraction_field_element.pyx +++ b/src/sage/rings/fraction_field_element.pyx @@ -22,7 +22,7 @@ AUTHORS: from sage.structure.element cimport FieldElement, parent from sage.structure.richcmp cimport richcmp -from .rational_field import QQ +from sage.rings.rational_field import QQ import sage.misc.latex as latex diff --git a/src/sage/rings/function_field/element.pyx b/src/sage/rings/function_field/element.pyx index dceaa85fd2e..93a0333a14c 100644 --- a/src/sage/rings/function_field/element.pyx +++ b/src/sage/rings/function_field/element.pyx @@ -83,7 +83,7 @@ def is_FunctionFieldElement(x): """ if isinstance(x, FunctionFieldElement): return True - from .function_field import is_FunctionField + from sage.rings.function_field.function_field import is_FunctionField return is_FunctionField(x.parent()) def make_FunctionFieldElement(parent, element_class, representing_element): diff --git a/src/sage/rings/function_field/element_polymod.pyx b/src/sage/rings/function_field/element_polymod.pyx index 5e748b22a6f..c6fdea83b09 100644 --- a/src/sage/rings/function_field/element_polymod.pyx +++ b/src/sage/rings/function_field/element_polymod.pyx @@ -385,7 +385,7 @@ cdef class FunctionFieldElement_polymod(FunctionFieldElement): if deg == 1: return self._parent(self._x[0].nth_root(self._parent.characteristic())) - from .function_field_rational import RationalFunctionField + from sage.rings.function_field.function_field_rational import RationalFunctionField if not isinstance(self.base_ring(), RationalFunctionField): raise NotImplementedError("only implemented for simple extensions of function fields") # compute a representation of the generator y of the field in terms of powers of y^p diff --git a/src/sage/rings/function_field/element_rational.pyx b/src/sage/rings/function_field/element_rational.pyx index 0b36c50f5f7..986a46300b8 100644 --- a/src/sage/rings/function_field/element_rational.pyx +++ b/src/sage/rings/function_field/element_rational.pyx @@ -302,7 +302,7 @@ cdef class FunctionFieldElement_rational(FunctionFieldElement): sage: (1/x^2).valuation(p) # needs sage.libs.pari -2 """ - from .place import FunctionFieldPlace + from sage.rings.function_field.place import FunctionFieldPlace if not isinstance(place, FunctionFieldPlace): # place is an irreducible polynomial diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 3ecd0bd986d..4cf42b666a1 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -183,7 +183,7 @@ from sage.structure.element import coerce_binop from sage.structure.richcmp cimport rich_to_bool_sgn -from . import integer_ring +from sage.rings import integer_ring cimport gmpy2 gmpy2.import_gmpy2() @@ -2536,7 +2536,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): cdef int pow_2 cdef size_t upper,lower,middle - from .real_mpfi import RIF as R + from sage.rings.real_mpfi import RIF as R rif_self = R(self) @@ -2723,7 +2723,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): # (suggested by David Harvey and Carl Witty) # "for randomly distributed integers, the chance of this # interval-based comparison failing is absurdly low" - from .real_mpfi import RIF + from sage.rings.real_mpfi import RIF approx_compare = RIF(m)**guess if self > approx_compare: guess_filled = 1 diff --git a/src/sage/rings/integer_ring.pyx b/src/sage/rings/integer_ring.pyx index b510c4ba992..1ee45b99a59 100644 --- a/src/sage/rings/integer_ring.pyx +++ b/src/sage/rings/integer_ring.pyx @@ -69,7 +69,7 @@ from sage.misc.randstate cimport randstate, current_randstate, SAGE_RAND_MAX cimport sage.rings.integer as integer -from . import ring +from sage.rings import ring arith = None cdef void late_import() noexcept: diff --git a/src/sage/rings/laurent_series_ring_element.pyx b/src/sage/rings/laurent_series_ring_element.pyx index 58f65513270..cac7acd812c 100644 --- a/src/sage/rings/laurent_series_ring_element.pyx +++ b/src/sage/rings/laurent_series_ring_element.pyx @@ -66,7 +66,7 @@ AUTHORS: # https://www.gnu.org/licenses/ # **************************************************************************** -from .infinity import infinity +from sage.rings.infinity import infinity from sage.rings.rational_field import QQ import sage.misc.latex diff --git a/src/sage/rings/morphism.pyx b/src/sage/rings/morphism.pyx index 9901eff95a3..a9cb8eda29e 100644 --- a/src/sage/rings/morphism.pyx +++ b/src/sage/rings/morphism.pyx @@ -406,7 +406,7 @@ compare equal:: # https://www.gnu.org/licenses/ # **************************************************************************** -from . import ideal +from sage.rings import ideal import sage.structure.all from sage.structure.richcmp cimport (richcmp, rich_to_bool) from sage.misc.cachefunc import cached_method @@ -650,7 +650,7 @@ cdef class RingHomomorphism(RingMap): True """ - from .homset import RingHomset_generic + from sage.rings.homset import RingHomset_generic if not isinstance(parent, RingHomset_generic): raise TypeError("parent must be a ring homset") RingMap.__init__(self, parent) @@ -1038,10 +1038,10 @@ cdef class RingHomomorphism(RingMap): sage: f.kernel() # needs sage.libs.singular Ideal (0) of Multivariate Polynomial Ring in t, u over Rational Field """ - from .polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing - from .quotient_ring import is_QuotientRing - from .polynomial.multi_polynomial_ring import is_MPolynomialRing - from .polynomial.polynomial_ring import is_PolynomialRing + from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing + from sage.rings.quotient_ring import is_QuotientRing + from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing + from sage.rings.polynomial.polynomial_ring import is_PolynomialRing B = self.codomain() graph, from_B, to_A = self._graph_ideal() Q = graph.ring() @@ -1287,8 +1287,8 @@ cdef class RingHomomorphism(RingMap): ... NotImplementedError: rings are not commutative """ - from .quotient_ring import is_QuotientRing - from .ideal import Ideal_generic + from sage.rings.quotient_ring import is_QuotientRing + from sage.rings.ideal import Ideal_generic A = self.domain() B = self.codomain() if not (A.is_commutative() and B.is_commutative()): @@ -2882,7 +2882,7 @@ cdef class FrobeniusEndomorphism_generic(RingHomomorphism): Frobenius endomorphism x |--> x^(5^2) of Power Series Ring in u over Finite Field of size 5 """ - from .ring import CommutativeRing + from sage.rings.ring import CommutativeRing from sage.categories.homset import Hom if not isinstance(domain, CommutativeRing): raise TypeError("The base ring must be a commutative ring") @@ -3135,14 +3135,14 @@ def _tensor_product_ring(B, A): ... ValueError: term ordering must be global """ - from .finite_rings.finite_field_base import FiniteField - from .number_field.number_field_base import NumberField - from .polynomial.multi_polynomial_ring import is_MPolynomialRing - from .polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing - from .polynomial.polynomial_ring import is_PolynomialRing - from .polynomial.polynomial_ring_constructor import PolynomialRing - from .polynomial.term_order import TermOrder - from .quotient_ring import is_QuotientRing + from sage.rings.finite_rings.finite_field_base import FiniteField + from sage.rings.number_field.number_field_base import NumberField + from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing + from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing + from sage.rings.polynomial.polynomial_ring import is_PolynomialRing + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + from sage.rings.polynomial.term_order import TermOrder + from sage.rings.quotient_ring import is_QuotientRing if set(B.variable_names()).isdisjoint(A.variable_names()): names = B.variable_names() + A.variable_names() diff --git a/src/sage/rings/number_field/number_field_element.pyx b/src/sage/rings/number_field/number_field_element.pyx index a0553fc31d9..a21d22e43a4 100644 --- a/src/sage/rings/number_field/number_field_element.pyx +++ b/src/sage/rings/number_field/number_field_element.pyx @@ -353,7 +353,7 @@ cdef class NumberFieldElement(NumberFieldElement_base): quadratic field elements) """ if check: - from .number_field import NumberField_cyclotomic + from sage.rings.number_field.number_field import NumberField_cyclotomic if not isinstance(self.number_field(), NumberField_cyclotomic) \ or not isinstance(new_parent, NumberField_cyclotomic): raise TypeError("The field and the new parent field must both be cyclotomic fields.") @@ -523,7 +523,7 @@ cdef class NumberFieldElement(NumberFieldElement_base): return str(self) p = self.polynomial() P = self.parent() - from .number_field import NumberField_cyclotomic + from sage.rings.number_field.number_field import NumberField_cyclotomic if isinstance(P, NumberField_cyclotomic): n = P._n() if n != 2 and n % 4 == 2: @@ -564,7 +564,7 @@ cdef class NumberFieldElement(NumberFieldElement_base): ....: t = K.random_element() ....: assert K(libgap(t)) == t, "n = {} t = {}".format(n,t) """ - from .number_field import NumberField_cyclotomic + from sage.rings.number_field.number_field import NumberField_cyclotomic P = self.parent() if not isinstance(P, NumberField_cyclotomic): raise NotImplementedError("libgap conversion is only implemented for cyclotomic fields") @@ -1991,7 +1991,7 @@ cdef class NumberFieldElement(NumberFieldElement_base): raise ArithmeticError("factorization of 0 is not defined") K = self.parent() - from .order import is_NumberFieldOrder + from sage.rings.number_field.order import is_NumberFieldOrder if is_NumberFieldOrder(K): K = K.number_field() fac = K.ideal(self).factor() @@ -2097,7 +2097,7 @@ cdef class NumberFieldElement(NumberFieldElement_base): if R.is_field(): return R.one() - from .order import is_NumberFieldOrder + from sage.rings.number_field.order import is_NumberFieldOrder if not is_NumberFieldOrder(R) or not R.is_maximal(): raise NotImplementedError("gcd() for %r is not implemented" % R) @@ -2886,7 +2886,7 @@ cdef class NumberFieldElement(NumberFieldElement_base): raise ValueError("need a real or complex embedding to convert " "a non rational element of a number field " "into an algebraic number") - from .number_field import refine_embedding + from sage.rings.number_field.number_field import refine_embedding emb = refine_embedding(emb, infinity) return parent(emb(self)) @@ -2999,7 +2999,7 @@ cdef class NumberFieldElement(NumberFieldElement_base): if embedding is None: raise TypeError("an embedding into RR or CC must be specified") - from .number_field import NumberField_cyclotomic + from sage.rings.number_field.number_field import NumberField_cyclotomic if isinstance(K, NumberField_cyclotomic): # solution by radicals may be difficult, but we have a closed form from sage.functions.log import exp @@ -3011,7 +3011,7 @@ cdef class NumberFieldElement(NumberFieldElement_base): gen_image = exp(k*two_pi_i/K._n()) return self.polynomial()(gen_image) else: - from .number_field import refine_embedding + from sage.rings.number_field.number_field import refine_embedding # Convert the embedding to an embedding into AA or QQbar embedding = refine_embedding(embedding, infinity) a = embedding(self).radical_expression() @@ -3365,7 +3365,7 @@ cdef class NumberFieldElement(NumberFieldElement_base): True """ if self.__multiplicative_order is None: - from .number_field import NumberField_cyclotomic + from sage.rings.number_field.number_field import NumberField_cyclotomic if self.is_rational(): if self.is_one(): self.__multiplicative_order = ZZ.one() @@ -3923,7 +3923,7 @@ cdef class NumberFieldElement(NumberFieldElement_base): ... ValueError: P must be prime """ - from .number_field_ideal import is_NumberFieldIdeal + from sage.rings.number_field.number_field_ideal import is_NumberFieldIdeal if not is_NumberFieldIdeal(P): if isinstance(P, NumberFieldElement): P = self.number_field().fractional_ideal(P) diff --git a/src/sage/rings/number_field/number_field_element_quadratic.pyx b/src/sage/rings/number_field/number_field_element_quadratic.pyx index 3cdaabb3140..88118848cc8 100644 --- a/src/sage/rings/number_field/number_field_element_quadratic.pyx +++ b/src/sage/rings/number_field/number_field_element_quadratic.pyx @@ -520,7 +520,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): - Craig Citro (reworked for quadratic elements) """ if check: - from .number_field import NumberField_cyclotomic + from sage.rings.number_field.number_field import NumberField_cyclotomic if not isinstance(self.number_field(), NumberField_cyclotomic) \ or not isinstance(new_parent, NumberField_cyclotomic): raise TypeError("The field and the new parent field must both be cyclotomic fields.") @@ -1918,10 +1918,10 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): else: # avoid circular import if self._parent._embedding is None: - from .number_field import NumberField + from sage.rings.number_field.number_field import NumberField K = NumberField(QQ['x'].gen()**2 - negD, 'sqrt%s' % negD) else: - from .number_field import QuadraticField + from sage.rings.number_field.number_field import QuadraticField K = QuadraticField(negD, 'sqrt%s' % negD) q = ( K._zero_element)._new() mpz_set(q.denom, self.denom) diff --git a/src/sage/rings/number_field/number_field_morphisms.pyx b/src/sage/rings/number_field/number_field_morphisms.pyx index 1f6e12ce2c5..38a8dfd3726 100644 --- a/src/sage/rings/number_field/number_field_morphisms.pyx +++ b/src/sage/rings/number_field/number_field_morphisms.pyx @@ -616,7 +616,7 @@ cdef class CyclotomicFieldEmbedding(NumberFieldEmbedding): -1 """ Morphism.__init__(self, K, L) - from .number_field import NumberField_cyclotomic + from sage.rings.number_field.number_field import NumberField_cyclotomic if not isinstance(K, NumberField_cyclotomic) or not isinstance(L, NumberField_cyclotomic): raise TypeError("CyclotomicFieldEmbedding only valid for cyclotomic fields.") Kn = K._n() diff --git a/src/sage/rings/number_field/totallyreal_data.pyx b/src/sage/rings/number_field/totallyreal_data.pyx index e504fb6b45f..9bce936b362 100644 --- a/src/sage/rings/number_field/totallyreal_data.pyx +++ b/src/sage/rings/number_field/totallyreal_data.pyx @@ -440,7 +440,7 @@ def easy_is_irreducible_py(f): cdef double eps_global eps_global = 10.**(-4) -from .totallyreal_phc import __lagrange_bounds_phc +from sage.rings.number_field.totallyreal_phc import __lagrange_bounds_phc cdef class tr_data: r""" diff --git a/src/sage/rings/padics/morphism.pyx b/src/sage/rings/padics/morphism.pyx index 3dbae06bc51..a50c92a06f9 100644 --- a/src/sage/rings/padics/morphism.pyx +++ b/src/sage/rings/padics/morphism.pyx @@ -21,7 +21,7 @@ from sage.structure.richcmp cimport (richcmp, rich_to_bool, richcmp_not_equal) from sage.rings.morphism cimport RingHomomorphism -from .padic_generic import pAdicGeneric +from sage.rings.padics.padic_generic import pAdicGeneric cdef class FrobeniusEndomorphism_padics(RingHomomorphism): diff --git a/src/sage/rings/padics/padic_printing.pyx b/src/sage/rings/padics/padic_printing.pyx index caf19c7bdf9..f92afb51529 100644 --- a/src/sage/rings/padics/padic_printing.pyx +++ b/src/sage/rings/padics/padic_printing.pyx @@ -464,7 +464,7 @@ cdef class pAdicPrinter_class(SageObject): raise ValueError("max_terse_terms must be positive and fit in a long") else: self.max_terse_terms = _printer_defaults._max_terse_terms - from .factory import _canonicalize_show_prec + from sage.rings.padics.factory import _canonicalize_show_prec self.show_prec = _canonicalize_show_prec(self.ring._prec_type(), mode, show_prec) # Incompatibilities diff --git a/src/sage/rings/padics/pow_computer.pyx b/src/sage/rings/padics/pow_computer.pyx index 83aa163d36b..942b2a6323e 100644 --- a/src/sage/rings/padics/pow_computer.pyx +++ b/src/sage/rings/padics/pow_computer.pyx @@ -624,13 +624,13 @@ cdef PowComputer_base PowComputer_c(Integer m, Integer cache_limit, Integer prec if PC is not None: return PC if prec_type == 'capped-rel': - from .padic_capped_relative_element import PowComputer_ as PC_class + from sage.rings.padics.padic_capped_relative_element import PowComputer_ as PC_class elif prec_type == 'capped-abs': - from .padic_capped_absolute_element import PowComputer_ as PC_class + from sage.rings.padics.padic_capped_absolute_element import PowComputer_ as PC_class elif prec_type == 'fixed-mod': - from .padic_fixed_mod_element import PowComputer_ as PC_class + from sage.rings.padics.padic_fixed_mod_element import PowComputer_ as PC_class elif prec_type == 'floating-point': - from .padic_floating_point_element import PowComputer_ as PC_class + from sage.rings.padics.padic_floating_point_element import PowComputer_ as PC_class else: PC_class = PowComputer_base PC = PC_class(m, mpz_get_ui(cache_limit.value), mpz_get_ui(prec_cap.value), mpz_get_ui(prec_cap.value), in_field) diff --git a/src/sage/rings/padics/pow_computer_flint.pyx b/src/sage/rings/padics/pow_computer_flint.pyx index 6d0837f7ee5..2ef7ff9e879 100644 --- a/src/sage/rings/padics/pow_computer_flint.pyx +++ b/src/sage/rings/padics/pow_computer_flint.pyx @@ -641,13 +641,13 @@ def PowComputer_flint_maker(prime, cache_limit, prec_cap, ram_prec_cap, in_field """ if prec_type == 'capped-rel': - from .qadic_flint_CR import PowComputer_ + from sage.rings.padics.qadic_flint_CR import PowComputer_ elif prec_type == 'capped-abs': - from .qadic_flint_CA import PowComputer_ + from sage.rings.padics.qadic_flint_CA import PowComputer_ elif prec_type == 'fixed-mod': - from .qadic_flint_FM import PowComputer_ + from sage.rings.padics.qadic_flint_FM import PowComputer_ elif prec_type == 'floating-point': - from .qadic_flint_FP import PowComputer_ + from sage.rings.padics.qadic_flint_FP import PowComputer_ else: raise ValueError("unknown prec_type `%s`" % prec_type) return PowComputer_(prime, cache_limit, prec_cap, ram_prec_cap, in_field, poly) diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index e9787a2e0f7..561136bac6d 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -253,7 +253,7 @@ from sage.misc.sage_eval import sage_eval import sage.rings.polynomial.polynomial_singular_interface cimport cypari2.gen -from . import polynomial_element +from sage.rings.polynomial import polynomial_element permstore=[] cdef class MPolynomialRing_libsingular(MPolynomialRing_base): diff --git a/src/sage/rings/polynomial/multi_polynomial_ring_base.pyx b/src/sage/rings/polynomial/multi_polynomial_ring_base.pyx index 66ade555385..44946845b83 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ring_base.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_ring_base.pyx @@ -22,9 +22,9 @@ from sage.arith.misc import binomial from sage.rings.integer_ring import ZZ -from . import polynomial_ring -from .term_order import TermOrder -from .polynomial_ring_constructor import (PolynomialRing, +from sage.rings.polynomial import polynomial_ring +from sage.rings.polynomial.term_order import TermOrder +from sage.rings.polynomial.polynomial_ring_constructor import (PolynomialRing, polynomial_default_category) @@ -135,7 +135,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing): """ base = self.base_ring() if is_MPolynomialRing(base) or polynomial_ring.is_PolynomialRing(base): - from .flatten import FlatteningMorphism + from sage.rings.polynomial.flatten import FlatteningMorphism return FlatteningMorphism(self) else: return IdentityMorphism(self) @@ -157,7 +157,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing): False """ - from .polynomial_ring_constructor import PolynomialRing + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.categories.pushout import MultiPolynomialFunctor return MultiPolynomialFunctor(self.variable_names(), self.term_order()), self.base_ring() @@ -323,7 +323,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing): vars.remove(str(v)) if len(vars) == 0: return self.base_ring() - from .polynomial_ring_constructor import PolynomialRing + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing if order is None: try: return PolynomialRing(self.base_ring(), vars, @@ -614,7 +614,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing): a dict with respect to ``self.variable_names()``. """ # This is probably horribly inefficient - from .polydict import ETuple + from sage.rings.polynomial.polydict import ETuple other_vars = list(x.parent().variable_names()) name_mapping = [(other_vars.index(var) if var in other_vars else -1) for var in self.variable_names()] K = self.base_ring() @@ -705,7 +705,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing): return "%s[%s]" % (sage.misc.latex.latex(self.base_ring()), vars) def _ideal_class_(self, n=0): - from .multi_polynomial_ideal import MPolynomialIdeal + from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal return MPolynomialIdeal def _is_valid_homomorphism_(self, codomain, im_gens, base_map=None): @@ -915,7 +915,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing): elif not set(my_vars).issubset(set(vars)): while my_vars[-1] in vars: my_vars.pop() - from .polynomial_ring_constructor import PolynomialRing + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing return PolynomialRing(self.base_ring(), my_vars) else: try: @@ -1357,7 +1357,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing): if order is None: order = self.term_order() - from .polynomial_ring_constructor import PolynomialRing + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing return PolynomialRing(base_ring, self.ngens(), names, order=order) def monomial(self, *exponents): @@ -1786,11 +1786,11 @@ cdef class BooleanPolynomialRing_base(MPolynomialRing_base): # Leave *all* old versions! def unpickle_MPolynomialRing_generic_v1(base_ring, n, names, order): - from .polynomial_ring_constructor import PolynomialRing + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing return PolynomialRing(base_ring, n, names=names, order=order) def unpickle_MPolynomialRing_generic(base_ring, n, names, order): - from .polynomial_ring_constructor import PolynomialRing + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing return PolynomialRing(base_ring, n, names=names, order=order) diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 44c86cb84cb..ede464edddf 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -118,7 +118,7 @@ from sage.misc.derivative import multi_derivative from sage.arith.misc import sort_complex_numbers_for_display, power_mod, is_prime from sage.arith.functions import lcm -from . import polynomial_fateman +from sage.rings.polynomial import polynomial_fateman from sage.rings.ideal import is_Ideal from sage.rings.polynomial.polynomial_ring import is_PolynomialRing diff --git a/src/sage/rings/polynomial/polynomial_number_field.pyx b/src/sage/rings/polynomial/polynomial_number_field.pyx index 96f1c002e99..5bd458e5d12 100644 --- a/src/sage/rings/polynomial/polynomial_number_field.pyx +++ b/src/sage/rings/polynomial/polynomial_number_field.pyx @@ -72,7 +72,7 @@ We can also construct polynomials over relative number fields:: # http://www.gnu.org/licenses/ #***************************************************************************** -from .polynomial_element_generic import Polynomial_generic_dense_field +from sage.rings.polynomial.polynomial_element_generic import Polynomial_generic_dense_field from sage.rings.rational_field import QQ from sage.structure.element import coerce_binop from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing diff --git a/src/sage/rings/power_series_mpoly.pyx b/src/sage/rings/power_series_mpoly.pyx index b65bda0dc81..d11eec97269 100644 --- a/src/sage/rings/power_series_mpoly.pyx +++ b/src/sage/rings/power_series_mpoly.pyx @@ -2,9 +2,9 @@ from sage.rings.power_series_ring_element cimport PowerSeries from sage.structure.element cimport Element -from .infinity import infinity -from .polynomial.multi_polynomial_ring_base import is_MPolynomialRing -from . import power_series_poly +from sage.rings.infinity import infinity +from sage.rings.polynomial.multi_polynomial_ring_base import is_MPolynomialRing +from sage.rings import power_series_poly cdef class PowerSeries_mpoly(PowerSeries): diff --git a/src/sage/rings/power_series_poly.pyx b/src/sage/rings/power_series_poly.pyx index 894d05c787b..c651fe03d02 100644 --- a/src/sage/rings/power_series_poly.pyx +++ b/src/sage/rings/power_series_poly.pyx @@ -6,7 +6,7 @@ The class ``PowerSeries_poly`` provides additional methods for univariate power """ from sage.rings.power_series_ring_element cimport PowerSeries from sage.structure.element cimport Element -from .infinity import infinity +from sage.rings.infinity import infinity from sage.libs.pari.all import pari_gen, PariError diff --git a/src/sage/rings/power_series_ring_element.pyx b/src/sage/rings/power_series_ring_element.pyx index b2ce51e09b3..31206e347f9 100644 --- a/src/sage/rings/power_series_ring_element.pyx +++ b/src/sage/rings/power_series_ring_element.pyx @@ -96,7 +96,7 @@ With power series the behavior is the same. # **************************************************************************** from cpython.object cimport Py_EQ, Py_NE -from .infinity import infinity, is_Infinite +from sage.rings.infinity import infinity, is_Infinite from sage.rings.rational_field import QQ @@ -104,7 +104,7 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing import sage.misc.misc import sage.arith.all as arith import sage.misc.latex -from .integer import Integer +from sage.rings.integer import Integer from sage.rings.finite_rings.integer_mod_ring import IntegerModRing from sage.categories.fields import Fields @@ -2957,7 +2957,7 @@ def _solve_linear_de(R, N, L, a, b, f0): def make_powerseries_poly_v0(parent, f, prec, is_gen): # This is only used to unpickle old pickles. The new pickling # works differently! - from . import power_series_poly + from sage.rings import power_series_poly return power_series_poly.PowerSeries_poly(parent, f, prec, 0, is_gen) diff --git a/src/sage/rings/rational.pyx b/src/sage/rings/rational.pyx index 09ff7be6a29..150e4a523bd 100644 --- a/src/sage/rings/rational.pyx +++ b/src/sage/rings/rational.pyx @@ -74,7 +74,7 @@ import sage.rings.rational_field cimport sage.rings.integer as integer from sage.rings.integer cimport Integer -from .integer_ring import ZZ +from sage.rings.integer_ring import ZZ from sage.structure.coerce cimport is_numpy_type @@ -1749,7 +1749,7 @@ cdef class Rational(sage.structure.element.FieldElement): return (self > 0) ## Check that p is prime - from .integer_ring import ZZ + from sage.rings.integer_ring import ZZ p = ZZ(p) if check and not p.is_prime(): raise ValueError('p must be "infinity" or a positive prime number.') @@ -4094,8 +4094,8 @@ cdef class Z_to_Q(Morphism): From: Integer Ring To: Rational Field """ - from . import integer_ring - from . import rational_field + from sage.rings import integer_ring + from sage.rings import rational_field import sage.categories.homset Morphism.__init__(self, sage.categories.homset.Hom(integer_ring.ZZ, rational_field.QQ)) @@ -4215,7 +4215,7 @@ cdef class int_to_Q(Morphism): From: Set of Python objects of class 'int' To: Rational Field """ - from . import rational_field + from sage.rings import rational_field import sage.categories.homset from sage.sets.pythonclass import Set_PythonType Morphism.__init__(self, sage.categories.homset.Hom( diff --git a/src/sage/rings/real_double.pyx b/src/sage/rings/real_double.pyx index f1e5eb0a2c8..19c9501bcf8 100644 --- a/src/sage/rings/real_double.pyx +++ b/src/sage/rings/real_double.pyx @@ -327,9 +327,9 @@ cdef class RealDoubleField_class(sage.rings.abc.RealDoubleField): if S is int or S is float: return ToRDF(S) - from .rational_field import QQ + from sage.rings.rational_field import QQ try: - from .real_lazy import RLF + from sage.rings.real_lazy import RLF except ImportError: RLF = None @@ -349,7 +349,7 @@ cdef class RealDoubleField_class(sage.rings.abc.RealDoubleField): return None try: - from .real_mpfr import RR + from sage.rings.real_mpfr import RR except ImportError: pass else: @@ -431,7 +431,7 @@ cdef class RealDoubleField_class(sage.rings.abc.RealDoubleField): if prec == 53: return self else: - from .real_mpfr import RealField + from sage.rings.real_mpfr import RealField return RealField(prec) @@ -979,7 +979,7 @@ cdef class RealDoubleElement(FieldElement): sage: mathematica(RDF(1e-25)) # optional - mathematica 1.*^-25 """ - from .real_mpfr import RR + from sage.rings.real_mpfr import RR return RR(self._value)._mathematica_init_() def _sage_input_(self, sib, coerced): @@ -2069,7 +2069,7 @@ def is_RealDoubleElement(x): cdef RealDoubleElement global_dummy_element try: - from .real_double_element_gsl import RealDoubleElement_gsl + from sage.rings.real_double_element_gsl import RealDoubleElement_gsl except ImportError: global_dummy_element = RealDoubleElement(0) else: @@ -2175,7 +2175,7 @@ cdef void fast_tp_dealloc(PyObject* o) noexcept: from sage.misc.allocator cimport hook_tp_functions, hook_tp_functions_type hook_tp_functions(global_dummy_element, (&fast_tp_new), (&fast_tp_dealloc), False) try: - from .real_double_element_gsl import RealDoubleElement_gsl + from sage.rings.real_double_element_gsl import RealDoubleElement_gsl except Exception: pass else: diff --git a/src/sage/rings/real_double_element_gsl.pyx b/src/sage/rings/real_double_element_gsl.pyx index 3ebb703b367..05346073d08 100644 --- a/src/sage/rings/real_double_element_gsl.pyx +++ b/src/sage/rings/real_double_element_gsl.pyx @@ -216,10 +216,10 @@ cdef class RealDoubleElement_gsl(RealDoubleElement): cdef _log_base(self, double log_of_base) noexcept: if self._value == 0: - from .real_double import RDF + from sage.rings.real_double import RDF return RDF(-1)/RDF(0) elif self._value < 0: - from .real_double import RDF + from sage.rings.real_double import RDF return RDF.NaN() sig_on() a = self._new_c(gsl_sf_log(self._value) / log_of_base) diff --git a/src/sage/rings/real_mpfi.pyx b/src/sage/rings/real_mpfi.pyx index d0ab92e3f8d..58e3d8de737 100644 --- a/src/sage/rings/real_mpfi.pyx +++ b/src/sage/rings/real_mpfi.pyx @@ -272,8 +272,8 @@ from sage.structure.richcmp cimport richcmp from sage.rings.convert.mpfi cimport mpfi_set_sage from sage.rings.real_mpfr cimport RealField_class, RealNumber, RealField from sage.rings.integer cimport Integer -from .integer_ring import ZZ -from .rational_field import QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ cimport sage.rings.abc diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 9117dfcd4ce..e3152522fbd 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -725,9 +725,9 @@ cdef class RealField_class(sage.rings.abc.RealField): sage: R.get_action(ZZ) Right scalar multiplication by Integer Ring on Univariate Polynomial Ring in x over Real Field with 53 bits of precision """ - from .integer_ring import ZZ - from .rational_field import QQ - from .real_double import RDF + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ + from sage.rings.real_double import RDF if S is ZZ: return ZZtoRR(ZZ, self) @@ -1875,7 +1875,7 @@ cdef class RealNumber(sage.structure.element.RingElement): sage: RealField(100)(2).imag() 0 """ - from .integer_ring import ZZ + from sage.rings.integer_ring import ZZ return ZZ(0) @@ -2389,7 +2389,7 @@ cdef class RealNumber(sage.structure.element.RingElement): if have_same_parent(left, right): return ( left)._add_(right) try: - from .real_mpfi import RealIntervalFieldElement + from sage.rings.real_mpfi import RealIntervalFieldElement except ImportError: RealIntervalFieldElement = None if type(right) is RealIntervalFieldElement: @@ -2413,7 +2413,7 @@ cdef class RealNumber(sage.structure.element.RingElement): if have_same_parent(left, right): return ( left)._sub_(right) try: - from .real_mpfi import RealIntervalFieldElement + from sage.rings.real_mpfi import RealIntervalFieldElement except ImportError: RealIntervalFieldElement = None if type(right) is RealIntervalFieldElement: @@ -2437,7 +2437,7 @@ cdef class RealNumber(sage.structure.element.RingElement): if have_same_parent(left, right): return ( left)._mul_(right) try: - from .real_mpfi import RealIntervalFieldElement + from sage.rings.real_mpfi import RealIntervalFieldElement except ImportError: RealIntervalFieldElement = None if type(right) is RealIntervalFieldElement: @@ -2461,7 +2461,7 @@ cdef class RealNumber(sage.structure.element.RingElement): if have_same_parent(left, right): return ( left)._div_(right) try: - from .real_mpfi import RealIntervalFieldElement + from sage.rings.real_mpfi import RealIntervalFieldElement except ImportError: RealIntervalFieldElement = None if type(right) is RealIntervalFieldElement: @@ -3714,7 +3714,7 @@ cdef class RealNumber(sage.structure.element.RingElement): if mpfr_zero_p(self.value): return Rational(0) - from .real_mpfi import RealIntervalField + from sage.rings.real_mpfi import RealIntervalField cdef mpfr_rnd_t rnd = (self._parent).rnd cdef mpfr_prec_t prec = (self._parent)._prec @@ -3834,7 +3834,7 @@ cdef class RealNumber(sage.structure.element.RingElement): raise ValueError('Must specify exactly one of max_error or max_denominator in nearby_rational()') if max_error is not None: - from .real_mpfi import RealIntervalField + from sage.rings.real_mpfi import RealIntervalField intv_field = RealIntervalField(self.prec()) intv = intv_field(self - max_error, self + max_error) @@ -5661,7 +5661,7 @@ cdef class RealNumber(sage.structure.element.RingElement): # If we got here, then we're not a perfect power of a boundary # point, so it's safe to use the interval arithmetic technique. - from .real_mpfi import RealIntervalField + from sage.rings.real_mpfi import RealIntervalField cdef mpfr_prec_t prec = fld._prec + 10 diff --git a/src/sage/rings/ring.pyx b/src/sage/rings/ring.pyx index 75f58656385..71e72f4f45c 100644 --- a/src/sage/rings/ring.pyx +++ b/src/sage/rings/ring.pyx @@ -1447,7 +1447,7 @@ cdef class CommutativeRing(Ring): sage: f(1+u) 1 + u^25 """ - from .morphism import FrobeniusEndomorphism_generic + from sage.rings.morphism import FrobeniusEndomorphism_generic return FrobeniusEndomorphism_generic(self, n) def derivation_module(self, codomain=None, twist=None): diff --git a/src/sage/rings/sum_of_squares.pyx b/src/sage/rings/sum_of_squares.pyx index e6ec62dc7f1..04be29e0fdc 100644 --- a/src/sage/rings/sum_of_squares.pyx +++ b/src/sage/rings/sum_of_squares.pyx @@ -22,7 +22,7 @@ from libc.math cimport sqrt from cysignals.signals cimport sig_on, sig_off cimport sage.rings.integer as integer -from . import integer +from sage.rings import integer cdef int two_squares_c(uint_fast32_t n, uint_fast32_t res[2]) noexcept: r""" diff --git a/src/sage/sat/solvers/satsolver.pyx b/src/sage/sat/solvers/satsolver.pyx index 1c4ac400cb6..c13a101c37a 100644 --- a/src/sage/sat/solvers/satsolver.pyx +++ b/src/sage/sat/solvers/satsolver.pyx @@ -390,16 +390,16 @@ def SAT(solver=None, *args, **kwds): from sage.sat.solvers.picosat import PicoSAT return PicoSAT(*args, **kwds) elif solver == "LP": - from .sat_lp import SatLP + from sage.sat.solvers.sat_lp import SatLP return SatLP() elif solver == 'glucose': - from .dimacs import Glucose + from sage.sat.solvers.dimacs import Glucose return Glucose(*args, **kwds) elif solver == 'glucose-syrup': - from .dimacs import GlucoseSyrup + from sage.sat.solvers.dimacs import GlucoseSyrup return GlucoseSyrup(*args, **kwds) elif solver == 'kissat': - from .dimacs import Kissat + from sage.sat.solvers.dimacs import Kissat return Kissat(*args, **kwds) else: raise ValueError("Solver '{}' is not available".format(solver)) diff --git a/src/sage/structure/parent.pyx b/src/sage/structure/parent.pyx index 9a0cbd66b9a..6ac939db3c8 100644 --- a/src/sage/structure/parent.pyx +++ b/src/sage/structure/parent.pyx @@ -2672,7 +2672,7 @@ cdef class Parent(sage.structure.category_object.CategoryObject): _register_pair(self, S, "action") # avoid possible infinite loops # detect actions defined by _rmul_, _lmul_, _act_on_, and _acted_upon_ methods - from .coerce_actions import detect_element_action + from sage.structure.coerce_actions import detect_element_action action = detect_element_action(self, S, self_on_left, self_el, S_el) if action is not None: return action diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 0b80c017a0b..9d86a81b24b 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -922,7 +922,7 @@ cdef class Expression(Expression_abc): if state[0] != 0 or len(state) != 3: raise ValueError("unknown state information") # set parent - from .ring import SR + from sage.symbolic.ring import SR self._parent = SR # get variables cdef GExList sym_lst @@ -966,7 +966,7 @@ cdef class Expression(Expression_abc): True """ - from .ring import SR + from sage.symbolic.ring import SR SR.cleanup_var(self) return False @@ -3250,7 +3250,7 @@ cdef class Expression(Expression_abc): sage: x.is_trivially_equal(QQbar(1/2)) True """ - from .ring import SR + from sage.symbolic.ring import SR cdef Expression _other = (SR(other)) sig_on() try: @@ -12130,7 +12130,7 @@ cdef class Expression(Expression_abc): ... ValueError: cannot convert """ - from . import units + from sage.symbolic import units return units.convert(self, target) ################################################################### diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx index 589c500d00d..e1c6b19f659 100644 --- a/src/sage/symbolic/function.pyx +++ b/src/sage/symbolic/function.pyx @@ -148,10 +148,10 @@ from sage.structure.richcmp cimport richcmp from sage.misc.fpickle import pickle_function, unpickle_function -from .symbols import symbol_table, register_symbol +from sage.symbolic.symbols import symbol_table, register_symbol try: - from .expression import ( + from sage.symbolic.expression import ( call_registered_function, find_registered_function, register_or_update_function, get_sfunction_from_hash, get_sfunction_from_serial as get_sfunction_from_serial ) @@ -528,7 +528,7 @@ cdef class Function(SageObject): # to a numeric type at the end symbolic_input = any(isinstance(arg, Expression) for arg in args) - from .ring import SR + from sage.symbolic.ring import SR if coerce: try: @@ -606,7 +606,7 @@ cdef class Function(SageObject): sage: sin.default_variable() # needs sage.symbolic x """ - from .ring import SR + from sage.symbolic.ring import SR return SR.var('x') def _is_numerical(self, x): @@ -1052,7 +1052,7 @@ cdef class BuiltinFunction(Function): if (self._preserved_arg and isinstance(args[self._preserved_arg-1], Element)): arg_parent = parent(args[self._preserved_arg-1]) - from .ring import SR + from sage.symbolic.ring import SR if arg_parent is SR: return res from sage.rings.polynomial.polynomial_ring import PolynomialRing_commutative diff --git a/src/sage/symbolic/pynac_impl.pxi b/src/sage/symbolic/pynac_impl.pxi index 88436ee2705..b2091522c49 100644 --- a/src/sage/symbolic/pynac_impl.pxi +++ b/src/sage/symbolic/pynac_impl.pxi @@ -70,7 +70,7 @@ cdef ex_to_pyExpression(GEx juice) noexcept: cdef Expression nex nex = Expression.__new__(Expression) nex._gobj = GEx(juice) - from .ring import SR + from sage.symbolic.ring import SR nex._parent = SR return nex @@ -189,7 +189,7 @@ cdef GEx pyExpression_to_ex(res) except *: """ if res is None: raise TypeError("function returned None, expected return value of type sage.symbolic.expression.Expression") - from .ring import SR + from sage.symbolic.ring import SR try: t = SR.coerce(res) except TypeError as err: @@ -1156,7 +1156,7 @@ cdef bint py_is_integer(x) noexcept: if not isinstance(x, Element): return False P = (x)._parent - from .ring import SymbolicRing + from sage.symbolic.ring import SymbolicRing return (isinstance(P, SymbolicRing) or P.is_exact()) and x in ZZ @@ -1246,7 +1246,7 @@ cdef bint py_is_exact(x) noexcept: if not isinstance(x, Element): return False P = (x)._parent - from .ring import SymbolicRing + from sage.symbolic.ring import SymbolicRing return isinstance(P, SymbolicRing) or P.is_exact() @@ -1553,7 +1553,7 @@ cdef py_step(n) noexcept: """ Return step function of n. """ - from .ring import SR + from sage.symbolic.ring import SR if n < 0: return SR(0) elif n > 0: @@ -2466,7 +2466,7 @@ def init_pynac_I(): from sage.rings.number_field.number_field import GaussianField pynac_I = GaussianField().gen() ginac_pyinit_I(pynac_I) - from .ring import SR + from sage.symbolic.ring import SR return new_Expression_from_GEx(SR, g_I) diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index f3f32b9c922..a74db5807d5 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -213,7 +213,7 @@ cdef class SymbolicRing(sage.rings.abc.SymbolicRing): from sage.rings.real_lazy import RLF, CLF from sage.rings.finite_rings.finite_field_base import FiniteField - from .subring import GenericSymbolicSubring + from sage.symbolic.subring import GenericSymbolicSubring if R._is_numerical(): # Almost anything with a coercion into any precision of CC @@ -1133,7 +1133,7 @@ cdef class SymbolicRing(sage.rings.abc.SymbolicRing): """ if self is not SR: raise NotImplementedError('cannot create subring of %s' % (self,)) - from .subring import SymbolicSubring + from sage.symbolic.subring import SymbolicSubring return SymbolicSubring(*args, **kwds) def _fricas_init_(self): From 3e5470499656dd737dad317a9ca87fa452a1b79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 11 Nov 2023 09:38:41 +0100 Subject: [PATCH 069/155] use less _element_constructor --- .../multiset_partition_into_sets_ordered.py | 2 +- src/sage/combinat/posets/hasse_cython.pyx | 35 +++++++++++-------- .../finite_rings/hom_prime_finite_field.pyx | 4 +-- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/sage/combinat/multiset_partition_into_sets_ordered.py b/src/sage/combinat/multiset_partition_into_sets_ordered.py index a8855beb412..c544d9ae2ef 100755 --- a/src/sage/combinat/multiset_partition_into_sets_ordered.py +++ b/src/sage/combinat/multiset_partition_into_sets_ordered.py @@ -1699,7 +1699,7 @@ def _satisfies_constraints(self, x): .. NOTE:: This test will cause an infinite recursion with - ``self._element_constructor()`` if the ``__contains__`` + ``self._element_constructor_()`` if the ``__contains__`` method in ``OrderedMultisetPartitionsIntoSets_X`` is removed. TESTS:: diff --git a/src/sage/combinat/posets/hasse_cython.pyx b/src/sage/combinat/posets/hasse_cython.pyx index 8f7a869fc17..1aac8c7cb37 100644 --- a/src/sage/combinat/posets/hasse_cython.pyx +++ b/src/sage/combinat/posets/hasse_cython.pyx @@ -30,8 +30,8 @@ class IncreasingChains(RecursivelyEnumeratedSet_forest): - ``positions`` -- a list of sets of integers describing the poset, as given by the lazy attribute ``_leq_storage`` of Hasse diagrams. - - ``element_constructor`` -- used to determine the type of chains, - for example ``list`` or ``tuple`` + - ``constructor`` -- used to determine the type of chains, + for example :class:`list` or :class:`tuple` - ``exclude`` -- list of integers that should not belong to the chains @@ -50,7 +50,7 @@ class IncreasingChains(RecursivelyEnumeratedSet_forest): sage: list(D) [[], [0], [0, 1], [1]] """ - def __init__(self, list positions, element_constructor, + def __init__(self, list positions, constructor, list exclude, conversion=None): """ The enumerated set of increasing chains. @@ -71,7 +71,7 @@ class IncreasingChains(RecursivelyEnumeratedSet_forest): self._greater_than = positions self._vertices = list(range(n)) - self._element_constructor = element_constructor + self._constructor = constructor self._conversion = conversion if conversion is not None: self._from_poset = {elt: i for i, elt in enumerate(conversion)} @@ -92,8 +92,8 @@ class IncreasingChains(RecursivelyEnumeratedSet_forest): sage: from sage.combinat.posets.hasse_cython import IncreasingChains sage: D = IncreasingChains([{0,1},{1}], list, []) - sage: [x in D for x in D] - [True, True, True, True] + sage: all(x in D for x in D) + True sage: [2] in D False sage: [1,1] in D @@ -102,6 +102,13 @@ class IncreasingChains(RecursivelyEnumeratedSet_forest): sage: P = Poset({'a':['b'],'b':[]}) sage: ['a'] in P.chains() True + + TESTS:: + + sage: from sage.combinat.posets.hasse_cython import IncreasingChains + sage: D = IncreasingChains([{0,1},{1}], list, []) + sage: all(tuple(x) in D for x in D) + True """ cdef int k cdef Py_ssize_t i, x, y @@ -109,9 +116,8 @@ class IncreasingChains(RecursivelyEnumeratedSet_forest): return True if self._conversion is not None: tup = [self._from_poset[elt] for elt in tup] - for i in tup: - if not(0 <= i < self._n): - return False + if any(not(0 <= i < self._n) for i in tup): + return False y = tup[0] for k in range(1, len(tup)): x = y @@ -127,7 +133,7 @@ class IncreasingChains(RecursivelyEnumeratedSet_forest): If ``conversion`` was provided, it first converts elements of the chain to elements of this list. - Then the given ``element_constructor`` is applied to the chain. + Then the given ``constructor`` is applied to the chain. EXAMPLES:: @@ -142,8 +148,8 @@ class IncreasingChains(RecursivelyEnumeratedSet_forest): """ cdef Py_ssize_t i if self._conversion is not None: - return self._element_constructor(self._conversion[i] for i in chain) - return self._element_constructor(chain) + return self._constructor(self._conversion[i] for i in chain) + return self._constructor(chain) def children(self, chain): """ @@ -163,6 +169,5 @@ class IncreasingChains(RecursivelyEnumeratedSet_forest): cdef Py_ssize_t x, y if not chain: return [(x,) for x in self._vertices] - else: - x = chain[-1] - return [chain + (y,) for y in self._greater_than[x] if x != y] + x = chain[-1] + return [chain + (y,) for y in self._greater_than[x] if x != y] diff --git a/src/sage/rings/finite_rings/hom_prime_finite_field.pyx b/src/sage/rings/finite_rings/hom_prime_finite_field.pyx index 6bc38546612..9453493ee6d 100644 --- a/src/sage/rings/finite_rings/hom_prime_finite_field.pyx +++ b/src/sage/rings/finite_rings/hom_prime_finite_field.pyx @@ -37,7 +37,7 @@ from sage.rings.finite_rings.finite_field_base import FiniteField cdef class SectionFiniteFieldHomomorphism_prime(SectionFiniteFieldHomomorphism_generic): cpdef Element _call_(self, x) noexcept: try: - return self._codomain._element_constructor(x) + return self._codomain._element_constructor_(x) except TypeError: raise ValueError("%s is not in the image of %s" % (x, self._inverse)) @@ -89,7 +89,7 @@ cdef class FiniteFieldHomomorphism_prime(FiniteFieldHomomorphism_generic): sage: a.parent() Finite Field in t of size 3^5 """ - return self._codomain._element_constructor(x) + return self._codomain._element_constructor_(x) cdef class FrobeniusEndomorphism_prime(FrobeniusEndomorphism_finite_field): From 039039b0c2256fa61269c2b13232128d0a7a9bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 11 Nov 2023 10:35:51 +0100 Subject: [PATCH 070/155] some details in combinations --- src/sage/combinat/combination.py | 41 ++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/sage/combinat/combination.py b/src/sage/combinat/combination.py index 8561935b403..916ca836c6b 100644 --- a/src/sage/combinat/combination.py +++ b/src/sage/combinat/combination.py @@ -153,6 +153,13 @@ class of combinations of ``mset`` of size ``k``. TESTS: + Run the test suites:: + + sage: C = Combinations([2,3]) + sage: TestSuite(C).run() + sage: C = Combinations([2,3], 1) + sage: TestSuite(C).run() + We check that the code works even for non mutable objects:: sage: l = [vector((0,0)), vector((0,1))] # needs sage.modules @@ -199,7 +206,7 @@ def __init__(self, mset): self.mset = mset Parent.__init__(self, category=FiniteEnumeratedSets()) - def __contains__(self, x): + def __contains__(self, x) -> bool: """ EXAMPLES:: @@ -218,7 +225,7 @@ def __contains__(self, x): return all(i in self.mset for i in x) and len(set(x)) == len(x) - def __eq__(self, other): + def __eq__(self, other) -> bool: """ Test for equality. @@ -232,7 +239,7 @@ def __eq__(self, other): """ return isinstance(other, Combinations_mset) and self.mset == other.mset - def __ne__(self, other): + def __ne__(self, other) -> bool: """ Test for unequality. @@ -244,7 +251,7 @@ def __ne__(self, other): """ return not (self == other) - def __repr__(self): + def __repr__(self) -> str: """ TESTS:: @@ -263,7 +270,7 @@ def __iter__(self): for k in range(len(self.mset) + 1): yield from Combinations_msetk(self.mset, k) - def cardinality(self): + def cardinality(self) -> Integer: """ TESTS:: @@ -272,10 +279,8 @@ def cardinality(self): sage: Combinations(['a','a','b']).cardinality() # needs sage.libs.gap 6 """ - c = 0 - for k in range(len(self.mset) + 1): - c += Combinations_msetk(self.mset, k).cardinality() - return c + return ZZ.sum(Combinations_msetk(self.mset, k).cardinality() + for k in range(len(self.mset) + 1)) class Combinations_set(Combinations_mset): @@ -332,7 +337,7 @@ def cardinality(self): sage: Combinations(range(16000)).cardinality() == 2^16000 True """ - return 2**len(self.mset) + return ZZ(2)**len(self.mset) class Combinations_msetk(Parent): @@ -348,7 +353,7 @@ def __init__(self, mset, k): self.k = k Parent.__init__(self, category=FiniteEnumeratedSets()) - def __contains__(self, x): + def __contains__(self, x) -> bool: """ EXAMPLES:: @@ -370,7 +375,7 @@ def __contains__(self, x): return False return x in Combinations_mset(self.mset) and len(x) == self.k - def __eq__(self, other): + def __eq__(self, other) -> bool: """ Test for equality. @@ -385,7 +390,7 @@ def __eq__(self, other): return (isinstance(other, Combinations_msetk) and self.mset == other.mset and self.k == other.k) - def __ne__(self, other): + def __ne__(self, other) -> bool: """ Test for unequality. @@ -397,7 +402,7 @@ def __ne__(self, other): """ return not (self == other) - def __repr__(self): + def __repr__(self) -> str: """ TESTS:: @@ -422,7 +427,7 @@ def __iter__(self): yield sum([[self.mset[indices[i]]] * iv[i] for i in range(len(indices))], []) - def cardinality(self): + def cardinality(self) -> Integer: """ Return the size of combinations(mset, k). @@ -490,7 +495,7 @@ def __iter__(self): else: return self._iterator(self.mset, self.k) - def list(self): + def list(self) -> list: """ EXAMPLES:: @@ -529,7 +534,7 @@ def rank(self, x): x = [self.mset.index(i) for i in x] return rank(x, len(self.mset)) - def cardinality(self): + def cardinality(self) -> Integer: """ Return the size of combinations(set, k). @@ -538,7 +543,7 @@ def cardinality(self): sage: Combinations(range(16000), 5).cardinality() 8732673194560003200 """ - return binomial(len(self.mset), self.k) + return ZZ(binomial(len(self.mset), self.k)) def rank(comb, n, check=True): From 5a0a079a23b3a9cff0981e2da92341dce3f8215f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 11 Nov 2023 13:02:41 +0100 Subject: [PATCH 071/155] make modform rings for triangle groups use Algebras --- .../modform_hecketriangle/abstract_ring.py | 185 ++++++++---------- .../modform_hecketriangle/graded_ring.py | 57 +++--- 2 files changed, 108 insertions(+), 134 deletions(-) diff --git a/src/sage/modular/modform_hecketriangle/abstract_ring.py b/src/sage/modular/modform_hecketriangle/abstract_ring.py index f28917578af..705a05a7341 100644 --- a/src/sage/modular/modform_hecketriangle/abstract_ring.py +++ b/src/sage/modular/modform_hecketriangle/abstract_ring.py @@ -17,6 +17,7 @@ # **************************************************************************** from sage.algebras.free_algebra import FreeAlgebra + from sage.misc.cachefunc import cached_method from sage.rings.fraction_field import FractionField from sage.rings.infinity import infinity @@ -30,7 +31,6 @@ from .series_constructor import MFSeriesConstructor -# Maybe replace Parent by just SageObject? class FormsRing_abstract(Parent): r""" Abstract (Hecke) forms ring. @@ -82,18 +82,18 @@ def __init__(self, group, base_ring, red_hom, n): # from graded_ring import canonical_parameters # (group, base_ring, red_hom, n) = canonical_parameters(group, base_ring, red_hom, n) - # if (not group.is_arithmetic() and base_ring.characteristic()>0): + # if not group.is_arithmetic() and base_ring.characteristic()>0: # raise NotImplementedError - # if (base_ring.characteristic().divides(2*group.n()*(group.n()-2))): + # if base_ring.characteristic().divides(2*group.n()*(group.n()-2)): # raise NotImplementedError - if (base_ring.characteristic() > 0): + if base_ring.characteristic() > 0: raise NotImplementedError("only characteristic 0 is supported") self._group = group self._red_hom = red_hom self._base_ring = base_ring - self._coeff_ring = FractionField(PolynomialRing(base_ring,'d')) - self._pol_ring = PolynomialRing(base_ring,'x,y,z,d') + self._coeff_ring = FractionField(PolynomialRing(base_ring, 'd')) + self._pol_ring = PolynomialRing(base_ring, 'x,y,z,d') self._rat_field = FractionField(self._pol_ring) # default values @@ -105,8 +105,6 @@ def __init__(self, group, base_ring, red_hom, n): self.disp_prec(5) self.default_num_prec(53) - # super().__init__(self.coeff_ring()) - def _repr_(self): r""" Return the string representation of ``self``. @@ -167,14 +165,18 @@ def _element_constructor_(self, el): from .graded_ring_element import FormsRingElement if isinstance(el, FormsRingElement): - if (self.hecke_n() == infinity and el.hecke_n() == ZZ(3)): + if self.hecke_n() == infinity and el.hecke_n() == ZZ(3): el_f = el._reduce_d()._rat - (x,y,z,d) = self.pol_ring().gens() + x, y, z, d = self.pol_ring().gens() - num_sub = el_f.numerator().subs( x=(y**2 + 3*x)/ZZ(4), y=(9*x*y - y**3)/ZZ(8), z=(3*z - y)/ZZ(2)) - denom_sub = el_f.denominator().subs( x=(y**2 + 3*x)/ZZ(4), y=(9*x*y - y**3)/ZZ(8), z=(3*z - y)/ZZ(2)) - new_num = num_sub.numerator()*denom_sub.denominator() - new_denom = denom_sub.numerator()*num_sub.denominator() + num_sub = el_f.numerator().subs(x=(y**2 + 3*x)/ZZ(4), + y=(9*x*y - y**3)/ZZ(8), + z=(3*z - y)/ZZ(2)) + denom_sub = el_f.denominator().subs(x=(y**2 + 3*x)/ZZ(4), + y=(9*x*y - y**3)/ZZ(8), + z=(3*z - y)/ZZ(2)) + new_num = num_sub.numerator() * denom_sub.denominator() + new_denom = denom_sub.numerator() * num_sub.denominator() el = self._rat_field(new_num) / self._rat_field(new_denom) elif self.group() == el.group(): @@ -225,18 +227,16 @@ def _coerce_map_from_(self, S): from .space import FormsSpace_abstract from .functors import _common_subgroup if (isinstance(S, FormsRing_abstract) - and self._group == _common_subgroup(self._group, S._group) - and self._analytic_type >= S._analytic_type - and self.base_ring().has_coerce_map_from(S.base_ring())): - return True + and self._group == _common_subgroup(self._group, S._group) + and self._analytic_type >= S._analytic_type + and self.base_ring().has_coerce_map_from(S.base_ring())): + return True if isinstance(S, FormsRing_abstract): return False if isinstance(S, FormsSpace_abstract): raise RuntimeError("this case should not occur") # return self._coerce_map_from_(S.graded_ring()) - if (self.AT("holo") <= self._analytic_type) and (self.coeff_ring().has_coerce_map_from(S)): - return True - return False + return self.AT("holo") <= self._analytic_type and self.coeff_ring().has_coerce_map_from(S) def _an_element_(self): r""" @@ -289,8 +289,7 @@ def default_prec(self, prec=None): sage: MF.default_prec() 2 """ - - if (prec is not None): + if prec is not None: self._prec = ZZ(prec) else: return self._prec @@ -359,8 +358,7 @@ def default_num_prec(self, prec=None): sage: f_rho.q_expansion_fixed_d(prec=2)[1] 9.92593243510795915276017782... """ - - if (prec is not None): + if prec is not None: self._num_prec = ZZ(prec) else: return self._num_prec @@ -444,7 +442,7 @@ def extend_type(self, analytic_type=None, ring=False): else: analytic_type = self._analytic_type.extend_by(analytic_type) - if (ring or not self.is_homogeneous()): + if ring or not self.is_homogeneous(): return FormsRing(analytic_type, group=self.group(), base_ring=self.base_ring(), red_hom=self.has_reduce_hom()) else: return FormsSpace(analytic_type, group=self.group(), base_ring=self.base_ring(), k=self.weight(), ep=self.ep()) @@ -491,13 +489,13 @@ def reduce_type(self, analytic_type=None, degree=None): else: analytic_type = self._analytic_type.reduce_to(analytic_type) - if (degree is None and not self.is_homogeneous()): + if degree is None and not self.is_homogeneous(): return FormsRing(analytic_type, group=self.group(), base_ring=self.base_ring(), red_hom=self.has_reduce_hom()) - elif (degree is None): + elif degree is None: return FormsSpace(analytic_type, group=self.group(), base_ring=self.base_ring(), k=self.weight(), ep=self.ep()) else: (weight, ep) = degree - if (self.is_homogeneous() and (weight != self.weight() or ep != self.ep())): + if self.is_homogeneous() and (weight != self.weight() or ep != self.ep()): analytic_type = self._analytic_type.reduce_to([]) return FormsSpace(analytic_type, group=self.group(), base_ring=self.base_ring(), k=weight, ep=ep) @@ -696,19 +694,18 @@ def get_d(self, fix_d=False, d_num_prec=None): sage: ModularFormsRing(n=5).get_d(fix_d=1).parent() Integer Ring """ - if d_num_prec is None: d_num_prec = self.default_num_prec() else: d_num_prec = ZZ(d_num_prec) - if (fix_d is True): + if fix_d is True: d = self._group.dvalue() - if (self._group.is_arithmetic()): - d = 1 / self.base_ring()(1/d) + if self._group.is_arithmetic(): + d = ~self.base_ring()(~d) else: d = self.group().dvalue().n(d_num_prec) - elif (fix_d is False): + elif fix_d is False: d = FractionField(PolynomialRing(self.base_ring(), "d")).gen() else: d = fix_d @@ -760,9 +757,8 @@ def get_q(self, prec=None, fix_d=False, d_num_prec=None): sage: ModularFormsRing(n=5).get_q(fix_d=1).parent() Power Series Ring in q over Rational Field """ - d = self.get_d(fix_d, d_num_prec) - if (prec is None): + if prec is None: prec = self.default_prec() base_ring = d.parent() @@ -812,17 +808,16 @@ def _derivative_op(self): sage: ModularFormsRing(n=infinity)._derivative_op() -X*Y*dX + X*Z*dX + 1/2*Y*Z*dY + 1/4*Z^2*dZ - 1/2*X*dY - 1/4*X*dZ """ + (X, Y, Z, dX, dY, dZ) = self.diff_alg().gens() - (X,Y,Z,dX,dY,dZ) = self.diff_alg().gens() - - if (self.hecke_n() == infinity): + if self.hecke_n() == infinity: return (X*Z-X*Y) * dX\ - + ZZ(1)/ZZ(2) * (Y*Z-X) * dY\ - + ZZ(1)/ZZ(4) * (Z**2-X) * dZ - else: - return 1/self._group.n() * (X*Z-Y) * dX\ - + ZZ(1)/ZZ(2) * (Y*Z-X**(self._group.n()-1)) * dY\ - + (self._group.n()-2) / (4*self._group.n()) * (Z**2-X**(self._group.n()-2)) * dZ + + ZZ(1)/ZZ(2) * (Y*Z-X) * dY\ + + ZZ(1)/ZZ(4) * (Z**2-X) * dZ + + return 1/self._group.n() * (X*Z-Y) * dX\ + + ZZ(1)/ZZ(2) * (Y*Z-X**(self._group.n()-1)) * dY\ + + (self._group.n()-2) / (4*self._group.n()) * (Z**2-X**(self._group.n()-2)) * dZ @cached_method def _serre_derivative_op(self): @@ -839,17 +834,16 @@ def _serre_derivative_op(self): sage: ModularFormsRing(n=infinity)._serre_derivative_op() -X*Y*dX - 1/4*Z^2*dZ - 1/2*X*dY - 1/4*X*dZ """ + (X, Y, Z, dX, dY, dZ) = self.diff_alg().gens() - (X,Y,Z,dX,dY,dZ) = self.diff_alg().gens() - - if (self.hecke_n() == infinity): + if self.hecke_n() == infinity: return - X * Y * dX\ - - ZZ(1)/ZZ(2) * X * dY\ - - ZZ(1)/ZZ(4) * (Z**2+X) * dZ - else: - return - 1/self._group.n() * Y*dX\ - - ZZ(1)/ZZ(2) * X**(self._group.n()-1) * dY\ - - (self._group.n()-2) / (4*self._group.n()) * (Z**2+X**(self._group.n()-2)) * dZ + - ZZ(1)/ZZ(2) * X * dY\ + - ZZ(1)/ZZ(4) * (Z**2+X) * dZ + + return - 1/self._group.n() * Y*dX\ + - ZZ(1)/ZZ(2) * X**(self._group.n()-1) * dY\ + - (self._group.n()-2) / (4*self._group.n()) * (Z**2+X**(self._group.n()-2)) * dZ @cached_method def has_reduce_hom(self): @@ -1038,8 +1032,7 @@ def homogeneous_part(self, k, ep): sage: QuasiMeromorphicModularFormsRing(n=7).homogeneous_part(k=2, ep=-1) QuasiMeromorphicModularForms(n=7, k=2, ep=-1) over Integer Ring """ - - return self.reduce_type(degree=(k,ep)) + return self.reduce_type(degree=(k, ep)) @cached_method def J_inv(self): @@ -1098,10 +1091,9 @@ def J_inv(self): sage: WeakModularForms().J_inv() 1/1728*q^-1 + 31/72 + 1823/16*q + 335840/27*q^2 + 16005555/32*q^3 + 11716352*q^4 + O(q^5) """ + (x, y, z, d) = self._pol_ring.gens() - (x,y,z,d) = self._pol_ring.gens() - - if (self.hecke_n() == infinity): + if self.hecke_n() == infinity: return self.extend_type("weak", ring=True)(x/(x-y**2)).reduce() else: return self.extend_type("weak", ring=True)(x**self._group.n()/(x**self._group.n()-y**2)).reduce() @@ -1150,13 +1142,11 @@ def j_inv(self): sage: WeakModularForms().j_inv() q^-1 + 744 + 196884*q + 21493760*q^2 + 864299970*q^3 + 20245856256*q^4 + O(q^5) """ + (x, y, z, d) = self._pol_ring.gens() - (x,y,z,d) = self._pol_ring.gens() - - if (self.hecke_n() == infinity): + if self.hecke_n() == infinity: return self.extend_type("weak", ring=True)(1/d*x/(x-y**2)).reduce() - else: - return self.extend_type("weak", ring=True)(1/d*x**self._group.n()/(x**self._group.n()-y**2)).reduce() + return self.extend_type("weak", ring=True)(1/d*x**self._group.n()/(x**self._group.n()-y**2)).reduce() @cached_method def f_rho(self): @@ -1227,13 +1217,11 @@ def f_rho(self): sage: ModularForms(k=4).f_rho() 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + O(q^5) """ + (x, y, z, d) = self._pol_ring.gens() - (x,y,z,d) = self._pol_ring.gens() - - if (self.hecke_n() == infinity): + if self.hecke_n() == infinity: return self.extend_type("holo", ring=True)(1).reduce() - else: - return self.extend_type("holo", ring=True)(x).reduce() + return self.extend_type("holo", ring=True)(x).reduce() @cached_method def f_i(self): @@ -1295,8 +1283,7 @@ def f_i(self): sage: ModularForms(k=6).f_i() 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 + O(q^5) """ - - (x,y,z,d) = self._pol_ring.gens() + (x, y, z, d) = self._pol_ring.gens() return self.extend_type("holo", ring=True)(y).reduce() @@ -1365,13 +1352,11 @@ def f_inf(self): sage: CuspForms(k=12).f_inf() q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5) """ + (x, y, z, d) = self._pol_ring.gens() - (x,y,z,d) = self._pol_ring.gens() - - if (self.hecke_n() == infinity): + if self.hecke_n() == infinity: return self.extend_type("holo", ring=True)(d*(x-y**2)).reduce() - else: - return self.extend_type("cusp", ring=True)(d*(x**self._group.n()-y**2)).reduce() + return self.extend_type("cusp", ring=True)(d*(x**self._group.n()-y**2)).reduce() @cached_method def G_inv(self): @@ -1443,12 +1428,11 @@ def G_inv(self): ... ArithmeticError: G_inv doesn't exist for odd n(=9). """ + (x, y, z, d) = self._pol_ring.gens() - (x,y,z,d) = self._pol_ring.gens() - - if (self.hecke_n() == infinity): + if self.hecke_n() == infinity: raise ArithmeticError("G_inv doesn't exist for n={} (it is not meromorphic at -1).".format(self._group.n())) - elif (ZZ(2).divides(self._group.n())): + elif ZZ(2).divides(self._group.n()): return self.extend_type("weak", ring=True)(d*y*x**(self._group.n()/ZZ(2))/(x**self._group.n()-y**2)).reduce() else: raise ArithmeticError("G_inv doesn't exist for odd n(={}).".format(self._group.n())) @@ -1516,11 +1500,10 @@ def g_inv(self): ... ArithmeticError: g_inv doesn't exist for odd n(=9). """ - - if (self.hecke_n() == infinity): + if self.hecke_n() == infinity: raise ArithmeticError("g_inv doesn't exist for n={} (it is not meromorphic at -1).".format(self._group.n())) - if (ZZ(2).divides(self._group.n())): - (x,y,z,d) = self._pol_ring.gens() + if ZZ(2).divides(self._group.n()): + (x, y, z, d) = self._pol_ring.gens() return self.extend_type("weak", ring=True)(1/d*y*x**(self._group.n()/ZZ(2))/(x**self._group.n()-y**2)).reduce() else: raise ArithmeticError("g_inv doesn't exist for odd n(={}).".format(self._group.n())) @@ -1592,13 +1575,11 @@ def E4(self): sage: ModularForms(k=4).E4() 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + O(q^5) """ + (x, y, z, d) = self._pol_ring.gens() - (x,y,z,d) = self._pol_ring.gens() - - if (self.hecke_n() == infinity): + if self.hecke_n() == infinity: return self.extend_type("holo", ring=True)(x).reduce() - else: - return self.extend_type("holo", ring=True)(x**(self._group.n()-2)).reduce() + return self.extend_type("holo", ring=True)(x**(self._group.n()-2)).reduce() @cached_method def E6(self): @@ -1659,13 +1640,11 @@ def E6(self): sage: ModularForms(k=6).E6() 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 + O(q^5) """ + (x, y, z, d) = self._pol_ring.gens() - (x,y,z,d) = self._pol_ring.gens() - - if (self.hecke_n() == infinity): + if self.hecke_n() == infinity: return self.extend_type("holo", ring=True)(x*y).reduce() - else: - return self.extend_type("holo", ring=True)(x**(self._group.n()-3)*y).reduce() + return self.extend_type("holo", ring=True)(x**(self._group.n()-3)*y).reduce() @cached_method def Delta(self): @@ -1732,13 +1711,11 @@ def Delta(self): sage: CuspForms(k=12).Delta() q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5) """ + (x, y, z, d) = self._pol_ring.gens() - (x,y,z,d) = self._pol_ring.gens() - - if (self.hecke_n() == infinity): + if self.hecke_n() == infinity: return self.extend_type("cusp", ring=True)(d*x**2*(x-y**2)).reduce() - else: - return self.extend_type("cusp", ring=True)(d*x**(2*self._group.n()-6)*(x**self._group.n()-y**2)).reduce() + return self.extend_type("cusp", ring=True)(d*x**(2*self._group.n()-6)*(x**self._group.n()-y**2)).reduce() @cached_method def E2(self): @@ -1803,9 +1780,7 @@ def E2(self): sage: QuasiModularForms(k=2).E2() 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 + O(q^5) """ - - (x,y,z,d) = self._pol_ring.gens() - + (x, y, z, d) = self._pol_ring.gens() return self.extend_type(["holo", "quasi"], ring=True)(z).reduce() @cached_method @@ -1946,8 +1921,8 @@ def EisensteinSeries(self, k=None): # reduced_self is a classical ModularForms space reduced_self = extended_self.reduce_type(["holo"], degree=(QQ(k), ep)) - if (n == infinity): - l2 = ZZ(0) + if n == infinity: + l2 = ZZ.zero() l1 = ZZ((k-(1-ep)) / ZZ(4)) else: num = ZZ((k-(1-ep)*n/(n-2)) * (n-2) / ZZ(4)) @@ -1961,7 +1936,7 @@ def EisensteinSeries(self, k=None): # The non-arithmetic remaining cases (incomplete, very hard in general) # TODO: the n = infinity case(s) (doable) # TODO: the n = 5 case (hard) - if (not self.group().is_arithmetic() or n == infinity): + if not self.group().is_arithmetic() or n == infinity: raise NotImplementedError("Eisenstein series are only supported in the finite arithmetic cases") # The arithmetic cases diff --git a/src/sage/modular/modform_hecketriangle/graded_ring.py b/src/sage/modular/modform_hecketriangle/graded_ring.py index 624341c8dc7..81b64aa7f48 100644 --- a/src/sage/modular/modform_hecketriangle/graded_ring.py +++ b/src/sage/modular/modform_hecketriangle/graded_ring.py @@ -19,8 +19,8 @@ from sage.rings.integer_ring import ZZ from sage.rings.infinity import infinity -from sage.rings.ring import CommutativeAlgebra -from sage.categories.commutative_algebras import CommutativeAlgebras +from sage.structure.parent import Parent +from sage.categories.algebras import Algebras from sage.structure.unique_representation import UniqueRepresentation from .hecke_triangle_groups import HeckeTriangleGroup @@ -39,11 +39,10 @@ def canonical_parameters(group, base_ring, red_hom, n=None): sage: canonical_parameters(infinity, RR, 0) (Hecke triangle group for n = +Infinity, Real Field with 53 bits of precision, False, +Infinity) """ - - if not (n is None): + if n is not None: group = n - if (group == infinity): + if group == infinity: group = HeckeTriangleGroup(infinity) else: try: @@ -57,7 +56,7 @@ def canonical_parameters(group, base_ring, red_hom, n=None): return (group, base_ring, red_hom, n) -class QuasiMeromorphicModularFormsRing(FormsRing_abstract, CommutativeAlgebra, UniqueRepresentation): +class QuasiMeromorphicModularFormsRing(FormsRing_abstract, Parent, UniqueRepresentation): r""" Graded ring of (Hecke) quasi meromorphic modular forms for the given group and base ring. @@ -114,13 +113,13 @@ def __init__(self, group, base_ring, red_hom, n): sage: QuasiMeromorphicModularFormsRing(n=infinity) QuasiMeromorphicModularFormsRing(n=+Infinity) over Integer Ring """ - FormsRing_abstract.__init__(self, group=group, base_ring=base_ring, red_hom=red_hom, n=n) - CommutativeAlgebra.__init__(self, base_ring=base_ring, category=CommutativeAlgebras(base_ring)) + cat = Algebras(base_ring).Commutative() + Parent.__init__(self, category=cat) self._analytic_type = self.AT(["quasi", "mero"]) -class QuasiWeakModularFormsRing(FormsRing_abstract, CommutativeAlgebra, UniqueRepresentation): +class QuasiWeakModularFormsRing(FormsRing_abstract, UniqueRepresentation): r""" Graded ring of (Hecke) quasi weakly holomorphic modular forms for the given group and base ring. @@ -174,13 +173,13 @@ def __init__(self, group, base_ring, red_hom, n): sage: MR in MR.category() True """ - FormsRing_abstract.__init__(self, group=group, base_ring=base_ring, red_hom=red_hom, n=n) - CommutativeAlgebra.__init__(self, base_ring=base_ring, category=CommutativeAlgebras(base_ring)) + cat = Algebras(base_ring).Commutative() + Parent.__init__(self, category=cat) self._analytic_type = self.AT(["quasi", "weak"]) -class QuasiModularFormsRing(FormsRing_abstract, CommutativeAlgebra, UniqueRepresentation): +class QuasiModularFormsRing(FormsRing_abstract, UniqueRepresentation): r""" Graded ring of (Hecke) quasi modular forms for the given group and base ring @@ -234,13 +233,13 @@ def __init__(self, group, base_ring, red_hom, n): sage: MR in MR.category() True """ - FormsRing_abstract.__init__(self, group=group, base_ring=base_ring, red_hom=red_hom, n=n) - CommutativeAlgebra.__init__(self, base_ring=base_ring, category=CommutativeAlgebras(base_ring)) + cat = Algebras(base_ring).Commutative() + Parent.__init__(self, category=cat) self._analytic_type = self.AT(["quasi", "holo"]) -class QuasiCuspFormsRing(FormsRing_abstract, CommutativeAlgebra, UniqueRepresentation): +class QuasiCuspFormsRing(FormsRing_abstract, UniqueRepresentation): r""" Graded ring of (Hecke) quasi cusp forms for the given group and base ring. @@ -294,13 +293,13 @@ def __init__(self, group, base_ring, red_hom, n): sage: MR in MR.category() True """ - FormsRing_abstract.__init__(self, group=group, base_ring=base_ring, red_hom=red_hom, n=n) - CommutativeAlgebra.__init__(self, base_ring=base_ring, category=CommutativeAlgebras(base_ring)) + cat = Algebras(base_ring).Commutative() + Parent.__init__(self, category=cat) self._analytic_type = self.AT(["quasi", "cusp"]) -class MeromorphicModularFormsRing(FormsRing_abstract, CommutativeAlgebra, UniqueRepresentation): +class MeromorphicModularFormsRing(FormsRing_abstract, UniqueRepresentation): r""" Graded ring of (Hecke) meromorphic modular forms for the given group and base ring @@ -354,13 +353,13 @@ def __init__(self, group, base_ring, red_hom, n): sage: MR in MR.category() True """ - FormsRing_abstract.__init__(self, group=group, base_ring=base_ring, red_hom=red_hom, n=n) - CommutativeAlgebra.__init__(self, base_ring=base_ring, category=CommutativeAlgebras(base_ring)) + cat = Algebras(base_ring).Commutative() + Parent.__init__(self, category=cat) self._analytic_type = self.AT(["mero"]) -class WeakModularFormsRing(FormsRing_abstract, CommutativeAlgebra, UniqueRepresentation): +class WeakModularFormsRing(FormsRing_abstract, UniqueRepresentation): r""" Graded ring of (Hecke) weakly holomorphic modular forms for the given group and base ring @@ -414,13 +413,13 @@ def __init__(self, group, base_ring, red_hom, n): sage: MR in MR.category() True """ - FormsRing_abstract.__init__(self, group=group, base_ring=base_ring, red_hom=red_hom, n=n) - CommutativeAlgebra.__init__(self, base_ring=base_ring, category=CommutativeAlgebras(base_ring)) + cat = Algebras(base_ring).Commutative() + Parent.__init__(self, category=cat) self._analytic_type = self.AT(["weak"]) -class ModularFormsRing(FormsRing_abstract, CommutativeAlgebra, UniqueRepresentation): +class ModularFormsRing(FormsRing_abstract, UniqueRepresentation): r""" Graded ring of (Hecke) modular forms for the given group and base ring @@ -473,13 +472,13 @@ def __init__(self, group, base_ring, red_hom, n): sage: MR in MR.category() True """ - FormsRing_abstract.__init__(self, group=group, base_ring=base_ring, red_hom=red_hom, n=n) - CommutativeAlgebra.__init__(self, base_ring=base_ring, category=CommutativeAlgebras(base_ring)) + cat = Algebras(base_ring).Commutative() + Parent.__init__(self, category=cat) self._analytic_type = self.AT(["holo"]) -class CuspFormsRing(FormsRing_abstract, CommutativeAlgebra, UniqueRepresentation): +class CuspFormsRing(FormsRing_abstract, UniqueRepresentation): r""" Graded ring of (Hecke) cusp forms for the given group and base ring @@ -536,7 +535,7 @@ def __init__(self, group, base_ring, red_hom, n): sage: CuspFormsRing(n=infinity, base_ring=CC, red_hom=True) CuspFormsRing(n=+Infinity) over Complex Field with 53 bits of precision """ - FormsRing_abstract.__init__(self, group=group, base_ring=base_ring, red_hom=red_hom, n=n) - CommutativeAlgebra.__init__(self, base_ring=base_ring, category=CommutativeAlgebras(base_ring)) + cat = Algebras(base_ring).Commutative() + Parent.__init__(self, category=cat) self._analytic_type = self.AT(["cusp"]) From 7c0b6889aeb1f1de4c0000382df0895186994db3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 11 Nov 2023 13:58:21 +0100 Subject: [PATCH 072/155] convert Tate algebra to use Parent and category --- src/sage/rings/tate_algebra.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/sage/rings/tate_algebra.py b/src/sage/rings/tate_algebra.py index 993f1a95aa1..839d0e05b18 100644 --- a/src/sage/rings/tate_algebra.py +++ b/src/sage/rings/tate_algebra.py @@ -132,12 +132,12 @@ from sage.structure.factory import UniqueFactory from sage.structure.unique_representation import UniqueRepresentation from sage.monoids.monoid import Monoid_class -from sage.rings.ring import CommutativeAlgebra +from sage.categories.algebras import Algebras +from sage.structure.parent import Parent from sage.rings.integer_ring import ZZ from sage.rings.padics.padic_generic import pAdicGeneric from sage.misc.misc_c import prod -from sage.categories.commutative_algebras import CommutativeAlgebras from sage.categories.pushout import pushout from sage.structure.category_object import normalize_names @@ -481,7 +481,6 @@ def _coerce_map_from_(self, R): False sage: U.has_coerce_map_from(T) # indirect doctest False - """ base = self._base if base.has_coerce_map_from(R): @@ -686,7 +685,7 @@ def some_elements(self): # Tate algebras ############### -class TateAlgebra_generic(CommutativeAlgebra): +class TateAlgebra_generic(Parent): def __init__(self, field, prec, log_radii, names, order, integral=False): """ Initialize the Tate algebra @@ -708,7 +707,7 @@ def __init__(self, field, prec, log_radii, names, order, integral=False): self._cap = prec self._log_radii = ETuple(log_radii) # TODO: allow log_radii in QQ self._names = names - self._latex_names = [ latex_variable_name(var) for var in names ] + self._latex_names = [latex_variable_name(var) for var in names] uniformizer = field.change(print_mode='terse', show_prec=False).uniformizer() self._uniformizer_repr = uniformizer._repr_() self._uniformizer_latex = uniformizer._latex_() @@ -719,17 +718,19 @@ def __init__(self, field, prec, log_radii, names, order, integral=False): base = field.integer_ring() else: base = field - CommutativeAlgebra.__init__(self, base, names, category=CommutativeAlgebras(base)) + Parent.__init__(self, base=base, names=names, + category=Algebras(base).Commutative()) self._polynomial_ring = _multi_variate(field, names, order=order) - one = field(1) + one = field.one() self._parent_terms = TateTermMonoid(self) self._oneterm = self._parent_terms(one, ETuple([0]*self._ngens)) if integral: # This needs to be update if log_radii are allowed to be non-integral - self._gens = [ self((one << log_radii[i]) * self._polynomial_ring.gen(i)) for i in range(self._ngens) ] + self._gens = [self.element_class(self, (one << log_radii[i]) * self._polynomial_ring.gen(i)) for i in range(self._ngens)] self._integer_ring = self else: - self._gens = [ self(g) for g in self._polynomial_ring.gens() ] + self._gens = [self.element_class(self, g) + for g in self._polynomial_ring.gens()] self._integer_ring = TateAlgebra_generic(field, prec, log_radii, names, order, integral=True) self._integer_ring._rational_ring = self._rational_ring = self @@ -1265,14 +1266,13 @@ def random_element(self, degree=2, terms=5, integral=False, prec=None): sage: B. = TateAlgebra(R, log_radii=[-1,-2]) sage: B.random_element(integral=True) # random (...1111111.001)*x*y + (...111000101.1)*x + (...11010111.01)*y^2 + ...0010011011*y + ...0010100011000 - """ if integral or self._integral: polring = self._polynomial_ring.change_ring(self._field.integer_ring()) gens = self._integer_ring._gens else: polring = self._polynomial_ring - gens = [ self.element_class(self, g) for g in self._integer_ring._gens ] + gens = [self.element_class(self, g) for g in self._integer_ring._gens] return self.element_class(self, polring.random_element(degree, terms)(*gens), prec) def is_integral_domain(self, proof=True): From 0fa05ea2d0c229939fc6e470c970d8ec230a0242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 12 Nov 2023 13:20:29 +0100 Subject: [PATCH 073/155] get rid of coerce_try --- .../coercion_and_categories.rst | 1 - src/sage/structure/parent_old.pyx | 25 ------------------- 2 files changed, 26 deletions(-) diff --git a/src/doc/en/thematic_tutorials/coercion_and_categories.rst b/src/doc/en/thematic_tutorials/coercion_and_categories.rst index 7f5712caea7..1c1d7c85b5f 100644 --- a/src/doc/en/thematic_tutorials/coercion_and_categories.rst +++ b/src/doc/en/thematic_tutorials/coercion_and_categories.rst @@ -114,7 +114,6 @@ This base class provides a lot more methods than a general parent:: '_coerce_', '_coerce_c', '_coerce_impl', - '_coerce_try', '_default_category', '_gens', '_ideal_class_', diff --git a/src/sage/structure/parent_old.pyx b/src/sage/structure/parent_old.pyx index c093febf375..03aac94b0fe 100644 --- a/src/sage/structure/parent_old.pyx +++ b/src/sage/structure/parent_old.pyx @@ -216,31 +216,6 @@ cdef class Parent(parent.Parent): check_old_coerce(self) return self._coerce_c_impl(x) - def _coerce_try(self, x, v): - """ - Given a list v of rings, try to coerce x canonically into each - one in turn. Return the __call__ coercion of the result into - self of the first canonical coercion that succeeds. Raise a - :class:`TypeError` if none of them succeed. - - INPUT: - - - x -- Python object - - v -- parent object or list (iterator) of parent objects - """ - deprecation(33464, "usage of _coerce_try is deprecated") - check_old_coerce(self) - if not isinstance(v, list): - v = [v] - - for R in v: - try: - y = R._coerce_(x) - return self(y) - except (TypeError, AttributeError) as msg: - pass - raise TypeError("no canonical coercion of element into self") - cdef __has_coerce_map_from_c(self, S) noexcept: check_old_coerce(self) if self == S: From 268b0860a939223ced794edefca76467989fe44c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 9 Nov 2023 09:32:05 -0800 Subject: [PATCH 074/155] .ci/merge-fixes.sh: Obtain patches via URL --- .ci/merge-fixes.sh | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/.ci/merge-fixes.sh b/.ci/merge-fixes.sh index 8ee138660ec..065cfe18c1a 100755 --- a/.ci/merge-fixes.sh +++ b/.ci/merge-fixes.sh @@ -2,7 +2,9 @@ # Merge open PRs from sagemath/sage labeled "blocker". REPO="sagemath/sage" GH="gh -R $REPO" -PRs="$($GH pr list --label "p: blocker / 1" --json number --jq '.[].number')" +mkdir -p upstream +PRs="$($GH pr list --label "p: blocker / 1" --json number --jq '.[].number' | tee upstream/ci-fixes.txt)" +date -u +"%Y-%m-%dT%H:%M:%SZ" > upstream/ci-fixes.date # Record the date, for future reference if [ -z "$PRs" ]; then echo 'Nothing to do: Found no open PRs with "blocker" status.' else @@ -14,22 +16,38 @@ else git tag -f test_base git commit -q -m "Uncommitted changes" --no-allow-empty -a for a in $PRs; do - git fetch --unshallow --all > /dev/null 2>&1 && echo "Unshallowed." - echo "::group::Merging PR https://github.com/$REPO/pull/$a" + echo "::group::Applying PR https://github.com/$REPO/pull/$a as a patch" git tag -f test_head - $GH pr checkout -b pr-$a $a - git checkout -q test_head - if git merge --no-edit --squash -q pr-$a; then + # We used to pull the branch and merge it (after unshallowing), but when run on PRs that are + # based on older releases, it has the side effect of updating to this release, + # which may be confusing. + # + # Here, we obtain the "git am"-able patch of the PR branch. + # This also makes it unnecessary to unshallow the repository. + # + # Considered alternative: Use https://github.com/$REPO/pull/$a.diff, + # which squashes everything into one diff without commit metadata. + PATH=build/bin:$PATH build/bin/sage-download-file "https://github.com/$REPO/pull/$a.patch" upstream/$a.patch + date -u +"%Y-%m-%dT%H:%M:%SZ" > upstream/$a.date # Record the date, for future reference + if git am --empty=keep < upstream/$a.patch; then + echo "Applied patch" + cat upstream/$a.patch echo "::endgroup::" - if git commit -q -m "Merge https://github.com/$REPO/pull/$a" -a --no-allow-empty; then - echo "Merged #$a" - else - echo "Empty, skipped" - fi + echo "Applied #$a as a patch" + elif git am --abort \ + && if git fetch --unshallow --all > /dev/null 2>&1; then echo "Unshallowed"; fi \ + && echo "Retrying with 3-way merge" \ + && git am --empty=keep --3way < upstream/$a.patch; then + echo "Applied patch" + cat upstream/$a.patch + echo "::endgroup::" + echo "Applied #$a as a patch" else + echo "Failure applying patch" + git am --show-current-patch=diff echo "::endgroup::" - echo "Failure merging #$a, resetting" - git reset --hard + echo "Failure applying #$a as a patch, resetting" + git am --abort fi done git log test_base..HEAD From 35cdbd0727a9bd0e4892785642c70001044ade72 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Nov 2023 16:18:29 -0800 Subject: [PATCH 075/155] .ci/merge-fixes.sh: Include commit URLs in console log and commit messages --- .ci/merge-fixes.sh | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.ci/merge-fixes.sh b/.ci/merge-fixes.sh index 065cfe18c1a..abd1ccad2a3 100755 --- a/.ci/merge-fixes.sh +++ b/.ci/merge-fixes.sh @@ -16,7 +16,6 @@ else git tag -f test_base git commit -q -m "Uncommitted changes" --no-allow-empty -a for a in $PRs; do - echo "::group::Applying PR https://github.com/$REPO/pull/$a as a patch" git tag -f test_head # We used to pull the branch and merge it (after unshallowing), but when run on PRs that are # based on older releases, it has the side effect of updating to this release, @@ -29,26 +28,30 @@ else # which squashes everything into one diff without commit metadata. PATH=build/bin:$PATH build/bin/sage-download-file "https://github.com/$REPO/pull/$a.patch" upstream/$a.patch date -u +"%Y-%m-%dT%H:%M:%SZ" > upstream/$a.date # Record the date, for future reference - if git am --empty=keep < upstream/$a.patch; then - echo "Applied patch" + LAST_SHA=$(sed -n -E '/^From [0-9a-f]{40}/s/^From ([0-9a-f]{40}).*/\1/p' upstream/$a.patch | tail -n 1) + echo "::group::Applying PR https://github.com/$REPO/pull/$a @ https://github.com/$REPO/commit/$LAST_SHA as a patch" + export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME applying https://github.com/$REPO/pull/$a @ https://github.com/$REPO/commit/$LAST_SHA" + if git am --signoff --empty=keep < upstream/$a.patch; then + echo "---- Applied patch ------------------------------------------------------------" cat upstream/$a.patch + echo "--------------------------------------------------------------------8<---------" echo "::endgroup::" - echo "Applied #$a as a patch" elif git am --abort \ && if git fetch --unshallow --all > /dev/null 2>&1; then echo "Unshallowed"; fi \ && echo "Retrying with 3-way merge" \ && git am --empty=keep --3way < upstream/$a.patch; then - echo "Applied patch" + echo "---- Applied patch ------------------------------------------------------------" cat upstream/$a.patch + echo "--------------------------------------------------------------------8<---------" echo "::endgroup::" - echo "Applied #$a as a patch" else - echo "Failure applying patch" - git am --show-current-patch=diff + echo "---- Failure applying patch ---------------------------------------------------" + git am --signoff --show-current-patch=diff + echo "--------------------------------------------------------------------8<---------" echo "::endgroup::" echo "Failure applying #$a as a patch, resetting" - git am --abort + git am --signoff --abort fi done - git log test_base..HEAD + #git log test_base..HEAD fi From 5ac6d130a3930df8460050eb5c7d6dc8424cc5ff Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 10 Nov 2023 15:21:35 -0800 Subject: [PATCH 076/155] .github/workflows/ci-linux-incremental.yml: Set max_parallel = 8, reduce platforms tested with standard-sitepackages --- .github/workflows/ci-linux-incremental.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci-linux-incremental.yml b/.github/workflows/ci-linux-incremental.yml index 7887597845c..74bf9611f0a 100644 --- a/.github/workflows/ci-linux-incremental.yml +++ b/.github/workflows/ci-linux-incremental.yml @@ -98,6 +98,7 @@ jobs: ["standard", "minimal"] docker_push_repository: ghcr.io/${{ github.repository }}/ + max_parallel: 8 site: needs: [changed_files] @@ -120,16 +121,10 @@ jobs: docker_targets: "with-targets" targets: "${{needs.changed_files.outputs.uninstall_targets}} ${{needs.changed_files.outputs.build_targets}} build doc-html ptest" # Only test systems with a usable system python (>= 3.9) + # with only a small number of test failures as of 10.2.rc0 tox_system_factors: >- - ["ubuntu-jammy", - "ubuntu-mantic", - "debian-bullseye", - "debian-bookworm", - "fedora-33", - "fedora-38", - "gentoo-python3.11", - "archlinux", - "debian-bullseye-i386"] + ["gentoo-python3.11", + "archlinux"] tox_packages_factors: >- ["standard-sitepackages"] docker_push_repository: ghcr.io/${{ github.repository }}/ From 9dac7295709a05dadb7b3c86b129c50444cc0605 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 12 Nov 2023 16:47:07 -0800 Subject: [PATCH 077/155] .ci/merge-fixes.sh: Use https://github.com/$REPO/commits/$LAST_SHA --- .ci/merge-fixes.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/merge-fixes.sh b/.ci/merge-fixes.sh index abd1ccad2a3..28785381673 100755 --- a/.ci/merge-fixes.sh +++ b/.ci/merge-fixes.sh @@ -29,8 +29,8 @@ else PATH=build/bin:$PATH build/bin/sage-download-file "https://github.com/$REPO/pull/$a.patch" upstream/$a.patch date -u +"%Y-%m-%dT%H:%M:%SZ" > upstream/$a.date # Record the date, for future reference LAST_SHA=$(sed -n -E '/^From [0-9a-f]{40}/s/^From ([0-9a-f]{40}).*/\1/p' upstream/$a.patch | tail -n 1) - echo "::group::Applying PR https://github.com/$REPO/pull/$a @ https://github.com/$REPO/commit/$LAST_SHA as a patch" - export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME applying https://github.com/$REPO/pull/$a @ https://github.com/$REPO/commit/$LAST_SHA" + echo "::group::Applying PR https://github.com/$REPO/pull/$a @ https://github.com/$REPO/commits/$LAST_SHA as a patch" + export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME applying https://github.com/$REPO/pull/$a @ https://github.com/$REPO/commits/$LAST_SHA" if git am --signoff --empty=keep < upstream/$a.patch; then echo "---- Applied patch ------------------------------------------------------------" cat upstream/$a.patch From f4a7f2692e7edab5a95dd90c1da2d5c18fd81d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 13 Nov 2023 09:10:52 +0100 Subject: [PATCH 078/155] change back the argument to element_constructor --- src/sage/combinat/posets/hasse_cython.pyx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/posets/hasse_cython.pyx b/src/sage/combinat/posets/hasse_cython.pyx index 1aac8c7cb37..2048febd192 100644 --- a/src/sage/combinat/posets/hasse_cython.pyx +++ b/src/sage/combinat/posets/hasse_cython.pyx @@ -30,7 +30,7 @@ class IncreasingChains(RecursivelyEnumeratedSet_forest): - ``positions`` -- a list of sets of integers describing the poset, as given by the lazy attribute ``_leq_storage`` of Hasse diagrams. - - ``constructor`` -- used to determine the type of chains, + - ``element_constructor`` -- used to determine the type of chains, for example :class:`list` or :class:`tuple` - ``exclude`` -- list of integers that should not belong to the chains @@ -50,7 +50,7 @@ class IncreasingChains(RecursivelyEnumeratedSet_forest): sage: list(D) [[], [0], [0, 1], [1]] """ - def __init__(self, list positions, constructor, + def __init__(self, list positions, element_constructor, list exclude, conversion=None): """ The enumerated set of increasing chains. @@ -71,7 +71,7 @@ class IncreasingChains(RecursivelyEnumeratedSet_forest): self._greater_than = positions self._vertices = list(range(n)) - self._constructor = constructor + self._constructor = element_constructor self._conversion = conversion if conversion is not None: self._from_poset = {elt: i for i, elt in enumerate(conversion)} @@ -133,7 +133,7 @@ class IncreasingChains(RecursivelyEnumeratedSet_forest): If ``conversion`` was provided, it first converts elements of the chain to elements of this list. - Then the given ``constructor`` is applied to the chain. + Then the given ``element_constructor`` is applied to the chain. EXAMPLES:: From 6b39c6899d8149df3562a3ab995c20263df93b1a Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Mon, 13 Nov 2023 20:02:18 +0900 Subject: [PATCH 079/155] Include pdf docs to live doc --- .github/workflows/doc-build-pdf.yml | 1 - .github/workflows/doc-build.yml | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/doc-build-pdf.yml b/.github/workflows/doc-build-pdf.yml index 1d14d0c29f7..e21aff9b961 100644 --- a/.github/workflows/doc-build-pdf.yml +++ b/.github/workflows/doc-build-pdf.yml @@ -58,7 +58,6 @@ jobs: eval $(sage-print-system-package-command auto --yes --no-install-recommends install zip) eval $(sage-print-system-package-command auto --spkg --yes --no-install-recommends install git texlive) - - name: Add prebuilt tree as a worktree id: worktree run: | diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 3660ff3a947..d9ecb201147 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -202,11 +202,15 @@ jobs: if: (success() || failure()) && steps.copy.outcome == 'success' && github.repository == 'sagemath/sage' && github.ref == 'refs/heads/develop' run: | set -ex + export PATH="build/bin:$PATH" + eval $(sage-print-system-package-command auto update) + eval $(sage-print-system-package-command auto --yes --no-install-recommends install zip) + eval $(sage-print-system-package-command auto --spkg --yes --no-install-recommends install git texlive) export SAGE_USE_CDNS=yes export SAGE_LIVE_DOC=yes export SAGE_JUPYTER_SERVER=binder:sagemath/sage-binder-env/dev make doc-clean doc-uninstall - ./config.status && make sagemath_doc_html-no-deps + ./config.status && make sagemath_doc_html-no-deps sagemath_doc_pdf-no-deps working-directory: ./worktree-image env: MAKE: make -j2 --output-sync=recurse @@ -219,6 +223,7 @@ jobs: set -ex mkdir -p ./livedoc cp -r -L /sage/local/share/doc/sage/html ./livedoc + cp -r -L /sage/local/share/doc/sage/pdf ./livedoc cp /sage/local/share/doc/sage/index.html ./livedoc zip -r livedoc.zip livedoc From 2579692b04ebbbd425ca1fe98f35015270f5e85a Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Mon, 13 Nov 2023 12:07:50 +0100 Subject: [PATCH 080/155] Address reviewer's comments --- src/sage/categories/simplicial_sets.py | 41 +++--- .../rings/polynomial/laurent_polynomial.pyx | 138 +++++++++--------- .../polynomial/laurent_polynomial_mpair.pyx | 71 ++++----- 3 files changed, 125 insertions(+), 125 deletions(-) diff --git a/src/sage/categories/simplicial_sets.py b/src/sage/categories/simplicial_sets.py index 72dd3b6220c..3b71c4b9dd4 100644 --- a/src/sage/categories/simplicial_sets.py +++ b/src/sage/categories/simplicial_sets.py @@ -17,7 +17,6 @@ from sage.categories.sets_cat import Sets from sage.categories.homsets import HomsetsCategory from sage.matrix.constructor import matrix -from sage.misc.flatten import flatten from sage.misc.misc_c import prod from sage.rings.infinity import Infinity from sage.rings.integer import Integer @@ -393,7 +392,7 @@ def _universal_cover_dict(self): z[i] = FG.one() rels.append(z[0]*z[1].inverse()*z[2]) G = FG.quotient(rels) - char = {g : G.gen(i) for i,g in enumerate(gens)} + char = {g: G.gen(i) for i, g in enumerate(gens)} for e in edges: if e not in gens: char[e] = G.one() @@ -514,7 +513,7 @@ def covering_map(self, character): grelems.append(cells_dict[(f.nondegenerate(), g)].apply_degeneracies(*f.degeneracies())) faces_dict[cell] = grelems cover = SimplicialSet(faces_dict, base_point=cells_dict[(self.base_point(), G.one())]) - cover_map_data = {c : s[0] for (s,c) in cells_dict.items()} + cover_map_data = {c: s[0] for (s, c) in cells_dict.items()} return SimplicialSetMorphism(data=cover_map_data, domain=cover, codomain=self) def cover(self, character): @@ -607,7 +606,6 @@ def _canonical_twisting_operator(self): Quotient of Univariate Laurent Polynomial Ring in F1 over Integer Ring by the ideal (-1 + F1^2) """ - from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing G, d = self._universal_cover_dict() phi = G.abelianization_map() abelG, R, I, images = G.abelianization_to_algebra(ZZ) @@ -618,8 +616,8 @@ def _canonical_twisting_operator(self): return res def twisted_chain_complex(self, twisting_operator=None, dimensions=None, augmented=False, - cochain=False, verbose=False, subcomplex=None, - check=False): + cochain=False, verbose=False, subcomplex=None, + check=False): r""" Return the normalized chain complex twisted by some operator. @@ -629,31 +627,31 @@ def twisted_chain_complex(self, twisting_operator=None, dimensions=None, augment INPUT: - ``twisting_operator`` -- a dictionary, associating the twist of each - simplex. If it is not given, the canonical one (associated to the - laurent polynomial ring abelianization of the fundamental group, ignoring - torsion) is used. + simplex. If it is not given, the canonical one (associated to the + laurent polynomial ring abelianization of the fundamental group, ignoring + torsion) is used. - ``dimensions`` -- if ``None``, compute the chain complex in all - dimensions. If a list or tuple of integers, compute the - chain complex in those dimensions, setting the chain groups - in all other dimensions to zero. + dimensions. If a list or tuple of integers, compute the + chain complex in those dimensions, setting the chain groups + in all other dimensions to zero. - ``augmented`` (optional, default ``False``) -- if ``True``, - return the augmented chain complex (that is, include a class - in dimension `-1` corresponding to the empty cell). + return the augmented chain complex (that is, include a class + in dimension `-1` corresponding to the empty cell). - ``cochain`` (optional, default ``False``) -- if ``True``, - return the cochain complex (that is, the dual of the chain - complex). + return the cochain complex (that is, the dual of the chain + complex). - ``verbose`` (optional, default ``False``) -- ignored. - ``subcomplex`` (optional, default ``None``) -- if present, - compute the chain complex relative to this subcomplex. + compute the chain complex relative to this subcomplex. - ``check`` (optional, default ``False``) -- If ``True``, make - sure that the chain complex is actually a chain complex: - the differentials are composable and their product is zero. + sure that the chain complex is actually a chain complex: + the differentials are composable and their product is zero. The normalized chain complex of a simplicial set is isomorphic to the chain complex obtained by modding out by degenerate @@ -768,7 +766,7 @@ def twist(s): if augmented and first == 0: differentials[first-1] = matrix(base_ring, 0, 1) differentials[first] = matrix(base_ring, 1, rank, - [1] * rank) + [1] * rank) else: differentials[first] = matrix(base_ring, 0, rank) @@ -800,7 +798,7 @@ def twist(s): sign *= -1 differentials[d] = matrix(base_ring, old_rank, - rank, matrix_data) + rank, matrix_data) else: rank = 0 @@ -884,6 +882,7 @@ def twisted_homology(self, n, reduced=False): CC = self.twisted_chain_complex() M1 = CC.differential(n).T M2 = CC.differential(n + 1).T + def convert_to_polynomial(p): if hasattr(p, "lift"): return p.lift()._as_extended_polynomial() diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index b61fb1024c3..9dfdc174a36 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -320,6 +320,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): William Stein, David Joyner, and Robert Bradshaw - Travis Scrimshaw (09-2013): Cleaned-up and added a few extra methods """ + def __init__(self, parent, f, n=0): r""" Create the Laurent polynomial `t^n \cdot f`. @@ -351,15 +352,15 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): CommutativeAlgebraElement.__init__(self, parent) if isinstance(f, LaurentPolynomial_univariate): - n += (f).__n - if (f).__u._parent is parent._R: - f = (f).__u + n += ( < LaurentPolynomial_univariate > f).__n + if ( < LaurentPolynomial_univariate > f).__u._parent is parent._R: + f = ( < LaurentPolynomial_univariate > f).__u else: - f = parent._R((f).__u) + f = parent._R(( < LaurentPolynomial_univariate > f).__u) elif (not isinstance(f, Polynomial)) or (parent is not f.parent()): if isinstance(f, dict): v = min(f) if f else 0 - f = {i-v: c for i,c in f.items()} + f = {i-v: c for i, c in f.items()} n += v f = parent._R(f) @@ -555,7 +556,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): self.__n = 0 return # we already caught the infinity and zero cases - cdef long v = self.__u.valuation() + cdef long v = self.__u.valuation() self.__n += v self.__u = self.__u >> v @@ -592,11 +593,11 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): elif e == 0: var = "" else: - var = "*{}^{}".format(X,e) - s += "{}{}".format(x,var) + var = "*{}^{}".format(X, e) + s += "{}{}".format(x, var) first = False s = s.replace(" + -", " - ") - s = s.replace(" 1*"," ") + s = s.replace(" 1*", " ") s = s.replace(" -1*", " -") return s[1:] @@ -653,19 +654,19 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): elif e == 0: var = "" elif e > 0: - var = "|{}^{{{}}}".format(X,e) + var = "|{}^{{{}}}".format(X, e) if e >= 0: - s += "{}{}".format(x,var) - else: # negative e + s += "{}{}".format(x, var) + else: # negative e if e == -1: s += "\\frac{{{}}}{{{}}}".format(x, X) else: - s += "\\frac{{{}}}{{{}^{{{}}}}}".format(x, X,-e) + s += "\\frac{{{}}}{{{}^{{{}}}}}".format(x, X, -e) first = False s = s.replace(" + -", " - ") - s = s.replace(" 1|"," ") + s = s.replace(" 1|", " ") s = s.replace(" -1|", " -") - s = s.replace("|","") + s = s.replace("|", "") return s[1:] @@ -701,7 +702,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): # degrees cdef long result = 0 cdef long result_mon - cdef int i,j + cdef int i, j cdef long var_hash_name = hash(self.__u._parent._names[0]) for i in range(self.__u.degree()+1): result_mon = hash(self.__u[i]) @@ -760,7 +761,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): self.__u[start:stop:step] # error out, see issue #18940 stop = stop - self.__n if stop is not None else self.__u.degree() + 1 f = self.__u[:stop] - ret = self._new_c() + ret = self._new_c() ret.__u = f ret.__n = self.__n ret._normalize() @@ -913,11 +914,11 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): j = i - self.__n if j >= 0: self.__u._unsafe_mutate(j, value) - else: # off to the left + else: # off to the left if value != 0: self.__n = self.__n + j R = self._parent.base_ring() - coeffs = [value] + [R.zero() for _ in range(1,-j)] + self.__u.list() + coeffs = [value] + [R.zero() for _ in range(1, -j)] + self.__u.list() self.__u = self.__u._parent(coeffs) self._normalize() @@ -945,7 +946,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): ALGORITHM: Shift the unit parts to align them, then add. """ - cdef LaurentPolynomial_univariate right = right_m + cdef LaurentPolynomial_univariate right = right_m cdef long m cdef LaurentPolynomial_univariate ret @@ -969,8 +970,8 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): f1 = self.__u f2 = right.__u # 3. Add - ret = self._new_c() - ret.__u = (f1 + f2) + ret = self._new_c() + ret.__u = (f1 + f2) ret.__n = m ret._normalize() return ret @@ -989,7 +990,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): ALGORITHM: Shift the unit parts to align them, then subtract. """ - cdef LaurentPolynomial_univariate right = right_m + cdef LaurentPolynomial_univariate right = right_m cdef long m cdef LaurentPolynomial_univariate ret @@ -1009,8 +1010,8 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): f1 = self.__u << self.__n - m f2 = right.__u # 3. Subtract - ret = self._new_c() - ret.__u = (f1 - f2) + ret = self._new_c() + ret.__u = (f1 - f2) ret.__n = m ret._normalize() return ret @@ -1042,8 +1043,8 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): -1 - t^5 """ cdef LaurentPolynomial_univariate ret - ret = self._new_c() - ret.__u = -self.__u + ret = self._new_c() + ret.__u = -self.__u ret.__n = self.__n # No need to normalize return ret @@ -1058,10 +1059,10 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): sage: f*g x^-3 + x^-2 + x^-1 + x^8 """ - cdef LaurentPolynomial_univariate right = right_r + cdef LaurentPolynomial_univariate right = right_r cdef LaurentPolynomial_univariate ret - ret = self._new_c() - ret.__u = (self.__u * right.__u) + ret = self._new_c() + ret.__u = (self.__u * right.__u) ret.__n = self.__n + right.__n ret._normalize() return ret @@ -1076,8 +1077,8 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): 3*x^-3 + 3*x + 3*x^2 + 9*x^4 """ cdef LaurentPolynomial_univariate ret - ret = self._new_c() - ret.__u = self.__u._rmul_(c) + ret = self._new_c() + ret.__u = self.__u._rmul_(c) ret.__n = self.__n ret._normalize() return ret @@ -1092,8 +1093,8 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): 3*x^-3 + 3*x + 3*x^2 + 9*x^4 """ cdef LaurentPolynomial_univariate ret - ret = self._new_c() - ret.__u = self.__u._lmul_(c) + ret = self._new_c() + ret.__u = self.__u._lmul_(c) ret.__n = self.__n ret._normalize() return ret @@ -1170,10 +1171,10 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): sage: 1 // f 0 """ - cdef LaurentPolynomial_univariate right = rhs + cdef LaurentPolynomial_univariate right = rhs cdef LaurentPolynomial_univariate ret - ret = self._new_c() - ret.__u = (self.__u // right.__u) + ret = self._new_c() + ret.__u = (self.__u // right.__u) ret.__n = self.__n - right.__n ret._normalize() return ret @@ -1196,7 +1197,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): 1 + 4*t^2 + 6*t^4 + 4*t^6 + t^8 """ cdef LaurentPolynomial_univariate ret - ret = self._new_c() + ret = self._new_c() ret.__u = self.__u ret.__n = self.__n + k # No need to normalize @@ -1215,7 +1216,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): 1 + 4*t^2 + 6*t^4 + 4*t^6 + t^8 """ cdef LaurentPolynomial_univariate ret - ret = self._new_c() + ret = self._new_c() ret.__u = self.__u ret.__n = self.__n + k # No need to normalize @@ -1234,7 +1235,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): t^-14 + 4*t^-12 + 6*t^-10 + 4*t^-8 + t^-6 """ cdef LaurentPolynomial_univariate ret - ret = self._new_c() + ret = self._new_c() ret.__u = self.__u ret.__n = self.__n - k # No need to normalize @@ -1256,7 +1257,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): sage: (x^-2 + x)*(x^-2 + 1) / ((x^-5 + x^-8)*(x + 2)) (x^6 + x^4)/(x + 2) """ - cdef LaurentPolynomial_univariate right = rhs + cdef LaurentPolynomial_univariate right = rhs if right.__u.is_zero(): raise ZeroDivisionError return self * ~right @@ -1282,8 +1283,8 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): Fraction Field of Univariate Polynomial Ring in t over Rational Field """ cdef LaurentPolynomial_univariate ret - if self.__u.is_constant(): # this has a single term c*x^n - ret = self._new_c() + if self.__u.is_constant(): # this has a single term c*x^n + ret = self._new_c() if self.__u.is_unit(): ret.__u = self.__u.inverse_of_unit() ret.__n = -self.__n @@ -1357,9 +1358,9 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): sage: gcd((t^-2 + t)*(t + t^-1), (t^5 + t^8)*(1 + t^-2)) t^-3 + t^-1 + 1 + t^2 """ - b = self._parent(right) + b = self._parent(right) cdef LaurentPolynomial_univariate ret - ret = self._new_c() + ret = self._new_c() ret.__u = self.__u.gcd(b.__u) ret.__n = min(self.__n, b.__n) ret._normalize() @@ -1402,15 +1403,15 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): sage: num == q * den + r True """ - cdef LaurentPolynomial_univariate right = other + cdef LaurentPolynomial_univariate right = other q, r = self.__u.quo_rem(right.__u) cdef LaurentPolynomial_univariate ql, qr - ql = self._new_c() - ql.__u = q + ql = self._new_c() + ql.__u = q ql.__n = self.__n - right.__n ql._normalize() - qr = self._new_c() - qr.__u = r + qr = self._new_c() + qr.__u = r qr.__n = self.__n qr._normalize() return ql, qr @@ -1455,7 +1456,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): sage: f > g True """ - cdef LaurentPolynomial_univariate right = right_r + cdef LaurentPolynomial_univariate right = right_r zero = self._parent.base_ring().zero() @@ -1516,8 +1517,8 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): if n <= self.valuation(): return self._parent.zero() cdef LaurentPolynomial_univariate ret - ret = self._new_c() - ret.__u = self.__u.truncate(n - self.__n) + ret = self._new_c() + ret.__u = self.__u.truncate(n - self.__n) ret.__n = self.__n ret._normalize() return ret @@ -1618,7 +1619,6 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): """ return self.__n == 0 and self.__u.is_constant() - def is_square(self, root=False): r""" Return whether this Laurent polynomial is a square. @@ -1700,7 +1700,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): """ from copy import copy cdef LaurentPolynomial_univariate ret - ret = self._new_c() + ret = self._new_c() ret.__u = copy(self.__u) ret.__n = self.__n # No need to normalize @@ -1793,8 +1793,8 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): try: # call _derivative() recursively on coefficients u = [coeff._derivative(var) for coeff in self.__u.list(copy=False)] - ret = self._new_c() - ret.__u = self._parent._R(u) + ret = self._new_c() + ret.__u = self._parent._R(u) ret.__n = self.__n ret._normalize() return ret @@ -1808,8 +1808,8 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): cdef list a = self.__u.list(copy=True) for m in range(len(a)): a[m] *= n + m - ret = self._new_c() - ret.__u = self._parent._R(a) + ret = self._new_c() + ret.__u = self._parent._R(a) ret.__n = self.__n - 1 ret._normalize() return ret @@ -1865,16 +1865,16 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): cdef list a = self.__u.list(copy=False) if n < 0: - v = [a[i]/(n+i+1) for i in range(min(-1-n,len(a)))] + [0] + v = [a[i]/(n+i+1) for i in range(min(-1-n, len(a)))] + [0] else: v = [] - v += [a[i]/(n+i+1) for i in range(max(-n,0), len(a))] + v += [a[i]/(n+i+1) for i in range(max(-n, 0), len(a))] try: u = self._parent._R(v) except TypeError: raise ArithmeticError("coefficients of integral cannot be coerced into the base ring") - ret = self._new_c() - ret.__u = u + ret = self._new_c() + ret.__u = u ret.__n = n + 1 ret._normalize() return ret @@ -1907,7 +1907,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): """ if kwds: f = self.subs(**kwds) - if x: # If there are non-keyword arguments + if x: # If there are non-keyword arguments return f(*x) else: return f @@ -1935,14 +1935,14 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): """ cdef LaurentPolynomial_univariate u, d pf = self.__u.factor() - u = self._new_c() + u = self._new_c() u.__u = pf.unit() u.__n = self.__n u._normalize() f = [] for t in pf: - d = self._new_c() + d = self._new_c() d.__u = t[0] d.__n = 0 d._normalize() @@ -2006,8 +2006,8 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): """ dres = {} for (e, c) in self.dict().items(): - if e > 0 : - dres[(e,0)] = c + if e > 0: + dres[(e, 0)] = c else: - dres[(0,-e)] = c + dres[(0, -e)] = c return self.parent()._extended_ring(dres) diff --git a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx index b428560c1ae..5d3628cb30a 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx @@ -22,6 +22,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): """ Multivariate Laurent polynomials. """ + def __init__(self, parent, x, mon=None, reduce=True): """ Currently, one can only create LaurentPolynomials out of dictionaries @@ -120,8 +121,8 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): x = {k.esub(self._mon): x_k for k, x_k in x.iteritems()} elif (isinstance(x, LaurentPolynomial_mpair) and parent.variable_names() == x.parent().variable_names()): - self._mon = (x)._mon - x = (x)._poly + self._mon = ( < LaurentPolynomial_mpair > x)._mon + x = ( < LaurentPolynomial_mpair > x)._poly else: # since x should coerce into parent, _mon should be (0,...,0) self._mon = ETuple({}, int(parent.ngens())) self._poly = parent._R(x) @@ -279,26 +280,26 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): # self._parent.variable_names(), # self._parent.base_ring() # ) - cdef dict D = self._poly.dict() + cdef dict D = self._poly.dict() cdef ETuple e if i is None: e = None for k in D: if e is None: - e = k + e = k else: e = e.emin(k) if not e.is_constant(): - self._poly = (self._poly // self._poly._parent({e: 1})) + self._poly = (self._poly // self._poly._parent({e: 1})) self._mon = self._mon.eadd(e) else: e = None for k in D: if e is None or k[i] < e: - e = k[i] + e = k[i] if e > 0: - self._poly = (self._poly // self._poly._parent.gen(i)) + self._poly = (self._poly // self._poly._parent.gen(i)) self._mon = self._mon.eadd_p(e, i) cdef _compute_polydict(self): @@ -312,7 +313,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): """ # cdef dict D = self._poly._mpoly_dict_recursive(self._parent.variable_names(), # self._parent.base_ring()) - cdef dict D = self._poly.dict() + cdef dict D = self._poly.dict() cdef dict DD if self._mon.is_constant(): self._prod = PolyDict(D) @@ -576,11 +577,11 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): for (e, c) in self.dict().items(): exps = [] for t in e: - if t > 0 : + if t > 0: exps += [t, 0] else: exps += [0, -t] - dres [tuple(exps)] = c + dres[tuple(exps)] = c return self.parent()._extended_ring(dres) def iterator_exp_coeff(self): @@ -649,7 +650,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): """ if parent(mon) != self._parent: raise TypeError("input must have the same parent") - cdef LaurentPolynomial_mpair m = mon + cdef LaurentPolynomial_mpair m = mon if m._prod is None: m._compute_polydict() if self._prod is None: @@ -738,7 +739,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): """ if mon.parent() is not self._parent: mon = self._parent(mon) - cdef LaurentPolynomial_mpair m = mon + cdef LaurentPolynomial_mpair m = mon if self._prod is None: self._compute_polydict() if m._prod is None: @@ -808,7 +809,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): """ if self._prod is None: self._compute_polydict() - return self._prod.dict() + return < dict > self._prod.dict() def _fraction_pair(self): """ @@ -850,7 +851,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): x + y + z + y^-1 """ cdef LaurentPolynomial_mpair ans = self._new_c() - cdef LaurentPolynomial_mpair right = _right + cdef LaurentPolynomial_mpair right = _right ans._mon, a, b = self._mon.combine_to_positives(right._mon) if not a.is_constant(): ans._poly = self._poly * self._poly._parent({a: 1}) @@ -875,7 +876,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): -y - z + y^-1 """ cdef LaurentPolynomial_mpair ans = self._new_c() - cdef LaurentPolynomial_mpair right = _right + cdef LaurentPolynomial_mpair right = _right cdef ETuple a, b ans._mon, a, b = self._mon.combine_to_positives(right._mon) if not a.is_constant(): @@ -911,7 +912,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): sage: (s+q)/(q^2*t^(-2)) s*q^-2*t^2 + q^-1*t^2 """ - cdef LaurentPolynomial_mpair right = rhs + cdef LaurentPolynomial_mpair right = rhs if right.is_zero(): raise ZeroDivisionError if right._poly.is_term(): @@ -1000,8 +1001,8 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): x*y + x*z + 1 + y^-1*z """ cdef LaurentPolynomial_mpair ans = self._new_c() - ans._mon = self._mon.eadd((right)._mon) - ans._poly = self._poly * (right)._poly + ans._mon = self._mon.eadd(( < LaurentPolynomial_mpair > right)._mon) + ans._poly = self._poly * ( < LaurentPolynomial_mpair > right)._poly return ans cpdef _floordiv_(self, right): @@ -1040,7 +1041,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): b + 1 """ cdef LaurentPolynomial_mpair ans = self._new_c() - cdef LaurentPolynomial_mpair rightl = right + cdef LaurentPolynomial_mpair rightl = right self._normalize() rightl._normalize() ans._mon = self._mon.esub(rightl._mon) @@ -1092,8 +1093,8 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): selfl._poly = self._poly selfl._mon = self._mon cdef LaurentPolynomial_mpair rightl = self._new_c() - rightl._poly = ( right)._poly - rightl._mon = ( right)._mon + rightl._poly = (< LaurentPolynomial_mpair > right)._poly + rightl._mon = (< LaurentPolynomial_mpair > right)._mon selfl._normalize() rightl._normalize() @@ -1126,15 +1127,15 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): """ if self._prod is None: self._compute_polydict() - if ( right)._prod is None: - ( right)._compute_polydict() + if (< LaurentPolynomial_mpair > right)._prod is None: + (< LaurentPolynomial_mpair > right)._compute_polydict() try: sortkey = self._parent.term_order().sortkey except AttributeError: sortkey = None - return self._prod.rich_compare((right)._prod, + return self._prod.rich_compare(( < LaurentPolynomial_mpair > right)._prod, op, sortkey) def exponents(self): @@ -1171,7 +1172,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): if not x: return self._poly.total_degree() + sum(self._mon) - cdef tuple g = self._parent.gens() + cdef tuple g = self._parent.gens() cdef Py_ssize_t i cdef bint no_generator_found = True for i in range(len(g)): @@ -1609,14 +1610,14 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): u = self.parent(pf.unit()) - cdef tuple g = self._parent.gens() + cdef tuple g = self._parent.gens() for i in self._mon.nonzero_positions(): u *= g[i] ** self._mon[i] cdef list f = [] cdef dict d for t in pf: - d = (t[0].dict()) + d = (t[0].dict()) if len(d) == 1: # monomials are units u *= self.parent(d) ** t[1] else: @@ -1728,14 +1729,14 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): val *= d[i]**v[i] df[v] = R(h(val)) - ans = self._new_c() + ans = self._new_c() ans._prod = PolyDict(df) ans._mon = self._mon if new_ring is None: S = self._poly._parent else: S = self._poly._parent.change_ring(R) - ans._poly = S({v.esub(ans._mon): df[v] for v in df}) + ans._poly = S({v.esub(ans._mon): df[v] for v in df}) if new_ring is not None: return new_ring(ans) return ans @@ -1791,8 +1792,8 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): x = 0 for i in range(n): if not mat.get_is_zero_unsafe(j, i): - x += ( v[i]) * int(mat.get_unsafe(j, i)) - if x < ( mon[j]): + x += (< int > v[i]) * int(mat.get_unsafe(j, i)) + if x < (< int > mon[j]): mon[j] = x exp[j] = x dr[ETuple(exp)] = d[v] @@ -1801,10 +1802,10 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): for v in dr: dr[v] = self._parent._base(h(dr[v])) - ans = self._new_c() + ans = self._new_c() ans._prod = PolyDict(dr) ans._mon = ETuple(mon) - ans._poly = self._poly._parent({v.esub(ans._mon): dr[v] for v in dr}) + ans._poly = self._poly._parent({v.esub(ans._mon): dr[v] for v in dr}) if new_ring is not None: return new_ring(ans) return ans @@ -1875,10 +1876,10 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): S = self._poly._parent else: S = self._poly._parent.change_ring(new_ring._base) - ans = self._new_c() + ans = self._new_c() ans._prod = PolyDict(dr) ans._mon = mon - ans._poly = S({v.esub(ans._mon): dr[v] for v in dr}) + ans._poly = S({v.esub(ans._mon): dr[v] for v in dr}) if new_ring is not None: return new_ring(ans) return ans From 400d0b8325b5b3659843e09d6ff61265f9e42be8 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Mon, 13 Nov 2023 20:48:39 +0900 Subject: [PATCH 081/155] Improve pdf icon style --- src/doc/common/static/custom-furo.css | 10 ++++++++ src/doc/en/website/templates/index_furo.html | 27 +++++++++++--------- src/sage_docbuild/builders.py | 4 +-- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/doc/common/static/custom-furo.css b/src/doc/common/static/custom-furo.css index 343fbb908cf..fc76a3f7c0f 100644 --- a/src/doc/common/static/custom-furo.css +++ b/src/doc/common/static/custom-furo.css @@ -11,3 +11,13 @@ body[data-theme="dark"] div.highlight { background: #383838; } +/* Copied the style for a.pdf from website/templates/index_furo.html */ + +a.pdf { + margin-right: 0.5em; +} + +a.pdf:hover { + text-decoration: none; +} + diff --git a/src/doc/en/website/templates/index_furo.html b/src/doc/en/website/templates/index_furo.html index 1dca6907c93..2b086f35d8a 100644 --- a/src/doc/en/website/templates/index_furo.html +++ b/src/doc/en/website/templates/index_furo.html @@ -10,10 +10,13 @@ border: none; } a.pdf { - margin-left: 0.5em; - {%- if hide_pdf_links %} + margin-right: 0.3em; + {%- if hide_pdf_links %} display: none; - {%- endif %} + {%- endif %} + } + a.pdf:hover { + text-decoration: none; } table.contentstable { align: center; @@ -41,7 +44,7 @@

markup. start = rst.rfind('*\n') + 1 end = rst.find('\nUser Interfaces') From 70137ce613c002bb2b180f8acf5a413992e69acd Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 13 Nov 2023 09:39:43 -0800 Subject: [PATCH 082/155] build/bin/sage-logger [V=0]: Show more lines of the end of failing build logs --- build/bin/sage-logger | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/bin/sage-logger b/build/bin/sage-logger index 1d8d92c0c75..9ae80d404f8 100755 --- a/build/bin/sage-logger +++ b/build/bin/sage-logger @@ -79,7 +79,7 @@ if [ -n "$SAGE_SILENT_BUILD" -a ${use_prefix} = true ]; then status=$? if [[ $status != 0 ]]; then echo " [$logname] error installing, exit status $status. End of log file:" - tail -n 72 "$logfile" | sed "/Please email sage-devel/,$ d;s;^; [$logname] ;" >&2 + tail -n 120 "$logfile" | sed "/Please email sage-devel/,$ d;s;^; [$logname] ;" >&2 echo " [$logname] Full log file: $logfile" else echo " [$logname] successfully installed." From 08939a85105824823ef0c071865d8fc654439560 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Mon, 13 Nov 2023 20:12:06 +0100 Subject: [PATCH 083/155] compute the length of a tree decomposition --- .../tree_decomposition.pyx | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/sage/graphs/graph_decompositions/tree_decomposition.pyx b/src/sage/graphs/graph_decompositions/tree_decomposition.pyx index 90f14298c5a..3a73cbc8cc5 100644 --- a/src/sage/graphs/graph_decompositions/tree_decomposition.pyx +++ b/src/sage/graphs/graph_decompositions/tree_decomposition.pyx @@ -78,6 +78,7 @@ The treewidth of a clique is `n-1` and its treelength is 1:: :meth:`is_valid_tree_decomposition` | Check whether `T` is a valid tree-decomposition for `G`. :meth:`reduced_tree_decomposition` | Return a reduced tree-decomposition of `T`. :meth:`width_of_tree_decomposition` | Return the width of the tree decomposition `T` of `G`. + :meth:`length_of_tree_decomposition` | Return the length of the tree decomposition `T` of `G`. .. TODO: @@ -779,6 +780,116 @@ def treewidth(g, k=None, kmin=None, certificate=False, algorithm=None): # Treelength # +def length_of_tree_decomposition(G, T, check=True): + r""" + Return the length of the tree decomposition `T` of `G`. + + The *length* of a tree decomposition, as proposed in [DG2006]_, is the + maximum *diameter* in `G` of its bags, where the diameter of a bag `X_i` is + the largest distance in `G` between the vertices in `X_i` (i.e., `\max_{u, v + \in X_i} dist_G(u, v)`). See the documentation of the + :mod:`~sage.graphs.graph_decompositions.tree_decomposition` module for more + details. + + INPUT: + + - ``G`` -- a sage Graph + + - ``T`` -- a tree-decomposition for `G` + + - ``check`` -- boolean (default: ``True``); whether to check that the + tree-decomposition `T` is valid for `G` + + EXAMPLES: + + Trees and cliques have treelength 1:: + + sage: from sage.graphs.graph_decompositions.tree_decomposition import length_of_tree_decomposition + sage: G = graphs.CompleteGraph(5) + sage: tl, T = G.treelength(certificate=True) + sage: tl + 1 + sage: length_of_tree_decomposition(G, T, check=True) + 1 + sage: G = graphs.RandomTree(20) + sage: tl, T = G.treelength(certificate=True) + sage: tl + 1 + sage: length_of_tree_decomposition(G, T, check=True) + 1 + + The Petersen graph has treelength 2:: + + sage: G = graphs.PetersenGraph() + sage: tl, T = G.treelength(certificate=True) + sage: tl + 2 + sage: length_of_tree_decomposition(G, T) + 2 + + When a tree-decomposition has a single bag containing all vertices of a + graph, the length of this tree-decomposition is the diameter of the graph:: + + sage: G = graphs.Grid2dGraph(2, 5) + sage: G.treelength() + 2 + sage: G.diameter() + 5 + sage: T = Graph({Set(G): []}) + sage: length_of_tree_decomposition(G, T) + 5 + + TESTS:: + + sage: G = Graph() + sage: _, T = G.treelength(certificate=True) + sage: length_of_tree_decomposition(G, T, check=True) + 0 + sage: length_of_tree_decomposition(Graph(1), T, check=True) + Traceback (most recent call last): + ... + ValueError: the tree-decomposition is not valid for this graph + """ + if check and not is_valid_tree_decomposition(G, T): + raise ValueError("the tree-decomposition is not valid for this graph") + + cdef unsigned int n = G.order() + + if n < 2: + return 0 + if any(len(bag) == n for bag in T): + return G.diameter() + + cdef unsigned int i, j + + # We map vertices to integers in range 0..n-1 + cdef list int_to_vertex = list(G) + cdef dict vertex_to_int = {u: i for i, u in enumerate(int_to_vertex)} + + # We compute the distance matrix. + cdef unsigned short * c_distances = c_distances_all_pairs(G, vertex_list=int_to_vertex) + cdef unsigned short ** distances = sig_calloc(n, sizeof(unsigned short *)) + for i in range(n): + distances[i] = c_distances + i * n + + # We now compute the maximum lengths of the bags + from itertools import combinations + cdef list bag_int + cdef unsigned short dij + cdef unsigned short length = 0 + for bag in T: + bag_int = [vertex_to_int[u] for u in bag] + for i, j in combinations(bag_int, 2): + dij = distances[i][j] + if dij > length: + length = dij + + sig_free(c_distances) + sig_free(distances) + + return length + + def treelength_lowerbound(G): r""" Return a lower bound on the treelength of `G`. From 28c86cbdf26b2432f693c2e804dd5cd4151c9a73 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 13 Nov 2023 11:27:54 -0800 Subject: [PATCH 084/155] .ci/merge-fixes.sh: Handle variable SAGE_CI_FIXES_FROM_REPOS --- .ci/merge-fixes.sh | 135 +++++++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 55 deletions(-) diff --git a/.ci/merge-fixes.sh b/.ci/merge-fixes.sh index 28785381673..e7f83621ef2 100755 --- a/.ci/merge-fixes.sh +++ b/.ci/merge-fixes.sh @@ -1,57 +1,82 @@ #!/bin/sh -# Merge open PRs from sagemath/sage labeled "blocker". -REPO="sagemath/sage" -GH="gh -R $REPO" +# Apply open PRs labeled "blocker" from sagemath/sage as patches. +# This script is invoked by various workflows in .github/workflows +# +# The repository secret SAGE_CI_FIXES_FROM_REPOS can be set +# to customize this for CI runs in forks: +# +# - If set to a whitespace-separated list of repositories, use them instead of sagemath/sage. +# - If set to "none", do not apply any PRs. +# +# https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository +export GIT_AUTHOR_NAME="ci-sage workflow" +export GIT_AUTHOR_EMAIL="ci-sage@example.com" +export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME" +export GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL" mkdir -p upstream -PRs="$($GH pr list --label "p: blocker / 1" --json number --jq '.[].number' | tee upstream/ci-fixes.txt)" -date -u +"%Y-%m-%dT%H:%M:%SZ" > upstream/ci-fixes.date # Record the date, for future reference -if [ -z "$PRs" ]; then - echo 'Nothing to do: Found no open PRs with "blocker" status.' -else - echo "Found PRs: " $PRs - export GIT_AUTHOR_NAME="ci-sage workflow" - export GIT_AUTHOR_EMAIL="ci-sage@example.com" - export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME" - export GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL" - git tag -f test_base - git commit -q -m "Uncommitted changes" --no-allow-empty -a - for a in $PRs; do - git tag -f test_head - # We used to pull the branch and merge it (after unshallowing), but when run on PRs that are - # based on older releases, it has the side effect of updating to this release, - # which may be confusing. - # - # Here, we obtain the "git am"-able patch of the PR branch. - # This also makes it unnecessary to unshallow the repository. - # - # Considered alternative: Use https://github.com/$REPO/pull/$a.diff, - # which squashes everything into one diff without commit metadata. - PATH=build/bin:$PATH build/bin/sage-download-file "https://github.com/$REPO/pull/$a.patch" upstream/$a.patch - date -u +"%Y-%m-%dT%H:%M:%SZ" > upstream/$a.date # Record the date, for future reference - LAST_SHA=$(sed -n -E '/^From [0-9a-f]{40}/s/^From ([0-9a-f]{40}).*/\1/p' upstream/$a.patch | tail -n 1) - echo "::group::Applying PR https://github.com/$REPO/pull/$a @ https://github.com/$REPO/commits/$LAST_SHA as a patch" - export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME applying https://github.com/$REPO/pull/$a @ https://github.com/$REPO/commits/$LAST_SHA" - if git am --signoff --empty=keep < upstream/$a.patch; then - echo "---- Applied patch ------------------------------------------------------------" - cat upstream/$a.patch - echo "--------------------------------------------------------------------8<---------" - echo "::endgroup::" - elif git am --abort \ - && if git fetch --unshallow --all > /dev/null 2>&1; then echo "Unshallowed"; fi \ - && echo "Retrying with 3-way merge" \ - && git am --empty=keep --3way < upstream/$a.patch; then - echo "---- Applied patch ------------------------------------------------------------" - cat upstream/$a.patch - echo "--------------------------------------------------------------------8<---------" - echo "::endgroup::" - else - echo "---- Failure applying patch ---------------------------------------------------" - git am --signoff --show-current-patch=diff - echo "--------------------------------------------------------------------8<---------" - echo "::endgroup::" - echo "Failure applying #$a as a patch, resetting" - git am --signoff --abort - fi - done - #git log test_base..HEAD -fi +for REPO in ${SAGE_CI_FIXES_FROM_REPOSITORIES:-sagemath/sage}; do + case $REPO in + none) + echo "Nothing to do for 'none' in SAGE_CI_FIXES_FROM_REPOSITORIES" + ;; + */*) + echo "Getting open PRs with 'blocker' status from https://github.com/$REPO/pulls?q=is%3Aopen+label%3A%22p%3A+blocker+%2F+1%22" + GH="gh -R $REPO" + REPO_FILE="upstream/ci-fixes-${REPO%%/*}-${REPO##*/}" + PRs="$($GH pr list --label "p: blocker / 1" --json number --jq '.[].number' | tee $REPO_FILE)" + date -u +"%Y-%m-%dT%H:%M:%SZ" > $REPO_FILE.date # Record the date, for future reference + if [ -z "$PRs" ]; then + echo "Nothing to do: Found no open PRs with 'blocker' status in $REPO." + else + echo "Found open PRs with 'blocker' status in $REPO: $(echo $PRs)" + git tag -f test_base + git commit -q -m "Uncommitted changes" --no-allow-empty -a + for a in $PRs; do + # We used to pull the branch and merge it (after unshallowing), but when run on PRs that are + # based on older releases, it has the side effect of updating to this release, + # which may be confusing. + # + # Here, we obtain the "git am"-able patch of the PR branch. + # This also makes it unnecessary to unshallow the repository. + # + # Considered alternative: Use https://github.com/$REPO/pull/$a.diff, + # which squashes everything into one diff without commit metadata. + PULL_URL="https://github.com/$REPO/pull/$a" + PULL_FILE=upstream/ci-fixes-${REPO%%/*}-${REPO##*/} + PATH=build/bin:$PATH build/bin/sage-download-file --quiet "$PULL_URL.patch" $PULL_FILE.patch + date -u +"%Y-%m-%dT%H:%M:%SZ" > $PULL_FILE.date # Record the date, for future reference + LAST_SHA=$(sed -n -E '/^From [0-9a-f]{40}/s/^From ([0-9a-f]{40}).*/\1/p' $PULL_FILE.patch | tail -n 1) + COMMITS_URL="https://github.com/$REPO/commits/$LAST_SHA" + echo "::group::Applying PR $PULL_URL @ $COMMITS_URL as a patch" + export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME applying $PULL_URL @ $COMMITS_URL" + if git am --signoff --empty=keep < $PULL_FILE.patch; then + echo "---- Applied patch --------------------------------------------------------------------------------" + cat $PULL_FILE.patch + echo "--------------------------------------------------------------------8<-----------------------------" + echo "::endgroup::" + elif git am --abort \ + && if git fetch --unshallow --all > /dev/null 2>&1; then echo "Unshallowed"; fi \ + && echo "Retrying with 3-way merge" \ + && git am --empty=keep --3way < $PULL_FILE.patch; then + echo "---- Applied patch --------------------------------------------------------------------------------" + cat $PULL_FILE.patch + echo "--------------------------------------------------------------------8<-----------------------------" + echo "::endgroup::" + else + echo "---- Failure applying patch -----------------------------------------------------------------------" + git am --signoff --show-current-patch=diff + echo "--------------------------------------------------------------------8<-----------------------------" + echo "::endgroup::" + echo "Failure applying $PULL_URL as a patch, resetting" + git am --signoff --abort + fi + done + fi + ;; + *) + echo "Repository secret SAGE_CI_FIXES_FROM_REPOSITORIES, if set, should be a whitespace-separated list of repositories or 'none'" + echo "Got: $SAGE_CI_FIXES_FROM_REPOSITORIES" + exit 1 + ;; + esac +done From 01d9b73bfe028b3ea031dca9156ed8ade358229a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 13 Nov 2023 12:20:42 -0800 Subject: [PATCH 085/155] .ci/merge-fixes.sh: Use repository variables, not secrets --- .ci/merge-fixes.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.ci/merge-fixes.sh b/.ci/merge-fixes.sh index e7f83621ef2..e4823d25a01 100755 --- a/.ci/merge-fixes.sh +++ b/.ci/merge-fixes.sh @@ -2,13 +2,13 @@ # Apply open PRs labeled "blocker" from sagemath/sage as patches. # This script is invoked by various workflows in .github/workflows # -# The repository secret SAGE_CI_FIXES_FROM_REPOS can be set +# The repository variable SAGE_CI_FIXES_FROM_REPOS can be set # to customize this for CI runs in forks: # # - If set to a whitespace-separated list of repositories, use them instead of sagemath/sage. # - If set to "none", do not apply any PRs. # -# https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository +# https://docs.github.com/en/actions/learn-github-actions/variables#creating-configuration-variables-for-a-repository export GIT_AUTHOR_NAME="ci-sage workflow" export GIT_AUTHOR_EMAIL="ci-sage@example.com" export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME" @@ -74,7 +74,7 @@ for REPO in ${SAGE_CI_FIXES_FROM_REPOSITORIES:-sagemath/sage}; do fi ;; *) - echo "Repository secret SAGE_CI_FIXES_FROM_REPOSITORIES, if set, should be a whitespace-separated list of repositories or 'none'" + echo "Repository variable SAGE_CI_FIXES_FROM_REPOSITORIES, if set, should be a whitespace-separated list of repositories or 'none'" echo "Got: $SAGE_CI_FIXES_FROM_REPOSITORIES" exit 1 ;; From e82c8ae9f3bee695a1c04ae8e3a93adcaf5a33fc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 13 Nov 2023 11:56:46 -0800 Subject: [PATCH 086/155] .github/workflows: Pass vars.SAGE_CI_FIXES_FROM_REPOSITORIES to .ci/merge-fixes.sh --- .github/workflows/build.yml | 1 + .github/workflows/ci-conda.yml | 1 + .github/workflows/doc-build-pdf.yml | 1 + .github/workflows/doc-build.yml | 1 + .github/workflows/docker.yml | 2 ++ .github/workflows/lint.yml | 1 + .github/workflows/macos.yml | 1 + 7 files changed, 8 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5f466d3a285..644ad35f801 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,6 +38,7 @@ jobs: .ci/merge-fixes.sh env: GH_TOKEN: ${{ github.token }} + SAGE_CI_FIXES_FROM_REPOSITORIES: ${{ vars.SAGE_CI_FIXES_FROM_REPOSITORIES }} - name: Store CI fixes in upstream artifact run: | mkdir -p upstream diff --git a/.github/workflows/ci-conda.yml b/.github/workflows/ci-conda.yml index 2240c224a52..7e6282b92cc 100644 --- a/.github/workflows/ci-conda.yml +++ b/.github/workflows/ci-conda.yml @@ -38,6 +38,7 @@ jobs: .ci/merge-fixes.sh env: GH_TOKEN: ${{ github.token }} + SAGE_CI_FIXES_FROM_REPOSITORIES: ${{ vars.SAGE_CI_FIXES_FROM_REPOSITORIES }} - name: Create conda environment files run: ./bootstrap-conda diff --git a/.github/workflows/doc-build-pdf.yml b/.github/workflows/doc-build-pdf.yml index 1d14d0c29f7..97fc4a9767a 100644 --- a/.github/workflows/doc-build-pdf.yml +++ b/.github/workflows/doc-build-pdf.yml @@ -32,6 +32,7 @@ jobs: .ci/merge-fixes.sh env: GH_TOKEN: ${{ github.token }} + SAGE_CI_FIXES_FROM_REPOSITORIES: ${{ vars.SAGE_CI_FIXES_FROM_REPOSITORIES }} - name: Store CI fixes in upstream artifact run: | mkdir -p upstream diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 3660ff3a947..1a645a7aa46 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -27,6 +27,7 @@ jobs: .ci/merge-fixes.sh env: GH_TOKEN: ${{ github.token }} + SAGE_CI_FIXES_FROM_REPOSITORIES: ${{ vars.SAGE_CI_FIXES_FROM_REPOSITORIES }} - name: Store CI fixes in upstream artifact run: | mkdir -p upstream diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 3f5bf2e592c..6a8275f0394 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -218,6 +218,8 @@ jobs: .ci/merge-fixes.sh env: GH_TOKEN: ${{ github.token }} + SAGE_CI_FIXES_FROM_REPOSITORIES: ${{ vars.SAGE_CI_FIXES_FROM_REPOSITORIES }} + - name: Show disk space run: | df -h diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 41560674b49..69abb95deb4 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -26,6 +26,7 @@ jobs: .ci/merge-fixes.sh env: GH_TOKEN: ${{ github.token }} + SAGE_CI_FIXES_FROM_REPOSITORIES: ${{ vars.SAGE_CI_FIXES_FROM_REPOSITORIES }} - name: Set up Python uses: actions/setup-python@v4 diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 91c38807e76..0399fd1a3bb 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -95,6 +95,7 @@ jobs: .ci/merge-fixes.sh env: GH_TOKEN: ${{ github.token }} + SAGE_CI_FIXES_FROM_REPOSITORIES: ${{ vars.SAGE_CI_FIXES_FROM_REPOSITORIES }} - uses: actions/download-artifact@v3 with: From 49b7f741187befa9c3b2636d32d3f1ea9a74eb6f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 13 Nov 2023 12:41:13 -0800 Subject: [PATCH 087/155] .ci/merge-fixes.sh: Fix up PULL_FILE --- .ci/merge-fixes.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/merge-fixes.sh b/.ci/merge-fixes.sh index e4823d25a01..73b4c665caf 100755 --- a/.ci/merge-fixes.sh +++ b/.ci/merge-fixes.sh @@ -42,7 +42,7 @@ for REPO in ${SAGE_CI_FIXES_FROM_REPOSITORIES:-sagemath/sage}; do # Considered alternative: Use https://github.com/$REPO/pull/$a.diff, # which squashes everything into one diff without commit metadata. PULL_URL="https://github.com/$REPO/pull/$a" - PULL_FILE=upstream/ci-fixes-${REPO%%/*}-${REPO##*/} + PULL_FILE="$REPO_FILE-$a" PATH=build/bin:$PATH build/bin/sage-download-file --quiet "$PULL_URL.patch" $PULL_FILE.patch date -u +"%Y-%m-%dT%H:%M:%SZ" > $PULL_FILE.date # Record the date, for future reference LAST_SHA=$(sed -n -E '/^From [0-9a-f]{40}/s/^From ([0-9a-f]{40}).*/\1/p' $PULL_FILE.patch | tail -n 1) From 791711997bf8b60c0da73c365246b599a4d4934b Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 14 Nov 2023 14:00:59 +0900 Subject: [PATCH 088/155] Adding support for cellular basis of SGA over general fields; fixing typos. --- src/sage/algebras/iwahori_hecke_algebra.py | 2 +- src/sage/combinat/symmetric_group_algebra.py | 56 +++++++++++++++++--- src/sage/libs/coxeter3/coxeter_group.py | 2 +- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 0b6696af043..404387c9e9b 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1885,7 +1885,7 @@ class Cp(_KLHeckeBasis): Iwahori--Hecke algebra was initialized in the "standard" presentation where `\{q_1,q_2\} = \{v^2,1\}` as sets or the "normalized" presentation where `\{q_1,q_2\} = \{v,-v^{-1}\}` as sets, the function - :func::`product_on_basis` in this class computes products in the + :func:`product_on_basis` in this class computes products in the `C^{\prime}`-basis directly in the basis itself, using ``coxeter3`` to calculate certain `\mu`-coefficients quickly. If the above conditions are not all met, the function computes such products indirectly, by diff --git a/src/sage/combinat/symmetric_group_algebra.py b/src/sage/combinat/symmetric_group_algebra.py index 3884747f825..70704a0e9f7 100644 --- a/src/sage/combinat/symmetric_group_algebra.py +++ b/src/sage/combinat/symmetric_group_algebra.py @@ -686,7 +686,7 @@ def cell_poset(self): """ from sage.combinat.posets.posets import Poset from sage.combinat.partition import Partitions - return Poset([Partitions(self.n), lambda x, y: x.dominates(y)]) + return Poset([Partitions(self.n), lambda x, y: y.dominates(x)]) def cell_module_indices(self, la): r""" @@ -713,25 +713,65 @@ def _from_cellular_index(self, x): sage: S = SymmetricGroupAlgebra(QQ, 3) sage: C = S.cellular_basis() sage: [S._from_cellular_index(i) for i in C.basis().keys()] - [1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] - + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1], + [1/6*[1, 2, 3] - 1/6*[1, 3, 2] - 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + + 1/6*[3, 1, 2] - 1/6*[3, 2, 1], 1/3*[1, 2, 3] + 1/6*[1, 3, 2] - 1/3*[2, 1, 3] - 1/6*[2, 3, 1] - 1/6*[3, 1, 2] + 1/6*[3, 2, 1], 1/3*[1, 3, 2] + 1/3*[2, 3, 1] - 1/3*[3, 1, 2] - 1/3*[3, 2, 1], 1/4*[1, 3, 2] - 1/4*[2, 3, 1] + 1/4*[3, 1, 2] - 1/4*[3, 2, 1], 1/3*[1, 2, 3] - 1/6*[1, 3, 2] + 1/3*[2, 1, 3] - 1/6*[2, 3, 1] - 1/6*[3, 1, 2] - 1/6*[3, 2, 1], - 1/6*[1, 2, 3] - 1/6*[1, 3, 2] - 1/6*[2, 1, 3] + 1/6*[2, 3, 1] - + 1/6*[3, 1, 2] - 1/6*[3, 2, 1]] + 1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] + + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1]] + + sage: S = SymmetricGroupAlgebra(GF(3), 3) + sage: C = S.cellular_basis() + sage: [S._from_cellular_index(i) for i in C.basis().keys()] + [[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1], + [1, 2, 3] + [2, 1, 3], + [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [3, 1, 2], + [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1], + [1, 2, 3] + [1, 3, 2], + [1, 2, 3]] + sage: TestSuite(C).run() """ + if ~factorial(self.n) not in self.base_ring(): + from sage.combinat.rsk import RSK_inverse + from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet + G = self.basis().keys() + one = self.base_ring().one() + # check if the KL polynomials can be computed using ``coxeter3`` + try: + from sage.libs.coxeter3.coxeter_group import CoxeterGroup as Coxeter3Group + except ImportError: + # Falback to using the KL polynomial + from sage.combinat.kazhdan_lusztig import KazhdanLusztigPolynomial + q = PolynomialRing(self.base_ring(), 'q').gen() + KLG = SymmetricGroup(self.n) + self._cellular_KL = KazhdanLusztigPolynomial(KLG, q) + polyfunc = self._cellular_KL.P + else: + self._cellular_KL = Coxeter3Group(['A', self.n+1]) + KLG = self._cellular_KL + polyfunc = self._cellular_KL.kazhdan_lusztig_polynomial + + def func(S, T, mult=None): + w = KLG.from_reduced_word(RSK_inverse(T, S, output="permutation").reduced_word()) + bruhat = RecursivelyEnumeratedSet([w], lambda u: u.bruhat_lower_covers(), structure='graded') + return self.element_class(self, {G.from_reduced_word(v.reduced_word()): c(q=one) + for v in bruhat if (c := polyfunc(v, w))}) + + else: + func = self.epsilon_ik + SGA = SymmetricGroupAlgebra(self.base_ring(), self.n) P = self.basis().keys() if SGA.basis().keys() is P: # Indexed by permutations - return self.epsilon_ik(x[1], x[2]) + return func(x[1], x[2]) from sage.groups.perm_gps.permgroup_named import SymmetricGroup if P == SymmetricGroup(self.n): - return self.epsilon_ik(x[1], x[2]) - ret = SGA.epsilon_ik(x[1], x[2], mult='r2l') + return func(x[1], x[2]) + ret = func(x[1], x[2], mult='r2l') try: return self(ret) except TypeError: diff --git a/src/sage/libs/coxeter3/coxeter_group.py b/src/sage/libs/coxeter3/coxeter_group.py index 527cfc61c6f..9263303f601 100644 --- a/src/sage/libs/coxeter3/coxeter_group.py +++ b/src/sage/libs/coxeter3/coxeter_group.py @@ -321,7 +321,7 @@ def kazhdan_lusztig_polynomial(self, u, v, constant_term_one=True): basis to the `(T_w)_{w\in W}` of the Hecke algebra of `W` with parameters `q` and `q^{-1}`: - .. MATH:: C_w = \sum_u P_{u,w} T_w + .. MATH:: C_w = \sum_u P_{u,w} T_u. In particular, `P_{u,u}=1`:: From e4c6c4a3574aa7b409a15b3d44a923abc844bf56 Mon Sep 17 00:00:00 2001 From: miguelmarco Date: Tue, 14 Nov 2023 12:55:10 +0100 Subject: [PATCH 089/155] Update src/sage/categories/simplicial_sets.py Co-authored-by: John H. Palmieri --- src/sage/categories/simplicial_sets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/categories/simplicial_sets.py b/src/sage/categories/simplicial_sets.py index 3b71c4b9dd4..f9b8e2ab63f 100644 --- a/src/sage/categories/simplicial_sets.py +++ b/src/sage/categories/simplicial_sets.py @@ -827,7 +827,7 @@ def twisted_homology(self, n, reduced=False): - ``n`` - a positive integer. - ``reduced`` - (default: False) if set to True, the presentation matrix - will be reduced. + will be reduced. EXAMPLES:: From 65687a9c8904be7b01e483399f270599e0b47511 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 15 Nov 2023 09:54:16 +0900 Subject: [PATCH 090/155] Fixing doctests. --- src/sage/algebras/cellular_basis.py | 8 ++++---- .../finite_dimensional_algebras_with_basis.py | 10 +++++++++- src/sage/combinat/symmetric_group_algebra.py | 7 ++++--- src/sage/modules/with_basis/cell_module.py | 8 ++++---- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/sage/algebras/cellular_basis.py b/src/sage/algebras/cellular_basis.py index 873bd899b3e..8aad8efcd71 100644 --- a/src/sage/algebras/cellular_basis.py +++ b/src/sage/algebras/cellular_basis.py @@ -135,21 +135,21 @@ class CellularBasis(CombinatorialFreeModule): sage: len(S.basis()) 6 sage: a,b,c,d,e,f = C.basis() - sage: a + sage: f C([3], [[1, 2, 3]], [[1, 2, 3]]) sage: c C([2, 1], [[1, 3], [2]], [[1, 2], [3]]) sage: d C([2, 1], [[1, 2], [3]], [[1, 3], [2]]) - sage: a * a + sage: f * f C([3], [[1, 2, 3]], [[1, 2, 3]]) - sage: a * c + sage: f * c 0 sage: d * c C([2, 1], [[1, 2], [3]], [[1, 2], [3]]) sage: c * d C([2, 1], [[1, 3], [2]], [[1, 3], [2]]) - sage: S(a) + sage: S(f) 1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1] sage: S(d) diff --git a/src/sage/categories/finite_dimensional_algebras_with_basis.py b/src/sage/categories/finite_dimensional_algebras_with_basis.py index b8ed6332ead..2ba4069a8d5 100644 --- a/src/sage/categories/finite_dimensional_algebras_with_basis.py +++ b/src/sage/categories/finite_dimensional_algebras_with_basis.py @@ -1437,7 +1437,15 @@ def simple_module_parameterization(self): sage: S = SymmetricGroupAlgebra(QQ, 4) # needs sage.groups sage.modules sage: S.simple_module_parameterization() # needs sage.groups sage.modules - ([4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]) + ([1, 1, 1, 1], [2, 1, 1], [2, 2], [3, 1], [4]) + + sage: S = SymmetricGroupAlgebra(GF(3), 4) # needs sage.groups sage.modules + sage: S.simple_module_parameterization() # needs sage.groups sage.modules + ([2, 1, 1], [2, 2], [3, 1], [4]) + + sage: S = SymmetricGroupAlgebra(GF(4), 4) # needs sage.groups sage.modules + sage: S.simple_module_parameterization() # needs sage.groups sage.modules + ([3, 1], [4]) """ return tuple([mu for mu in self.cell_poset() if self.cell_module(mu).nonzero_bilinear_form()]) diff --git a/src/sage/combinat/symmetric_group_algebra.py b/src/sage/combinat/symmetric_group_algebra.py index 70704a0e9f7..1d87c0bf31d 100644 --- a/src/sage/combinat/symmetric_group_algebra.py +++ b/src/sage/combinat/symmetric_group_algebra.py @@ -739,14 +739,15 @@ def _from_cellular_index(self, x): from sage.combinat.rsk import RSK_inverse from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet G = self.basis().keys() - one = self.base_ring().one() + R = self.base_ring() + one = R.one() # check if the KL polynomials can be computed using ``coxeter3`` try: from sage.libs.coxeter3.coxeter_group import CoxeterGroup as Coxeter3Group except ImportError: # Falback to using the KL polynomial from sage.combinat.kazhdan_lusztig import KazhdanLusztigPolynomial - q = PolynomialRing(self.base_ring(), 'q').gen() + q = PolynomialRing(QQ, 'q').gen() KLG = SymmetricGroup(self.n) self._cellular_KL = KazhdanLusztigPolynomial(KLG, q) polyfunc = self._cellular_KL.P @@ -758,7 +759,7 @@ def _from_cellular_index(self, x): def func(S, T, mult=None): w = KLG.from_reduced_word(RSK_inverse(T, S, output="permutation").reduced_word()) bruhat = RecursivelyEnumeratedSet([w], lambda u: u.bruhat_lower_covers(), structure='graded') - return self.element_class(self, {G.from_reduced_word(v.reduced_word()): c(q=one) + return self.element_class(self, {G.from_reduced_word(v.reduced_word()): R(c(q=one)) for v in bruhat if (c := polyfunc(v, w))}) else: diff --git a/src/sage/modules/with_basis/cell_module.py b/src/sage/modules/with_basis/cell_module.py index 66d72f648f8..25e6509dde7 100644 --- a/src/sage/modules/with_basis/cell_module.py +++ b/src/sage/modules/with_basis/cell_module.py @@ -334,9 +334,9 @@ def _acted_upon_(self, scalar, self_on_left=False): sage: elt = W.an_element(); elt 2*W[[1, 2], [3]] + 2*W[[1, 3], [2]] sage: sc = C.an_element(); sc - 3*C([2, 1], [[1, 3], [2]], [[1, 2], [3]]) + 2*C([1, 1, 1], [[1], [2], [3]], [[1], [2], [3]]) + + 3*C([2, 1], [[1, 3], [2]], [[1, 2], [3]]) + 2*C([2, 1], [[1, 3], [2]], [[1, 3], [2]]) - + 2*C([3], [[1, 2, 3]], [[1, 2, 3]]) sage: sc * elt 10*W[[1, 3], [2]] @@ -448,9 +448,9 @@ def _acted_upon_(self, scalar, self_on_left=False): sage: elt = L.an_element(); elt 2*L[[1, 2], [3]] + 2*L[[1, 3], [2]] sage: sc = C.an_element(); sc - 3*C([2, 1], [[1, 3], [2]], [[1, 2], [3]]) + 2*C([1, 1, 1], [[1], [2], [3]], [[1], [2], [3]]) + + 3*C([2, 1], [[1, 3], [2]], [[1, 2], [3]]) + 2*C([2, 1], [[1, 3], [2]], [[1, 3], [2]]) - + 2*C([3], [[1, 2, 3]], [[1, 2, 3]]) sage: sc * elt 10*L[[1, 3], [2]] From 96de804754b9a7100f70f5fc139b0f1466da75c2 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 15 Nov 2023 08:00:14 +0100 Subject: [PATCH 091/155] Match all release tags --- .github/workflows/push_to_docker_hub.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/push_to_docker_hub.yml b/.github/workflows/push_to_docker_hub.yml index 0ae58b7b13b..cd289f6a88b 100644 --- a/.github/workflows/push_to_docker_hub.yml +++ b/.github/workflows/push_to_docker_hub.yml @@ -7,8 +7,14 @@ on: - 'develop' push: tags: - # Create images on pushing a tag - - '*' + # Match all release tags including beta, rc + - '[0-9]+.[0-9]+' + - '[0-9]+.[0-9]+.[0-9]+' + - '[0-9]+.[0-9]+.beta[0-9]+' + - '[0-9]+.[0-9]+.[0-9]+.beta[0-9]+' + - '[0-9]+.[0-9]+.rc[0-9]+' + - '[0-9]+.[0-9]+.[0-9]+.rc[0-9]+' + schedule: # Recover failed runs each Tuesday and Thursday at one o'clock - cron: '0 1 * * 2,4' From 11cbf0cfa16568db7383a66ed52ad7d991b5ef97 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Wed, 15 Nov 2023 20:22:57 +0100 Subject: [PATCH 092/155] Remove unncessary line in doctest. --- src/sage/categories/simplicial_sets.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sage/categories/simplicial_sets.py b/src/sage/categories/simplicial_sets.py index f9b8e2ab63f..f568c4cef23 100644 --- a/src/sage/categories/simplicial_sets.py +++ b/src/sage/categories/simplicial_sets.py @@ -597,8 +597,6 @@ def _canonical_twisting_operator(self): sage: list(d.values())[0].parent() Multivariate Laurent Polynomial Ring in f2, f3 over Integer Ring sage: Y = simplicial_sets.RealProjectiveSpace(2) - sage: Y._canonical_twisting_operator() - {f: F1bar} sage: d2 = Y._canonical_twisting_operator() sage: d2 {f: F1bar} From 3dc879120a50836dbc319139660594cfac215a79 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 16 Nov 2023 13:56:32 +0900 Subject: [PATCH 093/155] Fixing non-coxeter3 code. --- src/sage/combinat/symmetric_group_algebra.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/combinat/symmetric_group_algebra.py b/src/sage/combinat/symmetric_group_algebra.py index 1d87c0bf31d..baa83f214ef 100644 --- a/src/sage/combinat/symmetric_group_algebra.py +++ b/src/sage/combinat/symmetric_group_algebra.py @@ -747,7 +747,8 @@ def _from_cellular_index(self, x): except ImportError: # Falback to using the KL polynomial from sage.combinat.kazhdan_lusztig import KazhdanLusztigPolynomial - q = PolynomialRing(QQ, 'q').gen() + from sage.groups.perm_gps.permgroup_named import SymmetricGroup + q = PolynomialRing(R, 'q').gen() KLG = SymmetricGroup(self.n) self._cellular_KL = KazhdanLusztigPolynomial(KLG, q) polyfunc = self._cellular_KL.P From 4920ae734c053b91074169b1c34b29d5a2574175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 16 Nov 2023 20:10:06 +0100 Subject: [PATCH 094/155] cython-lint for graphs/ --- src/sage/graphs/base/static_sparse_graph.pxd | 2 +- src/sage/graphs/base/static_sparse_graph.pyx | 2 -- src/sage/graphs/bliss.pyx | 2 -- src/sage/graphs/centrality.pyx | 2 +- src/sage/graphs/connectivity.pxd | 36 +++++++++---------- src/sage/graphs/connectivity.pyx | 10 +++--- src/sage/graphs/distances_all_pairs.pyx | 25 ++++++------- src/sage/graphs/edge_connectivity.pyx | 3 -- src/sage/graphs/generic_graph_pyx.pyx | 14 ++++---- src/sage/graphs/genus.pyx | 7 ++-- src/sage/graphs/graph_coloring.pyx | 4 +-- .../vertex_separation.pyx | 1 - src/sage/graphs/graph_generators_pyx.pyx | 8 ++--- src/sage/graphs/hyperbolicity.pyx | 4 +-- src/sage/graphs/independent_sets.pxd | 1 - src/sage/graphs/independent_sets.pyx | 1 - src/sage/graphs/matchpoly.pyx | 2 +- src/sage/graphs/path_enumeration.pyx | 2 -- src/sage/graphs/planarity.pyx | 1 - src/sage/graphs/strongly_regular_db.pyx | 10 +++--- src/sage/graphs/weakly_chordal.pyx | 8 ++--- 21 files changed, 62 insertions(+), 83 deletions(-) diff --git a/src/sage/graphs/base/static_sparse_graph.pxd b/src/sage/graphs/base/static_sparse_graph.pxd index b5cd2d73009..4a427f81237 100644 --- a/src/sage/graphs/base/static_sparse_graph.pxd +++ b/src/sage/graphs/base/static_sparse_graph.pxd @@ -14,7 +14,7 @@ cdef extern from "stdlib.h": size_t size, int(*compar)(const_void *, const_void *)) nogil ctypedef struct short_digraph_s: - uint32_t * edges + uint32_t * edges uint32_t ** neighbors PyObject * edge_labels int m diff --git a/src/sage/graphs/base/static_sparse_graph.pyx b/src/sage/graphs/base/static_sparse_graph.pyx index ddb30927931..35f3de67c98 100644 --- a/src/sage/graphs/base/static_sparse_graph.pyx +++ b/src/sage/graphs/base/static_sparse_graph.pyx @@ -784,10 +784,8 @@ cdef void strongly_connected_components_digraph_C(short_digraph g, int nscc, int cdef size_t s_nscc = nscc cdef vector[vector[int]] scc_list = vector[vector[int]](nscc, vector[int]()) cdef vector[vector[int]] sons = vector[vector[int]](nscc + 1, vector[int]()) - cdef vector[int].iterator iter cdef short *neighbors = mem.calloc(nscc, sizeof(short)) cdef long m = 0 - cdef uint32_t degv cdef uint32_t *p_tmp for v in range(s_nscc): diff --git a/src/sage/graphs/bliss.pyx b/src/sage/graphs/bliss.pyx index 40a576a99cb..156b095b1df 100644 --- a/src/sage/graphs/bliss.pyx +++ b/src/sage/graphs/bliss.pyx @@ -102,7 +102,6 @@ cdef void add_gen(void *user_param, unsigned int n, const unsigned int *aut) noe cdef int cur = 0 cdef list perm = [] cdef bint* done = check_calloc(n, sizeof(bint)) - cdef int i gens, int_to_vertex, N = user_param @@ -511,7 +510,6 @@ cpdef canonical_form(G, partition=None, return_graph=False, use_edge_labels=True cdef bint directed = G.is_directed() - cdef int labInd cdef list Vout = [] cdef list Vin = [] cdef list labels = [] diff --git a/src/sage/graphs/centrality.pyx b/src/sage/graphs/centrality.pyx index 2fa2d4d303e..118edd5d7b0 100755 --- a/src/sage/graphs/centrality.pyx +++ b/src/sage/graphs/centrality.pyx @@ -696,7 +696,7 @@ def centrality_closeness_top_k(G, int k=1, int verbose=0): cdef int* reachU cdef int* pred = mem.calloc(n, sizeof(int)) cdef double *farness = mem.malloc(n * sizeof(double)) - cdef int d, nd, x, v, w + cdef int d, nd, x, v cdef long f, gamma cdef int* queue = mem.malloc(n * sizeof(int)) cdef double tildefL, tildefU diff --git a/src/sage/graphs/connectivity.pxd b/src/sage/graphs/connectivity.pxd index 329d2d29dad..5e49e66cc3a 100644 --- a/src/sage/graphs/connectivity.pxd +++ b/src/sage/graphs/connectivity.pxd @@ -36,7 +36,7 @@ cdef class TriconnectivitySPQR: cdef int* edge_extremity_first cdef int* edge_extremity_second cdef list int_to_original_edge_label - cdef int virtual_edge_num # number of created virtual edges + cdef int virtual_edge_num # number of created virtual edges cdef int* edge_status cdef bint* reverse_edges @@ -48,25 +48,25 @@ cdef class TriconnectivitySPQR: # Translates DFS number of a vertex to its new number cdef int* old_to_new - cdef int* newnum # new number of vertex i - cdef int* node_at # node at dfs number of i - cdef int* lowpt1 # lowpt1 number of vertex i - cdef int* lowpt2 # lowpt2 number of vertex i + cdef int* newnum # new number of vertex i + cdef int* node_at # node at dfs number of i + cdef int* lowpt1 # lowpt1 number of vertex i + cdef int* lowpt2 # lowpt2 number of vertex i cdef _LinkedList ** adj cdef _LinkedListNode ** in_adj cdef int* nd # Number of descendants of vertex i cdef int* parent # Parent vertex of vertex i in the palm tree - cdef int* degree # Degree of vertex i - cdef int* tree_arc # Tree arc entering the vertex i - cdef int* vertex_at # vertex with DFS number of i + cdef int* degree # Degree of vertex i + cdef int* tree_arc # Tree arc entering the vertex i + cdef int* vertex_at # vertex with DFS number of i cdef int dfs_counter - cdef list components_list # list of components of `graph_copy` - cdef list graph_copy_adjacency # Stores adjacency list + cdef list components_list # list of components of `graph_copy` + cdef list graph_copy_adjacency # Stores adjacency list - cdef bint* starts_path # Does edge e_index start a path - cdef int start_vertex # First vertex of exploration + cdef bint* starts_path # Does edge e_index start a path + cdef int start_vertex # First vertex of exploration # Stacks used in `path_search` function cdef list e_stack @@ -75,10 +75,10 @@ cdef class TriconnectivitySPQR: cdef int* t_stack_b cdef int t_stack_top - cdef list comp_final_edge_list # entry i is list of edges in component i - cdef list comp_type # entry i is type of component i - cdef dict final_edge_to_edge_index # associate final edge e to its index in int_to_edge - cdef GenericGraph_pyx spqr_tree # The final SPQR tree is stored + cdef list comp_final_edge_list # entry i is list of edges in component i + cdef list comp_type # entry i is type of component i + cdef dict final_edge_to_edge_index # associate final edge e to its index in int_to_edge + cdef GenericGraph_pyx spqr_tree # The final SPQR tree is stored # Arrays used in different methods. Allocated only once cdef int* tmp_array_n_int_1 @@ -86,7 +86,7 @@ cdef class TriconnectivitySPQR: cdef int* tmp_array_n_int_3 cdef bint* tmp_array_n_bint_1 - ### Methods ### + # === Methods === cdef inline __tstack_push(self, int h, int a, int b) noexcept: """ @@ -142,7 +142,6 @@ cdef class TriconnectivitySPQR: return self.edge_extremity_second[e_index] return self.edge_extremity_first[e_index] - cdef int __new_virtual_edge(self, int u, int v) noexcept cdef _LinkedListNode * __new_LinkedListNode(self, Py_ssize_t e_index) noexcept cdef Py_ssize_t __high(self, Py_ssize_t v) noexcept @@ -155,4 +154,3 @@ cdef class TriconnectivitySPQR: cdef int __path_search(self, int start) except -1 cdef __assemble_triconnected_components(self) noexcept cdef __build_spqr_tree(self) noexcept - diff --git a/src/sage/graphs/connectivity.pyx b/src/sage/graphs/connectivity.pyx index 8880d1f2b75..5c8166bd540 100644 --- a/src/sage/graphs/connectivity.pyx +++ b/src/sage/graphs/connectivity.pyx @@ -71,6 +71,7 @@ Methods from sage.misc.superseded import deprecation + def is_connected(G): """ Check whether the (di)graph is connected. @@ -2041,7 +2042,7 @@ def bridges(G, labels=True): if G.order() < 2 or not is_connected(G): return - B, C = G.blocks_and_cut_vertices() + B, _ = G.blocks_and_cut_vertices() # A block of size 2 is a bridge, unless the vertices are connected with # multiple edges. @@ -2209,8 +2210,9 @@ def cleave(G, cut_vertices=None, virtual_edges=True, solver=None, verbose=0, # If a vertex cut is given, we check that it is valid. Otherwise, we compute # a small vertex cut if cut_vertices is None: - cut_size, cut_vertices = G.vertex_connectivity(value_only=False, solver=solver, verbose=verbose, - integrality_tolerance=integrality_tolerance) + _, cut_vertices = G.vertex_connectivity(value_only=False, + solver=solver, verbose=verbose, + integrality_tolerance=integrality_tolerance) if not cut_vertices: # Typical example is a clique raise ValueError("the input graph has no vertex cut") @@ -2218,7 +2220,7 @@ def cleave(G, cut_vertices=None, virtual_edges=True, solver=None, verbose=0, cut_vertices = list(cut_vertices) for u in cut_vertices: if u not in G: - raise ValueError("vertex {} is not a vertex of the input graph".format(u)) + raise ValueError(f"vertex {u} is not a vertex of the input graph") H = G.copy(immutable=False) H.delete_vertices(cut_vertices) diff --git a/src/sage/graphs/distances_all_pairs.pyx b/src/sage/graphs/distances_all_pairs.pyx index a61fd4168a4..ec24fd5378f 100644 --- a/src/sage/graphs/distances_all_pairs.pyx +++ b/src/sage/graphs/distances_all_pairs.pyx @@ -192,8 +192,6 @@ cdef inline c_all_pairs_shortest_path_BFS(short_digraph sd, # This data structure is well documented in the module # sage.graphs.base.static_sparse_graph cdef uint32_t** p_vertices = sd.neighbors - cdef uint32_t* p_edges = sd.edges - cdef uint32_t* p_next = p_edges # We run n different BFS taking each vertex as a source for source in range(n): @@ -549,7 +547,7 @@ def is_distance_regular(G, parameters=False): ([3, 2, 2, 2, 2, 2, None], [None, 1, 1, 1, 1, 1, 3]) """ - cdef int i, l, u, v, d, b, c, k + cdef int i, u, v, d, b, c, k cdef int n = G.order() cdef int infinity = -1 @@ -776,7 +774,7 @@ cdef uint32_t * c_eccentricity_bounding(short_digraph sd) except NULL: cdef bitset_t seen bitset_init(seen, n) - cdef uint32_t v, w, next_v, tmp, cpt = 0 + cdef uint32_t v, w, next_v, cpt = 0 # The first vertex is the one with largest degree next_v = max((out_degree(sd, v), v) for v in range(n))[1] @@ -1122,9 +1120,8 @@ cdef uint32_t diameter_lower_bound_2sweep(short_digraph g, - ``seen`` -- bitset of size ``n`` that must be initialized before calling this method (i.e., bitset_init(seen, n)). However, there is no need to clear it. - """ - cdef uint32_t LB, i, k, tmp + cdef uint32_t LB # We do a first BFS from source and get the eccentricity of source LB = simple_BFS(g, source, distances, NULL, waiting_list, seen) @@ -1354,11 +1351,11 @@ cdef uint32_t diameter_iFUB(short_digraph g, - ``source`` -- starting node of the first BFS """ - cdef uint32_t i, LB, s, m, d + cdef uint32_t i, LB, m cdef uint32_t n = g.n # We select a vertex m with low eccentricity using multi-sweep - LB, s, m, d = diameter_lower_bound_multi_sweep(g, source) + LB, _, m, _ = diameter_lower_bound_multi_sweep(g, source) # If the lower bound is a very large number, it means that the graph is not # connected and so the diameter is infinite. @@ -1457,12 +1454,12 @@ cdef uint32_t diameter_DiFUB(short_digraph sd, cdef short_digraph rev_sd # Copy of sd with edges reversed init_reverse(rev_sd, sd) - cdef uint32_t LB, s, m, d, LB_1, LB_2, UB + cdef uint32_t LB, m, LB_1, LB_2, UB cdef size_t i cdef bitset_t seen # We select a vertex with low eccentricity using 2Dsweep - LB, s, m, d = diameter_lower_bound_2Dsweep(sd, rev_sd, source) + LB, _, m, _ = diameter_lower_bound_2Dsweep(sd, rev_sd, source) # If the lower bound is a very large number, it means that the digraph is # not strongly connected and so the diameter is infinite. @@ -2725,15 +2722,15 @@ def floyd_warshall(gg, paths=True, distances=False): cdef unsigned int n = max(gverts) + 1 if n >= -1: - raise ValueError("the graph backend contains more than "+str( -1)+" nodes") + raise ValueError("the graph backend contains more than " + str( -1) + " nodes") # All this just creates two tables prec[n][n] and dist[n][n] cdef MemoryAllocator mem = MemoryAllocator() cdef unsigned short* t_prec = NULL - cdef unsigned short** prec = NULL + cdef unsigned short** prec = NULL # init dist - cdef unsigned short* t_dist = mem.allocarray(n * n, sizeof(unsigned short)) - cdef unsigned short** dist = mem.allocarray(n, sizeof(unsigned short*)) + cdef unsigned short* t_dist = mem.allocarray(n * n, sizeof(unsigned short)) + cdef unsigned short** dist = mem.allocarray(n, sizeof(unsigned short*)) dist[0] = t_dist cdef unsigned int i for i in range(1, n): diff --git a/src/sage/graphs/edge_connectivity.pyx b/src/sage/graphs/edge_connectivity.pyx index 72416b560b6..22163fc9c77 100644 --- a/src/sage/graphs/edge_connectivity.pyx +++ b/src/sage/graphs/edge_connectivity.pyx @@ -984,9 +984,6 @@ cdef class GabowEdgeConnectivity: sage: GabowEdgeConnectivity(D).edge_connectivity() 4 """ - # Target x and source y of joining edge e_id - cdef int x = self.my_to[e_id] - cdef int y = self.my_from[e_id] # Previous state (tree Ti or unused) of an edge cdef int previous_state = self.FIRSTEDGE diff --git a/src/sage/graphs/generic_graph_pyx.pyx b/src/sage/graphs/generic_graph_pyx.pyx index 613d6c1c4ef..d27b3b65047 100644 --- a/src/sage/graphs/generic_graph_pyx.pyx +++ b/src/sage/graphs/generic_graph_pyx.pyx @@ -612,6 +612,7 @@ def binary_string_from_dig6(s, n): m = "".join(l) return m[:n*n] + # Exhaustive search in graphs cdef class SubgraphSearch: @@ -831,16 +832,16 @@ cdef class SubgraphSearch: # whether both are of the same type) self.directed = G.is_directed() - cdef int i, j, k + cdef int i, j # A vertex is said to be busy if it is already part of the partial copy # of H in G. - self.busy = self.mem.allocarray(self.ng, sizeof(int)) - self.tmp_array = self.mem.allocarray(self.ng, sizeof(int)) - self.stack = self.mem.allocarray(self.nh, sizeof(int)) - self.vertices = self.mem.allocarray(self.nh, sizeof(int)) + self.busy = self.mem.allocarray(self.ng, sizeof(int)) + self.tmp_array = self.mem.allocarray(self.ng, sizeof(int)) + self.stack = self.mem.allocarray(self.nh, sizeof(int)) + self.vertices = self.mem.allocarray(self.nh, sizeof(int)) self.line_h_out = self.mem.allocarray(self.nh, sizeof(int *)) - self.line_h_in = self.mem.allocarray(self.nh, sizeof(int *)) if self.directed else NULL + self.line_h_in = self.mem.allocarray(self.nh, sizeof(int *)) if self.directed else NULL self.line_h_out[0] = self.mem.allocarray(self.nh*self.nh, sizeof(int)) @@ -1030,6 +1031,7 @@ cdef inline bint vectors_inferior(int n, int *a, int *b) noexcept: return False return True + ############################## # Further tests. Unit tests for methods, functions, classes defined with cdef. ############################## diff --git a/src/sage/graphs/genus.pyx b/src/sage/graphs/genus.pyx index 4370f3135af..441fae754d6 100644 --- a/src/sage/graphs/genus.pyx +++ b/src/sage/graphs/genus.pyx @@ -143,7 +143,7 @@ cdef class simple_connected_genus_backtracker: cdef int *w = self.mem.malloc((self.num_verts + self.num_darts) * sizeof(int)) cdef int *s = self.mem.malloc(2 * (self.num_darts - self.num_verts) * sizeof(int)) - cdef int i, j, du, dv, u, v + cdef int i, j, dv, u, v for v in range(self.num_verts): if not G.has_vertex(v): @@ -341,7 +341,6 @@ cdef class simple_connected_genus_backtracker: before the flip, the cycle breaks into three. Otherwise, the number of cycles stays the same. """ - cdef int cycles = 0 cdef int *w = self.vertex_darts[v] cdef int *face_map = self.face_map @@ -393,7 +392,7 @@ cdef class simple_connected_genus_backtracker: """ Count all cycles. """ - cdef int i, j, c, m + cdef int i self.num_cycles = 0 for i in range(self.num_darts): @@ -447,7 +446,7 @@ cdef class simple_connected_genus_backtracker: sage: gb.genus() 0 """ - cdef int g, i + cdef int g # in the original genus implementation, this case resulted in infinite # recursion. oops. Let's skip that. diff --git a/src/sage/graphs/graph_coloring.pyx b/src/sage/graphs/graph_coloring.pyx index 327435969fe..f5025a641ac 100644 --- a/src/sage/graphs/graph_coloring.pyx +++ b/src/sage/graphs/graph_coloring.pyx @@ -1437,7 +1437,6 @@ def edge_coloring(g, value_only=False, vizing=False, hex_colors=False, solver=No cdef list L = [g] if g.is_connected() else g.connected_components_subgraphs() cdef int chi = 0 cdef list classes = [], vertices - cdef list values if vizing: classes = _vizing_edge_coloring(g) @@ -1684,13 +1683,14 @@ def _vizing_edge_coloring(g): rotate_fan(fan_center, fan) e_colors[frozenset((fan_center, fan[-1]))] = d - matchings = dict() + matchings = {} for edge, c in e_colors.items(): matchings[c] = matchings.get(c, []) + [tuple(edge)] classes = list(matchings.values()) return classes + def round_robin(n): r""" Compute a round-robin coloring of the complete graph on `n` vertices. diff --git a/src/sage/graphs/graph_decompositions/vertex_separation.pyx b/src/sage/graphs/graph_decompositions/vertex_separation.pyx index 548229f303b..eaec31b5c96 100644 --- a/src/sage/graphs/graph_decompositions/vertex_separation.pyx +++ b/src/sage/graphs/graph_decompositions/vertex_separation.pyx @@ -332,7 +332,6 @@ def lower_bound(G): raise ValueError("the (di)graph can have at most 31 vertices") cdef FastDigraph FD = FastDigraph(G) - cdef int * g = FD.graph cdef unsigned int n = FD.n # minimums[i] is means to store the value of c'_{i+1} diff --git a/src/sage/graphs/graph_generators_pyx.pyx b/src/sage/graphs/graph_generators_pyx.pyx index 060ea9275c6..414f6fbb570 100644 --- a/src/sage/graphs/graph_generators_pyx.pyx +++ b/src/sage/graphs/graph_generators_pyx.pyx @@ -6,17 +6,17 @@ AUTHORS: - David Coudert (2012) """ - -################################################################################ +# ############################################################################# # Copyright (C) 2012 David Coudert # # Distributed under the terms of the GNU General Public License (GPL) -# http://www.gnu.org/licenses/ -################################################################################ +# https://www.gnu.org/licenses/ +# ############################################################################# from sage.misc.randstate cimport random from sage.misc.randstate import set_random_seed + def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None): r""" Return a random graph or a digraph on `n` nodes. diff --git a/src/sage/graphs/hyperbolicity.pyx b/src/sage/graphs/hyperbolicity.pyx index 5361ebbff95..6474e9d6869 100644 --- a/src/sage/graphs/hyperbolicity.pyx +++ b/src/sage/graphs/hyperbolicity.pyx @@ -641,7 +641,7 @@ cdef tuple hyperbolicity_BCCM(int N, cdef int a, b, c, d, h_UB, n_val, n_acc, i, j cdef int hplusone cdef int condacc - cdef int x, y, S1, S2, S3 + cdef int x, S1, S2, S3 cdef list certificate = [] cdef uint32_t nb_p # The total number of pairs. cdef unsigned short *dist_a @@ -1672,7 +1672,7 @@ def hyperbolicity_distribution(G, algorithm='sampling', sampling_size=10**6): return {0: sampling_size if algorithm=='sampling' else binomial(G.num_verts(), 4)} cdef int N = G.num_verts() - cdef int i, j + cdef int i cdef unsigned short** distances cdef unsigned short* _distances_ cdef dict hdict diff --git a/src/sage/graphs/independent_sets.pxd b/src/sage/graphs/independent_sets.pxd index 1ccf3837af1..91f65b64ff7 100644 --- a/src/sage/graphs/independent_sets.pxd +++ b/src/sage/graphs/independent_sets.pxd @@ -10,4 +10,3 @@ cdef class IndependentSets: cdef int i cdef int count_only cdef int maximal - diff --git a/src/sage/graphs/independent_sets.pyx b/src/sage/graphs/independent_sets.pyx index c5105df067d..3064ccbc86f 100644 --- a/src/sage/graphs/independent_sets.pyx +++ b/src/sage/graphs/independent_sets.pyx @@ -223,7 +223,6 @@ cdef class IndependentSets: bitset_init(tmp, self.n) cdef uint64_t count = 0 - cdef list ans cdef int j try: diff --git a/src/sage/graphs/matchpoly.pyx b/src/sage/graphs/matchpoly.pyx index 7bd14c38bcd..5d70faf40a1 100644 --- a/src/sage/graphs/matchpoly.pyx +++ b/src/sage/graphs/matchpoly.pyx @@ -389,7 +389,7 @@ cdef void delete_and_add(int **edges, int nverts, int nedges, int totverts, int cdef int edge1 = edges1[nedges] cdef int edge2 = edges2[nedges] cdef int new_nedges = 0 - cdef int i, new_edge1, new_edge2 + cdef int i # The new edges are all the edges that are not incident with (edge1, edge2) diff --git a/src/sage/graphs/path_enumeration.pyx b/src/sage/graphs/path_enumeration.pyx index 6ef3e79143e..140bbda60e7 100644 --- a/src/sage/graphs/path_enumeration.pyx +++ b/src/sage/graphs/path_enumeration.pyx @@ -1790,9 +1790,7 @@ def all_paths_iterator(self, starting_vertices=None, ending_vertices=None, starting_vertices = self cdef dict data = {} cdef dict vertex_iterators - cdef list paths = [] cdef list path - cdef list shortest_path if report_edges and labels: if use_multiedges: diff --git a/src/sage/graphs/planarity.pyx b/src/sage/graphs/planarity.pyx index 1088a7659de..987669d97fe 100644 --- a/src/sage/graphs/planarity.pyx +++ b/src/sage/graphs/planarity.pyx @@ -152,7 +152,6 @@ def is_planar(g, kuratowski=False, set_pos=False, set_embedding=False): if not kuratowski: return False g_dict = {} - from sage.graphs.graph import Graph for i in range(1, theGraph.N + 1): linked_list = [] j = theGraph.V[i].link[1] diff --git a/src/sage/graphs/strongly_regular_db.pyx b/src/sage/graphs/strongly_regular_db.pyx index dc5f9d960bf..4095448b606 100644 --- a/src/sage/graphs/strongly_regular_db.pyx +++ b/src/sage/graphs/strongly_regular_db.pyx @@ -1229,7 +1229,6 @@ def SRG_from_RSHCD(v, k, l, mu, existence=False, check=True): n = v a = (n-4*mu)//2 e = 2*k - n + 1 + a - t = abs(a//2) if (e**2 == 1 and k == (n-1-a+e)/2 and @@ -1510,7 +1509,7 @@ def is_twograph_descendant_of_srg(int v, int k0, int l, int mu): sage: graphs.strongly_regular_graph(279, 150, 85, 75).is_strongly_regular(parameters=True) # optional - gap_package_design internet (279, 150, 85, 75) """ - cdef int b, k, s + cdef int b, k if k0 != 2*mu or not v % 2: return b = v+1+4*mu @@ -1570,9 +1569,8 @@ def is_taylor_twograph_srg(int v, int k, int l, int mu): sage: is_taylor_twograph_srg(730, 369, 168, 205) # needs sage.libs.pari (, 9) - """ - r, s = eigenvalues(v, k, l, mu) + r, _ = eigenvalues(v, k, l, mu) if r is None: return p, t = is_prime_power(v-1, get_data=True) @@ -2391,8 +2389,8 @@ def strongly_regular_from_two_weight_code(L): if is_Matrix(L): L = LinearCode(L) V = [tuple(l) for l in L] - w1, w2 = sorted(set(sum(map(bool, x)) for x in V).difference([0])) - G = Graph([V, lambda u, v: sum(uu!=vv for uu, vv in zip(u, v)) == w1]) + w1, _ = sorted(set(sum(map(bool, x)) for x in V).difference([0])) + G = Graph([V, lambda u, v: sum(uu != vv for uu, vv in zip(u, v)) == w1]) G.relabel() G.name('two-weight code: '+str(L)) return G diff --git a/src/sage/graphs/weakly_chordal.pyx b/src/sage/graphs/weakly_chordal.pyx index d1a6b03ae5d..9153c8ee93d 100644 --- a/src/sage/graphs/weakly_chordal.pyx +++ b/src/sage/graphs/weakly_chordal.pyx @@ -204,14 +204,13 @@ def is_long_hole_free(g, certificate=False): if g.order() < 5: return (True, []) if certificate else True - cdef int a, b, c, d, i, u, v, w, vv, ww + cdef int u, v, w, vv, ww # Make a copy of the graph as a short_digraph. This data structure is well # documented in the module sage.graphs.base.static_sparse_graph. # Vertices are relabeled in 0..n-1 cdef int n = g.order() cdef list id_label = list(g) - cdef dict label_id = {label: i for i, label in enumerate(id_label)} cdef short_digraph sd init_short_digraph(sd, g, edge_labelled=False, vertex_list=id_label) @@ -228,7 +227,6 @@ def is_long_hole_free(g, certificate=False): # Allocate some data structures cdef MemoryAllocator mem = MemoryAllocator() cdef int* path = mem.allocarray(n, sizeof(int)) - cdef int path_top cdef int* InPath = mem.allocarray(n, sizeof(int)) for u in range(n): InPath[u] = -1 @@ -433,14 +431,13 @@ def is_long_antihole_free(g, certificate=False): if g.order() < 5: return (True, []) if certificate else True - cdef int a, b, c, d, i, u, v, w, vv, ww + cdef int u, v, w, vv, ww # Make a copy of the graph as a short_digraph. This data structure is well # documented in the module sage.graphs.base.static_sparse_graph. # Vertices are relabeled in 0..n-1 cdef int n = g.order() cdef list id_label = list(g) - cdef dict label_id = {label: i for i, label in enumerate(id_label)} cdef short_digraph sd init_short_digraph(sd, g, edge_labelled=False, vertex_list=id_label) @@ -457,7 +454,6 @@ def is_long_antihole_free(g, certificate=False): # Allocate some data structures cdef MemoryAllocator mem = MemoryAllocator() cdef int* path = mem.allocarray(n, sizeof(int)) - cdef int path_top cdef int* InPath = mem.allocarray(n, sizeof(int)) for u in range(n): InPath[u] = -1 From d76d2729a4193d8afe5adf7fa4170a0926d74c2e Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sat, 18 Nov 2023 17:46:54 -0500 Subject: [PATCH 095/155] build/pkgs/pari: require pari-2.5.14, drop tests for patched v2.5.13 We currently check for either pari-2.5.14, or an unofficial (patched) version of pari-2.5.13 that is missing two bugs present in the upstream release. However, one of those bug-checks fails on macOS, making it impossible to use the system pari there. pari-2.5.14 has been out for a few months. Any distro fast enough to have backported patches to pari-2.5.13 will likely have pari-2.5.14 by now. On that assumption, we simply require pari-2.5.14 to fix the macOS issue, and hope it does not affect anyone still using a patched pari-2.5.13. --- build/pkgs/pari/spkg-configure.m4 | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/build/pkgs/pari/spkg-configure.m4 b/build/pkgs/pari/spkg-configure.m4 index 1404defc518..5ece8b4891e 100644 --- a/build/pkgs/pari/spkg-configure.m4 +++ b/build/pkgs/pari/spkg-configure.m4 @@ -1,6 +1,6 @@ SAGE_SPKG_CONFIGURE([pari], [ dnl See gp_version below on how the version is computed from MAJV.MINV.PATCHV - m4_pushdef([SAGE_PARI_MINVER],["134912"])dnl this version and higher allowed + m4_pushdef([SAGE_PARI_MINVER],["134916"])dnl this version and higher allowed m4_pushdef([SAGE_PARI_MAXVER],["999999"])dnl this version and higher not allowed SAGE_SPKG_DEPCHECK([gmp readline], [ AC_PATH_PROG([GP], [gp]) @@ -68,24 +68,6 @@ SAGE_SPKG_CONFIGURE([pari], [ sage_spkg_install_pari=yes fi - AC_MSG_CHECKING([whether factor() bug 2469 of pari 2.15.3 is fixed]) - result=`echo "f=factor(2^2203-1); print(\"ok\")" | timeout 1 $GP -qf` - if test x"$result" = xok; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no; cannot use system pari/GP with known bug]) - sage_spkg_install_pari=yes - fi - - AC_MSG_CHECKING([whether qfbclassno() bug 2466 of pari 2.15.3 is fixed]) - result=`echo "qfbclassno(33844)" | $GP -qf` - if test x"$result" = x3; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no; cannot use system pari/GP with known bug]) - sage_spkg_install_pari=yes - fi - fi dnl end GP test if test x$sage_spkg_install_pari = xno; then dnl main PARI test From 0163fe20ad93d97f05039eb0a4f71cd5c9f78e06 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 18 Nov 2023 16:14:01 -0800 Subject: [PATCH 096/155] build/pkgs/meson_python: Update to 0.15.0 --- build/pkgs/meson_python/checksums.ini | 6 +++--- build/pkgs/meson_python/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/meson_python/checksums.ini b/build/pkgs/meson_python/checksums.ini index 7eb55561d9a..1561ae04424 100644 --- a/build/pkgs/meson_python/checksums.ini +++ b/build/pkgs/meson_python/checksums.ini @@ -1,5 +1,5 @@ tarball=meson_python-VERSION.tar.gz -sha1=ce9192048927ee724673f57d9881b6bee320ff82 -md5=27bc0a24d1f5e2e83236a73f0826eadb -cksum=530505556 +sha1=71bf382c2f2e76aada2f511a84bd59a99a6b1238 +md5=e91eb9946d7bb8be06e434c5a2dadd05 +cksum=535820777 upstream_url=https://pypi.io/packages/source/m/meson_python/meson_python-VERSION.tar.gz diff --git a/build/pkgs/meson_python/package-version.txt b/build/pkgs/meson_python/package-version.txt index a803cc227fe..a5510516948 100644 --- a/build/pkgs/meson_python/package-version.txt +++ b/build/pkgs/meson_python/package-version.txt @@ -1 +1 @@ -0.14.0 +0.15.0 From f2dccac2b6ffabce73da4ad57cbf79925983d61c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 18 Nov 2023 16:14:33 -0800 Subject: [PATCH 097/155] build/pkgs/cmake: Update to 3.27.8 --- build/pkgs/cmake/checksums.ini | 6 +++--- build/pkgs/cmake/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/cmake/checksums.ini b/build/pkgs/cmake/checksums.ini index a145b30dfb4..312edba61ff 100644 --- a/build/pkgs/cmake/checksums.ini +++ b/build/pkgs/cmake/checksums.ini @@ -1,5 +1,5 @@ tarball=cmake-VERSION.tar.gz -sha1=3e9b980bfb16974f57ca02b5e2b403a2ef2d4eca -md5=7228f5fcc8a858fdeac27e29bda0c144 -cksum=2027526722 +sha1=05de9ac807fefeb2a36ed5e8fcea376a00dd3d57 +md5=df0e65607c9280a8df68b2c93eac4437 +cksum=3851971657 upstream_url=https://github.com/Kitware/CMake/releases/download/vVERSION/cmake-VERSION.tar.gz diff --git a/build/pkgs/cmake/package-version.txt b/build/pkgs/cmake/package-version.txt index a155471fc06..f641ba7ef04 100644 --- a/build/pkgs/cmake/package-version.txt +++ b/build/pkgs/cmake/package-version.txt @@ -1 +1 @@ -3.27.3 +3.27.8 From a886d480f9e88ec604162e9eb88618af38109d69 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 18 Nov 2023 16:20:39 -0800 Subject: [PATCH 098/155] build/pkgs/trove_classifiers: Update to 2023.11.14 --- build/pkgs/trove_classifiers/checksums.ini | 6 +++--- build/pkgs/trove_classifiers/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/trove_classifiers/checksums.ini b/build/pkgs/trove_classifiers/checksums.ini index 1f04c749038..d59736dbac2 100644 --- a/build/pkgs/trove_classifiers/checksums.ini +++ b/build/pkgs/trove_classifiers/checksums.ini @@ -1,5 +1,5 @@ tarball=trove-classifiers-VERSION.tar.gz -sha1=4763a32114b3bb96dfd447404022586355c5f83f -md5=6ae148c8374d131dd18e28c22275d56a -cksum=1938191178 +sha1=c6821e6c6d57dc2eec2d4156d63cdca939373759 +md5=154ae4cdb69ac37bb35a35c6fbc477cd +cksum=84032195 upstream_url=https://pypi.io/packages/source/t/trove_classifiers/trove-classifiers-VERSION.tar.gz diff --git a/build/pkgs/trove_classifiers/package-version.txt b/build/pkgs/trove_classifiers/package-version.txt index 0497ae632a3..b82d6dba095 100644 --- a/build/pkgs/trove_classifiers/package-version.txt +++ b/build/pkgs/trove_classifiers/package-version.txt @@ -1 +1 @@ -2023.8.7 +2023.11.14 From 5560fa38f7aada6a6e5b6c2248351922facb3aee Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sun, 19 Nov 2023 16:04:42 +0100 Subject: [PATCH 099/155] clean import of Graph and DiGraph --- src/sage/categories/coxeter_groups.py | 4 ++-- src/sage/combinat/binary_tree.py | 2 +- src/sage/geometry/lattice_polytope.py | 3 ++- src/sage/graphs/bliss.pyx | 2 +- src/sage/graphs/graph.py | 2 +- src/sage/graphs/graph_generators_pyx.pyx | 4 ++-- src/sage/schemes/elliptic_curves/ell_field.py | 10 +++++++--- src/sage/sets/disjoint_set.pyx | 4 ++-- src/sage/sets/set.py | 2 +- 9 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 71285521a5e..1c59620f639 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -1088,7 +1088,7 @@ def bruhat_interval_poset(self, x, y, facade=False): nextlayer.add(t) curlayer = nextlayer - from sage.graphs.graph import DiGraph + from sage.graphs.digraph import DiGraph return Poset(DiGraph(d, format='dict_of_lists', data_structure='static_sparse'), cover_relations=True, @@ -1174,7 +1174,7 @@ def bruhat_graph(self, x=None, y=None, edge_labels=False): else: d.append((u, v)) - from sage.graphs.graph import DiGraph + from sage.graphs.digraph import DiGraph return DiGraph(d) def canonical_representation(self): diff --git a/src/sage/combinat/binary_tree.py b/src/sage/combinat/binary_tree.py index 3f7b8ae2fc5..f58f7558a73 100644 --- a/src/sage/combinat/binary_tree.py +++ b/src/sage/combinat/binary_tree.py @@ -748,7 +748,7 @@ def graph(self, with_leaves=True): sage: t1.graph(with_leaves=False).edges(sort=True) [(0, 1, None), (0, 2, None), (2, 3, None), (2, 4, None)] """ - from sage.graphs.graph import DiGraph + from sage.graphs.digraph import DiGraph if with_leaves: # We want leaves and nodes. diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index 7847955db7b..d117c1b5991 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -112,7 +112,6 @@ is_PointCollection, read_palp_point_collection) from sage.geometry.toric_lattice import ToricLattice, is_ToricLattice -from sage.graphs.graph import DiGraph, Graph from sage.groups.perm_gps.permgroup_named import SymmetricGroup from sage.misc.lazy_import import lazy_import @@ -2039,6 +2038,7 @@ def LPFace(vertices, facets): else: # Get face lattice as a sublattice of the ambient one allowed_indices = frozenset(self._ambient_vertex_indices) + from sage.graphs.digraph import DiGraph L = DiGraph() empty = self._ambient.face_lattice().bottom() L.add_vertex(0) # In case it is the only one @@ -3974,6 +3974,7 @@ def skeleton(self): sage: g.edges(sort=True) # needs palp sage.graphs [(0, 1, None), (0, 3, None), (1, 2, None), (2, 3, None)] """ + from sage.graphs.graph import Graph skeleton = Graph() skeleton.add_vertices(self.skeleton_points(1)) for edge in self.edges(): diff --git a/src/sage/graphs/bliss.pyx b/src/sage/graphs/bliss.pyx index 40a576a99cb..8e0bf5bb20d 100644 --- a/src/sage/graphs/bliss.pyx +++ b/src/sage/graphs/bliss.pyx @@ -581,7 +581,7 @@ cpdef canonical_form(G, partition=None, return_graph=False, use_edge_labels=True if return_graph: if directed: - from sage.graphs.graph import DiGraph + from sage.graphs.digraph import DiGraph H = DiGraph(new_edges, loops=G.allows_loops(), multiedges=G.allows_multiple_edges()) else: from sage.graphs.graph import Graph diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index b3c845af376..e0b999c44da 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -421,7 +421,6 @@ from sage.rings.integer_ring import ZZ import sage.graphs.generic_graph_pyx as generic_graph_pyx from sage.graphs.generic_graph import GenericGraph -from sage.graphs.digraph import DiGraph from sage.graphs.independent_sets import IndependentSets from sage.misc.rest_index_of_methods import doc_index, gen_thematic_rest_table_index from sage.graphs.views import EdgesView @@ -3514,6 +3513,7 @@ def orientations(self, data_structure=None, sparse=None): if name: name = 'An orientation of ' + name + from sage.graphs.digraph import DiGraph if not self.size(): D = DiGraph(data=[self.vertices(sort=False), []], format='vertices_and_edges', diff --git a/src/sage/graphs/graph_generators_pyx.pyx b/src/sage/graphs/graph_generators_pyx.pyx index 060ea9275c6..1d590441c3e 100644 --- a/src/sage/graphs/graph_generators_pyx.pyx +++ b/src/sage/graphs/graph_generators_pyx.pyx @@ -63,8 +63,6 @@ def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None): ... ValueError: parameter 'loops' can be set to True only when 'directed' is True """ - from sage.graphs.graph import Graph, DiGraph - if seed is not None: set_random_seed(seed) @@ -74,8 +72,10 @@ def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None): cdef int pp = int(round(float(p * RAND_MAX_f))) if directed: + from sage.graphs.digraph import DiGraph G = DiGraph(loops=loops) else: + from sage.graphs.graph import Graph G = Graph() if loops: raise ValueError("parameter 'loops' can be set to True only when 'directed' is True") diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index 7dd65c95749..5591525d066 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -1931,7 +1931,6 @@ class of curves. If the j-invariant is not unique in the isogeny """ from warnings import warn - from sage.graphs.graph import DiGraph, Graph from sage.matrix.constructor import Matrix # warn users if things are getting big @@ -1983,8 +1982,13 @@ class of curves. If the j-invariant is not unique in the isogeny labels.append(E._equation_string()) A = Matrix([r + [0] * (len(A) - len(r)) for r in A]) - G = (DiGraph if directed else Graph)(A, format="adjacency_matrix", - data_structure="static_sparse") + if directed: + from sage.graphs.digraph import DiGraph as GraphType + else: + from sage.graphs.graph import Graph as GraphType + + G = GraphType(A, format="adjacency_matrix", + data_structure="static_sparse") # inplace relabelling is necessary for static_sparse graphs GL = G.relabel(labels, inplace=False) return GL diff --git a/src/sage/sets/disjoint_set.pyx b/src/sage/sets/disjoint_set.pyx index 4db91f4f058..3d2f4dd1710 100644 --- a/src/sage/sets/disjoint_set.pyx +++ b/src/sage/sets/disjoint_set.pyx @@ -600,7 +600,7 @@ cdef class DisjointSet_of_integers(DisjointSet_class): [(0, 0, None), (1, 1, None), (2, 1, None), (3, 1, None), (4, 1, None)] """ d = {i: [self._nodes.parent[i]] for i in range(self.cardinality())} - from sage.graphs.graph import DiGraph + from sage.graphs.digraph import DiGraph return DiGraph(d) cdef class DisjointSet_of_hashables(DisjointSet_class): @@ -891,5 +891,5 @@ cdef class DisjointSet_of_hashables(DisjointSet_class): e = self._int_to_el[i] p = self._int_to_el[self._nodes.parent[i]] d[e] = [p] - from sage.graphs.graph import DiGraph + from sage.graphs.digraph import DiGraph return DiGraph(d) diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index 2ac71e73dbf..8131c044e86 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -813,7 +813,7 @@ def subsets_lattice(self): raise NotImplementedError( "this method is only implemented for finite sets") from sage.combinat.posets.lattices import FiniteLatticePoset - from sage.graphs.graph import DiGraph + from sage.graphs.digraph import DiGraph from sage.rings.integer import Integer n = self.cardinality() # list, contains at position 0 <= i < 2^n From b40ca73e708fea46daaebe02b316ca28cc3ed5a7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 22 Jun 2023 16:55:10 -0700 Subject: [PATCH 100/155] build/bin/sage-spkg: WIP: More options --- build/bin/sage-spkg | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index b540c8e866f..5835c703eb7 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -90,20 +90,25 @@ Search Sage's list of packages (see 'sage --package list') for a matching package, and if a match is found, install it. Options: - -s: do not delete the temporary build directory - -c: after installing, run the test suite for the package; - exit with an error on test suite failures - -w: after installing, run the test suite for the package; - print a warning on test suite failures - -d: only download the package -y: automatically reply "y" for all prompts regarding experimental and old-style packages; warning: there is no guarantee that these packages will build correctly; use at your own risk -n: automatically reply "n" for all prompts regarding experimental and old-style packages + -d: only download the package -o: allow fetching the package from its upstream URL when it is not available from the Sage mirrors (yet) + -b: build and stage only, do not install or check + -x: only run the test suite; this may assume that: + * the package has been installed already and/or that + * the temporary build directory has not been deleted + -c: after installing, run the test suite for the package; + exit with an error on test suite failures + -w: after installing, run the test suite for the package; + print a warning on test suite failures + -s: do not delete the temporary build directory, even + when the installation was successful EOF } @@ -230,6 +235,8 @@ fi INFO=0 YES=0 KEEP_EXISTING=0 +BUILD=1 +INSTALL=1 while true; do case "$1" in --info) @@ -246,6 +253,8 @@ while true; do export SAGE_CHECK=yes;; -w|--check-warning-only) export SAGE_CHECK=warn;; + -x|--check-only) + INSTALL=1;; -k|--keep-existing) KEEP_EXISTING=yes;; -o|--allow-upstream) From 1f2cc9e432e126d4b0d66149e70647feeaa36dad Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 18 Nov 2023 19:07:24 -0800 Subject: [PATCH 101/155] build/bin/sage-spkg: Manage SAGE_KEEP_BUILT_SPKGS via stamp file .keep --- build/bin/sage-spkg | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 5835c703eb7..0f2e8c0061b 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -460,6 +460,10 @@ echo "Setting up build directory for $PKG_NAME" cp -RLp "$PKG_SCRIPTS" "$PKG_NAME" cd "$PKG_NAME" || exit $? +if [ "$SAGE_KEEP_BUILT_SPKGS" = "yes" ]; then + touch .keep +fi + case "$PKG_SRC" in *.whl) # (Platform-independent) wheel @@ -823,7 +827,7 @@ echo "Successfully installed $PKG_NAME" ################################################################## # Delete the temporary build directory if required ################################################################## -if [ "x$SAGE_KEEP_BUILT_SPKGS" != "xyes" ]; then +if [ ! -e "$SAGE_BUILD_DIR/$PKG_NAME/.keep" ]; then echo "Deleting temporary build directory" echo "$SAGE_BUILD_DIR/$PKG_NAME" # On Solaris, the current working directory cannot be deleted, From f2339b28bf6d5ec1bb9b08acbe7ba5452b79fc95 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 19 Nov 2023 11:15:33 -0800 Subject: [PATCH 102/155] build/bin/sage-spkg: Split into separate bash functions --- build/bin/sage-spkg | 97 +++++++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 43 deletions(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 0f2e8c0061b..7adef6f2a97 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -9,21 +9,7 @@ # # sage-spkg [] # -# Options can be: -# -s: do not delete temporary build directory -# -k: do not uninstall existing installation of this package before -# installing; instead simply overwrite existing files. -# -c: after installing, run the test suite for the spkg. This should -# override the settings of SAGE_CHECK. -# Exit with an error if the test suite fails. -# -w: after installing, run the test suite for the spkg. This should -# override the settings of SAGE_CHECK. -# Print a warning if the test suite fails. -# -d: only download the package -# -y: automatically reply "y" for all prompts regarding -# experimental and old-style packages -# -n: automatically reply "n" for all prompts regarding -# experimental and old-style packages +# Options: see usage() below. # # A package may assume that the following environment # variables are defined: @@ -100,15 +86,16 @@ Options: -o: allow fetching the package from its upstream URL when it is not available from the Sage mirrors (yet) -b: build and stage only, do not install or check - -x: only run the test suite; this may assume that: + -x: exclusively run the test suite; this may assume that: * the package has been installed already and/or that * the temporary build directory has not been deleted -c: after installing, run the test suite for the package; exit with an error on test suite failures -w: after installing, run the test suite for the package; print a warning on test suite failures - -s: do not delete the temporary build directory, even - when the installation was successful + -s: save (do not delete) the temporary build directory, + even when the installation was successful + -e: erase (delete) the temporary build directory EOF } @@ -254,7 +241,7 @@ while true; do -w|--check-warning-only) export SAGE_CHECK=warn;; -x|--check-only) - INSTALL=1;; + INSTALL=0;; -k|--keep-existing) KEEP_EXISTING=yes;; -o|--allow-upstream) @@ -267,10 +254,6 @@ while true; do shift done - -################################################################## -# Figure out the package filename, download it if needed. -################################################################## # One should be able to install a package using # sage -i @@ -322,8 +305,14 @@ fi PKG_BASE_VER=`echo $PKG_VER | sed 's/\.p[0-9][0-9]*$//'` PKG_NAME_UPSTREAM=`lookup_param tarball "$PKG_SCRIPTS/checksums.ini" | sed "s/VERSION/$PKG_BASE_VER/"` -# Warning for experimental packages -if [ x`cat "$PKG_SCRIPTS/type"` = x"experimental" -a $INFO = 0 ]; then + +if [ $INFO -ne 0 ]; then + exec sage-spkg-info $PKG_BASE +fi + + +warning_for_experimental_packages() { ############################ +if [ x`cat "$PKG_SCRIPTS/type"` = x"experimental" ]; then if [ $YES != 1 ]; then # We use /dev/tty here because our output may be redirected # to a logfile, or line-buffered. @@ -353,11 +342,10 @@ EOF echo > /dev/tty "OK, installing $PKG_NAME now..." fi fi +} ################################################################ +warning_for_experimental_packages -if [ $INFO -ne 0 ]; then - exec sage-spkg-info $PKG_BASE -fi - +ensure_pkg_src() { ############################################### # If we haven't found the package yet, we must download it if [ ! -f "$PKG_SRC" ]; then if [ -n "$PKG_NAME_UPSTREAM" ]; then @@ -394,12 +382,15 @@ if [ -n "$SAGE_SPKG_COPY_UPSTREAM" ]; then exit 1 fi fi +} ################################################################ +ensure_pkg_src + if [ -n "$SAGE_INSTALL_FETCH_ONLY" ]; then exit 0 fi ################################################################## -# Setup directories +setup_directories() { ################################################################## for dir in "$SAGE_SPKG_INST" "$SAGE_SPKG_SCRIPTS" "$SAGE_BUILD_DIR"; do @@ -451,9 +442,11 @@ if [ -e "$PKG_NAME" ]; then error_msg "Error (re)moving $PKG_NAME" exit 1 fi +} ################################################################ +setup_directories ################################################################## -# Extract the package +extract_the_package() { ################################################################## echo "Setting up build directory for $PKG_NAME" @@ -489,9 +482,12 @@ case "$PKG_SRC" in cd .. ;; esac +} ################################################################ +extract_the_package ################################################################## -# The package has been extracted, prepare for installation +# The package has been extracted, +prepare_for_installation() { ################################################################## # Rewrites the given bash pseudo-script with a boilerplate header that includes @@ -579,6 +575,12 @@ for script in $WRAPPED_SCRIPTS; do write_script_wrapper "$(pwd)/$script" "$script_dir" fi done +} ################################################################ +prepare_for_installation + +################################################################## +actually_build_and_install() { +################################################################## echo "****************************************************" echo "Host system:" @@ -618,10 +620,6 @@ if [ "$UNAME" = "CYGWIN" ]; then sage-flock -s $lock_type 200 fi -################################################################## -# Actually install -################################################################## - # Set the $SAGE_DESTDIR variable to be passed to the spkg-install # script (the script itself could set this, but better to standardize # this in one place) @@ -671,7 +669,10 @@ else exit 1 fi fi +} ################################################################ +actually_build_and_install +unload_destdir() { # To work around #26996: Remove the symlink set, or we get "cp: cannot overwrite directory" rm -f "$SAGE_DESTDIR_LOCAL/lib64" @@ -705,13 +706,14 @@ if [ -d "$SAGE_DESTDIR" ]; then rm -rf "$SAGE_DESTDIR" fi - # At this stage the path in $SAGE_DESTDIR no longer exists, so the variable # should be unset unset SAGE_DESTDIR unset SAGE_DESTDIR_LOCAL +} ################################################################ +unload_destdir - +install_scripts() { ############################################## # Some spkg scripts, if they exist, should also be installed to # $SAGE_SPKG_SCRIPTS; they are not included in the package's manifest, but are # removed by sage-spkg-uninstall @@ -739,8 +741,10 @@ for script in $INSTALLED_SCRIPTS; do fi fi done +} ################################################################ +install_scripts - +post_install() { ################################################# # Run the post-install script, if any if [ -f spkg-postinst ]; then echo "Running post-install script for $PKG_NAME." @@ -763,8 +767,10 @@ if [ "$UNAME" = "CYGWIN" ]; then sage-flock -x "$SAGE_LOCAL/var/lock/rebase.lock" \ sage-rebase.sh "$SAGE_LOCAL" 2>/dev/null fi +} ################################################################ +post_install - +run_test_suite() { ############################################### # Note: spkg-check tests are run after the package has been copied into # SAGE_INST_LOCAL. It might make more sense to run the tests before, but the # spkg-check scripts were written before use of DESTDIR installs, and so @@ -792,7 +798,10 @@ if [ "$SAGE_CHECK" = "yes" -o "$SAGE_CHECK" = "warn" ]; then TEST_SUITE_RESULT="not available" fi fi +} ################################################################ +run_test_suite +write_installation_record() { #################################### # For each line in $FILE_LIST, enclose in double quotes: NEW_LIST="" for f in $FILE_LIST; do @@ -819,13 +828,14 @@ cat > "$PKG_NAME_INSTALLED" << __EOF__ ] } __EOF__ - +} ################################################################ +write_installation_record echo "Successfully installed $PKG_NAME" ################################################################## -# Delete the temporary build directory if required +delete_the_temporary_build_directory_if_required() { ################################################################## if [ ! -e "$SAGE_BUILD_DIR/$PKG_NAME/.keep" ]; then echo "Deleting temporary build directory" @@ -838,6 +848,7 @@ else echo "You can safely delete the temporary build directory" echo "$SAGE_BUILD_DIR/$PKG_NAME" fi - +} ################################################################ +delete_the_temporary_build_directory_if_required echo "Finished installing $PKG_NAME" From aa8124c9f757e37bcaad47132a53906f733f92af Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 19 Nov 2023 11:45:41 -0800 Subject: [PATCH 103/155] build/bin/sage-spkg: Move function calls to the bottom of the file --- build/bin/sage-spkg | 109 +++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 58 deletions(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 7adef6f2a97..f998a2dcf50 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -306,11 +306,6 @@ PKG_BASE_VER=`echo $PKG_VER | sed 's/\.p[0-9][0-9]*$//'` PKG_NAME_UPSTREAM=`lookup_param tarball "$PKG_SCRIPTS/checksums.ini" | sed "s/VERSION/$PKG_BASE_VER/"` -if [ $INFO -ne 0 ]; then - exec sage-spkg-info $PKG_BASE -fi - - warning_for_experimental_packages() { ############################ if [ x`cat "$PKG_SCRIPTS/type"` = x"experimental" ]; then if [ $YES != 1 ]; then @@ -342,8 +337,7 @@ EOF echo > /dev/tty "OK, installing $PKG_NAME now..." fi fi -} ################################################################ -warning_for_experimental_packages +} ############################## warning_for_experimental_packages ensure_pkg_src() { ############################################### # If we haven't found the package yet, we must download it @@ -382,16 +376,9 @@ if [ -n "$SAGE_SPKG_COPY_UPSTREAM" ]; then exit 1 fi fi -} ################################################################ -ensure_pkg_src +} ################################################# ensure_pkg_src -if [ -n "$SAGE_INSTALL_FETCH_ONLY" ]; then - exit 0 -fi - -################################################################## -setup_directories() { -################################################################## +setup_directories() { ############################################ for dir in "$SAGE_SPKG_INST" "$SAGE_SPKG_SCRIPTS" "$SAGE_BUILD_DIR"; do mkdir -p "$dir" @@ -442,12 +429,9 @@ if [ -e "$PKG_NAME" ]; then error_msg "Error (re)moving $PKG_NAME" exit 1 fi -} ################################################################ -setup_directories +} ############################################## setup_directories -################################################################## -extract_the_package() { -################################################################## +extract_the_package() { ########################################## echo "Setting up build directory for $PKG_NAME" cp -RLp "$PKG_SCRIPTS" "$PKG_NAME" @@ -482,13 +466,10 @@ case "$PKG_SRC" in cd .. ;; esac -} ################################################################ -extract_the_package +} ############################################ extract_the_package -################################################################## # The package has been extracted, -prepare_for_installation() { -################################################################## +prepare_for_installation() { ##################################### # Rewrites the given bash pseudo-script with a boilerplate header that includes # the shebang line and sourcing sage-env. Make sure the name of the script is @@ -575,12 +556,9 @@ for script in $WRAPPED_SCRIPTS; do write_script_wrapper "$(pwd)/$script" "$script_dir" fi done -} ################################################################ -prepare_for_installation +} ####################################### prepare_for_installation -################################################################## -actually_build_and_install() { -################################################################## +actually_build_and_install() { ################################### echo "****************************************************" echo "Host system:" @@ -591,15 +569,12 @@ echo "C compiler version:" $CC -v echo "****************************************************" -################################################################## # Poison the proxy variable to forbid downloads in spkg-install -################################################################## export http_proxy=http://192.0.2.0:5187/ export https_proxy=$http_proxy export ftp_proxy=$http_proxy export rsync_proxy=$http_proxy -################################################################## # We need to run sage-rebase.sh for each package installed, but it # can be dangerous to do this while other packages are installing # so we need to use a lock to manage when rebase is allowed to @@ -609,8 +584,6 @@ export rsync_proxy=$http_proxy # that. This also unfortunately slows down parallel builds since # all packages will eventually need to wait for this lock, but # again there's no simple way around that. -################################################################## - if [ "$UNAME" = "CYGWIN" ]; then # This is a global lock - so we use SAGE_LOCAL, not SAGE_INST_LOCAL. if [ ! -d "$SAGE_LOCAL/var/lock" ]; then @@ -669,11 +642,11 @@ else exit 1 fi fi -} ################################################################ -actually_build_and_install +} ##################################### actually_build_and_install -unload_destdir() { -# To work around #26996: Remove the symlink set, or we get "cp: cannot overwrite directory" +unload_destdir() { ############################################### +# To work around #26996: Remove the symlink set, +# or we get "cp: cannot overwrite directory" rm -f "$SAGE_DESTDIR_LOCAL/lib64" # All spkgs should eventually support this, but fall back on old behavior in @@ -710,8 +683,7 @@ fi # should be unset unset SAGE_DESTDIR unset SAGE_DESTDIR_LOCAL -} ################################################################ -unload_destdir +} ################################################# unload_destdir install_scripts() { ############################################## # Some spkg scripts, if they exist, should also be installed to @@ -741,8 +713,7 @@ for script in $INSTALLED_SCRIPTS; do fi fi done -} ################################################################ -install_scripts +} ################################################ install_scripts post_install() { ################################################# # Run the post-install script, if any @@ -767,8 +738,7 @@ if [ "$UNAME" = "CYGWIN" ]; then sage-flock -x "$SAGE_LOCAL/var/lock/rebase.lock" \ sage-rebase.sh "$SAGE_LOCAL" 2>/dev/null fi -} ################################################################ -post_install +} ################################################### post_install run_test_suite() { ############################################### # Note: spkg-check tests are run after the package has been copied into @@ -783,7 +753,8 @@ if [ "$SAGE_CHECK" = "yes" -o "$SAGE_CHECK" = "warn" ]; then if [ $? -ne 0 ]; then TEST_SUITE_RESULT="failed" if [ "$SAGE_CHECK" = "warn" ]; then - # The following warning message must be consistent with SAGE_ROOT/build/make/install (see trac:32781) + # The following warning message must be consistent + # with SAGE_ROOT/build/make/install (see #32781) error_msg "Warning: Failures testing package $PKG_NAME (ignored)" "make check" else error_msg "Error testing package $PKG_NAME" "make check" @@ -798,8 +769,7 @@ if [ "$SAGE_CHECK" = "yes" -o "$SAGE_CHECK" = "warn" ]; then TEST_SUITE_RESULT="not available" fi fi -} ################################################################ -run_test_suite +} ################################################# run_test_suite write_installation_record() { #################################### # For each line in $FILE_LIST, enclose in double quotes: @@ -828,15 +798,9 @@ cat > "$PKG_NAME_INSTALLED" << __EOF__ ] } __EOF__ -} ################################################################ -write_installation_record +} ###################################### write_installation_record -echo "Successfully installed $PKG_NAME" - - -################################################################## -delete_the_temporary_build_directory_if_required() { -################################################################## +delete_the_temporary_build_directory_if_required() { ############# if [ ! -e "$SAGE_BUILD_DIR/$PKG_NAME/.keep" ]; then echo "Deleting temporary build directory" echo "$SAGE_BUILD_DIR/$PKG_NAME" @@ -848,7 +812,36 @@ else echo "You can safely delete the temporary build directory" echo "$SAGE_BUILD_DIR/$PKG_NAME" fi -} ################################################################ +} ############### delete_the_temporary_build_directory_if_required + + +################################################################## +# MAIN +################################################################## + +if [ $INFO -ne 0 ]; then + exec sage-spkg-info $PKG_BASE +fi + +warning_for_experimental_packages +ensure_pkg_src + +if [ -n "$SAGE_INSTALL_FETCH_ONLY" ]; then + exit 0 +fi + +setup_directories +extract_the_package +prepare_for_installation +actually_build_and_install +unload_destdir +install_scripts +post_install +run_test_suite +write_installation_record + +echo "Successfully installed $PKG_NAME" + delete_the_temporary_build_directory_if_required echo "Finished installing $PKG_NAME" From 3af1f455206454bdaa7255a2f7fa4029beee5e31 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 19 Nov 2023 12:17:25 -0800 Subject: [PATCH 104/155] build/bin/sage-spkg: implement new options --- build/bin/sage-spkg | 76 +++++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index f998a2dcf50..64faf19e166 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -75,6 +75,16 @@ Usage: sage {-i|-p} Search Sage's list of packages (see 'sage --package list') for a matching package, and if a match is found, install it. +Modes of operation: + -d: only download the package + -b: build and install (stage) only, do not run post-install + or check + -p: post-install only + -x: exclusively run the test suite; this may assume that: + * the package has been installed already and/or that + * the temporary build directory has not been deleted + -e: erase (delete) the temporary build directory only + Options: -y: automatically reply "y" for all prompts regarding experimental and old-style packages; warning: there @@ -82,20 +92,14 @@ Options: use at your own risk -n: automatically reply "n" for all prompts regarding experimental and old-style packages - -d: only download the package -o: allow fetching the package from its upstream URL when it is not available from the Sage mirrors (yet) - -b: build and stage only, do not install or check - -x: exclusively run the test suite; this may assume that: - * the package has been installed already and/or that - * the temporary build directory has not been deleted -c: after installing, run the test suite for the package; exit with an error on test suite failures -w: after installing, run the test suite for the package; print a warning on test suite failures -s: save (do not delete) the temporary build directory, even when the installation was successful - -e: erase (delete) the temporary build directory EOF } @@ -222,8 +226,9 @@ fi INFO=0 YES=0 KEEP_EXISTING=0 -BUILD=1 INSTALL=1 +POST_INSTALL=1 +ERASE_ONLY=0 while true; do case "$1" in --info) @@ -240,10 +245,16 @@ while true; do export SAGE_CHECK=yes;; -w|--check-warning-only) export SAGE_CHECK=warn;; + -b|--build-and-stage-only) + POST_INSTALL=0; export SAGE_CHECK=no;; + -p|--post-install-only) + INSTALL=0; export SAGE_CHECK=no;; -x|--check-only) - INSTALL=0;; + INSTALL=0; POST_INSTALL=0; export SAGE_CHECK=yes;; -k|--keep-existing) KEEP_EXISTING=yes;; + -e|--erase-build-directory-only) + ERASE_ONLY=1;; -o|--allow-upstream) SAGE_DOWNLOAD_FILE_OPTIONS+=" --allow-upstream";; -*) @@ -800,14 +811,18 @@ cat > "$PKG_NAME_INSTALLED" << __EOF__ __EOF__ } ###################################### write_installation_record -delete_the_temporary_build_directory_if_required() { ############# -if [ ! -e "$SAGE_BUILD_DIR/$PKG_NAME/.keep" ]; then +delete_the_temporary_build_directory() { ######################### echo "Deleting temporary build directory" echo "$SAGE_BUILD_DIR/$PKG_NAME" # On Solaris, the current working directory cannot be deleted, # so we "cd" out of $SAGE_BUILD_DIR/$PKG_NAME. See #12637. cd "$SAGE_BUILD_DIR" rm -rf "$SAGE_BUILD_DIR/$PKG_NAME" +} ########################### delete_the_temporary_build_directory + +delete_the_temporary_build_directory_if_required() { ############# +if [ ! -e "$SAGE_BUILD_DIR/$PKG_NAME/.keep" ]; then + delete_the_temporary_build_directory else echo "You can safely delete the temporary build directory" echo "$SAGE_BUILD_DIR/$PKG_NAME" @@ -823,25 +838,38 @@ if [ $INFO -ne 0 ]; then exec sage-spkg-info $PKG_BASE fi -warning_for_experimental_packages -ensure_pkg_src +if [ $ERASE_ONLY = 1 ]; then + delete_the_temporary_build_directory + exit 0 +fi + +if [ $INSTALL = 1 ]; then + warning_for_experimental_packages + ensure_pkg_src +fi if [ -n "$SAGE_INSTALL_FETCH_ONLY" ]; then exit 0 fi -setup_directories -extract_the_package -prepare_for_installation -actually_build_and_install -unload_destdir -install_scripts -post_install -run_test_suite -write_installation_record +if [ $INSTALL = 1 ]; then + setup_directories + extract_the_package + prepare_for_installation + actually_build_and_install +fi -echo "Successfully installed $PKG_NAME" +if [ $POST_INSTALL = 1 ]; then + unload_destdir + install_scripts + post_install +fi -delete_the_temporary_build_directory_if_required +run_test_suite -echo "Finished installing $PKG_NAME" +if [ $POST_INSTALL = 1 ]; then + write_installation_record + echo "Successfully installed $PKG_NAME" + delete_the_temporary_build_directory_if_required + echo "Finished installing $PKG_NAME" +fi From 8628f2e5a056bc4880d746cba6c66527e9c9ea7b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 19 Nov 2023 14:39:37 -0800 Subject: [PATCH 105/155] build/bin/sage-spkg: Move some variable settings to top --- build/bin/sage-spkg | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 64faf19e166..8534d4ae37b 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -316,6 +316,20 @@ fi PKG_BASE_VER=`echo $PKG_VER | sed 's/\.p[0-9][0-9]*$//'` PKG_NAME_UPSTREAM=`lookup_param tarball "$PKG_SCRIPTS/checksums.ini" | sed "s/VERSION/$PKG_BASE_VER/"` +# Set the $SAGE_DESTDIR variable to be passed to the spkg-install +# script (the script itself could set this, but better to standardize +# this in one place) +export SAGE_DESTDIR="${SAGE_BUILD_DIR}/${PKG_NAME}/inst" + +# The actual prefix where the installation will be staged. This is the +# directory that you need to work in if you want to change the staged +# installation tree (before final installation to $SAGE_INST_LOCAL) at the +# end of spkg-install. +export SAGE_DESTDIR_LOCAL="${SAGE_DESTDIR}${SAGE_INST_LOCAL}" + +INSTALLED_SCRIPTS="prerm piprm postrm" +WRAPPED_SCRIPTS="build install check preinst postinst $INSTALLED_SCRIPTS" + warning_for_experimental_packages() { ############################ if [ x`cat "$PKG_SCRIPTS/type"` = x"experimental" ]; then @@ -543,10 +557,6 @@ __EOF__ trap - ERR } - -INSTALLED_SCRIPTS="prerm piprm postrm" -WRAPPED_SCRIPTS="build install check preinst postinst $INSTALLED_SCRIPTS" - # Prepare script for uninstallation of packages that use sdh_pip_install # or sdh_store_and_pip_install_wheel. echo 'sdh_pip_uninstall -r $SAGE_SPKG_SCRIPTS/$PKG_BASE/spkg-requirements.txt' > spkg-piprm.in @@ -604,17 +614,6 @@ if [ "$UNAME" = "CYGWIN" ]; then sage-flock -s $lock_type 200 fi -# Set the $SAGE_DESTDIR variable to be passed to the spkg-install -# script (the script itself could set this, but better to standardize -# this in one place) -export SAGE_DESTDIR="${SAGE_BUILD_DIR}/${PKG_NAME}/inst" - -# The actual prefix where the installation will be staged. This is the -# directory that you need to work in if you want to change the staged -# installation tree (before final installation to $SAGE_INST_LOCAL) at the -# end of spkg-install. -export SAGE_DESTDIR_LOCAL="${SAGE_DESTDIR}${SAGE_INST_LOCAL}" - # First uninstall the previous version of this package, if any if [ "$KEEP_EXISTING" != "yes" ]; then sage-spkg-uninstall "$PKG_BASE" "$SAGE_INST_LOCAL" From 5aa97fe1cc16d9a837c94d20728076bac2f3c249 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 19 Nov 2023 14:54:35 -0800 Subject: [PATCH 106/155] build/bin/sage-spkg: Fix build directory handling when using -x, -p --- build/bin/sage-spkg | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 8534d4ae37b..d097cd83588 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -458,6 +458,7 @@ fi extract_the_package() { ########################################## +cd "$SAGE_BUILD_DIR" || exit $? echo "Setting up build directory for $PKG_NAME" cp -RLp "$PKG_SCRIPTS" "$PKG_NAME" cd "$PKG_NAME" || exit $? @@ -661,8 +662,8 @@ rm -f "$SAGE_DESTDIR_LOCAL/lib64" # All spkgs should eventually support this, but fall back on old behavior in # case DESTDIR=$SAGE_DESTDIR installation was not used -echo "Copying package files from temporary location $SAGE_DESTDIR to $SAGE_INST_LOCAL" if [ -d "$SAGE_DESTDIR" ]; then + echo "Copying package files from temporary location $SAGE_DESTDIR to $SAGE_INST_LOCAL" # Some `find` implementations will put superfluous slashes in the # output if we give them a directory name with a slash; so make sure # any trailing slash is removed; https://github.com/sagemath/sage/issues/26013 @@ -687,6 +688,9 @@ if [ -d "$SAGE_DESTDIR" ]; then # Remove the $SAGE_DESTDIR entirely once all files have been moved to their # final location. rm -rf "$SAGE_DESTDIR" +else + echo "The temporary location $SAGE_DESTDIR does not exist; has the build directory been deleted?" + exit 1 fi # At this stage the path in $SAGE_DESTDIR no longer exists, so the variable @@ -856,6 +860,8 @@ if [ $INSTALL = 1 ]; then extract_the_package prepare_for_installation actually_build_and_install +else + cd "$SAGE_BUILD_DIR/$PKG_NAME" || exit $? fi if [ $POST_INSTALL = 1 ]; then From 7df77de0a032fc813942816d91c34bec6af5da9e Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Mon, 20 Nov 2023 13:50:24 +0100 Subject: [PATCH 107/155] make sure we get twisting of arbitrary simplices --- src/sage/categories/simplicial_sets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/categories/simplicial_sets.py b/src/sage/categories/simplicial_sets.py index f568c4cef23..99b06e1628e 100644 --- a/src/sage/categories/simplicial_sets.py +++ b/src/sage/categories/simplicial_sets.py @@ -712,7 +712,7 @@ def twist(s): if s in twop: return twop[s] if s.dimension() > 1: - return twist(self.face_data()[s][-1]) + return twist(self.face(s,s.dimension())) return 1 base_ring = cm.common_parent(*twop.values()) From b9ceb3ad5b0cdb05e684926d5da2715e513c8b6f Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Tue, 21 Nov 2023 09:38:44 +0900 Subject: [PATCH 108/155] Plant anchors for hunks --- .github/workflows/doc-build.yml | 65 ++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index b0f3e4566bc..3744489b34a 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -144,18 +144,32 @@ jobs: cat >> ./docs/CHANGES.html << EOF @@ -164,19 +178,36 @@ jobs: echo '' >> ./docs/CHANGES.html (cd /sage/local/share/doc/sage/html && git diff HEAD^ -- *.html; rm -rf .git) > ./docs/diff.txt /sage/sage -python - << EOF - import re, html + import os, re, html with open('./docs/diff.txt', 'r') as f: - diff_text = f.read() - diff_blocks = re.split(r'^(?=diff --git)', diff_text, flags=re.MULTILINE) - out_blocks = [] - for block in diff_blocks: - match = re.search(r'^diff --git a/(.*) b/\1', block, flags=re.MULTILINE) - if match: - path = 'html/' + match.group(1) - out_blocks.append(f'

{path}

\n
' + html.escape(block).strip() + '
') - output_text = '\n'.join(out_blocks) + diff_text = f.read() + diff_blocks = re.split(r'^(?=diff --git)', diff_text, flags=re.MULTILINE) + out_blocks = [] + for block in diff_blocks: + match = re.search(r'^diff --git a/(.*) b/\1', block, flags=re.MULTILINE) + if match: + path = 'html/' + match.group(1) + file_path = os.path.join('/sage/local/share/doc/sage', path) + with open(file_path, 'r') as file: + content = file.readlines() + count = 0 + for line in block.splitlines(): + if line.startswith('@@ -'): + line_number = int(re.search(r'@@ -(\d+)', line).group(1)) + for i in range(line_number, -1, -1): + if content[i].startswith('<'): + count += 1 + content[i] = f'' + content[i] + break + with open(file_path, 'w') as file: + file.writelines(content) + hunks = ' '.join(f'#{i+1}' for i in range(count)) + out_blocks.append(f'

{path} ' + hunks + ' 

' + + '\n
'
+                                  + html.escape(block).strip() + '
') + output_text = '\n'.join(out_blocks) with open('./docs/diff.html', 'w') as f: - f.write(output_text) + f.write(output_text) EOF cat ./docs/diff.html >> ./docs/CHANGES.html echo '' >> ./docs/CHANGES.html From aca1279eb1d1d2a57d9de3c4b6369565fced698d Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Tue, 21 Nov 2023 13:28:44 +0900 Subject: [PATCH 109/155] Fix a typo --- .github/workflows/doc-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 3744489b34a..2721d5b420a 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -149,7 +149,7 @@ jobs: const diffParagraphs = document.querySelectorAll('p.diff'); diffParagraphs.forEach(paragraph => { const rootURL = window.location.origin; - const docAnchor = paragraph.querySelector('a'); # first "a" element + const docAnchor = paragraph.querySelector('a'); // first "a" element const url = new URL(docAnchor.href); const path = url.pathname; const anchor = document.createElement('a'); From e193178afd76da250ab12c4d5a525865895bfd19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 21 Nov 2023 10:07:41 +0100 Subject: [PATCH 110/155] pep8 for maxima-lib interface --- src/sage/interfaces/maxima_lib.py | 214 ++++++++++++++++-------------- 1 file changed, 117 insertions(+), 97 deletions(-) diff --git a/src/sage/interfaces/maxima_lib.py b/src/sage/interfaces/maxima_lib.py index 211018e52cc..ea40cf4ed8a 100644 --- a/src/sage/interfaces/maxima_lib.py +++ b/src/sage/interfaces/maxima_lib.py @@ -120,11 +120,18 @@ from sage.libs.ecl import EclObject, ecl_eval from .maxima_abstract import (MaximaAbstract, MaximaAbstractFunction, - MaximaAbstractElement, MaximaAbstractFunctionElement, - MaximaAbstractElementFunction) + MaximaAbstractElement, MaximaAbstractFunctionElement, + MaximaAbstractElementFunction) from sage.misc.instancedoc import instancedoc from sage.env import MAXIMA_FAS +import sage.rings.real_double +import sage.symbolic.expression +import sage.symbolic.integration.integral + +from sage.rings.number_field.number_field_element_base import NumberFieldElement_base +from sage.symbolic.operators import FDerivativeOperator, add_vararg, mul_vararg + # We begin here by initializing Maxima in library mode # i.e. loading it into ECL @@ -203,15 +210,15 @@ (make-concatenated-stream) (make-broadcast-stream)))""") ecl_eval("(setf original-standard-output *standard-output*)") ecl_eval("(setf *standard-output* *dev-null*)") -#ecl_eval("(setf *error-output* *dev-null*)") +# ecl_eval("(setf *error-output* *dev-null*)") # Default options set in Maxima # display2d -- no ascii art output # keepfloat -- don't automatically convert floats to rationals init_code = ['besselexpand : true', 'display2d : false', 'domain : complex', 'keepfloat : true', - 'load(to_poly_solve)', 'load(simplify_sum)', - 'load(diag)'] + 'load(to_poly_solve)', 'load(simplify_sum)', + 'load(diag)'] # Turn off the prompt labels, since computing them *very @@ -225,7 +232,7 @@ ecl_eval("#$%s$" % l) # To get more debug information uncomment the next line # should allow to do this through a method -#ecl_eval("(setf *standard-output* original-standard-output)") +# ecl_eval("(setf *standard-output* original-standard-output)") # This is the main function (ECL object) used for evaluation # This returns an EclObject @@ -239,7 +246,7 @@ # Here we define several useful ECL/Maxima objects # The Maxima string function can change the structure of its input -#maxprint=EclObject("$STRING") +# maxprint=EclObject("$STRING") maxprint = EclObject(r"""(defun mstring-for-sage (form) (coerce (mstring form) 'string))""").eval() meval = EclObject("MEVAL") @@ -262,6 +269,7 @@ max_to_poly_solve = EclObject("$TO_POLY_SOLVE") max_at = EclObject("%AT") + def stdout_to_string(s): r""" Evaluate command ``s`` and catch Maxima stdout @@ -286,6 +294,7 @@ def stdout_to_string(s): return ecl_eval(r"""(with-output-to-string (*standard-output*) (maxima-eval #$%s$))""" % s).python()[1:-1] + def max_to_string(s): r""" Return the Maxima string corresponding to this ECL object. @@ -311,6 +320,7 @@ def max_to_string(s): (caddr (mread (make-string-input-stream cmd)))) """) + def parse_max_string(s): r""" Evaluate string in Maxima without *any* further simplification. @@ -329,6 +339,7 @@ def parse_max_string(s): """ return my_mread('"%s;"' % s) + class MaximaLib(MaximaAbstract): """ Interface to Maxima as a Library. @@ -377,7 +388,7 @@ def __init__(self): global init_code self.__init_code = init_code - MaximaAbstract.__init__(self,"maxima_lib") + MaximaAbstract.__init__(self, "maxima_lib") self.__seq = 0 def _coerce_from_special_method(self, x): @@ -398,9 +409,8 @@ def _coerce_from_special_method(self, x): """ if isinstance(x, EclObject): - return MaximaLibElement(self,self._create(x)) - else: - return MaximaAbstract._coerce_from_special_method(self,x) + return MaximaLibElement(self, self._create(x)) + return MaximaAbstract._coerce_from_special_method(self, x) def __reduce__(self): r""" @@ -466,12 +476,12 @@ def _eval_line(self, line, locals=None, reformat=True, **kwds): line = '' else: statement = line[:ind_semi] - line = line[ind_semi+1:] + line = line[ind_semi + 1:] if statement: result = ((result + '\n') if result else '') + max_to_string(maxima_eval("#$%s$" % statement)) else: statement = line[:ind_dollar] - line = line[ind_dollar+1:] + line = line[ind_dollar + 1:] if statement: maxima_eval("#$%s$" % statement) if not reformat: @@ -616,13 +626,13 @@ def _create(self, value, name=None): """ name = self._next_var_name() if name is None else name try: - if isinstance(value,EclObject): - maxima_eval([[msetq],cadadr("#$%s$#$" % name),value]) + if isinstance(value, EclObject): + maxima_eval([[msetq], cadadr("#$%s$#$" % name), value]) else: self.set(name, value) except RuntimeError as error: s = str(error) - if "Is" in s: # Maxima asked for a condition + if "Is" in s: # Maxima asked for a condition self._missing_assumption(s) else: raise @@ -697,7 +707,7 @@ def _object_function_class(self): # and return something that is hopefully coercible into the symbolic # ring again. - def sr_integral(self,*args): + def sr_integral(self, *args): """ Helper function to wrap calculus use of Maxima's integration. @@ -804,19 +814,21 @@ def sr_integral(self,*args): """ try: - return max_to_sr(maxima_eval(([max_integrate],[sr_to_max(SR(a)) for a in args]))) + return max_to_sr(maxima_eval(([max_integrate], + [sr_to_max(SR(a)) for a in args]))) except RuntimeError as error: s = str(error) if "Divergent" in s or "divergent" in s: -# in pexpect interface, one looks for this - e.g. integrate(1/x^3,x,-1,3) gives a principal value -# if "divergent" in s or 'Principal Value' in s: + # in pexpect interface, one looks for this + # - e.g. integrate(1/x^3,x,-1,3) gives a principal value + # if "divergent" in s or 'Principal Value' in s: raise ValueError("Integral is divergent.") - elif "Is" in s: # Maxima asked for a condition + elif "Is" in s: # Maxima asked for a condition self._missing_assumption(s) else: raise - def sr_sum(self,*args): + def sr_sum(self, *args): """ Helper function to wrap calculus use of Maxima's summation. @@ -889,20 +901,23 @@ def sr_sum(self,*args): RuntimeError: ECL says: Zero to negative power computed. """ try: - return max_to_sr(maxima_eval([[max_ratsimp],[[max_simplify_sum],([max_sum],[sr_to_max(SR(a)) for a in args])]])) + return max_to_sr(maxima_eval([[max_ratsimp], + [[max_simplify_sum], + ([max_sum], + [sr_to_max(SR(a)) for a in args])]])) except RuntimeError as error: s = str(error) if "divergent" in s: -# in pexpect interface, one looks for this; -# could not find an example where 'Pole encountered' occurred, though -# if "divergent" in s or 'Pole encountered' in s: + # in pexpect interface, one looks for this; + # could not find an example where 'Pole encountered' occurred, though + # if "divergent" in s or 'Pole encountered' in s: raise ValueError("Sum is divergent.") - elif "Is" in s: # Maxima asked for a condition + elif "Is" in s: # Maxima asked for a condition self._missing_assumption(s) else: raise - def sr_prod(self,*args): + def sr_prod(self, *args): """ Helper function to wrap calculus use of Maxima's product. @@ -917,7 +932,10 @@ def sr_prod(self,*args): """ try: - return max_to_sr(maxima_eval([[max_ratsimp],[[max_simplify_prod],([max_prod],[sr_to_max(SR(a)) for a in args])]])) + return max_to_sr(maxima_eval([[max_ratsimp], + [[max_simplify_prod], + ([max_prod], + [sr_to_max(SR(a)) for a in args])]])) except RuntimeError as error: s = str(error) if "divergent" in s: @@ -1007,7 +1025,7 @@ def sr_limit(self, expr, v, a, dir=None): return max_to_sr(maxima_eval(([max_limit], L))) except RuntimeError as error: s = str(error) - if "Is" in s: # Maxima asked for a condition + if "Is" in s: # Maxima asked for a condition self._missing_assumption(s) else: raise @@ -1029,7 +1047,7 @@ def sr_tlimit(self, expr, v, a, dir=None): L.append(max_minus) return max_to_sr(maxima_eval(([max_tlimit], L))) - def _missing_assumption(self,errstr): + def _missing_assumption(self, errstr): """ Helper function for unified handling of failed computation because an assumption was missing. @@ -1048,13 +1066,14 @@ def _missing_assumption(self,errstr): jj = 2 if errstr[3] == ' ': jj = 3 - k = errstr.find(' ',jj+1) + k = errstr.find(' ', jj + 1) outstr = "Computation failed since Maxima requested additional constraints; using the 'assume' command before evaluation *may* help (example of legal syntax is 'assume("\ - + errstr[jj+1:k] + ">0)', see `assume?` for more details)\n" + errstr - outstr = outstr.replace('_SAGE_VAR_','') + + errstr[jj + 1:k] + ">0)', see `assume?` for more details)\n" + errstr + outstr = outstr.replace('_SAGE_VAR_', '') raise ValueError(outstr) + def is_MaximaLibElement(x): r""" Return True if ``x`` is of type :class:`MaximaLibElement`. @@ -1113,7 +1132,7 @@ def ecl(self): self._ecl = maxima_eval("#$%s$" % self._name) return self._ecl - def to_poly_solve(self,vars,options=""): + def to_poly_solve(self, vars, options=""): r""" Use Maxima's to_poly_solver package. @@ -1137,7 +1156,7 @@ def to_poly_solve(self,vars,options=""): """ if options.find("use_grobner=true") != -1: cmd = EclObject([[max_to_poly_solve], self.ecl(), sr_to_max(vars), - [[mequal],max_use_grobner,True]]) + [[mequal], max_use_grobner, True]]) else: cmd = EclObject([[max_to_poly_solve], self.ecl(), sr_to_max(vars)]) return self.parent()(maxima_eval(cmd)) @@ -1167,7 +1186,7 @@ def display2d(self, onscreen=True): P = self.parent() P._eval_line('display2d : true$') s = stdout_to_string('disp(%s)' % self.name()) - #s = P._eval_line('disp(%s)$'%self.name()) + # s = P._eval_line('disp(%s)$'%self.name()) P._eval_line('display2d : false$') s = s.strip('\r\n') @@ -1182,6 +1201,7 @@ def display2d(self, onscreen=True): MaximaLibFunctionElement = MaximaAbstractFunctionElement MaximaLibFunction = MaximaAbstractFunction + @instancedoc class MaximaLibElementFunction(MaximaLibElement, MaximaAbstractElementFunction): pass @@ -1209,13 +1229,6 @@ def reduce_load_MaximaLib(): # Smart translations between SR and Maxima ############################################# -import sage.rings.real_double -import sage.symbolic.expression -import sage.symbolic.integration.integral - -from sage.rings.number_field.number_field_element_base import NumberFieldElement_base -from sage.symbolic.operators import FDerivativeOperator, add_vararg, mul_vararg - car = EclObject("car") cdr = EclObject("cdr") caar = EclObject("caar") @@ -1230,36 +1243,36 @@ def reduce_load_MaximaLib(): # Dictionaries for standard operators sage_op_dict = { - sage.functions.other.abs : "MABS", - add_vararg : "MPLUS", - sage.symbolic.expression.operator.truediv : "MQUOTIENT", - sage.symbolic.expression.operator.eq : "MEQUAL", - sage.symbolic.expression.operator.ge : "MGEQP", - sage.symbolic.expression.operator.gt : "MGREATERP", - sage.symbolic.expression.operator.le : "MLEQP", - sage.symbolic.expression.operator.lt : "MLESSP", - mul_vararg : "MTIMES", - sage.symbolic.expression.operator.ne : "MNOTEQUAL", - sage.symbolic.expression.operator.neg : "MMINUS", - sage.symbolic.expression.operator.pow : "MEXPT", - sage.symbolic.expression.operator.or_ : "MOR", - sage.symbolic.expression.operator.and_ : "MAND", - sage.functions.log.ln : "%LOG", - sage.functions.log.log : "%LOG", - sage.functions.log.lambert_w : "%LAMBERT_W", - sage.functions.other.factorial : "MFACTORIAL", - sage.functions.error.erf : "%ERF", - sage.functions.gamma.gamma_inc : "%GAMMA_INCOMPLETE", - sage.functions.other.conjugate : "$CONJUGATE", + sage.functions.other.abs: "MABS", + add_vararg: "MPLUS", + sage.symbolic.expression.operator.truediv: "MQUOTIENT", + sage.symbolic.expression.operator.eq: "MEQUAL", + sage.symbolic.expression.operator.ge: "MGEQP", + sage.symbolic.expression.operator.gt: "MGREATERP", + sage.symbolic.expression.operator.le: "MLEQP", + sage.symbolic.expression.operator.lt: "MLESSP", + mul_vararg: "MTIMES", + sage.symbolic.expression.operator.ne: "MNOTEQUAL", + sage.symbolic.expression.operator.neg: "MMINUS", + sage.symbolic.expression.operator.pow: "MEXPT", + sage.symbolic.expression.operator.or_: "MOR", + sage.symbolic.expression.operator.and_: "MAND", + sage.functions.log.ln: "%LOG", + sage.functions.log.log: "%LOG", + sage.functions.log.lambert_w: "%LAMBERT_W", + sage.functions.other.factorial: "MFACTORIAL", + sage.functions.error.erf: "%ERF", + sage.functions.gamma.gamma_inc: "%GAMMA_INCOMPLETE", + sage.functions.other.conjugate: "$CONJUGATE", } -#we compile the dictionary -sage_op_dict = dict([(k,EclObject(sage_op_dict[k])) for k in sage_op_dict]) -max_op_dict = dict([(sage_op_dict[k],k) for k in sage_op_dict]) +# we compile the dictionary +sage_op_dict = dict([(k, EclObject(sage_op_dict[k])) for k in sage_op_dict]) +max_op_dict = dict([(sage_op_dict[k], k) for k in sage_op_dict]) # Here we correct the dictionaries for some simple operators -def sage_rat(x,y): +def sage_rat(x, y): r""" Return quotient x/y. @@ -1277,7 +1290,7 @@ def sage_rat(x,y): sage: sage_rat(1,7) 1/7 """ - return x/y + return x / y mplus = EclObject("MPLUS") @@ -1331,7 +1344,8 @@ def mrat_to_sage(expr): sage: mrat_to_sage(c.ecl()) (x^6*z^8 + y*z^9 + y^3 + x*y)/(x^6*y) """ - return max_to_sr(meval(EclObject([[ratdisrep],expr]))) + return max_to_sr(meval(EclObject([[ratdisrep], expr]))) + def mqapply_to_sage(expr): r""" @@ -1370,6 +1384,7 @@ def mqapply_to_sage(expr): args = [max_to_sr(a) for a in max_args] return op(*args) + def mdiff_to_sage(expr): r""" Special conversion rule for %DERIVATIVE expressions. @@ -1391,6 +1406,7 @@ def mdiff_to_sage(expr): """ return max_to_sr(expr.cadr()).diff(*[max_to_sr(e) for e in expr.cddr()]) + def mlist_to_sage(expr): r""" Special conversion rule for MLIST expressions. @@ -1412,6 +1428,7 @@ def mlist_to_sage(expr): """ return [max_to_sr(x) for x in expr.cdr()] + def max_at_to_sage(expr): r""" Special conversion rule for AT expressions. @@ -1439,12 +1456,13 @@ def max_at_to_sage(expr): arg = max_to_sr(expr.cadr()) subsarg = caddr(expr) if caar(subsarg) == mlist: - subsvalues = dict( (v.lhs(),v.rhs()) for v in max_to_sr(subsarg)) + subsvalues = {v.lhs(): v.rhs() for v in max_to_sr(subsarg)} else: v = max_to_sr(subsarg) - subsvalues = dict([(v.lhs(),v.rhs())]) + subsvalues = dict([(v.lhs(), v.rhs())]) return SR(arg).subs(subsvalues) + def dummy_integrate(expr): r""" We would like to simply tie Maxima's integrate to @@ -1477,11 +1495,11 @@ def dummy_integrate(expr): args = [max_to_sr(a) for a in cdr(expr)] if len(args) == 4: return sage.symbolic.integration.integral.definite_integral(*args, - hold=True) - else: - return sage.symbolic.integration.integral.indefinite_integral(*args, + hold=True) + return sage.symbolic.integration.integral.indefinite_integral(*args, hold=True) + def max_harmonic_to_sage(expr): """ EXAMPLES:: @@ -1527,12 +1545,12 @@ def max_pochhammer_to_sage(expr): } special_sage_to_max = { - sage.functions.log.polylog : lambda N,X : [[mqapply],[[max_li, max_array],N],X], - sage.functions.gamma.psi1 : lambda X : [[mqapply],[[max_psi, max_array],0],X], - sage.functions.gamma.psi2 : lambda N,X : [[mqapply],[[max_psi, max_array],N],X], - sage.functions.log.lambert_w : lambda N,X : [[max_lambert_w], X] if N == EclObject(0) else [[mqapply],[[max_lambert_w, max_array],N],X], - sage.functions.log.harmonic_number : lambda N,X : [[max_harmo],X,N], - sage.functions.hypergeometric.hypergeometric : lambda A, B, X : [[mqapply],[[max_hyper, max_array],lisp_length(A.cdr()),lisp_length(B.cdr())],A,B,X] + sage.functions.log.polylog: lambda N, X: [[mqapply], [[max_li, max_array], N], X], + sage.functions.gamma.psi1: lambda X: [[mqapply], [[max_psi, max_array], 0], X], + sage.functions.gamma.psi2: lambda N, X: [[mqapply], [[max_psi, max_array], N], X], + sage.functions.log.lambert_w: lambda N, X: [[max_lambert_w], X] if N == EclObject(0) else [[mqapply], [[max_lambert_w, max_array], N], X], + sage.functions.log.harmonic_number: lambda N, X: [[max_harmo], X, N], + sage.functions.hypergeometric.hypergeometric: lambda A, B, X: [[mqapply], [[max_hyper, max_array], lisp_length(A.cdr()), lisp_length(B.cdr())], A, B, X] } @@ -1544,6 +1562,8 @@ def max_pochhammer_to_sage(expr): # Generic conversion functions max_i = EclObject("$%I") + + def pyobject_to_max(obj): r""" Convert a (simple) Python object into a Maxima object. @@ -1572,15 +1592,16 @@ def pyobject_to_max(obj): ... TypeError: Unimplemented type for python_to_ecl """ - if isinstance(obj,sage.rings.rational.Rational): - return EclObject(obj) if (obj.denom().is_one()) else EclObject([[rat], obj.numer(),obj.denom()]) + if isinstance(obj, sage.rings.rational.Rational): + return EclObject(obj) if (obj.denom().is_one()) else EclObject([[rat], obj.numer(), obj.denom()]) elif isinstance(obj, NumberFieldElement_base): from sage.rings.number_field.number_field_element_quadratic import NumberFieldElement_quadratic - if isinstance(obj, NumberFieldElement_quadratic) and obj.parent().defining_polynomial().list() == [1,0,1]: + if isinstance(obj, NumberFieldElement_quadratic) and obj.parent().defining_polynomial().list() == [1, 0, 1]: re, im = obj.list() return EclObject([[mplus], pyobject_to_max(re), [[mtimes], pyobject_to_max(im), max_i]]) return EclObject(obj) + # This goes from SR to EclObject def sr_to_max(expr): r""" @@ -1615,12 +1636,11 @@ def sr_to_max(expr): sage: f_prime = f(x).diff(x) sage: max_to_sr(sr_to_max(f_prime(x = 1))) D[0](f)(1) - """ global sage_op_dict, max_op_dict global sage_sym_dict, max_sym_dict if isinstance(expr, (list, tuple)): - return EclObject(([mlist],[sr_to_max(e) for e in expr])) + return EclObject(([mlist], [sr_to_max(e) for e in expr])) op = expr.operator() if op: # Stolen from sage.symbolic.expression_conversion @@ -1629,8 +1649,8 @@ def sr_to_max(expr): # (we need to have access to op, not only to expr.operands() if isinstance(op, FDerivativeOperator): args = expr.operands() - if (not all(isinstance(v, Expression) and v.is_symbol() for v in args) or - len(args) != len(set(args))): + if (not all(isinstance(v, Expression) and v.is_symbol() for v in args) + or len(args) != len(set(args))): # An evaluated derivative of the form f'(1) is not a # symbolic variable, yet we would like to treat it # like one. So, we replace the argument `1` with a @@ -1642,37 +1662,37 @@ def sr_to_max(expr): temp_args = [SR.symbol("_symbol%s" % i) for i in range(len(args))] f = sr_to_max(op.function()(*temp_args)) params = op.parameter_set() - deriv_max = [[mdiff],f] + deriv_max = [[mdiff], f] for i in set(params): deriv_max.extend([sr_to_max(temp_args[i]), EclObject(params.count(i))]) at_eval = sr_to_max([temp_args[i] == args[i] for i in range(len(args))]) - return EclObject([[max_at],deriv_max,at_eval]) + return EclObject([[max_at], deriv_max, at_eval]) f = sr_to_max(op.function()(*args)) params = op.parameter_set() deriv_max = [] [deriv_max.extend([sr_to_max(args[i]), EclObject(params.count(i))]) for i in set(params)] - l = [[mdiff],f] + l = [[mdiff], f] l.extend(deriv_max) return EclObject(l) elif (op in special_sage_to_max): return EclObject(special_sage_to_max[op](*[sr_to_max(o) for o in expr.operands()])) elif op == tuple: - return EclObject( ([mlist],list(sr_to_max(op) for op in expr.operands())) ) + return EclObject(([mlist], list(sr_to_max(op) for op in expr.operands()))) elif not (op in sage_op_dict): # Maxima does some simplifications automatically by default # so calling maxima(expr) can change the structure of expr - #op_max=caar(maxima(expr).ecl()) + # op_max=caar(maxima(expr).ecl()) # This should be safe if we treated all special operators above - #furthermore, this should already use any _maxima_ methods on op, so use any - #conversion methods that are registered in pynac. + # furthermore, this should already use any _maxima_ methods on op, so use any + # conversion methods that are registered in pynac. op_max = maxima(op).ecl() if op_max in max_op_dict: raise RuntimeError("Encountered operator mismatch in sr-to-maxima translation") sage_op_dict[op] = op_max max_op_dict[op_max] = op return EclObject(([sage_op_dict[op]], - [sr_to_max(o) for o in expr.operands()])) + [sr_to_max(o) for o in expr.operands()])) elif expr.is_symbol() or expr._is_registered_constant_(): if expr not in sage_sym_dict: sym_max = maxima(expr).ecl() From 62eb1d58d55812f186493a93ae6e5e8ae8d55ef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 21 Nov 2023 11:32:47 +0100 Subject: [PATCH 111/155] pep8 for axiom and sympy interfaces --- src/sage/interfaces/axiom.py | 79 +++++++++++++------------- src/sage/interfaces/sympy.py | 105 +++++++++++++++++++++++++++-------- 2 files changed, 121 insertions(+), 63 deletions(-) diff --git a/src/sage/interfaces/axiom.py b/src/sage/interfaces/axiom.py index 5df8d2e184a..c6ca4f7e747 100644 --- a/src/sage/interfaces/axiom.py +++ b/src/sage/interfaces/axiom.py @@ -317,8 +317,7 @@ def _commands(self): i = s.find(start) end = "To get more information about" j = s.find(end) - s = s[i+len(start):j].split() - return s + return s[i + len(start):j].split() def _tab_completion(self, verbose=True, use_disk_cache=True): """ @@ -357,15 +356,15 @@ def _tab_completion(self, verbose=True, use_disk_cache=True): print("To force rebuild later, delete %s." % self._COMMANDS_CACHE) v = self._commands() - #Process we now need process the commands to strip out things which - #are not valid Python identifiers. + # Process we now need process the commands to strip out things which + # are not valid Python identifiers. valid = re.compile('[^a-zA-Z0-9_]+') names = [x for x in v if valid.search(x) is None] - #Change everything that ends with ? to _q and - #everything that ends with ! to _e - names += [x[:-1]+"_q" for x in v if x.endswith("?")] - names += [x[:-1]+"_e" for x in v if x.endswith("!")] + # Change everything that ends with ? to _q and + # everything that ends with ! to _e + names += [x[:-1] + "_q" for x in v if x.endswith("?")] + names += [x[:-1] + "_e" for x in v if x.endswith("!")] self.__tab_completion = names if len(v) > 200: @@ -430,7 +429,7 @@ def _eval_line(self, line, reformat=True, allow_use_file=False, if self._expect is None: self._start() if allow_use_file and self.__eval_using_file_cutoff and \ - len(line) > self.__eval_using_file_cutoff: + len(line) > self.__eval_using_file_cutoff: return self._eval_line_using_file(line) try: E = self._expect @@ -458,14 +457,14 @@ def _eval_line(self, line, reformat=True, allow_use_file=False, return out # out = out.lstrip() i = out.find('\n') - out = out[i+1:] + out = out[i + 1:] outs = out.split("\n") i = 0 for line in outs: line = line.rstrip() if line[:4] == ' (': i = line.find('(') - i += line[i:].find(')')+1 + i += line[i:].find(')') + 1 if line[i:] == "": i = 0 outs = outs[1:] @@ -598,14 +597,13 @@ def _richcmp_(self, other, op): sage: f = axiom('sin(x)'); g = axiom('cos(x)') #optional - axiom sage: f == g #optional - axiom False - """ P = self.parent() - if 'true' in P.eval("(%s = %s) :: Boolean" % (self.name(),other.name())): + if 'true' in P.eval("(%s = %s) :: Boolean" % (self.name(), other.name())): return rich_to_bool(op, 0) elif 'true' in P.eval("(%s < %s) :: Boolean" % (self.name(), other.name())): return rich_to_bool(op, -1) - elif 'true' in P.eval("(%s > %s) :: Boolean" % (self.name(),other.name())): + elif 'true' in P.eval("(%s > %s) :: Boolean" % (self.name(), other.name())): return rich_to_bool(op, 1) return NotImplemented @@ -622,7 +620,7 @@ def type(self): P = self._check_valid() s = P._eval_line(self.name()) i = s.rfind('Type:') - return P(s[i+5:].strip()) + return P(s[i + 5:].strip()) def __len__(self): """ @@ -637,7 +635,7 @@ def __len__(self): P = self._check_valid() s = P.eval('# %s ' % self.name()) i = s.rfind('Type') - return int(s[:i-1]) + return int(s[:i - 1]) def __getitem__(self, n): r""" @@ -709,12 +707,12 @@ def _latex_(self): i = s.find('$$') j = s.rfind('$$') s = s[i + 2:j] - s = multiple_replace({'\r':'', '\n':' ', - ' \\sp ':'^', - '\\arcsin ':'\\sin^{-1} ', - '\\arccos ':'\\cos^{-1} ', - '\\arctan ':'\\tan^{-1} '}, - re.sub(r'\\leqno\(.*?\)','',s)) # no eq number! + s = multiple_replace({'\r': '', '\n': ' ', + ' \\sp ': '^', + '\\arcsin ': '\\sin^{-1} ', + '\\arccos ': '\\cos^{-1} ', + '\\arctan ': '\\tan^{-1} '}, + re.sub(r'\\leqno\(.*?\)', '', s)) # no eq number! return s def as_type(self, type): @@ -753,16 +751,13 @@ def unparsed_input_form(self): s = P.eval('unparse(%s::InputForm)' % self._name) if 'translation error' in s or 'Cannot convert' in s: raise NotImplementedError - s = multiple_replace({'\r\n':'', # fix stupid Fortran-ish - 'DSIN(':'sin(', - 'DCOS(':'cos(', - 'DTAN(':'tan(', - 'DSINH(':'sinh('}, s) - r = re.search(r'"(.*)"',s) - if r: - return r.groups(0)[0] - else: - return s + s = multiple_replace({'\r\n': '', # fix stupid Fortran-ish + 'DSIN(': 'sin(', + 'DCOS(': 'cos(', + 'DTAN(': 'tan(', + 'DSINH(': 'sinh('}, s) + r = re.search(r'"(.*)"', s) + return r.groups(0)[0] if r else s def _sage_(self): """ @@ -835,8 +830,8 @@ def _sage_(self): from sage.rings.integer_ring import ZZ prec = max(self.mantissa().length()._sage_(), 53) R = RealField(prec) - x,e,b = self.unparsed_input_form().lstrip('float(').rstrip(')').split(',') - return R(ZZ(x)*ZZ(b)**ZZ(e)) + x, e, b = self.unparsed_input_form().lstrip('float(').rstrip(')').split(',') + return R(ZZ(x) * ZZ(b)**ZZ(e)) elif type == "DoubleFloat": from sage.rings.real_double import RDF return RDF(repr(self)) @@ -850,16 +845,18 @@ def _sage_(self): R = PolynomialRing(base_ring, vars) return R(self.unparsed_input_form()) elif type.startswith('Fraction'): - return self.numer().sage()/self.denom().sage() + return self.numer().sage() / self.denom().sage() - #If all else fails, try using the unparsed input form + # If all else fails, try using the unparsed input form try: import sage.misc.sage_eval vars = sage.symbolic.ring.var(str(self.variables())[1:-1]) - if isinstance(vars,tuple): - return sage.misc.sage_eval.sage_eval(self.unparsed_input_form(), locals={str(x):x for x in vars}) + if isinstance(vars, tuple): + return sage.misc.sage_eval.sage_eval(self.unparsed_input_form(), + locals={str(x): x for x in vars}) else: - return sage.misc.sage_eval.sage_eval(self.unparsed_input_form(), locals={str(vars):vars}) + return sage.misc.sage_eval.sage_eval(self.unparsed_input_form(), + locals={str(vars): vars}) except Exception: raise NotImplementedError @@ -961,9 +958,10 @@ def is_AxiomElement(x): return isinstance(x, AxiomElement) -#Instances +# Instances axiom = Axiom(name='axiom') + def reduce_load_Axiom(): """ Returns the Axiom interface object defined in @@ -977,6 +975,7 @@ def reduce_load_Axiom(): """ return axiom + def axiom_console(): """ Spawn a new Axiom command-line session. diff --git a/src/sage/interfaces/sympy.py b/src/sage/interfaces/sympy.py index a334c241127..001b7bc687f 100644 --- a/src/sage/interfaces/sympy.py +++ b/src/sage/interfaces/sympy.py @@ -51,8 +51,10 @@ ################################################################ # Distributed under GNU GPL3, see www.gnu.org ################################################################ +from sage.misc.misc import run_once + -################# numbers and constants ############## +# ################ numbers and constants ############## def _sympysage_float(self): """ @@ -65,6 +67,7 @@ def _sympysage_float(self): from sage.rings.real_mpfr import create_RealNumber return create_RealNumber(str(self)) + def _sympysage_integer_ring(self): r""" EXAMPLES:: @@ -76,6 +79,7 @@ def _sympysage_integer_ring(self): from sage.rings.integer_ring import ZZ return ZZ + def _sympysage_integer(self): """ EXAMPLES:: @@ -89,6 +93,7 @@ def _sympysage_integer(self): from sage.rings.integer import Integer return Integer(self.p) + def _sympysage_rational(self): """ EXAMPLES:: @@ -101,6 +106,7 @@ def _sympysage_rational(self): from sage.rings.rational import Rational return Rational((Integer(self.p), Integer(self.q))) + def _sympysage_rational_field(self): r""" EXAMPLES:: @@ -112,6 +118,7 @@ def _sympysage_rational_field(self): from sage.rings.rational_field import QQ return QQ + def _sympysage_real_interval(self): r""" EXAMPLES:: @@ -138,6 +145,7 @@ def _sympysage_real_interval(self): domain = self.dom._sage_().fraction_field() return RIF(domain(self.a)).union(RIF(domain(self.b))) + def _sympysage_complex_interval(self): r""" EXAMPLES:: @@ -164,6 +172,7 @@ def _sympysage_complex_interval(self): domain = self.dom._sage_().fraction_field() return CIF(domain(self.ax), domain(self.ay)).union(CIF(domain(self.bx), domain(self.by))) + def _sympysage_polynomial_ring(self): r""" EXAMPLES:: @@ -184,6 +193,7 @@ def _sympysage_polynomial_ring(self): variables = ','.join(map(str, self.gens)) return base_ring[variables] + def _sympysage_polynomial(self): r""" EXAMPLES:: @@ -216,6 +226,7 @@ def _sympysage_polynomial(self): R = base_ring[variables] return R.sum(base_ring(coeff) * R.monomial(*exp) for exp, coeff in self.rep.terms(order=None)) + def _sympysage_pinfty(self): """ EXAMPLES:: @@ -227,6 +238,7 @@ def _sympysage_pinfty(self): from sage.rings.infinity import PlusInfinity return PlusInfinity() + def _sympysage_ninfty(self): """ EXAMPLES:: @@ -238,6 +250,7 @@ def _sympysage_ninfty(self): from sage.rings.infinity import MinusInfinity return MinusInfinity() + def _sympysage_uinfty(self): """ EXAMPLES:: @@ -249,6 +262,7 @@ def _sympysage_uinfty(self): from sage.rings.infinity import unsigned_infinity return unsigned_infinity + def _sympysage_nan(self): """ EXAMPLES:: @@ -260,6 +274,7 @@ def _sympysage_nan(self): from sage.symbolic.constants import NaN return NaN + def _sympysage_e(self): """ EXAMPLES:: @@ -271,6 +286,7 @@ def _sympysage_e(self): from sage.symbolic.constants import e return e + def _sympysage_pi(self): """ EXAMPLES:: @@ -282,6 +298,7 @@ def _sympysage_pi(self): from sage.symbolic.constants import pi return pi + def _sympysage_golden_ratio(self): """ EXAMPLES:: @@ -293,6 +310,7 @@ def _sympysage_golden_ratio(self): from sage.symbolic.constants import golden_ratio return golden_ratio + def _sympysage_eulerg(self): """ EXAMPLES:: @@ -304,6 +322,7 @@ def _sympysage_eulerg(self): from sage.symbolic.constants import euler_gamma return euler_gamma + def _sympysage_catalan(self): """ EXAMPLES:: @@ -315,6 +334,7 @@ def _sympysage_catalan(self): from sage.symbolic.constants import catalan return catalan + def _sympysage_i(self): """ EXAMPLES:: @@ -326,7 +346,8 @@ def _sympysage_i(self): from sage.symbolic.constants import I return I -################## basic operators ############## + +# ################# basic operators ############## def _sympysage_add(self): """ @@ -342,6 +363,7 @@ def _sympysage_add(self): s += x._sage_() return s + def _sympysage_mul(self): """ EXAMPLES:: @@ -356,6 +378,7 @@ def _sympysage_mul(self): s *= x._sage_() return s + def _sympysage_pow(self): """ EXAMPLES:: @@ -367,6 +390,7 @@ def _sympysage_pow(self): """ return self.args[0]._sage_()**self.args[1]._sage_() + def _sympysage_symbol(self): """ EXAMPLES:: @@ -398,7 +422,7 @@ def _sympysage_Subs(self): return args[0]._sage_().subs(substi) -############## functions ############### +# ############# functions ############### def _sympysage_function_by_name(fname): """ @@ -431,6 +455,7 @@ def _sympysage_function_by_name(fname): raise AttributeError return func + # the convoluted class structure with metaclasses and stuff sympy uses # to implement undefined functions makes things a bit harder for us # here @@ -451,7 +476,8 @@ def __get__(self, ins, typ): return lambda: _sympysage_function_by_name(typ.__name__) else: args = [arg._sage_() for arg in ins.args] - return lambda : _sympysage_function_by_name(ins.__class__.__name__)(*args) + return lambda: _sympysage_function_by_name(ins.__class__.__name__)(*args) + def _sympysage_function(self): """ @@ -484,6 +510,7 @@ def _sympysage_function(self): return func(*args) + def _sympysage_integral(self): """ EXAMPLES:: @@ -509,6 +536,7 @@ def _sympysage_integral(self): f = integral(f, (x._sage_(), a._sage_(), b._sage_()), hold=True) return f + def _sympysage_derivative(self): """ EXAMPLES:: @@ -546,6 +574,7 @@ def _sympysage_derivative(self): for a in (arg if isinstance(arg, (tuple, Tuple)) else [arg])] return derivative(f, *args) + def _sympysage_order(self): """ EXAMPLES:: @@ -558,6 +587,7 @@ def _sympysage_order(self): from sage.functions.other import Order return Order(self.args[0])._sage_() + def _sympysage_lambertw(self): """ EXAMPLES:: @@ -569,6 +599,7 @@ def _sympysage_lambertw(self): from sage.functions.log import lambert_w return lambert_w(self.args[0]._sage_()) + def _sympysage_rf(self): """ EXAMPLES:: @@ -582,6 +613,7 @@ def _sympysage_rf(self): from sage.arith.misc import rising_factorial return rising_factorial(self.args[0]._sage_(), self.args[1]._sage_()) + def _sympysage_ff(self): """ EXAMPLES:: @@ -595,6 +627,7 @@ def _sympysage_ff(self): from sage.arith.misc import falling_factorial return falling_factorial(self.args[0]._sage_(), self.args[1]._sage_()) + def _sympysage_lgamma(self): """ EXAMPLES:: @@ -606,6 +639,7 @@ def _sympysage_lgamma(self): from sage.functions.gamma import log_gamma return log_gamma(self.args[0]._sage_()) + def _sympysage_polygamma(self): """ EXAMPLES:: @@ -621,7 +655,8 @@ def _sympysage_polygamma(self): integrate(psi(x), x) """ from sage.functions.gamma import psi - return psi(self.args[0]._sage_(),self.args[1]._sage_()) + return psi(self.args[0]._sage_(), self.args[1]._sage_()) + def _sympysage_dirac_delta(self): """ @@ -634,6 +669,7 @@ def _sympysage_dirac_delta(self): from sage.functions.generalized import dirac_delta return dirac_delta(self.args[0]._sage_()) + def _sympysage_heaviside(self): """ EXAMPLES:: @@ -645,6 +681,7 @@ def _sympysage_heaviside(self): from sage.functions.generalized import heaviside return heaviside(self.args[0]._sage_()) + def _sympysage_expint(self): """ EXAMPLES:: @@ -658,6 +695,7 @@ def _sympysage_expint(self): from sage.functions.exp_integral import exp_integral_e return exp_integral_e(self.args[0]._sage_(), self.args[1]._sage_()) + def _sympysage_hyp(self): """ EXAMPLES:: @@ -673,6 +711,7 @@ def _sympysage_hyp(self): bq = [arg._sage_() for arg in self.args[1]] return hypergeometric(ap, bq, self.argument._sage_()) + def _sympysage_elliptic_k(self): """ EXAMPLES:: @@ -684,6 +723,7 @@ def _sympysage_elliptic_k(self): from sage.functions.special import elliptic_kc return elliptic_kc(self.args[0]._sage_()) + def _sympysage_kronecker_delta(self): """ EXAMPLES:: @@ -697,6 +737,7 @@ def _sympysage_kronecker_delta(self): from sage.functions.generalized import kronecker_delta return kronecker_delta(self.args[0]._sage_(), self.args[1]._sage_()) + def _sympysage_ceiling(self): """ EXAMPLES:: @@ -710,6 +751,7 @@ def _sympysage_ceiling(self): from sage.functions.other import ceil return ceil(self.args[0]._sage_()) + def _sympysage_piecewise(self): """ EXAMPLES:: @@ -726,7 +768,8 @@ def _sympysage_piecewise(self): -y*z + cases(((log(x) != 0, x^y/log(x)), (1, y))) """ from sage.functions.other import cases - return cases([(p.cond._sage_(),p.expr._sage_()) for p in self.args]) + return cases([(p.cond._sage_(), p.expr._sage_()) for p in self.args]) + def _sympysage_fresnels(self): """ @@ -742,6 +785,7 @@ def _sympysage_fresnels(self): from sage.functions.error import fresnel_sin return fresnel_sin(self.args[0]._sage_()) + def _sympysage_fresnelc(self): """ EXAMPLES:: @@ -756,6 +800,7 @@ def _sympysage_fresnelc(self): from sage.functions.error import fresnel_cos return fresnel_cos(self.args[0]._sage_()) + def _sympysage_besselj(self): """ EXAMPLES:: @@ -769,6 +814,7 @@ def _sympysage_besselj(self): from sage.functions.bessel import bessel_J return bessel_J(self.args[0]._sage_(), self.args[1]._sage_()) + def _sympysage_bessely(self): """ EXAMPLES:: @@ -782,6 +828,7 @@ def _sympysage_bessely(self): from sage.functions.bessel import bessel_Y return bessel_Y(self.args[0]._sage_(), self.args[1]._sage_()) + def _sympysage_besseli(self): """ EXAMPLES:: @@ -795,6 +842,7 @@ def _sympysage_besseli(self): from sage.functions.bessel import bessel_I return bessel_I(self.args[0]._sage_(), self.args[1]._sage_()) + def _sympysage_besselk(self): """ EXAMPLES:: @@ -808,6 +856,7 @@ def _sympysage_besselk(self): from sage.functions.bessel import bessel_K return bessel_K(self.args[0]._sage_(), self.args[1]._sage_()) + def _sympysage_ynm(self): """ EXAMPLES:: @@ -824,6 +873,7 @@ def _sympysage_ynm(self): self.args[2]._sage_(), self.args[3]._sage_()) + def _sympysage_re(self): """ EXAMPLES:: @@ -835,6 +885,7 @@ def _sympysage_re(self): from sage.functions.other import real_part return real_part(self.args[0]._sage_()) + def _sympysage_im(self): """ EXAMPLES:: @@ -846,6 +897,7 @@ def _sympysage_im(self): from sage.functions.other import imag_part return imag_part(self.args[0]._sage_()) + def _sympysage_abs(self): """ EXAMPLES:: @@ -857,6 +909,7 @@ def _sympysage_abs(self): from sage.functions.other import abs_symbolic return abs_symbolic(self.args[0]._sage_()) + def _sympysage_crootof(self): """ EXAMPLES:: @@ -875,6 +928,7 @@ def _sympysage_crootof(self): from sage.symbolic.ring import SR return complex_root_of(self.args[0]._sage_(), SR(self.args[1])) + def _sympysage_matrix(self): """ Convert SymPy matrix ``self`` to Sage. @@ -939,7 +993,6 @@ def _sympysage_matrix(self): [x - 1 1] sage: M == MutatedM False - """ try: return self._sage_object @@ -959,7 +1012,7 @@ def _sympysage_matrix(self): coercion_model = get_coercion_model() try: base_ring = coercion_model.common_parent(*d.values()) - except TypeError: # no common canonical parent + except TypeError: # no common canonical parent base_ring = SR result = matrix(base_ring, rows, cols, d, sparse=isinstance(self, SparseMatrix), @@ -968,6 +1021,7 @@ def _sympysage_matrix(self): self._sage_object = result return result + def _sympysage_relational(self): """ EXAMPLES:: @@ -989,9 +1043,10 @@ def _sympysage_relational(self): """ from operator import eq, ne, gt, lt, ge, le from sympy import Eq, Ne, Gt, Ge, Lt, Le - ops = {Eq : eq, Ne : ne, Gt : gt, Lt : lt, Ge : ge, Le : le} + ops = {Eq: eq, Ne: ne, Gt: gt, Lt: lt, Ge: ge, Le: le} return ops.get(self.func)(self.lhs._sage_(), self.rhs._sage_()) + def _sympysage_false(self): """ EXAMPLES:: @@ -1003,6 +1058,7 @@ def _sympysage_false(self): from sage.symbolic.ring import SR return SR(False) + def _sympysage_true(self): """ EXAMPLES:: @@ -1015,8 +1071,8 @@ def _sympysage_true(self): return SR(True) -#------------------------------------------------------------------ -from sage.misc.misc import run_once +# ------------------------------------------------------------------ + @run_once def sympy_init(): @@ -1043,12 +1099,13 @@ def sympy_init(): from sympy import Mul, Pow, Symbol, Subs from sympy.core.function import (Function, AppliedUndef, Derivative) from sympy.core.numbers import (Float, Integer, Rational, Infinity, - NegativeInfinity, ComplexInfinity, Exp1, Pi, GoldenRatio, - EulerGamma, Catalan, ImaginaryUnit) + NegativeInfinity, ComplexInfinity, + Exp1, Pi, GoldenRatio, + EulerGamma, Catalan, ImaginaryUnit) from sympy.core.numbers import NaN as sympy_nan from sympy.core.relational import Relational from sympy.functions.combinatorial.factorials import (RisingFactorial, - FallingFactorial) + FallingFactorial) from sympy.functions.elementary.complexes import (re, im, Abs) from sympy.functions.elementary.exponential import LambertW from sympy.functions.elementary.integers import ceiling @@ -1136,6 +1193,7 @@ def sympy_init(): BooleanTrue._sage_ = _sympysage_true ceiling._sage_ = _sympysage_ceiling + def check_expression(expr, var_symbols, only_from_sympy=False): """ Does ``eval(expr)`` both in Sage and SymPy and does other checks. @@ -1177,6 +1235,7 @@ def check_expression(expr, var_symbols, only_from_sympy=False): assert S(e_sage) == e_sympy assert e_sage == SR(e_sympy) + def test_all(): """ Call some tests that were originally in SymPy. @@ -1241,14 +1300,14 @@ def test_issue_4023(): from sage.symbolic.ring import SR from sage.functions.all import log from sympy import integrate, simplify - a,x = SR.var("a x") - i = integrate(log(x)/a, (x, a, a + 1)) + a, x = SR.var("a x") + i = integrate(log(x) / a, (x, a, a + 1)) i2 = simplify(i) s = SR(i2) - assert s == (a*log(1 + a) - a*log(a) + log(1 + a) - 1)/a + assert s == (a * log(1 + a) - a * log(a) + log(1 + a) - 1) / a def test_integral(): - #test Sympy-->Sage + # test Sympy-->Sage check_expression("Integral(x, (x,))", "x", only_from_sympy=True) check_expression("Integral(x, (x, 0, 1))", "x", only_from_sympy=True) check_expression("Integral(x*y, (x,), (y, ))", "x,y", only_from_sympy=True) @@ -1269,13 +1328,13 @@ def test_undefined_function(): from sympy import Symbol, Function f = function('f') sf = Function('f') - x,y = SR.var('x y') + x, y = SR.var('x y') sx = Symbol('x') sy = Symbol('y') assert f(x)._sympy_() == sf(sx) assert f(x) == sf(sx)._sage_() - assert f(x,y)._sympy_() == sf(sx, sy) - assert f(x,y) == sf(sx, sy)._sage_() + assert f(x, y)._sympy_() == sf(sx, sy) + assert f(x, y) == sf(sx, sy)._sage_() assert f._sympy_() == sf assert f == sf._sage_() @@ -1287,7 +1346,7 @@ def test_undefined_function(): test_functions() test_issue_4023() test_integral() - #test_integral_failing() + # test_integral_failing() test_undefined_function() @@ -1307,7 +1366,7 @@ def sympy_set_to_list(set, vars): if isinstance(set, (And, Or, Relational)): if isinstance(set, And): return [[item for rel in set._args[0] - for item in sympy_set_to_list(rel, vars) ]] + for item in sympy_set_to_list(rel, vars)]] elif isinstance(set, Or): return [sympy_set_to_list(iv, vars) for iv in set._args[0]] elif isinstance(set, Relational): From c729ddda569c077b70665892c3da8b7687b4a70f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 21 Nov 2023 11:40:48 +0100 Subject: [PATCH 112/155] pep8 in various interfaces --- src/sage/interfaces/jmoldata.py | 26 +++++++++++++------------- src/sage/interfaces/latte.py | 24 ++++++++++++------------ src/sage/interfaces/lisp.py | 14 +++++++------- src/sage/interfaces/psage.py | 7 ++++--- src/sage/interfaces/scilab.py | 14 +++++++------- src/sage/interfaces/tachyon.py | 10 +++++----- 6 files changed, 48 insertions(+), 47 deletions(-) diff --git a/src/sage/interfaces/jmoldata.py b/src/sage/interfaces/jmoldata.py index a68e53e2d85..119ff1624ce 100644 --- a/src/sage/interfaces/jmoldata.py +++ b/src/sage/interfaces/jmoldata.py @@ -10,14 +10,14 @@ - Jonathan Gutow (2012-03-21): initial version """ -#******************************************************************************* +# ****************************************************************************** # Copyright (C) 2012 Jonathan Gutow (gutow@uwosh.edu) # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. -# http://www.gnu.org/licenses/ -#******************************************************************************* +# https://www.gnu.org/licenses/ +# ****************************************************************************** from sage.structure.sage_object import SageObject @@ -72,12 +72,12 @@ def is_jvm_available(self): return java_version_number >= 7 def export_image(self, - targetfile, - datafile, #name (path) of data file Jmol can read or script file telling it what to read or load - datafile_cmd='script', #"script" or "load" - image_type='PNG', #PNG, JPG, GIF - figsize=5, - **kwds): + targetfile, + datafile, # name (path) of data file Jmol can read or script file telling it what to read or load + datafile_cmd='script', # "script" or "load" + image_type='PNG', # PNG, JPG, GIF + figsize=5, + **kwds): r""" This executes JmolData.jar to make an image file. @@ -170,7 +170,7 @@ def export_image(self, launchscript = launchscript + datafile imagescript = 'write {} {!r}\n'.format(image_type, target_native) - size_arg = "%sx%s" % (figsize*100,figsize*100) + size_arg = "%sx%s" % (figsize * 100, figsize * 100) # Scratch file for Jmol errors scratchout = tmp_filename(ext=".txt") with open(scratchout, 'w') as jout: @@ -179,9 +179,9 @@ def export_image(self, env['LC_ALL'] = 'C' env['LANG'] = 'C' subprocess.call(["java", "-Xmx512m", "-Djava.awt.headless=true", - "-jar", jmolpath, "-iox", "-g", size_arg, - "-J", launchscript, "-j", imagescript], - stdout=jout, stderr=jout, env=env) + "-jar", jmolpath, "-iox", "-g", size_arg, + "-J", launchscript, "-j", imagescript], + stdout=jout, stderr=jout, env=env) if not os.path.isfile(targetfile): raise RuntimeError(f"Jmol failed to create file {targetfile}: {Path(scratchout).read_text()}") os.unlink(scratchout) diff --git a/src/sage/interfaces/latte.py b/src/sage/interfaces/latte.py index 4c6d8e9f061..6923be55d53 100644 --- a/src/sage/interfaces/latte.py +++ b/src/sage/interfaces/latte.py @@ -1,15 +1,15 @@ r""" Interface to LattE integrale programs """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2017 Vincent Delecroix # # 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.cpython.string import str_to_bytes, bytes_to_str @@ -134,15 +134,15 @@ def count(arg, ehrhart_polynomial=False, multivariate_generating_function=False, if 'redundancy_check' not in kwds: args.append('--redundancy-check=none') - for key,value in kwds.items(): + for key, value in kwds.items(): if value is None or value is False: continue - key = key.replace('_','-') + key = key.replace('_', '-') if value is True: - args.append('--{}'.format(key)) + args.append(f'--{key}') else: - args.append('--{}={}'.format(key, value)) + args.append(f'--{key}={value}') if multivariate_generating_function: from sage.misc.temporary_file import tmp_filename @@ -200,12 +200,12 @@ def count(arg, ehrhart_polynomial=False, multivariate_generating_function=False, else: raise NotImplementedError("there is no Sage object to handle multivariate series from LattE, use raw_output=True") else: - if ans: # Sometimes (when LattE's preproc does the work), no output appears on stdout. + if ans: # Sometimes (when LattE's preproc does the work), no output appears on stdout. ans = ans.splitlines()[-1] if not ans: # opening a file is slow (30e-6s), so we read the file # numOfLatticePoints only in case of a IndexError above - with open(tempd.name+'/numOfLatticePoints', 'r') as f: + with open(tempd.name + '/numOfLatticePoints', 'r') as f: ans = f.read() if raw_output: @@ -363,11 +363,11 @@ def integrate(arg, polynomial=None, algorithm='triangulate', raw_output=False, v if value is None or value is False: continue - key = key.replace('_','-') + key = key.replace('_', '-') if value is True: - args.append('--{}'.format(key)) + args.append(f'--{key}') else: - args.append('--{}={}'.format(key, value)) + args.append(f'--{key}={value}') if got_polynomial: if not isinstance(polynomial, str): diff --git a/src/sage/interfaces/lisp.py b/src/sage/interfaces/lisp.py index 3d6e620c4d1..fbe1481bcb6 100644 --- a/src/sage/interfaces/lisp.py +++ b/src/sage/interfaces/lisp.py @@ -50,7 +50,7 @@ # https://www.gnu.org/licenses/ # ########################################################################## - +import os import random from .expect import Expect, ExpectElement, ExpectFunction, FunctionElement, gc_disabled @@ -124,10 +124,10 @@ def eval(self, code, strip=True, **kwds): self._synchronize() code = str(code) code = code.strip() - code = code.replace('\n',' ') + code = code.replace('\n', ' ') x = [] for L in code.split('\n'): - if L != '': + if L: try: s = self.__in_seq + 1 M = self._eval_line(L, wait_for_prompt=self._prompt) @@ -136,7 +136,7 @@ def eval(self, code, strip=True, **kwds): x.append(M.strip()) self.__in_seq = s except TypeError as s: - return 'error evaluating "%s":\n%s' % (code,s) + return 'error evaluating "%s":\n%s' % (code, s) return '\n'.join(x) def _an_element_impl(self): @@ -201,7 +201,7 @@ def _synchronize(self): self._start() E = self._expect r = random.randrange(2147483647) - s = str(r+1) + s = str(r + 1) cmd = "(+ 1 %s)" % r E.sendline(cmd) E.expect(s) @@ -354,7 +354,7 @@ def _equality_symbol(self): NotImplementedError: ... """ raise NotImplementedError("We should never reach here in the Lisp interface. " + - "Please report this as a bug.") + "Please report this as a bug.") def help(self, command): """ @@ -541,6 +541,7 @@ def is_LispElement(x): # An instance lisp = Lisp() + def reduce_load_Lisp(): """ EXAMPLES:: @@ -552,7 +553,6 @@ def reduce_load_Lisp(): return lisp -import os def lisp_console(): """ Spawn a new Lisp command-line session. diff --git a/src/sage/interfaces/psage.py b/src/sage/interfaces/psage.py index b64a0b15c5f..246ce1abcf7 100644 --- a/src/sage/interfaces/psage.py +++ b/src/sage/interfaces/psage.py @@ -50,7 +50,7 @@ class PSage(Sage): - def __init__(self, **kwds): + def __init__(self, **kwds): if 'server' in kwds: raise NotImplementedError("PSage doesn't work on remote server yet.") Sage.__init__(self, **kwds) @@ -136,7 +136,7 @@ def eval(self, x, strip=True, **kwds): return "<>" if self._locked: self._locked = False - #self._expect.expect('__unlocked__') + # self._expect.expect('__unlocked__') self.expect().send('\n') self.expect().expect(self._prompt) self.expect().expect(self._prompt) @@ -158,7 +158,7 @@ def set(self, var, value): """ Set the variable var to the given value. """ - cmd = '%s=%s' % (var,value) + cmd = '%s=%s' % (var, value) self._send_nowait(cmd) time.sleep(0.02) @@ -182,6 +182,7 @@ def _send_nowait(self, x): def _object_class(self): return PSageElement + class PSageElement(SageElement): def is_locked(self): return self.parent().is_locked() diff --git a/src/sage/interfaces/scilab.py b/src/sage/interfaces/scilab.py index 54c28f55598..743f761ba2c 100644 --- a/src/sage/interfaces/scilab.py +++ b/src/sage/interfaces/scilab.py @@ -208,7 +208,7 @@ class Scilab(Expect): 505. """ def __init__(self, maxread=None, script_subdirectory=None, - logfile=None, server=None,server_tmpdir=None, + logfile=None, server=None, server_tmpdir=None, seed=None): """ Initializes the Scilab class. @@ -315,8 +315,8 @@ def eval(self, command, *args, **kwds): sage: scilab.eval("d=44") # optional - scilab 'd =\n \n 44.' """ - s = Expect.eval(self, command, **kwds).replace("\x1b[?1l\x1b>","").strip() - return s + s = Expect.eval(self, command, **kwds) + return s.replace("\x1b[?1l\x1b>", "").strip() def whos(self, name=None, typ=None): """ @@ -349,7 +349,7 @@ def set(self, var, value): sage: scilab.get('a') # optional - scilab '\n \n 123.' """ - cmd = '%s=%s;' % (var,value) + cmd = '%s=%s;' % (var, value) out = self.eval(cmd) if out.find("error") != -1: raise TypeError("Error executing code in Scilab\nCODE:\n\t%s\nScilab ERROR:\n\t%s" % (cmd, out)) @@ -367,7 +367,7 @@ def get(self, var): """ s = self.eval('%s' % var) i = s.find('=') - return s[i+1:] + return s[i + 1:] def console(self): """ @@ -407,9 +407,9 @@ def sage2scilab_matrix_string(self, A): sage: A = M33([1,2,3,4,5,6,7,8,0]) # optional - scilab sage: scilab.sage2scilab_matrix_string(A) # optional - scilab '[1, 2, 3; 4, 5, 6; 7, 8, 0]' - """ - return str(A.rows()).replace('), (', '; ').replace('(', '').replace(')','') + s = str(A.rows()) + return s.replace('), (', '; ').replace('(', '').replace(')', '') def _object_class(self): """ diff --git a/src/sage/interfaces/tachyon.py b/src/sage/interfaces/tachyon.py index 6053d2519e4..253253620bd 100644 --- a/src/sage/interfaces/tachyon.py +++ b/src/sage/interfaces/tachyon.py @@ -673,14 +673,14 @@ properly. """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2006 John E. Stone # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** import os import re @@ -804,8 +804,8 @@ def __call__(self, model, outfile='sage.png', verbose=1, extra_opts=''): if self.version() >= '0.99.2': # this keyword was changed in 0.99.2 model = model.replace( - " focallength ", - " focaldist ") + " focallength ", + " focaldist ") modelfile = tmp_filename(ext='.dat') with open(modelfile, 'w') as file: file.write(model) From f70bfb27df6ea739b201ac12504f9bc89c0b71ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 21 Nov 2023 12:15:14 +0100 Subject: [PATCH 113/155] suggested details --- .../modform_hecketriangle/abstract_ring.py | 50 +++++++++---------- .../modform_hecketriangle/graded_ring.py | 2 +- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/sage/modular/modform_hecketriangle/abstract_ring.py b/src/sage/modular/modform_hecketriangle/abstract_ring.py index 705a05a7341..3b68a6e505c 100644 --- a/src/sage/modular/modform_hecketriangle/abstract_ring.py +++ b/src/sage/modular/modform_hecketriangle/abstract_ring.py @@ -80,7 +80,7 @@ def __init__(self, group, base_ring, red_hom, n): """ # from graded_ring import canonical_parameters - # (group, base_ring, red_hom, n) = canonical_parameters(group, base_ring, red_hom, n) + # group, base_ring, red_hom, n = canonical_parameters(group, base_ring, red_hom, n) # if not group.is_arithmetic() and base_ring.characteristic()>0: # raise NotImplementedError @@ -140,7 +140,7 @@ def _element_constructor_(self, el): sage: from sage.modular.modform_hecketriangle.graded_ring import ModularFormsRing sage: MR = ModularFormsRing() - sage: (x,y,z,d) = MR.pol_ring().gens() + sage: x,y,z,d = MR.pol_ring().gens() sage: MR(x^3) f_rho^3 @@ -494,7 +494,7 @@ def reduce_type(self, analytic_type=None, degree=None): elif degree is None: return FormsSpace(analytic_type, group=self.group(), base_ring=self.base_ring(), k=self.weight(), ep=self.ep()) else: - (weight, ep) = degree + weight, ep = degree if self.is_homogeneous() and (weight != self.weight() or ep != self.ep()): analytic_type = self._analytic_type.reduce_to([]) return FormsSpace(analytic_type, group=self.group(), base_ring=self.base_ring(), k=weight, ep=ep) @@ -808,15 +808,14 @@ def _derivative_op(self): sage: ModularFormsRing(n=infinity)._derivative_op() -X*Y*dX + X*Z*dX + 1/2*Y*Z*dY + 1/4*Z^2*dZ - 1/2*X*dY - 1/4*X*dZ """ - (X, Y, Z, dX, dY, dZ) = self.diff_alg().gens() + X, Y, Z, dX, dY, dZ = self.diff_alg().gens() if self.hecke_n() == infinity: - return (X*Z-X*Y) * dX\ - + ZZ(1)/ZZ(2) * (Y*Z-X) * dY\ - + ZZ(1)/ZZ(4) * (Z**2-X) * dZ + return (X*Z-X*Y) * dX + ZZ(1) / 2 * (Y*Z-X) * dY \ + + ZZ(1) / 4 * (Z**2-X) * dZ - return 1/self._group.n() * (X*Z-Y) * dX\ - + ZZ(1)/ZZ(2) * (Y*Z-X**(self._group.n()-1)) * dY\ + return 1/self._group.n() * (X*Z-Y) * dX \ + + ZZ(1) / 2 * (Y*Z-X**(self._group.n()-1)) * dY \ + (self._group.n()-2) / (4*self._group.n()) * (Z**2-X**(self._group.n()-2)) * dZ @cached_method @@ -834,15 +833,14 @@ def _serre_derivative_op(self): sage: ModularFormsRing(n=infinity)._serre_derivative_op() -X*Y*dX - 1/4*Z^2*dZ - 1/2*X*dY - 1/4*X*dZ """ - (X, Y, Z, dX, dY, dZ) = self.diff_alg().gens() + X, Y, Z, dX, dY, dZ = self.diff_alg().gens() if self.hecke_n() == infinity: - return - X * Y * dX\ - - ZZ(1)/ZZ(2) * X * dY\ - - ZZ(1)/ZZ(4) * (Z**2+X) * dZ + return - X * Y * dX - ZZ(1) / 2 * X * dY \ + - ZZ(1) / 4 * (Z**2+X) * dZ - return - 1/self._group.n() * Y*dX\ - - ZZ(1)/ZZ(2) * X**(self._group.n()-1) * dY\ + return - 1/self._group.n() * Y*dX \ + - ZZ(1) / 2 * X**(self._group.n()-1) * dY \ - (self._group.n()-2) / (4*self._group.n()) * (Z**2+X**(self._group.n()-2)) * dZ @cached_method @@ -1091,7 +1089,7 @@ def J_inv(self): sage: WeakModularForms().J_inv() 1/1728*q^-1 + 31/72 + 1823/16*q + 335840/27*q^2 + 16005555/32*q^3 + 11716352*q^4 + O(q^5) """ - (x, y, z, d) = self._pol_ring.gens() + x, y, z, d = self._pol_ring.gens() if self.hecke_n() == infinity: return self.extend_type("weak", ring=True)(x/(x-y**2)).reduce() @@ -1142,7 +1140,7 @@ def j_inv(self): sage: WeakModularForms().j_inv() q^-1 + 744 + 196884*q + 21493760*q^2 + 864299970*q^3 + 20245856256*q^4 + O(q^5) """ - (x, y, z, d) = self._pol_ring.gens() + x, y, z, d = self._pol_ring.gens() if self.hecke_n() == infinity: return self.extend_type("weak", ring=True)(1/d*x/(x-y**2)).reduce() @@ -1217,7 +1215,7 @@ def f_rho(self): sage: ModularForms(k=4).f_rho() 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + O(q^5) """ - (x, y, z, d) = self._pol_ring.gens() + x, y, z, d = self._pol_ring.gens() if self.hecke_n() == infinity: return self.extend_type("holo", ring=True)(1).reduce() @@ -1283,7 +1281,7 @@ def f_i(self): sage: ModularForms(k=6).f_i() 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 + O(q^5) """ - (x, y, z, d) = self._pol_ring.gens() + x, y, z, d = self._pol_ring.gens() return self.extend_type("holo", ring=True)(y).reduce() @@ -1352,7 +1350,7 @@ def f_inf(self): sage: CuspForms(k=12).f_inf() q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5) """ - (x, y, z, d) = self._pol_ring.gens() + x, y, z, d = self._pol_ring.gens() if self.hecke_n() == infinity: return self.extend_type("holo", ring=True)(d*(x-y**2)).reduce() @@ -1428,7 +1426,7 @@ def G_inv(self): ... ArithmeticError: G_inv doesn't exist for odd n(=9). """ - (x, y, z, d) = self._pol_ring.gens() + x, y, z, d = self._pol_ring.gens() if self.hecke_n() == infinity: raise ArithmeticError("G_inv doesn't exist for n={} (it is not meromorphic at -1).".format(self._group.n())) @@ -1503,7 +1501,7 @@ def g_inv(self): if self.hecke_n() == infinity: raise ArithmeticError("g_inv doesn't exist for n={} (it is not meromorphic at -1).".format(self._group.n())) if ZZ(2).divides(self._group.n()): - (x, y, z, d) = self._pol_ring.gens() + x, y, z, d = self._pol_ring.gens() return self.extend_type("weak", ring=True)(1/d*y*x**(self._group.n()/ZZ(2))/(x**self._group.n()-y**2)).reduce() else: raise ArithmeticError("g_inv doesn't exist for odd n(={}).".format(self._group.n())) @@ -1575,7 +1573,7 @@ def E4(self): sage: ModularForms(k=4).E4() 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + O(q^5) """ - (x, y, z, d) = self._pol_ring.gens() + x, y, z, d = self._pol_ring.gens() if self.hecke_n() == infinity: return self.extend_type("holo", ring=True)(x).reduce() @@ -1640,7 +1638,7 @@ def E6(self): sage: ModularForms(k=6).E6() 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 + O(q^5) """ - (x, y, z, d) = self._pol_ring.gens() + x, y, z, d = self._pol_ring.gens() if self.hecke_n() == infinity: return self.extend_type("holo", ring=True)(x*y).reduce() @@ -1711,7 +1709,7 @@ def Delta(self): sage: CuspForms(k=12).Delta() q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5) """ - (x, y, z, d) = self._pol_ring.gens() + x, y, z, d = self._pol_ring.gens() if self.hecke_n() == infinity: return self.extend_type("cusp", ring=True)(d*x**2*(x-y**2)).reduce() @@ -1780,7 +1778,7 @@ def E2(self): sage: QuasiModularForms(k=2).E2() 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 + O(q^5) """ - (x, y, z, d) = self._pol_ring.gens() + x, y, z, d = self._pol_ring.gens() return self.extend_type(["holo", "quasi"], ring=True)(z).reduce() @cached_method diff --git a/src/sage/modular/modform_hecketriangle/graded_ring.py b/src/sage/modular/modform_hecketriangle/graded_ring.py index 81b64aa7f48..877f6562235 100644 --- a/src/sage/modular/modform_hecketriangle/graded_ring.py +++ b/src/sage/modular/modform_hecketriangle/graded_ring.py @@ -56,7 +56,7 @@ def canonical_parameters(group, base_ring, red_hom, n=None): return (group, base_ring, red_hom, n) -class QuasiMeromorphicModularFormsRing(FormsRing_abstract, Parent, UniqueRepresentation): +class QuasiMeromorphicModularFormsRing(FormsRing_abstract, UniqueRepresentation): r""" Graded ring of (Hecke) quasi meromorphic modular forms for the given group and base ring. From f50d62f8b27a642bfcab647d9704cb5770ae6af5 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Tue, 21 Nov 2023 15:13:36 +0100 Subject: [PATCH 114/155] Switch to libsingular backend. --- src/sage/categories/simplicial_sets.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/sage/categories/simplicial_sets.py b/src/sage/categories/simplicial_sets.py index 99b06e1628e..f2668656555 100644 --- a/src/sage/categories/simplicial_sets.py +++ b/src/sage/categories/simplicial_sets.py @@ -796,12 +796,12 @@ def twist(s): sign *= -1 differentials[d] = matrix(base_ring, old_rank, - rank, matrix_data) + rank, matrix_data, sparse=False) else: rank = 0 current = [] - differentials[d] = matrix(base_ring, old_rank, rank) + differentials[d] = matrix(base_ring, old_rank, rank, sparse=False) if cochain: new_diffs = {} @@ -874,6 +874,13 @@ def twisted_homology(self, n, reduced=False): [0 0 0 0 1] """ + from sage.libs.singular.function import singular_function + from sage.libs.singular.option import opt_verb + opt_verb['not_warn_sb'] = True + singstd = singular_function("std") + singsyz = singular_function("syz") + singred = singular_function("reduce") + singlift = singular_function("lift") G, d = self._universal_cover_dict() phi = G.abelianization_map() abelG, R, I, images = G.abelianization_to_algebra(ZZ) @@ -895,7 +902,7 @@ def convert_to_polynomial(p): GBI = RP.ideal(GB) def reduce_laurent(a): - return a._singular_().reduce(GBI)._sage_() + return singred(a, GBI, ring=RP) def group_to_polynomial(el, RP): res = RP.one() @@ -915,7 +922,7 @@ def mkernel(M): n = res.ncols() for g in (IP+JP).gens(): res = res.stack(g*identity_matrix(n)) - syz = res.T._singular_().syz()._sage_() + syz = matrix(singsyz(res.T, ring=res.base_ring())).T trimmed = syz.T.submatrix(0, 0, syz.ncols(), M.nrows()) trimmed = trimmed.apply_map(reduce_laurent) to_delete = [i for (i, r) in enumerate(trimmed.rows()) if not r] @@ -927,7 +934,7 @@ def lift_to_submodule(S, M): res = M for g in GB: res = res.stack(g*identity_matrix(M.ncols())) - singres = res.T._singular_().lift(S.T._singular_())._sage_() + singres = matrix(singlift(res.T, S.T,ring=res.base_ring())) return singres.submatrix(0, 0, M.nrows(), S.nrows()) def mgb(M): @@ -936,7 +943,7 @@ def mgb(M): res = M for g in GB: res = res.stack(g*identity_matrix(M.ncols())) - sres = res.T._singular_().std()._sage_().T + sres = matrix(singstd(res.T, ring=RP)) to_delete = [i for i, r in enumerate(sres.apply_map(reduce_laurent)) if not r] return sres.delete_rows(to_delete) M2 = border_matrix(n+1) @@ -960,8 +967,9 @@ def mgb(M): for g in (IP+JP).gens(): resmat = resmat.stack(g * identity_matrix(resmat.ncols())) if reduced: - resmat = resmat.T._singular_().std()._sage_().T + resmat = matrix(singstd(resmat.T, ring=RP)) SM = AM.submodule(resmat) + opt_verb.reset_default() return AM.quotient_module(SM) def is_simply_connected(self): From fb77773bd3dfa8c6985d8080b6a0069a1c5f3eb8 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Tue, 21 Nov 2023 16:33:03 +0100 Subject: [PATCH 115/155] Fix bug consisting in applying twice the abelianization map. --- src/sage/categories/simplicial_sets.py | 27 +++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/sage/categories/simplicial_sets.py b/src/sage/categories/simplicial_sets.py index f2668656555..19ec792d9ab 100644 --- a/src/sage/categories/simplicial_sets.py +++ b/src/sage/categories/simplicial_sets.py @@ -593,7 +593,7 @@ def _canonical_twisting_operator(self): sage: X = simplicial_sets.Torus() sage: d = X._canonical_twisting_operator() sage: d - {(s_0 v_0, sigma_1): f2*f3^-1, (sigma_1, s_0 v_0): f3, (sigma_1, sigma_1): f2} + {(s_0 v_0, sigma_1): f3, (sigma_1, s_0 v_0): f2*f3^-1, (sigma_1, sigma_1): f2} sage: list(d.values())[0].parent() Multivariate Laurent Polynomial Ring in f2, f3 over Integer Ring sage: Y = simplicial_sets.RealProjectiveSpace(2) @@ -610,7 +610,7 @@ def _canonical_twisting_operator(self): QRP = R.quotient_ring(I) res = dict() for s, el in d.items(): - res[s] = QRP(prod(images[abs(a)-1]**sign(a) for a in phi(el).Tietze())) + res[s] = QRP(prod(images[abs(a)-1]**sign(a) for a in el.Tietze())) return res def twisted_chain_complex(self, twisting_operator=None, dimensions=None, augmented=False, @@ -675,10 +675,10 @@ def twisted_chain_complex(self, twisting_operator=None, dimensions=None, augment sage: X = simplicial_sets.Torus() sage: C = X.twisted_chain_complex() sage: C.differential(1) - [f2*f3^-1 - 1 f3 - 1 f2 - 1] + [ f3 - 1 f2*f3^-1 - 1 f2 - 1] sage: C.differential(2) - [ 1 f3] - [f2*f3^-1 1] + [ 1 f2*f3^-1] + [ f3 1] [ -1 -1] sage: C.differential(3) [] @@ -873,6 +873,21 @@ def twisted_homology(self, n, reduced=False): [0 0 0 1 0] [0 0 0 0 1] + TESTS:: + + sage: X = simplicial_sets.PresentationComplex(groups.presentation.FGAbelian((3,2))) + sage: TW2 = X.twisted_homology(2, reduced=True) + sage: M = TW2.relations_matrix() + sage: from sage.libs.singular.function import singular_function + sage: vdim = singular_function("vdim") + sage: vdim(M.T, ring=M.base_ring()) + // ** considering the image in Q[...] + // ** _ is no standard basis + 5 + sage: X.universal_cover().homology(2) + Z^5 + sage: from sage.libs.singular.function import singular_function + """ from sage.libs.singular.function import singular_function from sage.libs.singular.option import opt_verb @@ -948,6 +963,7 @@ def mgb(M): return sres.delete_rows(to_delete) M2 = border_matrix(n+1) if M1.nrows() == 0: + opt_verb.reset_default() return (RP**0).quotient_module([]) K = mkernel(M1) DK = mkernel(K) @@ -963,6 +979,7 @@ def mgb(M): AM = RP ** K.nrows() if resmat.ncols() == 0: SM = AM.submodule([]) + opt_verb.reset_default() return AM.quotient_module(SM) for g in (IP+JP).gens(): resmat = resmat.stack(g * identity_matrix(resmat.ncols())) From 2d6b854172a8b0ba7928af3dd33daa1fc71c8882 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Mon, 6 Nov 2023 12:23:16 +0100 Subject: [PATCH 116/155] =?UTF-8?q?implement=20Br=C3=B6ker's=20algorithm?= =?UTF-8?q?=20for=20constructing=20supersingular=20curves?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/doc/en/reference/references/index.rst | 3 + src/sage/schemes/elliptic_curves/all.py | 2 + .../elliptic_curves/ell_finite_field.py | 199 ++++++++++++++++++ 3 files changed, 204 insertions(+) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index fa67dade3ab..abefd6bf851 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1238,6 +1238,9 @@ REFERENCES: :doi:`10.1109/SFCS.1989.63516`, _ +.. [Bro2009] \R. Bröker: *Constructing supersingular elliptic curves*. + Journal of Combinatorics and Number Theory 1.3 (2009), pp. 269--273. + .. [Broder2000] Broder, A.Z., Kumar, R., Maghoul, F., Raghavan, P., Rajagopalan, S., Stata, R., Tomkins, A., Wiener, J.L.: Graph structure in the web. Computer Networks 33(1-6), 309–320 (2000) diff --git a/src/sage/schemes/elliptic_curves/all.py b/src/sage/schemes/elliptic_curves/all.py index fd2fb992360..3e2b9f233cd 100644 --- a/src/sage/schemes/elliptic_curves/all.py +++ b/src/sage/schemes/elliptic_curves/all.py @@ -29,6 +29,8 @@ lazy_import('sage.schemes.elliptic_curves.ell_rational_field', ['cremona_curves', 'cremona_optimal_curves']) +lazy_import('sage.schemes.elliptic_curves.ell_finite_field', 'special_supersingular_curve') + from .cm import ( cm_orders, cm_j_invariants, cm_j_invariants_and_orders, diff --git a/src/sage/schemes/elliptic_curves/ell_finite_field.py b/src/sage/schemes/elliptic_curves/ell_finite_field.py index 52115c51c7d..b95726615bf 100644 --- a/src/sage/schemes/elliptic_curves/ell_finite_field.py +++ b/src/sage/schemes/elliptic_curves/ell_finite_field.py @@ -13,6 +13,8 @@ - Mariah Lenox (2011-03): Added ``set_order`` method - Lorenz Panny, John Cremona (2023-02): ``.twists()`` + +- Lorenz Panny (2023): ``special_supersingular_curve()`` """ # **************************************************************************** @@ -2414,3 +2416,200 @@ def is_j_supersingular(j, proof=True): # expensive since it involves counting the number of points on E): return E.trace_of_frobenius() % p == 0 + +def special_supersingular_curve(F, *, endomorphism=False): + r""" + Given a finite field ``F``, construct a "special" supersingular + elliptic curve `E` defined over ``F``. + + Such a curve + + - has coefficients in `\FF_p`; + + - has group structure `E(\FF_p) \cong \ZZ/(p+1)` and + `E(\FF_{p^2}) \cong \ZZ/(p+1) \times \ZZ/(p+1)`; + + - has an endomorphism `\vartheta` of small degree `q` that + anticommutes with the `\FF_p`-Frobenius on `E`. + + (The significance of `\vartheta` is that any such endomorphism, + together with the `\FF_p`-Frobenius, generates the endomorphism + algebra `\End(E) \otimes \QQ`.) + + INPUT: + + - ``F`` -- finite field `\FF_{p^r}`; + + - ``endomorphism`` -- boolean (optional, default ``False``): + When set to ``True``, it is required that `2 \mid r`, and + the function then additionally returns `\vartheta`. + + EXAMPLES:: + + sage: special_supersingular_curve(GF(1013^2), endomorphism=True) + (Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 1013^2, + Isogeny of degree 3 from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 1013^2 to Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 1013^2) + + sage: special_supersingular_curve(GF(1019^2), endomorphism=True) + (Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1019^2, + Elliptic-curve endomorphism of Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1019^2 + Via: (u,r,s,t) = (389*z2 + 241, 0, 0, 0)) + + sage: special_supersingular_curve(GF(1021^2), endomorphism=True) + (Elliptic Curve defined by y^2 = x^3 + 785*x + 794 over Finite Field in z2 of size 1021^2, + Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 785*x + 794 over Finite Field in z2 of size 1021^2 to Elliptic Curve defined by y^2 = x^3 + 785*x + 794 over Finite Field in z2 of size 1021^2) + + sage: special_supersingular_curve(GF(1031^2), endomorphism=True) + (Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1031^2, + Elliptic-curve endomorphism of Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1031^2 + Via: (u,r,s,t) = (747*z2 + 284, 0, 0, 0)) + + sage: special_supersingular_curve(GF(1033^2), endomorphism=True) + (Elliptic Curve defined by y^2 = x^3 + 53*x + 980 over Finite Field in z2 of size 1033^2, + Isogeny of degree 11 from Elliptic Curve defined by y^2 = x^3 + 53*x + 980 over Finite Field in z2 of size 1033^2 to Elliptic Curve defined by y^2 = x^3 + 53*x + 980 over Finite Field in z2 of size 1033^2) + + sage: special_supersingular_curve(GF(1039^2), endomorphism=True) + (Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1039^2, + Elliptic-curve endomorphism of Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1039^2 + Via: (u,r,s,t) = (626*z2 + 200, 0, 0, 0)) + + sage: special_supersingular_curve(GF(1049^2), endomorphism=True) + (Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 1049^2, + Isogeny of degree 3 from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 1049^2 to Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 1049^2) + + sage: special_supersingular_curve(GF(1051^2), endomorphism=True) + (Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1051^2, + Elliptic-curve endomorphism of Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1051^2 + Via: (u,r,s,t) = (922*z2 + 129, 0, 0, 0)) + + TESTS:: + + sage: p = random_prime(1000) + sage: E = special_supersingular_curve(GF(p)) + sage: E.is_supersingular() + True + sage: E.order() == p + 1 + True + sage: F. = GF((p,2)) + sage: E, endo = special_supersingular_curve(F, endomorphism=True) + sage: E.is_supersingular() + True + sage: E.j_invariant() in GF(p) + True + sage: E.abelian_group().invariants() == (p+1, p+1) + True + sage: endo.domain() is endo.codomain() is E + True + sage: endo.trace() + 0 + sage: pi = E.frobenius_isogeny() + sage: pi.codomain() is pi.domain() is E + True + sage: pi * endo == -endo * pi + True + + Also try it for larger-degree fields:: + + sage: k = ZZ(randrange(3, 10, 2)) + sage: E = special_supersingular_curve(GF((p, k))) + sage: E.is_supersingular() + True + sage: F. = GF((p, 2*k)) + sage: E, endo = special_supersingular_curve(F, endomorphism=True) + sage: E.is_supersingular() + True + sage: E.j_invariant() in GF(p) + True + sage: endo.domain() is endo.codomain() is E + True + sage: endo.trace() + 0 + sage: pi = E.frobenius_isogeny() + sage: pi.codomain() is pi.domain() is E + True + sage: pi * endo == -endo * pi + True + + .. NOTE:: + + This function makes no guarantees about the distribution of + the output. The current implementation is deterministic in + many cases. + + ALGORITHM: [Bro2009]_, Algorithm 2.4 + """ + if not isinstance(F, FiniteField): + raise TypeError('input must be a finite field') + p = F.characteristic() + deg = F.degree() + + if endomorphism and deg % 2: + raise ValueError('endomorphism was requested but is not defined over given field') + + E = None + + # first find the degree q of our special endomorphism + if p == 2: + q = 3 + E = EllipticCurve(F, [0,0,1,0,0]) + + elif p % 4 == 3: + q = 1 + E = EllipticCurve(F, [1,0]) + + elif p % 3 == 2: + q = 3 + E = EllipticCurve(F, [0,1]) + + elif p % 8 == 5: + q = 2 + E = EllipticCurve(F, [-4320, 96768]) + + else: + from sage.arith.misc import legendre_symbol + for q in map(ZZ, range(3,p,4)): + if not q.is_prime(): + continue + if legendre_symbol(-q, p) == -1: + break + else: + assert False # should never happen + + if E is None: + from sage.arith.misc import fundamental_discriminant + from sage.schemes.elliptic_curves.cm import hilbert_class_polynomial + H = hilbert_class_polynomial(fundamental_discriminant(-q)) + j = H.change_ring(GF(p)).any_root() + a = 27 * j / (4 * (1728-j)) + E = EllipticCurve(F, [a,-a]) + + if ZZ(2).divides(deg): + k = deg//2 + E.set_order((p**k - (-1)**k)**2) + else: + E.set_order(p**deg - (-1)**deg) + + if not endomorphism: + return E + + if q == 1 or p <= 13: + if q == 1: + endos = E.automorphisms() + else: + endos = (iso*phi for phi in E.isogenies_prime_degree(q) + for iso in phi.codomain().isomorphisms(E)) + endo = next(endo for endo in endos if endo.trace().is_zero()) + + else: + from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism + iso = WeierstrassIsomorphism(None, (F(-q).sqrt(),0,0,0), E) + if q == 3 and E.a_invariants() == (0,0,0,0,1): + # workaround for #21883 + endo = E.isogeny(E(0,1)) + else: + endo = E.isogeny(None, iso.domain(), degree=q) + endo = iso * endo + + endo._degree = ZZ(q) + endo.trace.set_cache(ZZ.zero()) + return E, endo From 6c3fd7e4cfa906c249c9431e0c1f66f5573d2ebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 22 Nov 2023 15:29:13 +0100 Subject: [PATCH 117/155] suggested detail --- src/sage/interfaces/scilab.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/interfaces/scilab.py b/src/sage/interfaces/scilab.py index 743f761ba2c..92017fa4a6b 100644 --- a/src/sage/interfaces/scilab.py +++ b/src/sage/interfaces/scilab.py @@ -356,7 +356,7 @@ def set(self, var, value): def get(self, var): """ - Get the value of the variable var. + Get the value of the variable ``var``. EXAMPLES:: @@ -365,9 +365,9 @@ def get(self, var): sage: scilab.get('b') # optional - scilab '\n \n 124.' """ - s = self.eval('%s' % var) + s = self.eval(f'{var}') i = s.find('=') - return s[i + 1:] + return s[i+1:] def console(self): """ From 8d8b28d92bea793d1b17129d64a88b4864ed92a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 22 Nov 2023 15:32:11 +0100 Subject: [PATCH 118/155] suggested details --- src/sage/interfaces/axiom.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/interfaces/axiom.py b/src/sage/interfaces/axiom.py index c6ca4f7e747..51b3a26f90c 100644 --- a/src/sage/interfaces/axiom.py +++ b/src/sage/interfaces/axiom.py @@ -457,7 +457,7 @@ def _eval_line(self, line, reformat=True, allow_use_file=False, return out # out = out.lstrip() i = out.find('\n') - out = out[i + 1:] + out = out[i+1:] outs = out.split("\n") i = 0 for line in outs: @@ -620,7 +620,7 @@ def type(self): P = self._check_valid() s = P._eval_line(self.name()) i = s.rfind('Type:') - return P(s[i + 5:].strip()) + return P(s[i+5:].strip()) def __len__(self): """ From 44b42b8accbe1582602208755ce4231853fd9790 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 15 Nov 2023 17:11:20 +0900 Subject: [PATCH 119/155] Porting code from Jackson Walters to compute dimensions of simple modules over positive characteristics. --- src/sage/combinat/partition.py | 39 +++++++- src/sage/combinat/specht_module.py | 94 ++++++++++++++++++++ src/sage/combinat/symmetric_group_algebra.py | 20 +++++ src/sage/combinat/tableau.py | 11 ++- 4 files changed, 162 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/partition.py b/src/sage/combinat/partition.py index 9966a174cb1..064d7606222 100644 --- a/src/sage/combinat/partition.py +++ b/src/sage/combinat/partition.py @@ -5518,7 +5518,7 @@ def specht_module_dimension(self, base_ring=None): INPUT: - - ``BR`` -- (default: `\QQ`) the base ring + - ``base_ring`` -- (default: `\QQ`) the base ring EXAMPLES:: @@ -5534,6 +5534,43 @@ def specht_module_dimension(self, base_ring=None): from sage.combinat.specht_module import specht_module_rank return specht_module_rank(self, base_ring) + def simple_module_dimension(self, base_ring=None): + r""" + Return the dimension of the simple module corresponding to ``self``. + + This is equal to the dimension of the Specht module over a field + of characteristic `0`. + + INPUT: + + - ``base_ring`` -- (default: `\QQ`) the base ring + + EXAMPLES:: + + sage: Partition([2,2,1]).simple_module_dimension() + 5 + sage: Partition([2,2,1]).specht_module_dimension(GF(3)) # optional - sage.rings.finite_rings + 5 + sage: Partition([2,2,1]).simple_module_dimension(GF(3)) # optional - sage.rings.finite_rings + 4 + + sage: for la in Partitions(6, regular=3): + ....: print(la, la.specht_module_dimension(), la.simple_module_dimension(GF(3))) + [6] 1 1 + [5, 1] 5 4 + [4, 2] 9 9 + [4, 1, 1] 10 6 + [3, 3] 5 1 + [3, 2, 1] 16 4 + [2, 2, 1, 1] 9 9 + """ + from sage.categories.fields import Fields + if base_ring is None or (base_ring in Fields() and base_ring.characteristic() == 0): + from sage.combinat.tableau import StandardTableaux + return StandardTableaux(self).cardinality() + from sage.combinat.specht_module import simple_module_rank + return simple_module_rank(self, base_ring) + ############## # Partitions # diff --git a/src/sage/combinat/specht_module.py b/src/sage/combinat/specht_module.py index 209890c1bd1..be38fbb2c67 100644 --- a/src/sage/combinat/specht_module.py +++ b/src/sage/combinat/specht_module.py @@ -457,3 +457,97 @@ def specht_module_rank(D, base_ring=None): if base_ring is None: base_ring = QQ return matrix(base_ring, [v.to_vector() for v in span_set]).rank() + + +def polytabloid(T): + r""" + Compute the polytabloid element associated to a tableau ``T``. + + For a tableau `T`, the polytabloid associated to `T` is + + .. MATH:: + + e_T = \sum_{\sigma \in C_T} (-1)^{\sigma} \{\sigma T\}, + + where `\{\}` is the row-equivalence class, i.e. a tabloid, + and `C_T` is the column stabilizer of `T`. The sum takes place in + the module spanned by tabloids `\{T\}`. + + OUTPUT: + + A ``dict`` whose keys are taboids represented by tuples of frozensets + and whose values are the coefficient. + + EXAMPLES:: + + sage: from sage.combinat.specht_module import polytabloid + sage: T = StandardTableau([[1,3,4],[2,5]]) + sage: polytabloid(T) + {(frozenset({1, 3, 4}), frozenset({2, 5})): 1, + (frozenset({1, 4, 5}), frozenset({2, 3})): -1, + (frozenset({2, 3, 4}), frozenset({1, 5})): -1, + (frozenset({2, 4, 5}), frozenset({1, 3})): 1} + """ + e_T = {} + C_T = T.column_stabilizer() + for perm in C_T: + TT = tuple([frozenset(perm(val) for val in row) for row in T]) + if TT in e_T: + e_T[TT] += perm.sign() + else: + e_T[TT] = perm.sign() + return e_T + + +def tabloid_gram_matrix(la, base_ring): + r""" + Compute the Gram matrix of the bilinear form of a Specht module + pulled back from the tabloid module. + + For the module spanned by all tabloids, we define an bilinear form + by having the taboids be an orthonormal basis. We then pull this + bilinear form back across the natural injection of the Specht module + into the tabloid module. + + EXAMPLES:: + + sage: from sage.combinat.specht_module import tabloid_gram_matrix + sage: tabloid_gram_matrix([3,2], GF(5)) + [4 2 2 1 4] + [2 4 1 2 1] + [2 1 4 2 1] + [1 2 2 4 2] + [4 1 1 2 4] + """ + from sage.combinat.tableau import StandardTableaux + ST = StandardTableaux(la) + + def bilinear_form(p1, p2): + if len(p2) < len(p1): + p1, p2 = p2, p1 + return sum(c1 * p2.get(T1, 0) for T1, c1 in p1.items() if c1) + + gram_matrix = [[bilinear_form(polytabloid(T1), polytabloid(T2)) for T1 in ST] for T2 in ST] + return matrix(base_ring, gram_matrix) + + +def simple_module_rank(la, base_ring): + r""" + Return the rank of the simple `S_n`-module corresponding to the + partition ``la`` of size `n` over ``base_ring``. + + EXAMPLES:: + + sage: from sage.combinat.specht_module import simple_module_rank + sage: simple_module_rank([3,2,1,1], GF(3)) + 13 + """ + from sage.categories.fields import Fields + from sage.combinat.partition import Partition + if base_ring not in Fields(): + raise NotImplementedError("the base must be a field") + p = base_ring.characteristic() + la = Partition(la) + if not la.is_regular(p): + raise ValueError(f"the partition {la} is not {p}-regular") + return tabloid_gram_matrix(la, base_ring).rank() diff --git a/src/sage/combinat/symmetric_group_algebra.py b/src/sage/combinat/symmetric_group_algebra.py index 84b29a770b2..cb7df991ced 100644 --- a/src/sage/combinat/symmetric_group_algebra.py +++ b/src/sage/combinat/symmetric_group_algebra.py @@ -1587,6 +1587,26 @@ def specht_module_dimension(self, D): span_set = specht_module_spanning_set(D, self) return matrix(self.base_ring(), [v.to_vector() for v in span_set]).rank() + def simple_module_dimension(self, la): + r""" + Return the dimension of the simple module of ``self`` indexed by the + partition ``la``. + + EXAMPLES:: + + sage: SGA = SymmetricGroupAlgebra(GF(5), 6) + sage: SGA.simple_module_dimension(Partition([4,1,1])) + 10 + sage: SGA.simple_module_dimension(Partition([3,1,1])) + Traceback (most recent call last): + ... + ValueError: [3, 1, 1] is not a partition of 6 + """ + if sum(la) != self.n: + raise ValueError(f"{la} is not a partition of {self.n}") + from sage.combinat.specht_module import simple_module_rank + return simple_module_rank(la, self.base_ring()) + def jucys_murphy(self, k): r""" Return the Jucys-Murphy element `J_k` (also known as a diff --git a/src/sage/combinat/tableau.py b/src/sage/combinat/tableau.py index cf44091d16d..f716c7cd117 100644 --- a/src/sage/combinat/tableau.py +++ b/src/sage/combinat/tableau.py @@ -2999,7 +2999,16 @@ def column_stabilizer(self): sage: PermutationGroupElement([(1,4)]) in cs True """ - return self.conjugate().row_stabilizer() + # Ensure that the permutations involve all elements of the + # tableau, by including the identity permutation on the set [1..k]. + k = self.size() + gens = [list(range(1, k + 1))] + ell = len(self) + while ell > 1: + ell -= 1 + for i, val in enumerate(self[ell]): + gens.append((val, self[ell-1][i])) + return PermutationGroup(gens) def height(self): """ From 721b9521e5a85fdcb46449b5dd22d01379d5c0f6 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 17 Nov 2023 10:42:11 +0900 Subject: [PATCH 120/155] Addressing reviewer comments. --- src/sage/combinat/partition.py | 4 ++-- src/sage/combinat/specht_module.py | 18 ++++++++++++++++-- src/sage/combinat/symmetric_group_algebra.py | 4 ++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/partition.py b/src/sage/combinat/partition.py index 064d7606222..7d16d5d3410 100644 --- a/src/sage/combinat/partition.py +++ b/src/sage/combinat/partition.py @@ -5538,8 +5538,8 @@ def simple_module_dimension(self, base_ring=None): r""" Return the dimension of the simple module corresponding to ``self``. - This is equal to the dimension of the Specht module over a field - of characteristic `0`. + When the base ring is a field of characteristic `0`, this is equal + to the dimension of the Specht module. INPUT: diff --git a/src/sage/combinat/specht_module.py b/src/sage/combinat/specht_module.py index be38fbb2c67..62842b11a30 100644 --- a/src/sage/combinat/specht_module.py +++ b/src/sage/combinat/specht_module.py @@ -475,7 +475,7 @@ def polytabloid(T): OUTPUT: - A ``dict`` whose keys are taboids represented by tuples of frozensets + A ``dict`` whose keys are tabloids represented by tuples of frozensets and whose values are the coefficient. EXAMPLES:: @@ -505,7 +505,7 @@ def tabloid_gram_matrix(la, base_ring): pulled back from the tabloid module. For the module spanned by all tabloids, we define an bilinear form - by having the taboids be an orthonormal basis. We then pull this + by having the tabloids be an orthonormal basis. We then pull this bilinear form back across the natural injection of the Specht module into the tabloid module. @@ -541,6 +541,20 @@ def simple_module_rank(la, base_ring): sage: from sage.combinat.specht_module import simple_module_rank sage: simple_module_rank([3,2,1,1], GF(3)) 13 + + TESTS:: + + sage: from sage.combinat.specht_module import simple_module_rank + sage: simple_module_rank([1,1,1,1], GF(3)) + Traceback (most recent call last): + ... + ValueError: the partition [1, 1, 1, 1] is not 3-regular + + sage: from sage.combinat.specht_module import simple_module_rank + sage: simple_module_rank([2,1], GF(3)['x']) + Traceback (most recent call last): + ... + NotImplementedError: the base must be a field """ from sage.categories.fields import Fields from sage.combinat.partition import Partition diff --git a/src/sage/combinat/symmetric_group_algebra.py b/src/sage/combinat/symmetric_group_algebra.py index cb7df991ced..0b4ba3129d9 100644 --- a/src/sage/combinat/symmetric_group_algebra.py +++ b/src/sage/combinat/symmetric_group_algebra.py @@ -1597,6 +1597,10 @@ def simple_module_dimension(self, la): sage: SGA = SymmetricGroupAlgebra(GF(5), 6) sage: SGA.simple_module_dimension(Partition([4,1,1])) 10 + + TESTS:: + + sage: SGA = SymmetricGroupAlgebra(GF(5), 6) sage: SGA.simple_module_dimension(Partition([3,1,1])) Traceback (most recent call last): ... From 87f85b99cc7f6694b6a0f7ddc03e911cb6156fc1 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Wed, 8 Nov 2023 08:57:26 +0000 Subject: [PATCH 121/155] symengine 0.11.1 --- build/pkgs/symengine/checksums.ini | 6 +++--- build/pkgs/symengine/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/symengine/checksums.ini b/build/pkgs/symengine/checksums.ini index 1c1813e7eea..8eb65f05ef9 100644 --- a/build/pkgs/symengine/checksums.ini +++ b/build/pkgs/symengine/checksums.ini @@ -1,5 +1,5 @@ tarball=symengine-VERSION.tar.gz -sha1=11885879ddcd0a9ab69e36a79b93aef836d6c95d -md5=4673c85b423241ce85a9df35a7ed61bb -cksum=1344562381 +sha1=a2c8957f2099c9199751b165f107bf93d6823818 +md5=fe3c3fee1bd8dfdb9576fc2d28cb1076 +cksum=3544211225 upstream_url=https://github.com/symengine/symengine/releases/download/vVERSION/symengine-VERSION.tar.gz diff --git a/build/pkgs/symengine/package-version.txt b/build/pkgs/symengine/package-version.txt index 571215736a6..af88ba82486 100644 --- a/build/pkgs/symengine/package-version.txt +++ b/build/pkgs/symengine/package-version.txt @@ -1 +1 @@ -0.10.1 +0.11.1 From 5d7f73027a7cbd3cc62e61413937bcf8820e7bda Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Wed, 8 Nov 2023 09:48:38 +0000 Subject: [PATCH 122/155] spkg-configure for symengine --- build/pkgs/symengine/spkg-configure.m4 | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 build/pkgs/symengine/spkg-configure.m4 diff --git a/build/pkgs/symengine/spkg-configure.m4 b/build/pkgs/symengine/spkg-configure.m4 new file mode 100644 index 00000000000..c037d2e5f72 --- /dev/null +++ b/build/pkgs/symengine/spkg-configure.m4 @@ -0,0 +1,45 @@ +SAGE_SPKG_CONFIGURE([symengine], [ + m4_pushdef(SAGE_SYMENGINE_VERSION_MAJOR, [0]) + m4_pushdef(SAGE_SYMENGINE_VERSION_MINOR, [11]) + SAGE_SPKG_DEPCHECK([gmp arb ecm flint mpc mpfr], [ + AC_CHECK_HEADER([symengine/symengine_config.h], [], [sage_spkg_install_symengine=yes]) + AC_MSG_CHECKING([whether we can link a program using symengine]) + SYMENGINE_SAVED_LIBS=$LIBS + LIBS="$LIBS -lsymengine" + AC_LINK_IFELSE([ + AC_LANG_PROGRAM([[#include ]], + [[using SymEngine::Expression; + Expression x("x"); + auto ex = pow(x+sqrt(Expression(2)), 6);]] + )], [AC_MSG_RESULT([yes])], [ + AC_MSG_RESULT([no]); sage_spkg_install_symengine=yes + LIBS=$SYMENGINE_SAVED_LIBS + ]) + AC_MSG_CHECKING([symengine version >= ]SAGE_SYMENGINE_VERSION_MAJOR[.]SAGE_SYMENGINE_VERSION_MINOR) + AC_RUN_IFELSE([ + AC_LANG_PROGRAM( + [[#include + #include + ]], [[ + fprintf(stderr, "%s\n", SYMENGINE_VERSION); + if (SYMENGINE_MAJOR_VERSION >]] SAGE_SYMENGINE_VERSION_MAJOR[[) return 0; + else if (SYMENGINE_MAJOR_VERSION ==]] SAGE_SYMENGINE_VERSION_MAJOR[[ && + SYMENGINE_MINOR_VERSION >=]] SAGE_SYMENGINE_VERSION_MINOR[[) return 0; + else return 1; + ]])], [ + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + sage_spkg_install_symengine=yes + ], [ + dnl assume that the person running cross-compiling + dnl knows what they are doing + AC_MSG_RESULT([yes]) + ]) + ]) + + m4_popdef([SAGE_SYMENGINE_VERSION_MAJOR]) + m4_popdef([SAGE_SYMENGINE_VERSION_MINOR]) +], [], [], [] +) + From 68049b6cf31f03f8721dcd8f2e58b4830879bd24 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Wed, 8 Nov 2023 10:09:05 +0000 Subject: [PATCH 123/155] data for symengine_py from the system --- build/pkgs/symengine_py/distros/gentoo.txt | 1 + build/pkgs/symengine_py/package-version.txt | 2 +- build/pkgs/symengine_py/spkg-configure.m4 | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 build/pkgs/symengine_py/distros/gentoo.txt create mode 100644 build/pkgs/symengine_py/spkg-configure.m4 diff --git a/build/pkgs/symengine_py/distros/gentoo.txt b/build/pkgs/symengine_py/distros/gentoo.txt new file mode 100644 index 00000000000..e8851805aea --- /dev/null +++ b/build/pkgs/symengine_py/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/symengine diff --git a/build/pkgs/symengine_py/package-version.txt b/build/pkgs/symengine_py/package-version.txt index 78bc1abd14f..d9df1bbc0c7 100644 --- a/build/pkgs/symengine_py/package-version.txt +++ b/build/pkgs/symengine_py/package-version.txt @@ -1 +1 @@ -0.10.0 +0.11.0 diff --git a/build/pkgs/symengine_py/spkg-configure.m4 b/build/pkgs/symengine_py/spkg-configure.m4 new file mode 100644 index 00000000000..9559bdb6da0 --- /dev/null +++ b/build/pkgs/symengine_py/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([symengine_py], [SAGE_PYTHON_PACKAGE_CHECK([symengine_py])]) From 065e004492673ccb1f16588fc312d779cf00f8ab Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Thu, 23 Nov 2023 12:40:07 +0000 Subject: [PATCH 124/155] symengine_py now on PyPI --- build/pkgs/symengine_py/checksums.ini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/symengine_py/checksums.ini b/build/pkgs/symengine_py/checksums.ini index 0235c5e9cd9..f8790fdfb4e 100644 --- a/build/pkgs/symengine_py/checksums.ini +++ b/build/pkgs/symengine_py/checksums.ini @@ -1,5 +1,5 @@ tarball=symengine.py-VERSION.tar.gz -sha1=fbbf052e66077ec51df319444b71f94114f33d9e -md5=fc5d2d7f571a880aa2e040214aed2ff0 -cksum=2535731241 -upstream_url=https://github.com/symengine/symengine.py/archive/vVERSION.tar.gz +sha1=4a8da0d0a057c8709c5b28543dbb3d26a060f013 +md5=d10f4ba5c27b09ef234fcafddf824ce5 +cksum=1332096394 +upstream_url=https://pypi.io/packages/source/p/symengine/symengine-VERSION.tar.gz From aad29030459aee2b754737821ad099aa87d4662d Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Thu, 23 Nov 2023 13:14:03 +0000 Subject: [PATCH 125/155] features for symengine_py --- src/sage/features/symengine_py.py | 43 +++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/sage/features/symengine_py.py diff --git a/src/sage/features/symengine_py.py b/src/sage/features/symengine_py.py new file mode 100644 index 00000000000..e708992782e --- /dev/null +++ b/src/sage/features/symengine_py.py @@ -0,0 +1,43 @@ +r""" +Check for symengine_py +""" + +# **************************************************************************** +# Copyright (C) 2023 Dima Pasechnik +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from . import PythonModule +from .join_feature import JoinFeature + + +class symengine_py(JoinFeature): + r""" + A :class:`sage.features.Feature` describing the presence of the + Python package :ref:`symengine_py `. + + EXAMPLES:: + + sage: from sage.features.igraph import symengine_py + sage: symengine_py().is_present() # optional - symengine_py + FeatureTestResult('symengine_py', True) + """ + def __init__(self): + r""" + TESTS:: + + sage: from sage.features.symengine_py import symengine_py + sage: isinstance(symengine_py(), symengine_py) + True + """ + JoinFeature.__init__(self, 'symengine_py', + [PythonModule('symengine', spkg="symengine_py", + url="https://pypi.org/project/symengine")]) + +def all_features(): + return [symengine_py()] From 3560115cafbbb13b1986b799ea2e12a0cb4bea94 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Thu, 23 Nov 2023 15:04:09 +0100 Subject: [PATCH 126/155] better description of input parameter --- src/sage/graphs/graph_decompositions/tree_decomposition.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/graphs/graph_decompositions/tree_decomposition.pyx b/src/sage/graphs/graph_decompositions/tree_decomposition.pyx index 3a73cbc8cc5..68049866b15 100644 --- a/src/sage/graphs/graph_decompositions/tree_decomposition.pyx +++ b/src/sage/graphs/graph_decompositions/tree_decomposition.pyx @@ -793,7 +793,7 @@ def length_of_tree_decomposition(G, T, check=True): INPUT: - - ``G`` -- a sage Graph + - ``G`` -- a graph - ``T`` -- a tree-decomposition for `G` From 5b7edf7b5a45a5e8ce7ce4962c445922ca2d6c17 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Thu, 23 Nov 2023 15:28:13 +0100 Subject: [PATCH 127/155] add latex macro \dist and use it --- src/sage/graphs/graph_decompositions/tree_decomposition.pyx | 6 +++--- src/sage/misc/latex_macros.py | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sage/graphs/graph_decompositions/tree_decomposition.pyx b/src/sage/graphs/graph_decompositions/tree_decomposition.pyx index 68049866b15..def8c4e355f 100644 --- a/src/sage/graphs/graph_decompositions/tree_decomposition.pyx +++ b/src/sage/graphs/graph_decompositions/tree_decomposition.pyx @@ -29,7 +29,7 @@ treewidth of a tree equal to one. The *length* of a tree decomposition, as proposed in [DG2006]_, is the maximum *diameter* in `G` of its bags, where the diameter of a bag `X_i` is the largest distance in `G` between the vertices in `X_i` (i.e., `\max_{u, v \in X_i} -dist_G(u, v)`). The *treelength* `tl(G)` of a graph `G` is the minimum length +\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 @@ -787,7 +787,7 @@ def length_of_tree_decomposition(G, T, check=True): The *length* of a tree decomposition, as proposed in [DG2006]_, is the maximum *diameter* in `G` of its bags, where the diameter of a bag `X_i` is the largest distance in `G` between the vertices in `X_i` (i.e., `\max_{u, v - \in X_i} dist_G(u, v)`). See the documentation of the + \in X_i} \dist_G(u, v)`). See the documentation of the :mod:`~sage.graphs.graph_decompositions.tree_decomposition` module for more details. @@ -1387,7 +1387,7 @@ def treelength(G, k=None, certificate=False): The *length* of a tree decomposition, as proposed in [DG2006]_, is the maximum *diameter* in `G` of its bags, where the diameter of a bag `X_i` is the largest distance in `G` between the vertices in `X_i` (i.e., `\max_{u, v - \in X_i} dist_G(u, v)`). The *treelength* `tl(G)` of a graph `G` is the + \in X_i} \dist_G(u, v)`). The *treelength* `tl(G)` of a graph `G` is the minimum length among all possible tree decompositions of `G`. See the documentation of the :mod:`~sage.graphs.graph_decompositions.tree_decomposition` module for more diff --git a/src/sage/misc/latex_macros.py b/src/sage/misc/latex_macros.py index 238bd02c0e3..93fb11fbf48 100644 --- a/src/sage/misc/latex_macros.py +++ b/src/sage/misc/latex_macros.py @@ -174,7 +174,8 @@ def convert_latex_macro_to_mathjax(macro): # Use this list to define additional latex macros for sage documentation latex_macros = [r"\newcommand{\SL}{\mathrm{SL}}", r"\newcommand{\PSL}{\mathrm{PSL}}", - r"\newcommand{\lcm}{\mathop{\operatorname{lcm}}}"] + r"\newcommand{\lcm}{\mathop{\operatorname{lcm}}}", + r"\newcommand{\dist}{\mathrm{dist}}"] # The following is to allow customization of typesetting of rings: # mathbf vs mathbb. See latex.py for more information. From 7fcc517d44c72771bf609d746b24c1012e54fc4c Mon Sep 17 00:00:00 2001 From: dcoudert Date: Thu, 23 Nov 2023 18:50:52 +0100 Subject: [PATCH 128/155] fix doctest in src/sage/misc/latex.py --- src/sage/misc/latex.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/misc/latex.py b/src/sage/misc/latex.py index 602a24f404a..df469ca8189 100644 --- a/src/sage/misc/latex.py +++ b/src/sage/misc/latex.py @@ -651,6 +651,7 @@ def latex_extra_preamble(): \newcommand{\SL}{\mathrm{SL}} \newcommand{\PSL}{\mathrm{PSL}} \newcommand{\lcm}{\mathop{\operatorname{lcm}}} + \newcommand{\dist}{\mathrm{dist}} \newcommand{\Bold}[1]{\mathbf{#1}} """ From d41c0320f06ae6ab709e1c759a91a36c1657fd7b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 23 Nov 2023 11:33:40 -0800 Subject: [PATCH 129/155] build/bin/sage-spkg: Add long switches for all mode switches, complain if more than one given --- build/bin/sage-spkg | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index d097cd83588..5902d991940 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -75,17 +75,21 @@ Usage: sage {-i|-p} Search Sage's list of packages (see 'sage --package list') for a matching package, and if a match is found, install it. -Modes of operation: - -d: only download the package - -b: build and install (stage) only, do not run post-install - or check - -p: post-install only - -x: exclusively run the test suite; this may assume that: +Modes of operation (provide at most one): + -d, --download-only: only download the package + -b, --build-and-stage-only: build and install (stage) only, + do not run post-install or check + -p, --post-install-only: post-install only + -x, --check-only: exclusively run the test suite; + this may assume that: * the package has been installed already and/or that * the temporary build directory has not been deleted - -e: erase (delete) the temporary build directory only + -e, --erase-build-directory-only: erase (delete) the temporary + build directory only + --info: print information on the package only + --help: print this help only -Options: +Other options: -y: automatically reply "y" for all prompts regarding experimental and old-style packages; warning: there is no guarantee that these packages will build correctly; @@ -229,15 +233,21 @@ KEEP_EXISTING=0 INSTALL=1 POST_INSTALL=1 ERASE_ONLY=0 +MODE_SWITCHES= while true; do case "$1" in --info) + MODE_SWITCHES+=", $1" INFO=1;; + --help) + usage + exit 0;; -y) YES=1;; -n) YES=-1;; - -d) + -d|--download-only) + MODE_SWITCHES+=", $1" SAGE_INSTALL_FETCH_ONLY=1;; -s) export SAGE_KEEP_BUILT_SPKGS=yes;; @@ -246,14 +256,18 @@ while true; do -w|--check-warning-only) export SAGE_CHECK=warn;; -b|--build-and-stage-only) + MODE_SWITCHES+=", $1" POST_INSTALL=0; export SAGE_CHECK=no;; -p|--post-install-only) + MODE_SWITCHES+=", $1" INSTALL=0; export SAGE_CHECK=no;; -x|--check-only) + MODE_SWITCHES+=", $1" INSTALL=0; POST_INSTALL=0; export SAGE_CHECK=yes;; -k|--keep-existing) KEEP_EXISTING=yes;; -e|--erase-build-directory-only) + MODE_SWITCHES+=", $1" ERASE_ONLY=1;; -o|--allow-upstream) SAGE_DOWNLOAD_FILE_OPTIONS+=" --allow-upstream";; @@ -264,7 +278,15 @@ while true; do esac shift done - +MODE_SWITCHES=${MODE_SWITCHES#, } +case "$MODE_SWITCHES" in + *,*) + echo >&2 "Error: at most one of the mode switches may be given, got $MODE_SWITCHES" + echo >&2 + usage + exit 1 + ;; +esac # One should be able to install a package using # sage -i From 756ae53a73b943c56dd5f1d4de7b649eaeff0beb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 23 Nov 2023 11:37:34 -0800 Subject: [PATCH 130/155] build/bin/sage-spkg: Make it clearer that one can unload the staged installation only once --- build/bin/sage-spkg | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 5902d991940..19553b3c139 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -79,7 +79,8 @@ Modes of operation (provide at most one): -d, --download-only: only download the package -b, --build-and-stage-only: build and install (stage) only, do not run post-install or check - -p, --post-install-only: post-install only + -p, --post-install-only: unload the staged installation + directory and run other post-installation steps only -x, --check-only: exclusively run the test suite; this may assume that: * the package has been installed already and/or that @@ -685,7 +686,7 @@ rm -f "$SAGE_DESTDIR_LOCAL/lib64" # All spkgs should eventually support this, but fall back on old behavior in # case DESTDIR=$SAGE_DESTDIR installation was not used if [ -d "$SAGE_DESTDIR" ]; then - echo "Copying package files from temporary location $SAGE_DESTDIR to $SAGE_INST_LOCAL" + echo "Moving package files from temporary location $SAGE_DESTDIR to $SAGE_INST_LOCAL" # Some `find` implementations will put superfluous slashes in the # output if we give them a directory name with a slash; so make sure # any trailing slash is removed; https://github.com/sagemath/sage/issues/26013 @@ -703,7 +704,7 @@ if [ -d "$SAGE_DESTDIR" ]; then # Copy files into $SAGE_INST_LOCAL $SAGE_SUDO cp -Rp "$PREFIX/." "$SAGE_INST_LOCAL" if [ $? -ne 0 ]; then - error_msg "Error copying files for $PKG_NAME." + error_msg "Error moving files for $PKG_NAME." exit 1 fi @@ -711,7 +712,7 @@ if [ -d "$SAGE_DESTDIR" ]; then # final location. rm -rf "$SAGE_DESTDIR" else - echo "The temporary location $SAGE_DESTDIR does not exist; has the build directory been deleted?" + echo "The temporary location $SAGE_DESTDIR does not exist; has it been unloaded already?" exit 1 fi From 99eb4f354ec976c57ae6dbb5f481cb0b7878ecb1 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Fri, 24 Nov 2023 14:42:33 +0900 Subject: [PATCH 131/155] Split out script --- .ci/create-changes-html.sh | 92 +++++++++++++++++++++++++++++ .github/workflows/doc-build.yml | 100 ++++---------------------------- 2 files changed, 102 insertions(+), 90 deletions(-) create mode 100755 .ci/create-changes-html.sh diff --git a/.ci/create-changes-html.sh b/.ci/create-changes-html.sh new file mode 100755 index 00000000000..8399048c830 --- /dev/null +++ b/.ci/create-changes-html.sh @@ -0,0 +1,92 @@ +#!/bin/sh +if [ $# != 2 ]; then + echo >&2 "usage: $0 BASE_DOC_COMMIT DOC_REPOSITORY" + echo >&2 "Ensures that DOC_REPOSITORY is a git repository," + echo >&2 "then creates CHANGES.html in the docs subdirectory" + echo >&2 "for the diffs of DOC_REPOSITORY against BASE_DOC_COMMIT" +fi +BASE_DOC_COMMIT="$1" +DOC_REPOSITORY="$2" + +mkdir -p ./docs +(cd $DOC_REPOSITORY && git commit -a -m 'new') +# Wipe out chronic diffs between old doc and new doc +(cd $DOC_REPOSITORY && find . -name "*.html" | xargs sed -i -e '\;; d') +# Create CHANGES.html +echo '' > ./docs/CHANGES.html +echo '' >> ./docs/CHANGES.html +echo '' >> ./docs/CHANGES.html +echo '' >> ./docs/CHANGES.html +echo '' >> ./docs/CHANGES.html +cat >> ./docs/CHANGES.html << EOF + +EOF +echo '' >> ./docs/CHANGES.html +echo '' >> ./docs/CHANGES.html +(cd $DOC_REPOSITORY && git diff $BASE_DOC_COMMIT -- *.html; rm -rf .git) > ./docs/diff.txt +/sage/sage -python - << EOF +import os, re, html +with open('./docs/diff.txt', 'r') as f: +diff_text = f.read() +diff_blocks = re.split(r'^(?=diff --git)', diff_text, flags=re.MULTILINE) +out_blocks = [] +for block in diff_blocks: + match = re.search(r'^diff --git a/(.*) b/\1', block, flags=re.MULTILINE) + if match: + path = 'html/' + match.group(1) + file_path = os.path.join('/sage/local/share/doc/sage', path) + with open(file_path, 'r') as file: + content = file.readlines() + count = 0 + for line in block.splitlines(): + if line.startswith('@@ -'): + line_number = int(re.search(r'@@ -(\d+)', line).group(1)) + for i in range(line_number, -1, -1): + if content[i].startswith('<'): + count += 1 + content[i] = f'' + content[i] + break + with open(file_path, 'w') as file: + file.writelines(content) + hunks = ' '.join(f'#{i+1}' for i in range(count)) + out_blocks.append(f'

{path} ' + hunks + ' 

' + + '\n
'
+                      + html.escape(block).strip() + '
') +output_text = '\n'.join(out_blocks) +with open('./docs/diff.html', 'w') as f: +f.write(output_text) +EOF +cat ./docs/diff.html >> ./docs/CHANGES.html +echo '' >> ./docs/CHANGES.html +echo '' >>./docs/CHANGES.html +rm ./docs/diff.txt ./docs/diff.html diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 2721d5b420a..7ef2b0e406e 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -68,8 +68,8 @@ jobs: -e 's;'"$mathjax_path_from"';'"$mathjax_path_to"';' \ -e '\;; d') # Create git repo from old doc - (cd /sage/local/share/doc/sage/html && \ - git init && \ + DOC_DIR=/sage/local/share/doc/sage/html + (cd $DOC_DIR && git init && \ (echo "*.svg binary"; echo "*.pdf binary") >> .gitattributes && \ (echo ".buildinfo"; echo '*.inv'; echo '.git*'; echo '*.svg'; echo '*.pdf'; echo '*.png'; echo 'searchindex.js') > .gitignore; \ git add -A && git commit --quiet -m "old") @@ -115,10 +115,11 @@ jobs: # incremental docbuild may introduce broken links (inter-file references) though build succeeds run: | set -ex - export SAGE_USE_CDNS=yes - mv /sage/local/share/doc/sage/html/.git /sage/.git-doc + DOC_DIR=/sage/local/share/doc/sage/html + mv $DOC_DIR/.git /sage/.git-doc make doc-clean doc-uninstall - mkdir -p /sage/local/share/doc/sage/html/ && mv /sage/.git-doc /sage/local/share/doc/sage/html/.git + mkdir -p $DOC_DIR/ && mv /sage/.git-doc $DOC_DIR/.git + export SAGE_USE_CDNS=yes ./config.status && make sagemath_doc_html-no-deps working-directory: ./worktree-image env: @@ -130,94 +131,13 @@ jobs: if: (success() || failure()) && steps.docbuild.outcome == 'success' run: | set -ex - mkdir -p ./docs - (cd /sage/local/share/doc/sage/html && git commit -a -m 'new') - # Wipe out chronic diffs between old doc and new doc - (cd /sage/local/share/doc/sage/html && \ - find . -name "*.html" | xargs sed -i -e '\;; d') - # Create CHANGES.html - echo '' > ./docs/CHANGES.html - echo '' >> ./docs/CHANGES.html - echo '' >> ./docs/CHANGES.html - echo '' >> ./docs/CHANGES.html - echo '' >> ./docs/CHANGES.html - cat >> ./docs/CHANGES.html << EOF - - EOF - echo '' >> ./docs/CHANGES.html - echo '' >> ./docs/CHANGES.html - (cd /sage/local/share/doc/sage/html && git diff HEAD^ -- *.html; rm -rf .git) > ./docs/diff.txt - /sage/sage -python - << EOF - import os, re, html - with open('./docs/diff.txt', 'r') as f: - diff_text = f.read() - diff_blocks = re.split(r'^(?=diff --git)', diff_text, flags=re.MULTILINE) - out_blocks = [] - for block in diff_blocks: - match = re.search(r'^diff --git a/(.*) b/\1', block, flags=re.MULTILINE) - if match: - path = 'html/' + match.group(1) - file_path = os.path.join('/sage/local/share/doc/sage', path) - with open(file_path, 'r') as file: - content = file.readlines() - count = 0 - for line in block.splitlines(): - if line.startswith('@@ -'): - line_number = int(re.search(r'@@ -(\d+)', line).group(1)) - for i in range(line_number, -1, -1): - if content[i].startswith('<'): - count += 1 - content[i] = f'' + content[i] - break - with open(file_path, 'w') as file: - file.writelines(content) - hunks = ' '.join(f'#{i+1}' for i in range(count)) - out_blocks.append(f'

{path} ' + hunks + ' 

' - + '\n
'
-                                  + html.escape(block).strip() + '
') - output_text = '\n'.join(out_blocks) - with open('./docs/diff.html', 'w') as f: - f.write(output_text) - EOF - cat ./docs/diff.html >> ./docs/CHANGES.html - echo '' >> ./docs/CHANGES.html - echo '' >>./docs/CHANGES.html - rm ./docs/diff.txt ./docs/diff.html + DOC_DIR=/sage/local/share/doc/sage/html + .ci/create-doc-diffs-page.sh $(cd $DOC_DIR; git rev-parse HEAD^) $DOC_DIR # For some reason the deploy step below cannot find /sage/... # So copy everything from there to local folder # We also need to replace the symlinks because netlify is not following them - cp -r -L /sage/local/share/doc/sage/html ./docs - cp /sage/local/share/doc/sage/index.html ./docs + cp -r -L $DOC_DIR ./docs + cp $DOC_DIR/../index.html ./docs # Zip everything for increased performance zip -r docs.zip docs From fed139e5a9cd5525232c990d0056e343f3ac1960 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Fri, 24 Nov 2023 14:46:02 +0900 Subject: [PATCH 132/155] Error if wrong arguments --- .ci/create-changes-html.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/create-changes-html.sh b/.ci/create-changes-html.sh index 8399048c830..aa45b810d79 100755 --- a/.ci/create-changes-html.sh +++ b/.ci/create-changes-html.sh @@ -4,6 +4,7 @@ if [ $# != 2 ]; then echo >&2 "Ensures that DOC_REPOSITORY is a git repository," echo >&2 "then creates CHANGES.html in the docs subdirectory" echo >&2 "for the diffs of DOC_REPOSITORY against BASE_DOC_COMMIT" + exit 1 fi BASE_DOC_COMMIT="$1" DOC_REPOSITORY="$2" From 0265da1aa93652d1d7c1f281108c1e48ed1be6ad Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Fri, 24 Nov 2023 14:49:11 +0900 Subject: [PATCH 133/155] Make script name right --- .github/workflows/doc-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 7ef2b0e406e..b4964e4e163 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -132,7 +132,7 @@ jobs: run: | set -ex DOC_DIR=/sage/local/share/doc/sage/html - .ci/create-doc-diffs-page.sh $(cd $DOC_DIR; git rev-parse HEAD^) $DOC_DIR + .ci/create-changes-html.sh $(cd $DOC_DIR; git rev-parse HEAD^) $DOC_DIR # For some reason the deploy step below cannot find /sage/... # So copy everything from there to local folder # We also need to replace the symlinks because netlify is not following them From 380cc8e705d93ef4bb384e22543fc1da5c76dd88 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Fri, 24 Nov 2023 14:51:30 +0900 Subject: [PATCH 134/155] Fix help text --- .ci/create-changes-html.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.ci/create-changes-html.sh b/.ci/create-changes-html.sh index aa45b810d79..9aa3e31b0f6 100755 --- a/.ci/create-changes-html.sh +++ b/.ci/create-changes-html.sh @@ -1,8 +1,7 @@ #!/bin/sh if [ $# != 2 ]; then echo >&2 "usage: $0 BASE_DOC_COMMIT DOC_REPOSITORY" - echo >&2 "Ensures that DOC_REPOSITORY is a git repository," - echo >&2 "then creates CHANGES.html in the docs subdirectory" + echo >&2 "creates CHANGES.html in the docs subdirectory" echo >&2 "for the diffs of DOC_REPOSITORY against BASE_DOC_COMMIT" exit 1 fi From e8a63abbcf8a23174c24efc61895eedbbf64238a Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Fri, 24 Nov 2023 16:04:26 +0900 Subject: [PATCH 135/155] Fix indentation --- .ci/create-changes-html.sh | 47 ++++++++++++++++----------------- .github/workflows/doc-build.yml | 1 + 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.ci/create-changes-html.sh b/.ci/create-changes-html.sh index 9aa3e31b0f6..05a41e5f521 100755 --- a/.ci/create-changes-html.sh +++ b/.ci/create-changes-html.sh @@ -9,7 +9,6 @@ BASE_DOC_COMMIT="$1" DOC_REPOSITORY="$2" mkdir -p ./docs -(cd $DOC_REPOSITORY && git commit -a -m 'new') # Wipe out chronic diffs between old doc and new doc (cd $DOC_REPOSITORY && find . -name "*.html" | xargs sed -i -e '\;; d') # Create CHANGES.html @@ -57,34 +56,34 @@ echo '' >> ./docs/CHANGES.html /sage/sage -python - << EOF import os, re, html with open('./docs/diff.txt', 'r') as f: -diff_text = f.read() + diff_text = f.read() diff_blocks = re.split(r'^(?=diff --git)', diff_text, flags=re.MULTILINE) out_blocks = [] for block in diff_blocks: - match = re.search(r'^diff --git a/(.*) b/\1', block, flags=re.MULTILINE) - if match: - path = 'html/' + match.group(1) - file_path = os.path.join('/sage/local/share/doc/sage', path) - with open(file_path, 'r') as file: - content = file.readlines() - count = 0 - for line in block.splitlines(): - if line.startswith('@@ -'): - line_number = int(re.search(r'@@ -(\d+)', line).group(1)) - for i in range(line_number, -1, -1): - if content[i].startswith('<'): - count += 1 - content[i] = f'' + content[i] - break - with open(file_path, 'w') as file: - file.writelines(content) - hunks = ' '.join(f'#{i+1}' for i in range(count)) - out_blocks.append(f'

{path} ' + hunks + ' 

' - + '\n
'
-                      + html.escape(block).strip() + '
') + match = re.search(r'^diff --git a/(.*) b/\1', block, flags=re.MULTILINE) + if match: + path = 'html/' + match.group(1) + file_path = os.path.join('$DOC_REPOSITORY/..', path) + with open(file_path, 'r') as file: + content = file.readlines() + count = 0 + for line in block.splitlines(): + if line.startswith('@@ -'): + line_number = int(re.search(r'@@ -(\d+)', line).group(1)) + for i in range(line_number, -1, -1): + if content[i].startswith('<'): + count += 1 + content[i] = f'' + content[i] + break + with open(file_path, 'w') as file: + file.writelines(content) + hunks = ' '.join(f'#{i+1}' for i in range(count)) + out_blocks.append(f'

{path} ' + hunks + ' 

' + + '\n
'
+                            + html.escape(block).strip() + '
') output_text = '\n'.join(out_blocks) with open('./docs/diff.html', 'w') as f: -f.write(output_text) + f.write(output_text) EOF cat ./docs/diff.html >> ./docs/CHANGES.html echo '' >> ./docs/CHANGES.html diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index b4964e4e163..46e4e3badb2 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -132,6 +132,7 @@ jobs: run: | set -ex DOC_DIR=/sage/local/share/doc/sage/html + (cd $DOC_DIR && git commit -a -m 'new') .ci/create-changes-html.sh $(cd $DOC_DIR; git rev-parse HEAD^) $DOC_DIR # For some reason the deploy step below cannot find /sage/... # So copy everything from there to local folder From b637cc13307061f60edbb137ed554438a54866cf Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Fri, 24 Nov 2023 16:50:52 +0900 Subject: [PATCH 136/155] Separate the script more --- .ci/create-changes-html.sh | 29 ++++++++++++++--------------- .github/workflows/doc-build.yml | 6 ++++-- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/.ci/create-changes-html.sh b/.ci/create-changes-html.sh index 05a41e5f521..76f13650a64 100755 --- a/.ci/create-changes-html.sh +++ b/.ci/create-changes-html.sh @@ -1,23 +1,22 @@ #!/bin/sh if [ $# != 2 ]; then echo >&2 "usage: $0 BASE_DOC_COMMIT DOC_REPOSITORY" - echo >&2 "creates CHANGES.html in the docs subdirectory" + echo >&2 "creates CHANGES.html in the current directory" echo >&2 "for the diffs of DOC_REPOSITORY against BASE_DOC_COMMIT" exit 1 fi BASE_DOC_COMMIT="$1" DOC_REPOSITORY="$2" -mkdir -p ./docs # Wipe out chronic diffs between old doc and new doc (cd $DOC_REPOSITORY && find . -name "*.html" | xargs sed -i -e '\;; d') # Create CHANGES.html -echo '' > ./docs/CHANGES.html -echo '' >> ./docs/CHANGES.html -echo '' >> ./docs/CHANGES.html -echo '' >> ./docs/CHANGES.html -echo '' >> ./docs/CHANGES.html -cat >> ./docs/CHANGES.html << EOF +echo '' > CHANGES.html +echo '' >> CHANGES.html +echo '' >> CHANGES.html +echo '' >> CHANGES.html +echo '' >> CHANGES.html +cat >> CHANGES.html << EOF EOF -echo '' >> ./docs/CHANGES.html -echo '' >> ./docs/CHANGES.html -(cd $DOC_REPOSITORY && git diff $BASE_DOC_COMMIT -- *.html; rm -rf .git) > ./docs/diff.txt +echo '' >> CHANGES.html +echo '' >> CHANGES.html +(cd $DOC_REPOSITORY && git diff $BASE_DOC_COMMIT -- *.html) > diff.txt /sage/sage -python - << EOF import os, re, html with open('./docs/diff.txt', 'r') as f: @@ -85,7 +84,7 @@ output_text = '\n'.join(out_blocks) with open('./docs/diff.html', 'w') as f: f.write(output_text) EOF -cat ./docs/diff.html >> ./docs/CHANGES.html -echo '' >> ./docs/CHANGES.html -echo '' >>./docs/CHANGES.html -rm ./docs/diff.txt ./docs/diff.html +cat diff.html >> CHANGES.html +echo '' >> CHANGES.html +echo '' >> CHANGES.html +rm diff.txt diff.html diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 46e4e3badb2..b83c1c801be 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -134,9 +134,11 @@ jobs: DOC_DIR=/sage/local/share/doc/sage/html (cd $DOC_DIR && git commit -a -m 'new') .ci/create-changes-html.sh $(cd $DOC_DIR; git rev-parse HEAD^) $DOC_DIR - # For some reason the deploy step below cannot find /sage/... - # So copy everything from there to local folder + (cd $DOC_DIR && rm -rf .git) + # We copy everything to a local folder # We also need to replace the symlinks because netlify is not following them + mkdir -p ./docs + mv CHANGES.html ./docs cp -r -L $DOC_DIR ./docs cp $DOC_DIR/../index.html ./docs # Zip everything for increased performance From 65a5e01c7a1b947fe74d65ed5aa37ece7c5e6706 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Fri, 24 Nov 2023 17:03:42 +0900 Subject: [PATCH 137/155] Remove ./docs prefix --- .ci/create-changes-html.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.ci/create-changes-html.sh b/.ci/create-changes-html.sh index 76f13650a64..f4d85ec503b 100755 --- a/.ci/create-changes-html.sh +++ b/.ci/create-changes-html.sh @@ -54,15 +54,16 @@ echo '' >> CHANGES.html (cd $DOC_REPOSITORY && git diff $BASE_DOC_COMMIT -- *.html) > diff.txt /sage/sage -python - << EOF import os, re, html -with open('./docs/diff.txt', 'r') as f: +with open('diff.txt', 'r') as f: diff_text = f.read() diff_blocks = re.split(r'^(?=diff --git)', diff_text, flags=re.MULTILINE) out_blocks = [] for block in diff_blocks: match = re.search(r'^diff --git a/(.*) b/\1', block, flags=re.MULTILINE) if match: - path = 'html/' + match.group(1) - file_path = os.path.join('$DOC_REPOSITORY/..', path) + doc = match.group(1) + path = 'html/' + doc + file_path = os.path.join('$DOC_REPOSITORY', doc) with open(file_path, 'r') as file: content = file.readlines() count = 0 @@ -76,12 +77,12 @@ for block in diff_blocks: break with open(file_path, 'w') as file: file.writelines(content) - hunks = ' '.join(f'#{i+1}' for i in range(count)) - out_blocks.append(f'

{path} ' + hunks + ' 

' + hunks = ' '.join(f'#{i + 1}' for i in range(count)) + out_blocks.append(f'

{doc} ' + hunks + ' 

' + '\n
'
                             + html.escape(block).strip() + '
') output_text = '\n'.join(out_blocks) -with open('./docs/diff.html', 'w') as f: +with open('diff.html', 'w') as f: f.write(output_text) EOF cat diff.html >> CHANGES.html From bd423eb23c204f75c1561ab791365cb8e8daa081 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sat, 25 Nov 2023 17:06:14 +0900 Subject: [PATCH 138/155] Use system python --- .ci/create-changes-html.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/create-changes-html.sh b/.ci/create-changes-html.sh index f4d85ec503b..80e5a389959 100755 --- a/.ci/create-changes-html.sh +++ b/.ci/create-changes-html.sh @@ -52,7 +52,7 @@ EOF echo '' >> CHANGES.html echo '' >> CHANGES.html (cd $DOC_REPOSITORY && git diff $BASE_DOC_COMMIT -- *.html) > diff.txt -/sage/sage -python - << EOF +python - << EOF import os, re, html with open('diff.txt', 'r') as f: diff_text = f.read() From 00778d7ba4c23ecf675effec5790f191b56e3f06 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sat, 25 Nov 2023 18:55:37 +0900 Subject: [PATCH 139/155] Supply Sage root --- .ci/create-changes-html.sh | 7 ++++--- .github/workflows/doc-build.yml | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.ci/create-changes-html.sh b/.ci/create-changes-html.sh index 80e5a389959..6034e20e153 100755 --- a/.ci/create-changes-html.sh +++ b/.ci/create-changes-html.sh @@ -1,12 +1,13 @@ #!/bin/sh if [ $# != 2 ]; then - echo >&2 "usage: $0 BASE_DOC_COMMIT DOC_REPOSITORY" + echo >&2 "usage: $0 BASE_DOC_COMMIT DOC_REPO SAGE_ROOT" echo >&2 "creates CHANGES.html in the current directory" - echo >&2 "for the diffs of DOC_REPOSITORY against BASE_DOC_COMMIT" + echo >&2 "for the diffs of DOC_REPO against BASE_DOC_COMMIT" exit 1 fi BASE_DOC_COMMIT="$1" DOC_REPOSITORY="$2" +SAGE_ROOT="$3" # Wipe out chronic diffs between old doc and new doc (cd $DOC_REPOSITORY && find . -name "*.html" | xargs sed -i -e '\;; d') @@ -52,7 +53,7 @@ EOF echo '' >> CHANGES.html echo '' >> CHANGES.html (cd $DOC_REPOSITORY && git diff $BASE_DOC_COMMIT -- *.html) > diff.txt -python - << EOF +$SAGE_ROOT/sage -python - << EOF import os, re, html with open('diff.txt', 'r') as f: diff_text = f.read() diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index b83c1c801be..9ba52f28595 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -131,9 +131,10 @@ jobs: if: (success() || failure()) && steps.docbuild.outcome == 'success' run: | set -ex + SAGE_ROOT=/sage DOC_DIR=/sage/local/share/doc/sage/html (cd $DOC_DIR && git commit -a -m 'new') - .ci/create-changes-html.sh $(cd $DOC_DIR; git rev-parse HEAD^) $DOC_DIR + .ci/create-changes-html.sh $(cd $DOC_DIR; git rev-parse HEAD^) $DOC_DIR $SAGE_ROOT (cd $DOC_DIR && rm -rf .git) # We copy everything to a local folder # We also need to replace the symlinks because netlify is not following them From e1242810386725586412c673c4c08d231ef34eca Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sat, 25 Nov 2023 19:47:14 +0900 Subject: [PATCH 140/155] There are 3 arguments to the script --- .ci/create-changes-html.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/create-changes-html.sh b/.ci/create-changes-html.sh index 6034e20e153..ff0ae4cd131 100755 --- a/.ci/create-changes-html.sh +++ b/.ci/create-changes-html.sh @@ -1,5 +1,5 @@ #!/bin/sh -if [ $# != 2 ]; then +if [ $# != 3 ]; then echo >&2 "usage: $0 BASE_DOC_COMMIT DOC_REPO SAGE_ROOT" echo >&2 "creates CHANGES.html in the current directory" echo >&2 "for the diffs of DOC_REPO against BASE_DOC_COMMIT" From ac82ac4c61adab26df2a826cd3b38a576f9e18cd Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sun, 26 Nov 2023 06:36:20 +0900 Subject: [PATCH 141/155] Better solution for using python --- .ci/create-changes-html.sh | 7 +++---- .github/workflows/doc-build.yml | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.ci/create-changes-html.sh b/.ci/create-changes-html.sh index ff0ae4cd131..fe112616be5 100755 --- a/.ci/create-changes-html.sh +++ b/.ci/create-changes-html.sh @@ -1,13 +1,12 @@ #!/bin/sh -if [ $# != 3 ]; then - echo >&2 "usage: $0 BASE_DOC_COMMIT DOC_REPO SAGE_ROOT" +if [ $# != 2 ]; then + echo >&2 "usage: $0 BASE_DOC_COMMIT DOC_REPO" echo >&2 "creates CHANGES.html in the current directory" echo >&2 "for the diffs of DOC_REPO against BASE_DOC_COMMIT" exit 1 fi BASE_DOC_COMMIT="$1" DOC_REPOSITORY="$2" -SAGE_ROOT="$3" # Wipe out chronic diffs between old doc and new doc (cd $DOC_REPOSITORY && find . -name "*.html" | xargs sed -i -e '\;; d') @@ -53,7 +52,7 @@ EOF echo '' >> CHANGES.html echo '' >> CHANGES.html (cd $DOC_REPOSITORY && git diff $BASE_DOC_COMMIT -- *.html) > diff.txt -$SAGE_ROOT/sage -python - << EOF +python - << EOF import os, re, html with open('diff.txt', 'r') as f: diff_text = f.read() diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 9ba52f28595..72bf285226a 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -131,10 +131,9 @@ jobs: if: (success() || failure()) && steps.docbuild.outcome == 'success' run: | set -ex - SAGE_ROOT=/sage DOC_DIR=/sage/local/share/doc/sage/html (cd $DOC_DIR && git commit -a -m 'new') - .ci/create-changes-html.sh $(cd $DOC_DIR; git rev-parse HEAD^) $DOC_DIR $SAGE_ROOT + PATH=/sage/venv/bin:$PATH .ci/create-changes-html.sh $(cd $DOC_DIR; git rev-parse HEAD^) $DOC_DIR $SAGE_ROOT (cd $DOC_DIR && rm -rf .git) # We copy everything to a local folder # We also need to replace the symlinks because netlify is not following them From e1388ba683737c99867d08918a3ea568d3d2a00f Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sun, 26 Nov 2023 15:09:26 +0900 Subject: [PATCH 142/155] Remove --- .github/workflows/doc-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 72bf285226a..c82e94b7790 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -133,7 +133,7 @@ jobs: set -ex DOC_DIR=/sage/local/share/doc/sage/html (cd $DOC_DIR && git commit -a -m 'new') - PATH=/sage/venv/bin:$PATH .ci/create-changes-html.sh $(cd $DOC_DIR; git rev-parse HEAD^) $DOC_DIR $SAGE_ROOT + PATH=/sage/venv/bin:$PATH .ci/create-changes-html.sh $(cd $DOC_DIR; git rev-parse HEAD^) $DOC_DIR (cd $DOC_DIR && rm -rf .git) # We copy everything to a local folder # We also need to replace the symlinks because netlify is not following them From 976c1b3acdc7324796381e0c8511f51d2a0ca163 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sun, 26 Nov 2023 18:45:56 +0900 Subject: [PATCH 143/155] This seems to make a difference --- .ci/create-changes-html.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/create-changes-html.sh b/.ci/create-changes-html.sh index fe112616be5..a31b38ac663 100755 --- a/.ci/create-changes-html.sh +++ b/.ci/create-changes-html.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/sh if [ $# != 2 ]; then echo >&2 "usage: $0 BASE_DOC_COMMIT DOC_REPO" echo >&2 "creates CHANGES.html in the current directory" From 7b0c6705eeabbc68682747f9986686873a68a99e Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sun, 26 Nov 2023 19:11:23 +0900 Subject: [PATCH 144/155] Second attempt --- .ci/create-changes-html.sh | 4 ++-- .github/workflows/doc-build.yml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.ci/create-changes-html.sh b/.ci/create-changes-html.sh index a31b38ac663..1a6fbeef27b 100755 --- a/.ci/create-changes-html.sh +++ b/.ci/create-changes-html.sh @@ -1,4 +1,4 @@ -#!/usr/bin/sh +#!/bin/sh if [ $# != 2 ]; then echo >&2 "usage: $0 BASE_DOC_COMMIT DOC_REPO" echo >&2 "creates CHANGES.html in the current directory" @@ -52,7 +52,7 @@ EOF echo '' >> CHANGES.html echo '' >> CHANGES.html (cd $DOC_REPOSITORY && git diff $BASE_DOC_COMMIT -- *.html) > diff.txt -python - << EOF +python3 - << EOF import os, re, html with open('diff.txt', 'r') as f: diff_text = f.read() diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index c82e94b7790..e4806d4815b 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -133,6 +133,7 @@ jobs: set -ex DOC_DIR=/sage/local/share/doc/sage/html (cd $DOC_DIR && git commit -a -m 'new') + ls -l /sage/venv/bin PATH=/sage/venv/bin:$PATH .ci/create-changes-html.sh $(cd $DOC_DIR; git rev-parse HEAD^) $DOC_DIR (cd $DOC_DIR && rm -rf .git) # We copy everything to a local folder From 071599b3c5351764f1ac72456ee65f5556fb205b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6ppe?= Date: Sun, 26 Nov 2023 19:29:17 -0800 Subject: [PATCH 145/155] Update src/sage/features/symengine_py.py Co-authored-by: Tobias Diez --- src/sage/features/symengine_py.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/features/symengine_py.py b/src/sage/features/symengine_py.py index e708992782e..d32492085b7 100644 --- a/src/sage/features/symengine_py.py +++ b/src/sage/features/symengine_py.py @@ -23,7 +23,7 @@ class symengine_py(JoinFeature): EXAMPLES:: - sage: from sage.features.igraph import symengine_py + sage: from sage.features.symengine_py import symengine_py sage: symengine_py().is_present() # optional - symengine_py FeatureTestResult('symengine_py', True) """ From 55f70cf60cb6675798adfb82dead235fe4edb394 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 27 Nov 2023 11:51:41 +0000 Subject: [PATCH 146/155] more distro info for symengine(_py) --- build/pkgs/symengine/distros/arch.txt | 1 + build/pkgs/symengine/distros/homebrew.txt | 1 + build/pkgs/symengine_py/distros/arch.txt | 1 + build/pkgs/symengine_py/distros/freebsd.txt | 1 + 4 files changed, 4 insertions(+) create mode 100644 build/pkgs/symengine/distros/arch.txt create mode 100644 build/pkgs/symengine/distros/homebrew.txt create mode 100644 build/pkgs/symengine_py/distros/arch.txt create mode 100644 build/pkgs/symengine_py/distros/freebsd.txt diff --git a/build/pkgs/symengine/distros/arch.txt b/build/pkgs/symengine/distros/arch.txt new file mode 100644 index 00000000000..7bcf459b746 --- /dev/null +++ b/build/pkgs/symengine/distros/arch.txt @@ -0,0 +1 @@ +symengine diff --git a/build/pkgs/symengine/distros/homebrew.txt b/build/pkgs/symengine/distros/homebrew.txt new file mode 100644 index 00000000000..7bcf459b746 --- /dev/null +++ b/build/pkgs/symengine/distros/homebrew.txt @@ -0,0 +1 @@ +symengine diff --git a/build/pkgs/symengine_py/distros/arch.txt b/build/pkgs/symengine_py/distros/arch.txt new file mode 100644 index 00000000000..16ff7effe29 --- /dev/null +++ b/build/pkgs/symengine_py/distros/arch.txt @@ -0,0 +1 @@ +python-symengine diff --git a/build/pkgs/symengine_py/distros/freebsd.txt b/build/pkgs/symengine_py/distros/freebsd.txt new file mode 100644 index 00000000000..9fa30f46fb7 --- /dev/null +++ b/build/pkgs/symengine_py/distros/freebsd.txt @@ -0,0 +1 @@ +math/py-symengine From f65df40d97cc5964a40ad9d0ce6e550be1b6f56c Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Wed, 29 Nov 2023 01:31:37 +0000 Subject: [PATCH 147/155] promote symengine_py to optional --- build/pkgs/symengine_py/type | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/symengine_py/type b/build/pkgs/symengine_py/type index af4d63af86d..134d9bc32d5 100644 --- a/build/pkgs/symengine_py/type +++ b/build/pkgs/symengine_py/type @@ -1 +1 @@ -experimental \ No newline at end of file +optional From e5bfb0fa7f444ce20d8a8e3c31c676411e31b57e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Nov 2023 22:12:29 +0000 Subject: [PATCH 148/155] :arrow_up: Bump actions/github-script from 6.4.0 to 7.0.1 Bumps [actions/github-script](https://github.com/actions/github-script) from 6.4.0 to 7.0.1. - [Release notes](https://github.com/actions/github-script/releases) - [Commits](https://github.com/actions/github-script/compare/v6.4.0...v7.0.1) --- updated-dependencies: - dependency-name: actions/github-script dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/doc-publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/doc-publish.yml b/.github/workflows/doc-publish.yml index 961809e343e..361dafb22e0 100644 --- a/.github/workflows/doc-publish.yml +++ b/.github/workflows/doc-publish.yml @@ -28,7 +28,7 @@ jobs: # Once https://github.com/actions/download-artifact/issues/172 and/or https://github.com/actions/download-artifact/issues/60 is implemented, we can use the official download-artifact action # For now use the solution from https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow - name: Download docs - uses: actions/github-script@v6.4.0 + uses: actions/github-script@v7.0.1 with: script: | var artifacts = await github.rest.actions.listWorkflowRunArtifacts({ @@ -97,7 +97,7 @@ jobs: if: github.event.workflow_run.conclusion == 'success' && github.repository == 'sagemath/sage' && github.event.workflow_run.head_branch == 'develop' steps: - name: Download live doc - uses: actions/github-script@v6.4.1 + uses: actions/github-script@v7.0.1 with: script: | var artifacts = await github.rest.actions.listWorkflowRunArtifacts({ From 18593aeb1cc333aac4e0b74d37d3183ef9c0264d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 20 Nov 2023 16:59:19 -0800 Subject: [PATCH 149/155] build/bin/{sage-spkg,sage-dist-helpers}: For non-sudo DESTDIR-staged installation, defer installation of wheel to post-install phase --- build/bin/sage-dist-helpers | 50 ++++++++++++++++++++++++++----------- build/bin/sage-spkg | 22 +++++++++++++--- 2 files changed, 53 insertions(+), 19 deletions(-) diff --git a/build/bin/sage-dist-helpers b/build/bin/sage-dist-helpers index b6259ca9ef1..c2355a2afbb 100644 --- a/build/bin/sage-dist-helpers +++ b/build/bin/sage-dist-helpers @@ -355,38 +355,58 @@ sdh_store_and_pip_install_wheel() { shift done sdh_store_wheel "$@" - if [ -n "$SAGE_SUDO" ]; then - # Trac #29585: Do the SAGE_DESTDIR staging of the wheel installation - # ONLY if SAGE_SUDO is set (in that case, we still do the staging so - # that we do not invoke pip as root). + + wheel_basename="${wheel##*/}" + distname="${wheel_basename%%-*}" + + if [ -d "$SAGE_BUILD_DIR/$PKG_NAME" ]; then + # Normal package install through sage-spkg; + # scripts live in the package's build directory + # until copied to the final destination by sage-spkg. + script_dir="$SAGE_BUILD_DIR/$PKG_NAME" + else + script_dir="$SAGE_SPKG_SCRIPTS/$PKG_BASE" + fi + + if [ -n "$SAGE_DESTDIR" -a -z "$SAGE_SUDO" ]; then + # We stage the wheel file and do the actual installation in post. + echo "sdh_actually_pip_install_wheel $distname $pip_options -r \"\$SAGE_SPKG_SCRIPTS/\$PKG_BASE/spkg-requirements.txt\"" >> "$script_dir"/spkg-pipinst + else if [ -n "$SAGE_DESTDIR" ]; then + # Trac #29585: Do the SAGE_DESTDIR staging of the wheel installation + # ONLY if SAGE_SUDO is set (in that case, we still do the staging so + # that we do not invoke pip as root). # --no-warn-script-location: Suppress a warning caused by --root local sudo="" local root="--root=$SAGE_DESTDIR --no-warn-script-location" - else - # Trac #32361: Of course, this can only be done for normal packages, - # whose installation goes through sage-spkg. - # For script packages, we do have to invoke pip as root. + elif [ -n "$SAGE_SUDO" ]; then + # Trac #32361: For script packages, we do have to invoke pip as root. local sudo="$SAGE_SUDO" local root="" + else + # + local sudo="" + local root="" fi - else - local sudo="" - local root="" + sdh_actually_pip_install_wheel $distname $root $pip_options -r "$SAGE_SPKG_SCRIPTS/$PKG_BASE/spkg-requirements.txt" fi + echo "sdh_pip_uninstall -r \"\$SAGE_SPKG_SCRIPTS/\$PKG_BASE/spkg-requirements.txt\"" >> "$script_dir"/spkg-piprm +} + +sdh_actually_pip_install_wheel() { + distname=$1 + shift # Trac #32659: pip no longer reinstalls local wheels if the version is the same. # Because neither (1) applying patches nor (2) local changes (in the case # of sage-conf, sage-setup, etc.) bump the version number, we need to # override this behavior. The pip install option --force-reinstall does too # much -- it also reinstalls all dependencies, which we do not want. - wheel_basename="${wheel##*/}" - distname="${wheel_basename%%-*}" $sudo sage-pip-uninstall "$distname" if [ $? -ne 0 ]; then echo "(ignoring error)" >&2 fi - $sudo sage-pip-install $root $pip_options "$wheel" || \ - sdh_die "Error installing ${wheel##*/}" + $sudo sage-pip-install "$@" || \ + sdh_die "Error installing $@" } sdh_pip_uninstall() { diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index b540c8e866f..da732bae464 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -548,9 +548,13 @@ WRAPPED_SCRIPTS="build install check preinst postinst $INSTALLED_SCRIPTS" # Prepare script for uninstallation of packages that use sdh_pip_install # or sdh_store_and_pip_install_wheel. -echo 'sdh_pip_uninstall -r $SAGE_SPKG_SCRIPTS/$PKG_BASE/spkg-requirements.txt' > spkg-piprm.in +touch spkg-piprm.in -for script in $WRAPPED_SCRIPTS; do +# Prepare script for deferred installation of packages that use sdh_pip_install +# or sdh_store_and_pip_install_wheel. +touch spkg-pipinst.in + +for script in $WRAPPED_SCRIPTS pipinst; do # pipinst can be added to WRAPPED_SCRIPTS later # 'Installed' scripts are not run immediately out of the package build # directory, and may be run later, so set their root directory to # $SAGE_ROOT @@ -706,10 +710,11 @@ INSTALLED_SCRIPTS_DEST="$SAGE_SPKG_SCRIPTS/$PKG_BASE" if [ ! -f $INSTALLED_SCRIPTS_DEST/spkg-requirements.txt ]; then # No packages to uninstall with pip, so remove the prepared uninstall script - rm -f spkg-piprm spkg-piprm.in + # and the prepared deferred installation script + rm -f spkg-piprm spkg-piprm.in spkg-pipinst spkg-pipinst.in fi -for script in $INSTALLED_SCRIPTS; do +for script in $INSTALLED_SCRIPTS pipinst; do # pipinst can be added to WRAPPED_SCRIPTS later script="spkg-$script" if [ -f "$script" ]; then @@ -729,6 +734,15 @@ done # Run the post-install script, if any +# But first complete the delayed installation of wheels. +if [ -f spkg-pipinst ]; then + echo "Running pip-install script for $PKG_NAME." + $SAGE_SUDO ./spkg-pipinst + if [ $? -ne 0 ]; then + error_msg "Error running the pipinst script for $PKG_NAME." + exit 1 + fi +fi if [ -f spkg-postinst ]; then echo "Running post-install script for $PKG_NAME." time $SAGE_SUDO ./spkg-postinst From 96d251281d90113ee4898d29110d4b831e0e6e9e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 20 Nov 2023 18:00:36 -0800 Subject: [PATCH 150/155] build/pkgs/texttable: Update to 1.7.0 --- build/pkgs/texttable/checksums.ini | 6 +++--- build/pkgs/texttable/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/texttable/checksums.ini b/build/pkgs/texttable/checksums.ini index 380a205bdd3..d8725b785b2 100644 --- a/build/pkgs/texttable/checksums.ini +++ b/build/pkgs/texttable/checksums.ini @@ -1,5 +1,5 @@ tarball=texttable-VERSION.tar.gz -sha1=25e1b92e02c8e919dc0da053efbe8c4874418a8d -md5=83eb15fb541dd857ff051a8d0c979b9c -cksum=3183998721 +sha1=0fa175fa6e0fefea31434746641bedc8cbb60248 +md5=e5d380c04fab132ccf0bbfd4f761bd51 +cksum=274394355 upstream_url=https://pypi.io/packages/source/t/texttable/texttable-VERSION.tar.gz diff --git a/build/pkgs/texttable/package-version.txt b/build/pkgs/texttable/package-version.txt index 400084b1bf2..bd8bf882d06 100644 --- a/build/pkgs/texttable/package-version.txt +++ b/build/pkgs/texttable/package-version.txt @@ -1 +1 @@ -1.6.7 +1.7.0 From bd9aa02ec3238b929ea5755b5c4b561c42263e11 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Nov 2023 17:21:22 -0800 Subject: [PATCH 151/155] build/pkgs/pip/spkg-install.in: Delay setting the Python path for self-install to post --- build/pkgs/pip/spkg-install.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/pip/spkg-install.in b/build/pkgs/pip/spkg-install.in index 651f5c1dc1e..728694365cd 100644 --- a/build/pkgs/pip/spkg-install.in +++ b/build/pkgs/pip/spkg-install.in @@ -4,7 +4,7 @@ sdh_setup_bdist_wheel # pip can install its own wheel! But first we need to ensure that the pip # source directory in on the PYTHONPATH -export PYTHONPATH="$(pwd)/src" +echo "export PYTHONPATH=\"$(pwd)/src\"" >> ../spkg-pipinst # --ignore-installed makes sure that pip does not mistake # its own source tree as an existing installation From 1f0bc9d143507dd00d4219fd535c8743caa892f8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Nov 2023 18:34:31 -0800 Subject: [PATCH 152/155] Simplification --- build/pkgs/pip/spkg-install.in | 4 ---- build/pkgs/pip/spkg-pipinst.in | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 build/pkgs/pip/spkg-pipinst.in diff --git a/build/pkgs/pip/spkg-install.in b/build/pkgs/pip/spkg-install.in index 728694365cd..6712a1583bc 100644 --- a/build/pkgs/pip/spkg-install.in +++ b/build/pkgs/pip/spkg-install.in @@ -2,10 +2,6 @@ cd src sdh_setup_bdist_wheel -# pip can install its own wheel! But first we need to ensure that the pip -# source directory in on the PYTHONPATH -echo "export PYTHONPATH=\"$(pwd)/src\"" >> ../spkg-pipinst - # --ignore-installed makes sure that pip does not mistake # its own source tree as an existing installation sdh_store_and_pip_install_wheel --ignore-installed . diff --git a/build/pkgs/pip/spkg-pipinst.in b/build/pkgs/pip/spkg-pipinst.in new file mode 100644 index 00000000000..3e3f6bbc94e --- /dev/null +++ b/build/pkgs/pip/spkg-pipinst.in @@ -0,0 +1,5 @@ +cd src + +# pip can install its own wheel! But first we need to ensure that the pip +# source directory in on the PYTHONPATH +export PYTHONPATH="$(pwd)/src" From f981b15c3ff5869e9292dfda7a6760d36db0a2e9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Dec 2023 21:55:45 -0800 Subject: [PATCH 153/155] Fix installation of pip with SAGE_SUDO --- build/bin/sage-dist-helpers | 4 ++-- build/pkgs/pip/spkg-install.in | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/build/bin/sage-dist-helpers b/build/bin/sage-dist-helpers index c2355a2afbb..b159d696745 100644 --- a/build/bin/sage-dist-helpers +++ b/build/bin/sage-dist-helpers @@ -388,7 +388,7 @@ sdh_store_and_pip_install_wheel() { local sudo="" local root="" fi - sdh_actually_pip_install_wheel $distname $root $pip_options -r "$SAGE_SPKG_SCRIPTS/$PKG_BASE/spkg-requirements.txt" + sdh_actually_pip_install_wheel $distname $root $pip_options "$wheel" fi echo "sdh_pip_uninstall -r \"\$SAGE_SPKG_SCRIPTS/\$PKG_BASE/spkg-requirements.txt\"" >> "$script_dir"/spkg-piprm } @@ -406,7 +406,7 @@ sdh_actually_pip_install_wheel() { echo "(ignoring error)" >&2 fi $sudo sage-pip-install "$@" || \ - sdh_die "Error installing $@" + sdh_die "Error installing $distname" } sdh_pip_uninstall() { diff --git a/build/pkgs/pip/spkg-install.in b/build/pkgs/pip/spkg-install.in index 6712a1583bc..651f5c1dc1e 100644 --- a/build/pkgs/pip/spkg-install.in +++ b/build/pkgs/pip/spkg-install.in @@ -2,6 +2,10 @@ cd src sdh_setup_bdist_wheel +# pip can install its own wheel! But first we need to ensure that the pip +# source directory in on the PYTHONPATH +export PYTHONPATH="$(pwd)/src" + # --ignore-installed makes sure that pip does not mistake # its own source tree as an existing installation sdh_store_and_pip_install_wheel --ignore-installed . From 1e06b2241bbcf6cb326b703911b4d5dc96da7e01 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Wed, 6 Dec 2023 16:39:46 +0100 Subject: [PATCH 154/155] fix LaTeX errors in docstring --- .../schemes/elliptic_curves/ell_finite_field.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_finite_field.py b/src/sage/schemes/elliptic_curves/ell_finite_field.py index b95726615bf..ec2ccf7f9e0 100644 --- a/src/sage/schemes/elliptic_curves/ell_finite_field.py +++ b/src/sage/schemes/elliptic_curves/ell_finite_field.py @@ -2424,21 +2424,21 @@ def special_supersingular_curve(F, *, endomorphism=False): Such a curve - - has coefficients in `\FF_p`; + - has coefficients in `\mathbb F_p`; - - has group structure `E(\FF_p) \cong \ZZ/(p+1)` and - `E(\FF_{p^2}) \cong \ZZ/(p+1) \times \ZZ/(p+1)`; + - has group structure `E(\mathbb F_p) \cong \ZZ/(p+1)` and + `E(\mathbb F_{p^2}) \cong \ZZ/(p+1) \times \ZZ/(p+1)`; - has an endomorphism `\vartheta` of small degree `q` that - anticommutes with the `\FF_p`-Frobenius on `E`. + anticommutes with the `\mathbb F_p`-Frobenius on `E`. (The significance of `\vartheta` is that any such endomorphism, - together with the `\FF_p`-Frobenius, generates the endomorphism - algebra `\End(E) \otimes \QQ`.) + together with the `\mathbb F_p`-Frobenius, generates the endomorphism + algebra `\mathrm{End}(E) \otimes \QQ`.) INPUT: - - ``F`` -- finite field `\FF_{p^r}`; + - ``F`` -- finite field `\mathbb F_{p^r}`; - ``endomorphism`` -- boolean (optional, default ``False``): When set to ``True``, it is required that `2 \mid r`, and From ab24b1c3113de27c69c6acf0b84d1695102eac46 Mon Sep 17 00:00:00 2001 From: Release Manager Date: Sun, 10 Dec 2023 13:11:42 +0100 Subject: [PATCH 155/155] Updated SageMath version to 10.3.beta1 --- CITATION.cff | 4 ++-- VERSION.txt | 2 +- build/pkgs/configure/checksums.ini | 6 +++--- build/pkgs/configure/package-version.txt | 2 +- build/pkgs/sage_conf/install-requires.txt | 2 +- build/pkgs/sage_docbuild/install-requires.txt | 2 +- build/pkgs/sage_setup/install-requires.txt | 2 +- build/pkgs/sage_sws2rst/install-requires.txt | 2 +- build/pkgs/sagelib/install-requires.txt | 2 +- build/pkgs/sagemath_bliss/install-requires.txt | 2 +- build/pkgs/sagemath_categories/install-requires.txt | 2 +- build/pkgs/sagemath_coxeter3/install-requires.txt | 2 +- build/pkgs/sagemath_environment/install-requires.txt | 2 +- build/pkgs/sagemath_mcqd/install-requires.txt | 2 +- build/pkgs/sagemath_meataxe/install-requires.txt | 2 +- build/pkgs/sagemath_objects/install-requires.txt | 2 +- build/pkgs/sagemath_repl/install-requires.txt | 2 +- build/pkgs/sagemath_sirocco/install-requires.txt | 2 +- build/pkgs/sagemath_tdlib/install-requires.txt | 2 +- pkgs/sage-conf/VERSION.txt | 2 +- pkgs/sage-conf_conda/VERSION.txt | 2 +- pkgs/sage-conf_pypi/VERSION.txt | 2 +- pkgs/sage-docbuild/VERSION.txt | 2 +- pkgs/sage-setup/VERSION.txt | 2 +- pkgs/sage-sws2rst/VERSION.txt | 2 +- pkgs/sagemath-bliss/VERSION.txt | 2 +- pkgs/sagemath-categories/VERSION.txt | 2 +- pkgs/sagemath-coxeter3/VERSION.txt | 2 +- pkgs/sagemath-environment/VERSION.txt | 2 +- pkgs/sagemath-mcqd/VERSION.txt | 2 +- pkgs/sagemath-meataxe/VERSION.txt | 2 +- pkgs/sagemath-objects/VERSION.txt | 2 +- pkgs/sagemath-repl/VERSION.txt | 2 +- pkgs/sagemath-sirocco/VERSION.txt | 2 +- pkgs/sagemath-tdlib/VERSION.txt | 2 +- src/VERSION.txt | 2 +- src/bin/sage-version.sh | 6 +++--- src/sage/version.py | 6 +++--- 38 files changed, 45 insertions(+), 45 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 33dda263384..b4e265090f4 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -4,8 +4,8 @@ title: SageMath abstract: SageMath is a free open-source mathematics software system. authors: - name: "The SageMath Developers" -version: 10.3.beta0 +version: 10.3.beta1 doi: 10.5281/zenodo.593563 -date-released: 2023-12-05 +date-released: 2023-12-10 repository-code: "https://github.com/sagemath/sage" url: "https://www.sagemath.org/" diff --git a/VERSION.txt b/VERSION.txt index 75f3e554fbb..dc0e750e611 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 10.3.beta0, Release Date: 2023-12-05 +SageMath version 10.3.beta1, Release Date: 2023-12-10 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 65925793f12..d89eb3cf828 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=8690edbf631421d19b51fa0383185e5b77e64cdc -md5=2e5ce85812f7884700bdacdd5f6ff76e -cksum=3867469893 +sha1=60efc2b1ac7c0dcd9175cbfad5beefaf8969f24f +md5=0dc99ff8479a481293e59816a5d21488 +cksum=2783976116 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index c29cc404783..b10c55b0156 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -4ae6301b8a3eef9d003f2275a186ebe64c44b257 +f66d283d487c6f8bcee6e135c93c5613796ce9e2 diff --git a/build/pkgs/sage_conf/install-requires.txt b/build/pkgs/sage_conf/install-requires.txt index 38ec7e2cd5d..e21358d2d6c 100644 --- a/build/pkgs/sage_conf/install-requires.txt +++ b/build/pkgs/sage_conf/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-conf ~= 10.3b0 +sage-conf ~= 10.3b1 diff --git a/build/pkgs/sage_docbuild/install-requires.txt b/build/pkgs/sage_docbuild/install-requires.txt index 3769c7054e8..f1e8ac83886 100644 --- a/build/pkgs/sage_docbuild/install-requires.txt +++ b/build/pkgs/sage_docbuild/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-docbuild ~= 10.3b0 +sage-docbuild ~= 10.3b1 diff --git a/build/pkgs/sage_setup/install-requires.txt b/build/pkgs/sage_setup/install-requires.txt index 0913b873634..2cee4def9db 100644 --- a/build/pkgs/sage_setup/install-requires.txt +++ b/build/pkgs/sage_setup/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-setup ~= 10.3b0 +sage-setup ~= 10.3b1 diff --git a/build/pkgs/sage_sws2rst/install-requires.txt b/build/pkgs/sage_sws2rst/install-requires.txt index 8e3570a99d3..fe18058a251 100644 --- a/build/pkgs/sage_sws2rst/install-requires.txt +++ b/build/pkgs/sage_sws2rst/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-sws2rst ~= 10.3b0 +sage-sws2rst ~= 10.3b1 diff --git a/build/pkgs/sagelib/install-requires.txt b/build/pkgs/sagelib/install-requires.txt index 307a02db545..5ef8b7febd4 100644 --- a/build/pkgs/sagelib/install-requires.txt +++ b/build/pkgs/sagelib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-standard ~= 10.3b0 +sagemath-standard ~= 10.3b1 diff --git a/build/pkgs/sagemath_bliss/install-requires.txt b/build/pkgs/sagemath_bliss/install-requires.txt index b340ea27044..434216dc8ef 100644 --- a/build/pkgs/sagemath_bliss/install-requires.txt +++ b/build/pkgs/sagemath_bliss/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-bliss ~= 10.3b0 +sagemath-bliss ~= 10.3b1 diff --git a/build/pkgs/sagemath_categories/install-requires.txt b/build/pkgs/sagemath_categories/install-requires.txt index 9019a793f10..57a3530c389 100644 --- a/build/pkgs/sagemath_categories/install-requires.txt +++ b/build/pkgs/sagemath_categories/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-categories ~= 10.3b0 +sagemath-categories ~= 10.3b1 diff --git a/build/pkgs/sagemath_coxeter3/install-requires.txt b/build/pkgs/sagemath_coxeter3/install-requires.txt index e57fd056654..395192023e6 100644 --- a/build/pkgs/sagemath_coxeter3/install-requires.txt +++ b/build/pkgs/sagemath_coxeter3/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-coxeter3 ~= 10.3b0 +sagemath-coxeter3 ~= 10.3b1 diff --git a/build/pkgs/sagemath_environment/install-requires.txt b/build/pkgs/sagemath_environment/install-requires.txt index 9202789d78a..f44a3871358 100644 --- a/build/pkgs/sagemath_environment/install-requires.txt +++ b/build/pkgs/sagemath_environment/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-environment ~= 10.3b0 +sagemath-environment ~= 10.3b1 diff --git a/build/pkgs/sagemath_mcqd/install-requires.txt b/build/pkgs/sagemath_mcqd/install-requires.txt index 93f176e6fc5..04eb1f48c9f 100644 --- a/build/pkgs/sagemath_mcqd/install-requires.txt +++ b/build/pkgs/sagemath_mcqd/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-mcqd ~= 10.3b0 +sagemath-mcqd ~= 10.3b1 diff --git a/build/pkgs/sagemath_meataxe/install-requires.txt b/build/pkgs/sagemath_meataxe/install-requires.txt index ee1e280aad1..83a3c23ac0c 100644 --- a/build/pkgs/sagemath_meataxe/install-requires.txt +++ b/build/pkgs/sagemath_meataxe/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-meataxe ~= 10.3b0 +sagemath-meataxe ~= 10.3b1 diff --git a/build/pkgs/sagemath_objects/install-requires.txt b/build/pkgs/sagemath_objects/install-requires.txt index 07baf32ec81..46ec6f8eb68 100644 --- a/build/pkgs/sagemath_objects/install-requires.txt +++ b/build/pkgs/sagemath_objects/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-objects ~= 10.3b0 +sagemath-objects ~= 10.3b1 diff --git a/build/pkgs/sagemath_repl/install-requires.txt b/build/pkgs/sagemath_repl/install-requires.txt index 79c7e5a7ed0..4d3da43b2cf 100644 --- a/build/pkgs/sagemath_repl/install-requires.txt +++ b/build/pkgs/sagemath_repl/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-repl ~= 10.3b0 +sagemath-repl ~= 10.3b1 diff --git a/build/pkgs/sagemath_sirocco/install-requires.txt b/build/pkgs/sagemath_sirocco/install-requires.txt index 44ebb97d788..fa923dda429 100644 --- a/build/pkgs/sagemath_sirocco/install-requires.txt +++ b/build/pkgs/sagemath_sirocco/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-sirocco ~= 10.3b0 +sagemath-sirocco ~= 10.3b1 diff --git a/build/pkgs/sagemath_tdlib/install-requires.txt b/build/pkgs/sagemath_tdlib/install-requires.txt index ea24439a16a..913c85d2233 100644 --- a/build/pkgs/sagemath_tdlib/install-requires.txt +++ b/build/pkgs/sagemath_tdlib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-tdlib ~= 10.3b0 +sagemath-tdlib ~= 10.3b1 diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sage-conf_conda/VERSION.txt b/pkgs/sage-conf_conda/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sage-conf_conda/VERSION.txt +++ b/pkgs/sage-conf_conda/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sagemath-bliss/VERSION.txt b/pkgs/sagemath-bliss/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sagemath-bliss/VERSION.txt +++ b/pkgs/sagemath-bliss/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sagemath-coxeter3/VERSION.txt b/pkgs/sagemath-coxeter3/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sagemath-coxeter3/VERSION.txt +++ b/pkgs/sagemath-coxeter3/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sagemath-mcqd/VERSION.txt b/pkgs/sagemath-mcqd/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sagemath-mcqd/VERSION.txt +++ b/pkgs/sagemath-mcqd/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sagemath-meataxe/VERSION.txt b/pkgs/sagemath-meataxe/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sagemath-meataxe/VERSION.txt +++ b/pkgs/sagemath-meataxe/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sagemath-sirocco/VERSION.txt b/pkgs/sagemath-sirocco/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sagemath-sirocco/VERSION.txt +++ b/pkgs/sagemath-sirocco/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/pkgs/sagemath-tdlib/VERSION.txt b/pkgs/sagemath-tdlib/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/pkgs/sagemath-tdlib/VERSION.txt +++ b/pkgs/sagemath-tdlib/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/src/VERSION.txt b/src/VERSION.txt index d1741c9f234..84e7588ad82 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -10.3.beta0 +10.3.beta1 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index 9f4098364dc..d97ae9d5c1a 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -4,6 +4,6 @@ # which stops "setup.py develop" from rewriting it as a Python file. : # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='10.3.beta0' -SAGE_RELEASE_DATE='2023-12-05' -SAGE_VERSION_BANNER='SageMath version 10.3.beta0, Release Date: 2023-12-05' +SAGE_VERSION='10.3.beta1' +SAGE_RELEASE_DATE='2023-12-10' +SAGE_VERSION_BANNER='SageMath version 10.3.beta1, Release Date: 2023-12-10' diff --git a/src/sage/version.py b/src/sage/version.py index f7c0467ee4e..b7ee40a93da 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '10.3.beta0' -date = '2023-12-05' -banner = 'SageMath version 10.3.beta0, Release Date: 2023-12-05' +version = '10.3.beta1' +date = '2023-12-10' +banner = 'SageMath version 10.3.beta1, Release Date: 2023-12-10'