From e6e00150b922672d2795c1913d928a2b40837030 Mon Sep 17 00:00:00 2001 From: "E. Madison Bray" Date: Mon, 6 Jan 2020 16:14:15 +0100 Subject: [PATCH 001/217] Trac #28959: Upgrade zn_poly to v0.9.2 --- build/pkgs/zn_poly/checksums.ini | 6 +- build/pkgs/zn_poly/package-version.txt | 2 +- build/pkgs/zn_poly/patches/python3.patch | 433 ------------------ .../patches/python_2_6_format_support.patch | 72 --- 4 files changed, 4 insertions(+), 509 deletions(-) delete mode 100644 build/pkgs/zn_poly/patches/python3.patch delete mode 100644 build/pkgs/zn_poly/patches/python_2_6_format_support.patch diff --git a/build/pkgs/zn_poly/checksums.ini b/build/pkgs/zn_poly/checksums.ini index 157c596bd45..25cdb79c3b3 100644 --- a/build/pkgs/zn_poly/checksums.ini +++ b/build/pkgs/zn_poly/checksums.ini @@ -1,4 +1,4 @@ tarball=zn_poly-VERSION.tar.gz -sha1=13639b65d43c14809c3c74a22a12c0e458913957 -md5=2c123368da39d4bf4b8a988e9eed13e2 -cksum=1598413125 +sha1=ac13121e8ba03f12edd22b0a2e0ae3b3a79fc26e +md5=81f09badfe4f941159df70805681d9eb +cksum=2478176718 diff --git a/build/pkgs/zn_poly/package-version.txt b/build/pkgs/zn_poly/package-version.txt index 2305b1d26e3..2003b639c40 100644 --- a/build/pkgs/zn_poly/package-version.txt +++ b/build/pkgs/zn_poly/package-version.txt @@ -1 +1 @@ -0.9.1.p0 +0.9.2 diff --git a/build/pkgs/zn_poly/patches/python3.patch b/build/pkgs/zn_poly/patches/python3.patch deleted file mode 100644 index b61d2014c97..00000000000 --- a/build/pkgs/zn_poly/patches/python3.patch +++ /dev/null @@ -1,433 +0,0 @@ -commit f2bada31fd09f09c744d8ff0e1fab82c53dbf830 -Author: Jeroen Demeyer -Date: Tue Feb 12 15:08:39 2019 +0100 - - Make makemakefile.py compatible with Python 3 - -diff --git a/makemakefile.py b/makemakefile.py -index fa2b851..acb6084 100644 ---- a/makemakefile.py -+++ b/makemakefile.py -@@ -147,213 +147,221 @@ cpp_libs = libs + " -L" + ntl_lib_dir + " -lntl" - - import time - --print "#" --print "# Do not edit directly -- this file was auto-generated" --print "# by makemakefile.py on " + time.strftime("%a, %d %b %Y %H:%M:%S +0000", -- time.gmtime()) --print "#" --print "# (makemakefile.py patched for Sage, 04/2012)" --print -- --print --print "CC ?= gcc" --print "CPP ?= cpp" --print "CFLAGS = " + cflags --print "CPPFLAGS = " + cppflags --print "LDFLAGS = " + ldflags --print "INCLUDES = " + includes # These are options to the C preprocessor. --print "LIBS = " + libs # These are linker options passed to the compiler. --print --print "AR ?= ar" --print "RANLIB ?= ranlib" --print --print "SHARED_FLAG ?= -shared" --print "SONAME_FLAG ?= -soname" # '-h' for the Sun/Solaris linker -- --print --print "CXX ?= g++" # The C++ compiler. --print "CXXFLAGS = " + cxxflags # Options passed to the C++ compiler. --print "CPP_INCLUDES = " + cpp_includes --print "CPP_LIBS = " + cpp_libs -- --print --print "HEADERS = " + " ".join(install_headers + other_headers) --print "LIBOBJS = " + " ".join([x + ".o" for x in lib_modules]) --print "TESTOBJS = " + " ".join([x + "-DEBUG.o" for x in -- lib_modules + test_modules + testprof_modules]) --print "PROFOBJS = " + " ".join([x + ".o" for x in -- lib_modules + prof_modules + noncpp_prof_modules + testprof_modules]) --print "CPP_PROFOBJS = " + " ".join([x + ".o" for x in -- lib_modules + prof_modules + cpp_prof_modules + testprof_modules]) --print "TUNEOBJS = " + " ".join([x + ".o" for x in -- lib_modules + tune_modules + testprof_modules + prof_modules + -- noncpp_prof_modules if x not in ("src/tuning", "profile/prof_main")]) --print "ZN_POLY_TUNING = " + str(int(zn_poly_tuning)) --print "ZN_POLY_VERSION = " + version --print "ZN_POLY_ABI_VERSION = " + abi_version -- --print --print "all: libzn_poly.a" --print --print "test: test/test" --print "tune: tune/tune" --print --print "check: test" --print "\ttest/test -quick all" --print --print "install:" --print "\tmkdir -p %s/include/zn_poly" % prefix --print "\tmkdir -p %s/lib" % prefix --print "\tcp libzn_poly.a %s/lib" % prefix --print "\tcp include/zn_poly.h %s/include/zn_poly" % prefix --print "\tcp include/wide_arith.h %s/include/zn_poly" % prefix --print --print "clean:" --print "\trm -f *.o" --print "\trm -f test/*.o" --print "\trm -f profile/*.o" --print "\trm -f tune/*.o" --print "\trm -f src/tuning.c" --print "\trm -f src/*.o" --print "\trm -f demo/bernoulli/*.o" --print "\trm -f libzn_poly.a" --print "\trm -f libzn_poly.dylib" --print "\trm -f libzn_poly*.so*" --print "\trm -f libzn_poly*.dll.a" --print "\trm -f cygzn_poly.dll" --print "\trm -f test/test" --print "\trm -f tune/tune" -+now = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()) -+print( -+"""# -+# Do not edit directly -- this file was auto-generated -+# by {} on {} -+# -+# (makemakefile.py patched for Sage, 04/2012) -+""".format(__file__, now)) -+ -+ -+print( -+""" -+CC ?= gcc -+CPP ?= cpp -+CFLAGS = {} -+CPPFLAGS = {} -+LDFLAGS = {} -+INCLUDES = {} # These are options to the C preprocessor. -+LIBS = {} # These are linker options passed to the compiler. -+ -+AR ?= ar -+RANLIB ?= ranlib -+ -+SHARED_FLAG ?= -shared -+SONAME_FLAG ?= -soname # '-h' for the Sun/Solaris linker -+""".format(cflags, cppflags, ldflags, includes, libs)) -+ -+ -+print( -+"""CXX ?= g++ # The C++ compiler. -+CXXFLAGS = {} # Options passed to the C++ compiler. -+CPP_INCLUDES = {} -+CPP_LIBS = {} -+""".format(cxxflags, cpp_includes, cpp_libs)) -+ -+ -+print( -+"""HEADERS = {} -+LIBOBJS = {} -+TESTOBJS = {} -+PROFOBJS = {} -+CPP_PROFOBJS = {} -+TUNEOBJS = {}""".format( -+ " ".join(install_headers + other_headers), -+ " ".join([x + ".o" for x in lib_modules]), -+ " ".join([x + "-DEBUG.o" for x in -+ lib_modules + test_modules + testprof_modules]), -+ " ".join([x + ".o" for x in -+ lib_modules + prof_modules + noncpp_prof_modules + testprof_modules]), -+ " ".join([x + ".o" for x in -+ lib_modules + prof_modules + cpp_prof_modules + testprof_modules]), -+ " ".join([x + ".o" for x in -+ lib_modules + tune_modules + testprof_modules + prof_modules + -+ noncpp_prof_modules if x not in ("src/tuning", "profile/prof_main")]) -+)) -+ -+ -+print( -+"""ZN_POLY_TUNING = {} -+ZN_POLY_VERSION = {} -+ZN_POLY_ABI_VERSION = {} -+""".format(int(zn_poly_tuning), version, abi_version)) -+ -+ -+print( -+"""all: libzn_poly.a -+ -+test: test/test -+tune: tune/tune -+ -+check: test -+\ttest/test -quick all -+ -+install: -+\tmkdir -p {prefix}/include/zn_poly -+\tmkdir -p {prefix}/lib -+\tcp libzn_poly.a {prefix}/lib -+\tcp include/zn_poly.h {prefix}/include/zn_poly -+\tcp include/wide_arith.h {prefix}/include/zn_poly -+""".format(prefix=prefix)) -+ -+ -+print( -+"""clean: -+\trm -f *.o -+\trm -f test/*.o -+\trm -f profile/*.o -+\trm -f tune/*.o -+\trm -f src/tuning.c -+\trm -f src/*.o -+\trm -f demo/bernoulli/*.o -+\trm -f libzn_poly.a -+\trm -f libzn_poly.dylib -+\trm -f libzn_poly*.so* -+\trm -f libzn_poly*.dll.a -+\trm -f cygzn_poly.dll -+\trm -f test/test -+\trm -f tune/tune""") - for x in prof_progs: -- print "\trm -f " + x -- print "\trm -f " + x + "-ntl" -+ print("\trm -f " + x) -+ print("\trm -f " + x + "-ntl") - for x in demo_progs: -- print "\trm -f " + x --print --print "distclean: clean" --print "\trm -f makefile" --print --print "dist: distclean" --print "\ttar --exclude-vcs --exclude=.gitignore -czf zn_poly-$(ZN_POLY_VERSION).tar.gz *" -- -- --print --print --print "##### library targets" --print --print "ifeq ($(ZN_POLY_TUNING), 1)" --print "src/tuning.c: tune/tune" --print "\ttune/tune > src/tuning.c" --print "else" --print "src/tuning.c: tune/tuning.c" --print "\tcp tune/tuning.c src/tuning.c" --print "endif" --print --print "libzn_poly.a: $(LIBOBJS)" --print "\t$(AR) -r libzn_poly.a $(LIBOBJS)" --print "\t$(RANLIB) libzn_poly.a" --print --print "# TODO: Put '-single_module -fPIC -dynamiclib' into $(SHARED_FLAG)" --print "# and use that; also support $(SO_EXTENSION)..." --print "libzn_poly.dylib: $(LIBOBJS)" --print "\t$(CC) $(LDFLAGS) -single_module -fPIC -dynamiclib -o libzn_poly.dylib " \ -- "$(LIBOBJS) $(LIBS)" --print --print "# Left for compatibility with previous versions of Sage's 'spkg-install':" --print "libzn_poly.dylib64: $(LIBOBJS)" --print "\t$(CC) -m64 -single_module -fPIC -dynamiclib -o libzn_poly.dylib $(LIBOBJS) $(LIBS)" --print --print "cygzn_poly.dll: $(LIBOBJS)" --print "\t$(CC) $(SHARED_FLAG) $(LDFLAGS) " \ -- "-Wl,--out-implib,libzn_poly-$(ZN_POLY_VERSION).dll.a " \ -- "-o cygzn_poly.dll $(LIBOBJS) $(LIBS)" --print --print "libzn_poly-$(ZN_POLY_VERSION).dll.a: cygzn_poly.dll" --print --print "libzn_poly.dll.a: libzn_poly-$(ZN_POLY_VERSION).dll.a" --print "\tln -sf libzn_poly-$(ZN_POLY_VERSION).dll.a libzn_poly.dll.a" --print "\tln -sf libzn_poly-$(ZN_POLY_VERSION).dll.a libzn_poly-$(ZN_POLY_ABI_VERSION).dll.a" --print --print "libzn_poly.so: libzn_poly-$(ZN_POLY_VERSION).so" --print "\tln -sf libzn_poly-$(ZN_POLY_VERSION).so libzn_poly.so" --print "\tln -sf libzn_poly-$(ZN_POLY_VERSION).so libzn_poly-$(ZN_POLY_ABI_VERSION).so" -- --print --print "libzn_poly-$(ZN_POLY_VERSION).so: $(LIBOBJS)" --print "\t$(CC) $(SHARED_FLAG) $(LDFLAGS) -Wl,-soname,libzn_poly-$(ZN_POLY_ABI_VERSION).so " \ -- "-o libzn_poly-$(ZN_POLY_VERSION).so $(LIBOBJS) $(LIBS)" -- --print --print --print "##### test program" --print --print "test/test: $(TESTOBJS) $(HEADERS)" --print "\t$(CC) -g $(LDFLAGS) -o test/test $(TESTOBJS) $(LIBS)" -- --print --print --print "##### profiling programs" --print -+ print("\trm -f " + x) -+print( -+""" -+distclean: clean -+\trm -f makefile -+ -+dist: distclean -+\ttar --exclude-vcs --exclude=.gitignore -czf zn_poly-$(ZN_POLY_VERSION).tar.gz * -+ -+ -+##### library targets -+ -+ifeq ($(ZN_POLY_TUNING), 1) -+src/tuning.c: tune/tune -+\ttune/tune > src/tuning.c -+else -+src/tuning.c: tune/tuning.c -+\tcp tune/tuning.c src/tuning.c -+endif -+ -+libzn_poly.a: $(LIBOBJS) -+\t$(AR) -r libzn_poly.a $(LIBOBJS) -+\t$(RANLIB) libzn_poly.a -+ -+# TODO: Put '-single_module -fPIC -dynamiclib' into $(SHARED_FLAG) -+# and use that; also support $(SO_EXTENSION)... -+libzn_poly.dylib: $(LIBOBJS) -+\t$(CC) $(LDFLAGS) -single_module -fPIC -dynamiclib -o libzn_poly.dylib $(LIBOBJS) $(LIBS) -+ -+# Left for compatibility with previous versions of Sage's 'spkg-install': -+libzn_poly.dylib64: $(LIBOBJS) -+\t$(CC) -m64 -single_module -fPIC -dynamiclib -o libzn_poly.dylib $(LIBOBJS) $(LIBS) -+ -+cygzn_poly.dll: $(LIBOBJS) -+\t$(CC) $(SHARED_FLAG) $(LDFLAGS) -Wl,--out-implib,libzn_poly-$(ZN_POLY_VERSION).dll.a -o cygzn_poly.dll $(LIBOBJS) $(LIBS) -+ -+libzn_poly-$(ZN_POLY_VERSION).dll.a: cygzn_poly.dll -+ -+libzn_poly.dll.a: libzn_poly-$(ZN_POLY_VERSION).dll.a -+\tln -sf libzn_poly-$(ZN_POLY_VERSION).dll.a libzn_poly.dll.a -+\tln -sf libzn_poly-$(ZN_POLY_VERSION).dll.a libzn_poly-$(ZN_POLY_ABI_VERSION).dll.a -+ -+libzn_poly.so: libzn_poly-$(ZN_POLY_VERSION).so -+\tln -sf libzn_poly-$(ZN_POLY_VERSION).so libzn_poly.so -+\tln -sf libzn_poly-$(ZN_POLY_VERSION).so libzn_poly-$(ZN_POLY_ABI_VERSION).so -+ -+libzn_poly-$(ZN_POLY_VERSION).so: $(LIBOBJS) -+\t$(CC) $(SHARED_FLAG) $(LDFLAGS) -Wl,-soname,libzn_poly-$(ZN_POLY_ABI_VERSION).so -o libzn_poly-$(ZN_POLY_VERSION).so $(LIBOBJS) $(LIBS) -+ -+ -+##### test program -+ -+test/test: $(TESTOBJS) $(HEADERS) -+\t$(CC) -g $(LDFLAGS) -o test/test $(TESTOBJS) $(LIBS) -+ -+ -+##### profiling programs -+""") -+ - for x in prof_progs: -- print "%s-main.o: %s-main.c $(HEADERS)" % (x, x) -- print "\t$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -DNDEBUG -o %s-main.o -c %s-main.c" \ -- % (x, x) -- print -- print "%s: %s-main.o $(PROFOBJS)" % (x, x) -- print "\t$(CC) $(CFLAGS) $(LDFLAGS) -o %s %s-main.o $(PROFOBJS) $(LIBS)" \ -- % (x, x) -- print -- print "%s-main-ntl.o: %s-main.c $(HEADERS)" % (x, x) -- print "\t$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -DPROFILE_NTL -DNDEBUG " \ -- "-o %s-main-ntl.o -c %s-main.c" % (x, x) -- print -- print "%s-ntl: %s-main-ntl.o $(CPP_PROFOBJS)" % (x, x) -- print "\t$(CXX) $(CXXFLAGS) $(LDFLAGS) -o %s-ntl %s-main-ntl.o " \ -- "$(CPP_PROFOBJS) $(CPP_LIBS)" % (x, x) -- print -- --print --print --print "##### tuning utility" --print --print "tune/tune: $(TUNEOBJS)" --print "\t$(CC) $(CFLAGS) $(LDFLAGS) -o tune/tune $(TUNEOBJS) $(LIBS)" -- -- --print --print --print "##### demo programs" -+ print( -+"""{0}-main.o: {0}-main.c $(HEADERS) -+\t$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -DNDEBUG -o {0}-main.o -c {0}-main.c -+ -+{0}: {0}-main.o $(PROFOBJS) -+\t$(CC) $(CFLAGS) $(LDFLAGS) -o {0} {0}-main.o $(PROFOBJS) $(LIBS) -+ -+{0}-main-ntl.o: {0}-main.c $(HEADERS) -+\t$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -DPROFILE_NTL -DNDEBUG -o {0}-main-ntl.o -c {0}-main.c -+ -+{0}-ntl: {0}-main-ntl.o $(CPP_PROFOBJS) -+\t$(CXX) $(CXXFLAGS) $(LDFLAGS) -o {0}-ntl {0}-main-ntl.o $(CPP_PROFOBJS) $(CPP_LIBS) -+""".format(x)) -+ -+ -+print( -+""" -+ -+##### tuning utility -+ -+tune/tune: $(TUNEOBJS) -+\t$(CC) $(CFLAGS) $(LDFLAGS) -o tune/tune $(TUNEOBJS) $(LIBS) -+ -+ -+##### demo programs -+""") - for x in demo_progs: -- print -- print "%s: %s.o $(LIBOBJS)" % (x, x) -- print "\t$(CC) $(CFLAGS) $(LDFLAGS) -o %s %s.o $(LIBOBJS) $(LIBS)" % (x, x) -+ print( -+"""{0}: {0}.o $(LIBOBJS) -+\t$(CC) $(CFLAGS) $(LDFLAGS) -o {0} {0}.o $(LIBOBJS) $(LIBS) -+""".format(x)) - - --print --print --print "##### object files (with debug code)" -+print("\n##### object files (with debug code)\n") - for x in lib_modules + test_modules + testprof_modules + demo_progs: -- print -- print "%s-DEBUG.o: %s.c $(HEADERS)" % (x, x) -- print "\t$(CC) -g $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -DDEBUG -o %s-DEBUG.o -c %s.c" \ -- % (x, x) -- --print --print --print "##### object files (no debug code)" --for x in lib_modules + prof_modules + testprof_modules + \ -- tune_modules + demo_progs: -- print -- print "%s.o: %s.c $(HEADERS)" % (x, x) -- print "\t$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -DNDEBUG -o %s.o -c %s.c" % (x, x) -- --print --print --print "##### object files (C++, no debug code)" --for x in cpp_prof_modules: -- print -- print "%s.o: %s.c $(HEADERS)" % (x, x) -- print "\t$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(CPP_INCLUDES) -DNDEBUG -o %s.o -c %s.c" \ -- % (x, x) -+ print( -+"""{0}-DEBUG.o: {0}.c $(HEADERS) -+\t$(CC) -g $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -DDEBUG -o {0}-DEBUG.o -c {0}.c -+""".format(x)) -+ - -+print("\n##### object files (no debug code)\n") -+for x in (lib_modules + prof_modules + testprof_modules + -+ tune_modules + demo_progs): -+ print( -+"""{0}.o: {0}.c $(HEADERS) -+\t$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -DNDEBUG -o {0}.o -c {0}.c -+""".format(x)) - --### end of file -+ -+print("\n##### object files (C++, no debug code)\n") -+for x in cpp_prof_modules: -+ print( -+"""{0}.o: {0}.c $(HEADERS) -+\t$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(CPP_INCLUDES) -DNDEBUG -o {0}.o -c {0}.c -+""".format(x)) diff --git a/build/pkgs/zn_poly/patches/python_2_6_format_support.patch b/build/pkgs/zn_poly/patches/python_2_6_format_support.patch deleted file mode 100644 index f8a59665487..00000000000 --- a/build/pkgs/zn_poly/patches/python_2_6_format_support.patch +++ /dev/null @@ -1,72 +0,0 @@ -diff --git a/makemakefile.py b/makemakefile.py -index acb6084..9c0fb96 100644 ---- a/makemakefile.py -+++ b/makemakefile.py -@@ -151,7 +151,7 @@ now = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()) - print( - """# - # Do not edit directly -- this file was auto-generated --# by {} on {} -+# by {0} on {1} - # - # (makemakefile.py patched for Sage, 04/2012) - """.format(__file__, now)) -@@ -161,11 +161,11 @@ print( - """ - CC ?= gcc - CPP ?= cpp --CFLAGS = {} --CPPFLAGS = {} --LDFLAGS = {} --INCLUDES = {} # These are options to the C preprocessor. --LIBS = {} # These are linker options passed to the compiler. -+CFLAGS = {0} -+CPPFLAGS = {1} -+LDFLAGS = {2} -+INCLUDES = {3} # These are options to the C preprocessor. -+LIBS = {4} # These are linker options passed to the compiler. - - AR ?= ar - RANLIB ?= ranlib -@@ -177,19 +177,19 @@ SONAME_FLAG ?= -soname # '-h' for the Sun/Solaris linker - - print( - """CXX ?= g++ # The C++ compiler. --CXXFLAGS = {} # Options passed to the C++ compiler. --CPP_INCLUDES = {} --CPP_LIBS = {} -+CXXFLAGS = {0} # Options passed to the C++ compiler. -+CPP_INCLUDES = {1} -+CPP_LIBS = {2} - """.format(cxxflags, cpp_includes, cpp_libs)) - - - print( --"""HEADERS = {} --LIBOBJS = {} --TESTOBJS = {} --PROFOBJS = {} --CPP_PROFOBJS = {} --TUNEOBJS = {}""".format( -+"""HEADERS = {0} -+LIBOBJS = {1} -+TESTOBJS = {2} -+PROFOBJS = {3} -+CPP_PROFOBJS = {4} -+TUNEOBJS = {5}""".format( - " ".join(install_headers + other_headers), - " ".join([x + ".o" for x in lib_modules]), - " ".join([x + "-DEBUG.o" for x in -@@ -205,9 +205,9 @@ TUNEOBJS = {}""".format( - - - print( --"""ZN_POLY_TUNING = {} --ZN_POLY_VERSION = {} --ZN_POLY_ABI_VERSION = {} -+"""ZN_POLY_TUNING = {0} -+ZN_POLY_VERSION = {1} -+ZN_POLY_ABI_VERSION = {2} - """.format(int(zn_poly_tuning), version, abi_version)) - - From 4ba1ea86fe58d0123f240f5cd68694d619e0d184 Mon Sep 17 00:00:00 2001 From: Antonio Rojas Date: Fri, 13 Mar 2020 23:33:10 +0100 Subject: [PATCH 002/217] Update pari to 2.11.3 --- build/pkgs/pari/checksums.ini | 6 +-- build/pkgs/pari/fix-bnfisunit.patch | 60 +++++++++++++++++++++ build/pkgs/pari/package-version.txt | 2 +- build/pkgs/pari/patches/fix-bnfisunit.patch | 54 +++++++++++++++++++ 4 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 build/pkgs/pari/fix-bnfisunit.patch create mode 100644 build/pkgs/pari/patches/fix-bnfisunit.patch diff --git a/build/pkgs/pari/checksums.ini b/build/pkgs/pari/checksums.ini index c1e512cbee7..fdc47ee3034 100644 --- a/build/pkgs/pari/checksums.ini +++ b/build/pkgs/pari/checksums.ini @@ -1,4 +1,4 @@ tarball=pari-VERSION.tar.gz -sha1=49a638ebcce77b9e9e2d8305156f37e7322bc09f -md5=6afe748a472c33ae8787a5034d7742a9 -cksum=4122745815 +sha1=4535447ec298d3ede042d554b7b055b31fa28caf +md5=6ff176422113f2c83facaeda547be03c +cksum=2463676551 diff --git a/build/pkgs/pari/fix-bnfisunit.patch b/build/pkgs/pari/fix-bnfisunit.patch new file mode 100644 index 00000000000..d8945e672c3 --- /dev/null +++ b/build/pkgs/pari/fix-bnfisunit.patch @@ -0,0 +1,60 @@ +From c7a1d35f382e96ddf14694be27a0ca5746880700 Mon Sep 17 00:00:00 2001 +From: Karim Belabas +Date: Mon, 9 Sep 2019 17:20:21 +0200 +Subject: [PATCH] fix #2164 + +--- + src/basemath/buch2.c | 3 ++- + src/test/32/nf | 3 ++- + src/test/in/nf | 4 ++++ + 3 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/src/basemath/buch2.c b/src/basemath/buch2.c +index a853d3c48..e31b2278b 100644 +--- a/src/basemath/buch2.c ++++ b/src/basemath/buch2.c +@@ -2136,7 +2136,8 @@ bnfisunit(GEN bnf,GEN x) + for (i = 1; i < RU; i++) + if (gexpo(gel(emb,i)) > -1) break; + p1 = imag_i( row_i(logunit,i, 1,RU-1) ); +- p1 = RgV_dotproduct(p1, ex); if (!R1) p1 = gmul2n(p1, -1); ++ p1 = RgV_dotproduct(p1, ex); ++ if (i > R1) p1 = gmul2n(p1, -1); + p1 = gsub(garg(gel(emb,i),prec), p1); + /* p1 = arg(the missing root of 1) */ + +diff --git a/src/test/32/nf b/src/test/32/nf +index 16bf83ce3..e6c41f8b5 100644 +--- a/src/test/32/nf ++++ b/src/test/32/nf +@@ -502,6 +502,7 @@ Mod(1/2*x - 1/2, x^2 + 23) + [1, 1/2*x - 1/2] + Mod(0, x) + Mod(-6/5, x) ++[0, 2, Mod(0, 2)]~ + *** at top-level: nfinit([y^3+2,[1,x]]) + *** ^--------------------- + *** nfinit: incorrect type in nfinit_basic (t_VEC). +@@ -565,4 +566,4 @@ Mod(-6/5, x) + *** at top-level: nfalgtobasis(nf,['a,'a]~) + *** ^------------------------- + *** nfalgtobasis: incorrect type in nfalgtobasis (t_COL). +-Total time spent: 8888 ++Total time spent: 8403 +diff --git a/src/test/in/nf b/src/test/in/nf +index 49148123b..94d5165bc 100644 +--- a/src/test/in/nf ++++ b/src/test/in/nf +@@ -156,6 +156,10 @@ K.zk + nfinit(x, 3)[2] + nfinit(1/2*x + 3/5, 3)[2] + ++\\ #2164 ++bnf = bnfinit(y^4-y-1); ++bnfisunit(bnf,-y^3+2*y^2-1) ++ + \\ ERRORS: keep at end of file + + nfinit([y^3+2,[1,x]]) +-- +2.11.0 diff --git a/build/pkgs/pari/package-version.txt b/build/pkgs/pari/package-version.txt index 9e5bb77a3ba..f708f826e5b 100644 --- a/build/pkgs/pari/package-version.txt +++ b/build/pkgs/pari/package-version.txt @@ -1 +1 @@ -2.11.2 +2.11.3.p0 diff --git a/build/pkgs/pari/patches/fix-bnfisunit.patch b/build/pkgs/pari/patches/fix-bnfisunit.patch new file mode 100644 index 00000000000..3f83095440d --- /dev/null +++ b/build/pkgs/pari/patches/fix-bnfisunit.patch @@ -0,0 +1,54 @@ +From c7a1d35f382e96ddf14694be27a0ca5746880700 Mon Sep 17 00:00:00 2001 +From: Karim Belabas +Date: Mon, 9 Sep 2019 17:20:21 +0200 +Subject: [PATCH] fix #2164 + +--- + src/basemath/buch2.c | 3 ++- + src/test/32/nf | 3 ++- + src/test/in/nf | 4 ++++ + 3 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/src/basemath/buch2.c b/src/basemath/buch2.c +index a853d3c48..e31b2278b 100644 +--- a/src/basemath/buch2.c ++++ b/src/basemath/buch2.c +@@ -2136,7 +2136,8 @@ bnfisunit(GEN bnf,GEN x) + for (i = 1; i < RU; i++) + if (gexpo(gel(emb,i)) > -1) break; + p1 = imag_i( row_i(logunit,i, 1,RU-1) ); +- p1 = RgV_dotproduct(p1, ex); if (!R1) p1 = gmul2n(p1, -1); ++ p1 = RgV_dotproduct(p1, ex); ++ if (i > R1) p1 = gmul2n(p1, -1); + p1 = gsub(garg(gel(emb,i),prec), p1); + /* p1 = arg(the missing root of 1) */ + +diff --git a/src/test/32/nf b/src/test/32/nf +index 16bf83ce3..e6c41f8b5 100644 +--- a/src/test/32/nf ++++ b/src/test/32/nf +@@ -494,6 +494,7 @@ + [1, 1/2*x - 1/2] + Mod(0, x) + Mod(-6/5, x) ++[0, 2, Mod(0, 2)]~ + *** at top-level: nfinit([y^3+2,[1,x]]) + *** ^--------------------- + *** nfinit: incorrect type in nfbasic_init (t_VEC). +diff --git a/src/test/in/nf b/src/test/in/nf +index 49148123b..94d5165bc 100644 +--- a/src/test/in/nf ++++ b/src/test/in/nf +@@ -150,6 +150,10 @@ + nfinit(x, 3)[2] + nfinit(1/2*x + 3/5, 3)[2] + ++\\ #2164 ++bnf = bnfinit(y^4-y-1); ++bnfisunit(bnf,-y^3+2*y^2-1) ++ + \\ ERRORS: keep at end of file + + nfinit([y^3+2,[1,x]]) +-- +2.11.0 From d934a82f2d9c46f0afedd84487be1721b3466850 Mon Sep 17 00:00:00 2001 From: Antonio Rojas Date: Fri, 13 Mar 2020 23:34:02 +0100 Subject: [PATCH 003/217] Remove wrong patch --- build/pkgs/pari/fix-bnfisunit.patch | 60 ----------------------------- 1 file changed, 60 deletions(-) delete mode 100644 build/pkgs/pari/fix-bnfisunit.patch diff --git a/build/pkgs/pari/fix-bnfisunit.patch b/build/pkgs/pari/fix-bnfisunit.patch deleted file mode 100644 index d8945e672c3..00000000000 --- a/build/pkgs/pari/fix-bnfisunit.patch +++ /dev/null @@ -1,60 +0,0 @@ -From c7a1d35f382e96ddf14694be27a0ca5746880700 Mon Sep 17 00:00:00 2001 -From: Karim Belabas -Date: Mon, 9 Sep 2019 17:20:21 +0200 -Subject: [PATCH] fix #2164 - ---- - src/basemath/buch2.c | 3 ++- - src/test/32/nf | 3 ++- - src/test/in/nf | 4 ++++ - 3 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/src/basemath/buch2.c b/src/basemath/buch2.c -index a853d3c48..e31b2278b 100644 ---- a/src/basemath/buch2.c -+++ b/src/basemath/buch2.c -@@ -2136,7 +2136,8 @@ bnfisunit(GEN bnf,GEN x) - for (i = 1; i < RU; i++) - if (gexpo(gel(emb,i)) > -1) break; - p1 = imag_i( row_i(logunit,i, 1,RU-1) ); -- p1 = RgV_dotproduct(p1, ex); if (!R1) p1 = gmul2n(p1, -1); -+ p1 = RgV_dotproduct(p1, ex); -+ if (i > R1) p1 = gmul2n(p1, -1); - p1 = gsub(garg(gel(emb,i),prec), p1); - /* p1 = arg(the missing root of 1) */ - -diff --git a/src/test/32/nf b/src/test/32/nf -index 16bf83ce3..e6c41f8b5 100644 ---- a/src/test/32/nf -+++ b/src/test/32/nf -@@ -502,6 +502,7 @@ Mod(1/2*x - 1/2, x^2 + 23) - [1, 1/2*x - 1/2] - Mod(0, x) - Mod(-6/5, x) -+[0, 2, Mod(0, 2)]~ - *** at top-level: nfinit([y^3+2,[1,x]]) - *** ^--------------------- - *** nfinit: incorrect type in nfinit_basic (t_VEC). -@@ -565,4 +566,4 @@ Mod(-6/5, x) - *** at top-level: nfalgtobasis(nf,['a,'a]~) - *** ^------------------------- - *** nfalgtobasis: incorrect type in nfalgtobasis (t_COL). --Total time spent: 8888 -+Total time spent: 8403 -diff --git a/src/test/in/nf b/src/test/in/nf -index 49148123b..94d5165bc 100644 ---- a/src/test/in/nf -+++ b/src/test/in/nf -@@ -156,6 +156,10 @@ K.zk - nfinit(x, 3)[2] - nfinit(1/2*x + 3/5, 3)[2] - -+\\ #2164 -+bnf = bnfinit(y^4-y-1); -+bnfisunit(bnf,-y^3+2*y^2-1) -+ - \\ ERRORS: keep at end of file - - nfinit([y^3+2,[1,x]]) --- -2.11.0 From ce42f11db5d1d31fee916013492d69d56a6572c5 Mon Sep 17 00:00:00 2001 From: Antonio Rojas Date: Sat, 14 Mar 2020 00:37:03 +0100 Subject: [PATCH 004/217] Adjust doctests for new output with pari 2.11.3 --- src/sage/lfunctions/dokchitser.py | 4 ++-- src/sage/lfunctions/pari.py | 2 +- src/sage/rings/number_field/number_field.py | 18 +++++++++--------- .../number_field/number_field_element.pyx | 2 +- .../rings/number_field/number_field_ideal.py | 4 ++-- src/sage/rings/number_field/unit_group.py | 2 +- .../polynomial/polynomial_quotient_ring.py | 12 ++++++------ .../elliptic_curves/ell_number_field.py | 13 +++++++------ 8 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/sage/lfunctions/dokchitser.py b/src/sage/lfunctions/dokchitser.py index 680ac17dfd4..1bf8953a77b 100644 --- a/src/sage/lfunctions/dokchitser.py +++ b/src/sage/lfunctions/dokchitser.py @@ -111,7 +111,7 @@ class Dokchitser(SageObject): 0.000000000000000 + 0.305999773834052*z + 0.186547797268162*z^2 - 0.136791463097188*z^3 + O(z^4) sage: L.check_functional_equation() 6.11218974700000e-18 # 32-bit - 6.04442711160669e-18 # 64-bit + 6.11218974738703e-18 # 64-bit RANK 2 ELLIPTIC CURVE: @@ -670,7 +670,7 @@ def check_functional_equation(self, T=1.2): sage: L = Dokchitser(conductor=1, gammaV=[0], weight=1, eps=1, poles=[1], residues=[-1], init='1') sage: L.check_functional_equation() -1.35525271600000e-20 # 32-bit - -2.71050543121376e-20 # 64-bit + -1.35525271560688e-20 # 64-bit If we choose the sign in functional equation for the `\zeta` function incorrectly, the functional equation diff --git a/src/sage/lfunctions/pari.py b/src/sage/lfunctions/pari.py index c60f944ed4e..1daa219c007 100644 --- a/src/sage/lfunctions/pari.py +++ b/src/sage/lfunctions/pari.py @@ -423,7 +423,7 @@ class LFunction(SageObject): sage: L.taylor_series(1,4) 0.000000000000000 + 0.305999773834052*z + 0.186547797268162*z^2 - 0.136791463097188*z^3 + O(z^4) sage: L.check_functional_equation() - 1.08420217248550e-19 + 4.33680868994202e-19 .. RUBRIC:: Rank 2 elliptic curve diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index 4908fd22b27..a052995571e 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -4383,7 +4383,7 @@ def _S_class_group_and_units(self, S, proof=True): -1/13*a^2 + 6/13*a + 345/13, -1, 2/13*a^2 + 1/13*a - 755/13, - 1/13*a^2 - 19/13*a - 7/13], + 1/13*a^2 + 20/13*a - 7/13], [(Fractional ideal (11, a - 2), 2), (Fractional ideal (19, a + 7), 2)]) Number fields defined by non-monic and non-integral @@ -4541,9 +4541,9 @@ def selmer_group(self, S, m, proof=True, orders=False): -1/13*a^2 + 6/13*a + 345/13, -1, 2/13*a^2 + 1/13*a - 755/13, - 1/13*a^2 - 19/13*a - 7/13, - -1/13*a^2 + 45/13*a - 97/13, - 2/13*a^2 + 40/13*a - 27/13] + 1/13*a^2 + 20/13*a - 7/13, + 1/13*a^2 - 45/13*a + 97/13, + -2/13*a^2 - 40/13*a + 27/13] Verify that :trac:`16708` is fixed:: @@ -5188,7 +5188,7 @@ def elements_of_norm(self, n, proof=None): sage: K. = NumberField(7/9*x^3 + 7/3*x^2 - 56*x + 123) sage: K.elements_of_norm(7) - [7/225*a^2 - 7/75*a - 42/25] + [28/225*a^2 + 77/75*a - 133/25] """ proof = proof_flag(proof) B = self.pari_bnf(proof).bnfisintnorm(n) @@ -5291,7 +5291,7 @@ def factor(self, n): sage: pari('setrand(2)') sage: L. = K.extension(x^2 - 7) sage: f = L.factor(a + 1); f - (Fractional ideal (1/2*a*b - a + 1/2)) * (Fractional ideal (-1/2*a*b - a + 1/2)) + (Fractional ideal (-1/2*b + 1/2*a + 1)) * (Fractional ideal (-1/2*a*b - a + 1/2)) sage: f.value() == a+1 True @@ -6368,7 +6368,7 @@ def uniformizer(self, P, others="positive"): sage: [K.uniformizer(P) for P,e in factor(K.ideal(5))] [t^2 - t + 1, t + 2, t - 2] sage: [K.uniformizer(P) for P,e in factor(K.ideal(7))] - [t^2 + 3*t + 1] + [t^2 - 4*t + 1] sage: [K.uniformizer(P) for P,e in factor(K.ideal(67))] [t + 23, t + 26, t - 32, t - 18] @@ -7638,11 +7638,11 @@ def optimized_representation(self, name=None, both_maps=True): Ring morphism: From: Number Field in a1 with defining polynomial x^3 - 7*x - 7 To: Number Field in a with defining polynomial 7/9*x^3 + 7/3*x^2 - 56*x + 123 - Defn: a1 |--> 7/225*a^2 - 7/75*a - 42/25, + Defn: a1 |--> 28/225*a^2 + 77/75*a - 133/25, Ring morphism: From: Number Field in a with defining polynomial 7/9*x^3 + 7/3*x^2 - 56*x + 123 To: Number Field in a1 with defining polynomial x^3 - 7*x - 7 - Defn: a |--> -15/7*a1^2 + 9) + Defn: a |--> -60/7*a1^2 + 15*a1 + 39) """ if name is None: name = self.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 59bab07db08..079eaaa6a25 100644 --- a/src/sage/rings/number_field/number_field_element.pyx +++ b/src/sage/rings/number_field/number_field_element.pyx @@ -1733,7 +1733,7 @@ cdef class NumberFieldElement(FieldElement): sage: P. = K[] sage: L = NumberField(X^2 + a^2 + 2*a + 1, 'b') sage: K(17)._rnfisnorm(L) - ((a^2 - 2)*b - 4, 1) + ((a^2 - 2)*b + 4, 1) sage: K. = NumberField(x^3 + x + 1) sage: Q. = K[] diff --git a/src/sage/rings/number_field/number_field_ideal.py b/src/sage/rings/number_field/number_field_ideal.py index b4eabe8fb75..d746dcbf173 100644 --- a/src/sage/rings/number_field/number_field_ideal.py +++ b/src/sage/rings/number_field/number_field_ideal.py @@ -1827,7 +1827,7 @@ def factor(self): sage: F. = NumberField(2*x^3 + x + 1) sage: fact = F.factor(2); fact - (Fractional ideal (2*a^2 + 1))^2 * (Fractional ideal (-2*a^2)) + (Fractional ideal (-2*a^2 - 1))^2 * (Fractional ideal (2*a^2)) sage: [p[0].norm() for p in fact] [2, 2] """ @@ -2418,7 +2418,7 @@ def idealcoprime(self, J): sage: A.is_coprime(B) False sage: lam = A.idealcoprime(B); lam - -1/6*a + 1/6 + 1/6*a - 1/6 sage: (lam*A).is_coprime(B) True diff --git a/src/sage/rings/number_field/unit_group.py b/src/sage/rings/number_field/unit_group.py index 6ed0aea16b8..529e23a5593 100644 --- a/src/sage/rings/number_field/unit_group.py +++ b/src/sage/rings/number_field/unit_group.py @@ -279,7 +279,7 @@ def __init__(self, number_field, proof=True, S=None): sage: K.unit_group() Unit group with structure C2 x Z x Z of Number Field in a with defining polynomial 7/9*x^3 + 7/3*x^2 - 56*x + 123 sage: UnitGroup(K, S=tuple(K.primes_above(7))) - S-unit group with structure C2 x Z x Z x Z of Number Field in a with defining polynomial 7/9*x^3 + 7/3*x^2 - 56*x + 123 with S = (Fractional ideal (7/225*a^2 - 7/75*a - 42/25),) + S-unit group with structure C2 x Z x Z x Z of Number Field in a with defining polynomial 7/9*x^3 + 7/3*x^2 - 56*x + 123 with S = (Fractional ideal (28/225*a^2 + 77/75*a - 133/25),) Conversion from unit group to a number field and back gives the right results (:trac:`25874`):: diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index 397e92d0fdc..1974eaae8b0 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -1296,9 +1296,9 @@ def S_class_group(self, S, proof=True): 1/16*a*xbar^3 + (-1/16*a - 1/8)*xbar^2 + 23/16*a*xbar - 23/16*a - 23/8), 6), ((-5/4*xbar^2 - 115/4, - 1/4*a*xbar^2 + 23/4*a, - -1/16*xbar^3 - 7/16*xbar^2 - 23/16*xbar - 161/16, - 1/16*a*xbar^3 - 1/16*a*xbar^2 + 23/16*a*xbar - 23/16*a), + (1/8*a - 5/8)*xbar^2 + 23/8*a - 115/8, + -1/16*xbar^3 - 17/16*xbar^2 - 23/16*xbar - 391/16, + 1/16*a*xbar^3 + (-1/16*a - 5/8)*xbar^2 + 23/16*a*xbar - 23/16*a - 115/8), 2)] By using the ideal `(a)`, we cut the part of the class group coming from @@ -1428,9 +1428,9 @@ def class_group(self, proof=True): 1/16*a*xbar^3 + (-1/16*a - 1/8)*xbar^2 + 23/16*a*xbar - 23/16*a - 23/8), 6), ((-5/4*xbar^2 - 115/4, - 1/4*a*xbar^2 + 23/4*a, - -1/16*xbar^3 - 7/16*xbar^2 - 23/16*xbar - 161/16, - 1/16*a*xbar^3 - 1/16*a*xbar^2 + 23/16*a*xbar - 23/16*a), + (1/8*a - 5/8)*xbar^2 + 23/8*a - 115/8, + -1/16*xbar^3 - 17/16*xbar^2 - 23/16*xbar - 391/16, + 1/16*a*xbar^3 + (-1/16*a - 5/8)*xbar^2 + 23/16*a*xbar - 23/16*a - 115/8), 2)] Note that all the returned values live where we expect them to:: diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 2967f085cae..300278bf678 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -302,7 +302,8 @@ def simon_two_descent(self, verbose=0, lim1=2, lim3=4, limtriv=2, (3, 3, [(0 : 0 : 1), - (-1/2*zeta43_0^2 - 1/2*zeta43_0 + 7 : -3/2*zeta43_0^2 - 5/2*zeta43_0 + 18 : 1)]) + (-1/2*zeta43_0^2 - 1/2*zeta43_0 + 7 : -3/2*zeta43_0^2 - 5/2*zeta43_0 + 18 : 1), + (5/8*zeta43_0^2 + 17/8*zeta43_0 - 9/4 : -27/16*zeta43_0^2 - 103/16*zeta43_0 + 39/8 : 1)]) """ verbose = int(verbose) if known_points is None: @@ -810,7 +811,7 @@ def global_integral_model(self): sage: K. = NumberField(x^2 + 161*x - 150) sage: E = EllipticCurve([25105/216*v - 3839/36, 634768555/7776*v - 98002625/1296, 634768555/7776*v - 98002625/1296, 0, 0]) sage: E.global_integral_model() - Elliptic Curve defined by y^2 + (2094779518028859*v-1940492905300351)*x*y + (477997268472544193101178234454165304071127500*v-442791377441346852919930773849502871958097500)*y = x^3 + (26519784690047674853185542622500*v-24566525306469707225840460652500)*x^2 over Number Field in v with defining polynomial x^2 + 161*x - 150 + Elliptic Curve defined by y^2 + (33872485050625*v-31078224284250)*x*y + (2020602604156076340058146664245468750000*v-1871778534673615560803175189398437500000)*y = x^3 + (6933305282258321342920781250*v-6422644400723486559914062500)*x^2 over Number Field in v with defining polynomial x^2 + 161*x - 150 :trac:`14476`:: @@ -923,10 +924,10 @@ def _scale_by_units(self): sage: E1 = E.scale_curve(u^5) sage: E1.ainvs() (0, - 0, - 0, - 28087920796764302856*a + 88821804456186580548, - -77225139016967233228487820912*a - 244207331916752959911655344864) + 0, + 0, + 193309837823322216*a - 611299381639464252, + -3379649566176127326923323632*a + 10687390322316522207588229536) sage: E1._scale_by_units().ainvs() (0, 0, 0, 4536*a + 14148, -163728*a - 474336) From 507576f492419feff2c567988c11fb1abddc648f Mon Sep 17 00:00:00 2001 From: Antonio Rojas Date: Sat, 18 Apr 2020 14:11:59 +0200 Subject: [PATCH 005/217] Update to 2.11.4 --- build/pkgs/pari/checksums.ini | 6 +-- build/pkgs/pari/package-version.txt | 2 +- build/pkgs/pari/patches/fix-bnfisunit.patch | 54 --------------------- src/sage/rings/number_field/number_field.py | 10 ++-- 4 files changed, 9 insertions(+), 63 deletions(-) delete mode 100644 build/pkgs/pari/patches/fix-bnfisunit.patch diff --git a/build/pkgs/pari/checksums.ini b/build/pkgs/pari/checksums.ini index fdc47ee3034..bd0ec827018 100644 --- a/build/pkgs/pari/checksums.ini +++ b/build/pkgs/pari/checksums.ini @@ -1,4 +1,4 @@ tarball=pari-VERSION.tar.gz -sha1=4535447ec298d3ede042d554b7b055b31fa28caf -md5=6ff176422113f2c83facaeda547be03c -cksum=2463676551 +sha1=2b9ff51feb388664b834dc346a44867546c78618 +md5=fb2968d7805424518fe44a59a2024afd +cksum=1247903778 diff --git a/build/pkgs/pari/package-version.txt b/build/pkgs/pari/package-version.txt index f708f826e5b..a07f650f820 100644 --- a/build/pkgs/pari/package-version.txt +++ b/build/pkgs/pari/package-version.txt @@ -1 +1 @@ -2.11.3.p0 +2.11.4.p0 diff --git a/build/pkgs/pari/patches/fix-bnfisunit.patch b/build/pkgs/pari/patches/fix-bnfisunit.patch deleted file mode 100644 index 3f83095440d..00000000000 --- a/build/pkgs/pari/patches/fix-bnfisunit.patch +++ /dev/null @@ -1,54 +0,0 @@ -From c7a1d35f382e96ddf14694be27a0ca5746880700 Mon Sep 17 00:00:00 2001 -From: Karim Belabas -Date: Mon, 9 Sep 2019 17:20:21 +0200 -Subject: [PATCH] fix #2164 - ---- - src/basemath/buch2.c | 3 ++- - src/test/32/nf | 3 ++- - src/test/in/nf | 4 ++++ - 3 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/src/basemath/buch2.c b/src/basemath/buch2.c -index a853d3c48..e31b2278b 100644 ---- a/src/basemath/buch2.c -+++ b/src/basemath/buch2.c -@@ -2136,7 +2136,8 @@ bnfisunit(GEN bnf,GEN x) - for (i = 1; i < RU; i++) - if (gexpo(gel(emb,i)) > -1) break; - p1 = imag_i( row_i(logunit,i, 1,RU-1) ); -- p1 = RgV_dotproduct(p1, ex); if (!R1) p1 = gmul2n(p1, -1); -+ p1 = RgV_dotproduct(p1, ex); -+ if (i > R1) p1 = gmul2n(p1, -1); - p1 = gsub(garg(gel(emb,i),prec), p1); - /* p1 = arg(the missing root of 1) */ - -diff --git a/src/test/32/nf b/src/test/32/nf -index 16bf83ce3..e6c41f8b5 100644 ---- a/src/test/32/nf -+++ b/src/test/32/nf -@@ -494,6 +494,7 @@ - [1, 1/2*x - 1/2] - Mod(0, x) - Mod(-6/5, x) -+[0, 2, Mod(0, 2)]~ - *** at top-level: nfinit([y^3+2,[1,x]]) - *** ^--------------------- - *** nfinit: incorrect type in nfbasic_init (t_VEC). -diff --git a/src/test/in/nf b/src/test/in/nf -index 49148123b..94d5165bc 100644 ---- a/src/test/in/nf -+++ b/src/test/in/nf -@@ -150,6 +150,10 @@ - nfinit(x, 3)[2] - nfinit(1/2*x + 3/5, 3)[2] - -+\\ #2164 -+bnf = bnfinit(y^4-y-1); -+bnfisunit(bnf,-y^3+2*y^2-1) -+ - \\ ERRORS: keep at end of file - - nfinit([y^3+2,[1,x]]) --- -2.11.0 diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index a052995571e..52ed818c14e 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -3266,18 +3266,18 @@ def ideals_of_bdd_norm(self, bound): Fractional ideal (2, 1/2*a - 1/2) Fractional ideal (2, 1/2*a + 1/2) 3 - Fractional ideal (3, 1/2*a - 1/2) Fractional ideal (3, 1/2*a + 1/2) + Fractional ideal (3, 1/2*a - 1/2) 4 Fractional ideal (4, 1/2*a + 3/2) Fractional ideal (2) Fractional ideal (4, 1/2*a + 5/2) 5 6 - Fractional ideal (1/2*a - 1/2) - Fractional ideal (6, 1/2*a + 5/2) Fractional ideal (6, 1/2*a + 7/2) Fractional ideal (1/2*a + 1/2) + Fractional ideal (1/2*a - 1/2) + Fractional ideal (6, 1/2*a + 5/2) 7 8 Fractional ideal (1/2*a + 3/2) @@ -3285,9 +3285,9 @@ def ideals_of_bdd_norm(self, bound): Fractional ideal (4, a + 1) Fractional ideal (1/2*a - 3/2) 9 - Fractional ideal (9, 1/2*a + 11/2) - Fractional ideal (3) Fractional ideal (9, 1/2*a + 7/2) + Fractional ideal (3) + Fractional ideal (9, 1/2*a + 11/2) 10 """ hnf_ideals = self.pari_nf().ideallist(bound) From 68cee5252b8401d8143df121bdc2348d832539ee Mon Sep 17 00:00:00 2001 From: Markus Wageringel Date: Sat, 16 May 2020 21:18:02 +0200 Subject: [PATCH 006/217] 29694: fix conflict between lazy attribute/abstract method --- src/sage/structure/sage_object.pyx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/sage/structure/sage_object.pyx b/src/sage/structure/sage_object.pyx index 140e2defefd..fdada6ed554 100644 --- a/src/sage/structure/sage_object.pyx +++ b/src/sage/structure/sage_object.pyx @@ -592,6 +592,14 @@ cdef class SageObject: ... AssertionError: Not implemented method: bla + Check that only errors triggered by ``AbstractMethod`` are caught + (:trac:`29694`):: + + sage: class NotAbstract(SageObject): + ....: @lazy_attribute + ....: def bla(self): + ....: raise NotImplementedError("not implemented") + sage: NotAbstract()._test_not_implemented_methods() """ tester = self._tester(**options) try: @@ -601,9 +609,9 @@ cdef class SageObject: for name in dir(self): try: getattr(self, name) - except NotImplementedError: - # It would be best to make sure that this NotImplementedError was triggered by AbstractMethod - tester.fail("Not implemented method: %s"%name) + except NotImplementedError as e: + if 'abstract method' in str(e): + tester.fail("Not implemented method: %s" % name) except Exception: pass finally: From a924748e5144e825ef9c66f77ed2b30112fb5402 Mon Sep 17 00:00:00 2001 From: Alexander Galarraga Date: Mon, 1 Jun 2020 13:15:50 -0400 Subject: [PATCH 007/217] Removed p-adic xgcd warning --- .../polynomial_padic_capped_relative_dense.py | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py b/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py index 9ef55881d35..6f7087bf8f6 100644 --- a/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py +++ b/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py @@ -1131,12 +1131,6 @@ def xgcd(self, right): Polynomials ``g``, ``u``, and ``v`` such that ``g = u*self + v*other`` - .. WARNING:: - - The computations are performed using the standard Euclidean - algorithm which might produce mathematically incorrect results in - some cases. See :trac:`13439`. - EXAMPLES:: sage: R. = Qp(3,3)[] @@ -1144,24 +1138,20 @@ def xgcd(self, right): sage: f.xgcd(f^2) ((1 + O(3^3))*x + 1 + O(3^3), 1 + O(3^3), 0) - In these examples the results are incorrect, see :trac:`13439`:: + We check that :trac:`13439`: has been fixed: sage: R. = Qp(3,3)[] sage: f = 3*x + 7 sage: g = 5*x + 9 - sage: f.xgcd(f*g) # known bug - ((3 + O(3^4))*x + (1 + 2*3 + O(3^3)), (1 + O(3^3)), 0) + sage: f.xgcd(f*g) + ((1 + O(3^3))*x + 3^-1 + 2 + O(3^2), 3^-1 + O(3^2), 0) sage: R. = Qp(3)[] sage: f = 490473657*x + 257392844/729 sage: g = 225227399/59049*x - 8669753175 - sage: f.xgcd(f*g) # known bug - ((3^3 + 3^5 + 2*3^6 + 2*3^7 + 3^8 + 2*3^10 + 2*3^11 + 3^12 + 3^13 + 3^15 + 2*3^16 + 3^18 + O(3^23))*x + (2*3^-6 + 2*3^-5 + 3^-3 + 2*3^-2 + 3^-1 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 3^11 + O(3^14)), (1 + O(3^20)), 0) - + sage: f.xgcd(f*g) + ((1 + O(3^20))*x + 2*3^-9 + 2*3^-8 + 3^-7 + 2*3^-4 + 3^-3 + 3^-2 + 3^-1 + 3 + 3^2 + 2*3^4 + 3^5 + 3^7 + 2*3^10 + O(3^11), 3^-3 + 2*3^-1 + 3 + 2*3^2 + 3^3 + 3^4 + 2*3^5 + 2*3^7 + 2*3^9 + 3^10 + 3^11 + 3^12 + 2*3^14 + 3^15 + O(3^17),0) """ - from sage.misc.stopgap import stopgap - stopgap("Extended gcd computations over p-adic fields are performed using the standard Euclidean algorithm which might produce mathematically incorrect results in some cases.", 13439) - return Polynomial_generic_cdv.xgcd(self,right) #def discriminant(self): From 91f08d3e1412629a40a71ff4be30c9c400df5fde Mon Sep 17 00:00:00 2001 From: Alexander Galarraga Date: Tue, 2 Jun 2020 14:46:18 -0400 Subject: [PATCH 008/217] Partial fix for GCD's over Zp with precision 1 --- .../polynomial_padic_capped_relative_dense.py | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py b/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py index 6f7087bf8f6..60b2d2ea1c3 100644 --- a/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py +++ b/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py @@ -1112,8 +1112,8 @@ def _quo_rem_list(self, right, secure): parent = PolynomialRing(K, name=self.parent().variable_name()) return parent(q), parent(a[:db]) - #def gcd(self, right): - # raise NotImplementedError + def gcd(self, right): + return self.xgcd(right)[0] #def lcm(self, right): # raise NotImplementedError @@ -1151,7 +1151,31 @@ def xgcd(self, right): sage: g = 225227399/59049*x - 8669753175 sage: f.xgcd(f*g) ((1 + O(3^20))*x + 2*3^-9 + 2*3^-8 + 3^-7 + 2*3^-4 + 3^-3 + 3^-2 + 3^-1 + 3 + 3^2 + 2*3^4 + 3^5 + 3^7 + 2*3^10 + O(3^11), 3^-3 + 2*3^-1 + 3 + 2*3^2 + 3^3 + 3^4 + 2*3^5 + 2*3^7 + 2*3^9 + 3^10 + 3^11 + 3^12 + 2*3^14 + 3^15 + O(3^17),0) + + We check low precision examples over `Zp`: + + sage: R. = Zp(3,1)[] + sage: h = 3*x + 7 + sage: i = 4*x + 9 + sage: h.xgcd(h*i) + ((3 + O(3^2))*x + 1 + O(3), 1 + O(3), 0) """ + from sage.rings.padics.generic_nodes import pAdicRingGeneric as pAdicRingGeneric + if isinstance(self.base_ring(), pAdicRingGeneric): + base_ring = self.base_ring() + fracfield = (base_ring.fraction_field()) + sfield = self.change_ring(fracfield) + rfield = right.change_ring(fracfield) + xgcd = list(Polynomial_generic_cdv.xgcd(sfield,rfield)) + lcm = base_ring(1) + for f in xgcd: + for i in f: + lcm = (i.denominator()).lcm(lcm) + returnlst = [] + for f in xgcd: + f *= lcm + returnlst.append(f.change_ring(base_ring)) + return tuple(returnlst) return Polynomial_generic_cdv.xgcd(self,right) #def discriminant(self): From c83c0c57ce0c71ad9723605ee6e3b20f580d0837 Mon Sep 17 00:00:00 2001 From: Alexander Galarraga Date: Tue, 2 Jun 2020 15:06:23 -0400 Subject: [PATCH 009/217] Working GCD and xGCD for low-precision Zp --- src/sage/rings/padics/generic_nodes.py | 21 +++++++++++++++ .../polynomial_padic_capped_relative_dense.py | 26 ++++--------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/sage/rings/padics/generic_nodes.py b/src/sage/rings/padics/generic_nodes.py index a2dc8b2d2e8..d53b8585244 100644 --- a/src/sage/rings/padics/generic_nodes.py +++ b/src/sage/rings/padics/generic_nodes.py @@ -746,6 +746,27 @@ def krull_dimension(self): """ return 1 + def _xgcd_univariate_polynomial(self, other, *args, **kwards): + poly = args[0] + base_ring = poly.base_ring() + fracfield = (base_ring.fraction_field()) + sfield = poly.change_ring(fracfield) + rfield = other.change_ring(fracfield) + from sage.rings.polynomial.polynomial_element_generic import Polynomial_generic_cdv as Polynomial_generic_cdv + xgcd = list(Polynomial_generic_cdv.xgcd(sfield,rfield)) + lcm = base_ring(1) + for f in xgcd: + for i in f: + lcm = (i.denominator()).lcm(lcm) + returnlst = [] + for f in xgcd: + f *= lcm + returnlst.append(f.change_ring(base_ring)) + return tuple(returnlst) + + def _gcd_univariate_polynomial(self, other, *args, **kwards): + return self._xgcd_univariate_polynomial(other, *args, **kwards)[0] + def is_pAdicField(R): """ Returns ``True`` if and only if ``R`` is a `p`-adic field. diff --git a/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py b/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py index 60b2d2ea1c3..ccbe2f01200 100644 --- a/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py +++ b/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py @@ -1112,14 +1112,14 @@ def _quo_rem_list(self, right, secure): parent = PolynomialRing(K, name=self.parent().variable_name()) return parent(q), parent(a[:db]) - def gcd(self, right): - return self.xgcd(right)[0] + #def gcd(self, right): + # raise NotImplementedError #def lcm(self, right): # raise NotImplementedError - @coerce_binop - def xgcd(self, right): + #@coerce_binop + #def xgcd(self, right): """ Extended gcd of ``self`` and ``other``. @@ -1160,23 +1160,7 @@ def xgcd(self, right): sage: h.xgcd(h*i) ((3 + O(3^2))*x + 1 + O(3), 1 + O(3), 0) """ - from sage.rings.padics.generic_nodes import pAdicRingGeneric as pAdicRingGeneric - if isinstance(self.base_ring(), pAdicRingGeneric): - base_ring = self.base_ring() - fracfield = (base_ring.fraction_field()) - sfield = self.change_ring(fracfield) - rfield = right.change_ring(fracfield) - xgcd = list(Polynomial_generic_cdv.xgcd(sfield,rfield)) - lcm = base_ring(1) - for f in xgcd: - for i in f: - lcm = (i.denominator()).lcm(lcm) - returnlst = [] - for f in xgcd: - f *= lcm - returnlst.append(f.change_ring(base_ring)) - return tuple(returnlst) - return Polynomial_generic_cdv.xgcd(self,right) + #return Polynomial_generic_cdv.xgcd(self,right) #def discriminant(self): # raise NotImplementedError From c4a947aeb4e2c63f9e8fb4a397abbb0db4f479f6 Mon Sep 17 00:00:00 2001 From: Alexander Galarraga Date: Tue, 2 Jun 2020 19:16:16 -0400 Subject: [PATCH 010/217] Finished GCD for Zp. Removed GCD function in polynomial_padic_capped_relative_dense --- src/sage/rings/padics/generic_nodes.py | 54 +++++++++++++++++-- .../polynomial_padic_capped_relative_dense.py | 44 --------------- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/sage/rings/padics/generic_nodes.py b/src/sage/rings/padics/generic_nodes.py index d53b8585244..97642f7caba 100644 --- a/src/sage/rings/padics/generic_nodes.py +++ b/src/sage/rings/padics/generic_nodes.py @@ -747,13 +747,45 @@ def krull_dimension(self): return 1 def _xgcd_univariate_polynomial(self, other, *args, **kwards): + """ + Extended gcd for univariate polynomial rings over self + + EXAMPLES:: + + sage: R. = Zp(3,3)[] + sage: f = x + 1 + sage: f.xgcd(f^2) + ((1 + O(3^3))*x + 1 + O(3^3), 1 + O(3^3), 0) + + We check that :trac:`13439` has been fixed:: + + sage: R. = Zp(3,3)[] + sage: f = 3*x + 7 + sage: g = 5*x + 9 + sage: f.xgcd(f*g) + ((3 + O(3^4))*x + 1 + 2*3 + O(3^3), 0, 1 + O(3^3)) + + sage: R. = Zp(3)[] + sage: f = 357555295953*x + 257392844 + sage: g = 225227399*x - 511940255230575 + sage: f.xgcd(f*g) + ((3^9 + O(3^29))*x + 2 + 2*3 + 3^2 + 2*3^5 + 3^6 + 3^7 + 3^8 + 3^10 + 3^11 + 2*3^13 + 3^14 + 3^16 + 2*3^19 + O(3^20), 0, 1 + 2*3^2 + 3^4 + 2*3^5 + 3^6 + 3^7 + 2*3^8 + 2*3^10 + 2*3^12 + 3^13 + 3^14 + 3^15 + 2*3^17 + 3^18 + O(3^20)) + + We check low precision computations:: + + sage: R. = Zp(3,1)[] + sage: h = 3*x + 7 + sage: i = 4*x + 9 + sage: h.xgcd(h*i) + ((3 + O(3^2))*x + 1 + O(3), 1 + O(3), 0) + """ poly = args[0] base_ring = poly.base_ring() - fracfield = (base_ring.fraction_field()) - sfield = poly.change_ring(fracfield) - rfield = other.change_ring(fracfield) - from sage.rings.polynomial.polynomial_element_generic import Polynomial_generic_cdv as Polynomial_generic_cdv - xgcd = list(Polynomial_generic_cdv.xgcd(sfield,rfield)) + #low precision computation done over the ring fails, see trac 29777 + fracfield = base_ring.fraction_field() + pfield = poly.change_ring(fracfield) + ofield = other.change_ring(fracfield) + xgcd = fracfield._xgcd_univariate_polynomial(pfield,ofield) lcm = base_ring(1) for f in xgcd: for i in f: @@ -765,6 +797,18 @@ def _xgcd_univariate_polynomial(self, other, *args, **kwards): return tuple(returnlst) def _gcd_univariate_polynomial(self, other, *args, **kwards): + """ + gcd for univariate polynomial rings over self + + EXAMPLES:: + + sage: R. = Zq(27) + sage: K. = R[] + sage: h = 3*x + a + sage: i = 4*x + 2 + sage: h.gcd(h*i) + (3 + O(3^21))*x + a + O(3^20) + """ return self._xgcd_univariate_polynomial(other, *args, **kwards)[0] def is_pAdicField(R): diff --git a/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py b/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py index ccbe2f01200..cfd9193103b 100644 --- a/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py +++ b/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py @@ -1118,50 +1118,6 @@ def _quo_rem_list(self, right, secure): #def lcm(self, right): # raise NotImplementedError - #@coerce_binop - #def xgcd(self, right): - """ - Extended gcd of ``self`` and ``other``. - - INPUT: - - - ``other`` -- an element with the same parent as ``self`` - - OUTPUT: - - Polynomials ``g``, ``u``, and ``v`` such that ``g = u*self + v*other`` - - EXAMPLES:: - - sage: R. = Qp(3,3)[] - sage: f = x + 1 - sage: f.xgcd(f^2) - ((1 + O(3^3))*x + 1 + O(3^3), 1 + O(3^3), 0) - - We check that :trac:`13439`: has been fixed: - - sage: R. = Qp(3,3)[] - sage: f = 3*x + 7 - sage: g = 5*x + 9 - sage: f.xgcd(f*g) - ((1 + O(3^3))*x + 3^-1 + 2 + O(3^2), 3^-1 + O(3^2), 0) - - sage: R. = Qp(3)[] - sage: f = 490473657*x + 257392844/729 - sage: g = 225227399/59049*x - 8669753175 - sage: f.xgcd(f*g) - ((1 + O(3^20))*x + 2*3^-9 + 2*3^-8 + 3^-7 + 2*3^-4 + 3^-3 + 3^-2 + 3^-1 + 3 + 3^2 + 2*3^4 + 3^5 + 3^7 + 2*3^10 + O(3^11), 3^-3 + 2*3^-1 + 3 + 2*3^2 + 3^3 + 3^4 + 2*3^5 + 2*3^7 + 2*3^9 + 3^10 + 3^11 + 3^12 + 2*3^14 + 3^15 + O(3^17),0) - - We check low precision examples over `Zp`: - - sage: R. = Zp(3,1)[] - sage: h = 3*x + 7 - sage: i = 4*x + 9 - sage: h.xgcd(h*i) - ((3 + O(3^2))*x + 1 + O(3), 1 + O(3), 0) - """ - #return Polynomial_generic_cdv.xgcd(self,right) - #def discriminant(self): # raise NotImplementedError From 4511f7730331581a76bfbefe51b1ac7b1e8839d7 Mon Sep 17 00:00:00 2001 From: Stefan Grosser Date: Mon, 8 Jun 2020 00:02:04 -0400 Subject: [PATCH 011/217] Added a d-complete poset subclass with hook lengths. Modified Poset to have a poset type argument to allow subclasses of FinitePoset. Added a subclass of LinearExtensionsOfPoset to provide overloading on ``cardinality`` for posets with hook length formulas --- src/sage/combinat/posets/d_complete.py | 98 +++++++++++++++++++ src/sage/combinat/posets/linear_extensions.py | 19 ++++ src/sage/combinat/posets/posets.py | 5 +- 3 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 src/sage/combinat/posets/d_complete.py diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py new file mode 100644 index 00000000000..3c78ef34b92 --- /dev/null +++ b/src/sage/combinat/posets/d_complete.py @@ -0,0 +1,98 @@ +from sage.combinat.posets.posets import Poset, FinitePoset + +class DCompletePoset(FinitePoset): + r""" + A (finite) `n`-element d-complete poset constructed from a directed acyclic graph. + + INPUT: + + - ``hasse_diagram`` -- an instance of + :class:`~sage.combinat.posets.posets.FinitePoset`, or a + :class:`DiGraph` that is transitively-reduced, acyclic, + loop-free, and multiedge-free. + + - ``elements`` -- an optional list of elements, with ``element[i]`` + corresponding to vertex ``i``. If ``elements`` is ``None``, then it is + set to be the vertex set of the digraph. Note that if this option is set, + then ``elements`` is considered as a specified linear extension of the poset + and the `linear_extension` attribute is set. + + - ``category`` -- :class:`FinitePosets`, or a subcategory thereof. + + - ``facade`` -- a boolean or ``None`` (default); whether the + :class:`~sage.combinat.posets.posets.DCompletePoset`'s elements should be + wrapped to make them aware of the Poset they belong to. + + * If ``facade = True``, the + :class:`~sage.combinat.posets.posets.DCompletePoset`'s elements are exactly + those given as input. + + * If ``facade = False``, the + :class:`~sage.combinat.posets.posets.DCompletePoset`'s elements will become + :class:`~sage.combinat.posets.posets.PosetElement` objects. + + * If ``facade = None`` (default) the expected behaviour is the behaviour + of ``facade = True``, unless the opposite can be deduced from the + context (i.e. for instance if a + :class:`~sage.combinat.posets.posets.DCompletePoset` is built from another + :class:`~sage.combinat.posets.posets.DCompletePoset`, itself built with + ``facade = False``) + + - ``key`` -- any hashable value (default: ``None``). + + """ + + def _calculateHookLengths(self): + """ + Calculates the hook lengths of the elements of self + """ + hooks = {} + queue = list(self.minimal_elements()) + + while len(queue) > 0: + elmt = queue.pop(0) + print(elmt) + children = self.lower_covers(elmt) + + if len(children) != 2: + hooks[elmt] = sum(hooks[child] for child in children) + 1 + + else: + child_meets = set(self.lower_covers(children[0])).intersection(set(self.lower_covers(children[1]))) + if len(child_meets) == 1: + hooks[elmt] = hooks[children[0]] + hooks[children[1]] - hooks[child_meets.pop()] + + else: + hooks[elmt] = sum(hooks[child] for child in children) + 1 + + queue.extend(list(self.upper_covers(elmt))) + print(queue) + + return hooks + + def __init__(self, hasse_diagram, elements, category, facade, key): + FinitePoset.__init__(self, hasse_diagram=hasse_diagram, elements=elements, category=category, facade=facade, key=key) + self._hooks = self._calculateHookLengths() + + def get_hook(self, elmt): + """ + Get the hook length of a specific element + """ + return self._hooks[elmt] + + def get_hooks(self): + """ + Get all the hook lengths returned in a dictionary + """ + return _hooks + + @staticmethod + def is_d_complete(cls, poset): + """ + Check if a poset is d-complete + """ + pass + + def linear_extensions(self, facade): + from .linear_extensions import LinearExtensionsOfPosetWithHooks + return LinearExtensionsOfPosetWithHooks(self, facade=facade) \ No newline at end of file diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index b466e0a8c36..f5255c1cd56 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -844,3 +844,22 @@ def _element_constructor_(self, lst, check=True): return self.element_class(self, lst, check) Element = LinearExtensionOfPoset + +class LinearExtensionsOfPosetWithHooks(LinearExtensionsOfPoset): + r""" + A subclass of ``LinearExtensionOfPoset`` where the poset + has well-defined hook lengths (ie. d-complete). + """ + + def __init__(self, poset, facade): + LinearExtensionsOfPoset.__init__(self, poset=poset, facade=facade) + + def cardinality(self): + """ + Count the number of linear extensions + """ + num_elmts = poset.cardinality() + hooks = poset.get_hooks() + hook_product = prod(hooks[elmt] for elmt in hooks) + return factorial(num_elmts) / hook_product + diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index deac1eff88b..66929a4b1ab 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -299,9 +299,10 @@ from sage.combinat.posets.elements import PosetElement from sage.combinat.combinatorial_map import combinatorial_map from sage.combinat.subset import Subsets +from sage.combinat.posets.d_complete import DCompletePoset -def Poset(data=None, element_labels=None, cover_relations=False, linear_extension=False, category=None, facade=None, key=None): +def Poset(data=None, element_labels=None, cover_relations=False, linear_extension=False, category=None, facade=None, key=None, poset_type=FinitePoset): r""" Construct a finite poset from various forms of input data. @@ -761,7 +762,7 @@ def Poset(data=None, element_labels=None, cover_relations=False, linear_extensio "extension for the poset as it contains duplicate elements") else: elements = None - return FinitePoset(D, elements=elements, category=category, facade=facade, key=key) + return poset_type(D, elements=elements, category=category, facade=facade, key=key) class FinitePoset(UniqueRepresentation, Parent): From 18f984a65dccbfad994ded978bd225b09c22240c Mon Sep 17 00:00:00 2001 From: Stefan Grosser Date: Fri, 12 Jun 2020 16:20:55 -0400 Subject: [PATCH 012/217] remove change for poset constructor --- src/sage/combinat/posets/d_complete.py | 7 ++++--- src/sage/combinat/posets/linear_extensions.py | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index 3c78ef34b92..6d9f99d6d84 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -1,4 +1,5 @@ from sage.combinat.posets.posets import Poset, FinitePoset +from sage.misc.lazy_attribute import lazy_attribute class DCompletePoset(FinitePoset): r""" @@ -41,7 +42,7 @@ class DCompletePoset(FinitePoset): - ``key`` -- any hashable value (default: ``None``). """ - + @lazy_attribute def _calculateHookLengths(self): """ Calculates the hook lengths of the elements of self @@ -49,7 +50,7 @@ def _calculateHookLengths(self): hooks = {} queue = list(self.minimal_elements()) - while len(queue) > 0: + while queue: elmt = queue.pop(0) print(elmt) children = self.lower_covers(elmt) @@ -84,7 +85,7 @@ def get_hooks(self): """ Get all the hook lengths returned in a dictionary """ - return _hooks + return dict(self._hooks) @staticmethod def is_d_complete(cls, poset): diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index f5255c1cd56..82c923efd8c 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -6,6 +6,7 @@ - :class:`LinearExtensionOfPoset` - :class:`LinearExtensionsOfPoset` +- :class:`LinearExtensionsOfPosetWithHooks` Classes and methods ------------------- @@ -860,6 +861,6 @@ def cardinality(self): """ num_elmts = poset.cardinality() hooks = poset.get_hooks() - hook_product = prod(hooks[elmt] for elmt in hooks) - return factorial(num_elmts) / hook_product + hook_product = prod(hooks.values()) + return factorial(num_elmts) // hook_product From 0394382b6fd6e478dc733f6d7d02989e2d35edc2 Mon Sep 17 00:00:00 2001 From: Stefan Grosser Date: Sat, 13 Jun 2020 19:51:44 -0400 Subject: [PATCH 013/217] Added d_complete copyright. Added d_complete to module_list and init --- src/doc/en/reference/combinat/module_list.rst | 1 + src/sage/combinat/posets/__init__.py | 2 +- src/sage/combinat/posets/d_complete.py | 10 ++++++++++ src/sage/combinat/posets/posets.py | 4 ++-- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/doc/en/reference/combinat/module_list.rst b/src/doc/en/reference/combinat/module_list.rst index 64e844e9b8a..8ca1c08a1f9 100644 --- a/src/doc/en/reference/combinat/module_list.rst +++ b/src/doc/en/reference/combinat/module_list.rst @@ -192,6 +192,7 @@ Comprehensive Module list sage/combinat/posets/moebius_algebra sage/combinat/posets/poset_examples sage/combinat/posets/posets + sage/combinat/posets/d_complete sage/combinat/q_analogues sage/combinat/q_bernoulli sage/combinat/quickref diff --git a/src/sage/combinat/posets/__init__.py b/src/sage/combinat/posets/__init__.py index a2cd43889e5..b357f796b8f 100644 --- a/src/sage/combinat/posets/__init__.py +++ b/src/sage/combinat/posets/__init__.py @@ -12,7 +12,7 @@ - :ref:`sage.combinat.posets.lattices` - :ref:`sage.combinat.posets.linear_extensions` - +- :ref:`sage.combinat.posets.d_complete` - :ref:`sage.combinat.posets.incidence_algebras` - :ref:`sage.combinat.posets.cartesian_product` diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index 6d9f99d6d84..99c1d1df820 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -1,3 +1,13 @@ +# **************************************************************************** +# Copyright (C) 2020 Stefan Grosser +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + from sage.combinat.posets.posets import Poset, FinitePoset from sage.misc.lazy_attribute import lazy_attribute diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 66929a4b1ab..2226b224e22 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -302,7 +302,7 @@ from sage.combinat.posets.d_complete import DCompletePoset -def Poset(data=None, element_labels=None, cover_relations=False, linear_extension=False, category=None, facade=None, key=None, poset_type=FinitePoset): +def Poset(data=None, element_labels=None, cover_relations=False, linear_extension=False, category=None, facade=None, key=None): r""" Construct a finite poset from various forms of input data. @@ -762,7 +762,7 @@ def Poset(data=None, element_labels=None, cover_relations=False, linear_extensio "extension for the poset as it contains duplicate elements") else: elements = None - return poset_type(D, elements=elements, category=category, facade=facade, key=key) + return FinitePoset(D, elements=elements, category=category, facade=facade, key=key) class FinitePoset(UniqueRepresentation, Parent): From 0f9168c0df1a0bc19e88ffac0fbe5d88a1b42639 Mon Sep 17 00:00:00 2001 From: Stefan Grosser Date: Mon, 15 Jun 2020 19:41:19 -0400 Subject: [PATCH 014/217] added double tailed diamond to examples. commented hooks for fixing. removed circular imports --- src/sage/combinat/posets/d_complete.py | 5 ++--- src/sage/combinat/posets/poset_examples.py | 26 ++++++++++++++++++++++ src/sage/combinat/posets/posets.py | 1 - 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index 99c1d1df820..9c906a9cce1 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -53,7 +53,7 @@ class DCompletePoset(FinitePoset): """ @lazy_attribute - def _calculateHookLengths(self): + def _hooks(self): """ Calculates the hook lengths of the elements of self """ @@ -83,8 +83,7 @@ def _calculateHookLengths(self): def __init__(self, hasse_diagram, elements, category, facade, key): FinitePoset.__init__(self, hasse_diagram=hasse_diagram, elements=elements, category=category, facade=facade, key=key) - self._hooks = self._calculateHookLengths() - + def get_hook(self, elmt): """ Get the hook length of a specific element diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index 21f513686ef..1030e71e029 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -87,6 +87,7 @@ import sage.categories.posets from sage.combinat.permutation import Permutations, Permutation, to_standard from sage.combinat.posets.posets import Poset, FinitePoset, FinitePosets_n +from sage.combinat.posets.d_complete import DCompletePoset from sage.combinat.posets.lattices import (LatticePoset, MeetSemilattice, JoinSemilattice, FiniteLatticePoset) from sage.categories.finite_posets import FinitePosets @@ -1534,6 +1535,31 @@ def YoungFibonacci(n): D.relabel(lambda v: Word(v), inplace=True) return FiniteMeetSemilattice(hasse_diagram=D, category=FinitePosets()) + @staticmethod + def DoubleTailedDiamond(n): + r""" + Return a double-tailed diamond of 2n + 2 elements + + input: + + - ``n`` -- a positive integer + """ + try: + n = Integer(n) + except TypeError: + raise TypeError("number of elements must be an integer, not {}".format(n)) + if n <= 0: + raise ValueError("number of elements must be nonnegative, not {}".format(n)) + + edges = [(i,i+2) for i in range(1, n)] + edges.extend([(n, n+1), (n, n+2), (n+1, n+3), (n+2, n+3)]) + edges.extend([(i, i+1) for i in range(n+3, 2*n+2)]) + p = DiGraph([list(range(1, 2*n + 3)), edges]) + + return DCompletePoset(p) + + + @staticmethod def PermutationPattern(n): r""" diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 2226b224e22..deac1eff88b 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -299,7 +299,6 @@ from sage.combinat.posets.elements import PosetElement from sage.combinat.combinatorial_map import combinatorial_map from sage.combinat.subset import Subsets -from sage.combinat.posets.d_complete import DCompletePoset def Poset(data=None, element_labels=None, cover_relations=False, linear_extension=False, category=None, facade=None, key=None): From 3a6a7e5db9dcbe13a2c78e267c3bd4942b3b73b6 Mon Sep 17 00:00:00 2001 From: Alexander Galarraga Date: Wed, 17 Jun 2020 15:08:46 -0400 Subject: [PATCH 015/217] 29777: Added documentation --- src/sage/rings/padics/generic_nodes.py | 40 +++++++++++++++++++------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/src/sage/rings/padics/generic_nodes.py b/src/sage/rings/padics/generic_nodes.py index 97642f7caba..afd39fdbb1e 100644 --- a/src/sage/rings/padics/generic_nodes.py +++ b/src/sage/rings/padics/generic_nodes.py @@ -746,9 +746,20 @@ def krull_dimension(self): """ return 1 - def _xgcd_univariate_polynomial(self, other, *args, **kwards): + def _xgcd_univariate_polynomial(self, f, g): """ - Extended gcd for univariate polynomial rings over self + Extended gcd for univariate polynomial rings over self. + + Should not be called directly. Use f.xgcd(g) instead. + + INPUT: + + - ``f``, ``g`` - the polynomials of which to take the xgcd + + OUTPUT: + + - A tuple (a, b, c) which satisfies a = b*f + c*g. There + is not guarentee that a, b, and c are minimal. EXAMPLES:: @@ -779,13 +790,12 @@ def _xgcd_univariate_polynomial(self, other, *args, **kwards): sage: h.xgcd(h*i) ((3 + O(3^2))*x + 1 + O(3), 1 + O(3), 0) """ - poly = args[0] - base_ring = poly.base_ring() - #low precision computation done over the ring fails, see trac 29777 + base_ring = f.base_ring() + #low precision computation done over a ring fails, see trac 29777 fracfield = base_ring.fraction_field() - pfield = poly.change_ring(fracfield) - ofield = other.change_ring(fracfield) - xgcd = fracfield._xgcd_univariate_polynomial(pfield,ofield) + f_field = f.change_ring(fracfield) + g_field = g.change_ring(fracfield) + xgcd = fracfield._xgcd_univariate_polynomial(f_field,g_field) lcm = base_ring(1) for f in xgcd: for i in f: @@ -796,9 +806,17 @@ def _xgcd_univariate_polynomial(self, other, *args, **kwards): returnlst.append(f.change_ring(base_ring)) return tuple(returnlst) - def _gcd_univariate_polynomial(self, other, *args, **kwards): + def _gcd_univariate_polynomial(self, f, g): """ - gcd for univariate polynomial rings over self + gcd for univariate polynomial rings over self. + + INPUT: + + - ``f``, ``g`` - the polynomials of which to take the gcd + + OUTPUT: + + - A polynomial EXAMPLES:: @@ -809,7 +827,7 @@ def _gcd_univariate_polynomial(self, other, *args, **kwards): sage: h.gcd(h*i) (3 + O(3^21))*x + a + O(3^20) """ - return self._xgcd_univariate_polynomial(other, *args, **kwards)[0] + return self._xgcd_univariate_polynomial(f , g)[0] def is_pAdicField(R): """ From dfcdcb0fab6173ab598745e72706b0efa43f2e86 Mon Sep 17 00:00:00 2001 From: Antonio Rojas Date: Fri, 19 Jun 2020 13:59:15 +0200 Subject: [PATCH 016/217] Drop test fixes, handled in #29472 --- src/sage/lfunctions/dokchitser.py | 4 +-- src/sage/lfunctions/pari.py | 2 +- src/sage/rings/number_field/number_field.py | 28 +++++++++---------- .../number_field/number_field_element.pyx | 2 +- .../rings/number_field/number_field_ideal.py | 4 +-- src/sage/rings/number_field/unit_group.py | 2 +- .../polynomial/polynomial_quotient_ring.py | 12 ++++---- .../elliptic_curves/ell_number_field.py | 13 ++++----- 8 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/sage/lfunctions/dokchitser.py b/src/sage/lfunctions/dokchitser.py index 1bf8953a77b..680ac17dfd4 100644 --- a/src/sage/lfunctions/dokchitser.py +++ b/src/sage/lfunctions/dokchitser.py @@ -111,7 +111,7 @@ class Dokchitser(SageObject): 0.000000000000000 + 0.305999773834052*z + 0.186547797268162*z^2 - 0.136791463097188*z^3 + O(z^4) sage: L.check_functional_equation() 6.11218974700000e-18 # 32-bit - 6.11218974738703e-18 # 64-bit + 6.04442711160669e-18 # 64-bit RANK 2 ELLIPTIC CURVE: @@ -670,7 +670,7 @@ def check_functional_equation(self, T=1.2): sage: L = Dokchitser(conductor=1, gammaV=[0], weight=1, eps=1, poles=[1], residues=[-1], init='1') sage: L.check_functional_equation() -1.35525271600000e-20 # 32-bit - -1.35525271560688e-20 # 64-bit + -2.71050543121376e-20 # 64-bit If we choose the sign in functional equation for the `\zeta` function incorrectly, the functional equation diff --git a/src/sage/lfunctions/pari.py b/src/sage/lfunctions/pari.py index 1daa219c007..c60f944ed4e 100644 --- a/src/sage/lfunctions/pari.py +++ b/src/sage/lfunctions/pari.py @@ -423,7 +423,7 @@ class LFunction(SageObject): sage: L.taylor_series(1,4) 0.000000000000000 + 0.305999773834052*z + 0.186547797268162*z^2 - 0.136791463097188*z^3 + O(z^4) sage: L.check_functional_equation() - 4.33680868994202e-19 + 1.08420217248550e-19 .. RUBRIC:: Rank 2 elliptic curve diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index 9f4681c4b7d..26e219c1ed1 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -3431,18 +3431,18 @@ def ideals_of_bdd_norm(self, bound): Fractional ideal (2, 1/2*a - 1/2) Fractional ideal (2, 1/2*a + 1/2) 3 - Fractional ideal (3, 1/2*a + 1/2) Fractional ideal (3, 1/2*a - 1/2) + Fractional ideal (3, 1/2*a + 1/2) 4 Fractional ideal (4, 1/2*a + 3/2) Fractional ideal (2) Fractional ideal (4, 1/2*a + 5/2) 5 6 - Fractional ideal (6, 1/2*a + 7/2) - Fractional ideal (1/2*a + 1/2) Fractional ideal (1/2*a - 1/2) Fractional ideal (6, 1/2*a + 5/2) + Fractional ideal (6, 1/2*a + 7/2) + Fractional ideal (1/2*a + 1/2) 7 8 Fractional ideal (1/2*a + 3/2) @@ -3450,9 +3450,9 @@ def ideals_of_bdd_norm(self, bound): Fractional ideal (4, a + 1) Fractional ideal (1/2*a - 3/2) 9 - Fractional ideal (9, 1/2*a + 7/2) - Fractional ideal (3) Fractional ideal (9, 1/2*a + 11/2) + Fractional ideal (3) + Fractional ideal (9, 1/2*a + 7/2) 10 """ hnf_ideals = self.pari_nf().ideallist(bound) @@ -4548,7 +4548,7 @@ def _S_class_group_and_units(self, S, proof=True): -1/13*a^2 + 6/13*a + 345/13, -1, 2/13*a^2 + 1/13*a - 755/13, - 1/13*a^2 + 20/13*a - 7/13], + 1/13*a^2 - 19/13*a - 7/13], [(Fractional ideal (11, a - 2), 2), (Fractional ideal (19, a + 7), 2)]) Number fields defined by non-monic and non-integral @@ -4706,9 +4706,9 @@ def selmer_group(self, S, m, proof=True, orders=False): -1/13*a^2 + 6/13*a + 345/13, -1, 2/13*a^2 + 1/13*a - 755/13, - 1/13*a^2 + 20/13*a - 7/13, - 1/13*a^2 - 45/13*a + 97/13, - -2/13*a^2 - 40/13*a + 27/13] + 1/13*a^2 - 19/13*a - 7/13, + -1/13*a^2 + 45/13*a - 97/13, + 2/13*a^2 + 40/13*a - 27/13] Verify that :trac:`16708` is fixed:: @@ -5353,7 +5353,7 @@ def elements_of_norm(self, n, proof=None): sage: K. = NumberField(7/9*x^3 + 7/3*x^2 - 56*x + 123) sage: K.elements_of_norm(7) - [28/225*a^2 + 77/75*a - 133/25] + [7/225*a^2 - 7/75*a - 42/25] """ proof = proof_flag(proof) B = self.pari_bnf(proof).bnfisintnorm(n) @@ -5456,7 +5456,7 @@ def factor(self, n): sage: pari('setrand(2)') sage: L. = K.extension(x^2 - 7) sage: f = L.factor(a + 1); f - (Fractional ideal (-1/2*b + 1/2*a + 1)) * (Fractional ideal (-1/2*a*b - a + 1/2)) + (Fractional ideal (1/2*a*b - a + 1/2)) * (Fractional ideal (-1/2*a*b - a + 1/2)) sage: f.value() == a+1 True @@ -6533,7 +6533,7 @@ def uniformizer(self, P, others="positive"): sage: [K.uniformizer(P) for P,e in factor(K.ideal(5))] [t^2 - t + 1, t + 2, t - 2] sage: [K.uniformizer(P) for P,e in factor(K.ideal(7))] - [t^2 - 4*t + 1] + [t^2 + 3*t + 1] sage: [K.uniformizer(P) for P,e in factor(K.ideal(67))] [t + 23, t + 26, t - 32, t - 18] @@ -7803,11 +7803,11 @@ def optimized_representation(self, name=None, both_maps=True): Ring morphism: From: Number Field in a1 with defining polynomial x^3 - 7*x - 7 To: Number Field in a with defining polynomial 7/9*x^3 + 7/3*x^2 - 56*x + 123 - Defn: a1 |--> 28/225*a^2 + 77/75*a - 133/25, + Defn: a1 |--> 7/225*a^2 - 7/75*a - 42/25, Ring morphism: From: Number Field in a with defining polynomial 7/9*x^3 + 7/3*x^2 - 56*x + 123 To: Number Field in a1 with defining polynomial x^3 - 7*x - 7 - Defn: a |--> -60/7*a1^2 + 15*a1 + 39) + Defn: a |--> -15/7*a1^2 + 9) """ if name is None: name = self.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 079eaaa6a25..59bab07db08 100644 --- a/src/sage/rings/number_field/number_field_element.pyx +++ b/src/sage/rings/number_field/number_field_element.pyx @@ -1733,7 +1733,7 @@ cdef class NumberFieldElement(FieldElement): sage: P. = K[] sage: L = NumberField(X^2 + a^2 + 2*a + 1, 'b') sage: K(17)._rnfisnorm(L) - ((a^2 - 2)*b + 4, 1) + ((a^2 - 2)*b - 4, 1) sage: K. = NumberField(x^3 + x + 1) sage: Q. = K[] diff --git a/src/sage/rings/number_field/number_field_ideal.py b/src/sage/rings/number_field/number_field_ideal.py index 95ba0f54840..35ee5a6e4ba 100644 --- a/src/sage/rings/number_field/number_field_ideal.py +++ b/src/sage/rings/number_field/number_field_ideal.py @@ -1823,7 +1823,7 @@ def factor(self): sage: F. = NumberField(2*x^3 + x + 1) sage: fact = F.factor(2); fact - (Fractional ideal (-2*a^2 - 1))^2 * (Fractional ideal (2*a^2)) + (Fractional ideal (2*a^2 + 1))^2 * (Fractional ideal (-2*a^2)) sage: [p[0].norm() for p in fact] [2, 2] """ @@ -2414,7 +2414,7 @@ def idealcoprime(self, J): sage: A.is_coprime(B) False sage: lam = A.idealcoprime(B); lam - 1/6*a - 1/6 + -1/6*a + 1/6 sage: (lam*A).is_coprime(B) True diff --git a/src/sage/rings/number_field/unit_group.py b/src/sage/rings/number_field/unit_group.py index 529e23a5593..6ed0aea16b8 100644 --- a/src/sage/rings/number_field/unit_group.py +++ b/src/sage/rings/number_field/unit_group.py @@ -279,7 +279,7 @@ def __init__(self, number_field, proof=True, S=None): sage: K.unit_group() Unit group with structure C2 x Z x Z of Number Field in a with defining polynomial 7/9*x^3 + 7/3*x^2 - 56*x + 123 sage: UnitGroup(K, S=tuple(K.primes_above(7))) - S-unit group with structure C2 x Z x Z x Z of Number Field in a with defining polynomial 7/9*x^3 + 7/3*x^2 - 56*x + 123 with S = (Fractional ideal (28/225*a^2 + 77/75*a - 133/25),) + S-unit group with structure C2 x Z x Z x Z of Number Field in a with defining polynomial 7/9*x^3 + 7/3*x^2 - 56*x + 123 with S = (Fractional ideal (7/225*a^2 - 7/75*a - 42/25),) Conversion from unit group to a number field and back gives the right results (:trac:`25874`):: diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index e962ad584a5..de62148fd46 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -1291,9 +1291,9 @@ def S_class_group(self, S, proof=True): 1/16*a*xbar^3 + (-1/16*a - 1/8)*xbar^2 + 23/16*a*xbar - 23/16*a - 23/8), 6), ((-5/4*xbar^2 - 115/4, - (1/8*a - 5/8)*xbar^2 + 23/8*a - 115/8, - -1/16*xbar^3 - 17/16*xbar^2 - 23/16*xbar - 391/16, - 1/16*a*xbar^3 + (-1/16*a - 5/8)*xbar^2 + 23/16*a*xbar - 23/16*a - 115/8), + 1/4*a*xbar^2 + 23/4*a, + -1/16*xbar^3 - 7/16*xbar^2 - 23/16*xbar - 161/16, + 1/16*a*xbar^3 - 1/16*a*xbar^2 + 23/16*a*xbar - 23/16*a), 2)] By using the ideal `(a)`, we cut the part of the class group coming from @@ -1423,9 +1423,9 @@ def class_group(self, proof=True): 1/16*a*xbar^3 + (-1/16*a - 1/8)*xbar^2 + 23/16*a*xbar - 23/16*a - 23/8), 6), ((-5/4*xbar^2 - 115/4, - (1/8*a - 5/8)*xbar^2 + 23/8*a - 115/8, - -1/16*xbar^3 - 17/16*xbar^2 - 23/16*xbar - 391/16, - 1/16*a*xbar^3 + (-1/16*a - 5/8)*xbar^2 + 23/16*a*xbar - 23/16*a - 115/8), + 1/4*a*xbar^2 + 23/4*a, + -1/16*xbar^3 - 7/16*xbar^2 - 23/16*xbar - 161/16, + 1/16*a*xbar^3 - 1/16*a*xbar^2 + 23/16*a*xbar - 23/16*a), 2)] Note that all the returned values live where we expect them to:: diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 68cf4e3b63f..46e7af54bc3 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -301,8 +301,7 @@ def simon_two_descent(self, verbose=0, lim1=2, lim3=4, limtriv=2, (3, 3, [(0 : 0 : 1), - (-1/2*zeta43_0^2 - 1/2*zeta43_0 + 7 : -3/2*zeta43_0^2 - 5/2*zeta43_0 + 18 : 1), - (5/8*zeta43_0^2 + 17/8*zeta43_0 - 9/4 : -27/16*zeta43_0^2 - 103/16*zeta43_0 + 39/8 : 1)]) + (-1/2*zeta43_0^2 - 1/2*zeta43_0 + 7 : -3/2*zeta43_0^2 - 5/2*zeta43_0 + 18 : 1)]) """ verbose = int(verbose) if known_points is None: @@ -810,7 +809,7 @@ def global_integral_model(self): sage: K. = NumberField(x^2 + 161*x - 150) sage: E = EllipticCurve([25105/216*v - 3839/36, 634768555/7776*v - 98002625/1296, 634768555/7776*v - 98002625/1296, 0, 0]) sage: E.global_integral_model() - Elliptic Curve defined by y^2 + (33872485050625*v-31078224284250)*x*y + (2020602604156076340058146664245468750000*v-1871778534673615560803175189398437500000)*y = x^3 + (6933305282258321342920781250*v-6422644400723486559914062500)*x^2 over Number Field in v with defining polynomial x^2 + 161*x - 150 + Elliptic Curve defined by y^2 + (2094779518028859*v-1940492905300351)*x*y + (477997268472544193101178234454165304071127500*v-442791377441346852919930773849502871958097500)*y = x^3 + (26519784690047674853185542622500*v-24566525306469707225840460652500)*x^2 over Number Field in v with defining polynomial x^2 + 161*x - 150 :trac:`14476`:: @@ -920,10 +919,10 @@ def _scale_by_units(self): sage: E1 = E.scale_curve(u^5) sage: E1.ainvs() (0, - 0, - 0, - 193309837823322216*a - 611299381639464252, - -3379649566176127326923323632*a + 10687390322316522207588229536) + 0, + 0, + 28087920796764302856*a + 88821804456186580548, + -77225139016967233228487820912*a - 244207331916752959911655344864) sage: E1._scale_by_units().ainvs() (0, 0, 0, 4536*a + 14148, -163728*a - 474336) From 549e094174b9fb0b2fc5b7462d034f118e3fd1f3 Mon Sep 17 00:00:00 2001 From: Antonio Rojas Date: Fri, 19 Jun 2020 15:16:26 +0200 Subject: [PATCH 017/217] Add upstream url --- build/pkgs/pari/checksums.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/build/pkgs/pari/checksums.ini b/build/pkgs/pari/checksums.ini index bd0ec827018..f10b432dbb7 100644 --- a/build/pkgs/pari/checksums.ini +++ b/build/pkgs/pari/checksums.ini @@ -2,3 +2,4 @@ tarball=pari-VERSION.tar.gz sha1=2b9ff51feb388664b834dc346a44867546c78618 md5=fb2968d7805424518fe44a59a2024afd cksum=1247903778 +upstream_url=https://pari.math.u-bordeaux.fr/pub/pari/unix/pari-VERSION.tar.gz From 3cb69aa7dbf517e5cd7a7480e0857acbbecf071f Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Sat, 20 Jun 2020 00:21:32 +0200 Subject: [PATCH 018/217] add _test_dilation --- src/sage/geometry/polyhedron/base.py | 80 ++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 21 deletions(-) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 195e890c8f6..0464d932ecc 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -4733,27 +4733,6 @@ def dilation(self, scalar): () sage: (0*p).lines() () - - Dilation respects backend:: - - sage: P = polytopes.simplex(backend='field') - sage: P.dilation(3).backend() - 'field' - - Dilation with both Vrep and Hrep works correctly:: - - sage: def test_dilation(P): - ....: Q = P.change_ring(P.base_ring(), backend='field') - ....: assert 2*Q == 2*P - ....: assert 1/2*Q == 1/2*P - ....: assert (-3)*Q == (-3)*P - ....: assert (-1/2)*Q == (-1/2)*P - sage: test_dilation(polytopes.cube()) - sage: test_dilation(polytopes.cross_polytope(3)) - sage: test_dilation(polytopes.simplex(4)) - sage: test_dilation(polytopes.permutahedron(3)) - sage: test_dilation(polytopes.permutahedron(3)*Polyhedron(rays=[[0,0,1],[0,1,1],[1,2,3]])) - sage: test_dilation(polytopes.permutahedron(3)*Polyhedron(rays=[[0,0,1],[0,1,1]], lines=[[1,0,0]])) """ parent = self.parent().base_extend(scalar) @@ -4781,6 +4760,65 @@ def dilation(self, scalar): [new_inequalities, new_equations], Vrep_minimal=True, Hrep_minimal=True, pref_rep=pref_rep) + def _test_dilation(self, tester=None, **options): + """ + Run tests on the method :meth:`.dilation` + + TESTS:: + + sage: polytopes.cross_polytope(3)._test_dilation() + """ + if tester is None: + tester = self._tester(**options) + + # Testing that the backend is preserved. + tester.assertEqual(self.dilation(2*self.base_ring().gen()).backend(), self.backend()) + tester.assertEqual(self.dilation(ZZ(3)).backend(), self.backend()) + + if self.n_vertices() > 40: + # Avoid long time computations. + return + + # Testing that the double description is set up correctly. + if not self.backend() is 'field' and self.base_ring().is_exact(): + p = self.base_extend(self.base_ring(), backend='field') + tester.assertEqual(ZZ(2)*p, ZZ(2)*self) + tester.assertEqual(ZZ(1)/2*p, ZZ(1)/2*self) + tester.assertEqual(ZZ(-3)*p, ZZ(-3)*self) + tester.assertEqual((-ZZ(1)/2)*p, (-ZZ(1)/2)*self) + else: + tester.assertIsInstance(ZZ(1)/3*self, Polyhedron_base) + + if self.n_vertices() > 20: + # Avoid long time computations. + return + + # Some sanity check on the volume (only run for relativly small instances). + if self.dim() > -1 and self.is_compact() and self.base_ring().is_exact(): + tester.assertEqual(self.dilation(3).volume(measure='induced'), self.volume(measure='induced')*3**self.dim()) + + # Testing coercion with algebraic numbers. + from sage.rings.number_field.number_field import QuadraticField + K1 = QuadraticField(2, embedding=AA(2).sqrt()) + sqrt2 = K1.gen() + K2 = QuadraticField(3, embedding=AA(3).sqrt()) + sqrt3 = K2.gen() + + if self.base_ring() in (QQ,ZZ,AA,RDF): + tester.assertIsInstance(sqrt2*self, Polyhedron_base) + tester.assertIsInstance(sqrt3*self, Polyhedron_base) + elif hasattr(self.base_ring(), "composite_fields"): + for scalar, K in ((sqrt2, K1), (sqrt3, K2)): + new_ring = None + try: + new_ring = self.base_ring().composite_fields()[0] + except: + # This isn't about testing composite fields. + pass + if new_ring: + p = self.change_ring(new_ring) + tester.assertIsInstance(scalar*p, Polyhedron_base) + def linear_transformation(self, linear_transf): """ Return the linear transformation of ``self``. From bb6110cf37b33152ec09fb4f66ae659d2af8a9b8 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Sat, 20 Jun 2020 18:24:47 +0200 Subject: [PATCH 019/217] pyflakes --- src/sage/geometry/polyhedron/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 0464d932ecc..afdb00dc4a9 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -4780,7 +4780,7 @@ def _test_dilation(self, tester=None, **options): return # Testing that the double description is set up correctly. - if not self.backend() is 'field' and self.base_ring().is_exact(): + if self.backend() != 'field' and self.base_ring().is_exact(): p = self.base_extend(self.base_ring(), backend='field') tester.assertEqual(ZZ(2)*p, ZZ(2)*self) tester.assertEqual(ZZ(1)/2*p, ZZ(1)/2*self) From 99d1bb3eab83423786ef97a3fc2d6f4b9b182dc7 Mon Sep 17 00:00:00 2001 From: Stefan Grosser Date: Sun, 21 Jun 2020 15:17:14 -0400 Subject: [PATCH 020/217] Fixed calculating hooks and added the DoubleTailedDiamond example --- src/sage/combinat/posets/d_complete.py | 82 +++++++++++++++---- src/sage/combinat/posets/linear_extensions.py | 6 +- src/sage/combinat/posets/poset_examples.py | 2 +- src/sage/combinat/posets/posets.py | 17 ++++ 4 files changed, 87 insertions(+), 20 deletions(-) diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index 9c906a9cce1..57a40cf57ad 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -58,27 +58,75 @@ def _hooks(self): Calculates the hook lengths of the elements of self """ hooks = {} - queue = list(self.minimal_elements()) + + min_diamond = {} # Maps max of double-tailed diamond to min of double-tailed diamond + max_diamond = {} # Maps min of double-tailed diamond to max of double-tailed diamond + + diamonds = [] # Tuples of four elements that are diamonds + diamond_index = {} # Map max elmt of double tailed diamond to index of diamond + # Find all diamonds + for e in self._elements: + covers = self.upper_covers(e) + for p1, p2 in [(i,j) for i in covers for j in covers if i < j]: + top = self.common_upper_covers([p1, p2]) + if len(top) != 1: + continue + + else: + diamonds.append((e, p1, p2, top[0])) + min_diamond[top[0]] = e + max_diamond[e] = top[0] + diamond_index[top[0]] = len(diamonds) - 1 + break + # Find all the double-tailed diamonds and map the mins and maxes. + for index, d in enumerate(diamonds): + min_elmt = d[0] + max_elmt = d[3] + + while True: + potential_min = self.lower_covers(min_elmt) + + potential_max = self.upper_covers(max_elmt) + + # Check if any of these make a longer double tailed diamond + found_diamond = False + for (mn, mx) in [(i,j) for i in potential_min for j in potential_max]: + if len(self.lower_covers(mx)) != 1: + continue + if len(self._hasse_diagram.all_paths(self._element_to_vertex(mn), self._element_to_vertex(mx))) == 2: + # Success + min_elmt = mn + max_elmt = mx + + min_diamond[mx] = mn + max_diamond[mn] = mx + diamond_index[mx] = index + found_diamond = True + break + if not found_diamond: + break + + # Compute the hooks + queue = list(self.minimal_elements()) + enqueued = set() while queue: elmt = queue.pop(0) - print(elmt) - children = self.lower_covers(elmt) - - if len(children) != 2: - hooks[elmt] = sum(hooks[child] for child in children) + 1 - else: - child_meets = set(self.lower_covers(children[0])).intersection(set(self.lower_covers(children[1]))) - if len(child_meets) == 1: - hooks[elmt] = hooks[children[0]] + hooks[children[1]] - hooks[child_meets.pop()] + if elmt not in diamond_index: + hooks[elmt] = len(self.order_ideal([elmt])) + else: + diamond = diamonds[diamond_index[elmt]] + side1 = diamond[1] + side2 = diamond[2] + hooks[elmt] = hooks[side1] + hooks[side2] - hooks[min_diamond[elmt]] + enqueued.add(elmt) + + for c in self.upper_covers(elmt): + if c not in enqueued: + queue.append(c) + enqueued.add(c) - else: - hooks[elmt] = sum(hooks[child] for child in children) + 1 - - queue.extend(list(self.upper_covers(elmt))) - print(queue) - return hooks def __init__(self, hasse_diagram, elements, category, facade, key): @@ -103,6 +151,6 @@ def is_d_complete(cls, poset): """ pass - def linear_extensions(self, facade): + def linear_extensions(self, facade=False): from .linear_extensions import LinearExtensionsOfPosetWithHooks return LinearExtensionsOfPosetWithHooks(self, facade=facade) \ No newline at end of file diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index 2af6ecdff1f..9c4ebbe7a97 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -35,6 +35,8 @@ from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass from sage.graphs.dot2tex_utils import have_dot2tex from sage.structure.list_clone import ClonableArray +from sage.misc.all import prod +from sage.arith.all import factorial class LinearExtensionOfPoset(ClonableArray, @@ -857,8 +859,8 @@ def cardinality(self): """ Count the number of linear extensions """ - num_elmts = poset.cardinality() - hooks = poset.get_hooks() + num_elmts = self._poset.cardinality() + hooks = self._poset.get_hooks() hook_product = prod(hooks.values()) return factorial(num_elmts) // hook_product diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index 2d604300b7c..bf5645574e5 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -1549,7 +1549,7 @@ def DoubleTailedDiamond(n): if n <= 0: raise ValueError("number of elements must be nonnegative, not {}".format(n)) - edges = [(i,i+2) for i in range(1, n)] + edges = [(i,i+1) for i in range(1, n)] edges.extend([(n, n+1), (n, n+2), (n+1, n+3), (n+2, n+3)]) edges.extend([(i, i+1) for i in range(n+3, 2*n+2)]) p = DiGraph([list(range(1, 2*n + 3)), edges]) diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 2795700652b..6da60bfa93a 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -2083,6 +2083,23 @@ def relations(self): """ return list(self.relations_iterator()) + def common_upper_covers(self, elmts): + r""" + Return the list of all common upper covers of a list of elemements + + EXAMPLES:: + + sage: P = Poset({0: [1,2], 1: [3], 2: [3], 3: []}) + sage: P.common_upper_covers([1, 2]) + [3] + """ + covers = set(self.upper_covers(elmts.pop())) + + for e in elmts: + covers = covers.intersection(self.upper_covers(e)) + + return list(covers) + def intervals_poset(self): r""" Return the natural partial order on the set of intervals of the poset. From bdcd77483530b0e0aadb7d4655f8f7b1ee30f9fe Mon Sep 17 00:00:00 2001 From: Stefan Grosser Date: Sun, 21 Jun 2020 18:44:57 -0400 Subject: [PATCH 021/217] Added full docs, examples, and tests for DCompletePoset --- src/sage/combinat/posets/d_complete.py | 167 ++++++++++++++++----- src/sage/combinat/posets/poset_examples.py | 9 +- 2 files changed, 140 insertions(+), 36 deletions(-) diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index 57a40cf57ad..7f12d889f99 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -13,49 +13,63 @@ class DCompletePoset(FinitePoset): r""" - A (finite) `n`-element d-complete poset constructed from a directed acyclic graph. + D-complete posets are a class of posets introduced by Proctor in [1]. + It includes ommon families such as shapes, shifted shapes, and forests. Proctor showed in [2] + that d-complete posets have decompositions in ``irreducible`` posets, and showed in [3] that + d-complete posets admit a hook-length formula (see [4]). A complete proof of the hook-length formula + can be found in [5]. - INPUT: - - ``hasse_diagram`` -- an instance of - :class:`~sage.combinat.posets.posets.FinitePoset`, or a - :class:`DiGraph` that is transitively-reduced, acyclic, - loop-free, and multiedge-free. + REFERENCES: - - ``elements`` -- an optional list of elements, with ``element[i]`` - corresponding to vertex ``i``. If ``elements`` is ``None``, then it is - set to be the vertex set of the digraph. Note that if this option is set, - then ``elements`` is considered as a specified linear extension of the poset - and the `linear_extension` attribute is set. + .. [1] R. A. Proctor. Minuscule elements of Weyl groups, the numbers game, and d-complete posets. J. Algebra, + 213(1):272–303, 1999. + .. [2] R. A. Proctor. Dynkin diagram classification of λ-minuscule Bruhat lattices and of d-complete posets. J. + Algebraic Combin., 9(1):61–94, 1999. + .. [3] R. A. Proctor. d-complete posets generalize Young diagrams for the hook product formula: Partial Presentation + of Proof. RIMS Kˆokyˆuroku, 1913:120–140, 2014. + .. [4] https://en.wikipedia.org/wiki/Hook_length_formula - - ``category`` -- :class:`FinitePosets`, or a subcategory thereof. - - - ``facade`` -- a boolean or ``None`` (default); whether the - :class:`~sage.combinat.posets.posets.DCompletePoset`'s elements should be - wrapped to make them aware of the Poset they belong to. - - * If ``facade = True``, the - :class:`~sage.combinat.posets.posets.DCompletePoset`'s elements are exactly - those given as input. + .. [5] Kim, Jang Soo, and Meesue Yoo. "Hook length property of d-complete posets via q-integrals." + Journal of Combinatorial Theory, Series A 162 (2019): 167-221. + """ - * If ``facade = False``, the - :class:`~sage.combinat.posets.posets.DCompletePoset`'s elements will become - :class:`~sage.combinat.posets.posets.PosetElement` objects. + def _repr_(self): + r""" + TESTS:: - * If ``facade = None`` (default) the expected behaviour is the behaviour - of ``facade = True``, unless the opposite can be deduced from the - context (i.e. for instance if a - :class:`~sage.combinat.posets.posets.DCompletePoset` is built from another - :class:`~sage.combinat.posets.posets.DCompletePoset`, itself built with - ``facade = False``) + sage: from sage.combinat.posets.d_complete import DCompletePoset + sage: P = DCompletePoset(DiGraph({0: [1], 0: [2], 1: [3], 2: [3], 3: []})) + sage: P._repr_() + 'Finite d-complete poset containing 4 elements' + """ + s = "Finite d-complete poset containing %s elements" % self._hasse_diagram.order() + if self._with_linear_extension: + s += " with distinguished linear extension" + return s - - ``key`` -- any hashable value (default: ``None``). - """ @lazy_attribute def _hooks(self): - """ - Calculates the hook lengths of the elements of self + r""" + The hook lengths of the elements of the d-complete poset. For the definition + of hook lengths for d-complete posets, see [1]. + + TESTS:: + + sage: from sage.combinat.posets.d_complete import DCompletePoset + sage: P = DCompletePoset(DiGraph({0: [1, 2], 1: [3], 2: [3], 3: []})) + sage: P._hooks + {0: 1, 1: 2, 2: 2, 3: 3} + sage: from sage.combinat.posets.poset_examples import Posets + sage: P = DCompletePoset(Posets.YoungDiagramPoset(Partition([3,2,1]))._hasse_diagram.reverse()) + sage: P._hooks + {0: 5, 1: 3, 2: 1, 3: 3, 4: 1, 5: 1} + + REFERENCES: + + .. [1] Kim, Jang Soo, and Meesue Yoo. "Hook length property of d-complete posets via q-integrals." + Journal of Combinatorial Theory, Series A 162 (2019): 167-221. """ hooks = {} @@ -130,17 +144,56 @@ def _hooks(self): return hooks def __init__(self, hasse_diagram, elements, category, facade, key): + r""" + EXAMPLES:: + sage: from sage.combinat.posets.poset_examples import Posets + sage: P = Posets.DoubleTailedDiamond(2) + sage: type(P) + + + The additional internal data structure consists of: + + - the hook lengths of the elements of the poset + + sage: P._hooks + {1: 1, 2: 2, 3: 3, 4: 3, 5: 4, 6: 5} + + TESTS:: + + sage: TestSuite(P).run() + + See also the other tests in the class documentation. + """ FinitePoset.__init__(self, hasse_diagram=hasse_diagram, elements=elements, category=category, facade=facade, key=key) def get_hook(self, elmt): - """ - Get the hook length of a specific element + r""" + Get the hook length of a specific element. + + TESTS:: + + sage: from sage.combinat.posets.d_complete import DCompletePoset + sage: P = DCompletePoset(DiGraph({0: [1], 1: [2]})) + sage: P.get_hook(1) + 2 """ return self._hooks[elmt] def get_hooks(self): """ Get all the hook lengths returned in a dictionary + + TESTS:: + + sage: from sage.combinat.posets.d_complete import DCompletePoset + sage: P = DCompletePoset(DiGraph({0: [1, 2], 1: [3], 2: [3], 3: []})) + sage: P.get_hooks() + {0: 1, 1: 2, 2: 2, 3: 3} + sage: from sage.combinat.posets.poset_examples import Posets + sage: P = DCompletePoset(Posets.YoungDiagramPoset(Partition([3,2,1]))._hasse_diagram.reverse()) + sage: P.get_hooks() + {0: 5, 1: 3, 2: 1, 3: 3, 4: 1, 5: 1} + """ return dict(self._hooks) @@ -152,5 +205,49 @@ def is_d_complete(cls, poset): pass def linear_extensions(self, facade=False): + r""" + Returns the enumerated set of all the linear extensions of this poset with hook lengths + + INPUT: + + - ``facade`` -- a boolean (default: ``False``); + whether to return the linear extensions as plain lists + + EXAMPLES:: + + sage: from sage.combinat.posets.d_complete import DCompletePoset + sage: P = DCompletePoset(DiGraph({0: [1, 2], 1: [3], 2: [3], 3: [4]})) + sage: L = P.linear_extensions() + sage: L.cardinality() + 2 + sage: L.list() + [[0, 1, 2, 3, 4], [0, 2, 1, 3, 4]] + + TESTS:: + + sage: from sage.combinat.posets.d_complete import DCompletePoset + sage: from sage.combinat.posets.poset_examples import Posets + sage: P = DCompletePoset(Posets.YoungDiagramPoset(Partition([3,2,1]))._hasse_diagram.reverse()) + sage: L = P.linear_extensions() + sage: L.cardinality() + 16 + sage: L.list() + [[5, 4, 3, 2, 1, 0], + [4, 5, 3, 2, 1, 0], + [4, 5, 2, 3, 1, 0], + [4, 2, 5, 3, 1, 0], + [2, 4, 5, 3, 1, 0], + [2, 4, 5, 1, 3, 0], + [2, 4, 1, 5, 3, 0], + [4, 2, 1, 5, 3, 0], + [4, 2, 5, 1, 3, 0], + [4, 5, 2, 1, 3, 0], + [5, 4, 2, 1, 3, 0], + [5, 2, 4, 1, 3, 0], + [2, 5, 4, 1, 3, 0], + [2, 5, 4, 3, 1, 0], + [5, 2, 4, 3, 1, 0], + [5, 4, 2, 3, 1, 0]] + """ from .linear_extensions import LinearExtensionsOfPosetWithHooks return LinearExtensionsOfPosetWithHooks(self, facade=facade) \ No newline at end of file diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index bf5645574e5..c685b5dc16b 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -1538,9 +1538,16 @@ def DoubleTailedDiamond(n): r""" Return a double-tailed diamond of 2n + 2 elements - input: + Input: - ``n`` -- a positive integer + + EXAMPLES:: + + sage: P = posets.DoubleTailedDiamond(2); P + Finite d-complete poset containing 6 elements + sage: P.cover_relations() + [[1, 2], [2, 3], [2, 4], [3, 5], [4, 5], [5, 6]] """ try: n = Integer(n) From 121bdcbb8879b5446eba37da95d9dc8de2535d53 Mon Sep 17 00:00:00 2001 From: Stefan Grosser Date: Sun, 21 Jun 2020 21:48:03 -0400 Subject: [PATCH 022/217] small doc change --- src/sage/combinat/posets/d_complete.py | 2 +- src/sage/combinat/posets/linear_extensions.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index 7f12d889f99..9673de19fb0 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -14,7 +14,7 @@ class DCompletePoset(FinitePoset): r""" D-complete posets are a class of posets introduced by Proctor in [1]. - It includes ommon families such as shapes, shifted shapes, and forests. Proctor showed in [2] + It includes common families such as shapes, shifted shapes, and rooted forests. Proctor showed in [2] that d-complete posets have decompositions in ``irreducible`` posets, and showed in [3] that d-complete posets admit a hook-length formula (see [4]). A complete proof of the hook-length formula can be found in [5]. diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index 9c4ebbe7a97..387e8944c79 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -856,8 +856,8 @@ def __init__(self, poset, facade): LinearExtensionsOfPoset.__init__(self, poset=poset, facade=facade) def cardinality(self): - """ - Count the number of linear extensions + r""" + Count the number of linear extensions using a hook-length formula """ num_elmts = self._poset.cardinality() hooks = self._poset.get_hooks() From 34e8132064fa8bef0968e3ba0b8801acb51fbc57 Mon Sep 17 00:00:00 2001 From: Stefan Grosser Date: Sun, 21 Jun 2020 23:11:01 -0400 Subject: [PATCH 023/217] added forest class --- src/sage/combinat/posets/forest.py | 53 +++++++++++++++++++ src/sage/combinat/posets/linear_extensions.py | 15 ++++++ 2 files changed, 68 insertions(+) create mode 100644 src/sage/combinat/posets/forest.py diff --git a/src/sage/combinat/posets/forest.py b/src/sage/combinat/posets/forest.py new file mode 100644 index 00000000000..78b15cf88f0 --- /dev/null +++ b/src/sage/combinat/posets/forest.py @@ -0,0 +1,53 @@ +# **************************************************************************** +# Copyright (C) 2020 Stefan Grosser +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.combinat.posets.posets import Poset, FinitePoset +from sage.misc.lazy_attribute import lazy_attribute + +class ForestPoset(FinitePoset): + r""" + A forest poset is a poset where the underlying Hasse diagram and is + directed acyclic graph. + + """ + + def _repr_(self): + r""" + TESTS:: + + sage: from sage.combinat.posets.forest import ForestPoset + sage: P = ForestPoset(DiGraph({0: [2], 1: [2], 2: [3, 4], 3: [], 4: []})) + sage: P._repr_() + 'Finite forest poset containing 5 elements' + """ + s = "Finite forest poset containing %s elements" % self._hasse_diagram.order() + if self._with_linear_extension: + s += " with distinguished linear extension" + return s + + def __init__(self, hasse_diagram, elements, category, facade, key): + FinitePoset.__init__(self, hasse_diagram=hasse_diagram, elements=elements, category=category, facade=facade, key=key) + + + def linear_extensions(self, facade=False): + r""" + Returns the enumerated set of all the linear extensions of this forest poset + + INPUT: + + - ``facade`` -- a boolean (default: ``False``); + whether to return the linear extensions as plain lists + + EXAMPLES:: + + TESTS:: + """ + from .linear_extensions import LinearExtensionsOfForest + return LinearExtensionsOfForest(self, facade=facade) \ No newline at end of file diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index 387e8944c79..728536e2b42 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -863,4 +863,19 @@ def cardinality(self): hooks = self._poset.get_hooks() hook_product = prod(hooks.values()) return factorial(num_elmts) // hook_product + +class LinearExtensionsOfForest(LinearExtensionsOfPoset): + r""" + A subclass of ``LinearExtensionOfPoset`` where the poset + is a forest. + """ + + def __init__(self, poset, facade): + LinearExtensionsOfPoset.__init__(self, poset=poset, facade=facade) + + def cardinality(self): + r""" + Use Atkinson's algorithm to compute the number of linear extensions + """ + return sum(self.atkinson(self._elements[0])) From 966210e89bb94a31657e07b4d3dba188f519e2e4 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Mon, 22 Jun 2020 12:47:54 +0200 Subject: [PATCH 024/217] really test the correct double description --- src/sage/geometry/polyhedron/base.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 5fc88a2985d..80b79274cfd 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -4803,12 +4803,12 @@ def _test_dilation(self, tester=None, **options): return # Testing that the double description is set up correctly. - if self.backend() != 'field' and self.base_ring().is_exact(): + if self.base_ring().is_exact(): p = self.base_extend(self.base_ring(), backend='field') - tester.assertEqual(ZZ(2)*p, ZZ(2)*self) - tester.assertEqual(ZZ(1)/2*p, ZZ(1)/2*self) - tester.assertEqual(ZZ(-3)*p, ZZ(-3)*self) - tester.assertEqual((-ZZ(1)/2)*p, (-ZZ(1)/2)*self) + (ZZ(2)*p)._test_basic_properties(tester) + (ZZ(2)/2*p)._test_basic_properties(tester) + (ZZ(-3)*p)._test_basic_properties(tester) + (ZZ(-1)/2*p)._test_basic_properties(tester) else: tester.assertIsInstance(ZZ(1)/3*self, Polyhedron_base) From 75b97b49b62f50b9f59981504c8911f9a88dbc7a Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Mon, 22 Jun 2020 12:55:46 +0200 Subject: [PATCH 025/217] typo --- src/sage/geometry/polyhedron/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 80b79274cfd..194fd9f874b 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -4785,7 +4785,7 @@ def dilation(self, scalar): def _test_dilation(self, tester=None, **options): """ - Run tests on the method :meth:`.dilation` + Run tests on the method :meth:`.dilation`. TESTS:: From 068707835d7def1d492f44317030f2c1b5df71e4 Mon Sep 17 00:00:00 2001 From: Benjamin Hutz Date: Mon, 22 Jun 2020 13:56:15 -0500 Subject: [PATCH 026/217] 29777: doc fixes --- src/sage/rings/padics/generic_nodes.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/sage/rings/padics/generic_nodes.py b/src/sage/rings/padics/generic_nodes.py index afd39fdbb1e..7a6e40448cd 100644 --- a/src/sage/rings/padics/generic_nodes.py +++ b/src/sage/rings/padics/generic_nodes.py @@ -758,8 +758,8 @@ def _xgcd_univariate_polynomial(self, f, g): OUTPUT: - - A tuple (a, b, c) which satisfies a = b*f + c*g. There - is not guarentee that a, b, and c are minimal. + - A tuple (a, b, c) which satisfies `a = b*f + c*g`. There + is not guarentee that a, b, and c are minimal. EXAMPLES:: @@ -814,9 +814,7 @@ def _gcd_univariate_polynomial(self, f, g): - ``f``, ``g`` - the polynomials of which to take the gcd - OUTPUT: - - - A polynomial + OUTPUT: A polynomial EXAMPLES:: From f14366e396215de6d76b9986cb852d942f741f17 Mon Sep 17 00:00:00 2001 From: Alexander Galarraga Date: Wed, 24 Jun 2020 12:31:16 -0400 Subject: [PATCH 027/217] 29777: wrapped example lines --- src/sage/rings/padics/generic_nodes.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/padics/generic_nodes.py b/src/sage/rings/padics/generic_nodes.py index 7a6e40448cd..05b6a8db270 100644 --- a/src/sage/rings/padics/generic_nodes.py +++ b/src/sage/rings/padics/generic_nodes.py @@ -780,7 +780,11 @@ def _xgcd_univariate_polynomial(self, f, g): sage: f = 357555295953*x + 257392844 sage: g = 225227399*x - 511940255230575 sage: f.xgcd(f*g) - ((3^9 + O(3^29))*x + 2 + 2*3 + 3^2 + 2*3^5 + 3^6 + 3^7 + 3^8 + 3^10 + 3^11 + 2*3^13 + 3^14 + 3^16 + 2*3^19 + O(3^20), 0, 1 + 2*3^2 + 3^4 + 2*3^5 + 3^6 + 3^7 + 2*3^8 + 2*3^10 + 2*3^12 + 3^13 + 3^14 + 3^15 + 2*3^17 + 3^18 + O(3^20)) + ((3^9 + O(3^29))*x + 2 + 2*3 + 3^2 + 2*3^5 + 3^6 + 3^7 + + 3^8 + 3^10 + 3^11 + 2*3^13 + 3^14 + 3^16 + 2*3^19 + + O(3^20), 0, 1 + 2*3^2 + 3^4 + 2*3^5 + 3^6 + 3^7 + + 2*3^8 + 2*3^10 + 2*3^12 + 3^13 + 3^14 + 3^15 + 2*3^17 + + 3^18 + O(3^20)) We check low precision computations:: From 8c47b6ef7ce72dd43b6cba6a4d00ebddf48298d6 Mon Sep 17 00:00:00 2001 From: Alexander Galarraga Date: Fri, 26 Jun 2020 16:21:34 -0400 Subject: [PATCH 028/217] 29777: readded commit message --- src/sage/rings/padics/generic_nodes.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/sage/rings/padics/generic_nodes.py b/src/sage/rings/padics/generic_nodes.py index 05b6a8db270..23059cf3933 100644 --- a/src/sage/rings/padics/generic_nodes.py +++ b/src/sage/rings/padics/generic_nodes.py @@ -758,9 +758,16 @@ def _xgcd_univariate_polynomial(self, f, g): OUTPUT: - - A tuple (a, b, c) which satisfies `a = b*f + c*g`. There + - A tuple (a, b, c) which satisfies `a = b*f + c*g`. There is not guarentee that a, b, and c are minimal. + .. WARNING:: + + The computations are performed using the standard Euclidean + algorithm which might produce mathematically incorrect results in + some cases. See :trac:`13439`. + + EXAMPLES:: sage: R. = Zp(3,3)[] @@ -774,7 +781,7 @@ def _xgcd_univariate_polynomial(self, f, g): sage: f = 3*x + 7 sage: g = 5*x + 9 sage: f.xgcd(f*g) - ((3 + O(3^4))*x + 1 + 2*3 + O(3^3), 0, 1 + O(3^3)) + ((3 + O(3^4))*x + 1 + 2*3 + O(3^3), 1 + O(3^3), 0) sage: R. = Zp(3)[] sage: f = 357555295953*x + 257392844 @@ -782,9 +789,9 @@ def _xgcd_univariate_polynomial(self, f, g): sage: f.xgcd(f*g) ((3^9 + O(3^29))*x + 2 + 2*3 + 3^2 + 2*3^5 + 3^6 + 3^7 + 3^8 + 3^10 + 3^11 + 2*3^13 + 3^14 + 3^16 + 2*3^19 + - O(3^20), 0, 1 + 2*3^2 + 3^4 + 2*3^5 + 3^6 + 3^7 + + O(3^20), 1 + 2*3^2 + 3^4 + 2*3^5 + 3^6 + 3^7 + 2*3^8 + 2*3^10 + 2*3^12 + 3^13 + 3^14 + 3^15 + 2*3^17 - + 3^18 + O(3^20)) + + 3^18 + O(3^20), 0) We check low precision computations:: @@ -794,8 +801,10 @@ def _xgcd_univariate_polynomial(self, f, g): sage: h.xgcd(h*i) ((3 + O(3^2))*x + 1 + O(3), 1 + O(3), 0) """ + from sage.misc.stopgap import stopgap + stopgap("Extended gcd computations over p-adic fields are performed using the standard Euclidean algorithm which might produce mathematically incorrect results in some cases.", 13439) + base_ring = f.base_ring() - #low precision computation done over a ring fails, see trac 29777 fracfield = base_ring.fraction_field() f_field = f.change_ring(fracfield) g_field = g.change_ring(fracfield) From cc71813942882e29fafe72246de35ff54128fe4c Mon Sep 17 00:00:00 2001 From: Stefan Grosser Date: Sun, 28 Jun 2020 20:23:15 -0400 Subject: [PATCH 029/217] Moved references. Added diamonds, common_upper_covers, order_ideal_cardinality to FinitePoset and HasseDiagram classes. --- src/doc/en/reference/references/index.rst | 16 ++ src/sage/combinat/posets/d_complete.py | 159 +++++++----------- src/sage/combinat/posets/hasse_diagram.py | 82 +++++++++ src/sage/combinat/posets/linear_extensions.py | 4 +- src/sage/combinat/posets/posets.py | 51 +++++- 5 files changed, 210 insertions(+), 102 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 3cd8f30045c..a1896ddd344 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -2632,6 +2632,9 @@ REFERENCES: Algebras, J. Ramanujan Math. Soc., 25 (2010), 113--145. :arxiv:`0309168v3` :mathscinet:`MR2642451` +.. [HLF] :wikipedia:`Hook_length_formula`, accessed 27th + June 2020. + .. [HL1999] \L. Heath and N. Loehr (1999). New algorithms for generating Conway polynomials over finite fields. Proceedings of the tenth annual ACM-SIAM symposium on @@ -3388,6 +3391,10 @@ REFERENCES: CMS Conf. Proc., **24**, Amer. Math. Soc., Providence, RI, 1998. :mathscinet:`MR1648638` +.. [KY2019] Kim, Jang Soo, and Meesue Yoo. + "Hook length property of d-complete posets via q-integrals." + Journal of Combinatorial Theory, Series A 162 (2019): 167-221. + .. [KZ2003] \M. Kontsevich, A. Zorich "Connected components of the moduli space of Abelian differentials with prescripebd singularities" Invent. math. 153, 631-678 (2003) @@ -4341,6 +4348,15 @@ REFERENCES: Providence, RI, 2013. :arxiv:`1112.6163` +.. [Proc1999] R. A. Proctor. Minuscule elements of Weyl groups, the numbers game, + and d-complete posets. J. Algebra, 213(1):272–303, 1999. + +.. [PDynk1999] R. A. Proctor. Dynkin diagram classification of λ-minuscule Bruhat lattices + and of d-complete posets. J. Algebraic Combin., 9(1):61–94, 1999. + +.. [Proc2014] R. A. Proctor. d-complete posets generalize Young diagrams for the hook product + formula: Partial Presentation of Proof. RIMS Kˆokyˆuroku, 1913:120–140, 2014. + .. [PR2003] Perrin-Riou, *Arithmétique des courbes elliptiques à réduction supersingulière en `p`*, Experiment. Math. 12 (2003), no. 2, 155-186. diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index 9673de19fb0..fa44f0db928 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -13,25 +13,31 @@ class DCompletePoset(FinitePoset): r""" - D-complete posets are a class of posets introduced by Proctor in [1]. - It includes common families such as shapes, shifted shapes, and rooted forests. Proctor showed in [2] - that d-complete posets have decompositions in ``irreducible`` posets, and showed in [3] that - d-complete posets admit a hook-length formula (see [4]). A complete proof of the hook-length formula - can be found in [5]. + D-complete posets are a class of posets introduced by Proctor in [Proc1999]. + It includes common families such as shapes, shifted shapes, and rooted forests. Proctor showed in [PDynk1999] + that d-complete posets have decompositions in ``irreducible`` posets, and showed in [Proc2014] that + d-complete posets admit a hook-length formula (see [HLF]). A complete proof of the hook-length formula + can be found in [KY2019]. + + EXAMPLES:: + sage: from sage.combinat.posets.poset_examples import Posets + sage: P = Posets.DoubleTailedDiamond(2) + sage: type(P) + - REFERENCES: + The additional internal data structure consists of: - .. [1] R. A. Proctor. Minuscule elements of Weyl groups, the numbers game, and d-complete posets. J. Algebra, - 213(1):272–303, 1999. - .. [2] R. A. Proctor. Dynkin diagram classification of λ-minuscule Bruhat lattices and of d-complete posets. J. - Algebraic Combin., 9(1):61–94, 1999. - .. [3] R. A. Proctor. d-complete posets generalize Young diagrams for the hook product formula: Partial Presentation - of Proof. RIMS Kˆokyˆuroku, 1913:120–140, 2014. - .. [4] https://en.wikipedia.org/wiki/Hook_length_formula + - the hook lengths of the elements of the poset - .. [5] Kim, Jang Soo, and Meesue Yoo. "Hook length property of d-complete posets via q-integrals." - Journal of Combinatorial Theory, Series A 162 (2019): 167-221. + sage: P._hooks + {1: 1, 2: 2, 3: 3, 4: 3, 5: 4, 6: 5} + + TESTS:: + + sage: TestSuite(P).run() + + See also the other tests in the class documentation. """ def _repr_(self): @@ -53,7 +59,7 @@ def _repr_(self): def _hooks(self): r""" The hook lengths of the elements of the d-complete poset. For the definition - of hook lengths for d-complete posets, see [1]. + of hook lengths for d-complete posets, see [KY2019]. TESTS:: @@ -65,107 +71,71 @@ def _hooks(self): sage: P = DCompletePoset(Posets.YoungDiagramPoset(Partition([3,2,1]))._hasse_diagram.reverse()) sage: P._hooks {0: 5, 1: 3, 2: 1, 3: 3, 4: 1, 5: 1} - - REFERENCES: - - .. [1] Kim, Jang Soo, and Meesue Yoo. "Hook length property of d-complete posets via q-integrals." - Journal of Combinatorial Theory, Series A 162 (2019): 167-221. """ + from collections import deque hooks = {} min_diamond = {} # Maps max of double-tailed diamond to min of double-tailed diamond max_diamond = {} # Maps min of double-tailed diamond to max of double-tailed diamond - diamonds = [] # Tuples of four elements that are diamonds + diamonds = self.diamonds() # Tuples of four elements that are diamonds diamond_index = {} # Map max elmt of double tailed diamond to index of diamond - # Find all diamonds - for e in self._elements: - covers = self.upper_covers(e) - for p1, p2 in [(i,j) for i in covers for j in covers if i < j]: - top = self.common_upper_covers([p1, p2]) - if len(top) != 1: - continue - else: - diamonds.append((e, p1, p2, top[0])) - min_diamond[top[0]] = e - max_diamond[e] = top[0] - diamond_index[top[0]] = len(diamonds) - 1 - break # Find all the double-tailed diamonds and map the mins and maxes. for index, d in enumerate(diamonds): - min_elmt = d[0] - max_elmt = d[3] + min_diamond[d[3]] = d[0] + max_diamond[d[0]] = d[3] + diamond_index[d[3]] = index - while True: - potential_min = self.lower_covers(min_elmt) - - potential_max = self.upper_covers(max_elmt) - - # Check if any of these make a longer double tailed diamond - found_diamond = False - for (mn, mx) in [(i,j) for i in potential_min for j in potential_max]: - if len(self.lower_covers(mx)) != 1: - continue - if len(self._hasse_diagram.all_paths(self._element_to_vertex(mn), self._element_to_vertex(mx))) == 2: - # Success - min_elmt = mn - max_elmt = mx - - min_diamond[mx] = mn - max_diamond[mn] = mx - diamond_index[mx] = index - found_diamond = True - break - if not found_diamond: - break + min_elmt = d[0] + max_elmt = d[3] + + while True: + potential_min = self.lower_covers(min_elmt) + + potential_max = self.upper_covers(max_elmt) + + # Check if any of these make a longer double tailed diamond + found_diamond = False + for (mn, mx) in [(i,j) for i in potential_min for j in potential_max]: + if len(self.lower_covers(mx)) != 1: + continue + if len(self._hasse_diagram.all_paths(self._element_to_vertex(mn), self._element_to_vertex(mx))) == 2: + # Success + min_elmt = mn + max_elmt = mx + + min_diamond[mx] = mn + max_diamond[mn] = mx + diamond_index[mx] = index + found_diamond = True + break + if not found_diamond: + break # Compute the hooks - queue = list(self.minimal_elements()) + queue = deque(self.minimal_elements()) enqueued = set() while queue: - elmt = queue.pop(0) + elmt = queue.popleft() if elmt not in diamond_index: - hooks[elmt] = len(self.order_ideal([elmt])) + hooks[elmt] = self.order_ideal_cardinality([elmt]) else: - diamond = diamonds[diamond_index[elmt]] - side1 = diamond[1] - side2 = diamond[2] - hooks[elmt] = hooks[side1] + hooks[side2] - hooks[min_diamond[elmt]] + diamond = diamonds[diamond_index[elmt]] + side1 = diamond[1] + side2 = diamond[2] + hooks[elmt] = hooks[side1] + hooks[side2] - hooks[min_diamond[elmt]] enqueued.add(elmt) for c in self.upper_covers(elmt): - if c not in enqueued: - queue.append(c) - enqueued.add(c) + if c not in enqueued: + queue.append(c) + enqueued.add(c) return hooks - def __init__(self, hasse_diagram, elements, category, facade, key): - r""" - EXAMPLES:: - sage: from sage.combinat.posets.poset_examples import Posets - sage: P = Posets.DoubleTailedDiamond(2) - sage: type(P) - - - The additional internal data structure consists of: - - - the hook lengths of the elements of the poset - - sage: P._hooks - {1: 1, 2: 2, 3: 3, 4: 3, 5: 4, 6: 5} - - TESTS:: - - sage: TestSuite(P).run() - - See also the other tests in the class documentation. - """ - FinitePoset.__init__(self, hasse_diagram=hasse_diagram, elements=elements, category=category, facade=facade, key=key) - def get_hook(self, elmt): r""" Get the hook length of a specific element. @@ -206,7 +176,7 @@ def is_d_complete(cls, poset): def linear_extensions(self, facade=False): r""" - Returns the enumerated set of all the linear extensions of this poset with hook lengths + Return the enumerated set of all the linear extensions of this poset with hook lengths. INPUT: @@ -250,4 +220,5 @@ def linear_extensions(self, facade=False): [5, 4, 2, 3, 1, 0]] """ from .linear_extensions import LinearExtensionsOfPosetWithHooks - return LinearExtensionsOfPosetWithHooks(self, facade=facade) \ No newline at end of file + return LinearExtensionsOfPosetWithHooks(self, facade=facade) + \ No newline at end of file diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index 7d17bf29a4b..58bb2c080dc 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -1130,6 +1130,33 @@ def order_ideal(self, elements): return sorted(list( self.depth_first_search(elements, neighbors=self.neighbors_in))) + def order_ideal_cardinality(self, elements): + r""" + Return the cardinality of the order ideal generated by a list of elements. + + `I` is an order ideal if, for any `x` in `I` and `y` such that + `y \le x`, then `y` is in `I`. + + EXAMPLES:: + + sage: H = posets.BooleanLattice(4)._hasse_diagram + sage: H.order_ideal_cardinality([7,10]) + 10 + """ + from collections import deque + seen = set() + q = deque(elements) + size = 0 + while q: + v = q.popleft() + if v in seen: + continue + size += 1 + seen.add(v) + q.extend(self.neighbors_in(v)) + + return size + def principal_order_ideal(self, i): """ Return the order ideal generated by `i`. @@ -2238,6 +2265,61 @@ def chains(self, element_class=list, exclude=None): self.are_comparable, element_class=element_class) + def diamonds(self): + r""" + Return a list of all diamonds in the Hasse Diagram. + For a diamond + z + / \ + x y + \ / + w + the format would be (w, x, y, z). + + EXAMPLES:: + + sage: from sage.combinat.posets.hasse_diagram import HasseDiagram + sage: H = HasseDiagram({0: [1,2], 1: [3], 2: [3], 3: []}) + sage: H.diamonds() + [(0, 1, 2, 3)] + + TESTS:: + + sage: from sage.combinat.posets.hasse_diagram import HasseDiagram + sage: P = posets.YoungDiagramPoset(Partition([3, 2, 2])) + sage: H = P._hasse_diagram + sage: H.diamonds() + [(0, 1, 3, 4), (3, 4, 5, 6)] + """ + diamonds = [] + for w in self.vertices(): + covers = self.neighbors_out(w) + for i, x in enumerate(covers): + for y in covers[i+1:]: + zs = self.common_upper_covers([x, y]) + for z in zs: + diamonds.append((w, x, y, z)) + return diamonds + + + def common_upper_covers(self, vertices): + r""" + Return the list of all common upper covers of a list of vertices + + EXAMPLES:: + + sage: from sage.combinat.posets.hasse_diagram import HasseDiagram + sage: H = HasseDiagram({0: [1,2], 1: [3], 2: [3], 3: []}) + sage: H.common_upper_covers([1, 2]) + [3] + """ + covers = set(self.neighbors_out(vertices.pop())) + + for v in vertices: + covers = covers.intersection(self.neighbors_out(v)) + + return list(covers) + def _trivial_nonregular_congruence(self): """ Return a pair of elements giving "trivial" non-regular congruence. diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index 728536e2b42..b14590ccf86 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -35,8 +35,8 @@ from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass from sage.graphs.dot2tex_utils import have_dot2tex from sage.structure.list_clone import ClonableArray -from sage.misc.all import prod -from sage.arith.all import factorial +from sage.misc.misc_c import prod +from sage.functions.other import factorial class LinearExtensionOfPoset(ClonableArray, diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 6dfc0f37fe6..bc0fa590155 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -2230,6 +2230,33 @@ def relations(self): """ return list(self.relations_iterator()) + def diamonds(self): + r""" + Return a list of all diamonds in the poset. + For a diamond + z + / \ + x y + \ / + w + the format would be (w, x, y, z). + + EXAMPLES:: + + sage: P = Poset({0: [1,2], 1: [3], 2: [3], 3: []}) + sage: P.diamonds() + [(0, 1, 2, 3)] + + TESTS:: + + sage: P = posets.YoungDiagramPoset(Partition([3, 2, 2])) + sage: P.diamonds() + [((0, 0), (0, 1), (1, 0), (1, 1)), ((1, 0), (1, 1), (2, 0), (2, 1))] + """ + + diamonds = self._hasse_diagram.diamonds() + return [tuple(map(self._vertex_to_element, d)) for d in diamonds] + def common_upper_covers(self, elmts): r""" Return the list of all common upper covers of a list of elemements @@ -2240,12 +2267,8 @@ def common_upper_covers(self, elmts): sage: P.common_upper_covers([1, 2]) [3] """ - covers = set(self.upper_covers(elmts.pop())) - - for e in elmts: - covers = covers.intersection(self.upper_covers(e)) - - return list(covers) + vertices = list(map(self._element_to_vertex, elmts)) + return list(map(self._vertex_to_element, self._hasse_diagram.common_upper_covers(vertices))) def intervals_poset(self): r""" @@ -6275,6 +6298,22 @@ def order_ideal(self, elements): vertices = [self._element_to_vertex(_) for _ in elements] oi = self._hasse_diagram.order_ideal(vertices) return [self._vertex_to_element(_) for _ in oi] + + def order_ideal_cardinality(self, elements): + r""" + Return the cardinality of the order ideal generated by a list of elements. + + `I` is an order ideal if, for any `x` in `I` and `y` such that + `y \le x`, then `y` is in `I`. + + EXAMPLES:: + + sage: P = posets.BooleanLattice(4) + sage: P.order_ideal_cardinality([7,10]) + 10 + """ + vertices = list(map(self._element_to_vertex, elements)) + return self._hasse_diagram.order_ideal_cardinality(vertices) def order_ideal_plot(self, elements): r""" From 2d53b3edca6ef352aeaf12b4ff1221ac6b18f534 Mon Sep 17 00:00:00 2001 From: vipul79321 Date: Wed, 1 Jul 2020 18:27:23 +0530 Subject: [PATCH 030/217] weighted 2Dsweep added --- src/sage/graphs/base/boost_graph.pyx | 265 ++++++++++++++++++++++++++- 1 file changed, 264 insertions(+), 1 deletion(-) diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx index 1e99247025e..c172bb84f6f 100644 --- a/src/sage/graphs/base/boost_graph.pyx +++ b/src/sage/graphs/base/boost_graph.pyx @@ -1626,7 +1626,7 @@ cpdef radius_DHV(g, weight_function=None, check_weight=True): weight 1. - ``check_weight`` -- boolean (default: ``True``); if ``True``, we check - that the ``weight_function`` outputs a number for each edge + that the ``weight_function`` outputs a number for each edge. EXAMPLES:: @@ -1742,3 +1742,266 @@ cpdef radius_DHV(g, weight_function=None, check_weight=True): return +Infinity return UB + +cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, + BoostVecWeightedDiGraphU rev_g_boost, + v_index source, int n, + str algorithm) : + r""" + Returns lower bound on the diamter of weighted digraph using the weighted + version of the algorithm proposed in [Broder2000]_. + + In first part, it computes forward distances from `source` and selects a + vertex `vf` at a maximum forward distance from `source` and then it + calculates backward eccentricity from `vf`. + + In second part, it computes backward distances from `source` and selects a + vertex `vb` at a maximum backward distance from `source` and then it + calculates forward eccentricity from `vb`. + + It then calculates lower bound LB of diameter as the maximum of + backward eccentricity of `vf` and forward eccentricity of `vb` and `s` as + respective source vertex. + + This method returns (`LB`, `s`, `m`, `d`), where `LB` is best found lower + bound on diameter, `s` is vertex whose forward / backward eccentricity is + `LB`, `d` is vertex at a distance `LB` from / to `s` , `m` is vertex at + distance `LB/2` from / to both `s` and `d`. + + INPUT: + + - ``g_boost`` -- a boost weighted digraph. + + - ``rev_g_boost`` -- a copy of ``g_boost`` with edges reversed. + + - ``source`` -- starting node for forward and backward distance computation. + + - ``n`` -- number of vertices in g_boost. + + - ``algorithm`` -- string; algorithm for computing single source shortest + distances. If ``g_boost`` contains negative edge weights then it will be + ``Bellman-Ford``, otherwise it will be ``Dijkstra_Boost``. + """ + import sys + # These variables are automatically deleted when the function terminates. + cdef v_index source_1, source_2, m, s, d, antipode_1, antipode_2, v + cdef double LB_1 = 0, LB_2 = 0, LB, LB_m + cdef result_distances result_1, result_2 + + source_1 = source_2 = source + + # Algorithm + + # 1). Compute Forward distances from source_1 to all vertices and obtain its + # Forward eccentricity and obtain its antipode, that is vertex at maximum + # forward distance. + if algorithm == 'Bellman-Ford': + sig_on() + result_1 = g_boost.bellman_ford_shortest_paths(source_1) + sig_off() + else: + sig_on() + result_1 = g_boost.dijkstra_shortest_paths(source_1) + sig_off() + if not result_1.distances.size(): + raise ValueError("the graph contains a negative cycle") + + LB_1 = 0 + for v in range(n): + if result_1.distances[v] > LB_1: + LB_1 = result_1.distances[v] + antipode_1 = v + + if LB_1 == sys.float_info.max: + return (LB_1, 0, 0, 0) + + # 2). Compute Backward distances from source_2 to all vertices and obtain + # its Backward eccentricity and obtain its antipode, that is vertex at + # maximum backward distance. + if algorithm == 'Bellman-Ford': + sig_on() + result_2 = rev_g_boost.bellman_ford_shortest_paths(source_2) + sig_off() + else: + sig_on() + result_2 = rev_g_boost.dijkstra_shortest_paths(source_2) + sig_off() + if not result_2.distances.size(): + raise ValueError("the graph contains a negative cycle") + + LB_2 = 0 + for v in range(n): + if result_2.distances[v] > LB_2: + LB_2 = result_2.distances[v] + antipode_2 = v + + if LB_2 == sys.float_info.max: + return (LB_2, 0, 0, 0) + + # Now use antipode_1, antipode_2 as source_1, source_2 respectively. + source_1 = antipode_1 + source_2 = antipode_2 + + # 3). Compute Backward distances from source_1 to all vertices and obtain + # its Backward eccentricity and obtain its antipode, that is vertex at + # maximum backward distance. LB_1 will be Backward eccentricity of source_1. + if algorithm == 'Bellman-Ford': + sig_on() + result_1 = rev_g_boost.bellman_ford_shortest_paths(source_1) + sig_off() + else: + sig_on() + result_1 = rev_g_boost.dijkstra_shortest_paths(source_1) + sig_off() + if not result_1.distances.size(): + raise ValueError("the graph contains a negative cycle") + + LB_1 = 0 + for v in range(n): + if result_1.distances[v] > LB_1: + LB_1 = result_1.distances[v] + antipode_1 = v + + # 4). Compute Forward distances from source_2 to all vertices and obtain its + # Forward eccentricity and obtain its antipode, that is vertex at maximum + # forward distance. LB_2 will be Forward eccentricity of source_2. + if algorithm == 'Bellman-Ford': + sig_on() + result_2 = g_boost.bellman_ford_shortest_paths(source_2) + sig_off() + else: + sig_on() + result_2 = g_boost.dijkstra_shortest_paths(source_2) + sig_off() + if not result_2.distances.size(): + raise ValueError("the graph contains a negative cycle") + + LB_2 = 0 + for v in range(n): + if result_2.distances[v] > LB_2: + LB_2 = result_2.distances[v] + antipode_2 = v + + # We will select best found lower bound as LB and s, d as corresponding + # source and antipode respectively. And m as vertex at a distance LB/2 + # from/to both s and d. + if LB_1 < LB_2: + LB = LB_2 + s = source_2 + d = antipode_2 + LB_m = LB_2 / 2 + m = d + while result_2.distances[m] > LB_m: + m = result_2.predecessors[m] + else: + LB = LB_1 + s = source_1 + d = antipode_1 + LB_m = LB_1 / 2 + m = d + while result_1.distances[m] > LB_m: + m = result_1.predecessors[m] + + return (LB, s, m, d) + +cpdef diameter(G, algorithm=None, source=None, + weight_function=None, check_weight=True): + r""" + Return the diameter of `G`. + + This method returns Infinity if the digraph is not strongly connected. It + can also quickly return a lower bound on the diameter using the ``2Dsweep`` + scheme. + + INPUT: + + - ``G`` -- the input sage digraph. + + - ``algorithm`` -- string (default: ``None``); specifies the algorithm to + use among: + + - ``'2Dsweep'`` -- Computes lower bound on the diameter of an weighted + directed graph using the weighted version of the algorithm proposed in + [Broder2000]_. See the code's documentation for more details. + + - ``'DiFUB'`` -- Computes the diameter of an weighted directed graph + using the weighted version of the algorithm proposed in [CGLM2012]_. + See the code's documentation for more details. + + - ``source`` -- (default: ``None``) vertex from which to start the + computation. If ``source==None``, an arbitrary vertex of the graph is + chosen. Raise an error if the initial vertex is not in `G`. + + - ``weight_function`` -- function (default: ``None``); a function that + associates a weight to each edge. If ``None`` (default), the weights of + ``G`` are used, if ``G.weighted()==True``, otherwise all edges have + weight 1. + + - ``check_weight`` -- boolean (default: ``True``); if ``True``, we check + that the ``weight_function`` outputs a number for each edge. + """ + import sys + + cdef int n = G.order() + + if n <= 1: + return 0 + + if weight_function and check_weight: + G._check_weight_function(weight_function) + + # Algorithm for single source shortest distance computations. + cdef str algo = 'Dijkstra_Boost' + + # If digraph contains negative edge weight then + # algo is set to `Bellman-Ford` + if weight_function is not None: + for e in G.edge_iterator(): + if float(weight_function(e)) < 0: + algo = 'Bellman-Ford' + break + elif G.weighted(): + for _,_,w in G.edge_iterator(): + if w and float(w) < 0: + algo = 'Bellman-Ford' + break + + if algorithm is None: # default algorithm for diameter computation + algorithm = 'DiFUB' + + if not algorithm in ['2Dsweep', 'DiFUB']: + raise ValueError("unknown algorithm for computing the diameter of directed graph") + + if source is None: + source = next(G.vertex_iterator()) + elif not G.has_vertex(source): + raise ValueError("the specified source is not a vertex of the input Graph") + + # These variables are automatically deleted when the function terminates. + cdef dict v_to_int = {vv: vi for vi, vv in enumerate(G)} + + # boost copy of G + cdef BoostVecWeightedDiGraphU g_boost + # boost copy of G with edges reversed + cdef BoostVecWeightedDiGraphU rev_g_boost + + # Initializing + boost_weighted_graph_from_sage_graph(&g_boost, G, v_to_int, weight_function) + boost_weighted_graph_from_sage_graph(&rev_g_boost, G, v_to_int, weight_function, reverse=True) + + cdef v_index isource = 0 if source is None else v_to_int[source] + cdef double LB + + if algorithm == '2Dsweep': + LB = diameter_lower_bound_2Dsweep(g_boost, rev_g_boost, + isource, n, algo)[0] + + #else: + # LB = diameter_DiFUB(g_boost, rev_g_boost, + # isource, n, algo) + + if LB == sys.float_info.max: + from sage.rings.infinity import Infinity + return +Infinity + else: + return LB From 867a0a8dd653dc70b0280ec1f8532a781ece1a95 Mon Sep 17 00:00:00 2001 From: vipul79321 Date: Thu, 2 Jul 2020 19:12:23 +0530 Subject: [PATCH 031/217] weighted difub added and exposed in digraph.py --- src/sage/graphs/base/boost_graph.pyx | 211 +++++++++++++++++++++++- src/sage/graphs/digraph.py | 78 ++++++--- src/sage/graphs/distances_all_pairs.pyx | 2 +- 3 files changed, 259 insertions(+), 32 deletions(-) diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx index c172bb84f6f..93ab5dae3bf 100644 --- a/src/sage/graphs/base/boost_graph.pyx +++ b/src/sage/graphs/base/boost_graph.pyx @@ -1745,8 +1745,8 @@ cpdef radius_DHV(g, weight_function=None, check_weight=True): cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, BoostVecWeightedDiGraphU rev_g_boost, - v_index source, int n, - str algorithm) : + v_index source, + str algorithm): r""" Returns lower bound on the diamter of weighted digraph using the weighted version of the algorithm proposed in [Broder2000]_. @@ -1776,18 +1776,16 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, - ``source`` -- starting node for forward and backward distance computation. - - ``n`` -- number of vertices in g_boost. - - ``algorithm`` -- string; algorithm for computing single source shortest distances. If ``g_boost`` contains negative edge weights then it will be ``Bellman-Ford``, otherwise it will be ``Dijkstra_Boost``. """ import sys # These variables are automatically deleted when the function terminates. + cdef int n = g_boost.num_verts() cdef v_index source_1, source_2, m, s, d, antipode_1, antipode_2, v cdef double LB_1 = 0, LB_2 = 0, LB, LB_m cdef result_distances result_1, result_2 - source_1 = source_2 = source # Algorithm @@ -1904,6 +1902,179 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, return (LB, s, m, d) +cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, + BoostVecWeightedDiGraphU rev_g_boost, + v_index source, + str algorithm): + r""" + Return the diameter of a weighted directed graph. + + The ``DiFUB`` (Directed iterative Fringe Upper Bound) algorithm calculates + the exact value of the diameter of an weighted directed graph [CGLM2012]_. + + This algorithm starts from a vertex found through a 2Dsweep call (a directed + version of the 2sweep method). The worst case time complexity of the DiFUB + algorithm is `O(nm)`, but it can be very fast in practice. See the code's + documentation and [CGLM2012]_ for more details. + + If the digraph is not strongly connected, the returned value is infinity. + + INPUT: + + - ``g_boost`` -- a boost weighted digraph. + + - ``rev_g_boost`` -- a copy of ``g_boost`` with edges reversed. + + - ``source`` -- starting node for forward and backward distance computation. + + - ``algorithm`` -- string; algorithm for computing single source shortest + distances. If ``g_boost`` contains negative edge weights then it will be + ``Bellman-Ford``, otherwise it will be ``Dijkstra_Boost``. + """ + import sys + # These variables are automatically deleted when the function terminates. + cdef int n = g_boost.num_verts() + cdef double LB, LB_1, LB_2, UB + cdef v_index s, m, d, v, tmp + cdef size_t i + cdef vector[double] distances + cdef vector[pair[double, v_index]] order_1, order_2 + + # We select a vertex with low eccentricity using 2Dsweep + LB, s, m, d = diameter_lower_bound_2Dsweep(g_boost, rev_g_boost, + source, algorithm) + + # If the lower bound is a very large number, it means that the digraph is + # not strongly connected and so the diameter is infinite. + if LB == sys.float_info.max: + return LB + + # Compute Forward distances from `m`. + if algorithm == 'Bellman-Ford': + sig_on() + distances = g_boost.bellman_ford_shortest_paths(m).distances + sig_off() + else: + sig_on() + distances = g_boost.dijkstra_shortest_paths(m).distances + sig_off() + if not distances.size(): + raise ValueError("the graph contains a negative cycle") + + # Obtain Forward eccentricity of `m` and store pair of + # forward distances, vertex in order_1 + LB_1 = 0 + for v in range(n): + LB_1 = max(LB_1, distances[v]) + order_1.push_back(pair[double, v_index](distances[v], v)) + + # Compute Backward distances from `m`. + if algorithm == 'Bellman-Ford': + sig_on() + distances = rev_g_boost.bellman_ford_shortest_paths(m).distances + sig_off() + else: + sig_on() + distances = rev_g_boost.dijkstra_shortest_paths(m).distances + sig_off() + if not distances.size(): + raise ValueError("the graph contains a negative cycle") + + # Obtain Backward eccentricity of `m` and store pair of + # backward distances, vertex in order_2. + LB_2 = 0 + for v in range(n): + LB_2 = max(LB_2, distances[v]) + order_2.push_back(pair[double, v_index](distances[v], v)) + + # Now sort order_1 / order_2 in decreasing order of forward / backward + # distances respectively. + # Now order_1 and order_2 will contain order of vertices in which + # further distance computations will be done. + sorted(order_1, reverse=True) + sorted(order_2, reverse=True) + + LB = max(LB, LB_1, LB_2) + if LB == sys.float_info.max: + return LB + + # The algorithm: + # + # The diameter of the digraph is equal to the maximum forward or backward + # eccentricity of a vertex. Let `\[db_1, db_2,..., db_i\]` represents the + # different backward distances from `m` containing at least one vertex at + # that distance. Similarly, let `\[df_1, df_2,..., df_i\]` represents the + # different forward distances from `m` containing at least one vertex at + # that distance. + # + # The algorithm is based on the following two observations : + # + # 1). All the nodes `x` at a backward distance greater than `\[db_i\]` from + # `m` having forward eccentricity greater than `\[2db_{i-1}\]` have a + # corresponding node `y` whose backward eccentricity is greater than or + # equal to the forward eccentricity of `x`, at a forward distance greater + # than `\[db_i\]` from `m`. + # + # 2). All the nodes `x` at a forward distance greater than `\[df_i\]` from + # `m` having backward eccentricity greater than `\[2df_{i-1}\]` have a + # corresponding node `y` whose forward eccentricity is greater than or equal + # to the backward eccentricity of `x`, at a backward distance greater than + # `\[df_i\]` from `m`. + # + # Therefore, we calculate backward / forward eccentricity of all nodes at + # forward / backward distance `\[df_i / db_i\]` from `m` respectively. And + # their maximum is `LB`. If `LB` is greater than `2(next maximum forward / + # backward distance)` then we are done, else we proceed further. + + i = 0 + UB = max(2 * order_1[i].first, 2 * order_2[i].first) + + while LB < UB: + v = order_1[i].second + if algorithm == 'Bellman-Ford': + sig_on() + distances = rev_g_boost.bellman_ford_shortest_paths(v).distances + sig_off() + else: + sig_on() + distances = rev_g_boost.dijkstra_shortest_paths(v).distances + sig_off() + if not distances.size(): + raise ValueError("the graph contains a negative cycle") + + LB_1 = 0 + for tmp in range(n): + LB_1 = max(LB_1, distances[tmp]) + + v = order_2[i].second + if algorithm == 'Bellman-Ford': + sig_on() + distances = g_boost.bellman_ford_shortest_paths(v).distances + sig_off() + else: + sig_on() + distances = g_boost.dijkstra_shortest_paths(v).distances + sig_off() + if not distances.size(): + raise ValueError("the graph contains a negative cycle") + + LB_2 = 0 + for tmp in range(n): + LB_2 = max(LB_2, distances[tmp]) + + # Update the lower bound + LB = max(LB, LB_1, LB_2) + i += 1 + + if LB == sys.float_info.max or i == n: + break + + # next maximum forward / backward distance + UB = max( 2 * order_1[i].first, 2 * order_2[i].first) + + # Finally return the computed diameter + return LB + cpdef diameter(G, algorithm=None, source=None, weight_function=None, check_weight=True): r""" @@ -1939,9 +2110,31 @@ cpdef diameter(G, algorithm=None, source=None, - ``check_weight`` -- boolean (default: ``True``); if ``True``, we check that the ``weight_function`` outputs a number for each edge. + + EXAMPLES:: + + sage: from sage.graphs.base.boost_graph import diameter + sage: G = DiGraph([(0,1,2), (1,0,-1)]) + sage: diameter(G, algorithm='DiFUB') + 1.0 + sage: diameter(G, algorithm='DiFUB', weight_function=lambda e:e[2]) + 2.0 + + TESTS:: + + Diameter of weakly connected digraph is Infinity + + sage: G = DiGraph(2) + sage: diameter(G, algorithm='DiFUB') + +Infinity + sage: diameter(G, algorithm='2Dsweep') + +Infinity """ import sys + if not G.is_directed(): + raise TypeError("this method works only for digraphs") + cdef int n = G.order() if n <= 1: @@ -1994,11 +2187,11 @@ cpdef diameter(G, algorithm=None, source=None, if algorithm == '2Dsweep': LB = diameter_lower_bound_2Dsweep(g_boost, rev_g_boost, - isource, n, algo)[0] + isource, algo)[0] - #else: - # LB = diameter_DiFUB(g_boost, rev_g_boost, - # isource, n, algo) + else: + LB = diameter_DiFUB(g_boost, rev_g_boost, + isource, algo) if LB == sys.float_info.max: from sage.rings.infinity import Infinity diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index 40f922df893..2b2eae9337f 100644 --- a/src/sage/graphs/digraph.py +++ b/src/sage/graphs/digraph.py @@ -2126,12 +2126,12 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, - ``'Floyd-Warshall-Cython'`` - a Cython implementation of the Floyd-Warshall algorithm. Works only if ``by_weight==False`` and - ``v is None``. + ``v is None`` or ``v`` should contain all vertices of ``self``. - ``'Floyd-Warshall-Python'`` - a Python implementation of the Floyd-Warshall algorithm. Works also with weighted graphs, even with negative weights (but no negative cycle is allowed). However, ``v`` - must be ``None``. + must be ``None`` or ``v`` should contain all vertices of ``self``. - ``'Dijkstra_NetworkX'`` - the Dijkstra algorithm, implemented in NetworkX. It works with weighted graphs, but no negative weight is @@ -2142,7 +2142,8 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, - ``'Johnson_Boost'`` - the Johnson algorithm, implemented in Boost (works also with negative weights, if there is no negative - cycle). + cycle). Works only if ``v is None`` or ``v`` should contain all + vertices of ``self``. - ``'From_Dictionary'`` - uses the (already computed) distances, that are provided by input variable ``dist_dict``. @@ -2242,7 +2243,7 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, by_weight = True elif by_weight: def weight_function(e): - return e[2] + return 1 if e[2] is None else e[2] if algorithm is None: if dist_dict is not None: @@ -2261,7 +2262,13 @@ def weight_function(e): if algorithm is None: algorithm = 'Dijkstra_Boost' - if v is None: + if v is not None and not isinstance(v, list): + v = [v] + + if v is None or all(u in v for u in self): + if v is None: + v = list(self) + # If we want to use BFS, we use the Cython routine if algorithm == 'BFS': if by_weight: @@ -2269,8 +2276,7 @@ def weight_function(e): from sage.graphs.distances_all_pairs import eccentricity algo = 'standard' if with_labels: - vertex_list = list(self) - return dict(zip(vertex_list, eccentricity(self, algorithm=algo, vertex_list=vertex_list))) + return dict(zip(v, eccentricity(self, algorithm=algo, vertex_list=v))) else: return eccentricity(self, algorithm=algo) @@ -2280,14 +2286,10 @@ def weight_function(e): check_weight)[0] algorithm = 'From_Dictionary' - v = self.vertices() - elif algorithm in ['Floyd-Warshall-Python', 'Floyd-Warshall-Cython', 'Johnson_Boost']: raise ValueError("algorithm '" + algorithm + "' works only if all" + " eccentricities are needed") - if not isinstance(v, list): - v = [v] ecc = {} from sage.rings.infinity import Infinity @@ -2374,6 +2376,13 @@ def radius(self, by_weight=False, algorithm=None, weight_function=None, if not self.order(): raise ValueError("radius is not defined for the empty DiGraph") + if weight_function is not None: + by_weight = True + + if by_weight and not weight_function: + def weight_function(e): + return 1 if e[2] is None else e[2] + return min(self.eccentricity(v=list(self), by_weight=by_weight, weight_function=weight_function, check_weight=check_weight, @@ -2415,10 +2424,18 @@ def diameter(self, by_weight=False, algorithm=None, weight_function=None, NetworkX. It works with weighted graphs, but no negative weight is allowed. - - ``'standard'``, ``'2Dsweep'``, ``'DiFUB'``: these algorithms are - implemented in :func:`sage.graphs.distances_all_pairs.diameter`. - They work only if ``by_weight==False``. See the function - documentation for more information. + - ``'DiFUB'``, ``'2Dsweep'``: these algorithms are + implemented in :func:`sage.graphs.distances_all_pairs.diameter` and + :func:`sage.graphs.base.boost_graph.diameter`. ``'2Dsweep'`` returns + lower bound on the diameter, while ``'DiFUB'`` returns the exact + computed diameter. They also works with negative weight, if there is + no negative cycle. See the functions documentation for more + information. + + - ``'standard'`` : the standard algorithm is implemented in + :func:`sage.graphs.distances_all_pairs.diameter`. It works only + if ``by_weight==False``. See the function documentation for more + information. - ``'Dijkstra_Boost'``: the Dijkstra algorithm, implemented in Boost (works only with positive weights). @@ -2454,16 +2471,19 @@ def diameter(self, by_weight=False, algorithm=None, weight_function=None, sage: G = digraphs.Path(5) sage: G.diameter(algorithm = 'DiFUB') +Infinity + sage: G = DiGraph([(1,2,4), (2,1,7)]) + sage: G.diameter(algorithm='2Dsweep', by_weight=True) + 7.0 + sage: G.delete_edge(2,1,7); G.add_edge(2,1,-5); + sage: G.diameter(algorithm='2Dsweep', by_weight=True) + Traceback (most recent call last): + ... + ValueError: the graph contains a negative cycle sage: G = DiGraph() sage: G.diameter() Traceback (most recent call last): ... ValueError: diameter is not defined for the empty DiGraph - sage: g = DiGraph([(1, 2, {'weight': 1})]) - sage: g.diameter(algorithm='2Dsweep', weight_function=lambda e: e[2]['weight']) - Traceback (most recent call last): - ... - ValueError: algorithm '2Dsweep' does not work on weighted DiGraphs """ if not self.order(): raise ValueError("diameter is not defined for the empty DiGraph") @@ -2471,12 +2491,26 @@ def diameter(self, by_weight=False, algorithm=None, weight_function=None, if weight_function is not None: by_weight = True - if algorithm is None and not by_weight: + if by_weight and not weight_function: + def weight_function(e): + return 1 if e[2] is None else e[2] + + if algorithm is None: algorithm = 'DiFUB' elif algorithm == 'BFS': algorithm = 'standard' - if algorithm in ['standard', '2Dsweep', 'DiFUB']: + if algorithm in ['2Dsweep', 'DiFUB']: + if not by_weight: + from sage.graphs.distances_all_pairs import diameter + return diameter(self, algorithm=algorithm) + else: + from sage.graphs.base.boost_graph import diameter + return diameter(self, algorithm=algorithm, + weight_function=weight_function, + check_weight=check_weight) + + if algorithm == 'standard': if by_weight: raise ValueError("algorithm '" + algorithm + "' does not work" + " on weighted DiGraphs") diff --git a/src/sage/graphs/distances_all_pairs.pyx b/src/sage/graphs/distances_all_pairs.pyx index 277887a112b..5fec760720a 100644 --- a/src/sage/graphs/distances_all_pairs.pyx +++ b/src/sage/graphs/distances_all_pairs.pyx @@ -1525,7 +1525,7 @@ def diameter(G, algorithm=None, source=None): if G.is_directed(): if algorithm is None: - algorithm = 'standard' + algorithm = 'DiFUB' elif not algorithm in ['2Dsweep', 'standard', 'DiFUB']: raise ValueError("unknown algorithm for computing the diameter of directed graph") else: From 14e44ec709d3daf6bb3b849febb419605a400d57 Mon Sep 17 00:00:00 2001 From: vipul79321 Date: Fri, 3 Jul 2020 16:41:22 +0530 Subject: [PATCH 032/217] minor changes in documentation --- src/sage/graphs/base/boost_graph.pyx | 7 ++-- src/sage/graphs/digraph.py | 50 ++++++++++++++++------------ 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx index 93ab5dae3bf..0c40aa46fa6 100644 --- a/src/sage/graphs/base/boost_graph.pyx +++ b/src/sage/graphs/base/boost_graph.pyx @@ -1748,8 +1748,10 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, v_index source, str algorithm): r""" - Returns lower bound on the diamter of weighted digraph using the weighted - version of the algorithm proposed in [Broder2000]_. + Return a lower bound on the diameter of `G`. + + This method implements the weighted version of the algorithm proposed + in [Broder2000]_ to compute a lower bound of the weighted digraph `G`. In first part, it computes forward distances from `source` and selects a vertex `vf` at a maximum forward distance from `source` and then it @@ -1967,7 +1969,6 @@ cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, for v in range(n): LB_1 = max(LB_1, distances[v]) order_1.push_back(pair[double, v_index](distances[v], v)) - # Compute Backward distances from `m`. if algorithm == 'Bellman-Ford': sig_on() diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index 2b2eae9337f..64c4d33c202 100644 --- a/src/sage/graphs/digraph.py +++ b/src/sage/graphs/digraph.py @@ -2156,8 +2156,8 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, - ``weight_function`` -- function (default: ``None``); a function that takes as input an edge ``(u, v, l)`` and outputs its weight. If not ``None``, ``by_weight`` is automatically set to ``True``. If ``None`` - and ``by_weight`` is ``True``, we use the edge label ``l`` as a - weight. + and ``by_weight`` is ``True``, we use the edge label ``l``, if ``l`` + is not ``None``, else ``1`` as a weight. - ``check_weight`` -- boolean (default: ``True``); if ``True``, we check that the ``weight_function`` outputs a number for each edge @@ -2341,8 +2341,8 @@ def radius(self, by_weight=False, algorithm=None, weight_function=None, - ``weight_function`` -- function (default: ``None``); a function that takes as input an edge ``(u, v, l)`` and outputs its weight. If not ``None``, ``by_weight`` is automatically set to ``True``. If ``None`` - and ``by_weight`` is ``True``, we use the edge label ``l`` as a - weight. + and ``by_weight`` is ``True``, we use the edge label ``l``, if ``l`` + is not ``None``, else ``1`` as a weight. - ``check_weight`` -- boolean (default: ``True``); if ``True``, we check that the ``weight_function`` outputs a number for each edge @@ -2383,7 +2383,7 @@ def radius(self, by_weight=False, algorithm=None, weight_function=None, def weight_function(e): return 1 if e[2] is None else e[2] - return min(self.eccentricity(v=list(self), by_weight=by_weight, + return min(self.eccentricity(v=None, by_weight=by_weight, weight_function=weight_function, check_weight=check_weight, algorithm=algorithm)) @@ -2409,50 +2409,53 @@ def diameter(self, by_weight=False, algorithm=None, weight_function=None, algorithms: - ``'BFS'``: the computation is done through a BFS centered on each - vertex successively. Works only if ``by_weight==False``. + vertex successively. Works only if ``by_weight==False``. It computes + all the eccentricities and return the maximum value. - ``'Floyd-Warshall-Cython'``: a Cython implementation of the - Floyd-Warshall algorithm. Works only if ``by_weight==False`` and ``v - is None``. + Floyd-Warshall algorithm. Works only if ``by_weight==False``. It + computes all the eccentricities and return the maximum value. - ``'Floyd-Warshall-Python'``: a Python implementation of the Floyd-Warshall algorithm. Works also with weighted graphs, even with - negative weights (but no negative cycle is allowed). However, ``v`` - must be ``None``. + negative weights (but no negative cycle is allowed). It computes all + the eccentricities and return the maximum value. - ``'Dijkstra_NetworkX'``: the Dijkstra algorithm, implemented in NetworkX. It works with weighted graphs, but no negative weight is - allowed. + allowed. It computes all the eccentricities and return the maximum + value. - ``'DiFUB'``, ``'2Dsweep'``: these algorithms are implemented in :func:`sage.graphs.distances_all_pairs.diameter` and :func:`sage.graphs.base.boost_graph.diameter`. ``'2Dsweep'`` returns lower bound on the diameter, while ``'DiFUB'`` returns the exact - computed diameter. They also works with negative weight, if there is + computed diameter. They also work with negative weight, if there is no negative cycle. See the functions documentation for more information. - ``'standard'`` : the standard algorithm is implemented in :func:`sage.graphs.distances_all_pairs.diameter`. It works only if ``by_weight==False``. See the function documentation for more - information. + information. It computes all the eccentricities and return the + maximum value. - ``'Dijkstra_Boost'``: the Dijkstra algorithm, implemented in Boost - (works only with positive weights). + (works only with positive weights). It computes all the + eccentricities and return the maximum value. - ``'Johnson_Boost'``: the Johnson algorithm, implemented in Boost (works also with negative weights, if there is no negative - cycle). + cycle). It computes all the eccentricities and return the maximum + value. - - ``None`` (default): Sage chooses the best algorithm: ``'iFUB'`` for - unweighted graphs, ``'Dijkstra_Boost'`` if all weights are positive, - ``'Johnson_Boost'`` otherwise. + - ``None`` (default): Sage chooses the best algorithm: ``'DiFUB'``. - ``weight_function`` -- function (default: ``None``); a function that takes as input an edge ``(u, v, l)`` and outputs its weight. If not ``None``, ``by_weight`` is automatically set to ``True``. If ``None`` - and ``by_weight`` is ``True``, we use the edge label ``l`` as a - weight. + and ``by_weight`` is ``True``, we use the edge label ``l``, if ``l`` + is not ``None``, else ``1`` as weight. - ``check_weight`` -- boolean (default: ``True``); if ``True``, we check that the ``weight_function`` outputs a number for each edge @@ -2468,6 +2471,11 @@ def diameter(self, by_weight=False, algorithm=None, weight_function=None, TESTS:: + sage: G = graphs.RandomGNP(40, 0.4).to_directed() + sage: d1 = G.diameter(algorithm='DiFUB', by_weight=True) + sage: d2 = max(G.eccentricity(algorithm='Dijkstra_Boost', by_weight=True)) + sage: d1 == d2 + True sage: G = digraphs.Path(5) sage: G.diameter(algorithm = 'DiFUB') +Infinity @@ -2517,7 +2525,7 @@ def weight_function(e): from sage.graphs.distances_all_pairs import diameter return diameter(self, algorithm=algorithm) - return max(self.eccentricity(v=list(self), by_weight=by_weight, + return max(self.eccentricity(v=None, by_weight=by_weight, weight_function=weight_function, check_weight=check_weight, algorithm=algorithm)) From 68ea7be4ce107685995da17ccda7fcee8220ad71 Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Tue, 31 Mar 2020 23:18:37 +0200 Subject: [PATCH 033/217] upgrade rpy2 version --- build/pkgs/rpy2/checksums.ini | 6 +++--- build/pkgs/rpy2/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/rpy2/checksums.ini b/build/pkgs/rpy2/checksums.ini index c6670edbb27..808cb371fc0 100644 --- a/build/pkgs/rpy2/checksums.ini +++ b/build/pkgs/rpy2/checksums.ini @@ -1,4 +1,4 @@ tarball=rpy2-VERSION.tar.gz -sha1=24f7c538a734618dfcf2343304729c0b1e429717 -md5=729946166b43103db7697e69db8c5c45 -cksum=3858682977 +sha1=05ad6e4a8c4912a5bc8b403f1772f5e04d4ec173 +md5=eaa65c233eb2d60678dabe2b58894aa4 +cksum=282685783 diff --git a/build/pkgs/rpy2/package-version.txt b/build/pkgs/rpy2/package-version.txt index 4b18da28f6e..406ebcbd95f 100644 --- a/build/pkgs/rpy2/package-version.txt +++ b/build/pkgs/rpy2/package-version.txt @@ -1 +1 @@ -2.8.2.p1 +3.2.7 From f1cd4e2ef423bccdeac62218a6c5140182a622a9 Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Tue, 31 Mar 2020 23:18:54 +0200 Subject: [PATCH 034/217] remove cygwin.patch (rpy2) --- build/pkgs/rpy2/patches/cygwin.patch | 108 --------------------------- 1 file changed, 108 deletions(-) delete mode 100644 build/pkgs/rpy2/patches/cygwin.patch diff --git a/build/pkgs/rpy2/patches/cygwin.patch b/build/pkgs/rpy2/patches/cygwin.patch deleted file mode 100644 index d2088e419e1..00000000000 --- a/build/pkgs/rpy2/patches/cygwin.patch +++ /dev/null @@ -1,108 +0,0 @@ -diff -ru rpy2-2.7.4.orig/rpy/rinterface/na_values.c rpy2-2.7.4/rpy/rinterface/na_values.c ---- rpy2-2.7.4.orig/rpy/rinterface/na_values.c 2015-09-05 01:15:16.000000000 +0200 -+++ rpy2-2.7.4/rpy/rinterface/na_values.c 2015-12-01 11:46:40.675932500 +0100 -@@ -203,7 +203,7 @@ - 0, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*tp_getset*/ --#if defined(Win32) || defined(Win64) -+#if defined(Win32) || defined(Win64) || defined(__CYGWIN__) - NULL, - #else - &PyLong_Type, /*tp_base*/ -@@ -401,7 +401,7 @@ - 0, //NAInteger_methods, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*tp_getset*/ --#if defined(Win32) || defined(Win64) -+#if defined(Win32) || defined(Win64) || defined(__CYGWIN__) - NULL, - #else - &PyLong_Type, /*tp_base*/ -@@ -587,7 +587,7 @@ - 0, //NAInteger_methods, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*tp_getset*/ --#if defined(Win32) || defined(Win64) -+#if defined(Win32) || defined(Win64) || defined(__CYGWIN__) - NULL, - #else - &PyFloat_Type, /*tp_base*/ -@@ -689,7 +689,7 @@ - 0, //NAInteger_methods, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*tp_getset*/ --#if defined(Win32) || defined(Win64) -+#if defined(Win32) || defined(Win64) || defined(__CYGWIN__) - NULL, - #elif (PY_VERSION_HEX < 0x03010000) - &PyString_Type, /*tp_base*/ -@@ -856,7 +856,7 @@ - 0, //NAInteger_methods, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*tp_getset*/ --#if defined(Win32) || defined(Win64) -+#if defined(Win32) || defined(Win64) || defined(__CYGWIN__) - NULL, - #else - &PyComplex_Type, /*tp_base*/ -diff -ru rpy2-2.7.4.orig/rpy/rinterface/_rinterface.c rpy2-2.7.4/rpy/rinterface/_rinterface.c ---- rpy2-2.7.4.orig/rpy/rinterface/_rinterface.c 2015-09-12 23:23:55.000000000 +0200 -+++ rpy2-2.7.4/rpy/rinterface/_rinterface.c 2015-12-01 11:45:53.163820335 +0100 -@@ -1162,7 +1162,7 @@ - "and R_runHandlers (on other platforms)."); - - --#if defined(Win32) || defined(Win64) -+#if defined(Win32) || defined(Win64) || defined(__CYGWIN__) - void win32CallBack() - { - /* called during i/o, eval, graphics in ProcessEvents */ -@@ -3749,7 +3749,7 @@ - } - - /* NA types */ --#if defined(Win32) || defined(Win64) -+#if defined(Win32) || defined(Win64) || defined(__CYGWIN__) - NAInteger_Type.tp_base=&PyLong_Type; - #endif - if (PyType_Ready(&NAInteger_Type) < 0) { -@@ -3759,7 +3759,7 @@ - return NULL; - #endif - } --#if defined(Win32) || defined(Win64) -+#if defined(Win32) || defined(Win64) || defined(__CYGWIN__) - NALogical_Type.tp_base=&PyLong_Type; - #endif - if (PyType_Ready(&NALogical_Type) < 0) { -@@ -3769,7 +3769,7 @@ - return NULL; - #endif - } --#if defined(Win32) || defined(Win64) -+#if defined(Win32) || defined(Win64) || defined(__CYGWIN__) - NAReal_Type.tp_base=&PyFloat_Type; - #endif - if (PyType_Ready(&NAReal_Type) < 0) { -@@ -3779,7 +3779,7 @@ - return NULL; - #endif - } --#if defined(Win32) || defined(Win64) -+#if defined(Win32) || defined(Win64) || defined(__CYGWIN__) - NAComplex_Type.tp_base=&PyComplex_Type; - #endif - if (PyType_Ready(&NAComplex_Type) < 0) { -diff -ru rpy2-2.7.4.orig/setup rpy2-2.7.4/setup.py ---- rpy2-2.7.4.orig/setup.py 2016-01-15 01:45:48.447894400 -0800 -+++ rpy2-2.7.4/setup.py 2016-01-15 01:48:55.222874000 -0800 -@@ -160,7 +160,7 @@ - extra_link_args = [] - extra_compile_args = [] - include_dirs = [] -- libraries = [] -+ libraries = ['readline'] - library_dirs = [] - - #FIXME: crude way (will break in many cases) From 68f6f928b4042228cbd1f2bb8c2b102a79eec992 Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Tue, 31 Mar 2020 23:19:07 +0200 Subject: [PATCH 035/217] add setup.patch (rpy2) --- build/pkgs/rpy2/patches/setup.patch | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 build/pkgs/rpy2/patches/setup.patch diff --git a/build/pkgs/rpy2/patches/setup.patch b/build/pkgs/rpy2/patches/setup.patch new file mode 100644 index 00000000000..d9a03da11c4 --- /dev/null +++ b/build/pkgs/rpy2/patches/setup.patch @@ -0,0 +1,16 @@ +diff --git a/setup.py b/setup.py +index a9f96f8..e82ca80 100755 +--- a/setup.py ++++ b/setup.py +@@ -182,11 +182,3 @@ if __name__ == '__main__': + package_data={'rpy2': ['rinterface_lib/R_API.h', + 'rinterface_lib/R_API_eventloop.h']} + ) +- +- print('---') +- if 'rpy2/_rinterface_cffi_build.py:ffibuilder_abi' in cffi_modules: +- print('ABI mode interface built and installed') +- if 'rpy2/_rinterface_cffi_build.py:ffibuilder_api' in cffi_modules: +- print('API mode interface built and installed') +- else: +- print('API mode interface not build because: %s' % c_extension_status) From b550f43cefe88466e080ff4fc72bf8cd5c22f8bb Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Tue, 31 Mar 2020 23:48:00 +0200 Subject: [PATCH 036/217] add upstream_url field to rpy2 checksums.ini --- build/pkgs/rpy2/checksums.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/build/pkgs/rpy2/checksums.ini b/build/pkgs/rpy2/checksums.ini index 808cb371fc0..9c71a70b04f 100644 --- a/build/pkgs/rpy2/checksums.ini +++ b/build/pkgs/rpy2/checksums.ini @@ -2,3 +2,4 @@ tarball=rpy2-VERSION.tar.gz sha1=05ad6e4a8c4912a5bc8b403f1772f5e04d4ec173 md5=eaa65c233eb2d60678dabe2b58894aa4 cksum=282685783 +upstream_url=https://files.pythonhosted.org/packages/39/c0/61120f9dae06b4887426d229b68a7a5f0ca1f9cb3986319bb9484819a28d/rpy2-3.2.7.tar.gz From 2cd2191f620f82cddaa047d8db3a4f81433d1be9 Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Tue, 31 Mar 2020 23:58:14 +0200 Subject: [PATCH 037/217] let rpy2 not depend on pytest --- build/pkgs/rpy2/patches/setup.patch | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/build/pkgs/rpy2/patches/setup.patch b/build/pkgs/rpy2/patches/setup.patch index d9a03da11c4..72346553571 100644 --- a/build/pkgs/rpy2/patches/setup.patch +++ b/build/pkgs/rpy2/patches/setup.patch @@ -1,8 +1,31 @@ diff --git a/setup.py b/setup.py -index a9f96f8..e82ca80 100755 +index a9f96f8..7ba69a1 100755 --- a/setup.py +++ b/setup.py -@@ -182,11 +182,3 @@ if __name__ == '__main__': +@@ -142,7 +142,7 @@ ipython. + if __name__ == '__main__': + pack_dir = {PACKAGE_NAME: os.path.join(package_prefix, 'rpy2')} + +- requires = ['pytest', 'jinja2', 'pytz', 'simplegeneric', 'tzlocal'] ++ requires = ['jinja2', 'pytz', 'simplegeneric', 'tzlocal'] + + setup( + name=PACKAGE_NAME, +@@ -161,12 +161,7 @@ if __name__ == '__main__': + packages=([PACKAGE_NAME] + + ['{pack_name}.{x}'.format(pack_name=PACKAGE_NAME, x=x) + for x in ('rlike', 'rinterface_lib', 'robjects', +- 'robjects.lib', 'interactive', 'ipython', +- 'tests', +- 'tests.rinterface', 'tests.rlike', +- 'tests.robjects', +- 'tests.ipython', +- 'tests.robjects.lib')] ++ 'robjects.lib', 'interactive', 'ipython')] + ), + classifiers = ['Programming Language :: Python', + 'Programming Language :: Python :: 3', +@@ -182,11 +177,3 @@ if __name__ == '__main__': package_data={'rpy2': ['rinterface_lib/R_API.h', 'rinterface_lib/R_API_eventloop.h']} ) From b76ee25d67fccc77e1f4ba7fb0f4589c022bca4f Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Wed, 1 Apr 2020 00:13:55 +0200 Subject: [PATCH 038/217] cffi package (rpy2 dependency) --- build/pkgs/cffi/SPKG.txt | 15 +++++++++++++++ build/pkgs/cffi/checksums.ini | 5 +++++ build/pkgs/cffi/package-version.txt | 1 + build/pkgs/cffi/spkg-install.in | 1 + build/pkgs/cffi/type | 1 + 5 files changed, 23 insertions(+) create mode 100644 build/pkgs/cffi/SPKG.txt create mode 100644 build/pkgs/cffi/checksums.ini create mode 100644 build/pkgs/cffi/package-version.txt create mode 100644 build/pkgs/cffi/spkg-install.in create mode 100644 build/pkgs/cffi/type diff --git a/build/pkgs/cffi/SPKG.txt b/build/pkgs/cffi/SPKG.txt new file mode 100644 index 00000000000..075e8abf25b --- /dev/null +++ b/build/pkgs/cffi/SPKG.txt @@ -0,0 +1,15 @@ += cffi = + +== Description == + +development website: https://foss.heptapod.net/pypy/cffi +documentation website: https://cffi.readthedocs.io/en/latest/ +PyPI page: https://pypi.org/project/cffi/ + +== License == + + * MIT + +== Upstream Contact == + + * https://foss.heptapod.net/pypy/cffi diff --git a/build/pkgs/cffi/checksums.ini b/build/pkgs/cffi/checksums.ini new file mode 100644 index 00000000000..710656a87a7 --- /dev/null +++ b/build/pkgs/cffi/checksums.ini @@ -0,0 +1,5 @@ +tarball=cffi-VERSION.tar.gz +sha1=2a8f05a7d51d77ef1e641cb359a54e4d8fa019cb +md5=74845f8d2b7b583dd9a3574f402edf39 +cksum=1594930691 +upstream_url=https://files.pythonhosted.org/packages/05/54/3324b0c46340c31b909fcec598696aaec7ddc8c18a63f2db352562d3354c/cffi-1.14.0.tar.gz diff --git a/build/pkgs/cffi/package-version.txt b/build/pkgs/cffi/package-version.txt new file mode 100644 index 00000000000..850e742404b --- /dev/null +++ b/build/pkgs/cffi/package-version.txt @@ -0,0 +1 @@ +1.14.0 diff --git a/build/pkgs/cffi/spkg-install.in b/build/pkgs/cffi/spkg-install.in new file mode 100644 index 00000000000..deba1bb42bb --- /dev/null +++ b/build/pkgs/cffi/spkg-install.in @@ -0,0 +1 @@ +cd src && sdh_pip_install . diff --git a/build/pkgs/cffi/type b/build/pkgs/cffi/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/cffi/type @@ -0,0 +1 @@ +standard From 84ded30cafa163fd19da294d546dd24ff6550e46 Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Wed, 1 Apr 2020 00:14:10 +0200 Subject: [PATCH 039/217] pycparser (rpy2 dependency) --- build/pkgs/pycparser/SPKG.txt | 15 +++++++++++++++ build/pkgs/pycparser/checksums.ini | 5 +++++ build/pkgs/pycparser/package-version.txt | 1 + build/pkgs/pycparser/spkg-install.in | 1 + build/pkgs/pycparser/type | 1 + 5 files changed, 23 insertions(+) create mode 100644 build/pkgs/pycparser/SPKG.txt create mode 100644 build/pkgs/pycparser/checksums.ini create mode 100644 build/pkgs/pycparser/package-version.txt create mode 100644 build/pkgs/pycparser/spkg-install.in create mode 100644 build/pkgs/pycparser/type diff --git a/build/pkgs/pycparser/SPKG.txt b/build/pkgs/pycparser/SPKG.txt new file mode 100644 index 00000000000..56334914f0d --- /dev/null +++ b/build/pkgs/pycparser/SPKG.txt @@ -0,0 +1,15 @@ += pycparser = + +== Description == + +development website: https://github.com/eliben/pycparser +PyPI page: https://pypi.org/project/pycparser/ + +== License == + + * BSD + +== Upstream Contact == + + * https://github.com/eliben/pycparser + diff --git a/build/pkgs/pycparser/checksums.ini b/build/pkgs/pycparser/checksums.ini new file mode 100644 index 00000000000..9ad2ce58fb5 --- /dev/null +++ b/build/pkgs/pycparser/checksums.ini @@ -0,0 +1,5 @@ +tarball=pycparser-VERSION.tar.gz +sha1=0ae93d89b69fab48af3a407a2f8663bcea270c3d +md5=b8f88de737db8c346ee8d31c07c7a25a +cksum=3289554032 +upstream_url=https://files.pythonhosted.org/packages/0f/86/e19659527668d70be91d0369aeaa055b4eb396b0f387a4f92293a20035bd/pycparser-2.20.tar.gz diff --git a/build/pkgs/pycparser/package-version.txt b/build/pkgs/pycparser/package-version.txt new file mode 100644 index 00000000000..a4b5a6f4a49 --- /dev/null +++ b/build/pkgs/pycparser/package-version.txt @@ -0,0 +1 @@ +2.20 diff --git a/build/pkgs/pycparser/spkg-install.in b/build/pkgs/pycparser/spkg-install.in new file mode 100644 index 00000000000..deba1bb42bb --- /dev/null +++ b/build/pkgs/pycparser/spkg-install.in @@ -0,0 +1 @@ +cd src && sdh_pip_install . diff --git a/build/pkgs/pycparser/type b/build/pkgs/pycparser/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/pycparser/type @@ -0,0 +1 @@ +standard From 2e0fe7351b0151e94fca927ddb9e6c15913b2aad Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Wed, 1 Apr 2020 00:14:57 +0200 Subject: [PATCH 040/217] update rpy2 dependencies --- build/pkgs/rpy2/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/rpy2/dependencies b/build/pkgs/rpy2/dependencies index c939931f297..3fbebabc078 100644 --- a/build/pkgs/rpy2/dependencies +++ b/build/pkgs/rpy2/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) r six singledispatch | $(PYTHON_TOOLCHAIN) +$(PYTHON) r cffi | $(PYTHON_TOOLCHAIN) pycparser ---------- All lines of this file are ignored except the first. From 81f580eff5007a666dc712e5219d47f5933e1573 Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Sun, 19 Apr 2020 23:26:25 +0200 Subject: [PATCH 041/217] still install tests along rpy2 --- build/pkgs/rpy2/patches/setup.patch | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/build/pkgs/rpy2/patches/setup.patch b/build/pkgs/rpy2/patches/setup.patch index 72346553571..3e6f81c2db4 100644 --- a/build/pkgs/rpy2/patches/setup.patch +++ b/build/pkgs/rpy2/patches/setup.patch @@ -11,20 +11,6 @@ index a9f96f8..7ba69a1 100755 setup( name=PACKAGE_NAME, -@@ -161,12 +161,7 @@ if __name__ == '__main__': - packages=([PACKAGE_NAME] + - ['{pack_name}.{x}'.format(pack_name=PACKAGE_NAME, x=x) - for x in ('rlike', 'rinterface_lib', 'robjects', -- 'robjects.lib', 'interactive', 'ipython', -- 'tests', -- 'tests.rinterface', 'tests.rlike', -- 'tests.robjects', -- 'tests.ipython', -- 'tests.robjects.lib')] -+ 'robjects.lib', 'interactive', 'ipython')] - ), - classifiers = ['Programming Language :: Python', - 'Programming Language :: Python :: 3', @@ -182,11 +177,3 @@ if __name__ == '__main__': package_data={'rpy2': ['rinterface_lib/R_API.h', 'rinterface_lib/R_API_eventloop.h']} From d4c16728171baa763dcb653f83aa485fdbeedefa Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 3 Jul 2020 12:02:59 -0700 Subject: [PATCH 042/217] build/pkgs: Upgrade rpy2 to 3.3.4, use patterns for upstream_urls of dependencies --- build/pkgs/cffi/checksums.ini | 2 +- build/pkgs/pycparser/checksums.ini | 2 +- build/pkgs/rpy2/checksums.ini | 8 ++++---- build/pkgs/rpy2/package-version.txt | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/pkgs/cffi/checksums.ini b/build/pkgs/cffi/checksums.ini index 710656a87a7..88dd9628d4c 100644 --- a/build/pkgs/cffi/checksums.ini +++ b/build/pkgs/cffi/checksums.ini @@ -2,4 +2,4 @@ tarball=cffi-VERSION.tar.gz sha1=2a8f05a7d51d77ef1e641cb359a54e4d8fa019cb md5=74845f8d2b7b583dd9a3574f402edf39 cksum=1594930691 -upstream_url=https://files.pythonhosted.org/packages/05/54/3324b0c46340c31b909fcec598696aaec7ddc8c18a63f2db352562d3354c/cffi-1.14.0.tar.gz +upstream_url=https://pypi.io/packages/source/c/cffi/cffi-VERSION.tar.gz diff --git a/build/pkgs/pycparser/checksums.ini b/build/pkgs/pycparser/checksums.ini index 9ad2ce58fb5..885d94acf9d 100644 --- a/build/pkgs/pycparser/checksums.ini +++ b/build/pkgs/pycparser/checksums.ini @@ -2,4 +2,4 @@ tarball=pycparser-VERSION.tar.gz sha1=0ae93d89b69fab48af3a407a2f8663bcea270c3d md5=b8f88de737db8c346ee8d31c07c7a25a cksum=3289554032 -upstream_url=https://files.pythonhosted.org/packages/0f/86/e19659527668d70be91d0369aeaa055b4eb396b0f387a4f92293a20035bd/pycparser-2.20.tar.gz +upstream_url=https://pypi.io/packages/source/p/pycparser/pycparser-VERSION.tar.gz diff --git a/build/pkgs/rpy2/checksums.ini b/build/pkgs/rpy2/checksums.ini index 9c71a70b04f..6cb4be003c2 100644 --- a/build/pkgs/rpy2/checksums.ini +++ b/build/pkgs/rpy2/checksums.ini @@ -1,5 +1,5 @@ tarball=rpy2-VERSION.tar.gz -sha1=05ad6e4a8c4912a5bc8b403f1772f5e04d4ec173 -md5=eaa65c233eb2d60678dabe2b58894aa4 -cksum=282685783 -upstream_url=https://files.pythonhosted.org/packages/39/c0/61120f9dae06b4887426d229b68a7a5f0ca1f9cb3986319bb9484819a28d/rpy2-3.2.7.tar.gz +sha1=64762fe2abe3a6469975ff86187396f8339f85e4 +md5=da70a5c4e35e22c469c37444d45257ee +cksum=2800144752 +upstream_url=https://pypi.io/packages/source/r/rpy2/rpy2-VERSION.tar.gz diff --git a/build/pkgs/rpy2/package-version.txt b/build/pkgs/rpy2/package-version.txt index 406ebcbd95f..a0891f563f3 100644 --- a/build/pkgs/rpy2/package-version.txt +++ b/build/pkgs/rpy2/package-version.txt @@ -1 +1 @@ -3.2.7 +3.3.4 From 28552a28400afe4afd1ff2e51b64b1a09271e659 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 3 Jul 2020 21:29:16 -0700 Subject: [PATCH 043/217] Update patches --- build/pkgs/rpy2/patches/716.patch | 89 +++++++++++++++++++ build/pkgs/rpy2/patches/setup-no-pytest.patch | 13 +++ build/pkgs/rpy2/patches/setup.patch | 25 ------ 3 files changed, 102 insertions(+), 25 deletions(-) create mode 100644 build/pkgs/rpy2/patches/716.patch create mode 100644 build/pkgs/rpy2/patches/setup-no-pytest.patch delete mode 100644 build/pkgs/rpy2/patches/setup.patch diff --git a/build/pkgs/rpy2/patches/716.patch b/build/pkgs/rpy2/patches/716.patch new file mode 100644 index 00000000000..8446b281633 --- /dev/null +++ b/build/pkgs/rpy2/patches/716.patch @@ -0,0 +1,89 @@ +From 87d0f82e2f4be94893881913018ca9085c0ff8e5 Mon Sep 17 00:00:00 2001 +From: Matthias Koeppe +Date: Fri, 3 Jul 2020 12:47:41 -0700 +Subject: [PATCH] setup.py: Print CFFI configuration messages only on build + +--- + setup.py | 44 ++++++++++++++++++++++++++------------------ + 1 file changed, 26 insertions(+), 18 deletions(-) + +diff --git a/setup.py b/setup.py +index e4337838..7fead893 100755 +--- a/setup.py ++++ b/setup.py +@@ -21,6 +21,7 @@ + from rpy2 import situation + + from setuptools import setup ++from distutils.command.build import build as du_build + + PACKAGE_NAME = 'rpy2' + pack_version = __import__('rpy2').__version__ +@@ -111,7 +112,6 @@ def get_r_c_extension_status(): + + + cffi_mode = situation.get_cffi_mode() +-print('cffi mode: %s' % cffi_mode) + c_extension_status = get_r_c_extension_status() + if cffi_mode == situation.CFFI_MODE.ABI: + cffi_modules = ['rpy2/_rinterface_cffi_build.py:ffibuilder_abi'] +@@ -135,6 +135,30 @@ def get_r_c_extension_status(): + # This should never happen. + raise ValueError('Invalid value for cffi_mode') + ++class build(du_build): ++ ++ def run(self): ++ print('cffi mode: %s' % cffi_mode) ++ ++ du_build.run(self) ++ ++ print('---') ++ print(cffi_mode) ++ if cffi_mode in (situation.CFFI_MODE.ABI, ++ situation.CFFI_MODE.BOTH, ++ situation.CFFI_MODE.ANY): ++ print('ABI mode interface built.') ++ if cffi_mode in (situation.CFFI_MODE.API, ++ situation.CFFI_MODE.BOTH): ++ print('API mode interface built.') ++ if cffi_mode == situation.CFFI_MODE.ANY: ++ if c_extension_status == COMPILATION_STATUS.OK: ++ print('API mode interface built.') ++ else: ++ print('API mode interface not built because: %s' % c_extension_status) ++ print('To change the API/ABI build mode, set or modify the environment ' ++ 'variable RPY2_CFFI_MODE.') ++ + LONG_DESCRIPTION = """ + Python interface to the R language. + +@@ -168,6 +192,7 @@ def get_r_c_extension_status(): + install_requires=requires + ['cffi>=1.10.0'], + setup_requires=['cffi>=1.10.0'], + cffi_modules=cffi_modules, ++ cmdclass = dict(build=build), + package_dir=pack_dir, + packages=([PACKAGE_NAME] + + ['{pack_name}.{x}'.format(pack_name=PACKAGE_NAME, x=x) +@@ -193,20 +218,3 @@ def get_r_c_extension_status(): + package_data={'rpy2': ['rinterface_lib/R_API.h', + 'rinterface_lib/R_API_eventloop.h']} + ) +- +- print('---') +- print(cffi_mode) +- if cffi_mode in (situation.CFFI_MODE.ABI, +- situation.CFFI_MODE.BOTH, +- situation.CFFI_MODE.ANY): +- print('ABI mode interface built and installed.') +- if cffi_mode in (situation.CFFI_MODE.API, +- situation.CFFI_MODE.BOTH): +- print('API mode interface built and installed.') +- if cffi_mode == situation.CFFI_MODE.ANY: +- if c_extension_status == COMPILATION_STATUS.OK: +- print('API mode interface built and installed.') +- else: +- print('API mode interface not build because: %s' % c_extension_status) +- print('To change the API/ABI build mode, set or modify the environment ' +- 'variable RPY2_CFFI_MODE.') diff --git a/build/pkgs/rpy2/patches/setup-no-pytest.patch b/build/pkgs/rpy2/patches/setup-no-pytest.patch new file mode 100644 index 00000000000..91cb5127572 --- /dev/null +++ b/build/pkgs/rpy2/patches/setup-no-pytest.patch @@ -0,0 +1,13 @@ +diff --git a/setup.py b/setup.py +index a9f96f8..7ba69a1 100755 +--- a/setup.py ++++ b/setup.py +@@ -142,7 +142,7 @@ ipython. + if __name__ == '__main__': + pack_dir = {PACKAGE_NAME: os.path.join(package_prefix, 'rpy2')} + +- requires = ['pytest', 'jinja2', 'pytz', 'tzlocal'] ++ requires = ['jinja2', 'pytz', 'tzlocal'] + + setup( + name=PACKAGE_NAME, diff --git a/build/pkgs/rpy2/patches/setup.patch b/build/pkgs/rpy2/patches/setup.patch deleted file mode 100644 index 3e6f81c2db4..00000000000 --- a/build/pkgs/rpy2/patches/setup.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/setup.py b/setup.py -index a9f96f8..7ba69a1 100755 ---- a/setup.py -+++ b/setup.py -@@ -142,7 +142,7 @@ ipython. - if __name__ == '__main__': - pack_dir = {PACKAGE_NAME: os.path.join(package_prefix, 'rpy2')} - -- requires = ['pytest', 'jinja2', 'pytz', 'simplegeneric', 'tzlocal'] -+ requires = ['jinja2', 'pytz', 'simplegeneric', 'tzlocal'] - - setup( - name=PACKAGE_NAME, -@@ -182,11 +177,3 @@ if __name__ == '__main__': - package_data={'rpy2': ['rinterface_lib/R_API.h', - 'rinterface_lib/R_API_eventloop.h']} - ) -- -- print('---') -- if 'rpy2/_rinterface_cffi_build.py:ffibuilder_abi' in cffi_modules: -- print('ABI mode interface built and installed') -- if 'rpy2/_rinterface_cffi_build.py:ffibuilder_api' in cffi_modules: -- print('API mode interface built and installed') -- else: -- print('API mode interface not build because: %s' % c_extension_status) From 20133ada14046474d5c0a5b563580e6949caeaba Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 3 Jul 2020 21:34:13 -0700 Subject: [PATCH 044/217] build/pkgs/rpy2: Add spkg-check.in, add conditional dep on pytest, simplify spkg-install.in --- build/pkgs/rpy2/dependencies | 2 +- build/pkgs/rpy2/spkg-check.in | 1 + build/pkgs/rpy2/spkg-install.in | 6 ------ 3 files changed, 2 insertions(+), 7 deletions(-) create mode 100644 build/pkgs/rpy2/spkg-check.in diff --git a/build/pkgs/rpy2/dependencies b/build/pkgs/rpy2/dependencies index 3fbebabc078..1da6d526a51 100644 --- a/build/pkgs/rpy2/dependencies +++ b/build/pkgs/rpy2/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) r cffi | $(PYTHON_TOOLCHAIN) pycparser +$(PYTHON) r cffi | $(PYTHON_TOOLCHAIN) pycparser $(and $(filter-out no,$(SAGE_CHECK)), pytest) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/rpy2/spkg-check.in b/build/pkgs/rpy2/spkg-check.in new file mode 100644 index 00000000000..e079f8a6038 --- /dev/null +++ b/build/pkgs/rpy2/spkg-check.in @@ -0,0 +1 @@ +pytest diff --git a/build/pkgs/rpy2/spkg-install.in b/build/pkgs/rpy2/spkg-install.in index 105eb0153d0..3098724e3a4 100644 --- a/build/pkgs/rpy2/spkg-install.in +++ b/build/pkgs/rpy2/spkg-install.in @@ -1,9 +1,3 @@ -if [ -z "$SAGE_LOCAL" ]; then - echo >&2 "SAGE_LOCAL undefined ... exiting" - echo >&2 "Maybe run 'sage --sh'?" - exit 1 -fi - set -e cd src From c02362ea4e827885fc95a356e77ff31d7c1355b5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 3 Jul 2020 21:41:11 -0700 Subject: [PATCH 045/217] build/pkgs/tzlocal: New (pip package) --- build/pkgs/tzlocal/requirements.txt | 1 + build/pkgs/tzlocal/type | 1 + 2 files changed, 2 insertions(+) create mode 100644 build/pkgs/tzlocal/requirements.txt create mode 100644 build/pkgs/tzlocal/type diff --git a/build/pkgs/tzlocal/requirements.txt b/build/pkgs/tzlocal/requirements.txt new file mode 100644 index 00000000000..cd5e9b12a4b --- /dev/null +++ b/build/pkgs/tzlocal/requirements.txt @@ -0,0 +1 @@ +tzlocal diff --git a/build/pkgs/tzlocal/type b/build/pkgs/tzlocal/type new file mode 100644 index 00000000000..134d9bc32d5 --- /dev/null +++ b/build/pkgs/tzlocal/type @@ -0,0 +1 @@ +optional From d33797fe7e8f7a069a39eb446419592916fc90a9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 3 Jul 2020 21:41:34 -0700 Subject: [PATCH 046/217] build/pkgs/rpy2/dependencies: Add conditional dep on tzlocal, numpy --- build/pkgs/rpy2/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/rpy2/dependencies b/build/pkgs/rpy2/dependencies index 1da6d526a51..7f2d42901ef 100644 --- a/build/pkgs/rpy2/dependencies +++ b/build/pkgs/rpy2/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) r cffi | $(PYTHON_TOOLCHAIN) pycparser $(and $(filter-out no,$(SAGE_CHECK)), pytest) +$(PYTHON) r cffi | $(PYTHON_TOOLCHAIN) pycparser $(and $(filter-out no,$(SAGE_CHECK)), pytest tzlocal numpy) ---------- All lines of this file are ignored except the first. From b66e9df749993b975920a440f870bc3f6df19884 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 4 Jul 2020 08:46:22 -0700 Subject: [PATCH 047/217] build/pkgs/{cffi,pycparser}/dependencies: New --- build/pkgs/cffi/dependencies | 5 +++++ build/pkgs/pycparser/dependencies | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 build/pkgs/cffi/dependencies create mode 100644 build/pkgs/pycparser/dependencies diff --git a/build/pkgs/cffi/dependencies b/build/pkgs/cffi/dependencies new file mode 100644 index 00000000000..15df0c4d6d8 --- /dev/null +++ b/build/pkgs/cffi/dependencies @@ -0,0 +1,5 @@ +$(PYTHON) | $(PYTHON_TOOLCHAIN) + +---------- +All lines of this file are ignored except the first. +It is copied by SAGE_ROOT/build/make/install into SAGE_ROOT/build/make/Makefile. diff --git a/build/pkgs/pycparser/dependencies b/build/pkgs/pycparser/dependencies new file mode 100644 index 00000000000..15df0c4d6d8 --- /dev/null +++ b/build/pkgs/pycparser/dependencies @@ -0,0 +1,5 @@ +$(PYTHON) | $(PYTHON_TOOLCHAIN) + +---------- +All lines of this file are ignored except the first. +It is copied by SAGE_ROOT/build/make/install into SAGE_ROOT/build/make/Makefile. From 4fe3d4ac2c6bcfe8891bea8b2accfa2237a2c591 Mon Sep 17 00:00:00 2001 From: vipul79321 Date: Sun, 5 Jul 2020 22:38:52 +0530 Subject: [PATCH 048/217] Patchbot issues fixed --- src/sage/graphs/base/boost_graph.pyx | 2 +- src/sage/graphs/distances_all_pairs.pyx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx index 0c40aa46fa6..a4e7e0147f0 100644 --- a/src/sage/graphs/base/boost_graph.pyx +++ b/src/sage/graphs/base/boost_graph.pyx @@ -2008,7 +2008,7 @@ cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, # different forward distances from `m` containing at least one vertex at # that distance. # - # The algorithm is based on the following two observations : + # The algorithm is based on the following two observations: # # 1). All the nodes `x` at a backward distance greater than `\[db_i\]` from # `m` having forward eccentricity greater than `\[2db_{i-1}\]` have a diff --git a/src/sage/graphs/distances_all_pairs.pyx b/src/sage/graphs/distances_all_pairs.pyx index 5fec760720a..3fdce23289a 100644 --- a/src/sage/graphs/distances_all_pairs.pyx +++ b/src/sage/graphs/distances_all_pairs.pyx @@ -1349,7 +1349,7 @@ cdef uint32_t diameter_DiFUB(short_digraph sd, # # The diameter of the digraph is equal to the maximum forward or backward # eccentricity of a vertex. The algorithm is based on the following two - # observations : + # observations: # 1). All the nodes `x` above the level `i` in Backward BFS of `m` having # forward eccentricity greater than `2(i-1)` have a corresponding node `y`, # whose backward eccentricity is greater than or equal to the forward From b2ce08ebb8857946b118e0352aefbc48a0f319f8 Mon Sep 17 00:00:00 2001 From: Stefan Grosser Date: Sun, 5 Jul 2020 20:15:48 -0400 Subject: [PATCH 049/217] Added static is_d_complete method in FinitePoset and added a `dual` option for the YoungDiagramPoset example --- src/sage/combinat/posets/d_complete.py | 9 +- src/sage/combinat/posets/hasse_diagram.py | 21 ++++- src/sage/combinat/posets/poset_examples.py | 17 +++- src/sage/combinat/posets/posets.py | 102 ++++++++++++++++++++- 4 files changed, 129 insertions(+), 20 deletions(-) diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index fa44f0db928..2cb3d2dd8c9 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -78,7 +78,7 @@ def _hooks(self): min_diamond = {} # Maps max of double-tailed diamond to min of double-tailed diamond max_diamond = {} # Maps min of double-tailed diamond to max of double-tailed diamond - diamonds = self.diamonds() # Tuples of four elements that are diamonds + diamonds, _ = self.diamonds() # Tuples of four elements that are diamonds diamond_index = {} # Map max elmt of double tailed diamond to index of diamond @@ -167,13 +167,6 @@ def get_hooks(self): """ return dict(self._hooks) - @staticmethod - def is_d_complete(cls, poset): - """ - Check if a poset is d-complete - """ - pass - def linear_extensions(self, facade=False): r""" Return the enumerated set of all the linear extensions of this poset with hook lengths. diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index 58bb2c080dc..d93e16a6932 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -2267,7 +2267,11 @@ def chains(self, element_class=list, exclude=None): def diamonds(self): r""" - Return a list of all diamonds in the Hasse Diagram. + Return in a tuple + - a list of all diamonds in the Hasse Diagram, + - a Boolean checking that every w,x,y that form a ``V``, there is a unique element z + which completes the diamond. + For a diamond z / \ @@ -2281,7 +2285,7 @@ def diamonds(self): sage: from sage.combinat.posets.hasse_diagram import HasseDiagram sage: H = HasseDiagram({0: [1,2], 1: [3], 2: [3], 3: []}) sage: H.diamonds() - [(0, 1, 2, 3)] + ([(0, 1, 2, 3)], True) TESTS:: @@ -2289,19 +2293,21 @@ def diamonds(self): sage: P = posets.YoungDiagramPoset(Partition([3, 2, 2])) sage: H = P._hasse_diagram sage: H.diamonds() - [(0, 1, 3, 4), (3, 4, 5, 6)] + ([(0, 1, 3, 4), (3, 4, 5, 6)], False) """ diamonds = [] + all_diamonds_completed = True for w in self.vertices(): covers = self.neighbors_out(w) for i, x in enumerate(covers): for y in covers[i+1:]: zs = self.common_upper_covers([x, y]) + if len(zs) != 1 : + all_diamonds_completed = False for z in zs: diamonds.append((w, x, y, z)) - return diamonds + return (diamonds, all_diamonds_completed) - def common_upper_covers(self, vertices): r""" Return the list of all common upper covers of a list of vertices @@ -2312,6 +2318,11 @@ def common_upper_covers(self, vertices): sage: H = HasseDiagram({0: [1,2], 1: [3], 2: [3], 3: []}) sage: H.common_upper_covers([1, 2]) [3] + + sage: from sage.combinat.posets.poset_examples import Posets + sage: H = Posets.YoungDiagramPoset(Partition([3, 2, 2]))._hasse_diagram + sage: H.common_upper_covers([4, 5]) + [6] """ covers = set(self.neighbors_out(vertices.pop())) diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index c685b5dc16b..1a57077e115 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -1375,7 +1375,7 @@ def UpDownPoset(n, m=1): return Poset((range(n), covers), cover_relations=True) @staticmethod - def YoungDiagramPoset(lam): + def YoungDiagramPoset(lam, dual=False): """ Return the poset of cells in the Young diagram of a partition. @@ -1399,7 +1399,20 @@ def cell_leq(a, b): """ return ((a[0] == b[0] - 1 and a[1] == b[1]) or (a[1] == b[1] - 1 and a[0] == b[0])) - return MeetSemilattice((lam.cells(), cell_leq), cover_relations=True) + + def cell_geq(a, b): + """ + Nested function that returns `True` if the cell `a` is + to the right or below + the cell `b` in the (English) Young diagram. + """ + return ((a[0] == b[0] + 1 and a[1] == b[1]) or + (a[1] == b[1] + 1 and a[0] == b[0])) + + if dual: + return JoinSemilattice((lam.cells(), cell_geq), cover_relations=True) + else: + return MeetSemilattice((lam.cells(), cell_leq), cover_relations=True) @staticmethod def YoungsLattice(n): diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index bc0fa590155..8af515b89aa 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -2232,7 +2232,11 @@ def relations(self): def diamonds(self): r""" - Return a list of all diamonds in the poset. + Returns in a tuple + - a list of all diamonds in the Hasse Diagram, + - a Boolean checking that every w,x,y that form a ``V``, there is a unique element z + which completes the diamond. + For a diamond z / \ @@ -2245,17 +2249,18 @@ def diamonds(self): sage: P = Poset({0: [1,2], 1: [3], 2: [3], 3: []}) sage: P.diamonds() - [(0, 1, 2, 3)] + ([(0, 1, 2, 3)], True) TESTS:: sage: P = posets.YoungDiagramPoset(Partition([3, 2, 2])) sage: P.diamonds() - [((0, 0), (0, 1), (1, 0), (1, 1)), ((1, 0), (1, 1), (2, 0), (2, 1))] + ([((0, 0), (0, 1), (1, 0), (1, 1)), ((1, 0), (1, 1), (2, 0), (2, 1))], False) + """ - diamonds = self._hasse_diagram.diamonds() - return [tuple(map(self._vertex_to_element, d)) for d in diamonds] + diamonds, all_diamonds_completed = self._hasse_diagram.diamonds() + return ([tuple(map(self._vertex_to_element, d)) for d in diamonds], all_diamonds_completed) def common_upper_covers(self, elmts): r""" @@ -2269,6 +2274,93 @@ def common_upper_covers(self, elmts): """ vertices = list(map(self._element_to_vertex, elmts)) return list(map(self._vertex_to_element, self._hasse_diagram.common_upper_covers(vertices))) + + @staticmethod + def is_d_complete(poset): + r""" + Return True if a poset is d-complete. Otherwise, return False. + + TESTS:: + + sage: from sage.combinat.posets.posets import FinitePoset + sage: A = Poset({0: [1,2]}) + sage: FinitePoset.is_d_complete(A) + False + + sage: from sage.combinat.posets.poset_examples import Posets + sage: B = Posets.DoubleTailedDiamond(3) + sage: FinitePoset.is_d_complete(B) + True + + sage: C = Poset({0: [2], 1: [2], 2: [3, 4], 3: [5], 4: [5], 5: [6]}) + sage: FinitePoset.is_d_complete(C) + False + + sage: D = Poset({0: [1, 2], 1: [4], 2: [4], 3: [4]}) + sage: FinitePoset.is_d_complete(D) + False + + sage: E = Posets.YoungDiagramPoset(Partition([3, 2, 2]), dual=True) + sage: FinitePoset.is_d_complete(E) + True + """ + + min_diamond = {} # Maps max of double-tailed diamond to min of double-tailed diamond + max_diamond = {} # Maps min of double-tailed diamond to max of double-tailed diamond + + diamonds, all_diamonds_completed = poset.diamonds() # Tuples of four elements that are diamonds + + if not all_diamonds_completed: + return False + + diamond_index = {} # Map max elmt of double tailed diamond to index of diamond + + # Find all the double-tailed diamonds and map the mins and maxes. + for index, d in enumerate(diamonds): + min_diamond[d[3]] = d[0] + max_diamond[d[0]] = d[3] + diamond_index[d[3]] = index + + min_elmt = d[0] + max_elmt = d[3] + + if len(poset.lower_covers(max_elmt)) != 2: + # Top of diamond cannot cover anything but the two side elements + return False + + while True: + potential_min = poset.lower_covers(min_elmt) + potential_max = poset.upper_covers(max_elmt) + max_dk_minus = max_elmt + + # Check if any of these make a longer double tailed diamond + found_diamond = False + for mn in potential_min: + if len(poset._hasse_diagram.all_paths(poset._element_to_vertex(mn), poset._element_to_vertex(max_dk_minus))) > 2: + continue + for mx in potential_max: + + if len(poset._hasse_diagram.all_paths(poset._element_to_vertex(mn), poset._element_to_vertex(mx))) == 2: + + if len(poset.lower_covers(mx)) != 1: + # Max element covers something outside of double tailed diamond + return False + # Success + if mx in min_diamond or mn in max_diamond: + # Two double tail diamonds that differ by minimal element + # or the dual + return False + min_elmt = mn + max_elmt = mx + + min_diamond[mx] = mn + max_diamond[mn] = mx + diamond_index[mx] = index + found_diamond = True + if not found_diamond: + break + + return True def intervals_poset(self): r""" From e3606cd053e367bd8fba89a8a6a3ab8f11be6fc9 Mon Sep 17 00:00:00 2001 From: Stefan Grosser Date: Sun, 5 Jul 2020 20:46:55 -0400 Subject: [PATCH 050/217] changed _hooks and is_d_complete to run on the Hasse diagram --- src/sage/combinat/posets/d_complete.py | 23 ++++++++++++----------- src/sage/combinat/posets/posets.py | 16 +++++++++------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index 2cb3d2dd8c9..8904f3d6547 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -77,8 +77,10 @@ def _hooks(self): min_diamond = {} # Maps max of double-tailed diamond to min of double-tailed diamond max_diamond = {} # Maps min of double-tailed diamond to max of double-tailed diamond + + H = self._hasse_diagram - diamonds, _ = self.diamonds() # Tuples of four elements that are diamonds + diamonds, _ = H.diamonds() # Tuples of four elements that are diamonds diamond_index = {} # Map max elmt of double tailed diamond to index of diamond @@ -92,16 +94,16 @@ def _hooks(self): max_elmt = d[3] while True: - potential_min = self.lower_covers(min_elmt) + potential_min = H.neighbors_in(min_elmt) - potential_max = self.upper_covers(max_elmt) + potential_max = H.neighbors_out(max_elmt) # Check if any of these make a longer double tailed diamond found_diamond = False for (mn, mx) in [(i,j) for i in potential_min for j in potential_max]: - if len(self.lower_covers(mx)) != 1: + if len(H.neighbors_in(mx)) != 1: continue - if len(self._hasse_diagram.all_paths(self._element_to_vertex(mn), self._element_to_vertex(mx))) == 2: + if len(H.all_paths(mn, mx)) == 2: # Success min_elmt = mn max_elmt = mx @@ -113,15 +115,13 @@ def _hooks(self): break if not found_diamond: break - # Compute the hooks - queue = deque(self.minimal_elements()) + queue = deque(H.sources()) enqueued = set() while queue: elmt = queue.popleft() - if elmt not in diamond_index: - hooks[elmt] = self.order_ideal_cardinality([elmt]) + hooks[elmt] = H.order_ideal_cardinality([elmt]) else: diamond = diamonds[diamond_index[elmt]] side1 = diamond[1] @@ -129,12 +129,13 @@ def _hooks(self): hooks[elmt] = hooks[side1] + hooks[side2] - hooks[min_diamond[elmt]] enqueued.add(elmt) - for c in self.upper_covers(elmt): + for c in H.neighbors_out(elmt): if c not in enqueued: queue.append(c) enqueued.add(c) - return hooks + poset_hooks = {self._vertex_to_element(key): value for (key, value) in hooks.items()} + return poset_hooks def get_hook(self, elmt): r""" diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 8af515b89aa..27bcc087414 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -2307,8 +2307,10 @@ def is_d_complete(poset): min_diamond = {} # Maps max of double-tailed diamond to min of double-tailed diamond max_diamond = {} # Maps min of double-tailed diamond to max of double-tailed diamond + + H = poset._hasse_diagram - diamonds, all_diamonds_completed = poset.diamonds() # Tuples of four elements that are diamonds + diamonds, all_diamonds_completed = H.diamonds() # Tuples of four elements that are diamonds if not all_diamonds_completed: return False @@ -2324,25 +2326,25 @@ def is_d_complete(poset): min_elmt = d[0] max_elmt = d[3] - if len(poset.lower_covers(max_elmt)) != 2: + if len(H.neighbors_in(max_elmt)) != 2: # Top of diamond cannot cover anything but the two side elements return False while True: - potential_min = poset.lower_covers(min_elmt) - potential_max = poset.upper_covers(max_elmt) + potential_min = H.neighbors_in(min_elmt) + potential_max = H.neighbors_out(max_elmt) max_dk_minus = max_elmt # Check if any of these make a longer double tailed diamond found_diamond = False for mn in potential_min: - if len(poset._hasse_diagram.all_paths(poset._element_to_vertex(mn), poset._element_to_vertex(max_dk_minus))) > 2: + if len(H.all_paths(mn, max_dk_minus)) > 2: continue for mx in potential_max: - if len(poset._hasse_diagram.all_paths(poset._element_to_vertex(mn), poset._element_to_vertex(mx))) == 2: + if len(H.all_paths(mn, mx)) == 2: - if len(poset.lower_covers(mx)) != 1: + if len(H.neighbors_in(mx)) != 1: # Max element covers something outside of double tailed diamond return False # Success From 7710e0cf9d98c8d45049a93b94ec29c37ff5ab5e Mon Sep 17 00:00:00 2001 From: Stefan Grosser Date: Sun, 5 Jul 2020 21:28:11 -0400 Subject: [PATCH 051/217] made _desc and _lin_ext_type class attributes of FinitePoset so _repr_ and linear_extensions dont need to be overloaded --- src/sage/combinat/posets/d_complete.py | 8 +++- src/sage/combinat/posets/forest.py | 34 ++------------ src/sage/combinat/posets/lattices.py | 46 +++---------------- src/sage/combinat/posets/linear_extensions.py | 4 ++ src/sage/combinat/posets/posets.py | 12 +++-- 5 files changed, 30 insertions(+), 74 deletions(-) diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index 8904f3d6547..2bc3be202e4 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -10,6 +10,7 @@ from sage.combinat.posets.posets import Poset, FinitePoset from sage.misc.lazy_attribute import lazy_attribute +from .linear_extensions import LinearExtensionsOfPosetWithHooks class DCompletePoset(FinitePoset): r""" @@ -39,6 +40,11 @@ class DCompletePoset(FinitePoset): See also the other tests in the class documentation. """ + + def __init__(self, hasse_diagram, elements, category, facade, key): + FinitePoset.__init__(self, hasse_diagram=hasse_diagram, elements=elements, category=category, facade=facade, key=key) + self._lin_ext_type = LinearExtensionsOfPosetWithHooks + self._desc = "Finite d-complete poset" def _repr_(self): r""" @@ -213,6 +219,6 @@ def linear_extensions(self, facade=False): [5, 2, 4, 3, 1, 0], [5, 4, 2, 3, 1, 0]] """ - from .linear_extensions import LinearExtensionsOfPosetWithHooks + return LinearExtensionsOfPosetWithHooks(self, facade=facade) \ No newline at end of file diff --git a/src/sage/combinat/posets/forest.py b/src/sage/combinat/posets/forest.py index 78b15cf88f0..6f32a3b7f65 100644 --- a/src/sage/combinat/posets/forest.py +++ b/src/sage/combinat/posets/forest.py @@ -10,6 +10,7 @@ from sage.combinat.posets.posets import Poset, FinitePoset from sage.misc.lazy_attribute import lazy_attribute +from .linear_extensions import LinearExtensionsOfForest class ForestPoset(FinitePoset): r""" @@ -17,37 +18,8 @@ class ForestPoset(FinitePoset): directed acyclic graph. """ - - def _repr_(self): - r""" - TESTS:: - - sage: from sage.combinat.posets.forest import ForestPoset - sage: P = ForestPoset(DiGraph({0: [2], 1: [2], 2: [3, 4], 3: [], 4: []})) - sage: P._repr_() - 'Finite forest poset containing 5 elements' - """ - s = "Finite forest poset containing %s elements" % self._hasse_diagram.order() - if self._with_linear_extension: - s += " with distinguished linear extension" - return s def __init__(self, hasse_diagram, elements, category, facade, key): FinitePoset.__init__(self, hasse_diagram=hasse_diagram, elements=elements, category=category, facade=facade, key=key) - - - def linear_extensions(self, facade=False): - r""" - Returns the enumerated set of all the linear extensions of this forest poset - - INPUT: - - - ``facade`` -- a boolean (default: ``False``); - whether to return the linear extensions as plain lists - - EXAMPLES:: - - TESTS:: - """ - from .linear_extensions import LinearExtensionsOfForest - return LinearExtensionsOfForest(self, facade=facade) \ No newline at end of file + self._lin_ext_type = LinearExtensionsOfForest + self._desc = 'Finite forest poset' diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 11718697a2b..2bdb1d3abb9 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -227,25 +227,9 @@ class FiniteMeetSemilattice(FinitePoset): """ Element = MeetSemilatticeElement - def _repr_(self): - r""" - TESTS:: - - sage: M = MeetSemilattice([[1,2],[3],[3]]) - sage: M._repr_() - 'Finite meet-semilattice containing 3 elements' - - :: - - sage: P = Poset([[1,2],[3],[3]]) - sage: M = MeetSemilattice(P) - sage: M._repr_() - 'Finite meet-semilattice containing 3 elements' - """ - s = "Finite meet-semilattice containing %s elements" % self._hasse_diagram.order() - if self._with_linear_extension: - s += " with distinguished linear extension" - return s + def __init__(self, hasse_diagram, elements, category, facade, key): + FinitePoset.__init__(self, hasse_diagram=hasse_diagram, elements=elements, category=category, facade=facade, key=key) + self._desc = 'Finite meet-semilattice' def meet_matrix(self): """ @@ -566,26 +550,10 @@ class FiniteJoinSemilattice(FinitePoset): """ Element = JoinSemilatticeElement - - def _repr_(self): - r""" - TESTS:: - - sage: J = JoinSemilattice([[1,2],[3],[3]]) - sage: J._repr_() - 'Finite join-semilattice containing 3 elements' - - :: - - sage: P = Poset([[1,2],[3],[3]]) - sage: J = JoinSemilattice(P) - sage: J._repr_() - 'Finite join-semilattice containing 3 elements' - """ - s = "Finite join-semilattice containing %s elements" % self._hasse_diagram.order() - if self._with_linear_extension: - s += " with distinguished linear extension" - return s + + def __init__(self, hasse_diagram, elements, category, facade, key): + FinitePoset.__init__(self, hasse_diagram=hasse_diagram, elements=elements, category=category, facade=facade, key=key) + self._desc = 'Finite join-semilattice' def join_matrix(self): """ diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index b14590ccf86..243d857f18b 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -860,6 +860,10 @@ def cardinality(self): Count the number of linear extensions using a hook-length formula """ num_elmts = self._poset.cardinality() + + if num_elmts == 0: + return 1 + hooks = self._poset.get_hooks() hook_product = prod(hooks.values()) return factorial(num_elmts) // hook_product diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 27bcc087414..43ac4fce0e4 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -299,6 +299,7 @@ from sage.combinat.posets.elements import PosetElement from sage.combinat.combinatorial_map import combinatorial_map from sage.combinat.subset import Subsets +from .linear_extensions import LinearExtensionsOfPoset def Poset(data=None, element_labels=None, cover_relations=False, linear_extension=False, category=None, facade=None, key=None): @@ -780,6 +781,10 @@ class FinitePoset(UniqueRepresentation, Parent): set to be the vertex set of the digraph. Note that if this option is set, then ``elements`` is considered as a specified linear extension of the poset and the `linear_extension` attribute is set. + + - ``lin_ext_type`` -- the type of linear extensions that should be returned. + + - ``desc`` -- a string representation used for _repr_. - ``category`` -- :class:`FinitePosets`, or a subcategory thereof. @@ -1053,6 +1058,8 @@ def __init__(self, hasse_diagram, elements, category, facade, key): self._element_to_vertex_dict = {self._elements[i]: i for i in range(len(self._elements))} self._is_facade = facade + self._lin_ext_type = LinearExtensionsOfPoset + self._desc = 'Finite poset' @lazy_attribute def _list(self): @@ -1370,7 +1377,7 @@ def _repr_(self): sage: P5._repr_() 'Finite poset containing 7 elements' """ - s = "Finite poset containing %s elements" % self._hasse_diagram.order() + s = "%s containing %s elements" % (self._desc, self._hasse_diagram.order()) if self._with_linear_extension: s += " with distinguished linear extension" return s @@ -1627,8 +1634,7 @@ def linear_extensions(self, facade=False): sage: list(D.linear_extensions()) [[0, 1, 2, 3, 4], [0, 2, 1, 3, 4], [0, 2, 1, 4, 3], [0, 2, 4, 1, 3], [0, 1, 2, 4, 3]] """ - from .linear_extensions import LinearExtensionsOfPoset - return LinearExtensionsOfPoset(self, facade = facade) + return self._lin_ext_type(self, facade = facade) def spectrum(self, a): r""" From 8b31261d0be43e63bccc72a59cae67510ecf6a24 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 5 Jul 2020 22:36:32 -0700 Subject: [PATCH 052/217] sage.symbolic.assumptions.GenericDeclaration: Make it a UniqueRepresentation --- src/sage/symbolic/assumptions.py | 45 +++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/src/sage/symbolic/assumptions.py b/src/sage/symbolic/assumptions.py index 3e0ca736ba5..c29d0d6adc5 100644 --- a/src/sage/symbolic/assumptions.py +++ b/src/sage/symbolic/assumptions.py @@ -71,11 +71,13 @@ from sage.structure.sage_object import SageObject from sage.rings.all import ZZ, QQ, RR, CC from sage.symbolic.ring import is_SymbolicVariable +from sage.structure.unique_representation import UniqueRepresentation + _assumptions = [] _valid_feature_strings = set() -class GenericDeclaration(SageObject): +class GenericDeclaration(UniqueRepresentation): """ This class represents generic assumptions, such as a variable being an integer or a function being increasing. It passes such @@ -107,6 +109,12 @@ class GenericDeclaration(SageObject): sage: maxima('features') [integer,noninteger,even,odd,rational,irrational,real,imaginary,complex,analytic,increasing,decreasing,oddfun,evenfun,posfun,constant,commutative,lassociative,rassociative,symmetric,antisymmetric,integervalued] + + Test unique representation behavior:: + + sage: GenericDeclaration(x, 'integer') is GenericDeclaration(SR.var("x"), 'integer') + True + """ def __init__(self, var, assumption): @@ -256,18 +264,49 @@ def assume(self): sage: decl.forget() """ from sage.calculus.calculus import maxima + cur = None + context = None if self._context is None: self._validate_feature() cur = maxima.get("context") - self._context = maxima.newcontext('context' + maxima._next_var_name()) + # newcontext makes a fresh context that only has $global as + # a subcontext, and makes it the current $context, + # but does not deactivate other current contexts. + context = maxima.newcontext('context' + maxima._next_var_name()) + must_declare = True + elif not maxima.featurep(self._var, self._assumption): + # Reactivating a previously active context. + # Run $declare again with the assumption + # to catch possible inconsistency + # with the active contexts. + cur = maxima.get("context") + # Redeclaring on the existing context does not seem to trigger + # inconsistency checking. + ## maxima.set("context", self._context._maxima_init_()) + # Instead, use a temporary context for this purpose + context = maxima.newcontext('context' + maxima._next_var_name()) + must_declare = True + else: + must_declare = False + + if must_declare: try: maxima.eval("declare(%s, %s)" % (self._var._maxima_init_(), self._assumption)) except RuntimeError as mess: if 'inconsistent' in str(mess): # note Maxima doesn't tell you if declarations are redundant + # Inconsistency with one of the active contexts. raise ValueError("Assumption is inconsistent") else: raise - maxima.set("context", cur) + else: + if self._context is None: + self._context = context + context = None + finally: + assert cur is not None + maxima.set("context", cur) + if context is not None: + maxima.killcontext(context) if not self in _assumptions: maxima.activate(self._context) From 51ea23d9a4d75d66ddef7b1670d14e5324909183 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 5 Jul 2020 23:19:40 -0700 Subject: [PATCH 053/217] sage.symbolic.assumptions.GenericDeclaration.assume: Check first if already in _assumptions --- src/sage/symbolic/assumptions.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sage/symbolic/assumptions.py b/src/sage/symbolic/assumptions.py index c29d0d6adc5..8f2045f006f 100644 --- a/src/sage/symbolic/assumptions.py +++ b/src/sage/symbolic/assumptions.py @@ -263,6 +263,8 @@ def assume(self): ValueError: Assumption is inconsistent sage: decl.forget() """ + if self in _assumptions: + return from sage.calculus.calculus import maxima cur = None context = None @@ -308,10 +310,9 @@ def assume(self): if context is not None: maxima.killcontext(context) - if not self in _assumptions: - maxima.activate(self._context) - self._var.decl_assume(self._assumption) - _assumptions.append(self) + maxima.activate(self._context) + self._var.decl_assume(self._assumption) + _assumptions.append(self) def forget(self): """ From 9119e82f95e36847383ca29a9d5a96376c35fde0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 5 Jul 2020 23:45:22 -0700 Subject: [PATCH 054/217] sage.symbolic.assumptions._assumptions: Change from list to OrderDict --- src/sage/symbolic/assumptions.py | 13 +++++++------ src/sage/symbolic/expression.pyx | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/sage/symbolic/assumptions.py b/src/sage/symbolic/assumptions.py index 8f2045f006f..6dad76040c5 100644 --- a/src/sage/symbolic/assumptions.py +++ b/src/sage/symbolic/assumptions.py @@ -73,7 +73,8 @@ from sage.symbolic.ring import is_SymbolicVariable from sage.structure.unique_representation import UniqueRepresentation -_assumptions = [] +from collections import OrderedDict +_assumptions = OrderedDict() _valid_feature_strings = set() @@ -312,7 +313,7 @@ def assume(self): maxima.activate(self._context) self._var.decl_assume(self._assumption) - _assumptions.append(self) + _assumptions[self] = True def forget(self): """ @@ -335,8 +336,8 @@ def forget(self): from sage.calculus.calculus import maxima if self._context is not None: try: - _assumptions.remove(self) - except ValueError: + del _assumptions[self] + except KeyError: return maxima.deactivate(self._context) else: # trying to forget a declaration explicitly rather than implicitly @@ -849,9 +850,9 @@ def _forget_all(): if not(_assumptions): return #maxima._eval_line('forget([%s]);'%(','.join([x._maxima_init_() for x in _assumptions]))) - for x in _assumptions[:]: # need to do this because x.forget() removes x from _assumptions + for x in list(_assumptions): # need to do this because x.forget() removes x from _assumptions x.forget() - _assumptions = [] + _assumptions = OrderedDict() class assuming: diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 7dff02cc00a..b5315c41fda 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -2021,7 +2021,7 @@ cdef class Expression(CommutativeRingElement): pynac_assume_rel(self._gobj) if str(s._sage_()[0]) in ['meaningless','inconsistent','redundant']: raise ValueError("Assumption is %s" % str(s._sage_()[0])) - _assumptions.append(self) + _assumptions[self] = True def forget(self): """ @@ -2067,8 +2067,8 @@ cdef class Expression(CommutativeRingElement): m = self._maxima_init_assume_() maxima.forget(m) try: - _assumptions.remove(self) - except ValueError: + del _assumptions[self] + except KeyError: pass def _maxima_init_assume_(self): From cda81ff3e8a54f4ec09fecd04a0673866736940a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 5 Jul 2020 23:46:04 -0700 Subject: [PATCH 055/217] sage.symbolic.assumptions.GenericDeclaration: Make it hashable by inheriting comparisons from UniqueRepresentation --- src/sage/symbolic/assumptions.py | 39 -------------------------------- 1 file changed, 39 deletions(-) diff --git a/src/sage/symbolic/assumptions.py b/src/sage/symbolic/assumptions.py index 6dad76040c5..760acbf710f 100644 --- a/src/sage/symbolic/assumptions.py +++ b/src/sage/symbolic/assumptions.py @@ -163,45 +163,6 @@ def __repr__(self): """ return "%s is %s" % (self._var, self._assumption) - def __eq__(self, other): - """ - Check whether ``self`` and ``other`` are equal. - - TESTS:: - - sage: from sage.symbolic.assumptions import GenericDeclaration as GDecl - sage: var('y') - y - sage: GDecl(x, 'integer') == GDecl(x, 'integer') - True - sage: GDecl(x, 'integer') == GDecl(x, 'rational') - False - sage: GDecl(x, 'integer') == GDecl(y, 'integer') - False - """ - if not isinstance(other, GenericDeclaration): - return False - return (bool(self._var == other._var) and - self._assumption == other._assumption) - - def __ne__(self, other): - """ - Check whether ``self`` and ``other`` are not equal. - - TESTS:: - - sage: from sage.symbolic.assumptions import GenericDeclaration as GDecl - sage: var('y') - y - sage: GDecl(x, 'integer') != GDecl(x, 'integer') - False - sage: GDecl(x, 'integer') != GDecl(x, 'rational') - True - sage: GDecl(x, 'integer') != GDecl(y, 'integer') - True - """ - return not self == other - def has(self, arg): """ Check if this assumption contains the argument ``arg``. From 642836dc080f10de1da5a502ccb8bad19113c46b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 7 Jul 2020 09:20:05 -0700 Subject: [PATCH 056/217] sage.symbolic.assumptions: Use dict instead of OrderedDict for _assumptions --- src/sage/symbolic/assumptions.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/sage/symbolic/assumptions.py b/src/sage/symbolic/assumptions.py index 760acbf710f..1eda9935a93 100644 --- a/src/sage/symbolic/assumptions.py +++ b/src/sage/symbolic/assumptions.py @@ -73,8 +73,11 @@ from sage.symbolic.ring import is_SymbolicVariable from sage.structure.unique_representation import UniqueRepresentation -from collections import OrderedDict -_assumptions = OrderedDict() +# #30074: We use the keys of a dict to store the assumptions. +# As of Python 3.6.x, dicts preserve the insertion order. +# In this way, we keep the same order of the assumptions +# as previous code that was using lists. +_assumptions = dict() _valid_feature_strings = set() @@ -813,7 +816,7 @@ def _forget_all(): #maxima._eval_line('forget([%s]);'%(','.join([x._maxima_init_() for x in _assumptions]))) for x in list(_assumptions): # need to do this because x.forget() removes x from _assumptions x.forget() - _assumptions = OrderedDict() + _assumptions = dict() class assuming: From fccbf438290e2404a79a4c7a650721120157a6c0 Mon Sep 17 00:00:00 2001 From: Eric Gourgoulhon Date: Tue, 7 Jul 2020 18:32:03 +0200 Subject: [PATCH 057/217] Improve initialization of elements of a free module basis --- src/sage/tensor/modules/free_module_basis.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/sage/tensor/modules/free_module_basis.py b/src/sage/tensor/modules/free_module_basis.py index c174570d46c..791b9549eaf 100644 --- a/src/sage/tensor/modules/free_module_basis.py +++ b/src/sage/tensor/modules/free_module_basis.py @@ -389,11 +389,11 @@ def __init__(self, basis, symbol, latex_symbol=None, indices=None, indices, latex_indices) # The individual linear forms: vl = list() - for i in self._fmodule.irange(): - v = self._fmodule.linear_form() - for j in self._fmodule.irange(): - v.set_comp(basis)[j] = 0 - v.set_comp(basis)[i] = 1 + fmodule = self._fmodule + ring_one = fmodule._ring.one() + for i in fmodule.irange(): + v = fmodule.linear_form() + v.set_comp(basis)[i] = ring_one vl.append(v) self._vec = tuple(vl) # The names: @@ -583,11 +583,10 @@ def __init__(self, fmodule, symbol, latex_symbol=None, indices=None, fmodule._known_bases.append(self) # The individual vectors: vl = list() + ring_one = fmodule._ring.one() for i in fmodule.irange(): v = fmodule.element_class(fmodule) - for j in fmodule.irange(): - v.set_comp(self)[j] = fmodule._ring.zero() - v.set_comp(self)[i] = fmodule._ring.one() + v.set_comp(self)[i] = ring_one vl.append(v) self._vec = tuple(vl) # The names: From bfb2fb439694e7fee3e2a0adfd4b4367915362eb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 7 Jul 2020 17:57:09 -0700 Subject: [PATCH 058/217] tox.ini: Add environment local-homebrew-usrlocal --- tox.ini | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index ce7daee90b3..4219055fe11 100644 --- a/tox.ini +++ b/tox.ini @@ -65,6 +65,10 @@ envlist = # # $ tox -e local-homebrew-macos-standard -- ppl-clean ppl V=1 # + # The variant "local-homebrew-macos-usrlocal" uses the global installation in /usr/local + # instead. It may install packages or update packages. It will not remove packages. + # Use at your own risk. + # local-homebrew-macos } -{### @@ -271,6 +275,7 @@ setenv = local-!direct: PATH=/usr/bin:/bin:/usr/sbin:/sbin # brew caches downloaded files in ${HOME}/Library/Caches. We share it between different toxenvs. local-homebrew: HOMEBREW={envdir}/homebrew + local-homebrew-usrlocal: HOMEBREW=/usr/local local-homebrew: PATH={env:HOMEBREW}/bin:/usr/bin:/bin:/usr/sbin:/sbin local-homebrew-nokegonly: BOOTSTRAP=ACLOCAL_PATH="$HOMEBREW/opt/gettext/share/aclocal:$ACLOCAL_PATH" PATH="$HOMEBREW/opt/gettext/bin/:$PATH" ./bootstrap local-homebrew-!nokegonly: SETENV=. .homebrew-build-env @@ -322,7 +327,7 @@ commands = # local-homebrew # # https://docs.brew.sh/Installation - homebrew: bash -c 'if [ ! -x {env:HOMEBREW}/bin/brew ]; then mkdir -p {envdir}/homebrew && cd {envdir}/homebrew && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 ; fi' + homebrew: bash -c 'if [ ! -x {env:HOMEBREW}/bin/brew ]; then mkdir -p {env:HOMEBREW} && cd {env:HOMEBREW} && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 ; fi' # homebrew-minimal: Minimal for bootstrapping and build. # gettext and pkg-config are needed so that their aclocal macros are available. homebrew: bash -c 'PACKAGES=`sed "s/#.*//;" build/pkgs/homebrew*.txt`; {env:HOMEBREW}/bin/brew install $PACKAGES; {env:HOMEBREW}/bin/brew upgrade $PACKAGES' From e9a452008ac35064258f7889851d72ac640eb083 Mon Sep 17 00:00:00 2001 From: vipul79321 Date: Thu, 9 Jul 2020 11:12:43 +0530 Subject: [PATCH 059/217] Fixed segmentation fault in 2dsweep --- src/sage/graphs/base/boost_graph.pyx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx index a4e7e0147f0..9b60e789714 100644 --- a/src/sage/graphs/base/boost_graph.pyx +++ b/src/sage/graphs/base/boost_graph.pyx @@ -1808,7 +1808,7 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, LB_1 = 0 for v in range(n): - if result_1.distances[v] > LB_1: + if result_1.distances[v] >= LB_1: LB_1 = result_1.distances[v] antipode_1 = v @@ -1831,7 +1831,7 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, LB_2 = 0 for v in range(n): - if result_2.distances[v] > LB_2: + if result_2.distances[v] >= LB_2: LB_2 = result_2.distances[v] antipode_2 = v @@ -1858,7 +1858,7 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, LB_1 = 0 for v in range(n): - if result_1.distances[v] > LB_1: + if result_1.distances[v] >= LB_1: LB_1 = result_1.distances[v] antipode_1 = v @@ -1878,7 +1878,7 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, LB_2 = 0 for v in range(n): - if result_2.distances[v] > LB_2: + if result_2.distances[v] >= LB_2: LB_2 = result_2.distances[v] antipode_2 = v @@ -2130,6 +2130,14 @@ cpdef diameter(G, algorithm=None, source=None, +Infinity sage: diameter(G, algorithm='2Dsweep') +Infinity + + DiGraph containing negative cycle + + sage: G = DiGraph([(0,1,-2), (1,0,1)]) + sage: diameter(G, algorithm='2Dsweep', weight_function=lambda e:e[2]) + Traceback (most recent call last): + ... + ValueError: the graph contains a negative cycle """ import sys From f7e1ad5313c6e861f8bcdd06d62ce76e96492154 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Thu, 9 Jul 2020 15:40:40 +0200 Subject: [PATCH 060/217] trac 30039: review commit --- src/sage/graphs/base/boost_graph.pyx | 162 ++++++++++++++++----------- 1 file changed, 97 insertions(+), 65 deletions(-) diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx index 5f9053754a7..e8a2fa9efa9 100644 --- a/src/sage/graphs/base/boost_graph.pyx +++ b/src/sage/graphs/base/boost_graph.pyx @@ -1941,21 +1941,23 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, This method implements the weighted version of the algorithm proposed in [Broder2000]_ to compute a lower bound of the weighted digraph `G`. - In first part, it computes forward distances from `source` and selects a - vertex `vf` at a maximum forward distance from `source` and then it - calculates backward eccentricity from `vf`. - - In second part, it computes backward distances from `source` and selects a - vertex `vb` at a maximum backward distance from `source` and then it - calculates forward eccentricity from `vb`. - - It then calculates lower bound LB of diameter as the maximum of - backward eccentricity of `vf` and forward eccentricity of `vb` and `s` as - respective source vertex. - - This method returns (`LB`, `s`, `m`, `d`), where `LB` is best found lower - bound on diameter, `s` is vertex whose forward / backward eccentricity is - `LB`, `d` is vertex at a distance `LB` from / to `s` , `m` is vertex at + Firstly, this method fcomputes forward distances from `source` and selects a + vertex `vf` at maximum forward distance from `source` (i.e. an + antipode). Then, it computes backward eccentricity of `vf`. Observe that the + backward eccentricity of `vf` is at least the forward eccentricity of + `source`. + + Secondly, this method computes backward distances from `source` and selects + a vertex `vb` at maximum backward distance from `source`. Then, it computes + the forward eccentricity of `vb`, which is at least the backward + eccentricity of `source`. + + The lower bound on the diameter is the maximum among the backward + eccentricity of `vf` and forward eccentricity of `vb`. + + The method returns `(LB, s, m, d)`, where `LB` is best found lower bound on + diameter, `s` is a vertex whose forward / backward eccentricity is `LB`, `d` + is a vertex at a distance `LB` from / to `s` , and `m` is a vertex at distance `LB/2` from / to both `s` and `d`. INPUT: @@ -1969,10 +1971,25 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, - ``algorithm`` -- string; algorithm for computing single source shortest distances. If ``g_boost`` contains negative edge weights then it will be ``Bellman-Ford``, otherwise it will be ``Dijkstra_Boost``. + + TESTS:: + + sage: from sage.graphs.base.boost_graph import diameter + sage: G = DiGraph() + sage: diameter(DiGraph(), algorithm='2Dsweep') + 0 + sage: diameter(DiGraph(1), algorithm='2Dsweep') + 0 + sage: diameter(DiGraph(2), algorithm='2Dsweep') + +Infinity """ import sys - # These variables are automatically deleted when the function terminates. + cdef int n = g_boost.num_verts() + + if n == 1: + return (0, 0, 0, 0) + cdef v_index source_1, source_2, m, s, d, antipode_1, antipode_2, v cdef double LB_1 = 0, LB_2 = 0, LB, LB_m cdef result_distances result_1, result_2 @@ -1980,9 +1997,8 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, # Algorithm - # 1). Compute Forward distances from source_1 to all vertices and obtain its - # Forward eccentricity and obtain its antipode, that is vertex at maximum - # forward distance. + # 1) Compute forward distances from source_1. + # Get forward eccentricity and antipode (vertex at maximum forward distance) if algorithm == 'Bellman-Ford': sig_on() result_1 = g_boost.bellman_ford_shortest_paths(source_1) @@ -1994,65 +2010,62 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, if not result_1.distances.size(): raise ValueError("the graph contains a negative cycle") - LB_1 = 0 + LB_1 = -sys.float_info.max for v in range(n): - if result_1.distances[v] >= LB_1: + if result_1.distances[v] > LB_1: LB_1 = result_1.distances[v] antipode_1 = v if LB_1 == sys.float_info.max: return (LB_1, 0, 0, 0) - # 2). Compute Backward distances from source_2 to all vertices and obtain - # its Backward eccentricity and obtain its antipode, that is vertex at - # maximum backward distance. + + # 2) Compute backward distances from antipode_1. + source_1, antipode_1 = antipode_1, source_1 if algorithm == 'Bellman-Ford': sig_on() - result_2 = rev_g_boost.bellman_ford_shortest_paths(source_2) + result_1 = rev_g_boost.bellman_ford_shortest_paths(source_1) sig_off() else: sig_on() - result_2 = rev_g_boost.dijkstra_shortest_paths(source_2) + result_1 = rev_g_boost.dijkstra_shortest_paths(source_1) sig_off() - if not result_2.distances.size(): + if not result_1.distances.size(): raise ValueError("the graph contains a negative cycle") - LB_2 = 0 for v in range(n): - if result_2.distances[v] >= LB_2: - LB_2 = result_2.distances[v] - antipode_2 = v + if result_1.distances[v] > LB_1: + LB_1 = result_1.distances[v] + antipode_1 = v - if LB_2 == sys.float_info.max: - return (LB_2, 0, 0, 0) + if LB_1 == sys.float_info.max: + return (LB_1, 0, 0, 0) - # Now use antipode_1, antipode_2 as source_1, source_2 respectively. - source_1 = antipode_1 - source_2 = antipode_2 - # 3). Compute Backward distances from source_1 to all vertices and obtain - # its Backward eccentricity and obtain its antipode, that is vertex at - # maximum backward distance. LB_1 will be Backward eccentricity of source_1. + # 3) Compute backward distances from source_2. + # Get backward eccentricity and antipode. if algorithm == 'Bellman-Ford': sig_on() - result_1 = rev_g_boost.bellman_ford_shortest_paths(source_1) + result_2 = rev_g_boost.bellman_ford_shortest_paths(source_2) sig_off() else: sig_on() - result_1 = rev_g_boost.dijkstra_shortest_paths(source_1) + result_2 = rev_g_boost.dijkstra_shortest_paths(source_2) sig_off() - if not result_1.distances.size(): + if not result_2.distances.size(): raise ValueError("the graph contains a negative cycle") - LB_1 = 0 + LB_2 = -sys.float_info.max for v in range(n): - if result_1.distances[v] >= LB_1: - LB_1 = result_1.distances[v] - antipode_1 = v + if result_2.distances[v] > LB_2: + LB_2 = result_2.distances[v] + antipode_2 = v - # 4). Compute Forward distances from source_2 to all vertices and obtain its - # Forward eccentricity and obtain its antipode, that is vertex at maximum - # forward distance. LB_2 will be Forward eccentricity of source_2. + if LB_2 == sys.float_info.max: + return (LB_2, 0, 0, 0) + + # 4) Compute forward distances from antipode_2. + source_2, antipode_2 = antipode_2, source_2 if algorithm == 'Bellman-Ford': sig_on() result_2 = g_boost.bellman_ford_shortest_paths(source_2) @@ -2064,15 +2077,17 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, if not result_2.distances.size(): raise ValueError("the graph contains a negative cycle") - LB_2 = 0 for v in range(n): - if result_2.distances[v] >= LB_2: + if result_2.distances[v] > LB_2: LB_2 = result_2.distances[v] antipode_2 = v - # We will select best found lower bound as LB and s, d as corresponding - # source and antipode respectively. And m as vertex at a distance LB/2 - # from/to both s and d. + if LB_2 == sys.float_info.max: + return (LB_2, 0, 0, 0) + + + # 5) Select best found lower bound as LB with corresponding source s and + # antipode d. Then find a vertex m at a distance LB/2 from/to both s and d. if LB_1 < LB_2: LB = LB_2 s = source_2 @@ -2120,10 +2135,24 @@ cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, - ``algorithm`` -- string; algorithm for computing single source shortest distances. If ``g_boost`` contains negative edge weights then it will be ``Bellman-Ford``, otherwise it will be ``Dijkstra_Boost``. + + TESTS:: + + sage: from sage.graphs.base.boost_graph import diameter + sage: G = DiGraph() + sage: diameter(DiGraph(), algorithm='DiFUB') + 0 + sage: diameter(DiGraph(1), algorithm='DiFUB') + 0 + sage: diameter(DiGraph(2), algorithm='DiFUB') + +Infinity """ + cdef int n = g_boost.num_verts() + if n <= 1: + return 0 + import sys # These variables are automatically deleted when the function terminates. - cdef int n = g_boost.num_verts() cdef double LB, LB_1, LB_2, UB cdef v_index s, m, d, v, tmp cdef size_t i @@ -2153,10 +2182,10 @@ cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, # Obtain Forward eccentricity of `m` and store pair of # forward distances, vertex in order_1 - LB_1 = 0 + LB_1 = -sys.float_info.max for v in range(n): LB_1 = max(LB_1, distances[v]) - order_1.push_back(pair[double, v_index](distances[v], v)) + order_1.push_back(pair[double,v_index](distances[v], v)) # Compute Backward distances from `m`. if algorithm == 'Bellman-Ford': sig_on() @@ -2171,10 +2200,10 @@ cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, # Obtain Backward eccentricity of `m` and store pair of # backward distances, vertex in order_2. - LB_2 = 0 + LB_2 = -sys.float_info.max for v in range(n): LB_2 = max(LB_2, distances[v]) - order_2.push_back(pair[double, v_index](distances[v], v)) + order_2.push_back(pair[double,v_index](distances[v], v)) # Now sort order_1 / order_2 in decreasing order of forward / backward # distances respectively. @@ -2231,7 +2260,7 @@ cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, if not distances.size(): raise ValueError("the graph contains a negative cycle") - LB_1 = 0 + LB_1 = -sys.float_info.max for tmp in range(n): LB_1 = max(LB_1, distances[tmp]) @@ -2247,7 +2276,7 @@ cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, if not distances.size(): raise ValueError("the graph contains a negative cycle") - LB_2 = 0 + LB_2 = -sys.float_info.max for tmp in range(n): LB_2 = max(LB_2, distances[tmp]) @@ -2303,15 +2332,18 @@ cpdef diameter(G, algorithm=None, source=None, EXAMPLES:: sage: from sage.graphs.base.boost_graph import diameter - sage: G = DiGraph([(0,1,2), (1,0,-1)]) + sage: G = DiGraph([(0, 1, 2), (1, 0, -1)]) sage: diameter(G, algorithm='DiFUB') 1.0 sage: diameter(G, algorithm='DiFUB', weight_function=lambda e:e[2]) 2.0 + sage: G = DiGraph([(0, 1, -1), (1, 0, 2)]) + sage: diameter(G, algorithm='DiFUB', weight_function=lambda e:e[2]) + 2.0 - TESTS:: + TESTS: - Diameter of weakly connected digraph is Infinity + Diameter of weakly connected digraph is Infinity:: sage: G = DiGraph(2) sage: diameter(G, algorithm='DiFUB') @@ -2319,7 +2351,7 @@ cpdef diameter(G, algorithm=None, source=None, sage: diameter(G, algorithm='2Dsweep') +Infinity - DiGraph containing negative cycle + DiGraph containing negative cycle:: sage: G = DiGraph([(0,1,-2), (1,0,1)]) sage: diameter(G, algorithm='2Dsweep', weight_function=lambda e:e[2]) From d033760a973be8fd73d49377c4a00f75ea6f40e5 Mon Sep 17 00:00:00 2001 From: vipul79321 Date: Fri, 10 Jul 2020 11:01:39 +0530 Subject: [PATCH 061/217] minor improvements --- src/sage/graphs/base/boost_graph.pyx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx index e8a2fa9efa9..05dd86481a4 100644 --- a/src/sage/graphs/base/boost_graph.pyx +++ b/src/sage/graphs/base/boost_graph.pyx @@ -1939,9 +1939,12 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, Return a lower bound on the diameter of `G`. This method implements the weighted version of the algorithm proposed - in [Broder2000]_ to compute a lower bound of the weighted digraph `G`. + in [Broder2000]_ to compute a lower bound on the diameter of the + weighted digraph `G`. - Firstly, this method fcomputes forward distances from `source` and selects a + If the digraph is not strongly connected, the returned value is infinity. + + Firstly, this method computes forward distances from `source` and selects a vertex `vf` at maximum forward distance from `source` (i.e. an antipode). Then, it computes backward eccentricity of `vf`. Observe that the backward eccentricity of `vf` is at least the forward eccentricity of @@ -1987,7 +1990,7 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, cdef int n = g_boost.num_verts() - if n == 1: + if n <= 1: return (0, 0, 0, 0) cdef v_index source_1, source_2, m, s, d, antipode_1, antipode_2, v @@ -2086,7 +2089,7 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, return (LB_2, 0, 0, 0) - # 5) Select best found lower bound as LB with corresponding source s and + # 5) Select the best found lower bound as LB with corresponding source s and # antipode d. Then find a vertex m at a distance LB/2 from/to both s and d. if LB_1 < LB_2: LB = LB_2 From 70a6351c733c505722268bf0ba730f5bea6323be Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 10 Jul 2020 13:28:03 -0700 Subject: [PATCH 062/217] sage.libs.ecl.EclObject.__init__: Add optional argument read_strings --- src/sage/libs/ecl.pyx | 80 ++++++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/src/sage/libs/ecl.pyx b/src/sage/libs/ecl.pyx index 1f05f4a5656..9c14e46e8e1 100644 --- a/src/sage/libs/ecl.pyx +++ b/src/sage/libs/ecl.pyx @@ -434,12 +434,13 @@ def print_objects(): if c == Cnil: break -cdef cl_object python_to_ecl(pyobj) except NULL: +cdef cl_object python_to_ecl(pyobj, bint read_strings) except NULL: # conversion of a python object into an ecl object # most conversions are straightforward. Noteworthy are: # python lists -> lisp (NIL terminated) lists # tuples -> dotted lists - # strings ->parsed by lisp reader + # strings -> if read_strings is true, parsed by lisp reader + # otherwise creates a simple-string cdef bytes s cdef cl_object L, ptr @@ -455,17 +456,26 @@ cdef cl_object python_to_ecl(pyobj) except NULL: if pyobj >= MOST_NEGATIVE_FIXNUM and pyobj <= MOST_POSITIVE_FIXNUM: return ecl_make_integer(pyobj) else: - return python_to_ecl(Integer(pyobj)) + return python_to_ecl(Integer(pyobj), read_strings) elif isinstance(pyobj,int): return ecl_make_integer(pyobj) elif isinstance(pyobj,float): return ecl_make_doublefloat(pyobj) elif isinstance(pyobj,unicode): s=str_to_bytes(pyobj) - return ecl_safe_read_string(s) + if read_strings: + return ecl_safe_read_string(s) + else: + b = ecl_cstring_to_base_string_or_nil(s) + # if b == Cnil: + # raise NotImplementedError("Converting unicode to Lisp strings is not implemented") + return b elif isinstance(pyobj,bytes): s=pyobj - return ecl_safe_read_string(s) + if read_strings: + return ecl_safe_read_string(s) + else: + return ecl_cstring_to_base_string_or_nil(s) elif isinstance(pyobj,Integer): if pyobj >= MOST_NEGATIVE_FIXNUM and pyobj <= MOST_POSITIVE_FIXNUM: return ecl_make_integer(pyobj) @@ -473,32 +483,32 @@ cdef cl_object python_to_ecl(pyobj) except NULL: return ecl_bignum_from_mpz( (pyobj).value ) elif isinstance(pyobj,Rational): return ecl_make_ratio( - python_to_ecl( (pyobj).numerator() ), - python_to_ecl( (pyobj).denominator())) + python_to_ecl( (pyobj).numerator(), read_strings ), + python_to_ecl( (pyobj).denominator(), read_strings )) elif isinstance(pyobj,EclObject): return (pyobj).obj elif isinstance(pyobj, list): if not pyobj: return Cnil else: - L=cl_cons(python_to_ecl(pyobj[0]),Cnil) - ptr=L + L = cl_cons(python_to_ecl(pyobj[0], read_strings),Cnil) + ptr = L for a in pyobj[1:]: - cl_rplacd(ptr,cl_cons(python_to_ecl(a),Cnil)) - ptr=cl_cdr(ptr) + cl_rplacd(ptr, cl_cons(python_to_ecl(a, read_strings), Cnil)) + ptr = cl_cdr(ptr) return L elif isinstance(pyobj, tuple): if not pyobj: return Cnil elif len(pyobj) == 1: - return python_to_ecl(pyobj[0]) + return python_to_ecl(pyobj[0], read_strings) else: - L=cl_cons(python_to_ecl(pyobj[0]),Cnil) - ptr=L + L = cl_cons(python_to_ecl(pyobj[0], read_strings), Cnil) + ptr = L for a in pyobj[1:-1]: - cl_rplacd(ptr,cl_cons(python_to_ecl(a),Cnil)) - ptr=cl_cdr(ptr) - cl_rplacd(ptr,python_to_ecl(pyobj[-1])) + cl_rplacd(ptr, cl_cons(python_to_ecl(a, read_strings), Cnil)) + ptr = cl_cdr(ptr) + cl_rplacd(ptr, python_to_ecl(pyobj[-1], read_strings)) return L else: raise TypeError("Unimplemented type for python_to_ecl") @@ -595,6 +605,8 @@ cdef class EclObject: sage: EclObject( (false, true)) + sage: EclObject( (1, 2, 3) ) + Strings are fed to the reader, so a string normally results in a symbol:: @@ -606,6 +618,28 @@ cdef class EclObject: sage: EclObject('"Symbol"') + Or any other object that the Lisp reader can construct:: + + sage: EclObject('#("I" am "just" a "simple" vector)') + + + By means of Lisp reader macros, you can include arbitrary objects:: + + sage: EclObject([ 1, 2, '''#.(make-hash-table :test #'equal)''', 4]) + 4)> + + Using an optional argument, you can control how strings are handled:: + + sage: EclObject("String", False) + + sage: EclObject('#(I may look like a vector but I am a string)', False) + + + This also affects strings within nested lists and tuples :: + + sage: EclObject([1, 2, "String", 4], False) + + EclObjects translate to themselves, so one can mix:: sage: EclObject([1,2,EclObject([3])]) @@ -652,7 +686,7 @@ cdef class EclObject: if not(bint_fixnump(o) or bint_characterp(o) or bint_nullp(o)): self.node=insert_node_after(list_of_objects,o) - def __init__(self,*args): + def __init__(self, *args): r""" Create an EclObject @@ -665,8 +699,14 @@ cdef class EclObject: """ - if len(args) != 0: - self.set_obj(python_to_ecl(args[0])) + if not args: + return + elif len(args) == 1: + self.set_obj(python_to_ecl(args[0], True)) + elif len(args) == 2: + self.set_obj(python_to_ecl(args[0], args[1])) + else: + raise TypeError('EclObject.__init__ received a wrong number of arguments') def __reduce__(self): r""" From 9b6163b9d58dcd0bc917a34d858d4cfe38f4f9d1 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 11 Jul 2020 15:17:04 +0200 Subject: [PATCH 063/217] trac #30039: fix error message and some compilation warnings --- src/sage/graphs/base/boost_graph.pyx | 31 +++++++++++++--------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx index 05dd86481a4..bc161833224 100644 --- a/src/sage/graphs/base/boost_graph.pyx +++ b/src/sage/graphs/base/boost_graph.pyx @@ -720,9 +720,9 @@ cpdef min_spanning_tree(g, result = g_boost.prim_min_spanning_tree() sig_off() - cdef size_t n = g.num_verts() + cdef v_index n = g.num_verts() - if result.size() != 2 * (n - 1): + if result.size() != 2 * (n - 1): return [] else: edges = [(int_to_vertex[ result[2*i]], int_to_vertex[ result[2*i+1]]) for i in range(n-1)] @@ -1665,7 +1665,7 @@ cpdef eccentricity_DHV(g, vertex_list=None, weight_function=None, check_weight=T if g.is_directed(): raise TypeError("the 'DHV' algorithm only works on undirected graphs") - cdef int n = g.order() + cdef v_index n = g.order() if not n: return [] if n == 1: @@ -1696,7 +1696,7 @@ cpdef eccentricity_DHV(g, vertex_list=None, weight_function=None, check_weight=T import sys cdef v_index u, antipode, v cdef double ecc_u, ecc_antipode, tmp - cdef size_t i, idx + cdef v_index i, idx cdef list active = list(range(n)) cdef vector[double] ecc_lower_bound @@ -1994,7 +1994,7 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, return (0, 0, 0, 0) cdef v_index source_1, source_2, m, s, d, antipode_1, antipode_2, v - cdef double LB_1 = 0, LB_2 = 0, LB, LB_m + cdef double LB_1, LB_2, LB, LB_m cdef result_distances result_1, result_2 source_1 = source_2 = source @@ -2113,7 +2113,7 @@ cdef tuple diameter_lower_bound_2Dsweep(BoostVecWeightedDiGraphU g_boost, cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, BoostVecWeightedDiGraphU rev_g_boost, v_index source, - str algorithm): + str algorithm) except? -1: r""" Return the diameter of a weighted directed graph. @@ -2150,7 +2150,7 @@ cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, sage: diameter(DiGraph(2), algorithm='DiFUB') +Infinity """ - cdef int n = g_boost.num_verts() + cdef v_index n = g_boost.num_verts() if n <= 1: return 0 @@ -2158,7 +2158,7 @@ cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, # These variables are automatically deleted when the function terminates. cdef double LB, LB_1, LB_2, UB cdef v_index s, m, d, v, tmp - cdef size_t i + cdef v_index i cdef vector[double] distances cdef vector[pair[double, v_index]] order_1, order_2 @@ -2185,7 +2185,7 @@ cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, # Obtain Forward eccentricity of `m` and store pair of # forward distances, vertex in order_1 - LB_1 = -sys.float_info.max + LB_1 = sys.float_info.min for v in range(n): LB_1 = max(LB_1, distances[v]) order_1.push_back(pair[double,v_index](distances[v], v)) @@ -2203,7 +2203,7 @@ cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, # Obtain Backward eccentricity of `m` and store pair of # backward distances, vertex in order_2. - LB_2 = -sys.float_info.max + LB_2 = sys.float_info.min for v in range(n): LB_2 = max(LB_2, distances[v]) order_2.push_back(pair[double,v_index](distances[v], v)) @@ -2263,7 +2263,7 @@ cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, if not distances.size(): raise ValueError("the graph contains a negative cycle") - LB_1 = -sys.float_info.max + LB_1 = sys.float_info.min for tmp in range(n): LB_1 = max(LB_1, distances[tmp]) @@ -2279,7 +2279,7 @@ cdef double diameter_DiFUB(BoostVecWeightedDiGraphU g_boost, if not distances.size(): raise ValueError("the graph contains a negative cycle") - LB_2 = -sys.float_info.max + LB_2 = sys.float_info.min for tmp in range(n): LB_2 = max(LB_2, distances[tmp]) @@ -2418,12 +2418,9 @@ cpdef diameter(G, algorithm=None, source=None, cdef double LB if algorithm == '2Dsweep': - LB = diameter_lower_bound_2Dsweep(g_boost, rev_g_boost, - isource, algo)[0] - + LB = diameter_lower_bound_2Dsweep(g_boost, rev_g_boost, isource, algo)[0] else: - LB = diameter_DiFUB(g_boost, rev_g_boost, - isource, algo) + LB = diameter_DiFUB(g_boost, rev_g_boost, isource, algo) if LB == sys.float_info.max: from sage.rings.infinity import Infinity From 1f4f9422e393844eb2edbcbd59b8a8b0b4f5daa4 Mon Sep 17 00:00:00 2001 From: Eric Gourgoulhon Date: Sat, 11 Jul 2020 17:53:18 +0200 Subject: [PATCH 064/217] Provide EuclideanSpace with dist() method and add it to category of metric space --- .../manifolds/differentiable/euclidean.py | 55 +++++++++++++++++-- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/src/sage/manifolds/differentiable/euclidean.py b/src/sage/manifolds/differentiable/euclidean.py index 755adf60f06..7c245b6df58 100644 --- a/src/sage/manifolds/differentiable/euclidean.py +++ b/src/sage/manifolds/differentiable/euclidean.py @@ -412,6 +412,9 @@ from sage.functions.trig import cos, sin, atan2 from sage.functions.other import sqrt from sage.misc.latex import latex +from sage.rings.real_mpfr import RR +from sage.categories.manifolds import Manifolds +from sage.categories.metric_spaces import MetricSpaces from sage.manifolds.differentiable.pseudo_riemannian import \ PseudoRiemannianManifold @@ -612,10 +615,11 @@ class EuclideanSpace(PseudoRiemannianManifold): sage: latex(E) \mathbb{E}^{4} - ``E`` is a real smooth manifold of dimension `4`:: + ``E`` is both a real smooth manifold of dimension `4` and a metric space:: sage: E.category() - Category of smooth manifolds over Real Field with 53 bits of precision + Join of Category of differentiable manifolds over Real Field with + 53 bits of precision and Category of metric spaces sage: dim(E) 4 @@ -772,6 +776,10 @@ def __init__(self, n, name=None, latex_name=None, name = 'E^{}'.format(n) if latex_name is None: latex_name = r'\mathbb{E}^{' + str(n) + '}' + if category is None: + category = Manifolds(RR).Differentiable() & MetricSpaces() + # NB: RR is a proxy for the field of real numbers, until + # Trac #24456 is ready PseudoRiemannianManifold.__init__(self, n, name, metric_name=metric_name, signature=n, base_manifold=base_manifold, latex_name=latex_name, @@ -948,6 +956,39 @@ def cartesian_frame(self): # we simply return this frame: return self._cartesian_chart.frame() + def dist(self, p, q): + r""" + Euclidean distance between two points. + + INPUT: + + - ``p`` -- an element of ``self`` + - ``q`` -- an element of ``self`` + + OUTPUT: + + - the Euclidean distance `d(p, q)` + + EXAMPLES:: + + sage: E. = EuclideanSpace() + sage: p = E((1,0)) + sage: q = E((0,2)) + sage: E.dist(p, q) + sqrt(5) + sage: p.dist(q) # indirect doctest + sqrt(5) + + """ + chart = self.cartesian_coordinates() + coords_p = chart(p) + coords_q = chart(q) + d2 = 0 + for xp, xq in zip(coords_p, coords_q): + dx = xp - xq + d2 += dx*dx + return sqrt(d2) + ############################################################################### class EuclideanPlane(EuclideanSpace): @@ -1025,10 +1066,11 @@ class EuclideanPlane(EuclideanSpace): sage: E. = EuclideanSpace(); E Euclidean plane E^2 - ``E`` is a real smooth manifold of dimension 2:: + ``E`` is both a real smooth manifold of dimension `2` and a metric space:: sage: E.category() - Category of smooth manifolds over Real Field with 53 bits of precision + Join of Category of differentiable manifolds over Real Field with + 53 bits of precision and Category of metric spaces sage: dim(E) 2 @@ -1553,10 +1595,11 @@ class Euclidean3dimSpace(EuclideanSpace): sage: type(E) - ``E`` is a real smooth manifold of dimension 3:: + ``E`` is both a real smooth manifold of dimension `3` and a metric space:: sage: E.category() - Category of smooth manifolds over Real Field with 53 bits of precision + Join of Category of differentiable manifolds over Real Field with + 53 bits of precision and Category of metric spaces sage: dim(E) 3 From 3eba4e13c69609daf63ec89005fc98b37cee2b11 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Sat, 11 Jul 2020 19:13:14 +0200 Subject: [PATCH 065/217] Trac #30108: != bug fixed --- src/sage/manifolds/differentiable/mixed_form.py | 16 +++++++++++----- src/sage/manifolds/differentiable/tensorfield.py | 5 +++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/sage/manifolds/differentiable/mixed_form.py b/src/sage/manifolds/differentiable/mixed_form.py index 4fabf3111ed..036f7cab01a 100644 --- a/src/sage/manifolds/differentiable/mixed_form.py +++ b/src/sage/manifolds/differentiable/mixed_form.py @@ -582,15 +582,21 @@ def _richcmp_(self, other, op): sage: G.set_restriction(F.restrict(V)) sage: F == G # True now True + sage: H = M.mixed_form([f, 0, 0]) + sage: F != H # this is fixed by ticket #30108 + True sage: F.parent().zero() == 0 True """ - # Compare all elements separately: - for j in self.irange(): - if not richcmp(self[j], other[j], op): - return False - return True + from sage.structure.richcmp import op_NE, op_EQ + if op == op_NE: + return not self == other + elif op == op_EQ: + # Compare all elements separately: + return all(self[j] == other[j] for j in self.irange()) + # Fall back on default implementation: + return AlgebraElement._richcmp_(self, other, op) def _add_(self, other): r""" diff --git a/src/sage/manifolds/differentiable/tensorfield.py b/src/sage/manifolds/differentiable/tensorfield.py index e136fb8055e..1db698e2ce0 100644 --- a/src/sage/manifolds/differentiable/tensorfield.py +++ b/src/sage/manifolds/differentiable/tensorfield.py @@ -2192,12 +2192,17 @@ def __eq__(self, other): sage: t.parent().zero() == 0 True """ + from .mixed_form import MixedForm + if other is self: return True if other in ZZ: # to compare with 0 if other == 0: return self.is_zero() return False + elif isinstance(other, MixedForm): + # use comparison of MixedForm: + return other == self elif not isinstance(other, TensorField): return False else: # other is another tensor field From aa605ab62771d4e0e5c0282f15ee910bf210f966 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Sat, 11 Jul 2020 19:24:26 +0200 Subject: [PATCH 066/217] Trac #30108: eq check between scalar fields and mixed forms --- src/sage/manifolds/scalarfield.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sage/manifolds/scalarfield.py b/src/sage/manifolds/scalarfield.py index edb52ecd954..c2af17df817 100644 --- a/src/sage/manifolds/scalarfield.py +++ b/src/sage/manifolds/scalarfield.py @@ -1265,8 +1265,13 @@ def __eq__(self, other): True """ + from .mixed_form import MixedForm + if other is self: return True + if isinstance(other, MixedForm): + # use comparison of MixedForm: + return other == self if not isinstance(other, ScalarField): # We try a conversion of other to a scalar field, except if # other is None (since this would generate an undefined scalar From b7d9f475e9aff734e814a4607f20ba469d29c36d Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Sat, 11 Jul 2020 19:26:54 +0200 Subject: [PATCH 067/217] Trac #30108: wrong import --- src/sage/manifolds/scalarfield.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/manifolds/scalarfield.py b/src/sage/manifolds/scalarfield.py index c2af17df817..7791728197c 100644 --- a/src/sage/manifolds/scalarfield.py +++ b/src/sage/manifolds/scalarfield.py @@ -1265,8 +1265,8 @@ def __eq__(self, other): True """ - from .mixed_form import MixedForm - + from sage.manifolds.differentiable.mixed_form import MixedForm + if other is self: return True if isinstance(other, MixedForm): From 0b93b22c6aeb12b08a9ab210dc16a1e58d3d6685 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Sat, 11 Jul 2020 20:22:40 +0200 Subject: [PATCH 068/217] Trac #30108: unused import richcmp removed --- src/sage/manifolds/differentiable/mixed_form.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/manifolds/differentiable/mixed_form.py b/src/sage/manifolds/differentiable/mixed_form.py index 036f7cab01a..5bb1ffe3d0c 100644 --- a/src/sage/manifolds/differentiable/mixed_form.py +++ b/src/sage/manifolds/differentiable/mixed_form.py @@ -27,7 +27,6 @@ from sage.misc.cachefunc import cached_method from sage.structure.element import AlgebraElement from sage.rings.integer import Integer -from sage.structure.richcmp import richcmp class MixedForm(AlgebraElement): r""" From dd27b331b73bba9b2ee1a522b0b047f5fa1ffedb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jul 2020 12:46:12 -0700 Subject: [PATCH 069/217] sage.libs.ecl: Update uses of python_to_ecl --- src/sage/libs/ecl.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/libs/ecl.pyx b/src/sage/libs/ecl.pyx index 1697440d2df..1c67ba6761c 100644 --- a/src/sage/libs/ecl.pyx +++ b/src/sage/libs/ecl.pyx @@ -454,7 +454,7 @@ cdef cl_object python_to_ecl(pyobj, bint read_strings) except NULL: s = str_to_bytes(pyobj, 'ascii') except UnicodeEncodeError: o = cl_funcall(2, make_unicode_string_clobj, - python_to_ecl([ord(c) for c in pyobj])) + python_to_ecl([ord(c) for c in pyobj], read_strings)) else: o = ecl_cstring_to_base_string_or_nil(s) @@ -1390,7 +1390,7 @@ cpdef EclObject ecl_eval(str s): """ cdef cl_object o - o=ecl_safe_eval(python_to_ecl(s)) + o=ecl_safe_eval(python_to_ecl(s, True)) return ecl_wrap(o) init_ecl() From 7712555c3449cd8601405a54026970c6bf47462c Mon Sep 17 00:00:00 2001 From: Markus Wageringel Date: Sat, 6 Jun 2020 14:31:12 +0200 Subject: [PATCH 070/217] 30114: fix code blocks in padics/factory.py --- src/sage/rings/padics/factory.py | 46 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/sage/rings/padics/factory.py b/src/sage/rings/padics/factory.py index 0f81744a510..4aa383f5cdd 100644 --- a/src/sage/rings/padics/factory.py +++ b/src/sage/rings/padics/factory.py @@ -429,7 +429,7 @@ class Qp_class(UniqueFactory): It can be either 'none' (or equivalently ``False``), 'bigoh' (or equivalently ``True``) or 'bigoh'. The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. + and ``True`` for all other types. :: sage: Qp(5)(6) 1 + 5 + O(5^20) @@ -468,7 +468,7 @@ class Qp_class(UniqueFactory): It can be either 'none' (or equivalently ``False``) or 'bigoh' (or equivalently ``True``). The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. + and ``True`` for all other types. :: sage: Qp(5, print_mode='val-unit', show_prec=False)(30) 5 * 6 @@ -514,7 +514,7 @@ class Qp_class(UniqueFactory): It can be either 'none' (or equivalently ``False``) or 'bigoh' (or equivalently ``True``). The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. + and ``True`` for all other types. :: sage: Qp(5, print_mode='terse', show_prec=False)(6) 6 @@ -585,7 +585,7 @@ class Qp_class(UniqueFactory): It can be either 'none' (or equivalently ``False``), 'dots' (or equivalently ``True``) or 'bigoh'. The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. + and ``True`` for all other types. :: sage: repr(Zp(5, print_mode='digits', show_prec=True)(6)) '...00000000000000000011' @@ -610,7 +610,7 @@ class Qp_class(UniqueFactory): sage: d = R(-707/5^2); repr(d) '...4|4|4|4|4|4|4|4|4|4|4|4|4|4|4|3|4|1|.|3|3' - Again, note that it's not possible to read of the precision from the representation in this mode. + Again, note that it's not possible to read off the precision from the representation in this mode. *print_pos* controls whether the digits can be negative.:: @@ -641,7 +641,7 @@ class Qp_class(UniqueFactory): It can be either 'none' (or equivalently ``False``), 'dots' (or equivalently ``True``) or 'bigoh' The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. + and ``True`` for all other types. :: sage: repr(Qp(5, print_mode='bars', show_prec='bigoh')(6)) '...1|1 + O(5^20)' @@ -982,7 +982,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, It can be either 'none' (or equivalently ``False``), 'bigoh' (or equivalently ``True``). The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. + and ``True`` for all other types. :: sage: U. = Qq(9, 2, show_prec=False); repr(-3*(1+2*e)^4) '3 + e*3^2' @@ -1029,7 +1029,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, It can be either 'none' (or equivalently ``False``), 'bigoh' (or equivalently ``True``). The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. + and ``True`` for all other types. :: sage: U. = Qq(9, 2, print_mode='val-unit', show_prec=False); repr(-3*(1+2*e)^4) '3 * (1 + 3*e)' @@ -1083,7 +1083,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, It can be either 'none' (or equivalently ``False``), 'bigoh' (or equivalently ``True``). The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. + and ``True`` for all other types. :: sage: U. = Qq(9, 2, print_mode='terse', show_prec=False); repr(-3*(1+2*e)^4) '3 + 9*e' @@ -1125,7 +1125,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: repr((a+R(1/5,relprec=3))^7) '...|.|?|?|?|?|[0, 1, 1]|[0, 2]|[1]' - Note that it's not possible to read of the precision from the + Note that it's not possible to read off the precision from the representation in this mode.:: sage: b = a + 3; repr(b) @@ -1174,7 +1174,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, It can be either 'none' (or equivalently ``False``), 'dots' (or equivalently ``True``) or 'bigoh' The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. + and ``True`` for all other types. :: sage: U. = Qq(9, 2, print_mode='bars', show_prec=True); repr(-3*(1+2*e)^4) '...[0, 1]|[1]|[]' @@ -1576,7 +1576,7 @@ class Zp_class(UniqueFactory): It can be either 'none' (or equivalently ``False``), 'bigoh' (or equivalently ``True``). The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: Zp(5, show_prec=False)(6) 1 + 5 @@ -1610,7 +1610,7 @@ class Zp_class(UniqueFactory): It can be either 'none' (or equivalently ``False``), 'bigoh' (or equivalently ``True``). The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: Zp(5, print_mode='val-unit', show_prec=False)(30) 5 * 6 @@ -1644,7 +1644,7 @@ class Zp_class(UniqueFactory): It can be either 'none' (or equivalently ``False``), 'bigoh' (or equivalently ``True``). The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: Zp(5, print_mode='terse', show_prec=False)(30) 30 @@ -1686,7 +1686,7 @@ class Zp_class(UniqueFactory): It can be either 'none' (or equivalently ``False``), 'dots' (or equivalently ``True``) or 'bigoh'. The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: repr(Zp(5, 2, print_mode='digits', show_prec=True)(6)) '...11' @@ -1701,14 +1701,14 @@ class Zp_class(UniqueFactory): (False, False, False) 5. **bars**: elements are displayed as a string of base `p` digits - with separators + with separators:: sage: R = Zp(5, print_mode='bars'); a = R(70700); repr(a) '...4|2|3|0|3|0|0' sage: b = R(-70700); repr(b) '...4|4|4|4|4|4|4|4|4|4|4|4|4|4|4|0|2|1|4|2|0|0' - Again, note that it's not possible to read of the precision from + Again, note that it's not possible to read off the precision from the representation in this mode. *print_pos* controls whether the digits can be negative.:: @@ -1730,7 +1730,7 @@ class Zp_class(UniqueFactory): It can be either 'none' (or equivalently ``False``), 'dots' (or equivalently ``True``) or 'bigoh'. The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: repr(Zp(5, 2, print_mode='bars', show_prec=True)(6)) '...1|1' @@ -2194,7 +2194,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, It can be either 'none' (or equivalently ``False``), 'bigoh' (or equivalently ``True``). The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: U. = Zq(9, 2, show_prec=False); repr(-3*(1+2*e)^4) '3 + e*3^2' @@ -2239,7 +2239,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, It can be either 'none' (or equivalently ``False``), 'bigoh' (or equivalently ``True``). The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: U. = Zq(9, 2, print_mode='val-unit', show_prec=False); repr(-3*(1+2*e)^4) '3 * (1 + 3*e)' @@ -2296,7 +2296,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, It can be either 'none' (or equivalently ``False``), 'bigoh' (or equivalently ``True``). The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: U. = Zq(9, 2, print_mode='terse', show_prec=False); repr(-3*(1+2*e)^4) '3 + 9*e' @@ -2323,7 +2323,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: repr((a-5)^6) '...[0, 4]|[1, 4]|[2, 0, 2]|[1, 4, 3]|[2, 3, 1]|[4, 4, 3]|[2, 4, 4]|[4, 3, 4]' - Note that it's not possible to read of the precision from the + Note that it's not possible to read off the precision from the representation in this mode.:: sage: b = a + 3; repr(b) @@ -2374,7 +2374,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, It can be either 'none' (or equivalently ``False``), 'dots' (or equivalently ``True``) or 'bigoh'. The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: U. = Zq(9, 2, print_mode='bars', show_prec='bigoh'); repr(-3*(1+2*e)^4) '[0, 1]|[1]|[] + O(3^3)' From bd15fb95c0720aff65ee8fce1c7c261c7aee40fc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jul 2020 15:12:13 -0700 Subject: [PATCH 071/217] build/bin/write-dockerfile.sh, tox.ini: Do not run testsuites that need pip (ssl) --- build/bin/write-dockerfile.sh | 8 ++++---- tox.ini | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/bin/write-dockerfile.sh b/build/bin/write-dockerfile.sh index 563db179665..cfaee46b2bc 100755 --- a/build/bin/write-dockerfile.sh +++ b/build/bin/write-dockerfile.sh @@ -186,7 +186,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake" +ENV SAGE_CHECK_PACKAGES="!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!symengine_py" #:toolchain: $RUN make \${USE_MAKEFLAGS} base-toolchain @@ -195,7 +195,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake" +ENV SAGE_CHECK_PACKAGES="!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!symengine_py" #:make: ARG TARGETS_PRE="sagelib-build-deps" $RUN make SAGE_SPKG="sage-spkg -y -o" \${USE_MAKEFLAGS} \${TARGETS_PRE} @@ -205,7 +205,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake" +ENV SAGE_CHECK_PACKAGES="!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!symengine_py" ADD src src ARG TARGETS="build" $RUN make SAGE_SPKG="sage-spkg -y -o" \${USE_MAKEFLAGS} \${TARGETS} @@ -215,7 +215,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake" +ENV SAGE_CHECK_PACKAGES="!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!symengine_py" ARG TARGETS_OPTIONAL="ptest" $RUN make SAGE_SPKG="sage-spkg -y -o" \${USE_MAKEFLAGS} \${TARGETS_OPTIONAL} || echo "(error ignored)" diff --git a/tox.ini b/tox.ini index 4219055fe11..870945536e7 100644 --- a/tox.ini +++ b/tox.ini @@ -380,7 +380,7 @@ commands = docker: done' # pathpy checksuite needs tox. #28728: gap fails its test suite. # linbox/cysignals testsuites fail. ppl takes very long. - local: bash -c 'export PATH={env:PATH} && {env:SETENV} && {env:BOOTSTRAP:./bootstrap} && ./configure --prefix={envdir}/local {env:CONFIGURE_ARGS} && make -k V=0 base-toolchain && make -k V=0 SAGE_SPKG="sage-spkg -y -o" SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake" {env:TARGETS_PRE:} {posargs:build} && (make -k V=0 SAGE_SPKG="sage-spkg -y -o" SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake" {env:TARGETS_OPTIONAL:} || echo "(error ignored)" ) ' + local: bash -c 'export PATH={env:PATH} && {env:SETENV} && {env:BOOTSTRAP:./bootstrap} && ./configure --prefix={envdir}/local {env:CONFIGURE_ARGS} && make -k V=0 base-toolchain && make -k V=0 SAGE_SPKG="sage-spkg -y -o" SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!symengine_py" {env:TARGETS_PRE:} {posargs:build} && (make -k V=0 SAGE_SPKG="sage-spkg -y -o" SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake" {env:TARGETS_OPTIONAL:} || echo "(error ignored)" ) ' [testenv:check_configure] ## Test that configure behaves properly From 3b14bf51517e2c8c77a49dcc286fe6dfaf38dc48 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jul 2020 22:10:53 -0700 Subject: [PATCH 072/217] build/pkgs/rpy2/dependencies: Conditionalize on SAGE_CHECK_rpy2 --- build/pkgs/rpy2/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/rpy2/dependencies b/build/pkgs/rpy2/dependencies index 7f2d42901ef..4e37a7ddf02 100644 --- a/build/pkgs/rpy2/dependencies +++ b/build/pkgs/rpy2/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) r cffi | $(PYTHON_TOOLCHAIN) pycparser $(and $(filter-out no,$(SAGE_CHECK)), pytest tzlocal numpy) +$(PYTHON) r cffi | $(PYTHON_TOOLCHAIN) pycparser $(and $(filter-out no,$(SAGE_CHECK_rpy2)), pytest tzlocal numpy) ---------- All lines of this file are ignored except the first. From 002b8c2ea12b30b05231c35fe6a39997f422d5a3 Mon Sep 17 00:00:00 2001 From: vipul79321 Date: Sun, 12 Jul 2020 16:15:28 +0530 Subject: [PATCH 073/217] doc test added --- src/sage/graphs/base/boost_graph.pyx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx index bc161833224..326f61437b3 100644 --- a/src/sage/graphs/base/boost_graph.pyx +++ b/src/sage/graphs/base/boost_graph.pyx @@ -2361,6 +2361,10 @@ cpdef diameter(G, algorithm=None, source=None, Traceback (most recent call last): ... ValueError: the graph contains a negative cycle + sage: diameter(G, algorithm='DiFUB', weight_function=lambda e:e[2]) + Traceback (most recent call last): + ... + ValueError: the graph contains a negative cycle """ import sys From c9e35a585176ac7918dea89508de79fd399a4929 Mon Sep 17 00:00:00 2001 From: Markus Wageringel Date: Sun, 12 Jul 2020 12:53:39 +0200 Subject: [PATCH 074/217] 30114: replace `.::` by `. ::` --- src/sage/rings/padics/factory.py | 174 +++++++++++++++---------------- 1 file changed, 87 insertions(+), 87 deletions(-) diff --git a/src/sage/rings/padics/factory.py b/src/sage/rings/padics/factory.py index 4aa383f5cdd..00c9f0991f2 100644 --- a/src/sage/rings/padics/factory.py +++ b/src/sage/rings/padics/factory.py @@ -372,7 +372,7 @@ class Qp_class(UniqueFactory): precision, so the effect of various arithmetic operations on precision is tracked. When you cast an exact element into a capped relative field, it truncates it to the precision cap of the - field.:: + field. :: sage: R = Qp(5, 5, 'capped-rel', 'series'); a = R(4006); a 1 + 5 + 2*5^3 + 5^4 + O(5^5) @@ -400,7 +400,7 @@ class Qp_class(UniqueFactory): compact. Note that the printing options affect whether different `p`-adic fields are considered equal. - 1. **series**: elements are displayed as series in `p`.:: + 1. **series**: elements are displayed as series in `p`. :: sage: R = Qp(5, print_mode='series'); a = R(70700); a 3*5^2 + 3*5^4 + 2*5^5 + 4*5^6 + O(5^22) @@ -408,19 +408,19 @@ class Qp_class(UniqueFactory): 2*5^2 + 4*5^3 + 5^4 + 2*5^5 + 4*5^7 + 4*5^8 + 4*5^9 + 4*5^10 + 4*5^11 + 4*5^12 + 4*5^13 + 4*5^14 + 4*5^15 + 4*5^16 + 4*5^17 + 4*5^18 + 4*5^19 + 4*5^20 + 4*5^21 + O(5^22) *print_pos* controls whether negatives can be used in the - coefficients of powers of `p`.:: + coefficients of powers of `p`. :: sage: S = Qp(5, print_mode='series', print_pos=False); a = S(70700); a -2*5^2 + 5^3 - 2*5^4 - 2*5^5 + 5^7 + O(5^22) sage: b = S(-70700); b 2*5^2 - 5^3 + 2*5^4 + 2*5^5 - 5^7 + O(5^22) - *print_max_terms* limits the number of terms that appear.:: + *print_max_terms* limits the number of terms that appear. :: sage: T = Qp(5, print_mode='series', print_max_terms=4); b = R(-70700); repr(b) '2*5^2 + 4*5^3 + 5^4 + 2*5^5 + ... + O(5^22)' - *names* affects how the prime is printed.:: + *names* affects how the prime is printed. :: sage: U.

= Qp(5); p p + O(p^21) @@ -454,12 +454,12 @@ class Qp_class(UniqueFactory): 5^-1 * 95367431639918 + O(5^19) *print_pos* controls whether to use a balanced representation or - not.:: + not. :: sage: S = Qp(5, print_mode='val-unit', print_pos=False); b = S(-70700); b 5^2 * (-2828) + O(5^22) - *names* affects how the prime is printed.:: + *names* affects how the prime is printed. :: sage: T = Qp(5, print_mode='val-unit', names='pi'); a = T(70700); a pi^2 * 2828 + O(pi^22) @@ -491,19 +491,19 @@ class Qp_class(UniqueFactory): 95367431639918/5 + O(5^19) The denominator, as of version 3.3, is always printed - explicitly as a power of `p`, for predictability.:: + explicitly as a power of `p`, for predictability. :: sage: d = R(707/5^2); d 707/5^2 + O(5^18) - *print_pos* controls whether to use a balanced representation or not.:: + *print_pos* controls whether to use a balanced representation or not. :: sage: S = Qp(5, print_mode='terse', print_pos=False); b = S(-70700); b -70700 + O(5^22) sage: c = S(-707/5); c -707/5 + O(5^19) - *name* affects how the name is printed.:: + *name* affects how the name is printed. :: sage: T. = Qp(5, print_mode='terse'); c = T(-707/5); c 95367431639918/unif + O(unif^19) @@ -530,7 +530,7 @@ class Qp_class(UniqueFactory): Restriction: you can only use the digits printing mode for small primes. Namely, `p` must be less than the length of the - alphabet tuple (default alphabet has length 62).:: + alphabet tuple (default alphabet has length 62). :: sage: R = Qp(5, print_mode='digits'); a = R(70700); repr(a) '...0000000000000004230300' @@ -560,7 +560,7 @@ class Qp_class(UniqueFactory): *print_max_terms* limits the number of digits that are printed. Note that if the valuation of the element is very negative, more - digits will be printed.:: + digits will be printed. :: sage: S = Qp(5, print_max_terms=4); S(-70700) 2*5^2 + 4*5^3 + 5^4 + 2*5^5 + ... + O(5^22) @@ -612,14 +612,14 @@ class Qp_class(UniqueFactory): Again, note that it's not possible to read off the precision from the representation in this mode. - *print_pos* controls whether the digits can be negative.:: + *print_pos* controls whether the digits can be negative. :: sage: S = Qp(5, print_mode='bars',print_pos=False); b = S(-70700); repr(b) '...-1|0|2|2|-1|2|0|0' *print_max_terms* limits the number of digits that are printed. Note that if the valuation of the element is very negative, more - digits will be printed.:: + digits will be printed. :: sage: T = Qp(5, print_max_terms=4); T(-70700) 2*5^2 + 4*5^3 + 5^4 + 2*5^5 + ... + O(5^22) @@ -632,7 +632,7 @@ class Qp_class(UniqueFactory): sage: T(-707/5^4) 3*5^-4 + 3*5^-3 + 5^-2 + 4*5^-1 + ... + O(5^16) - *print_sep* controls the separation character.:: + *print_sep* controls the separation character. :: sage: U = Qp(5, print_mode='bars', print_sep=']['); a = U(70700); repr(a) '...4][2][3][0][3][0][0' @@ -844,7 +844,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, precision, so the effect of various arithmetic operations on precision is tracked. When you cast an exact element into a capped relative field, it truncates it to the precision cap of the - field.:: + field. :: sage: R. = Qq(9, 5, 'capped-rel', print_mode='series'); b = (1+2*a)^4; b 2 + (2*a + 2)*3 + (2*a + 1)*3^2 + O(3^5) @@ -866,7 +866,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, 1. A **polynomial**. - The base ring can be `\ZZ`, `\QQ`, `\ZZ_p`, `\QQ_p`, `\GF{p}`.:: + The base ring can be `\ZZ`, `\QQ`, `\ZZ_p`, `\QQ_p`, `\GF{p}`. :: sage: P. = ZZ[] sage: R. = Qq(27, modulus = x^3 + 2*x + 1); R.modulus() @@ -888,7 +888,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, unless the precision of the modulus differs. In the case of V, the modulus is only given to precision 1, so the resulting field - has a precision cap of 1.:: + has a precision cap of 1. :: sage: V.precision_cap() 1 @@ -901,7 +901,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: W. = Qq(27, modulus = modulus); W.precision_cap() 7 - 2. The modulus can also be given as a **symbolic expression**.:: + 2. The modulus can also be given as a **symbolic expression**. :: sage: x = var('x') sage: X. = Qq(27, modulus = x^3 + 2*x + 1); X.modulus() @@ -910,7 +910,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, True By default, the polynomial chosen is the standard lift of the - generator chosen for `\GF{q}`.:: + generator chosen for `\GF{q}`. :: sage: GF(125, 'a').modulus() x^3 + 3*x + 3 @@ -918,7 +918,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, (1 + O(5^20))*x^3 + O(5^20)*x^2 + (3 + O(5^20))*x + 3 + O(5^20) However, you can choose another polynomial if desired (as long as - the reduction to `\GF{p}[x]` is irreducible).:: + the reduction to `\GF{p}[x]` is irreducible). :: sage: P. = ZZ[] sage: Z. = Qq(125, modulus = x^3 + 3*x^2 + x + 1); Z.modulus() @@ -937,7 +937,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, compact. Note that the printing options affect whether different `p`-adic fields are considered equal. - 1. **series**: elements are displayed as series in `p`.:: + 1. **series**: elements are displayed as series in `p`. :: sage: R. = Qq(9, 20, 'capped-rel', print_mode='series'); (1+2*a)^4 2 + (2*a + 2)*3 + (2*a + 1)*3^2 + O(3^20) @@ -947,25 +947,25 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, (a + 2)*3^-1 + 1 + 2*3 + (a + 1)*3^2 + 3^3 + 2*3^4 + (a + 1)*3^5 + 3^6 + 2*3^7 + (a + 1)*3^8 + 3^9 + 2*3^10 + (a + 1)*3^11 + 3^12 + 2*3^13 + (a + 1)*3^14 + 3^15 + 2*3^16 + (a + 1)*3^17 + 3^18 + O(3^19) *print_pos* controls whether negatives can be used in the - coefficients of powers of `p`.:: + coefficients of powers of `p`. :: sage: S. = Qq(9, print_mode='series', print_pos=False); (1+2*b)^4 -1 - b*3 - 3^2 + (b + 1)*3^3 + O(3^20) sage: -3*(1+2*b)^4 3 + b*3^2 + 3^3 + (-b - 1)*3^4 + O(3^21) - *ram_name* controls how the prime is printed.:: + *ram_name* controls how the prime is printed. :: sage: T. = Qq(9, print_mode='series', ram_name='p'); 3*(1+2*d)^4 2*p + (2*d + 2)*p^2 + (2*d + 1)*p^3 + O(p^21) - *print_max_ram_terms* limits the number of powers of `p` that appear.:: + *print_max_ram_terms* limits the number of powers of `p` that appear. :: sage: U. = Qq(9, print_mode='series', print_max_ram_terms=4); repr(-3*(1+2*e)^4) '3 + e*3^2 + 3^3 + (2*e + 2)*3^4 + ... + O(3^21)' *print_max_unram_terms* limits the number of terms that appear in a - coefficient of a power of `p`.:: + coefficient of a power of `p`. :: sage: V. = Qq(128, prec = 8, print_mode='series'); repr((1+f)^9) '(f^3 + 1) + (f^5 + f^4 + f^3 + f^2)*2 + (f^6 + f^5 + f^4 + f + 1)*2^2 + (f^5 + f^4 + f^2 + f + 1)*2^3 + (f^6 + f^5 + f^4 + f^3 + f^2 + f + 1)*2^4 + (f^5 + f^4)*2^5 + (f^6 + f^5 + f^4 + f^3 + f + 1)*2^6 + (f + 1)*2^7 + O(2^8)' @@ -1002,14 +1002,14 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, 3^-3 * (41 + a) + O(3) *print_pos* controls whether to use a balanced representation or - not.:: + not. :: sage: S. = Qq(9, 7, print_mode='val-unit', print_pos=False); b = (1+3*a)^9 - 1; b 3^3 * (15 - 17*a) + O(3^7) sage: ~b 3^-3 * (-40 + a) + O(3) - *ram_name* affects how the prime is printed.:: + *ram_name* affects how the prime is printed. :: sage: A. = Qp(next_prime(10^6), print_mode='val-unit')[] sage: T. = Qq(next_prime(10^6)^3, 4, print_mode='val-unit', ram_name='p', modulus=x^3+385831*x^2+106556*x+321036); b = ~(next_prime(10^6)^2*(a^2 + a - 4)); b @@ -1018,7 +1018,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, p^-2 * 1 + O(p^2) *print_max_terse_terms* controls how many terms of the polynomial - appear in the unit part.:: + appear in the unit part. :: sage: U. = Qq(17^4, 6, print_mode='val-unit', print_max_terse_terms=3); b = ~(17*(a^3-a+14)); b 17^-1 * (22110411 + 11317400*a + 20656972*a^2 + ...) + O(17^5) @@ -1043,7 +1043,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, (False, False, False, False, False, False) 3. **terse**: elements are displayed as a polynomial of degree less - than the degree of the extension.:: + than the degree of the extension. :: sage: R. = Qq(125, print_mode='terse') sage: (a+5)^177 @@ -1053,13 +1053,13 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, As of version 3.3, if coefficients of the polynomial are non-integral, they are always printed with an explicit power of `p` - in the denominator.:: + in the denominator. :: sage: 5*a + a^2/25 5*a + 1/5^2*a^2 + O(5^18) *print_pos* controls whether to use a balanced representation or - not.:: + not. :: sage: (a-5)^6 22864 + 95367431627998*a + 8349*a^2 + O(5^20) @@ -1068,13 +1068,13 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: (a - 1/5)^6 -20624/5^6 + 18369/5^5*a + 1353/5^3*a^2 + O(5^14) - *ram_name* affects how the prime is printed.:: + *ram_name* affects how the prime is printed. :: sage: T. = Qq(125, print_mode='terse', ram_name='p'); (a - 1/5)^6 95367431620001/p^6 + 18369/p^5*a + 1353/p^3*a^2 + O(p^14) *print_max_terse_terms* controls how many terms of the polynomial - are shown.:: + are shown. :: sage: U. = Qq(625, print_mode='terse', print_max_terse_terms=2); (a-1/5)^6 106251/5^6 + 49994/5^5*a + ... + O(5^14) @@ -1103,7 +1103,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, this isn't implemented. 5. **bars**: elements are displayed in a similar fashion to - series, but more compactly.:: + series, but more compactly. :: sage: R. = Qq(125); (a+5)^6 (4*a^2 + 3*a + 4) + (3*a^2 + 2*a)*5 + (a^2 + a + 1)*5^2 + (3*a + 2)*5^3 + (3*a^2 + a + 3)*5^4 + (2*a^2 + 3*a + 2)*5^5 + O(5^20) @@ -1113,20 +1113,20 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, '...[0, 4]|[1, 4]|[2, 0, 2]|[1, 4, 3]|[2, 3, 1]|[4, 4, 3]|[2, 4, 4]|[4, 3, 4]' Note that elements with negative valuation are shown with a - decimal point at valuation 0.:: + decimal point at valuation 0. :: sage: repr((a+1/5)^6) '...[3]|[4, 1, 3]|.|[1, 2, 3]|[3, 3]|[0, 0, 3]|[0, 1]|[0, 1]|[1]' sage: repr((a+1/5)^2) '...[0, 0, 1]|.|[0, 2]|[1]' - If not enough precision is known, ``'?'`` is used instead.:: + If not enough precision is known, ``'?'`` is used instead. :: sage: repr((a+R(1/5,relprec=3))^7) '...|.|?|?|?|?|[0, 1, 1]|[0, 2]|[1]' Note that it's not possible to read off the precision from the - representation in this mode.:: + representation in this mode. :: sage: b = a + 3; repr(b) '...[3, 1]' @@ -1137,7 +1137,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: c.precision_absolute() 4 - *print_pos* controls whether the digits can be negative.:: + *print_pos* controls whether the digits can be negative. :: sage: S. = Qq(125, print_mode='bars', print_pos=False); repr((a-5)^6) '...[1, -1, 1]|[2, 1, -2]|[2, 0, -2]|[-2, -1, 2]|[0, 0, -1]|[-2]|[-1, -2, -1]' @@ -1146,14 +1146,14 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, *print_max_ram_terms* controls the maximum number of "digits" shown. Note that this puts a cap on the relative precision, not the - absolute precision.:: + absolute precision. :: sage: T. = Qq(125, print_max_ram_terms=3, print_pos=False); (a-5)^6 (-a^2 - 2*a - 1) - 2*5 - a^2*5^2 + ... + O(5^20) sage: 5*(a-5)^6 + 50 (-a^2 - 2*a - 1)*5 - a^2*5^3 + (2*a^2 - a - 2)*5^4 + ... + O(5^21) - *print_sep* controls the separating character (``'|'`` by default).:: + *print_sep* controls the separating character (``'|'`` by default). :: sage: U. = Qq(625, print_mode='bars', print_sep=''); b = (a+5)^6; repr(b) '...[0, 1][4, 0, 2][3, 2, 2, 3][4, 2, 2, 4][0, 3][1, 1, 3][3, 1, 4, 1]' @@ -1192,7 +1192,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, However, you can use ``check=False`` to pass in a pair in order to not have to factor. If you do so, you need to use names explicitly - rather than the ``R.`` syntax.:: + rather than the ``R.`` syntax. :: sage: p = next_prime(2^123) sage: k = Qp(p) @@ -1491,7 +1491,7 @@ class Zp_class(UniqueFactory): precision, so the effect of various arithmetic operations on precision is tracked. When you cast an exact element into a capped relative field, it truncates it to the precision cap of the - field.:: + field. :: sage: R = Zp(5, 5, 'capped-rel', 'series'); a = R(4006); a 1 + 5 + 2*5^3 + 5^4 + O(5^5) @@ -1504,7 +1504,7 @@ class Zp_class(UniqueFactory): relative precision of an element there is instead a cap on the absolute precision. Elements still store their own precisions, and as with the capped relative case, exact elements are truncated - when cast into the ring.:: + when cast into the ring. :: sage: R = Zp(5, 5, 'capped-abs', 'series'); a = R(4005); a 5 + 2*5^3 + 5^4 + O(5^5) @@ -1519,7 +1519,7 @@ class Zp_class(UniqueFactory): basically just a wrapper around `\ZZ / p^n \ZZ` providing a unified interface with the rest of the `p`-adics. This is the type you should use if your sole interest is speed. It does not track - precision of elements.:: + precision of elements. :: sage: R = Zp(5,5,'fixed-mod','series'); a = R(4005); a 5 + 2*5^3 + 5^4 @@ -1547,7 +1547,7 @@ class Zp_class(UniqueFactory): representations more compact. Note that the printing options affect whether different `p`-adic fields are considered equal. - 1. **series**: elements are displayed as series in `p`.:: + 1. **series**: elements are displayed as series in `p`. :: sage: R = Zp(5, print_mode='series'); a = R(70700); a 3*5^2 + 3*5^4 + 2*5^5 + 4*5^6 + O(5^22) @@ -1555,19 +1555,19 @@ class Zp_class(UniqueFactory): 2*5^2 + 4*5^3 + 5^4 + 2*5^5 + 4*5^7 + 4*5^8 + 4*5^9 + 4*5^10 + 4*5^11 + 4*5^12 + 4*5^13 + 4*5^14 + 4*5^15 + 4*5^16 + 4*5^17 + 4*5^18 + 4*5^19 + 4*5^20 + 4*5^21 + O(5^22) *print_pos* controls whether negatives can be used in the - coefficients of powers of `p`.:: + coefficients of powers of `p`. :: sage: S = Zp(5, print_mode='series', print_pos=False); a = S(70700); a -2*5^2 + 5^3 - 2*5^4 - 2*5^5 + 5^7 + O(5^22) sage: b = S(-70700); b 2*5^2 - 5^3 + 2*5^4 + 2*5^5 - 5^7 + O(5^22) - *print_max_terms* limits the number of terms that appear.:: + *print_max_terms* limits the number of terms that appear. :: sage: T = Zp(5, print_mode='series', print_max_terms=4); b = R(-70700); b 2*5^2 + 4*5^3 + 5^4 + 2*5^5 + ... + O(5^22) - *names* affects how the prime is printed.:: + *names* affects how the prime is printed. :: sage: U.

= Zp(5); p p + O(p^21) @@ -1596,12 +1596,12 @@ class Zp_class(UniqueFactory): 5 * 95367431639918 + O(5^21) *print_pos* controls whether to use a balanced representation or - not.:: + not. :: sage: S = Zp(5, print_mode='val-unit', print_pos=False); b = S(-70700); b 5^2 * (-2828) + O(5^22) - *names* affects how the prime is printed.:: + *names* affects how the prime is printed. :: sage: T = Zp(5, print_mode='val-unit', names='pi'); a = T(70700); a pi^2 * 2828 + O(pi^22) @@ -1629,13 +1629,13 @@ class Zp_class(UniqueFactory): sage: b = R(-70700); b 2384185790944925 + O(5^22) - *print_pos* controls whether to use a balanced representation or not.:: + *print_pos* controls whether to use a balanced representation or not. :: sage: S = Zp(5, print_mode='terse', print_pos=False); b = S(-70700); b -70700 + O(5^22) *name* affects how the name is printed. Note that this interacts - with the choice of shorter string for denominators.:: + with the choice of shorter string for denominators. :: sage: T. = Zp(5, print_mode='terse'); c = T(-707); c 95367431639918 + O(unif^20) @@ -1660,7 +1660,7 @@ class Zp_class(UniqueFactory): Restriction: you can only use the digits printing mode for small primes. Namely, `p` must be less than the length of the alphabet - tuple (default alphabet has length 62).:: + tuple (default alphabet has length 62). :: sage: R = Zp(5, print_mode='digits'); a = R(70700); repr(a) '...4230300' @@ -1670,7 +1670,7 @@ class Zp_class(UniqueFactory): Note that it's not possible to read off the precision from the representation in this mode. - *print_max_terms* limits the number of digits that are printed.:: + *print_max_terms* limits the number of digits that are printed. :: sage: S = Zp(5, print_max_terms=4); S(-70700) 2*5^2 + 4*5^3 + 5^4 + 2*5^5 + ... + O(5^22) @@ -1711,17 +1711,17 @@ class Zp_class(UniqueFactory): Again, note that it's not possible to read off the precision from the representation in this mode. - *print_pos* controls whether the digits can be negative.:: + *print_pos* controls whether the digits can be negative. :: sage: S = Zp(5, print_mode='bars',print_pos=False); b = S(-70700); repr(b) '...-1|0|2|2|-1|2|0|0' - *print_max_terms* limits the number of digits that are printed.:: + *print_max_terms* limits the number of digits that are printed. :: sage: T = Zp(5, print_max_terms=4); T(-70700) 2*5^2 + 4*5^3 + 5^4 + 2*5^5 + ... + O(5^22) - *print_sep* controls the separation character.:: + *print_sep* controls the separation character. :: sage: U = Zp(5, print_mode='bars', print_sep=']['); a = U(70700); repr(a) '...4][2][3][0][3][0][0' @@ -1747,7 +1747,7 @@ class Zp_class(UniqueFactory): EXAMPLES: We allow non-prime `p`, but only if ``check = False``. Note that some - features will not work.:: + features will not work. :: sage: K = Zp(15, check=False); a = K(999); a 9 + 6*15 + 4*15^2 + O(15^20) @@ -2020,7 +2020,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, precision, so the effect of various arithmetic operations on precision is tracked. When you cast an exact element into a capped relative field, it truncates it to the precision cap of the - field.:: + field. :: sage: R. = Zq(9, 5, 'capped-rel', print_mode='series'); b = (1+2*a)^4; b 2 + (2*a + 2)*3 + (2*a + 1)*3^2 + O(3^5) @@ -2029,7 +2029,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: b + c 2 + (2*a + 2)*3 + (2*a + 2)*3^2 + 3^4 + O(3^5) - One can invert non-units: the result is in the fraction field.:: + One can invert non-units: the result is in the fraction field. :: sage: d = ~(3*b+c); d 2*3^-1 + (a + 1) + (a + 1)*3 + a*3^3 + O(3^4) @@ -2038,7 +2038,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, The capped absolute case is the same as the capped relative case, except that the cap is on the absolute precision rather than the - relative precision.:: + relative precision. :: sage: R. = Zq(9, 5, 'capped-abs', print_mode='series'); b = 3*(1+2*a)^4; b 2*3 + (2*a + 2)*3^2 + (2*a + 1)*3^3 + O(3^5) @@ -2050,7 +2050,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, 2*3^2 + (2*a + 2)*3^3 + O(3^4) The fixed modulus case is like the capped absolute, except that - individual elements don't track their precision.:: + individual elements don't track their precision. :: sage: R. = Zq(9, 5, 'fixed-mod', print_mode='series'); b = 3*(1+2*a)^4; b 2*3 + (2*a + 2)*3^2 + (2*a + 1)*3^3 @@ -2075,7 +2075,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, 1. A **polynomial**. The base ring can be `\ZZ`, `\QQ`, `\ZZ_p`, `\GF{p}`, or anything that can - be converted to `\ZZ_p`.:: + be converted to `\ZZ_p`. :: sage: P. = ZZ[] sage: R. = Zq(27, modulus = x^3 + 2*x + 1); R.modulus() @@ -2097,7 +2097,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, unless the modulus is different, or the precision of the modulus differs. In the case of ``V``, the modulus is only given to precision - ``1``, so the resulting field has a precision cap of ``1``.:: + ``1``, so the resulting field has a precision cap of ``1``. :: sage: V.precision_cap() 1 @@ -2110,7 +2110,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: W. = Zq(27, modulus = modulus); W.precision_cap() 7 - 2. The modulus can also be given as a **symbolic expression**.:: + 2. The modulus can also be given as a **symbolic expression**. :: sage: x = var('x') sage: X. = Zq(27, modulus = x^3 + 2*x + 1); X.modulus() @@ -2119,7 +2119,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, True By default, the polynomial chosen is the standard lift of the - generator chosen for `\GF{q}`.:: + generator chosen for `\GF{q}`. :: sage: GF(125, 'a').modulus() x^3 + 3*x + 3 @@ -2127,7 +2127,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, (1 + O(5^20))*x^3 + O(5^20)*x^2 + (3 + O(5^20))*x + 3 + O(5^20) However, you can choose another polynomial if desired (as long as - the reduction to `\GF{p}[x]` is irreducible).:: + the reduction to `\GF{p}[x]` is irreducible). :: sage: P. = ZZ[] sage: Z. = Zq(125, modulus = x^3 + 3*x^2 + x + 1); Z.modulus() @@ -2146,7 +2146,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, compact. Note that the printing options affect whether different `p`-adic fields are considered equal. - 1. **series**: elements are displayed as series in `p`.:: + 1. **series**: elements are displayed as series in `p`. :: sage: R. = Zq(9, 20, 'capped-rel', print_mode='series'); (1+2*a)^4 2 + (2*a + 2)*3 + (2*a + 1)*3^2 + O(3^20) @@ -2158,26 +2158,26 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, True *print_pos* controls whether negatives can be used in the - coefficients of powers of `p`.:: + coefficients of powers of `p`. :: sage: S. = Zq(9, print_mode='series', print_pos=False); (1+2*b)^4 -1 - b*3 - 3^2 + (b + 1)*3^3 + O(3^20) sage: -3*(1+2*b)^4 3 + b*3^2 + 3^3 + (-b - 1)*3^4 + O(3^21) - *ram_name* controls how the prime is printed.:: + *ram_name* controls how the prime is printed. :: sage: T. = Zq(9, print_mode='series', ram_name='p'); 3*(1+2*d)^4 2*p + (2*d + 2)*p^2 + (2*d + 1)*p^3 + O(p^21) *print_max_ram_terms* limits the number of powers of `p` that - appear.:: + appear. :: sage: U. = Zq(9, print_mode='series', print_max_ram_terms=4); repr(-3*(1+2*e)^4) '3 + e*3^2 + 3^3 + (2*e + 2)*3^4 + ... + O(3^21)' *print_max_unram_terms* limits the number of terms that appear in a - coefficient of a power of `p`.:: + coefficient of a power of `p`. :: sage: V. = Zq(128, prec = 8, print_mode='series'); repr((1+f)^9) '(f^3 + 1) + (f^5 + f^4 + f^3 + f^2)*2 + (f^6 + f^5 + f^4 + f + 1)*2^2 + (f^5 + f^4 + f^2 + f + 1)*2^3 + (f^6 + f^5 + f^4 + f^3 + f^2 + f + 1)*2^4 + (f^5 + f^4)*2^5 + (f^6 + f^5 + f^4 + f^3 + f + 1)*2^6 + (f + 1)*2^7 + O(2^8)' @@ -2214,14 +2214,14 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, 3^-3 * (41 + a) + O(3) *print_pos* controls whether to use a balanced representation or - not.:: + not. :: sage: S. = Zq(9, 7, print_mode='val-unit', print_pos=False); b = (1+3*a)^9 - 1; b 3^3 * (15 - 17*a) + O(3^7) sage: ~b 3^-3 * (-40 + a) + O(3) - *ram_name* affects how the prime is printed.:: + *ram_name* affects how the prime is printed. :: sage: A. = Zp(next_prime(10^6), print_mode='val-unit')[] sage: T. = Zq(next_prime(10^6)^3, 4, print_mode='val-unit', ram_name='p', modulus=x^3+385831*x^2+106556*x+321036); b = (next_prime(10^6)^2*(a^2 + a - 4)^4); b @@ -2230,7 +2230,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, p^2 * 1 + O(p^6) *print_max_terse_terms* controls how many terms of the polynomial - appear in the unit part.:: + appear in the unit part. :: sage: U. = Zq(17^4, 6, print_mode='val-unit', print_max_terse_terms=3); b = (17*(a^3-a+14)^6); b 17 * (12131797 + 12076378*a + 10809706*a^2 + ...) + O(17^7) @@ -2252,7 +2252,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, (False, False, False, False, False, False) 3. **terse**: elements are displayed as a polynomial of degree less - than the degree of the extension.:: + than the degree of the extension. :: sage: R. = Zq(125, print_mode='terse') sage: (a+5)^177 @@ -2266,13 +2266,13 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, As of version 3.3, if coefficients of the polynomial are non-integral, they are always printed with an explicit power of `p` - in the denominator.:: + in the denominator. :: sage: 5*a + a^2/25 5*a + 1/5^2*a^2 + O(5^18) *print_pos* controls whether to use a balanced representation or - not.:: + not. :: sage: (a-5)^6 22864 + 95367431627998*a + 8349*a^2 + O(5^20) @@ -2281,13 +2281,13 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: (a - 1/5)^6 -20624/5^6 + 18369/5^5*a + 1353/5^3*a^2 + O(5^14) - *ram_name* affects how the prime is printed.:: + *ram_name* affects how the prime is printed. :: sage: T. = Zq(125, print_mode='terse', ram_name='p'); (a - 1/5)^6 95367431620001/p^6 + 18369/p^5*a + 1353/p^3*a^2 + O(p^14) *print_max_terse_terms* controls how many terms of the polynomial - are shown.:: + are shown. :: sage: U. = Zq(625, print_mode='terse', print_max_terse_terms=2); (a-1/5)^6 106251/5^6 + 49994/5^5*a + ... + O(5^14) @@ -2314,7 +2314,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, for small fields, but this isn't implemented. 5. **bars**: elements are displayed in a similar fashion to series, - but more compactly.:: + but more compactly. :: sage: R. = Zq(125); (a+5)^6 (4*a^2 + 3*a + 4) + (3*a^2 + 2*a)*5 + (a^2 + a + 1)*5^2 + (3*a + 2)*5^3 + (3*a^2 + a + 3)*5^4 + (2*a^2 + 3*a + 2)*5^5 + O(5^20) @@ -2324,7 +2324,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, '...[0, 4]|[1, 4]|[2, 0, 2]|[1, 4, 3]|[2, 3, 1]|[4, 4, 3]|[2, 4, 4]|[4, 3, 4]' Note that it's not possible to read off the precision from the - representation in this mode.:: + representation in this mode. :: sage: b = a + 3; repr(b) '...[3, 1]' @@ -2335,7 +2335,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: c.precision_absolute() 4 - *print_pos* controls whether the digits can be negative.:: + *print_pos* controls whether the digits can be negative. :: sage: S. = Zq(125, print_mode='bars', print_pos=False); repr((a-5)^6) '...[1, -1, 1]|[2, 1, -2]|[2, 0, -2]|[-2, -1, 2]|[0, 0, -1]|[-2]|[-1, -2, -1]' @@ -2344,7 +2344,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, *print_max_ram_terms* controls the maximum number of "digits" shown. Note that this puts a cap on the relative precision, not the - absolute precision.:: + absolute precision. :: sage: T. = Zq(125, print_max_ram_terms=3, print_pos=False); (a-5)^6 (-a^2 - 2*a - 1) - 2*5 - a^2*5^2 + ... + O(5^20) @@ -2353,7 +2353,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: (a-1/5)^6 5^-6 - a*5^-5 - a*5^-4 + ... + O(5^14) - *print_sep* controls the separating character (``'|'`` by default).:: + *print_sep* controls the separating character (``'|'`` by default). :: sage: U. = Zq(625, print_mode='bars', print_sep=''); b = (a+5)^6; repr(b) '...[0, 1][4, 0, 2][3, 2, 2, 3][4, 2, 2, 4][0, 3][1, 1, 3][3, 1, 4, 1]' @@ -2392,7 +2392,7 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, However, you can use ``check=False`` to pass in a pair in order to not have to factor. If you do so, you need to use names explicitly - rather than the ``R.`` syntax.:: + rather than the ``R.`` syntax. :: sage: p = next_prime(2^123) sage: k = Zp(p) From e8c952e24660402b6e75d1c45251600f28e713d3 Mon Sep 17 00:00:00 2001 From: Markus Wageringel Date: Sun, 12 Jul 2020 13:03:16 +0200 Subject: [PATCH 075/217] 30114: fix indentation of enumerated list entries --- src/sage/rings/padics/factory.py | 544 +++++++++++++++---------------- 1 file changed, 272 insertions(+), 272 deletions(-) diff --git a/src/sage/rings/padics/factory.py b/src/sage/rings/padics/factory.py index 00c9f0991f2..95feaa27f54 100644 --- a/src/sage/rings/padics/factory.py +++ b/src/sage/rings/padics/factory.py @@ -407,29 +407,29 @@ class Qp_class(UniqueFactory): sage: b = R(-70700); b 2*5^2 + 4*5^3 + 5^4 + 2*5^5 + 4*5^7 + 4*5^8 + 4*5^9 + 4*5^10 + 4*5^11 + 4*5^12 + 4*5^13 + 4*5^14 + 4*5^15 + 4*5^16 + 4*5^17 + 4*5^18 + 4*5^19 + 4*5^20 + 4*5^21 + O(5^22) - *print_pos* controls whether negatives can be used in the - coefficients of powers of `p`. :: + *print_pos* controls whether negatives can be used in the + coefficients of powers of `p`. :: sage: S = Qp(5, print_mode='series', print_pos=False); a = S(70700); a -2*5^2 + 5^3 - 2*5^4 - 2*5^5 + 5^7 + O(5^22) sage: b = S(-70700); b 2*5^2 - 5^3 + 2*5^4 + 2*5^5 - 5^7 + O(5^22) - *print_max_terms* limits the number of terms that appear. :: + *print_max_terms* limits the number of terms that appear. :: sage: T = Qp(5, print_mode='series', print_max_terms=4); b = R(-70700); repr(b) '2*5^2 + 4*5^3 + 5^4 + 2*5^5 + ... + O(5^22)' - *names* affects how the prime is printed. :: + *names* affects how the prime is printed. :: sage: U.

= Qp(5); p p + O(p^21) - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'bigoh' - (or equivalently ``True``) or 'bigoh'. - The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'bigoh' + (or equivalently ``True``) or 'bigoh'. + The default is ``False`` for the ``'floating-point'`` type + and ``True`` for all other types. :: sage: Qp(5)(6) 1 + 5 + O(5^20) @@ -439,9 +439,9 @@ class Qp_class(UniqueFactory): sage: QpFP(5)(6) 1 + 5 - *print_sep* and *print_alphabet* have no effect in series mode. + *print_sep* and *print_alphabet* have no effect in series mode. - Note that print options affect equality:: + Note that print options affect equality:: sage: R == S, R == T, R == U, S == T, S == U, T == U (False, False, False, False, False, False) @@ -453,29 +453,29 @@ class Qp_class(UniqueFactory): sage: b = R(-707/5); b 5^-1 * 95367431639918 + O(5^19) - *print_pos* controls whether to use a balanced representation or - not. :: + *print_pos* controls whether to use a balanced representation or + not. :: sage: S = Qp(5, print_mode='val-unit', print_pos=False); b = S(-70700); b 5^2 * (-2828) + O(5^22) - *names* affects how the prime is printed. :: + *names* affects how the prime is printed. :: sage: T = Qp(5, print_mode='val-unit', names='pi'); a = T(70700); a pi^2 * 2828 + O(pi^22) - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``) or 'bigoh' - (or equivalently ``True``). - The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``) or 'bigoh' + (or equivalently ``True``). + The default is ``False`` for the ``'floating-point'`` type + and ``True`` for all other types. :: sage: Qp(5, print_mode='val-unit', show_prec=False)(30) 5 * 6 - *print_max_terms*, *print_sep* and *print_alphabet* have no effect. + *print_max_terms*, *print_sep* and *print_alphabet* have no effect. - Equality again depends on the printing options:: + Equality again depends on the printing options:: sage: R == S, R == T, S == T (False, False, False) @@ -490,47 +490,47 @@ class Qp_class(UniqueFactory): sage: c = R(-707/5); c 95367431639918/5 + O(5^19) - The denominator, as of version 3.3, is always printed - explicitly as a power of `p`, for predictability. :: + The denominator, as of version 3.3, is always printed + explicitly as a power of `p`, for predictability. :: sage: d = R(707/5^2); d 707/5^2 + O(5^18) - *print_pos* controls whether to use a balanced representation or not. :: + *print_pos* controls whether to use a balanced representation or not. :: sage: S = Qp(5, print_mode='terse', print_pos=False); b = S(-70700); b -70700 + O(5^22) sage: c = S(-707/5); c -707/5 + O(5^19) - *name* affects how the name is printed. :: + *name* affects how the name is printed. :: sage: T. = Qp(5, print_mode='terse'); c = T(-707/5); c 95367431639918/unif + O(unif^19) sage: d = T(-707/5^10); d 95367431639918/unif^10 + O(unif^10) - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``) or 'bigoh' - (or equivalently ``True``). - The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``) or 'bigoh' + (or equivalently ``True``). + The default is ``False`` for the ``'floating-point'`` type + and ``True`` for all other types. :: sage: Qp(5, print_mode='terse', show_prec=False)(6) 6 - *print_max_terms*, *print_sep* and *print_alphabet* have no effect. + *print_max_terms*, *print_sep* and *print_alphabet* have no effect. - Equality depends on printing options:: + Equality depends on printing options:: sage: R == S, R == T, S == T (False, False, False) 4. **digits**: elements are displayed as a string of base `p` digits - Restriction: you can only use the digits printing mode for - small primes. Namely, `p` must be less than the length of the - alphabet tuple (default alphabet has length 62). :: + Restriction: you can only use the digits printing mode for + small primes. Namely, `p` must be less than the length of the + alphabet tuple (default alphabet has length 62). :: sage: R = Qp(5, print_mode='digits'); a = R(70700); repr(a) '...0000000000000004230300' @@ -541,11 +541,11 @@ class Qp_class(UniqueFactory): sage: d = R(-707/5^2); repr(d) '...444444444444444341.33' - Observe that the significant 0's are printed even if they are - located in front of the number. On the contrary, unknown digits - located after the comma appears as question marks. - The precision can therefore be read in this mode as well. - Here are more examples:: + Observe that the significant 0's are printed even if they are + located in front of the number. On the contrary, unknown digits + located after the comma appears as question marks. + The precision can therefore be read in this mode as well. + Here are more examples:: sage: p = 7 sage: K = Qp(p, prec=10, print_mode='digits') @@ -558,9 +558,9 @@ class Qp_class(UniqueFactory): sage: repr(K(p^-20)) '...?.??????????0000000001' - *print_max_terms* limits the number of digits that are printed. - Note that if the valuation of the element is very negative, more - digits will be printed. :: + *print_max_terms* limits the number of digits that are printed. + Note that if the valuation of the element is very negative, more + digits will be printed. :: sage: S = Qp(5, print_max_terms=4); S(-70700) 2*5^2 + 4*5^3 + 5^4 + 2*5^5 + ... + O(5^22) @@ -573,19 +573,19 @@ class Qp_class(UniqueFactory): sage: S(-707/5^4) 3*5^-4 + 3*5^-3 + 5^-2 + 4*5^-1 + ... + O(5^16) - *print_alphabet* controls the symbols used to substitute for digits - greater than 9. + *print_alphabet* controls the symbols used to substitute for digits + greater than 9. - Defaults to ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'):: + Defaults to ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'):: sage: T = Qp(5, print_mode='digits', print_alphabet=('1','2','3','4','5')); repr(T(-70700)) '...5555555555555551325311' - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'dots' - (or equivalently ``True``) or 'bigoh'. - The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'dots' + (or equivalently ``True``) or 'bigoh'. + The default is ``False`` for the ``'floating-point'`` type + and ``True`` for all other types. :: sage: repr(Zp(5, print_mode='digits', show_prec=True)(6)) '...00000000000000000011' @@ -593,9 +593,9 @@ class Qp_class(UniqueFactory): sage: repr(Zp(5, print_mode='digits', show_prec='bigoh')(6)) '11 + O(5^20)' - *print_pos*, *name* and *print_sep* have no effect. + *print_pos*, *name* and *print_sep* have no effect. - Equality depends on printing options:: + Equality depends on printing options:: sage: R == S, R == T, S == T (False, False, False) @@ -610,16 +610,16 @@ class Qp_class(UniqueFactory): sage: d = R(-707/5^2); repr(d) '...4|4|4|4|4|4|4|4|4|4|4|4|4|4|4|3|4|1|.|3|3' - Again, note that it's not possible to read off the precision from the representation in this mode. + Again, note that it's not possible to read off the precision from the representation in this mode. - *print_pos* controls whether the digits can be negative. :: + *print_pos* controls whether the digits can be negative. :: sage: S = Qp(5, print_mode='bars',print_pos=False); b = S(-70700); repr(b) '...-1|0|2|2|-1|2|0|0' - *print_max_terms* limits the number of digits that are printed. - Note that if the valuation of the element is very negative, more - digits will be printed. :: + *print_max_terms* limits the number of digits that are printed. + Note that if the valuation of the element is very negative, more + digits will be printed. :: sage: T = Qp(5, print_max_terms=4); T(-70700) 2*5^2 + 4*5^3 + 5^4 + 2*5^5 + ... + O(5^22) @@ -632,23 +632,23 @@ class Qp_class(UniqueFactory): sage: T(-707/5^4) 3*5^-4 + 3*5^-3 + 5^-2 + 4*5^-1 + ... + O(5^16) - *print_sep* controls the separation character. :: + *print_sep* controls the separation character. :: sage: U = Qp(5, print_mode='bars', print_sep=']['); a = U(70700); repr(a) '...4][2][3][0][3][0][0' - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'dots' - (or equivalently ``True``) or 'bigoh' - The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'dots' + (or equivalently ``True``) or 'bigoh' + The default is ``False`` for the ``'floating-point'`` type + and ``True`` for all other types. :: sage: repr(Qp(5, print_mode='bars', show_prec='bigoh')(6)) '...1|1 + O(5^20)' - *name* and *print_alphabet* have no effect. + *name* and *print_alphabet* have no effect. - Equality depends on printing options:: + Equality depends on printing options:: sage: R == S, R == T, R == U, S == T, S == U, T == U (False, False, False, False, False, False) @@ -866,7 +866,7 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, 1. A **polynomial**. - The base ring can be `\ZZ`, `\QQ`, `\ZZ_p`, `\QQ_p`, `\GF{p}`. :: + The base ring can be `\ZZ`, `\QQ`, `\ZZ_p`, `\QQ_p`, `\GF{p}`. :: sage: P. = ZZ[] sage: R. = Qq(27, modulus = x^3 + 2*x + 1); R.modulus() @@ -880,15 +880,15 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: P. = GF(3)[] sage: V. = Qq(27, modulus = x^3 + 2*x + 1) - Which form the modulus is given in has no effect on the unramified - extension produced:: + Which form the modulus is given in has no effect on the unramified + extension produced:: sage: R == S, S == T, T == U, U == V (True, True, True, False) - unless the precision of the modulus differs. In the case of V, - the modulus is only given to precision 1, so the resulting field - has a precision cap of 1. :: + unless the precision of the modulus differs. In the case of V, + the modulus is only given to precision 1, so the resulting field + has a precision cap of 1. :: sage: V.precision_cap() 1 @@ -909,16 +909,16 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: X == R True - By default, the polynomial chosen is the standard lift of the - generator chosen for `\GF{q}`. :: + By default, the polynomial chosen is the standard lift of the + generator chosen for `\GF{q}`. :: sage: GF(125, 'a').modulus() x^3 + 3*x + 3 sage: Y. = Qq(125); Y.modulus() (1 + O(5^20))*x^3 + O(5^20)*x^2 + (3 + O(5^20))*x + 3 + O(5^20) - However, you can choose another polynomial if desired (as long as - the reduction to `\GF{p}[x]` is irreducible). :: + However, you can choose another polynomial if desired (as long as + the reduction to `\GF{p}[x]` is irreducible). :: sage: P. = ZZ[] sage: Z. = Qq(125, modulus = x^3 + 3*x^2 + x + 1); Z.modulus() @@ -946,26 +946,26 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: ~(3*a+18) (a + 2)*3^-1 + 1 + 2*3 + (a + 1)*3^2 + 3^3 + 2*3^4 + (a + 1)*3^5 + 3^6 + 2*3^7 + (a + 1)*3^8 + 3^9 + 2*3^10 + (a + 1)*3^11 + 3^12 + 2*3^13 + (a + 1)*3^14 + 3^15 + 2*3^16 + (a + 1)*3^17 + 3^18 + O(3^19) - *print_pos* controls whether negatives can be used in the - coefficients of powers of `p`. :: + *print_pos* controls whether negatives can be used in the + coefficients of powers of `p`. :: sage: S. = Qq(9, print_mode='series', print_pos=False); (1+2*b)^4 -1 - b*3 - 3^2 + (b + 1)*3^3 + O(3^20) sage: -3*(1+2*b)^4 3 + b*3^2 + 3^3 + (-b - 1)*3^4 + O(3^21) - *ram_name* controls how the prime is printed. :: + *ram_name* controls how the prime is printed. :: sage: T. = Qq(9, print_mode='series', ram_name='p'); 3*(1+2*d)^4 2*p + (2*d + 2)*p^2 + (2*d + 1)*p^3 + O(p^21) - *print_max_ram_terms* limits the number of powers of `p` that appear. :: + *print_max_ram_terms* limits the number of powers of `p` that appear. :: sage: U. = Qq(9, print_mode='series', print_max_ram_terms=4); repr(-3*(1+2*e)^4) '3 + e*3^2 + 3^3 + (2*e + 2)*3^4 + ... + O(3^21)' - *print_max_unram_terms* limits the number of terms that appear in a - coefficient of a power of `p`. :: + *print_max_unram_terms* limits the number of terms that appear in a + coefficient of a power of `p`. :: sage: V. = Qq(128, prec = 8, print_mode='series'); repr((1+f)^9) '(f^3 + 1) + (f^5 + f^4 + f^3 + f^2)*2 + (f^6 + f^5 + f^4 + f + 1)*2^2 + (f^5 + f^4 + f^2 + f + 1)*2^3 + (f^6 + f^5 + f^4 + f^3 + f^2 + f + 1)*2^4 + (f^5 + f^4)*2^5 + (f^6 + f^5 + f^4 + f^3 + f + 1)*2^6 + (f + 1)*2^7 + O(2^8)' @@ -978,18 +978,18 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: V. = Qq(128, prec = 8, print_mode='series', print_max_unram_terms = 0); repr((1+f)^9 - 1 - f^3) '(...)*2 + (...)*2^2 + (...)*2^3 + (...)*2^4 + (...)*2^5 + (...)*2^6 + (...)*2^7 + O(2^8)' - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'bigoh' - (or equivalently ``True``). - The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'bigoh' + (or equivalently ``True``). + The default is ``False`` for the ``'floating-point'`` type + and ``True`` for all other types. :: sage: U. = Qq(9, 2, show_prec=False); repr(-3*(1+2*e)^4) '3 + e*3^2' - *print_sep* and *print_max_terse_terms* have no effect. + *print_sep* and *print_max_terse_terms* have no effect. - Note that print options affect equality:: + Note that print options affect equality:: sage: R == S, R == T, R == U, R == V, S == T, S == U, S == V, T == U, T == V, U == V (False, False, False, False, False, False, False, False, False, False) @@ -1001,15 +1001,15 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: ~b 3^-3 * (41 + a) + O(3) - *print_pos* controls whether to use a balanced representation or - not. :: + *print_pos* controls whether to use a balanced representation or + not. :: sage: S. = Qq(9, 7, print_mode='val-unit', print_pos=False); b = (1+3*a)^9 - 1; b 3^3 * (15 - 17*a) + O(3^7) sage: ~b 3^-3 * (-40 + a) + O(3) - *ram_name* affects how the prime is printed. :: + *ram_name* affects how the prime is printed. :: sage: A. = Qp(next_prime(10^6), print_mode='val-unit')[] sage: T. = Qq(next_prime(10^6)^3, 4, print_mode='val-unit', ram_name='p', modulus=x^3+385831*x^2+106556*x+321036); b = ~(next_prime(10^6)^2*(a^2 + a - 4)); b @@ -1017,27 +1017,27 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: b * (a^2 + a - 4) p^-2 * 1 + O(p^2) - *print_max_terse_terms* controls how many terms of the polynomial - appear in the unit part. :: + *print_max_terse_terms* controls how many terms of the polynomial + appear in the unit part. :: sage: U. = Qq(17^4, 6, print_mode='val-unit', print_max_terse_terms=3); b = ~(17*(a^3-a+14)); b 17^-1 * (22110411 + 11317400*a + 20656972*a^2 + ...) + O(17^5) sage: b*17*(a^3-a+14) 1 + O(17^6) - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'bigoh' - (or equivalently ``True``). - The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'bigoh' + (or equivalently ``True``). + The default is ``False`` for the ``'floating-point'`` type + and ``True`` for all other types. :: sage: U. = Qq(9, 2, print_mode='val-unit', show_prec=False); repr(-3*(1+2*e)^4) '3 * (1 + 3*e)' - *print_sep*, *print_max_ram_terms* and *print_max_unram_terms* have no - effect. + *print_sep*, *print_max_ram_terms* and *print_max_unram_terms* have no + effect. - Equality again depends on the printing options:: + Equality again depends on the printing options:: sage: R == S, R == T, R == U, S == T, S == U, T == U (False, False, False, False, False, False) @@ -1051,15 +1051,15 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: (a/5+1)^177 68210977979428/5^177 + 90313850704069/5^177*a + 73948093055069/5^177*a^2 + O(5^-157) - As of version 3.3, if coefficients of the polynomial are - non-integral, they are always printed with an explicit power of `p` - in the denominator. :: + As of version 3.3, if coefficients of the polynomial are + non-integral, they are always printed with an explicit power of `p` + in the denominator. :: sage: 5*a + a^2/25 5*a + 1/5^2*a^2 + O(5^18) - *print_pos* controls whether to use a balanced representation or - not. :: + *print_pos* controls whether to use a balanced representation or + not. :: sage: (a-5)^6 22864 + 95367431627998*a + 8349*a^2 + O(5^20) @@ -1068,30 +1068,30 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: (a - 1/5)^6 -20624/5^6 + 18369/5^5*a + 1353/5^3*a^2 + O(5^14) - *ram_name* affects how the prime is printed. :: + *ram_name* affects how the prime is printed. :: sage: T. = Qq(125, print_mode='terse', ram_name='p'); (a - 1/5)^6 95367431620001/p^6 + 18369/p^5*a + 1353/p^3*a^2 + O(p^14) - *print_max_terse_terms* controls how many terms of the polynomial - are shown. :: + *print_max_terse_terms* controls how many terms of the polynomial + are shown. :: sage: U. = Qq(625, print_mode='terse', print_max_terse_terms=2); (a-1/5)^6 106251/5^6 + 49994/5^5*a + ... + O(5^14) - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'bigoh' - (or equivalently ``True``). - The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'bigoh' + (or equivalently ``True``). + The default is ``False`` for the ``'floating-point'`` type + and ``True`` for all other types. :: sage: U. = Qq(9, 2, print_mode='terse', show_prec=False); repr(-3*(1+2*e)^4) '3 + 9*e' - *print_sep*, *print_max_ram_terms* and *print_max_unram_terms* have no - effect. + *print_sep*, *print_max_ram_terms* and *print_max_unram_terms* have no + effect. - Equality again depends on the printing options:: + Equality again depends on the printing options:: sage: R == S, R == T, R == U, S == T, S == U, T == U (False, False, False, False, False, False) @@ -1099,8 +1099,8 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, 4. **digits**: This print mode is not available when the residue field is not prime. - It might make sense to have a dictionary for small fields, but - this isn't implemented. + It might make sense to have a dictionary for small fields, but + this isn't implemented. 5. **bars**: elements are displayed in a similar fashion to series, but more compactly. :: @@ -1112,21 +1112,21 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: repr((a-5)^6) '...[0, 4]|[1, 4]|[2, 0, 2]|[1, 4, 3]|[2, 3, 1]|[4, 4, 3]|[2, 4, 4]|[4, 3, 4]' - Note that elements with negative valuation are shown with a - decimal point at valuation 0. :: + Note that elements with negative valuation are shown with a + decimal point at valuation 0. :: sage: repr((a+1/5)^6) '...[3]|[4, 1, 3]|.|[1, 2, 3]|[3, 3]|[0, 0, 3]|[0, 1]|[0, 1]|[1]' sage: repr((a+1/5)^2) '...[0, 0, 1]|.|[0, 2]|[1]' - If not enough precision is known, ``'?'`` is used instead. :: + If not enough precision is known, ``'?'`` is used instead. :: sage: repr((a+R(1/5,relprec=3))^7) '...|.|?|?|?|?|[0, 1, 1]|[0, 2]|[1]' - Note that it's not possible to read off the precision from the - representation in this mode. :: + Note that it's not possible to read off the precision from the + representation in this mode. :: sage: b = a + 3; repr(b) '...[3, 1]' @@ -1137,29 +1137,29 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: c.precision_absolute() 4 - *print_pos* controls whether the digits can be negative. :: + *print_pos* controls whether the digits can be negative. :: sage: S. = Qq(125, print_mode='bars', print_pos=False); repr((a-5)^6) '...[1, -1, 1]|[2, 1, -2]|[2, 0, -2]|[-2, -1, 2]|[0, 0, -1]|[-2]|[-1, -2, -1]' sage: repr((a-1/5)^6) '...[0, 1, 2]|[-1, 1, 1]|.|[-2, -1, -1]|[2, 2, 1]|[0, 0, -2]|[0, -1]|[0, -1]|[1]' - *print_max_ram_terms* controls the maximum number of "digits" shown. - Note that this puts a cap on the relative precision, not the - absolute precision. :: + *print_max_ram_terms* controls the maximum number of "digits" shown. + Note that this puts a cap on the relative precision, not the + absolute precision. :: sage: T. = Qq(125, print_max_ram_terms=3, print_pos=False); (a-5)^6 (-a^2 - 2*a - 1) - 2*5 - a^2*5^2 + ... + O(5^20) sage: 5*(a-5)^6 + 50 (-a^2 - 2*a - 1)*5 - a^2*5^3 + (2*a^2 - a - 2)*5^4 + ... + O(5^21) - *print_sep* controls the separating character (``'|'`` by default). :: + *print_sep* controls the separating character (``'|'`` by default). :: sage: U. = Qq(625, print_mode='bars', print_sep=''); b = (a+5)^6; repr(b) '...[0, 1][4, 0, 2][3, 2, 2, 3][4, 2, 2, 4][0, 3][1, 1, 3][3, 1, 4, 1]' - *print_max_unram_terms* controls how many terms are shown in each - "digit":: + *print_max_unram_terms* controls how many terms are shown in each + "digit":: sage: with local_print_mode(U, {'max_unram_terms': 3}): repr(b) '...[0, 1][4,..., 0, 2][3,..., 2, 3][4,..., 2, 4][0, 3][1,..., 1, 3][3,..., 4, 1]' @@ -1170,23 +1170,23 @@ def Qq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: with local_print_mode(U, {'max_unram_terms':0}): repr(b-75*a) '...[...][...][...][...][][...][...]' - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'dots' - (or equivalently ``True``) or 'bigoh' - The default is ``False`` for the ``'floating-point'`` type - and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'dots' + (or equivalently ``True``) or 'bigoh' + The default is ``False`` for the ``'floating-point'`` type + and ``True`` for all other types. :: sage: U. = Qq(9, 2, print_mode='bars', show_prec=True); repr(-3*(1+2*e)^4) '...[0, 1]|[1]|[]' - *ram_name* and *print_max_terse_terms* have no effect. + *ram_name* and *print_max_terse_terms* have no effect. - Equality depends on printing options:: + Equality depends on printing options:: sage: R == S, R == T, R == U, S == T, S == U, T == U (False, False, False, False, False, False) - EXAMPLES + EXAMPLES: Unlike for ``Qp``, you can't create ``Qq(N)`` when ``N`` is not a prime power. @@ -1554,36 +1554,36 @@ class Zp_class(UniqueFactory): sage: b = R(-70700); b 2*5^2 + 4*5^3 + 5^4 + 2*5^5 + 4*5^7 + 4*5^8 + 4*5^9 + 4*5^10 + 4*5^11 + 4*5^12 + 4*5^13 + 4*5^14 + 4*5^15 + 4*5^16 + 4*5^17 + 4*5^18 + 4*5^19 + 4*5^20 + 4*5^21 + O(5^22) - *print_pos* controls whether negatives can be used in the - coefficients of powers of `p`. :: + *print_pos* controls whether negatives can be used in the + coefficients of powers of `p`. :: sage: S = Zp(5, print_mode='series', print_pos=False); a = S(70700); a -2*5^2 + 5^3 - 2*5^4 - 2*5^5 + 5^7 + O(5^22) sage: b = S(-70700); b 2*5^2 - 5^3 + 2*5^4 + 2*5^5 - 5^7 + O(5^22) - *print_max_terms* limits the number of terms that appear. :: + *print_max_terms* limits the number of terms that appear. :: sage: T = Zp(5, print_mode='series', print_max_terms=4); b = R(-70700); b 2*5^2 + 4*5^3 + 5^4 + 2*5^5 + ... + O(5^22) - *names* affects how the prime is printed. :: + *names* affects how the prime is printed. :: sage: U.

= Zp(5); p p + O(p^21) - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'bigoh' - (or equivalently ``True``). - The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'bigoh' + (or equivalently ``True``). + The default is ``False`` for the ``'floating-point'`` and + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: Zp(5, show_prec=False)(6) 1 + 5 - *print_sep* and *print_alphabet* have no effect. + *print_sep* and *print_alphabet* have no effect. - Note that print options affect equality:: + Note that print options affect equality:: sage: R == S, R == T, R == U, S == T, S == U, T == U (False, False, False, False, False, False) @@ -1595,29 +1595,29 @@ class Zp_class(UniqueFactory): sage: b = R(-707*5); b 5 * 95367431639918 + O(5^21) - *print_pos* controls whether to use a balanced representation or - not. :: + *print_pos* controls whether to use a balanced representation or + not. :: sage: S = Zp(5, print_mode='val-unit', print_pos=False); b = S(-70700); b 5^2 * (-2828) + O(5^22) - *names* affects how the prime is printed. :: + *names* affects how the prime is printed. :: sage: T = Zp(5, print_mode='val-unit', names='pi'); a = T(70700); a pi^2 * 2828 + O(pi^22) - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'bigoh' - (or equivalently ``True``). - The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'bigoh' + (or equivalently ``True``). + The default is ``False`` for the ``'floating-point'`` and + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: Zp(5, print_mode='val-unit', show_prec=False)(30) 5 * 6 - *print_max_terms*, *print_sep* and *print_alphabet* have no effect. + *print_max_terms*, *print_sep* and *print_alphabet* have no effect. - Equality again depends on the printing options:: + Equality again depends on the printing options:: sage: R == S, R == T, S == T (False, False, False) @@ -1629,73 +1629,73 @@ class Zp_class(UniqueFactory): sage: b = R(-70700); b 2384185790944925 + O(5^22) - *print_pos* controls whether to use a balanced representation or not. :: + *print_pos* controls whether to use a balanced representation or not. :: sage: S = Zp(5, print_mode='terse', print_pos=False); b = S(-70700); b -70700 + O(5^22) - *name* affects how the name is printed. Note that this interacts - with the choice of shorter string for denominators. :: + *name* affects how the name is printed. Note that this interacts + with the choice of shorter string for denominators. :: sage: T. = Zp(5, print_mode='terse'); c = T(-707); c 95367431639918 + O(unif^20) - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'bigoh' - (or equivalently ``True``). - The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'bigoh' + (or equivalently ``True``). + The default is ``False`` for the ``'floating-point'`` and + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: Zp(5, print_mode='terse', show_prec=False)(30) 30 - *print_max_terms*, *print_sep* and *print_alphabet* have no effect. + *print_max_terms*, *print_sep* and *print_alphabet* have no effect. - Equality depends on printing options:: + Equality depends on printing options:: sage: R == S, R == T, S == T (False, False, False) 4. **digits**: elements are displayed as a string of base `p` digits - Restriction: you can only use the digits printing mode for small - primes. Namely, `p` must be less than the length of the alphabet - tuple (default alphabet has length 62). :: + Restriction: you can only use the digits printing mode for small + primes. Namely, `p` must be less than the length of the alphabet + tuple (default alphabet has length 62). :: sage: R = Zp(5, print_mode='digits'); a = R(70700); repr(a) '...4230300' sage: b = R(-70700); repr(b) '...4444444444444440214200' - Note that it's not possible to read off the precision from the - representation in this mode. + Note that it's not possible to read off the precision from the + representation in this mode. - *print_max_terms* limits the number of digits that are printed. :: + *print_max_terms* limits the number of digits that are printed. :: sage: S = Zp(5, print_max_terms=4); S(-70700) 2*5^2 + 4*5^3 + 5^4 + 2*5^5 + ... + O(5^22) - *print_alphabet* controls the symbols used to substitute for digits - greater than 9. Defaults to - ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'):: + *print_alphabet* controls the symbols used to substitute for digits + greater than 9. Defaults to + ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'):: sage: T = Zp(5, print_mode='digits', print_alphabet=('1','2','3','4','5')); repr(T(-70700)) '...5555555555555551325311' - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'dots' - (or equivalently ``True``) or 'bigoh'. - The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'dots' + (or equivalently ``True``) or 'bigoh'. + The default is ``False`` for the ``'floating-point'`` and + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: repr(Zp(5, 2, print_mode='digits', show_prec=True)(6)) '...11' sage: repr(Zp(5, 2, print_mode='digits', show_prec='bigoh')(6)) '11 + O(5^2)' - *print_pos*, *name* and *print_sep* have no effect. + *print_pos*, *name* and *print_sep* have no effect. - Equality depends on printing options:: + Equality depends on printing options:: sage: R == S, R == T, S == T (False, False, False) @@ -1708,38 +1708,38 @@ class Zp_class(UniqueFactory): sage: b = R(-70700); repr(b) '...4|4|4|4|4|4|4|4|4|4|4|4|4|4|4|0|2|1|4|2|0|0' - Again, note that it's not possible to read off the precision from - the representation in this mode. + Again, note that it's not possible to read off the precision from + the representation in this mode. - *print_pos* controls whether the digits can be negative. :: + *print_pos* controls whether the digits can be negative. :: sage: S = Zp(5, print_mode='bars',print_pos=False); b = S(-70700); repr(b) '...-1|0|2|2|-1|2|0|0' - *print_max_terms* limits the number of digits that are printed. :: + *print_max_terms* limits the number of digits that are printed. :: sage: T = Zp(5, print_max_terms=4); T(-70700) 2*5^2 + 4*5^3 + 5^4 + 2*5^5 + ... + O(5^22) - *print_sep* controls the separation character. :: + *print_sep* controls the separation character. :: sage: U = Zp(5, print_mode='bars', print_sep=']['); a = U(70700); repr(a) '...4][2][3][0][3][0][0' - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'dots' - (or equivalently ``True``) or 'bigoh'. - The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'dots' + (or equivalently ``True``) or 'bigoh'. + The default is ``False`` for the ``'floating-point'`` and + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: repr(Zp(5, 2, print_mode='bars', show_prec=True)(6)) '...1|1' sage: repr(Zp(5, 2, print_mode='bars', show_prec=False)(6)) '1|1' - *name* and *print_alphabet* have no effect. + *name* and *print_alphabet* have no effect. - Equality depends on printing options:: + Equality depends on printing options:: sage: R == S, R == T, R == U, S == T, S == U, T == U (False, False, False, False, False, False) @@ -2074,8 +2074,8 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, 1. A **polynomial**. - The base ring can be `\ZZ`, `\QQ`, `\ZZ_p`, `\GF{p}`, or anything that can - be converted to `\ZZ_p`. :: + The base ring can be `\ZZ`, `\QQ`, `\ZZ_p`, `\GF{p}`, or anything that can + be converted to `\ZZ_p`. :: sage: P. = ZZ[] sage: R. = Zq(27, modulus = x^3 + 2*x + 1); R.modulus() @@ -2089,15 +2089,15 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: P. = GF(3)[] sage: V. = Zq(27, modulus = x^3 + 2*x + 1) - Which form the modulus is given in has no effect on the unramified - extension produced:: + Which form the modulus is given in has no effect on the unramified + extension produced:: sage: R == S, R == T, T == U, U == V (False, True, True, False) - unless the modulus is different, or the precision of the modulus - differs. In the case of ``V``, the modulus is only given to precision - ``1``, so the resulting field has a precision cap of ``1``. :: + unless the modulus is different, or the precision of the modulus + differs. In the case of ``V``, the modulus is only given to precision + ``1``, so the resulting field has a precision cap of ``1``. :: sage: V.precision_cap() 1 @@ -2118,16 +2118,16 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: X == R True - By default, the polynomial chosen is the standard lift of the - generator chosen for `\GF{q}`. :: + By default, the polynomial chosen is the standard lift of the + generator chosen for `\GF{q}`. :: sage: GF(125, 'a').modulus() x^3 + 3*x + 3 sage: Y. = Zq(125); Y.modulus() (1 + O(5^20))*x^3 + O(5^20)*x^2 + (3 + O(5^20))*x + 3 + O(5^20) - However, you can choose another polynomial if desired (as long as - the reduction to `\GF{p}[x]` is irreducible). :: + However, you can choose another polynomial if desired (as long as + the reduction to `\GF{p}[x]` is irreducible). :: sage: P. = ZZ[] sage: Z. = Zq(125, modulus = x^3 + 3*x^2 + x + 1); Z.modulus() @@ -2157,27 +2157,27 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: b.parent() is R.fraction_field() True - *print_pos* controls whether negatives can be used in the - coefficients of powers of `p`. :: + *print_pos* controls whether negatives can be used in the + coefficients of powers of `p`. :: sage: S. = Zq(9, print_mode='series', print_pos=False); (1+2*b)^4 -1 - b*3 - 3^2 + (b + 1)*3^3 + O(3^20) sage: -3*(1+2*b)^4 3 + b*3^2 + 3^3 + (-b - 1)*3^4 + O(3^21) - *ram_name* controls how the prime is printed. :: + *ram_name* controls how the prime is printed. :: sage: T. = Zq(9, print_mode='series', ram_name='p'); 3*(1+2*d)^4 2*p + (2*d + 2)*p^2 + (2*d + 1)*p^3 + O(p^21) - *print_max_ram_terms* limits the number of powers of `p` that - appear. :: + *print_max_ram_terms* limits the number of powers of `p` that + appear. :: sage: U. = Zq(9, print_mode='series', print_max_ram_terms=4); repr(-3*(1+2*e)^4) '3 + e*3^2 + 3^3 + (2*e + 2)*3^4 + ... + O(3^21)' - *print_max_unram_terms* limits the number of terms that appear in a - coefficient of a power of `p`. :: + *print_max_unram_terms* limits the number of terms that appear in a + coefficient of a power of `p`. :: sage: V. = Zq(128, prec = 8, print_mode='series'); repr((1+f)^9) '(f^3 + 1) + (f^5 + f^4 + f^3 + f^2)*2 + (f^6 + f^5 + f^4 + f + 1)*2^2 + (f^5 + f^4 + f^2 + f + 1)*2^3 + (f^6 + f^5 + f^4 + f^3 + f^2 + f + 1)*2^4 + (f^5 + f^4)*2^5 + (f^6 + f^5 + f^4 + f^3 + f + 1)*2^6 + (f + 1)*2^7 + O(2^8)' @@ -2190,18 +2190,18 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: V. = Zq(128, prec = 8, print_mode='series', print_max_unram_terms = 0); repr((1+f)^9 - 1 - f^3) '(...)*2 + (...)*2^2 + (...)*2^3 + (...)*2^4 + (...)*2^5 + (...)*2^6 + (...)*2^7 + O(2^8)' - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'bigoh' - (or equivalently ``True``). - The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'bigoh' + (or equivalently ``True``). + The default is ``False`` for the ``'floating-point'`` and + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: U. = Zq(9, 2, show_prec=False); repr(-3*(1+2*e)^4) '3 + e*3^2' - *print_sep* and *print_max_terse_terms* have no effect. + *print_sep* and *print_max_terse_terms* have no effect. - Note that print options affect equality:: + Note that print options affect equality:: sage: R == S, R == T, R == U, R == V, S == T, S == U, S == V, T == U, T == V, U == V (False, False, False, False, False, False, False, False, False, False) @@ -2213,15 +2213,15 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: ~b 3^-3 * (41 + a) + O(3) - *print_pos* controls whether to use a balanced representation or - not. :: + *print_pos* controls whether to use a balanced representation or + not. :: sage: S. = Zq(9, 7, print_mode='val-unit', print_pos=False); b = (1+3*a)^9 - 1; b 3^3 * (15 - 17*a) + O(3^7) sage: ~b 3^-3 * (-40 + a) + O(3) - *ram_name* affects how the prime is printed. :: + *ram_name* affects how the prime is printed. :: sage: A. = Zp(next_prime(10^6), print_mode='val-unit')[] sage: T. = Zq(next_prime(10^6)^3, 4, print_mode='val-unit', ram_name='p', modulus=x^3+385831*x^2+106556*x+321036); b = (next_prime(10^6)^2*(a^2 + a - 4)^4); b @@ -2229,24 +2229,24 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: b * (a^2 + a - 4)^-4 p^2 * 1 + O(p^6) - *print_max_terse_terms* controls how many terms of the polynomial - appear in the unit part. :: + *print_max_terse_terms* controls how many terms of the polynomial + appear in the unit part. :: sage: U. = Zq(17^4, 6, print_mode='val-unit', print_max_terse_terms=3); b = (17*(a^3-a+14)^6); b 17 * (12131797 + 12076378*a + 10809706*a^2 + ...) + O(17^7) - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'bigoh' - (or equivalently ``True``). - The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'bigoh' + (or equivalently ``True``). + The default is ``False`` for the ``'floating-point'`` and + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: U. = Zq(9, 2, print_mode='val-unit', show_prec=False); repr(-3*(1+2*e)^4) '3 * (1 + 3*e)' - *print_sep*, *print_max_ram_terms* and *print_max_unram_terms* have no effect. + *print_sep*, *print_max_ram_terms* and *print_max_unram_terms* have no effect. - Equality again depends on the printing options:: + Equality again depends on the printing options:: sage: R == S, R == T, R == U, S == T, S == U, T == U (False, False, False, False, False, False) @@ -2260,19 +2260,19 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: (a/5+1)^177 68210977979428/5^177 + 90313850704069/5^177*a + 73948093055069/5^177*a^2 + O(5^-157) - Note that in this last computation, you get one fewer `p`-adic digit - than one might expect. This is because ``R`` is capped absolute, and - thus 5 is cast in with relative precision 19. + Note that in this last computation, you get one fewer `p`-adic digit + than one might expect. This is because ``R`` is capped absolute, and + thus 5 is cast in with relative precision 19. - As of version 3.3, if coefficients of the polynomial are - non-integral, they are always printed with an explicit power of `p` - in the denominator. :: + As of version 3.3, if coefficients of the polynomial are + non-integral, they are always printed with an explicit power of `p` + in the denominator. :: sage: 5*a + a^2/25 5*a + 1/5^2*a^2 + O(5^18) - *print_pos* controls whether to use a balanced representation or - not. :: + *print_pos* controls whether to use a balanced representation or + not. :: sage: (a-5)^6 22864 + 95367431627998*a + 8349*a^2 + O(5^20) @@ -2281,30 +2281,30 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: (a - 1/5)^6 -20624/5^6 + 18369/5^5*a + 1353/5^3*a^2 + O(5^14) - *ram_name* affects how the prime is printed. :: + *ram_name* affects how the prime is printed. :: sage: T. = Zq(125, print_mode='terse', ram_name='p'); (a - 1/5)^6 95367431620001/p^6 + 18369/p^5*a + 1353/p^3*a^2 + O(p^14) - *print_max_terse_terms* controls how many terms of the polynomial - are shown. :: + *print_max_terse_terms* controls how many terms of the polynomial + are shown. :: sage: U. = Zq(625, print_mode='terse', print_max_terse_terms=2); (a-1/5)^6 106251/5^6 + 49994/5^5*a + ... + O(5^14) - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'bigoh' - (or equivalently ``True``). - The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'bigoh' + (or equivalently ``True``). + The default is ``False`` for the ``'floating-point'`` and + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: U. = Zq(9, 2, print_mode='terse', show_prec=False); repr(-3*(1+2*e)^4) '3 + 9*e' - *print_sep*, *print_max_ram_terms* and *print_max_unram_terms* have no - effect. + *print_sep*, *print_max_ram_terms* and *print_max_unram_terms* have no + effect. - Equality again depends on the printing options:: + Equality again depends on the printing options:: sage: R == S, R == T, R == U, S == T, S == U, T == U (False, False, False, False, False, False) @@ -2323,8 +2323,8 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: repr((a-5)^6) '...[0, 4]|[1, 4]|[2, 0, 2]|[1, 4, 3]|[2, 3, 1]|[4, 4, 3]|[2, 4, 4]|[4, 3, 4]' - Note that it's not possible to read off the precision from the - representation in this mode. :: + Note that it's not possible to read off the precision from the + representation in this mode. :: sage: b = a + 3; repr(b) '...[3, 1]' @@ -2335,16 +2335,16 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: c.precision_absolute() 4 - *print_pos* controls whether the digits can be negative. :: + *print_pos* controls whether the digits can be negative. :: sage: S. = Zq(125, print_mode='bars', print_pos=False); repr((a-5)^6) '...[1, -1, 1]|[2, 1, -2]|[2, 0, -2]|[-2, -1, 2]|[0, 0, -1]|[-2]|[-1, -2, -1]' sage: repr((a-1/5)^6) '...[0, 1, 2]|[-1, 1, 1]|.|[-2, -1, -1]|[2, 2, 1]|[0, 0, -2]|[0, -1]|[0, -1]|[1]' - *print_max_ram_terms* controls the maximum number of "digits" shown. - Note that this puts a cap on the relative precision, not the - absolute precision. :: + *print_max_ram_terms* controls the maximum number of "digits" shown. + Note that this puts a cap on the relative precision, not the + absolute precision. :: sage: T. = Zq(125, print_max_ram_terms=3, print_pos=False); (a-5)^6 (-a^2 - 2*a - 1) - 2*5 - a^2*5^2 + ... + O(5^20) @@ -2353,13 +2353,13 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: (a-1/5)^6 5^-6 - a*5^-5 - a*5^-4 + ... + O(5^14) - *print_sep* controls the separating character (``'|'`` by default). :: + *print_sep* controls the separating character (``'|'`` by default). :: sage: U. = Zq(625, print_mode='bars', print_sep=''); b = (a+5)^6; repr(b) '...[0, 1][4, 0, 2][3, 2, 2, 3][4, 2, 2, 4][0, 3][1, 1, 3][3, 1, 4, 1]' - *print_max_unram_terms* controls how many terms are shown in each - ``'digit'``:: + *print_max_unram_terms* controls how many terms are shown in each + ``'digit'``:: sage: with local_print_mode(U, {'max_unram_terms': 3}): repr(b) '...[0, 1][4,..., 0, 2][3,..., 2, 3][4,..., 2, 4][0, 3][1,..., 1, 3][3,..., 4, 1]' @@ -2370,23 +2370,23 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, sage: with local_print_mode(U, {'max_unram_terms':0}): repr(b-75*a) '...[...][...][...][...][][...][...]' - *show_prec* determines how the precision is printed. - It can be either 'none' (or equivalently ``False``), 'dots' - (or equivalently ``True``) or 'bigoh'. - The default is ``False`` for the ``'floating-point'`` and - ``'fixed-mod'`` types and ``True`` for all other types. :: + *show_prec* determines how the precision is printed. + It can be either 'none' (or equivalently ``False``), 'dots' + (or equivalently ``True``) or 'bigoh'. + The default is ``False`` for the ``'floating-point'`` and + ``'fixed-mod'`` types and ``True`` for all other types. :: sage: U. = Zq(9, 2, print_mode='bars', show_prec='bigoh'); repr(-3*(1+2*e)^4) '[0, 1]|[1]|[] + O(3^3)' - *ram_name* and *print_max_terse_terms* have no effect. + *ram_name* and *print_max_terse_terms* have no effect. - Equality depends on printing options:: + Equality depends on printing options:: sage: R == S, R == T, R == U, S == T, S == U, T == U (False, False, False, False, False, False) - EXAMPLES + EXAMPLES: Unlike for ``Zp``, you can't create ``Zq(N)`` when ``N`` is not a prime power. From 41eb3ec1b07e842a5a889d3f83e6e5bb4e32f2d3 Mon Sep 17 00:00:00 2001 From: Ivo Maffei Date: Sat, 11 Jul 2020 00:12:32 +0200 Subject: [PATCH 076/217] fixed bugs in LJCR DB use --- src/sage/combinat/designs/bibd.py | 41 ++++++++++++-------- src/sage/combinat/designs/covering_design.py | 2 +- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/sage/combinat/designs/bibd.py b/src/sage/combinat/designs/bibd.py index 0d2e51e80d0..d836ac8d52e 100644 --- a/src/sage/combinat/designs/bibd.py +++ b/src/sage/combinat/designs/bibd.py @@ -155,11 +155,9 @@ def balanced_incomplete_block_design(v, k, lambd=1, existence=False, use_LJCR=Fa [[0, 1, 3], [0, 2, 4], [0, 5, 6], [1, 2, 6], [1, 4, 5], [2, 3, 5], [3, 4, 6]] sage: B = designs.balanced_incomplete_block_design(66, 6, 1, use_LJCR=True) # optional - internet sage: B # optional - internet - Incidence structure with 66 points and 143 blocks + (66,6,1)-Balanced Incomplete Block Design sage: B.blocks() # optional - internet [[0, 1, 2, 3, 4, 65], [0, 5, 22, 32, 38, 58], [0, 6, 21, 30, 43, 48], ... - sage: designs.balanced_incomplete_block_design(66, 6, 1, use_LJCR=True) # optional - internet - Incidence structure with 66 points and 143 blocks sage: designs.balanced_incomplete_block_design(216, 6, 1) Traceback (most recent call last): ... @@ -314,21 +312,30 @@ def balanced_incomplete_block_design(v, k, lambd=1, existence=False, use_LJCR=Fa G, D = difference_family(v, k, l=lambd) return BalancedIncompleteBlockDesign(v, BIBD_from_difference_family(G, D, check=False), lambd=lambd, copy=False) if lambd == 1 and use_LJCR: + #print("LJCR with params {}, {}, 1".format(v,k)) from .covering_design import best_known_covering_design_www - B = best_known_covering_design_www(v, k, 2) - - # Is it a BIBD or just a good covering ? - expected_n_of_blocks = binomial(v, 2)//binomial(k, 2) - if B.low_bd() > expected_n_of_blocks: - if existence: - return False - raise EmptySetError("There exists no ({},{},{})-BIBD".format(v, k, lambd)) - B = B.incidence_structure() - if B.num_blocks() == expected_n_of_blocks: - if existence: - return True - else: - return B + values_in_db = False + try: + B = best_known_covering_design_www(v, k, 2) + values_in_db = True + except ValueError: + # the parameters are not in the LJCR database + pass + + if values_in_db: + # Is it a BIBD or just a good covering ? + expected_n_of_blocks = binomial(v, 2)//binomial(k, 2) + if B.low_bd() > expected_n_of_blocks: + if existence: + return False + raise EmptySetError("There exists no ({},{},{})-BIBD".format(v, k, lambd)) + B = B.incidence_structure() + if B.num_blocks() == expected_n_of_blocks: + if existence: + return True + else: + return BalancedIncompleteBlockDesign(B.ground_set(), B.blocks(), k=k, lambd=1, copy=False) + if ( (k+lambd)*(k+lambd-1) == lambd*(v+k+lambd-1) and balanced_incomplete_block_design(v+k+lambd, k+lambd, lambd, existence=True) is True): diff --git a/src/sage/combinat/designs/covering_design.py b/src/sage/combinat/designs/covering_design.py index 41d1fe32754..8a7351799c2 100644 --- a/src/sage/combinat/designs/covering_design.py +++ b/src/sage/combinat/designs/covering_design.py @@ -521,7 +521,7 @@ def best_known_covering_design_www(v, k, t, verbose=False): k = int(k) t = int(t) param = "?v=%s&k=%s&t=%s" % (v, k, t) - url = "https://ljcr.dmgordon.org/cover/get_cover.php" + param + url = "http://ljcr.dmgordon.org/cover/get_cover.php" + param if verbose: print("Looking up the bounds at %s" % url) From 89fac3f7a17c609e23bf9b57458c63cc796729b4 Mon Sep 17 00:00:00 2001 From: Ivo Maffei Date: Sun, 12 Jul 2020 12:59:53 +0200 Subject: [PATCH 077/217] revert http to https --- src/sage/combinat/designs/covering_design.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/designs/covering_design.py b/src/sage/combinat/designs/covering_design.py index 8a7351799c2..41d1fe32754 100644 --- a/src/sage/combinat/designs/covering_design.py +++ b/src/sage/combinat/designs/covering_design.py @@ -521,7 +521,7 @@ def best_known_covering_design_www(v, k, t, verbose=False): k = int(k) t = int(t) param = "?v=%s&k=%s&t=%s" % (v, k, t) - url = "http://ljcr.dmgordon.org/cover/get_cover.php" + param + url = "https://ljcr.dmgordon.org/cover/get_cover.php" + param if verbose: print("Looking up the bounds at %s" % url) From 59f43c1d9290f082c2a493d9cccf479664bf2c50 Mon Sep 17 00:00:00 2001 From: Ivo Maffei Date: Sun, 12 Jul 2020 23:19:45 +0200 Subject: [PATCH 078/217] code formatting --- src/sage/combinat/designs/bibd.py | 33 ++++++++++++++++--------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/sage/combinat/designs/bibd.py b/src/sage/combinat/designs/bibd.py index d836ac8d52e..c5a9af0a48a 100644 --- a/src/sage/combinat/designs/bibd.py +++ b/src/sage/combinat/designs/bibd.py @@ -238,12 +238,12 @@ def balanced_incomplete_block_design(v, k, lambd=1, existence=False, use_LJCR=Fa if v == 1: if existence: return True - return BalancedIncompleteBlockDesign(v, [], check=False) + return BIBD(v, [], check=False) if k == v: if existence: return True - return BalancedIncompleteBlockDesign(v, [list(range(v)) for _ in range(lambd)],lambd=lambd, check=False, copy=False) + return BIBD(v, [list(range(v)) for _ in range(lambd)],lambd=lambd, check=False, copy=False) # Non-existence of BIBD if (v < k or @@ -271,7 +271,7 @@ def balanced_incomplete_block_design(v, k, lambd=1, existence=False, use_LJCR=Fa if k == 2: if existence: return True - return BalancedIncompleteBlockDesign(v, [[x, y] for _ in range(lambd) for x in range(v) for y in range(x+1, v) if x != y], lambd=lambd, check=False, copy=True) + return BIBD(v, [[x, y] for _ in range(lambd) for x in range(v) for y in range(x+1, v) if x != y], lambd=lambd, check=False, copy=True) if k == 3 and lambd == 1: if existence: return v%6 == 1 or v%6 == 3 @@ -279,11 +279,11 @@ def balanced_incomplete_block_design(v, k, lambd=1, existence=False, use_LJCR=Fa if k == 4 and lambd == 1: if existence: return v%12 == 1 or v%12 == 4 - return BalancedIncompleteBlockDesign(v, v_4_1_BIBD(v), copy=False) + return BIBD(v, v_4_1_BIBD(v), copy=False) if k == 5 and lambd == 1: if existence: return v%20 == 1 or v%20 == 5 - return BalancedIncompleteBlockDesign(v, v_5_1_BIBD(v), copy=False) + return BIBD(v, v_5_1_BIBD(v), copy=False) from .difference_family import difference_family from .database import BIBD_constructions @@ -291,28 +291,27 @@ def balanced_incomplete_block_design(v, k, lambd=1, existence=False, use_LJCR=Fa if (v, k, lambd) in BIBD_constructions: if existence: return True - return BalancedIncompleteBlockDesign(v,BIBD_constructions[(v, k, lambd)](), lambd=lambd, copy=False) + return BIBD(v,BIBD_constructions[(v, k, lambd)](), lambd=lambd, copy=False) if lambd == 1 and BIBD_from_arc_in_desarguesian_projective_plane(v, k, existence=True): if existence: return True B = BIBD_from_arc_in_desarguesian_projective_plane(v, k) - return BalancedIncompleteBlockDesign(v, B, copy=False) + return BIBD(v, B, copy=False) if lambd == 1 and BIBD_from_TD(v, k, existence=True) is True: if existence: return True - return BalancedIncompleteBlockDesign(v, BIBD_from_TD(v, k), copy=False) + return BIBD(v, BIBD_from_TD(v, k), copy=False) if lambd == 1 and v == (k-1)**2+k and is_prime_power(k-1): if existence: return True from .block_design import projective_plane - return BalancedIncompleteBlockDesign(v, projective_plane(k-1),copy=False) + return BIBD(v, projective_plane(k-1),copy=False) if difference_family(v, k, l=lambd, existence=True) is True: if existence: return True G, D = difference_family(v, k, l=lambd) - return BalancedIncompleteBlockDesign(v, BIBD_from_difference_family(G, D, check=False), lambd=lambd, copy=False) + return BIBD(v, BIBD_from_difference_family(G, D, check=False), lambd=lambd, copy=False) if lambd == 1 and use_LJCR: - #print("LJCR with params {}, {}, 1".format(v,k)) from .covering_design import best_known_covering_design_www values_in_db = False try: @@ -323,18 +322,18 @@ def balanced_incomplete_block_design(v, k, lambd=1, existence=False, use_LJCR=Fa pass if values_in_db: - # Is it a BIBD or just a good covering ? - expected_n_of_blocks = binomial(v, 2)//binomial(k, 2) + # Is it a BIBD or just a good covering? + expected_n_of_blocks = binomial(v, 2) // binomial(k, 2) if B.low_bd() > expected_n_of_blocks: if existence: return False - raise EmptySetError("There exists no ({},{},{})-BIBD".format(v, k, lambd)) + raise EmptySetError(f"there exists no ({v},{k},{lambd})-BIBD") B = B.incidence_structure() if B.num_blocks() == expected_n_of_blocks: if existence: return True else: - return BalancedIncompleteBlockDesign(B.ground_set(), B.blocks(), k=k, lambd=1, copy=False) + return BIBD(B.ground_set(), B.blocks(), k=k, lambd=1, copy=False) if ( (k+lambd)*(k+lambd-1) == lambd*(v+k+lambd-1) and @@ -517,7 +516,7 @@ def steiner_triple_system(n): # apply T and remove duplicates sts = set(frozenset(T(xx) for xx in x) for x in sts) - return BalancedIncompleteBlockDesign(n, sts, name=name,check=False) + return BIBD(n, sts, name=name,check=False) def BIBD_from_TD(v,k,existence=False): @@ -1631,3 +1630,5 @@ def arc(self, s=2, solver=None, verbose=0): p.add_constraint(p.sum(b[k] for k in i) <= s) p.solve(log=verbose) return [self._points[i] for (i,j) in p.get_values(b).items() if j == 1] + +BIBD = BalancedIncompleteBlockDesign From 03c980ff19ca9c17667e3919ea194eb578b22e6b Mon Sep 17 00:00:00 2001 From: Joshua Campbell Date: Sun, 26 Apr 2020 10:35:22 -0700 Subject: [PATCH 079/217] Add support for simple keyframe-based animation to Three.js viewer. Invoked using the new `interactive` method in `sage.plot.animate.Animation`. In addition, add ability to save a 3D plot to an HTML file using Three.js viewer. --- src/doc/en/reference/plot3d/threejs.rst | 35 +- .../plot3d/threejs_examples/animation.html | 981 ++++++++++++++++++ src/sage/ext_data/threejs/animation.css | 158 +++ src/sage/ext_data/threejs/animation.html | 85 ++ src/sage/ext_data/threejs/animation.js | 273 +++++ .../ext_data/threejs/threejs_template.html | 31 +- src/sage/plot/animate.py | 71 +- src/sage/plot/plot3d/base.pyx | 137 ++- 8 files changed, 1751 insertions(+), 20 deletions(-) create mode 100644 src/doc/en/reference/plot3d/threejs_examples/animation.html create mode 100644 src/sage/ext_data/threejs/animation.css create mode 100644 src/sage/ext_data/threejs/animation.html create mode 100644 src/sage/ext_data/threejs/animation.js diff --git a/src/doc/en/reference/plot3d/threejs.rst b/src/doc/en/reference/plot3d/threejs.rst index 3d33c8fa78a..3c1cda92343 100644 --- a/src/doc/en/reference/plot3d/threejs.rst +++ b/src/doc/en/reference/plot3d/threejs.rst @@ -1,3 +1,4 @@ +.. _threejs_viewer: ================================== Three.js JavaScript WebGL Renderer @@ -6,7 +7,7 @@ Three.js JavaScript WebGL Renderer A web-based interactive viewer using the Three.js JavaScript library maintained by https://threejs.org. -The viewer is invoked by adding the keyword argument ``viewer='threejs'`` to the command +The viewer is invoked by adding the keyword argument ``viewer='threejs'`` to the command ``show()`` or any three-dimensional graphic. The scene is rendered and displayed in the users's web browser. Interactivity includes @@ -63,6 +64,24 @@ Options currently supported by the viewer: viewpoint of the scene, where angle is in degrees; can be determined using the 'Get Viewpoint' option of the information menu +In addition, the following animation-related options are supported: + +- ``animate`` -- (default: depends) whether to enable animation. Automatically set to ``True`` + if animation data is present in the plot. If ``False``, all frames of animation will be displayed + simultaneously. + +- ``animation_controls`` -- (default: True) whether to include the playback slider and buttons + (play, pause, etc.) in the page + +- ``auto_play`` -- (default: True) whether to immediately start playing the animation when the page + loads. Recommend setting ``animation_controls=True`` to be able to start playback. + +- ``delay`` -- (default: 20) an integer amount of time between consecutive frames of animation, + in hundredths of a second + +- ``loop`` -- (default: True) whether to loop the animation or have it stop after reaching the end. + Can be toggled on the page itself if ``animation_controls`` is set. + Clicking on the information icon in the lower right-hand corner of the viewer opens a menu of available actions. These include saving the three-dimensional scene as a static PNG image or as complete HTML source code. @@ -70,6 +89,7 @@ PNG image or as complete HTML source code. AUTHORS: - Paul Masson (2016): Initial version +- Joshua Campbell (2020): Animation support EXAMPLES: @@ -91,6 +111,19 @@ A parametric helix:: .. RAW:: html :file: threejs_examples/helix.html +An :meth:`~sage.plot.animate.Animation.interactive` animation:: + + sage: def build_frame(t): + ....: e = parametric_plot3d([sin(x-t), 0, x], (x, 0, 2*pi), color='red') + ....: m = parametric_plot3d([0, -sin(x-t), x], (x, 0, 2*pi), color='green') + ....: return e + m + sage: frames = [build_frame(t) for t in (0, pi/32, pi/16, .., 2*pi)] + sage: plot = animate(frames).interactive() + sage: show(plot, delay=5, auto_play=False, projection='orthographic') + +.. RAW:: html + :file: threejs_examples/animation.html + .. RAW:: html diff --git a/src/doc/en/reference/plot3d/threejs_examples/animation.html b/src/doc/en/reference/plot3d/threejs_examples/animation.html new file mode 100644 index 00000000000..9446377891f --- /dev/null +++ b/src/doc/en/reference/plot3d/threejs_examples/animation.html @@ -0,0 +1,981 @@ + \ No newline at end of file diff --git a/src/sage/ext_data/threejs/animation.css b/src/sage/ext_data/threejs/animation.css new file mode 100644 index 00000000000..2f7bdc41eec --- /dev/null +++ b/src/sage/ext_data/threejs/animation.css @@ -0,0 +1,158 @@ +/* animation.css */ + +#animation-ui { + position: absolute; + top: 0; + left: 0; + width: 100%; +} + +#animation-ui .tick-marks { + height: 6px; + margin-bottom: 6px; + margin-left: 6px; /* Take into account the slider knob/thumb's width. */ + margin-right: 5px; /* Same, but save a pixel for the last tick mark. */ + background-image: repeating-linear-gradient( + to right, + darkgray 0 1px, /* Make each tick 1px wide. */ + /* -1px here because of that extra pixel on the right margin */ + transparent 1px calc((100% - 1px) / SAGE_FRAME_COUNT) + ); +} + +#animation-ui, +#animation-ui .buttons { + font-size: 0; /* hack to ignore white-space between inline-block elements */ +} + +#animation-ui button { + display: inline-block; + margin: 0; + padding: 2px; + width: 28px; + height: 28px; + background: none; + border: none; + border-radius: 28px; + cursor: pointer; +} + +#animation-ui button:focus { + background: #b8b9ff; + outline: none; +} + +/* Setting the outline to none isn't enough for Firefox. */ +#animation-ui button::-moz-focus-inner { + border: none; +} + +#animation-ui button:active { + background: #efefff; +} + +#animation-ui.playing .play, +#animation-ui.paused .pause, +#animation-ui.loop .once, +#animation-ui.once .loop { + display: none; +} + +/* +Slider styled using range.css tool by Daniel Stern + http://danielstern.ca/range.css/#/ + Generated April 24, 2020 +Customizations: + - darker focus color + - focused styling for Firefox. +*/ +input[type=range].slider { + -webkit-appearance: none; + width: 100%; + margin: 0px 0; +} +input[type=range].slider:focus { + outline: none; +} +input[type=range].slider::-webkit-slider-runnable-track { + width: 100%; + height: 12px; + cursor: pointer; + box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d; + background: #efefff; + border-radius: 6px; + border: 0px solid #000000; +} +input[type=range].slider::-webkit-slider-thumb { + box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d; + border: 0px solid #000000; + height: 12px; + width: 12px; + border-radius: 6px; + background: #3131ff; + cursor: pointer; + -webkit-appearance: none; + margin-top: 0px; +} +input[type=range].slider:focus::-webkit-slider-runnable-track { + background: #b8b9f6; +} +input[type=range].slider::-moz-range-track { + width: 100%; + height: 12px; + cursor: pointer; + box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d; + background: #efefff; + border-radius: 6px; + border: 0px solid #000000; +} +input[type=range].slider::-moz-range-thumb { + box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d; + border: 0px solid #000000; + height: 12px; + width: 12px; + border-radius: 6px; + background: #3131ff; + cursor: pointer; +} +input[type=range].slider:focus::-moz-range-track { + background: #b8b9f6; +} +input[type=range].slider::-moz-focus-outer { + border: none; +} +input[type=range].slider::-ms-track { + width: 100%; + height: 12px; + cursor: pointer; + background: transparent; + border-color: transparent; + color: transparent; +} +input[type=range].slider::-ms-fill-lower { + background: #efefff; + border: 0px solid #000000; + border-radius: 6px; + box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d; +} +input[type=range].slider::-ms-fill-upper { + background: #efefff; + border: 0px solid #000000; + border-radius: 6px; + box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d; +} +input[type=range].slider::-ms-thumb { + box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d; + border: 0px solid #000000; + width: 12px; + border-radius: 6px; + background: #3131ff; + cursor: pointer; + height: 12px; +} +input[type=range].slider:focus::-ms-fill-lower { + background: #b8b9f6; +} +input[type=range].slider:focus::-ms-fill-upper { + background: #b8b9f6; +} diff --git a/src/sage/ext_data/threejs/animation.html b/src/sage/ext_data/threejs/animation.html new file mode 100644 index 00000000000..ced2f4fb7d1 --- /dev/null +++ b/src/sage/ext_data/threejs/animation.html @@ -0,0 +1,85 @@ + + + + +

diff --git a/src/sage/ext_data/threejs/animation.js b/src/sage/ext_data/threejs/animation.js new file mode 100644 index 00000000000..35d0997c16f --- /dev/null +++ b/src/sage/ext_data/threejs/animation.js @@ -0,0 +1,273 @@ +// animation.js + +window.updateAnimation = (function() { + + var frameDuration = options.delay; + var frameCount, totalDuration; + var mixer, action, clock; + var ui, slider; + + init(); + options.animationControls && initUI(); + options.autoPlay && play(); + return update; + + function init() { + + var frames = partitionScene(); + frameCount = frames.length; + totalDuration = frameCount * frameDuration; + + var tracks = createTracks( frames ); + var clip = new THREE.AnimationClip( 'sage_animation', totalDuration, tracks ); + + mixer = new THREE.AnimationMixer( scene ); + mixer.addEventListener( 'finished', function() { pause(); } ); + + action = mixer.clipAction( clip ); + action.timeScale = 100; // Our times are in hundredths of a second. + action.clampWhenFinished = true; // Sets paused=true instead of disabling. + action.loop = options.loop ? THREE.LoopRepeat : THREE.LoopOnce; + + // We start/stop the clock to play/pause. The action's `paused` property + // is instead used to determine if the animation has finished. + action.play(); + + clock = new THREE.Clock( false ); // Don't start playing yet. + + } + + // Group objects in by keyframe. The result is a potentially sparse list of + // lists of objects. Assumes keyframe index specified in objects' user data. + function partitionScene() { + var frames = []; + for ( var i=0 ; i < scene.children.length ; i++) { + var obj = scene.children[i]; + var k = obj.userData && parseInt( obj.userData.keyframe ); + if ( k >= 0 ){ + if ( k in frames ) frames[k].push( obj ); + else frames[k] = [obj]; + } + } + return frames; + } + + // Create and return a list of keyframe tracks to animate objects' + // visibility depending on which keyframe they appear in. + function createTracks( frames ) { + var tracks = []; + for ( var keyframe=0 ; keyframe < frames.length ; keyframe++ ) { + var frame = frames[keyframe]; + if ( frame ) { + // Show during the frame. + var times = [keyframe * frameDuration]; + var values = [true]; + // For all but the first frame, start off hidden. + if ( keyframe > 0 ) { + times.unshift( 0 ); + values.unshift( false ); + } + // For all but the last frame, end up hidden. + if ( keyframe < frames.length - 1 ) { + times.push( ( keyframe + 1 ) * frameDuration ); + values.push( false ); + } + for ( var i=0; i < frame.length ; i++ ) { + var binding = frame[i].uuid + '.visible'; + var track = new THREE.BooleanKeyframeTrack( binding, times, values ); + tracks.push( track ); + } + } + } + return tracks; + } + + function initUI() { + + ui = document.getElementById( 'animation-ui' ); + + initSlider(); + + hookupButton( 'play-pause', togglePlayback ); + hookupButton( 'previous', gotoPreviousFrame ); + hookupButton( 'next', gotoNextFrame ); + hookupButton( 'slower', slowDown ); + hookupButton( 'faster', speedUp ); + hookupButton( 'toggle-loop', toggleLooping ); + + function hookupButton( _class, onclick ) { + var button = ui.getElementsByClassName( _class )[0]; + button.addEventListener( 'click', onclick ); + return button; + } + + } + + function initSlider() { + + slider = ui.getElementsByClassName( 'slider' )[0]; + slider.value = action.time; + slider.setAttribute( 'max', totalDuration ); + slider.addEventListener( 'change', change ); + slider.addEventListener( 'input', change ); + slider.addEventListener( 'mousedown', mousedown ); + slider.addEventListener( 'mouseup', mouseup ); + slider.addEventListener( 'keydown', keydown ); + + function change() { + // Keep animation in sync with position of the knob. + seek( parseFloat( slider.value ) ); + } + + // Temporarily pause playback while the knob is being dragged around. + var dragging = false; + var wasPlaying = false; + function mousedown( event ) { + if ( event.button === 0 && !dragging ) { + dragging = true; + wasPlaying = isPlaying(); + pause(); + } + } + function mouseup( event ) { + if ( event.button === 0 && dragging ) { + dragging = false; + if ( wasPlaying && !isFinished() ) play(); + } + } + + function keydown( event ) { + switch ( event.key ) { + // Toggle playback using spacebar/enter. + case ' ': + case 'Enter': + if ( !event.repeat ) { + togglePlayback(); + event.preventDefault(); + } + break; + // Adjust speed using up/down arrows. + case 'Down': + case 'ArrowDown': + slowDown(); + event.preventDefault(); + break; + case 'Up': + case 'ArrowUp': + speedUp(); + event.preventDefault(); + break; + // Navigate frame-by-frame using left/right arrows. + case 'Left': + case 'ArrowLeft': + gotoPreviousFrame(); + event.preventDefault(); + break; + case 'Right': + case 'ArrowRight': + gotoNextFrame(); + event.preventDefault(); + break; + } + } + + } + + function isPlaying() { + return clock.running; + } + + function isFinished() { + return action.paused; + } + + function play() { + if ( isFinished() ) action.reset(); // Return to the beginning. + clock.start(); + updateUI(); + requestAnimationFrame( render ); // Re-enter render loop. + } + + function pause() { + clock.stop(); + updateUI(); + } + + function togglePlayback() { + isPlaying() ? pause() : play(); + } + + function seek( time ) { + + // Ensure time is in range: [0, totalDuration]. + time = Math.max( 0, Math.min( totalDuration, time ) ); + action.time = time; + + // Make sure the animation is treated as finished if set to the very + // end of the animation. + action.paused = ( !isLooping() && time == totalDuration ); + + updateUI(); + + if ( !isPlaying() ) { + // Ensure the animation gets re-rendered at the new position. + requestAnimationFrame( render ); // Trigger a re-render. + } + + } + + function moveKeyframes( delta ) { + var keyframe = Math.floor( action.time / frameDuration ); + keyframe += delta; + // Ensure keyframe is in range: [0, frameCount]. + keyframe = Math.max( 0, Math.min( frameCount, keyframe ) ); + seek( keyframe * frameDuration ); + } + + function gotoPreviousFrame() { + pause(); + moveKeyframes( -1 ); + } + + function gotoNextFrame() { + pause(); + moveKeyframes( +1 ); + } + + function speedUp() { + action.timeScale *= 1.25; + } + + function slowDown() { + action.timeScale /= 1.25; + } + + function isLooping() { + return action.loop === THREE.LoopRepeat; + } + + function setLooping( looping ) { + action.loop = looping ? THREE.LoopRepeat : THREE.LoopOnce; + updateUI(); + } + + function toggleLooping() { + setLooping( !isLooping() ); + } + + function update() { + mixer.update( clock.getDelta() ); + updateUI(); + return clock.running; // Should exit render loop if false. + } + + function updateUI() { + if ( ui ) { + ui.classList.remove( 'playing', 'paused', 'once', 'loop' ); + ui.classList.add( isPlaying() ? 'playing' : 'paused' ); + ui.classList.add( isLooping() ? 'loop' : 'once' ); + } + if ( slider ) slider.value = action.time; + } + +})(); diff --git a/src/sage/ext_data/threejs/threejs_template.html b/src/sage/ext_data/threejs/threejs_template.html index 5f48fc8b981..711a3f7ab6a 100644 --- a/src/sage/ext_data/threejs/threejs_template.html +++ b/src/sage/ext_data/threejs/threejs_template.html @@ -20,8 +20,9 @@ #menu-content div { border-top: 1px solid black; padding: 10px; white-space: nowrap; } #menu-content div:hover { background-color: #FEFEFE;; } - + +SAGE_STYLES @@ -37,10 +38,7 @@ document.body.appendChild( renderer.domElement ); var options = SAGE_OPTIONS; - - // When animations are supported by the viewer, the value 'false' - // will be replaced with an option set in Python by the user - var animate = false; // options.animate; + var animate = options.animate; var b = SAGE_BOUNDS; // bounds @@ -140,6 +138,8 @@ scene.add( sprite ); + return sprite; + } if ( options.axes ) scene.add( new THREE.AxesHelper( Math.min( a[0]*b[1].x, a[1]*b[1].y, a[2]*b[1].z ) ) ); @@ -220,16 +220,20 @@ controls.addEventListener( 'change', function() { if ( !animate ) render(); } ); window.addEventListener( 'resize', function() { - + renderer.setSize( window.innerWidth, window.innerHeight ); updateCameraAspect( camera, window.innerWidth / window.innerHeight ); if ( !animate ) render(); - + } ); var texts = SAGE_TEXTS; - for ( var i=0 ; i < texts.length ; i++ ) - addLabel( texts[i].text, a[0]*texts[i].x, a[1]*texts[i].y, a[2]*texts[i].z, texts[i].color ); + for ( var i=0 ; i < texts.length ; i++ ) addText( texts[i] ); + + function addText( json ) { + var sprite = addLabel( json.text, a[0]*json.x, a[1]*json.y, a[2]*json.z, json.color ); + sprite.userData = json; + } var points = SAGE_POINTS; for ( var i=0 ; i < points.length ; i++ ) addPoint( points[i] ); @@ -265,6 +269,7 @@ var mesh = new THREE.Points( geometry, material ); mesh.position.set( c.x, c.y, c.z ); + mesh.userData = json; scene.add( mesh ); } @@ -291,6 +296,7 @@ var mesh = new THREE.Line( geometry, material ); mesh.position.set( c.x, c.y, c.z ); + mesh.userData = json; scene.add( mesh ); } @@ -335,6 +341,7 @@ var mesh = new THREE.Mesh( geometry, material ); mesh.position.set( c.x, c.y, c.z ); if ( transparent && json.renderOrder ) mesh.renderOrder = json.renderOrder; + mesh.userData = json; scene.add( mesh ); if ( json.showMeshGrid ) { @@ -363,6 +370,7 @@ var mesh = new THREE.LineSegments( geometry, material ); mesh.position.set( c.x, c.y, c.z ); + mesh.userData = json; scene.add( mesh ); } @@ -373,7 +381,9 @@ function render() { + if ( window.updateAnimation ) animate = updateAnimation(); if ( animate ) requestAnimationFrame( render ); + renderer.render( scene, camera ); // Resize text based on distance from camera. @@ -389,7 +399,7 @@ } } } - + render(); controls.update(); if ( !animate ) render(); @@ -462,5 +472,6 @@
Close Menu
+SAGE_EXTRA_HTML diff --git a/src/sage/plot/animate.py b/src/sage/plot/animate.py index 3525806b673..606e95d5214 100644 --- a/src/sage/plot/animate.py +++ b/src/sage/plot/animate.py @@ -96,6 +96,7 @@ - John Palmieri - Niles Johnson (2013-12): Expand to animate more graphics objects - Martin von Gagern (2014-12): Added APNG support +- Joshua Campbell (2020): interactive animation via Three.js viewer REFERENCES: @@ -1015,7 +1016,9 @@ def save(self, filename=None, show_path=False, use_ffmpeg=False, **kwds): files. If filename is None, then in notebook mode, display the - animation; otherwise, save the animation to a GIF file. If + animation; otherwise, save the animation to a GIF file. If + filename ends in '.html', save an :meth:`interactive` version of + the animation to an HTML file that uses the Three.js viewer. If filename ends in '.sobj', save to an sobj file. Otherwise, try to determine the format from the filename extension ('.mpg', '.gif', '.avi', etc.). If the format cannot be @@ -1023,7 +1026,7 @@ def save(self, filename=None, show_path=False, use_ffmpeg=False, **kwds): For GIF files, either ffmpeg or the ImageMagick suite must be installed. For other movie formats, ffmpeg must be installed. - An sobj file can be saved with no extra software installed. + sobj and HTML files can be saved with no extra software installed. EXAMPLES:: @@ -1039,6 +1042,9 @@ def save(self, filename=None, show_path=False, use_ffmpeg=False, **kwds): sage: a.save(td + 'wave0.sobj') sage: a.save(td + 'wave1.sobj', show_path=True) Animation saved to file .../wave1.sobj. + sage: a.save(td + 'wave0.html', online=True) + sage: a.save(td + 'wave1.html', show_path=True, online=True) + Animation saved to file .../wave1.html. TESTS: @@ -1079,9 +1085,70 @@ def save(self, filename=None, show_path=False, use_ffmpeg=False, **kwds): SageObject.save(self, filename) if show_path: print("Animation saved to file %s." % filename) + elif suffix == '.html': + self.interactive(**kwds).save(filename) + if show_path: + print("Animation saved to file %s." % filename) else: self.ffmpeg(savefile=filename, show_path=show_path, **kwds) + def interactive(self, **kwds): + r""" + Create an interactive depiction of the animation. + + INPUT: + + - ``**kwds`` -- any of the viewing options accepted by show() are valid + as keyword arguments to this function and they will behave in the same + way. Those that are animation-related and recognized by the Three.js + viewer are: ``animate``, ``animation_controls``, ``auto_play``, + ``delay``, and ``loop``. + + OUTPUT: + + A 3D graphics object which, by default, will use the Three.js viewer. + + EXAMPLES:: + + sage: frames = [point3d((sin(x), cos(x), x)) for x in (0, pi/16, .., 2*pi)] + sage: animate(frames).interactive(online=True) + Graphics3d Object + + Works with frames that are 2D or 3D graphics objects or convertible to + 2D or 3D graphics objects via a ``plot`` or ``plot3d`` method:: + + sage: frames = [dodecahedron(), circle(center=(0, 0), radius=1), x^2] + sage: animate(frames).interactive(online=True, delay=100) + Graphics3d Object + + .. SEEALSO:: + + :ref:`threejs_viewer` + + """ + from sage.plot.plot3d.base import Graphics3d, KeyframeAnimationGroup + # Attempt to convert frames to Graphics3d objects. + g3d_frames = [] + for i, frame in enumerate(self._frames): + if not isinstance(frame, Graphics3d): + try: + frame = frame.plot3d() + except (AttributeError, TypeError): + try: + frame = frame.plot().plot3d() + except (AttributeError, TypeError): + frame = None + if not isinstance(frame, Graphics3d): + raise TypeError("Could not convert frame {} to Graphics3d".format(i)) + g3d_frames.append(frame) + # Give preference to this method's keyword arguments over those provided + # to animate or the constructor. + kwds = dict(self._kwds, **kwds) + # Three.js is the only viewer that supports animation at present. + if 'viewer' not in kwds: + kwds['viewer'] = 'threejs' + return KeyframeAnimationGroup(g3d_frames, **kwds) + class APngAssembler(object): r""" diff --git a/src/sage/plot/plot3d/base.pyx b/src/sage/plot/plot3d/base.pyx index a2740add101..57bf7636d62 100644 --- a/src/sage/plot/plot3d/base.pyx +++ b/src/sage/plot/plot3d/base.pyx @@ -11,6 +11,8 @@ AUTHORS: - Paul Masson (2016): Three.js support +- Joshua Campbell (2020): Three.js animation support + .. TODO:: finish integrating tachyon -- good default lights, camera @@ -362,17 +364,56 @@ cdef class Graphics3d(SageObject): sage: sphere(online=True)._rich_repr_threejs() OutputSceneThreejs container + + TESTS:: + + sage: js = '// animation.js' + sage: css = '/* animation.css */' + sage: html = '' + sage: d = dodecahedron() + sage: i = icosahedron() + sage: g1 = animate([d]).interactive() + sage: g2 = animate([d, i]).interactive() + + Animation files are only included when at least 2 frames are present:: + + sage: str = g1._rich_repr_threejs(online=True).html.get_str() + sage: (js in str) or (css in str) or (html in str) + False + sage: str = g2._rich_repr_threejs(online=True).html.get_str() + sage: (js in str) and (css in str) and (html in str) + True + + Animation can be explicitly disabled by setting animate=False:: + + sage: str = g2._rich_repr_threejs(online=True, animate=False).html.get_str() + sage: (js in str) or (css in str) or (html in str) + False + + Animation CSS and HTML are not included when animation_controls=False:: + + sage: str = g2._rich_repr_threejs(online=True, animation_controls=False).html.get_str() + sage: js in str + True + sage: (css in str) or (html in str) + False + """ options = self._process_viewing_options(kwds) options.setdefault('online', False) js_options = {} # options passed to Three.js template + js_options['animate'] = options.get('animate', True) + js_options['animationControls'] = options.get('animation_controls', True) js_options['aspectRatio'] = options.get('aspect_ratio', [1,1,1]) + js_options['autoPlay'] = options.get('auto_play', True) js_options['axes'] = options.get('axes', False) js_options['axesLabels'] = options.get('axes_labels', ['x','y','z']) js_options['decimals'] = options.get('decimals', 2) + js_options['delay'] = options.get('delay', 20) js_options['frame'] = options.get('frame', True) + js_options['loop'] = options.get('loop', True) js_options['projection'] = options.get('projection', 'perspective') js_options['viewpoint'] = options.get('viewpoint', False) @@ -384,6 +425,7 @@ cdef class Graphics3d(SageObject): # Normalization of options values for proper JSONing js_options['aspectRatio'] = [float(i) for i in js_options['aspectRatio']] js_options['decimals'] = int(js_options['decimals']) + js_options['delay'] = int(js_options['delay']) if js_options['viewpoint']: if len(js_options['viewpoint']) != 2 or len(js_options['viewpoint'][0]) != 3: @@ -403,6 +445,8 @@ cdef class Graphics3d(SageObject): from sage.repl.rich_output import get_display_manager scripts = get_display_manager().threejs_scripts(options['online']) + styles = '' + extra_html = '' b = self.bounding_box() bounds = '[{{"x":{}, "y":{}, "z":{}}}, {{"x":{}, "y":{}, "z":{}}}]'.format( @@ -416,8 +460,11 @@ cdef class Graphics3d(SageObject): import json reprs = {'point': [], 'line': [], 'text': [], 'surface': []} + frame_count = 0 for kind, desc in self.threejs_repr(self.default_render_params()): reprs[kind].append(desc) + keyframe = int(desc.get('keyframe', -1)) + frame_count = max(frame_count, keyframe + 1) reprs = {kind: json.dumps(descs) for kind, descs in reprs.items()} from sage.env import SAGE_EXTCODE @@ -425,7 +472,21 @@ cdef class Graphics3d(SageObject): SAGE_EXTCODE, 'threejs', 'threejs_template.html')) as f: html = f.read() + js_options['animate'] = js_options['animate'] and frame_count > 1 + if js_options['animate']: + if js_options['animationControls']: + with open(os.path.join(SAGE_EXTCODE, 'threejs', 'animation.css')) as f: + css = f.read() + css = css.replace('SAGE_FRAME_COUNT', str(frame_count)) + styles += '' + with open(os.path.join(SAGE_EXTCODE, 'threejs', 'animation.html')) as f: + extra_html += f.read() + with open(os.path.join(SAGE_EXTCODE, 'threejs', 'animation.js')) as f: + extra_html += '' + html = html.replace('SAGE_SCRIPTS', scripts) + html = html.replace('SAGE_STYLES', styles) + html = html.replace('SAGE_EXTRA_HTML', extra_html) html = html.replace('SAGE_OPTIONS', json.dumps(js_options)) html = html.replace('SAGE_BOUNDS', bounds) html = html.replace('SAGE_LIGHTS', lights) @@ -436,7 +497,7 @@ cdef class Graphics3d(SageObject): html = html.replace('SAGE_SURFACES', str(reprs['surface'])) from sage.repl.rich_output.output_catalog import OutputSceneThreejs - return OutputSceneThreejs(html); + return OutputSceneThreejs(html) def __str__(self): """ @@ -1586,6 +1647,8 @@ end_scene""" % (render_params.antialiasing, - a Sage object file (of type ``.sobj``) that you can load back later (a pickle), + - an HTML file depicting the graphic using the Three.js viewer, + - a data file (of type: X3D, STL, AMF, PLY) for export and use in other software. @@ -1596,12 +1659,12 @@ end_scene""" % (render_params.antialiasing, - ``filename`` -- string. Where to save the image or object. - - ``**kwds`` -- When specifying an image file to be rendered by Tachyon - or Jmol, any of the viewing options accepted by show() are valid as - keyword arguments to this function and they will behave in the same - way. Accepted keywords include: ``viewer``, ``verbosity``, - ``figsize``, ``aspect_ratio``, ``frame_aspect_ratio``, ``zoom``, - ``frame``, and ``axes``. Default values are provided. + - ``**kwds`` -- When specifying an HTML file or an image file to be + rendered by Tachyon or Jmol, any of the viewing options accepted by + show() are valid as keyword arguments to this function and they will + behave in the same way. Accepted keywords include: ``viewer``, + ``verbosity``, ``figsize``, ``aspect_ratio``, ``frame_aspect_ratio``, + ``zoom``, ``frame``, and ``axes``. Default values are provided. EXAMPLES:: @@ -1631,6 +1694,12 @@ end_scene""" % (render_params.antialiasing, sage: open(f).read().splitlines()[7] "" + + Producing a Three.js-based HTML file:: + + sage: f = tmp_filename(ext='.html') + sage: G.save(f, frame=False, online=True) + """ ext = os.path.splitext(filename)[1].lower() if ext == '' or ext == '.sobj': @@ -1654,6 +1723,8 @@ end_scene""" % (render_params.antialiasing, elif ext == '.ply': with open(filename, 'w') as outfile: outfile.write(self.ply_ascii_string()) + elif ext == '.html': + self._rich_repr_threejs(**kwds).html.save_as(filename) else: raise ValueError('filetype {} not supported by save()'.format(ext)) @@ -2515,6 +2586,58 @@ class TransformGroup(Graphics3dGroup): return Graphics3d.transform(self, **kwds) +class KeyframeAnimationGroup(Graphics3dGroup): + """A group of objects, each depicting a single frame of animation""" + def __init__(self, all=(), **kwds): + r""" + EXAMPLES:: + + sage: frames = [dodecahedron(), icosahedron(), tetrahedron()] + sage: sage.plot.plot3d.base.KeyframeAnimationGroup(frames) + Graphics3d Object + + They are usually constructed from an class:`~sage.plot.animate.Animation`:: + + sage: type(animate(frames).interactive()) + + + """ + Graphics3dGroup.__init__(self, all) + self._extra_kwds.update(kwds) + + def threejs_repr(self, render_params): + r""" + Adds keyframe information to the representations of the group's contents. + + EXAMPLES:: + + sage: a = point3d((0, 0, 1)) + sage: b = point3d((0, 1, 0)) + sage: c = point3d((1, 0, 0)) + sage: g = sage.plot.plot3d.base.KeyframeAnimationGroup([a, b, c]) + sage: g.threejs_repr(g.default_render_params()) + [('point', {..., 'keyframe': 0, ..., 'point': (0.0, 0.0, 1.0), ...}), + ('point', {..., 'keyframe': 1, ..., 'point': (0.0, 1.0, 0.0), ...}), + ('point', {..., 'keyframe': 2, ..., 'point': (1.0, 0.0, 0.0), ...})] + + Only top-level objects get a unique keyframe. Nested objects share the + same keyframe:: + + sage: g = sage.plot.plot3d.base.KeyframeAnimationGroup([a + b, c]) + sage: g.threejs_repr(g.default_render_params()) + [('point', {..., 'keyframe': 0, ..., 'point': (0.0, 0.0, 1.0), ...}), + ('point', {..., 'keyframe': 0, ..., 'point': (0.0, 1.0, 0.0), ...}), + ('point', {..., 'keyframe': 1, ..., 'point': (1.0, 0.0, 0.0), ...})] + + """ + reprs = [] + for i, g in enumerate(self.all): + for (kind, desc) in g.threejs_repr(render_params): + desc['keyframe'] = i + reprs.append((kind, desc)) + return reprs + + class Viewpoint(Graphics3d): """ This class represents a viewpoint, necessary for x3d. From 65cf295d4761a929ee413c8bf8095f55acf64f38 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Mon, 13 Jul 2020 11:16:34 -0400 Subject: [PATCH 080/217] Trac #30132: update resolvelinks() in ./sage from ./src/bin/sage-env. This copy/pasted function got updated in one place but not in the other. Obviously the duplication should be addressed eventually, but for now let's make the two agree once more. --- sage | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/sage b/sage index 837f3e6866f..4f9579c909a 100755 --- a/sage +++ b/sage @@ -25,7 +25,11 @@ # Resolve all symbolic links in a filename. This more or less behaves # like "readlink -f" except that it does not convert the filename to an # absolute path (a relative path remains relative), nor does it treat -# "." or ".." specially. See Trac ticket #5852. +# "." or ".." specially. +# +# WARNING: this function is copy/pasted from src/bin/sage-env, and +# deserves to be factored out at some point in the future. In the +# meantime however the two should be kept synchronized. resolvelinks() { # $in is what still needs to be converted (normally has no starting slash) in="$1" @@ -35,12 +39,10 @@ resolvelinks() { # Move stuff from $in to $out while [ -n "$in" ]; do # Normalize $in by replacing consecutive slashes by one slash - while { in_single_slash=${in//\/\//\/}; [ "$in" != "$in_single_slash" ]; }; do - in=$in_single_slash - done + in=$(echo "${in}" | sed 's://*:/:g') # If $in starts with a slash, remove it and set $out to the root - in_without_slash=${in/#\//} + in_without_slash=${in#/} if [ "$in" != "$in_without_slash" ]; then in=$in_without_slash out="/" @@ -62,7 +64,7 @@ resolvelinks() { out="$out$f" # If the new $in starts with a slash, move it to $out - in_without_slash=${in/#\//} + in_without_slash=${in#/} if [ "$in" != "$in_without_slash" ]; then in=$in_without_slash out="$out/" @@ -94,7 +96,8 @@ resolvelinks() { fi # In $in, replace $f by $f_resolved (leave $out alone) - in=${in/#"$f"/"$f_resolved"} + in="${in#${f}}" + in="${f_resolved}${in}" done # Return $out From c5666a36cd7041fa24143cc228a46196c4301fed Mon Sep 17 00:00:00 2001 From: Joshua Campbell Date: Mon, 13 Jul 2020 09:28:42 -0700 Subject: [PATCH 081/217] Change increase/decrease playback speed icons --- src/sage/ext_data/threejs/animation.html | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sage/ext_data/threejs/animation.html b/src/sage/ext_data/threejs/animation.html index ced2f4fb7d1..3fc96ffd92f 100644 --- a/src/sage/ext_data/threejs/animation.html +++ b/src/sage/ext_data/threejs/animation.html @@ -49,19 +49,19 @@ From d48807cad635f39a9ad96e08721e44fb58883e89 Mon Sep 17 00:00:00 2001 From: Joshua Campbell Date: Mon, 13 Jul 2020 09:29:56 -0700 Subject: [PATCH 082/217] Revert a documentation change in Graphics3d.save --- src/sage/plot/plot3d/base.pyx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sage/plot/plot3d/base.pyx b/src/sage/plot/plot3d/base.pyx index 57bf7636d62..047ded4db2d 100644 --- a/src/sage/plot/plot3d/base.pyx +++ b/src/sage/plot/plot3d/base.pyx @@ -1659,12 +1659,12 @@ end_scene""" % (render_params.antialiasing, - ``filename`` -- string. Where to save the image or object. - - ``**kwds`` -- When specifying an HTML file or an image file to be - rendered by Tachyon or Jmol, any of the viewing options accepted by - show() are valid as keyword arguments to this function and they will - behave in the same way. Accepted keywords include: ``viewer``, - ``verbosity``, ``figsize``, ``aspect_ratio``, ``frame_aspect_ratio``, - ``zoom``, ``frame``, and ``axes``. Default values are provided. + - ``**kwds`` -- When specifying an image file to be rendered by Tachyon + or Jmol, any of the viewing options accepted by show() are valid as + keyword arguments to this function and they will behave in the same + way. Accepted keywords include: ``viewer``, ``verbosity``, + ``figsize``, ``aspect_ratio``, ``frame_aspect_ratio``, ``zoom``, + ``frame``, and ``axes``. Default values are provided. EXAMPLES:: From 78c9ebdc569f44a0aa32fe4c3efee2b6beedaedb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 13 Jul 2020 21:49:18 +0200 Subject: [PATCH 083/217] various fixes suggested by lgtm (variables redefined later) --- .../cluster_algebra_quiver/cluster_seed.py | 4 ++-- .../modular_decomposition.py | 1 - src/sage/groups/free_group.py | 1 - src/sage/groups/generic.py | 1 - src/sage/homology/chain_complex.py | 4 +--- .../modular/arithgroup/arithgroup_generic.py | 16 +++++++++------- src/sage/modular/modform/eis_series.py | 6 +++--- src/sage/modular/overconvergent/genus0.py | 5 ++--- .../polynomial/polynomial_element_generic.py | 7 +++---- .../cyclic_covers/cycliccover_finite_field.py | 1 - .../schemes/elliptic_curves/ell_number_field.py | 6 +++--- 11 files changed, 23 insertions(+), 29 deletions(-) diff --git a/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py b/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py index beee549e25c..f4eaa4c1295 100644 --- a/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py +++ b/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py @@ -4554,9 +4554,8 @@ def _produce_upper_cluster_algebra_element(self, vd, cList): finalP = [] #Laurent polynomial for each vector in {0,1}^n for i in range(len(vd)): - final = 1 numerator = 0 - if cList[i] != []: + if cList[i]: #If the vector in vd is negative then it did not contribute any compatible vectors. It will only contribute a Laurent monomial. This is the case when cList[i]=[] #Each compatible sequence gives a term in the numerator of the Laurent polynomial. for s in cList[i]: @@ -4587,6 +4586,7 @@ def _produce_upper_cluster_algebra_element(self, vd, cList): laurentP *= p return laurentP + def _bino(n, k): """ Binomial coefficient which we define as zero for negative n. diff --git a/src/sage/graphs/graph_decompositions/modular_decomposition.py b/src/sage/graphs/graph_decompositions/modular_decomposition.py index 689165311b3..8cae0968454 100644 --- a/src/sage/graphs/graph_decompositions/modular_decomposition.py +++ b/src/sage/graphs/graph_decompositions/modular_decomposition.py @@ -1160,7 +1160,6 @@ def check_parallel(graph, root, left, right, # module can be formed if source_index != new_right_index: node = create_parallel_node() - temp = source_index for temp in range(source_index, new_right_index + 1): # if module X to be included in the new parallel module Y is also diff --git a/src/sage/groups/free_group.py b/src/sage/groups/free_group.py index d046f201b9a..198e17baabc 100644 --- a/src/sage/groups/free_group.py +++ b/src/sage/groups/free_group.py @@ -505,7 +505,6 @@ def syllables(self): """ g = self.gap().UnderlyingElement() k = g.NumberSyllables().sage() - gen = self.parent().gen exponent_syllable = libgap.eval('ExponentSyllable') generator_syllable = libgap.eval('GeneratorSyllable') result = [] diff --git a/src/sage/groups/generic.py b/src/sage/groups/generic.py index 45c4d0222f1..c52e7b0863a 100644 --- a/src/sage/groups/generic.py +++ b/src/sage/groups/generic.py @@ -476,7 +476,6 @@ def bsgs(a, b, bounds, operation='*', identity=None, inverse=None, op=None): c = op(inverse(b),multiple(a,lb,operation=operation)) if ran < 30: # use simple search for small ranges - i = lb d = c # for i,d in multiples(a,ran,c,indexed=True,operation=operation): for i0 in range(ran): diff --git a/src/sage/homology/chain_complex.py b/src/sage/homology/chain_complex.py index 234878e9d54..a782c58bb8d 100644 --- a/src/sage/homology/chain_complex.py +++ b/src/sage/homology/chain_complex.py @@ -1999,10 +1999,8 @@ def cartesian_product(self, *factors, **kwds): R = self.base_ring() zero = matrix(R, []) subdivide = kwds.get('subdivide', False) - ret = self - diffs = [D.differential() for D in factors] - keys = reduce(lambda X,d: X.union(d.keys()), diffs, set()) + keys = reduce(lambda X, d: X.union(d.keys()), diffs, set()) ret = {k: matrix.block_diagonal([d.get(k, zero) for d in diffs], subdivide=subdivide) for k in keys} diff --git a/src/sage/modular/arithgroup/arithgroup_generic.py b/src/sage/modular/arithgroup/arithgroup_generic.py index 7b075efb54b..7001bbfa869 100644 --- a/src/sage/modular/arithgroup/arithgroup_generic.py +++ b/src/sage/modular/arithgroup/arithgroup_generic.py @@ -685,6 +685,7 @@ def cusps(self, algorithm='default'): r""" Return a sorted list of inequivalent cusps for self, i.e. a set of representatives for the orbits of self on `\mathbb{P}^1(\QQ)`. + These should be returned in a reduced form where this makes sense. INPUT: @@ -708,19 +709,20 @@ def cusps(self, algorithm='default'): """ try: return copy(self._cusp_list[algorithm]) - except (AttributeError,KeyError): + except (AttributeError, KeyError): self._cusp_list = {} from .congroup_sl2z import is_SL2Z - if is_SL2Z(self): - s = [Cusp(1,0)] - if algorithm == 'default': - s = self._find_cusps() + if is_SL2Z(self): + s = [Cusp(1, 0)] + else: + s = self._find_cusps() elif algorithm == 'modsym': - s = sorted([self.reduce_cusp(c) for c in self.modular_symbols().cusps()]) + s = sorted(self.reduce_cusp(c) + for c in self.modular_symbols().cusps()) else: - raise ValueError("unknown algorithm: %s"%algorithm) + raise ValueError("unknown algorithm: %s" % algorithm) self._cusp_list[algorithm] = s return copy(s) diff --git a/src/sage/modular/modform/eis_series.py b/src/sage/modular/modform/eis_series.py index e649a1e9270..9e55c9f396c 100644 --- a/src/sage/modular/modform/eis_series.py +++ b/src/sage/modular/modform/eis_series.py @@ -362,18 +362,18 @@ def __find_eisen_chars_gamma1(N, k): #end if triples = [] - D = divisors(N) for chi, psi in pairs: c_chi = chi.conductor() c_psi = psi.conductor() - D = divisors(N/(c_chi * c_psi)) - if (k==2 and chi.is_trivial() and psi.is_trivial()): + D = divisors(N // (c_chi * c_psi)) + if k == 2 and chi.is_trivial() and psi.is_trivial(): D.remove(1) chi, psi = __common_minimal_basering(chi, psi) for t in D: triples.append((chi, psi, t)) return triples + def eisenstein_series_lseries(weight, prec=53, max_imaginary_part=0, max_asymp_coeffs=40): diff --git a/src/sage/modular/overconvergent/genus0.py b/src/sage/modular/overconvergent/genus0.py index 730991e6deb..e8fd60393ac 100644 --- a/src/sage/modular/overconvergent/genus0.py +++ b/src/sage/modular/overconvergent/genus0.py @@ -1086,17 +1086,16 @@ def eigenfunctions(self, n, F = None, exact_arith=True): eigenfunctions = [] verbose("Expected %s eigenvalues, got %s" % (n, len(eigenvalues))) for (r, d) in eigenvalues: - v = r.valuation() if d != 1: continue - mr = (m.__pari__() - r.__pari__()) + mr = m.__pari__() - r.__pari__() # Annoying thing: r isn't quite as precise as it claims to be # (bug reported to sage-support list) while F(mr.matdet()) != 0: verbose("p-adic solver returned wrong result in slope %s; refining" % r.valuation(), level=2) r = r - cp(r)/cp.derivative()(r) - mr2 = (m.__pari__() - r.__pari__()) + mr2 = m.__pari__() - r.__pari__() if mr2.matdet().valuation(self.prime()) > mr.matdet().valuation(self.prime()): mr = mr2 else: diff --git a/src/sage/rings/polynomial/polynomial_element_generic.py b/src/sage/rings/polynomial/polynomial_element_generic.py index 7319ae55443..8bc566884fb 100644 --- a/src/sage/rings/polynomial/polynomial_element_generic.py +++ b/src/sage/rings/polynomial/polynomial_element_generic.py @@ -1260,14 +1260,13 @@ def _factor_of_degree(self, deg): parent = self.parent() a = parent(a) - b = v = parent(1) + v = parent.one() x = self % a - while(not x.is_zero()): + while not x.is_zero(): a += (v * x) % a b, x = self.quo_rem(a) b %= a - v = (v * (2 - b*v)) % a - + v = (v * (2 - b * v)) % a return a def factor_of_slope(self, slope=None): diff --git a/src/sage/schemes/cyclic_covers/cycliccover_finite_field.py b/src/sage/schemes/cyclic_covers/cycliccover_finite_field.py index a9a6d436269..37c3617ce03 100644 --- a/src/sage/schemes/cyclic_covers/cycliccover_finite_field.py +++ b/src/sage/schemes/cyclic_covers/cycliccover_finite_field.py @@ -170,7 +170,6 @@ def _find_N_43(): d = self._d delta = self._delta N0 = self._N0 - n = N0 left_side = N0 + floor(log((d * p * (r - 1) + r) / delta) / log(p)) def right_side_log(n): diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 6ba7a5754f3..3e58424ed96 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -3797,10 +3797,10 @@ def saturation(self, points, verbose=False, ([(-1/4*a + 3/4 : 59/8*a - 317/8 : 1)], 2, 0.344624259712631) """ full_saturation = (max_prime == 0) and (one_prime == 0) - Plist = [self(P) for P in points] - Plist = [P for P in points if P.has_infinite_order()] + Plist = (self(P) for P in points) + Plist = [P for P in Plist if P.has_infinite_order()] n = len(Plist) - index = ZZ(1) + index = ZZ.one() if n == 0: return Plist, index, RealField()(1) From 8af227dc286a4659c213a72b2a5ee69fe9d9e88f Mon Sep 17 00:00:00 2001 From: Joshua Campbell Date: Mon, 13 Jul 2020 14:57:16 -0700 Subject: [PATCH 084/217] Update animation example in Three.js documentation with new icons --- .../plot3d/threejs_examples/animation.html | 59 +++++++++++-------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/src/doc/en/reference/plot3d/threejs_examples/animation.html b/src/doc/en/reference/plot3d/threejs_examples/animation.html index 9446377891f..5a8a1e1e884 100644 --- a/src/doc/en/reference/plot3d/threejs_examples/animation.html +++ b/src/doc/en/reference/plot3d/threejs_examples/animation.html @@ -186,14 +186,8 @@ - - - + + +
@@ -670,17 +681,17 @@ From 1dc8a3bc66f0c82ec5b4a5abc18921de2dd8d10a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Labb=C3=A9?= Date: Tue, 14 Jul 2020 10:33:01 +0200 Subject: [PATCH 085/217] 30138: add random tag to unstable doctest --- src/sage/databases/oeis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/databases/oeis.py b/src/sage/databases/oeis.py index 79010884e27..688de468bb6 100644 --- a/src/sage/databases/oeis.py +++ b/src/sage/databases/oeis.py @@ -90,7 +90,7 @@ :: - sage: p.cross_references(fetch=True) # optional -- internet + sage: p.cross_references(fetch=True) # optional -- internet # random 0: A000798: Number of different quasi-orders (or topologies, or transitive digraphs) with n labeled elements. 1: A001035: Number of partially ordered sets ("posets") with n labeled elements (or labeled acyclic transitive digraphs). 2: A001930: Number of topologies, or transitive digraphs with n unlabeled nodes. From 9e0cbed2ca26f85160ad363c2b298cb109822ffe Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 14 Jul 2020 12:50:27 -0700 Subject: [PATCH 086/217] src/sage/symbolic/assumptions.py: Fix style warning --- src/sage/symbolic/assumptions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/symbolic/assumptions.py b/src/sage/symbolic/assumptions.py index 1eda9935a93..351048c40f6 100644 --- a/src/sage/symbolic/assumptions.py +++ b/src/sage/symbolic/assumptions.py @@ -973,4 +973,5 @@ def __exit__(self, *args, **kwds): forget(assumptions()) assume(self.OldAss) else: - if len(self.Ass)>0: forget(self.Ass) + if len(self.Ass) > 0: + forget(self.Ass) From d1dd77313c9d1089e6e3803bec857a9308136f6d Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Mon, 13 Jul 2020 11:16:34 -0400 Subject: [PATCH 087/217] Trac #30132: update resolvelinks() in ./sage from ./src/bin/sage-env. This copy/pasted function got updated in one place but not in the other. Obviously the duplication should be addressed eventually, but for now let's make the two agree once more. --- sage | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/sage b/sage index 837f3e6866f..4f9579c909a 100755 --- a/sage +++ b/sage @@ -25,7 +25,11 @@ # Resolve all symbolic links in a filename. This more or less behaves # like "readlink -f" except that it does not convert the filename to an # absolute path (a relative path remains relative), nor does it treat -# "." or ".." specially. See Trac ticket #5852. +# "." or ".." specially. +# +# WARNING: this function is copy/pasted from src/bin/sage-env, and +# deserves to be factored out at some point in the future. In the +# meantime however the two should be kept synchronized. resolvelinks() { # $in is what still needs to be converted (normally has no starting slash) in="$1" @@ -35,12 +39,10 @@ resolvelinks() { # Move stuff from $in to $out while [ -n "$in" ]; do # Normalize $in by replacing consecutive slashes by one slash - while { in_single_slash=${in//\/\//\/}; [ "$in" != "$in_single_slash" ]; }; do - in=$in_single_slash - done + in=$(echo "${in}" | sed 's://*:/:g') # If $in starts with a slash, remove it and set $out to the root - in_without_slash=${in/#\//} + in_without_slash=${in#/} if [ "$in" != "$in_without_slash" ]; then in=$in_without_slash out="/" @@ -62,7 +64,7 @@ resolvelinks() { out="$out$f" # If the new $in starts with a slash, move it to $out - in_without_slash=${in/#\//} + in_without_slash=${in#/} if [ "$in" != "$in_without_slash" ]; then in=$in_without_slash out="$out/" @@ -94,7 +96,8 @@ resolvelinks() { fi # In $in, replace $f by $f_resolved (leave $out alone) - in=${in/#"$f"/"$f_resolved"} + in="${in#${f}}" + in="${f_resolved}${in}" done # Return $out From c6b8a5ea040ce5f869ae7f26dc16269c782a3755 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Tue, 14 Jul 2020 17:55:34 -0400 Subject: [PATCH 088/217] Trac #30135: make trivial bash -> sh shebang conversions. Many scripts in the sage repository are alread written for POSIX sh and require no modification to run them with /bin/sh instead of /bin/bash in the shebang. This commit changes only those scripts. --- build/bin/sage-get-system-packages | 2 +- build/bin/sage-guess-package-system | 2 +- build/bin/sage-python23 | 2 +- build/bin/sage-spkg-info | 2 +- build/bin/sage-starts | 2 +- sage | 2 +- src/bin/sage-cachegrind | 2 +- src/bin/sage-callgrind | 2 +- src/bin/sage-clone-source | 2 +- src/bin/sage-download-upstream | 2 +- src/bin/sage-grep | 2 +- src/bin/sage-grepdoc | 2 +- src/bin/sage-inline-fortran | 2 +- src/bin/sage-massif | 2 +- src/bin/sage-omega | 2 +- src/bin/sage-open | 2 +- src/bin/sage-python | 2 +- src/bin/sage-upgrade | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/build/bin/sage-get-system-packages b/build/bin/sage-get-system-packages index 868b6838298..47e08301052 100755 --- a/build/bin/sage-get-system-packages +++ b/build/bin/sage-get-system-packages @@ -1,4 +1,4 @@ -#! /usr/bin/env bash +#!/bin/sh SYSTEM=$1 if [ -z "$SYSTEM" ]; then echo >&2 "usage: $0 {debian|arch|conda|...} SPKGS..." diff --git a/build/bin/sage-guess-package-system b/build/bin/sage-guess-package-system index e414d10c413..32a97330744 100755 --- a/build/bin/sage-guess-package-system +++ b/build/bin/sage-guess-package-system @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # # First test for user-installable package systems, then system package systems if conda --version > /dev/null 2>&1; then diff --git a/build/bin/sage-python23 b/build/bin/sage-python23 index 25abc6b1034..83a5668def4 100755 --- a/build/bin/sage-python23 +++ b/build/bin/sage-python23 @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # Run the Python interpreter that we are currently building Sage with diff --git a/build/bin/sage-spkg-info b/build/bin/sage-spkg-info index 1a8847bb875..9575df7f20e 100755 --- a/build/bin/sage-spkg-info +++ b/build/bin/sage-spkg-info @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # # sage-spkg-info SPKG # Format information about a Sage package diff --git a/build/bin/sage-starts b/build/bin/sage-starts index 64d9b29f0de..1adcdccaa06 100755 --- a/build/bin/sage-starts +++ b/build/bin/sage-starts @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # Run this test from SAGE_ROOT. # If SAGE_ROOT is not defined (this will be the case when called from diff --git a/sage b/sage index 4f9579c909a..3fad670c839 100755 --- a/sage +++ b/sage @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # # Sage: a free open-source mathematics software system # diff --git a/src/bin/sage-cachegrind b/src/bin/sage-cachegrind index f23427e03a7..a23c6b8c344 100755 --- a/src/bin/sage-cachegrind +++ b/src/bin/sage-cachegrind @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # We reuse the gdb pythonstartup script. PYTHONSTARTUP=`dirname $0`/sage-ipython diff --git a/src/bin/sage-callgrind b/src/bin/sage-callgrind index d78acd6fc9f..e3bf54dae55 100755 --- a/src/bin/sage-callgrind +++ b/src/bin/sage-callgrind @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh if [ ! -d "$DOT_SAGE/valgrind" ]; then mkdir "$DOT_SAGE/valgrind" diff --git a/src/bin/sage-clone-source b/src/bin/sage-clone-source index bb826ca920f..6720ea7391d 100755 --- a/src/bin/sage-clone-source +++ b/src/bin/sage-clone-source @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh ######################################################################## # Helper script for sdist diff --git a/src/bin/sage-download-upstream b/src/bin/sage-download-upstream index c5d9afe31e0..93725a5024c 100755 --- a/src/bin/sage-download-upstream +++ b/src/bin/sage-download-upstream @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh for pkg in $SAGE_ROOT/build/pkgs/* do diff --git a/src/bin/sage-grep b/src/bin/sage-grep index d78cfce6a5d..8441fa83519 100755 --- a/src/bin/sage-grep +++ b/src/bin/sage-grep @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh cd "$SAGE_SRC" diff --git a/src/bin/sage-grepdoc b/src/bin/sage-grepdoc index 51cb3218ac7..ec0383178ed 100755 --- a/src/bin/sage-grepdoc +++ b/src/bin/sage-grepdoc @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh cd "$SAGE_DOC" diff --git a/src/bin/sage-inline-fortran b/src/bin/sage-inline-fortran index e0250cb6d9a..e417d5b9a3f 100755 --- a/src/bin/sage-inline-fortran +++ b/src/bin/sage-inline-fortran @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # Compile Fortran code within Sage, # see src/sage/misc/inline_fortran.py diff --git a/src/bin/sage-massif b/src/bin/sage-massif index 45ffd02307f..083831d9293 100755 --- a/src/bin/sage-massif +++ b/src/bin/sage-massif @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # We reuse the gdb pythonstartup script. PYTHONSTARTUP=`dirname $0`/sage-ipython diff --git a/src/bin/sage-omega b/src/bin/sage-omega index dc2a7fc37a9..b0f0f981106 100755 --- a/src/bin/sage-omega +++ b/src/bin/sage-omega @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # We reuse the gdb pythonstartup script. PYTHONSTARTUP=`dirname $0`/sage-ipython diff --git a/src/bin/sage-open b/src/bin/sage-open index 5c829ea0c3e..2bdea59891a 100755 --- a/src/bin/sage-open +++ b/src/bin/sage-open @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # SAGE open command for OS X -- needed since # the SAGE libraries clash with some OS X libraries, diff --git a/src/bin/sage-python b/src/bin/sage-python index 896386c8015..596a467e242 100755 --- a/src/bin/sage-python +++ b/src/bin/sage-python @@ -1,2 +1,2 @@ -#!/usr/bin/env bash +#!/bin/sh sage -python "$@" diff --git a/src/bin/sage-upgrade b/src/bin/sage-upgrade index 9ed4b88c765..957f9b523f7 100755 --- a/src/bin/sage-upgrade +++ b/src/bin/sage-upgrade @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # This script must be run from $SAGE_ROOT and without having sourced # sage-env. From 5e14f5d3ec48d27c1b672629edff9560addd8a14 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Tue, 14 Jul 2020 21:36:40 -0400 Subject: [PATCH 089/217] Trac #30135: make build/bin/sage-system-python POSIX-compatible. This script was essentially already written in POSIX sh, except for one (unnecessary) bash test [[ syntax ]]. We change the test to use single brackets, and the shebang to /bin/sh. --- build/bin/sage-system-python | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/bin/sage-system-python b/build/bin/sage-system-python index 9e18639da1d..8f3d9949213 100755 --- a/build/bin/sage-system-python +++ b/build/bin/sage-system-python @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # Run the system python. # @@ -25,7 +25,7 @@ fi PYTHONS="python python3 python3.8 python3.7 python2.7 python3.6 python2" for PY in $PYTHONS; do PYTHON="$(PATH="$SAGE_ORIG_PATH" command -v $PY)" - if [[ -n "$PYTHON" ]]; then + if [ -n "$PYTHON" ]; then if "$PYTHON" -c 'import urllib'; then exec "$PYTHON" "$@" fi From 4adcb204aca95916a01535ba4c3a98ec0d13d39d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 14 Jul 2020 22:01:54 -0700 Subject: [PATCH 090/217] src/sage/symbolic/assumptions.py: Remove unused import --- src/sage/symbolic/assumptions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/symbolic/assumptions.py b/src/sage/symbolic/assumptions.py index 351048c40f6..e39c78dde22 100644 --- a/src/sage/symbolic/assumptions.py +++ b/src/sage/symbolic/assumptions.py @@ -68,7 +68,6 @@ ValueError: Assumption is inconsistent sage: forget() """ -from sage.structure.sage_object import SageObject from sage.rings.all import ZZ, QQ, RR, CC from sage.symbolic.ring import is_SymbolicVariable from sage.structure.unique_representation import UniqueRepresentation From 07e4ab1c319a420b00bdf5e43199d3195ba1efa3 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Wed, 15 Jul 2020 07:49:46 +0200 Subject: [PATCH 091/217] fix bog introduced by 39843 --- src/sage/geometry/polyhedron/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 4759707ab2f..dc621f9a050 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -5035,11 +5035,11 @@ def linear_transformation(self, linear_transf, new_base_ring=None): else: new_vertices = () if self.n_rays(): - new_rays = ( r for r in (linear_transf*matrix(R, self.rays()).transpose()) ) + new_rays = ( r for r in (linear_transf*matrix(R, self.rays()).transpose()).transpose() ) else: new_rays = () if self.n_lines(): - new_lines = ( l for l in (linear_transf*matrix(R, self.lines()).transpose()) ) + new_lines = ( l for l in (linear_transf*matrix(R, self.lines()).transpose()).transpose() ) else: new_lines = () From 4eff4137dfac9c656bb8e50343be76efae2974ae Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Wed, 15 Jul 2020 07:56:58 +0200 Subject: [PATCH 092/217] add tiny testsuite to doctest --- src/sage/geometry/polyhedron/base.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index dc621f9a050..7005afe1f37 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -5094,6 +5094,21 @@ def linear_transformation(self, linear_transf, new_base_ring=None): return new_parent.element_class(new_parent, [tuple(new_vertices), tuple(new_rays), tuple(new_lines)], None) + def _test_linear_transformation(self, tester=None, **options): + """ + Run some tests on linear transformation. + + TESTS:: + + Polyhedron(rays=[(0,1)])._test_linear_transformation() + """ + if tester is None: + tester = self._tester(**options) + + # Check that :trac:`30146` is fixed. + from sage.matrix.special import identity_matrix + tester.assertEqual(self, self.linear_transformation(identity_matrix(self.ambient_dim()))) + def _acted_upon_(self, actor, self_on_left): """ Implement the action by scalars, vectors, matrices or other polyhedra. From 7fe6b43d2ab3adde507fe745726b82c3bbc8059d Mon Sep 17 00:00:00 2001 From: Salvatore Stella Date: Wed, 15 Jul 2020 09:28:20 +0200 Subject: [PATCH 093/217] One transposition only --- src/sage/geometry/polyhedron/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 7005afe1f37..646b6e2bae1 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -5035,11 +5035,11 @@ def linear_transformation(self, linear_transf, new_base_ring=None): else: new_vertices = () if self.n_rays(): - new_rays = ( r for r in (linear_transf*matrix(R, self.rays()).transpose()).transpose() ) + new_rays = ( r for r in matrix(R, self.rays())*linear_transf.transpose() ) else: new_rays = () if self.n_lines(): - new_lines = ( l for l in (linear_transf*matrix(R, self.lines()).transpose()).transpose() ) + new_lines = ( l for l in matrix(R, self.lines())*linear_transf.transpose() ) else: new_lines = () From 150d834d51f1df74f02434cc477779ccefc964da Mon Sep 17 00:00:00 2001 From: Johan Rosenkilde Date: Wed, 15 Jul 2020 11:14:27 +0200 Subject: [PATCH 094/217] Example for coding.linear_code_no_metric.__init__ --- src/sage/coding/linear_code_no_metric.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/sage/coding/linear_code_no_metric.py b/src/sage/coding/linear_code_no_metric.py index eb87a84439f..a2c0bf7242c 100644 --- a/src/sage/coding/linear_code_no_metric.py +++ b/src/sage/coding/linear_code_no_metric.py @@ -157,6 +157,22 @@ def __init__(self, base_field, length, default_encoder_name, default_decoder_nam - ``default_decoder_name`` -- the name of the default decoder of ``self`` - ``metric`` -- (default: ``Hamming``) the metric of ``self`` + + EXAMPLES: + + sage: from sage.coding.linear_code_no_metric import AbstractLinearCodeNoMetric + sage: from sage.coding.linear_code import LinearCodeSyndromeDecoder + sage: class MyLinearCode(AbstractLinearCodeNoMetric): + ....: def __init__(self, field, length, dimension, generator_matrix): + ....: self._registered_decoders['Syndrome'] = LinearCodeSyndromeDecoder + ....: AbstractLinearCodeNoMetric.__init__(self, field, length, "Systematic", "Syndrome") + ....: self._dimension = dimension + ....: self._generator_matrix = generator_matrix + ....: def generator_matrix(self): + ....: return self._generator_matrix + ....: def _repr_(self): + ....: return "[%d, %d] dummy code over GF(%s)" % (self.length(), self.dimension(), self.base_field().cardinality()) + sage: C = MyLinearCode(GF(2), 1, 1, matrix(GF(2), [1])) """ self._registered_encoders['Systematic'] = LinearCodeSystematicEncoder From 4a770f8855537945c70069ba429079e2529e569b Mon Sep 17 00:00:00 2001 From: Johan Rosenkilde Date: Wed, 15 Jul 2020 11:36:14 +0200 Subject: [PATCH 095/217] Fix __eq__ and __ne__ for AbstractLinearCodeNoMetric, and remove it from AbstractLinearCode --- src/sage/coding/linear_code.py | 54 ---------------------- src/sage/coding/linear_code_no_metric.py | 58 +++++++++++++++++++++++- 2 files changed, 57 insertions(+), 55 deletions(-) diff --git a/src/sage/coding/linear_code.py b/src/sage/coding/linear_code.py index 42370bde53e..31ba2a55450 100644 --- a/src/sage/coding/linear_code.py +++ b/src/sage/coding/linear_code.py @@ -1158,60 +1158,6 @@ def construction_x(self, other, aux): G = left.augment(right) return LinearCode(G) - def __eq__(self, right): - """ - Checks if ``self`` is equal to ``right``. - - EXAMPLES:: - - sage: C1 = codes.HammingCode(GF(2), 3) - sage: C2 = codes.HammingCode(GF(2), 3) - sage: C1 == C2 - True - - TESTS: - - We check that :trac:`16644` is fixed:: - - sage: C = codes.HammingCode(GF(2), 3) - sage: C == ZZ - False - """ - if not (isinstance(right, LinearCode)\ - and self.length() == right.length()\ - and self.dimension() == right.dimension()\ - and self.base_ring() == right.base_ring()): - return False - Ks = self.parity_check_matrix().right_kernel() - rbas = right.gens() - if not all(c in Ks for c in rbas): - return False - Kr = right.parity_check_matrix().right_kernel() - sbas = self.gens() - if not all(c in Kr for c in sbas): - return False - return True - - def __ne__(self, other): - r""" - Tests inequality of ``self`` and ``other``. - - This is a generic implementation, which returns the inverse of ``__eq__`` for self. - - EXAMPLES:: - - sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0],[1,0,0,1,1,0,0],[0,1,0,1,0,1,0],[1,1,0,1,0,0,1]]) - sage: C1 = LinearCode(G) - sage: C2 = LinearCode(G) - sage: C1 != C2 - False - sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0],[1,0,0,1,1,0,0],[0,1,0,1,0,1,0],[1,1,0,1,0,1,1]]) - sage: C2 = LinearCode(G) - sage: C1 != C2 - True - """ - return not self == other - def extended_code(self): r""" Returns `self` as an extended code. diff --git a/src/sage/coding/linear_code_no_metric.py b/src/sage/coding/linear_code_no_metric.py index 8fd4fd8c24a..d5e1fdf1ec0 100644 --- a/src/sage/coding/linear_code_no_metric.py +++ b/src/sage/coding/linear_code_no_metric.py @@ -243,7 +243,63 @@ def generator_matrix(self, encoder_name=None, **kwargs): return E.generator_matrix() def __eq__(self, other): - return self.generator_matrix() == other.generator_matrix() + r""" + Tests equality between two linear codes. + + EXAMPLES:: + + sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0],[1,0,0,1,1,0,0],[0,1,0,1,0,1,0],[1,1,0,1,0,0,1]]) + sage: C1 = LinearCode(G) + sage: C1 == 5 + False + sage: C2 = LinearCode(G) + sage: C1 == C2 + True + sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0],[1,0,0,1,1,0,0],[0,1,0,1,0,1,0],[1,1,0,1,0,1,1]]) + sage: C2 = LinearCode(G) + sage: C1 == C2 + False + sage: G = Matrix(GF(3), [[1,2,1,0,0,0,0]]) + sage: C3 = LinearCode(G) + sage: C1 == C3 + False + """ + # Fail without computing the generator matrix if possible: + if not (isinstance(other, AbstractLinearCodeNoMetric)\ + and self.length() == other.length()\ + and self.dimension() == other.dimension()\ + and self.base_ring() == other.base_ring()): + return False + # Check that basis elements of `other` are all in `self.` + # Since we're over a field and since the dimensions match, the codes + # must be equal. + # This implementation may avoid linear algebra altogether, if `self` + # implements an efficient way to obtain a parity check matrix, and in + # the worst case does only one system solving. + for c in other.gens(): + if not (c in self): + return False + return True + + def __ne__(self, other): + r""" + Tests inequality of ``self`` and ``other``. + + This is a generic implementation, which returns the inverse of ``__eq__`` for self. + + EXAMPLES:: + + sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0],[1,0,0,1,1,0,0],[0,1,0,1,0,1,0],[1,1,0,1,0,0,1]]) + sage: C1 = LinearCode(G) + sage: C2 = LinearCode(G) + sage: C1 != C2 + False + sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0],[1,0,0,1,1,0,0],[0,1,0,1,0,1,0],[1,1,0,1,0,1,1]]) + sage: C2 = LinearCode(G) + sage: C1 != C2 + True + """ + return not self == other def dimension(self): r""" From 9ef1e9ccea82398a622bcbfe5d013eeaa0588e86 Mon Sep 17 00:00:00 2001 From: Johan Rosenkilde Date: Wed, 15 Jul 2020 11:42:04 +0200 Subject: [PATCH 096/217] Add doctest to coding.linear_rank_metric.LinearRankMetricCodeNearestNeighborDecoder.decode_to_code --- src/sage/coding/linear_rank_metric.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/sage/coding/linear_rank_metric.py b/src/sage/coding/linear_rank_metric.py index 931173f6602..145b0be764d 100644 --- a/src/sage/coding/linear_rank_metric.py +++ b/src/sage/coding/linear_rank_metric.py @@ -860,6 +860,15 @@ def decode_to_code(self, r): OUTPUT: - a vector of ``self``'s message space + + EXAMPLES:: + + sage: F.
= GF(4) + sage: G = Matrix(F, [[1,1,0]]) + sage: C = codes.LinearRankMetricCode(G, GF(2)) + sage: D = codes.decoders.LinearRankMetricCodeNearestNeighborDecoder(C) + sage: D.decode_to_code(vector(F, [a, a, 1])) + (a, a, 0) """ C = self.code() c_min = C.zero() From 5f46031a26bee3eb4a57c17b611c29c451e45525 Mon Sep 17 00:00:00 2001 From: Johan Rosenkilde Date: Wed, 15 Jul 2020 11:47:04 +0200 Subject: [PATCH 097/217] Make doctests of sage.coding.linear_rank_metric run 50 times faster --- src/sage/coding/linear_rank_metric.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/sage/coding/linear_rank_metric.py b/src/sage/coding/linear_rank_metric.py index 145b0be764d..ace4c206272 100644 --- a/src/sage/coding/linear_rank_metric.py +++ b/src/sage/coding/linear_rank_metric.py @@ -558,10 +558,11 @@ def minimum_distance(self): EXAMPLES:: - sage: G = Matrix(GF(64), [[1,1,0], [0,0,1]]) - sage: C = codes.LinearRankMetricCode(G, GF(4)) + sage: F. = GF(8) + sage: G = Matrix(F, [[1,a,a^2,0]]) + sage: C = codes.LinearRankMetricCode(G, GF(2)) sage: C.minimum_distance() - 1 + 3 """ d = Infinity for c in self: @@ -886,11 +887,12 @@ def decoding_radius(self): EXAMPLES:: - sage: G = Matrix(GF(64), [[1,1,0], [0,0,1]]) - sage: C = codes.LinearRankMetricCode(G, GF(4)) + sage: F. = GF(8) + sage: G = Matrix(F, [[1,a,a^2,0]]) + sage: C = codes.LinearRankMetricCode(G, GF(2)) sage: D = codes.decoders.LinearRankMetricCodeNearestNeighborDecoder(C) sage: D.decoding_radius() - 0 + 1 """ return (self.code().minimum_distance()-1) // 2 From 7bb3b2ca0e32b0f7445484cfe936c7ef9f1bc8e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Philippe=20Labb=C3=A9?= Date: Tue, 14 Apr 2020 14:03:05 +0200 Subject: [PATCH 098/217] First version --- .../hyperplane_arrangement/arrangement.py | 46 ++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index d7455f1f8ab..76dd92093c4 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -1565,11 +1565,16 @@ def _make_region(self, hyperplanes): base_ring=self.parent().base_ring()) @cached_method - def regions(self): + def regions(self,backend=None): r""" Return the regions of the hyperplane arrangement. The base field must have characteristic zero. + + INPUT: + + - ``backend`` -- string (optional; default: ``None``); the backend to + use for the polyhedra. OUTPUT: @@ -1627,6 +1632,21 @@ def regions(self): sage: len(A.regions()) # not tested (~25s) 11292 + It is possible to specify the backend:: + + sage: K. = CyclotomicField(9) + sage: L. = NumberField((q+q^(-1)).minpoly(),embedding = AA(q+q^-1)) + sage: norms = [[1,1/3*(-2*r9^2-r9+1),0],[1,-r9^2-r9,0], + [1,-r9^2+1,0],[1,-r9^2,0],[1,r9^2-4,-r9^2+3]] + sage: H. = HyperplaneArrangements(L) + sage: A = H() + sage: for v in norms: + ....: a,b,c = v + ....: A = A.add_hyperplane(a*x + b*y + c*z) + sage: R = A.regions(backend='normaliz') # optional - pynormaliz + sage: R[0].backend() + 'normaliz' + TESTS:: sage: K. = HyperplaneArrangements(QQ) @@ -1639,7 +1659,9 @@ def regions(self): from sage.geometry.polyhedron.constructor import Polyhedron R = self.base_ring() dim = self.dimension() - universe = Polyhedron(eqns=[[0] + [0] * dim], base_ring=R) + universe = Polyhedron(eqns=[[0] + [0] * dim], + base_ring=R, + backend=backend) regions = [universe] if self.is_linear() and self.n_hyperplanes(): # We only take the positive half w.r. to the first hyperplane. @@ -1648,8 +1670,8 @@ def regions(self): for hyperplane in self: ieq = vector(R, hyperplane.dense_coefficient_list()) - pos_half = Polyhedron(ieqs=[ ieq], base_ring=R) - neg_half = Polyhedron(ieqs=[-ieq], base_ring=R) + pos_half = Polyhedron(ieqs=[ ieq], base_ring=R, backend=backend) + neg_half = Polyhedron(ieqs=[-ieq], base_ring=R, backend=backend) if not regions: # See comment above. regions = [pos_half] @@ -1704,7 +1726,7 @@ def regions(self): return tuple(regions) @cached_method - def poset_of_regions(self, B=None, numbered_labels=True): + def poset_of_regions(self, B=None, numbered_labels=True, backend=None): r""" Return the poset of regions for a central hyperplane arrangement. @@ -1722,6 +1744,9 @@ def poset_of_regions(self, B=None, numbered_labels=True): then the elements of the poset are numbered. Else they are labelled with the regions themselves. + - ``backend`` -- string (optional; default: ``None``); the backend to + use for the polyhedra. + OUTPUT: A Poset object containing the poset of regions. @@ -1749,10 +1774,19 @@ def poset_of_regions(self, B=None, numbered_labels=True): sage: A.poset_of_regions(B=base_region) Finite poset containing 14 elements + It is possible to specify the backend:: + + sage: R = A.regions(backend='normaliz') # optional - pynormaliz + sage: base_region = R[3] # optional - pynormaliz + sage: PR = A.poset_of_regions(B=base_region, + numbered_labels=False, + backend='normaliz') # optional - pynormaliz + sage: PR.an_element().backend() # optional - pynormaliz + 'normaliz' """ # We use RX to keep track of indexes and R to keep track of which regions # we've already hit. This poset is graded, so we can go one set at a time - RX = self.regions() + RX = self.regions(backend=backend) R = set(RX) if B in R: R.discard(B) From 99ecd79e337d97751d4423b381add5e0a089d22f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Philippe=20Labb=C3=A9?= Date: Fri, 17 Apr 2020 10:57:03 +0200 Subject: [PATCH 099/217] Addons to documentation --- .../hyperplane_arrangement/arrangement.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index 76dd92093c4..e0e6ee38757 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -64,6 +64,18 @@ sage: a = H([(1,2,3), 4], [(5,6,7), 8]); a Arrangement +Number fields are also possible:: + + sage: NF. = NumberField(x^4 - 5*x^2 + 5,embedding=1.90) + sage: H. = HyperplaneArrangements(NF) + sage: A = H([[(-a^3 + 3*a, -a^2 + 4), 1], [(a^3 - 4*a, -1), 1], + ....: [(0, 2*a^2 - 6), 1], [(-a^3 + 4*a, -1), 1], + ....: [(a^3 - 3*a, -a^2 + 4), 1]]) + sage: A + Arrangement of 5 hyperplanes of dimension 2 and rank 2 + sage: A.base_ring() + Number Field in a with defining polynomial x^4 - 5*x^2 + 5 with a = 1.902113032590308? + Notation (iii): a list or tuple of hyperplanes:: sage: H. = HyperplaneArrangements(GF(5)) @@ -116,6 +128,9 @@ sage: b == hyperplane_arrangements.coordinate(3) True +Properties of Arrangements +-------------------------- + A hyperplane arrangement is *essential* if the normals to its hyperplanes span the ambient space. Otherwise, it is *inessential*. The essentialization is formed by intersecting the hyperplanes by this From 39e147bc0c6e3458e677ff6aa47f82c40d68ab79 Mon Sep 17 00:00:00 2001 From: Ivo Maffei Date: Wed, 15 Jul 2020 13:50:55 +0200 Subject: [PATCH 100/217] simplified if-else statement --- src/sage/combinat/designs/bibd.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/sage/combinat/designs/bibd.py b/src/sage/combinat/designs/bibd.py index 0a61d02ae6e..64b76a6df80 100644 --- a/src/sage/combinat/designs/bibd.py +++ b/src/sage/combinat/designs/bibd.py @@ -1210,10 +1210,6 @@ def _get_r_s_t_u(v): t,u = 30*s+5, 5 elif x <= 51: t,u = 30*s+5, x-25 - elif x <= 66: - t,u = 30*s+11, x-55 - elif x <= 96: - t,u = 30*s+11, x-55 elif x <= 121: t,u = 30*s+11, x-55 elif x <= 146: From f6db6a55c45606f41d2f5abf997bc66875673f10 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Wed, 15 Jul 2020 14:11:44 +0200 Subject: [PATCH 101/217] trac #30039: use edges instead of edge_iterator --- src/sage/graphs/base/boost_graph.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx index 326f61437b3..932a646cf98 100644 --- a/src/sage/graphs/base/boost_graph.pyx +++ b/src/sage/graphs/base/boost_graph.pyx @@ -2385,12 +2385,12 @@ cpdef diameter(G, algorithm=None, source=None, # If digraph contains negative edge weight then # algo is set to `Bellman-Ford` if weight_function is not None: - for e in G.edge_iterator(): + for e in G.edges(sort=False): if float(weight_function(e)) < 0: algo = 'Bellman-Ford' break elif G.weighted(): - for _,_,w in G.edge_iterator(): + for _,_,w in G.edges(sort=False): if w and float(w) < 0: algo = 'Bellman-Ford' break From 9ace361fd916ed1ef90992c86c3b0b4296067184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Philippe=20Labb=C3=A9?= Date: Wed, 15 Jul 2020 15:12:25 +0200 Subject: [PATCH 102/217] Second version, more robust --- .../hyperplane_arrangement/arrangement.py | 161 +++++++++++++----- 1 file changed, 115 insertions(+), 46 deletions(-) diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index e0e6ee38757..83c8a7ce61c 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -367,7 +367,7 @@ class HyperplaneArrangementElement(Element): :class:`HyperplaneArrangementElement` instances directly, always use the parent. """ - def __init__(self, parent, hyperplanes, check=True): + def __init__(self, parent, hyperplanes, check=True, backend=None): """ Construct a hyperplane arrangement. @@ -380,15 +380,30 @@ def __init__(self, parent, hyperplanes, check=True): - ``check`` -- boolean (optional; default ``True``); whether to check input + - ``backend`` -- string (optional; default: ``None``); the backend to + use for the related polyhedral objects. + EXAMPLES:: sage: H. = HyperplaneArrangements(QQ) sage: elt = H(x, y); elt Arrangement sage: TestSuite(elt).run() + + It is possible to specify a backend for polyhedral computations:: + + sage: R. = QuadraticField(5) + sage: H = HyperplaneArrangements(R, names='xyz') + sage: x,y,z = H.gens() + sage: A = H(sqrt5*x+2*y+3*z, backend='normaliz') + sage: A.backend() + 'normaliz' + sage: A.regions()[0].backend() + 'normaliz' """ super(HyperplaneArrangementElement, self).__init__(parent) self._hyperplanes = hyperplanes + self._backend = backend if check: if not isinstance(hyperplanes, tuple): raise ValueError("the hyperplanes must be given as a tuple") @@ -561,6 +576,33 @@ def rank(self): normals = [h.normal() for h in self] return matrix(R, normals).rank() + def backend(self): + """ + Return the backend used for polyhedral objects. + + OUTPUT: + + A string giving the backend or None (default) + + EXAMPLES: + + By default, no backend is specified:: + + sage: H = HyperplaneArrangements(QQ) + sage: A = H() + sage: A.backend() + + Otherwise, one may specify a polyhedral backend:: + + sage: A = H(backend='ppl') + sage: A.backend() + 'ppl' + sage: A = H(backend='normaliz') + sage: A.backend() + 'normaliz' + """ + return self._backend + def _richcmp_(self, other, op): """ Compare two hyperplane arrangements. @@ -617,7 +659,7 @@ def union(self, other): P = self.parent() other = P(other) hyperplanes = self._hyperplanes + other._hyperplanes - return P(*hyperplanes) + return P(*hyperplanes, backend=self._backend) add_hyperplane = union @@ -695,7 +737,7 @@ def cone(self, variable='t'): P = self.parent() names = (variable,) + P._names H = HyperplaneArrangements(self.parent().base_ring(), names=names) - return H(*hyperplanes) + return H(*hyperplanes,backend=self._backend) @cached_method def intersection_poset(self): @@ -863,6 +905,15 @@ def deletion(self, hyperplanes): Traceback (most recent call last): ... ValueError: hyperplane is not in the arrangement + + Checks that deletion preserves the backend:: + + sage: H = HyperplaneArrangements(QQ,names='xyz') + sage: x,y,z = H.gens() + sage: h1,h2 = [1*x+2*y+3*z,3*x+2*y+1*z] + sage: A = H(h1,h2,backend='normaliz') + sage: A.deletion(h2).backend() + 'normaliz' """ parent = self.parent() hyperplanes = parent(hyperplanes) @@ -872,7 +923,7 @@ def deletion(self, hyperplanes): planes.remove(hyperplane) except ValueError: raise ValueError('hyperplane is not in the arrangement') - return parent(*planes) + return parent(*planes,backend=self._backend) def restriction(self, hyperplane): r""" @@ -908,6 +959,17 @@ def restriction(self, hyperplane): .. SEEALSO:: :meth:`deletion` + + TESTS: + + Checks that restriction preserves the backend:: + + sage: H = HyperplaneArrangements(QQ,names='xyz') + sage: x,y,z = H.gens() + sage: h1,h2 = [1*x+2*y+3*z,3*x+2*y+1*z] + sage: A = H(h1, h2, backend='normaliz') + sage: A.restriction(h2).backend() + 'normaliz' """ parent = self.parent() hyperplane = parent(hyperplane)[0] @@ -928,7 +990,7 @@ def restriction(self, hyperplane): names = list(parent._names) names.pop(pivot) H = HyperplaneArrangements(parent.base_ring(), names=tuple(names)) - return H(*hyperplanes, signed=False) + return H(*hyperplanes, signed=False, backend=self._backend) def change_ring(self, base_ring): """ @@ -960,9 +1022,20 @@ def change_ring(self, base_ring): sage: A = H([(1,1), 0], [(2,3), -1]) sage: A.change_ring(FiniteField(2)) Arrangement + + TESTS: + + Checks that changing the ring preserves the backend:: + + sage: H = HyperplaneArrangements(QQ,names='xyz') + sage: x,y,z = H.gens() + sage: h1,h2 = [1*x+2*y+3*z,3*x+2*y+1*z] + sage: A = H(h1, h2, backend='normaliz') + sage: A.change_ring(RDF).backend() + 'normaliz' """ parent = self.parent().change_ring(base_ring) - return parent(self) + return parent(self, backend=self._backend) @cached_method def n_regions(self): @@ -1166,7 +1239,7 @@ def is_central(self, certificate=False): if self.n_hyperplanes() == 0: if certificate: from sage.geometry.polyhedron.parent import Polyhedra - pp = Polyhedra(R, self.dimension()) + pp = Polyhedra(R, self.dimension(), backend=self._backend) return (True, pp.universe()) else: return True @@ -1180,7 +1253,7 @@ def is_central(self, certificate=False): # The solution set is empty, therefore the center is empty if certificate: from sage.geometry.polyhedron.parent import Polyhedra - pp = Polyhedra(R, self.dimension()) + pp = Polyhedra(R, self.dimension(), backend=self._backend) return (False, pp.empty()) else: return False @@ -1188,7 +1261,9 @@ def is_central(self, certificate=False): if certificate: Ker = m.right_kernel() from sage.geometry.polyhedron.constructor import Polyhedron - return (True, Polyhedron(base_ring=R, vertices=[x], lines=Ker.basis())) + return (True, Polyhedron(base_ring=R, vertices=[x], + lines=Ker.basis(), + backend=self._backend)) else: return True @@ -1360,7 +1435,7 @@ def echelon_col_iter(row_iter): names = tuple(name for i, name in enumerate(parent._names) if i not in echelon_pivots) # Construct the result restricted_parent = HyperplaneArrangements(R, names=names) - return restricted_parent(*restricted, signed=False) + return restricted_parent(*restricted, signed=False, backend=self._backend) def sign_vector(self, p): r""" @@ -1573,24 +1648,28 @@ def _make_region(self, hyperplanes): sage: h = H(x) sage: h._make_region([x, 1-x, y, 1-y]) A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices + + TESTS: + + Checks that it creates the regions with the appropriate backend:: + + sage: h = H(x,backend='normaliz') + sage: h._make_region([x, 1-x, y, 1-y]).backend() + 'normaliz' """ ieqs = [h.dense_coefficient_list() for h in hyperplanes] from sage.geometry.polyhedron.constructor import Polyhedron return Polyhedron(ieqs=ieqs, ambient_dim=self.dimension(), - base_ring=self.parent().base_ring()) + base_ring=self.parent().base_ring(), + backend=self._backend) @cached_method - def regions(self,backend=None): + def regions(self): r""" Return the regions of the hyperplane arrangement. The base field must have characteristic zero. - INPUT: - - - ``backend`` -- string (optional; default: ``None``); the backend to - use for the polyhedra. - OUTPUT: A tuple containing the regions as polyhedra. @@ -1654,12 +1733,12 @@ def regions(self,backend=None): sage: norms = [[1,1/3*(-2*r9^2-r9+1),0],[1,-r9^2-r9,0], [1,-r9^2+1,0],[1,-r9^2,0],[1,r9^2-4,-r9^2+3]] sage: H. = HyperplaneArrangements(L) - sage: A = H() + sage: A = H(backend='normaliz') sage: for v in norms: ....: a,b,c = v ....: A = A.add_hyperplane(a*x + b*y + c*z) - sage: R = A.regions(backend='normaliz') # optional - pynormaliz - sage: R[0].backend() + sage: R = A.regions() # optional - pynormaliz + sage: R[0].backend() # optional - pynormaliz 'normaliz' TESTS:: @@ -1674,9 +1753,10 @@ def regions(self,backend=None): from sage.geometry.polyhedron.constructor import Polyhedron R = self.base_ring() dim = self.dimension() + be = self._backend universe = Polyhedron(eqns=[[0] + [0] * dim], base_ring=R, - backend=backend) + backend=be) regions = [universe] if self.is_linear() and self.n_hyperplanes(): # We only take the positive half w.r. to the first hyperplane. @@ -1685,8 +1765,8 @@ def regions(self,backend=None): for hyperplane in self: ieq = vector(R, hyperplane.dense_coefficient_list()) - pos_half = Polyhedron(ieqs=[ ieq], base_ring=R, backend=backend) - neg_half = Polyhedron(ieqs=[-ieq], base_ring=R, backend=backend) + pos_half = Polyhedron(ieqs=[ ieq], base_ring=R, backend=be) + neg_half = Polyhedron(ieqs=[-ieq], base_ring=R, backend=be) if not regions: # See comment above. regions = [pos_half] @@ -1741,7 +1821,7 @@ def regions(self,backend=None): return tuple(regions) @cached_method - def poset_of_regions(self, B=None, numbered_labels=True, backend=None): + def poset_of_regions(self, B=None, numbered_labels=True): r""" Return the poset of regions for a central hyperplane arrangement. @@ -1759,9 +1839,6 @@ def poset_of_regions(self, B=None, numbered_labels=True, backend=None): then the elements of the poset are numbered. Else they are labelled with the regions themselves. - - ``backend`` -- string (optional; default: ``None``); the backend to - use for the polyhedra. - OUTPUT: A Poset object containing the poset of regions. @@ -1788,20 +1865,10 @@ def poset_of_regions(self, B=None, numbered_labels=True, backend=None): sage: base_region = R[3] sage: A.poset_of_regions(B=base_region) Finite poset containing 14 elements - - It is possible to specify the backend:: - - sage: R = A.regions(backend='normaliz') # optional - pynormaliz - sage: base_region = R[3] # optional - pynormaliz - sage: PR = A.poset_of_regions(B=base_region, - numbered_labels=False, - backend='normaliz') # optional - pynormaliz - sage: PR.an_element().backend() # optional - pynormaliz - 'normaliz' """ # We use RX to keep track of indexes and R to keep track of which regions # we've already hit. This poset is graded, so we can go one set at a time - RX = self.regions(backend=backend) + RX = self.regions() R = set(RX) if B in R: R.discard(B) @@ -1837,7 +1904,6 @@ def poset_of_regions(self, B=None, numbered_labels=True, backend=None): else: return Poset([RX,edges]) - @cached_method def closed_faces(self, labelled=True): r""" @@ -2036,7 +2102,8 @@ def closed_faces(self, labelled=True): from sage.geometry.polyhedron.constructor import Polyhedron dim = self.dimension() hypes = self.hyperplanes() - universe = Polyhedron(eqns=[[0] + [0] * dim], base_ring=R) + be = self._backend + universe = Polyhedron(eqns=[[0] + [0] * dim], base_ring=R, backend=be) faces = [((), universe)] for k, hyperplane in enumerate(hypes): # Loop invariant: @@ -2044,11 +2111,11 @@ def closed_faces(self, labelled=True): # hyperplane arrangement given by the first ``k`` hyperplanes # in the list ``hypes`` (that is, by ``hypes[:k]``). ieq = vector(R, hyperplane.dense_coefficient_list()) - zero_half = Polyhedron(eqns=[ieq], base_ring=R) + zero_half = Polyhedron(eqns=[ieq], base_ring=R, backend=be) # ``zero_half`` is the hyperplane ``hyperplane`` itself # (viewed as a polyhedron). - pos_half = Polyhedron(ieqs=[ ieq], base_ring=R) - neg_half = Polyhedron(ieqs=[-ieq], base_ring=R) + pos_half = Polyhedron(ieqs=[ ieq], base_ring=R, backend=be) + neg_half = Polyhedron(ieqs=[-ieq], base_ring=R, backend=be) subdivided = [] for signs, face in faces: # So ``face`` is a face of the hyperplane arrangement @@ -2207,7 +2274,7 @@ def face_product(self, F, G, normalize=True): ieqs.append(-ieq) else: ieqs.append(ieq) - face = Polyhedron(eqns=eqns, ieqs=ieqs, base_ring=R) + face = Polyhedron(eqns=eqns, ieqs=ieqs, base_ring=R, backend=self._backend) if not normalize: return face # Look for ``I`` in ``self.closed_faces()``: @@ -2402,7 +2469,8 @@ def _bounded_region_indices(self): """ from sage.geometry.polyhedron.constructor import Polyhedron normal = Polyhedron(vertices=[[0]*self.dimension()], - lines=[hyperplane.normal() for hyperplane in self]) + lines=[hyperplane.normal() for hyperplane in self], + backend=self._backend) if normal.dim() == 0: transverse = lambda poly: poly else: @@ -3379,6 +3447,7 @@ def _element_constructor_(self, *args, **kwds): signed = kwds.pop('signed', not_char2) warn_duplicates = kwds.pop('warn_duplicates', False) check = kwds.pop('check', True) + backend = kwds.pop('backend', None) if len(kwds) > 0: raise ValueError('unknown keyword argument') # process positional arguments @@ -3408,7 +3477,7 @@ def _element_constructor_(self, *args, **kwds): raise ValueError('linear expression must be non-constant to define a hyperplane') if not_char2 and -h in hyperplanes: raise ValueError('arrangement cannot simultaneously have h and -h as hyperplane') - return self.element_class(self, tuple(sorted(hyperplanes))) + return self.element_class(self, tuple(sorted(hyperplanes)), backend=backend) @cached_method def ngens(self): From 7734ce902b4f5916075cd6627b597285dd10601f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Philippe=20Labb=C3=A9?= Date: Wed, 15 Jul 2020 15:32:53 +0200 Subject: [PATCH 103/217] Made test pass --- .../hyperplane_arrangement/arrangement.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index 83c8a7ce61c..3e700ca9445 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -66,11 +66,12 @@ Number fields are also possible:: - sage: NF. = NumberField(x^4 - 5*x^2 + 5,embedding=1.90) + sage: x = var('x') + sage: NF. = NumberField(x**4 - 5*x**2 + 5,embedding=1.90) sage: H. = HyperplaneArrangements(NF) - sage: A = H([[(-a^3 + 3*a, -a^2 + 4), 1], [(a^3 - 4*a, -1), 1], - ....: [(0, 2*a^2 - 6), 1], [(-a^3 + 4*a, -1), 1], - ....: [(a^3 - 3*a, -a^2 + 4), 1]]) + sage: A = H([[(-a**3 + 3*a, -a**2 + 4), 1], [(a**3 - 4*a, -1), 1], + ....: [(0, 2*a**2 - 6), 1], [(-a**3 + 4*a, -1), 1], + ....: [(a**3 - 3*a, -a**2 + 4), 1]]) sage: A Arrangement of 5 hyperplanes of dimension 2 and rank 2 sage: A.base_ring() @@ -1729,9 +1730,12 @@ def regions(self): It is possible to specify the backend:: sage: K. = CyclotomicField(9) - sage: L. = NumberField((q+q^(-1)).minpoly(),embedding = AA(q+q^-1)) - sage: norms = [[1,1/3*(-2*r9^2-r9+1),0],[1,-r9^2-r9,0], - [1,-r9^2+1,0],[1,-r9^2,0],[1,r9^2-4,-r9^2+3]] + sage: L. = NumberField((q+q**(-1)).minpoly(),embedding = AA(q+q**-1)) + sage: norms = [[1,1/3*(-2*r9**2-r9+1),0], \ + [1,-r9**2-r9,0], \ + [1,-r9**2+1,0], \ + [1,-r9**2,0], \ + [1,r9**2-4,-r9**2+3]] sage: H. = HyperplaneArrangements(L) sage: A = H(backend='normaliz') sage: for v in norms: From 49eed46afd9fb431cc666e99233ed0768d3b6e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Philippe=20Labb=C3=A9?= Date: Wed, 15 Jul 2020 15:36:21 +0200 Subject: [PATCH 104/217] pep8 --- .../hyperplane_arrangement/arrangement.py | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index 3e700ca9445..fad72747bcb 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -591,7 +591,7 @@ def backend(self): sage: H = HyperplaneArrangements(QQ) sage: A = H() - sage: A.backend() + sage: A.backend() Otherwise, one may specify a polyhedral backend:: @@ -738,7 +738,7 @@ def cone(self, variable='t'): P = self.parent() names = (variable,) + P._names H = HyperplaneArrangements(self.parent().base_ring(), names=names) - return H(*hyperplanes,backend=self._backend) + return H(*hyperplanes, backend=self._backend) @cached_method def intersection_poset(self): @@ -924,7 +924,7 @@ def deletion(self, hyperplanes): planes.remove(hyperplane) except ValueError: raise ValueError('hyperplane is not in the arrangement') - return parent(*planes,backend=self._backend) + return parent(*planes, backend=self._backend) def restriction(self, hyperplane): r""" @@ -1023,7 +1023,7 @@ def change_ring(self, base_ring): sage: A = H([(1,1), 0], [(2,3), -1]) sage: A.change_ring(FiniteField(2)) Arrangement - + TESTS: Checks that changing the ring preserves the backend:: @@ -1263,7 +1263,7 @@ def is_central(self, certificate=False): Ker = m.right_kernel() from sage.geometry.polyhedron.constructor import Polyhedron return (True, Polyhedron(base_ring=R, vertices=[x], - lines=Ker.basis(), + lines=Ker.basis(), backend=self._backend)) else: return True @@ -1341,7 +1341,6 @@ def is_simplicial(self): rank = self.rank() return all(R.n_facets() == rank for R in self.regions()) - @cached_method def essentialization(self): r""" @@ -1670,7 +1669,7 @@ def regions(self): Return the regions of the hyperplane arrangement. The base field must have characteristic zero. - + OUTPUT: A tuple containing the regions as polyhedra. @@ -1894,19 +1893,19 @@ def poset_of_regions(self, B=None, numbered_labels=True): for r in R: # Since it's graded, it suffices to look at the regions of the previous rank for b in curTest: - if self.distance_between_regions(b,r) == 1: + if self.distance_between_regions(b, r) == 1: nextTest.add(r) if numbered_labels: - edges.append([RX.index(b),RX.index(r)]) + edges.append([RX.index(b), RX.index(r)]) else: - edges.append([b,r]) + edges.append([b, r]) for x in nextTest: R.discard(x) if numbered_labels: - return Poset([range(len(RX)),edges]) + return Poset([range(len(RX)), edges]) else: - return Poset([RX,edges]) + return Poset([RX, edges]) @cached_method def closed_faces(self, labelled=True): @@ -2794,7 +2793,7 @@ def distance_enumerator(self, base_region): sage: c.distance_enumerator(c.region_containing_point([1,1,1])) x^3 + 3*x^2 + 3*x + 1 """ - d = [self.distance_between_regions(r,base_region) for r in self.regions()] + d = [self.distance_between_regions(r, base_region) for r in self.regions()] d = [d.count(i) for i in range(max(d)+1)] from sage.rings.polynomial.polynomial_ring import polygen x = polygen(QQ, 'x') @@ -2842,7 +2841,7 @@ def varchenko_matrix(self, names='h'): for j in range(i+1, k): t = prod(h[p] for p in range(k) if self.is_separating_hyperplane(region[i], region[j], self[p])) - v[i,j] = v[j,i] = t + v[i, j] = v[j, i] = t v.set_immutable() return v @@ -2985,7 +2984,7 @@ def minimal_generated_number(self): d = list(d) dep = V.linear_dependence([norms[j] for j in d]) w = W.zero().list() - for j,k in enumerate(d): + for j, k in enumerate(d): w[k] = dep[0][j] sol.append(w) mat = matrix(sol) @@ -3081,7 +3080,7 @@ def derivation_module_free_chain(self): from sage.geometry.hyperplane_arrangement.check_freeness import construct_free_chain return construct_free_chain(self) - @cached_method(key=lambda self,a: None) + @cached_method(key=lambda self, a: None) def is_free(self, algorithm="singular"): r""" Return if ``self`` is free. @@ -3216,14 +3215,14 @@ def derivation_module_basis(self, algorithm="singular"): """ alg = algorithm # prevent possible changes to a global variable if alg == "singular": - #import sage.libs.singular.function_factory - #syz = sage.libs.singular.function_factory.ff.syz + # import sage.libs.singular.function_factory + # syz = sage.libs.singular.function_factory.ff.syz f = self.defining_polynomial() I = f + f.jacobian_ideal() IS = I._singular_() ISS = IS.syz() MSTD = ISS.mstd() - basis = MSTD[2]._sage_().transpose().submatrix(0,1) + basis = MSTD[2]._sage_().transpose().submatrix(0, 1) try: det = basis.det() # Check using Saito's criterion @@ -3249,6 +3248,7 @@ def derivation_module_basis(self, algorithm="singular"): else: raise ValueError("invalid algorithm") + class HyperplaneArrangements(Parent, UniqueRepresentation): """ Hyperplane arrangements. @@ -3297,7 +3297,7 @@ def __init__(self, base_ring, names=tuple()): sage: TestSuite(K).run() """ from sage.categories.all import Fields, Sets - if not base_ring in Fields: + if base_ring not in Fields: raise ValueError('base ring must be a field') super(HyperplaneArrangements, self).__init__(category=Sets()) self._base_ring = base_ring @@ -3567,4 +3567,3 @@ def _coerce_map_from_(self, P): if isinstance(P, HyperplaneArrangements): return self.base_ring().has_coerce_map_from(P.base_ring()) return super(HyperplaneArrangements, self)._coerce_map_from_(P) - From a60814d1f9bdf2bd4199451ffc71039a406ccf48 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Wed, 15 Jul 2020 11:14:47 -0400 Subject: [PATCH 105/217] Trac #30135: remove obsolete comment from ./bootstrap script. Dima says: "we got rid of our autotools copy, so this comment makes no sense any more." --- bootstrap | 1 - 1 file changed, 1 deletion(-) diff --git a/bootstrap b/bootstrap index a4cd01305bc..6b0edbec21a 100755 --- a/bootstrap +++ b/bootstrap @@ -203,7 +203,6 @@ fi $MAKE bootstrap-clean 2>/dev/null mkdir config 2>/dev/null -# Get autotools from our own package into PATH (Trac #21214). # If Sage has not been built yet, this will fail due to a missing # sage-env-config. We just ignore that error. source src/bin/sage-env-config 2>/dev/null From 68bfa4bc65a7d073e80e08b5d57ab64091c6cf73 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Jul 2020 08:57:49 -0700 Subject: [PATCH 106/217] build/pkgs/scons: Remove --- build/pkgs/scons/SPKG.rst | 30 ---------------------------- build/pkgs/scons/checksums.ini | 4 ---- build/pkgs/scons/dependencies | 5 ----- build/pkgs/scons/package-version.txt | 1 - build/pkgs/scons/spkg-install.in | 11 ---------- build/pkgs/scons/type | 1 - 6 files changed, 52 deletions(-) delete mode 100644 build/pkgs/scons/SPKG.rst delete mode 100644 build/pkgs/scons/checksums.ini delete mode 100644 build/pkgs/scons/dependencies delete mode 100644 build/pkgs/scons/package-version.txt delete mode 100644 build/pkgs/scons/spkg-install.in delete mode 100644 build/pkgs/scons/type diff --git a/build/pkgs/scons/SPKG.rst b/build/pkgs/scons/SPKG.rst deleted file mode 100644 index 2a3822517f8..00000000000 --- a/build/pkgs/scons/SPKG.rst +++ /dev/null @@ -1,30 +0,0 @@ -SCons -===== - -Description ------------ - -SCons is an Open Source software construction tool—that is, a -next-generation build tool. Think of SCons as an improved, -cross-platform substitute for the classic Make utility with integrated -functionality similar to autoconf/automake and compiler caches such as -ccache. In short, SCons is an easier, more reliable and faster way to -build software. - -Website: http://www.scons.org/ - -License -------- - -X/MIT - - -Upstream Contact ----------------- - -- SCons mailing lists - see http://www.scons.org/lists.php - -Dependencies ------------- - -- Python diff --git a/build/pkgs/scons/checksums.ini b/build/pkgs/scons/checksums.ini deleted file mode 100644 index b562e0d8cfc..00000000000 --- a/build/pkgs/scons/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=scons-VERSION.tar.bz2 -sha1=f64373026891502f0ba328504d3126a58e9ec2de -md5=2d9988b88d18a6ed105da3a5838283d4 -cksum=4171645742 diff --git a/build/pkgs/scons/dependencies b/build/pkgs/scons/dependencies deleted file mode 100644 index 304d0c987a2..00000000000 --- a/build/pkgs/scons/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) - ----------- -All lines of this file are ignored except the first. -It is copied by SAGE_ROOT/build/make/install into SAGE_ROOT/build/make/Makefile. diff --git a/build/pkgs/scons/package-version.txt b/build/pkgs/scons/package-version.txt deleted file mode 100644 index 26aaba0e866..00000000000 --- a/build/pkgs/scons/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.2.0 diff --git a/build/pkgs/scons/spkg-install.in b/build/pkgs/scons/spkg-install.in deleted file mode 100644 index 663ebd71bbf..00000000000 --- a/build/pkgs/scons/spkg-install.in +++ /dev/null @@ -1,11 +0,0 @@ -cd src - -rm -rf $SAGE_LOCAL/lib/scons-* - -# scons does not work with pip -sage-python23 setup.py --no-user-cfg install - -if [ $? -ne 0 ]; then - echo "Error installing scons" - exit 1 -fi diff --git a/build/pkgs/scons/type b/build/pkgs/scons/type deleted file mode 100644 index 9839eb20815..00000000000 --- a/build/pkgs/scons/type +++ /dev/null @@ -1 +0,0 @@ -experimental From f7213c57463ab5af8441cd8410d26cca6ef95d2f Mon Sep 17 00:00:00 2001 From: "E. Madison Bray" Date: Thu, 16 Jul 2020 18:50:47 +0200 Subject: [PATCH 107/217] Trac #30149: When creating the Python venv on Cygwin make sure to copy the python executable instead of creating symlinks --- build/bin/sage-venv | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/bin/sage-venv b/build/bin/sage-venv index 46c81889318..9ee9fc794be 100755 --- a/build/bin/sage-venv +++ b/build/bin/sage-venv @@ -4,7 +4,7 @@ # Adapted from examples in https://docs.python.org/3/library/venv.html import venv -import os +import sys import argparse parser = argparse.ArgumentParser(prog=__name__, @@ -37,8 +37,8 @@ options = parser.parse_args() if options.upgrade and options.clear: raise ValueError('you cannot supply --upgrade and --clear together.') -if os.name == 'nt': - # default for Windows +if sys.platform == 'cygwin': + # default for Cygwin; see https://trac.sagemath.org/ticket/30149 use_symlinks = False else: # default for posix From 41a3e6634640ac6fd67de69045d6787bdbcee22b Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Thu, 16 Jul 2020 10:12:24 -0700 Subject: [PATCH 108/217] trac 30155: remove "sage --scons", remove scons info from COPYING.txt --- COPYING.txt | 1 - src/bin/sage | 6 ------ 2 files changed, 7 deletions(-) diff --git a/COPYING.txt b/COPYING.txt index 9a223312b7d..c85f5b35b87 100644 --- a/COPYING.txt +++ b/COPYING.txt @@ -121,7 +121,6 @@ sage_scripts GPLv2+ sagenb GPLv3 sagetex GPLv2+ (CC BY-SA 3.0 for included documentation) scipy Modified BSD -scons MIT License setuptools Python License singular GPLv2 or GPLv3 (see below) six MIT License diff --git a/src/bin/sage b/src/bin/sage index b4786bf3aae..92d80bb0b8c 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -339,7 +339,6 @@ usage_advanced() { echo " --python [...], --python3 [...]" echo " -- run the Python 3 interpreter" echo " -R [...] -- run Sage's R with the given arguments" - echo " --scons [...] -- run Sage's scons" echo " --singular [...] -- run Sage's singular with the given arguments" echo " --sqlite3 [...] -- run Sage's sqlite3 with given arguments" echo @@ -611,11 +610,6 @@ if [ "$1" = '-M2' -o "$1" = '--M2' ]; then exec M2 "$@" fi -if [ "$1" = '-scons' -o "$1" = '--scons' ]; then - shift - exec scons "$@" -fi - if [ "$1" = '-R' -o "$1" = '--R' ]; then shift exec R "$@" From 5f93e7f059fcbfa3eecf1dd22112fb647498a506 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Jul 2020 10:21:43 -0700 Subject: [PATCH 109/217] build/pkgs/pytz: Update to 2020.1 --- build/pkgs/pytz/checksums.ini | 9 +++++---- build/pkgs/pytz/package-version.txt | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/build/pkgs/pytz/checksums.ini b/build/pkgs/pytz/checksums.ini index 08b15bb59c5..d4db734e428 100644 --- a/build/pkgs/pytz/checksums.ini +++ b/build/pkgs/pytz/checksums.ini @@ -1,4 +1,5 @@ -tarball=pytz-VERSION.tar.bz2 -sha1=8a01d7f19c8b8b189827e026b76c51be4b537b89 -md5=4b91594c440aa20c76ac92043efa75e1 -cksum=591864951 +tarball=pytz-VERSION.tar.gz +sha1=60f6db35e92688c4701c16bd3d2b9cbfac1fd604 +md5=0349106ac02f2bfe565dd6d5594e3a15 +cksum=1599443821 +upstream_url=https://pypi.io/packages/source/p/pytz/pytz-VERSION.tar.gz diff --git a/build/pkgs/pytz/package-version.txt b/build/pkgs/pytz/package-version.txt index b3d91a9d2f9..b0a4aa2fe24 100644 --- a/build/pkgs/pytz/package-version.txt +++ b/build/pkgs/pytz/package-version.txt @@ -1 +1 @@ -2018.7 +2020.1 From 091ed905e020537a18ff6f7c1251c87253537a0d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Jul 2020 10:26:55 -0700 Subject: [PATCH 110/217] build/pkgs/tzlocal: Make it a normal, standard package (new dep of standard package rpy2) --- build/pkgs/tzlocal/SPKG.rst | 16 ++++++++++++++++ build/pkgs/tzlocal/checksums.ini | 5 +++++ build/pkgs/tzlocal/dependencies | 5 +++++ build/pkgs/tzlocal/package-version.txt | 1 + build/pkgs/tzlocal/requirements.txt | 1 - build/pkgs/tzlocal/spkg-install.in | 1 + build/pkgs/tzlocal/type | 2 +- 7 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 build/pkgs/tzlocal/SPKG.rst create mode 100644 build/pkgs/tzlocal/checksums.ini create mode 100644 build/pkgs/tzlocal/dependencies create mode 100644 build/pkgs/tzlocal/package-version.txt delete mode 100644 build/pkgs/tzlocal/requirements.txt create mode 100644 build/pkgs/tzlocal/spkg-install.in diff --git a/build/pkgs/tzlocal/SPKG.rst b/build/pkgs/tzlocal/SPKG.rst new file mode 100644 index 00000000000..ebeba1ad914 --- /dev/null +++ b/build/pkgs/tzlocal/SPKG.rst @@ -0,0 +1,16 @@ +pytz +==== + +Description +----------- + +World Timezone Definitions for Python + + +Special Update/Build Instructions +--------------------------------- + +The upstream tarball was repackaged after sanitizing the file +permissions with + +$ chmod go-w diff --git a/build/pkgs/tzlocal/checksums.ini b/build/pkgs/tzlocal/checksums.ini new file mode 100644 index 00000000000..d595a9d3d16 --- /dev/null +++ b/build/pkgs/tzlocal/checksums.ini @@ -0,0 +1,5 @@ +tarball=tzlocal-VERSION.tar.gz +sha1=7d2d590f68849e6b6371210bd808b40ec5619faf +md5=c0877603ff9de71cd8ca6ee2b50d2ebd +cksum=950088034 +upstream_url=https://pypi.io/packages/source/t/tzlocal/tzlocal-VERSION.tar.gz diff --git a/build/pkgs/tzlocal/dependencies b/build/pkgs/tzlocal/dependencies new file mode 100644 index 00000000000..15df0c4d6d8 --- /dev/null +++ b/build/pkgs/tzlocal/dependencies @@ -0,0 +1,5 @@ +$(PYTHON) | $(PYTHON_TOOLCHAIN) + +---------- +All lines of this file are ignored except the first. +It is copied by SAGE_ROOT/build/make/install into SAGE_ROOT/build/make/Makefile. diff --git a/build/pkgs/tzlocal/package-version.txt b/build/pkgs/tzlocal/package-version.txt new file mode 100644 index 00000000000..879b416e609 --- /dev/null +++ b/build/pkgs/tzlocal/package-version.txt @@ -0,0 +1 @@ +2.1 diff --git a/build/pkgs/tzlocal/requirements.txt b/build/pkgs/tzlocal/requirements.txt deleted file mode 100644 index cd5e9b12a4b..00000000000 --- a/build/pkgs/tzlocal/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -tzlocal diff --git a/build/pkgs/tzlocal/spkg-install.in b/build/pkgs/tzlocal/spkg-install.in new file mode 100644 index 00000000000..deba1bb42bb --- /dev/null +++ b/build/pkgs/tzlocal/spkg-install.in @@ -0,0 +1 @@ +cd src && sdh_pip_install . diff --git a/build/pkgs/tzlocal/type b/build/pkgs/tzlocal/type index 134d9bc32d5..a6a7b9cd726 100644 --- a/build/pkgs/tzlocal/type +++ b/build/pkgs/tzlocal/type @@ -1 +1 @@ -optional +standard From b01e92dd86b042c17d2bb17d44354d60bef861ab Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Jul 2020 10:28:11 -0700 Subject: [PATCH 111/217] build/pkgs/rpy2/dependencies: Add tzlocal pytz as normal dependencies --- build/pkgs/rpy2/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/rpy2/dependencies b/build/pkgs/rpy2/dependencies index 4e37a7ddf02..215375ee02d 100644 --- a/build/pkgs/rpy2/dependencies +++ b/build/pkgs/rpy2/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) r cffi | $(PYTHON_TOOLCHAIN) pycparser $(and $(filter-out no,$(SAGE_CHECK_rpy2)), pytest tzlocal numpy) +$(PYTHON) r cffi tzlocal pytz | $(PYTHON_TOOLCHAIN) pycparser $(and $(filter-out no,$(SAGE_CHECK_rpy2)), pytest numpy) ---------- All lines of this file are ignored except the first. From 4ce897074e0570143ec4642a91bf2d846f313635 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Jul 2020 10:49:41 -0700 Subject: [PATCH 112/217] build/pkgs/rpy2: Update to 3.3.5 --- build/pkgs/rpy2/checksums.ini | 6 +++--- build/pkgs/rpy2/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/rpy2/checksums.ini b/build/pkgs/rpy2/checksums.ini index 6cb4be003c2..9b7f0ea2ec3 100644 --- a/build/pkgs/rpy2/checksums.ini +++ b/build/pkgs/rpy2/checksums.ini @@ -1,5 +1,5 @@ tarball=rpy2-VERSION.tar.gz -sha1=64762fe2abe3a6469975ff86187396f8339f85e4 -md5=da70a5c4e35e22c469c37444d45257ee -cksum=2800144752 +sha1=af1c7ffe900233ac5add5195f106299bd72fd575 +md5=8a5db07798763b9c6672b5f80451b944 +cksum=828149660 upstream_url=https://pypi.io/packages/source/r/rpy2/rpy2-VERSION.tar.gz diff --git a/build/pkgs/rpy2/package-version.txt b/build/pkgs/rpy2/package-version.txt index a0891f563f3..fa7adc7ac72 100644 --- a/build/pkgs/rpy2/package-version.txt +++ b/build/pkgs/rpy2/package-version.txt @@ -1 +1 @@ -3.3.4 +3.3.5 From 628e7d01166f21f480b0ae22361b9a29c4d854ef Mon Sep 17 00:00:00 2001 From: "E. Madison Bray" Date: Thu, 16 Jul 2020 20:46:07 +0200 Subject: [PATCH 113/217] Trac #30157: Undo sqlite3's munging of DLL search paths Includes a Cython function specifically targeted to fixing the sqlite3 issue, and adds a monkey-patching at sage import time which wraps sqlite3.connect (the first place where the issue that causes this is invoked) to call the workaround function. --- src/module_list.py | 7 +++- src/sage/__init__.py | 38 +++++++++++++++++++ src/sage/misc/sage_ostools.pyx | 41 +++++++++++++++++++++ src/sage_setup/command/sage_build_cython.py | 1 + 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/module_list.py b/src/module_list.py index eee34f58369..7a3d75e7b27 100644 --- a/src/module_list.py +++ b/src/module_list.py @@ -655,6 +655,9 @@ ################################ Extension('*', ['sage/misc/*.pyx']), + Extension('sage.misc.sage_ostools', + sources = ['sage/misc/sage_ostools.pyx'], + libraries = ['sqlite3']), ################################ ## @@ -1120,10 +1123,10 @@ Extension('sage.rings.polynomial.ore_polynomial_element', sources = ['sage/rings/polynomial/ore_polynomial_element.pyx']), - + Extension('sage.rings.polynomial.skew_polynomial_element', sources = ['sage/rings/polynomial/skew_polynomial_element.pyx']), - + Extension('sage.rings.polynomial.skew_polynomial_finite_order', sources = ['sage/rings/polynomial/skew_polynomial_finite_order.pyx']), diff --git a/src/sage/__init__.py b/src/sage/__init__.py index e2ae5b8cebc..5be0bace31a 100644 --- a/src/sage/__init__.py +++ b/src/sage/__init__.py @@ -4,6 +4,7 @@ # to many other Python packages. from sage.version import version as __version__ +import sys # Make sure that the correct zlib library is loaded. This is needed # to prevent the system zlib to be loaded instead of the Sage one. # See https://trac.sagemath.org/ticket/23122 @@ -66,3 +67,40 @@ def isfunction(obj): pass # Python 2 else: del ExtensionFileLoader.get_source + + +# Work around a Cygwin-specific bug caused by sqlite3; see +# https://trac.sagemath.org/ticket/30157 and the docstring for +# fix_for_ticket_30157 +# Here we monkey-patch the sqlite3 module to ensure the fix is +# applied the very first time a connection is made to a sqlite3 +# database +if sys.platform == 'cygwin': + def patch_sqlite3(): + try: + from sage.misc.sage_ostools import fix_for_ticket_30157 + except ImportError: + # The module might not have been re-built yet; don't worry about it + # then + return + + import sqlite3, functools + orig_sqlite3_connect = sqlite3.connect + + @functools.wraps(orig_sqlite3_connect) + def connect(*args, **kwargs): + if fix_for_ticket_30157(): + raise RuntimeError( + 'patch for Trac ticket #30157 failed; please report this ' + 'bug to https://trac.sagemath.org') + + # Undo the monkey-patch + try: + return orig_sqlite3_connect(*args, **kwargs) + finally: + sqlite3.connect = orig_sqlite3_connect + + sqlite3.connect = connect + + patch_sqlite3() + del patch_sqlite3 diff --git a/src/sage/misc/sage_ostools.pyx b/src/sage/misc/sage_ostools.pyx index 75b0d7a8a0d..37fd4cf18b8 100644 --- a/src/sage/misc/sage_ostools.pyx +++ b/src/sage/misc/sage_ostools.pyx @@ -8,6 +8,7 @@ from cpython.exc cimport PyErr_SetFromErrno import os import contextlib + def have_program(program, path=None): """ Return ``True`` if a ``program`` executable is found in the path @@ -302,3 +303,43 @@ cdef class redirection: if self.close_dest: self.dest_file.close() self.dest_fd = -1 + + +IF PY_PLATFORM == 'cygwin': + from libc.stddef cimport wchar_t + + cdef extern from "Windows.h": + int SetDllDirectoryW(wchar_t* lpPathName) + + cdef extern from "sqlite3.h": + int sqlite3_initialize() + + def fix_for_ticket_30157(): + """ + Cygwin-only workaround for an issue caused by the sqlite3 library. See + trac:`30157`. + + The issue here is that when the sqlite3 library is first initialized + it modifies Windows' default DLL search path order, which can possibly + break the correct search path for subsequent DLL loads. + + This workaround ensures that the sqlite3 library is initialized very + early on (this does not add any significant overhead) and then + immediately undoes its deleterious effects. In particular, calling + SetDllDirectoryW(NULL) restores the default DLL search path. + + To be clear, there's no reason sqlite3 needs this to function + correctly; it's just a poorly-considered hack that attempted to work + around a problem that doesn't affect us. + + Returns 0 if it succeeeds or a non-zero value if not. + """ + + ret = sqlite3_initialize() + + if ret != 0: + # Library initialization failed for some reason + return ret + + # SetDllDirectory returns 1 if it succeeds. + return not SetDllDirectoryW(NULL) diff --git a/src/sage_setup/command/sage_build_cython.py b/src/sage_setup/command/sage_build_cython.py index bf9bf976a37..3faeaf0790b 100644 --- a/src/sage_setup/command/sage_build_cython.py +++ b/src/sage_setup/command/sage_build_cython.py @@ -163,6 +163,7 @@ def finalize_options(self): self.compile_time_env = dict( PY_VERSION_HEX=sys.hexversion, PY_MAJOR_VERSION=sys.version_info[0], + PY_PLATFORM=sys.platform ) # We check the Cython version and some relevant configuration From 7a91c05926de5ec62d306c6955c989dec02788e4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Jul 2020 12:29:28 -0700 Subject: [PATCH 114/217] build/make/Makefile.in: Add target SPKG-no-deps for all SPKGs --- build/make/Makefile.in | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/build/make/Makefile.in b/build/make/Makefile.in index f9c3786d842..05a9a530cce 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -427,6 +427,11 @@ $$(INST)/$(1)-$(2): $(3) $(1): $$(INST)/$(1)-$(2) +$(1)-no-deps: + +$(AM_V_at)sage-logger -p '$$(SAGE_SPKG) $$(SAGE_SPKG_OPTIONS) \ + $(if $(filter $(1),$(TOOLCHAIN_DEPS)),--keep-existing) \ + $(1)-$(2)' '$$(SAGE_LOGS)/$(1)-$(2).log' + $(1)-clean: sage-spkg-uninstall $(if $(filter $(1),$(TOOLCHAIN_DEPS)),--keep-files) \ $(1) '$(SAGE_LOCAL)' @@ -464,6 +469,9 @@ $(1)-build-deps: $(2) $(1): $(2) $(AM_V_at)sage-logger -p 'sage --pip install -r "$$(SAGE_ROOT)/build/pkgs/$(1)/requirements.txt"' '$$(SAGE_LOGS)/$(1).log' +$(1)-no-deps: + $(AM_V_at)sage-logger -p 'sage --pip install -r "$$(SAGE_ROOT)/build/pkgs/$(1)/requirements.txt"' '$$(SAGE_LOGS)/$(1).log' + $(1)-clean: -sage --pip uninstall -y -r '$$(SAGE_ROOT)/build/pkgs/$(1)/requirements.txt' @@ -514,6 +522,12 @@ $$(INST)/$(1)-$(2): $(3) $(1): $$(INST)/$(1)-$(2) +$(1)-no-deps: + $(AM_V_at)cd '$$(SAGE_ROOT)/build/pkgs/$(1)' && \ + . '$$(SAGE_ROOT)/src/bin/sage-env' && . '$$(SAGE_ROOT)/build/bin/sage-build-env-config' && \ + sage-logger -p '$$(SAGE_ROOT)/build/pkgs/$(1)/spkg-install' '$$(SAGE_LOGS)/$(1)-$(2).log' + touch "$$@" + $(1)-uninstall: -$(AM_V_at)cd '$$(SAGE_ROOT)/build/pkgs/$(1)' && \ . '$$(SAGE_ROOT)/src/bin/sage-env-config' && \ From 4fc909c5143bf2b690ee1d22fd56a3c79db4ec23 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Jul 2020 12:30:23 -0700 Subject: [PATCH 115/217] src/bin/sage: Repair ./sage -b etc. by using make sagelib-clean, make sagelib-no-deps --- src/bin/sage | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/sage b/src/bin/sage index 439691a4910..12839635771 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -803,7 +803,7 @@ fi build_sage() { maybe_sage_location - ( cd "$SAGE_SRC" && $MAKE ) || exit $? + ( cd "$SAGE_ROOT/build/make" && $MAKE sagelib-no-deps ) || exit $? } if [[ "$1" =~ ^--notebook=.* || "$1" =~ ^-n=.* || "$1" =~ ^-notebook=.* ]] ; then @@ -855,7 +855,7 @@ if [ "$1" = '-r' ]; then fi if [ "$1" = '-ba' -o "$1" = '-ba-force' -o "$1" = '--ba-force' ]; then - ( cd "$SAGE_SRC" && make clean ) + ( cd "$SAGE_ROOT/build/make" && make sagelib-clean ) build_sage exit $? fi From 03a2dbee520f08a0d3aa090239ee2cf04d36334c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Jul 2020 13:25:26 -0700 Subject: [PATCH 116/217] build/make/Makefile.in: Make SPKG-no-deps targets phony; for script packages, create the correct installation stamp file --- build/make/Makefile.in | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/build/make/Makefile.in b/build/make/Makefile.in index 05a9a530cce..6abc09e745b 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -436,7 +436,7 @@ $(1)-clean: sage-spkg-uninstall $(if $(filter $(1),$(TOOLCHAIN_DEPS)),--keep-files) \ $(1) '$(SAGE_LOCAL)' -.PHONY: $(1) $(1)-clean $(1)-build-deps +.PHONY: $(1) $(1)-clean $(1)-build-deps $(1)-no-deps endef $(foreach pkgname, $(NORMAL_PACKAGES),\ @@ -475,7 +475,7 @@ $(1)-no-deps: $(1)-clean: -sage --pip uninstall -y -r '$$(SAGE_ROOT)/build/pkgs/$(1)/requirements.txt' -.PHONY: $(1) $(1)-clean $(1)-build-deps +.PHONY: $(1) $(1)-clean $(1)-build-deps $(1)-no-deps $(1)-clean endef $(foreach pkgname,$(PIP_PACKAGES),\ @@ -526,7 +526,7 @@ $(1)-no-deps: $(AM_V_at)cd '$$(SAGE_ROOT)/build/pkgs/$(1)' && \ . '$$(SAGE_ROOT)/src/bin/sage-env' && . '$$(SAGE_ROOT)/build/bin/sage-build-env-config' && \ sage-logger -p '$$(SAGE_ROOT)/build/pkgs/$(1)/spkg-install' '$$(SAGE_LOGS)/$(1)-$(2).log' - touch "$$@" + touch "$$(INST)/$(1)-$(2)" $(1)-uninstall: -$(AM_V_at)cd '$$(SAGE_ROOT)/build/pkgs/$(1)' && \ @@ -536,7 +536,7 @@ $(1)-uninstall: '$$(SAGE_ROOT)/build/pkgs/$(1)/spkg-uninstall' -rm -f "$$(INST)/$(1)-$(2)" -.PHONY: $(1) $(1)-uninstall $(1)-build-deps +.PHONY: $(1) $(1)-uninstall $(1)-build-deps $(1)-no-deps $(1)-clean endef $(foreach pkgname,$(SCRIPT_PACKAGES),\ @@ -559,7 +559,4 @@ list: done -.PHONY: $(NORMAL_PACKAGES) $(addsuffix -clean,$(NORMAL_PACKAGES)) \ - $(PIP_PACKAGES) $(addsuffix -clean,$(PIP_PACKAGES)) \ - $(SCRIPT_PACKAGES) $(addsuffix -clean,$(SCRIPT_PACKAGES)) \ - list +.PHONY: list From 62ddd0290f29776898dfb6ced584a9ae24f6a69b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Jul 2020 13:26:46 -0700 Subject: [PATCH 117/217] build/make/Makefile.in [SPKG-no-deps]: Do not forget to source sage-env-config --- build/make/Makefile.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build/make/Makefile.in b/build/make/Makefile.in index 6abc09e745b..55c667dfaf1 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -524,7 +524,9 @@ $(1): $$(INST)/$(1)-$(2) $(1)-no-deps: $(AM_V_at)cd '$$(SAGE_ROOT)/build/pkgs/$(1)' && \ - . '$$(SAGE_ROOT)/src/bin/sage-env' && . '$$(SAGE_ROOT)/build/bin/sage-build-env-config' && \ + . '$$(SAGE_ROOT)/src/bin/sage-env-config' && \ + . '$$(SAGE_ROOT)/src/bin/sage-env' && \ + . '$$(SAGE_ROOT)/build/bin/sage-build-env-config' && \ sage-logger -p '$$(SAGE_ROOT)/build/pkgs/$(1)/spkg-install' '$$(SAGE_LOGS)/$(1)-$(2).log' touch "$$(INST)/$(1)-$(2)" From 830843beb72ac0f9841fa32509fda3d744167528 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Thu, 16 Jul 2020 15:06:02 -0700 Subject: [PATCH 118/217] trac 30153: add, clarify some comments --- build/make/Makefile.in | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/build/make/Makefile.in b/build/make/Makefile.in index 55c667dfaf1..92afb2bd362 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -119,7 +119,7 @@ SCRIPT_PACKAGES = @SAGE_SCRIPT_PACKAGES@ # # For example: # -# inst_python2 = $(INST)/python2-$(vers_python2) +# inst_python3 = $(INST)/python3-$(vers_python3) # # inst_git = $(INST)/.dummy @@ -360,11 +360,11 @@ _clean-broken-gcc: # Define a function for generating the list of a package's dependencies # as $(inst_) variables. For example, takes: # -# deps_cysignals = python2 cython pari | pip +# deps_cysignals = python3 cython pari | pip # # to: # -# $(inst_python2) $(inst_cython) $(inst_pari) | $(inst_pip) +# $(inst_python3) $(inst_cython) $(inst_pari) | $(inst_pip) # # If some value in the dependencies list is not a package name (e.g. it is # the name of some arbitrary file, or it is the '|' symbol) then it is just @@ -382,25 +382,35 @@ pkg_deps = \ # ============================= normal packages ============================== # Generate build rules for 'normal' packages; this template is used to generate -# three rules in the form: +# rules in the form: # # $(INST)/-: # +$(AM_V_at)sage-logger -p '$(SAGE_SPKG) -' '$(SAGE_LOGS)/-.log' # # : $(INST)/- # +# -build-deps: +# +# -no-deps: +# +$(AM_V_at)sage-logger -p '$(SAGE_SPKG) -' '$(SAGE_LOGS)/-.log' +# # -clean: # sage-spkg-uninstall '$(SAGE_LOCAL)' # -# For example, for python2 this will expand to: +# So -build-deps installs just the dependencies, while +# -no-deps tries to install the package without its +# dependencies. This is currently used in SAGE_SRC/bin/sage when +# running 'sage -b' to build the Sage library. +# +# For example, for python3 this will expand to: # -# $(INST)/python2-2.7.14: $(inst_zlib) $(inst_readline) $(inst_sqlite) $(inst_libpng) $(inst_bzip2) -# +$(AM_V_at)sage-logger -p '$(SAGE_SPKG) python2-2.7.14' '$(SAGE_LOGS)/python2-2.7.14.log' +# $(INST)/python3-3.7.3: $(inst_zlib) $(inst_readline) $(inst_sqlite) $(inst_libpng) $(inst_bzip2) $(inst_xz) $(inst_libffi) +# +$(AM_V_at)sage-logger -p '$(SAGE_SPKG) python3-3.7.3' '$(SAGE_LOGS)/python3-3.7.3.log' # -# python2: $(INST)/python2-2.7.14 +# python3: $(INST)/python3-3.7.3 # -# python2-clean: -# sage-spkg-uninstall python2 '$(SAGE_LOCAL)' +# python3-clean: +# sage-spkg-uninstall python3 '$(SAGE_LOCAL)' # # Note: In these rules the $(INST)/- target is used # explicitly, rather than expanding the $(inst_) variable, since @@ -475,7 +485,7 @@ $(1)-no-deps: $(1)-clean: -sage --pip uninstall -y -r '$$(SAGE_ROOT)/build/pkgs/$(1)/requirements.txt' -.PHONY: $(1) $(1)-clean $(1)-build-deps $(1)-no-deps $(1)-clean +.PHONY: $(1) $(1)-clean $(1)-build-deps $(1)-no-deps endef $(foreach pkgname,$(PIP_PACKAGES),\ From 6ba54fb141b9151bcaa5bb3c837faf5f9dc1d7c9 Mon Sep 17 00:00:00 2001 From: Stefan Grosser Date: Thu, 16 Jul 2020 18:08:14 -0400 Subject: [PATCH 119/217] adjusted references, made d-complete a subclass of join semilattice, added tests for cardinality, add documentation for ``dual`` in YoungDiagramPoset example --- src/doc/en/reference/combinat/module_list.rst | 1 + src/doc/en/reference/references/index.rst | 7 +- src/sage/combinat/posets/__init__.py | 1 + src/sage/combinat/posets/d_complete.py | 81 +++---------------- src/sage/combinat/posets/forest.py | 8 +- src/sage/combinat/posets/hasse_diagram.py | 3 +- src/sage/combinat/posets/lattices.py | 10 +-- src/sage/combinat/posets/linear_extensions.py | 28 +++++-- src/sage/combinat/posets/mobile.py | 32 ++++++++ src/sage/combinat/posets/poset_examples.py | 2 + src/sage/combinat/posets/posets.py | 31 +++---- 11 files changed, 89 insertions(+), 115 deletions(-) create mode 100644 src/sage/combinat/posets/mobile.py diff --git a/src/doc/en/reference/combinat/module_list.rst b/src/doc/en/reference/combinat/module_list.rst index 4cf75e02f29..d121084f532 100644 --- a/src/doc/en/reference/combinat/module_list.rst +++ b/src/doc/en/reference/combinat/module_list.rst @@ -194,6 +194,7 @@ Comprehensive Module list sage/combinat/posets/poset_examples sage/combinat/posets/posets sage/combinat/posets/d_complete + sage/combinat/posets/forest sage/combinat/q_analogues sage/combinat/q_bernoulli sage/combinat/quickref diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index a1896ddd344..be1fa60526b 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -2632,9 +2632,6 @@ REFERENCES: Algebras, J. Ramanujan Math. Soc., 25 (2010), 113--145. :arxiv:`0309168v3` :mathscinet:`MR2642451` -.. [HLF] :wikipedia:`Hook_length_formula`, accessed 27th - June 2020. - .. [HL1999] \L. Heath and N. Loehr (1999). New algorithms for generating Conway polynomials over finite fields. Proceedings of the tenth annual ACM-SIAM symposium on @@ -3391,7 +3388,7 @@ REFERENCES: CMS Conf. Proc., **24**, Amer. Math. Soc., Providence, RI, 1998. :mathscinet:`MR1648638` -.. [KY2019] Kim, Jang Soo, and Meesue Yoo. +.. [KY2019] Jang Soo Kim, Meesue Yoo. "Hook length property of d-complete posets via q-integrals." Journal of Combinatorial Theory, Series A 162 (2019): 167-221. @@ -4348,7 +4345,7 @@ REFERENCES: Providence, RI, 2013. :arxiv:`1112.6163` -.. [Proc1999] R. A. Proctor. Minuscule elements of Weyl groups, the numbers game, +.. [Proc1999] R. A. Proctor, Minuscule elements of Weyl groups, the numbers game, and d-complete posets. J. Algebra, 213(1):272–303, 1999. .. [PDynk1999] R. A. Proctor. Dynkin diagram classification of λ-minuscule Bruhat lattices diff --git a/src/sage/combinat/posets/__init__.py b/src/sage/combinat/posets/__init__.py index b357f796b8f..fbf11e9efb9 100644 --- a/src/sage/combinat/posets/__init__.py +++ b/src/sage/combinat/posets/__init__.py @@ -13,6 +13,7 @@ - :ref:`sage.combinat.posets.linear_extensions` - :ref:`sage.combinat.posets.d_complete` +- :ref:`sage.combinat.posets.forest` - :ref:`sage.combinat.posets.incidence_algebras` - :ref:`sage.combinat.posets.cartesian_product` diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index 2bc3be202e4..af949255824 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -11,13 +11,15 @@ from sage.combinat.posets.posets import Poset, FinitePoset from sage.misc.lazy_attribute import lazy_attribute from .linear_extensions import LinearExtensionsOfPosetWithHooks +from .lattices import FiniteJoinSemilattice +from collections import deque -class DCompletePoset(FinitePoset): +class DCompletePoset(FiniteJoinSemilattice): r""" D-complete posets are a class of posets introduced by Proctor in [Proc1999]. It includes common families such as shapes, shifted shapes, and rooted forests. Proctor showed in [PDynk1999] that d-complete posets have decompositions in ``irreducible`` posets, and showed in [Proc2014] that - d-complete posets admit a hook-length formula (see [HLF]). A complete proof of the hook-length formula + d-complete posets admit a hook-length formula (see [1]). A complete proof of the hook-length formula can be found in [KY2019]. EXAMPLES:: @@ -39,27 +41,15 @@ class DCompletePoset(FinitePoset): sage: TestSuite(P).run() See also the other tests in the class documentation. + + REFERENCES:: + + .. [1] :wikipedia:`Hook_length_formula`, accessed 27th + June 2020. """ - def __init__(self, hasse_diagram, elements, category, facade, key): - FinitePoset.__init__(self, hasse_diagram=hasse_diagram, elements=elements, category=category, facade=facade, key=key) - self._lin_ext_type = LinearExtensionsOfPosetWithHooks - self._desc = "Finite d-complete poset" - - def _repr_(self): - r""" - TESTS:: - - sage: from sage.combinat.posets.d_complete import DCompletePoset - sage: P = DCompletePoset(DiGraph({0: [1], 0: [2], 1: [3], 2: [3], 3: []})) - sage: P._repr_() - 'Finite d-complete poset containing 4 elements' - """ - s = "Finite d-complete poset containing %s elements" % self._hasse_diagram.order() - if self._with_linear_extension: - s += " with distinguished linear extension" - return s - + _lin_ext_type = LinearExtensionsOfPosetWithHooks + _desc = "Finite d-complete poset" @lazy_attribute def _hooks(self): @@ -78,7 +68,6 @@ def _hooks(self): sage: P._hooks {0: 5, 1: 3, 2: 1, 3: 3, 4: 1, 5: 1} """ - from collections import deque hooks = {} min_diamond = {} # Maps max of double-tailed diamond to min of double-tailed diamond @@ -173,52 +162,4 @@ def get_hooks(self): """ return dict(self._hooks) - - def linear_extensions(self, facade=False): - r""" - Return the enumerated set of all the linear extensions of this poset with hook lengths. - - INPUT: - - - ``facade`` -- a boolean (default: ``False``); - whether to return the linear extensions as plain lists - - EXAMPLES:: - - sage: from sage.combinat.posets.d_complete import DCompletePoset - sage: P = DCompletePoset(DiGraph({0: [1, 2], 1: [3], 2: [3], 3: [4]})) - sage: L = P.linear_extensions() - sage: L.cardinality() - 2 - sage: L.list() - [[0, 1, 2, 3, 4], [0, 2, 1, 3, 4]] - - TESTS:: - - sage: from sage.combinat.posets.d_complete import DCompletePoset - sage: from sage.combinat.posets.poset_examples import Posets - sage: P = DCompletePoset(Posets.YoungDiagramPoset(Partition([3,2,1]))._hasse_diagram.reverse()) - sage: L = P.linear_extensions() - sage: L.cardinality() - 16 - sage: L.list() - [[5, 4, 3, 2, 1, 0], - [4, 5, 3, 2, 1, 0], - [4, 5, 2, 3, 1, 0], - [4, 2, 5, 3, 1, 0], - [2, 4, 5, 3, 1, 0], - [2, 4, 5, 1, 3, 0], - [2, 4, 1, 5, 3, 0], - [4, 2, 1, 5, 3, 0], - [4, 2, 5, 1, 3, 0], - [4, 5, 2, 1, 3, 0], - [5, 4, 2, 1, 3, 0], - [5, 2, 4, 1, 3, 0], - [2, 5, 4, 1, 3, 0], - [2, 5, 4, 3, 1, 0], - [5, 2, 4, 3, 1, 0], - [5, 4, 2, 3, 1, 0]] - """ - - return LinearExtensionsOfPosetWithHooks(self, facade=facade) \ No newline at end of file diff --git a/src/sage/combinat/posets/forest.py b/src/sage/combinat/posets/forest.py index 6f32a3b7f65..1f1adeee9ca 100644 --- a/src/sage/combinat/posets/forest.py +++ b/src/sage/combinat/posets/forest.py @@ -18,8 +18,6 @@ class ForestPoset(FinitePoset): directed acyclic graph. """ - - def __init__(self, hasse_diagram, elements, category, facade, key): - FinitePoset.__init__(self, hasse_diagram=hasse_diagram, elements=elements, category=category, facade=facade, key=key) - self._lin_ext_type = LinearExtensionsOfForest - self._desc = 'Finite forest poset' + + _lin_ext_type = LinearExtensionsOfForest + _desc = 'Finite forest poset' diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index d93e16a6932..bb6787d6c15 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -25,7 +25,7 @@ from sage.misc.cachefunc import cached_method from sage.functions.other import binomial from sage.misc.rest_index_of_methods import gen_rest_table_index - +from collections import deque class LatticeError(ValueError): """ @@ -1143,7 +1143,6 @@ def order_ideal_cardinality(self, elements): sage: H.order_ideal_cardinality([7,10]) 10 """ - from collections import deque seen = set() q = deque(elements) size = 0 diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 2bdb1d3abb9..f9d892e00e5 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -226,10 +226,7 @@ class FiniteMeetSemilattice(FinitePoset): sage: TestSuite(M).run() """ Element = MeetSemilatticeElement - - def __init__(self, hasse_diagram, elements, category, facade, key): - FinitePoset.__init__(self, hasse_diagram=hasse_diagram, elements=elements, category=category, facade=facade, key=key) - self._desc = 'Finite meet-semilattice' + _desc = 'Finite meet-semilattice' def meet_matrix(self): """ @@ -550,10 +547,7 @@ class FiniteJoinSemilattice(FinitePoset): """ Element = JoinSemilatticeElement - - def __init__(self, hasse_diagram, elements, category, facade, key): - FinitePoset.__init__(self, hasse_diagram=hasse_diagram, elements=elements, category=category, facade=facade, key=key) - self._desc = 'Finite join-semilattice' + _desc = 'Finite join-semilattice' def join_matrix(self): """ diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index 243d857f18b..022bc73e8db 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -851,13 +851,18 @@ class LinearExtensionsOfPosetWithHooks(LinearExtensionsOfPoset): A subclass of ``LinearExtensionOfPoset`` where the poset has well-defined hook lengths (ie. d-complete). """ - - def __init__(self, poset, facade): - LinearExtensionsOfPoset.__init__(self, poset=poset, facade=facade) def cardinality(self): r""" Count the number of linear extensions using a hook-length formula + + TESTS:: + + sage: from sage.combinat.posets.d_complete import DComplete + sage: from sage.combinat.posets.poset_examples import Posets + sage: P = Posets.YoungDiagramPoset(Partition([3,2]), dual=True) + sage: P.linear_extensions().cardinality() + 5 """ num_elmts = self._poset.cardinality() @@ -873,13 +878,22 @@ class LinearExtensionsOfForest(LinearExtensionsOfPoset): A subclass of ``LinearExtensionOfPoset`` where the poset is a forest. """ - - def __init__(self, poset, facade): - LinearExtensionsOfPoset.__init__(self, poset=poset, facade=facade) def cardinality(self): r""" Use Atkinson's algorithm to compute the number of linear extensions + + TESTS:: + + sage: from sage.combinat.posets.forest import ForestPoset + sage: from sage.combinat.posets.poset_examples import Posets + sage: P = Poset({0: [2], 1: [2], 2: [3, 4], 3: [], 4: []}) + sage: P.linear_extensions().cardinality() + 4 + + sage: Q = Poset({0: [1], 1: [2, 3], 2: [], 3: [], 4: [5, 6], 5: [], 6: []}) + sage: Q.linear_extensions().cardinality() + 140 """ return sum(self.atkinson(self._elements[0])) - + \ No newline at end of file diff --git a/src/sage/combinat/posets/mobile.py b/src/sage/combinat/posets/mobile.py new file mode 100644 index 00000000000..4a3636aa1cc --- /dev/null +++ b/src/sage/combinat/posets/mobile.py @@ -0,0 +1,32 @@ +# **************************************************************************** +# Copyright (C) 2020 Stefan Grosser +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.combinat.posets.posets import Poset, FinitePoset +from sage.combinat.posets.d_complete import DCompletePoset +from sage.misc.lazy_attribute import lazy_attribute +#from .linear_extensions import LinearExtensionsOfForest + +class MobilePoset(FinitePoset): + r""" + Mobile posets are an extension of d-complete posets which permit a determinant + formula for counting linear extensions. + + """ + + #_lin_ext_type = LinearExtensionsOfForest + _desc = 'Finite mobile poset' + + def _compute_mobile_structure(self): + pass + + + + + diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index 1a57077e115..7ee6613f0b8 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -1382,6 +1382,8 @@ def YoungDiagramPoset(lam, dual=False): INPUT: - ``lam`` -- a partition + + - ``dual`` -- Determines the orientation of the poset EXAMPLES:: diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 43ac4fce0e4..9fa93914d51 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -781,10 +781,6 @@ class FinitePoset(UniqueRepresentation, Parent): set to be the vertex set of the digraph. Note that if this option is set, then ``elements`` is considered as a specified linear extension of the poset and the `linear_extension` attribute is set. - - - ``lin_ext_type`` -- the type of linear extensions that should be returned. - - - ``desc`` -- a string representation used for _repr_. - ``category`` -- :class:`FinitePosets`, or a subcategory thereof. @@ -925,7 +921,9 @@ class contains. For example, for this class, ``FinitePoset``, sage: Q == P True """ - + _lin_ext_type = LinearExtensionsOfPoset + _desc = 'Finite poset' + # The parsing of the construction data (like a list of cover relations) # into a :class:`DiGraph` is done in :func:`Poset`. @staticmethod @@ -1058,8 +1056,6 @@ def __init__(self, hasse_diagram, elements, category, facade, key): self._element_to_vertex_dict = {self._elements[i]: i for i in range(len(self._elements))} self._is_facade = facade - self._lin_ext_type = LinearExtensionsOfPoset - self._desc = 'Finite poset' @lazy_attribute def _list(self): @@ -2239,8 +2235,8 @@ def relations(self): def diamonds(self): r""" Returns in a tuple - - a list of all diamonds in the Hasse Diagram, - - a Boolean checking that every w,x,y that form a ``V``, there is a unique element z + - a list of all diamonds in the Hasse Diagram, + - a Boolean checking that every w,x,y that form a ``V``, there is a unique element z which completes the diamond. For a diamond @@ -2281,8 +2277,7 @@ def common_upper_covers(self, elmts): vertices = list(map(self._element_to_vertex, elmts)) return list(map(self._vertex_to_element, self._hasse_diagram.common_upper_covers(vertices))) - @staticmethod - def is_d_complete(poset): + def is_d_complete(self): r""" Return True if a poset is d-complete. Otherwise, return False. @@ -2290,31 +2285,31 @@ def is_d_complete(poset): sage: from sage.combinat.posets.posets import FinitePoset sage: A = Poset({0: [1,2]}) - sage: FinitePoset.is_d_complete(A) + sage: A.is_d_complete() False sage: from sage.combinat.posets.poset_examples import Posets sage: B = Posets.DoubleTailedDiamond(3) - sage: FinitePoset.is_d_complete(B) + sage: B.is_d_complete() True sage: C = Poset({0: [2], 1: [2], 2: [3, 4], 3: [5], 4: [5], 5: [6]}) - sage: FinitePoset.is_d_complete(C) + sage: C.is_d_complete() False sage: D = Poset({0: [1, 2], 1: [4], 2: [4], 3: [4]}) - sage: FinitePoset.is_d_complete(D) + sage: D.is_d_complete() False - sage: E = Posets.YoungDiagramPoset(Partition([3, 2, 2]), dual=True) - sage: FinitePoset.is_d_complete(E) + sage: P = Posets.YoungDiagramPoset(Partition([3, 2, 2]), dual=True) + sage: P.is_d_complete() True """ min_diamond = {} # Maps max of double-tailed diamond to min of double-tailed diamond max_diamond = {} # Maps min of double-tailed diamond to max of double-tailed diamond - H = poset._hasse_diagram + H = self._hasse_diagram diamonds, all_diamonds_completed = H.diamonds() # Tuples of four elements that are diamonds From 60a8922223959424b9e89140c9c5258fa23cb826 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Jul 2020 19:21:39 -0700 Subject: [PATCH 120/217] In doctests, accept both can't and cannot in error messages --- src/doc/en/faq/faq-usage.rst | 2 +- src/sage/combinat/parallelogram_polyomino.py | 8 ++++---- src/sage/combinat/words/word.py | 8 ++++---- src/sage/data_structures/bitset.pyx | 2 +- src/sage/data_structures/bounded_integer_sequences.pyx | 2 +- src/sage/doctest/sources.py | 2 +- src/sage/geometry/hyperbolic_space/hyperbolic_point.py | 2 +- .../combinatorial_polyhedron/conversions.pyx | 2 +- src/sage/graphs/views.pyx | 2 +- src/sage/interfaces/scilab.py | 2 +- src/sage/libs/arb/arith.pyx | 2 +- src/sage/matrix/matrix0.pyx | 2 +- src/sage/matrix/matrix_rational_dense.pyx | 2 +- src/sage/misc/lazy_attribute.pyx | 2 +- src/sage/misc/persist.pyx | 4 ++-- src/sage/modules/free_module.py | 2 +- src/sage/modules/vector_mod2_dense.pyx | 2 +- .../quadratic_form__variable_substitutions.py | 2 +- src/sage/rings/complex_arb.pyx | 4 ++-- src/sage/rings/complex_double.pyx | 2 +- src/sage/rings/complex_interval.pyx | 6 +++--- src/sage/rings/complex_mpc.pyx | 8 ++++---- src/sage/rings/complex_number.pyx | 4 ++-- src/sage/rings/polynomial/polynomial_complex_arb.pyx | 2 +- src/sage/rings/real_mpfr.pyx | 2 +- .../schemes/elliptic_curves/period_lattice_region.pyx | 2 +- src/sage/schemes/product_projective/point.py | 2 +- src/sage/schemes/projective/projective_point.py | 2 +- src/sage/symbolic/callable.py | 10 +++++----- 29 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/doc/en/faq/faq-usage.rst b/src/doc/en/faq/faq-usage.rst index 44db03050d6..afc3d22060b 100644 --- a/src/doc/en/faq/faq-usage.rst +++ b/src/doc/en/faq/faq-usage.rst @@ -342,7 +342,7 @@ errors, e.g. .. CODE-BLOCK:: text - TypeError: function not supported for these types, and can't coerce safely to supported types. + TypeError: function not supported for these types, and can...t coerce safely to supported types. When you type in numbers into Sage, the pre-processor converts them to a base ring, which you can see by doing:: diff --git a/src/sage/combinat/parallelogram_polyomino.py b/src/sage/combinat/parallelogram_polyomino.py index f2f903c828b..fc6fe7e1029 100644 --- a/src/sage/combinat/parallelogram_polyomino.py +++ b/src/sage/combinat/parallelogram_polyomino.py @@ -1061,22 +1061,22 @@ def check(self): sage: pp = ParallelogramPolyomino([[0], [0]]) # indirect doctest Traceback (most recent call last): ... - ValueError: the lower or the upper path can't be equal to [0] + ValueError: the lower or the upper path can...t be equal to [0] sage: pp = ParallelogramPolyomino([[], [0]]) # indirect doctest Traceback (most recent call last): ... - ValueError: the lower or the upper path can't be equal to [] + ValueError: the lower or the upper path can...t be equal to [] sage: pp = ParallelogramPolyomino([[0], []]) # indirect doctest Traceback (most recent call last): ... - ValueError: the lower or the upper path can't be equal to [] + ValueError: the lower or the upper path can...t be equal to [] sage: pp = ParallelogramPolyomino([[], []]) # indirect doctest Traceback (most recent call last): ... - ValueError: the lower or the upper path can't be equal to [] + ValueError: the lower or the upper path can...t be equal to [] """ lower_path = self.lower_path() upper_path = self.upper_path() diff --git a/src/sage/combinat/words/word.py b/src/sage/combinat/words/word.py index b3d0fdf5957..24f006fe4dd 100644 --- a/src/sage/combinat/words/word.py +++ b/src/sage/combinat/words/word.py @@ -511,7 +511,7 @@ class InfiniteWord_iter_with_caching(WordDatatype_iter_with_caching, InfiniteWor sage: dumps(w) Traceback (most recent call last): ... - TypeError: can't pickle generator objects + TypeError: can...t pickle generator objects """ pass @@ -549,7 +549,7 @@ class InfiniteWord_iter(WordDatatype_iter, InfiniteWord_class): sage: dumps(w) Traceback (most recent call last): ... - TypeError: can't pickle generator objects + TypeError: can...t pickle generator objects """ pass @@ -648,7 +648,7 @@ class Word_iter_with_caching(WordDatatype_iter_with_caching, Word_class): sage: dumps(w) Traceback (most recent call last): ... - TypeError: can't pickle generator objects + TypeError: can...t pickle generator objects """ pass @@ -684,7 +684,7 @@ class Word_iter(WordDatatype_iter, Word_class): sage: dumps(w) Traceback (most recent call last): ... - TypeError: can't pickle generator objects + TypeError: can...t pickle generator objects """ pass diff --git a/src/sage/data_structures/bitset.pyx b/src/sage/data_structures/bitset.pyx index 231792138b5..708eae1cb05 100644 --- a/src/sage/data_structures/bitset.pyx +++ b/src/sage/data_structures/bitset.pyx @@ -278,7 +278,7 @@ cdef class FrozenBitset: sage: FrozenBitset("110110", capacity=-2) Traceback (most recent call last): ... - OverflowError: can't convert negative value to mp_bitcnt_t + OverflowError: can...t convert negative value to mp_bitcnt_t """ def __cinit__(self, iter=None, capacity=None): """ diff --git a/src/sage/data_structures/bounded_integer_sequences.pyx b/src/sage/data_structures/bounded_integer_sequences.pyx index 2f1da5274eb..ded2429a2ea 100644 --- a/src/sage/data_structures/bounded_integer_sequences.pyx +++ b/src/sage/data_structures/bounded_integer_sequences.pyx @@ -587,7 +587,7 @@ cdef class BoundedIntegerSequence: sage: BoundedIntegerSequence(16, [2, 7, -20]) Traceback (most recent call last): ... - OverflowError: can't convert negative value to size_t + OverflowError: can...t convert negative value to size_t sage: BoundedIntegerSequence(1, [0, 0, 0]) <0, 0, 0> sage: BoundedIntegerSequence(1, [0, 1, 0]) diff --git a/src/sage/doctest/sources.py b/src/sage/doctest/sources.py index 8db29fc7673..db45e3e845a 100644 --- a/src/sage/doctest/sources.py +++ b/src/sage/doctest/sources.py @@ -561,7 +561,7 @@ def __iter__(self): sage: L = list(FDS) Traceback (most recent call last): ... - UnicodeDecodeError: 'utf...8' codec can't decode byte 0xf4 in position 18: invalid continuation byte + UnicodeDecodeError: 'utf...8' codec can...t decode byte 0xf4 in position 18: invalid continuation byte This works if we add a PEP 0263 encoding declaration:: diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_point.py b/src/sage/geometry/hyperbolic_space/hyperbolic_point.py index dc16085fe99..b697c5e05f6 100644 --- a/src/sage/geometry/hyperbolic_space/hyperbolic_point.py +++ b/src/sage/geometry/hyperbolic_space/hyperbolic_point.py @@ -589,7 +589,7 @@ def show(self, boundary=True, **options): sage: HyperbolicPlane().UHP().get_point(infinity).show() Traceback (most recent call last): ... - NotImplementedError: can't draw the point infinity + NotImplementedError: can...t draw the point infinity """ p = self.coordinates() if p == infinity: diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx index c7319fcb5ed..124858e6be3 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx @@ -140,7 +140,7 @@ cdef int Vrep_list_to_bit_rep(tuple Vrep_list, uint64_t *output, sage: Vrep_list_to_bit_rep_wrapper((-1, 12)) # long time Traceback (most recent call last): ... - OverflowError: can't convert negative value to size_t + OverflowError: can...t convert negative value to size_t sage: Vrep_list_to_bit_rep_wrapper((0, 0)) # long time Traceback (most recent call last): ... diff --git a/src/sage/graphs/views.pyx b/src/sage/graphs/views.pyx index 3c28b0de50e..0642dfe5643 100644 --- a/src/sage/graphs/views.pyx +++ b/src/sage/graphs/views.pyx @@ -695,7 +695,7 @@ cdef class EdgesView: sage: E * 1.5 Traceback (most recent call last): ... - TypeError: can't multiply sequence by non-int of type 'sage.rings.real_mpfr.RealLiteral' + TypeError: can...t multiply sequence by non-int of type 'sage.rings.real_mpfr.RealLiteral' """ if isinstance(left, EdgesView): return list(left) * right diff --git a/src/sage/interfaces/scilab.py b/src/sage/interfaces/scilab.py index 466347bd9a5..6ea490d5603 100644 --- a/src/sage/interfaces/scilab.py +++ b/src/sage/interfaces/scilab.py @@ -164,7 +164,7 @@ sage: M(9) = x # optional - scilab Traceback (most recent call last): ... - SyntaxError: can't assign to function call (..., line 1) + SyntaxError: can...t assign to function call (..., line 1) AUTHORS: diff --git a/src/sage/libs/arb/arith.pyx b/src/sage/libs/arb/arith.pyx index dba1a4fc461..31db27d6bb6 100644 --- a/src/sage/libs/arb/arith.pyx +++ b/src/sage/libs/arb/arith.pyx @@ -46,7 +46,7 @@ def bernoulli(n): sage: bernoulli(-1) Traceback (most recent call last): ... - OverflowError: can't convert negative value to mp_limb_t + OverflowError: can...t convert negative value to mp_limb_t """ cdef ulong i = n cdef Rational q = Rational.__new__(Rational) diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index eb110f0c635..aebb0453322 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -1620,7 +1620,7 @@ cdef class Matrix(sage.structure.element.Matrix): sage: A.change_ring(ZZ) Traceback (most recent call last): ... - TypeError: matrix has denominators so can't change to ZZ. + TypeError: matrix has denominators so can...t change to ZZ. Changing rings preserves subdivisions:: diff --git a/src/sage/matrix/matrix_rational_dense.pyx b/src/sage/matrix/matrix_rational_dense.pyx index dad006d03bf..2129cad7e23 100644 --- a/src/sage/matrix/matrix_rational_dense.pyx +++ b/src/sage/matrix/matrix_rational_dense.pyx @@ -1443,7 +1443,7 @@ cdef class Matrix_rational_dense(Matrix_dense): sage: a.change_ring(ZZ) Traceback (most recent call last): ... - TypeError: matrix has denominators so can't change to ZZ. + TypeError: matrix has denominators so can...t change to ZZ. sage: b = a.change_ring(QQ['x']); b [1/2 -1] [ 2 3] diff --git a/src/sage/misc/lazy_attribute.pyx b/src/sage/misc/lazy_attribute.pyx index f9191797377..b72cfb49d67 100644 --- a/src/sage/misc/lazy_attribute.pyx +++ b/src/sage/misc/lazy_attribute.pyx @@ -363,7 +363,7 @@ class lazy_attribute(_lazy_attribute): sage: a.x = 4 Traceback (most recent call last): ... - AttributeError: can't set attribute + AttributeError: can...t set attribute sage: a.__dict__ {} sage: a.x diff --git a/src/sage/misc/persist.pyx b/src/sage/misc/persist.pyx index 71e209c383b..97c2c0f33db 100644 --- a/src/sage/misc/persist.pyx +++ b/src/sage/misc/persist.pyx @@ -833,7 +833,7 @@ class SagePickler(_BasePickler): sage: loads(b'x\x9ck`J\x8e\x8f\xcfM\xcc\xcc\x8b\x8f\xe7r\xcb\xcf\xe7*d\x0cej`/dj\r*d\xd6\x03\x00\x89\xc5\x08{', encoding='ASCII') #py3 Traceback (most recent call last): ... - UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128) + UnicodeDecodeError: 'ascii' codec can...t decode byte 0x80 in position 0: ordinal not in range(128) """ @@ -1023,7 +1023,7 @@ def loads(s, compress=True, **kwargs): sage: loads(b'x\x9ck`J\x8e\x8f\xcfM\xcc\xcc\x8b\x8f\xe7r\xcb\xcf\xe7*d\x0cej`/dj\r*d\xd6\x03\x00\x89\xc5\x08{', encoding='ASCII') #py3 Traceback (most recent call last): ... - UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128) + UnicodeDecodeError: 'ascii' codec can...t decode byte 0x80 in position 0: ordinal not in range(128) """ if not isinstance(s, bytes): diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index f77c41fc3b5..13595e01435 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -1652,7 +1652,7 @@ def basis_matrix(self, ring=None): sage: M.basis_matrix(ZZ) Traceback (most recent call last): ... - TypeError: matrix has denominators so can't change to ZZ. + TypeError: matrix has denominators so can...t change to ZZ. """ try: A = self.__basis_matrix diff --git a/src/sage/modules/vector_mod2_dense.pyx b/src/sage/modules/vector_mod2_dense.pyx index d01fd24b5a9..549e33c43d1 100644 --- a/src/sage/modules/vector_mod2_dense.pyx +++ b/src/sage/modules/vector_mod2_dense.pyx @@ -188,7 +188,7 @@ cdef class Vector_mod2_dense(free_module_element.FreeModuleElement): sage: (GF(2)**5)(1) Traceback (most recent call last): ... - TypeError: can't initialize vector from nonzero non-list + TypeError: can...t initialize vector from nonzero non-list sage: (GF(2)**0).zero_vector() () """ diff --git a/src/sage/quadratic_forms/quadratic_form__variable_substitutions.py b/src/sage/quadratic_forms/quadratic_form__variable_substitutions.py index 4dda6fe451a..8d3b7dac337 100644 --- a/src/sage/quadratic_forms/quadratic_form__variable_substitutions.py +++ b/src/sage/quadratic_forms/quadratic_form__variable_substitutions.py @@ -386,7 +386,7 @@ def add_symmetric(self, c, i, j, in_place = False): sage: Q.add_symmetric(-3/2, 2, 0) ## ERROR: -3/2 isn't in the base ring ZZ Traceback (most recent call last): ... - RuntimeError: Oops! This coefficient can't be coerced to an element of the base ring for the quadratic form. + RuntimeError: Oops! This coefficient can...t be coerced to an element of the base ring for the quadratic form. :: diff --git a/src/sage/rings/complex_arb.pyx b/src/sage/rings/complex_arb.pyx index c09a02b6d25..c504ef7070d 100644 --- a/src/sage/rings/complex_arb.pyx +++ b/src/sage/rings/complex_arb.pyx @@ -1624,7 +1624,7 @@ cdef class ComplexBall(RingElement): sage: float(CBF(1,1)) Traceback (most recent call last): ... - TypeError: can't convert complex ball to float + TypeError: can...t convert complex ball to float """ if not arb_is_zero(acb_imagref(self.value)): raise TypeError("can't convert complex ball to float") @@ -1665,7 +1665,7 @@ cdef class ComplexBall(RingElement): sage: RDF(CBF(1 + I)) Traceback (most recent call last): ... - TypeError: can't convert complex ball to float + TypeError: can...t convert complex ball to float sage: RDF(CBF(3)).parent() Real Double Field diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index 3dc6d7679b2..7d2e92f7a1f 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -923,7 +923,7 @@ cdef class ComplexDoubleElement(FieldElement): sage: int(CDF(1,1)) Traceback (most recent call last): ... - TypeError: can't convert complex to int; use int(abs(z)) + TypeError: can...t convert complex to int; use int(abs(z)) sage: int(abs(CDF(1,1))) 1 """ diff --git a/src/sage/rings/complex_interval.pyx b/src/sage/rings/complex_interval.pyx index 30b89561070..a55306f8e75 100644 --- a/src/sage/rings/complex_interval.pyx +++ b/src/sage/rings/complex_interval.pyx @@ -1416,7 +1416,7 @@ cdef class ComplexIntervalFieldElement(sage.structure.element.FieldElement): sage: int(CIF(1,1)) Traceback (most recent call last): ... - TypeError: can't convert complex interval to int + TypeError: can...t convert complex interval to int """ raise TypeError("can't convert complex interval to int") @@ -1431,7 +1431,7 @@ cdef class ComplexIntervalFieldElement(sage.structure.element.FieldElement): sage: float(CIF(1,1)) Traceback (most recent call last): ... - TypeError: can't convert complex interval to float + TypeError: can...t convert complex interval to float """ if self.imag() == 0: return float(self.real().n(self._prec)) @@ -1817,7 +1817,7 @@ cdef class ComplexIntervalFieldElement(sage.structure.element.FieldElement): sage: CIF(RIF(-1,1),RIF(-1,1)).log() Traceback (most recent call last): ... - ValueError: Can't take the argument of interval strictly containing zero + ValueError: Can...t take the argument of interval strictly containing zero But we allow the exact input zero:: diff --git a/src/sage/rings/complex_mpc.pyx b/src/sage/rings/complex_mpc.pyx index 748bdc0c240..8873eaef083 100644 --- a/src/sage/rings/complex_mpc.pyx +++ b/src/sage/rings/complex_mpc.pyx @@ -1124,11 +1124,11 @@ cdef class MPComplexNumber(sage.structure.element.FieldElement): sage: int(a) Traceback (most recent call last): ... - TypeError: can't convert complex to int; use int(abs(z)) + TypeError: can...t convert complex to int; use int(abs(z)) sage: a.__int__() Traceback (most recent call last): ... - TypeError: can't convert complex to int; use int(abs(z)) + TypeError: can...t convert complex to int; use int(abs(z)) """ raise TypeError("can't convert complex to int; use int(abs(z))") @@ -1149,11 +1149,11 @@ cdef class MPComplexNumber(sage.structure.element.FieldElement): sage: float(a) Traceback (most recent call last): ... - TypeError: can't convert complex to float; use abs(z) + TypeError: can...t convert complex to float; use abs(z) sage: a.__float__() Traceback (most recent call last): ... - TypeError: can't convert complex to float; use abs(z) + TypeError: can...t convert complex to float; use abs(z) """ if mpfr_zero_p(self.value.im): return mpfr_get_d(self.value.re,\ diff --git a/src/sage/rings/complex_number.pyx b/src/sage/rings/complex_number.pyx index dd6bd7c8eec..0f7b55720c4 100644 --- a/src/sage/rings/complex_number.pyx +++ b/src/sage/rings/complex_number.pyx @@ -1112,11 +1112,11 @@ cdef class ComplexNumber(sage.structure.element.FieldElement): sage: int(a) Traceback (most recent call last): ... - TypeError: can't convert complex to int; use int(abs(z)) + TypeError: can...t convert complex to int; use int(abs(z)) sage: a.__int__() Traceback (most recent call last): ... - TypeError: can't convert complex to int; use int(abs(z)) + TypeError: can...t convert complex to int; use int(abs(z)) """ raise TypeError("can't convert complex to int; use int(abs(z))") diff --git a/src/sage/rings/polynomial/polynomial_complex_arb.pyx b/src/sage/rings/polynomial/polynomial_complex_arb.pyx index dc1d699d7b7..6f6e45d81ac 100644 --- a/src/sage/rings/polynomial/polynomial_complex_arb.pyx +++ b/src/sage/rings/polynomial/polynomial_complex_arb.pyx @@ -586,7 +586,7 @@ cdef class Polynomial_complex_arb(Polynomial): sage: (x^2 + 1)._power_trunc(-1, 0) Traceback (most recent call last): ... - OverflowError: can't convert negative value to unsigned long + OverflowError: can...t convert negative value to unsigned long """ cdef Polynomial_complex_arb res = self._new() if n < 0: diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 310d30c5468..2c231973f3a 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -1978,7 +1978,7 @@ cdef class RealNumber(sage.structure.element.RingElement): sage: x.str(digits=-10) Traceback (most recent call last): ... - OverflowError: can't convert negative value to size_t + OverflowError: can...t convert negative value to size_t sage: x.str(base=16, truncate=True) Traceback (most recent call last): ... diff --git a/src/sage/schemes/elliptic_curves/period_lattice_region.pyx b/src/sage/schemes/elliptic_curves/period_lattice_region.pyx index 1f8a9ce8c9e..f58258de2b3 100644 --- a/src/sage/schemes/elliptic_curves/period_lattice_region.pyx +++ b/src/sage/schemes/elliptic_curves/period_lattice_region.pyx @@ -413,7 +413,7 @@ cdef class PeriodicRegion: sage: S / (-1) Traceback (most recent call last): ... - OverflowError: can't convert negative value to unsigned int + OverflowError: can...t convert negative value to unsigned int """ cdef unsigned int i, j, a, b, rows, cols if n <= 1: diff --git a/src/sage/schemes/product_projective/point.py b/src/sage/schemes/product_projective/point.py index f77caa27f29..c981dcdc888 100644 --- a/src/sage/schemes/product_projective/point.py +++ b/src/sage/schemes/product_projective/point.py @@ -356,7 +356,7 @@ def dehomogenize(self, L): sage: A.dehomogenize([0,0]) Traceback (most recent call last): ... - ValueError: can't dehomogenize at 0 coordinate + ValueError: can...t dehomogenize at 0 coordinate """ PP = self.codomain() A = PP.affine_patch(L) diff --git a/src/sage/schemes/projective/projective_point.py b/src/sage/schemes/projective/projective_point.py index c0c2cb199cb..351b490fbce 100644 --- a/src/sage/schemes/projective/projective_point.py +++ b/src/sage/schemes/projective/projective_point.py @@ -653,7 +653,7 @@ def dehomogenize(self,n): sage: Q.dehomogenize(2) Traceback (most recent call last): ... - ValueError: can't dehomogenize at 0 coordinate + ValueError: can...t dehomogenize at 0 coordinate """ if self[n] == 0: raise ValueError("can't dehomogenize at 0 coordinate") diff --git a/src/sage/symbolic/callable.py b/src/sage/symbolic/callable.py index 40a196b964a..758fa7ff790 100644 --- a/src/sage/symbolic/callable.py +++ b/src/sage/symbolic/callable.py @@ -38,27 +38,27 @@ sage: f(1)=2 Traceback (most recent call last): ... - SyntaxError: can't assign to function call + SyntaxError: can...t assign to function call sage: f(x,1)=2 Traceback (most recent call last): ... - SyntaxError: can't assign to function call + SyntaxError: can...t assign to function call sage: f(1,2)=3 Traceback (most recent call last): ... - SyntaxError: can't assign to function call + SyntaxError: can...t assign to function call sage: f(1,2)=x Traceback (most recent call last): ... - SyntaxError: can't assign to function call + SyntaxError: can...t assign to function call sage: f(x,2)=x Traceback (most recent call last): ... - SyntaxError: can't assign to function call + SyntaxError: can...t assign to function call """ from sage.symbolic.ring import SymbolicRing, SR From 71da37b486fed8c95fe5e303d62030d0de8086d9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Jul 2020 22:59:01 -0700 Subject: [PATCH 121/217] Fixup --- src/doc/en/faq/faq-usage.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/en/faq/faq-usage.rst b/src/doc/en/faq/faq-usage.rst index afc3d22060b..44db03050d6 100644 --- a/src/doc/en/faq/faq-usage.rst +++ b/src/doc/en/faq/faq-usage.rst @@ -342,7 +342,7 @@ errors, e.g. .. CODE-BLOCK:: text - TypeError: function not supported for these types, and can...t coerce safely to supported types. + TypeError: function not supported for these types, and can't coerce safely to supported types. When you type in numbers into Sage, the pre-processor converts them to a base ring, which you can see by doing:: From 2727aa8a97da050c3a0702a66aa37723a940ee09 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Jul 2020 23:23:19 -0700 Subject: [PATCH 122/217] src/sage/combinat/words/word.py: More wildcarding for respelled error messages --- src/sage/combinat/words/word.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/words/word.py b/src/sage/combinat/words/word.py index 24f006fe4dd..21c442fe4ba 100644 --- a/src/sage/combinat/words/word.py +++ b/src/sage/combinat/words/word.py @@ -511,7 +511,7 @@ class InfiniteWord_iter_with_caching(WordDatatype_iter_with_caching, InfiniteWor sage: dumps(w) Traceback (most recent call last): ... - TypeError: can...t pickle generator objects + TypeError: can...t...pickle...generator...object... """ pass @@ -549,7 +549,7 @@ class InfiniteWord_iter(WordDatatype_iter, InfiniteWord_class): sage: dumps(w) Traceback (most recent call last): ... - TypeError: can...t pickle generator objects + TypeError: can...t...pickle...generator...object... """ pass @@ -648,7 +648,7 @@ class Word_iter_with_caching(WordDatatype_iter_with_caching, Word_class): sage: dumps(w) Traceback (most recent call last): ... - TypeError: can...t pickle generator objects + TypeError: can...t...pickle...generator...object... """ pass @@ -684,7 +684,7 @@ class Word_iter(WordDatatype_iter, Word_class): sage: dumps(w) Traceback (most recent call last): ... - TypeError: can...t pickle generator objects + TypeError: can...t...pickle...generator...object... """ pass From c43343c3b767e0029b1f1d3c3fdc102dc1e8cd31 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Jul 2020 23:48:26 -0700 Subject: [PATCH 123/217] Even more wildcarding for respelled error messages; remove some py2-only tests --- src/sage/cpython/getattr.pyx | 2 +- src/sage/cpython/wrapperdescr.pyx | 2 +- src/sage/repl/preparse.py | 26 +++++++++----------------- src/sage/sets/real_set.py | 4 ++-- 4 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/sage/cpython/getattr.pyx b/src/sage/cpython/getattr.pyx index 94d1d7fabfb..dae36199416 100644 --- a/src/sage/cpython/getattr.pyx +++ b/src/sage/cpython/getattr.pyx @@ -319,7 +319,7 @@ cpdef getattr_from_other_class(self, cls, name): Traceback (most recent call last): ... TypeError: descriptor '__weakref__' for 'A' objects doesn't apply - to 'sage.rings.integer.Integer' object + to ...'sage.rings.integer.Integer' object When this occurs, an ``AttributeError`` is raised:: diff --git a/src/sage/cpython/wrapperdescr.pyx b/src/sage/cpython/wrapperdescr.pyx index c25d955fa03..30f6771d504 100644 --- a/src/sage/cpython/wrapperdescr.pyx +++ b/src/sage/cpython/wrapperdescr.pyx @@ -79,7 +79,7 @@ def wrapperdescr_call(slotwrapper, self, *args, **kwds): sage: wrapperdescr_call(Integer.__mul__, 1, 2, 3) Traceback (most recent call last): ... - TypeError: expected 1 arguments, got 2 + TypeError: expected 1 arg..., got 2 sage: wrapperdescr_call(Integer.__mul__, 6, other=9) Traceback (most recent call last): ... diff --git a/src/sage/repl/preparse.py b/src/sage/repl/preparse.py index e57ca429e0e..1206835df95 100644 --- a/src/sage/repl/preparse.py +++ b/src/sage/repl/preparse.py @@ -800,25 +800,17 @@ def preparse_numeric_literals(code, extract=False): sage: preparse_numeric_literals('123__45') '123__45' - sage: 123__45 # py2 + sage: 123__45 Traceback (most recent call last): ... - SyntaxError: invalid syntax - sage: 123__45 # py3 - Traceback (most recent call last): - ... - SyntaxError: invalid token + SyntaxError: invalid ... sage: preparse_numeric_literals('3040_1_') '3040_1_' - sage: 3040_1_ # py2 - Traceback (most recent call last): - ... - SyntaxError: invalid syntax - sage: 3040_1_ # py3 + sage: 3040_1_ Traceback (most recent call last): ... - SyntaxError: invalid token + SyntaxError: invalid ... """ literals = {} last = 0 @@ -1006,7 +998,7 @@ def preparse_calculus(code): Check support for unicode characters (:trac:`29278`):: - sage: preparse("μ(x) = x^2") # py3 + sage: preparse("μ(x) = x^2") '__tmp__=var("x"); μ = symbolic_expression(x**Integer(2)).function(x)' """ new_code = [] @@ -1157,7 +1149,7 @@ def preparse_generators(code): Check support for unicode characters (:trac:`29278`):: - sage: preparse('Ω.<λ,μ> = QQ[]') # py3 + sage: preparse('Ω.<λ,μ> = QQ[]') "Ω = QQ['λ, μ']; (λ, μ,) = Ω._first_ngens(2)" """ new_code = [] @@ -1264,7 +1256,7 @@ def preparse(line, reset=True, do_time=False, ignore_prompts=False, Check support for unicode characters (:trac:`29278`):: - sage: preparse("Ω.0") # py3 + sage: preparse("Ω.0") 'Ω.gen(0)' """ global quote_state @@ -1473,7 +1465,7 @@ def implicit_mul(code, level=5): Check handling of Python 3 keywords (:trac:`29391`):: - sage: implicit_mul('nonlocal a') # py3 + sage: implicit_mul('nonlocal a') 'nonlocal a' Although these are not keywords in Python 3, we explicitly avoid implicit @@ -1487,7 +1479,7 @@ def implicit_mul(code, level=5): Check support for unicode characters (:trac:`29278`):: - sage: implicit_mul('3λ') # py3 + sage: implicit_mul('3λ') '3*λ' """ from keyword import iskeyword diff --git a/src/sage/sets/real_set.py b/src/sage/sets/real_set.py index 537501f526a..a4621569133 100644 --- a/src/sage/sets/real_set.py +++ b/src/sage/sets/real_set.py @@ -20,8 +20,8 @@ sage: RealSet([0,1)) Traceback (most recent call last): ... - SyntaxError: invalid syntax - + SyntaxError: ... + Instead, you can use the following construction functions:: sage: RealSet.open_closed(0,1) From 7a92b60ad53cc25a20ea86e29ef82fb52f2babc7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 17 Jul 2020 00:18:56 -0700 Subject: [PATCH 124/217] sage.categories.metric_spaces.MetricSpaces: Rename metric to metric_function with deprecation --- src/sage/categories/metric_spaces.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/sage/categories/metric_spaces.py b/src/sage/categories/metric_spaces.py index 2edf200f96a..bdcd09bad98 100644 --- a/src/sage/categories/metric_spaces.py +++ b/src/sage/categories/metric_spaces.py @@ -9,6 +9,7 @@ #****************************************************************************** from sage.misc.cachefunc import cached_method +from sage.misc.superseded import deprecated_function_alias from sage.categories.category import Category from sage.categories.category_with_axiom import CategoryWithAxiom from sage.categories.covariant_functorial_construction import RegressiveCovariantConstructionCategory @@ -113,7 +114,7 @@ def _repr_object_names(self): return "metric spaces" class ParentMethods: - def _test_metric(self, **options): + def _test_metric_function(self, **options): r""" Test that this metric space has a properly implemented metric. @@ -125,13 +126,13 @@ def _test_metric(self, **options): EXAMPLES:: sage: UHP = HyperbolicPlane().UHP() - sage: UHP._test_metric() + sage: UHP._test_metric_function() sage: elts = [UHP.random_element() for i in range(5)] - sage: UHP._test_metric(some_elements=elts) + sage: UHP._test_metric_function(some_elements=elts) """ tester = self._tester(**options) S = tester.some_elements() - dist = self.metric() + dist = self.metric_function() for a in S: for b in S: d = dist(a, b) @@ -140,14 +141,14 @@ def _test_metric(self, **options): else: tester.assertEqual(d, 0) - def metric(self): + def metric_function(self): """ - Return the metric of ``self``. + Return the metric function of ``self``. EXAMPLES:: sage: UHP = HyperbolicPlane().UHP() - sage: m = UHP.metric() + sage: m = UHP.metric_function() sage: p1 = UHP.get_point(5 + 7*I) sage: p2 = UHP.get_point(1.0 + I) sage: m(p1, p2) @@ -155,6 +156,8 @@ def metric(self): """ return lambda a,b: a.dist(b) + metric = deprecated_function_alias(30062, metric_function) + def dist(self, a, b): """ Return the distance between ``a`` and ``b`` in ``self``. From ccaf79dcb9dd7f34d26b7334c52eb32e619b0811 Mon Sep 17 00:00:00 2001 From: "Martin R. Albrecht" Date: Fri, 17 Jul 2020 17:41:43 +0100 Subject: [PATCH 125/217] check rank before inverting --- src/sage/matrix/matrix_gf2e_dense.pyx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sage/matrix/matrix_gf2e_dense.pyx b/src/sage/matrix/matrix_gf2e_dense.pyx index 420209cd273..2638ccd612d 100644 --- a/src/sage/matrix/matrix_gf2e_dense.pyx +++ b/src/sage/matrix/matrix_gf2e_dense.pyx @@ -981,8 +981,13 @@ cdef class Matrix_gf2e_dense(matrix_dense.Matrix_dense): cdef Matrix_gf2e_dense A A = Matrix_gf2e_dense.__new__(Matrix_gf2e_dense, self._parent, 0, 0, 0) - if self._nrows and self._nrows == self._ncols: + if self.rank() != self._nrows: + raise ZeroDivisionError("Matrix does not have full rank.") + + if self._nrows: + sig_on() mzed_invert_newton_john(A._entries, self._entries) + sig_off() return A From 1a0e5c3c15a91e32742ca1cfc1ebf7c13b2be320 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Fri, 17 Jul 2020 11:31:59 -0400 Subject: [PATCH 126/217] Trac #30153: factor out $(1)-no-deps targets in build/make/Makefile.in. The no-deps package targets in build/make/Makefile.in are duplicates of what I shall refer to as the "yes-deps" targets. Instead of manually synchronizing the two which differ only in their prerequisites, this commit changes the yes-deps targets to run $(MAKE) on the no-deps targets after building the deps. --- build/make/Makefile.in | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/build/make/Makefile.in b/build/make/Makefile.in index 92afb2bd362..700a383e153 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -385,7 +385,7 @@ pkg_deps = \ # rules in the form: # # $(INST)/-: -# +$(AM_V_at)sage-logger -p '$(SAGE_SPKG) -' '$(SAGE_LOGS)/-.log' +# $(MAKE) $(1)-no-deps # # : $(INST)/- # @@ -431,9 +431,7 @@ define NORMAL_PACKAGE_templ $(1)-build-deps: $(3) $$(INST)/$(1)-$(2): $(3) - +$(AM_V_at)sage-logger -p '$$(SAGE_SPKG) $$(SAGE_SPKG_OPTIONS) \ - $(if $(filter $(1),$(TOOLCHAIN_DEPS)),--keep-existing) \ - $(1)-$(2)' '$$(SAGE_LOGS)/$(1)-$(2).log' + $(MAKE) $(1)-no-deps $(1): $$(INST)/$(1)-$(2) @@ -477,7 +475,7 @@ define PIP_PACKAGE_templ $(1)-build-deps: $(2) $(1): $(2) - $(AM_V_at)sage-logger -p 'sage --pip install -r "$$(SAGE_ROOT)/build/pkgs/$(1)/requirements.txt"' '$$(SAGE_LOGS)/$(1).log' + $(MAKE) $(1)-no-deps $(1)-no-deps: $(AM_V_at)sage-logger -p 'sage --pip install -r "$$(SAGE_ROOT)/build/pkgs/$(1)/requirements.txt"' '$$(SAGE_LOGS)/$(1).log' @@ -523,12 +521,7 @@ define SCRIPT_PACKAGE_templ $(1)-build-deps: $(3) $$(INST)/$(1)-$(2): $(3) - $(AM_V_at)cd '$$(SAGE_ROOT)/build/pkgs/$(1)' && \ - . '$$(SAGE_ROOT)/src/bin/sage-env-config' && \ - . '$$(SAGE_ROOT)/src/bin/sage-env' && \ - . '$$(SAGE_ROOT)/build/bin/sage-build-env-config' && \ - sage-logger -p '$$(SAGE_ROOT)/build/pkgs/$(1)/spkg-install' '$$(SAGE_LOGS)/$(1)-$(2).log' - touch "$$@" + $(MAKE) $(1)-no-deps $(1): $$(INST)/$(1)-$(2) From 9d71815dbe951cdc6643e83d0dc30bccd2820cb8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 17 Jul 2020 21:53:39 -0700 Subject: [PATCH 127/217] sage.categories.metric_spaces: Make Cartesian products of metric spaces metric spaces --- src/sage/categories/metric_spaces.py | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/sage/categories/metric_spaces.py b/src/sage/categories/metric_spaces.py index 2edf200f96a..ef528e5e369 100644 --- a/src/sage/categories/metric_spaces.py +++ b/src/sage/categories/metric_spaces.py @@ -11,6 +11,7 @@ from sage.misc.cachefunc import cached_method from sage.categories.category import Category from sage.categories.category_with_axiom import CategoryWithAxiom +from sage.categories.cartesian_product import CartesianProductsCategory from sage.categories.covariant_functorial_construction import RegressiveCovariantConstructionCategory from sage.categories.with_realizations import WithRealizationsCategory @@ -232,6 +233,48 @@ def dist(self, a, b): R = self.a_realization() return R.dist(R(a), R(b)) + class CartesianProducts(CartesianProductsCategory): + def extra_super_categories(self): + r""" + Implement the fact that a (finite) Cartesian product of metric spaces is + a metric space. + + EXAMPLES:: + + sage: from sage.categories.metric_spaces import MetricSpaces + sage: C = MetricSpaces().CartesianProducts() + sage: C.extra_super_categories() + [Category of metric spaces] + sage: C.super_categories() + [Category of Cartesian products of sets, Category of metric spaces] + sage: C.axioms() + frozenset() + """ + return [MetricSpaces()] + + class ParentMethods: + + def dist(self, a, b): + r""" + Return the distance between ``a`` and ``b`` in ``self``. + + It is defined as the maximum of the distances within + the Cartesian factors. + + EXAMPLES:: + + sage: from sage.categories.metric_spaces import MetricSpaces + sage: Q2 = QQ.cartesian_product(QQ) + sage: Q2.category() + Join of Category of Cartesian products of commutative rings and Category of Cartesian products of metric spaces + sage: Q2 in MetricSpaces() + True + sage: Q2.dist((0, 0), (2, 3)) + 3 + """ + return max(x.dist(y) for x, y in zip(self(a).cartesian_factors(), + self(b).cartesian_factors())) + class SubcategoryMethods: @cached_method def Complete(self): From 11cebb221cc305a40846c748c0759dda3b68e89f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 17 Jul 2020 22:14:52 -0700 Subject: [PATCH 128/217] sage.categories.metric_spaces: Make Cartesian products of complete metric spaces complete --- src/sage/categories/metric_spaces.py | 32 ++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/sage/categories/metric_spaces.py b/src/sage/categories/metric_spaces.py index ef528e5e369..545b146b1cf 100644 --- a/src/sage/categories/metric_spaces.py +++ b/src/sage/categories/metric_spaces.py @@ -299,3 +299,35 @@ class Complete(CategoryWithAxiom): The category of complete metric spaces. """ + class CartesianProducts(CartesianProductsCategory): + + def extra_super_categories(self): + r""" + Implement the fact that a (finite) Cartesian product of complete + metric spaces is a complete metric space. + + EXAMPLES:: + + sage: from sage.categories.metric_spaces import MetricSpaces + sage: C = MetricSpaces().Complete().CartesianProducts() + sage: C.extra_super_categories() + [Category of complete metric spaces] + sage: C.super_categories() + [Category of Cartesian products of metric spaces, + Category of complete metric spaces] + sage: C.axioms() + frozenset({'Complete'}) + + sage: R2 = RR.cartesian_product(RR) + sage: R2 in MetricSpaces() + True + sage: R2 in MetricSpaces().Complete() + True + + sage: QR = QQ.cartesian_product(RR) + sage: QR in MetricSpaces() + True + sage: QR in MetricSpaces().Complete() + False + """ + return [MetricSpaces().Complete()] From 9ea31b84414adf0cc9866f40cf9fbf1d76ef9976 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 17 Jul 2020 22:52:23 -0700 Subject: [PATCH 129/217] sage.categories.topological_spaces: Make Cartesian products of (compact/connected) topological spaces (compact/connected) topological spaces --- src/sage/categories/topological_spaces.py | 60 +++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/sage/categories/topological_spaces.py b/src/sage/categories/topological_spaces.py index 41f98e0decc..409e6cdcd8f 100644 --- a/src/sage/categories/topological_spaces.py +++ b/src/sage/categories/topological_spaces.py @@ -10,6 +10,7 @@ from sage.misc.cachefunc import cached_method from sage.categories.category_with_axiom import CategoryWithAxiom +from sage.categories.cartesian_product import CartesianProductsCategory from sage.categories.covariant_functorial_construction import RegressiveCovariantConstructionCategory from sage.categories.sets_cat import Sets @@ -59,6 +60,25 @@ def _repr_object_names(self): """ return "topological spaces" + class CartesianProducts(CartesianProductsCategory): + def extra_super_categories(self): + r""" + Implement the fact that a (finite) Cartesian product of topological spaces is + a topological space. + + EXAMPLES:: + + sage: from sage.categories.topological_spaces import TopologicalSpaces + sage: C = TopologicalSpaces().CartesianProducts() + sage: C.extra_super_categories() + [Category of topological spaces] + sage: C.super_categories() + [Category of Cartesian products of sets, Category of topological spaces] + sage: C.axioms() + frozenset() + """ + return [TopologicalSpaces()] + class SubcategoryMethods: @cached_method def Connected(self): @@ -101,8 +121,48 @@ class Connected(CategoryWithAxiom): The category of connected topological spaces. """ + class CartesianProducts(CartesianProductsCategory): + def extra_super_categories(self): + r""" + Implement the fact that a (finite) Cartesian product of connected + topological spaces is connected. + + EXAMPLES:: + + sage: from sage.categories.topological_spaces import TopologicalSpaces + sage: C = TopologicalSpaces().Connected().CartesianProducts() + sage: C.extra_super_categories() + [Category of connected topological spaces] + sage: C.super_categories() + [Category of Cartesian products of topological spaces, + Category of connected topological spaces] + sage: C.axioms() + frozenset({'Connected'}) + """ + return [TopologicalSpaces().Connected()] + + class Compact(CategoryWithAxiom): """ The category of compact topological spaces. """ + class CartesianProducts(CartesianProductsCategory): + def extra_super_categories(self): + r""" + Implement the fact that a (finite) Cartesian product of compact + topological spaces is compact. + + EXAMPLES:: + + sage: from sage.categories.topological_spaces import TopologicalSpaces + sage: C = TopologicalSpaces().Compact().CartesianProducts() + sage: C.extra_super_categories() + [Category of compact topological spaces] + sage: C.super_categories() + [Category of Cartesian products of topological spaces, + Category of compact topological spaces] + sage: C.axioms() + frozenset({'Compact'}) + """ + return [TopologicalSpaces().Compact()] From 91e44f4479bfb30663873faa7de0467e542daebb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 18 Jul 2020 15:10:24 -0700 Subject: [PATCH 130/217] sage.tensor.modules.FiniteRankFreeModule.basis_fixing_map: New --- .../tensor/modules/finite_rank_free_module.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/sage/tensor/modules/finite_rank_free_module.py b/src/sage/tensor/modules/finite_rank_free_module.py index 77d71c40324..62cb27dce7e 100644 --- a/src/sage/tensor/modules/finite_rank_free_module.py +++ b/src/sage/tensor/modules/finite_rank_free_module.py @@ -2515,6 +2515,35 @@ def hom(self, codomain, matrix_rep, bases=None, name=None, return homset(matrix_rep, bases=bases, name=name, latex_name=latex_name) + def basis_fixing_map(self, basis): + r""" + Construct the canonical isomorphism from the free module ``self`` + to a free module in which ``basis`` of ``self`` is the distinguished basis. + + EXAMPLES:: + + sage: self = V = FiniteRankFreeModule(QQ, 3); V + 3-dimensional vector space over the Rational Field + sage: basis = e = V.basis("e"); e + Basis (e_0,e_1,e_2) on the 3-dimensional vector space over the Rational Field + sage: phi_e = V.basis_fixing_map(basis); phi_e + Generic morphism: + From: 3-dimensional vector space over the Rational Field + To: Free module generated by {'e_0', 'e_1', 'e_2'} over Rational Field + sage: phi_e.codomain().category() + Category of finite dimensional vector spaces with basis over Rational Field + sage: phi_e(e[1] + 2 * e[2]) + B[1] + 2*B[2] + """ + from sage.combinat.free_module import CombinatorialFreeModule + from sage.modules.with_basis.morphism import ModuleMorphismFromFunction + base_ring = self.base_ring() + codomain = CombinatorialFreeModule(base_ring, [b._name for b in basis]) + def function(x): + return codomain._from_dict({i: x[basis, i] for i in self.irange()}) + return ModuleMorphismFromFunction(self, function, codomain, + category=Modules(base_ring)) + def endomorphism(self, matrix_rep, basis=None, name=None, latex_name=None): r""" Construct an endomorphism of the free module ``self``. From 1af18a1b546b81590f691b51bd290cefc8357007 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 18 Jul 2020 16:38:34 -0700 Subject: [PATCH 131/217] Fix doctests --- src/sage/categories/magmas.py | 2 +- src/sage/categories/metric_spaces.py | 3 ++- src/sage/categories/sets_cat.py | 9 ++------- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/sage/categories/magmas.py b/src/sage/categories/magmas.py index 8073599c0d3..2c492da1338 100644 --- a/src/sage/categories/magmas.py +++ b/src/sage/categories/magmas.py @@ -1082,7 +1082,7 @@ def example(self): sage: C = Magmas().CartesianProducts().example(); C The Cartesian product of (Rational Field, Integer Ring, Integer Ring) sage: C.category() - Category of Cartesian products of commutative rings + Join of Category of Cartesian products of commutative rings and Category of Cartesian products of metric spaces sage: sorted(C.category().axioms()) ['AdditiveAssociative', 'AdditiveCommutative', 'AdditiveInverse', 'AdditiveUnital', 'Associative', 'Commutative', diff --git a/src/sage/categories/metric_spaces.py b/src/sage/categories/metric_spaces.py index 545b146b1cf..73d5c2f4efb 100644 --- a/src/sage/categories/metric_spaces.py +++ b/src/sage/categories/metric_spaces.py @@ -246,7 +246,8 @@ def extra_super_categories(self): sage: C.extra_super_categories() [Category of metric spaces] sage: C.super_categories() - [Category of Cartesian products of sets, Category of metric spaces] + [Category of Cartesian products of topological spaces, + Category of metric spaces] sage: C.axioms() frozenset() """ diff --git a/src/sage/categories/sets_cat.py b/src/sage/categories/sets_cat.py index 53c2da3400e..482dca9476b 100644 --- a/src/sage/categories/sets_cat.py +++ b/src/sage/categories/sets_cat.py @@ -1503,14 +1503,9 @@ def cartesian_product(*parents, **kwargs): sage: cartesian_product([ZZ, ZZ], category=Sets()).category() Category of sets sage: cartesian_product([ZZ, ZZ]).category() - Join of - Category of Cartesian products of commutative rings and - Category of Cartesian products of enumerated sets + Join of Category of Cartesian products of commutative rings and Category of Cartesian products of metric spaces and Category of Cartesian products of enumerated sets sage: cartesian_product([ZZ, ZZ], extra_category=Posets()).category() - Join of - Category of Cartesian products of commutative rings and - Category of posets and - Category of Cartesian products of enumerated sets + Join of Category of Cartesian products of commutative rings and Category of posets and Category of Cartesian products of metric spaces and Category of Cartesian products of enumerated sets """ category = kwargs.pop('category', None) extra_category = kwargs.pop('extra_category', None) From 73667410fb02014b789a49ef58e9846ecc729419 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 18 Jul 2020 17:13:33 -0700 Subject: [PATCH 132/217] Rename, generalize --- .../tensor/modules/finite_rank_free_module.py | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/sage/tensor/modules/finite_rank_free_module.py b/src/sage/tensor/modules/finite_rank_free_module.py index 62cb27dce7e..301377cbbe3 100644 --- a/src/sage/tensor/modules/finite_rank_free_module.py +++ b/src/sage/tensor/modules/finite_rank_free_module.py @@ -2515,7 +2515,7 @@ def hom(self, codomain, matrix_rep, bases=None, name=None, return homset(matrix_rep, bases=bases, name=name, latex_name=latex_name) - def basis_fixing_map(self, basis): + def isomorphism_with_fixed_basis(self, basis, codomain=None): r""" Construct the canonical isomorphism from the free module ``self`` to a free module in which ``basis`` of ``self`` is the distinguished basis. @@ -2526,21 +2526,34 @@ def basis_fixing_map(self, basis): 3-dimensional vector space over the Rational Field sage: basis = e = V.basis("e"); e Basis (e_0,e_1,e_2) on the 3-dimensional vector space over the Rational Field - sage: phi_e = V.basis_fixing_map(basis); phi_e + sage: phi_e = V.isomorphism_with_fixed_basis(basis); phi_e Generic morphism: From: 3-dimensional vector space over the Rational Field To: Free module generated by {'e_0', 'e_1', 'e_2'} over Rational Field sage: phi_e.codomain().category() Category of finite dimensional vector spaces with basis over Rational Field sage: phi_e(e[1] + 2 * e[2]) - B[1] + 2*B[2] + B['e_1'] + 2*B['e_2'] + + TESTS:: + + sage: V.isomorphism_with_fixed_basis(e, codomain=QQ^42) + Traceback (most recent call last): + ... + ValueError: domain and codomain should have the same rank + """ from sage.combinat.free_module import CombinatorialFreeModule from sage.modules.with_basis.morphism import ModuleMorphismFromFunction base_ring = self.base_ring() - codomain = CombinatorialFreeModule(base_ring, [b._name for b in basis]) + if codomain is None: + codomain = CombinatorialFreeModule(base_ring, [b._name for b in basis]) + else: + if codomain.rank() != self.rank(): + raise ValueError("domain and codomain should have the same rank") + codomain_basis = list(codomain.basis()) def function(x): - return codomain._from_dict({i: x[basis, i] for i in self.irange()}) + return codomain.sum(x[basis, i] * codomain_basis[i] for i in self.irange()) return ModuleMorphismFromFunction(self, function, codomain, category=Modules(base_ring)) From a8816abf7c8893742ee9b573b58d72becac1c3ef Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 18 Jul 2020 17:48:50 -0700 Subject: [PATCH 133/217] Fix up linebreaks in doctests --- src/sage/categories/magmas.py | 3 ++- src/sage/categories/metric_spaces.py | 4 +++- src/sage/categories/sets_cat.py | 11 +++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/sage/categories/magmas.py b/src/sage/categories/magmas.py index 2c492da1338..89af2269084 100644 --- a/src/sage/categories/magmas.py +++ b/src/sage/categories/magmas.py @@ -1082,7 +1082,8 @@ def example(self): sage: C = Magmas().CartesianProducts().example(); C The Cartesian product of (Rational Field, Integer Ring, Integer Ring) sage: C.category() - Join of Category of Cartesian products of commutative rings and Category of Cartesian products of metric spaces + Join of Category of Cartesian products of commutative rings and + Category of Cartesian products of metric spaces sage: sorted(C.category().axioms()) ['AdditiveAssociative', 'AdditiveCommutative', 'AdditiveInverse', 'AdditiveUnital', 'Associative', 'Commutative', diff --git a/src/sage/categories/metric_spaces.py b/src/sage/categories/metric_spaces.py index 73d5c2f4efb..da9f75dd899 100644 --- a/src/sage/categories/metric_spaces.py +++ b/src/sage/categories/metric_spaces.py @@ -267,7 +267,9 @@ def dist(self, a, b): sage: from sage.categories.metric_spaces import MetricSpaces sage: Q2 = QQ.cartesian_product(QQ) sage: Q2.category() - Join of Category of Cartesian products of commutative rings and Category of Cartesian products of metric spaces + Join of + Category of Cartesian products of commutative rings and + Category of Cartesian products of metric spaces sage: Q2 in MetricSpaces() True sage: Q2.dist((0, 0), (2, 3)) diff --git a/src/sage/categories/sets_cat.py b/src/sage/categories/sets_cat.py index 482dca9476b..f8b1ed19a3f 100644 --- a/src/sage/categories/sets_cat.py +++ b/src/sage/categories/sets_cat.py @@ -1503,9 +1503,16 @@ def cartesian_product(*parents, **kwargs): sage: cartesian_product([ZZ, ZZ], category=Sets()).category() Category of sets sage: cartesian_product([ZZ, ZZ]).category() - Join of Category of Cartesian products of commutative rings and Category of Cartesian products of metric spaces and Category of Cartesian products of enumerated sets + Join of + Category of Cartesian products of commutative rings and + Category of Cartesian products of metric spaces and + Category of Cartesian products of enumerated sets sage: cartesian_product([ZZ, ZZ], extra_category=Posets()).category() - Join of Category of Cartesian products of commutative rings and Category of posets and Category of Cartesian products of metric spaces and Category of Cartesian products of enumerated sets + Join of + Category of Cartesian products of commutative rings and + Category of posets and + Category of Cartesian products of metric spaces and + Category of Cartesian products of enumerated sets """ category = kwargs.pop('category', None) extra_category = kwargs.pop('extra_category', None) From 3911823ba0a74962c668f8fc6db474b411dd1c91 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 18 Jul 2020 18:53:09 -0700 Subject: [PATCH 134/217] sage.categories.metric_spaces.MetricSpaces.Homsets.ElementMethods._test_metric_map: New --- src/sage/categories/metric_spaces.py | 40 ++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/sage/categories/metric_spaces.py b/src/sage/categories/metric_spaces.py index 2edf200f96a..5af5b6ece54 100644 --- a/src/sage/categories/metric_spaces.py +++ b/src/sage/categories/metric_spaces.py @@ -13,6 +13,7 @@ from sage.categories.category_with_axiom import CategoryWithAxiom from sage.categories.covariant_functorial_construction import RegressiveCovariantConstructionCategory from sage.categories.with_realizations import WithRealizationsCategory +from sage.categories.homsets import HomsetsCategory class MetricSpacesCategory(RegressiveCovariantConstructionCategory): @@ -213,6 +214,45 @@ def dist(self, b): """ return self.parent().dist(self, b) + class Homsets(HomsetsCategory): + """ + The category of homsets of metric spaces + + It consists of the metric maps, that is, the Lipschitz functions + with Lipschitz constant 1. + """ + + class ElementMethods: + + def _test_metric_map(self, **options): + r""" + Test that this metric space morphism is a metric map, + that is, a Lipschitz function with Lipschitz constant 1. + + EXAMPLES:: + + sage: from sage.categories.metric_spaces import MetricSpaces + sage: from sage.categories.morphism import SetMorphism + sage: Q_abs = SetMorphism(Hom(QQ, QQ, MetricSpaces()), operator.__abs__) + sage: TestSuite(Q_abs).run() + + TESTS:: + + sage: Q_square = SetMorphism(Hom(QQ, QQ, MetricSpaces()), lambda x: x ** 2) + sage: TestSuite(Q_square).run(skip=['_test_pickling']) + Failure in _test_metric_map: + Traceback (most recent call last): + ... + AssertionError: ... not less than or equal to ... + ... + The following tests failed: _test_metric_map + """ + tester = self._tester(**options) + S = self.domain().some_elements() + for a in S: + for b in S: + tester.assertLessEqual(self(a).dist(self(b)), a.dist(b)) + class WithRealizations(WithRealizationsCategory): class ParentMethods: def dist(self, a, b): From 25152f6b7224c34745ed2431a492e736078f891a Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Sun, 19 Jul 2020 08:32:07 +0200 Subject: [PATCH 135/217] small fix --- src/sage/geometry/polyhedron/base.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index a107fdbdd66..53887b5da12 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -4970,7 +4970,6 @@ def _test_dilation(self, tester=None, **options): p = self.change_ring(new_ring) tester.assertIsInstance(scalar*p, Polyhedron_base) - def linear_transformation(self, linear_transf): def linear_transformation(self, linear_transf, new_base_ring=None): """ Return the linear transformation of ``self``. From c9c7b63f1ed9fda028044385920f2b7849cfbd2b Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Sun, 19 Jul 2020 08:40:30 +0200 Subject: [PATCH 136/217] missed preceeding `sage:` of doctests --- src/sage/geometry/polyhedron/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 646b6e2bae1..9ec4dc0d978 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -5100,7 +5100,7 @@ def _test_linear_transformation(self, tester=None, **options): TESTS:: - Polyhedron(rays=[(0,1)])._test_linear_transformation() + sage: Polyhedron(rays=[(0,1)])._test_linear_transformation() """ if tester is None: tester = self._tester(**options) From c2350315b34523561167367494a703bed67d7825 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 19 Jul 2020 07:18:40 -0700 Subject: [PATCH 137/217] build/pkgs/ecl/spkg-install.in: Do not build the manual --- build/pkgs/ecl/spkg-install.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/ecl/spkg-install.in b/build/pkgs/ecl/spkg-install.in index 97bdf4830d1..6a4d1eabf2b 100644 --- a/build/pkgs/ecl/spkg-install.in +++ b/build/pkgs/ecl/spkg-install.in @@ -43,7 +43,7 @@ if [ $? -ne 0 ]; then # texi2any not found -> makeinfo too old, if present ECL_CONFIGURE="$ECL_CONFIGURE --enable-manual=no" fi -sdh_configure $SAGE_CONFIGURE_GMP --disable-threads \ +sdh_configure $SAGE_CONFIGURE_GMP --disable-threads --disable-manual \ --enable-unicode=yes --with-defsystem $ECL_CONFIGURE # Before running make we touch build/TAGS so its building process is never triggered From 81e0ec0c1902a55269214f81e2cce130253b0de8 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Sun, 19 Jul 2020 21:14:44 +0200 Subject: [PATCH 138/217] Trac #30094: docstring improved + raise error for different base rings --- .../tensor/modules/finite_rank_free_module.py | 61 +++++++++++++++---- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/src/sage/tensor/modules/finite_rank_free_module.py b/src/sage/tensor/modules/finite_rank_free_module.py index 301377cbbe3..88251dbe9f1 100644 --- a/src/sage/tensor/modules/finite_rank_free_module.py +++ b/src/sage/tensor/modules/finite_rank_free_module.py @@ -2518,43 +2518,78 @@ def hom(self, codomain, matrix_rep, bases=None, name=None, def isomorphism_with_fixed_basis(self, basis, codomain=None): r""" Construct the canonical isomorphism from the free module ``self`` - to a free module in which ``basis`` of ``self`` is the distinguished basis. + to a free module in which ``basis`` of ``self`` is mapped to the + distinguished basis of ``codomain``. + + INPUT: + + - ``basis`` -- the basis of ``self`` which should be mapped to the + distinguished basis on ``codomain`` + - ``codomain`` -- (default: ``None``) the codomain of the + isomorphism represented by a free module within the category + ``ModulesWithBasis`` with the same rank and base ring as ``self``; if + ``None`` a free module represented by + :class:`~sage.combinat.free_module.CombinatorialFreeModule` is + constructed EXAMPLES:: sage: self = V = FiniteRankFreeModule(QQ, 3); V 3-dimensional vector space over the Rational Field - sage: basis = e = V.basis("e"); e - Basis (e_0,e_1,e_2) on the 3-dimensional vector space over the Rational Field + sage: basis = e = V.basis("e"); basis + Basis (e_0,e_1,e_2) on the 3-dimensional vector space over the + Rational Field sage: phi_e = V.isomorphism_with_fixed_basis(basis); phi_e Generic morphism: From: 3-dimensional vector space over the Rational Field - To: Free module generated by {'e_0', 'e_1', 'e_2'} over Rational Field + To: Free module generated by {'e_0', 'e_1', 'e_2'} over + Rational Field sage: phi_e.codomain().category() - Category of finite dimensional vector spaces with basis over Rational Field + Category of finite dimensional vector spaces with basis over + Rational Field sage: phi_e(e[1] + 2 * e[2]) B['e_1'] + 2*B['e_2'] TESTS:: + sage: V = FiniteRankFreeModule(QQ, 3); V + 3-dimensional vector space over the Rational Field + sage: e = V.basis("e") sage: V.isomorphism_with_fixed_basis(e, codomain=QQ^42) Traceback (most recent call last): ... - ValueError: domain and codomain should have the same rank + ValueError: domain and codomain must have the same rank + sage: V.isomorphism_with_fixed_basis(e, codomain=RR^3) + Traceback (most recent call last): + ... + ValueError: domain and codomain must have the same base ring """ - from sage.combinat.free_module import CombinatorialFreeModule - from sage.modules.with_basis.morphism import ModuleMorphismFromFunction base_ring = self.base_ring() if codomain is None: - codomain = CombinatorialFreeModule(base_ring, [b._name for b in basis]) + from sage.combinat.free_module import CombinatorialFreeModule + + codomain = CombinatorialFreeModule(base_ring, + [b._name for b in basis]) else: if codomain.rank() != self.rank(): - raise ValueError("domain and codomain should have the same rank") + raise ValueError("domain and codomain must have the same rank") + if codomain.base_ring() != base_ring: + raise ValueError("domain and codomain must have the same " + "base ring") + + from sage.modules.with_basis.morphism import ModuleMorphismFromFunction + codomain_basis = list(codomain.basis()) - def function(x): - return codomain.sum(x[basis, i] * codomain_basis[i] for i in self.irange()) - return ModuleMorphismFromFunction(self, function, codomain, + + def _isomorphism(x): + r""" + Concrete isomorphism from ``self`` to ``codomain``. + """ + return codomain.sum(x[basis, i] * codomain_basis[i] + for i in self.irange()) + + return ModuleMorphismFromFunction(self, _isomorphism, codomain, category=Modules(base_ring)) def endomorphism(self, matrix_rep, basis=None, name=None, latex_name=None): From bdc6e2c8194911acf4e2a6a021e2f417504b9752 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Sun, 19 Jul 2020 22:22:39 +0200 Subject: [PATCH 139/217] Trac #30094: minor improvements in docstring --- src/sage/tensor/modules/finite_rank_free_module.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/sage/tensor/modules/finite_rank_free_module.py b/src/sage/tensor/modules/finite_rank_free_module.py index 88251dbe9f1..b746c91b81a 100644 --- a/src/sage/tensor/modules/finite_rank_free_module.py +++ b/src/sage/tensor/modules/finite_rank_free_module.py @@ -2527,11 +2527,17 @@ def isomorphism_with_fixed_basis(self, basis, codomain=None): distinguished basis on ``codomain`` - ``codomain`` -- (default: ``None``) the codomain of the isomorphism represented by a free module within the category - ``ModulesWithBasis`` with the same rank and base ring as ``self``; if - ``None`` a free module represented by + :class:`~sage.categories.modules_with_basis.ModulesWithBasis` with + the same rank and base ring as ``self``; if ``None`` a free module + represented by :class:`~sage.combinat.free_module.CombinatorialFreeModule` is constructed + OUTPUT: + + - a module morphism represented by + :class:`~sage.modules.with_basis.morphism.ModuleMorphismFromFunction` + EXAMPLES:: sage: self = V = FiniteRankFreeModule(QQ, 3); V From 886707ebda154c105e10b6e6c1d918c59bd111c5 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 20 Jul 2020 11:27:30 +1000 Subject: [PATCH 140/217] Reviewer changes for new poset classes. --- src/doc/en/reference/combinat/module_list.rst | 4 +- src/doc/en/reference/references/index.rst | 20 ++-- src/sage/combinat/posets/__init__.py | 2 +- src/sage/combinat/posets/d_complete.py | 77 +++++++--------- src/sage/combinat/posets/forest.py | 17 +++- src/sage/combinat/posets/hasse_diagram.py | 41 +++++---- src/sage/combinat/posets/linear_extensions.py | 32 +++---- src/sage/combinat/posets/mobile.py | 32 ------- src/sage/combinat/posets/poset_examples.py | 57 ++++++------ src/sage/combinat/posets/posets.py | 91 ++++++++++--------- 10 files changed, 176 insertions(+), 197 deletions(-) delete mode 100644 src/sage/combinat/posets/mobile.py diff --git a/src/doc/en/reference/combinat/module_list.rst b/src/doc/en/reference/combinat/module_list.rst index e7ebdbd0f46..d8be446a41e 100644 --- a/src/doc/en/reference/combinat/module_list.rst +++ b/src/doc/en/reference/combinat/module_list.rst @@ -188,7 +188,9 @@ Comprehensive Module list sage/combinat/posets/__init__ sage/combinat/posets/all sage/combinat/posets/cartesian_product + sage/combinat/posets/d_complete sage/combinat/posets/elements + sage/combinat/posets/forest sage/combinat/posets/hasse_diagram sage/combinat/posets/incidence_algebras sage/combinat/posets/lattices @@ -196,8 +198,6 @@ Comprehensive Module list sage/combinat/posets/moebius_algebra sage/combinat/posets/poset_examples sage/combinat/posets/posets - sage/combinat/posets/d_complete - sage/combinat/posets/forest sage/combinat/q_analogues sage/combinat/q_bernoulli sage/combinat/quickref diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 7aecf4aa66b..264e4790398 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -3448,9 +3448,9 @@ REFERENCES: CMS Conf. Proc., **24**, Amer. Math. Soc., Providence, RI, 1998. :mathscinet:`MR1648638` -.. [KY2019] Jang Soo Kim, Meesue Yoo. - "Hook length property of d-complete posets via q-integrals." - Journal of Combinatorial Theory, Series A 162 (2019): 167-221. +.. [KY2019] Jang Soo Kim, Meesue Yoo. + *Hook length property of d-complete posets via q-integrals*. + J. Combin. Theory Ser. A, **162** (2019), pp. 167-221. .. [KZ2003] \M. Kontsevich, A. Zorich "Connected components of the moduli space of Abelian differentials with prescripebd @@ -4415,14 +4415,16 @@ REFERENCES: Providence, RI, 2013. :arxiv:`1112.6163` -.. [Proc1999] R. A. Proctor, Minuscule elements of Weyl groups, the numbers game, - and d-complete posets. J. Algebra, 213(1):272–303, 1999. +.. [Proc1999] \R. A. Proctor, *Minuscule elements of Weyl groups, the numbers game, + and d-complete posets*. J. Algebra, 213(1):272–303, 1999. -.. [PDynk1999] R. A. Proctor. Dynkin diagram classification of λ-minuscule Bruhat lattices - and of d-complete posets. J. Algebraic Combin., 9(1):61–94, 1999. +.. [PDynk1999] \R. A. Proctor. *Dynkin diagram classification of λ-minuscule + Bruhat lattices and of d-complete posets*. J. Algebraic Combin., + 9(1):61-94, 1999. -.. [Proc2014] R. A. Proctor. d-complete posets generalize Young diagrams for the hook product - formula: Partial Presentation of Proof. RIMS Kˆokyˆuroku, 1913:120–140, 2014. +.. [Proc2014] \R. A. Proctor. `d`-*complete posets generalize Young diagrams + for the hook product formula: Partial Presentation of Proof*. + RIMS Kôkyûroku, 1913:120-140, 2014. .. [PR2003] Perrin-Riou, *Arithmétique des courbes elliptiques à réduction supersingulière en `p`*, diff --git a/src/sage/combinat/posets/__init__.py b/src/sage/combinat/posets/__init__.py index fbf11e9efb9..01e0e411a96 100644 --- a/src/sage/combinat/posets/__init__.py +++ b/src/sage/combinat/posets/__init__.py @@ -30,5 +30,5 @@ :class:`~sage.categories.finite_posets.FinitePosets`, :class:`~sage.categories.lattice_posets.LatticePosets` and :class:`~sage.categories.finite_lattice_posets.FiniteLatticePosets`. +""" - """ diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index af949255824..56617771a58 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -1,3 +1,11 @@ +r""" +D-Complete Posets + +AUTHORS: + +- Stefan Grosser (06-2020): initial implementation +""" + # **************************************************************************** # Copyright (C) 2020 Stefan Grosser # @@ -16,46 +24,31 @@ class DCompletePoset(FiniteJoinSemilattice): r""" - D-complete posets are a class of posets introduced by Proctor in [Proc1999]. - It includes common families such as shapes, shifted shapes, and rooted forests. Proctor showed in [PDynk1999] - that d-complete posets have decompositions in ``irreducible`` posets, and showed in [Proc2014] that - d-complete posets admit a hook-length formula (see [1]). A complete proof of the hook-length formula - can be found in [KY2019]. - + A d-complete poset. + + D-complete posets are a class of posets introduced by Proctor + in [Proc1999]_. It includes common families such as shapes, shifted + shapes, and rooted forests. Proctor showed in [PDynk1999]_ that + d-complete posets have decompositions in *irreducible* posets, + and showed in [Proc2014]_ that d-complete posets admit a hook-length + formula (see :wikipedia:`Hook_length_formula`). A complete proof of + the hook-length formula can be found in [KY2019]_. + EXAMPLES:: sage: from sage.combinat.posets.poset_examples import Posets sage: P = Posets.DoubleTailedDiamond(2) - sage: type(P) - - - The additional internal data structure consists of: - - - the hook lengths of the elements of the poset - - sage: P._hooks - {1: 1, 2: 2, 3: 3, 4: 3, 5: 4, 6: 5} - - TESTS:: - sage: TestSuite(P).run() - - See also the other tests in the class documentation. - - REFERENCES:: - - .. [1] :wikipedia:`Hook_length_formula`, accessed 27th - June 2020. """ - _lin_ext_type = LinearExtensionsOfPosetWithHooks _desc = "Finite d-complete poset" @lazy_attribute def _hooks(self): r""" - The hook lengths of the elements of the d-complete poset. For the definition - of hook lengths for d-complete posets, see [KY2019]. + The hook lengths of the elements of the d-complete poset. + + See [KY2019]_ for the definition of hook lengths for d-complete posets. TESTS:: @@ -64,7 +57,7 @@ def _hooks(self): sage: P._hooks {0: 1, 1: 2, 2: 2, 3: 3} sage: from sage.combinat.posets.poset_examples import Posets - sage: P = DCompletePoset(Posets.YoungDiagramPoset(Partition([3,2,1]))._hasse_diagram.reverse()) + sage: P = DCompletePoset(Posets.YoungDiagramPoset(Partition([3,2,1]))._hasse_diagram.reverse()) sage: P._hooks {0: 5, 1: 3, 2: 1, 3: 3, 4: 1, 5: 1} """ @@ -72,14 +65,14 @@ def _hooks(self): min_diamond = {} # Maps max of double-tailed diamond to min of double-tailed diamond max_diamond = {} # Maps min of double-tailed diamond to max of double-tailed diamond - + H = self._hasse_diagram diamonds, _ = H.diamonds() # Tuples of four elements that are diamonds - + diamond_index = {} # Map max elmt of double tailed diamond to index of diamond - # Find all the double-tailed diamonds and map the mins and maxes. + # Find all the double-tailed diamonds and map the mins and maxes for index, d in enumerate(diamonds): min_diamond[d[3]] = d[0] max_diamond[d[0]] = d[3] @@ -90,7 +83,6 @@ def _hooks(self): while True: potential_min = H.neighbors_in(min_elmt) - potential_max = H.neighbors_out(max_elmt) # Check if any of these make a longer double tailed diamond @@ -131,12 +123,12 @@ def _hooks(self): poset_hooks = {self._vertex_to_element(key): value for (key, value) in hooks.items()} return poset_hooks - + def get_hook(self, elmt): r""" - Get the hook length of a specific element. + Return the hook length of the element ``elmt``. - TESTS:: + EXAMPLES:: sage: from sage.combinat.posets.d_complete import DCompletePoset sage: P = DCompletePoset(DiGraph({0: [1], 1: [2]})) @@ -146,20 +138,19 @@ def get_hook(self, elmt): return self._hooks[elmt] def get_hooks(self): - """ - Get all the hook lengths returned in a dictionary - - TESTS:: + r""" + Return all the hook lengths as a dictionary. + + EXAMPLES:: sage: from sage.combinat.posets.d_complete import DCompletePoset sage: P = DCompletePoset(DiGraph({0: [1, 2], 1: [3], 2: [3], 3: []})) sage: P.get_hooks() {0: 1, 1: 2, 2: 2, 3: 3} sage: from sage.combinat.posets.poset_examples import Posets - sage: P = DCompletePoset(Posets.YoungDiagramPoset(Partition([3,2,1]))._hasse_diagram.reverse()) + sage: P = DCompletePoset(Posets.YoungDiagramPoset(Partition([3,2,1]))._hasse_diagram.reverse()) sage: P.get_hooks() {0: 5, 1: 3, 2: 1, 3: 3, 4: 1, 5: 1} - """ return dict(self._hooks) - \ No newline at end of file + diff --git a/src/sage/combinat/posets/forest.py b/src/sage/combinat/posets/forest.py index 1f1adeee9ca..5dac3005a98 100644 --- a/src/sage/combinat/posets/forest.py +++ b/src/sage/combinat/posets/forest.py @@ -1,3 +1,11 @@ +r""" +Forest Posets + +AUTHORS: + +- Stefan Grosser (06-2020): initial implementation +""" + # **************************************************************************** # Copyright (C) 2020 Stefan Grosser # @@ -10,14 +18,13 @@ from sage.combinat.posets.posets import Poset, FinitePoset from sage.misc.lazy_attribute import lazy_attribute -from .linear_extensions import LinearExtensionsOfForest +from sage.combinat.posets.linear_extensions import LinearExtensionsOfForest class ForestPoset(FinitePoset): r""" - A forest poset is a poset where the underlying Hasse diagram and is - directed acyclic graph. - + A forest poset is a poset where the underlying Hasse diagram and is + directed acyclic graph. """ - _lin_ext_type = LinearExtensionsOfForest _desc = 'Finite forest poset' + diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index 36e28c7cfe4..aada410cf31 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -1155,7 +1155,7 @@ def order_ideal(self, elements): def order_ideal_cardinality(self, elements): r""" - Return the cardinality of the order ideal generated by a list of elements. + Return the cardinality of the order ideal generated by ``elements``. `I` is an order ideal if, for any `x` in `I` and `y` such that `y \le x`, then `y` is in `I`. @@ -1176,7 +1176,7 @@ def order_ideal_cardinality(self, elements): size += 1 seen.add(v) q.extend(self.neighbors_in(v)) - + return size def principal_order_ideal(self, i): @@ -2284,18 +2284,26 @@ def chains(self, element_class=list, exclude=None): def diamonds(self): r""" - Return in a tuple - - a list of all diamonds in the Hasse Diagram, - - a Boolean checking that every w,x,y that form a ``V``, there is a unique element z - which completes the diamond. - - For a diamond + Return the list of diamonds of ``self``. + + A diamond is the following subgraph of the Hasse diagram:: + z / \ x y \ / w - the format would be (w, x, y, z). + + Thus each edge represents a cover relation in the Hasse diagram. + We represent his as the tuple `(w, x, y, z)`. + + OUTPUT: + + A tuple with + + - a list of all diamonds in the Hasse Diagram, + - a boolean checking that every `w,x,y` that form a ``V``, there is a + unique element `z`, which completes the diamond. EXAMPLES:: @@ -2303,14 +2311,11 @@ def diamonds(self): sage: H = HasseDiagram({0: [1,2], 1: [3], 2: [3], 3: []}) sage: H.diamonds() ([(0, 1, 2, 3)], True) - - TESTS:: - sage: from sage.combinat.posets.hasse_diagram import HasseDiagram sage: P = posets.YoungDiagramPoset(Partition([3, 2, 2])) sage: H = P._hasse_diagram sage: H.diamonds() - ([(0, 1, 3, 4), (3, 4, 5, 6)], False) + ([(0, 1, 3, 4), (3, 4, 5, 6)], False) """ diamonds = [] all_diamonds_completed = True @@ -2324,28 +2329,26 @@ def diamonds(self): for z in zs: diamonds.append((w, x, y, z)) return (diamonds, all_diamonds_completed) - + def common_upper_covers(self, vertices): r""" - Return the list of all common upper covers of a list of vertices + Return the list of all common upper covers of ``vertices``. EXAMPLES:: - + sage: from sage.combinat.posets.hasse_diagram import HasseDiagram sage: H = HasseDiagram({0: [1,2], 1: [3], 2: [3], 3: []}) sage: H.common_upper_covers([1, 2]) [3] - + sage: from sage.combinat.posets.poset_examples import Posets sage: H = Posets.YoungDiagramPoset(Partition([3, 2, 2]))._hasse_diagram sage: H.common_upper_covers([4, 5]) [6] """ covers = set(self.neighbors_out(vertices.pop())) - for v in vertices: covers = covers.intersection(self.neighbors_out(v)) - return list(covers) def _trivial_nonregular_congruence(self): diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index 022bc73e8db..674f2b39a76 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -7,6 +7,7 @@ - :class:`LinearExtensionOfPoset` - :class:`LinearExtensionsOfPoset` - :class:`LinearExtensionsOfPosetWithHooks` +- :class:`LinearExtensionsOfForest` Classes and methods ------------------- @@ -848,16 +849,15 @@ def _element_constructor_(self, lst, check=True): class LinearExtensionsOfPosetWithHooks(LinearExtensionsOfPoset): r""" - A subclass of ``LinearExtensionOfPoset`` where the poset - has well-defined hook lengths (ie. d-complete). + Linear extensions such that the poset has well-defined + hook lengths (i.e., d-complete). """ - def cardinality(self): r""" - Count the number of linear extensions using a hook-length formula - - TESTS:: - + Count the number of linear extensions using a hook-length formula. + + EXAMPLES:: + sage: from sage.combinat.posets.d_complete import DComplete sage: from sage.combinat.posets.poset_examples import Posets sage: P = Posets.YoungDiagramPoset(Partition([3,2]), dual=True) @@ -865,26 +865,24 @@ def cardinality(self): 5 """ num_elmts = self._poset.cardinality() - + if num_elmts == 0: return 1 - + hooks = self._poset.get_hooks() hook_product = prod(hooks.values()) return factorial(num_elmts) // hook_product class LinearExtensionsOfForest(LinearExtensionsOfPoset): r""" - A subclass of ``LinearExtensionOfPoset`` where the poset - is a forest. + Linear extensions such that the poset is a forest. """ - def cardinality(self): r""" - Use Atkinson's algorithm to compute the number of linear extensions - - TESTS:: - + Use Atkinson's algorithm to compute the number of linear extensions. + + EXAMPLES:: + sage: from sage.combinat.posets.forest import ForestPoset sage: from sage.combinat.posets.poset_examples import Posets sage: P = Poset({0: [2], 1: [2], 2: [3, 4], 3: [], 4: []}) @@ -896,4 +894,4 @@ def cardinality(self): 140 """ return sum(self.atkinson(self._elements[0])) - \ No newline at end of file + diff --git a/src/sage/combinat/posets/mobile.py b/src/sage/combinat/posets/mobile.py deleted file mode 100644 index 4a3636aa1cc..00000000000 --- a/src/sage/combinat/posets/mobile.py +++ /dev/null @@ -1,32 +0,0 @@ -# **************************************************************************** -# Copyright (C) 2020 Stefan Grosser -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# https://www.gnu.org/licenses/ -# **************************************************************************** - -from sage.combinat.posets.posets import Poset, FinitePoset -from sage.combinat.posets.d_complete import DCompletePoset -from sage.misc.lazy_attribute import lazy_attribute -#from .linear_extensions import LinearExtensionsOfForest - -class MobilePoset(FinitePoset): - r""" - Mobile posets are an extension of d-complete posets which permit a determinant - formula for counting linear extensions. - - """ - - #_lin_ext_type = LinearExtensionsOfForest - _desc = 'Finite mobile poset' - - def _compute_mobile_structure(self): - pass - - - - - diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index 7ee6613f0b8..ccb831771aa 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -1382,38 +1382,42 @@ def YoungDiagramPoset(lam, dual=False): INPUT: - ``lam`` -- a partition - - - ``dual`` -- Determines the orientation of the poset + - ``dual`` -- (default: ``False``) determines the orientation + of the poset; if ``True``, then it is a join semilattice, + otherwise it is a meet semilattice EXAMPLES:: - sage: P = posets.YoungDiagramPoset(Partition([2,2])); P + sage: P = posets.YoungDiagramPoset(Partition([2, 2])); P Finite meet-semilattice containing 4 elements sage: sorted(P.cover_relations()) [[(0, 0), (0, 1)], [(0, 0), (1, 0)], [(0, 1), (1, 1)], [(1, 0), (1, 1)]] + + sage: posets.YoungDiagramPoset([3, 2], dual=True) + Finite join-semilattice containing 5 elements """ - def cell_leq(a, b): - """ - Nested function that returns `True` if the cell `a` is - to the left or above - the cell `b` in the (English) Young diagram. - """ - return ((a[0] == b[0] - 1 and a[1] == b[1]) or - (a[1] == b[1] - 1 and a[0] == b[0])) - - def cell_geq(a, b): - """ - Nested function that returns `True` if the cell `a` is - to the right or below - the cell `b` in the (English) Young diagram. - """ - return ((a[0] == b[0] + 1 and a[1] == b[1]) or - (a[1] == b[1] + 1 and a[0] == b[0])) - + from sage.combinat.partition import Partition + lam = Partition(lam) if dual: + def cell_geq(a, b): + """ + Nested function that returns `True` if the cell `a` is + to the right or below + the cell `b` in the (English) Young diagram. + """ + return ((a[0] == b[0] + 1 and a[1] == b[1]) or + (a[1] == b[1] + 1 and a[0] == b[0])) return JoinSemilattice((lam.cells(), cell_geq), cover_relations=True) else: + def cell_leq(a, b): + """ + Nested function that returns `True` if the cell `a` is + to the left or above + the cell `b` in the (English) Young diagram. + """ + return ((a[0] == b[0] - 1 and a[1] == b[1]) or + (a[1] == b[1] - 1 and a[0] == b[0])) return MeetSemilattice((lam.cells(), cell_leq), cover_relations=True) @staticmethod @@ -1551,9 +1555,9 @@ def YoungFibonacci(n): @staticmethod def DoubleTailedDiamond(n): r""" - Return a double-tailed diamond of 2n + 2 elements + Return a double-tailed diamond of `2n + 2` elements. - Input: + INPUT: - ``n`` -- a positive integer @@ -1570,16 +1574,13 @@ def DoubleTailedDiamond(n): raise TypeError("number of elements must be an integer, not {}".format(n)) if n <= 0: raise ValueError("number of elements must be nonnegative, not {}".format(n)) - - edges = [(i,i+1) for i in range(1, n)] + + edges = [(i, i+1) for i in range(1, n)] edges.extend([(n, n+1), (n, n+2), (n+1, n+3), (n+2, n+3)]) edges.extend([(i, i+1) for i in range(n+3, 2*n+2)]) p = DiGraph([list(range(1, 2*n + 3)), edges]) - return DCompletePoset(p) - - @staticmethod def PermutationPattern(n): r""" diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 07b4d8e2c9a..9e04daddfdd 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -923,7 +923,7 @@ class contains. For example, for this class, ``FinitePoset``, """ _lin_ext_type = LinearExtensionsOfPoset _desc = 'Finite poset' - + # The parsing of the construction data (like a list of cover relations) # into a :class:`DiGraph` is done in :func:`Poset`. @staticmethod @@ -1372,6 +1372,10 @@ def _repr_(self): sage: P5 = Poset(partitions_of_five) sage: P5._repr_() 'Finite poset containing 7 elements' + + sage: M = MeetSemilattice([[1,2],[3],[3]]) + sage: M._repr_() + 'Finite meet-semilattice containing 3 elements' """ s = "%s containing %s elements" % (self._desc, self._hasse_diagram.order()) if self._with_linear_extension: @@ -2234,39 +2238,43 @@ def relations(self): def diamonds(self): r""" - Returns in a tuple - - a list of all diamonds in the Hasse Diagram, - - a Boolean checking that every w,x,y that form a ``V``, there is a unique element z - which completes the diamond. - - For a diamond + Return the list of diamonds of ``self``. + + A diamond is the following subgraph of the Hasse diagram:: + z / \ x y \ / w - the format would be (w, x, y, z). + + Thus each edge represents a cover relation in the Hasse diagram. + We represent his as the tuple `(w, x, y, z)`. + + OUTPUT: + + A tuple with + + - a list of all diamonds in the Hasse Diagram, + - a boolean checking that every `w,x,y` that form a ``V``, there is a + unique element `z`, which completes the diamond. EXAMPLES:: sage: P = Poset({0: [1,2], 1: [3], 2: [3], 3: []}) sage: P.diamonds() ([(0, 1, 2, 3)], True) - - TESTS:: sage: P = posets.YoungDiagramPoset(Partition([3, 2, 2])) sage: P.diamonds() ([((0, 0), (0, 1), (1, 0), (1, 1)), ((1, 0), (1, 1), (2, 0), (2, 1))], False) - """ - diamonds, all_diamonds_completed = self._hasse_diagram.diamonds() return ([tuple(map(self._vertex_to_element, d)) for d in diamonds], all_diamonds_completed) def common_upper_covers(self, elmts): r""" - Return the list of all common upper covers of a list of elemements + Return all of the common upper covers of the elements ``elmts``. EXAMPLES:: @@ -2276,49 +2284,52 @@ def common_upper_covers(self, elmts): """ vertices = list(map(self._element_to_vertex, elmts)) return list(map(self._vertex_to_element, self._hasse_diagram.common_upper_covers(vertices))) - + def is_d_complete(self): r""" - Return True if a poset is d-complete. Otherwise, return False. - - TESTS:: - + Return ``True`` if a poset is d-complete and ``False`` otherwise. + + .. SEEALSO:: + + - :mod:`~sage.combinat.posets.d_complete` + + EXAMPLES:: + sage: from sage.combinat.posets.posets import FinitePoset sage: A = Poset({0: [1,2]}) sage: A.is_d_complete() False - + sage: from sage.combinat.posets.poset_examples import Posets sage: B = Posets.DoubleTailedDiamond(3) sage: B.is_d_complete() True - + sage: C = Poset({0: [2], 1: [2], 2: [3, 4], 3: [5], 4: [5], 5: [6]}) sage: C.is_d_complete() False - + sage: D = Poset({0: [1, 2], 1: [4], 2: [4], 3: [4]}) sage: D.is_d_complete() False - + sage: P = Posets.YoungDiagramPoset(Partition([3, 2, 2]), dual=True) sage: P.is_d_complete() True """ - min_diamond = {} # Maps max of double-tailed diamond to min of double-tailed diamond max_diamond = {} # Maps min of double-tailed diamond to max of double-tailed diamond - + H = self._hasse_diagram diamonds, all_diamonds_completed = H.diamonds() # Tuples of four elements that are diamonds - + if not all_diamonds_completed: return False - + diamond_index = {} # Map max elmt of double tailed diamond to index of diamond - # Find all the double-tailed diamonds and map the mins and maxes. + # Find all the double-tailed diamonds and map the mins and maxes for index, d in enumerate(diamonds): min_diamond[d[3]] = d[0] max_diamond[d[0]] = d[3] @@ -2326,33 +2337,31 @@ def is_d_complete(self): min_elmt = d[0] max_elmt = d[3] - + if len(H.neighbors_in(max_elmt)) != 2: - # Top of diamond cannot cover anything but the two side elements + # Top of a diamond cannot cover anything but the two side elements return False - + while True: potential_min = H.neighbors_in(min_elmt) potential_max = H.neighbors_out(max_elmt) max_dk_minus = max_elmt - + # Check if any of these make a longer double tailed diamond found_diamond = False for mn in potential_min: if len(H.all_paths(mn, max_dk_minus)) > 2: continue for mx in potential_max: - if len(H.all_paths(mn, mx)) == 2: - if len(H.neighbors_in(mx)) != 1: # Max element covers something outside of double tailed diamond - return False + return False # Success if mx in min_diamond or mn in max_diamond: - # Two double tail diamonds that differ by minimal element + # Two double tail diamonds that differ by minimal element # or the dual - return False + return False min_elmt = mn max_elmt = mx @@ -2362,7 +2371,7 @@ def is_d_complete(self): found_diamond = True if not found_diamond: break - + return True def intervals_poset(self): @@ -6393,13 +6402,13 @@ def order_ideal(self, elements): vertices = [self._element_to_vertex(_) for _ in elements] oi = self._hasse_diagram.order_ideal(vertices) return [self._vertex_to_element(_) for _ in oi] - + def order_ideal_cardinality(self, elements): r""" - Return the cardinality of the order ideal generated by a list of elements. + Return the cardinality of the order ideal generated by ``elements``. - `I` is an order ideal if, for any `x` in `I` and `y` such that - `y \le x`, then `y` is in `I`. + The elements `I` is an order ideal if, for any `x \in I` and `y` + such that `y \le x`, then `y \in I`. EXAMPLES:: From 20816a8f4e3c4016cf616be52208e1efea9b5b7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Philippe=20Labb=C3=A9?= Date: Mon, 20 Jul 2020 11:36:51 +0200 Subject: [PATCH 141/217] Fix tests and comments --- .../hyperplane_arrangement/arrangement.py | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index fad72747bcb..744291a255f 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -382,7 +382,7 @@ def __init__(self, parent, hyperplanes, check=True, backend=None): to check input - ``backend`` -- string (optional; default: ``None``); the backend to - use for the related polyhedral objects. + use for the related polyhedral objects EXAMPLES:: @@ -399,7 +399,7 @@ def __init__(self, parent, hyperplanes, check=True, backend=None): sage: A = H(sqrt5*x+2*y+3*z, backend='normaliz') sage: A.backend() 'normaliz' - sage: A.regions()[0].backend() + sage: A.regions()[0].backend() # optional - pynormaliz 'normaliz' """ super(HyperplaneArrangementElement, self).__init__(parent) @@ -579,11 +579,11 @@ def rank(self): def backend(self): """ - Return the backend used for polyhedral objects. + Return the backend used for polyhedral objects OUTPUT: - A string giving the backend or None (default) + A string giving the backend or ``None`` if none is specified. EXAMPLES: @@ -1653,8 +1653,8 @@ def _make_region(self, hyperplanes): Checks that it creates the regions with the appropriate backend:: - sage: h = H(x,backend='normaliz') - sage: h._make_region([x, 1-x, y, 1-y]).backend() + sage: h = H(x,backend='normaliz') # optional - pynormaliz + sage: h._make_region([x, 1-x, y, 1-y]).backend() # optional - pynormaliz 'normaliz' """ ieqs = [h.dense_coefficient_list() for h in hyperplanes] @@ -1730,10 +1730,10 @@ def regions(self): sage: K. = CyclotomicField(9) sage: L. = NumberField((q+q**(-1)).minpoly(),embedding = AA(q+q**-1)) - sage: norms = [[1,1/3*(-2*r9**2-r9+1),0], \ - [1,-r9**2-r9,0], \ - [1,-r9**2+1,0], \ - [1,-r9**2,0], \ + sage: norms = [[1,1/3*(-2*r9**2-r9+1),0], + [1,-r9**2-r9,0], + [1,-r9**2+1,0], + [1,-r9**2,0], [1,r9**2-4,-r9**2+3]] sage: H. = HyperplaneArrangements(L) sage: A = H(backend='normaliz') @@ -3296,8 +3296,9 @@ def __init__(self, base_ring, names=tuple()): sage: K = HyperplaneArrangements(QQ) sage: TestSuite(K).run() """ - from sage.categories.all import Fields, Sets - if base_ring not in Fields: + from sage.categories.all import Sets + from sage.rings.ring import _Fields + if base_ring not in _Fields: raise ValueError('base ring must be a field') super(HyperplaneArrangements, self).__init__(category=Sets()) self._base_ring = base_ring From 4a396298d78588463356c01806c2095bf4ce1dda Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Mon, 20 Jul 2020 14:37:03 +0200 Subject: [PATCH 142/217] Trac #30108: use super() --- src/sage/manifolds/differentiable/mixed_form.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/manifolds/differentiable/mixed_form.py b/src/sage/manifolds/differentiable/mixed_form.py index 5bb1ffe3d0c..b479b16455c 100644 --- a/src/sage/manifolds/differentiable/mixed_form.py +++ b/src/sage/manifolds/differentiable/mixed_form.py @@ -595,7 +595,7 @@ def _richcmp_(self, other, op): # Compare all elements separately: return all(self[j] == other[j] for j in self.irange()) # Fall back on default implementation: - return AlgebraElement._richcmp_(self, other, op) + return super()._richcmp_(self, other, op) def _add_(self, other): r""" From acaaa7fbb60c891ba80ecf504430a7c68c99dad9 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Mon, 20 Jul 2020 15:34:34 +0200 Subject: [PATCH 143/217] Trac #30094: starting index corrected --- src/sage/tensor/modules/finite_rank_free_module.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/tensor/modules/finite_rank_free_module.py b/src/sage/tensor/modules/finite_rank_free_module.py index b746c91b81a..72a0dd7dede 100644 --- a/src/sage/tensor/modules/finite_rank_free_module.py +++ b/src/sage/tensor/modules/finite_rank_free_module.py @@ -2540,15 +2540,15 @@ def isomorphism_with_fixed_basis(self, basis, codomain=None): EXAMPLES:: - sage: self = V = FiniteRankFreeModule(QQ, 3); V + sage: V = FiniteRankFreeModule(QQ, 3, start_index=1); V 3-dimensional vector space over the Rational Field sage: basis = e = V.basis("e"); basis - Basis (e_0,e_1,e_2) on the 3-dimensional vector space over the + Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the Rational Field sage: phi_e = V.isomorphism_with_fixed_basis(basis); phi_e Generic morphism: From: 3-dimensional vector space over the Rational Field - To: Free module generated by {'e_0', 'e_1', 'e_2'} over + To: Free module generated by {'e_1', 'e_2', 'e_3'} over Rational Field sage: phi_e.codomain().category() Category of finite dimensional vector spaces with basis over @@ -2592,7 +2592,7 @@ def _isomorphism(x): r""" Concrete isomorphism from ``self`` to ``codomain``. """ - return codomain.sum(x[basis, i] * codomain_basis[i] + return codomain.sum(x[basis, i] * codomain_basis[i - self._sindex] for i in self.irange()) return ModuleMorphismFromFunction(self, _isomorphism, codomain, From 927b707aa4cd44e76484a5bfc80057c879838e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Philippe=20Labb=C3=A9?= Date: Mon, 20 Jul 2020 16:30:02 +0200 Subject: [PATCH 144/217] added dots --- src/sage/geometry/hyperplane_arrangement/arrangement.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index 744291a255f..b46759c0d04 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -1731,10 +1731,10 @@ def regions(self): sage: K. = CyclotomicField(9) sage: L. = NumberField((q+q**(-1)).minpoly(),embedding = AA(q+q**-1)) sage: norms = [[1,1/3*(-2*r9**2-r9+1),0], - [1,-r9**2-r9,0], - [1,-r9**2+1,0], - [1,-r9**2,0], - [1,r9**2-4,-r9**2+3]] + ....: [1,-r9**2-r9,0], + ....: [1,-r9**2+1,0], + ....: [1,-r9**2,0], + ....: [1,r9**2-4,-r9**2+3]] sage: H. = HyperplaneArrangements(L) sage: A = H(backend='normaliz') sage: for v in norms: From d4dbeae4e223fe0d2cdd8d2f2fd8c38a0f772e3d Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 6 Jul 2020 12:06:53 +0100 Subject: [PATCH 145/217] remove sagenb docs --- src/doc/.gitignore | 2 - src/doc/Makefile | 2 - src/doc/de/tutorial/interactive_shell.rst | 106 +---- src/doc/en/developer/doctesting.rst | 2 - src/doc/en/developer/index.rst | 8 - .../developer/sagenb/development_workflow.rst | 415 ------------------ .../en/developer/sagenb/following_latest.rst | 36 -- src/doc/en/developer/sagenb/forking_hell.rst | 33 -- src/doc/en/developer/sagenb/git_links.inc | 60 --- .../developer/sagenb/github_development.rst | 15 - src/doc/en/developer/sagenb/index.rst | 61 --- .../en/developer/sagenb/known_projects.inc | 41 -- src/doc/en/developer/sagenb/links.inc | 4 - .../developer/sagenb/maintainer_workflow.rst | 96 ---- src/doc/en/developer/sagenb/patching.rst | 143 ------ src/doc/en/developer/sagenb/set_up_fork.rst | 68 --- src/doc/en/developer/sagenb/this_project.inc | 5 - src/doc/en/faq/faq-usage.rst | 7 - src/doc/en/prep/Intro-Tutorial.rst | 206 +-------- src/doc/en/prep/Logging-On.rst | 192 +------- src/doc/en/reference/conf.py | 6 +- src/doc/en/reference/index.rst | 1 - src/doc/en/reference/repl/index.rst | 1 - src/doc/en/thematic_tutorials/sws2rst.rst | 99 ----- src/doc/en/tutorial/interactive_shell.rst | 92 +--- src/doc/ja/tutorial/interactive_shell.rst | 87 +--- src/doc/pt/tutorial/interactive_shell.rst | 96 +--- src/doc/ru/tutorial/interactive_shell.rst | 77 +--- t | 7 + 29 files changed, 24 insertions(+), 1944 deletions(-) delete mode 100644 src/doc/en/developer/sagenb/development_workflow.rst delete mode 100644 src/doc/en/developer/sagenb/following_latest.rst delete mode 100644 src/doc/en/developer/sagenb/forking_hell.rst delete mode 100644 src/doc/en/developer/sagenb/git_links.inc delete mode 100644 src/doc/en/developer/sagenb/github_development.rst delete mode 100644 src/doc/en/developer/sagenb/index.rst delete mode 100644 src/doc/en/developer/sagenb/known_projects.inc delete mode 100644 src/doc/en/developer/sagenb/links.inc delete mode 100644 src/doc/en/developer/sagenb/maintainer_workflow.rst delete mode 100644 src/doc/en/developer/sagenb/patching.rst delete mode 100644 src/doc/en/developer/sagenb/set_up_fork.rst delete mode 100644 src/doc/en/developer/sagenb/this_project.inc delete mode 100644 src/doc/en/thematic_tutorials/sws2rst.rst create mode 100755 t diff --git a/src/doc/.gitignore b/src/doc/.gitignore index a52195617d8..dd2abbd9cf1 100644 --- a/src/doc/.gitignore +++ b/src/doc/.gitignore @@ -1,7 +1,5 @@ /en/reference/*/sage -/en/reference/*/sagenb /en/reference/sage -/en/reference/sagenb /en/reference/spkg/*.rst /output /en/installation/*.txt diff --git a/src/doc/Makefile b/src/doc/Makefile index 5160e35cc71..de8689b56ea 100644 --- a/src/doc/Makefile +++ b/src/doc/Makefile @@ -3,7 +3,5 @@ all: @echo "'sage -docbuild all html'. See 'sage -docbuild help' for more informations." clean: rm -rf en/reference/*/sage - rm -rf en/reference/*/sagenb rm -rf en/reference/sage - rm -rf en/reference/sagenb rm -f common/*.pyc diff --git a/src/doc/de/tutorial/interactive_shell.rst b/src/doc/de/tutorial/interactive_shell.rst index 6af196a271a..71fc309e4df 100644 --- a/src/doc/de/tutorial/interactive_shell.rst +++ b/src/doc/de/tutorial/interactive_shell.rst @@ -875,110 +875,6 @@ Variable ``b`` wurde nicht überschrieben. Die Notebook Umgebung ===================== -Folgendes beschreibt das alte Sage Browser Notebook, auch "sagenb" genannt. - SageMath wird demnächst die `Jupyter notebook `_ -als Hauptnotebookoption verwenden. Der wichtigste -Unterschied hier liegt darin, dass die einzelnen Worksheet-Dateien -nicht auf einem Server wohnen, sondern werden wie in üblichen -Anwendungen gespeichert. - - -Altes SageNB Notebook ----------------------- - -**Der Befehl notebook() wurde entfernt. Verwenden Sie die Option ``-n``, während Sie Sage aus Shell starten, und wählen Sie dann SageNB** - -Das Sage Browser Notebook wird mit - -.. skip - -:: - - sage: notebook() - -in der Sage Kommandozeile gestartet. Der Befehl startet das Sage -Notebook und ebenso Ihren Standardbrowser. Die Serverstatus-Dateien -liegen unter ``$HOME/.sage/sage\_notebook.sagenb``. - -Die andere Optionen enthalten z.B. - -.. skip - -:: - - sage: notebook("Verzeichnis") - -was einen neuen Notebook Server mit den Dateien aus dem angegebenen Verzeichnis -``Verzeichnis.sagenb`` -startet (anstelle des Standardverzeichnises ``$HOME/.sage/sage_notebook.sagenb``). -Das kann hilfreich sein, wenn Sie einige Worksheets für ein Projekt oder -verschiedene gleichzeitig laufende Notebook Server von einander trennen wollen. - -Wenn Sie das Notebook starten, werden zuerst die folgenden Dateien erzeugt -in ``$HOME/.sage/sage_notebook.sagenb``: - -:: - - conf.pickle - openid.pickle - twistedconf.tac - sagenb.pid - users.pickle - home/admin/ (Das Verzeichnis für den Hauptbenutzer) - home/guest/ (Ein Verzeichnis für Gäste) - home/pub/ (Ein Verzeichnis für veröffentlichte Worksheets) - -Nach dem Anlegen dieser Dateien, startet das notebook als Webserver. - -Ein "Notebook" ist eine Sammlung von Benutzerkonten, von dem jedes -verschiedene Worksheets enthalten kann. Wenn Sie ein neues Worksheet -erstellen, werden alle zugehörigen Daten unter -``home/benutzer/nummer`` gespeichert. In jedem solchen -Verzeichnis ist eine Klartextdatei namens ``worksheet.html`` - sollte -mit Ihren Worksheets oder Sage irgendetwas Unvorhergesehenes -passieren, enthält diese Datei alles was Sie benötigen um Ihre -Worksheets wiederherzustellen. Das Verzeichnis enthält: - -:: - - cells/ - worksheet.html - data/ - worksheet_conf.pickle - -Innerhalb von Sage können Sie mit ``notebook?`` mehr Informationen zum Start eines -Notebook-Servers erhalten. - -Das folgende Diagramm veranschaulicht die Architektur eines Sage Notebooks. - -:: - - ---------------------- - | | - | | - | firefox/safari | - | | - | javascript | - | programm | - | | - | | - ---------------------- - | ^ - | AJAX | - V | - ---------------------- - | | - | sage | SAGE Prozess 1 - | web | ------------> SAGE Prozess 2 (Python Prozesse) - | server | pexpect SAGE Prozess 3 - | | . - | | . - ---------------------- . - -Um Hilfe zu einem Sage-Befehl ``befehl`` im Notebook-Browser zu bekommen -geben Sie ``befehl?`` ein und drücken Sie ```` (nicht ````). - -Für Informationen zu Tastenbefehlen des Notebook-Browsers klicken Sie auf -den ``Help`` Link. +als Hauptnotebookoption verwenden. diff --git a/src/doc/en/developer/doctesting.rst b/src/doc/en/developer/doctesting.rst index 70c715f7c42..773422f1dbc 100644 --- a/src/doc/en/developer/doctesting.rst +++ b/src/doc/en/developer/doctesting.rst @@ -942,8 +942,6 @@ as well as testing the Sage notebook:: [304 tests, 69.0 s] ... -If you want to just run the notebook tests, use the ``--sagenb`` flag instead. - Debugging Tools --------------- diff --git a/src/doc/en/developer/index.rst b/src/doc/en/developer/index.rst index bfedacc3006..dfe9b6024c0 100644 --- a/src/doc/en/developer/index.rst +++ b/src/doc/en/developer/index.rst @@ -160,14 +160,6 @@ Packaging Third-Party Code packaging -Sage Notebook Developer Guide -============================= - -.. toctree:: - :maxdepth: 3 - - sagenb/index - Indices and tables ================== diff --git a/src/doc/en/developer/sagenb/development_workflow.rst b/src/doc/en/developer/sagenb/development_workflow.rst deleted file mode 100644 index 75c9fdccc08..00000000000 --- a/src/doc/en/developer/sagenb/development_workflow.rst +++ /dev/null @@ -1,415 +0,0 @@ -.. _development-workflow: - -#################### -Development Workflow -#################### - -You already have your own forked copy of the `Sage Notebook`_ repository, by -following :ref:`forking`. You have :ref:`set-up-fork`. You have configured -git by following :ref:`section-git-configuration`. Now you are ready for some real work. - -Workflow Summary -================ - -In what follows we'll refer to the upstream Sage Notebook ``master`` branch, as -"trunk". - -* Don't use your ``master`` branch for anything. Consider deleting it. -* When you are starting a new set of changes, fetch any changes from trunk, - and start a new *feature branch* from that. -* Make a new branch for each separable set of changes |emdash| "one task, one - branch" (`ipython git workflow`_). -* Name your branch for the purpose of the changes - e.g. - ``bugfix-for-issue-14`` or ``refactor-database-code``. -* If you can possibly avoid it, avoid merging trunk or any other branches into - your feature branch while you are working. -* If you do find yourself merging from trunk, consider :ref:`rebase-on-trunk` -* Ask on the `Sage Notebook mailing list`_ if you get stuck. -* Ask for code review! - -This way of working helps to keep work well organized, with readable history. -This in turn makes it easier for project maintainers (that might be you) to see -what you've done, and why you did it. - -See `linux git workflow`_ and `ipython git workflow`_ for some explanation. - -Consider Deleting Your Master Branch -==================================== - -It may sound strange, but deleting your own ``master`` branch can help reduce -confusion about which branch you are on. See `deleting master on github`_ for -details. - -.. _update-mirror-trunk: - -Update the Mirror of trunk -========================== - -First make sure you have done :ref:`linking-to-upstream`. - -From time to time you should fetch the upstream (trunk) changes from github:: - - git fetch upstream - -This will pull down any commits you don't have, and set the remote branches to -point to the right commit. For example, 'trunk' is the branch referred to by -(remote/branchname) ``upstream/master`` - and if there have been commits since -you last checked, ``upstream/master`` will change after you do the fetch. - -.. _make-feature-branch: - -Make a New Feature Branch -========================= - -When you are ready to make some changes to the code, you should start a new -branch. Branches that are for a collection of related edits are often called -'feature branches'. - -Making an new branch for each set of related changes will make it easier for -someone reviewing your branch to see what you are doing. - -Choose an informative name for the branch to remind yourself and the rest of us -what the changes in the branch are for. For example ``add-ability-to-fly``, or -``buxfix-for-issue-42``. - -:: - - # Update the mirror of trunk - git fetch upstream - # Make new feature branch starting at current trunk - git branch my-new-feature upstream/master - git checkout my-new-feature - -Generally, you will want to keep your feature branches on your public github_ -fork of `Sage Notebook`_. To do this, you `git push`_ this new branch up to your -github repo. Generally (if you followed the instructions in these pages, and by -default), git will have a link to your github repo, called ``origin``. You push -up to your own repo on github with:: - - git push origin my-new-feature - -In git >= 1.7 you can ensure that the link is correctly set by using the -``--set-upstream`` option:: - - git push --set-upstream origin my-new-feature - -From now on git will know that ``my-new-feature`` is related to the -``my-new-feature`` branch in the github repo. - -.. _edit-flow: - -The Editing Workflow -==================== - -Overview --------- - -:: - - # hack hack - git add my_new_file - git commit -am 'NF - some message' - git push - -In More Detail --------------- - -#. Make some changes -#. See which files have changed with ``git status`` (see `git status`_). - You'll see a listing like this one:: - - # On branch ny-new-feature - # Changed but not updated: - # (use "git add ..." to update what will be committed) - # (use "git checkout -- ..." to discard changes in working directory) - # - # modified: README - # - # Untracked files: - # (use "git add ..." to include in what will be committed) - # - # INSTALL - no changes added to commit (use "git add" and/or "git commit -a") - -#. Check what the actual changes are with ``git diff`` (`git diff`_). -#. Add any new files to version control ``git add new_file_name`` (see - `git add`_). -#. To commit all modified files into the local copy of your repo,, do - ``git commit -am 'A commit message'``. Note the ``-am`` options to - ``commit``. The ``m`` flag just signals that you're going to type a - message on the command line. The ``a`` flag |emdash| you can just take on - faith |emdash| or see `why the -a flag?`_ |emdash| and the helpful use-case - description in the `tangled working copy problem`_. The `git commit`_ manual - page might also be useful. -#. To push the changes up to your forked repo on github, do a ``git - push`` (see `git push`_). - -Ask for Your Changes to be Reviewed or Merged -============================================= - -When you are ready to ask for someone to review your code and consider a merge: - -#. Go to the URL of your forked repo, say - ``http://github.com/your-user-name/sagenb``. -#. Use the 'Switch Branches' dropdown menu near the top left of the page to - select the branch with your changes: - - .. image:: branch_dropdown.png - -#. Click on the 'Pull request' button: - - .. image:: pull_button.png - - Enter a title for the set of changes, and some explanation of what you've - done. Say if there is anything you'd like particular attention for - like a - complicated change or some code you are not happy with. - - If you don't think your request is ready to be merged, just say so in your - pull request message. This is still a good way of getting some preliminary - code review. - -Some Other Things You Might Want to Do -====================================== - -Delete a Branch on Github -------------------------- - -:: - - git checkout master - # delete branch locally - git branch -D my-unwanted-branch - # delete branch on github - git push origin :my-unwanted-branch - -(Note the colon ``:`` before ``test-branch``. See also: -http://github.com/guides/remove-a-remote-branch - -Several People Sharing a Single Repository ------------------------------------------- - -If you want to work on some stuff with other people, where you are all -committing into the same repository, or even the same branch, then just -share it via github. - -First fork Sage Notebook into your account, as from :ref:`forking`. - -Then, go to your forked repository github page, say -``http://github.com/your-user-name/sagenb`` - -Click on the 'Admin' button, and add anyone else to the repo as a -collaborator: - - .. image:: pull_button.png - -Now all those people can do:: - - git clone git@githhub.com:your-user-name/sagenb.git - -Remember that links starting with ``git@`` use the ssh protocol and are -read-write; links starting with ``git://`` are read-only. - -Your collaborators can then commit directly into that repo with the -usual:: - - git commit -am 'ENH - much better code' - git push origin master # pushes directly into your repo - -Explore Your Repository ------------------------ - -To see a graphical representation of the repository branches and -commits:: - - gitk --all - -To see a linear list of commits for this branch:: - - git log - -You can also look at the `network graph visualizer`_ for your github -repo. - -Finally the :ref:`section-fancy-log` ``lg`` alias will give you a -reasonable text-based graph of the repository. - -.. _rebase-on-trunk: - -Rebasing on trunk ------------------ - -Let's say you thought of some work you'd like to do. You -:ref:`update-mirror-trunk` and :ref:`make-feature-branch` called -``cool-feature``. At this stage trunk is at some commit, let's call it E. Now -you make some new commits on your ``cool-feature`` branch, let's call them A, B, -C. Maybe your changes take a while, or you come back to them after a while. In -the meantime, trunk has progressed from commit E to commit (say) G:: - - A---B---C cool-feature - / - D---E---F---G trunk - -At this stage you consider merging trunk into your feature branch, and you -remember that this here page sternly advises you not to do that, because the -history will get messy. Most of the time you can just ask for a review, and not -worry that trunk has got a little ahead. But sometimes, the changes in trunk -might affect your changes, and you need to harmonize them. In this situation -you may prefer to do a rebase. - -rebase takes your changes (A, B, C) and replays them as if they had been made to -the current state of ``trunk``. In other words, in this case, it takes the -changes represented by A, B, C and replays them on top of G. After the rebase, -your history will look like this:: - - A'--B'--C' cool-feature - / - D---E---F---G trunk - -See `rebase without tears`_ for more detail. - -To do a rebase on trunk:: - - # Update the mirror of trunk - git fetch upstream - # go to the feature branch - git checkout cool-feature - # make a backup in case you mess up - git branch tmp cool-feature - # rebase cool-feature onto trunk - git rebase --onto upstream/master upstream/master cool-feature - -In this situation, where you are already on branch ``cool-feature``, the last -command can be written more succinctly as:: - - git rebase upstream/master - -When all looks good you can delete your backup branch:: - - git branch -D tmp - -If it doesn't look good you may need to have a look at -:ref:`recovering-from-mess-up`. - -If you have made changes to files that have also changed in trunk, this may -generate merge conflicts that you need to resolve - see the `git rebase`_ man -page for some instructions at the end of the "Description" section. There is -some related help on merging in the git user manual - see `resolving a merge`_. - -.. _recovering-from-mess-up: - -Recovering From Mess-Ups ------------------------- - -Sometimes, you mess up merges or rebases. Luckily, in git it is -relatively straightforward to recover from such mistakes. - -If you mess up during a rebase:: - - git rebase --abort - -If you notice you messed up after the rebase:: - - # reset branch back to the saved point - git reset --hard tmp - -If you forgot to make a backup branch:: - - # look at the reflog of the branch - git reflog show cool-feature - - 8630830 cool-feature@{0}: commit: BUG: io: close file handles immediately - 278dd2a cool-feature@{1}: rebase finished: refs/heads/my-feature-branch onto 11ee694744f2552d - 26aa21a cool-feature@{2}: commit: BUG: lib: make seek_gzip_factory not leak gzip obj - ... - - # reset the branch to where it was before the botched rebase - git reset --hard cool-feature@{2} - -.. _rewriting-commit-history: - -Rewriting Commit History ------------------------- - -.. note:: - - Do this only for your own feature branches. - -There's an embarassing typo in a commit you made? Or perhaps the you -made several false starts you would like the posterity not to see. - -This can be done via *interactive rebasing*. - -Suppose that the commit history looks like this:: - - git log --oneline - eadc391 Fix some remaining bugs - a815645 Modify it so that it works - 2dec1ac Fix a few bugs + disable - 13d7934 First implementation - 6ad92e5 * masked is now an instance of a new object, MaskedConstant - 29001ed Add pre-nep for a copule of structured_array_extensions. - ... - -and ``6ad92e5`` is the last commit in the ``cool-feature`` branch. Suppose we -want to make the following changes: - -* Rewrite the commit message for ``13d7934`` to something more sensible. -* Combine the commits ``2dec1ac``, ``a815645``, ``eadc391`` into a single one. - -We do as follows:: - - # make a backup of the current state - git branch tmp HEAD - # interactive rebase - git rebase -i 6ad92e5 - -This will open an editor with the following text in it:: - - pick 13d7934 First implementation - pick 2dec1ac Fix a few bugs + disable - pick a815645 Modify it so that it works - pick eadc391 Fix some remaining bugs - - # Rebase 6ad92e5..eadc391 onto 6ad92e5 - # - # Commands: - # p, pick = use commit - # r, reword = use commit, but edit the commit message - # e, edit = use commit, but stop for amending - # s, squash = use commit, but meld into previous commit - # f, fixup = like "squash", but discard this commit's log message - # - # If you remove a line here THAT COMMIT WILL BE LOST. - # However, if you remove everything, the rebase will be aborted. - # - -To achieve what we want, we will make the following changes to it:: - - r 13d7934 First implementation - pick 2dec1ac Fix a few bugs + disable - f a815645 Modify it so that it works - f eadc391 Fix some remaining bugs - -This means that (i) we want to edit the commit message for -``13d7934``, and (ii) collapse the last three commits into one. Now we -save and quit the editor. - -Git will then immediately bring up an editor for editing the commit -message. After revising it, we get the output:: - - [detached HEAD 721fc64] FOO: First implementation - 2 files changed, 199 insertions(+), 66 deletions(-) - [detached HEAD 0f22701] Fix a few bugs + disable - 1 files changed, 79 insertions(+), 61 deletions(-) - Successfully rebased and updated refs/heads/my-feature-branch. - -and the history looks now like this:: - - 0f22701 Fix a few bugs + disable - 721fc64 ENH: Sophisticated feature - 6ad92e5 * masked is now an instance of a new object, MaskedConstant - -If it went wrong, recovery is again possible as explained :ref:`above -`. - -.. include:: links.inc diff --git a/src/doc/en/developer/sagenb/following_latest.rst b/src/doc/en/developer/sagenb/following_latest.rst deleted file mode 100644 index 2bc5c374cca..00000000000 --- a/src/doc/en/developer/sagenb/following_latest.rst +++ /dev/null @@ -1,36 +0,0 @@ -.. _following-latest: - -============================= - Following the Latest Source -============================= - -These are the instructions if you just want to follow the latest -*Sage Notebook* source, but you don't need to do any development for now. - -The steps are: - -* :ref:`section-git-install` -* get local copy of the `Sage Notebook github`_ git repository -* update local copy from time to time - -Get the Local Copy of the Code -============================== - -From the command line:: - - git clone git://github.com/sagemath/sagenb.git - -You now have a copy of the code tree in the new ``sagenb`` directory. - -Updating the Code -================= - -From time to time you may want to pull down the latest code. Do this with:: - - cd sagenb - git pull - -The tree in ``sagenb`` will now have the latest changes from the initial -repository. - -.. include:: links.inc diff --git a/src/doc/en/developer/sagenb/forking_hell.rst b/src/doc/en/developer/sagenb/forking_hell.rst deleted file mode 100644 index d33bdfb953f..00000000000 --- a/src/doc/en/developer/sagenb/forking_hell.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. _forking: - -====================================================== -Making Your Own Copy (Fork) of Sage Notebook -====================================================== - -You need to do this only once. The instructions here are very similar -to the instructions at http://help.github.com/forking/ |emdash| please see -that page for more detail. We're repeating some of it here just to give the -specifics for the `Sage Notebook`_ project, and to suggest some default names. - -Set Up and Configure a Github Account -===================================== - -If you don't have a github account, go to the github page, and make one. - -You then need to configure your account to allow write access |emdash| see -the ``Generating SSH keys`` help on `github help`_. - -Create Your Own Forked Copy of `Sage Notebook`_ -====================================================== - -#. Log into your github account. -#. Go to the `Sage Notebook`_ github home at `Sage Notebook github`_. -#. Click on the *fork* button: - - .. image:: forking_button.png - - Now, after a short pause, you should find yourself at the home - page for your own forked copy of `Sage Notebook`_. - -.. include:: links.inc - diff --git a/src/doc/en/developer/sagenb/git_links.inc b/src/doc/en/developer/sagenb/git_links.inc deleted file mode 100644 index bbaeda39dab..00000000000 --- a/src/doc/en/developer/sagenb/git_links.inc +++ /dev/null @@ -1,60 +0,0 @@ -.. This (-*- rst -*-) format file contains commonly used link targets - and name substitutions. It may be included in many files, - therefore it should only contain link targets and name - substitutions. Try grepping for "^\.\. _" to find plausible - candidates for this list. - -.. NOTE: reST targets are - __not_case_sensitive__, so only one target definition is needed for - nipy, NIPY, Nipy, etc... - -.. git stuff -.. _github: http://github.com -.. _github help: http://help.github.com -.. _msysgit: http://code.google.com/p/msysgit/downloads/list -.. _git-osx-installer: http://code.google.com/p/git-osx-installer/downloads/list -.. _subversion: http://subversion.tigris.org/ -.. _git cheat sheet: http://github.com/guides/git-cheat-sheet -.. _pro git book: http://progit.org/ -.. _git svn crash course: http://git-scm.com/course/svn.html -.. _learn.github: http://learn.github.com/ -.. _network graph visualizer: http://github.com/blog/39-say-hello-to-the-network-graph-visualizer -.. _git user manual: http://schacon.github.com/git/user-manual.html -.. _git tutorial: http://schacon.github.com/git/gittutorial.html -.. _git community book: http://book.git-scm.com/ -.. _git ready: http://www.gitready.com/ -.. _git casts: http://www.gitcasts.com/ -.. _Fernando's git page: http://www.fperez.org/py4science/git.html -.. _git magic: http://www-cs-students.stanford.edu/~blynn/gitmagic/index.html -.. _git concepts: http://www.eecs.harvard.edu/~cduan/technical/git/ -.. _git clone: http://schacon.github.com/git/git-clone.html -.. _git checkout: http://schacon.github.com/git/git-checkout.html -.. _git commit: http://schacon.github.com/git/git-commit.html -.. _git push: http://schacon.github.com/git/git-push.html -.. _git pull: http://schacon.github.com/git/git-pull.html -.. _git add: http://schacon.github.com/git/git-add.html -.. _git status: http://schacon.github.com/git/git-status.html -.. _git diff: http://schacon.github.com/git/git-diff.html -.. _git log: http://schacon.github.com/git/git-log.html -.. _git branch: http://schacon.github.com/git/git-branch.html -.. _git remote: http://schacon.github.com/git/git-remote.html -.. _git rebase: http://schacon.github.com/git/git-rebase.html -.. _git config: http://schacon.github.com/git/git-config.html -.. _why the -a flag?: http://www.gitready.com/beginner/2009/01/18/the-staging-area.html -.. _git staging area: http://www.gitready.com/beginner/2009/01/18/the-staging-area.html -.. _tangled working copy problem: http://tomayko.com/writings/the-thing-about-git -.. _git management: http://kerneltrap.org/Linux/Git_Management -.. _linux git workflow: http://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html -.. _git parable: http://tom.preston-werner.com/2009/05/19/the-git-parable.html -.. _git foundation: http://matthew-brett.github.com/pydagogue/foundation.html -.. _deleting master on github: http://matthew-brett.github.com/pydagogue/gh_delete_master.html -.. _rebase without tears: http://matthew-brett.github.com/pydagogue/rebase_without_tears.html -.. _resolving a merge: http://schacon.github.com/git/user-manual.html#resolving-a-merge -.. _ipython git workflow: http://mail.scipy.org/pipermail/ipython-dev/2010-October/006746.html - -.. other stuff -.. _python: http://www.python.org - -.. |emdash| unicode:: U+02014 - -.. vim: ft=rst diff --git a/src/doc/en/developer/sagenb/github_development.rst b/src/doc/en/developer/sagenb/github_development.rst deleted file mode 100644 index 1ae96f3cd79..00000000000 --- a/src/doc/en/developer/sagenb/github_development.rst +++ /dev/null @@ -1,15 +0,0 @@ -.. _github-development: - -===================== - Git for Development -===================== - -Contents: - -.. toctree:: - :maxdepth: 2 - - forking_hell - set_up_fork - development_workflow - maintainer_workflow diff --git a/src/doc/en/developer/sagenb/index.rst b/src/doc/en/developer/sagenb/index.rst deleted file mode 100644 index 5e2a7f9db0c..00000000000 --- a/src/doc/en/developer/sagenb/index.rst +++ /dev/null @@ -1,61 +0,0 @@ -.. _sagenb: - -============================= -Sage Notebook Developer Guide -============================= - - -Development of the Sage notebook currently occurs on Github using the -Git revision control system. The development model for the `Sage -Notebook`_ project is a `git `_ and github_ -workflow. - -To update to the latest development source, run the commands below, -where ``SAGE_ROOT`` is the root directory of the Sage installation, -and where ``hackdir`` is a directory you create for working on code -changes (it need not have the name or location given below). - -.. warning:: This will create a new sagenb repository ignoring any - changes you have made to the files. - -:: - - mkdir ~/hackdir - cd ~/hackdir - git clone git://github.com/sagemath/sagenb.git sagenb-git - cd SAGE_ROOT/src - rm sagenb - ln -s ~/hackdir/sagenb sagenb - cd sagenb - ../../sage setup.py develop - -What this has done is to create a new directory, move to that -directory, and create a clone of the most up-to-date version of -the upstream notebook sources there. Then we remove a symbolic -link ``sagenb`` in the Sage folder and replace it with a link -to your clone of upstream, finally making sure that the notebook -has the correct dependencies. - -An advantage of having the separate directory for sagenb is that -you would later be able to keep it and do development work in it -even when you upgrade Sage, or even if you accidentally destroy your -Sage installation somehow. - -The rest of these instructions is some very generic documentation, -slightly adapted to help develop the notebook using Git and Github. - -The most important section involves how to update your new sagenb -source repository and create a "fork" of the master copy, so that you -will be able to request your changes to be merged in the Sage notebook, -called a "pull request"; see :ref:`github-development`. - - -.. toctree:: - :maxdepth: 2 - - following_latest - patching - github_development - - -.. include:: links.inc diff --git a/src/doc/en/developer/sagenb/known_projects.inc b/src/doc/en/developer/sagenb/known_projects.inc deleted file mode 100644 index 29723528779..00000000000 --- a/src/doc/en/developer/sagenb/known_projects.inc +++ /dev/null @@ -1,41 +0,0 @@ -.. Known projects - -.. PROJECTNAME placeholders -.. _PROJECTNAME: http://neuroimaging.scipy.org -.. _`PROJECTNAME github`: http://github.com/nipy -.. _`PROJECTNAME mailing list`: http://projects.scipy.org/mailman/listinfo/nipy-devel - -.. numpy -.. _numpy: hhttp://numpy.scipy.org -.. _`numpy github`: http://github.com/numpy/numpy -.. _`numpy mailing list`: http://mail.scipy.org/mailman/listinfo/numpy-discussion - -.. scipy -.. _scipy: http://www.scipy.org -.. _`scipy github`: http://github.com/scipy/scipy -.. _`scipy mailing list`: http://mail.scipy.org/mailman/listinfo/scipy-dev - -.. nipy -.. _nipy: http://nipy.org/nipy -.. _`nipy github`: http://github.com/nipy/nipy -.. _`nipy mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel - -.. ipython -.. _ipython: http://ipython.scipy.org -.. _`ipython github`: http://github.com/ipython/ipython -.. _`ipython mailing list`: http://mail.scipy.org/mailman/listinfo/IPython-dev - -.. dipy -.. _dipy: http://nipy.org/dipy -.. _`dipy github`: http://github.com/Garyfallidis/dipy -.. _`dipy mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel - -.. nibabel -.. _nibabel: http://nipy.org/nibabel -.. _`nibabel github`: http://github.com/nipy/nibabel -.. _`nibabel mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel - -.. marsbar -.. _marsbar: http://marsbar.sourceforge.net -.. _`marsbar github`: http://github.com/matthew-brett/marsbar -.. _`MarsBaR mailing list`: https://lists.sourceforge.net/lists/listinfo/marsbar-users diff --git a/src/doc/en/developer/sagenb/links.inc b/src/doc/en/developer/sagenb/links.inc deleted file mode 100644 index 20f4dcfffd4..00000000000 --- a/src/doc/en/developer/sagenb/links.inc +++ /dev/null @@ -1,4 +0,0 @@ -.. compiling links file -.. include:: known_projects.inc -.. include:: this_project.inc -.. include:: git_links.inc diff --git a/src/doc/en/developer/sagenb/maintainer_workflow.rst b/src/doc/en/developer/sagenb/maintainer_workflow.rst deleted file mode 100644 index fdc1d2cdf50..00000000000 --- a/src/doc/en/developer/sagenb/maintainer_workflow.rst +++ /dev/null @@ -1,96 +0,0 @@ -.. _maintainer-workflow: - -################### -Maintainer Workflow -################### - -This page is for maintainers |emdash| those of us who merge our own or other -peoples' changes into the upstream repository. - -Being as how you're a maintainer, you are completely on top of the basic stuff -in :ref:`development-workflow`. - -The instructions in :ref:`linking-to-upstream` add a remote that has read-only -access to the upstream repo. Being a maintainer, you've got read-write access. - -It's good to have your upstream remote have a scary name, to remind you that -it's a read-write remote:: - - git remote add upstream-rw git@github.com:sagemath/sagenb.git - git fetch upstream-rw - -******************* -Integrating Changes -******************* - -Let's say you have some changes that need to go into trunk -(``upstream-rw/master``). - -The changes are in some branch that you are currently on. For example, you are -looking at someone's changes like this:: - - git remote add someone git://github.com/someone/sagenb.git - git fetch someone - git branch cool-feature --track someone/cool-feature - git checkout cool-feature - -So now you are on the branch with the changes to be incorporated upstream. The -rest of this section assumes you are on this branch. - -A Few Commits -============= - -If there are only a few commits, consider rebasing to upstream:: - - # Fetch upstream changes - git fetch upstream-rw - # rebase - git rebase upstream-rw/master - -Remember that, if you do a rebase, and push that, you'll have to close any -github pull requests manually, because github will not be able to detect the -changes have already been merged. - -A Long Series of Commits -======================== - -If there are a longer series of related commits, consider a merge instead:: - - git fetch upstream-rw - git merge --no-ff upstream-rw/master - -The merge will be detected by github, and should close any related pull requests -automatically. - -Note the ``--no-ff`` above. This forces git to make a merge commit, rather than -doing a fast-forward, so that these set of commits branch off trunk then rejoin -the main history with a merge, rather than appearing to have been made directly -on top of trunk. - -Check the History -================= - -Now, in either case, you should check that the history is sensible and you have -the right commits:: - - git log --oneline --graph - git log -p upstream-rw/master.. - -The first line above just shows the history in a compact way, with a text -representation of the history graph. The second line shows the log of commits -excluding those that can be reached from trunk (``upstream-rw/master``), and -including those that can be reached from current HEAD (implied with the ``..`` -at the end). So, it shows the commits unique to this branch compared to trunk. -The ``-p`` option shows the diff for these commits in patch form. - -Push to trunk -============= - -:: - - git push upstream-rw my-new-feature:master - -This pushes the ``my-new-feature`` branch in this repository to the ``master`` -branch in the ``upstream-rw`` repository. - -.. include:: links.inc diff --git a/src/doc/en/developer/sagenb/patching.rst b/src/doc/en/developer/sagenb/patching.rst deleted file mode 100644 index fb7fc4cbe95..00000000000 --- a/src/doc/en/developer/sagenb/patching.rst +++ /dev/null @@ -1,143 +0,0 @@ -================ - Making a Patch -================ - -You've discovered a bug or something else you want to change -in `Sage Notebook`_ |emdash| excellent! - -You've worked out a way to fix it |emdash| even better! - -You want to tell us about it |emdash| best of all! - -The easiest way is to make a *patch* or set of patches. Here -we explain how. - -Making a patch is simple and quick, but it is not part of our -normal workflow. So if you are going to be doing anything more -than a once-off patch one time, please consider following the -:ref:`github-development` model instead. See especially the part -about "pull requests" at :ref:`edit-flow`. - -.. _making-patches: - -Making Patches -============== - -Overview --------- - -:: - - # tell git who you are - git config --global user.email you@yourdomain.example.com - git config --global user.name "Your Name Comes Here" - # get the repository if you don't have it - git clone git://github.com/sagemath/sagenb.git - # make a branch for your patching - cd sagenb - git branch the-fix-im-thinking-of - git checkout the-fix-im-thinking-of - # hack, hack, hack - # Tell git about any new files you've made - git add somewhere/tests/test_my_bug.py - # commit work in progress as you go - git commit -am 'BF - added tests for Funny bug' - # hack hack, hack - git commit -am 'BF - added fix for Funny bug' - # make the patch files - git format-patch -M -C master - -You may attach a short generated patch file to the `Sage Notebook -mailing list`_ or better, open an issue at the `Sage Notebook github`_ -site (see :ref:`github-development`) and cut and paste your patch in a -comment there. In either case we will thank you warmly. - -In Detail ---------- - -#. Tell git who you are so it can label the commits you've - made:: - - git config --global user.email you@yourdomain.example.com - git config --global user.name "Your Name Comes Here" - -#. If you don't already have one, clone a copy of the - `Sage Notebook`_ repository:: - - git clone git://github.com/sagemath/sagenb.git - cd sagenb - -#. Make a 'feature branch'. This will be where you work on - your bug fix. It's nice and safe and leaves you with - access to an unmodified copy of the code in the main - branch:: - - git branch the-fix-im-thinking-of - git checkout the-fix-im-thinking-of - -#. Do some edits, and commit them as you go:: - - # hack, hack, hack - # Tell git about any new files you've made - git add somewhere/tests/test_my_bug.py - # commit work in progress as you go - git commit -am 'BF - added tests for Funny bug' - # hack hack, hack - git commit -am 'BF - added fix for Funny bug' - - Note the ``-am`` options to ``commit``. The ``m`` flag just - signals that you're going to type a message on the command - line. The ``a`` flag |emdash| you can just take on faith |emdash| - or see `why the -a flag?`_. - -#. When you have finished, check you have committed all your - changes:: - - git status - -#. Finally, make your commits into patches. You want all the - commits since you branched from the ``master`` branch:: - - git format-patch -M -C master - - You will now have several files named for the commits:: - - 0001-BF-added-tests-for-Funny-bug.patch - 0002-BF-added-fix-for-Funny-bug.patch - - Although some projects would have you send these files to - the `Sage Notebook mailing list`_, we prefer submitting an issue - request at the web interface to the `Sage Notebook github`_ - page. See :ref:`edit-flow` for how to create a "pull request" once you - have created a Github account. - -When you are done, to switch back to the main copy of the -code, just return to the ``master`` branch:: - - git checkout master - -Moving from Patching to Development -=================================== - -If you find you have done some patches, and you have one or -more feature branches, you will probably want to switch to -development mode. You can do this with the repository you -have. - -Fork the `Sage Notebook`_ repository on github |emdash| :ref:`forking`. -Then:: - - # checkout and refresh master branch from main repo - git checkout master - git pull origin master - # rename pointer to main repository to 'upstream' - git remote rename origin upstream - # point your repo to default read / write to your fork on github - git remote add origin git@github.com:your-user-name/sagenb.git - # push up any branches you've made and want to keep - git push origin the-fix-im-thinking-of - -Then you can, if you want, follow the -:ref:`development-workflow`. - -.. include:: links.inc diff --git a/src/doc/en/developer/sagenb/set_up_fork.rst b/src/doc/en/developer/sagenb/set_up_fork.rst deleted file mode 100644 index b0c82043b49..00000000000 --- a/src/doc/en/developer/sagenb/set_up_fork.rst +++ /dev/null @@ -1,68 +0,0 @@ -.. _set-up-fork: - -================== -Set Up Your Fork -================== - -First you follow the instructions for :ref:`forking`. - -Overview -======== - -:: - - git clone git@github.com:your-user-name/sagenb.git - cd sagenb - git remote add upstream git://github.com/sagemath/sagenb.git - -In Detail -========= - -Clone Your Fork ---------------- - -#. Clone your fork to the local computer with ``git clone - git@github.com:your-user-name/sagenb.git`` -#. Investigate. Change directory to your new repo: ``cd sagenb``. Then - ``git branch -a`` to show you all branches. You'll get something - like:: - - * master - remotes/origin/master - - This tells you that you are currently on the ``master`` branch, and - that you also have a ``remote`` connection to ``origin/master``. - What remote repository is ``remote/origin``? Try ``git remote -v`` to - see the URLs for the remote. They will point to your github fork. - - Now you want to connect to the upstream `Sage Notebook github`_ repository, so - you can merge in changes from trunk. - -.. _linking-to-upstream: - -Linking Your Repository to the Upstream Repo --------------------------------------------- - -:: - - cd sagenb - git remote add upstream git://github.com/sagemath/sagenb.git - -``upstream`` here is just the arbitrary name we're using to refer to the -main `Sage Notebook`_ repository at `Sage Notebook github`_. - -Note that we've used ``git://`` for the URL rather than ``git@``. The -``git://`` URL is read only. This means we that we can't accidentally -(or deliberately) write to the upstream repo, and we are only going to -use it to merge into our own code. - -Just for your own satisfaction, show yourself that you now have a new -'remote', with ``git remote -v show``, giving you something like:: - - upstream git://github.com/sagemath/sagenb.git (fetch) - upstream git://github.com/sagemath/sagenb.git (push) - origin git@github.com:your-user-name/sagenb.git (fetch) - origin git@github.com:your-user-name/sagenb.git (push) - -.. include:: links.inc - diff --git a/src/doc/en/developer/sagenb/this_project.inc b/src/doc/en/developer/sagenb/this_project.inc deleted file mode 100644 index 3b331f10fa3..00000000000 --- a/src/doc/en/developer/sagenb/this_project.inc +++ /dev/null @@ -1,5 +0,0 @@ -.. Sage Notebook -.. _`Sage Notebook`: http://nb.sagemath.org -.. _`Sage Notebook github`: http://github.com/sagemath/sagenb - -.. _`Sage Notebook mailing list`: http://groups.google.com/group/sage-notebook diff --git a/src/doc/en/faq/faq-usage.rst b/src/doc/en/faq/faq-usage.rst index 44db03050d6..127d24a95e8 100644 --- a/src/doc/en/faq/faq-usage.rst +++ b/src/doc/en/faq/faq-usage.rst @@ -788,13 +788,6 @@ You will need to do this from the command line. Just run a command like this. $ BROWSER='open -a Firefox %s' ./sage --notebook jupyter $ BROWSER='open -a Google\ Chrome %s' ./sage --notebook jupyter - With the old SageNB notebook: - - .. CODE-BLOCK:: shell-session - - $ BROWSER='open -a Firefox' ./sage --notebook - $ BROWSER='open -a Google\ Chrome' ./sage --notebook - Where is the source code for ````? """""""""""""""""""""""""""""""""""""""""""" diff --git a/src/doc/en/prep/Intro-Tutorial.rst b/src/doc/en/prep/Intro-Tutorial.rst index c7624c96070..2febd01ac19 100644 --- a/src/doc/en/prep/Intro-Tutorial.rst +++ b/src/doc/en/prep/Intro-Tutorial.rst @@ -24,7 +24,6 @@ following sections: - :ref:`SageCommands` - See :ref:`SageJupyterCommands` for the Jupyter notebook - - See :ref:`SageNBCommands` for the legacy Sage notebook - :ref:`SageFunctions` @@ -33,7 +32,6 @@ following sections: - :ref:`SageAnnotation` - See :ref:`JupyterAnnotation` for the Jupyter notebook - - See :ref:`SageNBAnnotation` for the legacy Sage notebook This tutorial only introduces the most basic level of functionality. @@ -47,11 +45,7 @@ Evaluating Sage Commands .. rubric:: Or, How do I get Sage to do some math? -We have two parallel subsections here which cover (roughly) the -same content. - - See :ref:`SageJupyterCommands` for the Jupyter notebook -- See :ref:`SageNBCommands` for the legacy Sage notebook .. _SageJupyterCommands: @@ -97,7 +91,7 @@ To do more mathematics, just do the same thing with more cells! .. image:: media/MoreCells.png :align: center -Unlike in the SageNB, one has to learn a variety of keyboard shortcuts +One has to learn a variety of keyboard shortcuts or click on various menu items to manipulate cells. There is a help menu to get you started on this; the Jupyter developers also maintain `an example notebook `_ @@ -106,93 +100,6 @@ which may assist you. .. image:: media/JupyterHelpMenu.png :align: center - - -.. _SageNBCommands: - -Evaluating in the SageNB notebook -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In any Sage worksheet, there are little boxes called *input cells* or -*code cells*. They should be about the width of your browser. - -.. image:: media/FirstCell.png - :align: center - -Evaluating the content of an input cell is very easy. - -- First, click inside the cell so that the cell is active (i.e., has a - bright blue border). - - .. image:: media/ActiveCell.png - :align: center - -- Then, just below the cell on the left, an "evaluate" link appears; - clicking this link evaluates the cell. - - .. image:: media/EvaluateCell.png - :align: center - -If you are using the live version of this documentation, try evaluating -the following cell. - -:: - - sage: 2+2 - 4 - -Sage prints out its response just below the cell (that's the ``4`` -above, so Sage confirms that :math:`2+2=4`). Note also that Sage has -automatically made the next cell active after you evaluated your first -cell. - -You can also evaluate a cell using a keyboard shortcut. - -- If a cell isn't active (such as below, in the live documentation), - click in it. - -- Then hold down the Shift key while you press the Enter key. - -We call this "Shift\-Enter". Try doing Shift\-Enter with this cell. - -:: - - sage: factor(2012) - 2^2 * 503 - -An input cell isn't much use if it can only do one thing, so you can -edit a cell and evaluate it again. Just click inside, and then make any -changes you wish by typing as usual. - -Try changing the number ``2012`` above to ``2011`` and evaluate the cell -to find its factorization (surprised?); then try your own favorite -number. - -To do more math, we'll need to be able to create new input cells. This -is also easy. - -- Move your cursor over the space above or below another cell. - -- A blue horizontal line as wide as the browser should appear. - -- Click on the line to insert a new cell. - -.. image:: media/ClickBlueLine.png - :align: center - -If for some reason you need to remove or delete an input cell, just -delete all the text inside of it, and then press backspace in the -now\-empty cell. - -Try creating a few new input cells below, doing some arithmetic in those -cells, and then deleting one of the input cells. - -.. skip - -:: - - 'Do some arithmetic in me, and make some other cells after me!' - .. _SageFunctions: Functions in Sage @@ -599,7 +506,6 @@ helpful to describe to the reader what is being done, such as in the description you are now reading. - :ref:`JupyterAnnotation` -- :ref:`SageNBAnnotation` .. _JupyterAnnotation: @@ -613,8 +519,7 @@ and the TeX rendering engine called more in Sage than just Sage commands. This math\-aware setup makes Sage perfect for annotating computations. -While the Jupyter notebook does not have as fully-featured a word -processor as the SageNB, we can still do a fair amount. +Jupyter notebook can function as a word processor. To use this functionality, we create a *Markdown cell* (as opposed to a *input cell* that contains Sage commands that Sage evaluates). @@ -656,113 +561,6 @@ in a Markdown cell. :align: center - -.. _SageNBAnnotation: - -SageNB Annotation -~~~~~~~~~~~~~~~~~ - -Thanks to `the mini\-word processor TinyMCE -`_ and a TeX rendering engine called -`MathJax `_, you can type much -more in the SageNB notebook worksheets -than just Sage commands. This math\-aware setup makes Sage -perfect for annotating computations. - -To use the word processor, we create a *text cell* (as opposed to a -*input cell* that contains Sage commands that Sage evaluates). - -To create a text cell, do the following. - -- First, move the cursor between two input cells, until the thin blue - line appears. - -- Then hold the Shift key and click on the thin blue line. - - .. image:: media/ClickBlueLine.png - :align: center - -So to create an input cell, one merely clicks, but one "Shift\-Click"s -to create a text cell. Here is what your text cell will look like. - - .. image:: media/TextEditor.png - :align: center - -In the live documentation, try inserting a text cell between the input -cells below. - -.. skip - -:: - - 2+2 - -.. skip - -:: - - 2+2 - -TinyMCE makes it easy for format text in many ways. Try experimenting -with the usual **bold** button, underline button, different text fonts -and colors, ordered and unordered lists, centering, and so on. Some of -the shortcut keys you are familiar with from other word processors may -also work, depending on your system. - -There are two other things you can do which take advantage of the -worksheet being on the web. - -- It is easy to link to other helpful websites for additional information. - - - While in the editor, highlight a word or two, and then click on the - little chain link toward the bottom right of the buttons. - - - You can now type in a web address to link to. - - - Be sure to prepend ``http://`` to the address. Normally, one should - also select it to appear in a new window (so the Sage session isn't - interrupted if someone clicks on it). - -- You may have already noticed that some of the descriptions above had - typeset mathematics in them. In fact we can add nearly arbitrary LaTeX - to our text cells! - - - For instance, it isn't too hard to add things like - - .. MATH:: - - \zeta(s)=\sum_{n=1}^{\infty}\frac{1}{n^s}=\prod_p \left(\frac{1}{1-p^{-s}}\right)\; . - - - One just types things like: - - .. CODE-BLOCK:: latex - - $$\zeta(s)=\sum_{n=1}^{\infty}\frac{1}{n^s}=\prod_p \left(\frac{1}{1-p^{-s}}\right)$$ - - in the word processor. - - - Whether this shows up as nicely as possible depends on what fonts you - have in your browser, but it should be legible. - - - More realistically, we might type ``$f(x)=x^2$`` so that we remember - that :math:`f(x)=x^2` in this worksheet. - -Here is a simpler example. - -:: - - sage: f(x)=x^2 - sage: f(9) - 81 - -If :math:`f(x)=x^2`, then :math:`f(9)=81`. - -It is simple to edit a text cell; simply double\-click on the text. - -If you are in the live version of this tutorial, try double\-clicking on -this text to edit this text cell (or any text cell) to see how we typed -the mathematics! - Of course, one can do much more, since Sage can execute arbitrary commands in the `Python `_ programming language, as well as output nicely formatted HTML, and so on. If you have enough diff --git a/src/doc/en/prep/Logging-On.rst b/src/doc/en/prep/Logging-On.rst index 3c5b1e43b70..cad2c8455c6 100644 --- a/src/doc/en/prep/Logging-On.rst +++ b/src/doc/en/prep/Logging-On.rst @@ -32,16 +32,6 @@ somewhat similar behavior. contact them or read some of their `documentation `_ for further assistance. -- Further below, we describe the process for logging on and making a - worksheet in the legacy :ref:`SageNB ` server, including: - - - :ref:`logging in ` for the first time - - - :ref:`editing a copy ` of a worksheet someone sent you - - - :ref:`making your own worksheet ` from scratch - - .. _Export: The Export screen and Jupyter notebook @@ -61,9 +51,8 @@ the third option to "export" them will not make sense. .. image:: media/NotebookExportDetails.png :align: center -The legacy SageNB is still a powerful web app, and has some advantages, -but is not longer under active development, so we recommend that new users -start with the Jupyter notebook. Jupyter will bring you to a screen +The legacy SageNB has been retired in Sage 9.1. +Please use the Jupyter notebook. Jupyter will bring you to a screen that is simply a listing of files in whatever folder Sage has opened in. .. image:: media/JupyterIntroScreen.png @@ -97,180 +86,3 @@ You should now have a worksheet that looks more or less like this. Now you are ready to begin to :ref:`evaluate Sage commands `! - - -.. _SageNB: - -Instructions for SageNB server -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. _LogOn: - -Creating an Account -------------------- - -When coming to a Sage server for the first time, it will look something -like this. - -.. image:: media/SignIn.png - :align: center - -You can create an account in three ways. - -- Use an :ref:`OpenID ` account to verify your account - -- Create a login in the :ref:`standard way ` by creating a - username and password. - -- If you have opened it on your local machine (e.g. from the command - line or the Mac app), you should be automatically logged in. - -.. _OpenID: - -OpenID -~~~~~~ - -With many public Sage servers, you can use an OpenID such as Google, -Yahoo!, and so forth to create an account. - -.. image:: media/SignInOpenID.png - :align: center - -To create an account, just make sure you are logged in with your -verification website, and then click the correct logo of the many on the -lower right. Then you should come to a page like this. - -.. image:: media/OpenIDPage.png - :align: center - -From there, you should be taken directly to your new notebook, ready to -make your :ref:`first worksheet `. - -.. _Standard: - -Standard Account Creation -~~~~~~~~~~~~~~~~~~~~~~~~~ - -The normal way to create an account is quite straightforward as well. - -.. image:: media/SignInNormal.png - :align: center - -Just click on the relevant link, and you'll be taken to a page where you -create a new username and password. - -.. image:: media/RegularSigninPage.png - :align: center - -In this example, there is a "magic word"; there could be a different -security question as well. In that case, you'll have already been given -the information if you're authorized to be on that server. - -In this scenario, you'll be taken back to the main login page, where -you'll need to put in your new login information. - -.. image:: media/HaveSignin.png - :align: center - -Then you'll be sent to a new notebook, ready to make your :ref:`first -worksheet `. - -Two Usage Scenarios -------------------- - -There are two main scenarios when starting with Sage. - -- You are running Sage locally or - going to a Sage server, and just want to start trying some - mathematics. We cover this situation :ref:`first `. - -- Someone has given you a link to a published tutorial or other - worksheet (perhaps one similar to this!) and you would like to try out - the mathematics there, using your own editable copy of the worksheet. - We cover this less common situation :ref:`below `. - -.. NOTE:: - - In either scenario, the Sage notebook will be saving your files - in a "hidden" location not meant for ordinary users and you will - ordinarily interact with your Sage worksheets only through the - notebook server. - -.. _FromScratch: - -Starting a New Worksheet from Scratch -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Sage on a server functions via individual documents called *worksheets*. -If you are sent to one and you want to make a :ref:`live copy -`, that is one thing, but usually you will start your Sage -session with just an empty notebook, with no worksheets yet in it. - -.. image:: media/EmptyNotebook.png - :align: center - -There are a few things you can do here, but usually you'll want to start -a new worksheet. - -.. image:: media/EmptyNotebookGetNew.png - :align: center - -Once you've done this, it should look something like this: - -.. image:: media/NewWorksheet.png - :align: center - -You can leave the name, or call it whatever you like. Then you should -see your first "cell", the rectangle in this picture. - -.. image:: media/FirstCell.png - :align: center - -But at this point you are ready to go on :ref:`evaluate Sage commands -`! - -.. _LiveCopy: - -Getting a Live Copy of a Worksheet -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Occasionally, you'll get started with Sage by someone giving you a link -to a *published worksheet* that someone else has created. In order to -do math on it, you'll need your *own* copy of the worksheet on the -server. - -If you are logged in and have your own copy, it should look like this at -the top: - -.. image:: media/LiveWorksheet.png - :align: center - -Except, of course, *your* username will appear! If you already have a -live copy, you're all set and should start trying it out, possibly -referring to the :doc:`first tutorial ` for tips. - -More likely, you'll need to follow a few steps. - -- Take another look at the top of the screen. Does it look like this? - - .. image:: media/NotLoggedIn.png - :align: center - - If you already have an account on the server, log in; otherwise, you - may want to review how to :ref:`get an account `. - -- Once you have an account and are logged in, you'll need to go back to - your original link for the published worksheet. In either event, the - worksheet should now look like this. - - .. image:: media/LoggedIn.png - :align: center - -- Now just click 'Edit a copy' so that it looks like this! - - .. image:: media/LiveWorksheet.png - :align: center - -Now you're ready to learn how to actually :ref:`evaluate those Sage -commands `! Good luck. - diff --git a/src/doc/en/reference/conf.py b/src/doc/en/reference/conf.py index f6a5c4490dc..c2372cf6ca3 100644 --- a/src/doc/en/reference/conf.py +++ b/src/doc/en/reference/conf.py @@ -59,8 +59,8 @@ # Sorted list of subdocs. Include all subdirectories of ref_src except # for 'static' and 'templates', and to deal with upgrades: 'sage', -# 'sagenb', 'media', and 'other'. -bad_directories = ['static', 'templates', 'sage', 'sagenb', 'media', 'other'] +# 'media', and 'other'. +bad_directories = ['static', 'templates', 'sage', 'media', 'other'] multidocs_subdoc_list = sorted([x for x in os.listdir(ref_src) if os.path.isdir(os.path.join(ref_src, x)) and x not in bad_directories]) @@ -68,5 +68,5 @@ # List of directories, relative to source directory, that shouldn't be # searched for source files. exclude_patterns += multidocs_subdoc_list + [ - 'sage', 'sagenb', 'options' + 'sage', 'options' ] diff --git a/src/doc/en/reference/index.rst b/src/doc/en/reference/index.rst index 9ad57e5cec5..d23093fe77d 100644 --- a/src/doc/en/reference/index.rst +++ b/src/doc/en/reference/index.rst @@ -14,7 +14,6 @@ User Interface * :doc:`Command Line Interface (REPL) ` * For the Jupyter notebook interface, visit `its documentation `_. -* For the legacy notebook interface, which is no longer actively maintained, visit the `source repository `_. Graphics ======== diff --git a/src/doc/en/reference/repl/index.rst b/src/doc/en/reference/repl/index.rst index 0110f585c88..572ec416246 100644 --- a/src/doc/en/reference/repl/index.rst +++ b/src/doc/en/reference/repl/index.rst @@ -91,7 +91,6 @@ Miscellaneous sage/repl/interface_magic sage/repl/ipython_kernel/interact sage/repl/ipython_kernel/widgets - sage/repl/ipython_kernel/widgets_sagenb sage/repl/ipython_kernel/install sage/repl/ipython_kernel/kernel sage/repl/ipython_tests diff --git a/src/doc/en/thematic_tutorials/sws2rst.rst b/src/doc/en/thematic_tutorials/sws2rst.rst deleted file mode 100644 index 1a6552b2518..00000000000 --- a/src/doc/en/thematic_tutorials/sws2rst.rst +++ /dev/null @@ -1,99 +0,0 @@ -.. _sws2srt: - -==================================== -Creating a Tutorial from a Worksheet -==================================== - -Sage has a number of `thematic tutorials `_ and contains everything -needed to turn a worksheet created in the `Sage notebook -`_ (sagenb) into a tutorial. - -.. WARNING:: - - The following will only work if Sage is built using Python 2 rather - than Python 3. As of version 9.0, the default is to build Sage with - Python 3. So either use an older version of Sage, or build a new - version of Sage with Python 2 by obtaining a Sage tarball and doing - - .. CODE-BLOCK:: shell-session - - $ make configure - $ ./configure --with-python=2 - $ make - -* Once you have created a worksheet and are satisfied with the text and - computations, download it to a directory. - -We will assume here that the worksheet is called ``Tutorial.sws`` -and the directory is called ``make_tutorial``. We also assume that -``sage`` is your Sage command; if it is not in your ``PATH`` then replace -this with the path to your Sage installation, such as -``/Applications/Sage-6.2.app/Contents/Resources/sage/sage`` if you are -using the Mac app and have placed it in your Applications directory. - -* Next, you will need an optional package to parse your worksheet. Use the - command: - - .. CODE-BLOCK:: shell-session - - $ sage --pip install beautifulsoup4 - - to install it (or, in the Mac app, use the ``Terminal Session`` advanced - menu with ``--pip install beautifulsoup4``). - -* Then we will use the ``sws2rst`` script to turn the worksheet into - a document in the `ReStructuredText `_ - format. Be sure you are in the same directory as the worksheet: - - .. CODE-BLOCK:: shell-session - - $ sage --sws2rst Tutorial.sws - - This will create an ``.rst`` file along with a subdirectory of image - files (which may be empty if there are no images). - - You can find help for ``sws2rst`` with the command - ``sage --sws2rst -h`` once you have installed beautifulsoup4. - -* In principle, such a file could be added directly to Sage's documentation (see - the `developer's manual <../developer/index.html>`_). However, you probably - want to check whether it looks right first. So next we will compile this file - to html documentation. - - * Follow the instructions of ``sage --sws2rst --sphinxify``. First, - we will open a Sage shell session, where all appropriate Sage - references already work properly: - - .. CODE-BLOCK:: shell-session - - $ sage --sh - - From here, you should be able to just type: - - .. CODE-BLOCK:: shell-session - - $ sphinx-quickstart - - and then respond to prompts for turning your ``.rst`` file into - documentation. For most of them you can just hit enter/return to - accept the defaults. However, you will probably want to - - * Enter a name for the project - * Enter a name for you - * Type ``y`` for the question about using MathJax - - Keep note of the instructions; the main other thing to do is add - your file's name to ``index.rst``, and then just do: - - .. CODE-BLOCK:: shell-session - - $ make html - - and wait while magic happens. To see the results, open the file - ``make_tutorial/_build/html/Tutorial.html`` with a browser, or - use your graphical file system to navigate to the same place. - -* Now you can modify the ``.rst`` file more and repeat the steps - of compiling it until it is ready for inclusion, or just for distribution - among other Sage users as an HTML file. (Do ``make pdf`` for a PDF - version.) diff --git a/src/doc/en/tutorial/interactive_shell.rst b/src/doc/en/tutorial/interactive_shell.rst index 901f9a1bd0c..26e5ee37aa1 100644 --- a/src/doc/en/tutorial/interactive_shell.rst +++ b/src/doc/en/tutorial/interactive_shell.rst @@ -949,94 +949,8 @@ Each saved variable is again available. Moreover, the variable .. _section-notebook: -The legacy Notebook Interface +The Notebook Interface ============================= -This section refers to the legacy Sage notebook, or "sagenb". - -SageMath is transitioning to using the -`Jupyter notebook -`_ -as a default, which has a different structure. The most important -difference for users is that individual worksheets in Jupyter -are saved on your local system just like any other file, whereas -in the Sage notebook the main point of access is in the files -described below via the server. - - -Legacy SageNB Notebook ----------------------- - -The Sage notebook is run by choosing it after starting Sage with ``-n`` option. -This starts the Sage notebook and -opens your default web browser to view it. The server's state files -are stored in ``$HOME/.sage/sage\_notebook.sagenb``. - -When you start the notebook, it first creates the following files -in ``$HOME/.sage/sage_notebook.sagenb``: - -.. CODE-BLOCK:: text - - conf.pickle - openid.pickle - twistedconf.tac - sagenb.pid - users.pickle - home/admin/ (a directory for the admin user) - home/guest/ (a directory for guests) - home/pub/ (a directory for published worksheets) - -After creating the above files, the notebook starts a web server. - -A "notebook" is a collection of user accounts, each of which can -have any number of worksheets. When you create a new worksheet, the -data that defines it is stored in the ``home/username/number`` -directories. In each such directory there is a plain text file -``worksheet.html`` - if anything ever happens to your worksheets, or Sage, -or whatever, that human-readable file contains everything needed to -reconstruct your worksheet. Each worksheet also has, at a minimum, -the files/folders: - -.. CODE-BLOCK:: text - - cells/ - worksheet.html - data/ - worksheet_conf.pickle - - -From within Sage, type ``notebook?`` for much more about how to start a -notebook server. - -The following diagram illustrates the architecture of the Sage -Notebook: - -.. CODE-BLOCK:: text - - ---------------------- - | | - | | - | firefox/safari | - | | - | javascript | - | program | - | | - | | - ---------------------- - | ^ - | AJAX | - V | - ---------------------- - | | - | sage | SAGE process 1 - | web | ------------> SAGE process 2 (Python processes) - | server | pexpect SAGE process 3 - | | . - | | . - ---------------------- . - -For help on a Sage command, ``cmd``, in the notebook browser box, -type ``cmd?`` and now hit ```` (not ````). - -For help on the keyboard shortcuts available in the notebook -interface, click on the ``Help`` link. +SageMath is using the `Jupyter notebook +`_ as the default. diff --git a/src/doc/ja/tutorial/interactive_shell.rst b/src/doc/ja/tutorial/interactive_shell.rst index 38925e550dd..e454ea3cc91 100644 --- a/src/doc/ja/tutorial/interactive_shell.rst +++ b/src/doc/ja/tutorial/interactive_shell.rst @@ -893,88 +893,5 @@ Sageは,セッション全体を保存し再ロードするための非常に ノートブックインターフェイス ================================== -Sageノートブックを起動するには、Sageコマンドライン上で - -.. skip - -:: - - sage: notebook() - -と実行する. -これでSageノートブックが起動すると同時に,閲覧用のデフォルトWebブラウザが開かれる. -ノートブックサーバが使用する状態ファイル群は, ``$HOME/.sage/sage\_notebook.sagenb`` に保存される. - - -起動時に指定できるオプションとして - -.. skip - - -:: - - sage: notebook("ディレクトリ名") - - -とすると,標準ディレクトリ ``$HOME/.sage/sage_notebook.sagenb`` ではなく指定した ``ディレクトリ名.sagenb`` のディレクトリにある状態ファイル群を使って新しくノートブックサーバを起動する. -このオプションは,特定のプロジェクトに多数のワークシート群がぶら下がっていたり,同時に複数のノートブックサーバを動かしたい場合に便利だ. - -ノートブックを起動すると、まず ``$HOME/.sage/sage_notebook.sagenb`` 内に以下のようなファイル群が生成される: - - -:: - - conf.pickle - openid.pickle - twistedconf.tac - sagenb.pid - users.pickle - home/admin/ - home/guest/ - home/pub/ - -上のファイル群の作成後,ノートブックはWebサーバの起動を行なう. - - -「ノートブック」(notebook)とはユーザーアカウントの集合であって,各ノートブックにはワークシートを好きな数だけ保持することができる. -ワークシートを新規に作成すると,そのワークシートを定義するデータが ``home/username/number`` ディレクトリに保存される. -これらのディレクトリに必ず出来ているのがファイル ``worksheet.html`` である. -このプレーンテキストからなるファイルには,ワークシートやSageその他に何によらず変更が加えられた場合,元のワークシートを復元するために必要な全情報が可読形式で保存されている. - - -Sage上で ``notebook?`` と入力すると,ノートブックサーバを起動する方法に関する詳しい情報が得られる. - - -次の図を見ると,Sageノートブックの構造が分る: - -:: - - ---------------------- - | | - | | - | firefox/safari | - | | - | javascript | - | program | - | | - | | - ---------------------- - | ^ - | AJAX | - V | - ---------------------- - | | - | sage | SAGE process 1 - | web | ------------> SAGE process 2 (Python processes) - | server | pexpect SAGE process 3 - | | . - | | . - ---------------------- . - - - -ノートブックからSageコマンド ``コマンド名`` のヘルプを見たければ,ブラウザ表示画面内入力ボックスで ``コマンド名?`` と入力し, ```` を押せばよい(```` ではない). - - -ノートブック上で通用するキーボードショートカットを確認するには, ``Help`` リンクをクリックする. - +SageMath is using the `Jupyter notebook +`_ as the default. diff --git a/src/doc/pt/tutorial/interactive_shell.rst b/src/doc/pt/tutorial/interactive_shell.rst index 3e2392d8742..3552cc4d3f0 100644 --- a/src/doc/pt/tutorial/interactive_shell.rst +++ b/src/doc/pt/tutorial/interactive_shell.rst @@ -943,99 +943,5 @@ variável ``b`` não foi redefinida. A Interface do Notebook ======================= -Esta seção refere-se ao notebook Sage legado, ou "sagenb". - SageMath está em transição para uso do -`Jupyter `_ -como padrão, que tem uma -estrutura diferente. A diferença mais importante para os usuários é que -as planilhas individuais no Jupyter são salvas no seu sistema local -(como qualquer outro arquivo é salvo), enquanto que no tipo de notebook -anterior Sage (ou sagenb) o principal ponto de acesso está nos arquivos -descritos abaixo através do servidor. - -Notebook Sage legado --------------------- - -O Sage Notebook é iniciado digitando - -.. skip - -:: - - sage: notebook() - -na linha de comando do Sage. Isso inicia o Notebook e abre o seu -navegador padrão para visualizá-lo. Os arquivos de estado do servidor -são armazenados em ``$HOME/.sage/sage\_notebook.sagenb``. - -Outras opções incluem: - -.. skip - -:: - - sage: notebook("directory") - -a qual inicia um novo servidor para o Notebook usando arquivos em um -dado diretório ``directory.sagenb``, em vez do diretório padrão -``$HOME/.sage/sage_notebook.sagenb``. Isso pode ser útil se você quiser ter -uma coleção de folhas de trabalho (worksheets) associadas com um -projeto específico, ou executar vários Notebooks separadamente ao -mesmo tempo. - -Quando você inicia o Notebook, ele primeiro cria os seguintes arquivos -em ``$HOME/.sage/sage_notebook.sagenb``: - -:: - - conf.pickle - openid.pickle - twistedconf.tac - sagenb.pid - users.pickle - home/admin/ - home/guest/ - home/pub/ - -Após criar os arquivos acima, o Notebook inicia o servidor web. - -Um "Notebook" é uma coleção de contas de usuário, cada qual pode ter -várias folhas de trabalho (worksheets). Quando você cria uma nova -folha de trabalho, os dados dela são armazenados no diretórios -``home/username/number``. Em cada diretório desse há um arquivo -texto ``worksheet.html`` - se algum problema ocorrer com as suas -folhas de trabalho, ou com o Sage, esse arquivo texto contém toda -informação necessária para reconstruir a folha de trabalho. - -A partir do Sage, digite ``notebook?`` para mais informações sobre -como iniciar um servidor. - -O seguinte diagrama ilustra a arquitetura do Notebook Sage: - -:: - - ---------------------- - | | - | | - | firefox/safari | - | | - | javascript | - | program | - | | - | | - ---------------------- - | ^ - | AJAX | - V | - ---------------------- - | | - | sage | SAGE process 1 - | web | ------------> SAGE process 2 (Python processes) - | server | pexpect SAGE process 3 - | | . - | | . - ---------------------- . - -Para ajuda sobre as teclas de atalho disponíveis no Notebook, clique -no link ``Help``. +`Jupyter `_. diff --git a/src/doc/ru/tutorial/interactive_shell.rst b/src/doc/ru/tutorial/interactive_shell.rst index 564587352fa..967409bf989 100644 --- a/src/doc/ru/tutorial/interactive_shell.rst +++ b/src/doc/ru/tutorial/interactive_shell.rst @@ -844,79 +844,8 @@ Sage обладает очень гибкими возможностями со .. _section-notebook: -Интерфейсы Notebook +Интерфейс Notebook ============================= -SageMath переходит на -`Jupyter notebook `_ - -где документы имеют другую структуру. Наиболее существенное -отличие для пользователей в том, что индивидуальные рабочие листы -сохраняются Jupyter на локальной файловой системе как обычные файлы, -в то время как Sage notebook делает это как описано ниже. - -Интерфейс Notebook (устаревший, работает только с Python 2) -============================================================== - -Sage notebook запускается путем выбора опции SageNB после запуска Sage из -терминала с указанием опции ``-n``. Sage notebook и откроется в дефолтном -браузере. Файлы состояния сервера хранятся в -``$HOME/.sage/sage\_notebook.sagenb``. - -Когда вы запускаете Notebook, вначале он создает следующие файлы в директории -``$HOME/.sage/sage_notebook.sagenb``: - -:: - - conf.pickle - openid.pickle - twistedconf.tac - sagenb.pid - users.pickle - home/admin/ - home/guest/ - home/pub/ - -После создания этих файлов, Notebook запускает веб-сервер. - -Notebook — это коллекция учетных записей пользователей (аккаунтов), каждый -из которых может иметь любое количество рабочих листов. Когда вы создаете -новый рабочий лист, информация, которая описывает его, сохраняется в директории -``home/username/number``. В каждой такой директории находится простой -текстовый файл ``worksheet.html``; если что-то случится с вашими рабочими листами, -или с Sage, или что-нибудь еще пойдет не так, то текcтовый файл, который легко -читается, поможет восстановить ваш лист полностью. - -В Sage введите ``notebook?`` для получения подробной информации о том, как -запустить сервер Notebook. - -Следующая диаграмма иллюстрирует архитектуру Sage Notebook: - -:: - - ---------------------- - | | - | | - | firefox/safari | - | | - | javascript | - | program | - | | - | | - ---------------------- - | ^ - | AJAX | - V | - ---------------------- - | | - | sage | SAGE process 1 - | web | ------------> SAGE process 2 (Python processes) - | server | pexpect SAGE process 3 - | | . - | | . - ---------------------- . - -Для получения справки о команде Sage, ``cmd``, в notebook введите, ``cmd?`` и -нажмите ```` (не ````). - -Для получения справки о горячих клавишах интерфейса notebook нажмите ссылку -``Help``. +SageMath перешел на +`Jupyter notebook `_. diff --git a/t b/t new file mode 100755 index 00000000000..094d00d25b8 --- /dev/null +++ b/t @@ -0,0 +1,7 @@ +if test x`locale -a | grep C\.UTF-8` != x; then + export LC_ALL=C.UTF-8; +else + export LC_ALL=C; +fi + +echo $LC_ALL From fd48549329b7cd7909d8d8353c3b2884553a088c Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 6 Jul 2020 16:14:07 +0100 Subject: [PATCH 146/217] more traces of sws --- src/bin/sage | 10 -- src/bin/sage-rst2sws | 144 ---------------- src/bin/sage-sws2rst | 198 ---------------------- src/doc/en/developer/sage_manuals.rst | 3 - src/doc/en/thematic_tutorials/toctree.rst | 1 - src/sage/tests/cmdline.py | 44 ----- 6 files changed, 400 deletions(-) delete mode 100755 src/bin/sage-rst2sws delete mode 100755 src/bin/sage-sws2rst diff --git a/src/bin/sage b/src/bin/sage index b4786bf3aae..b7e7d0c28ac 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -783,16 +783,6 @@ if [ "$1" = '-rst2txt' -o "$1" = '--rst2txt' ]; then exec sage-rst2txt "$@" fi -if [ "$1" = '-rst2sws' -o "$1" = '--rst2sws' ]; then - shift - exec sage-rst2sws "$@" -fi - -if [ "$1" = '-sws2rst' -o "$1" = '--sws2rst' ]; then - shift - exec sage-sws2rst "$@" -fi - ##################################################################### # The notebook, grep, building Sage, testing Sage ##################################################################### diff --git a/src/bin/sage-rst2sws b/src/bin/sage-rst2sws deleted file mode 100755 index 3cbde0e05d5..00000000000 --- a/src/bin/sage-rst2sws +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env sage-python -r""" -sage-rst2sws -============ - -Translate a rst file into a Sage worksheet file (.sws). - -Usage:: - - sage --rst2sws [options] - -Print the help message:: - - sage --rst2sws -h - -EXAMPLES:: - - sage --rst2sws file.rst file.sws - -In reStructuredText, "an escaped character represents the character -itself, and is prevented from playing a role in any markup -interpretation. The backslash is removed from the output" [1]_ [2]_. So, -if the backslashes of your reST file are not escaped, they will get lost -in the process. This is not practical for Sage since most of the -documentation and examples are Python raw strings where backslashes are -not escaped. Use the following command to escape all backslashes in the -input file:: - - sage --rst2sws --escape-backslashes input.rst output.sws - -AUTHOR: - - - Sebastien Labbe (2011, June 14th, at Sage Days 31): Initial - version - -REFERENCES: - -.. [1] Escaping Mechanism, reStructuredText Markup Specification, - http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#escaping-mechanism -.. [2] Escaping with backslashes, Quick reStructuredText Reference, - http://docutils.sourceforge.net/docs/user/rst/quickref.html#escaping -""" -############################################################################# -# Copyright (C) 2011 Sebastien Labbe -# Distributed under the terms of the GNU General Public License (GPL) -# The full text of the GPL is available at: -# http://www.gnu.org/licenses/ -############################################################################# -import sys -from optparse import OptionParser - -# Set the parser -usage = r""" - - sage -rst2sws [options] - -Generates Sage worksheet (.sws) from standalone reStructuredText source. - -Example: - - sage -rst2sws file.rst file.sws - -Remarks: - - About LaTeX: - - You can put LaTeX expression between backticks "`", dollar signs - "$" or double dollar signs "$$". Math role is not supported yet - (get involved!). - - Examples: `\\alpha`, $\\beta$ or $$\\gamma$$. - - About backslashes: - - In reStructuredText, backslashes must be escaped, otherwise they - are ignored. This is not quite practical for Sage's purposes - since backslashes are never escaped in the docstrings. If you - write `\alpha`, $\beta$ or $$\gamma$$, add the line - - .. escape-backslashes - - to the file and this script will consider all backslashes - escaped. Alternatively, you may use the available options.""" -parser = OptionParser(usage=usage) -parser.add_option("--escape-backslashes", - action="store_true", dest="escape_backslashes", - help="Escape all backslashes in the input file before execution. Default: disabled.") -parser.add_option("--no-escape-backslashes", - action="store_true", dest="no_escape_backslashes", - help="Disable escaping all backslashes in the input file before execution. This overrides the presence of the line '.. escape-backslashes' in the file, which can also be used to escape all backslashes in the file.") -(options, args) = parser.parse_args() - -# Parse arguments -if len(args) != 2: - parser.print_usage() - sys.exit(1) -input = args[0] -output = args[1] - -# Read the ReST input -try: - with open(input, 'r') as f: - rst = f.read() -except IOError as e: - print("IOError: {}".format(e)) - print("Unable to open source file for reading ('{}'). Exiting.".format(input)) - sys.exit(1) - -# docutils loses the single backslashes, so we precede them with escapes -# A better solution would be to escape baskslashes only in the math sections -import re -if options.escape_backslashes: - rst = rst.replace('\\','\\\\') -elif options.no_escape_backslashes: - pass -elif re.search(r'^\.\.[ \t]+escape-backslashes', rst, re.MULTILINE) is not None: - rst = rst.replace('\\','\\\\') - -# Do the translation rst -> html (using docutils) -from docutils.core import publish_parts -D = publish_parts(rst, writer_name='html') -title = D['title'] -html = D['whole'] - -# Do the translation html -> worksheet txt -from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor -translator = docutilsHTMLProcessor() -worksheet_txt = translator.process_doc_html(html) - -# create a Notebook object -from sagenb.notebook.notebook import Notebook -from sage.misc.all import tmp_dir -nb = Notebook(tmp_dir()+'.sagenb') -nb.user_manager().create_default_users('password') - -# create a worksheet -W = nb.create_new_worksheet(title, 'admin') -W.edit_save(worksheet_txt) - -# export the worksheet as sws -nb.export_worksheet(W.filename(), output, title=title) - -# delete the Notebook object -nb.delete() diff --git a/src/bin/sage-sws2rst b/src/bin/sage-sws2rst deleted file mode 100755 index fb3eabeb966..00000000000 --- a/src/bin/sage-sws2rst +++ /dev/null @@ -1,198 +0,0 @@ -#!/usr/bin/env sage-python -# -*- coding: utf-8 -*- -r""" -sage-sws2rst -============ - -Translate a Sage worksheet file (.sws) into an rst file. The result is -saved in the current working directory. - -Usage:: - - sage --sws2rst [-h] - -Print the help message:: - - sage --sws2rst -h - -EXAMPLES:: - - sage --sws2rst file.sws - -AUTHORS: - -- Pablo Angulo (January 2011): Initial version -- Karl-Dieter Crisman (June 2012): Documentation - and minor refinements -- Karl-Dieter Crisman (November 2014): Correct use of temporary files, - see :trac:`17308`. -""" - -#***************************************************************************** -# Copyright (C) 2011 Pablo Angulo -# Copyright (C) 2012-2014 Karl-Dieter Crisman -# -# 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/ -#***************************************************************************** - -import sys -import tarfile -import os -import shutil -import codecs -import tempfile -from sagenb.misc.worksheet2rst import worksheet2rst - -from optparse import OptionParser - - -def process_sws(sws_file): - """ - Process the ``.sws`` file ``sws_file`` and create an ``.rst`` file - (and possible media files) in the current working directory. - """ - base_name = os.path.basename(os.path.splitext(sws_file)[0]) - base_name = base_name.replace(' ','_') - - tempdir = tempfile.mkdtemp() - try: - with tarfile.open(sws_file, mode='r:bz2') as sws_file: - sws_file.extractall(tempdir) - worksheet_dir = os.path.join(tempdir, 'sage_worksheet') - if not os.path.isdir(worksheet_dir): - raise RuntimeError("Worksheeet file %r does not contain a 'sage_worksheet' directory" % sws_file) - process_worksheet(worksheet_dir, base_name) - finally: - shutil.rmtree(tempdir) - -def process_worksheet(worksheet_dir, base_name): - """ - Process the extracted worksheet directory ``worksheet_dir`` and - create the ``.rst`` and media files with base name ``base_name``. - - Files are moved from ``worksheet_dir``, so make sure these are - temporary files! - """ - #Images - images_dir = base_name + '_media' - try: - os.mkdir(images_dir) - except OSError: - if not os.path.isdir(images_dir): - raise - - #"data" dir - data_path = os.path.join(worksheet_dir, 'data') - if os.path.isdir(data_path): - for image in os.listdir(data_path): - shutil.move(os.path.join(data_path, image), os.path.join(images_dir, image.replace(' ','_'))) - - #cells - cells_path = os.path.join(worksheet_dir, 'cells') - if os.path.isdir(cells_path): - for cell in os.listdir(cells_path): - cell_path = os.path.join(cells_path, cell) - for image in os.listdir(cell_path): - if os.path.isfile(os.path.join(cell_path, image)): - shutil.move(os.path.join(cell_path, image), - os.path.join(images_dir, 'cell_%s_%s'%(cell,image))) - # could be Jmol image directory - code for future - #elif os.path.isdir(os.path.join(cell_path, image)): - # if image == '.jmol_images': - # for jmolimg in os.listdir(os.path.join(cell_path, image)): - # shutil.move(os.path.join(cell_path, image, jmolimg), - # os.path.join(images_dir, 'cell_%s_%s'%(cell,jmolimg))) - - #read html file, parse it, write rst file - html_file = os.path.join(worksheet_dir, 'worksheet.html') - with codecs.open(html_file, mode='r', encoding='utf-8') as f: - html_text = f.read() - - rst_text = worksheet2rst(html_text, images_dir=images_dir) - rst_file = base_name + '.rst' - - with codecs.open(rst_file, mode='w', encoding='utf-8') as out_file: - out_file.write(rst_text) - - print("File at", rst_file) - print("Image directory at", images_dir) - - -# Set the parser -usage = r""" - - sage --sws2rst [options] ... - -Translate a Sage worksheet file (.sws) into an reStructuredText -(.rst) file. At least one sws file argument is required; all sws -files will be parsed and translated. Spaces in the names of the -worksheet will be converted to underscores. The resulting files will -be stored in the current working directory. - -Examples: - - sage --sws2rst file.sws - sage --sws2rst file1.sws file2.sws file3.sws - sage --sws2rst -h # this help message prints - sage --sws2rst --sphinxify # information about how to use - # Sphinx to compile your rst file -""" - -sphinxify_text = r""" - -Once you have made your rst file, what can you do with it? - -If this is a file which is likely to become part of the Sage -standard documentation, you will want to edit the appropriate -file in $SAGE_ROOT/src/doc to include your file, or -simply include your file as appropriate. - -However, you may simply want to make great-looking documentation -for some other purpose out of your worksheet. The following -steps are one way to do so. - - - Assume that the generated .rst file is ``My_Project.rst``. - - Make a folder somewhere convenient to compile in, say, ``MyProject``. - - Then move your .rst file into that folder, and cd into it. - - Now the key is to use Sage's shell to run Sphinx on it! Run ``sage --sh``. - - Then type ``sphinx-quickstart`` and follow the instructions in the - Sphinx tutorial [1]_. You will probably want to choose to render math - with MathJax [2]_, but you can accept the defaults for the other options. - - Finally, edit ``index.rst`` by adding ``My_Project`` in the table of - contents, as detailed in the Sphinx tutorial [3]_. - - If you now type ``make html`` you should get a beautiful-looking web page - in ``_build/html``. If you did not have a header at the top of your worksheet, - you may get an error, but you can ignore this. - -REFERENCES: - -.. [1] First Steps with Sphinx, - http://sphinx.pocoo.org/tutorial.html -.. [2] MathJax, - http://www.mathjax.org/ -.. [3] Defining Document Structure, First Steps with Sphinx, - http://sphinx.pocoo.org/tutorial.html#defining-document-structure""" - -parser = OptionParser(usage=usage) -parser.add_option("--sphinxify", - action="store_true", dest="sphinxify", - help="Print information about how to use Sphinx to compile your rst file, then exit.") -(options, args) = parser.parse_args() - -# Parse option -if options.sphinxify: - print(sphinxify_text) - sys.exit(0) - -# Parse arguments -if len(args) < 1: - parser.print_usage() - sys.exit(1) - -for file_name in args: - print("Processing", file_name) - process_sws(file_name) diff --git a/src/doc/en/developer/sage_manuals.rst b/src/doc/en/developer/sage_manuals.rst index 65a82c5f2d5..047a949900b 100644 --- a/src/doc/en/developer/sage_manuals.rst +++ b/src/doc/en/developer/sage_manuals.rst @@ -45,9 +45,6 @@ Sage's manuals are written in `ReST `_ Editing the documentation ========================= -(*Do you want to convert a Sage worksheet into documentation?* `Click here -<../thematic_tutorials/sws2rst.html>`_) - After modifying some files in the Sage tutorial (``SAGE_ROOT/src/doc/en/tutorial/``), you will want to visualize the result. In order to build a **html** version of this document, type:: diff --git a/src/doc/en/thematic_tutorials/toctree.rst b/src/doc/en/thematic_tutorials/toctree.rst index d5b272291a9..1fd24066025 100644 --- a/src/doc/en/thematic_tutorials/toctree.rst +++ b/src/doc/en/thematic_tutorials/toctree.rst @@ -25,5 +25,4 @@ Thematic tutorial document tree cython_interface numerical_sage/index explicit_methods_in_number_theory/index - sws2rst profiling diff --git a/src/sage/tests/cmdline.py b/src/sage/tests/cmdline.py index 310e55d2ff2..a423f3a8a19 100644 --- a/src/sage/tests/cmdline.py +++ b/src/sage/tests/cmdline.py @@ -39,7 +39,6 @@ --rst2ipynb --ipynb2rst --rst2txt ---rst2sws --sh --singular --sqlite3 @@ -794,49 +793,6 @@ def test_executable(args, input="", timeout=100.0, pydebug_ignore_warnings=False 4 }}} - Test ``sage --rst2sws file.rst file.sws`` on a ReST file:: - - sage: s = "Thetitle\n--------\n\n::\n\n sage: 2^10\n 1024\n sage: 2 + 2\n 4" - sage: input = tmp_filename(ext='.rst') - sage: output = tmp_filename(ext='.sws') - sage: with open(input, 'w') as F: - ....: _ = F.write(s) - sage: test_executable(["sage", "--rst2sws", input, output]) # py2 # optional -- sagenb - ('', '', 0) - sage: import tarfile # py2 - sage: f = tarfile.open(output, 'r') # py2 # optional -- sagenb - sage: print(f.extractfile('sage_worksheet/worksheet.html').read()) # py2 # optional -- sagenb -

Thetitle

- - {{{id=0| - 2^10 - /// - 1024 - }}} - - {{{id=1| - 2 + 2 - /// - 4 - }}} - sage: print(f.extractfile('sage_worksheet/worksheet.txt').read()) # py2 # optional -- sagenb - Thetitle - system:sage - - -

Thetitle

- - {{{id=0| - 2^10 - /// - 1024 - }}} - - {{{id=1| - 2 + 2 - /// - 4 - }}} """ pexpect_env = dict(os.environ) try: From 89a1b10698e7d41c9bf694d7381b1a7b1b3816f8 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 6 Jul 2020 19:25:35 +0100 Subject: [PATCH 147/217] rest of the traces of sws --- src/doc/de/tutorial/latex.rst | 15 - src/doc/en/thematic_tutorials/index.rst | 4 - src/doc/en/thematic_tutorials/toctree.rst | 1 - .../tutorial-notebook-and-help-long.rst | 425 ------------------ src/doc/en/tutorial/latex.rst | 18 - src/doc/fr/tutorial/latex.rst | 18 - src/doc/ja/tutorial/latex.rst | 11 - src/doc/pt/tutorial/latex.rst | 18 - 8 files changed, 510 deletions(-) delete mode 100644 src/doc/en/thematic_tutorials/tutorial-notebook-and-help-long.rst diff --git a/src/doc/de/tutorial/latex.rst b/src/doc/de/tutorial/latex.rst index a4b14924334..5133e699140 100644 --- a/src/doc/de/tutorial/latex.rst +++ b/src/doc/de/tutorial/latex.rst @@ -484,18 +484,3 @@ alle Berechnungs- oder LaTeX-Formatierungseigenschaften von Sage automatisch gen Als Beispiel hierfür kann in einer mathematischen Betrachtung die korrekte Reihenfolge von Fragen und Antworten beibehalten werden, indem sagetex dazu genutzt wird Sage die einen aus den anderen berechnen zu lassen. Siehe hierfür auch :ref:`sec-sagetex` - -tex2sws beginnt mit einem LaTeX-Dokument, aber definiert einige zusätzliche -Umgebungen für Sage Code. Wenn es richtig genutzt wird, ist das Ergebnis ein -Sage Arbeitsblatt mit korrekt von MathJax formatiertem Inhalt und dem dazugehörigen -Sage Code in den Eingabezellen. Ein Lehrbuch oder Artikel kann also mit Sage Code Blöcken -in LaTeX gesetzt werden und es kann "live" das ganze Dokument in ein Sage Arbeitsblatt überführt werden; -unter Beibehaltung der Sage Code Blöcke und mit schön formatiertem mathematischen Text. -Momentan in Arbeit, siehe `tex2sws @ BitBucket -`_ . - -sws2tex kehrt den Prozess um, indem es mit einem Sage Arbeitsblatt beginnt, und -es in ein legitimes LaTeX-Dokument zur weiteren Bearbeitung mit allen -LaTeX-Werkzeugen verwandelt. -Momentan in Arbeit, siehe `sws2tex @ BitBucket -`_ . diff --git a/src/doc/en/thematic_tutorials/index.rst b/src/doc/en/thematic_tutorials/index.rst index 6041c18f5af..01ae01f4f1d 100644 --- a/src/doc/en/thematic_tutorials/index.rst +++ b/src/doc/en/thematic_tutorials/index.rst @@ -30,9 +30,7 @@ This documentation is licensed under a `Creative Commons Attribution-Share Alike Introduction to Sage -------------------- -* `Logging on to a Sage Server and Creating a Worksheet (PREP) <../prep/Logging-On.html>`_ * `Introductory Sage Tutorial (PREP) <../prep/Intro-Tutorial.html>`_ -* :ref:`tutorial-notebook-and-help-long` * `Sage's main tutorial <../tutorial/>`_ .. _programming_design: @@ -121,8 +119,6 @@ Advanced Programming Documentation ============= -* :ref:`sws2srt` - .. Sage development .. ---------------- diff --git a/src/doc/en/thematic_tutorials/toctree.rst b/src/doc/en/thematic_tutorials/toctree.rst index 1fd24066025..18d35b70fb1 100644 --- a/src/doc/en/thematic_tutorials/toctree.rst +++ b/src/doc/en/thematic_tutorials/toctree.rst @@ -6,7 +6,6 @@ Thematic tutorial document tree :maxdepth: 2 algebraic_combinatorics - tutorial-notebook-and-help-long sandpile group_theory lie diff --git a/src/doc/en/thematic_tutorials/tutorial-notebook-and-help-long.rst b/src/doc/en/thematic_tutorials/tutorial-notebook-and-help-long.rst deleted file mode 100644 index 54e3c162248..00000000000 --- a/src/doc/en/thematic_tutorials/tutorial-notebook-and-help-long.rst +++ /dev/null @@ -1,425 +0,0 @@ -.. _tutorial-notebook-and-help-long: - -============================================================================== -Tutorial: Using the Sage notebook, navigating the help system, first exercises -============================================================================== - -.. linkall - -This worksheet is based on William Stein's `JPL09__intro_to_sage.sws -`_ -worksheet and the `Sage days 20.5_demo `_ -worksheet and aims to be an interactive introduction to Sage through exercises. -You will learn how to use the notebook and call the help. - -Making this help page into a worksheet -====================================== - -If you are browsing this document as a static web page, you can see all the -examples; however you need to copy-paste them one by one to experiment with them. -Use the ``Upload worksheet`` button of the notebook and copy-paste the URL of -this page to obtain an editable copy in your notebook. - -If you are browsing this document as part of Sage's live documentation, you can -play with the examples directly here; however your changes will be lost when -you close this page. Use ``Copy worksheet`` from the ``File...`` menu at the -top of this page to get an editable copy in your notebook. - -Both in the live tutorial and in the notebook, you can clear all output by -selecting ``Delete All Output`` from the ``Action...`` menu next to the -``File...`` menu at the top of the worksheet. - -Entering, Editing and Evaluating Input -====================================== - -To *evaluate code* in the Sage Notebook, type the code into an input cell and -press ``shift-enter`` or click the ``evaluate`` link. Try it now with a simple -expression (e.g., `2+3`). The first time you evaluate a cell takes longer -than subsequent times since a new Sage process is started:: - - sage: 2 + 3 - 5 - - sage: # edit here - - sage: # edit here - -To create *new input cells*, click the blue line that appears between -cells when you move your mouse around. Try it now:: - - sage: 1 + 1 - 2 - - sage: # edit here - -You can *go back* and edit any cell by clicking in it (or using the -arrow keys on your keyboard to move up or down). Go back and change -your `2+3` above to `3+3` and re-evaluate it. An empty cell can be -*deleted* with backspace. - -You can also *edit this text* right here by double clicking on it, -which will bring up the TinyMCE Javascript text editor. You can even -put embedded mathematics like this $\sin(x) - y^3$ by using dollar signs -just like in TeX or LaTeX. - -Help systems -============ - -There are various ways of getting help in Sage. - -- navigate through the documentation (there is a link ``Help`` at the top right - of the worksheet), -- ``tab`` completion, -- contextual help. - -We detail below the latter two methods through examples. - -Completion and contextual documentation -======================================= - -Start typing something and press the ``tab`` key. The interface tries to -complete it with a command name. If there is more than one completion, then -they are all presented to you. Remember that Sage is case sensitive, i.e. it -differentiates upper case from lower case. Hence the ``tab`` completion of -``klein`` won't show you the ``KleinFourGroup`` command that builds the group -`\ZZ/2 \times \ZZ/2` as a permutation group. Try it on the next cells: - -.. skip - -:: - - sage: klein - - sage: Klein - -To see documentation and examples for a command, type a question mark ``?`` at -the end of the command name and press the ``tab`` key as in: - -.. skip - -:: - - sage: KleinFourGroup? - -:: - - sage: # edit here - -.. TOPIC:: Exercise A - - What is the largest prime factor of `600851475143`? - - .. skip - - :: - - sage: factor? - - :: - - sage: # edit here - -In the above manipulations we have not stored any data for -later use. This can be done in Sage with the ``=`` symbol as in:: - - sage: a = 3 - sage: b = 2 - sage: a+b - 5 - -This can be understood as Sage evaluating the expression to the right -of the ``=`` sign and creating the appropriate object, and then -associating that object with a label, given by the left-hand side (see -the foreword of :ref:`tutorial-objects-and-classes` for -details). Multiple assignments can be done at once:: - - sage: a,b = 2,3 - sage: a - 2 - sage: b - 3 - -This allows us to swap the values of two variables directly:: - - sage: a,b = 2,3 - sage: a,b = b,a - sage: a,b - (3, 2) - -We can also assign a common value to several variables simultaneously:: - - sage: c = d = 1 - sage: c, d - (1, 1) - sage: d = 2 - sage: c, d - (1, 2) - -Note that when we use the word *variable* in the computer-science sense we -mean "a label attached to some data stored by Sage". Once an object is -created, some *methods* apply to it. This means *functions* but instead of -writing **f(my_object)** you write **my_object.f()**:: - - sage: p = 17 - sage: p.is_prime() - True - -See :ref:`tutorial-objects-and-classes` for details. -To know all methods of an object you can once more use tab-completion. Write the -name of the object followed by a dot and then press ``tab``: - -.. skip - -:: - - sage: a. - - sage: # edit here - -.. TOPIC:: Exercise B - - Create the permutation 51324 and assign it to the variable ``p``. - - .. skip - - :: - - sage: Permutation? - - :: - - sage: # edit here - - - What is the ``inverse`` of ``p``? - - .. skip - - :: - - sage: p.inv - - sage: # edit here - - Does ``p`` have the ``pattern`` 123? What about 1234? And 312? (even if you don't - know what a pattern is, you should be able to find a command that does this). - - .. skip - - :: - - sage: p.pat - - sage: # edit here - -Some linear algebra -=================== - -.. TOPIC:: Exercise C - - Use the :func:`matrix` command to create the following matrix. - - .. MATH:: - - M = \left(\begin{array}{rrrr} - 10 & 4 & 1 & 1 \\ - 4 & 6 & 5 & 1 \\ - 1 & 5 & 6 & 4 \\ - 1 & 1 & 4 & 10 - \end{array}\right) - - .. skip - - :: - - sage: matrix? - - :: - - sage: # edit here - - Then, using methods of the matrix, - - 1. Compute the determinant of the matrix. - 2. Compute the echelon form of the matrix. - 3. Compute the eigenvalues of the matrix. - 4. Compute the kernel of the matrix. - 5. Compute the LLL decomposition of the matrix (and lookup the - documentation for what LLL is if needed!) - - :: - - sage: # edit here - - sage: # edit here - - Now that you know how to access the different methods of matrices, - - 6. Create the vector `v = (1,-1,-1,1)`. - 7. Compute the two products: `M\cdot v` and `v\cdot M`. What mathematically - borderline operation is Sage doing implicitly? - - .. skip - - :: - - sage: vector? - - :: - - sage: # edit here - -.. NOTE:: - - Vectors in Sage are row vectors. A method such as ``eigenspaces`` might not - return what you expect, so it is best to specify ``eigenspaces_left`` or - ``eigenspaces_right`` instead. Same thing for kernel (``left_kernel`` or - ``right_kernel``), and so on. - - -Some Plotting -============= - -The :func:`plot` command allows you to draw plots of functions. Recall -that you can access the documentation by pressing the ``tab`` key -after writing ``plot?`` in a cell: - -.. skip - -:: - - sage: plot? - -:: - - sage: # edit here - -Here is a simple example:: - - sage: var('x') # make sure x is a symbolic variable - x - sage: plot(sin(x^2), (x,0,10)) - Graphics object consisting of 1 graphics primitive - -Here is a more complicated plot. Try to change every single input to the plot -command in some way, evaluating to see what happens:: - - sage: P = plot(sin(x^2), (x,-2,2), rgbcolor=(0.8,0,0.2), thickness=3, linestyle='--', fill='axis') - sage: show(P, gridlines=True) - -Above we used the :func:`show` command to show a plot after it was created. You can -also use ``P.show`` instead:: - - sage: P.show(gridlines=True) - -Try putting the cursor right after ``P.show(`` and pressing tab to get a list of -the options for how you can change the values of the given inputs. - -.. skip - -:: - - sage: P.show( - -Plotting multiple functions at once is as easy as adding them together:: - - sage: P1 = plot(sin(x), (x,0,2*pi)) - sage: P2 = plot(cos(x), (x,0,2*pi), rgbcolor='red') - sage: P1 + P2 - Graphics object consisting of 2 graphics primitives - -Symbolic Expressions -==================== - -Here is an example of a symbolic function:: - - sage: f(x) = x^4 - 8*x^2 - 3*x + 2 - sage: f(x) - x^4 - 8*x^2 - 3*x + 2 - - sage: f(-3) - 20 - -This is an example of a function in the *mathematical* variable `x`. When Sage -starts, it defines the symbol `x` to be a mathematical variable. If you want -to use other symbols for variables, you must define them first:: - - sage: x^2 - x^2 - sage: u + v - Traceback (most recent call last): - ... - NameError: name 'u' is not defined - - sage: var('u v') - (u, v) - sage: u + v - u + v - -Still, it is possible to define symbolic functions without first -defining their variables:: - - sage: f(w) = w^2 - sage: f(3) - 9 - -In this case those variables are defined implicitly:: - - sage: w - w - -.. TOPIC:: Exercise D - - Define the symbolic function `f(x) = x \sin(x^2)`. Plot `f` on the - domain `[-3,3]` and color it red. Use the :func:`find_root` method to - numerically approximate the root of `f` on the interval `[1,2]`:: - - sage: # edit here - - Compute the tangent line to `f` at `x=1`:: - - sage: # edit here - - Plot `f` and the tangent line to `f` at `x=1` in one image:: - - sage: # edit here - -.. TOPIC:: Exercise E (Advanced) - - Solve the following equation for `y`: - - .. MATH:: - - y = 1 + x y^2 - - There are two solutions, take the one for which `\lim_{x\to0}y(x)=1`. - (Don't forget to create the variables `x` and `y`!). - - :: - - sage: # edit here - - Expand `y` as a truncated Taylor series around `0` and containing - `n=10` terms. - - :: - - sage: # edit here - - Do you recognize the coefficients of the Taylor series expansion? You might - want to use the `On-Line Encyclopedia of Integer Sequences - `_, or better yet, Sage's class :class:`OEIS` which - queries the encyclopedia: - - .. skip - - :: - - - sage: oeis? - - :: - - sage: # edit here - -Congratulations for completing your first Sage tutorial! diff --git a/src/doc/en/tutorial/latex.rst b/src/doc/en/tutorial/latex.rst index 46498619539..e2bc6816008 100644 --- a/src/doc/en/tutorial/latex.rst +++ b/src/doc/en/tutorial/latex.rst @@ -491,21 +491,3 @@ mathematics examination can maintain a correct correspondence between questions and answers by using sagetex to have Sage compute one from the other. See :ref:`sec-sagetex` for more information. - - -tex2sws begins with a LaTeX document, but defines extra -environments for the placement of Sage code. When processed with -the right tools, the result is a Sage worksheet, with content -properly formatted for MathJax and the Sage code incorporated as -input cells. So a textbook or article can be authored in -LaTeX, blocks of Sage code included, and the whole -document can be transformed into a Sage worksheet where the -mathematical text is nicely formatted and the blocks of Sage code -are "live." Currently in development, see `tex2sws @ BitBucket -`_ for more information. - -sws2tex reverses the process by beginning with a Sage worksheet -and converting it to legitimate LaTeX for subsequent -processing with all the tools available for LaTeX -documents. Currently in development, see `sws2tex @ BitBucket -`_ for more information. diff --git a/src/doc/fr/tutorial/latex.rst b/src/doc/fr/tutorial/latex.rst index 5082872a0ca..a66eea92e7c 100644 --- a/src/doc/fr/tutorial/latex.rst +++ b/src/doc/fr/tutorial/latex.rst @@ -460,21 +460,3 @@ on peut imaginer de maintenir la correspondance entre questions et réponses dans un sujet d'examen en utilisant Sage pour calculer les unes à partir des autres. Sagetex est décrit plus en détail en section :ref:`sec-sagetex` de ce document. - -tex2sws est un convertisseur LaTeX vers feuille de travail Sage. Il prend lui -aussi en entrée un document LaTeX contenant du code Sage dans des -environnements spécifiques. Après traitement convenable, on obtient une feuille -de travail pour le bloc-notes, dans laquelle les formules du document de départ -sont affichées avec MathJax et le code Sage repris dans des cellules d'entrée. -Ainsi, un manuel ou un article initialement rédigé avec LaTeX qui contient du -code Sage peut être transformé en une page web interactive où les formules -mathématiques restent formatées correctement tandis que les blocs de code Sage -deviennent exécutables. Cet outil est en cours de développement, on consultera -la page `tex2sws @ BitBucket `_ pour -plus d'information. - -sws2tex fait l'inverse : il part d'une feuille de travail Sage, qu'il convertit -en document LaTeX pour permettre de la traiter ensuite avec tous les outils -disponibles pour les documents LaTeX. sws2tex est en cours de développement, on -pourra se référer à la page `sws2tex @ BitBucket -`_ pour plus d'information. diff --git a/src/doc/ja/tutorial/latex.rst b/src/doc/ja/tutorial/latex.rst index 39573f38bce..12162959f3b 100644 --- a/src/doc/ja/tutorial/latex.rst +++ b/src/doc/ja/tutorial/latex.rst @@ -402,14 +402,3 @@ TeXとSageのさらなる統合運用に役立つプログラムが三つある LaTeX文書のコンパイル処理過程で,Sageの演算やLaTeXによるフォーマット支援などの全ての機能も自動的に実行されるのである. sagetexを使えば,例えば数学試験作成において,問題の計算そのものをSageに実行させて対応する解答を正確に維持管理することなどが可能になる. 詳細は :ref:`sec-sagetex` 節を参照してほしい. - - -tex2swsはLaTeX文書にSageコードを組込むための環境を定義している. -これをしかるべきツールで処理すると,MathJaxで適切に表示される本文と入力セル経由で動作するSageコードが組込まれたSageワークシートが出来上がる. -tex2sws環境を使えばLaTeXで教科書や記事をSageコードのブロックを含んだ形で執筆することができるが,これを変換すると数式混じりの本文は美しく整形され,かつSageコード部分が機能するSageワークシートになるわけである. -現在も開発進行中で,詳細は `tex2sws @ BitBucket `_ を見てほしい. - - -これとは逆に,sws2texはSageワークシートをLaTeX形式に変換してLaTeX関連ツールによる処理を可能にする. -現在も開発中で,詳細は `sws2tex @ BitBucket `_ を見てほしい. - diff --git a/src/doc/pt/tutorial/latex.rst b/src/doc/pt/tutorial/latex.rst index 3bc919e14e1..b31804422e9 100644 --- a/src/doc/pt/tutorial/latex.rst +++ b/src/doc/pt/tutorial/latex.rst @@ -492,21 +492,3 @@ ser executados automaticamente. Como um exemplo, um exame matemático pode manter uma correspondência entre questões e respostas usando o sagetex para fazer cálculos com o Sage. Veja :ref:`sec-sagetex` para mais informações. - -O tex2sws começa com um documento LaTeX, mas define ambientes -adicionais para inserir código em Sage. Quando processado com as -ferramentas adequadas, o resultado é uma folha de trabalho do Sage, -com conteúdo apropriadamente formatado para o MathJax e com código em -Sage incorporado como células de entrada. Então um livro texto ou -artigo pode ser criado em LaTeX, ter blocos de código em Sage -incluídos, e o documento todo pode ser transformado em uma folha de -trabalho do Sage onde o texto matemático é bem formatado e os blocos -de código em Sage podem ser facilmente executados. Atualmente em -desenvolvimento, veja `tex2sws @ BitBucket -`_ para mais informações. - -O sws2tex reverte o processo partindo de uma folha de trabalho do Sage -e convertendo o conteúdo para LaTeX para ser posteriormente processado -com as ferramentas disponíveis para documentos em LaTeX. Atualmente em -desenvolvimento, veja `sws2tex @ BitBucket -`_ para mais informações. From b2d66ff6d4fe24ff91e23169aa9c13cf5a2a4887 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 6 Jul 2020 19:55:11 +0100 Subject: [PATCH 148/217] removed _section-notebook and rewrote --- src/doc/de/tutorial/interactive_shell.rst | 10 ------- src/doc/de/tutorial/introduction.rst | 4 +-- src/doc/en/tutorial/interactive_shell.rst | 9 ------- src/doc/en/tutorial/introduction.rst | 4 +-- src/doc/es/tutorial/introduction.rst | 5 ++-- src/doc/fr/tutorial/interactive_shell.rst | 32 ----------------------- src/doc/fr/tutorial/introduction.rst | 5 ++-- src/doc/ja/tutorial/interactive_shell.rst | 9 ------- src/doc/ja/tutorial/introduction.rst | 3 ++- src/doc/pt/tutorial/interactive_shell.rst | 9 ------- src/doc/pt/tutorial/introduction.rst | 4 +-- src/doc/ru/tutorial/interactive_shell.rst | 9 ------- src/doc/ru/tutorial/introduction.rst | 4 +-- 13 files changed, 14 insertions(+), 93 deletions(-) diff --git a/src/doc/de/tutorial/interactive_shell.rst b/src/doc/de/tutorial/interactive_shell.rst index 71fc309e4df..bb9ac60b903 100644 --- a/src/doc/de/tutorial/interactive_shell.rst +++ b/src/doc/de/tutorial/interactive_shell.rst @@ -868,13 +868,3 @@ Variable ``b`` wurde nicht überschrieben. sage: a 389 - - -.. _section-notebook: - -Die Notebook Umgebung -===================== - -SageMath wird demnächst die `Jupyter notebook -`_ -als Hauptnotebookoption verwenden. diff --git a/src/doc/de/tutorial/introduction.rst b/src/doc/de/tutorial/introduction.rst index a1f7360ecb8..28aab155157 100644 --- a/src/doc/de/tutorial/introduction.rst +++ b/src/doc/de/tutorial/introduction.rst @@ -110,8 +110,8 @@ Wie man Sage benutzen kann Sie können Sage auf verschiedene Weise benutzen. -- **graphisches Notebook-Interface:** lesen Sie den Abschnitt - zum Notebook im Referenzhandbuch und :ref:`section-notebook` weiter unten, +- **graphisches Notebook-Interface:** aufrufen Sie `sage -n jupyter`; lesen Sie + `Jupyter documentation on-line `_, - **interaktive Kommandozeile:** lesen Sie :ref:`chapter-interactive_shell`, diff --git a/src/doc/en/tutorial/interactive_shell.rst b/src/doc/en/tutorial/interactive_shell.rst index 26e5ee37aa1..d1407f09d38 100644 --- a/src/doc/en/tutorial/interactive_shell.rst +++ b/src/doc/en/tutorial/interactive_shell.rst @@ -945,12 +945,3 @@ Each saved variable is again available. Moreover, the variable sage: a 389 - - -.. _section-notebook: - -The Notebook Interface -============================= - -SageMath is using the `Jupyter notebook -`_ as the default. diff --git a/src/doc/en/tutorial/introduction.rst b/src/doc/en/tutorial/introduction.rst index 10f929fc971..8364820c47a 100644 --- a/src/doc/en/tutorial/introduction.rst +++ b/src/doc/en/tutorial/introduction.rst @@ -103,8 +103,8 @@ Ways to Use Sage You can use Sage in several ways. -- **Notebook graphical interface:** see the section on the - Notebook in the reference manual and :ref:`section-notebook` below, +- **Notebook graphical interface:** run `sage -n jupyter`; see + `the Jupyter documentation on-line `_, - **Interactive command line:** see :ref:`chapter-interactive_shell`, diff --git a/src/doc/es/tutorial/introduction.rst b/src/doc/es/tutorial/introduction.rst index 999e26cb4b7..97273f80498 100644 --- a/src/doc/es/tutorial/introduction.rst +++ b/src/doc/es/tutorial/introduction.rst @@ -104,9 +104,8 @@ Formas de usar Sage Puedes usar Sage de varias maneras. -- **Interfáz gráfico del Notebook:** Permite usar Sage en forma interactiva - desde el navegador web. Véase la sección que trata sobre el - Notebook en el manual de referencia, +- **Interfáz gráfico del Notebook:** run `sage -n jupyter`; see + `the Jupyter documentation on-line `_, - **Línea de comandos interactiva:**, diff --git a/src/doc/fr/tutorial/interactive_shell.rst b/src/doc/fr/tutorial/interactive_shell.rst index b9aaf9ba9c7..b8158786ab4 100644 --- a/src/doc/fr/tutorial/interactive_shell.rst +++ b/src/doc/fr/tutorial/interactive_shell.rst @@ -963,35 +963,3 @@ la variable ``b`` n'a pas été écrasée. sage: a 389 - - -.. _section-notebook: - -L'ancienne interface *bloc-note sagenb* -======================================= - -L'ancien bloc-note de Sage (“sagenb”) est obsolète et n'est plus -disponible à partir de la version 9.0 de SageMath, pour cause -d'incompatibilité avec Python 3. SageMath utilise désormais le -`bloc-note Jupyter -`_. - -Pour les utilisateurs, une différence notable est la suivante : les -feuilles de calcul du bloc-note Jupyter sont sauvegardées sous le -nouveau format ``.ipynb`` dans le système de fichiers local comme -n'importe quel autre fichier, alors que pour l'ancien bloc-note le -principal accès aux feuilles de calcul passait par le serveur. - -La nouvelle interface *bloc-note Jupyter* -========================================= - -Pour démarrer le bloc-note Jupyter, tapez - -.. skip - -:: - - sage -n jupyter - -sur la ligne de commande dans un terminal. Cela démarre le serveur Jupyter et -ouvre votre navigateur web par défaut sur la page correspondante. diff --git a/src/doc/fr/tutorial/introduction.rst b/src/doc/fr/tutorial/introduction.rst index 3937ed183fe..74d2570a8bc 100644 --- a/src/doc/fr/tutorial/introduction.rst +++ b/src/doc/fr/tutorial/introduction.rst @@ -108,9 +108,8 @@ Les différentes manières d'utiliser Sage Il y a plusieurs façons d'utiliser Sage. -- **Interface graphique (« notebook ») :** voir la section sur le - *Notebook* du manuel de référence, et :ref:`section-notebook` - ci-dessous ; +- **Interface graphique (« notebook ») :** run `sage -n jupyter`; see + `Jupyter documentation on-line `_ ; - **Ligne de commande :** voir :ref:`chapter-interactive_shell` ; diff --git a/src/doc/ja/tutorial/interactive_shell.rst b/src/doc/ja/tutorial/interactive_shell.rst index e454ea3cc91..6abce17c4b6 100644 --- a/src/doc/ja/tutorial/interactive_shell.rst +++ b/src/doc/ja/tutorial/interactive_shell.rst @@ -886,12 +886,3 @@ Sageは,セッション全体を保存し再ロードするための非常に sage: a 389 - - -.. _section-notebook: - -ノートブックインターフェイス -================================== - -SageMath is using the `Jupyter notebook -`_ as the default. diff --git a/src/doc/ja/tutorial/introduction.rst b/src/doc/ja/tutorial/introduction.rst index 98cddfa9b7f..a10dccd3d18 100644 --- a/src/doc/ja/tutorial/introduction.rst +++ b/src/doc/ja/tutorial/introduction.rst @@ -83,7 +83,8 @@ Sageの使いかた Sageを使うには以下のようなやり方がある. -- **ノートブック グラフィカル インターフェイス:** レファレンスマニュアルのノートブックに関する節,および以下の :ref:`section-notebook` 節を参照. +- **ノートブック グラフィカル インターフェイス:** run `sage -n jupyter`; see + `the Jupyter documentation on-line `_. - **対話的コマンドライン:** :ref:`chapter-interactive_shell` 節を参照. diff --git a/src/doc/pt/tutorial/interactive_shell.rst b/src/doc/pt/tutorial/interactive_shell.rst index 3552cc4d3f0..29e2e395331 100644 --- a/src/doc/pt/tutorial/interactive_shell.rst +++ b/src/doc/pt/tutorial/interactive_shell.rst @@ -936,12 +936,3 @@ variável ``b`` não foi redefinida. sage: a 389 - - -.. _section-notebook: - -A Interface do Notebook -======================= - -SageMath está em transição para uso do -`Jupyter `_. diff --git a/src/doc/pt/tutorial/introduction.rst b/src/doc/pt/tutorial/introduction.rst index 3446f4f5720..aad63101448 100644 --- a/src/doc/pt/tutorial/introduction.rst +++ b/src/doc/pt/tutorial/introduction.rst @@ -103,8 +103,8 @@ Formas de usar o Sage Você pode usar o Sage de diversas formas. -- **Interface gráfica Notebook:** veja a seção sobre o Notebook em - :ref:`section-notebook`, +- **Interface gráfica Notebook:** run `sage -n jupyter`; see + `Jupyter documentation on-line `_, - **Linha de comando interativa:** veja :ref:`chapter-interactive_shell`, diff --git a/src/doc/ru/tutorial/interactive_shell.rst b/src/doc/ru/tutorial/interactive_shell.rst index 967409bf989..7e0b3f43795 100644 --- a/src/doc/ru/tutorial/interactive_shell.rst +++ b/src/doc/ru/tutorial/interactive_shell.rst @@ -840,12 +840,3 @@ Sage обладает очень гибкими возможностями со sage: a 389 - - -.. _section-notebook: - -Интерфейс Notebook -============================= - -SageMath перешел на -`Jupyter notebook `_. diff --git a/src/doc/ru/tutorial/introduction.rst b/src/doc/ru/tutorial/introduction.rst index 8489fd51c85..9da1c11dd07 100644 --- a/src/doc/ru/tutorial/introduction.rst +++ b/src/doc/ru/tutorial/introduction.rst @@ -98,8 +98,8 @@ Sage в разделе документации: [SA]_ Здесь мы прив Работа в Sage может быть осуществлена несколькими путями: -- **Notebook (графический интерфейс):** см. раздел о Notebook в справочном - руководстве, а также :ref:`section-notebook` ниже; +- **Notebook (графический интерфейс):** запустите `sage -n jupyter`; читайте + `Jupyter documentation on-line `_, - **Интерактивная командная строка:** см. :ref:`chapter-interactive_shell`; From b42bae2410dead90c94feada01f67895da0adef1 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 6 Jul 2020 20:31:27 +0100 Subject: [PATCH 149/217] google-translated for es/fr/ja/pt --- src/doc/es/tutorial/introduction.rst | 4 ++-- src/doc/fr/tutorial/introduction.rst | 2 +- src/doc/ja/tutorial/introduction.rst | 4 ++-- src/doc/pt/tutorial/introduction.rst | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/es/tutorial/introduction.rst b/src/doc/es/tutorial/introduction.rst index 97273f80498..f2564c420d6 100644 --- a/src/doc/es/tutorial/introduction.rst +++ b/src/doc/es/tutorial/introduction.rst @@ -104,8 +104,8 @@ Formas de usar Sage Puedes usar Sage de varias maneras. -- **Interfáz gráfico del Notebook:** run `sage -n jupyter`; see - `the Jupyter documentation on-line `_, +- **Interfáz gráfico del Notebook:** iniciar `sage -n jupyter`; leer + `Jupyter documentation on-line `_, - **Línea de comandos interactiva:**, diff --git a/src/doc/fr/tutorial/introduction.rst b/src/doc/fr/tutorial/introduction.rst index 74d2570a8bc..1cabe9676f4 100644 --- a/src/doc/fr/tutorial/introduction.rst +++ b/src/doc/fr/tutorial/introduction.rst @@ -108,7 +108,7 @@ Les différentes manières d'utiliser Sage Il y a plusieurs façons d'utiliser Sage. -- **Interface graphique (« notebook ») :** run `sage -n jupyter`; see +- **Interface graphique (« notebook ») :** démarrer `sage -n jupyter`; lire `Jupyter documentation on-line `_ ; - **Ligne de commande :** voir :ref:`chapter-interactive_shell` ; diff --git a/src/doc/ja/tutorial/introduction.rst b/src/doc/ja/tutorial/introduction.rst index a10dccd3d18..004c67dcad1 100644 --- a/src/doc/ja/tutorial/introduction.rst +++ b/src/doc/ja/tutorial/introduction.rst @@ -83,8 +83,8 @@ Sageの使いかた Sageを使うには以下のようなやり方がある. -- **ノートブック グラフィカル インターフェイス:** run `sage -n jupyter`; see - `the Jupyter documentation on-line `_. +- **ノートブック グラフィカル インターフェイス:** `sage -n jupyter` を起動します。 + `Jupyter documentation on-line `_ を読む. - **対話的コマンドライン:** :ref:`chapter-interactive_shell` 節を参照. diff --git a/src/doc/pt/tutorial/introduction.rst b/src/doc/pt/tutorial/introduction.rst index aad63101448..ba676759d06 100644 --- a/src/doc/pt/tutorial/introduction.rst +++ b/src/doc/pt/tutorial/introduction.rst @@ -103,7 +103,7 @@ Formas de usar o Sage Você pode usar o Sage de diversas formas. -- **Interface gráfica Notebook:** run `sage -n jupyter`; see +- **Interface gráfica Notebook:** inicie `sage -n jupyter`; leia `Jupyter documentation on-line `_, - **Linha de comando interativa:** veja From e7f698133dcc5d5116e3b71c1341d017064b86c1 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Tue, 7 Jul 2020 09:06:33 +0100 Subject: [PATCH 150/217] complete rebase by stripping last bits of sws also, we can remove mentioning of sws in few TODOs --- src/bin/sage | 4 ---- src/mac-app/AppController.m | 4 ++-- src/setup.py | 2 -- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/bin/sage b/src/bin/sage index b7e7d0c28ac..545a21aab23 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -419,10 +419,6 @@ usage_advanced() { echo " a Jupyter notebook (.ipynb)." echo " --rst2txt [...] -- Generates Sage worksheet text file from standalone" echo " reStructuredText source." - echo " --rst2sws [...] -- Generates Sage worksheet (.sws) from standalone" - echo " reStructuredText source." - echo " --sws2rst -- Generates a reStructuredText source file from" - echo " a Sage worksheet (.sws) document." echo #### 1.......................26..................................................78 #### |.....................--.|...................................................| diff --git a/src/mac-app/AppController.m b/src/mac-app/AppController.m index 161a8a70277..be8a19b538c 100644 --- a/src/mac-app/AppController.m +++ b/src/mac-app/AppController.m @@ -852,9 +852,9 @@ -(BOOL)isTigerOrLess{ // TODO: make installing packages easy -- stringByLaunchingPath:withArguments:error: // TODO: maybe this should be written in py-objc so that we can call into sage directly (but then we would have to worry about environment etc.) -// TODO: make some services (search for NSSendTypes) -- pack/unpack spkg, extract sws from pdf, crap/fixdoctests/preparse/Test/coverage/pkg/pkg_nc/etc. +// TODO: make some services (search for NSSendTypes) -- pack/unpack spkg, crap/fixdoctests/preparse/Test/coverage/pkg/pkg_nc/etc. -// TODO: open files such as .sws, .sage, .py, .spkg, -- .pdf (and extract sws from them), .htm, whatever else I can handle +// TODO: open files such as .sage, .py, .spkg, -- .pdf, .htm, whatever else I can handle // TODO: quicklook generator, spotlight importer -- use UTI // NOTE: http://developer.apple.com/mac/library/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html // TODO: icons for files -- they need some help with the alpha channel. I clearly don't know what I'm doing. I should really make them all from by script... diff --git a/src/setup.py b/src/setup.py index 4b82e1a57fb..ac9cfb616e4 100755 --- a/src/setup.py +++ b/src/setup.py @@ -157,12 +157,10 @@ 'bin/sage-rebase.sh', 'bin/sage-rebaseall.bat', 'bin/sage-rebaseall.sh', - 'bin/sage-rst2sws', 'bin/sage-rst2txt', 'bin/sage-run', 'bin/sage-run-cython', 'bin/sage-startuptime.py', - 'bin/sage-sws2rst', 'bin/sage-update-src', 'bin/sage-update-version', 'bin/sage-upgrade', From 979aaa778bb9a40f6b7d3b2d3217d30024d7c4c2 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Tue, 7 Jul 2020 09:12:32 +0100 Subject: [PATCH 151/217] fix DE typo --- src/doc/de/tutorial/introduction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/de/tutorial/introduction.rst b/src/doc/de/tutorial/introduction.rst index 28aab155157..a40dd4d59fb 100644 --- a/src/doc/de/tutorial/introduction.rst +++ b/src/doc/de/tutorial/introduction.rst @@ -110,7 +110,7 @@ Wie man Sage benutzen kann Sie können Sage auf verschiedene Weise benutzen. -- **graphisches Notebook-Interface:** aufrufen Sie `sage -n jupyter`; lesen Sie +- **graphisches Notebook-Interface:** rufen Sie `sage -n jupyter` auf; lesen Sie `Jupyter documentation on-line `_, - **interaktive Kommandozeile:** lesen Sie :ref:`chapter-interactive_shell`, From 2d962ea287eb135498afb0b95056ef385c523f1f Mon Sep 17 00:00:00 2001 From: Reimundo Heluani Date: Tue, 7 Jul 2020 10:22:10 -0300 Subject: [PATCH 152/217] small fixes to the tutorial in spanish --- src/doc/es/tutorial/introduction.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/doc/es/tutorial/introduction.rst b/src/doc/es/tutorial/introduction.rst index f2564c420d6..a0b02e01e63 100644 --- a/src/doc/es/tutorial/introduction.rst +++ b/src/doc/es/tutorial/introduction.rst @@ -3,9 +3,9 @@ Introducción ************ Completar este tutorial debería llevarte unas 3 o 4 horas. Puedes leerlo en versión HTML o PDF, o desde el -notebook (interfaz interactiva vía web) de Sage (Haz click en ``Help``, luego haz click en ``Tutorial`` para trabajar interactivamente en el tutorial desde dentro de Sage). +notebook (interfaz interactiva vía web) de Sage (haz click en ``Help``, luego haz click en ``Tutorial`` para trabajar interactivamente en el tutorial desde dentro de Sage). -Aunque gran parte de Sage está implementado usando el lenguaje de programación +Aunque gran parte de Sage está implementada usando el lenguaje de programación Python, no es necesario ningún conocimiento previo de Python para poder leer este tutorial. En algún punto seguramente querrás aprender Python (¡un lenguaje muy divertido!), y hay muchos recursos gratuitos excelentes para hacerlo, incluyendo [PyT]_ y [Dive]_. @@ -56,7 +56,7 @@ Instalación ============ Si no tienes instalado Sage en tu computador y sólo quieres -probar algunos comandos, usa la versión en linea en http://sagecell.sagemath.org. +probar algunos comandos, usa la versión en línea en http://sagecell.sagemath.org. Mira la Guía De Instalación Para Sage en la sección de documentación de la página web principal de [Sage]_ para obtener instrucciones sobre cómo instalar @@ -84,7 +84,7 @@ Sage en tu computador. Aquí hacemos simplemente dos comentarios: los resultados de tus cálculos con Sage en un archivo LaTeX), necesitarás hacerle conocer SageTeX a tu distribución de TeX. Para hacer esto, consulta la sección - "Haciendo que TeX conozca a SageTeX" en la guía de intalación de Sage + "Haciendo que TeX conozca a SageTeX" en la guía de instalación de Sage `Sage installation guide `_ (`Este enlace <../../en/installation/index.html>`_ debería llevarte a tu copia @@ -104,7 +104,7 @@ Formas de usar Sage Puedes usar Sage de varias maneras. -- **Interfáz gráfico del Notebook:** iniciar `sage -n jupyter`; leer +- **Interfaz gráfico del Notebook:** iniciar `sage -n jupyter`; leer `Jupyter documentation on-line `_, - **Línea de comandos interactiva:**, @@ -132,7 +132,7 @@ Metas a largo plazo de Sage libremente disponible, de modo que los usuarios puedan entender qué está haciendo realmente el sistema y así poder extenderlo fácilmente. Tal como los matemáticos logran un entendimiento más profundo de un teorema al leerlo cuidadosamente o, por lo - ménos, al echarle una ojeada a la prueba, la gente que efectúa cálculos debe ser capaz de comprender + menos, al echarle una ojeada a la prueba, la gente que efectúa cálculos debe ser capaz de comprender cómo funcionan los cálculos leyendo el código fuente documentado. Si utilizas Sage para hacer cálculos en un artículo que vas a publicar, puedes estar seguro que tus lectores siempre tendrán libre acceso @@ -155,7 +155,7 @@ Metas a largo plazo de Sage - **Extensible:** Debe ser posible definir nuevos tipos de datos o derivar de tipos incorporados y utilizar código escrito en una amplia gama de lenguajes. -- **Fácil de usar**: Debe de ser fácil comprender qué +- **Fácil de usar**: Debe de ser fácil comprender cual funcionalidad se ha provisto para un objeto dado y examinar la documentación y el código fuente, así como alcanzar un alto nivel de soporte al usuario. From cd421040539e989ee9e115fd3220ec1bda64eedd Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 20 Jul 2020 21:11:41 +0100 Subject: [PATCH 153/217] remove stray file --- t | 7 ------- 1 file changed, 7 deletions(-) delete mode 100755 t diff --git a/t b/t deleted file mode 100755 index 094d00d25b8..00000000000 --- a/t +++ /dev/null @@ -1,7 +0,0 @@ -if test x`locale -a | grep C\.UTF-8` != x; then - export LC_ALL=C.UTF-8; -else - export LC_ALL=C; -fi - -echo $LC_ALL From 5e8765e354de92831cc514da9eca775a3b19c8fd Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 20 Jul 2020 14:12:07 -0700 Subject: [PATCH 154/217] build/pkgs/ecl/spkg-install.in: Disable building the manual if SAGE_SPKG_INSTALL_DOCS != yes --- build/pkgs/ecl/spkg-install.in | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/build/pkgs/ecl/spkg-install.in b/build/pkgs/ecl/spkg-install.in index 6a4d1eabf2b..bf6a769d96a 100644 --- a/build/pkgs/ecl/spkg-install.in +++ b/build/pkgs/ecl/spkg-install.in @@ -37,13 +37,17 @@ echo "" # Use newer version of config.guess and config.sub (see Trac #19732) cp "$SAGE_ROOT"/config/config.* src -# ECL 2020 needs modern makeinfo -command -v texi2any >/dev/null 2>&1 -if [ $? -ne 0 ]; then # texi2any not found -> makeinfo too old, if present - ECL_CONFIGURE="$ECL_CONFIGURE --enable-manual=no" +if [ x"$SAGE_SPKG_INSTALL_DOCS" != xyes ] ; then + ECL_CONFIGURE="$ECL_CONFIGURE --enable-manual=no" +else + # ECL 2020 needs modern makeinfo + command -v texi2any >/dev/null 2>&1 + if [ $? -ne 0 ]; then # texi2any not found -> makeinfo too old, if present + ECL_CONFIGURE="$ECL_CONFIGURE --enable-manual=no" + fi fi -sdh_configure $SAGE_CONFIGURE_GMP --disable-threads --disable-manual \ +sdh_configure $SAGE_CONFIGURE_GMP --disable-threads \ --enable-unicode=yes --with-defsystem $ECL_CONFIGURE # Before running make we touch build/TAGS so its building process is never triggered From 42e6c43198528cc864456894cb8476085474ed5a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 20 Jul 2020 14:20:28 -0700 Subject: [PATCH 155/217] build/pkgs/ecl/spkg-install.in: Add test for makeinfo -c --- build/pkgs/ecl/spkg-install.in | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build/pkgs/ecl/spkg-install.in b/build/pkgs/ecl/spkg-install.in index bf6a769d96a..4e2d7aa2763 100644 --- a/build/pkgs/ecl/spkg-install.in +++ b/build/pkgs/ecl/spkg-install.in @@ -44,6 +44,12 @@ else command -v texi2any >/dev/null 2>&1 if [ $? -ne 0 ]; then # texi2any not found -> makeinfo too old, if present ECL_CONFIGURE="$ECL_CONFIGURE --enable-manual=no" + else + if makeinfo -c foo 2>&1 | grep -q invalid; then + # makeinfo found but does not support all options that ecl + # likes to use + ECL_CONFIGURE="$ECL_CONFIGURE --enable-manual=no" + fi fi fi From 81fa95dd8abee38ce70b57d35f1aa3c8667c7ffd Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Mon, 20 Jul 2020 23:38:31 +0200 Subject: [PATCH 156/217] Trac #30094: indexing improved --- src/sage/tensor/modules/finite_rank_free_module.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/sage/tensor/modules/finite_rank_free_module.py b/src/sage/tensor/modules/finite_rank_free_module.py index 72a0dd7dede..241a3624c1e 100644 --- a/src/sage/tensor/modules/finite_rank_free_module.py +++ b/src/sage/tensor/modules/finite_rank_free_module.py @@ -2548,13 +2548,12 @@ def isomorphism_with_fixed_basis(self, basis, codomain=None): sage: phi_e = V.isomorphism_with_fixed_basis(basis); phi_e Generic morphism: From: 3-dimensional vector space over the Rational Field - To: Free module generated by {'e_1', 'e_2', 'e_3'} over - Rational Field + To: Free module generated by {1, 2, 3} over Rational Field sage: phi_e.codomain().category() Category of finite dimensional vector spaces with basis over Rational Field sage: phi_e(e[1] + 2 * e[2]) - B['e_1'] + 2*B['e_2'] + B[1] + 2*B[2] TESTS:: @@ -2575,8 +2574,7 @@ def isomorphism_with_fixed_basis(self, basis, codomain=None): if codomain is None: from sage.combinat.free_module import CombinatorialFreeModule - codomain = CombinatorialFreeModule(base_ring, - [b._name for b in basis]) + codomain = CombinatorialFreeModule(base_ring, list(self.irange())) else: if codomain.rank() != self.rank(): raise ValueError("domain and codomain must have the same rank") From 5657108b4d0ea40f08e79de42e1a7675dd2f2400 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 20 Jul 2020 14:49:31 -0700 Subject: [PATCH 157/217] Add an example with a provided codomain --- src/sage/tensor/modules/finite_rank_free_module.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/sage/tensor/modules/finite_rank_free_module.py b/src/sage/tensor/modules/finite_rank_free_module.py index 241a3624c1e..c5bcdf442f9 100644 --- a/src/sage/tensor/modules/finite_rank_free_module.py +++ b/src/sage/tensor/modules/finite_rank_free_module.py @@ -2555,6 +2555,16 @@ def isomorphism_with_fixed_basis(self, basis, codomain=None): sage: phi_e(e[1] + 2 * e[2]) B[1] + 2*B[2] + Providing a codomain:: + + sage: W = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) + sage: phi_eW = V.isomorphism_with_fixed_basis(basis, codomain=W); phi_eW + Generic morphism: + From: 3-dimensional vector space over the Rational Field + To: Free module generated by {'a', 'b', 'c'} over Rational Field + sage: phi_eW(e[1] + 2 * e[2]) + B['a'] + 2*B['b'] + TESTS:: sage: V = FiniteRankFreeModule(QQ, 3); V From 7d0a8581d86a0b2f2a3f2c40969f648310173908 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 21 Jul 2020 09:57:18 +1000 Subject: [PATCH 158/217] Fixing doctest failure and pyflakes. --- src/sage/combinat/posets/d_complete.py | 1 - src/sage/combinat/posets/forest.py | 3 +-- src/sage/combinat/posets/hasse_diagram.py | 2 +- src/sage/combinat/posets/linear_extensions.py | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index 56617771a58..ef4e85f8324 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -16,7 +16,6 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.combinat.posets.posets import Poset, FinitePoset from sage.misc.lazy_attribute import lazy_attribute from .linear_extensions import LinearExtensionsOfPosetWithHooks from .lattices import FiniteJoinSemilattice diff --git a/src/sage/combinat/posets/forest.py b/src/sage/combinat/posets/forest.py index 5dac3005a98..41e29cd5f9a 100644 --- a/src/sage/combinat/posets/forest.py +++ b/src/sage/combinat/posets/forest.py @@ -16,8 +16,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.combinat.posets.posets import Poset, FinitePoset -from sage.misc.lazy_attribute import lazy_attribute +from sage.combinat.posets.posets import FinitePoset from sage.combinat.posets.linear_extensions import LinearExtensionsOfForest class ForestPoset(FinitePoset): diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index aada410cf31..7160f629f6c 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -2324,7 +2324,7 @@ def diamonds(self): for i, x in enumerate(covers): for y in covers[i+1:]: zs = self.common_upper_covers([x, y]) - if len(zs) != 1 : + if len(zs) != 1: all_diamonds_completed = False for z in zs: diamonds.append((w, x, y, z)) diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index 674f2b39a76..60dbf6ff4a4 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -858,7 +858,6 @@ def cardinality(self): EXAMPLES:: - sage: from sage.combinat.posets.d_complete import DComplete sage: from sage.combinat.posets.poset_examples import Posets sage: P = Posets.YoungDiagramPoset(Partition([3,2]), dual=True) sage: P.linear_extensions().cardinality() From 40f589f9033607bae86eec49b1eeb2d020003880 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 20 Jul 2020 17:55:12 -0700 Subject: [PATCH 159/217] Use basis._symbol as prefix instead of B --- src/sage/tensor/modules/finite_rank_free_module.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sage/tensor/modules/finite_rank_free_module.py b/src/sage/tensor/modules/finite_rank_free_module.py index c5bcdf442f9..fc631087e52 100644 --- a/src/sage/tensor/modules/finite_rank_free_module.py +++ b/src/sage/tensor/modules/finite_rank_free_module.py @@ -2553,7 +2553,7 @@ def isomorphism_with_fixed_basis(self, basis, codomain=None): Category of finite dimensional vector spaces with basis over Rational Field sage: phi_e(e[1] + 2 * e[2]) - B[1] + 2*B[2] + e[1] + 2*e[2] Providing a codomain:: @@ -2584,7 +2584,8 @@ def isomorphism_with_fixed_basis(self, basis, codomain=None): if codomain is None: from sage.combinat.free_module import CombinatorialFreeModule - codomain = CombinatorialFreeModule(base_ring, list(self.irange())) + codomain = CombinatorialFreeModule(base_ring, list(self.irange()), + prefix=basis._symbol) else: if codomain.rank() != self.rank(): raise ValueError("domain and codomain must have the same rank") From 2cbfdf2f5f6f702fabce05193b884a5bf115d2d6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 11 Jul 2020 15:24:34 -0700 Subject: [PATCH 160/217] build/pkgs/pillow: Update to 7.2.0 --- build/pkgs/pillow/checksums.ini | 7 ++++--- build/pkgs/pillow/package-version.txt | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/build/pkgs/pillow/checksums.ini b/build/pkgs/pillow/checksums.ini index 83633e72667..cddbf885333 100644 --- a/build/pkgs/pillow/checksums.ini +++ b/build/pkgs/pillow/checksums.ini @@ -1,4 +1,5 @@ tarball=Pillow-VERSION.tar.gz -sha1=b1d2d766b82efe28958025e4b3ee109e591cb483 -md5=0da5a4c9c548aa5cfe999302aea8c8f1 -cksum=379384082 +sha1=aa3ea4f9df720f210f9f7c4dde75b247bf76ef61 +md5=3da1c992ce9fcc67597d83036f591712 +cksum=88669447 +upstream_url=https://pypi.io/packages/source/p/pillow/Pillow-VERSION.tar.gz diff --git a/build/pkgs/pillow/package-version.txt b/build/pkgs/pillow/package-version.txt index 19369614319..0ee843cc604 100644 --- a/build/pkgs/pillow/package-version.txt +++ b/build/pkgs/pillow/package-version.txt @@ -1 +1 @@ -5.3.0.p0 +7.2.0 From affd0c974f144ca19f2095f3546130f04b188823 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 21 Jul 2020 07:47:51 -0700 Subject: [PATCH 161/217] Use basis._symbol as prefix only when it is a string --- .../tensor/modules/finite_rank_free_module.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/sage/tensor/modules/finite_rank_free_module.py b/src/sage/tensor/modules/finite_rank_free_module.py index fc631087e52..a4cb6514bd2 100644 --- a/src/sage/tensor/modules/finite_rank_free_module.py +++ b/src/sage/tensor/modules/finite_rank_free_module.py @@ -2555,6 +2555,15 @@ def isomorphism_with_fixed_basis(self, basis, codomain=None): sage: phi_e(e[1] + 2 * e[2]) e[1] + 2*e[2] + sage: abc = V.basis(['a', 'b', 'c'], symbol_dual=['d', 'e', 'f']); abc + Basis (a,b,c) on the 3-dimensional vector space over the Rational Field + sage: phi_abc = V.isomorphism_with_fixed_basis(abc); phi_abc + Generic morphism: + From: 3-dimensional vector space over the Rational Field + To: Free module generated by {1, 2, 3} over Rational Field + sage: phi_abc(abc[1] + 2 * abc[2]) + B[1] + 2*B[2] + Providing a codomain:: sage: W = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) @@ -2578,14 +2587,16 @@ def isomorphism_with_fixed_basis(self, basis, codomain=None): Traceback (most recent call last): ... ValueError: domain and codomain must have the same base ring - """ base_ring = self.base_ring() if codomain is None: from sage.combinat.free_module import CombinatorialFreeModule - + if isinstance(basis._symbol, str): + prefix = basis._symbol + else: + prefix = None codomain = CombinatorialFreeModule(base_ring, list(self.irange()), - prefix=basis._symbol) + prefix=prefix) else: if codomain.rank() != self.rank(): raise ValueError("domain and codomain must have the same rank") From f34d2a5b563f8b5f0582d3f880065c5515dfcd00 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 21 Jul 2020 07:55:45 -0700 Subject: [PATCH 162/217] Move parent method linear_combination from ModulesWithBasis to Modules --- src/sage/categories/modules.py | 32 +++++++++++++++++++++++ src/sage/categories/modules_with_basis.py | 31 ---------------------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/sage/categories/modules.py b/src/sage/categories/modules.py index 9940314265d..1f111aa26e1 100644 --- a/src/sage/categories/modules.py +++ b/src/sage/categories/modules.py @@ -521,6 +521,38 @@ def extra_super_categories(self): at_startup=True) class ParentMethods: + + def linear_combination(self, iter_of_elements_coeff, factor_on_left=True): + r""" + Return the linear combination `\lambda_1 v_1 + \cdots + + \lambda_k v_k` (resp. the linear combination `v_1 \lambda_1 + + \cdots + v_k \lambda_k`) where ``iter_of_elements_coeff`` iterates + through the sequence `((\lambda_1, v_1), ..., (\lambda_k, v_k))`. + + INPUT: + + - ``iter_of_elements_coeff`` -- iterator of pairs + ``(element, coeff)`` with ``element`` in ``self`` and + ``coeff`` in ``self.base_ring()`` + + - ``factor_on_left`` -- (optional) if ``True``, the coefficients + are multiplied from the left; if ``False``, the coefficients + are multiplied from the right + + EXAMPLES:: + + sage: m = matrix([[0,1],[1,1]]) + sage: J. = JordanAlgebra(m) + sage: J.linear_combination(((a+b, 1), (-2*b + c, -1))) + 1 + (3, -1) + """ + if factor_on_left: + return self.sum(coeff * element + for element, coeff in iter_of_elements_coeff) + else: + return self.sum(element * coeff + for element, coeff in iter_of_elements_coeff) + @cached_method def tensor_square(self): """ diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index f77b2d0cbf3..d31f0aaeef2 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -1113,37 +1113,6 @@ def sum_of_terms(self, terms): """ return self.sum(self.term(index, coeff) for (index, coeff) in terms) - def linear_combination(self, iter_of_elements_coeff, factor_on_left=True): - r""" - Return the linear combination `\lambda_1 v_1 + \cdots + - \lambda_k v_k` (resp. the linear combination `v_1 \lambda_1 + - \cdots + v_k \lambda_k`) where ``iter_of_elements_coeff`` iterates - through the sequence `((\lambda_1, v_1), ..., (\lambda_k, v_k))`. - - INPUT: - - - ``iter_of_elements_coeff`` -- iterator of pairs - ``(element, coeff)`` with ``element`` in ``self`` and - ``coeff`` in ``self.base_ring()`` - - - ``factor_on_left`` -- (optional) if ``True``, the coefficients - are multiplied from the left; if ``False``, the coefficients - are multiplied from the right - - EXAMPLES:: - - sage: m = matrix([[0,1],[1,1]]) - sage: J. = JordanAlgebra(m) - sage: J.linear_combination(((a+b, 1), (-2*b + c, -1))) - 1 + (3, -1) - """ - if factor_on_left: - return self.sum(coeff * element - for element, coeff in iter_of_elements_coeff) - else: - return self.sum(element * coeff - for element, coeff in iter_of_elements_coeff) - def _apply_module_morphism(self, x, on_basis, codomain=False): """ Return the image of ``x`` under the module morphism defined by From 0afa01cfcb1ad3ded5cde7ba2df3dc3231c6a3f8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 21 Jul 2020 10:30:40 -0700 Subject: [PATCH 163/217] Modules: Add parent method module_morphism --- src/sage/categories/modules.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/sage/categories/modules.py b/src/sage/categories/modules.py index 9940314265d..11e8b11813e 100644 --- a/src/sage/categories/modules.py +++ b/src/sage/categories/modules.py @@ -15,7 +15,9 @@ from sage.misc.cachefunc import cached_method from sage.misc.lazy_import import LazyImport from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring +from sage.categories.morphism import SetMorphism from sage.categories.homsets import HomsetsCategory +from sage.categories.homset import Hom from .category import Category from .category_types import Category_module from sage.categories.tensor import TensorProductsCategory, tensor @@ -538,6 +540,37 @@ def tensor_square(self): """ return tensor([self, self]) + def module_morphism(self, *, function, category=None, codomain, **keywords): + r""" + Construct a module morphism from ``self`` to ``codomain``. + + Let ``self`` be a module `X` over a ring `R`. + This constructs a morphism `f: X \to Y`. + + INPUT: + + - ``self`` -- a parent `X` in ``Modules(R)``. + + - ``function`` -- a function `f` from `X` to `Y` + + - ``codomain`` -- the codomain `Y` of the morphism (default: + ``f.codomain()`` if it's defined; otherwise it must be specified) + + - ``category`` -- a category or ``None`` (default: ``None``) + + EXAMPLES:: + + sage: V = FiniteRankFreeModule(QQ, 2) + sage: e = V.basis('e'); e + Basis (e_0,e_1) on the 2-dimensional vector space over the Rational Field + sage: neg = V.module_morphism(function=operator.neg, codomain=V); neg + Generic endomorphism of 2-dimensional vector space over the Rational Field + sage: neg(e[0]) + Element -e_0 of the 2-dimensional vector space over the Rational Field + + """ + return SetMorphism(Hom(self, codomain, category), function) + class ElementMethods: pass From 3c8d08013740e2f406008f189792b53f3a2efa0f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 21 Jul 2020 10:31:16 -0700 Subject: [PATCH 164/217] Fix docstring markup --- src/sage/categories/modules_with_basis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index f77b2d0cbf3..5775c51b613 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -255,7 +255,7 @@ def module_morphism(self, on_basis=None, matrix=None, function=None, - ``codomain`` -- the codomain `Y` of the morphism (default: ``f.codomain()`` if it's defined; otherwise it must be specified) - - ``category`` -- a category or ``None`` (default: `None``) + - ``category`` -- a category or ``None`` (default: ``None``) - ``zero`` -- the zero of the codomain (default: ``codomain.zero()``); can be used (with care) to define affine maps. From 1bbc8306a46da97fdcf9ed82bdcf6bc1cf0dec74 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Tue, 21 Jul 2020 20:29:28 +0200 Subject: [PATCH 165/217] Trac #30191: AttributeError catched and TypeError raised instead --- .../differentiable/diff_form_module.py | 12 ++++++--- .../differentiable/multivector_module.py | 14 ++++++---- .../differentiable/tensorfield_module.py | 27 ++++++++++++------- .../differentiable/vectorfield_module.py | 12 ++++++--- src/sage/manifolds/section_module.py | 12 ++++++--- 5 files changed, 51 insertions(+), 26 deletions(-) diff --git a/src/sage/manifolds/differentiable/diff_form_module.py b/src/sage/manifolds/differentiable/diff_form_module.py index 07d216a936c..6b904378171 100644 --- a/src/sage/manifolds/differentiable/diff_form_module.py +++ b/src/sage/manifolds/differentiable/diff_form_module.py @@ -334,7 +334,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - if isinstance(comp, (DiffForm, DiffFormParal)): + elif isinstance(comp, (DiffForm, DiffFormParal)): # coercion by domain restriction if (self._degree == comp._tensor_type[1] and self._domain.is_subset(comp._domain) @@ -343,7 +343,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) - if isinstance(comp, TensorField): + elif isinstance(comp, TensorField): # coercion of a tensor of type (0,1) to a linear form tensor = comp # for readability if (tensor.tensor_type() == (0,1) and self._degree == 1 @@ -356,7 +356,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(tensor) + "to an element of {}".format(self)) - if isinstance(comp, ScalarField): + elif isinstance(comp, ScalarField): # since the degree of self is >= 1, we cannot coerce scalar fields: raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) @@ -364,7 +364,11 @@ def _element_constructor_(self, comp=[], frame=None, name=None, resu = self.element_class(self._vmodule, self._degree, name=name, latex_name=latex_name) if comp != []: - resu.set_comp(frame)[:] = comp + try: + resu.set_comp(frame)[:] = comp + except AttributeError: + raise TypeError("cannot convert the {} ".format(comp) + + "to an element of {}".format(self)) return resu def _an_element_(self): diff --git a/src/sage/manifolds/differentiable/multivector_module.py b/src/sage/manifolds/differentiable/multivector_module.py index d6b7c6a9c3b..34434db90c3 100644 --- a/src/sage/manifolds/differentiable/multivector_module.py +++ b/src/sage/manifolds/differentiable/multivector_module.py @@ -36,7 +36,7 @@ from sage.misc.cachefunc import cached_method from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent -from sage.rings.integer import Integer +from sage.symbolic.ring import ZZ from sage.categories.modules import Modules from sage.tensor.modules.ext_pow_free_module import ExtPowerFreeModule from sage.manifolds.differentiable.multivectorfield import ( @@ -301,9 +301,9 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if isinstance(comp, (int, Integer)) and comp == 0: + if comp in ZZ and comp == 0: return self.zero() - if isinstance(comp, (MultivectorField, MultivectorFieldParal)): + elif isinstance(comp, (MultivectorField, MultivectorFieldParal)): # coercion by domain restriction if (self._degree == comp._tensor_type[0] and self._domain.is_subset(comp._domain) @@ -316,8 +316,12 @@ def _element_constructor_(self, comp=[], frame=None, name=None, # standard construction resu = self.element_class(self._vmodule, self._degree, name=name, latex_name=latex_name) - if comp: - resu.set_comp(frame)[:] = comp + if comp != []: + try: + resu.set_comp(frame)[:] = comp + except AttributeError: + raise TypeError("cannot convert the {} ".format(comp) + + "to an element of {}".format(self)) return resu def _an_element_(self): diff --git a/src/sage/manifolds/differentiable/tensorfield_module.py b/src/sage/manifolds/differentiable/tensorfield_module.py index 91a3dc5e59e..3a908c0aec6 100644 --- a/src/sage/manifolds/differentiable/tensorfield_module.py +++ b/src/sage/manifolds/differentiable/tensorfield_module.py @@ -41,7 +41,7 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent from sage.categories.modules import Modules -from sage.rings.integer import Integer +from sage.symbolic.ring import ZZ from sage.tensor.modules.tensor_free_module import TensorFreeModule from sage.manifolds.differentiable.tensorfield import TensorField from sage.manifolds.differentiable.tensorfield_paral import TensorFieldParal @@ -310,7 +310,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if isinstance(comp, (int, Integer)) and comp == 0: + if comp in ZZ and comp == 0: return self.zero() if isinstance(comp, DiffForm): # coercion of a p-form to a type-(0,p) tensor field: @@ -378,7 +378,11 @@ def _element_constructor_(self, comp=[], frame=None, name=None, name=name, latex_name=latex_name, sym=sym, antisym=antisym) if comp != []: - resu.set_comp(frame)[:] = comp + try: + resu.set_comp(frame)[:] = comp + except AttributeError: + raise TypeError("cannot convert the {} ".format(comp) + + "to an element of {}".format(self)) return resu def _an_element_(self): @@ -793,9 +797,9 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if isinstance(comp, (int, Integer)) and comp == 0: + if comp in ZZ and comp == 0: return self.zero() - if isinstance(comp, DiffFormParal): + elif isinstance(comp, DiffFormParal): # coercion of a p-form to a type-(0,p) tensor field: form = comp # for readability p = form.degree() @@ -814,7 +818,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, for frame, cp in form._components.items(): resu._components[frame] = cp.copy() return resu - if isinstance(comp, MultivectorFieldParal): + elif isinstance(comp, MultivectorFieldParal): # coercion of a p-vector field to a type-(p,0) tensor field: pvect = comp # for readability p = pvect.degree() @@ -833,7 +837,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, for frame, cp in pvect._components.items(): resu._components[frame] = cp.copy() return resu - if isinstance(comp, AutomorphismFieldParal): + elif isinstance(comp, AutomorphismFieldParal): # coercion of an automorphism to a type-(1,1) tensor: autom = comp # for readability if (self._tensor_type != (1,1) or @@ -846,7 +850,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, for basis, comp in autom._components.items(): resu._components[basis] = comp.copy() return resu - if isinstance(comp, TensorField): + elif isinstance(comp, TensorField): # coercion by domain restriction if (self._tensor_type == comp._tensor_type and self._domain.is_subset(comp._domain) @@ -861,7 +865,12 @@ def _element_constructor_(self, comp=[], frame=None, name=None, name=name, latex_name=latex_name, sym=sym, antisym=antisym) if comp != []: - resu.set_comp(frame)[:] = comp + try: + resu.set_comp(frame)[:] = comp + except AttributeError: + raise NotImplementedError("cannot convert " + "the {} ".format(comp) + + "to an element of {}".format(self)) return resu # Rem: _an_element_ is declared in the superclass TensorFreeModule diff --git a/src/sage/manifolds/differentiable/vectorfield_module.py b/src/sage/manifolds/differentiable/vectorfield_module.py index a507ab01419..483d8e579b5 100644 --- a/src/sage/manifolds/differentiable/vectorfield_module.py +++ b/src/sage/manifolds/differentiable/vectorfield_module.py @@ -42,7 +42,7 @@ from sage.structure.parent import Parent from sage.categories.modules import Modules from sage.misc.cachefunc import cached_method -from sage.rings.integer import Integer +from sage.symbolic.ring import ZZ from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule from sage.manifolds.differentiable.vectorfield import (VectorField, VectorFieldParal) @@ -268,9 +268,9 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if isinstance(comp, (int, Integer)) and comp == 0: + if comp in ZZ and comp == 0: return self.zero() - if isinstance(comp, VectorField): + elif isinstance(comp, VectorField): if (self._domain.is_subset(comp._domain) and self._ambient_domain.is_subset(comp._ambient_domain)): return comp.restrict(self._domain) @@ -279,7 +279,11 @@ def _element_constructor_(self, comp=[], frame=None, name=None, "to a vector field in {}".format(self)) resu = self.element_class(self, name=name, latex_name=latex_name) if comp != []: - resu.set_comp(frame)[:] = comp + try: + resu.set_comp(frame)[:] = comp + except AttributeError: + raise TypeError("cannot convert the {} ".format(comp) + + "to an element of {}".format(self)) return resu def _an_element_(self): diff --git a/src/sage/manifolds/section_module.py b/src/sage/manifolds/section_module.py index 66cdbffce12..dfd18b9d688 100644 --- a/src/sage/manifolds/section_module.py +++ b/src/sage/manifolds/section_module.py @@ -32,7 +32,7 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent from sage.misc.cachefunc import cached_method -from sage.rings.integer import Integer +from sage.symbolic.ring import ZZ from sage.categories.modules import Modules from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule from sage.manifolds.section import Section, TrivialSection @@ -222,9 +222,9 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if isinstance(comp, (int, Integer)) and comp == 0: + if comp in ZZ and comp == 0: return self.zero() - if isinstance(comp, Section): + elif isinstance(comp, Section): if self._domain.is_subset(comp._domain): return comp.restrict(self._domain) else: @@ -232,7 +232,11 @@ def _element_constructor_(self, comp=[], frame=None, name=None, "to a local section in {}".format(self)) resu = self.element_class(self, name=name, latex_name=latex_name) if comp != []: - resu.set_comp(frame)[:] = comp + try: + resu.set_comp(frame)[:] = comp + except AttributeError: + raise TypeError("cannot convert the {} ".format(comp) + + "to an element of {}".format(self)) return resu def _an_element_(self): From e2fc5d54c00a65e852cd8cbd9598417f686b3436 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 21 Jul 2020 11:34:00 -0700 Subject: [PATCH 166/217] Make sure that we only create a module morphism --- src/sage/categories/modules.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sage/categories/modules.py b/src/sage/categories/modules.py index 11e8b11813e..1979dd29eea 100644 --- a/src/sage/categories/modules.py +++ b/src/sage/categories/modules.py @@ -569,6 +569,10 @@ def module_morphism(self, *, function, category=None, codomain, **keywords): Element -e_0 of the 2-dimensional vector space over the Rational Field """ + # Make sure that we only create a module morphism, even if + # domain and codomain have more structure + if category is None: + category = Modules(self.base_ring()) return SetMorphism(Hom(self, codomain, category), function) class ElementMethods: From 66c2ca857cf22bcccab528d5808810924774a214 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Tue, 21 Jul 2020 21:27:55 +0200 Subject: [PATCH 167/217] Trac #30191: integer check via ZZ + not convertible error if no list --- .../differentiable/diff_form_module.py | 17 ++++------ .../differentiable/multivector_module.py | 14 ++++---- .../differentiable/tensorfield_module.py | 28 +++++++--------- .../differentiable/vectorfield_module.py | 32 +++++++++++-------- src/sage/manifolds/section_module.py | 16 ++++++---- 5 files changed, 54 insertions(+), 53 deletions(-) diff --git a/src/sage/manifolds/differentiable/diff_form_module.py b/src/sage/manifolds/differentiable/diff_form_module.py index 6b904378171..343719bbd64 100644 --- a/src/sage/manifolds/differentiable/diff_form_module.py +++ b/src/sage/manifolds/differentiable/diff_form_module.py @@ -356,19 +356,14 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(tensor) + "to an element of {}".format(self)) - elif isinstance(comp, ScalarField): - # since the degree of self is >= 1, we cannot coerce scalar fields: + elif not isinstance(comp, (list, tuple, slice)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction resu = self.element_class(self._vmodule, self._degree, name=name, latex_name=latex_name) if comp != []: - try: - resu.set_comp(frame)[:] = comp - except AttributeError: - raise TypeError("cannot convert the {} ".format(comp) + - "to an element of {}".format(self)) + resu.set_comp(frame)[:] = comp return resu def _an_element_(self): @@ -808,7 +803,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - if isinstance(comp, (DiffForm, DiffFormParal)): + elif isinstance(comp, (DiffForm, DiffFormParal)): # coercion by domain restriction if (self._degree == comp._tensor_type[1] and self._domain.is_subset(comp._domain) @@ -817,7 +812,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(comp) + "to a differential form in {}".format(self)) - if isinstance(comp, TensorFieldParal): + elif isinstance(comp, TensorFieldParal): # coercion of a tensor of type (0,1) to a linear form tensor = comp # for readability if (tensor.tensor_type() == (0,1) and self._degree == 1 @@ -830,10 +825,10 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(tensor) + "to an element of {}".format(self)) - if isinstance(comp, ScalarField): - # since the degree of self is >= 1, we cannot coerce scalar fields: + elif not isinstance(comp, (list, tuple, slice)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) + # standard construction resu = self.element_class(self._fmodule, self._degree, name=name, latex_name=latex_name) if comp != []: diff --git a/src/sage/manifolds/differentiable/multivector_module.py b/src/sage/manifolds/differentiable/multivector_module.py index 34434db90c3..06c99bedcad 100644 --- a/src/sage/manifolds/differentiable/multivector_module.py +++ b/src/sage/manifolds/differentiable/multivector_module.py @@ -313,15 +313,14 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) + elif not isinstance(comp, (list, tuple, slice)): + raise TypeError("cannot convert the {} ".format(comp) + + "to an element of {}".format(self)) # standard construction resu = self.element_class(self._vmodule, self._degree, name=name, latex_name=latex_name) if comp != []: - try: - resu.set_comp(frame)[:] = comp - except AttributeError: - raise TypeError("cannot convert the {} ".format(comp) + - "to an element of {}".format(self)) + resu.set_comp(frame)[:] = comp return resu def _an_element_(self): @@ -726,7 +725,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if isinstance(comp, (int, Integer)) and comp == 0: + if comp in ZZ and comp == 0: return self.zero() if isinstance(comp, (MultivectorField, MultivectorFieldParal)): # coercion by domain restriction @@ -738,6 +737,9 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(comp) + "to a multivector field in {}".format(self)) + elif not isinstance(comp, (list, tuple, slice)): + raise TypeError("cannot convert the {} ".format(comp) + + "to an element of {}".format(self)) # standard construction resu = self.element_class(self._fmodule, self._degree, name=name, latex_name=latex_name) diff --git a/src/sage/manifolds/differentiable/tensorfield_module.py b/src/sage/manifolds/differentiable/tensorfield_module.py index 3a908c0aec6..b7d19b4c763 100644 --- a/src/sage/manifolds/differentiable/tensorfield_module.py +++ b/src/sage/manifolds/differentiable/tensorfield_module.py @@ -312,7 +312,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - if isinstance(comp, DiffForm): + elif isinstance(comp, DiffForm): # coercion of a p-form to a type-(0,p) tensor field: form = comp # for readability p = form.degree() @@ -331,7 +331,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, for dom, rst in form._restrictions.items(): resu._restrictions[dom] = dom.tensor_field_module((0,p))(rst) return resu - if isinstance(comp, MultivectorField): + elif isinstance(comp, MultivectorField): # coercion of a p-vector field to a type-(p,0) tensor: pvect = comp # for readability p = pvect.degree() @@ -350,7 +350,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, for dom, rst in pvect._restrictions.items(): resu._restrictions[dom] = dom.tensor_field_module((p,0))(rst) return resu - if isinstance(comp, AutomorphismField): + elif isinstance(comp, AutomorphismField): # coercion of an automorphism to a type-(1,1) tensor: autom = comp # for readability if (self._tensor_type != (1,1) or @@ -363,7 +363,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, for dom, rest in autom._restrictions.items(): resu._restrictions[dom] = dom.tensor_field_module((1,1))(rest) return resu - if isinstance(comp, TensorField): + elif isinstance(comp, TensorField): # coercion by domain restriction if (self._tensor_type == comp._tensor_type and self._domain.is_subset(comp._domain) @@ -372,17 +372,15 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {}".format(comp) + " to an element of {}".format(self)) - + elif not isinstance(comp, (list, tuple, slice)): + raise TypeError("cannot convert the {} ".format(comp) + + "to an element of {}".format(self)) # standard construction resu = self.element_class(self._vmodule, self._tensor_type, name=name, latex_name=latex_name, sym=sym, antisym=antisym) if comp != []: - try: - resu.set_comp(frame)[:] = comp - except AttributeError: - raise TypeError("cannot convert the {} ".format(comp) + - "to an element of {}".format(self)) + resu.set_comp(frame)[:] = comp return resu def _an_element_(self): @@ -860,17 +858,15 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {}".format(comp) + " to an element of {}".format(self)) + elif not isinstance(comp, (list, tuple, slice)): + raise TypeError("cannot convert the {} ".format(comp) + + "to an element of {}".format(self)) # Standard construction resu = self.element_class(self._fmodule, self._tensor_type, name=name, latex_name=latex_name, sym=sym, antisym=antisym) if comp != []: - try: - resu.set_comp(frame)[:] = comp - except AttributeError: - raise NotImplementedError("cannot convert " - "the {} ".format(comp) + - "to an element of {}".format(self)) + resu.set_comp(frame)[:] = comp return resu # Rem: _an_element_ is declared in the superclass TensorFreeModule diff --git a/src/sage/manifolds/differentiable/vectorfield_module.py b/src/sage/manifolds/differentiable/vectorfield_module.py index 483d8e579b5..039030c5721 100644 --- a/src/sage/manifolds/differentiable/vectorfield_module.py +++ b/src/sage/manifolds/differentiable/vectorfield_module.py @@ -277,13 +277,13 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise ValueError("cannot convert the {} ".format(comp) + "to a vector field in {}".format(self)) + elif not isinstance(comp, (list, tuple, slice)): + raise TypeError("cannot convert the {} ".format(comp) + + "to an element of {}".format(self)) + # standard construction resu = self.element_class(self, name=name, latex_name=latex_name) if comp != []: - try: - resu.set_comp(frame)[:] = comp - except AttributeError: - raise TypeError("cannot convert the {} ".format(comp) + - "to an element of {}".format(self)) + resu.set_comp(frame)[:] = comp return resu def _an_element_(self): @@ -773,7 +773,7 @@ def tensor(self, tensor_type, name=None, latex_name=None, sym=None, return self.automorphism(name=name, latex_name=latex_name) elif tensor_type[0] == 0 and tensor_type[1] > 1 and antisym: - if isinstance(antisym[0], (int, Integer)): + if antisym[0] in ZZ: # a single antisymmetry is provided as a tuple or a # range object; it is converted to a 1-item list: antisym = [tuple(antisym)] @@ -785,7 +785,7 @@ def tensor(self, tensor_type, name=None, latex_name=None, sym=None, return self.alternating_form(tensor_type[1], name=name, latex_name=latex_name) elif tensor_type[0] > 1 and tensor_type[1] == 0 and antisym: - if isinstance(antisym[0], (int, Integer)): + if antisym[0] in ZZ: # a single antisymmetry is provided as a tuple or a # range object; it is converted to a 1-item list: antisym = [tuple(antisym)] @@ -1090,7 +1090,7 @@ def metric(self, name, signature=None, latex_name=None): ndim = self._ambient_domain.dimension() try: for elt in signature: - if (elt<0) or (not isinstance(elt, (int, Integer))): + if (elt<0) or elt not in ZZ: raise ValueError("{} must be a positive integer".format(elt)) if elt > ndim: raise ValueError("{} must be less than {}".format(elt,ndim)) @@ -1106,7 +1106,7 @@ def metric(self, name, signature=None, latex_name=None): pass if signature is None: signature = (ndim,0) - if isinstance(signature, (Integer, int)): + if signature in ZZ: if (signature+ndim)%2 == 1: if ndim%2 == 0: raise ValueError("the metric signature must be even") @@ -1471,7 +1471,7 @@ def _element_constructor_(self, comp=[], basis=None, name=None, True """ - if isinstance(comp, (int, Integer)) and comp == 0: + if comp in ZZ and comp == 0: return self.zero() if isinstance(comp, VectorField): if (self._domain.is_subset(comp._domain) @@ -1480,6 +1480,10 @@ def _element_constructor_(self, comp=[], basis=None, name=None, else: raise ValueError("cannot convert the {}".format(comp) + "to a vector field in {}".format(self)) + elif not isinstance(comp, (list, tuple, slice)): + raise TypeError("cannot convert the {} ".format(comp) + + "to an element of {}".format(self)) + # standard construction resu = self.element_class(self, name=name, latex_name=latex_name) if comp != []: resu.set_comp(basis=basis)[:] = comp @@ -2008,7 +2012,7 @@ def tensor(self, tensor_type, name=None, latex_name=None, sym=None, (AutomorphismField, AutomorphismFieldParal)): return self.automorphism(name=name, latex_name=latex_name) elif tensor_type[0] == 0 and tensor_type[1] > 1 and antisym: - if isinstance(antisym[0], (int, Integer)): + if antisym[0] in ZZ: # a single antisymmetry is provided as a tuple or a # range object; it is converted to a 1-item list: antisym = [tuple(antisym)] @@ -2020,7 +2024,7 @@ def tensor(self, tensor_type, name=None, latex_name=None, sym=None, return self.alternating_form(tensor_type[1], name=name, latex_name=latex_name) elif tensor_type[0] > 1 and tensor_type[1] == 0 and antisym: - if isinstance(antisym[0], (int, Integer)): + if antisym[0] in ZZ: # a single antisymmetry is provided as a tuple or a # range object; it is converted to a 1-item list: antisym = [tuple(antisym)] @@ -2227,7 +2231,7 @@ def metric(self, name, signature=None, latex_name=None): ndim = self._ambient_domain.dimension() try: for elt in signature: - if (elt<0) or (not isinstance(elt, (int, Integer))): + if (elt<0) or elt not in ZZ: raise ValueError("{} must be a positive integer".format(elt)) sign = signature[0]+signature[1]+signature[2] if sign!=ndim: @@ -2241,7 +2245,7 @@ def metric(self, name, signature=None, latex_name=None): pass if signature is None: signature = (ndim,0) - if isinstance(signature, (Integer, int)): + if signature in ZZ: if (signature+ndim)%2 == 1: if ndim%2 == 0: raise ValueError("the metric signature must be even") diff --git a/src/sage/manifolds/section_module.py b/src/sage/manifolds/section_module.py index dfd18b9d688..995860b179f 100644 --- a/src/sage/manifolds/section_module.py +++ b/src/sage/manifolds/section_module.py @@ -230,13 +230,13 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise ValueError("cannot convert the {} ".format(comp) + "to a local section in {}".format(self)) + elif not isinstance(comp, (list, tuple, slice)): + raise TypeError("cannot convert the {} ".format(comp) + + "to an element of {}".format(self)) + # standard construction resu = self.element_class(self, name=name, latex_name=latex_name) if comp != []: - try: - resu.set_comp(frame)[:] = comp - except AttributeError: - raise TypeError("cannot convert the {} ".format(comp) + - "to an element of {}".format(self)) + resu.set_comp(frame)[:] = comp return resu def _an_element_(self): @@ -641,7 +641,7 @@ def _element_constructor_(self, comp=[], basis=None, name=None, True """ - if isinstance(comp, (int, Integer)) and comp == 0: + if comp in ZZ and comp == 0: return self.zero() if isinstance(comp, Section): if self._domain.is_subset(comp._domain): @@ -649,6 +649,10 @@ def _element_constructor_(self, comp=[], basis=None, name=None, else: raise ValueError("cannot convert the {}".format(comp) + "to a local section in {}".format(self)) + elif not isinstance(comp, (list, tuple, slice)): + raise TypeError("cannot convert the {} ".format(comp) + + "to an element of {}".format(self)) + # standard construction resu = self.element_class(self, name=name, latex_name=latex_name) if comp != []: resu.set_comp(basis)[:] = comp From d577e16f3ec58365235d20fa387ed23785a0d693 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Tue, 21 Jul 2020 21:42:33 +0200 Subject: [PATCH 168/217] Trac #30191: conversion error for automorphism group --- src/sage/manifolds/differentiable/automorphismfield_group.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sage/manifolds/differentiable/automorphismfield_group.py b/src/sage/manifolds/differentiable/automorphismfield_group.py index 4cc248e67dd..a3acb07d2e7 100644 --- a/src/sage/manifolds/differentiable/automorphismfield_group.py +++ b/src/sage/manifolds/differentiable/automorphismfield_group.py @@ -210,6 +210,9 @@ def _element_constructor_(self, comp=[], frame=None, name=None, """ if comp == 1: return self.one() + if not isinstance(comp, (list, tuple, slice)): + raise TypeError("cannot convert the {} ".format(comp) + + "to an element of {}".format(self)) # standard construction resu = self.element_class(self._vmodule, name=name, latex_name=latex_name) From 585bdac80224f6f6daace3d7d8ab663bf309f752 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 21 Jul 2020 21:07:32 -0700 Subject: [PATCH 169/217] tox.ini: Add centos-6, docker-nobootstrap, manylinux-* --- build/bin/write-dockerfile.sh | 3 ++- tox.ini | 29 ++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/build/bin/write-dockerfile.sh b/build/bin/write-dockerfile.sh index cfaee46b2bc..966ddd9f182 100755 --- a/build/bin/write-dockerfile.sh +++ b/build/bin/write-dockerfile.sh @@ -162,7 +162,8 @@ ADD src/doc/bootstrap src/doc/bootstrap ADD src/bin src/bin ADD m4 ./m4 ADD build ./build -$RUN ./bootstrap +ARG BOOTSTRAP=./bootstrap +$RUN \${BOOTSTRAP} FROM bootstrapped as configured #:configuring: diff --git a/tox.ini b/tox.ini index 8a4e0c54a31..9609df0ecb4 100644 --- a/tox.ini +++ b/tox.ini @@ -190,11 +190,13 @@ setenv = fedora-32: BASE_TAG=32 # # https://hub.docker.com/_/centos + # centos-6 only has autoconf 2.63 -- too old for bootstrap # centos: SYSTEM=fedora centos: BASE_IMAGE=centos centos: IGNORE_MISSING_SYSTEM_PACKAGES=yes - #centos-6: BASE_TAG=centos6 # only has autoconf 2.63 -- too old for bootstrap + centos-6: BASE_TAG=centos6 + centos-6: BOOTSTRAP=./bootstrap -D centos-7: BASE_TAG=centos7 centos-8: BASE_TAG=centos8 # @@ -262,9 +264,27 @@ setenv = linuxmint: ARCH_IMAGE_SUFFIX=-amd64 linuxmint-i386: ARCH_IMAGE_SUFFIX=-i386 # + # manylinux + # https://github.com/pypa/manylinux + # + manylinux: SYSTEM=fedora + manylinux: IGNORE_MISSING_SYSTEM_PACKAGES=yes + manylinux: BOOTSTRAP=./bootstrap -D + manylinux-1: BASE_IMAGE=quay.io/pypa/manylinux1 + manylinux-2010: BASE_IMAGE=quay.io/pypa/manylinux2010 + manylinux-2014: BASE_IMAGE=quay.io/pypa/manylinux2014 + manylinux: ARCH_IMAGE_PREFIX= + manylinux: ARCH_IMAGE_SUFFIX=_x86_64 + manylinux-i686: ARCH_IMAGE_SUFFIX=_i686 + manylinux-2014-aarch64: ARCH_IMAGE_SUFFIX=_aarch64 + manylinux-2014-ppc64le: ARCH_IMAGE_SUFFIX=_ppc64le + manylinux-2014-s390x: ARCH_IMAGE_SUFFIX=_s390x + # # Resulting full image:tag name # docker: FULL_BASE_IMAGE_AND_TAG={env:ARCH_IMAGE_PREFIX:}{env:BASE_IMAGE}{env:ARCH_IMAGE_SUFFIX:}:{env:ARCH_TAG_PREFIX:}{env:BASE_TAG}{env:ARCH_TAG_SUFFIX:} + # + docker-nobootstrap: BOOTSTRAP=./bootstrap -D ### ### "local" envs ### @@ -298,6 +318,12 @@ setenv = macos-python3_xcode: CONFIG_CONFIGURE_ARGS_1=--with-python=3 PYTHON3=/usr/bin/python3 # Must manually download and install from https://www.python.org/ftp/python/3.7.7/python-3.7.7-macosx10.9.pkg macos-python3_pythonorg: CONFIG_CONFIGURE_ARGS_1=--with-python=3 PYTHON3=/Library/Frameworks/Python.framework/Versions/3.7/bin/python3 + # https://github.com/pypa/manylinux + manylinux: CONFIG_CONFIGURE_ARGS_1= PYTHON3=/opt/python/cp38-cp38/bin/python3 + manylinux-python3.6: CONFIG_CONFIGURE_ARGS_1= PYTHON3=/opt/python/cp36-cp36m/bin/python3 + manylinux-python3.7: CONFIG_CONFIGURE_ARGS_1= PYTHON3=/opt/python/cp37-cp37m/bin/python3 + manylinux-python3.8: CONFIG_CONFIGURE_ARGS_1= PYTHON3=/opt/python/cp38-cp38/bin/python3 + manylinux-python3.9: CONFIG_CONFIGURE_ARGS_1= PYTHON3=/opt/python/cp39-cp39/bin/python3 # # - toolchain # @@ -372,6 +398,7 @@ commands = docker: --build-arg EXTRA_CONFIGURE_ARGS="{env:CONFIGURE_ARGS}" \ docker: --build-arg BASE_IMAGE={env:FULL_BASE_IMAGE_AND_TAG} \ docker-conda: --build-arg USE_CONDARC="{env:CONDARC}" \ + docker: --build-arg BOOTSTRAP="{env:BOOTSTRAP}" \ docker: --build-arg TARGETS_PRE="$(if test -n "$TARGETS_PRE"; then echo $TARGETS_PRE; else echo {posargs:sagelib-build-deps}; fi)" \ docker: --build-arg TARGETS="{posargs:build}" \ docker: --build-arg TARGETS_OPTIONAL="{env:TARGETS_OPTIONAL:ptest}" \ From fe4391559ee7d34dede77b532c1293be1a25b0b2 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Wed, 22 Jul 2020 09:05:43 +0200 Subject: [PATCH 170/217] Trac #30191: code improvements + in ZZ check removed again --- .../differentiable/automorphismfield_group.py | 2 +- .../differentiable/diff_form_module.py | 2 +- .../differentiable/multivector_module.py | 2 +- .../differentiable/tensorfield_module.py | 4 +-- .../differentiable/vectorfield_module.py | 25 ++++++++++--------- src/sage/manifolds/section_module.py | 6 ++--- 6 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/sage/manifolds/differentiable/automorphismfield_group.py b/src/sage/manifolds/differentiable/automorphismfield_group.py index a3acb07d2e7..648f5eaf788 100644 --- a/src/sage/manifolds/differentiable/automorphismfield_group.py +++ b/src/sage/manifolds/differentiable/automorphismfield_group.py @@ -210,7 +210,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, """ if comp == 1: return self.one() - if not isinstance(comp, (list, tuple, slice)): + if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction diff --git a/src/sage/manifolds/differentiable/diff_form_module.py b/src/sage/manifolds/differentiable/diff_form_module.py index 343719bbd64..f995e5fa15a 100644 --- a/src/sage/manifolds/differentiable/diff_form_module.py +++ b/src/sage/manifolds/differentiable/diff_form_module.py @@ -356,7 +356,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(tensor) + "to an element of {}".format(self)) - elif not isinstance(comp, (list, tuple, slice)): + elif not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction diff --git a/src/sage/manifolds/differentiable/multivector_module.py b/src/sage/manifolds/differentiable/multivector_module.py index 06c99bedcad..a43461f42b0 100644 --- a/src/sage/manifolds/differentiable/multivector_module.py +++ b/src/sage/manifolds/differentiable/multivector_module.py @@ -313,7 +313,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) - elif not isinstance(comp, (list, tuple, slice)): + elif not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction diff --git a/src/sage/manifolds/differentiable/tensorfield_module.py b/src/sage/manifolds/differentiable/tensorfield_module.py index b7d19b4c763..666797bb4eb 100644 --- a/src/sage/manifolds/differentiable/tensorfield_module.py +++ b/src/sage/manifolds/differentiable/tensorfield_module.py @@ -372,7 +372,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {}".format(comp) + " to an element of {}".format(self)) - elif not isinstance(comp, (list, tuple, slice)): + elif not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction @@ -858,7 +858,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {}".format(comp) + " to an element of {}".format(self)) - elif not isinstance(comp, (list, tuple, slice)): + elif not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # Standard construction diff --git a/src/sage/manifolds/differentiable/vectorfield_module.py b/src/sage/manifolds/differentiable/vectorfield_module.py index 039030c5721..365d732b717 100644 --- a/src/sage/manifolds/differentiable/vectorfield_module.py +++ b/src/sage/manifolds/differentiable/vectorfield_module.py @@ -42,7 +42,8 @@ from sage.structure.parent import Parent from sage.categories.modules import Modules from sage.misc.cachefunc import cached_method -from sage.symbolic.ring import ZZ +from sage.rings.integer import Integer +from sage.rings.integer_ring import ZZ from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule from sage.manifolds.differentiable.vectorfield import (VectorField, VectorFieldParal) @@ -277,7 +278,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise ValueError("cannot convert the {} ".format(comp) + "to a vector field in {}".format(self)) - elif not isinstance(comp, (list, tuple, slice)): + elif not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction @@ -773,7 +774,7 @@ def tensor(self, tensor_type, name=None, latex_name=None, sym=None, return self.automorphism(name=name, latex_name=latex_name) elif tensor_type[0] == 0 and tensor_type[1] > 1 and antisym: - if antisym[0] in ZZ: + if isinstance(antisym[0], (int, Integer)): # a single antisymmetry is provided as a tuple or a # range object; it is converted to a 1-item list: antisym = [tuple(antisym)] @@ -785,7 +786,7 @@ def tensor(self, tensor_type, name=None, latex_name=None, sym=None, return self.alternating_form(tensor_type[1], name=name, latex_name=latex_name) elif tensor_type[0] > 1 and tensor_type[1] == 0 and antisym: - if antisym[0] in ZZ: + if isinstance(antisym[0], (int, Integer)): # a single antisymmetry is provided as a tuple or a # range object; it is converted to a 1-item list: antisym = [tuple(antisym)] @@ -1090,7 +1091,7 @@ def metric(self, name, signature=None, latex_name=None): ndim = self._ambient_domain.dimension() try: for elt in signature: - if (elt<0) or elt not in ZZ: + if (elt<0) or (not isinstance(elt, (int, Integer))): raise ValueError("{} must be a positive integer".format(elt)) if elt > ndim: raise ValueError("{} must be less than {}".format(elt,ndim)) @@ -1106,7 +1107,7 @@ def metric(self, name, signature=None, latex_name=None): pass if signature is None: signature = (ndim,0) - if signature in ZZ: + if isinstance(signature, (Integer, int)): if (signature+ndim)%2 == 1: if ndim%2 == 0: raise ValueError("the metric signature must be even") @@ -1473,14 +1474,14 @@ def _element_constructor_(self, comp=[], basis=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - if isinstance(comp, VectorField): + elif isinstance(comp, VectorField): if (self._domain.is_subset(comp._domain) and self._ambient_domain.is_subset(comp._ambient_domain)): return comp.restrict(self._domain) else: raise ValueError("cannot convert the {}".format(comp) + "to a vector field in {}".format(self)) - elif not isinstance(comp, (list, tuple, slice)): + elif not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction @@ -2012,7 +2013,7 @@ def tensor(self, tensor_type, name=None, latex_name=None, sym=None, (AutomorphismField, AutomorphismFieldParal)): return self.automorphism(name=name, latex_name=latex_name) elif tensor_type[0] == 0 and tensor_type[1] > 1 and antisym: - if antisym[0] in ZZ: + if isinstance(antisym[0], (int, Integer)): # a single antisymmetry is provided as a tuple or a # range object; it is converted to a 1-item list: antisym = [tuple(antisym)] @@ -2024,7 +2025,7 @@ def tensor(self, tensor_type, name=None, latex_name=None, sym=None, return self.alternating_form(tensor_type[1], name=name, latex_name=latex_name) elif tensor_type[0] > 1 and tensor_type[1] == 0 and antisym: - if antisym[0] in ZZ: + if isinstance(antisym[0], (int, Integer)): # a single antisymmetry is provided as a tuple or a # range object; it is converted to a 1-item list: antisym = [tuple(antisym)] @@ -2231,7 +2232,7 @@ def metric(self, name, signature=None, latex_name=None): ndim = self._ambient_domain.dimension() try: for elt in signature: - if (elt<0) or elt not in ZZ: + if (elt<0) or (not isinstance(elt, (int, Integer))): raise ValueError("{} must be a positive integer".format(elt)) sign = signature[0]+signature[1]+signature[2] if sign!=ndim: @@ -2245,7 +2246,7 @@ def metric(self, name, signature=None, latex_name=None): pass if signature is None: signature = (ndim,0) - if signature in ZZ: + if isinstance(signature, (Integer, int)): if (signature+ndim)%2 == 1: if ndim%2 == 0: raise ValueError("the metric signature must be even") diff --git a/src/sage/manifolds/section_module.py b/src/sage/manifolds/section_module.py index 995860b179f..1aa29373158 100644 --- a/src/sage/manifolds/section_module.py +++ b/src/sage/manifolds/section_module.py @@ -230,7 +230,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise ValueError("cannot convert the {} ".format(comp) + "to a local section in {}".format(self)) - elif not isinstance(comp, (list, tuple, slice)): + elif not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction @@ -643,13 +643,13 @@ def _element_constructor_(self, comp=[], basis=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - if isinstance(comp, Section): + elif isinstance(comp, Section): if self._domain.is_subset(comp._domain): return comp.restrict(self._domain) else: raise ValueError("cannot convert the {}".format(comp) + "to a local section in {}".format(self)) - elif not isinstance(comp, (list, tuple, slice)): + elif not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction From 461ff656bc938720022b0bebdaef8ac1511916d0 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Wed, 22 Jul 2020 09:13:58 +0200 Subject: [PATCH 171/217] Trac #30191: != [] removal reverted --- src/sage/manifolds/differentiable/multivector_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/manifolds/differentiable/multivector_module.py b/src/sage/manifolds/differentiable/multivector_module.py index a43461f42b0..c8ace2f242c 100644 --- a/src/sage/manifolds/differentiable/multivector_module.py +++ b/src/sage/manifolds/differentiable/multivector_module.py @@ -743,7 +743,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, # standard construction resu = self.element_class(self._fmodule, self._degree, name=name, latex_name=latex_name) - if comp: + if comp != []: resu.set_comp(frame)[:] = comp return resu From af5af8f7ed6cbc57832a64b75907f0fac054cb07 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Wed, 22 Jul 2020 09:41:49 +0200 Subject: [PATCH 172/217] Trac #30191: elif reverted + in ZZ check for automorphismfield_group --- .../differentiable/automorphismfield_group.py | 3 ++- .../differentiable/multivector_module.py | 6 +++--- .../differentiable/tensorfield_module.py | 20 +++++++++---------- .../differentiable/vectorfield_module.py | 8 ++++---- src/sage/manifolds/section_module.py | 8 ++++---- 5 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/sage/manifolds/differentiable/automorphismfield_group.py b/src/sage/manifolds/differentiable/automorphismfield_group.py index 648f5eaf788..916efee36e5 100644 --- a/src/sage/manifolds/differentiable/automorphismfield_group.py +++ b/src/sage/manifolds/differentiable/automorphismfield_group.py @@ -41,6 +41,7 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent +from sage.symbolic.ring import ZZ from sage.categories.groups import Groups from sage.misc.cachefunc import cached_method from sage.tensor.modules.free_module_linear_group import FreeModuleLinearGroup @@ -208,7 +209,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, a = (x^2 + 1) d/dx*dx + (y^2 + 1) d/dy*dy """ - if comp == 1: + if comp in ZZ and comp == 1: return self.one() if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + diff --git a/src/sage/manifolds/differentiable/multivector_module.py b/src/sage/manifolds/differentiable/multivector_module.py index c8ace2f242c..e182ee30ad0 100644 --- a/src/sage/manifolds/differentiable/multivector_module.py +++ b/src/sage/manifolds/differentiable/multivector_module.py @@ -303,7 +303,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - elif isinstance(comp, (MultivectorField, MultivectorFieldParal)): + if isinstance(comp, (MultivectorField, MultivectorFieldParal)): # coercion by domain restriction if (self._degree == comp._tensor_type[0] and self._domain.is_subset(comp._domain) @@ -313,7 +313,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) - elif not isinstance(comp, (list, tuple)): + if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction @@ -737,7 +737,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(comp) + "to a multivector field in {}".format(self)) - elif not isinstance(comp, (list, tuple, slice)): + if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction diff --git a/src/sage/manifolds/differentiable/tensorfield_module.py b/src/sage/manifolds/differentiable/tensorfield_module.py index 666797bb4eb..a9d346278c0 100644 --- a/src/sage/manifolds/differentiable/tensorfield_module.py +++ b/src/sage/manifolds/differentiable/tensorfield_module.py @@ -312,7 +312,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - elif isinstance(comp, DiffForm): + if isinstance(comp, DiffForm): # coercion of a p-form to a type-(0,p) tensor field: form = comp # for readability p = form.degree() @@ -331,7 +331,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, for dom, rst in form._restrictions.items(): resu._restrictions[dom] = dom.tensor_field_module((0,p))(rst) return resu - elif isinstance(comp, MultivectorField): + if isinstance(comp, MultivectorField): # coercion of a p-vector field to a type-(p,0) tensor: pvect = comp # for readability p = pvect.degree() @@ -350,7 +350,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, for dom, rst in pvect._restrictions.items(): resu._restrictions[dom] = dom.tensor_field_module((p,0))(rst) return resu - elif isinstance(comp, AutomorphismField): + if isinstance(comp, AutomorphismField): # coercion of an automorphism to a type-(1,1) tensor: autom = comp # for readability if (self._tensor_type != (1,1) or @@ -363,7 +363,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, for dom, rest in autom._restrictions.items(): resu._restrictions[dom] = dom.tensor_field_module((1,1))(rest) return resu - elif isinstance(comp, TensorField): + if isinstance(comp, TensorField): # coercion by domain restriction if (self._tensor_type == comp._tensor_type and self._domain.is_subset(comp._domain) @@ -372,7 +372,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {}".format(comp) + " to an element of {}".format(self)) - elif not isinstance(comp, (list, tuple)): + if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction @@ -797,7 +797,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - elif isinstance(comp, DiffFormParal): + if isinstance(comp, DiffFormParal): # coercion of a p-form to a type-(0,p) tensor field: form = comp # for readability p = form.degree() @@ -816,7 +816,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, for frame, cp in form._components.items(): resu._components[frame] = cp.copy() return resu - elif isinstance(comp, MultivectorFieldParal): + if isinstance(comp, MultivectorFieldParal): # coercion of a p-vector field to a type-(p,0) tensor field: pvect = comp # for readability p = pvect.degree() @@ -835,7 +835,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, for frame, cp in pvect._components.items(): resu._components[frame] = cp.copy() return resu - elif isinstance(comp, AutomorphismFieldParal): + if isinstance(comp, AutomorphismFieldParal): # coercion of an automorphism to a type-(1,1) tensor: autom = comp # for readability if (self._tensor_type != (1,1) or @@ -848,7 +848,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, for basis, comp in autom._components.items(): resu._components[basis] = comp.copy() return resu - elif isinstance(comp, TensorField): + if isinstance(comp, TensorField): # coercion by domain restriction if (self._tensor_type == comp._tensor_type and self._domain.is_subset(comp._domain) @@ -858,7 +858,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {}".format(comp) + " to an element of {}".format(self)) - elif not isinstance(comp, (list, tuple)): + if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # Standard construction diff --git a/src/sage/manifolds/differentiable/vectorfield_module.py b/src/sage/manifolds/differentiable/vectorfield_module.py index 365d732b717..8227a767229 100644 --- a/src/sage/manifolds/differentiable/vectorfield_module.py +++ b/src/sage/manifolds/differentiable/vectorfield_module.py @@ -271,14 +271,14 @@ def _element_constructor_(self, comp=[], frame=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - elif isinstance(comp, VectorField): + if isinstance(comp, VectorField): if (self._domain.is_subset(comp._domain) and self._ambient_domain.is_subset(comp._ambient_domain)): return comp.restrict(self._domain) else: raise ValueError("cannot convert the {} ".format(comp) + "to a vector field in {}".format(self)) - elif not isinstance(comp, (list, tuple)): + if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction @@ -1474,14 +1474,14 @@ def _element_constructor_(self, comp=[], basis=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - elif isinstance(comp, VectorField): + if isinstance(comp, VectorField): if (self._domain.is_subset(comp._domain) and self._ambient_domain.is_subset(comp._ambient_domain)): return comp.restrict(self._domain) else: raise ValueError("cannot convert the {}".format(comp) + "to a vector field in {}".format(self)) - elif not isinstance(comp, (list, tuple)): + if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction diff --git a/src/sage/manifolds/section_module.py b/src/sage/manifolds/section_module.py index 1aa29373158..f8d1b6e6f13 100644 --- a/src/sage/manifolds/section_module.py +++ b/src/sage/manifolds/section_module.py @@ -224,13 +224,13 @@ def _element_constructor_(self, comp=[], frame=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - elif isinstance(comp, Section): + if isinstance(comp, Section): if self._domain.is_subset(comp._domain): return comp.restrict(self._domain) else: raise ValueError("cannot convert the {} ".format(comp) + "to a local section in {}".format(self)) - elif not isinstance(comp, (list, tuple)): + if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction @@ -643,13 +643,13 @@ def _element_constructor_(self, comp=[], basis=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - elif isinstance(comp, Section): + if isinstance(comp, Section): if self._domain.is_subset(comp._domain): return comp.restrict(self._domain) else: raise ValueError("cannot convert the {}".format(comp) + "to a local section in {}".format(self)) - elif not isinstance(comp, (list, tuple)): + if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction From f0c6ee814ec3965b908073fd2dd47f2faead7e2b Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Wed, 22 Jul 2020 09:45:10 +0200 Subject: [PATCH 173/217] Trac #30191: minor fix --- .../manifolds/differentiable/diff_form_module.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/sage/manifolds/differentiable/diff_form_module.py b/src/sage/manifolds/differentiable/diff_form_module.py index f995e5fa15a..6f25aafd26b 100644 --- a/src/sage/manifolds/differentiable/diff_form_module.py +++ b/src/sage/manifolds/differentiable/diff_form_module.py @@ -334,7 +334,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - elif isinstance(comp, (DiffForm, DiffFormParal)): + if isinstance(comp, (DiffForm, DiffFormParal)): # coercion by domain restriction if (self._degree == comp._tensor_type[1] and self._domain.is_subset(comp._domain) @@ -343,7 +343,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) - elif isinstance(comp, TensorField): + if isinstance(comp, TensorField): # coercion of a tensor of type (0,1) to a linear form tensor = comp # for readability if (tensor.tensor_type() == (0,1) and self._degree == 1 @@ -356,7 +356,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(tensor) + "to an element of {}".format(self)) - elif not isinstance(comp, (list, tuple)): + if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction @@ -777,7 +777,7 @@ def __init__(self, vector_field_module, degree): #### Parent methods - def _element_constructor_(self, comp=[], frame=None, name=None, + def _element_constructor_(self, comp=[], frame=None, name=None, latex_name=None): r""" Construct a differential form. @@ -803,7 +803,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - elif isinstance(comp, (DiffForm, DiffFormParal)): + if isinstance(comp, (DiffForm, DiffFormParal)): # coercion by domain restriction if (self._degree == comp._tensor_type[1] and self._domain.is_subset(comp._domain) @@ -812,7 +812,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(comp) + "to a differential form in {}".format(self)) - elif isinstance(comp, TensorFieldParal): + if isinstance(comp, TensorFieldParal): # coercion of a tensor of type (0,1) to a linear form tensor = comp # for readability if (tensor.tensor_type() == (0,1) and self._degree == 1 @@ -825,7 +825,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(tensor) + "to an element of {}".format(self)) - elif not isinstance(comp, (list, tuple, slice)): + if not isinstance(comp, (list, tuple, slice)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction From f1221da5168e9b3231e00bde01a138bb4f9dc5f0 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Wed, 22 Jul 2020 09:47:14 +0200 Subject: [PATCH 174/217] Trac #30191: minor fix --- .../manifolds/differentiable/diff_form_module.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sage/manifolds/differentiable/diff_form_module.py b/src/sage/manifolds/differentiable/diff_form_module.py index f995e5fa15a..73bd3c93279 100644 --- a/src/sage/manifolds/differentiable/diff_form_module.py +++ b/src/sage/manifolds/differentiable/diff_form_module.py @@ -334,7 +334,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - elif isinstance(comp, (DiffForm, DiffFormParal)): + if isinstance(comp, (DiffForm, DiffFormParal)): # coercion by domain restriction if (self._degree == comp._tensor_type[1] and self._domain.is_subset(comp._domain) @@ -343,7 +343,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) - elif isinstance(comp, TensorField): + if isinstance(comp, TensorField): # coercion of a tensor of type (0,1) to a linear form tensor = comp # for readability if (tensor.tensor_type() == (0,1) and self._degree == 1 @@ -356,7 +356,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(tensor) + "to an element of {}".format(self)) - elif not isinstance(comp, (list, tuple)): + if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction @@ -803,7 +803,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, """ if comp in ZZ and comp == 0: return self.zero() - elif isinstance(comp, (DiffForm, DiffFormParal)): + if isinstance(comp, (DiffForm, DiffFormParal)): # coercion by domain restriction if (self._degree == comp._tensor_type[1] and self._domain.is_subset(comp._domain) @@ -812,7 +812,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(comp) + "to a differential form in {}".format(self)) - elif isinstance(comp, TensorFieldParal): + if isinstance(comp, TensorFieldParal): # coercion of a tensor of type (0,1) to a linear form tensor = comp # for readability if (tensor.tensor_type() == (0,1) and self._degree == 1 @@ -825,7 +825,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, else: raise TypeError("cannot convert the {} ".format(tensor) + "to an element of {}".format(self)) - elif not isinstance(comp, (list, tuple, slice)): + if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) # standard construction From 4cc92e908ce58c863330aac9001ddccbd76437d5 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Wed, 22 Jul 2020 09:58:28 +0200 Subject: [PATCH 175/217] Trac #30191: comp check unified to if comp --- src/sage/manifolds/differentiable/automorphismfield_group.py | 2 +- src/sage/manifolds/differentiable/diff_form_module.py | 4 ++-- src/sage/manifolds/differentiable/multivector_module.py | 4 ++-- src/sage/manifolds/differentiable/tensorfield_module.py | 4 ++-- src/sage/manifolds/differentiable/vectorfield_module.py | 4 ++-- src/sage/manifolds/section_module.py | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/sage/manifolds/differentiable/automorphismfield_group.py b/src/sage/manifolds/differentiable/automorphismfield_group.py index 916efee36e5..bd5b5f6c80d 100644 --- a/src/sage/manifolds/differentiable/automorphismfield_group.py +++ b/src/sage/manifolds/differentiable/automorphismfield_group.py @@ -217,7 +217,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, # standard construction resu = self.element_class(self._vmodule, name=name, latex_name=latex_name) - if comp != []: + if comp: resu.set_comp(frame)[:] = comp return resu diff --git a/src/sage/manifolds/differentiable/diff_form_module.py b/src/sage/manifolds/differentiable/diff_form_module.py index 73bd3c93279..0e03b18a75d 100644 --- a/src/sage/manifolds/differentiable/diff_form_module.py +++ b/src/sage/manifolds/differentiable/diff_form_module.py @@ -362,7 +362,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, # standard construction resu = self.element_class(self._vmodule, self._degree, name=name, latex_name=latex_name) - if comp != []: + if comp: resu.set_comp(frame)[:] = comp return resu @@ -831,7 +831,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, # standard construction resu = self.element_class(self._fmodule, self._degree, name=name, latex_name=latex_name) - if comp != []: + if comp: resu.set_comp(frame)[:] = comp return resu diff --git a/src/sage/manifolds/differentiable/multivector_module.py b/src/sage/manifolds/differentiable/multivector_module.py index e182ee30ad0..0e13e81ec80 100644 --- a/src/sage/manifolds/differentiable/multivector_module.py +++ b/src/sage/manifolds/differentiable/multivector_module.py @@ -319,7 +319,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, # standard construction resu = self.element_class(self._vmodule, self._degree, name=name, latex_name=latex_name) - if comp != []: + if comp: resu.set_comp(frame)[:] = comp return resu @@ -743,7 +743,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, # standard construction resu = self.element_class(self._fmodule, self._degree, name=name, latex_name=latex_name) - if comp != []: + if comp: resu.set_comp(frame)[:] = comp return resu diff --git a/src/sage/manifolds/differentiable/tensorfield_module.py b/src/sage/manifolds/differentiable/tensorfield_module.py index a9d346278c0..95954bc3e0e 100644 --- a/src/sage/manifolds/differentiable/tensorfield_module.py +++ b/src/sage/manifolds/differentiable/tensorfield_module.py @@ -379,7 +379,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, resu = self.element_class(self._vmodule, self._tensor_type, name=name, latex_name=latex_name, sym=sym, antisym=antisym) - if comp != []: + if comp: resu.set_comp(frame)[:] = comp return resu @@ -865,7 +865,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, resu = self.element_class(self._fmodule, self._tensor_type, name=name, latex_name=latex_name, sym=sym, antisym=antisym) - if comp != []: + if comp: resu.set_comp(frame)[:] = comp return resu diff --git a/src/sage/manifolds/differentiable/vectorfield_module.py b/src/sage/manifolds/differentiable/vectorfield_module.py index 8227a767229..3f22b3da98f 100644 --- a/src/sage/manifolds/differentiable/vectorfield_module.py +++ b/src/sage/manifolds/differentiable/vectorfield_module.py @@ -283,7 +283,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, "to an element of {}".format(self)) # standard construction resu = self.element_class(self, name=name, latex_name=latex_name) - if comp != []: + if comp: resu.set_comp(frame)[:] = comp return resu @@ -1486,7 +1486,7 @@ def _element_constructor_(self, comp=[], basis=None, name=None, "to an element of {}".format(self)) # standard construction resu = self.element_class(self, name=name, latex_name=latex_name) - if comp != []: + if comp: resu.set_comp(basis=basis)[:] = comp return resu diff --git a/src/sage/manifolds/section_module.py b/src/sage/manifolds/section_module.py index f8d1b6e6f13..962ce48e130 100644 --- a/src/sage/manifolds/section_module.py +++ b/src/sage/manifolds/section_module.py @@ -235,7 +235,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, "to an element of {}".format(self)) # standard construction resu = self.element_class(self, name=name, latex_name=latex_name) - if comp != []: + if comp: resu.set_comp(frame)[:] = comp return resu @@ -654,7 +654,7 @@ def _element_constructor_(self, comp=[], basis=None, name=None, "to an element of {}".format(self)) # standard construction resu = self.element_class(self, name=name, latex_name=latex_name) - if comp != []: + if comp: resu.set_comp(basis)[:] = comp return resu From 899d3900180c956773f3d34c53b96483aa95c57f Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Wed, 22 Jul 2020 09:40:51 +0100 Subject: [PATCH 176/217] make \beta unicode --- src/sage/coding/linear_rank_metric.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/sage/coding/linear_rank_metric.py b/src/sage/coding/linear_rank_metric.py index ace4c206272..888864d9c27 100644 --- a/src/sage/coding/linear_rank_metric.py +++ b/src/sage/coding/linear_rank_metric.py @@ -153,8 +153,8 @@ def to_matrix_representation(v, sub_field=None, basis=None): - ``basis`` -- (default: ``None``) a basis of `F_{q^m}` as a vector space over ``sub_field``. If not specified, given that `q = p^s`, let - `1,\beta,\ldots,\beta^{sm}` be the power basis that SageMath uses to - represent `F_{q^m}`. The default basis is then `1,\beta,\ldots,beta^{m-1}`. + `1,β,\ldots,β^{sm}` be the power basis that SageMath uses to + represent `F_{q^m}`. The default basis is then `1,β,\ldots,β^{m-1}`. EXAMPLES:: @@ -204,8 +204,8 @@ def from_matrix_representation(w, base_field=None, basis=None): - ``basis`` -- (default: ``None``) a basis of `F_{q^m}` as a vector space over ``F_q``. If not specified, given that `q = p^s`, let - `1,\beta,\ldots,\beta^{sm}` be the power basis that SageMath uses to - represent `F_{q^m}`. The default basis is then `1,\beta,\ldots,beta^{m-1}`. + `1,β,\ldots,β^{sm}` be the power basis that SageMath uses to + represent `F_{q^m}`. The default basis is then `1,β,\ldots,β^{m-1}`. EXAMPLES:: @@ -247,8 +247,8 @@ def rank_weight(c, sub_field=None, basis=None): - ``basis`` -- (default: ``None``) a basis of `F_{q^m}` as a vector space over ``sub_field``. If not specified, given that `q = p^s`, let - `1,\beta,\ldots,\beta^{sm}` be the power basis that SageMath uses to - represent `F_{q^m}`. The default basis is then `1,\beta,\ldots,beta^{m-1}`. + `1,β,\ldots,β^{sm}` be the power basis that SageMath uses to + represent `F_{q^m}`. The default basis is then `1,β,\ldots,β^{m-1}`. EXAMPLES:: @@ -284,8 +284,8 @@ def rank_distance(a, b, sub_field=None, basis=None): - ``basis`` -- (default: ``None``) a basis of `F_{q^m}` as a vector space over ``sub_field``. If not specified, given that `q = p^s`, let - `1,\beta,\ldots,\beta^{sm}` be the power basis that SageMath uses to - represent `F_{q^m}`. The default basis is then `1,\beta,\ldots,beta^{m-1}`. + `1,β,\ldots,β^{sm}` be the power basis that SageMath uses to + represent `F_{q^m}`. The default basis is then `1,β,\ldots,β^{m-1}`. EXAMPLES:: @@ -386,8 +386,8 @@ def __init__(self, base_field, sub_field, length, default_encoder_name, - ``basis`` -- (default: ``None``) a basis of `F_{q^m}` as a vector space over ``sub_field``. If not specified, given that `q = p^s`, let - `1,\beta,\ldots,\beta^{sm}` be the power basis that SageMath uses to - represent `F_{q^m}`. The default basis is then `1,\beta,\ldots,beta^{m-1}`. + `1,β,\ldots,β^{sm}` be the power basis that SageMath uses to + represent `F_{q^m}`. The default basis is then `1,β,\ldots,β^{m-1}`. EXAMPLES: @@ -682,8 +682,8 @@ def __init__(self, generator, sub_field=None, basis=None): - ``basis`` -- (default: ``None``) a basis of `F_{q^m}` as a vector space over ``sub_field``. If not specified, given that `q = p^s`, let - `1,\beta,\ldots,\beta^{sm}` be the power basis that SageMath uses to - represent `F_{q^m}`. The default basis is then `1,\beta,\ldots,beta^{m-1}`. + `1,β,\ldots,β^{sm}` be the power basis that SageMath uses to + represent `F_{q^m}`. The default basis is then `1,β,\ldots,β^{m-1}`. EXAMPLES:: From 8a800cc0734fe2c0c9e4e201faf5b9435fdab78e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 22 Jul 2020 08:40:01 -0700 Subject: [PATCH 177/217] FiniteRankFreeModule.isomorphism_with_fixed_basis: Simplify using self.module_morphism --- src/sage/tensor/modules/finite_rank_free_module.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/sage/tensor/modules/finite_rank_free_module.py b/src/sage/tensor/modules/finite_rank_free_module.py index a4cb6514bd2..6a87a8abd92 100644 --- a/src/sage/tensor/modules/finite_rank_free_module.py +++ b/src/sage/tensor/modules/finite_rank_free_module.py @@ -2604,8 +2604,6 @@ def isomorphism_with_fixed_basis(self, basis, codomain=None): raise ValueError("domain and codomain must have the same " "base ring") - from sage.modules.with_basis.morphism import ModuleMorphismFromFunction - codomain_basis = list(codomain.basis()) def _isomorphism(x): @@ -2615,8 +2613,7 @@ def _isomorphism(x): return codomain.sum(x[basis, i] * codomain_basis[i - self._sindex] for i in self.irange()) - return ModuleMorphismFromFunction(self, _isomorphism, codomain, - category=Modules(base_ring)) + return self.module_morphism(function=_isomorphism, codomain=codomain) def endomorphism(self, matrix_rep, basis=None, name=None, latex_name=None): r""" From 756f310bce050bd1c4303398638d061a0705feb4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 22 Jul 2020 08:47:24 -0700 Subject: [PATCH 178/217] tox.ini: Initialize the BOOTSTRAP variable --- .gitignore | 1 + tox.ini | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index d91c194b1b1..59ac38b3a15 100644 --- a/.gitignore +++ b/.gitignore @@ -107,3 +107,4 @@ gitlab-build-docker.log /.tox /prefix +worktree* diff --git a/tox.ini b/tox.ini index 9609df0ecb4..fd52a97d125 100644 --- a/tox.ini +++ b/tox.ini @@ -107,6 +107,8 @@ passenv = local-direct: * setenv = + # By default, we bootstrap using autotools and do not allow downloads of the configure tarball. + BOOTSTRAP=./bootstrap # For https downloads from upstream_url listed in checksums.ini, do not # check certificates, to avoid problems on Docker images with outdated # certificates and with system python3 on macOS (#29418) @@ -190,7 +192,7 @@ setenv = fedora-32: BASE_TAG=32 # # https://hub.docker.com/_/centos - # centos-6 only has autoconf 2.63 -- too old for bootstrap + # centos-6 only has autoconf 2.63 -- too old for bootstrap; download configure tarball instead. # centos: SYSTEM=fedora centos: BASE_IMAGE=centos @@ -408,7 +410,7 @@ commands = docker: done' # pathpy checksuite needs tox. #28728: gap fails its test suite. # linbox/cysignals testsuites fail. ppl takes very long. - local: bash -c 'export PATH={env:PATH} && {env:SETENV} && {env:BOOTSTRAP:./bootstrap} && ./configure --prefix={envdir}/local {env:CONFIGURE_ARGS} && make -k V=0 base-toolchain && make -k V=0 SAGE_SPKG="sage-spkg -y -o" SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!symengine_py" {env:TARGETS_PRE:} {posargs:build} && (make -k V=0 SAGE_SPKG="sage-spkg -y -o" SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake" {env:TARGETS_OPTIONAL:} || echo "(error ignored)" ) ' + local: bash -c 'export PATH={env:PATH} && {env:SETENV} && {env:BOOTSTRAP} && ./configure --prefix={envdir}/local {env:CONFIGURE_ARGS} && make -k V=0 base-toolchain && make -k V=0 SAGE_SPKG="sage-spkg -y -o" SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!symengine_py" {env:TARGETS_PRE:} {posargs:build} && (make -k V=0 SAGE_SPKG="sage-spkg -y -o" SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake" {env:TARGETS_OPTIONAL:} || echo "(error ignored)" ) ' [testenv:check_configure] ## Test that configure behaves properly From 837f7bd7678cc6e889bc3308db16557e9e93c122 Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Wed, 22 Jul 2020 09:20:39 -0700 Subject: [PATCH 179/217] Toric coordinate changes for Laurent polynomials --- .../rings/polynomial/laurent_polynomial.pxd | 3 + .../rings/polynomial/laurent_polynomial.pyx | 109 +++++++++++++++++- 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pxd b/src/sage/rings/polynomial/laurent_polynomial.pxd index e96de696a6f..33624915549 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pxd +++ b/src/sage/rings/polynomial/laurent_polynomial.pxd @@ -23,4 +23,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): cdef PolyDict _prod cdef _compute_polydict(self) cdef _normalize(self, i=*) + cpdef rescale_vars(self, d, h=*, new_ring=*) + cpdef toric_coordinate_change(self, M, h=*, new_ring=*) + cpdef toric_substitute(self, v, v1, a, h=*, new_ring=*) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index 45c9cfca578..c7132033a24 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -3446,7 +3446,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): def is_square(self, root=False): r""" - Test whether this Laurent polynomial is a square root. + Test whether this Laurent polynomial is a square. INPUT: @@ -3493,3 +3493,110 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): ans._poly = root return (True, ans) + cpdef rescale_vars(self, d, h=None, new_ring=None): + r""" + Rescale variables in a Laurent polynomial. + + The optional argument ``h`` is a map to be applied to coefficients. + This is done after rescaling. + + EXAMPLES:: + + sage: L. = LaurentPolynomialRing(QQ, 2) + sage: p = x^2*y + x*y^2 + sage: p.rescale_vars({0: 2, 1: 3}) + 12*x^2*y + 18*x*y^2 + """ + cdef int i + if new_ring is None: + P = self.parent() + else: + P = new_ring + df = self.dict() + df2 = {} + for v in df: + w = df[v] + for i in d: + w *= d[i]**v[i] + if h is not None: + w = h(w) + df2[v] = w + return P(df2) + + cpdef toric_coordinate_change(self, M, h=None, new_ring=None): + r""" + Apply a matrix to the exponents in a Laurent polynomial. + + For efficiency, we implement this directly, rather than as a substitution. + + The optional argument ``h`` is a map to be applied to coefficients. + + EXAMPLES:: + + sage: L. = LaurentPolynomialRing(QQ,2) + sage: p = 2*x^2 + y + x*y + sage: p.toric_coordinate_change(Matrix([[1,-3],[1,1]])) + 2*x^2*y^2 + x^-2*y^2 + x^-3*y + sage: F = GF(2) + sage: p.toric_coordinate_change(Matrix([[1,-3],[1,1]]), new_ring=L.change_ring(F)) + x^-2*y^2 + x^-3*y + """ + cdef n, i, j + if new_ring is None: + P = self.parent() + else: + P = new_ring + n = P.ngens() + if self == 0: + return P.zero() + l = [] + for j in range(n): + l.append(ETuple(tuple(M.column(j)))) + d = self.dict() + d2 = {} + for v in d: + x = d[v] + t = ETuple({}, n) + for j in range(n): + t = t.eadd(l[j].emul(v[j])) + if h is not None: + x = h(x) + d2[t] = x + return P(d2) + + cpdef toric_substitute(self, v, v1, a, h=None, new_ring=None): + r""" + Perform a single-variable substitution up to a toric coordinate change. + + The optional argument ``h`` is a map to be applied to coefficients. + + EXAMPLES:: + + sage: L. = LaurentPolynomialRing(QQ, 2) + sage: p = x + y + sage: p.toric_substitute((2,3), (-1,1), 2) + 1/2*x^3*y^3 + 2*x^-2*y^-2 + sage: F = GF(5) + sage: p.toric_substitute((2,3), (-1,1), 2, new_ring=L.change_ring(F)) + 3*x^3*y^3 + 2*x^-2*y^-2 + """ + if new_ring is None: + P = self.parent() + else: + P = new_ring + d = self.dict() + d2 = {} + v = ETuple(v) + v1 = ETuple(v1) + for w in d: + x = d[w] + if h is not None: + x = h(x) + t = w.dotprod(v1) + w1 = w.eadd(v.emul(-t)) + if w1 in d2: + d2[w1] += x * a**t + else: + d2[w1] = x * a**t + return P(d2) + From 605c0ae8df9ca539fd2c31cca3a36cd580c74c7a Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Wed, 22 Jul 2020 11:55:26 -0700 Subject: [PATCH 180/217] Implement ideals in Laurent polynomial rings --- .../polynomial/laurent_polynomial_ideal.py | 579 ++++++++++++++++++ .../polynomial/laurent_polynomial_ring.py | 25 +- .../rings/polynomial/polynomial_element.pyx | 2 +- 3 files changed, 596 insertions(+), 10 deletions(-) create mode 100644 src/sage/rings/polynomial/laurent_polynomial_ideal.py diff --git a/src/sage/rings/polynomial/laurent_polynomial_ideal.py b/src/sage/rings/polynomial/laurent_polynomial_ideal.py new file mode 100644 index 00000000000..3bb73232e6b --- /dev/null +++ b/src/sage/rings/polynomial/laurent_polynomial_ideal.py @@ -0,0 +1,579 @@ +# -*- coding: utf-8 -*- +r""" +Ideals in Laurent polynomial rings. + +For `R` a commutative ring, ideals in the Laurent polynomial ring +`R[x_1^{\pm 1}, x_2^{\pm 1}, \ldots, x_n^{\pm 1}]` are implemented as +ideals in the ordinary polynomial ring `R[x_1, \ldots, x_n]` which are +saturated with respect to the ideal `(x_1 \cdots x_n)`. + +AUTHORS: + +- Kiran S. Kedlaya (2020): initial implementation + +""" +# **************************************************************************** +# Copyright (C) 2020 Kiran S. Kedlaya +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.rings.ideal import Ideal_generic + +class LaurentPolynomialIdeal( Ideal_generic ): + def __init__(self, ring, gens, coerce=True, hint=None): + r""" + Create an ideal in a Laurent polynomial ring. + + To compute structural properties of an ideal in the Laurent polynomial ring + `R[x_1^{\pm},\dots,x_n^{\pm}]`, we form the corresponding ideal in the + associated ordinary polynomial ring `R[x_1,\dots,x_n]` which is saturated + with respect to the ideal `(x_1 \cdots x_n)`. Since computing the saturation + can be expensive, we employ some strategies to reduce the need for it. + + - We only create the polynomial ideal as needed. + + - For some operations, we try some superficial tests first. E.g., for + comparisons, we first look directly at generators. + - The attribute ``hint`` is a lower bound on the associated polynomial ideal. + Hints are automatically forwarded by certain creation operations (such as + sums and base extensions), and can be manually forwarded in other cases. + + INPUT: + + - ``ring`` - the ring the ideal is defined in + + - ``gens`` - a list of generators for the ideal + + - ``coerce`` - coerce elements to the ring ``ring``? + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(IntegerRing(), 2, order='lex') + sage: R.ideal([x, y]) + Ideal (x, y) of Multivariate Laurent Polynomial Ring in x, y over Integer Ring + sage: R. = LaurentPolynomialRing(GF(3), 2) + sage: R.ideal([x0^2, x1^-3]) + Ideal (x0^2, x1^-3) of Multivariate Laurent Polynomial Ring in x0, x1 over Finite Field of size 3 + + sage: P. = LaurentPolynomialRing(QQ, 2) + sage: I = P.ideal([~x + ~y - 1]) + sage: print(I) + Ideal (-1 + y^-1 + x^-1) of Multivariate Laurent Polynomial Ring in x, y over Rational Field + sage: I.is_zero() + False + sage: (x^(-2) + x^(-1)*y^(-1) - x^(-1)) in I + True + + sage: P. = LaurentPolynomialRing(QQ, 3) + sage: I1 = P.ideal([x*y*z+x*y+2*y^2, x+z]) + sage: I2 = P.ideal([x*y*z+x*y+2*y^2+x+z, x+z]) + sage: I1 == I2 + True + sage: I3 = P.ideal([x*y*z+x*y+2*y^2+x+z, x+z, y]) + sage: I1 < I3 + True + sage: I1.minimal_associated_primes() + (Ideal (-1/2*z^2 + y - 1/2*z, x + z) of Multivariate Laurent Polynomial Ring in x, y, z over Rational Field,) + + sage: K. = CyclotomicField(4) + sage: J = I1.base_extend(K) + sage: J.base_ring() + Cyclotomic Field of order 4 and degree 2 + """ + Ideal_generic.__init__(self, ring, gens, coerce=coerce) + self._poly_ring = ring.polynomial_ring() + self._poly_ideal = None # Create only as needed + self._saturated = False + if hint is None: + self._hint = self._poly_ring.zero_ideal() + else: + self._hint = hint.change_ring(self._poly_ring) + + def set_hint(self, hint): + """ + Set the hint of this ideal. + + The hint is an ideal of the associated polynomial ring, which is + assumed to be contained in the associated ideal. It is used internally + to speed up computation of the associated ideal in some cases; + normally the end user will have no need to work with it directly. + + sage: P. = LaurentPolynomialRing(QQ, 3) + sage: I = P.ideal([x^2*y + 3*x*y^2]) + sage: I.hint() + Ideal (0) of Multivariate Polynomial Ring in x, y, z over Rational Field + sage: I.set_hint(P.polynomial_ring().ideal([x + 3*y])) + sage: I.hint() + Ideal (x + 3*y) of Multivariate Polynomial Ring in x, y, z over Rational Field + """ + self._hint = hint + + def hint(self): + """ + Return the hint of this ideal. + + The hint is an ideal of the associated polynomial ring, which is + assumed to be contained in the associated ideal. It is used internally + to speed up computation of the associated ideal in some cases; + normally the end user will have no need to work with it directly. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 3) + sage: I = P.ideal([x^2*y + 3*x*y^2]) + sage: I.hint() + Ideal (0) of Multivariate Polynomial Ring in x, y, z over Rational Field + """ + return self._hint + + # Comparisons, using the associated polynomial ideal. + def __eq__(self, other): + """ + Implement equality comparison (==) for Laurent polynomial ideals. + + To save time, we check equality of generators before + comparing polynomial ideals. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 3) + sage: I1 = P.ideal([x*y*z+x*y+2*y^2, x+z]) + sage: I2 = P.ideal([x*y*z+x*y+2*y^2+x+z, x+z]) + sage: I1 == I2 + True + """ + if set(self.gens()) == set(other.gens()): # Early abort + return True + return self.polynomial_ideal() == other.polynomial_ideal() + + def __ne__(self, other): + """ + Implement inequality comparison (!=) for Laurent polynomial ideals. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 3) + sage: I1 = P.ideal([x*y*z+x*y+2*y^2, x+z]) + sage: I2 = P.ideal([x*y*z+x*y+2*y^2+x+z, x+z]) + sage: I1 != I2 + False + """ + return not (self == other) + + def __le__(self, other): + """ + Implement less-than-or-equal-to comparison (<=) for Laurent polynomial ideals. + + When testing ideal containment, it is not necessary to saturate + the smaller ideal. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 3) + sage: I1 = P.ideal([x*y*z+x*y+2*y^2, x+z]) + sage: I3 = P.ideal([x*y*z+x*y+2*y^2+x+z, x+z, y]) + sage: I1 <= I3 + True + """ + if not isinstance(other, Ideal_generic): + raise NotImplementedError + if all(f in other.gens() for f in self.gens()): # Early abort + return True + return self.polynomial_ideal(saturate=False) <= other.polynomial_ideal() + + def __ge__(self, other): + """ + Implement greater-than-or-equal-to comparison (>=) for Laurent polynomial ideals. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 3) + sage: I1 = P.ideal([x*y*z+x*y+2*y^2, x+z]) + sage: I3 = P.ideal([x*y*z+x*y+2*y^2+x+z, x+z, y]) + sage: I3 >= I1 + True + """ + if not isinstance(other, Ideal_generic): + raise NotImplementedError + if all(f in self.gens() for f in other.gens()): # Early abort + return True + return other.polynomial_ideal(saturate=False) <= self.polynomial_ideal() + + def __lt__(self, other): + """ + Implement less-than comparison (<) for Laurent polynomial ideals. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 3) + sage: I1 = P.ideal([x*y*z+x*y+2*y^2, x+z]) + sage: I3 = P.ideal([x*y*z+x*y+2*y^2+x+z, x+z, y]) + sage: I1 < I3 + True + """ + if not isinstance(other, Ideal_generic): + raise NotImplementedError + return (self <= other and not self == other) + + def __gt__(self, other): + """ + Implement greater-than comparison (>) for Laurent polynomial ideals. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 3) + sage: I1 = P.ideal([x*y*z+x*y+2*y^2, x+z]) + sage: I3 = P.ideal([x*y*z+x*y+2*y^2+x+z, x+z, y]) + sage: I3 > I1 + True + """ + if not isinstance(other, Ideal_generic): + raise NotImplementedError + return (other <= self and not self == other) + + def __contains__(self, f): + """ + Implement containment testing (in) for Laurent polynomial ideals. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 2) + sage: I = P.ideal([x^2*y + 3*x*y^2]) + sage: x + 3*y in I + True + """ + if not f or f in self.gens(): + return True + f = self.ring()(f) + g = f.__reduce__()[1][0] + return (g in self.polynomial_ideal()) + + # Operations on ideals + + def change_ring(self, R, hint=None): + """ + Coerce an ideal into a new ring. + + This operation does not forward hints, but a new hint can be + specified manually. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 2) + sage: I = P.ideal([x+y]) + sage: Q. = LaurentPolynomialRing(QQ, 3) + sage: I.change_ring(Q) + Ideal (x + y) of Multivariate Laurent Polynomial Ring in x, y, z over Rational Field + """ + return R.ideal(self.gens(), hint=hint) + + def base_extend(self, F): + """ + Form the base extension of ``self`` to the base ring ``F``. + + This operation forwards hints. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 2) + sage: I = P.ideal([x+y]) + sage: K. = CyclotomicField(3) + sage: I.base_extend(K) + Ideal (x + y) of Multivariate Laurent Polynomial Ring in x, y over Cyclotomic Field of order 3 and degree 2 + """ + ring = self.ring() + return self.change_ring(ring.change_ring(F), hint=self._hint) + + def apply_map(self, f, new_ring=None, new_base_ring=None, apply_to_hint=None): + """ + Return the new ideal obtained by applying ``f`` to each generator. + + By default, this does not forward hints. To do so, set ``apply_to_hint`` + to specify a function to apply to generators of ``hint``. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 2) + sage: I = P.ideal([x+1, y-1]) + sage: I.apply_map(lambda z: z+2) + Ideal (x + 3, y + 1) of Multivariate Laurent Polynomial Ring in x, y over Rational Field + """ + ring = self.ring() + if new_ring is not None: + R = new_ring + elif new_base_ring is not None: + R = R.change_ring(new_base_ring) + else: + R = ring + if apply_to_hint: + hint = self._poly_ring.ideal([apply_to_hint(x) for x in self._hint.gens()]) + else: + hint = None + return R.ideal(tuple(f(x) for x in self.gens()), hint=hint) + + def apply_coeff_map(self, f, new_base_ring=None, forward_hint=True): + """ + Apply a function to coefficients. + + This operation forwards hints by default. + + EXAMPLES:: + + sage: K. = CyclotomicField(3) + sage: P. = LaurentPolynomialRing(K, 2) + sage: I = P.ideal([x+z, y-z]) + sage: h = K.hom([z^2]) + sage: I.apply_coeff_map(h) + Ideal (x - z - 1, y + z + 1) of Multivariate Laurent Polynomial Ring in x, y over Cyclotomic Field of order 3 and degree 2 + """ + ring = self.ring() + if new_base_ring is None: + R = ring + else: + R = R.change_ring(new_base_ring) + if forward_hint: + apply_to_hint = lambda x,f=f: x.map_coefficients(f) + else: + apply_to_hint = None + return self.apply_map(lambda x,f=f: + x.map_coefficients(f, new_base_ring=new_base_ring), + new_ring=R, apply_to_hint=apply_to_hint) + + def toric_coordinate_change(self, M, forward_hint=True): + """ + Compute the toric change of coordinates defined by the integer matrix ``M``. + + This operation forwards hints by default. + + EXAMPLES:: + + sage: K. = CyclotomicField(3) + sage: P. = LaurentPolynomialRing(K, 2) + sage: I = P.ideal([x+1, y-1]) + sage: M = Matrix([[2,1],[1,-3]]) + sage: I.toric_coordinate_change(M) + Ideal (x^2*y + 1, -1 + x*y^-3) of Multivariate Laurent Polynomial Ring in x, y over Cyclotomic Field of order 3 and degree 2 + """ + if forward_hint: + R = self.ring() + apply_to_hint = lambda x, M=M, R=R: R(x).toric_coordinate_change(M).__reduce__()[1][0] + else: + apply_to_hint = None + return self.apply_map(lambda x, M=M: x.toric_coordinate_change(M), + apply_to_hint=apply_to_hint) + + def __add__(self, other): + """ + Return the sum of two ideals in the same ring. + + Currently this operation does not support coercion. + + This operation forwards hints. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 2) + sage: I = P.ideal([x+y]) + sage: J = P.ideal([y+1]) + sage: (I+J).groebner_basis() + (x - 1, y + 1) + """ + ring = self.ring() + ring2 = other.ring() + if ring != ring2: + return ValueError("Ambient rings are not equal") + hint = self._hint + if hint.is_zero(): + hint = other._hint + elif not other._hint.is_zero(): + hint += other._hint + return ring.ideal(self.gens() + other.gens(), hint=hint) + + def normalize_gens(self): + """ + Redefine the ideal with a normalized set of generators. + + For two ideals returned by this function, equality testing can be done + by comparing generators. + + This operation forwards hints. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 2) + sage: I = P.ideal([~x+y]) + sage: J = P.ideal([y+1]) + sage: I+J + Ideal (y + x^-1, y + 1) of Multivariate Laurent Polynomial Ring in x, y over Rational Field + sage: (I+J).normalize_gens() + Ideal (x - 1, y + 1) of Multivariate Laurent Polynomial Ring in x, y over Rational Field + """ + return self.ring().ideal(self.groebner_basis(), hint=self._hint) + + # Structural queries and properties + + def polynomial_ideal(self, saturate=True): + """ + Return the associated polynomial ideal. + + By default, the ideal is saturated with respect to the product of the + polynomial ring generators; this is necessary for testing equality and inclusion. + As saturation can be quite time-consuming, it can be disabled by setting + ``saturate=False``; however, the result will then depend not just on the original ideal + but also on the choice of generators. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 2) + sage: I = P.ideal([x^2*y + 3*x*y^2]) + sage: I.polynomial_ideal() + Ideal (x + 3*y) of Multivariate Polynomial Ring in x, y over Rational Field + """ + if self._poly_ideal is not None and (self._saturated or not saturate): + return self._poly_ideal + P = self.ring() + Q = self._poly_ring + gens = self.gens() + if len(gens) == 0: + I = Q.ideal([]) + self._poly_ideal = I + self._hint = I + self._saturated = True + return I + l2 = [f.__reduce__()[1][0] for f in gens] + hint = self._hint + l2 += list(hint.groebner_basis()) + I = Q.ideal(l2) + if not saturate: + self._poly_ideal = I + self._hint = I + return Q.ideal(l2) + n = P.ngens() + I = I.saturation(Q.ideal([Q.monomial(*((1,) * n))]))[0] + self._poly_ideal = I + self._hint = I + self._saturated = True + return I + + def groebner_basis(self, saturate=True): + """ + Return the reduced Groebner basis for the specified term order. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 2) + sage: I = P.ideal([x+y]) + sage: J = P.ideal([y+1]) + sage: (I+J).groebner_basis() + (x - 1, y + 1) + """ + l = self.polynomial_ideal(saturate=saturate).groebner_basis() + return tuple(self.ring()(x) for x in l) + + def is_one(self): + """ + Determine whether or not ``self`` is the unit ideal. + + This requires saturation of the polynomial ideal. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 2) + sage: I = P.ideal([~x + ~y - 1, x + y]) + sage: I.is_one() + True + """ + return self.polynomial_ideal().is_one() + + def is_binomial(self, groebner_basis=False): + """ + Determine whether every generator of ``self`` is a binomial. + + If ``groebner_basis`` is True, this becomes intrinsic (for a choice of + term order). + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 2) + sage: I = P.ideal([x + y]) + sage: I.is_binomial() + True + """ + if groebner_basis: + l = self.groebner_basis() + else: + l = self.gens() + return all(not f or f.number_of_terms() == 2 for f in l) + + def associated_primes(self): + """ + Return associated primes of this ideal. + + These are computed from the polynomial ideal, but it is not necessary to + saturate. Instead, we omit primes containing any polynomial generator. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 3) + sage: p = z^2 + 1; q = z^3 + 2 + sage: I = P.ideal((p*q^2, y-z^2)) + sage: I.associated_primes() + (Ideal (y + 1, z^2 + 1) of Multivariate Laurent Polynomial Ring in x, y, z over Rational Field, + Ideal (z^2 - y, y*z + 2, y^2 + 2*z) of Multivariate Laurent Polynomial Ring in x, y, z over Rational Field) + """ + l = self.polynomial_ideal(saturate=False).associated_primes() + l2 = [self.ring().ideal(I.gens(), hint=I) for I in l] + return tuple(I for I in l2 if not I.is_one()) + + def minimal_associated_primes(self, saturate=False): + """ + Return minimal associated primes of this ideal. + + These are computed from the polynomial ideal, but it is not necessary to + saturate. Instead, we omit primes containing any polynomial generator. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 3) + sage: p = z^2 + 1; q = z^3 + 2 + sage: I = P.ideal((p*q^2, y-z^2)) + sage: I.minimal_associated_primes() + (Ideal (z^2 + 1, -z^2 + y) of Multivariate Laurent Polynomial Ring in x, y, z over Rational Field, + Ideal (z^3 + 2, -z^2 + y) of Multivariate Laurent Polynomial Ring in x, y, z over Rational Field) + """ + l = self.polynomial_ideal(saturate=saturate).minimal_associated_primes() + l2 = [self.ring().ideal(I.gens(), hint=I) for I in l] + return tuple(I for I in l2 if not I.is_one()) + + def radical(self): + """ + Return the radical of this ideal. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 3) + sage: I = P.ideal(((x+1)^2, (y+1)^3, ((x+1)*z)^4 + (y+1)^3 + 10*(x+1)^2)) + sage: I.radical() + Ideal (y + 1, x + 1) of Multivariate Laurent Polynomial Ring in x, y, z over Rational Field + """ + J = self.polynomial_ideal().radical() + return self.ring().ideal(J.gens()) + + def dimension(self): + """ + Return the dimension of this ideal. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ, 3) + sage: I = P.ideal(((x+1)^2, (y+1)^3, ((x+1)*z)^4 + (y+1)^3 + 10*(x+1)^2)) + sage: I.dimension() + 1 + """ + return self.polynomial_ideal().dimension() + diff --git a/src/sage/rings/polynomial/laurent_polynomial_ring.py b/src/sage/rings/polynomial/laurent_polynomial_ring.py index 207c63ee724..348f48e99e2 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_ring.py +++ b/src/sage/rings/polynomial/laurent_polynomial_ring.py @@ -51,6 +51,7 @@ from sage.rings.polynomial.laurent_polynomial import LaurentPolynomial_mpair, LaurentPolynomial_univariate from sage.rings.ring import CommutativeRing +import sage.rings.polynomial.laurent_polynomial_ideal as lp_ideal def is_LaurentPolynomialRing(R): """ @@ -689,7 +690,7 @@ def _ideal_class_(self, n=0): ... NotImplementedError """ - # One may eventually want ideals in these guys. + # One may eventually want ideal classes in these guys. raise NotImplementedError def ideal(self, *args, **kwds): @@ -697,9 +698,7 @@ def ideal(self, *args, **kwds): EXAMPLES:: sage: LaurentPolynomialRing(QQ,2,'x').ideal([1]) - Traceback (most recent call last): - ... - NotImplementedError + Ideal (1) of Multivariate Laurent Polynomial Ring in x0, x1 over Rational Field TESTS: @@ -709,11 +708,9 @@ def ideal(self, *args, **kwds): sage: P. = PolynomialRing(R) sage: p = x-t sage: p.content_ideal() # indirect doctest - Traceback (most recent call last): - ... - NotImplementedError + Ideal (-t, 1) of Univariate Laurent Polynomial Ring in t over Integer Ring """ - raise NotImplementedError + return lp_ideal.LaurentPolynomialIdeal(self, *args, **kwds) def _is_valid_homomorphism_(self, codomain, im_gens, base_map=None): """ @@ -840,12 +837,22 @@ def change_ring(self, base_ring=None, names=None, sparse=False, order=None): sage: R = LaurentPolynomialRing(QQ,2,'x') sage: R.change_ring(ZZ) Multivariate Laurent Polynomial Ring in x0, x1 over Integer Ring + + Check that the distinction between a univariate ring and a multivariate ring with one + generator is preserved:: + + sage: P. = LaurentPolynomialRing(QQ, 1) + sage: P + Multivariate Laurent Polynomial Ring in x over Rational Field + sage: K. = CyclotomicField(4) + sage: P.change_ring(K) + Multivariate Laurent Polynomial Ring in x over Cyclotomic Field of order 4 and degree 2 """ if base_ring is None: base_ring = self.base_ring() if names is None: names = self.variable_names() - if self._n == 1: + if isinstance(self, LaurentPolynomialRing_univariate): return LaurentPolynomialRing(base_ring, names[0], sparse = sparse) if order is None: diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index b7f6ce35cd7..12e42d1dd77 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -7930,7 +7930,7 @@ cdef class Polynomial(CommutativeAlgebraElement): # integer c = self.content_ideal().gen() self = self//c - except (AttributeError, NotImplementedError): + except (AttributeError, NotImplementedError, TypeError): pass return self._roots_from_factorization(self.factor(), multiplicities) else: From f58a6f73f160b8ff5a9274e15807fef2d5d8db65 Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Wed, 22 Jul 2020 13:16:13 -0700 Subject: [PATCH 181/217] Fix apply_map and apply_coeff_map --- src/sage/rings/polynomial/laurent_polynomial_ideal.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial_ideal.py b/src/sage/rings/polynomial/laurent_polynomial_ideal.py index 3bb73232e6b..6e48615d12c 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_ideal.py +++ b/src/sage/rings/polynomial/laurent_polynomial_ideal.py @@ -302,12 +302,15 @@ def apply_map(self, f, new_ring=None, new_base_ring=None, apply_to_hint=None): sage: I = P.ideal([x+1, y-1]) sage: I.apply_map(lambda z: z+2) Ideal (x + 3, y + 1) of Multivariate Laurent Polynomial Ring in x, y over Rational Field + sage: K. = CyclotomicField(4) + sage: I.apply_map(lambda z: z+2, new_base_ring=K) + Ideal (x + 3, y + 1) of Multivariate Laurent Polynomial Ring in x, y over Cyclotomic Field of order 4 and degree 2 """ ring = self.ring() if new_ring is not None: R = new_ring elif new_base_ring is not None: - R = R.change_ring(new_base_ring) + R = ring.change_ring(new_base_ring) else: R = ring if apply_to_hint: @@ -330,12 +333,16 @@ def apply_coeff_map(self, f, new_base_ring=None, forward_hint=True): sage: h = K.hom([z^2]) sage: I.apply_coeff_map(h) Ideal (x - z - 1, y + z + 1) of Multivariate Laurent Polynomial Ring in x, y over Cyclotomic Field of order 3 and degree 2 + sage: K1. = CyclotomicField(12) + sage: h1 = K.hom([z1^4]) + sage: I.apply_coeff_map(h1, new_base_ring=K1) + Ideal (x + z1^2 - 1, y - z1^2 + 1) of Multivariate Laurent Polynomial Ring in x, y over Cyclotomic Field of order 12 and degree 4 """ ring = self.ring() if new_base_ring is None: R = ring else: - R = R.change_ring(new_base_ring) + R = ring.change_ring(new_base_ring) if forward_hint: apply_to_hint = lambda x,f=f: x.map_coefficients(f) else: From 20082d5132efccf048686b596b24700465dd2d57 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 22 Jul 2020 15:33:13 -0700 Subject: [PATCH 182/217] sage.geometry.polyhedron.parent.Polyhedra: Generalize the factory --- src/sage/geometry/polyhedron/parent.py | 31 ++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/sage/geometry/polyhedron/parent.py b/src/sage/geometry/polyhedron/parent.py index 8b2eb3a08f6..da1e938c4b6 100644 --- a/src/sage/geometry/polyhedron/parent.py +++ b/src/sage/geometry/polyhedron/parent.py @@ -13,16 +13,19 @@ from sage.structure.parent import Parent from sage.structure.element import get_coercion_model from sage.structure.unique_representation import UniqueRepresentation -from sage.modules.free_module import is_FreeModule +from sage.modules.free_module import FreeModule, is_FreeModule from sage.misc.cachefunc import cached_method, cached_function from sage.rings.all import ZZ, QQ, RDF, CommutativeRing from sage.categories.fields import Fields +from sage.categories.rings import Rings + from sage.geometry.polyhedron.base import is_Polyhedron from .representation import Inequality, Equation, Vertex, Ray, Line -def Polyhedra(base_ring, ambient_dim, backend=None): +def Polyhedra(ambient_space_or_base_ring=None, ambient_dim=None, backend=None, *, + ambient_space=None, base_ring=None): r""" Construct a suitable parent class for polyhedra @@ -33,6 +36,8 @@ def Polyhedra(base_ring, ambient_dim, backend=None): - ``ambient_dim`` -- integer. The ambient space dimension. + - ``ambient_space`` -- A free module. + - ``backend`` -- string. The name of the backend for computations. There are several backends implemented: @@ -72,6 +77,16 @@ def Polyhedra(base_ring, ambient_dim, backend=None): sage: Polyhedra(ZZ, 3, backend='cdd') Polyhedra in QQ^3 + Using a more general form of the constructor:: + + sage: V = VectorSpace(QQ, 3) + sage: Polyhedra(V) is Polyhedra(QQ, 3) + True + sage: Polyhedra(V, backend='field') is Polyhedra(QQ, 3, 'field') + True + sage: Polyhedra(backend='field', ambient_space=V) is Polyhedra(QQ, 3, 'field') + True + TESTS:: sage: Polyhedra(RR, 3, backend='field') @@ -88,6 +103,18 @@ def Polyhedra(base_ring, ambient_dim, backend=None): ValueError: invalid base ring: Number Field in I with defining polynomial x^2 + 1 with I = 1*I cannot be coerced to a real field """ + if ambient_space_or_base_ring is not None: + if ambient_space_or_base_ring in Rings(): + base_ring = ambient_space_or_base_ring + else: + ambient_space = ambient_space_or_base_ring + if ambient_space is not None: + if base_ring is None: + base_ring = ambient_space.base_ring() + if ambient_dim is None: + ambient_dim = ambient_space.dimension() + if ambient_space is not FreeModule(base_ring, ambient_dim): + raise NotImplementedError('ambient_space must be standard free module') if backend is None: if base_ring is ZZ or base_ring is QQ: backend = 'ppl' From 11448a68499ee087ad7cac6e0c979cdf9f01a370 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 20 Mar 2020 12:24:37 -0400 Subject: [PATCH 183/217] Update R to 3.6.3, add upstream_url --- build/pkgs/r/checksums.ini | 7 ++++--- build/pkgs/r/package-version.txt | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/build/pkgs/r/checksums.ini b/build/pkgs/r/checksums.ini index b97750a51de..69a1a7059dc 100644 --- a/build/pkgs/r/checksums.ini +++ b/build/pkgs/r/checksums.ini @@ -1,4 +1,5 @@ tarball=R-VERSION.tar.gz -sha1=8eda2af51d63877fcc6674274b6801af605173c5 -md5=90d23d138cee26d275da14b58296e521 -cksum=1222866983 +sha1=d2383dabc0d6c70f8a0171a0fb1bfdc31ddb5b52 +md5=506c9576ba33e1262ad5b5624db9d96a +cksum=2403187565 +upstream_url=https://cran.r-project.org/src/base/R-3/R-VERSION.tar.gz diff --git a/build/pkgs/r/package-version.txt b/build/pkgs/r/package-version.txt index e4097539c1a..4a788a01dad 100644 --- a/build/pkgs/r/package-version.txt +++ b/build/pkgs/r/package-version.txt @@ -1 +1 @@ -3.6.2.p0 +3.6.3 From 9d667e828a60c0782c60876d8b470d20b035d1c9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 23 Jul 2020 11:50:33 -0700 Subject: [PATCH 184/217] build/pkgs/r/spkg-install.in: Set rpath --- build/pkgs/r/spkg-install.in | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build/pkgs/r/spkg-install.in b/build/pkgs/r/spkg-install.in index d77db37688d..905fc2a6150 100644 --- a/build/pkgs/r/spkg-install.in +++ b/build/pkgs/r/spkg-install.in @@ -100,6 +100,14 @@ fi # See patches/R.sh.patch export SAGE_BUILDING_R=yes +R_HOME="$SAGE_LOCAL"/lib/R +# Set LDFLAGS as it is done in sage-env for $SAGE_LOCAL/lib +LDFLAGS="-L$R_HOME/lib -Wl,-rpath,$R_HOME/lib $LDFLAGS" +if [ "$UNAME" = "Linux" ]; then + LDFLAGS="-Wl,-rpath-link,$R_HOME/lib $LDFLAGS" +fi +export LDFLAGS + config() { sdh_configure --enable-R-shlib --with-recommended-packages \ --with-readline=yes --with-x=$XSUPPORT \ From f98a47b9bc2302325a73ad1774dab26dc8a185d5 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Thu, 23 Jul 2020 21:32:38 +0200 Subject: [PATCH 185/217] Trac #30191: unused ScalarField import removed --- src/sage/manifolds/differentiable/diff_form_module.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/manifolds/differentiable/diff_form_module.py b/src/sage/manifolds/differentiable/diff_form_module.py index 0e03b18a75d..e2292494f9a 100644 --- a/src/sage/manifolds/differentiable/diff_form_module.py +++ b/src/sage/manifolds/differentiable/diff_form_module.py @@ -40,7 +40,6 @@ from sage.categories.modules import Modules from sage.symbolic.ring import ZZ from sage.tensor.modules.ext_pow_free_module import ExtPowerDualFreeModule -from sage.manifolds.scalarfield import ScalarField from sage.manifolds.differentiable.diff_form import DiffForm, DiffFormParal from sage.manifolds.differentiable.tensorfield import TensorField from sage.manifolds.differentiable.tensorfield_paral import TensorFieldParal From 8c13ac7bef0b07070f761035064c6920384ca46b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 23 Jul 2020 15:47:58 -0700 Subject: [PATCH 186/217] tox.ini: Make manylinux default to manylinux-2014, add documentation --- tox.ini | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index fd52a97d125..bc0607b8996 100644 --- a/tox.ini +++ b/tox.ini @@ -266,12 +266,20 @@ setenv = linuxmint: ARCH_IMAGE_SUFFIX=-amd64 linuxmint-i386: ARCH_IMAGE_SUFFIX=-i386 # - # manylinux + # manylinux. # https://github.com/pypa/manylinux # + # There are manylinux-1, manylinux-2010, and manylinux-2014. + # manylinux-1 is too old - it only has python2.4, which is not supported by + # sage_bootstrap. + # Our default is manylinux-2014. + # + # Default arch is x86_64. Use -i686 for 32-bit build. manylinux-2014 supports more archs. + # manylinux: SYSTEM=fedora manylinux: IGNORE_MISSING_SYSTEM_PACKAGES=yes manylinux: BOOTSTRAP=./bootstrap -D + manylinux: BASE_IMAGE=quay.io/pypa/manylinux2014 manylinux-1: BASE_IMAGE=quay.io/pypa/manylinux1 manylinux-2010: BASE_IMAGE=quay.io/pypa/manylinux2010 manylinux-2014: BASE_IMAGE=quay.io/pypa/manylinux2014 From 4c670d38765d730a4e54e2bc502d92aecc687b5e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 23 Jul 2020 17:03:00 -0700 Subject: [PATCH 187/217] build/pkgs/xz/spkg-configure.m4: Slightly lower the xz version bound set in #26286, for manylinux-2010 --- build/pkgs/xz/spkg-configure.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/pkgs/xz/spkg-configure.m4 b/build/pkgs/xz/spkg-configure.m4 index 820b5187802..ec6c4a9a9bb 100644 --- a/build/pkgs/xz/spkg-configure.m4 +++ b/build/pkgs/xz/spkg-configure.m4 @@ -2,11 +2,11 @@ SAGE_SPKG_CONFIGURE([xz], [ AC_CHECK_LIB([lzma], [lzma_raw_decoder], [lzma_cv_liblzma=yes], [lzma_cv_liblzma=no]) AC_CHECK_HEADER([lzma.h], [lzma_cv_lzma_h=yes], [lzma_cv_lzma_h=no]) if test "$lzma_cv_liblzma" = "yes" && test "$lzma_cv_lzma_h" = "yes"; then - AC_CACHE_CHECK([for xz >= 5.0.0], [ac_cv_path_XZ], [ + AC_CACHE_CHECK([for xz >= 4.999.0], [ac_cv_path_XZ], [ AC_PATH_PROGS_FEATURE_CHECK([XZ], [xz], [ xz_version=`$ac_path_XZ --version 2>&1 | cut -d' ' -f4 | $SED -n 1p` AS_IF([test -n "$xz_version"], [ - AX_COMPARE_VERSION([$xz_version], [ge], [5.0.0], [ + AX_COMPARE_VERSION([$xz_version], [ge], [4.999.0], [ ac_cv_path_XZ="$ac_path_XZ" ]) ]) From 2f431648cad8a3b649a94bd6b7d9ef2e70ad3f4f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 23 Jul 2020 17:03:38 -0700 Subject: [PATCH 188/217] tox.ini [manylinux]: Use --with-system-python3=force --- tox.ini | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tox.ini b/tox.ini index bc0607b8996..b8eced3610f 100644 --- a/tox.ini +++ b/tox.ini @@ -329,11 +329,11 @@ setenv = # Must manually download and install from https://www.python.org/ftp/python/3.7.7/python-3.7.7-macosx10.9.pkg macos-python3_pythonorg: CONFIG_CONFIGURE_ARGS_1=--with-python=3 PYTHON3=/Library/Frameworks/Python.framework/Versions/3.7/bin/python3 # https://github.com/pypa/manylinux - manylinux: CONFIG_CONFIGURE_ARGS_1= PYTHON3=/opt/python/cp38-cp38/bin/python3 - manylinux-python3.6: CONFIG_CONFIGURE_ARGS_1= PYTHON3=/opt/python/cp36-cp36m/bin/python3 - manylinux-python3.7: CONFIG_CONFIGURE_ARGS_1= PYTHON3=/opt/python/cp37-cp37m/bin/python3 - manylinux-python3.8: CONFIG_CONFIGURE_ARGS_1= PYTHON3=/opt/python/cp38-cp38/bin/python3 - manylinux-python3.9: CONFIG_CONFIGURE_ARGS_1= PYTHON3=/opt/python/cp39-cp39/bin/python3 + manylinux: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force PYTHON3=/opt/python/cp38-cp38/bin/python3 + manylinux-python3.6: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force PYTHON3=/opt/python/cp36-cp36m/bin/python3 + manylinux-python3.7: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force PYTHON3=/opt/python/cp37-cp37m/bin/python3 + manylinux-python3.8: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force PYTHON3=/opt/python/cp38-cp38/bin/python3 + manylinux-python3.9: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force PYTHON3=/opt/python/cp39-cp39/bin/python3 # # - toolchain # From 2747c379b26310253b4a5996b9dd6e74858d3323 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 23 Jul 2020 18:23:18 -0700 Subject: [PATCH 189/217] tox.ini [manylinux]: Patch the downloaded configure file so that system xz is accepted --- build/bin/write-dockerfile.sh | 2 +- tox.ini | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/build/bin/write-dockerfile.sh b/build/bin/write-dockerfile.sh index 966ddd9f182..7fffabe17c3 100755 --- a/build/bin/write-dockerfile.sh +++ b/build/bin/write-dockerfile.sh @@ -163,7 +163,7 @@ ADD src/bin src/bin ADD m4 ./m4 ADD build ./build ARG BOOTSTRAP=./bootstrap -$RUN \${BOOTSTRAP} +$RUN sh -x -c "\${BOOTSTRAP}" FROM bootstrapped as configured #:configuring: diff --git a/tox.ini b/tox.ini index b8eced3610f..c2774bd2ca0 100644 --- a/tox.ini +++ b/tox.ini @@ -278,7 +278,10 @@ setenv = # manylinux: SYSTEM=fedora manylinux: IGNORE_MISSING_SYSTEM_PACKAGES=yes - manylinux: BOOTSTRAP=./bootstrap -D + # temporarily because we do not have autotools, we have to patch the downloaded + # configure tarball. The sed command can be removed once the relaxed version check + # in build/pkgs/xz/spkg-configure.m4 has been included in a release. + manylinux: BOOTSTRAP=./bootstrap -D && sed -i.bak s/5[.]0[.]0/4.999.0/ configure manylinux: BASE_IMAGE=quay.io/pypa/manylinux2014 manylinux-1: BASE_IMAGE=quay.io/pypa/manylinux1 manylinux-2010: BASE_IMAGE=quay.io/pypa/manylinux2010 From c34e4810fa3c8eea494ec67756987a7585e34a1e Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Fri, 24 Jul 2020 09:29:18 +0200 Subject: [PATCH 190/217] Trac #30191: remove in ZZ check --- .../manifolds/differentiable/automorphismfield_group.py | 3 +-- src/sage/manifolds/differentiable/diff_form_module.py | 5 ++--- src/sage/manifolds/differentiable/mixed_form_algebra.py | 6 +++--- src/sage/manifolds/differentiable/multivector_module.py | 5 ++--- src/sage/manifolds/differentiable/tensorfield_module.py | 5 ++--- src/sage/manifolds/differentiable/vectorfield_module.py | 5 ++--- src/sage/manifolds/section_module.py | 5 ++--- 7 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/sage/manifolds/differentiable/automorphismfield_group.py b/src/sage/manifolds/differentiable/automorphismfield_group.py index bd5b5f6c80d..1ab4458232f 100644 --- a/src/sage/manifolds/differentiable/automorphismfield_group.py +++ b/src/sage/manifolds/differentiable/automorphismfield_group.py @@ -41,7 +41,6 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent -from sage.symbolic.ring import ZZ from sage.categories.groups import Groups from sage.misc.cachefunc import cached_method from sage.tensor.modules.free_module_linear_group import FreeModuleLinearGroup @@ -209,7 +208,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, a = (x^2 + 1) d/dx*dx + (y^2 + 1) d/dy*dy """ - if comp in ZZ and comp == 1: + if comp == 1: return self.one() if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + diff --git a/src/sage/manifolds/differentiable/diff_form_module.py b/src/sage/manifolds/differentiable/diff_form_module.py index e2292494f9a..97f34e4dcd1 100644 --- a/src/sage/manifolds/differentiable/diff_form_module.py +++ b/src/sage/manifolds/differentiable/diff_form_module.py @@ -38,7 +38,6 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent from sage.categories.modules import Modules -from sage.symbolic.ring import ZZ from sage.tensor.modules.ext_pow_free_module import ExtPowerDualFreeModule from sage.manifolds.differentiable.diff_form import DiffForm, DiffFormParal from sage.manifolds.differentiable.tensorfield import TensorField @@ -331,7 +330,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if comp in ZZ and comp == 0: + if comp == 0: return self.zero() if isinstance(comp, (DiffForm, DiffFormParal)): # coercion by domain restriction @@ -800,7 +799,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, False """ - if comp in ZZ and comp == 0: + if comp == 0: return self.zero() if isinstance(comp, (DiffForm, DiffFormParal)): # coercion by domain restriction diff --git a/src/sage/manifolds/differentiable/mixed_form_algebra.py b/src/sage/manifolds/differentiable/mixed_form_algebra.py index f8e5a524781..87c36ccd1fc 100644 --- a/src/sage/manifolds/differentiable/mixed_form_algebra.py +++ b/src/sage/manifolds/differentiable/mixed_form_algebra.py @@ -27,7 +27,7 @@ from sage.structure.parent import Parent from sage.categories.graded_algebras import GradedAlgebras from sage.structure.unique_representation import UniqueRepresentation -from sage.symbolic.ring import ZZ, SR +from sage.symbolic.ring import SR from sage.manifolds.differentiable.mixed_form import MixedForm class MixedFormAlgebra(Parent, UniqueRepresentation): @@ -193,9 +193,9 @@ def _element_constructor_(self, comp=None, name=None, latex_name=None): res = self.element_class(self, name=name, latex_name=latex_name) if comp is None: return res - elif comp in ZZ and comp == 0: + elif comp == 0: return self.zero() - elif comp in ZZ and comp == 1: + elif comp == 1: return self.one() elif isinstance(comp, (tuple, list)): if len(comp) != self._max_deg + 1: diff --git a/src/sage/manifolds/differentiable/multivector_module.py b/src/sage/manifolds/differentiable/multivector_module.py index 0e13e81ec80..58d8b25f732 100644 --- a/src/sage/manifolds/differentiable/multivector_module.py +++ b/src/sage/manifolds/differentiable/multivector_module.py @@ -36,7 +36,6 @@ from sage.misc.cachefunc import cached_method from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent -from sage.symbolic.ring import ZZ from sage.categories.modules import Modules from sage.tensor.modules.ext_pow_free_module import ExtPowerFreeModule from sage.manifolds.differentiable.multivectorfield import ( @@ -301,7 +300,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if comp in ZZ and comp == 0: + if comp == 0: return self.zero() if isinstance(comp, (MultivectorField, MultivectorFieldParal)): # coercion by domain restriction @@ -725,7 +724,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if comp in ZZ and comp == 0: + if comp == 0: return self.zero() if isinstance(comp, (MultivectorField, MultivectorFieldParal)): # coercion by domain restriction diff --git a/src/sage/manifolds/differentiable/tensorfield_module.py b/src/sage/manifolds/differentiable/tensorfield_module.py index 95954bc3e0e..168a1fdde81 100644 --- a/src/sage/manifolds/differentiable/tensorfield_module.py +++ b/src/sage/manifolds/differentiable/tensorfield_module.py @@ -41,7 +41,6 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent from sage.categories.modules import Modules -from sage.symbolic.ring import ZZ from sage.tensor.modules.tensor_free_module import TensorFreeModule from sage.manifolds.differentiable.tensorfield import TensorField from sage.manifolds.differentiable.tensorfield_paral import TensorFieldParal @@ -310,7 +309,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if comp in ZZ and comp == 0: + if comp == 0: return self.zero() if isinstance(comp, DiffForm): # coercion of a p-form to a type-(0,p) tensor field: @@ -795,7 +794,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if comp in ZZ and comp == 0: + if comp == 0: return self.zero() if isinstance(comp, DiffFormParal): # coercion of a p-form to a type-(0,p) tensor field: diff --git a/src/sage/manifolds/differentiable/vectorfield_module.py b/src/sage/manifolds/differentiable/vectorfield_module.py index 3f22b3da98f..fac288eff2f 100644 --- a/src/sage/manifolds/differentiable/vectorfield_module.py +++ b/src/sage/manifolds/differentiable/vectorfield_module.py @@ -43,7 +43,6 @@ from sage.categories.modules import Modules from sage.misc.cachefunc import cached_method from sage.rings.integer import Integer -from sage.rings.integer_ring import ZZ from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule from sage.manifolds.differentiable.vectorfield import (VectorField, VectorFieldParal) @@ -269,7 +268,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if comp in ZZ and comp == 0: + if comp == 0: return self.zero() if isinstance(comp, VectorField): if (self._domain.is_subset(comp._domain) @@ -1472,7 +1471,7 @@ def _element_constructor_(self, comp=[], basis=None, name=None, True """ - if comp in ZZ and comp == 0: + if comp == 0: return self.zero() if isinstance(comp, VectorField): if (self._domain.is_subset(comp._domain) diff --git a/src/sage/manifolds/section_module.py b/src/sage/manifolds/section_module.py index 962ce48e130..4cce43a8aa9 100644 --- a/src/sage/manifolds/section_module.py +++ b/src/sage/manifolds/section_module.py @@ -32,7 +32,6 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent from sage.misc.cachefunc import cached_method -from sage.symbolic.ring import ZZ from sage.categories.modules import Modules from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule from sage.manifolds.section import Section, TrivialSection @@ -222,7 +221,7 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if comp in ZZ and comp == 0: + if comp == 0: return self.zero() if isinstance(comp, Section): if self._domain.is_subset(comp._domain): @@ -641,7 +640,7 @@ def _element_constructor_(self, comp=[], basis=None, name=None, True """ - if comp in ZZ and comp == 0: + if comp == 0: return self.zero() if isinstance(comp, Section): if self._domain.is_subset(comp._domain): From 14da64d27c43ad7f3328da208ee942a54b889b5b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 24 Jul 2020 08:38:51 -0700 Subject: [PATCH 191/217] tox.ini [manylinux]: Do not use --with-system-python3=force for -minimal --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index c2774bd2ca0..5ef93c2c9d2 100644 --- a/tox.ini +++ b/tox.ini @@ -332,7 +332,7 @@ setenv = # Must manually download and install from https://www.python.org/ftp/python/3.7.7/python-3.7.7-macosx10.9.pkg macos-python3_pythonorg: CONFIG_CONFIGURE_ARGS_1=--with-python=3 PYTHON3=/Library/Frameworks/Python.framework/Versions/3.7/bin/python3 # https://github.com/pypa/manylinux - manylinux: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force PYTHON3=/opt/python/cp38-cp38/bin/python3 + manylinux-standard: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force PYTHON3=/opt/python/cp38-cp38/bin/python3 manylinux-python3.6: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force PYTHON3=/opt/python/cp36-cp36m/bin/python3 manylinux-python3.7: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force PYTHON3=/opt/python/cp37-cp37m/bin/python3 manylinux-python3.8: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force PYTHON3=/opt/python/cp38-cp38/bin/python3 From bb2d7eb3f032bc549760ef9c1373be1d501ed6a1 Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Fri, 24 Jul 2020 15:08:02 -0700 Subject: [PATCH 192/217] Implement _richcmp_ --- .../polynomial/laurent_polynomial_ideal.py | 109 ++++-------------- 1 file changed, 25 insertions(+), 84 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial_ideal.py b/src/sage/rings/polynomial/laurent_polynomial_ideal.py index 6e48615d12c..60709e7e481 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_ideal.py +++ b/src/sage/rings/polynomial/laurent_polynomial_ideal.py @@ -23,6 +23,7 @@ # **************************************************************************** from sage.rings.ideal import Ideal_generic +from sage.structure.richcmp import richcmp, op_EQ, op_NE, op_LT, op_LE, op_GT, op_GE class LaurentPolynomialIdeal( Ideal_generic ): def __init__(self, ring, gens, coerce=True, hint=None): @@ -132,12 +133,13 @@ def hint(self): return self._hint # Comparisons, using the associated polynomial ideal. - def __eq__(self, other): - """ - Implement equality comparison (==) for Laurent polynomial ideals. + def _richcmp_(self, right_r, op): + r""" + Comparison of ``self`` and ``right_r``. - To save time, we check equality of generators before - comparing polynomial ideals. + When testing equality, we first check generators to save time. + + When testing ideal containment, we do not saturate the smaller ideal. EXAMPLES:: @@ -146,96 +148,35 @@ def __eq__(self, other): sage: I2 = P.ideal([x*y*z+x*y+2*y^2+x+z, x+z]) sage: I1 == I2 True - """ - if set(self.gens()) == set(other.gens()): # Early abort - return True - return self.polynomial_ideal() == other.polynomial_ideal() - - def __ne__(self, other): - """ - Implement inequality comparison (!=) for Laurent polynomial ideals. - - EXAMPLES:: - - sage: P. = LaurentPolynomialRing(QQ, 3) - sage: I1 = P.ideal([x*y*z+x*y+2*y^2, x+z]) - sage: I2 = P.ideal([x*y*z+x*y+2*y^2+x+z, x+z]) sage: I1 != I2 False - """ - return not (self == other) - - def __le__(self, other): - """ - Implement less-than-or-equal-to comparison (<=) for Laurent polynomial ideals. - - When testing ideal containment, it is not necessary to saturate - the smaller ideal. - - EXAMPLES:: - - sage: P. = LaurentPolynomialRing(QQ, 3) - sage: I1 = P.ideal([x*y*z+x*y+2*y^2, x+z]) sage: I3 = P.ideal([x*y*z+x*y+2*y^2+x+z, x+z, y]) sage: I1 <= I3 True - """ - if not isinstance(other, Ideal_generic): - raise NotImplementedError - if all(f in other.gens() for f in self.gens()): # Early abort - return True - return self.polynomial_ideal(saturate=False) <= other.polynomial_ideal() - - def __ge__(self, other): - """ - Implement greater-than-or-equal-to comparison (>=) for Laurent polynomial ideals. - - EXAMPLES:: - - sage: P. = LaurentPolynomialRing(QQ, 3) - sage: I1 = P.ideal([x*y*z+x*y+2*y^2, x+z]) - sage: I3 = P.ideal([x*y*z+x*y+2*y^2+x+z, x+z, y]) sage: I3 >= I1 True - """ - if not isinstance(other, Ideal_generic): - raise NotImplementedError - if all(f in self.gens() for f in other.gens()): # Early abort - return True - return other.polynomial_ideal(saturate=False) <= self.polynomial_ideal() - - def __lt__(self, other): - """ - Implement less-than comparison (<) for Laurent polynomial ideals. - - EXAMPLES:: - - sage: P. = LaurentPolynomialRing(QQ, 3) - sage: I1 = P.ideal([x*y*z+x*y+2*y^2, x+z]) - sage: I3 = P.ideal([x*y*z+x*y+2*y^2+x+z, x+z, y]) sage: I1 < I3 True - """ - if not isinstance(other, Ideal_generic): - raise NotImplementedError - return (self <= other and not self == other) - - def __gt__(self, other): - """ - Implement greater-than comparison (>) for Laurent polynomial ideals. - - EXAMPLES:: - - sage: P. = LaurentPolynomialRing(QQ, 3) - sage: I1 = P.ideal([x*y*z+x*y+2*y^2, x+z]) - sage: I3 = P.ideal([x*y*z+x*y+2*y^2+x+z, x+z, y]) sage: I3 > I1 True """ - if not isinstance(other, Ideal_generic): - raise NotImplementedError - return (other <= self and not self == other) - + if op in (op_EQ, op_NE): + if set(self.gens()) == set(right_r.gens()): # Early abort + return (op == op_EQ) + return ((self.polynomial_ideal() == right_r.polynomial_ideal()) == (op == op_EQ)) + elif op == op_LE: + if all(f in right_r.gens() for f in self.gens()): # Early abort + return True + return self.polynomial_ideal(saturate=False) <= right_r.polynomial_ideal() + elif op == op_GE: + return right_r._richcmp_(self, op_LE) + elif op == op_LT: + return self._richcmp_(right_r, op_LE) and self._richcmp_(right_r, op_NE) + elif op == op_GT: + return right_r._richcmp_(self, op_LE) and right_r._richcmp_(self, op_NE) + else: + raise ValueError("invalid comparison") + def __contains__(self, f): """ Implement containment testing (in) for Laurent polynomial ideals. @@ -393,7 +334,7 @@ def __add__(self, other): ring = self.ring() ring2 = other.ring() if ring != ring2: - return ValueError("Ambient rings are not equal") + return ValueError("ambient rings are not equal") hint = self._hint if hint.is_zero(): hint = other._hint From ab7c5ff933880df5fd645fcbc82acb25b667fe88 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 24 Jul 2020 15:25:53 -0700 Subject: [PATCH 193/217] Polyhedra: Handle ambient_space = a free module correctly --- src/sage/geometry/polyhedron/parent.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/sage/geometry/polyhedron/parent.py b/src/sage/geometry/polyhedron/parent.py index da1e938c4b6..e8de9191ddd 100644 --- a/src/sage/geometry/polyhedron/parent.py +++ b/src/sage/geometry/polyhedron/parent.py @@ -18,7 +18,7 @@ from sage.rings.all import ZZ, QQ, RDF, CommutativeRing from sage.categories.fields import Fields from sage.categories.rings import Rings - +from sage.categories.modules import Modules from sage.geometry.polyhedron.base import is_Polyhedron from .representation import Inequality, Equation, Vertex, Ray, Line @@ -87,6 +87,10 @@ def Polyhedra(ambient_space_or_base_ring=None, ambient_dim=None, backend=None, * sage: Polyhedra(backend='field', ambient_space=V) is Polyhedra(QQ, 3, 'field') True + sage: M = FreeModule(ZZ, 2) + sage: Polyhedra(M, backend='ppl') is Polyhedra(ZZ, 2, 'ppl') + True + TESTS:: sage: Polyhedra(RR, 3, backend='field') @@ -109,12 +113,21 @@ def Polyhedra(ambient_space_or_base_ring=None, ambient_dim=None, backend=None, * else: ambient_space = ambient_space_or_base_ring if ambient_space is not None: + if ambient_space not in Modules: + # There is no category of free modules, unfortunately + # (see https://trac.sagemath.org/ticket/30164)... + raise ValueError('ambient_space must be a free module') if base_ring is None: base_ring = ambient_space.base_ring() if ambient_dim is None: - ambient_dim = ambient_space.dimension() + try: + ambient_dim = ambient_space.rank() + except AttributeError: + # ... so we test whether it is free using the existence of + # a rank method + raise ValueError('ambient_space must be a free module') if ambient_space is not FreeModule(base_ring, ambient_dim): - raise NotImplementedError('ambient_space must be standard free module') + raise NotImplementedError('ambient_space must be a standard free module') if backend is None: if base_ring is ZZ or base_ring is QQ: backend = 'ppl' From cd0b81a08da1d5f06a938a749767f609967f999c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 24 Jul 2020 16:31:16 -0700 Subject: [PATCH 194/217] VectorSpaces: Add parent method dimension --- src/sage/categories/vector_spaces.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/sage/categories/vector_spaces.py b/src/sage/categories/vector_spaces.py index 75ae92b54ce..c31f47ead35 100644 --- a/src/sage/categories/vector_spaces.py +++ b/src/sage/categories/vector_spaces.py @@ -147,7 +147,26 @@ def additional_structure(self): return None class ParentMethods: - pass + + def dimension(self): + """ + Return the dimension of this vector space. + + EXAMPLES:: + + sage: M = FreeModule(FiniteField(19), 100) + sage: W = M.submodule([M.gen(50)]) + sage: W.dimension() + 1 + + sage: M = FiniteRankFreeModule(QQ, 3) + sage: M.dimension() + 3 + sage: M.tensor_module(1,2).dimension() + 27 + + """ + return self.rank() class ElementMethods: pass From 00304212a481365319a08ab8e36338994effd9fe Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Fri, 24 Jul 2020 21:30:16 -0700 Subject: [PATCH 195/217] Some updates to new Laurent polynomial functions --- .../rings/polynomial/laurent_polynomial.pxd | 2 +- .../rings/polynomial/laurent_polynomial.pyx | 54 +++++++++++-------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pxd b/src/sage/rings/polynomial/laurent_polynomial.pxd index 33624915549..9f0f45823f9 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pxd +++ b/src/sage/rings/polynomial/laurent_polynomial.pxd @@ -23,7 +23,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): cdef PolyDict _prod cdef _compute_polydict(self) cdef _normalize(self, i=*) - cpdef rescale_vars(self, d, h=*, new_ring=*) + cpdef rescale_vars(self, dict d, h=*, new_ring=*) cpdef toric_coordinate_change(self, M, h=*, new_ring=*) cpdef toric_substitute(self, v, v1, a, h=*, new_ring=*) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index c7132033a24..19f6f479ea9 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -3493,7 +3493,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): ans._poly = root return (True, ans) - cpdef rescale_vars(self, d, h=None, new_ring=None): + cpdef rescale_vars(self, dict d, h=None, new_ring=None): r""" Rescale variables in a Laurent polynomial. @@ -3506,22 +3506,28 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): sage: p = x^2*y + x*y^2 sage: p.rescale_vars({0: 2, 1: 3}) 12*x^2*y + 18*x*y^2 + sage: F = GF(2) + sage: p.rescale_vars({0: 3, 1: 7}, new_ring=L.change_ring(F)) + x^2*y + x*y^2 """ cdef int i + cdef dict df + cdef ETuple v + + df = self.dict() + if h is None: + for v in df: + for i in d: + df[v] *= d[i]**v[i] + else: + for v in df: + for i in d: + df[v] = h(df[v]*d[i]**v[i]) if new_ring is None: P = self.parent() else: P = new_ring - df = self.dict() - df2 = {} - for v in df: - w = df[v] - for i in d: - w *= d[i]**v[i] - if h is not None: - w = h(w) - df2[v] = w - return P(df2) + return P(df) cpdef toric_coordinate_change(self, M, h=None, new_ring=None): r""" @@ -3541,13 +3547,16 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): sage: p.toric_coordinate_change(Matrix([[1,-3],[1,1]]), new_ring=L.change_ring(F)) x^-2*y^2 + x^-3*y """ - cdef n, i, j + cdef int n, i, j + cdef dict d, d2 + cdef ETuple v, t + if new_ring is None: P = self.parent() else: P = new_ring n = P.ngens() - if self == 0: + if not self: return P.zero() l = [] for j in range(n): @@ -3580,23 +3589,26 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): sage: p.toric_substitute((2,3), (-1,1), 2, new_ring=L.change_ring(F)) 3*x^3*y^3 + 2*x^-2*y^-2 """ - if new_ring is None: - P = self.parent() - else: - P = new_ring + cdef dict d, d2 + cdef ETuple ve, v1e, w, w1 + d = self.dict() d2 = {} - v = ETuple(v) - v1 = ETuple(v1) + ve = ETuple(v) + v1e = ETuple(v1) for w in d: x = d[w] if h is not None: x = h(x) - t = w.dotprod(v1) - w1 = w.eadd(v.emul(-t)) + t = w.dotprod(v1e) + w1 = w.eadd(ve.emul(-t)) if w1 in d2: d2[w1] += x * a**t else: d2[w1] = x * a**t + if new_ring is None: + P = self.parent() + else: + P = new_ring return P(d2) From 6d028fee1d9baeecc3608d9bf44fdc0b0dc4462b Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Fri, 24 Jul 2020 21:37:51 -0700 Subject: [PATCH 196/217] Factor "h is not None" checks out of loops in laurent_polynomial.pyx --- src/sage/rings/polynomial/laurent_polynomial.pyx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index 19f6f479ea9..2d10a17bc26 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -3563,13 +3563,14 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): l.append(ETuple(tuple(M.column(j)))) d = self.dict() d2 = {} + if h is not None: + for v in d: + d[v] = h(d[v]) for v in d: x = d[v] t = ETuple({}, n) for j in range(n): t = t.eadd(l[j].emul(v[j])) - if h is not None: - x = h(x) d2[t] = x return P(d2) @@ -3596,10 +3597,11 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): d2 = {} ve = ETuple(v) v1e = ETuple(v1) + if h is not None: + for w in d: + d[w] = h(d[w]) for w in d: x = d[w] - if h is not None: - x = h(x) t = w.dotprod(v1e) w1 = w.eadd(ve.emul(-t)) if w1 in d2: From d99aedae454ab73e0a587fd661609e6e3046bd4b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 25 Jul 2020 17:30:18 -0700 Subject: [PATCH 197/217] src/sage/rings/padics/padic_base_leaves.py: Update use of _test_metric --- src/sage/rings/padics/padic_base_leaves.py | 52 +++++++++++----------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/sage/rings/padics/padic_base_leaves.py b/src/sage/rings/padics/padic_base_leaves.py index 8523228a5a8..8cacb2aa453 100644 --- a/src/sage/rings/padics/padic_base_leaves.py +++ b/src/sage/rings/padics/padic_base_leaves.py @@ -233,15 +233,15 @@ def __init__(self, p, prec, print_mode, names): sage: R = ZpCR(2) sage: TestSuite(R).run() - sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^10)], max_runs = 2^12, skip='_test_metric') # long time - sage: R._test_metric(elements = [R.random_element() for i in range(2^3)]) # long time + sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^10)], max_runs = 2^12, skip='_test_metric_function') # long time + sage: R._test_metric_function(elements = [R.random_element() for i in range(2^3)]) # long time sage: R = ZpCR(3, 1) sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^3)]) sage: R = ZpCR(3, 2) - sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^6)], skip='_test_metric') # long time - sage: R._test_metric(elements = [R.random_element() for i in range(2^3)]) # long time + sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^6)], skip='_test_metric_function') # long time + sage: R._test_metric_function(elements = [R.random_element() for i in range(2^3)]) # long time sage: R = ZpCR(next_prime(10^60)) sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^3)], max_runs = 2^5, skip='_test_log') # long time @@ -329,15 +329,15 @@ def __init__(self, p, prec, print_mode, names): sage: R = ZpCA(2) sage: TestSuite(R).run() - sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^10)], max_runs = 2^12, skip='_test_metric') # long time - sage: R._test_metric(elements = [R.random_element() for i in range(2^3)]) # long time + sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^10)], max_runs = 2^12, skip='_test_metric_function') # long time + sage: R._test_metric_function(elements = [R.random_element() for i in range(2^3)]) # long time sage: R = ZpCA(3, 1) sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^3)]) sage: R = ZpCA(3, 2) - sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^6)], skip='_test_metric') # long time - sage: R._test_metric(elements = [R.random_element() for i in range(2^3)]) # long time + sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^6)], skip='_test_metric_function') # long time + sage: R._test_metric_function(elements = [R.random_element() for i in range(2^3)]) # long time sage: R = ZpCA(next_prime(10^60)) sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^3)], max_runs = 2^5, skip='_test_log') # long time @@ -428,15 +428,15 @@ def __init__(self, p, prec, print_mode, names): sage: R = ZpFP(2) sage: TestSuite(R).run() - sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^10)], max_runs = 2^12, skip='_test_metric') # long time - sage: R._test_metric(elements = [R.random_element() for i in range(2^3)]) # long time + sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^10)], max_runs = 2^12, skip='_test_metric_function') # long time + sage: R._test_metric_function(elements = [R.random_element() for i in range(2^3)]) # long time sage: R = ZpFP(3, 1) sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^3)]) sage: R = ZpFP(3, 2) - sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^6)], skip='_test_metric') # long time - sage: R._test_metric(elements = [R.random_element() for i in range(2^3)]) # long time + sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^6)], skip='_test_metric_function') # long time + sage: R._test_metric_function(elements = [R.random_element() for i in range(2^3)]) # long time sage: R = ZpFP(next_prime(10^60)) sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^3)], max_runs = 2^5, skip='_test_log') # long time @@ -521,15 +521,15 @@ def __init__(self, p, prec, print_mode, names): sage: R = ZpFM(2) sage: TestSuite(R).run() - sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^10)], max_runs = 2^12, skip='_test_metric') # long time - sage: R._test_metric(elements = [R.random_element() for i in range(2^3)]) # long time + sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^10)], max_runs = 2^12, skip='_test_metric_function') # long time + sage: R._test_metric_function(elements = [R.random_element() for i in range(2^3)]) # long time sage: R = ZpFM(3, 1) sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^3)]) sage: R = ZpFM(3, 2) - sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^6)], skip='_test_metric') # long time - sage: R._test_metric(elements = [R.random_element() for i in range(2^3)]) # long time + sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^6)], skip='_test_metric_function') # long time + sage: R._test_metric_function(elements = [R.random_element() for i in range(2^3)]) # long time sage: R = ZpFM(next_prime(10^60)) sage: TestSuite(R).run(skip='_test_log') @@ -633,16 +633,16 @@ def __init__(self, p, prec, print_mode, names): sage: R = Qp(2) sage: TestSuite(R).run() - sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^10)], max_runs = 2^12, skip='_test_metric') # long time - sage: R._test_metric(elements = [R.random_element() for i in range(2^3)]) # long time + sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^10)], max_runs = 2^12, skip='_test_metric_function') # long time + sage: R._test_metric_function(elements = [R.random_element() for i in range(2^3)]) # long time sage: R = Qp(3, 1) - sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^6)], skip='_test_metric') # long time - sage: R._test_metric(elements = [R.random_element() for i in range(2^3)]) # long time + sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^6)], skip='_test_metric_function') # long time + sage: R._test_metric_function(elements = [R.random_element() for i in range(2^3)]) # long time sage: R = Qp(3, 2) - sage: TestSuite(R).run(elements=[R.random_element() for i in range(3^9)], skip="_test_metric") # long time - sage: R._test_metric(elements=[R.random_element() for i in range(3^3)]) + sage: TestSuite(R).run(elements=[R.random_element() for i in range(3^9)], skip="_test_metric_function") # long time + sage: R._test_metric_function(elements=[R.random_element() for i in range(3^3)]) sage: R = Qp(next_prime(10^60)) sage: TestSuite(R).run(skip='_test_log') @@ -759,15 +759,15 @@ def __init__(self, p, prec, print_mode, names): sage: R = QpFP(2) sage: TestSuite(R).run() - sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^10)], max_runs = 2^12, skip='_test_metric') # long time - sage: R._test_metric(elements = [R.random_element() for i in range(2^3)]) # long time + sage: TestSuite(R).run(elements = [R.random_element() for i in range(2^10)], max_runs = 2^12, skip='_test_metric_function') # long time + sage: R._test_metric_function(elements = [R.random_element() for i in range(2^3)]) # long time sage: R = QpFP(3, 1) sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^3)]) sage: R = QpFP(3, 2) - sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^6)], skip='_test_metric') # long time - sage: R._test_metric(elements = [R.random_element() for i in range(2^3)]) # long time + sage: TestSuite(R).run(elements = [R.random_element() for i in range(3^6)], skip='_test_metric_function') # long time + sage: R._test_metric_function(elements = [R.random_element() for i in range(2^3)]) # long time sage: R = QpFP(next_prime(10^60)) sage: TestSuite(R).run(skip='_test_log') From 93facad6b5da6e8fdfb3f432226a505f556aecc4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 25 Jul 2020 17:32:44 -0700 Subject: [PATCH 198/217] src/sage/structure/category_object.pyx: Update use of _test_metric --- src/sage/structure/category_object.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/structure/category_object.pyx b/src/sage/structure/category_object.pyx index 676ba61e9d8..3bb4384b677 100644 --- a/src/sage/structure/category_object.pyx +++ b/src/sage/structure/category_object.pyx @@ -813,7 +813,7 @@ cdef class CategoryObject(SageObject): running ._test_euclidean_degree() . . . pass running ._test_fraction_field() . . . pass running ._test_gcd_vs_xgcd() . . . pass - running ._test_metric() . . . pass + running ._test_metric_function() . . . pass running ._test_new() . . . pass running ._test_not_implemented_methods() . . . pass running ._test_one() . . . pass @@ -878,7 +878,7 @@ cdef class CategoryObject(SageObject): _test_euclidean_degree _test_fraction_field _test_gcd_vs_xgcd - _test_metric + _test_metric_function _test_new _test_not_implemented_methods _test_one From a1389d8b139b76a4b284b746e69f845da25a4361 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 25 Jul 2020 17:33:08 -0700 Subject: [PATCH 199/217] src/doc/en/thematic_tutorials/vector_calculus: Update categories in doctest --- .../vector_calculus/vector_calc_advanced.rst | 4 +++- .../thematic_tutorials/vector_calculus/vector_calc_plane.rst | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) 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 ed4bf792b4b..c4c3b8e213b 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 @@ -29,7 +29,9 @@ Cartesian coordinates `(x,y,z)`:: manifold endowed with a positive definite metric tensor:: sage: E.category() - Category of smooth manifolds over Real Field with 53 bits of precision + Join of + Category of differentiable manifolds over Real Field with 53 bits of precision and + Category of metric spaces sage: E.base_field() is RR True sage: E.metric() 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 06ee9ba2fab..13ff0d8499e 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 @@ -491,7 +491,9 @@ Then we have:: manifold endowed with a positive definite metric tensor:: sage: E.category() - Category of smooth manifolds over Real Field with 53 bits of precision + Join of + Category of differentiable manifolds over Real Field with 53 bits of precision and + Category of metric spaces sage: E.base_field() is RR True From de9d408fa5fba200a877fb96df94acb727c86c41 Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Sat, 25 Jul 2020 20:11:29 -0700 Subject: [PATCH 200/217] Some more minor edits to laurent_polynomial.pyx --- .../rings/polynomial/laurent_polynomial.pyx | 39 ++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index 2d10a17bc26..6c7822167dc 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -3513,7 +3513,10 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): cdef int i cdef dict df cdef ETuple v + cdef LaurentPolynomial_mpair ans + if self._prod is None: + self._compute_polydict() df = self.dict() if h is None: for v in df: @@ -3522,12 +3525,15 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): else: for v in df: for i in d: - df[v] = h(df[v]*d[i]**v[i]) + df[v] = df[v]*d[i]**v[i] + df[v] = h(df[v]) if new_ring is None: - P = self.parent() + ans = self._new_c() + ans._prod = PolyDict(df) + return ans else: P = new_ring - return P(df) + return P(df) cpdef toric_coordinate_change(self, M, h=None, new_ring=None): r""" @@ -3550,14 +3556,14 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): cdef int n, i, j cdef dict d, d2 cdef ETuple v, t + cdef LaurentPolynomial_mpair ans - if new_ring is None: - P = self.parent() - else: - P = new_ring - n = P.ngens() if not self: - return P.zero() + if new_ring is None: + return self._parent.zero() + else: + return new_ring.zero() + n = self._parent.ngens() l = [] for j in range(n): l.append(ETuple(tuple(M.column(j)))) @@ -3572,7 +3578,12 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): for j in range(n): t = t.eadd(l[j].emul(v[j])) d2[t] = x - return P(d2) + if new_ring is None: + ans = self._new_c() + ans._prod = PolyDict(d2) + return ans + else: + return new_ring(d2) cpdef toric_substitute(self, v, v1, a, h=None, new_ring=None): r""" @@ -3592,6 +3603,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): """ cdef dict d, d2 cdef ETuple ve, v1e, w, w1 + cdef LaurentPolynomial_mpair ans d = self.dict() d2 = {} @@ -3609,8 +3621,9 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): else: d2[w1] = x * a**t if new_ring is None: - P = self.parent() + ans = self._new_c() + ans._prod = PolyDict(d2) + return ans else: - P = new_ring - return P(d2) + return new_ring(d2) From d574dfe77a9d625b4847eb85556185599efe5d71 Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Sat, 25 Jul 2020 20:15:57 -0700 Subject: [PATCH 201/217] Fix pyflakes for LP ideal --- src/sage/rings/polynomial/laurent_polynomial_ideal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial_ideal.py b/src/sage/rings/polynomial/laurent_polynomial_ideal.py index 60709e7e481..d7f9e932390 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_ideal.py +++ b/src/sage/rings/polynomial/laurent_polynomial_ideal.py @@ -23,7 +23,7 @@ # **************************************************************************** from sage.rings.ideal import Ideal_generic -from sage.structure.richcmp import richcmp, op_EQ, op_NE, op_LT, op_LE, op_GT, op_GE +from sage.structure.richcmp import op_EQ, op_NE, op_LT, op_LE, op_GT, op_GE class LaurentPolynomialIdeal( Ideal_generic ): def __init__(self, ring, gens, coerce=True, hint=None): From 2f9e0cf6b2823eac607a94e5a6bd89668f69008d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Leli=C3=A8vre?= Date: Sun, 26 Jul 2020 14:40:03 +0200 Subject: [PATCH 202/217] #29334: SPKG.rst for r_jupyter --- build/pkgs/r_jupyter/SPKG.rst | 26 ++++++++++++++++++++++++++ build/pkgs/r_jupyter/dependencies | 1 + 2 files changed, 27 insertions(+) create mode 100644 build/pkgs/r_jupyter/SPKG.rst create mode 100644 build/pkgs/r_jupyter/dependencies diff --git a/build/pkgs/r_jupyter/SPKG.rst b/build/pkgs/r_jupyter/SPKG.rst new file mode 100644 index 00000000000..e48f758f0a8 --- /dev/null +++ b/build/pkgs/r_jupyter/SPKG.rst @@ -0,0 +1,26 @@ +r_jupyter +========= + +Description +----------- + +This package installs IRkernel, the R Jupyter kernel. + +It gets installed via R's package installer on top of Jupyter. + +License +------- + +MIT + +Upstream Contact +---------------- + +- https://github.com/IRkernel/IRkernel +- https://irkernel.github.io/ + +Dependencies +------------ + +- R +- notebook diff --git a/build/pkgs/r_jupyter/dependencies b/build/pkgs/r_jupyter/dependencies new file mode 100644 index 00000000000..981f46753f0 --- /dev/null +++ b/build/pkgs/r_jupyter/dependencies @@ -0,0 +1 @@ +notebook r \ No newline at end of file From d785c0d05c92d9ea96cdaa63df9f52824fa03ce3 Mon Sep 17 00:00:00 2001 From: Eric Gourgoulhon Date: Sun, 26 Jul 2020 16:10:20 +0200 Subject: [PATCH 203/217] Better category for Euclidean spaces --- .../vector_calculus/vector_calc_advanced.rst | 4 +- .../vector_calculus/vector_calc_plane.rst | 4 +- .../manifolds/differentiable/euclidean.py | 37 +++++++++---------- 3 files changed, 21 insertions(+), 24 deletions(-) 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 c4c3b8e213b..54157db8e45 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 @@ -30,8 +30,8 @@ manifold endowed with a positive definite metric tensor:: sage: E.category() Join of - Category of differentiable manifolds over Real Field with 53 bits of precision and - Category of metric spaces + Category of smooth manifolds over Real Field with 53 bits of precision and + Category of complete metric spaces sage: E.base_field() is RR True sage: E.metric() 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 13ff0d8499e..5b7a911d01e 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 @@ -492,8 +492,8 @@ manifold endowed with a positive definite metric tensor:: sage: E.category() Join of - Category of differentiable manifolds over Real Field with 53 bits of precision and - Category of metric spaces + Category of smooth manifolds over Real Field with 53 bits of precision and + Category of complete metric spaces sage: E.base_field() is RR True diff --git a/src/sage/manifolds/differentiable/euclidean.py b/src/sage/manifolds/differentiable/euclidean.py index 7c245b6df58..9246f58b406 100644 --- a/src/sage/manifolds/differentiable/euclidean.py +++ b/src/sage/manifolds/differentiable/euclidean.py @@ -615,11 +615,12 @@ class EuclideanSpace(PseudoRiemannianManifold): sage: latex(E) \mathbb{E}^{4} - ``E`` is both a real smooth manifold of dimension `4` and a metric space:: + ``E`` is both a real smooth manifold of dimension `4` and a complete metric + space:: sage: E.category() - Join of Category of differentiable manifolds over Real Field with - 53 bits of precision and Category of metric spaces + Join of Category of smooth manifolds over Real Field with 53 bits of + precision and Category of complete metric spaces sage: dim(E) 4 @@ -746,10 +747,8 @@ def __init__(self, n, name=None, latex_name=None, an Euclidean space; the created object is then an open subset of ``base_manifold`` - ``category`` -- (default: ``None``) to specify the category; - if ``None``, ``Manifolds(RR).Differentiable()`` (or - ``Manifolds(RR).Smooth()`` if ``diff_degree`` = ``infinity``) - is assumed (see the category - :class:`~sage.categories.manifolds.Manifolds`) + if ``None``, + ``Manifolds(RR).Smooth() & MetricSpaces().Complete()`` is assumed - ``init_coord_methods`` -- (default: ``None``) dictionary of methods to initialize the various type of coordinates, with each key being a string describing the type of coordinates; to be @@ -777,7 +776,7 @@ def __init__(self, n, name=None, latex_name=None, if latex_name is None: latex_name = r'\mathbb{E}^{' + str(n) + '}' if category is None: - category = Manifolds(RR).Differentiable() & MetricSpaces() + category = Manifolds(RR).Smooth() & MetricSpaces().Complete() # NB: RR is a proxy for the field of real numbers, until # Trac #24456 is ready PseudoRiemannianManifold.__init__(self, n, name, metric_name=metric_name, @@ -1039,9 +1038,7 @@ class EuclideanPlane(EuclideanSpace): - ``base_manifold`` -- (default: ``None``) if not ``None``, must be an Euclidean plane; the created object is then an open subset of ``base_manifold`` - ``category`` -- (default: ``None``) to specify the category; if ``None``, - ``Manifolds(RR).Differentiable()`` (or ``Manifolds(RR).Smooth()`` - if ``diff_degree`` = ``infinity``) is assumed (see the category - :class:`~sage.categories.manifolds.Manifolds`) + ``Manifolds(RR).Smooth() & MetricSpaces().Complete()`` is assumed - ``names`` -- (default: ``None``) unused argument, except if ``symbols`` is not provided; it must then be a tuple containing the coordinate symbols (this is guaranteed if the shortcut operator @@ -1066,11 +1063,12 @@ class EuclideanPlane(EuclideanSpace): sage: E. = EuclideanSpace(); E Euclidean plane E^2 - ``E`` is both a real smooth manifold of dimension `2` and a metric space:: + ``E`` is both a real smooth manifold of dimension `2` and a complete metric + space:: sage: E.category() - Join of Category of differentiable manifolds over Real Field with - 53 bits of precision and Category of metric spaces + Join of Category of smooth manifolds over Real Field with 53 bits of + precision and Category of complete metric spaces sage: dim(E) 2 @@ -1560,9 +1558,7 @@ class Euclidean3dimSpace(EuclideanSpace): Euclidean 3-space; the created object is then an open subset of ``base_manifold`` - ``category`` -- (default: ``None``) to specify the category; if ``None``, - ``Manifolds(RR).Differentiable()`` (or ``Manifolds(RR).Smooth()`` - if ``diff_degree`` = ``infinity``) is assumed (see the category - :class:`~sage.categories.manifolds.Manifolds`) + ``Manifolds(RR).Smooth() & MetricSpaces().Complete()`` is assumed - ``names`` -- (default: ``None``) unused argument, except if ``symbols`` is not provided; it must then be a tuple containing the coordinate symbols (this is guaranteed if the shortcut operator @@ -1595,11 +1591,12 @@ class Euclidean3dimSpace(EuclideanSpace): sage: type(E) - ``E`` is both a real smooth manifold of dimension `3` and a metric space:: + ``E`` is both a real smooth manifold of dimension `3` and a complete metric + space:: sage: E.category() - Join of Category of differentiable manifolds over Real Field with - 53 bits of precision and Category of metric spaces + Join of Category of smooth manifolds over Real Field with 53 bits of + precision and Category of complete metric spaces sage: dim(E) 3 From acc407cc24226e8bee44bf30b39c24c7be86cb02 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Sun, 26 Jul 2020 17:15:25 +0200 Subject: [PATCH 204/217] Trac #30191: try-except block for zero check --- .../differentiable/automorphismfield_group.py | 8 ++++++-- .../manifolds/differentiable/diff_form_module.py | 16 ++++++++++++---- .../differentiable/mixed_form_algebra.py | 16 +++++++++++----- .../differentiable/multivector_module.py | 16 ++++++++++++---- .../differentiable/tensorfield_module.py | 16 ++++++++++++---- .../differentiable/vectorfield_module.py | 16 ++++++++++++---- src/sage/manifolds/scalarfield.py | 4 +++- src/sage/manifolds/scalarfield_algebra.py | 10 ++++++++++ src/sage/manifolds/section_module.py | 16 ++++++++++++---- 9 files changed, 90 insertions(+), 28 deletions(-) diff --git a/src/sage/manifolds/differentiable/automorphismfield_group.py b/src/sage/manifolds/differentiable/automorphismfield_group.py index 1ab4458232f..1f55518310c 100644 --- a/src/sage/manifolds/differentiable/automorphismfield_group.py +++ b/src/sage/manifolds/differentiable/automorphismfield_group.py @@ -208,8 +208,12 @@ def _element_constructor_(self, comp=[], frame=None, name=None, a = (x^2 + 1) d/dx*dx + (y^2 + 1) d/dy*dy """ - if comp == 1: - return self.one() + try: + if (comp - 1).is_trivial_zero(): + return self.one() + except AttributeError: + if comp == 1: + return self.one() if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) diff --git a/src/sage/manifolds/differentiable/diff_form_module.py b/src/sage/manifolds/differentiable/diff_form_module.py index 97f34e4dcd1..bb2e03343aa 100644 --- a/src/sage/manifolds/differentiable/diff_form_module.py +++ b/src/sage/manifolds/differentiable/diff_form_module.py @@ -330,8 +330,12 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if comp == 0: - return self.zero() + try: + if comp.is_trivial_zero(): + return self.zero() + except AttributeError: + if comp == 0: + return self.zero() if isinstance(comp, (DiffForm, DiffFormParal)): # coercion by domain restriction if (self._degree == comp._tensor_type[1] @@ -799,8 +803,12 @@ def _element_constructor_(self, comp=[], frame=None, name=None, False """ - if comp == 0: - return self.zero() + try: + if comp.is_trivial_zero(): + return self.zero() + except AttributeError: + if comp == 0: + return self.zero() if isinstance(comp, (DiffForm, DiffFormParal)): # coercion by domain restriction if (self._degree == comp._tensor_type[1] diff --git a/src/sage/manifolds/differentiable/mixed_form_algebra.py b/src/sage/manifolds/differentiable/mixed_form_algebra.py index 87c36ccd1fc..cdc77fafa5a 100644 --- a/src/sage/manifolds/differentiable/mixed_form_algebra.py +++ b/src/sage/manifolds/differentiable/mixed_form_algebra.py @@ -193,11 +193,17 @@ def _element_constructor_(self, comp=None, name=None, latex_name=None): res = self.element_class(self, name=name, latex_name=latex_name) if comp is None: return res - elif comp == 0: - return self.zero() - elif comp == 1: - return self.one() - elif isinstance(comp, (tuple, list)): + try: + if comp.is_trivial_zero(): + return self.zero() + if (comp - 1).is_trivial_zero(): + return self.one() + except AttributeError: + if comp == 0: + return self.zero() + if comp == 1: + return self.one() + if isinstance(comp, (tuple, list)): if len(comp) != self._max_deg + 1: raise IndexError("input list must have " "length {}".format(self._max_deg + 1)) diff --git a/src/sage/manifolds/differentiable/multivector_module.py b/src/sage/manifolds/differentiable/multivector_module.py index 58d8b25f732..82f82c013a2 100644 --- a/src/sage/manifolds/differentiable/multivector_module.py +++ b/src/sage/manifolds/differentiable/multivector_module.py @@ -300,8 +300,12 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if comp == 0: - return self.zero() + try: + if comp.is_trivial_zero(): + return self.zero() + except AttributeError: + if comp == 0: + return self.zero() if isinstance(comp, (MultivectorField, MultivectorFieldParal)): # coercion by domain restriction if (self._degree == comp._tensor_type[0] @@ -724,8 +728,12 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if comp == 0: - return self.zero() + try: + if comp.is_trivial_zero(): + return self.zero() + except AttributeError: + if comp == 0: + return self.zero() if isinstance(comp, (MultivectorField, MultivectorFieldParal)): # coercion by domain restriction if (self._degree == comp._tensor_type[0] diff --git a/src/sage/manifolds/differentiable/tensorfield_module.py b/src/sage/manifolds/differentiable/tensorfield_module.py index 168a1fdde81..fff3fac10bc 100644 --- a/src/sage/manifolds/differentiable/tensorfield_module.py +++ b/src/sage/manifolds/differentiable/tensorfield_module.py @@ -309,8 +309,12 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if comp == 0: - return self.zero() + try: + if comp.is_trivial_zero(): + return self.zero() + except AttributeError: + if comp == 0: + return self.zero() if isinstance(comp, DiffForm): # coercion of a p-form to a type-(0,p) tensor field: form = comp # for readability @@ -794,8 +798,12 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if comp == 0: - return self.zero() + try: + if comp.is_trivial_zero(): + return self.zero() + except AttributeError: + if comp == 0: + return self.zero() if isinstance(comp, DiffFormParal): # coercion of a p-form to a type-(0,p) tensor field: form = comp # for readability diff --git a/src/sage/manifolds/differentiable/vectorfield_module.py b/src/sage/manifolds/differentiable/vectorfield_module.py index fac288eff2f..dad8c54f75e 100644 --- a/src/sage/manifolds/differentiable/vectorfield_module.py +++ b/src/sage/manifolds/differentiable/vectorfield_module.py @@ -268,8 +268,12 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if comp == 0: - return self.zero() + try: + if comp.is_trivial_zero(): + return self.zero() + except AttributeError: + if comp == 0: + return self.zero() if isinstance(comp, VectorField): if (self._domain.is_subset(comp._domain) and self._ambient_domain.is_subset(comp._ambient_domain)): @@ -1471,8 +1475,12 @@ def _element_constructor_(self, comp=[], basis=None, name=None, True """ - if comp == 0: - return self.zero() + try: + if comp.is_trivial_zero(): + return self.zero() + except AttributeError: + if comp == 0: + return self.zero() if isinstance(comp, VectorField): if (self._domain.is_subset(comp._domain) and self._ambient_domain.is_subset(comp._ambient_domain)): diff --git a/src/sage/manifolds/scalarfield.py b/src/sage/manifolds/scalarfield.py index edb52ecd954..2aff1211fd0 100644 --- a/src/sage/manifolds/scalarfield.py +++ b/src/sage/manifolds/scalarfield.py @@ -2663,8 +2663,10 @@ def _lmul_(self, number): True """ - if number == 0: + if number.is_trivial_zero(): return self.parent().zero() + if (number - 1).is_trivial_zero(): + return self.parent().one() result = type(self)(self.parent()) if isinstance(number, Expression): var = number.variables() # possible symbolic variables in number diff --git a/src/sage/manifolds/scalarfield_algebra.py b/src/sage/manifolds/scalarfield_algebra.py index cca0307059d..63f7610289b 100644 --- a/src/sage/manifolds/scalarfield_algebra.py +++ b/src/sage/manifolds/scalarfield_algebra.py @@ -451,6 +451,16 @@ def _element_constructor_(self, coord_expression=None, chart=None, (x, y) |--> y^2 + x """ + try: + if coord_expression.is_trivial_zero(): + return self.zero() + if (coord_expression - 1).is_trivial_zero(): + return self.one() + except AttributeError: + if coord_expression == 0: + return self.zero() + if coord_expression == 1: + return self.one() if isinstance(coord_expression, ScalarField): if self._domain.is_subset(coord_expression._domain): # restriction of the scalar field to self._domain: diff --git a/src/sage/manifolds/section_module.py b/src/sage/manifolds/section_module.py index 4cce43a8aa9..501b2c68c02 100644 --- a/src/sage/manifolds/section_module.py +++ b/src/sage/manifolds/section_module.py @@ -221,8 +221,12 @@ def _element_constructor_(self, comp=[], frame=None, name=None, True """ - if comp == 0: - return self.zero() + try: + if comp.is_trivial_zero(): + return self.zero() + except AttributeError: + if comp == 0: + return self.zero() if isinstance(comp, Section): if self._domain.is_subset(comp._domain): return comp.restrict(self._domain) @@ -640,8 +644,12 @@ def _element_constructor_(self, comp=[], basis=None, name=None, True """ - if comp == 0: - return self.zero() + try: + if comp.is_trivial_zero(): + return self.zero() + except AttributeError: + if comp == 0: + return self.zero() if isinstance(comp, Section): if self._domain.is_subset(comp._domain): return comp.restrict(self._domain) From 0d27b57ae5b5fefa64c56aadf29ee15806b84c77 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Sun, 26 Jul 2020 17:16:44 +0200 Subject: [PATCH 205/217] Trac #30191: unnecessary comment block removed --- src/sage/manifolds/scalarfield_algebra.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/manifolds/scalarfield_algebra.py b/src/sage/manifolds/scalarfield_algebra.py index 63f7610289b..e68220955f1 100644 --- a/src/sage/manifolds/scalarfield_algebra.py +++ b/src/sage/manifolds/scalarfield_algebra.py @@ -466,7 +466,6 @@ def _element_constructor_(self, coord_expression=None, chart=None, # restriction of the scalar field to self._domain: return coord_expression.restrict(self._domain) else: - ### # Anything going wrong here should produce a readable error: try: # generic constructor: From f94bcbe14781945c7d0e6a2643710599d1239e38 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Sun, 26 Jul 2020 17:18:10 +0200 Subject: [PATCH 206/217] Trac #30191: if blocks rearranged --- src/sage/manifolds/differentiable/mixed_form_algebra.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/manifolds/differentiable/mixed_form_algebra.py b/src/sage/manifolds/differentiable/mixed_form_algebra.py index cdc77fafa5a..e2bef4d16df 100644 --- a/src/sage/manifolds/differentiable/mixed_form_algebra.py +++ b/src/sage/manifolds/differentiable/mixed_form_algebra.py @@ -190,9 +190,6 @@ def _element_constructor_(self, comp=None, name=None, latex_name=None): manifold M """ - res = self.element_class(self, name=name, latex_name=latex_name) - if comp is None: - return res try: if comp.is_trivial_zero(): return self.zero() @@ -203,7 +200,10 @@ def _element_constructor_(self, comp=None, name=None, latex_name=None): return self.zero() if comp == 1: return self.one() - if isinstance(comp, (tuple, list)): + res = self.element_class(self, name=name, latex_name=latex_name) + if comp is None: + return res + elif isinstance(comp, (tuple, list)): if len(comp) != self._max_deg + 1: raise IndexError("input list must have " "length {}".format(self._max_deg + 1)) From 895268429db02632c5a5adc7785bf6379f08effb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20R=C3=BCth?= Date: Tue, 23 Jun 2020 17:49:18 +0200 Subject: [PATCH 207/217] Do not pretend to build Python 2 docker images we are not actually building these anymore so we should not try to build everything twice. --- .ci/push-dockerhub.sh | 4 ++++ .gitlab-ci.yml | 40 ---------------------------------------- docker/README.md | 4 ++-- 3 files changed, 6 insertions(+), 42 deletions(-) diff --git a/.ci/push-dockerhub.sh b/.ci/push-dockerhub.sh index a685ae8dd6e..c047448e758 100755 --- a/.ci/push-dockerhub.sh +++ b/.ci/push-dockerhub.sh @@ -26,4 +26,8 @@ if [ -z "$DOCKER_USER" -o -z "$SECRET_DOCKER_PASS" ]; then else cat "$SECRET_DOCKER_PASS" | docker login -u $DOCKER_USER --password-stdin docker push ${DOCKER_NAMESPACE:-sagemath}/$1:$DOCKER_TAG + + # For historic reasons, we also provide a -py3 tag. It's identical to the non-py3 tag. + docker tag ${DOCKER_NAMESPACE:-sagemath}/$1:$DOCKER_TAG ${DOCKER_NAMESPACE:-sagemath}/$1:$DOCKER_TAG-py3 + docker push ${DOCKER_NAMESPACE:-sagemath}/$1:$DOCKER_TAG-py3 fi diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6d335bc1eb2..e80a04b422b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -193,43 +193,3 @@ push-dockerhub-dev: script: - . .ci/pull-gitlab.sh sagemath-dev - sh .ci/push-dockerhub.sh sagemath-dev - -.py3: - variables: - WITH_PYTHON: 3 - DEFAULT_ARTIFACT_BASE: sagemath/sagemath-dev:develop-py3 - -build-from-latest-py3: - extends: - - build-from-latest - - .py3 - -build-from-clean-py3: - extends: - - build-from-clean - - .py3 - -test-dev-py3: - extends: - - test-dev - - .py3 - -test-cli-py3: - extends: - - test-cli - - .py3 - -test-jupyter-py3: - extends: - - test-jupyter - - .py3 - -push-dockerhub-py3: - extends: - - push-dockerhub - - .py3 - -push-dockerhub-dev-py3: - extends: - - push-dockerhub-dev - - .py3 diff --git a/docker/README.md b/docker/README.md index a39e0021050..b40186937c1 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,4 +1,4 @@ -[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://github.com/sagemath/sage/COPYING.txt) [![Maintained](https://img.shields.io/maintenance/yes/2020.svg)](https://github.com/sagemath/sage/commits/master) +[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://github.com/sagemath/sage/COPYING.txt) # Supported tags @@ -6,7 +6,7 @@ * `x.x` — all stable releases of Sage are tagged with their version number. * `x.x.{beta,rc}x` - betas and release candidates of Sage as [tagged in our git repository](https://github.com/sagemath/sage/tags). * `develop` — the current development version of Sage which gets merged into the `master` branch when a new version of Sage is released [![GitHub last commit (branch)](https://img.shields.io/github/last-commit/sagemath/sage/develop.svg)](https://github.com/sagemath/sage/commits/develop) [![GitLab CI](https://gitlab.com/sagemath/sage/badges/develop/pipeline.svg)](https://gitlab.com/sagemath/sage/commits/develop) -* all the above tags can be complemented by `-py3` for Python 3 based images +* `-py3` - in the past, we distinguished Python 2 and Python 3 builds. Now, since 9.1, we only provide Python 3 based images so the `-py3` suffix is only there for historic reasons. # What is SageMath From 9d0a8d19f549330dfb519cde349427e8092f3409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Leli=C3=A8vre?= Date: Sun, 26 Jul 2020 15:22:15 +0200 Subject: [PATCH 208/217] 29944-reviewer-rewording --- .ci/push-dockerhub.sh | 2 +- docker/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/push-dockerhub.sh b/.ci/push-dockerhub.sh index c047448e758..5f0b5b5eab5 100755 --- a/.ci/push-dockerhub.sh +++ b/.ci/push-dockerhub.sh @@ -27,7 +27,7 @@ else cat "$SECRET_DOCKER_PASS" | docker login -u $DOCKER_USER --password-stdin docker push ${DOCKER_NAMESPACE:-sagemath}/$1:$DOCKER_TAG - # For historic reasons, we also provide a -py3 tag. It's identical to the non-py3 tag. + # For historical reasons, we also provide a -py3 tag. It's identical to the non-py3 tag. docker tag ${DOCKER_NAMESPACE:-sagemath}/$1:$DOCKER_TAG ${DOCKER_NAMESPACE:-sagemath}/$1:$DOCKER_TAG-py3 docker push ${DOCKER_NAMESPACE:-sagemath}/$1:$DOCKER_TAG-py3 fi diff --git a/docker/README.md b/docker/README.md index b40186937c1..e77008fc886 100644 --- a/docker/README.md +++ b/docker/README.md @@ -6,7 +6,7 @@ * `x.x` — all stable releases of Sage are tagged with their version number. * `x.x.{beta,rc}x` - betas and release candidates of Sage as [tagged in our git repository](https://github.com/sagemath/sage/tags). * `develop` — the current development version of Sage which gets merged into the `master` branch when a new version of Sage is released [![GitHub last commit (branch)](https://img.shields.io/github/last-commit/sagemath/sage/develop.svg)](https://github.com/sagemath/sage/commits/develop) [![GitLab CI](https://gitlab.com/sagemath/sage/badges/develop/pipeline.svg)](https://gitlab.com/sagemath/sage/commits/develop) -* `-py3` - in the past, we distinguished Python 2 and Python 3 builds. Now, since 9.1, we only provide Python 3 based images so the `-py3` suffix is only there for historic reasons. +* `-py3` - until Sage 9.1, we provided Python 2 builds (with no suffix) and Python 3 builds (with the `-py3` suffix). From Sage 9.2.beta0 on, all images we provide are based on Python 3 and the `-py3` suffix survives only for historical reasons: with or without it, you get Python 3. # What is SageMath From 490d38d93b1f75a3ca245f9c3add92c017f35d42 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Mon, 27 Jul 2020 01:37:47 +0200 Subject: [PATCH 209/217] Trac #30228: init comp with string --- src/sage/manifolds/section.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sage/manifolds/section.py b/src/sage/manifolds/section.py index 9c95f4beb10..88bb8488949 100644 --- a/src/sage/manifolds/section.py +++ b/src/sage/manifolds/section.py @@ -465,6 +465,9 @@ def _init_components(self, *comp, **kwargs): # frame is actually a pair (frame, chart): frame, chart = frame self.add_comp(frame)[:, chart] = components + elif isinstance(comp0, str): + # For compatibility with previous use of tensor_field(): + self.set_name(comp0) else: if hasattr(comp0, '__getitem__'): # comp0 is a list/vector of components From 78692a6b4a712cbaf5f20b5f8199a529f9755be7 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Mon, 27 Jul 2020 01:53:45 +0200 Subject: [PATCH 210/217] Trac #30228: misleading comment corrected --- src/sage/manifolds/section.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/manifolds/section.py b/src/sage/manifolds/section.py index 88bb8488949..2ec56af88d6 100644 --- a/src/sage/manifolds/section.py +++ b/src/sage/manifolds/section.py @@ -466,7 +466,7 @@ def _init_components(self, *comp, **kwargs): frame, chart = frame self.add_comp(frame)[:, chart] = components elif isinstance(comp0, str): - # For compatibility with previous use of tensor_field(): + # For consistency with tensor fields: self.set_name(comp0) else: if hasattr(comp0, '__getitem__'): From 2bd25467358b820abe61b9fa90ac14f7d70cc958 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 27 Jul 2020 12:51:22 +1000 Subject: [PATCH 211/217] Changes for rescale_vars. --- .../rings/polynomial/laurent_polynomial.pyx | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index 6c7822167dc..93461fc0026 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -3497,13 +3497,19 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): r""" Rescale variables in a Laurent polynomial. - The optional argument ``h`` is a map to be applied to coefficients. - This is done after rescaling. + INPUT: + + - ``d`` -- a ``dict`` whose keys are the generator indices + and values are the coefficients; so a pair ``(i, v)`` + means `x_i \mapsto v x_i` + - ``h`` -- (optional) a map to be applied to coefficients + done after rescaling + - ``new_ring`` -- (optional) a new ring to map the result into EXAMPLES:: sage: L. = LaurentPolynomialRing(QQ, 2) - sage: p = x^2*y + x*y^2 + sage: p = x^-2*y + x*y^-2 sage: p.rescale_vars({0: 2, 1: 3}) 12*x^2*y + 18*x*y^2 sage: F = GF(2) @@ -3517,23 +3523,28 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): if self._prod is None: self._compute_polydict() - df = self.dict() + + ans = self._new_c() + df = self._prod.dict() # This makes a copy for us to manipulate + ans._mon = self._mon if h is None: for v in df: + val = df[v] for i in d: - df[v] *= d[i]**v[i] + val *= d[i]**v[i] + df[v] = val else: + R = self._parent._base for v in df: + val = df[v] for i in d: - df[v] = df[v]*d[i]**v[i] - df[v] = h(df[v]) - if new_ring is None: - ans = self._new_c() - ans._prod = PolyDict(df) - return ans - else: - P = new_ring - return P(df) + val *= d[i]**v[i] + df[v] = R(h(val)) + ans._prod = PolyDict(df) + ans._poly = self._poly._parent({v.esub(ans._mon): df[v] for v in df}) + if new_ring is not None: + return new_ring(ans) + return ans cpdef toric_coordinate_change(self, M, h=None, new_ring=None): r""" From cbc4321a4317121cad0852d5093858da5246cae2 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 27 Jul 2020 14:56:26 +1000 Subject: [PATCH 212/217] Reworking the toric_coordinate_change for speed. --- .../rings/polynomial/laurent_polynomial.pyx | 77 +++++++++++-------- 1 file changed, 47 insertions(+), 30 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index 93461fc0026..f1ce24efbcb 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -19,7 +19,7 @@ from sage.misc.derivative import multi_derivative from sage.rings.polynomial.polynomial_element import Polynomial from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.structure.richcmp cimport richcmp, rich_to_bool - +from sage.matrix.matrix0 cimport Matrix cdef class LaurentPolynomial(CommutativeAlgebraElement): """ @@ -3511,10 +3511,10 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): sage: L. = LaurentPolynomialRing(QQ, 2) sage: p = x^-2*y + x*y^-2 sage: p.rescale_vars({0: 2, 1: 3}) - 12*x^2*y + 18*x*y^2 + 2/9*x*y^-2 + 3/4*x^-2*y sage: F = GF(2) sage: p.rescale_vars({0: 3, 1: 7}, new_ring=L.change_ring(F)) - x^2*y + x*y^2 + x*y^-2 + x^-2*y """ cdef int i cdef dict df @@ -3525,7 +3525,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): self._compute_polydict() ans = self._new_c() - df = self._prod.dict() # This makes a copy for us to manipulate + df = dict(self._prod.__repn) # This makes a copy for us to manipulate ans._mon = self._mon if h is None: for v in df: @@ -3556,45 +3556,62 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): EXAMPLES:: - sage: L. = LaurentPolynomialRing(QQ,2) - sage: p = 2*x^2 + y + x*y + sage: L. = LaurentPolynomialRing(QQ, 2) + sage: p = 2*x^2 + y - x*y sage: p.toric_coordinate_change(Matrix([[1,-3],[1,1]])) - 2*x^2*y^2 + x^-2*y^2 + x^-3*y + 2*x^2*y^2 - x^-2*y^2 + x^-3*y sage: F = GF(2) sage: p.toric_coordinate_change(Matrix([[1,-3],[1,1]]), new_ring=L.change_ring(F)) x^-2*y^2 + x^-3*y """ - cdef int n, i, j - cdef dict d, d2 - cdef ETuple v, t + cdef int n, i, j, x + cdef dict d, dr + cdef ETuple v cdef LaurentPolynomial_mpair ans - + cdef list L, mon, exp + cdef Matrix mat = M + + n = self._parent.ngens() + if mat.dimensions() != (n, n): + raise ValueError("the matrix M must be a {k} x {k} matrix".format(k=n)) + if not self: if new_ring is None: return self._parent.zero() else: return new_ring.zero() - n = self._parent.ngens() - l = [] - for j in range(n): - l.append(ETuple(tuple(M.column(j)))) - d = self.dict() - d2 = {} - if h is not None: - for v in d: - d[v] = h(d[v]) + + if self._prod is None: + self._compute_polydict() + + ans = self._new_c() + d = self._prod.__repn + dr = {} + mon = [0] * n for v in d: - x = d[v] - t = ETuple({}, n) + # Make a copy of mon as this might be faster than creating the data from scratch. + # We will set every entry, so no need to clear the data. + exp = list(mon) for j in range(n): - t = t.eadd(l[j].emul(v[j])) - d2[t] = x - if new_ring is None: - ans = self._new_c() - ans._prod = PolyDict(d2) - return ans - else: - return new_ring(d2) + 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]): + mon[j] = x + exp[j] = x + dr[ETuple(exp)] = d[v] + + if h is not None: + for v in dr: + dr[v] = self._parent._base(h(dr[v])) + + ans._prod = PolyDict(dr) + ans._mon = ETuple(mon) + 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 cpdef toric_substitute(self, v, v1, a, h=None, new_ring=None): r""" From 25ec8ad0a679cc49b3a4437a425b77cfe5453592 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 27 Jul 2020 15:08:18 +1000 Subject: [PATCH 213/217] Similar changes to toric_substitute(). --- .../rings/polynomial/laurent_polynomial.pyx | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index f1ce24efbcb..21946987100 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -3524,9 +3524,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): if self._prod is None: self._compute_polydict() - ans = self._new_c() df = dict(self._prod.__repn) # This makes a copy for us to manipulate - ans._mon = self._mon if h is None: for v in df: val = df[v] @@ -3540,7 +3538,10 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): for i in d: val *= d[i]**v[i] df[v] = R(h(val)) + + ans = self._new_c() ans._prod = PolyDict(df) + ans._mon = self._mon ans._poly = self._poly._parent({v.esub(ans._mon): df[v] for v in df}) if new_ring is not None: return new_ring(ans) @@ -3584,7 +3585,6 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): if self._prod is None: self._compute_polydict() - ans = self._new_c() d = self._prod.__repn dr = {} mon = [0] * n @@ -3606,6 +3606,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): for v in dr: dr[v] = self._parent._base(h(dr[v])) + 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}) @@ -3629,29 +3630,37 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): sage: p.toric_substitute((2,3), (-1,1), 2, new_ring=L.change_ring(F)) 3*x^3*y^3 + 2*x^-2*y^-2 """ - cdef dict d, d2 - cdef ETuple ve, v1e, w, w1 + cdef dict d, dr + cdef ETuple ve, v1e, w, w1, mon cdef LaurentPolynomial_mpair ans + + if self._prod is None: + self._compute_polydict() - d = self.dict() - d2 = {} + d = self._prod.__repn + dr = {} ve = ETuple(v) v1e = ETuple(v1) + mon = self._mon if h is not None: + d = dict(d) # Make a copy so we can manipulate it for w in d: d[w] = h(d[w]) for w in d: x = d[w] t = w.dotprod(v1e) w1 = w.eadd(ve.emul(-t)) - if w1 in d2: - d2[w1] += x * a**t + if w1 in dr: + dr[w1] += x * a**t else: - d2[w1] = x * a**t - if new_ring is None: - ans = self._new_c() - ans._prod = PolyDict(d2) - return ans - else: - return new_ring(d2) + dr[w1] = x * a**t + mon = mon.emin(w1) + + ans = self._new_c() + ans._prod = PolyDict(dr) + ans._mon = mon + 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 From 8f0f0cc08964c8ae2bf658f9906bceab62ca376d Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 27 Jul 2020 15:37:23 +1000 Subject: [PATCH 214/217] Speeding up toric_substitute and some other misc improvements to polydict.pyx. --- .../rings/polynomial/laurent_polynomial.pyx | 3 +- src/sage/rings/polynomial/polydict.pxd | 11 ++-- src/sage/rings/polynomial/polydict.pyx | 65 +++++++++++++++---- 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index 21946987100..45d342aa291 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -3633,6 +3633,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): cdef dict d, dr cdef ETuple ve, v1e, w, w1, mon cdef LaurentPolynomial_mpair ans + cdef int t if self._prod is None: self._compute_polydict() @@ -3649,7 +3650,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): for w in d: x = d[w] t = w.dotprod(v1e) - w1 = w.eadd(ve.emul(-t)) + w1 = w.eadd_scaled(ve, -t) if w1 in dr: dr[w1] += x * a**t else: diff --git a/src/sage/rings/polynomial/polydict.pxd b/src/sage/rings/polynomial/polydict.pxd index f466c445082..b2c3145c112 100644 --- a/src/sage/rings/polynomial/polydict.pxd +++ b/src/sage/rings/polynomial/polydict.pxd @@ -1,5 +1,5 @@ cdef class PolyDict: - cdef object __repn + cdef dict __repn cdef object __zero cdef class ETuple: @@ -11,12 +11,13 @@ cdef class ETuple: cdef size_t weighted_degree(self, tuple w) cdef size_t unweighted_quotient_degree(self, ETuple other) cdef size_t weighted_quotient_degree(self, ETuple other, tuple w) - cpdef ETuple eadd(ETuple self, ETuple self) - cpdef ETuple esub(ETuple self, ETuple self) + cpdef ETuple eadd(ETuple self, ETuple other) + cpdef ETuple esub(ETuple self, ETuple other) cpdef ETuple emul(ETuple self, int factor) - cpdef ETuple emin(ETuple self, ETuple self) - cpdef ETuple emax(ETuple self, ETuple self) + cpdef ETuple emin(ETuple self, ETuple other) + cpdef ETuple emax(ETuple self, ETuple other) cpdef ETuple eadd_p(ETuple self, int other, int pos) + cpdef ETuple eadd_scaled(ETuple self, ETuple other, int scalar) cpdef int dotprod(ETuple self, ETuple other) cpdef ETuple escalar_div(ETuple self, int n) cdef ETuple divide_by_gcd(self, ETuple other) diff --git a/src/sage/rings/polynomial/polydict.pyx b/src/sage/rings/polynomial/polydict.pyx index 48567384b9e..a309986fc5d 100644 --- a/src/sage/rings/polynomial/polydict.pyx +++ b/src/sage/rings/polynomial/polydict.pyx @@ -59,14 +59,14 @@ cdef class PolyDict: """ INPUT: - - ``pdict`` -- dict or list, which represents a multi-variable polynomial with - the distribute representation (a copy is not made) + - ``pdict`` -- dict or list, which represents a multi-variable + polynomial with the distribute representation (a copy is not made) - ``zero`` -- (optional) zero in the base ring - ``force_int_exponents`` -- bool (optional) arithmetic with int exponents is much faster than some of the alternatives, so this is - True by default. + ``True`` by default - ``force_etuples`` -- bool (optional) enforce that the exponent tuples are instances of ETuple class @@ -87,23 +87,25 @@ cdef class PolyDict: sage: PolyDict({(0,0):RIF(-1,1)}, remove_zero=True) PolyDict with representation {(0, 0): 0.?} """ + cdef dict v + if not isinstance(pdict, dict): if isinstance(pdict, list): v = {} - for w in pdict: + L = pdict + for w in L: if w[0] != 0: v[ETuple(w[1])] = w[0] remove_zero = False pdict = v else: - raise TypeError("pdict must be a list.") + raise TypeError("pdict must be a list") if isinstance(pdict, dict) and force_etuples is True: - pdict2 = [] - for k, v in pdict.iteritems(): - pdict2.append((ETuple(k), v)) - - pdict = dict(pdict2) + v = pdict + pdict = {} + for k, val in v.iteritems(): + pdict[ETuple(k)] = val if force_int_exponents: new_pdict = {} @@ -120,7 +122,7 @@ cdef class PolyDict: for k in list(pdict): if pdict[k] == zero: del pdict[k] - self.__repn = pdict + self.__repn = pdict self.__zero = zero def __hash__(self): @@ -1720,6 +1722,45 @@ cdef class ETuple: return result + cpdef ETuple eadd_scaled(ETuple self, ETuple other, int scalar): + """ + Vector addition of ``self`` with ``scalar * other``. + + EXAMPLES:: + + sage: from sage.rings.polynomial.polydict import ETuple + sage: e = ETuple([1,0,2]) + sage: f = ETuple([0,1,1]) + sage: e.eadd_scaled(f, 3) + (1, 3, 5) + """ + if self._length != other._length: + raise ArithmeticError + + cdef size_t ind1 = 0 + cdef size_t ind2 = 0 + cdef size_t index + cdef int exp1 + cdef int exp2 + cdef int s # sum + cdef size_t alloc_len = self._nonzero + other._nonzero # we simply guesstimate the length -- there might be double the correct amount allocated -- who cares? + if alloc_len > self._length: + alloc_len = self._length + cdef ETuple result = self._new() + result._nonzero = 0 # we don't know the correct length quite yet + result._data = sig_malloc(sizeof(int)*alloc_len*2) + while dual_etuple_iter(self, other, &ind1, &ind2, &index, &exp1, &exp2): + exp2 *= scalar + s = exp1 + exp2 + # Check for overflow and underflow + if (exp2 > 0 and s < exp1) or (exp2 < 0 and s > exp1): + raise OverflowError("exponent overflow (%s)" % (int(exp1)+int(exp2))) + if s != 0: + result._data[2*result._nonzero] = index + result._data[2*result._nonzero+1] = s + result._nonzero += 1 + return result + cpdef ETuple esub(ETuple self, ETuple other): """ Vector subtraction of ``self`` with ``other``. @@ -1751,7 +1792,7 @@ cdef class ETuple: # Check for overflow and underflow d = exp1 - exp2 if (exp2 > 0 and d > exp1) or (exp2 < 0 and d < exp1): - raise OverflowError("Exponent overflow (%s)." % (int(exp1)-int(exp2))) + raise OverflowError("Exponent overflow (%s)" % (int(exp1)-int(exp2))) if d != 0: result._data[2*result._nonzero] = index result._data[2*result._nonzero+1] = d From 28dec692737c1ce7e9fadb753ff3b8b1c378d4c2 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Mon, 27 Jul 2020 15:37:50 +0200 Subject: [PATCH 215/217] Trac #30191: doctest errors fixed --- .../differentiable/automorphismfield_group.py | 7 ++- .../manifolds/differentiable/mixed_form.py | 16 ++++-- .../differentiable/mixed_form_algebra.py | 49 ++++++++++--------- .../manifolds/differentiable/scalarfield.py | 4 +- src/sage/manifolds/scalarfield.py | 23 ++++++--- src/sage/manifolds/scalarfield_algebra.py | 2 +- src/sage/manifolds/trivialization.py | 10 ++-- 7 files changed, 62 insertions(+), 49 deletions(-) diff --git a/src/sage/manifolds/differentiable/automorphismfield_group.py b/src/sage/manifolds/differentiable/automorphismfield_group.py index 1f55518310c..3c20d70df86 100644 --- a/src/sage/manifolds/differentiable/automorphismfield_group.py +++ b/src/sage/manifolds/differentiable/automorphismfield_group.py @@ -208,12 +208,11 @@ def _element_constructor_(self, comp=[], frame=None, name=None, a = (x^2 + 1) d/dx*dx + (y^2 + 1) d/dy*dy """ - try: + if hasattr(comp, 'is_trivial_zero'): if (comp - 1).is_trivial_zero(): return self.one() - except AttributeError: - if comp == 1: - return self.one() + elif comp == 1: + return self.one() if not isinstance(comp, (list, tuple)): raise TypeError("cannot convert the {} ".format(comp) + "to an element of {}".format(self)) diff --git a/src/sage/manifolds/differentiable/mixed_form.py b/src/sage/manifolds/differentiable/mixed_form.py index 4fabf3111ed..90fcab1430c 100644 --- a/src/sage/manifolds/differentiable/mixed_form.py +++ b/src/sage/manifolds/differentiable/mixed_form.py @@ -896,11 +896,17 @@ def _lmul_(self, other): y/\(x/\F) = [0] + [x^2*y^2 dx] + [0] """ - # Simple checks: - if other.is_trivial_zero(): - return self.parent().zero() - elif (other - 1).is_trivial_zero(): - return self + try: + if other.is_trivial_zero(): + return self.parent().zero() + if (other - 1).is_trivial_zero(): + return self + except AttributeError: + # in case base ring is not SR: + if other == 0: + return self.parent().zero() + if other == 1: + return self resu = self._new_instance() resu[:] = [other * form for form in self._comp] # Compose name: diff --git a/src/sage/manifolds/differentiable/mixed_form_algebra.py b/src/sage/manifolds/differentiable/mixed_form_algebra.py index e2bef4d16df..5edb7b22955 100644 --- a/src/sage/manifolds/differentiable/mixed_form_algebra.py +++ b/src/sage/manifolds/differentiable/mixed_form_algebra.py @@ -33,8 +33,8 @@ class MixedFormAlgebra(Parent, UniqueRepresentation): r""" An instance of this class represents the graded algebra of mixed form. That - is, if `\varphi: M \to N` is a differentiable map between two differentiable - manifolds `M` and `N`, the *graded algebra of mixed forms* + is, if `\varphi: M \to N` is a differentiable map between two + differentiable manifolds `M` and `N`, the *graded algebra of mixed forms* `\Omega^*(M,\varphi)` *along* `\varphi` is defined via the direct sum `\bigoplus^{n}_{j=0} \Omega^j(M,\varphi)` consisting of differential form modules @@ -112,8 +112,8 @@ class MixedFormAlgebra(Parent, UniqueRepresentation): sage: U = M.open_subset('U'); U Open subset U of the 3-dimensional differentiable manifold M sage: OmegaU = U.mixed_form_algebra(); OmegaU - Graded algebra Omega^*(U) of mixed differential forms on the Open subset - U of the 3-dimensional differentiable manifold M + Graded algebra Omega^*(U) of mixed differential forms on the Open + subset U of the 3-dimensional differentiable manifold M sage: OmegaU.has_coerce_map_from(Omega) True @@ -137,8 +137,8 @@ def __init__(self, vector_field_module): ....: intersection_name='W', restrictions1= x>0, ....: restrictions2= u+v>0) sage: inv = transf.inverse() - sage: from sage.manifolds.differentiable.mixed_form_algebra import ( - ....: MixedFormAlgebra) + sage: from sage.manifolds.differentiable.mixed_form_algebra \ + ....: import MixedFormAlgebra sage: A = MixedFormAlgebra(M.vector_field_module()) sage: TestSuite(A).run() @@ -174,7 +174,7 @@ def __init__(self, vector_field_module): self._vmodule = vector_field_module self._max_deg = vector_field_module._ambient_domain.dim() - def _element_constructor_(self, comp=None, name=None, latex_name=None): + def _element_constructor_(self, comp, name=None, latex_name=None): r""" Construct a mixed form. @@ -193,7 +193,7 @@ def _element_constructor_(self, comp=None, name=None, latex_name=None): try: if comp.is_trivial_zero(): return self.zero() - if (comp - 1).is_trivial_zero(): + elif (comp - 1).is_trivial_zero(): return self.one() except AttributeError: if comp == 0: @@ -201,29 +201,27 @@ def _element_constructor_(self, comp=None, name=None, latex_name=None): if comp == 1: return self.one() res = self.element_class(self, name=name, latex_name=latex_name) - if comp is None: - return res - elif isinstance(comp, (tuple, list)): + if isinstance(comp, (tuple, list)): if len(comp) != self._max_deg + 1: raise IndexError("input list must have " "length {}".format(self._max_deg + 1)) if isinstance(comp, tuple): comp = list(comp) res[:] = comp[:] - elif isinstance(comp, self.Element): - res[:] = comp[:] else: for d in self.irange(): - dmodule = self._domain.diff_form_module(d, dest_map=self._dest_map) + dom = self._domain + dmodule = dom.diff_form_module(d, dest_map=self._dest_map) if dmodule.has_coerce_map_from(comp.parent()): deg = d break else: raise TypeError("cannot convert {} into an element of " "the {}".format(comp, self)) - res[:] = [0] * (self._max_deg + 1) # fill up with zeroes... - res[deg] = comp # ...and set comp at deg of res; - # the coercion is performed here + # fill up with zeroes: + res[:] = [0] * (self._max_deg + 1) + # set comp where it belongs: + res[deg] = comp # coercion is performed here # In case, no other name is given, use name of comp: if name is None: if hasattr(comp, '_name'): @@ -250,7 +248,8 @@ def _an_element_(self): """ res = self.element_class(self) - res[:] = [self._domain.diff_form_module(j, self._dest_map)._an_element_() + dom = self._domain + res[:] = [dom.diff_form_module(j, self._dest_map)._an_element_() for j in self.irange()] return res @@ -283,7 +282,7 @@ def _coerce_map_from_(self, S): if isinstance(S, type(self)): # coercion by domain restriction if (self._domain.is_subset(S._domain) and - self._ambient_domain.is_subset(S._ambient_domain)): + self._ambient_domain.is_subset(S._ambient_domain)): return True # Still, there could be a coerce map if self.irange() != S.irange(): @@ -297,8 +296,9 @@ def _coerce_map_from_(self, S): # Each degree is coercible so there must be a coerce map: return True # Let us check for each degree consecutively: - return any(self._domain.diff_form_module(deg, - self._dest_map).has_coerce_map_from(S) + dom = self._domain + return any(dom.diff_form_module(deg, + self._dest_map).has_coerce_map_from(S) for deg in self.irange()) @cached_method @@ -377,12 +377,13 @@ def _repr_(self): 3-dimensional differentiable manifold M """ - desc = ("Graded algebra " + self._name + " of mixed differential forms ") + desc = "Graded algebra " + self._name + desc += " of mixed differential forms " if self._dest_map is self._domain.identity_map(): desc += "on the {}".format(self._domain) else: - desc += "along the {} mapped into the {} ".format(self._domain, - self._ambient_domain) + desc += "along the {} mapped ".format(self._domain) + desc += "into the {} ".format(self._ambient_domain) if self._dest_map._name is None: dm_name = "unnamed map" else: diff --git a/src/sage/manifolds/differentiable/scalarfield.py b/src/sage/manifolds/differentiable/scalarfield.py index e8f7ae76a19..58b643bed5f 100644 --- a/src/sage/manifolds/differentiable/scalarfield.py +++ b/src/sage/manifolds/differentiable/scalarfield.py @@ -392,9 +392,9 @@ class DiffScalarField(ScalarField): field:: sage: s = f + 1 ; s - Scalar field on the 2-dimensional differentiable manifold M + Scalar field f+1 on the 2-dimensional differentiable manifold M sage: s.display() - M --> R + f+1: M --> R on U: (x, y) |--> (x^2 + y^2 + 2)/(x^2 + y^2 + 1) on V: (u, v) |--> (2*u^2 + 2*v^2 + 1)/(u^2 + v^2 + 1) sage: (f+1)-1 == f diff --git a/src/sage/manifolds/scalarfield.py b/src/sage/manifolds/scalarfield.py index 2aff1211fd0..8035b792acb 100644 --- a/src/sage/manifolds/scalarfield.py +++ b/src/sage/manifolds/scalarfield.py @@ -391,9 +391,9 @@ class ScalarField(CommutativeAlgebraElement): field:: sage: s = f + 1 ; s - Scalar field on the 2-dimensional topological manifold M + Scalar field f+1 on the 2-dimensional topological manifold M sage: s.display() - M --> R + f+1: M --> R on U: (x, y) |--> (x^2 + y^2 + 2)/(x^2 + y^2 + 1) on V: (u, v) |--> (2*u^2 + 2*v^2 + 1)/(u^2 + v^2 + 1) sage: (f+1)-1 == f @@ -850,9 +850,9 @@ class ScalarField(CommutativeAlgebraElement): field:: sage: s = f + 1 ; s - Scalar field on the 2-dimensional topological manifold M + Scalar field f+1 on the 2-dimensional topological manifold M sage: s.display() - M --> R + f+1: M --> R on U: (x, y) |--> (x**2 + y**2 + 2)/(x**2 + y**2 + 1) on V: (u, v) |--> (2*u**2 + 2*v**2 + 1)/(u**2 + v**2 + 1) sage: (f+1)-1 == f @@ -2663,10 +2663,17 @@ def _lmul_(self, number): True """ - if number.is_trivial_zero(): - return self.parent().zero() - if (number - 1).is_trivial_zero(): - return self.parent().one() + try: + if number.is_trivial_zero(): + return self.parent().zero() + if (number - 1).is_trivial_zero(): + return self + except AttributeError: + # in case base ring is not SR: + if number == 0: + return self.parent().zero() + if number == 1: + return self result = type(self)(self.parent()) if isinstance(number, Expression): var = number.variables() # possible symbolic variables in number diff --git a/src/sage/manifolds/scalarfield_algebra.py b/src/sage/manifolds/scalarfield_algebra.py index e68220955f1..e5eed57d2fd 100644 --- a/src/sage/manifolds/scalarfield_algebra.py +++ b/src/sage/manifolds/scalarfield_algebra.py @@ -454,7 +454,7 @@ def _element_constructor_(self, coord_expression=None, chart=None, try: if coord_expression.is_trivial_zero(): return self.zero() - if (coord_expression - 1).is_trivial_zero(): + elif (coord_expression - 1).is_trivial_zero(): return self.one() except AttributeError: if coord_expression == 0: diff --git a/src/sage/manifolds/trivialization.py b/src/sage/manifolds/trivialization.py index bac36a2a2c9..ac18adb9099 100644 --- a/src/sage/manifolds/trivialization.py +++ b/src/sage/manifolds/trivialization.py @@ -665,9 +665,9 @@ def matrix(self): sage: phi_U_to_phi_V = phi_U.transition_map(phi_V, [[0,1],[1,0]]) sage: matrix = phi_U_to_phi_V.matrix(); matrix [Scalar field zero on the Open subset W of the 2-dimensional - topological manifold S^2 Scalar field on the Open subset W of - the 2-dimensional topological manifold S^2] - [ Scalar field on the Open subset W of the 2-dimensional + topological manifold S^2 Scalar field 1 on the Open subset + W of the 2-dimensional topological manifold S^2] + [ Scalar field 1 on the Open subset W of the 2-dimensional topological manifold S^2 Scalar field zero on the Open subset W of the 2-dimensional topological manifold S^2] @@ -678,11 +678,11 @@ def matrix(self): (x, y) |--> 0 (u, v) |--> 0 sage: matrix[0,1].display() - W --> R + 1: W --> R (x, y) |--> 1 (u, v) |--> 1 sage: matrix[1,0].display() - W --> R + 1: W --> R (x, y) |--> 1 (u, v) |--> 1 sage: matrix[1,1].display() From afb1d8c246e970d0c43a8bef016903c2f711e4fb Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Mon, 27 Jul 2020 16:55:32 -0700 Subject: [PATCH 216/217] Docstring edits --- .../rings/polynomial/laurent_polynomial_ideal.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial_ideal.py b/src/sage/rings/polynomial/laurent_polynomial_ideal.py index d7f9e932390..886458ff1ed 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_ideal.py +++ b/src/sage/rings/polynomial/laurent_polynomial_ideal.py @@ -31,8 +31,8 @@ def __init__(self, ring, gens, coerce=True, hint=None): Create an ideal in a Laurent polynomial ring. To compute structural properties of an ideal in the Laurent polynomial ring - `R[x_1^{\pm},\dots,x_n^{\pm}]`, we form the corresponding ideal in the - associated ordinary polynomial ring `R[x_1,\dots,x_n]` which is saturated + `R[x_1^{\pm},\ldots,x_n^{\pm}]`, we form the corresponding ideal in the + associated ordinary polynomial ring `R[x_1,\ldots,x_n]` which is saturated with respect to the ideal `(x_1 \cdots x_n)`. Since computing the saturation can be expensive, we employ some strategies to reduce the need for it. @@ -46,11 +46,10 @@ def __init__(self, ring, gens, coerce=True, hint=None): INPUT: - - ``ring`` - the ring the ideal is defined in - - - ``gens`` - a list of generators for the ideal - - - ``coerce`` - coerce elements to the ring ``ring``? + - ``ring`` -- the ring the ideal is defined in + - ``gens`` -- a list of generators for the ideal + - ``coerce`` -- whether or not to coerce elements into ``ring`` + - ``hint`` -- an ideal in the associated polynomial ring (optional; see above) EXAMPLES:: From 83caa4befae463aa5db739041ff9172a8800f64c Mon Sep 17 00:00:00 2001 From: Release Manager Date: Sun, 2 Aug 2020 19:45:46 +0200 Subject: [PATCH 217/217] Updated SageMath version to 9.2.beta7 --- VERSION.txt | 2 +- build/pkgs/configure/checksums.ini | 6 +++--- build/pkgs/configure/package-version.txt | 2 +- build/pkgs/sagelib/package-version.txt | 2 +- src/bin/sage-version.sh | 6 +++--- src/sage/version.py | 6 +++--- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index a2da42a97e3..1e13779e143 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 9.2.beta6, Release Date: 2020-07-25 +SageMath version 9.2.beta7, Release Date: 2020-08-02 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index d2a7ac8f76d..257b9c40744 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=9d04a7066f0c543084ac8249cb280c86d2bf867d -md5=ac1516d0c732111da045ff977b68230c -cksum=2699179254 +sha1=450767d58fcd094130bcc0bae6a17340adde685f +md5=fc57202cf758c74e29dcf906e0287859 +cksum=4241511310 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 651f8b20af5..22939da2abf 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -ddd5258c401e17c0ecfb66bdf0b294133abbb4b9 +acf026331eeef4295aebdf3cdef0a0f5c2bdd19e diff --git a/build/pkgs/sagelib/package-version.txt b/build/pkgs/sagelib/package-version.txt index ced95177443..14514c94332 100644 --- a/build/pkgs/sagelib/package-version.txt +++ b/build/pkgs/sagelib/package-version.txt @@ -1 +1 @@ -9.2.beta6 +9.2.beta7 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index 055dfda229b..1fac24a2111 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -1,5 +1,5 @@ # Sage version information for shell scripts # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='9.2.beta6' -SAGE_RELEASE_DATE='2020-07-25' -SAGE_VERSION_BANNER='SageMath version 9.2.beta6, Release Date: 2020-07-25' +SAGE_VERSION='9.2.beta7' +SAGE_RELEASE_DATE='2020-08-02' +SAGE_VERSION_BANNER='SageMath version 9.2.beta7, Release Date: 2020-08-02' diff --git a/src/sage/version.py b/src/sage/version.py index 1c864c35436..fd9df52e561 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '9.2.beta6' -date = '2020-07-25' -banner = 'SageMath version 9.2.beta6, Release Date: 2020-07-25' +version = '9.2.beta7' +date = '2020-08-02' +banner = 'SageMath version 9.2.beta7, Release Date: 2020-08-02'