diff --git a/COPYING.txt b/COPYING.txt index e0a41011c88..66c2e7fb438 100644 --- a/COPYING.txt +++ b/COPYING.txt @@ -88,6 +88,7 @@ pari GPLv2+ patch GPLv2+ pexpect Python License pillow Apache License 2.0 +pip MIT License pkgconf ISC License (equivalent to Simplified BSD) pkgconfig MIT License polybori GPLv2+ diff --git a/VERSION.txt b/VERSION.txt index 4afc69a93ce..1eb6787b435 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -Sage version 6.5.beta2, released 2014-12-04 +Sage version 6.5.beta3, released 2014-12-18 diff --git a/build/deps b/build/deps index 1d813da63bb..afb6f3c9947 100644 --- a/build/deps +++ b/build/deps @@ -79,6 +79,7 @@ all-sage: \ $(INST)/$(PARI) \ $(INST)/$(PEXPECT) \ $(INST)/$(PILLOW) \ + $(INST)/$(PIP) \ $(INST)/$(PKGCONF) \ $(INST)/$(PKGCONFIG) \ $(INST)/$(POLYBORI) \ @@ -243,6 +244,9 @@ $(INST)/$(PARI_GALDATA): $(INST)/$(PARI_SEADATA_SMALL): +$(PIPE) "$(SAGE_SPKG) $(PARI_SEADATA_SMALL) 2>&1" "tee -a $(SAGE_LOGS)/$(PARI_SEADATA_SMALL).log" +$(INST)/$(PIP): $(INST)/$(PYTHON) $(INST)/$(SETUPTOOLS) + +$(PIPE) "$(SAGE_SPKG) $(PIP) 2>&1" "tee -a $(SAGE_LOGS)/$(PIP).log" + $(INST)/$(POLYBORI): $(INST)/$(PYTHON) $(INST)/$(IPYTHON) \ $(INST)/$(SCONS) $(INST)/$(BOOST_CROPPED) \ $(INST)/$(M4RI) $(INST)/$(GD) diff --git a/build/install b/build/install index 2c290ba6548..7c689a2aabd 100755 --- a/build/install +++ b/build/install @@ -328,6 +328,7 @@ PARI_SEADATA_SMALL=`newest_version pari_seadata_small` PATCH=`newest_version patch` PEXPECT=`newest_version pexpect` PILLOW=`newest_version pillow` +PIP=`newest_version pip` PKGCONF=`newest_version pkgconf` PKGCONFIG=`newest_version pkgconfig` POLYBORI=`newest_version polybori` diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 9914cf6bbdb..1c0d65aacc8 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=0f967b9ca98cae14812330184bc194d856061516 -md5=c0e386d4c47d2c67b0539a887b854374 -cksum=2809241126 +sha1=7df2518840c5f58481a970d8b1de534ca54fe928 +md5=9e2fdde9e4a7f182e4487bcb973ee044 +cksum=1438863796 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index abdfb053e41..b1e7d265fcc 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -60 +61 diff --git a/build/pkgs/fricas/SPKG.txt b/build/pkgs/fricas/SPKG.txt new file mode 100644 index 00000000000..32fc0067717 --- /dev/null +++ b/build/pkgs/fricas/SPKG.txt @@ -0,0 +1,20 @@ += fricas = + +== Description == + +This package install the software fricas. + +== License == + +Modified BSD license. + +== Upstream Contact == + +http://fricas.sourceforge.net/ + +== Dependencies == + +Put a bulleted list of dependencies here: + +* ecl + diff --git a/build/pkgs/fricas/checksums.ini b/build/pkgs/fricas/checksums.ini new file mode 100644 index 00000000000..a71ad016624 --- /dev/null +++ b/build/pkgs/fricas/checksums.ini @@ -0,0 +1,4 @@ +tarball=fricas-VERSION.tar.bz2 +sha1=689b3e474579655b76686a56a1928ef411cb179b +md5=ba4f3927d93f49b0d866e5e80fc5bf18 +cksum=2927195574 diff --git a/build/pkgs/fricas/package-version.txt b/build/pkgs/fricas/package-version.txt new file mode 100644 index 00000000000..e8ea05db814 --- /dev/null +++ b/build/pkgs/fricas/package-version.txt @@ -0,0 +1 @@ +1.2.4 diff --git a/build/pkgs/fricas/spkg-install b/build/pkgs/fricas/spkg-install new file mode 100755 index 00000000000..b88f37b1d34 --- /dev/null +++ b/build/pkgs/fricas/spkg-install @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +cd src + +./configure --prefix="$SAGE_LOCAL" \ + --libdir="$SAGE_LOCAL/lib" \ + --with-lisp=ecl + +if [ $? -ne 0 ]; then + echo >&2 "Error configuring fricas." + exit 1 +fi + +$MAKE +if [ $? -ne 0 ]; then + echo >&2 "Error building fricas." + exit 1 +fi + +$MAKE -j1 install +if [ $? -ne 0 ]; then + echo >&2 "Error installing fricas." + exit 1 +fi diff --git a/build/pkgs/iml/SPKG.txt b/build/pkgs/iml/SPKG.txt index b1bfe7438d1..88c3e68ab00 100644 --- a/build/pkgs/iml/SPKG.txt +++ b/build/pkgs/iml/SPKG.txt @@ -22,13 +22,14 @@ Website: http://www.cs.uwaterloo.ca/~astorjoh/iml.html * Arne Storjohann astorjoh@uwaterloo.ca == Dependencies == - * GMP/MPIR + * GMP * ATLAS == Special Update/Build Instructions == - * Various files should be made executable. Run spkg-src after - extracting the sources to src/ to fix this. + * As of version 1.0.4, you need to repackage the upstream tarball + using the spkg-src script because there was a bugfix version of 1.0.4 + reposted upstream without version number bump. === Patches === diff --git a/build/pkgs/iml/checksums.ini b/build/pkgs/iml/checksums.ini index a8b36a10f71..01b215549c7 100644 --- a/build/pkgs/iml/checksums.ini +++ b/build/pkgs/iml/checksums.ini @@ -1,4 +1,4 @@ tarball=iml-VERSION.tar.bz2 -sha1=713a19f1076ddde07a7c3a45493440b745bd266b -md5=b5958c8d6ba89fff96ee82af6854cf7d -cksum=3114321274 +sha1=72355b1f4c4df8cd3ecf5fcbcbd72c9ad9afdba7 +md5=362f1a6a1d2df0c5f0ab41e5d2c87ac7 +cksum=507867168 diff --git a/build/pkgs/iml/package-version.txt b/build/pkgs/iml/package-version.txt index ee90284c27f..03f0209fbb3 100644 --- a/build/pkgs/iml/package-version.txt +++ b/build/pkgs/iml/package-version.txt @@ -1 +1 @@ -1.0.4 +1.0.4p1 diff --git a/build/pkgs/iml/spkg-install b/build/pkgs/iml/spkg-install index 79406956469..5f6986599a0 100755 --- a/build/pkgs/iml/spkg-install +++ b/build/pkgs/iml/spkg-install @@ -31,15 +31,12 @@ if [ "$SAGE64" = "yes" ]; then CFLAGS="-m64 $CFLAGS" fi -EXTRA_BLAS="" if [ $UNAME = "Darwin" ]; then - # copy cblas headers from gsl - cp ../patches/gsl_cblas.h cblas.h - EXTRA_BLAS="--with-cblas=-lcblas" + IML_CONFIGURE="--with-cblas=-lcblas $IML_CONFIGURE" fi ./configure --prefix="$SAGE_LOCAL" --libdir="$SAGE_LOCAL/lib" \ - --enable-shared --with-default="$SAGE_LOCAL" "$EXTRA_BLAS" + --enable-shared --with-default="$SAGE_LOCAL" "$IML_CONFIGURE" if [ $? -ne 0 ]; then echo >&2 "Error configuring IML." exit 1 diff --git a/build/pkgs/iml/spkg-src b/build/pkgs/iml/spkg-src new file mode 100755 index 00000000000..fc299e09315 --- /dev/null +++ b/build/pkgs/iml/spkg-src @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +VERSION="1.0.4" +PATCHLEVEL="p1" + +if [ $# -ne 0 ]; then + UPSTREAM_SOURCE_DIRECTORY=$1 + echo "Using tarballs from $UPSTREAM_SOURCE_DIRECTORY instead of downloading" +fi + +SPKG_ROOT=`pwd` + +set -e +shopt -s extglob + +# Download sources +URL="http://www.cs.uwaterloo.ca/~astorjoh/" +if [ -z "$UPSTREAM_SOURCE_DIRECTORY" ]; then + tar xjf <( curl -L "$URL/iml-$VERSION.tar.bz2" ) +else + tar xjf "$UPSTREAM_SOURCE_DIRECTORY/iml-$VERSION.tar.bz2" +fi + +mv "iml-$VERSION" "iml-$VERSION$PATCHLEVEL" +tar cjf "iml-$VERSION$PATCHLEVEL.tar.bz2" "iml-$VERSION$PATCHLEVEL" diff --git a/build/pkgs/ipython/package-version.txt b/build/pkgs/ipython/package-version.txt index 276cbf9e285..a0ffc34b8f6 100644 --- a/build/pkgs/ipython/package-version.txt +++ b/build/pkgs/ipython/package-version.txt @@ -1 +1 @@ -2.3.0 +2.3.0.p0 diff --git a/build/pkgs/ipython/patches/ultratb-master.patch b/build/pkgs/ipython/patches/ultratb-master.patch new file mode 100644 index 00000000000..dd50aacb6ad --- /dev/null +++ b/build/pkgs/ipython/patches/ultratb-master.patch @@ -0,0 +1,1022 @@ +Trac #17382: upgrade the whole file ultratb.py to latest git master + +--- a/IPython/core/ultratb.py 2014-10-02 01:55:50.000000000 +0200 ++++ b/IPython/core/ultratb.py 2014-12-06 10:59:11.228558666 +0100 +@@ -39,7 +39,7 @@ + Verbose). + + +-Installation instructions for ColorTB:: ++Installation instructions for VerboseTB:: + + import sys,ultratb + sys.excepthook = ultratb.VerboseTB() +@@ -73,11 +73,11 @@ + """ + + #***************************************************************************** +-# Copyright (C) 2001 Nathaniel Gray +-# Copyright (C) 2001-2004 Fernando Perez ++# Copyright (C) 2001 Nathaniel Gray ++# Copyright (C) 2001-2004 Fernando Perez + # +-# Distributed under the terms of the BSD License. The full license is in +-# the file COPYING, distributed as part of this software. ++# Distributed under the terms of the BSD License. The full license is in ++# the file COPYING, distributed as part of this software. + #***************************************************************************** + + from __future__ import unicode_literals +@@ -95,14 +95,14 @@ + import traceback + import types + +-try: # Python 2 ++try: # Python 2 + generate_tokens = tokenize.generate_tokens +-except AttributeError: # Python 3 ++except AttributeError: # Python 3 + generate_tokens = tokenize.tokenize + + # For purposes of monkeypatching inspect to fix a bug in it. +-from inspect import getsourcefile, getfile, getmodule,\ +- ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode ++from inspect import getsourcefile, getfile, getmodule, \ ++ ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode + + # IPython's own modules + # Modified pdb which doesn't damage IPython's readline handling +@@ -125,11 +125,11 @@ + + # Default color scheme. This is used, for example, by the traceback + # formatter. When running in an actual IPython instance, the user's rc.colors +-# value is used, but havinga module global makes this functionality available ++# value is used, but having a module global makes this functionality available + # to users of ultratb who are NOT running inside ipython. + DEFAULT_SCHEME = 'NoColor' + +-#--------------------------------------------------------------------------- ++# --------------------------------------------------------------------------- + # Code begins + + # Utility functions +@@ -141,6 +141,7 @@ + error('Internal Python error in the inspect module.\n' + 'Below is the traceback from this internal error.\n') + ++ + # This function is a monkeypatch we apply to the Python inspect module. We have + # now found when it's needed (see discussion on issue gh-1456), and we have a + # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if +@@ -212,7 +213,7 @@ + pmatch = pat.match + # fperez - fix: sometimes, co_firstlineno can give a number larger than + # the length of lines, which causes an error. Safeguard against that. +- lnum = min(object.co_firstlineno,len(lines))-1 ++ lnum = min(object.co_firstlineno, len(lines)) - 1 + while lnum > 0: + if pmatch(lines[lnum]): break + lnum -= 1 +@@ -220,9 +221,11 @@ + return lines, lnum + raise IOError('could not find code object') + ++ + # Monkeypatch inspect to apply our bugfix. + def with_patch_inspect(f): + """decorator for monkeypatching inspect.findsource""" ++ + def wrapped(*args, **kwargs): + save_findsource = inspect.findsource + inspect.findsource = findsource +@@ -230,8 +233,10 @@ + return f(*args, **kwargs) + finally: + inspect.findsource = save_findsource ++ + return wrapped + ++ + def fix_frame_records_filenames(records): + """Try to fix the filenames in each record from inspect.getinnerframes(). + +@@ -240,24 +245,25 @@ + """ + fixed_records = [] + for frame, filename, line_no, func_name, lines, index in records: +- # Look inside the frame's globals dictionary for __file__, which should +- # be better. +- better_fn = frame.f_globals.get('__file__', None) +- if isinstance(better_fn, str): +- # Check the type just in case someone did something weird with +- # __file__. It might also be None if the error occurred during +- # import. +- filename = better_fn ++ # Look inside the frame's globals dictionary for __file__, ++ # which should be better. However, keep Cython filenames since ++ # we prefer the source filenames over the compiled .so file. ++ if not filename.endswith(('.pyx', '.pxd', '.pxi')): ++ better_fn = frame.f_globals.get('__file__', None) ++ if isinstance(better_fn, str): ++ # Check the type just in case someone did something weird with ++ # __file__. It might also be None if the error occurred during ++ # import. ++ filename = better_fn + fixed_records.append((frame, filename, line_no, func_name, lines, index)) + return fixed_records + + + @with_patch_inspect +-def _fixed_getinnerframes(etb, context=1,tb_offset=0): +- LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5 +- +- records = fix_frame_records_filenames(inspect.getinnerframes(etb, context)) ++def _fixed_getinnerframes(etb, context=1, tb_offset=0): ++ LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5 + ++ records = fix_frame_records_filenames(inspect.getinnerframes(etb, context)) + # If the error is at the console, don't build any context, since it would + # otherwise produce 5 blank lines printed out (there is no file at the + # console) +@@ -272,9 +278,9 @@ + aux = traceback.extract_tb(etb) + assert len(records) == len(aux) + for i, (file, lnum, _, _) in zip(range(len(records)), aux): +- maybeStart = lnum-1 - context//2 +- start = max(maybeStart, 0) +- end = start + context ++ maybeStart = lnum - 1 - context // 2 ++ start = max(maybeStart, 0) ++ end = start + context + lines = ulinecache.getlines(file)[start:end] + buf = list(records[i]) + buf[LNUM_POS] = lnum +@@ -290,7 +296,8 @@ + + _parser = PyColorize.Parser() + +-def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None): ++ ++def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, scheme=None): + numbers_width = INDENT_SIZE - 1 + res = [] + i = lnum - index +@@ -315,7 +322,7 @@ + # This is the line with the error + pad = numbers_width - len(str(i)) + if pad >= 3: +- marker = '-'*(pad-3) + '-> ' ++ marker = '-' * (pad - 3) + '-> ' + elif pad == 2: + marker = '> ' + elif pad == 1: +@@ -323,12 +330,12 @@ + else: + marker = '' + num = marker + str(i) +- line = '%s%s%s %s%s' %(Colors.linenoEm, num, +- Colors.line, line, Colors.Normal) ++ line = '%s%s%s %s%s' % (Colors.linenoEm, num, ++ Colors.line, line, Colors.Normal) + else: +- num = '%*s' % (numbers_width,i) +- line = '%s%s%s %s' %(Colors.lineno, num, +- Colors.Normal, line) ++ num = '%*s' % (numbers_width, i) ++ line = '%s%s%s %s' % (Colors.lineno, num, ++ Colors.Normal, line) + + res.append(line) + if lvals and i == lnum: +@@ -389,16 +396,16 @@ + + ostream = property(_get_ostream, _set_ostream) + +- def set_colors(self,*args,**kw): ++ def set_colors(self, *args, **kw): + """Shorthand access to the color table scheme selector method.""" + + # Set own color table +- self.color_scheme_table.set_active_scheme(*args,**kw) ++ self.color_scheme_table.set_active_scheme(*args, **kw) + # for convenience, set Colors to the active scheme + self.Colors = self.color_scheme_table.active_colors + # Also set colors of debugger +- if hasattr(self,'pdb') and self.pdb is not None: +- self.pdb.set_colors(*args,**kw) ++ if hasattr(self, 'pdb') and self.pdb is not None: ++ self.pdb.set_colors(*args, **kw) + + def color_toggle(self): + """Toggle between the currently active color scheme and NoColor.""" +@@ -453,7 +460,7 @@ + Because they are meant to be called without a full traceback (only a + list), instances of this class can't call the interactive pdb debugger.""" + +- def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None): ++ def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None): + TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, + ostream=ostream) + +@@ -497,7 +504,7 @@ + elist = elist[tb_offset:] + + out_list.append('Traceback %s(most recent call last)%s:' % +- (Colors.normalEm, Colors.Normal) + '\n') ++ (Colors.normalEm, Colors.Normal) + '\n') + out_list.extend(self._format_list(elist)) + # The exception info should be a single entry in the list. + lines = ''.join(self._format_exception_only(etype, value)) +@@ -510,7 +517,7 @@ + ## out_list.append(lines[-1]) + + # This means it was indenting everything but the last line by a little +- # bit. I've disabled this for now, but if we see ugliness somewhre we ++ # bit. I've disabled this for now, but if we see ugliness somewhere we + # can restore it. + + return out_list +@@ -532,25 +539,24 @@ + list = [] + for filename, lineno, name, line in extracted_list[:-1]: + item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \ +- (Colors.filename, filename, Colors.Normal, +- Colors.lineno, lineno, Colors.Normal, +- Colors.name, name, Colors.Normal) ++ (Colors.filename, filename, Colors.Normal, ++ Colors.lineno, lineno, Colors.Normal, ++ Colors.name, name, Colors.Normal) + if line: + item += ' %s\n' % line.strip() + list.append(item) + # Emphasize the last entry + filename, lineno, name, line = extracted_list[-1] + item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \ +- (Colors.normalEm, +- Colors.filenameEm, filename, Colors.normalEm, +- Colors.linenoEm, lineno, Colors.normalEm, +- Colors.nameEm, name, Colors.normalEm, +- Colors.Normal) ++ (Colors.normalEm, ++ Colors.filenameEm, filename, Colors.normalEm, ++ Colors.linenoEm, lineno, Colors.normalEm, ++ Colors.nameEm, name, Colors.normalEm, ++ Colors.Normal) + if line: + item += '%s %s%s\n' % (Colors.line, line.strip(), +- Colors.Normal) ++ Colors.Normal) + list.append(item) +- #from pprint import pformat; print 'LISTTB', pformat(list) # dbg + return list + + def _format_exception_only(self, etype, value): +@@ -572,11 +578,10 @@ + stype = Colors.excName + etype.__name__ + Colors.Normal + if value is None: + # Not sure if this can still happen in Python 2.6 and above +- list.append( py3compat.cast_unicode(stype) + '\n') ++ list.append(py3compat.cast_unicode(stype) + '\n') + else: + if issubclass(etype, SyntaxError): + have_filedata = True +- #print 'filename is',filename # dbg + if not value.filename: value.filename = "" + if value.lineno: + lineno = value.lineno +@@ -585,9 +590,9 @@ + lineno = 'unknown' + textline = '' + list.append('%s File %s"%s"%s, line %s%s%s\n' % \ +- (Colors.normalEm, +- Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm, +- Colors.linenoEm, lineno, Colors.Normal )) ++ (Colors.normalEm, ++ Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm, ++ Colors.linenoEm, lineno, Colors.Normal )) + if textline == '': + textline = py3compat.cast_unicode(value.text, "utf-8") + +@@ -600,13 +605,13 @@ + Colors.Normal)) + if value.offset is not None: + s = ' ' +- for c in textline[i:value.offset-1]: ++ for c in textline[i:value.offset - 1]: + if c.isspace(): + s += c + else: + s += ' ' + list.append('%s%s^%s\n' % (Colors.caret, s, +- Colors.Normal) ) ++ Colors.Normal)) + + try: + s = value.msg +@@ -636,7 +641,6 @@ + """ + return ListTB.structured_traceback(self, etype, value, []) + +- + def show_exception_only(self, etype, evalue): + """Only print the exception type and message, without a traceback. + +@@ -659,6 +663,7 @@ + except: + return '' % type(value).__name__ + ++ + #---------------------------------------------------------------------------- + class VerboseTB(TBTools): + """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead +@@ -668,7 +673,7 @@ + traceback, to be used with alternate interpreters (because their own code + would appear in the traceback).""" + +- def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None, ++ def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None, + tb_offset=0, long_header=False, include_vars=True, + check_cache=None): + """Specify traceback offset, headers and color scheme. +@@ -691,132 +696,51 @@ + check_cache = linecache.checkcache + self.check_cache = check_cache + +- def structured_traceback(self, etype, evalue, etb, tb_offset=None, +- context=5): +- """Return a nice text document describing the traceback.""" +- +- tb_offset = self.tb_offset if tb_offset is None else tb_offset +- +- # some locals +- try: +- etype = etype.__name__ +- except AttributeError: +- pass +- Colors = self.Colors # just a shorthand + quicker name lookup +- ColorsNormal = Colors.Normal # used a lot +- col_scheme = self.color_scheme_table.active_scheme_name +- indent = ' '*INDENT_SIZE +- em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal) +- undefined = '%sundefined%s' % (Colors.em, ColorsNormal) +- exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal) +- +- # some internal-use functions +- def text_repr(value): +- """Hopefully pretty robust repr equivalent.""" +- # this is pretty horrible but should always return *something* +- try: +- return pydoc.text.repr(value) +- except KeyboardInterrupt: +- raise +- except: +- try: +- return repr(value) +- except KeyboardInterrupt: +- raise +- except: +- try: +- # all still in an except block so we catch +- # getattr raising +- name = getattr(value, '__name__', None) +- if name: +- # ick, recursion +- return text_repr(name) +- klass = getattr(value, '__class__', None) +- if klass: +- return '%s instance' % text_repr(klass) +- except KeyboardInterrupt: +- raise +- except: +- return 'UNRECOVERABLE REPR FAILURE' +- def eqrepr(value, repr=text_repr): return '=%s' % repr(value) +- def nullrepr(value, repr=text_repr): return '' +- +- # meat of the code begins +- try: +- etype = etype.__name__ +- except AttributeError: +- pass +- +- if self.long_header: +- # Header with the exception type, python version, and date +- pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable +- date = time.ctime(time.time()) +- +- head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal, +- exc, ' '*(75-len(str(etype))-len(pyver)), +- pyver, date.rjust(75) ) +- head += "\nA problem occured executing Python code. Here is the sequence of function"\ +- "\ncalls leading up to the error, with the most recent (innermost) call last." +- else: +- # Simplified header +- head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc, +- 'Traceback (most recent call last)'.\ +- rjust(75 - len(str(etype)) ) ) ++ def format_records(self, records): ++ Colors = self.Colors # just a shorthand + quicker name lookup ++ ColorsNormal = Colors.Normal # used a lot ++ col_scheme = self.color_scheme_table.active_scheme_name ++ indent = ' ' * INDENT_SIZE ++ em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal) ++ undefined = '%sundefined%s' % (Colors.em, ColorsNormal) + frames = [] +- # Flush cache before calling inspect. This helps alleviate some of the +- # problems with python 2.3's inspect.py. +- ##self.check_cache() +- # Drop topmost frames if requested +- try: +- # Try the default getinnerframes and Alex's: Alex's fixes some +- # problems, but it generates empty tracebacks for console errors +- # (5 blanks lines) where none should be returned. +- #records = inspect.getinnerframes(etb, context)[tb_offset:] +- #print 'python records:', records # dbg +- records = _fixed_getinnerframes(etb, context, tb_offset) +- #print 'alex records:', records # dbg +- except: +- +- # FIXME: I've been getting many crash reports from python 2.3 +- # users, traceable to inspect.py. If I can find a small test-case +- # to reproduce this, I should either write a better workaround or +- # file a bug report against inspect (if that's the real problem). +- # So far, I haven't been able to find an isolated example to +- # reproduce the problem. +- inspect_error() +- traceback.print_exc(file=self.ostream) +- info('\nUnfortunately, your original traceback can not be constructed.\n') +- return '' +- + # build some color string templates outside these nested loops +- tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal) +- tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm, +- ColorsNormal) +- tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \ +- (Colors.vName, Colors.valEm, ColorsNormal) +- tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal) ++ tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal) ++ tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ++ ColorsNormal) ++ tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \ ++ (Colors.vName, Colors.valEm, ColorsNormal) ++ tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal) + tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal, + Colors.vName, ColorsNormal) +- tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal) +- tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal) +- tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line, +- ColorsNormal) ++ tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal) ++ ++ tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal) ++ tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line, ++ ColorsNormal) + +- # now, loop over all records printing context and info + abspath = os.path.abspath + for frame, file, lnum, func, lines, index in records: + #print '*** record:',file,lnum,func,lines,index # dbg + if not file: + file = '?' +- elif not(file.startswith(str("<")) and file.endswith(str(">"))): +- # Guess that filenames like aren't real filenames, so +- # don't call abspath on them. +- try: +- file = abspath(file) +- except OSError: +- # Not sure if this can still happen: abspath now works with +- # file names like +- pass ++ elif file.startswith(str("<")) and file.endswith(str(">")): ++ # Not a real filename, no problem... ++ pass ++ elif not os.path.isabs(file): ++ # Try to make the filename absolute by trying all ++ # sys.path entries (which is also what linecache does) ++ for dirname in sys.path: ++ try: ++ fullname = os.path.join(dirname, file) ++ if os.path.isfile(fullname): ++ file = os.path.abspath(fullname) ++ break ++ except Exception: ++ # Just in case that sys.path contains very ++ # strange entries... ++ pass ++ + file = py3compat.cast_unicode(file, util_path.fs_encoding) + link = tpl_link % file + args, varargs, varkw, locals = inspect.getargvalues(frame) +@@ -827,9 +751,9 @@ + # Decide whether to include variable details or not + var_repr = self.include_vars and eqrepr or nullrepr + try: +- call = tpl_call % (func,inspect.formatargvalues(args, +- varargs, varkw, +- locals,formatvalue=var_repr)) ++ call = tpl_call % (func, inspect.formatargvalues(args, ++ varargs, varkw, ++ locals, formatvalue=var_repr)) + except KeyError: + # This happens in situations like errors inside generator + # expressions, where local variables are listed in the +@@ -848,12 +772,12 @@ + # will illustrate the error, if this exception catch is + # disabled. + call = tpl_call_fail % func +- ++ + # Don't attempt to tokenize binary files. + if file.endswith(('.so', '.pyd', '.dll')): +- frames.append('%s %s\n' % (link,call)) ++ frames.append('%s %s\n' % (link, call)) + continue +- elif file.endswith(('.pyc','.pyo')): ++ elif file.endswith(('.pyc', '.pyo')): + # Look up the corresponding source file. + file = openpy.source_from_cache(file) + +@@ -867,7 +791,7 @@ + try: + names = [] + name_cont = False +- ++ + for token_type, token, start, end, line in generate_tokens(linereader): + # build composite names + if token_type == tokenize.NAME and token not in keyword.kwlist: +@@ -890,9 +814,11 @@ + name_cont = True + elif token_type == tokenize.NEWLINE: + break +- +- except (IndexError, UnicodeDecodeError): ++ ++ except (IndexError, UnicodeDecodeError, SyntaxError): + # signals exit of tokenizer ++ # SyntaxError can occur if the file is not actually Python ++ # - see gh-6300 + pass + except tokenize.TokenError as msg: + _m = ("An unexpected error occurred while tokenizing input\n" +@@ -909,11 +835,11 @@ + lvals = [] + if self.include_vars: + for name_full in unique_names: +- name_base = name_full.split('.',1)[0] ++ name_base = name_full.split('.', 1)[0] + if name_base in frame.f_code.co_varnames: + if name_base in locals: + try: +- value = repr(eval(name_full,locals)) ++ value = repr(eval(name_full, locals)) + except: + value = undefined + else: +@@ -922,69 +848,191 @@ + else: + if name_base in frame.f_globals: + try: +- value = repr(eval(name_full,frame.f_globals)) ++ value = repr(eval(name_full, frame.f_globals)) + except: + value = undefined + else: + value = undefined + name = tpl_global_var % name_full +- lvals.append(tpl_name_val % (name,value)) ++ lvals.append(tpl_name_val % (name, value)) + if lvals: +- lvals = '%s%s' % (indent,em_normal.join(lvals)) ++ lvals = '%s%s' % (indent, em_normal.join(lvals)) + else: + lvals = '' + +- level = '%s %s\n' % (link,call) ++ level = '%s %s\n' % (link, call) + + if index is None: + frames.append(level) + else: +- frames.append('%s%s' % (level,''.join( +- _format_traceback_lines(lnum,index,lines,Colors,lvals, ++ frames.append('%s%s' % (level, ''.join( ++ _format_traceback_lines(lnum, index, lines, Colors, lvals, + col_scheme)))) + ++ return frames ++ ++ def prepare_chained_exception_message(self, cause): ++ direct_cause = "\nThe above exception was the direct cause of the following exception:\n" ++ exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n" ++ ++ if cause: ++ message = [[direct_cause]] ++ else: ++ message = [[exception_during_handling]] ++ return message ++ ++ def prepare_header(self, etype, long_version=False): ++ colors = self.Colors # just a shorthand + quicker name lookup ++ colorsnormal = colors.Normal # used a lot ++ exc = '%s%s%s' % (colors.excName, etype, colorsnormal) ++ if long_version: ++ # Header with the exception type, python version, and date ++ pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable ++ date = time.ctime(time.time()) ++ ++ head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * 75, colorsnormal, ++ exc, ' ' * (75 - len(str(etype)) - len(pyver)), ++ pyver, date.rjust(75) ) ++ head += "\nA problem occurred executing Python code. Here is the sequence of function" \ ++ "\ncalls leading up to the error, with the most recent (innermost) call last." ++ else: ++ # Simplified header ++ head = '%s%s' % (exc, 'Traceback (most recent call last)'. \ ++ rjust(75 - len(str(etype))) ) ++ ++ return head ++ ++ def format_exception(self, etype, evalue): ++ colors = self.Colors # just a shorthand + quicker name lookup ++ colorsnormal = colors.Normal # used a lot ++ indent = ' ' * INDENT_SIZE + # Get (safely) a string form of the exception info + try: +- etype_str,evalue_str = map(str,(etype,evalue)) ++ etype_str, evalue_str = map(str, (etype, evalue)) + except: + # User exception is improperly defined. +- etype,evalue = str,sys.exc_info()[:2] +- etype_str,evalue_str = map(str,(etype,evalue)) ++ etype, evalue = str, sys.exc_info()[:2] ++ etype_str, evalue_str = map(str, (etype, evalue)) + # ... and format it +- exception = ['%s%s%s: %s' % (Colors.excName, etype_str, +- ColorsNormal, py3compat.cast_unicode(evalue_str))] ++ exception = ['%s%s%s: %s' % (colors.excName, etype_str, ++ colorsnormal, py3compat.cast_unicode(evalue_str))] ++ + if (not py3compat.PY3) and type(evalue) is types.InstanceType: + try: + names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)] + except: +- # Every now and then, an object with funny inernals blows up ++ # Every now and then, an object with funny internals blows up + # when dir() is called on it. We do the best we can to report + # the problem and continue + _m = '%sException reporting error (object with broken dir())%s:' +- exception.append(_m % (Colors.excName,ColorsNormal)) +- etype_str,evalue_str = map(str,sys.exc_info()[:2]) +- exception.append('%s%s%s: %s' % (Colors.excName,etype_str, +- ColorsNormal, py3compat.cast_unicode(evalue_str))) ++ exception.append(_m % (colors.excName, colorsnormal)) ++ etype_str, evalue_str = map(str, sys.exc_info()[:2]) ++ exception.append('%s%s%s: %s' % (colors.excName, etype_str, ++ colorsnormal, py3compat.cast_unicode(evalue_str))) + names = [] + for name in names: + value = text_repr(getattr(evalue, name)) + exception.append('\n%s%s = %s' % (indent, name, value)) + +- # vds: >> ++ return exception ++ ++ def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset): ++ # some locals ++ try: ++ etype = etype.__name__ ++ except AttributeError: ++ pass ++ ++ tb_offset = self.tb_offset if tb_offset is None else tb_offset ++ head = self.prepare_header(etype, self.long_header) ++ records = self.get_records(etb, number_of_lines_of_context, tb_offset) ++ ++ frames = self.format_records(records) ++ if records is None: ++ return "" ++ ++ formatted_exception = self.format_exception(etype, evalue) + if records: +- filepath, lnum = records[-1][1:3] +- #print "file:", str(file), "linenb", str(lnum) # dbg +- filepath = os.path.abspath(filepath) +- ipinst = get_ipython() +- if ipinst is not None: +- ipinst.hooks.synchronize_with_editor(filepath, lnum, 0) +- # vds: << +- +- # return all our info assembled as a single string +- # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) ) +- return [head] + frames + [''.join(exception[0])] ++ filepath, lnum = records[-1][1:3] ++ filepath = os.path.abspath(filepath) ++ ipinst = get_ipython() ++ if ipinst is not None: ++ ipinst.hooks.synchronize_with_editor(filepath, lnum, 0) ++ ++ return [[head] + frames + [''.join(formatted_exception[0])]] ++ ++ def get_records(self, etb, number_of_lines_of_context, tb_offset): ++ try: ++ # Try the default getinnerframes and Alex's: Alex's fixes some ++ # problems, but it generates empty tracebacks for console errors ++ # (5 blanks lines) where none should be returned. ++ return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset) ++ except: ++ # FIXME: I've been getting many crash reports from python 2.3 ++ # users, traceable to inspect.py. If I can find a small test-case ++ # to reproduce this, I should either write a better workaround or ++ # file a bug report against inspect (if that's the real problem). ++ # So far, I haven't been able to find an isolated example to ++ # reproduce the problem. ++ inspect_error() ++ traceback.print_exc(file=self.ostream) ++ info('\nUnfortunately, your original traceback can not be constructed.\n') ++ return None ++ ++ def get_parts_of_chained_exception(self, evalue): ++ def get_chained_exception(exception_value): ++ cause = getattr(exception_value, '__cause__', None) ++ if cause: ++ return cause ++ return getattr(exception_value, '__context__', None) ++ ++ chained_evalue = get_chained_exception(evalue) ++ ++ if chained_evalue: ++ return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__ ++ ++ def structured_traceback(self, etype, evalue, etb, tb_offset=None, ++ number_of_lines_of_context=5): ++ """Return a nice text document describing the traceback.""" ++ ++ formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context, ++ tb_offset) + +- def debugger(self,force=False): ++ colors = self.Colors # just a shorthand + quicker name lookup ++ colorsnormal = colors.Normal # used a lot ++ head = '%s%s%s' % (colors.topline, '-' * 75, colorsnormal) ++ structured_traceback_parts = [head] ++ if py3compat.PY3: ++ chained_exceptions_tb_offset = 0 ++ lines_of_context = 3 ++ formatted_exceptions = formatted_exception ++ exception = self.get_parts_of_chained_exception(evalue) ++ if exception: ++ formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__) ++ etype, evalue, etb = exception ++ else: ++ evalue = None ++ while evalue: ++ formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context, ++ chained_exceptions_tb_offset) ++ exception = self.get_parts_of_chained_exception(evalue) ++ ++ if exception: ++ formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__) ++ etype, evalue, etb = exception ++ else: ++ evalue = None ++ ++ # we want to see exceptions in a reversed order: ++ # the first exception should be on top ++ for formatted_exception in reversed(formatted_exceptions): ++ structured_traceback_parts += formatted_exception ++ else: ++ structured_traceback_parts += formatted_exception[0] ++ ++ return structured_traceback_parts ++ ++ def debugger(self, force=False): + """Call up the pdb debugger if desired, always clean up the tb + reference. + +@@ -1014,7 +1062,7 @@ + with display_trap: + self.pdb.reset() + # Find the right frame so we don't pop up inside ipython itself +- if hasattr(self,'tb') and self.tb is not None: ++ if hasattr(self, 'tb') and self.tb is not None: + etb = self.tb + else: + etb = self.tb = sys.last_traceback +@@ -1025,7 +1073,7 @@ + self.pdb.botframe = etb.tb_frame + self.pdb.interaction(self.tb.tb_frame, self.tb) + +- if hasattr(self,'tb'): ++ if hasattr(self, 'tb'): + del self.tb + + def handler(self, info=None): +@@ -1050,6 +1098,7 @@ + except KeyboardInterrupt: + print("\nKeyboardInterrupt") + ++ + #---------------------------------------------------------------------------- + class FormattedTB(VerboseTB, ListTB): + """Subclass ListTB but allow calling with a traceback. +@@ -1069,7 +1118,7 @@ + check_cache=None): + + # NEVER change the order of this list. Put new modes at the end: +- self.valid_modes = ['Plain','Context','Verbose'] ++ self.valid_modes = ['Plain', 'Context', 'Verbose'] + self.verbose_modes = self.valid_modes[1:3] + + VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, +@@ -1083,19 +1132,19 @@ + # set_mode also sets the tb_join_char attribute + self.set_mode(mode) + +- def _extract_tb(self,tb): ++ def _extract_tb(self, tb): + if tb: + return traceback.extract_tb(tb) + else: + return None + +- def structured_traceback(self, etype, value, tb, tb_offset=None, context=5): ++ def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5): + tb_offset = self.tb_offset if tb_offset is None else tb_offset + mode = self.mode + if mode in self.verbose_modes: + # Verbose modes need a full traceback + return VerboseTB.structured_traceback( +- self, etype, value, tb, tb_offset, context ++ self, etype, value, tb, tb_offset, number_of_lines_of_context + ) + else: + # We must check the source cache because otherwise we can print +@@ -1104,7 +1153,7 @@ + # Now we can extract and format the exception + elist = self._extract_tb(tb) + return ListTB.structured_traceback( +- self, etype, value, elist, tb_offset, context ++ self, etype, value, elist, tb_offset, number_of_lines_of_context + ) + + def stb2text(self, stb): +@@ -1112,18 +1161,18 @@ + return self.tb_join_char.join(stb) + + +- def set_mode(self,mode=None): ++ def set_mode(self, mode=None): + """Switch to the desired mode. + + If mode is not specified, cycles through the available modes.""" + + if not mode: +- new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \ ++ new_idx = (self.valid_modes.index(self.mode) + 1 ) % \ + len(self.valid_modes) + self.mode = self.valid_modes[new_idx] + elif mode not in self.valid_modes: +- raise ValueError('Unrecognized mode in FormattedTB: <'+mode+'>\n' +- 'Valid modes: '+str(self.valid_modes)) ++ raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n' ++ 'Valid modes: ' + str(self.valid_modes)) + else: + self.mode = mode + # include variable details only in 'Verbose' mode +@@ -1131,7 +1180,7 @@ + # Set the join character for generating text tracebacks + self.tb_join_char = self._join_chars[self.mode] + +- # some convenient shorcuts ++ # some convenient shortcuts + def plain(self): + self.set_mode(self.valid_modes[0]) + +@@ -1141,6 +1190,7 @@ + def verbose(self): + self.set_mode(self.valid_modes[2]) + ++ + #---------------------------------------------------------------------------- + class AutoFormattedTB(FormattedTB): + """A traceback printer which can be called on the fly. +@@ -1156,8 +1206,8 @@ + AutoTB() # or AutoTB(out=logfile) where logfile is an open file object + """ + +- def __call__(self,etype=None,evalue=None,etb=None, +- out=None,tb_offset=None): ++ def __call__(self, etype=None, evalue=None, etb=None, ++ out=None, tb_offset=None): + """Print out a formatted exception traceback. + + Optional arguments: +@@ -1167,7 +1217,6 @@ + per-call basis (this overrides temporarily the instance's tb_offset + given at initialization time. """ + +- + if out is None: + out = self.ostream + out.flush() +@@ -1182,33 +1231,36 @@ + print("\nKeyboardInterrupt") + + def structured_traceback(self, etype=None, value=None, tb=None, +- tb_offset=None, context=5): ++ tb_offset=None, number_of_lines_of_context=5): + if etype is None: +- etype,value,tb = sys.exc_info() ++ etype, value, tb = sys.exc_info() + self.tb = tb + return FormattedTB.structured_traceback( +- self, etype, value, tb, tb_offset, context) ++ self, etype, value, tb, tb_offset, number_of_lines_of_context) ++ + + #--------------------------------------------------------------------------- + + # A simple class to preserve Nathan's original functionality. + class ColorTB(FormattedTB): + """Shorthand to initialize a FormattedTB in Linux colors mode.""" +- def __init__(self,color_scheme='Linux',call_pdb=0): +- FormattedTB.__init__(self,color_scheme=color_scheme, ++ ++ def __init__(self, color_scheme='Linux', call_pdb=0): ++ FormattedTB.__init__(self, color_scheme=color_scheme, + call_pdb=call_pdb) + + + class SyntaxTB(ListTB): + """Extension which holds some state: the last exception value""" + +- def __init__(self,color_scheme = 'NoColor'): +- ListTB.__init__(self,color_scheme) ++ def __init__(self, color_scheme='NoColor'): ++ ListTB.__init__(self, color_scheme) + self.last_syntax_error = None + + def __call__(self, etype, value, elist): + self.last_syntax_error = value +- ListTB.__call__(self,etype,value,elist) ++ ++ ListTB.__call__(self, etype, value, elist) + + def structured_traceback(self, etype, value, elist, tb_offset=None, + context=5): +@@ -1223,7 +1275,7 @@ + if newtext: + value.text = newtext + return super(SyntaxTB, self).structured_traceback(etype, value, elist, +- tb_offset=tb_offset, context=context) ++ tb_offset=tb_offset, context=context) + + def clear_err_state(self): + """Return the current error state and clear it""" +@@ -1236,7 +1288,46 @@ + return ''.join(stb) + + ++# some internal-use functions ++def text_repr(value): ++ """Hopefully pretty robust repr equivalent.""" ++ # this is pretty horrible but should always return *something* ++ try: ++ return pydoc.text.repr(value) ++ except KeyboardInterrupt: ++ raise ++ except: ++ try: ++ return repr(value) ++ except KeyboardInterrupt: ++ raise ++ except: ++ try: ++ # all still in an except block so we catch ++ # getattr raising ++ name = getattr(value, '__name__', None) ++ if name: ++ # ick, recursion ++ return text_repr(name) ++ klass = getattr(value, '__class__', None) ++ if klass: ++ return '%s instance' % text_repr(klass) ++ except KeyboardInterrupt: ++ raise ++ except: ++ return 'UNRECOVERABLE REPR FAILURE' ++ ++ ++def eqrepr(value, repr=text_repr): ++ return '=%s' % repr(value) ++ ++ ++def nullrepr(value, repr=text_repr): ++ return '' ++ ++ + #---------------------------------------------------------------------------- ++ + # module testing (minimal) + if __name__ == "__main__": + def spam(c, d_e): diff --git a/build/pkgs/maxima/SPKG.txt b/build/pkgs/maxima/SPKG.txt index 7639f9da2b0..f74b2daed8a 100644 --- a/build/pkgs/maxima/SPKG.txt +++ b/build/pkgs/maxima/SPKG.txt @@ -36,25 +36,15 @@ COPYING. == Special Update/Build Instructions == 1. Go to http://sourceforge.net/projects/maxima/files/Maxima-source/ - and download the source tarball maxima-x.y.z.tar.gz. + and download the source tarball maxima-x.y.z.tar.gz; place it in + the upstream/ directory. -2. Extract the tarball. +2. Update package-version.txt and run sage-fix-pkg-checksums. -3. In the directory maxima-x.y.z, run the spkg-src script. - -4. Compress the directory into a new file maxima-x.y.z.tar.bz2 and - place it in the upstream/ directory. - -5. Make sure the patches still apply cleanly, and update them if +3. Make sure the patches still apply cleanly, and update them if necessary. -6. Test the resulting package. - -Here's what spkg-src does: - - * Removes the unneeded PDF figures from the documentation. - - * Removes the foreign language versions of the info files. +4. Test the resulting package. All patch files in the patches/ directory are applied. Descriptions of these patches are either in the patch files themselves or below. diff --git a/build/pkgs/maxima/checksums.ini b/build/pkgs/maxima/checksums.ini index 888cea34145..6ea9155fed4 100644 --- a/build/pkgs/maxima/checksums.ini +++ b/build/pkgs/maxima/checksums.ini @@ -1,4 +1,4 @@ -tarball=maxima-VERSION.tar.bz2 -sha1=f7bc8466016a9bcb23027ec4e1a28bdc48bdc7df -md5=dd6c256cf1eb5a0ea3e8804874e33772 -cksum=2007386721 +tarball=maxima-VERSION.tar.gz +sha1=4431afec577e3cc42370fd768262cf7e1cef9f7f +md5=4bb0b999645ec2b20b7e301d36f83a4c +cksum=80051208 diff --git a/build/pkgs/maxima/package-version.txt b/build/pkgs/maxima/package-version.txt index 8ae1b97e268..6a6a6f9b14e 100644 --- a/build/pkgs/maxima/package-version.txt +++ b/build/pkgs/maxima/package-version.txt @@ -1 +1 @@ -5.34.1.p1 +5.35.1.p0 diff --git a/build/pkgs/maxima/patches/compile.patch b/build/pkgs/maxima/patches/compile.patch deleted file mode 100644 index fb6140a01d6..00000000000 --- a/build/pkgs/maxima/patches/compile.patch +++ /dev/null @@ -1,21 +0,0 @@ -Do not use the C compiler for compiling regexes at Maxima startup. -This reverts Maxima commit 4226ee2. Introduced in Trac #17375 -(Maxima should not need a working C compiler to run). - ---- a/src/commac.lisp -+++ b/src/commac.lisp -@@ -376,10 +376,10 @@ - (or (strip-float-zeros string) string) - string))) - --(defparameter trailing-zeros-regex-f-0 (compile nil (maxima-nregex::regex-compile "^(.*\\.[0-9]*[1-9])00*$"))) --(defparameter trailing-zeros-regex-f-1 (compile nil (maxima-nregex::regex-compile "^(.*\\.0)00*$"))) --(defparameter trailing-zeros-regex-e-0 (compile nil (maxima-nregex::regex-compile "^(.*\\.[0-9]*[1-9])00*([^0-9][+-][0-9]*)$"))) --(defparameter trailing-zeros-regex-e-1 (compile nil (maxima-nregex::regex-compile "^(.*\\.0)00*([^0-9][+-][0-9]*)$"))) -+(defvar trailing-zeros-regex-f-0 (coerce (maxima-nregex::regex-compile "^(.*\\.[0-9]*[1-9])00*$") 'function)) -+(defvar trailing-zeros-regex-f-1 (coerce (maxima-nregex::regex-compile "^(.*\\.0)00*$") 'function)) -+(defvar trailing-zeros-regex-e-0 (coerce (maxima-nregex::regex-compile "^(.*\\.[0-9]*[1-9])00*([^0-9][+-][0-9]*)$") 'function)) -+(defvar trailing-zeros-regex-e-1 (coerce (maxima-nregex::regex-compile "^(.*\\.0)00*([^0-9][+-][0-9]*)$") 'function)) - - ;; Return S with trailing zero digits stripped off, or NIL if there are none. - diff --git a/build/pkgs/maxima/patches/makeinfo.patch b/build/pkgs/maxima/patches/makeinfo.patch new file mode 100644 index 00000000000..c98d3b3c7a2 --- /dev/null +++ b/build/pkgs/maxima/patches/makeinfo.patch @@ -0,0 +1,14 @@ +Use $(MAKEINFO) instead of hardcoded makeinfo to build maxima.info. +Introduced in Trac #17514 (Upgrade Maxima to 5.35.1). + +--- a/doc/info/Makefile.am ++++ b/doc/info/Makefile.am +@@ -211,7 +211,7 @@ + all-local: maxima.info maxima-index.lisp $(MAXIMA_CHM) + + maxima.info : maxima.texi +- makeinfo --split-size=1000000 maxima.texi ++ $(MAKEINFO) --split-size=1000000 maxima.texi + + html: maxima.html contents.hhc + diff --git a/build/pkgs/maxima/spkg-install b/build/pkgs/maxima/spkg-install index 42352480392..3c80e5c953d 100755 --- a/build/pkgs/maxima/spkg-install +++ b/build/pkgs/maxima/spkg-install @@ -24,7 +24,6 @@ exec +# +# 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. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 5 + +AC_DEFUN([AX_CHECK_ROOT],[ +AC_MSG_CHECKING([for root user]) + +uid=`id -u` +if test "x$uid" == "x0"; then + AC_MSG_RESULT([yes]) + $1 +else + AC_MSG_RESULT([no]) + $2 +fi;dnl + +]) diff --git a/src/bin/sage b/src/bin/sage index 4205ea5ff01..2452a092c14 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -204,7 +204,6 @@ usage_advanced() { #### |.....................--.|...................................................| echo "Making Sage packages or distributions:" echo " -bdist VER -- build a binary distribution of Sage" - echo " -crap sage-ver.tar -- detect suspicious garbage in sage source tarball" echo " -pkg -- create Sage package dir.spkg from a given directory" echo " -pkg_nc -- as -pkg, but do not compress the package" echo " -sdist -- build a source distribution of Sage" @@ -449,10 +448,6 @@ if [ "$1" = '-scons' -o "$1" = '--scons' ]; then fi if [ "$1" = '-pip' -o "$1" = '--pip' ]; then - if [ ! -x "$SAGE_LOCAL/bin/pip" ]; then - echo "Pip is not installed. Run \"sage -i pip\" to install it." - exit 1 - fi shift exec pip "$@" fi @@ -628,15 +623,6 @@ if [ "$1" = '-rst2sws' -o "$1" = '--rst2sws' ]; then exec sage-rst2sws "$@" fi -##################################################################### -# Crap -##################################################################### - -if [ "$1" = "-crap" -o "$1" = "--crap" ]; then - shift - exec sage-crap $@ -fi - ##################################################################### # Run Sage's versions of the standard Algebra/Geometry etc. software ##################################################################### diff --git a/src/bin/sage-banner b/src/bin/sage-banner index 045d57dac02..820c5e36410 100644 --- a/src/bin/sage-banner +++ b/src/bin/sage-banner @@ -1,5 +1,5 @@ ┌────────────────────────────────────────────────────────────────────┐ -│ Sage Version 6.5.beta2, Release Date: 2014-12-04 │ +│ Sage Version 6.5.beta3, Release Date: 2014-12-18 │ │ Type "notebook()" for the browser-based notebook interface. │ │ Type "help()" for help. │ └────────────────────────────────────────────────────────────────────┘ diff --git a/src/bin/sage-crap b/src/bin/sage-crap deleted file mode 100755 index f84010f6f19..00000000000 --- a/src/bin/sage-crap +++ /dev/null @@ -1,621 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2008, William Stein (with permission) -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the Sage Project nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY WILLIAM STEIN ``AS IS'' AND ANY -# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL William Stein BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# uses system command 'file' to print out -# types of all files in (Sage) source tar -# -# prints "DONE" when finished -# -# takes about 15 CPU minutes to go through Sage -# -# version 20080118 -# -# The following file types are considered understood -# so no comment is made by them -# -# TXT type -# __init__.py, nodoctest.py files -# .hg directories -# *.html files (XML type) -# *.pdf (PDF type) -# symbolic links -# *.png (PNG image data) -# *.gif (GIF image data) -# *.tiff (TIFF image data) -# *.jpg (JPEG image data) -# *.s (Assembler source) -# -# Bad files (understood so NOT considered weird) -# -# MS-DOS executables -# ._* (AppleDouble encoded Macintosh files) -# *.class (JAVA) -# *.so (MACH-O) -# *.o (MACH-O) -# *.dylib (MACH-O) -# ELF -# - - -#runlevel = 0 # print everything -#runlevel = 1 # only print weird file types -runlevel = 2 # only print "bad" stuff - -import sys,os -import sage.misc.misc - -if len(sys.argv) != 2: - print "tar file required" - sys.exit() - -print os.path.abspath('.') -name = sys.argv[1] -basename = os.path.split(name)[1] -tempdir = sage.misc.misc.tmp_dir() -cmd = "cp %s %s"%(name,tempdir) -os.system(cmd) - -os.chdir(tempdir) -cmd = "tar xvf " + basename -print cmd -os.system(cmd) - -def cleanup(): - global tempdir - os.system('rm -rf "%s"'%tempdir) - -name = basename - -stack = [ name ] -print os.getcwd() + "/" + name -print "runlevel= ", runlevel -if (os.path.isfile(name) == False) and (os.path.isdir(name) == False): - print "does not exist!!!" - cleanup() - sys.exit() -while len(stack) > 0: - name = stack.pop() - if name == -1: # go up one level - os.chdir("..") - elif name == -2: # tar what you have looked at - basename = stack.pop() - tarname = stack.pop() - cmd = "tar cf " + tarname + " " + basename - os.system(cmd) - # remove base - cmd = "rm -rf '" + basename + "'" - if runlevel == 0: - print basename + " -> " + tarname - os.system(cmd) - elif name == -3: # gzip file - name = stack.pop() - if runlevel == 0: - print name + " -> " + name + ".gz" - cmd = "gzip '" + name + "'" - os.system(cmd) - elif name == -4: # bzip file - name = stack.pop() - cmd = "bzip2 '" + name + "'" - if runlevel == 0: - print name + " -> " + name + ".bz2" - os.system(cmd) - elif name == -5: # rename - newname = stack.pop() - name = stack.pop() - os.rename(newname,name) - if runlevel == 0: - print newname + " -> " + name - else: - fullname = os.getcwd() + "/" + name - # get file type - cmd = "file '" + name + "' > /tmp/temp" - os.system(cmd) - f = open('/tmp/temp','r') - file_output = f.read() - # if file is a directory - if file_output.find(': directory') > 0: - if name == ".hg": - if runlevel == 0: - print fullname + ": IGNORING" - # spkg/standard/fortran-20071120.p3/src/ - elif name == "g95": - if runlevel == 0: - print fullname + ": IGNORING" - else: - if runlevel == 0: - print fullname + ": DIR" - stack.append(-1) - sys.stdout.flush() - stack = stack + os.listdir(name) - os.chdir(name) - elif name.endswith('.spkg') > 0: - # if file name ends in .spkg - basename = name[0:name.find('.spkg')] - if file_output.find('bzip2') > 0: - newname = basename + '.tar.bz2' - elif file_output.find('tar') > 0: - newname = basename + '.tar' - os.rename(name,newname) - if runlevel == 0: - print fullname + " -> " + newname - stack.append(name) - stack.append(newname) - stack.append(-5) - stack.append(newname) - elif file_output.find(': bzip2') > 0: - # if file is a bzip2 file - cmd = 'bunzip2 ' + name - os.system(cmd) - basename = name[0:name.find('.bz2')] - if runlevel == 0: - print fullname + " -> " + basename - stack.append(basename) - stack.append(-4) - stack.append(basename) - elif file_output.find(': gzip ') > 0: - if name.endswith(".gz"): - # special case - BAD!!! - # 'spkg/standard/tachyon-0.98beta.p3/src/docs/tachyon.html.tar.gz' - # overwrites dir 'tachyon' - if name == "tachyon.html.tar.gz": - if runlevel <= 1: - print fullname + ": IGNORING" - else: - cmd = 'gunzip ' + name - os.system(cmd) - basename = name[0:name.find('.gz')] - stack.append(basename) - stack.append(-3) - stack.append(basename) - if runlevel == 0: - print fullname + " -> " + basename - elif name.endswith(".tgz"): - basename = name[0:name.find('.tgz')] - newname = basename + ".tar.gz" - os.rename(name, newname) - stack.append(name) - stack.append(newname) - stack.append(-5) - stack.append(newname) - if runlevel == 0: - print fullname + " -> " + newname - elif name.endswith(".dia"): # See http://live.gnome.org/Dia - basename = name[0:name.find('.dia')] - newname = basename + ".gz" - os.rename(name, newname) - stack.append(name) - stack.append(newname) - stack.append(-5) - stack.append(newname) - if runlevel == 0: - print fullname + " -> " + newname - elif name.endswith(".rda"): - if runlevel <= 1: - print fullname + ": R data format? (find error)" - else: - print fullname + ": GZIP with unusual suffix" - print "abnormal exit" - cleanup() - sys.exit() - elif file_output.find(': POSIX tar archive') > 0: - # special case BAD!!! - # 'spkg/standard/python-2.5.1.p10/src/Lib/test/testtar.tar' - # untars with error BAD!!! - if name == "testtar.tar": - if runlevel <= 1: - print fullname + ": IGNORING" - # special case BAD!!! - # 'spkg/standard/jmol-11.5.2/jmol/jars/vecmath1.2-1.14.tar' - # 'tar tvf' first line does NOT tell directory name - elif name == "vecmath1.2-1.14.tar": - if runlevel <= 1: - print fullname + ": IGNORING" - else: - # if file is a tar file - # get name that tar unpacks to - cmd = "tar tvf " + name + " > /tmp/temp" - os.system(cmd) - f = open('/tmp/temp','r') - temp0 = f.read() - temp1 = temp0.splitlines() - temp2 = temp1[0] - temp3 = temp2.split() - temp4 = temp3[len(temp3) - 1] - newname = temp4[0:len(temp4)-1] - # now untar - cmd = 'tar xf ' + name - os.system(cmd) - # remove tar file - os.unlink(os.getcwd() + '/' + name) - if runlevel == 0: - print fullname + " -> " + newname - # save tarfilename and newname on stack - stack.append(name) - stack.append(newname) - stack.append(-2) - stack.append(newname) - elif file_output.find('text') != -1: - if runlevel == 0: - print fullname + ": TXT" - elif file_output.find('TeX DVI') > 0: - if runlevel < 2: - print fullname + ": TeX DVI" - elif file_output.find(': XML') > 0: - if name.endswith(".html") > 0: - if runlevel == 0: - print fullname + ": XML" - else: - if runlevel < 2: - print fullname + ": XML" - elif file_output.find(': Zip archive data') > 0: - if runlevel < 2: - print fullname + ": ZIP" - elif file_output.find('Java') > 0: - if name.endswith(".class"): - if runlevel == 0: - print fullname + ": JAVA" - if runlevel == 2: - print fullname - else: - if runlevel < 2: - print fullname + ": JAVA" - elif file_output.find(': data') > 0: - if runlevel < 2: - print fullname + ": DATA" - elif file_output.find(': very short file (no magic)') > 0: - if name == "__init__.py": - if runlevel == 0: - print fullname + ": very short file (no magic)" - else: - if runlevel < 2: - print fullname + ": very short file (no magic)" - elif file_output.find(': DCL command file') > 0: - if runlevel < 2: - print fullname + ": DCL command file" - elif file_output.find(': CLIPPER instruction trace') > 0: - if runlevel < 2: - print fullname + ": CLIPPER instruction trace" - elif file_output.find(': Palm OS dynamic library data') > 0: - if runlevel < 2: - print fullname + ": Palm OS dynamic library data" - elif file_output.find(': 80386 COFF') > 0: - if runlevel < 2: - print fullname + ": 80386 COFF" - elif file_output.find(': ACB archive data') > 0: - if runlevel < 2: - print fullname + ": ACB archive data" - elif file_output.find(': MS Windows HtmlHelp Data') > 0: - if runlevel < 2: - print fullname + ": MS Windows HtmlHelp Data" - elif file_output.find(': AppleDouble encoded Macintosh file') > 0: - if name.startswith("._"): - if runlevel == 0: - print fullname + ": AppleDouble encoded Macintosh file" - if runlevel == 2: - print fullname - else: - if runlevel < 2: - print fullname + ": AppleDouble encoded Macintosh file" - elif file_output.find(': Macromedia Flash data') > 0: - if runlevel < 2: - print fullname + ": Macromedia Flash data" - elif file_output.find(': Microsoft Installer') > 0: - if runlevel < 2: - print fullname + ": Microsoft Installer" - elif file_output.find(': PNG image data') > 0: - if name.endswith(".png") > 0: - if runlevel == 0: - print fullname + ": PNG image data" - else: - if runlevel < 2: - print fullname + ": PNG image data" - elif file_output.find(': empty') > 0: - if name == "__init__.py": - if runlevel == 0: - print fullname + ": empty" - elif name == "nodoctest.py": - if runlevel == 0: - print fullname + ": empty" - else: - if runlevel < 2: - print fullname + ": empty" - elif file_output.find('8086 relocatable') > 0: - if runlevel < 2: - print fullname + ": 8086 relocatable" - elif file_output.find(': PC bitmap data') > 0: - if runlevel < 2: - print fullname + ": PC bitmap data" - elif file_output.find(': GIF image data') > 0: - if name.endswith(".gif") > 0: - if runlevel == 0: - print fullname + ": GIF image data" - else: - if runlevel < 2: - print fullname + ": GIF image data" - elif file_output.find(': Apple binary property list') > 0: - if runlevel < 2: - print fullname + ": Apple binary property list" - elif file_output.find(': LaTeX table of contents') > 0: - if runlevel < 2: - print fullname + ": LaTeX table of contents" - elif file_output.find(': Makeindex log file') > 0: - if runlevel < 2: - print fullname + ": Makeindex log file" - elif file_output.find(': LaTeX raw index file') > 0: - if runlevel < 2: - print fullname + ": LaTeX raw index file" - elif file_output.find('LaTeX auxiliary file') > 0: - if runlevel < 2: - print fullname + ": LaTeX auxiliary file" - elif file_output.find('TIFF image data') > 0: - if name.endswith(".tiff"): - if runlevel == 0: - print fullname + ": TIFF image data" - else: - if runlevel < 2: - print fullname + ": TIFF image data" - elif file_output.find('DOS EPS Binary File') > 0: - if runlevel < 2: - print fullname + ": DOS EPS Binary File" - elif file_output.find('MPEG sequence') > 0: - if runlevel < 2: - print fullname + ": MPEG sequence" - elif file_output.find('JPEG image data') > 0: - if name.endswith(".jpg"): - if runlevel == 0: - print fullname + ": JPEG image data" - else: - if runlevel < 2: - print fullname + ": JPEG image data" - elif file_output.find(': Apple Old Partition') > 0: - if runlevel < 2: - print fullname + ": Apple Old Partition" - elif file_output.find(': current ar archive') > 0: - if runlevel < 2: - print fullname + ": current ar archive" - elif file_output.find(': python 2.3 byte-compiled') > 0: - if runlevel < 2: - print fullname + ": python 2.3 byte-compiled" - elif file_output.find(': python 2.4 byte-compiled') > 0: - if runlevel < 2: - print fullname + ": python 2.4 byte-compiled" - elif file_output.find(': python 2.5 byte-compiled') > 0: - if runlevel < 2: - print fullname + ": python 2.5 byte-compiled" - elif file_output.find('Assembler source') > 0: - if name.endswith(".s"): - if runlevel == 0: - print fullname + ": Assembler source" - else: - if runlevel < 2: - print fullname + ": Assembler source" - elif file_output.find(': PDF') > 0: - if name.endswith(".pdf") > 0: - if runlevel == 0: - print fullname + ": PDF" - else: - if runlevel < 2: - print fullname + ": PDF" - elif file_output.find(': MS-DOS executable') > 0: - if runlevel == 0: - print fullname + ": MS-DOS executable" - if runlevel == 2: - print fullname - elif file_output.find(': DOS executable') > 0: - if runlevel < 2: - print fullname + ": DOS executable" - elif file_output.find(': Matlab v5 mat-file') > 0: - if runlevel < 2: - print fullname + ": Matlab v5 mat-file" - elif file_output.find(': Extreme Tracker AMS Module v1.3') > 0: - if runlevel < 2: - print fullname + ": Extreme Tracker AMS Module v1.3" - elif file_output.find(': JVT NAL sequence') > 0: - if runlevel < 2: - print fullname + ": JVT NAL sequence" - elif file_output.find(': NeXT/Apple typedstream data') > 0: - if runlevel < 2: - print fullname + ": NeXT/Apple typedstream data" - elif file_output.find(': Rich Text Format data') > 0: - if runlevel < 2: - print fullname + ": Rich Text Format data" - elif file_output.find(': AppleSingle encoded Macintosh file') > 0: - if runlevel < 2: - print fullname + ": AppleSingle encoded Macintosh file" - elif file_output.find(': Adobe Photoshop Image') > 0: - if runlevel < 2: - print fullname + ": Adobe Photoshop Image" - elif file_output.find(': Macintosh Application (data)') > 0: - if runlevel < 2: - print fullname + ": Macintosh Application (data)" - elif file_output.find(': X11 SNF font data') > 0: - if runlevel < 2: - print fullname + ": X11 SNF font data" - elif file_output.find(': Sun/NeXT audio data') > 0: - if runlevel < 2: - print fullname + ": Sun/NeXT audio data" - elif file_output.find(': Berkeley DB') > 0: - if runlevel < 2: - print fullname + ": Berkeley DB" - elif file_output.find(': multipart/mixed') > 0: - if runlevel < 2: - print fullname + ": multipart/mixed" - elif file_output.find(': message/rfc822') > 0: - if runlevel < 2: - print fullname + ": message/rfc822" - elif file_output.find(': LaTeX sorted index') > 0: - if runlevel < 2: - print fullname + ": LaTeX sorted index" - elif file_output.find(': Xara graphics file') > 0: - if runlevel < 2: - print fullname + ": Xara graphics file" - elif file_output.find(': PalmOS application') > 0: - if runlevel < 2: - print fullname + ": PalmOS application" - elif file_output.find(': Par archive data') > 0: - if runlevel < 2: - print fullname + ": Par archive data" - elif file_output.find(': PGP key public ring') > 0: - if runlevel < 2: - print fullname + ": PGP key public ring" - elif file_output.find(': GPG key public ring') > 0: - if runlevel < 2: - print fullname + ": GPG key public ring" - elif file_output.find(': PGP key security ring') > 0: - if runlevel < 2: - print fullname + ": PGP key security ring" - elif file_output.find(': FITS image data') > 0: - if runlevel < 2: - print fullname + ": FITS image data" - elif file_output.find(': Bio-Rad .PIC Image File') > 0: - if runlevel < 2: - print fullname + ": Bio-Rad .PIC Image File" - elif file_output.find(': Arhangel archive data') > 0: - if runlevel < 2: - print fullname + ": Arhangel archive data" - elif file_output.find(': RISC OS Draw file data') > 0: - if runlevel < 2: - print fullname + ": RISC OS Draw file data" - elif file_output.find(': CLIPPER instruction profile') > 0: - if runlevel < 2: - print fullname + ": CLIPPER instruction profile" - elif file_output.find(': character Computer Graphics Metafile') > 0: - if runlevel < 2: - print fullname + ": character Computer Graphics Metafile" - elif file_output.find(': Windows INF file') > 0: - if runlevel < 2: - print fullname + ": Windows INF file" - elif file_output.find(': Emacs v18 byte-compiled Lisp data') > 0: - if runlevel < 2: - print fullname + ": Emacs v18 byte-compiled Lisp data" - elif file_output.find(': Netpbm PPM') > 0: - if runlevel < 2: - print fullname + ": Netpbm PPM" - elif file_output.find(': TrueType font data') > 0: - if runlevel < 2: - print fullname + ": TrueType font data" - elif file_output.find(': ASCII font metrics') > 0: - if runlevel < 2: - print fullname + ": ASCII font metrics" - elif file_output.find(': Maple worksheet') > 0: - if runlevel < 2: - print fullname + ": Maple worksheet" - elif file_output.find(': GNU message catalog') > 0: - if runlevel < 2: - print fullname + ": GNU message catalog" - elif file_output.find(': ELF 32-bit LSB executable, Intel 80386') > 0: - if runlevel == 0: - print fullname + ": ELF 32-bit LSB executable" - if runlevel == 2: - print fullname - elif file_output.find(': symbolic link') > 0: - if runlevel == 0: - print fullname + ": symbolic link" - elif file_output.find('SysEx File') > 0: - if runlevel < 2: - print fullname + ": SysEx File" - elif file_output.find(': libtool library file') > 0: - if runlevel < 2: - print fullname + ": libtool library file" - elif file_output.find(': SQLite 3.x database') > 0: - if runlevel < 2: - print fullname + ": SQLite 3.x database" - elif file_output.find(': YAC archive data') > 0: - if runlevel < 2: - print fullname + ": YAC archive data" - elif file_output.find(': PGP armored data') > 0: - if runlevel < 2: - print fullname + ": PGP armored data" - elif file_output.find(': Apple QuickTime movie') > 0: - if runlevel < 2: - print fullname + ": Apple QuickTime movie" - elif file_output.find(': Quake I or II world') > 0: - if runlevel < 2: - print fullname + ": Quake I or II world" - elif file_output.find(': Mach-O') > 0: - if name.endswith(".so") | name.endswith(".o") | name.endswith(".dylib"): - if runlevel == 0: - print fullname + ": Mach-O" - if runlevel == 2: - print fullname - else: - if runlevel < 2: - print fullname + ": Mach-O" - elif file_output.find(': ELF 64-bit') > 0: - if runlevel == 0: - print fullname + ": ELF 64-bit" - if runlevel == 2: - print fullname - elif file_output.find(': ELF 32-bit') > 0: - if runlevel == 0: - print fullname + ": ELF 32-bit" - if runlevel == 2: - print fullname - elif file_output.find(': SPEC') > 0: - if runlevel < 2: - print fullname + ": SPEC" - elif file_output.find(': Octave binary data') > 0: - if runlevel < 2: - print fullname + ": Octave binary data" - elif file_output.find(': DBase 3 data file') > 0: - if runlevel < 2: - print fullname + ": DBase 3 data file" - elif file_output.find(': OpenOffice.org') > 0: - if runlevel < 2: - print fullname + ": OpenOffice.org" - elif file_output.find(': fifo (named pipe)') > 0: - if runlevel < 2: - print fullname + ": fifo (named pipe)" - elif file_output.find(': broken symbolic link') > 0: - if runlevel < 2: - print fullname + ": broken symbolic link" - elif file_output.find(': timezone data') > 0: - if runlevel < 2: - print fullname + ": timezone data" - elif file_output.find(': Macintosh Library (data)') > 0: - if runlevel < 2: - print fullname + ": Macintosh Library (data)" - elif file_output.find(': SPSS System File') > 0: - if runlevel < 2: - print fullname + ": SPSS System File" - elif file_output.find(': mc68020 pure executable not stripped') > 0: - if runlevel < 2: - print fullname + ": mc68020 pure executable not stripped" - elif file_output.find(': MPEG ADTS') > 0: - if runlevel < 2: - print fullname + ": MPEG ADTS" - elif file_output.find(': XPack DiskImage archive data') > 0: - if runlevel < 2: - print fullname + ": XPack DiskImage archive data" - elif file_output.find(': VMS Alpha executable') > 0: - if runlevel < 2: - print fullname + ": VMS Alpha executable" - else: - print fullname + ": UNKNOWN" - print file_output -cleanup() -print "DONE!!!" diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index b559d5390c3..76157011ab2 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -1,4 +1,4 @@ # Sage version information for shell scripts # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='6.5.beta2' -SAGE_RELEASE_DATE='2014-12-04' +SAGE_VERSION='6.5.beta3' +SAGE_RELEASE_DATE='2014-12-18' diff --git a/src/doc/common/builder.py b/src/doc/common/builder.py index a5473c8eb5c..c817d8624c0 100644 --- a/src/doc/common/builder.py +++ b/src/doc/common/builder.py @@ -974,7 +974,7 @@ def write_auto_rest_file(self, module_name): # Don't doctest the autogenerated file. outfile.write(".. nodoctest\n\n") # Now write the actual content. - outfile.write(".. _%s:\n\n"%module_name) + outfile.write(".. _%s:\n\n"%(module_name.replace(".__init__",""))) outfile.write(title + '\n') outfile.write('='*len(title) + "\n\n") outfile.write('.. This file has been autogenerated.\n\n') diff --git a/src/doc/en/a_tour_of_sage/index.rst b/src/doc/en/a_tour_of_sage/index.rst index cdd49dadcad..ef3222ef4c1 100644 --- a/src/doc/en/a_tour_of_sage/index.rst +++ b/src/doc/en/a_tour_of_sage/index.rst @@ -59,6 +59,11 @@ The result is a list of equalities. sage: S[0].rhs() -1/2*sqrt(4*a + 1) - 1/2 + +Naturally, Sage can plot various useful functions. + +:: + sage: show(plot(sin(x) + sin(1.6*x), 0, 40)) .. image:: sin_plot.* diff --git a/src/doc/en/constructions/interface_issues.rst b/src/doc/en/constructions/interface_issues.rst index bfdef630e67..71f89b9e845 100644 --- a/src/doc/en/constructions/interface_issues.rst +++ b/src/doc/en/constructions/interface_issues.rst @@ -424,53 +424,14 @@ use an editor to read the code itself. "Special functions" in Sage =========================== -Sage has several special functions: - - -- Bessel functions and Airy functions - -- spherical harmonic functions - -- spherical Bessel functions (of the 1st and 2nd kind) - -- spherical Hankel functions (of the 1st and 2nd kind) - -- Jacobi elliptic functions - -- complete/incomplete elliptic integrals - -- hyperbolic trig functions (for completeness, since they are - special cases of elliptic functions) - - -and orthogonal polynomials - - -- chebyshev\_T (n, x), chebyshev\_U (n, x) - the Chebyshev - polynomial of the first, second kind for integers - :math:`n > -1`. - -- laguerre (n, x), gen\_laguerre (n, a, x) - the (generalized) - Laguerre poly. for :math:`n > -1`. - -- legendre\_P (n, x), legendre\_Q (n, x), gen\_legendre\_P (n, x), - gen\_legendre\_Q (n, x) - the (generalized) Legendre function of - the first, second kind for integers :math:`n > -1`. - -- hermite (n,x) - the Hermite poly. for integers - :math:`n > -1`. - -- jacobi\_P (n, a, b, x) - the Jacobi polynomial for integers - :math:`n > -1` and :math:`a` and :math:`b` symbolic or - :math:`a > -1` and :math:`b > -1`. - -- ultraspherical (n,a,x) - the ultraspherical polynomials for - integers :math:`n > -1`. The ultraspherical polynomials are also - known as Gegenbauer polynomials. - - -In Sage, these are restricted to numerical evaluation and plotting but -via maxima, some symbolic manipulation is allowed: +Sage has many special functions (see the reference +manual at http://sagemath.org/doc/reference/functions/), +and most of them can be +manipulated symbolically. Where this is not implemented, +it is possible that other symbolic packages have the +functionality. + +Via Maxima, some symbolic manipulation is allowed: :: diff --git a/src/doc/en/developer/coding_basics.rst b/src/doc/en/developer/coding_basics.rst index dadad1d400a..ee3b282d366 100644 --- a/src/doc/en/developer/coding_basics.rst +++ b/src/doc/en/developer/coding_basics.rst @@ -218,24 +218,27 @@ Docstring Markup With ReST and Sphinx ------------------------------------- **Every** function must have a docstring that includes the following -information. Source files in the Sage library contain numerous -examples on how to format your documentation, so you could use them as -a guide. - -- A one-sentence description of the function, followed by a blank line - and ending in a period. It prescribes the function or method's - effect as a command ("Do this", "Return that"), not as a - description; e.g. don't write "Returns the pathname ...". - -- An INPUT and an OUTPUT block for input and output arguments (see - below for format). The type names should be descriptive, but do not - have to represent the exact Sage/Python types. For example, use - "integer" for anything that behaves like an integer; you do not have - to put a precise type name such as ``int``. The INPUT block - describes the expected input to your function or method, while the - OUTPUT block describes the expected output of the - function/method. If appropriate, you need to describe any default - values for the input arguments. For example:: +information. You can use the existing functions of Sage as templates. + +- A **one-sentence description** of the function. + + It must be followed by a blank line and end in a period. It + describes the function or method's effect as a command ("Do this", + "Return that"), not as a description like "Returns the pathname ...". + +- An **INPUT** and an **OUTPUT** block describing the input/output of + the function. This is not optional. + + The INPUT block describes all arguments that the function accepts, + and the OUTPUT section describes its expected output. + + 1. The type names should be descriptive, but do not have to represent + the exact Sage/Python types. For example, use "integer" for + anything that behaves like an integer, rather than ``int``. + + 2. Mention the default values of the input arguments when applicable. + + Example:: INPUT: @@ -251,35 +254,36 @@ a guide. 4. the largest prime primitive root modulo p 5. total number of prime primitive roots modulo p - Some people prefer to format their OUTPUT section as a block by - using a dash. That is acceptable as well:: + You can start the OUTPUT block with a dash if you prefer:: OUTPUT: - The plaintext resulting from decrypting the ciphertext ``C`` using the Blum-Goldwasser decryption algorithm. -- An EXAMPLES block for examples. This is not optional. These - examples are used both for documentation and for automatic testing - before each release so should have good coverage of the functionality - in question. New functions without these doctests will not be accepted - for inclusion with Sage. +- An **EXAMPLES** block for examples. This is not optional. -- A SEEALSO block (optional) with links to related things in Sage. A SEEALSO - block should start with ``.. SEEALSO::``. It can also be the lower-case form - ``.. seealso::``. However, you are encouraged to use the upper-case form - ``.. SEEALSO::``. See :ref:`chapter-sage_manuals_links` for details on how - to setup link in Sage. Here's an example of a SEEALSO block:: + These examples are used both for: + + 1. Documentation + 2. Automatic testing before each release. + + They should have good coverage of the functionality in question. + +- A **SEEALSO** block (optional) with links to related parts of Sage. :: .. SEEALSO:: - :ref:`chapter-sage_manuals_links` + :ref:`chapter-sage_manuals_links` + + See :ref:`chapter-sage_manuals_links` for details on how to setup + link in Sage. -- An ALGORITHM block (optional) which indicates what algorithm - and/or what software is used. For example - ``ALGORITHM: Uses Pari``. Here's a longer example that describes an - algorithm used. Note that it also cites the reference where this - algorithm can be found:: +- An **ALGORITHM** block (optional). + + It indicates what algorithm and/or what software is used, e.g. + ``ALGORITHM: Uses Pari``. Here's a longer example with a + bibliographical reference:: ALGORITHM: @@ -302,56 +306,17 @@ a guide. .. [Nat2000] M.B. Nathanson. Elementary Methods in Number Theory. Springer, 2000. - You can also number the steps in your algorithm using the hash-dot - symbol. This way, the actual numbering of the steps are - automatically taken care of when you build the documentation:: - - ALGORITHM: - - The Blum-Goldwasser decryption algorithm is described in Algorithm - 8.56, page 309 of [MenezesEtAl1996]_. The algorithm works as follows: - - #. Let `C` be the ciphertext `C = (c_1, c_2, \dots, c_t, x_{t+1})`. - Then `t` is the number of ciphertext sub-blocks and `h` is the - length of each binary string sub-block `c_i`. - #. Let `(p, q, a, b)` be the private key whose corresponding - public key is `n = pq`. Note that `\gcd(p, q) = ap + bq = 1`. - #. Compute `d_1 = ((p + 1) / 4)^{t+1} \bmod{(p - 1)}`. - #. Compute `d_2 = ((q + 1) / 4)^{t+1} \bmod{(q - 1)}`. - #. Let `u = x_{t+1}^{d_1} \bmod p`. - #. Let `v = x_{t+1}^{d_2} \bmod q`. - #. Compute `x_0 = vap + ubq \bmod n`. - #. For `i` from 1 to `t`, do: - - #. Compute `x_i = x_{t-1}^2 \bmod n`. - #. Let `p_i` be the `h` least significant bits of `x_i`. - #. Compute `m_i = p_i \oplus c_i`. - - #. The plaintext is `m = m_1 m_2 \cdots m_t`. - -- A NOTE block for special notes (optional). Include information - such as purpose etc. A NOTE block should start with - ``.. NOTE::``. You can also use the lower-case version - ``.. note::``, but do not mix lower-case with upper-case. However, - you are encouraged to use the upper-case version ``.. NOTE::``. If - you want to put anything within the NOTES block, you should - indent it at least 4 spaces (no tabs). Here's an example of a NOTE - block:: +- A **NOTE** block for tips/tricks (optional). :: .. NOTE:: You should note that this sentence is indented at least 4 - spaces. Avoid tab characters as much as possible when - writing code or editing the Sage documentation. You should - follow Python conventions by using spaces only. - -- A WARNING block for critical information about your code. For - example, the WARNING block might include information about when or - under which conditions your code might break, or information that - the user should be particularly aware of. A WARNING block should start - with ``.. WARNING::``. It can also be the lower-case form - ``.. warning::``. However, you are encouraged to use the upper-case - form ``.. WARNING::``. Here's an example of a WARNING block:: + spaces. Never use the tab character. + +- A **WARNING** block for critical information about your code (optional). + + For example known situations for which the code breaks, or anything + that the user should be aware of. :: .. WARNING:: @@ -362,30 +327,23 @@ a guide. build, it is very likely that you would be requested to change your patch. -- A TODO block for room for improvements. The TODO block might - contains disabled doctests to demonstrate the desired feature. A TODO block - should start with ``.. TODO::``. It can also be the lower-case form - ``.. todo::``. However, you are encouraged to use the upper-case form - ``.. TODO::``. Here's an example of a TODO block:: +- A **TODO** block for future improvements (optional). + + It can contain disabled doctests to demonstrate the desired + feature. Here's an example of a TODO block:: .. TODO:: - Improve further function ``have_fresh_beers`` using algorithm - ``buy_a_better_fridge``:: + Add to ``have_fresh_beers`` an interface with the faster + algorithm "Buy a Better Fridge" (BaBF):: - sage: have_fresh_beers('Bière de l\'Yvette') # todo: not implemented + sage: have_fresh_beers('Bière de l\'Yvette', algorithm="BaBF") # not implemented Enjoy ! -- A REFERENCES block to list books or papers (optional). This block serves - a similar purpose to a list of references in a research paper, or a - bibliography in a monograph. If your method, function or class uses an - algorithm that can be found in a standard reference, you should list - that reference under this block. The Sphinx/ReST markup for - citations is described at - http://sphinx.pocoo.org/rest.html#citations. See below for an example. - Sage also add specific markup for links to sage trac tickets and - Wikipedia. See :ref:`chapter-sage_manuals_links`. Here's an example of a - REFERENCES block:: +- A **REFERENCES** block to list related books or papers (optional) + + It should cite the books/research papers relevant to the code, e.g. the source + of the algorithm that it implements. :: This docstring is referencing [SC]_. Just remember that references are global, so we can also reference to [Nat2000]_ in the ALGORITHM @@ -397,12 +355,17 @@ a guide. .. [SC] Conventions for coding in sage. http://www.sagemath.org/doc/developer/conventions.html. -- A TESTS block (optional), formatted just like EXAMPLES, for additional - tests which should be part of the regression suite but are not - illustrative enough to merit placement in EXAMPLES. + See the `Sphinx/ReST markup for citations `_. For links toward trac tickets or wikipedia, see :ref:`chapter-sage_manuals_links`. + +- A **TESTS** block (optional) + + Formatted just like EXAMPLES, containing tests that are not relevant to users. + +Template +^^^^^^^^ Use the following template when documenting functions. Note the -indentation +indentation: .. skip # do not doctest @@ -469,31 +432,36 @@ indentation You are strongly encouraged to: -- Use nice LaTeX formatting everywhere, see - :ref:`section-latex-typeset`. +- Use LaTeX typesetting (see :ref:`section-latex-typeset`). + +- Liberally describe what the examples do. + + .. NOTE:: + + There must be a blank line after the example code and before the + explanatory text for the next example (indentation is not enough). -- Liberally describe what the examples do. Note that there must be a - blank line after the example code and before the explanatory text - for the next example (indentation is not enough). +- Illustrate the exceptions raised by the function with examples (as + given above: "It is an error to [..]", ...) -- Illustrate any exceptions raised by the function with examples, as - given above. (It is an error to ...; In particular, use ...) +- Include many examples. -- Include many examples. These are automatically tested on a regular - basis, and are crucial for the quality and adaptability of - Sage. Without such examples, small changes to one part of Sage that - break something else might not go seen until much later when someone - uses the system, which is unacceptable. Note that new functions - without doctests will not be accepted for inclusion in Sage. + They are helpful for the users, and are crucial for the quality and + adaptability of Sage. Without such examples, small changes to one part + of Sage that break something else might not go seen until much later + when someone uses the system, which is unacceptable. + +Private functions +^^^^^^^^^^^^^^^^^ Functions whose names start with an underscore are considered -private. Hence they do not appear in the reference manual, and their -docstring should not contain any information that is crucial for Sage -users. Having said that, you can explicitly enable their docstrings to -be shown as part of the documentation of another method. For example:: +private. They do not appear in the reference manual, and their docstring +should not contain any information that is crucial for Sage users. You +can make their docstrings be part of the documentation of another +method. For example:: class Foo(SageObject): - + def f(self): """ @@ -501,18 +469,17 @@ be shown as part of the documentation of another method. For example:: .. automethod:: _f """ return self._f() - + def _f(self): """ This would be hidden without the ``.. automethod::`` """ -An EXAMPLES or TESTS block is still required for these private functions. +Private functions should contain an EXAMPLES (or TESTS) block. -A special case is the constructor ``__init__``, which clearly starts -with an underscore. However, due to its special status the -``__init__`` docstring is used as the class docstring if there is not -one already. That is, you can do the following:: +A special case is the constructor ``__init__``: due to its special +status the ``__init__`` docstring is used as the class docstring if +there is not one already. That is, you can do the following:: sage: class Foo(SageObject): ....: # no class docstring @@ -532,7 +499,6 @@ one already. That is, you can do the following:: LaTeX Typesetting ----------------- - In ReST documentation, you use backticks \` to mark LaTeX code to be typeset. In Sage docstrings, you may also use dollar signs instead. Thus ```x^2 + y^2 = 1``` and ``$x^2 + y^2 = 1$`` should produce diff --git a/src/doc/en/developer/packaging.rst b/src/doc/en/developer/packaging.rst index 6abadf6e866..f78420e30c1 100644 --- a/src/doc/en/developer/packaging.rst +++ b/src/doc/en/developer/packaging.rst @@ -204,9 +204,8 @@ The ``SPKG.txt`` file should follow this pattern:: == Special Update/Build Instructions == - List patches that need to be applied and what they do. If the - tarball was modified by hand and not via a spkg-src script, - describe what was changed. + If the tarball was modified by hand and not via a spkg-src + script, describe what was changed. with ``PACKAGE_NAME`` replaced by the the package name. Legacy @@ -220,10 +219,29 @@ Patching Sources ---------------- Actual changes to the source code must be via patches, which should be -placed in the ``patches`` directory. GNU patch is distributed with Sage, -so you can rely on it being available. All patches must be documented in -``SPKG.txt``, i.e. what they do, if they are platform specific, if they -should be pushed upstream, etc. +placed in the ``patches`` directory. GNU patch is distributed with +Sage, so you can rely on it being available. Patches must include +documentation in their header (before the first diff hunk), so a +typical patch file should look like this:: + + Add autodoc_builtin_argspec config option + + Following the title line you can add a multi-line description of + what the patch does, where you got it from if you did not write it + yourself, if they are platform specific, if they should be pushed + upstream, etc... + + diff -dru Sphinx-1.2.2/sphinx/ext/autodoc.py.orig Sphinx-1.2.2/sphinx/ext/autodoc.py + --- Sphinx-1.2.2/sphinx/ext/autodoc.py.orig 2014-03-02 20:38:09.000000000 +1300 + +++ Sphinx-1.2.2/sphinx/ext/autodoc.py 2014-10-19 23:02:09.000000000 +1300 + @@ -1452,6 +1462,7 @@ + + app.add_config_value('autoclass_content', 'class', True) + app.add_config_value('autodoc_member_order', 'alphabetic', True) + + app.add_config_value('autodoc_builtin_argspec', None, True) + app.add_config_value('autodoc_default_flags', [], True) + app.add_config_value('autodoc_docstring_signature', True, True) + app.add_event('autodoc-process-docstring') Patches to files in ``src/`` need to be applied in ``spkg-install``, that is, if there are any patches then your ``spkg-install`` script @@ -240,12 +258,6 @@ should contain a section like this:: which applies the patches to the sources. -A special case where no patch would be necessary is when an author -provides an already fine SPKG on the net which includes all files needed -for ``SAGE_ROOT/build/pkgs/foo`` and the source in its ``src/`` -subdirectory. Here it suffices to put the web link to the package into -the ticket. - .. _section-spkg-src: diff --git a/src/doc/en/developer/packaging_old_spkgs.rst b/src/doc/en/developer/packaging_old_spkgs.rst index 0ec2361633d..bcc07d37b27 100644 --- a/src/doc/en/developer/packaging_old_spkgs.rst +++ b/src/doc/en/developer/packaging_old_spkgs.rst @@ -124,11 +124,11 @@ More precisely, the directory should contain the following: - ``patches/``: this directory contains patches to source files in ``src/``. See :ref:`section-old-spkg-patching-overview`. Patches to files in ``src/`` should be applied in ``spkg-install``, and all - patches must be documented in ``SPKG.txt``, i.e. what they do, if - they are platform specific, if they should be pushed upstream, - etc. To ensure that all patched versions of upstream source files - under ``src/`` are under revision control, the whole directory - ``patches/`` must be under revision control. + patches must be self-documenting, i.e. the header must contain what + they do, if they are platform specific, if they should be pushed + upstream, etc. To ensure that all patched versions of upstream + source files under ``src/`` are under revision control, the whole + directory ``patches/`` must be under revision control. **Never** apply patches to upstream source files under ``src/`` and then package up an spkg. Such a mixture of upstream source with Sage diff --git a/src/doc/en/installation/source.rst b/src/doc/en/installation/source.rst index bb81f8b8a13..7ac1e3c1a04 100644 --- a/src/doc/en/installation/source.rst +++ b/src/doc/en/installation/source.rst @@ -941,6 +941,10 @@ Here are some of the more commonly used variables affecting the build process: Typically, building the documentation using LaTeX and dvipng takes longer and uses more memory and disk space than using MathJax. +- :envvar:`SAGE_DOCBUILD_OPTS` - the value of this variable is passed + as an argument to ``sage --docbuild all html`` or ``sage --docbuild + all pdf`` when you run ``make``, ``make doc``, or ``make doc-pdf``. + - :envvar:`SAGE_BUILD_DIR` - the default behavior is to build each spkg in a subdirectory of :file:`$SAGE_ROOT/local/var/tmp/sage/build/`; for example, build version 3.8.3.p12 of @@ -1142,6 +1146,21 @@ Environment variables dealing with specific Sage packages: - If this variable is unset, include the patch on sun4v machines only. +- :envvar:`PARI_CONFIGURE` - use this to pass extra parameters to + PARI's ``Configure`` script, for example to specify graphics + support (which is disabled by default). See the file + :file:`build/pkgs/pari/spkg-install` for more information. + +- :envvar:`SAGE_TUNE_PARI`: If yes, enable PARI self-tuning. Note that + this can be time-consuming. If you set this variable to "yes", you + will also see this: ``WARNING: Tuning PARI/GP is unreliable. You may + find your build of PARI fails, or PARI/GP does not work properly + once built. We recommend to build this package with + SAGE_CHECK="yes".`` + +- :envvar:`PARI_MAKEFLAGS`: The value of this variable is passed as an + argument to the ``$MAKE`` command when compiling PARI. + Some standard environment variables which are used by Sage: - :envvar:`CC` - while some programs allow you to use this to specify your C @@ -1170,7 +1189,13 @@ Some standard environment variables which are used by Sage: - :envvar:`CFLAGS`, :envvar:`CXXFLAGS` and :envvar:`FCFLAGS` - the flags for the C compiler, the C++ compiler and the Fortran compiler, respectively. The same comments apply to these: setting them may cause problems, because - they are not universally respected among the Sage packages. + they are not universally respected among the Sage packages. Note + also that ``export CFLAGS=""`` does not have the same effect as + ``unset CFLAGS``. The latter is preferable. + +- Similar comments apply to other compiler and linker flags like + :envvar:`CPPFLAGS`, :envvar:`LDFLAGS`, :envvar:`CXXFLAG64`, + :envvar:`LDFLAG64`, and :envvar:`LD`. Sage uses the following environment variables when it runs: @@ -1235,7 +1260,7 @@ Variables dealing with doctesting: - :envvar:`SAGE_TIMEOUT` - used for Sage's doctesting: the number of seconds to allow a doctest before timing it out. - If this isn't set, the default is 360 seconds (6 minutes). + If this isn't set, the default is 300 seconds (5 minutes). - :envvar:`SAGE_TIMEOUT_LONG` - used for Sage's doctesting: the number of seconds to allow a doctest before timing it out, if tests are run using @@ -1252,6 +1277,27 @@ Variables dealing with doctesting: and `here (unpickle_all) `_. +- :envvar:`SAGE_TEST_GLOBAL_ITER`, :envvar:`SAGE_TEST_ITER`: these can + be used instead of passing the flags ``--global-iterations`` and + ``--file-iterations``, respectively, to ``sage -t``. Indeed, these + variables are only used if the flags are unset. Run ``sage -t -h`` + for more information on the effects of these flags (and therefore + these variables). + +Sage sets some other environment variables. The most accurate way to +see what Sage does is to first run ``env`` from a shell prompt to see +what environment variables you have set. Then run ``sage --sh -c +env`` to see the list after Sage sets its variables. (This runs a +separate shell, executes the shell command ``env``, and then exits +that shell, so after running this, your settings will be restored.) +Alternatively, you can peruse the shell script +:file:`src/bin/sage-env`. + +Sage also has some environment-like settings. Some of these correspond +to actual environment variables while others have names like +environment variables but are only available while Sage is running. To +see a list, execute ``sage.env.[TAB]`` while running Sage. + .. comment: *************************************************************************** FIX THIS! @@ -1374,4 +1420,4 @@ would be appropriate if you have a Core i3/5/7 processor with AVX support. -**This page was last updated in October 2014 (Sage 6.4).** +**This page was last updated in November 2014 (Sage 6.5).** diff --git a/src/doc/en/reference/algebras/index.rst b/src/doc/en/reference/algebras/index.rst index 311348b80b5..cd0ac5a1767 100644 --- a/src/doc/en/reference/algebras/index.rst +++ b/src/doc/en/reference/algebras/index.rst @@ -28,6 +28,9 @@ Algebras sage/algebras/group_algebra_new sage/algebras/iwahori_hecke_algebra + sage/algebras/iwahori_hecke_algebra + sage/algebras/nil_coxeter_algebra + sage/algebras/affine_nil_temperley_lieb sage/algebras/hall_algebra diff --git a/src/doc/en/reference/coding/index.rst b/src/doc/en/reference/coding/index.rst index 57ce7d93e3b..313fa839ab0 100644 --- a/src/doc/en/reference/coding/index.rst +++ b/src/doc/en/reference/coding/index.rst @@ -1,3 +1,5 @@ +.. _sage.coding: + Coding Theory ============= diff --git a/src/doc/en/reference/combinat/algebra.rst b/src/doc/en/reference/combinat/algebra.rst deleted file mode 100644 index 860f25ab1d4..00000000000 --- a/src/doc/en/reference/combinat/algebra.rst +++ /dev/null @@ -1,17 +0,0 @@ -Combinatorial Algebras -====================== - -.. toctree:: - :maxdepth: 2 - - ../sage/combinat/free_module - ../sage/combinat/combinatorial_algebra - ../sage/combinat/descent_algebra - ../sage/combinat/diagram_algebras - ../sage/combinat/symmetric_group_algebra - ../sage/combinat/symmetric_group_representations - ../sage/combinat/schubert_polynomial - ../sage/combinat/partition_algebra - ../sage/algebras/iwahori_hecke_algebra - ../sage/algebras/nil_coxeter_algebra - ../sage/algebras/affine_nil_temperley_lieb diff --git a/src/doc/en/reference/combinat/cluster_algebras.rst b/src/doc/en/reference/combinat/cluster_algebras.rst deleted file mode 100644 index 926496fe874..00000000000 --- a/src/doc/en/reference/combinat/cluster_algebras.rst +++ /dev/null @@ -1,9 +0,0 @@ -Cluster Algebras and Quivers -============================ - -.. toctree:: - :maxdepth: 2 - - ../sage/combinat/cluster_algebra_quiver/quiver_mutation_type - ../sage/combinat/cluster_algebra_quiver/quiver - ../sage/combinat/cluster_algebra_quiver/cluster_seed diff --git a/src/doc/en/reference/combinat/crystals.rst b/src/doc/en/reference/combinat/crystals.rst deleted file mode 100644 index c7888ada12e..00000000000 --- a/src/doc/en/reference/combinat/crystals.rst +++ /dev/null @@ -1,38 +0,0 @@ -Crystals -======== - -Catalogs --------- - -.. toctree:: - :maxdepth: 2 - - sage/combinat/crystals/catalog - sage/combinat/crystals/catalog_elementary_crystals - sage/combinat/crystals/catalog_infinity_crystals - sage/combinat/crystals/catalog_kirillov_reshetikhin - -Crystal Modules ---------------- - -.. toctree:: - :maxdepth: 2 - - sage/combinat/crystals/affine - sage/combinat/crystals/affine_factorization - sage/combinat/crystals/alcove_path - sage/combinat/crystals/infinity_crystals - sage/combinat/crystals/crystals - sage/combinat/crystals/generalized_young_walls - sage/combinat/crystals/letters - sage/combinat/crystals/monomial_crystals - sage/combinat/crystals/direct_sum - sage/combinat/crystals/elementary_crystals - sage/combinat/crystals/fast_crystals - sage/combinat/crystals/highest_weight_crystals - sage/combinat/crystals/kirillov_reshetikhin - sage/combinat/crystals/kyoto_path_model - sage/combinat/crystals/littelmann_path - sage/combinat/crystals/spins - sage/combinat/crystals/tensor_product - diff --git a/src/doc/en/reference/combinat/designs.rst b/src/doc/en/reference/combinat/designs.rst deleted file mode 100644 index edb9aee23cf..00000000000 --- a/src/doc/en/reference/combinat/designs.rst +++ /dev/null @@ -1,42 +0,0 @@ -Designs and Incidence Structures -================================ - -All designs can be accessed by ``designs.`` and are listed in -the design catalog: - -.. toctree:: - :maxdepth: 1 - - ../sage/combinat/designs/design_catalog - -**Design-related classes** - -.. toctree:: - :maxdepth: 1 - - ../sage/combinat/designs/incidence_structures - ../sage/combinat/designs/covering_design - -**Constructions** - -.. toctree:: - :maxdepth: 1 - - ../sage/combinat/designs/block_design - ../sage/combinat/designs/bibd - ../sage/combinat/designs/latin_squares - ../sage/combinat/designs/orthogonal_arrays - ../sage/combinat/designs/orthogonal_arrays_build_recursive - ../sage/combinat/designs/orthogonal_arrays_find_recursive - ../sage/combinat/designs/difference_family - ../sage/combinat/designs/difference_matrices - ../sage/combinat/designs/steiner_quadruple_systems - ../sage/combinat/designs/database - -**Technical things** - -.. toctree:: - :maxdepth: 1 - - ../sage/combinat/designs/ext_rep - ../sage/combinat/designs/designs_pyx diff --git a/src/doc/en/reference/combinat/developer.rst b/src/doc/en/reference/combinat/developer.rst deleted file mode 100644 index 96fe8685a22..00000000000 --- a/src/doc/en/reference/combinat/developer.rst +++ /dev/null @@ -1,15 +0,0 @@ -Developer Tools -=============== - -.. toctree:: - :maxdepth: 2 - - ../sage/combinat/backtrack - ../sage/combinat/output - ../sage/combinat/permutation_nk - ../sage/combinat/split_nk - ../sage/combinat/choose_nk - ../sage/combinat/multichoose_nk - ../sage/combinat/tools - ../sage/combinat/ranker - diff --git a/src/doc/en/reference/combinat/index.rst b/src/doc/en/reference/combinat/index.rst index 6157e514543..1066b9a34f3 100644 --- a/src/doc/en/reference/combinat/index.rst +++ b/src/doc/en/reference/combinat/index.rst @@ -1,212 +1,16 @@ Combinatorics ============= -**Algebra** - -.. toctree:: - :maxdepth: 1 - - cluster_algebras - algebra - -**Backtracking solvers** - -.. toctree:: - :maxdepth: 1 - - sage/combinat/tiling - sage/combinat/dlx - sage/combinat/matrices/dlxcpp - -**Combinatorial Objects** - -.. toctree:: - :maxdepth: 1 - - sage/combinat/alternating_sign_matrix - sage/combinat/composition - sage/combinat/core - designs - sage/combinat/knutson_tao_puzzles - sage/combinat/gelfand_tsetlin_patterns - sage/combinat/necklace - sage/combinat/non_decreasing_parking_function - sage/combinat/parking_functions - sage/combinat/perfect_matching - sage/combinat/six_vertex_model - sage/combinat/tamari_lattices - sage/combinat/interval_posets - sage/combinat/yang_baxter_graph - -**Compositions** - -.. toctree:: - :maxdepth: 1 - - sage/combinat/composition_signed - sage/combinat/composition - -**Counting** - -.. toctree:: - :maxdepth: 1 - - sage/combinat/sloane_functions - sage/databases/oeis - sage/combinat/expnums - sage/combinat/combinat +.. automodule:: sage.combinat -**Finite State Machines** +Comprehensive Module List +------------------------- .. toctree:: :maxdepth: 1 - sage/combinat/finite_state_machine - sage/combinat/finite_state_machine_generators - -**Integer Lists/Matrices/Vectors** - -.. toctree:: - :maxdepth: 1 - - sage/combinat/integer_list - sage/combinat/integer_matrices - sage/combinat/integer_vector - sage/combinat/integer_vector_weighted - -**Partitions** - -.. toctree:: - :maxdepth: 1 - - partitions - sage/combinat/partition - sage/combinat/partition_tuple - sage/combinat/set_partition_ordered - sage/combinat/set_partition - sage/combinat/skew_partition - sage/combinat/vector_partition - -**Permutations** - -.. toctree:: - :maxdepth: 1 - - sage/combinat/permutation - sage/combinat/affine_permutation - sage/combinat/derangements - sage/combinat/integer_vectors_mod_permgroup - sage/combinat/enumeration_mod_permgroup - -**Polynomials** - -.. toctree:: - :maxdepth: 1 - - sage/combinat/hall_polynomial - sage/combinat/kazhdan_lusztig - -**Posets** - -.. toctree:: - :maxdepth: 1 - - posets - -**q-analogues** - -.. toctree:: - :maxdepth: 1 - - sage/combinat/q_analogues - sage/combinat/q_bernoulli - -**Sequences** - -.. toctree:: - :maxdepth: 1 - - sage/combinat/binary_recurrence_sequences - sage/combinat/debruijn_sequence - sage/combinat/degree_sequences - -**Symmetric Functions** - -.. toctree:: - :maxdepth: 1 - - symmetric_functions - ncsf_qsym - ncsym - -**Tableaux** - -.. toctree:: - :maxdepth: 1 - - tableaux - sage/combinat/rsk - -**Trees** - -.. toctree:: - :maxdepth: 1 - - sage/combinat/abstract_tree - sage/combinat/ordered_tree - sage/combinat/binary_tree - -**Word** - -.. toctree:: - :maxdepth: 1 - - words - sage/combinat/subword - sage/combinat/lyndon_word - sage/combinat/dyck_word - -**Unsorted** - -.. toctree:: - :maxdepth: 1 - - sage/combinat/tutorial - - sage/combinat/cartesian_product - sage/combinat/combination - sage/combinat/e_one_star - sage/combinat/finite_class - sage/combinat/matrices/hadamard_matrix - sage/combinat/restricted_growth - sage/combinat/graph_path - sage/combinat/matrices/latin - sage/combinat/sidon_sets - sage/combinat/similarity_class_type - sage/combinat/subset - sage/combinat/subsets_pairwise - sage/combinat/subsets_hereditary - sage/combinat/tuple - sage/combinat/gray_codes - - root_systems - crystals - rigged_configurations - species - -**Developer Tools** - - -.. toctree:: - :maxdepth: 1 - - sage/combinat/shuffle - sage/combinat/dict_addition - sage/combinat/misc - sage/combinat/combinatorial_map - - developer + module_list .. include:: ../footer.txt diff --git a/src/doc/en/reference/combinat/module_list.rst b/src/doc/en/reference/combinat/module_list.rst new file mode 100644 index 00000000000..e84dc84733e --- /dev/null +++ b/src/doc/en/reference/combinat/module_list.rst @@ -0,0 +1,323 @@ +Comprehensive Module list +========================= + +.. NOTE:: + + This list is currently sorted in alphabetical order w.r.t. the module names. + It can be updated semi-automatically by running in ``src/sage/combinat``:: + + find -name "*.py*" | sed 's|\.pyx\?$||; s|\./| sage/combinat/|' | LANG=en_US.UTF-8 LC_COLLATE=C sort > /tmp/module_list.rst + + and copy pasting the result back there. + +.. TODO:: See :trac:`17421` for desirable improvements. + +.. toctree:: + :maxdepth: 1 + + sage/combinat/__init__ + sage/combinat/abstract_tree + sage/combinat/affine_permutation + sage/combinat/algebraic_combinatorics + sage/combinat/all + sage/combinat/alternating_sign_matrix + sage/combinat/backtrack + sage/combinat/binary_recurrence_sequences + sage/combinat/binary_tree + sage/combinat/cartesian_product + sage/combinat/catalog_partitions + sage/combinat/choose_nk + sage/combinat/cluster_algebra_quiver/__init__ + sage/combinat/cluster_algebra_quiver/all + sage/combinat/cluster_algebra_quiver/cluster_seed + sage/combinat/cluster_algebra_quiver/mutation_class + sage/combinat/cluster_algebra_quiver/mutation_type + sage/combinat/cluster_algebra_quiver/quiver + sage/combinat/cluster_algebra_quiver/quiver_mutation_type + sage/combinat/combinat + sage/combinat/combinat_cython + sage/combinat/combination + sage/combinat/combinatorial_algebra + sage/combinat/combinatorial_map + sage/combinat/composition + sage/combinat/composition_signed + sage/combinat/composition_tableau + sage/combinat/core + sage/combinat/counting + sage/combinat/crystals/__init__ + sage/combinat/crystals/affine + sage/combinat/crystals/affine_factorization + sage/combinat/crystals/alcove_path + sage/combinat/crystals/all + sage/combinat/crystals/catalog + sage/combinat/crystals/catalog_elementary_crystals + sage/combinat/crystals/catalog_infinity_crystals + sage/combinat/crystals/catalog_kirillov_reshetikhin + sage/combinat/crystals/crystals + sage/combinat/crystals/direct_sum + sage/combinat/crystals/elementary_crystals + sage/combinat/crystals/fast_crystals + sage/combinat/crystals/generalized_young_walls + sage/combinat/crystals/highest_weight_crystals + sage/combinat/crystals/infinity_crystals + sage/combinat/crystals/kirillov_reshetikhin + sage/combinat/crystals/kyoto_path_model + sage/combinat/crystals/letters + sage/combinat/crystals/littelmann_path + sage/combinat/crystals/monomial_crystals + sage/combinat/crystals/spins + sage/combinat/crystals/tensor_product + sage/combinat/cyclic_sieving_phenomenon + sage/combinat/debruijn_sequence + sage/combinat/degree_sequences + sage/combinat/derangements + sage/combinat/descent_algebra + sage/combinat/designs/__init__ + sage/combinat/designs/all + sage/combinat/designs/bibd + sage/combinat/designs/block_design + sage/combinat/designs/covering_design + sage/combinat/designs/database + sage/combinat/designs/design_catalog + sage/combinat/designs/designs_pyx + sage/combinat/designs/difference_family + sage/combinat/designs/difference_matrices + sage/combinat/designs/ext_rep + sage/combinat/designs/incidence_structures + sage/combinat/designs/latin_squares + sage/combinat/designs/orthogonal_arrays + sage/combinat/designs/orthogonal_arrays_build_recursive + sage/combinat/designs/orthogonal_arrays_find_recursive + sage/combinat/designs/steiner_quadruple_systems + sage/combinat/diagram_algebras + sage/combinat/dict_addition + sage/combinat/dlx + sage/combinat/dyck_word + sage/combinat/e_one_star + sage/combinat/enumerated_sets + sage/combinat/enumeration_mod_permgroup + sage/combinat/expnums + sage/combinat/family + sage/combinat/finite_class + sage/combinat/finite_state_machine + sage/combinat/finite_state_machine_generators + sage/combinat/free_module + sage/combinat/gelfand_tsetlin_patterns + sage/combinat/graph_path + sage/combinat/gray_codes + sage/combinat/hall_polynomial + sage/combinat/integer_list + sage/combinat/integer_matrices + sage/combinat/integer_vector + sage/combinat/integer_vector_weighted + sage/combinat/integer_vectors_mod_permgroup + sage/combinat/interval_posets + sage/combinat/k_tableau + sage/combinat/kazhdan_lusztig + sage/combinat/knutson_tao_puzzles + sage/combinat/lyndon_word + sage/combinat/matrices/__init__ + sage/combinat/matrices/all + sage/combinat/matrices/dancing_links + sage/combinat/matrices/dlxcpp + sage/combinat/matrices/hadamard_matrix + sage/combinat/matrices/latin + sage/combinat/misc + sage/combinat/multichoose_nk + sage/combinat/ncsf_qsym/__init__ + sage/combinat/ncsf_qsym/all + sage/combinat/ncsf_qsym/combinatorics + sage/combinat/ncsf_qsym/generic_basis_code + sage/combinat/ncsf_qsym/ncsf + sage/combinat/ncsf_qsym/qsym + sage/combinat/ncsf_qsym/tutorial + sage/combinat/ncsym/__init__ + sage/combinat/ncsym/all + sage/combinat/ncsym/bases + sage/combinat/ncsym/dual + sage/combinat/ncsym/ncsym + sage/combinat/necklace + sage/combinat/non_decreasing_parking_function + sage/combinat/ordered_tree + sage/combinat/output + sage/combinat/parking_functions + sage/combinat/partition + sage/combinat/partition_algebra + sage/combinat/partition_tuple + sage/combinat/partitions + sage/combinat/perfect_matching + sage/combinat/permutation + sage/combinat/permutation_cython + sage/combinat/permutation_nk + sage/combinat/posets/__init__ + sage/combinat/posets/all + sage/combinat/posets/elements + sage/combinat/posets/hasse_diagram + sage/combinat/posets/lattices + sage/combinat/posets/linear_extensions + sage/combinat/posets/poset_examples + sage/combinat/posets/posets + sage/combinat/q_analogues + sage/combinat/q_bernoulli + sage/combinat/quickref + sage/combinat/ranker + sage/combinat/restricted_growth + sage/combinat/ribbon + sage/combinat/ribbon_shaped_tableau + sage/combinat/ribbon_tableau + sage/combinat/rigged_configurations/__init__ + sage/combinat/rigged_configurations/all + sage/combinat/rigged_configurations/bij_abstract_class + sage/combinat/rigged_configurations/bij_type_A + sage/combinat/rigged_configurations/bij_type_A2_dual + sage/combinat/rigged_configurations/bij_type_A2_even + sage/combinat/rigged_configurations/bij_type_A2_odd + sage/combinat/rigged_configurations/bij_type_B + sage/combinat/rigged_configurations/bij_type_C + sage/combinat/rigged_configurations/bij_type_D + sage/combinat/rigged_configurations/bij_type_D_twisted + sage/combinat/rigged_configurations/bijection + sage/combinat/rigged_configurations/kleber_tree + sage/combinat/rigged_configurations/kr_tableaux + sage/combinat/rigged_configurations/rc_crystal + sage/combinat/rigged_configurations/rc_infinity + sage/combinat/rigged_configurations/rigged_configuration_element + sage/combinat/rigged_configurations/rigged_configurations + sage/combinat/rigged_configurations/rigged_partition + sage/combinat/rigged_configurations/tensor_product_kr_tableaux + sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element + sage/combinat/root_system/__init__ + sage/combinat/root_system/all + sage/combinat/root_system/ambient_space + sage/combinat/root_system/associahedron + sage/combinat/root_system/branching_rules + sage/combinat/root_system/cartan_matrix + sage/combinat/root_system/cartan_type + sage/combinat/root_system/coxeter_group + sage/combinat/root_system/coxeter_matrix + sage/combinat/root_system/dynkin_diagram + sage/combinat/root_system/hecke_algebra_representation + sage/combinat/root_system/non_symmetric_macdonald_polynomials + sage/combinat/root_system/pieri_factors + sage/combinat/root_system/plot + sage/combinat/root_system/root_lattice_realization_algebras + sage/combinat/root_system/root_lattice_realizations + sage/combinat/root_system/root_space + sage/combinat/root_system/root_system + sage/combinat/root_system/type_A + sage/combinat/root_system/type_A_affine + sage/combinat/root_system/type_B + sage/combinat/root_system/type_BC_affine + sage/combinat/root_system/type_B_affine + sage/combinat/root_system/type_C + sage/combinat/root_system/type_C_affine + sage/combinat/root_system/type_D + sage/combinat/root_system/type_D_affine + sage/combinat/root_system/type_E + sage/combinat/root_system/type_E_affine + sage/combinat/root_system/type_F + sage/combinat/root_system/type_F_affine + sage/combinat/root_system/type_G + sage/combinat/root_system/type_G_affine + sage/combinat/root_system/type_H + sage/combinat/root_system/type_I + sage/combinat/root_system/type_affine + sage/combinat/root_system/type_dual + sage/combinat/root_system/type_folded + sage/combinat/root_system/type_marked + sage/combinat/root_system/type_reducible + sage/combinat/root_system/type_relabel + sage/combinat/root_system/weight_lattice_realizations + sage/combinat/root_system/weight_space + sage/combinat/root_system/weyl_characters + sage/combinat/root_system/weyl_group + sage/combinat/rsk + sage/combinat/schubert_polynomial + sage/combinat/set_partition + sage/combinat/set_partition_ordered + sage/combinat/sf/__init__ + sage/combinat/sf/all + sage/combinat/sf/classical + sage/combinat/sf/dual + sage/combinat/sf/elementary + sage/combinat/sf/hall_littlewood + sage/combinat/sf/homogeneous + sage/combinat/sf/jack + sage/combinat/sf/k_dual + sage/combinat/sf/kfpoly + sage/combinat/sf/llt + sage/combinat/sf/macdonald + sage/combinat/sf/monomial + sage/combinat/sf/multiplicative + sage/combinat/sf/new_kschur + sage/combinat/sf/ns_macdonald + sage/combinat/sf/orthotriang + sage/combinat/sf/powersum + sage/combinat/sf/schur + sage/combinat/sf/sf + sage/combinat/sf/sfa + sage/combinat/sf/witt + sage/combinat/shuffle + sage/combinat/sidon_sets + sage/combinat/similarity_class_type + sage/combinat/six_vertex_model + sage/combinat/skew_partition + sage/combinat/skew_tableau + sage/combinat/sloane_functions + sage/combinat/species/__init__ + sage/combinat/species/all + sage/combinat/species/characteristic_species + sage/combinat/species/combinatorial_logarithm + sage/combinat/species/composition_species + sage/combinat/species/cycle_species + sage/combinat/species/empty_species + sage/combinat/species/functorial_composition_species + sage/combinat/species/generating_series + sage/combinat/species/library + sage/combinat/species/linear_order_species + sage/combinat/species/misc + sage/combinat/species/partition_species + sage/combinat/species/permutation_species + sage/combinat/species/product_species + sage/combinat/species/recursive_species + sage/combinat/species/series + sage/combinat/species/series_order + sage/combinat/species/set_species + sage/combinat/species/species + sage/combinat/species/stream + sage/combinat/species/structure + sage/combinat/species/subset_species + sage/combinat/species/sum_species + sage/combinat/split_nk + sage/combinat/subset + sage/combinat/subsets_hereditary + sage/combinat/subsets_pairwise + sage/combinat/subword + sage/combinat/symmetric_group_algebra + sage/combinat/symmetric_group_representations + sage/combinat/tableau + sage/combinat/tableau_tuple + sage/combinat/tamari_lattices + sage/combinat/tiling + sage/combinat/tools + sage/combinat/tuple + sage/combinat/tutorial + sage/combinat/vector_partition + sage/combinat/words/__init__ + sage/combinat/words/abstract_word + sage/combinat/words/all + sage/combinat/words/alphabet + sage/combinat/words/finite_word + sage/combinat/words/infinite_word + sage/combinat/words/morphism + sage/combinat/words/paths + sage/combinat/words/shuffle_product + sage/combinat/words/suffix_trees + sage/combinat/words/word + sage/combinat/words/word_char + sage/combinat/words/word_datatypes + sage/combinat/words/word_generators + sage/combinat/words/word_infinite_datatypes + sage/combinat/words/word_options + sage/combinat/words/words + sage/combinat/yang_baxter_graph diff --git a/src/doc/en/reference/combinat/ncsf_qsym.rst b/src/doc/en/reference/combinat/ncsf_qsym.rst deleted file mode 100644 index 286d42edec6..00000000000 --- a/src/doc/en/reference/combinat/ncsf_qsym.rst +++ /dev/null @@ -1,11 +0,0 @@ -Non-Commutative Symmetric Functions and Quasi-Symmetric Functions -================================================================= - -.. toctree:: - :maxdepth: 2 - - ../sage/combinat/ncsf_qsym/tutorial - ../sage/combinat/ncsf_qsym/combinatorics - ../sage/combinat/ncsf_qsym/generic_basis_code - ../sage/combinat/ncsf_qsym/ncsf - ../sage/combinat/ncsf_qsym/qsym diff --git a/src/doc/en/reference/combinat/ncsym.rst b/src/doc/en/reference/combinat/ncsym.rst deleted file mode 100644 index e06e8345861..00000000000 --- a/src/doc/en/reference/combinat/ncsym.rst +++ /dev/null @@ -1,10 +0,0 @@ -Symmetric Functions in Non-Commuting Variables -============================================== - -.. toctree:: - :maxdepth: 2 - - ../sage/combinat/ncsym/bases - ../sage/combinat/ncsym/dual - ../sage/combinat/ncsym/ncsym - diff --git a/src/doc/en/reference/combinat/partitions.rst b/src/doc/en/reference/combinat/partitions.rst deleted file mode 100644 index 19b3f4feb7f..00000000000 --- a/src/doc/en/reference/combinat/partitions.rst +++ /dev/null @@ -1,9 +0,0 @@ -Partitions and Partition-like Objects -===================================== - -.. toctree:: - :maxdepth: 2 - - sage/combinat/partition - sage/combinat/partition_tuple - sage/combinat/skew_partition diff --git a/src/doc/en/reference/combinat/posets.rst b/src/doc/en/reference/combinat/posets.rst deleted file mode 100644 index 54cecfec639..00000000000 --- a/src/doc/en/reference/combinat/posets.rst +++ /dev/null @@ -1,12 +0,0 @@ -Posets -====== - -.. toctree:: - :maxdepth: 1 - - ../sage/combinat/posets/posets - ../sage/combinat/posets/hasse_diagram - ../sage/combinat/posets/elements - ../sage/combinat/posets/lattices - ../sage/combinat/posets/linear_extensions - ../sage/combinat/posets/poset_examples diff --git a/src/doc/en/reference/combinat/rc_bijections.rst b/src/doc/en/reference/combinat/rc_bijections.rst deleted file mode 100644 index f20901e3382..00000000000 --- a/src/doc/en/reference/combinat/rc_bijections.rst +++ /dev/null @@ -1,17 +0,0 @@ -Rigged Configuration Bijections -=============================== - -.. toctree:: - :maxdepth: 1 - - ../sage/combinat/rigged_configurations/bijection - ../sage/combinat/rigged_configurations/bij_abstract_class - ../sage/combinat/rigged_configurations/bij_type_A - ../sage/combinat/rigged_configurations/bij_type_B - ../sage/combinat/rigged_configurations/bij_type_C - ../sage/combinat/rigged_configurations/bij_type_D - ../sage/combinat/rigged_configurations/bij_type_A2_odd - ../sage/combinat/rigged_configurations/bij_type_A2_even - ../sage/combinat/rigged_configurations/bij_type_A2_dual - ../sage/combinat/rigged_configurations/bij_type_D_twisted - diff --git a/src/doc/en/reference/combinat/rigged_configurations.rst b/src/doc/en/reference/combinat/rigged_configurations.rst deleted file mode 100644 index 5242a466514..00000000000 --- a/src/doc/en/reference/combinat/rigged_configurations.rst +++ /dev/null @@ -1,22 +0,0 @@ -Rigged Configurations -===================== - -.. toctree:: - :maxdepth: 1 - - ../sage/combinat/rigged_configurations/rc_crystal - ../sage/combinat/rigged_configurations/rc_infinity - - ../sage/combinat/rigged_configurations/rigged_configurations - ../sage/combinat/rigged_configurations/rigged_configuration_element - - ../sage/combinat/rigged_configurations/tensor_product_kr_tableaux - ../sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element - ../sage/combinat/rigged_configurations/kr_tableaux - - ../sage/combinat/rigged_configurations/kleber_tree - - ../sage/combinat/rigged_configurations/rigged_partition - - rc_bijections - diff --git a/src/doc/en/reference/combinat/root_systems.rst b/src/doc/en/reference/combinat/root_systems.rst deleted file mode 100644 index 42fdeaf095e..00000000000 --- a/src/doc/en/reference/combinat/root_systems.rst +++ /dev/null @@ -1,31 +0,0 @@ -Root Systems -============ - -.. toctree:: - :maxdepth: 2 - - ../sage/combinat/root_system/cartan_type - ../sage/combinat/root_system/dynkin_diagram - ../sage/combinat/root_system/cartan_matrix - ../sage/combinat/root_system/coxeter_matrix - ../sage/combinat/root_system/type_folded - - ../sage/combinat/root_system/root_system - ../sage/combinat/root_system/plot - ../sage/combinat/root_system/root_lattice_realizations - ../sage/combinat/root_system/root_lattice_realization_algebras - ../sage/combinat/root_system/weight_lattice_realizations - ../sage/combinat/root_system/root_space - ../sage/combinat/root_system/weight_space - ../sage/combinat/root_system/ambient_space - - ../sage/combinat/root_system/coxeter_group - ../sage/combinat/root_system/weyl_group - - ../sage/combinat/root_system/weyl_characters - ../sage/combinat/root_system/branching_rules - ../sage/combinat/root_system/hecke_algebra_representation - ../sage/combinat/root_system/non_symmetric_macdonald_polynomials - - root_systems_types - diff --git a/src/doc/en/reference/combinat/root_systems_types.rst b/src/doc/en/reference/combinat/root_systems_types.rst deleted file mode 100644 index 2cea9fee5cd..00000000000 --- a/src/doc/en/reference/combinat/root_systems_types.rst +++ /dev/null @@ -1,29 +0,0 @@ -Root System Types -================= - -.. toctree:: - :maxdepth: 2 - - ../sage/combinat/root_system/type_affine - ../sage/combinat/root_system/type_dual - ../sage/combinat/root_system/type_marked - ../sage/combinat/root_system/type_reducible - ../sage/combinat/root_system/type_relabel - ../sage/combinat/root_system/type_A - ../sage/combinat/root_system/type_B - ../sage/combinat/root_system/type_C - ../sage/combinat/root_system/type_D - ../sage/combinat/root_system/type_E - ../sage/combinat/root_system/type_F - ../sage/combinat/root_system/type_G - ../sage/combinat/root_system/type_H - ../sage/combinat/root_system/type_I - ../sage/combinat/root_system/type_A_affine - ../sage/combinat/root_system/type_B_affine - ../sage/combinat/root_system/type_C_affine - ../sage/combinat/root_system/type_D_affine - ../sage/combinat/root_system/type_E_affine - ../sage/combinat/root_system/type_F_affine - ../sage/combinat/root_system/type_G_affine - ../sage/combinat/root_system/type_BC_affine - diff --git a/src/doc/en/reference/combinat/species.rst b/src/doc/en/reference/combinat/species.rst deleted file mode 100644 index 76f62e4c96d..00000000000 --- a/src/doc/en/reference/combinat/species.rst +++ /dev/null @@ -1,54 +0,0 @@ -Combinatorial Species -===================== - - -Power Series ------------- - -.. toctree:: - :maxdepth: 2 - - ../sage/combinat/species/stream - ../sage/combinat/species/series_order - ../sage/combinat/species/series - ../sage/combinat/species/generating_series - -Basic Species -------------- - -.. toctree:: - :maxdepth: 2 - - ../sage/combinat/species/species - ../sage/combinat/species/empty_species - ../sage/combinat/species/recursive_species - ../sage/combinat/species/characteristic_species - ../sage/combinat/species/cycle_species - ../sage/combinat/species/partition_species - ../sage/combinat/species/permutation_species - ../sage/combinat/species/linear_order_species - ../sage/combinat/species/set_species - ../sage/combinat/species/subset_species - ../sage/combinat/species/library - -Operations on Species ---------------------- - -.. toctree:: - :maxdepth: 2 - - ../sage/combinat/species/sum_species - ../sage/combinat/species/product_species - ../sage/combinat/species/composition_species - ../sage/combinat/species/functorial_composition_species - -Miscellaneous -------------- - -.. toctree:: - :maxdepth: 2 - - ../sage/combinat/species/structure - ../sage/combinat/species/misc - ../sage/combinat/species/combinatorial_logarithm - diff --git a/src/doc/en/reference/combinat/symmetric_functions.rst b/src/doc/en/reference/combinat/symmetric_functions.rst deleted file mode 100644 index 4a25c4c0f45..00000000000 --- a/src/doc/en/reference/combinat/symmetric_functions.rst +++ /dev/null @@ -1,26 +0,0 @@ -Symmetric Functions -=================== - -.. toctree:: - :maxdepth: 2 - - ../sage/combinat/sf/sfa - ../sage/combinat/sf/sf - ../sage/combinat/sf/classical - ../sage/combinat/sf/schur - ../sage/combinat/sf/monomial - ../sage/combinat/sf/multiplicative - ../sage/combinat/sf/elementary - ../sage/combinat/sf/homogeneous - ../sage/combinat/sf/powersum - ../sage/combinat/sf/dual - ../sage/combinat/sf/orthotriang - ../sage/combinat/sf/kfpoly - ../sage/combinat/sf/hall_littlewood - ../sage/combinat/sf/jack - ../sage/combinat/sf/new_kschur - ../sage/combinat/sf/k_dual - ../sage/combinat/sf/llt - ../sage/combinat/sf/macdonald - ../sage/combinat/sf/ns_macdonald - ../sage/combinat/sf/witt diff --git a/src/doc/en/reference/combinat/tableaux.rst b/src/doc/en/reference/combinat/tableaux.rst deleted file mode 100644 index f33bd3db3ef..00000000000 --- a/src/doc/en/reference/combinat/tableaux.rst +++ /dev/null @@ -1,12 +0,0 @@ -Tableaux and Tableaux-like Objects -================================== - -.. toctree:: - :maxdepth: 2 - - sage/combinat/tableau - sage/combinat/skew_tableau - sage/combinat/ribbon - sage/combinat/ribbon_tableau - sage/combinat/tableau_tuple - sage/combinat/k_tableau diff --git a/src/doc/en/reference/combinat/words.rst b/src/doc/en/reference/combinat/words.rst deleted file mode 100644 index eb827ea8984..00000000000 --- a/src/doc/en/reference/combinat/words.rst +++ /dev/null @@ -1,17 +0,0 @@ -Words -===== - -.. toctree:: - :maxdepth: 2 - - ../sage/combinat/words/alphabet - ../sage/combinat/words/abstract_word - ../sage/combinat/words/finite_word - ../sage/combinat/words/infinite_word - ../sage/combinat/words/word - ../sage/combinat/words/word_generators - ../sage/combinat/words/words - ../sage/combinat/words/shuffle_product - ../sage/combinat/words/suffix_trees - ../sage/combinat/words/morphism - ../sage/combinat/words/paths diff --git a/src/doc/en/reference/data_structures/index.rst b/src/doc/en/reference/data_structures/index.rst index 08696ce02ae..0bc8339d83c 100644 --- a/src/doc/en/reference/data_structures/index.rst +++ b/src/doc/en/reference/data_structures/index.rst @@ -1,9 +1,10 @@ -Data structures +Data Structures =============== .. toctree:: :maxdepth: 2 sage/data_structures/bitset + sage/data_structures/bounded_integer_sequences .. include:: ../footer.txt diff --git a/src/doc/en/reference/dynamics/index.rst b/src/doc/en/reference/dynamics/index.rst index 3ded1bba00b..7bc1004aed2 100644 --- a/src/doc/en/reference/dynamics/index.rst +++ b/src/doc/en/reference/dynamics/index.rst @@ -1,3 +1,5 @@ +.. _sage.dynamics: + Discrete dynamics ================= diff --git a/src/doc/en/reference/graphs/index.rst b/src/doc/en/reference/graphs/index.rst index a598f8c6fe0..0a6995e6147 100644 --- a/src/doc/en/reference/graphs/index.rst +++ b/src/doc/en/reference/graphs/index.rst @@ -1,3 +1,4 @@ +.. _sage.graphs: Graph Theory ============ diff --git a/src/doc/en/reference/groups/index.rst b/src/doc/en/reference/groups/index.rst index 72ea0bfa33d..b0974cdc9bf 100644 --- a/src/doc/en/reference/groups/index.rst +++ b/src/doc/en/reference/groups/index.rst @@ -23,12 +23,14 @@ Groups sage/groups/abelian_gps/abelian_group_morphism sage/groups/additive_abelian/additive_abelian_group sage/groups/additive_abelian/additive_abelian_wrapper + sage/groups/perm_gps/permutation_groups_catalog sage/groups/perm_gps/permgroup sage/groups/perm_gps/permgroup_named sage/groups/perm_gps/permgroup_element sage/groups/perm_gps/permgroup_morphism sage/groups/perm_gps/cubegroup sage/groups/perm_gps/symgp_conjugacy_class + sage/groups/matrix_gps/catalog sage/groups/matrix_gps/matrix_group sage/groups/matrix_gps/group_element sage/groups/matrix_gps/finitely_generated diff --git a/src/doc/en/reference/index.rst b/src/doc/en/reference/index.rst index bf6c7aeae25..bda723ef6c6 100644 --- a/src/doc/en/reference/index.rst +++ b/src/doc/en/reference/index.rst @@ -35,6 +35,7 @@ Structures, Coercion, Categories -------------------------------- * :doc:`Basic Structures ` +* :doc:`Data Structures ` * :doc:`Coercion ` * :doc:`Category Theory and Categories ` diff --git a/src/doc/en/reference/repl/options.rst b/src/doc/en/reference/repl/options.rst index a8738520ce5..10e1e9d6a97 100644 --- a/src/doc/en/reference/repl/options.rst +++ b/src/doc/en/reference/repl/options.rst @@ -208,8 +208,6 @@ Command-line options for Sage - ``--bdist VER`` -- build a binary distribution of Sage, with version ``VER`` - ``--sdist`` -- build a source distribution of Sage -- ``--crap sage-ver.tar`` -- detect suspicious garbage in the Sage - source tarball .. rubric:: Valgrind memory debugging diff --git a/src/module_list.py b/src/module_list.py index 34a8b37f41e..0684b954b7c 100755 --- a/src/module_list.py +++ b/src/module_list.py @@ -285,6 +285,10 @@ def uname_specific(name, value, alternative): ## ################################ + Extension('sage.data_structures.bounded_integer_sequences', + sources = ['sage/data_structures/bounded_integer_sequences.pyx'], + libraries = ['gmp']), + Extension('sage.data_structures.bitset', sources = ['sage/data_structures/bitset.pyx'], libraries = ['gmp']), diff --git a/src/sage/algebras/all.py b/src/sage/algebras/all.py index 79404a916bc..4e6c1d9f0d6 100644 --- a/src/sage/algebras/all.py +++ b/src/sage/algebras/all.py @@ -38,7 +38,7 @@ from group_algebra_new import GroupAlgebra -from iwahori_hecke_algebra import IwahoriHeckeAlgebra, IwahoriHeckeAlgebraT +from iwahori_hecke_algebra import IwahoriHeckeAlgebra from affine_nil_temperley_lieb import AffineNilTemperleyLiebTypeA lazy_import('sage.algebras.nil_coxeter_algebra', 'NilCoxeterAlgebra') diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py index f59e67985a7..3e9fab6156f 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py @@ -170,8 +170,7 @@ def _Hom_(self, B, category): sage: A._Hom_(B, A.category()) Set of Homomorphisms from Finite-dimensional algebra of degree 1 over Rational Field to Finite-dimensional algebra of degree 2 over Rational Field """ - if isinstance(B, FiniteDimensionalAlgebra): - category = FiniteDimensionalAlgebrasWithBasis(self.base_ring()).or_subcategory(category) + if category.is_subcategory(FiniteDimensionalAlgebrasWithBasis(self.base_ring())): from sage.algebras.finite_dimensional_algebras.finite_dimensional_algebra_morphism import FiniteDimensionalAlgebraHomset return FiniteDimensionalAlgebraHomset(self, B, category=category) return super(FiniteDimensionalAlgebra, self)._Hom_(B, category) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index d826ae4f228..3bd17b63960 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2270,23 +2270,6 @@ def to_T_basis(self, w): # \tau is the Hecke involution. return (-1)**w.length()*self.realization_of().Cp().to_T_basis(w).hash_involution() -def IwahoriHeckeAlgebraT(W, q1, q2=-1, base_ring=None, prefix="T"): - """ - TESTS:: - - sage: H = IwahoriHeckeAlgebraT("A2", 1) - doctest:...: DeprecationWarning: this class is deprecated. Use IwahoriHeckeAlgebra().T instead - See http://trac.sagemath.org/14261 for details. - """ - from sage.misc.superseded import deprecation - deprecation(14261,'this class is deprecated. Use IwahoriHeckeAlgebra().T instead') - if W not in CoxeterGroups(): - W = WeylGroup(W) - if base_ring is None: - base_ring = q1.parent() - q2 = base_ring(q2) - return IwahoriHeckeAlgebra(W, q1=q1, q2=q2, base_ring=base_ring).T(prefix=prefix) - from sage.structure.sage_object import register_unpickle_override register_unpickle_override('sage.algebras.iwahori_hecke_algebra', - 'IwahoriHeckeAlgebraT', IwahoriHeckeAlgebraT) + 'IwahoriHeckeAlgebraT', IwahoriHeckeAlgebra) diff --git a/src/sage/all.py b/src/sage/all.py index e1a7289eb73..acdb356cc00 100644 --- a/src/sage/all.py +++ b/src/sage/all.py @@ -97,6 +97,7 @@ except ImportError: pass # dev scripts are disabled +from sage.structure.all import * from sage.rings.all import * from sage.matrix.all import * @@ -111,7 +112,6 @@ from sage.graphs.all import * from sage.groups.all import * from sage.databases.all import * -from sage.structure.all import * from sage.categories.all import * from sage.sets.all import * from sage.probability.all import * @@ -188,6 +188,11 @@ from sage.rings.qqbar import _init_qqbar _init_qqbar() +# Add SAGE_SRC at the end of sys.path to enable Cython tracebacks +# (which use paths relative to SAGE_SRC) +sys.path.append(sage.env.SAGE_SRC) + + ########################################################### #### WARNING: # DO *not* import numpy / matplotlib / networkx here!! @@ -196,25 +201,10 @@ # when they are first needed. ########################################################### -################################################################### - -# maximize memory resources -#try: -# import resource # unix only... -# resource.setrlimit(resource.RLIMIT_AS, (-1,-1)) -#except Exception: -# pass - -# very useful 2-letter shortcuts CC = ComplexField() QQ = RationalField() RR = RealField() # default real field ZZ = IntegerRing() -# NOTE: QQ, RR, and ZZ are used by the pre-parser, and should not be -# overwritten by the user, unless they want to change the meaning of -# int and real in the interpreter (which is a potentially valid thing -# to do, and doesn't mess up anything else in the Sage library). - true = True false = False diff --git a/src/sage/all_notebook.py b/src/sage/all_notebook.py index 3c8ac98c6fd..741fee09f32 100644 --- a/src/sage/all_notebook.py +++ b/src/sage/all_notebook.py @@ -20,9 +20,7 @@ from sage.misc.html import html -from sage.server.support import help - -from sagenb.misc.support import automatic_names +from sagenb.misc.support import help, automatic_names sage.misc.session.init() diff --git a/src/sage/calculus/desolvers.py b/src/sage/calculus/desolvers.py index 783e70ae34a..ac28e833249 100644 --- a/src/sage/calculus/desolvers.py +++ b/src/sage/calculus/desolvers.py @@ -706,7 +706,9 @@ def desolve_system(des, vars, ics=None, ivar=None): - ``vars`` - list of dependent variables - - ``ics`` - (optional) list of initial values for ivar and vars + - ``ics`` - (optional) list of initial values for ivar and vars. + If ics is defined, it should provide initial conditions for each variable, + otherwise an exception would be raised. - ``ivar`` - (optional) the independent variable, which must be specified if there is more than one independent variable in the @@ -770,11 +772,31 @@ def desolve_system(des, vars, ics=None, ivar=None): Now type show(P1), show(P2) to view these plots. + Check that :trac:`9824` is fixed:: + + sage: t = var('t') + sage: epsilon = var('epsilon') + sage: x1 = function('x1', t) + sage: x2 = function('x2', t) + sage: de1 = diff(x1,t) == epsilon + sage: de2 = diff(x2,t) == -2 + sage: desolve_system([de1, de2], [x1, x2], ivar=t) + [x1(t) == epsilon*t + x1(0), x2(t) == -2*t + x2(0)] + sage: desolve_system([de1, de2], [x1, x2], ics=[1,1], ivar=t) + Traceback (most recent call last): + ... + ValueError: Initial conditions aren't complete: number of vars is different from number of dependent variables. Got ics = [1, 1], vars = [x1(t), x2(t)] + + AUTHORS: - Robert Bradshaw (10-2008) - Sergey Bykov (10-2014) """ + if ics is not None: + if len(ics) != (len(vars) + 1): + raise ValueError("Initial conditions aren't complete: number of vars is different from number of dependent variables. Got ics = {0}, vars = {1}".format(ics, vars)) + if len(des)==1: return desolve_laplace(des[0], vars[0], ics=ics, ivar=ivar) ivars = set([]) diff --git a/src/sage/calculus/var.pyx b/src/sage/calculus/var.pyx index 599bfb48c00..98592f51979 100644 --- a/src/sage/calculus/var.pyx +++ b/src/sage/calculus/var.pyx @@ -71,12 +71,12 @@ def var(*args, **kwds): Custom latex expression can be assigned to variable:: sage: x = var('sui', latex_name="s_{u,i}"); x._latex_() - 's_{u,i}' + '{s_{u,i}}' In notebook, we can also colorize latex expression:: sage: x = var('sui', latex_name="\\color{red}{s_{u,i}}"); x._latex_() - '\\color{red}{s_{u,i}}' + '{\\color{red}{s_{u,i}}}' We can substitute a new variable name for n:: diff --git a/src/sage/categories/additive_magmas.py b/src/sage/categories/additive_magmas.py index 1ae0cebf9cc..d53224417cf 100644 --- a/src/sage/categories/additive_magmas.py +++ b/src/sage/categories/additive_magmas.py @@ -489,7 +489,7 @@ def extra_super_categories(self): sage: AdditiveMagmas().Homsets().extra_super_categories() [Category of additive magmas] sage: AdditiveMagmas().Homsets().super_categories() - [Category of additive magmas] + [Category of additive magmas, Category of homsets] """ return [AdditiveMagmas()] @@ -864,7 +864,7 @@ def extra_super_categories(self): sage: AdditiveMagmas().AdditiveUnital().Homsets().extra_super_categories() [Category of additive unital additive magmas] sage: AdditiveMagmas().AdditiveUnital().Homsets().super_categories() - [Category of additive unital additive magmas] + [Category of additive unital additive magmas, Category of homsets] """ return [AdditiveMagmas().AdditiveUnital()] diff --git a/src/sage/categories/examples/finite_coxeter_groups.py b/src/sage/categories/examples/finite_coxeter_groups.py index d9a0bd75260..029e1b07274 100644 --- a/src/sage/categories/examples/finite_coxeter_groups.py +++ b/src/sage/categories/examples/finite_coxeter_groups.py @@ -145,6 +145,7 @@ def __contains__(self, x): Check in the element x is in the mathematical parent self. EXAMPLES:: + sage: D5 = FiniteCoxeterGroups().example() sage: D5.an_element() in D5 True @@ -153,7 +154,7 @@ def __contains__(self, x): (also tested by :meth:`test_an_element` :meth:`test_some_elements`) """ - from sage.misc.functional import parent + from sage.structure.all import parent return parent(x) is self @cached_method diff --git a/src/sage/categories/fields.py b/src/sage/categories/fields.py index 8260966d3c0..ebcc79f9708 100644 --- a/src/sage/categories/fields.py +++ b/src/sage/categories/fields.py @@ -126,7 +126,10 @@ def _contains_helper(cls): sage: P. = QQ[] sage: Q = P.quotient(x^2+2) sage: Q.category() - Join of Category of commutative algebras over Rational Field and Category of subquotients of monoids and Category of quotients of semigroups + Join of Category of integral domains + and Category of commutative algebras over Rational Field + and Category of subquotients of monoids + and Category of quotients of semigroups sage: F = Fields() sage: F._contains_helper(Q) False diff --git a/src/sage/categories/hecke_modules.py b/src/sage/categories/hecke_modules.py index 2f1cb3a29d1..a1c12a3f02b 100644 --- a/src/sage/categories/hecke_modules.py +++ b/src/sage/categories/hecke_modules.py @@ -151,15 +151,14 @@ def _Hom_(self, Y, category): return HeckeModuleHomspace(self, Y, category = category) class Homsets(HomsetsCategory): - def extra_super_categories_disabled(self): - """ - EXAMPLES:: + """ + .. TODO:: shall there be any additional category structure on Homsets of hecke modules? - sage: HeckeModules(ZZ).Homsets().extra_super_categories() - [Category of homsets] - """ - return [] # FIXME: what category structure is there on Homsets of hecke modules? + TESTS:: + sage: HeckeModules(ZZ).Homsets().super_categories() + [Category of homsets] + """ def base_ring(self): """ diff --git a/src/sage/categories/homsets.py b/src/sage/categories/homsets.py index c9eaa79a8c1..7306aa6e94a 100644 --- a/src/sage/categories/homsets.py +++ b/src/sage/categories/homsets.py @@ -23,126 +23,87 @@ class HomsetsCategory(FunctorialConstructionCategory): _functor_category = "Homsets" @classmethod - @cached_function - def category_of(cls, category, *args): + def default_super_categories(cls, category): """ - Return the homsets category of ``category``. - - This classmethod centralizes the construction of all homset - categories. - - The ``cls`` and ``args`` arguments below are essentially - unused. Their purpose is solely to let the code deviate as - little as possible from the generic implementation of this - method: :meth:`FunctorialConstructionCategory.category_of`. - The reason for this deviation is that, unlike in the other - functorial constructions which are covariant, we recurse only - on *full* supercategories; then, we need a special treatment - for the base case were a category neither defines the - ``Homsets`` construction, nor inherits it from its full - supercategories. + Return the default super categories of ``category.Homsets()``. INPUT: - - ``cls`` -- :class:`HomsetsCategory` or a subclass thereof + - ``cls`` -- the category class for the functor `F` - ``category`` -- a category `Cat` - - ``*args`` -- (unused) + + OUTPUT: a category + + As for the other functorial constructions, if ``category`` + implements a nested ``Homsets`` class, this method is used in + combination with ``category.Homsets().extra_super_categories()`` + to compute the super categories of ``category.Homsets()``. EXAMPLES: - If ``category`` implements a ``Homsets`` class, then this - class is used to build the homset category:: + If ``category`` has one or more full super categories, then + the join of their respective homsets category is returned. In + this example, this join consists of a single category:: sage: from sage.categories.homsets import HomsetsCategory - sage: H = HomsetsCategory.category_of(Modules(ZZ)); H - Category of homsets of modules over Integer Ring - sage: type(H) - - - Otherwise, if ``category`` has one or more full super - categories, then the join of their respective homsets category - is returned. In this example, the join consists of a single - category:: + sage: from sage.categories.additive_groups import AdditiveGroups - sage: C = Modules(ZZ).WithBasis().FiniteDimensional() + sage: C = AdditiveGroups() sage: C.full_super_categories() - [Category of modules with basis over Integer Ring, - Category of finite dimensional modules over Integer Ring] - sage: H = HomsetsCategory.category_of(C); H - Category of homsets of modules with basis over Integer Ring + [Category of additive inverse additive unital additive magmas, + Category of additive monoids] + sage: H = HomsetsCategory.default_super_categories(C); H + Category of homsets of additive monoids sage: type(H) - - - As a last resort, a :class:`HomsetsOf` of the categories - forming the structure of ``self`` is constructed:: + - sage: H = HomsetsCategory.category_of(Magmas()); H - Category of homsets of magmas - sage: type(H) - + and, given that nothing specific is currently implemented for + homsets of additive groups, ``H`` is directly the category + thereof:: - sage: HomsetsCategory.category_of(Rings()) - Category of homsets of unital magmas and additive unital additive magmas - """ - functor_category = getattr(category.__class__, cls._functor_category) - if isinstance(functor_category, type) and issubclass(functor_category, Category): - return functor_category(category, *args) - elif category.full_super_categories(): - return cls.default_super_categories(category, *args) - else: - return HomsetsOf(Category.join(category.structure())) - - @classmethod - def default_super_categories(cls, category): - """ - Return the default super categories of ``category.Homsets()`` - - INPUT: - - - ``cls`` -- the category class for the functor `F` - - ``category`` -- a category `Cat` + sage: C.Homsets() + Category of homsets of additive monoids - OUTPUT: a category + Similarly for rings: a ring homset is just a homset of unital + magmas and additive magmas:: - .. TODO:: adapt everything below + sage: Rings().Homsets() + Category of homsets of unital magmas and additive unital additive magmas - The default implementation is to return the join of the - categories of `F(A,B,...)` for `A,B,...` in turn in each of - the super categories of ``category``. + Otherwise, if ``category`` implements a nested class + ``Homsets``, this method returns the category of all homsets:: - This is implemented as a class method, in order to be able to - reconstruct the functorial category associated to each of the - super categories of ``category``. + sage: AdditiveMagmas.Homsets + + sage: HomsetsCategory.default_super_categories(AdditiveMagmas()) + Category of homsets - EXAMPLES:: + which gives one of the super categories of + ``category.Homsets()``:: sage: AdditiveMagmas().Homsets().super_categories() - [Category of additive magmas] + [Category of additive magmas, Category of homsets] sage: AdditiveMagmas().AdditiveUnital().Homsets().super_categories() - [Category of additive unital additive magmas] - - For now nothing specific is implemented for homsets of - additive groups compared to homsets of monoids:: - - sage: from sage.categories.additive_groups import AdditiveGroups - sage: AdditiveGroups().Homsets() - Category of homsets of additive monoids + [Category of additive unital additive magmas, Category of homsets] - Similarly for rings; so a ring homset is a homset of unital - magmas and additive magmas:: + the other coming from ``category.Homsets().extra_super_categories()``:: - sage: Rings().Homsets() - Category of homsets of unital magmas and additive unital additive magmas - """ - return Category.join([getattr(cat, cls._functor_category)() - for cat in category.full_super_categories()]) + sage: AdditiveMagmas().Homsets().extra_super_categories() + [Category of additive magmas] + Finally, as a last resort, this method returns a stub category + modelling the homsets of this category:: - def extra_super_categories(self): - """ - Return the extra super categories of ``self``. + sage: hasattr(Posets, "Homsets") + False + sage: H = HomsetsCategory.default_super_categories(Posets()); H + Category of homsets of posets + sage: type(H) + + sage: Posets().Homsets() + Category of homsets of posets - EXAMPLES:: + TESTS:: sage: Objects().Homsets().super_categories() [Category of homsets] @@ -151,8 +112,15 @@ def extra_super_categories(self): sage: (Magmas() & Posets()).Homsets().super_categories() [Category of homsets] """ - return [Homsets()] - + if category.full_super_categories(): + return Category.join([getattr(cat, cls._functor_category)() + for cat in category.full_super_categories()]) + else: + functor_category = getattr(category.__class__, cls._functor_category) + if isinstance(functor_category, type) and issubclass(functor_category, Category): + return Homsets() + else: + return HomsetsOf(Category.join(category.structure())) def _test_homsets_category(self, **options): r""" @@ -169,6 +137,7 @@ def _test_homsets_category(self, **options): #from sage.categories.sets_cat import Sets tester = self._tester(**options) tester.assert_(self.is_subcategory(Category.join(self.base_category().structure()).Homsets())) + tester.assert_(self.is_subcategory(Homsets())) @cached_method def base(self): @@ -233,6 +202,24 @@ def _repr_object_names(self): object_names = ' and '.join(cat._repr_object_names() for cat in base_category.super_categories()) return "homsets of %s"%(object_names) + def super_categories(self): + r""" + Return the super categories of ``self``. + + A stub homset category admits a single super category, namely + the category of all homsets. + + EXAMPLES: + + sage: C = (Magmas() & Posets()).Homsets(); C + Category of homsets of magmas and posets + sage: type(C) + + sage: C.super_categories() + [Category of homsets] + """ + return [Homsets()] + class Homsets(Category_singleton): """ The category of all homsets. @@ -252,10 +239,17 @@ class Homsets(Category_singleton): or equivalently that we only implement locally small categories. See :wikipedia:`Category_(mathematics)`. - .. TODO:: + :trac:`17364`: every homset category shall be a subcategory of the + category of all homsets: + + sage: Schemes().Homsets().is_subcategory(Homsets()) + True + sage: AdditiveMagmas().Homsets().is_subcategory(Homsets()) + True + sage: AdditiveMagmas().AdditiveUnital().Homsets().is_subcategory(Homsets()) + True - We would want a more general mechanism. See also - :meth:`Monoids.Homsets.extra_super_categories`. + This is tested in :meth:`HomsetsCategory._test_homsets_category`. """ def super_categories(self): """ diff --git a/src/sage/categories/map.pxd b/src/sage/categories/map.pxd index c364d90262b..4d2b0d7fe63 100644 --- a/src/sage/categories/map.pxd +++ b/src/sage/categories/map.pxd @@ -15,6 +15,7 @@ cdef class Map(Element): cdef public domain # will be either a weakref or a constant map cdef public codomain # will be a constant map cdef Parent _codomain # for accessing the codomain directly + cdef object _category_for # category in which this is a morphism cdef public _repr_type_str diff --git a/src/sage/categories/map.pyx b/src/sage/categories/map.pyx index 95b572901d1..4ed59b2b908 100644 --- a/src/sage/categories/map.pyx +++ b/src/sage/categories/map.pyx @@ -135,6 +135,7 @@ cdef class Map(Element): Element.__init__(self, parent) D = parent.domain() C = parent.codomain() + self._category_for = parent.homset_category() self._codomain = C self.domain = ConstantFunction(D) self.codomain = ConstantFunction(C) @@ -235,7 +236,7 @@ cdef class Map(Element): C = self._codomain if C is None or D is None: raise ValueError("This map is in an invalid state, the domain has been garbage collected") - return homset.Hom(D, C) + return homset.Hom(D, C, self._category_for) return self._parent def _make_weak_references(self): @@ -295,6 +296,8 @@ cdef class Map(Element): if not isinstance(self.domain, ConstantFunction): return self.domain = weakref.ref(self.domain()) + # Save the category before clearing the parent. + self._category_for = self._parent.homset_category() self._parent = None def _make_strong_references(self): @@ -367,7 +370,7 @@ cdef class Map(Element): if D is None or C is None: raise RuntimeError("The domain of this map became garbage collected") self.domain = ConstantFunction(D) - self._parent = homset.Hom(D, C) + self._parent = homset.Hom(D, C, self._category_for) cdef _update_slots(self, dict _slots): """ @@ -624,7 +627,14 @@ cdef class Map(Element): FIXME: find a better name for this method """ - return self.parent().homset_category() + if self._category_for is None: + # This can happen if the map is the result of unpickling. + # We have initialised self._parent, but could not set + # self._category_for at that moment, because it could + # happen that the parent was not fully constructed and + # did not know its category yet. + self._category_for = self._parent.homset_category() + return self._category_for def __call__(self, x, *args, **kwds): """ diff --git a/src/sage/categories/pushout.py b/src/sage/categories/pushout.py index 6565d807e87..5ea332dfb52 100644 --- a/src/sage/categories/pushout.py +++ b/src/sage/categories/pushout.py @@ -91,12 +91,13 @@ class ConstructionFunctor(Functor): """ def __mul__(self, other): """ - Compose construction functors to a composit construction functor, unless one of them is the identity. + Compose ``self`` and ``other`` to a composite construction + functor, unless one of them is the identity. NOTE: - The product is in functorial notation, i.e., when applying the product to an object - then the second factor is applied first. + The product is in functorial notation, i.e., when applying the + product to an object, the second factor is applied first. TESTS:: @@ -286,6 +287,9 @@ def expand(self): """ return [self] + # See the pushout() function below for explanation. + coercion_reversed = False + class CompositeConstructionFunctor(ConstructionFunctor): """ @@ -1719,6 +1723,10 @@ class SubspaceFunctor(ConstructionFunctor): """ rank = 11 # ranking of functor, not rank of module + # The subspace construction returns an object admitting a coercion + # map into the original, not vice versa. + coercion_reversed = True + def __init__(self, basis): """ INPUT: @@ -3061,48 +3069,53 @@ def __cmp__(self, other): def pushout(R, S): r""" - Given a pair of Objects R and S, try and construct a - reasonable object Y and return maps such that - canonically $R \leftarrow Y \rightarrow S$. + Given a pair of objects `R` and `S`, try to construct a + reasonable object `Y` and return maps such that + canonically `R \leftarrow Y \rightarrow S`. ALGORITHM: - This incorporates the idea of functors discussed Sage Days 4. - Every object R can be viewed as an initial object and - a series of functors (e.g. polynomial, quotient, extension, - completion, vector/matrix, etc.). Call the series of - increasingly-simple rings (with the associated functors) - the "tower" of R. The construction method is used to - create the tower. + This incorporates the idea of functors discussed at Sage Days 4. + Every object `R` can be viewed as an initial object and a series + of functors (e.g. polynomial, quotient, extension, completion, + vector/matrix, etc.). Call the series of increasingly simple + objects (with the associated functors) the "tower" of `R`. The + construction method is used to create the tower. - Given two objects R and S, try and find a common initial - object Z. If the towers of R and S meet, let Z be their - join. Otherwise, see if the top of one coerces naturally into - the other. + Given two objects `R` and `S`, try to find a common initial object + `Z`. If the towers of `R` and `S` meet, let `Z` be their join. + Otherwise, see if the top of one coerces naturally into the other. - Now we have an initial object and two ordered lists of - functors to apply. We wish to merge these in an unambiguous order, - popping elements off the top of one or the other tower as we - apply them to Z. + Now we have an initial object and two ordered lists of functors to + apply. We wish to merge these in an unambiguous order, popping + elements off the top of one or the other tower as we apply them to + `Z`. - - If the functors are distinct types, there is an absolute ordering - given by the rank attribute. Use this. + - If the functors are of distinct types, there is an absolute + ordering given by the rank attribute. Use this. - Otherwise: - If the tops are equal, we (try to) merge them. - - If exactly one occurs lower in the other tower - we may unambiguously apply the other (hoping for a later merge). + - If exactly one occurs lower in the other tower, we may + unambiguously apply the other (hoping for a later merge). - If the tops commute, we can apply either first. - Otherwise fail due to ambiguity. + The algorithm assumes by default that when a construction `F` is + applied to an object `X`, the object `F(X)` admits a coercion map + from `X`. However, the algorithm can also handle the case where + `F(X)` has a coercion map *to* `X` instead. In this case, the + attribute ``coercion_reversed`` of the class implementing `F` + should be set to ``True``. + EXAMPLES: - Here our "towers" are $R = Complete_7(Frac(\ZZ))$ and $Frac(Poly_x(\ZZ))$, - which give us $Frac(Poly_x(Complete_7(Frac(\ZZ))))$:: + Here our "towers" are `R = Complete_7(Frac(\ZZ))` and `Frac(Poly_x(\ZZ))`, + which give us `Frac(Poly_x(Complete_7(Frac(\ZZ))))`:: sage: from sage.categories.pushout import pushout sage: pushout(Qp(7), Frac(ZZ['x'])) @@ -3141,6 +3154,75 @@ def pushout(R, S): sage: pushout(Frac(ZZ['x']), QQ[['x']]) Laurent Series Ring in x over Rational Field + A construction with ``coercion_reversed = True`` (currently only + the :class:`SubspaceFunctor` construction) is only applied if it + leads to a valid coercion:: + + sage: A = ZZ^2 + sage: V = span([[1, 2]], QQ) + sage: P = sage.categories.pushout.pushout(A, V) + sage: P + Vector space of dimension 2 over Rational Field + sage: P.has_coerce_map_from(A) + True + + sage: V = (QQ^3).span([[1, 2, 3/4]]) + sage: A = ZZ^3 + sage: pushout(A, V) + Vector space of dimension 3 over Rational Field + sage: B = A.span([[0, 0, 2/3]]) + sage: pushout(B, V) + Vector space of degree 3 and dimension 2 over Rational Field + User basis matrix: + [1 2 0] + [0 0 1] + + Some more tests with ``coercion_reversed = True``:: + + sage: from sage.categories.pushout import ConstructionFunctor + sage: class EvenPolynomialRing(type(QQ['x'])): + ....: def __init__(self, base, var): + ....: super(EvenPolynomialRing, self).__init__(base, var) + ....: self.register_embedding(base[var]) + ....: def __repr__(self): + ....: return "Even Power " + super(EvenPolynomialRing, self).__repr__() + ....: def construction(self): + ....: return EvenPolynomialFunctor(), self.base()[self.variable_name()] + ....: def _coerce_map_from_(self, R): + ....: return self.base().has_coerce_map_from(R) + ....: + sage: class EvenPolynomialFunctor(ConstructionFunctor): + ....: rank = 10 + ....: coercion_reversed = True + ....: def __init__(self): + ....: ConstructionFunctor.__init__(self, Rings(), Rings()) + ....: def __call__(self, R): + ....: return EvenPolynomialRing(R.base(), R.variable_name()) + ....: + sage: pushout(EvenPolynomialRing(QQ, 'x'), ZZ) + Even Power Univariate Polynomial Ring in x over Rational Field + sage: pushout(EvenPolynomialRing(QQ, 'x'), QQ) + Even Power Univariate Polynomial Ring in x over Rational Field + sage: pushout(EvenPolynomialRing(QQ, 'x'), RR) + Even Power Univariate Polynomial Ring in x over Real Field with 53 bits of precision + + sage: pushout(EvenPolynomialRing(QQ, 'x'), ZZ['x']) + Univariate Polynomial Ring in x over Rational Field + sage: pushout(EvenPolynomialRing(QQ, 'x'), QQ['x']) + Univariate Polynomial Ring in x over Rational Field + sage: pushout(EvenPolynomialRing(QQ, 'x'), RR['x']) + Univariate Polynomial Ring in x over Real Field with 53 bits of precision + + sage: pushout(EvenPolynomialRing(QQ, 'x'), EvenPolynomialRing(QQ, 'x')) + Even Power Univariate Polynomial Ring in x over Rational Field + sage: pushout(EvenPolynomialRing(QQ, 'x'), EvenPolynomialRing(RR, 'x')) + Even Power Univariate Polynomial Ring in x over Real Field with 53 bits of precision + + sage: pushout(EvenPolynomialRing(QQ, 'x')^2, RR^2) + Ambient free module of rank 2 over the principal ideal domain Even Power Univariate Polynomial Ring in x over Real Field with 53 bits of precision + sage: pushout(EvenPolynomialRing(QQ, 'x')^2, RR['x']^2) + Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in x over Real Field with 53 bits of precision + AUTHORS: -- Robert Bradshaw @@ -3160,9 +3242,11 @@ def pushout(R, S): Ss = [c[1] for c in S_tower] if R in Ss: - return S + if not any(c[0].coercion_reversed for c in S_tower[1:]): + return S elif S in Rs: - return R + if not any(c[0].coercion_reversed for c in R_tower[1:]): + return R if Rs[-1] in Ss: Rs, Ss = Ss, Rs @@ -3197,28 +3281,37 @@ def pushout(R, S): raise CoercionException("No common base") # Rc is a list of functors from Z to R and Sc is a list of functors from Z to S - Rc = [c[0] for c in R_tower[1:len(Rs)+1]] - Sc = [c[0] for c in S_tower[1:len(Ss)+1]] - - Rc = sum([c.expand() for c in Rc], []) - Sc = sum([c.expand() for c in Sc], []) + R_tower = expand_tower(R_tower[:len(Rs)+1]) + S_tower = expand_tower(S_tower[:len(Ss)+1]) + Rc = [c[0] for c in R_tower[1:]] + Sc = [c[0] for c in S_tower[1:]] all = IdentityConstructionFunctor() + def apply_from(Xc): + c = Xc.pop() + if c.coercion_reversed: + Yc = Sc if Xc is Rc else Rc + Y_tower = S_tower if Xc is Rc else R_tower + Y_partial = Y_tower[len(Yc)][1] + if not (c * all)(Z).has_coerce_map_from(Y_partial): + return all + return c * all + try: while len(Rc) > 0 or len(Sc) > 0: # print Z # if we are out of functors in either tower, there is no ambiguity if len(Sc) == 0: - all = Rc.pop() * all + all = apply_from(Rc) elif len(Rc) == 0: - all = Sc.pop() * all + all = apply_from(Sc) # if one of the functors has lower rank, do it first elif Rc[-1].rank < Sc[-1].rank: - all = Rc.pop() * all + all = apply_from(Rc) elif Sc[-1].rank < Rc[-1].rank: - all = Sc.pop() * all + all = apply_from(Sc) else: # the ranks are the same, so things are a bit subtler if Rc[-1] == Sc[-1]: @@ -3241,9 +3334,9 @@ def pushout(R, S): if Sc[-1] in Rc: raise CoercionException("Ambiguous Base Extension", R, S) else: - all = Sc.pop() * all + all = apply_from(Sc) elif Sc[-1] in Rc: - all = Rc.pop() * all + all = apply_from(Rc) # If, perchance, the two functors commute, then we may do them in any order. elif Rc[-1].commutes(Sc[-1]) or Sc[-1].commutes(Rc[-1]): all = Sc.pop() * Rc.pop() * all @@ -3272,18 +3365,18 @@ def pushout(R, S): def pushout_lattice(R, S): r""" - Given a pair of Objects $R$ and $S$, try and construct a - reasonable object $Y$ and return maps such that - canonically $R \leftarrow Y \rightarrow S$. + Given a pair of objects `R` and `S`, try to construct a + reasonable object `Y` and return maps such that + canonically `R \leftarrow Y \rightarrow S`. ALGORITHM: - This is based on the model that arose from much discussion at Sage Days 4. - Going up the tower of constructions of $R$ and $S$ (e.g. the reals - come from the rationals come from the integers) try and find a - common parent, and then try and fill in a lattice with these - two towers as sides with the top as the common ancestor and - the bottom will be the desired ring. + This is based on the model that arose from much discussion at + Sage Days 4. Going up the tower of constructions of `R` and `S` + (e.g. the reals come from the rationals come from the integers), + try to find a common parent, and then try to fill in a lattice + with these two towers as sides with the top as the common ancestor + and the bottom will be the desired ring. See the code for a specific worked-out example. @@ -3478,7 +3571,43 @@ def construction_tower(R): c = R.construction() return tower +def expand_tower(tower): + """ + An auxiliary function that is used in :func:`pushout`. + + INPUT: + + A construction tower as returned by :func:`construction_tower`. + OUTPUT: + + A new construction tower with all the construction functors expanded. + + EXAMPLE:: + + sage: from sage.categories.pushout import construction_tower, expand_tower + sage: construction_tower(QQ['x,y,z']) + [(None, Multivariate Polynomial Ring in x, y, z over Rational Field), + (MPoly[x,y,z], Rational Field), + (FractionField, Integer Ring)] + sage: expand_tower(construction_tower(QQ['x,y,z'])) + [(None, Multivariate Polynomial Ring in x, y, z over Rational Field), + (MPoly[z], Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field), + (MPoly[y], Univariate Polynomial Ring in x over Rational Field), + (MPoly[x], Rational Field), + (FractionField, Integer Ring)] + """ + new_tower = [] + for f, R in reversed(tower): + if f is None: + new_tower.append((f, R)) + else: + fs = f.expand() + for ff in reversed(fs[1:]): + new_tower.append((ff, R)) + R = ff(R) + new_tower.append((fs[0], R)) + return list(reversed(new_tower)) def type_to_parent(P): """ diff --git a/src/sage/categories/schemes.py b/src/sage/categories/schemes.py index 8e4658c586a..dd5ace46f21 100644 --- a/src/sage/categories/schemes.py +++ b/src/sage/categories/schemes.py @@ -146,24 +146,14 @@ def _call_(self, x): class Homsets(HomsetsCategory): - def extra_super_categories(self): - """ - EXAMPLES:: - - sage: Schemes().Homsets().extra_super_categories() - [] - sage: Schemes().Homsets().super_categories() - [Category of objects] - - .. TODO:: - - What category structure is there on Homsets of schemes? - - .. TODO:: check that the result above is correct now - """ - return [] + """ + TESTS:: + sage: Schemes().Homsets().super_categories() + [Category of homsets] + .. TODO:: shall there be any additional category structure on Homsets of hecke modules? + """ ############################################################# # Schemes over a given base scheme. diff --git a/src/sage/categories/unique_factorization_domains.py b/src/sage/categories/unique_factorization_domains.py index 9f2b106528b..206c5d486a6 100644 --- a/src/sage/categories/unique_factorization_domains.py +++ b/src/sage/categories/unique_factorization_domains.py @@ -55,7 +55,7 @@ def additional_structure(self): return None class ParentMethods: - def is_unique_factorization_domain(self): + def is_unique_factorization_domain(self, proof=True): """ Return True, since this in an object of the category of unique factorization domains. diff --git a/src/sage/combinat/__init__.py b/src/sage/combinat/__init__.py index 3f4a1cc701b..ed3aaf07d74 100644 --- a/src/sage/combinat/__init__.py +++ b/src/sage/combinat/__init__.py @@ -1 +1,51 @@ +__doc__ = r""" +Combinatorics +============= + +Introductory material +--------------------- + +- :ref:`sage.combinat.quickref` +- :ref:`sage.combinat.tutorial` + +Thematic indexes +---------------- + +- :ref:`sage.combinat.algebraic_combinatorics` + + - :ref:`sage.combinat.cluster_algebra_quiver` + - :ref:`sage.combinat.crystals` + - :ref:`sage.combinat.root_system` + - :ref:`sage.combinat.sf` + +- :ref:`sage.combinat.counting` +- :ref:`sage.combinat.enumerated_sets` +- :ref:`sage.combinat.catalog_partitions` +- :ref:`sage.combinat.finite_state_machine` +- :ref:`sage.combinat.species` +- :ref:`sage.combinat.designs` +- :ref:`sage.combinat.posets` +- :ref:`sage.combinat.words` + +Utilities +--------- + +- :ref:`sage.combinat.output` +- :ref:`sage.combinat.ranker` +- :func:`Combinatorial maps ` +- :ref:`sage.combinat.misc` + +Related topics +-------------- + +- :ref:`sage.coding` +- :ref:`sage.dynamics` +- :ref:`sage.graphs` + +""" +#import demo +#import demo_short +#import demo_algebraic_combinatorics +#import tutorial_enumerated_sets +import quickref import tutorial diff --git a/src/sage/combinat/algebraic_combinatorics.py b/src/sage/combinat/algebraic_combinatorics.py new file mode 100644 index 00000000000..152fe358b83 --- /dev/null +++ b/src/sage/combinat/algebraic_combinatorics.py @@ -0,0 +1,60 @@ +r""" +Algebraic combinatorics +======================= + +Quickref +-------- + +.. TODO:: write it! + +Thematic tutorials +------------------ + +.. TODO:: get Sphinx to create those cross links properly + +- `Algebraic Combinatorics in Sage <../../../../thematic_tutorials/algebraic_combinatorics.html>`_ +- `Lie Methods and Related Combinatorics in Sage <../../../../thematic_tutorials/lie.html>`_ +- `Linear Programming (Mixed Integer) <../../../../thematic_tutorials/linear_programming.html>`_ + +Enumerated sets of combinatorial objects +---------------------------------------- + +- :ref:`sage.combinat.catalog_partitions` +- :class:`~sage.combinat.gelfand_tsetlin_patterns.GelfandTsetlinPattern`, :class:`~sage.combinat.gelfand_tsetlin_patterns.GelfandTsetlinPatterns` +- :class:`~sage.combinat.knutson_tao_puzzles.KnutsonTaoPuzzleSolver` + +Combinatorial Hopf Algebras +--------------------------- + +- :ref:`sage.combinat.sf` +- :ref:`sage.combinat.ncsf_qsym` +- :ref:`sage.combinat.schubert_polynomial` +- :ref:`sage.combinat.ncsym` + +Groups and Algebras +------------------- + +.. TODO:: add link to the catalog of algebras when it exists + +- :ref:`Groups ` +- :class:`SymmetricGroup`, :class:`CoxeterGroup`, :class:`WeylGroup` +- :class:`~sage.combinat.diagram_algebras.PartitionAlgebra` +- :class:`~sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra` +- :class:`~sage.combinat.symmetric_group_algebra.SymmetricGroupAlgebra` +- :class:`~sage.algebras.nil_coxeter_algebra.NilCoxeterAlgebra` +- :class:`~sage.algebras.affine_nil_temperley_lieb.AffineNilTemperleyLiebTypeA` +- :ref:`sage.combinat.descent_algebra` +- :ref:`sage.combinat.diagram_algebras` + +Combinatorial Representation Theory +----------------------------------- + +- :ref:`sage.combinat.root_system` +- :ref:`sage.combinat.crystals` +- :ref:`sage.combinat.rigged_configurations` +- :ref:`sage.combinat.cluster_algebra_quiver` +- :class:`~sage.combinat.kazhdan_lusztig.KazhdanLusztigPolynomial` +- :class:`~sage.combinat.symmetric_group_representations.SymmetricGroupRepresentation` +- :ref:`sage.combinat.yang_baxter_graph` +- :ref:`sage.combinat.hall_polynomial` +""" diff --git a/src/sage/combinat/all.py b/src/sage/combinat/all.py index 1d0aa066dda..c171cefa2ec 100644 --- a/src/sage/combinat/all.py +++ b/src/sage/combinat/all.py @@ -1,3 +1,6 @@ +""" +Combinatorics features that are imported by default in the interpreter namespace +""" from combinat import bell_number, catalan_number, euler_number, fibonacci, \ lucas_number1, lucas_number2, stirling_number1, stirling_number2, \ CombinatorialObject, CombinatorialClass, FilteredCombinatorialClass, \ @@ -85,9 +88,6 @@ from ribbon_shaped_tableau import RibbonShapedTableau, StandardRibbonShapedTableaux from ribbon_tableau import RibbonTableaux, RibbonTableau, MultiSkewTableaux, MultiSkewTableau, SemistandardMultiSkewTableaux from composition_tableau import CompositionTableau, CompositionTableaux -#deprecated -from ribbon import Ribbon, StandardRibbons - from sage.combinat.tableau_tuple import TableauTuple, StandardTableauTuple, TableauTuples, StandardTableauTuples from k_tableau import WeakTableau, WeakTableaux, StrongTableau, StrongTableaux diff --git a/src/sage/combinat/catalog_partitions.py b/src/sage/combinat/catalog_partitions.py new file mode 100644 index 00000000000..a890577ac07 --- /dev/null +++ b/src/sage/combinat/catalog_partitions.py @@ -0,0 +1,22 @@ +r""" +Enumerated sets of partitions, tableaux, ... +============================================ + +Quickref +-------- + +Catalog +------- + +- :ref:`sage.combinat.partition` +- :ref:`sage.combinat.tableau` +- :ref:`sage.combinat.partition_tuple` +- :ref:`sage.combinat.tableau_tuple` +- :ref:`sage.combinat.skew_partition` +- :ref:`sage.combinat.skew_tableau` +- :ref:`sage.combinat.ribbon` +- :ref:`sage.combinat.ribbon_tableau` +- :ref:`sage.combinat.core` +- :ref:`sage.combinat.k_tableau` +- :ref:`sage.combinat.rsk` +""" diff --git a/src/sage/combinat/cluster_algebra_quiver/__init__.py b/src/sage/combinat/cluster_algebra_quiver/__init__.py index dde638a6077..0c697cb0f2f 100644 --- a/src/sage/combinat/cluster_algebra_quiver/__init__.py +++ b/src/sage/combinat/cluster_algebra_quiver/__init__.py @@ -1 +1,10 @@ -# Initialization file for cluster algebras and quivers +__doc__ = r""" +Cluster Algebras and Quivers +============================ + +- `A compendium on the cluster algebra and quiver package in Sage `_ arXiv:1102.4844 [math.CO] + +- :ref:`sage.combinat.cluster_algebra_quiver.quiver_mutation_type` +- :ref:`sage.combinat.cluster_algebra_quiver.quiver` +- :ref:`sage.combinat.cluster_algebra_quiver.cluster_seed` +""" diff --git a/src/sage/combinat/cluster_algebra_quiver/all.py b/src/sage/combinat/cluster_algebra_quiver/all.py index 31fc8e6253b..44060e2b3cb 100644 --- a/src/sage/combinat/cluster_algebra_quiver/all.py +++ b/src/sage/combinat/cluster_algebra_quiver/all.py @@ -1,3 +1,6 @@ +""" +Cluster algebra and quivers features that are imported by default in the interpreter namespace +""" from sage.misc.lazy_import import lazy_import lazy_import("sage.combinat.cluster_algebra_quiver.quiver_mutation_type", "QuiverMutationType") lazy_import("sage.combinat.cluster_algebra_quiver.quiver", "ClusterQuiver") diff --git a/src/sage/combinat/counting.py b/src/sage/combinat/counting.py new file mode 100644 index 00000000000..65f425baff4 --- /dev/null +++ b/src/sage/combinat/counting.py @@ -0,0 +1,16 @@ +r""" +Counting +======== + +- :ref:`sage.databases.oeis` +- :ref:`sage.combinat.sloane_functions` +- :ref:`sage.combinat.expnums` +- :ref:`sage.combinat.q_analogues`, :ref:`sage.combinat.q_bernoulli` +- :ref:`sage.combinat.binary_recurrence_sequences` +- :ref:`sage.combinat.combinat` + +.. TODO:: + + Mention sage/combinat/degree_sequences? + +""" diff --git a/src/sage/combinat/crystals/__init__.py b/src/sage/combinat/crystals/__init__.py index 149bd499807..f26dcdc1f20 100644 --- a/src/sage/combinat/crystals/__init__.py +++ b/src/sage/combinat/crystals/__init__.py @@ -1,5 +1,28 @@ -#This makes sure that sage.combinat.crystals? points to the correct -#documentation about crystals -from crystals import __doc__ +__doc__ = r""" +Crystals +======== + +Quickref +-------- + +.. TODO:: Write it! + +Introductory material +--------------------- + +- :ref:`sage.combinat.crystals.crystals` +- The `Lie Methods and Related Combinatorics <../../../../../thematic_tutorials/lie.html>`_ thematic tutorial + +Catalogs of crystals +-------------------- + +- :ref:`sage.combinat.crystals.catalog` + +See also +-------- + +- The categories for crystals: :class:`Crystals`, :class:`HighestWeightCrystals`, :class:`FiniteCrystals`, :class:`ClassicalCrystals`, :class:`RegularCrystals` -- The categories for crystals +- :ref:`sage.combinat.root_system` +""" import all diff --git a/src/sage/combinat/crystals/all.py b/src/sage/combinat/crystals/all.py index eb4c093d8be..a644325a7e0 100644 --- a/src/sage/combinat/crystals/all.py +++ b/src/sage/combinat/crystals/all.py @@ -1,3 +1,6 @@ +""" +Crystal features that are imported by default in the interpreter namespace +""" import catalog as crystals from sage.misc.lazy_import import lazy_import diff --git a/src/sage/combinat/crystals/catalog.py b/src/sage/combinat/crystals/catalog.py index 792bb57fe7b..9e8a0204f46 100644 --- a/src/sage/combinat/crystals/catalog.py +++ b/src/sage/combinat/crystals/catalog.py @@ -1,42 +1,6 @@ r""" Catalog Of Crystals -Definition of a Crystal ------------------------ - -Let `C` be a CartanType with index set `I`, and `P` be -the corresponding weight lattice of the type `C`. Let `\alpha_i` -and `\alpha^{\vee}_i` denote the corresponding simple roots -and coroots respectively. Let us give the axiomatic definition -of a crystal. - -A type `C` crystal `\mathcal{B}` is a non-empty set with maps -`\operatorname{wt} : \mathcal{B} \to P`, -`e_i, f_i : \mathcal{B} \to \mathcal{B} \cup \{0\}`, and -`\varepsilon_i, \varphi_i : \mathcal{B} \to \ZZ \cup \{-\infty\}` -for `i \in I` satisfying the following properties for all `i \in I`: - -- `\varphi_i(b) = \varepsilon_i(b) + \langle \alpha^{\vee}_i, - \operatorname{wt}(b) \rangle`, - -- if `e_i b \in \mathcal{B}`, then: - - * `\operatorname{wt}(e_i x) = \operatorname{wt}(b) + \alpha_i`, - * `\varepsilon_i(e_i b) = \varepsilon_i(b) - 1`, - * `\varphi_i(e_i b) = \varphi_i(b) + 1`, - -- if `f_i b \in \mathcal{B}`, then: - - * `\operatorname{wt}(f_i b) = \operatorname{wt}(b) - \alpha_i`, - * `\varepsilon_i(f_i b) = \varepsilon_i(b) + 1`, - * `\varphi_i(f_i b) = \varphi_i(b) - 1`, - -- `f_i b^{\prime} = b` if and only if `e_i b = b^{\prime}` - for `b, b^{\prime} \in \mathcal{B}`, - -- if `\varphi_i(b) = -\infty` for `b \in \mathcal{B}`, - then `e_i b = f_i b = 0`. - .. SEEALSO:: - :mod:`sage.categories.crystals` @@ -45,7 +9,7 @@ Catalog ------- -This is a catalog of crystals that are currently in Sage: +This is a catalog of crystals that are currently implemented in Sage: * :class:`~sage.combinat.crystals.affine.AffineCrystalFromClassical` * :class:`~sage.combinat.crystals.affine.AffineCrystalFromClassicalAndPromotion` @@ -69,16 +33,16 @@ * :class:`SpinsMinus ` * :class:`Tableaux ` +Subcatalogs: + +* :ref:`sage.combinat.crystals.catalog_infinity_crystals` +* :ref:`sage.combinat.crystals.catalog_elementary_crystals` +* :ref:`sage.combinat.crystals.catalog_kirillov_reshetikhin` + Functorial constructions: * :class:`DirectSum ` * :class:`TensorProduct ` - -Subcatalogs: - -* `B(\infty)` :mod:`(infinity) crystals ` -* :mod:`Elementary crystals ` -* :mod:`Kirillov-Reshetihkin crystals ` """ from letters import CrystalOfLetters as Letters from spins import CrystalOfSpins as Spins diff --git a/src/sage/combinat/crystals/crystals.py b/src/sage/combinat/crystals/crystals.py index 1a079c863dd..d63e8c11bb8 100644 --- a/src/sage/combinat/crystals/crystals.py +++ b/src/sage/combinat/crystals/crystals.py @@ -1,36 +1,69 @@ r""" -Crystals +An introduction to crystals +=========================== -Let `T` be a CartanType with index set `I`, and -`W` be a realization of the type `T` weight -lattice. +Informally, a crystal `\mathcal{B}` is an oriented graph with edges +colored in some set `I` such that, for each `i\in I`, each node `x` +has: -A type `T` crystal `C` is a colored oriented graph -equipped with a weight function from the nodes to some realization -of the type `T` weight lattice such that: +- at most one `i`-successor, denoted `f_i x`; +- at most one `i`-predecessor, denoted `e_i x`. -- Each edge is colored with a label in `i \in I`. +By convention, one writes `f_i x=\emptyset` and `e_i x=\emptyset` when +`x` has no successor resp. predecessor. -- For each `i\in I`, each node `x` has: +One may think of `\mathcal{B}` as essentially a deterministic +automaton whose dual is also deterministic; in this context, the +`f_i`'s and `e_i`'s are respectively the transition functions of the +automaton and of its dual, and `\emptyset` is the sink. +A crystal comes further endowed with a weight function +`\operatorname{wt}: \mathcal{B}\mapsto L` which shall satisfies +appropriate conditions. - - at most one `i`-successor `f_i(x)`; +In combinatorial representation theory, Crystals are used as +combinatorial data to model representations of Lie algebra. - - at most one `i`-predecessor `e_i(x)`. +Axiomatic definition +-------------------- +Let `C` be a CartanType with index set `I`, and `L` be a realization +of the weight lattice of the type `C`. Let `\alpha_i` and +`\alpha^{\vee}_i` denote the simple roots and coroots +respectively. - Furthermore, when they exist, +A type `C` crystal is a non-empty set `\mathcal{B}` endowed with maps +`\operatorname{wt} : \mathcal{B} \to L`, +`e_i, f_i : \mathcal{B} \to \mathcal{B} \cup \{\emptyset\}`, and +`\varepsilon_i, \varphi_i : \mathcal{B} \to \ZZ \cup \{-\infty\}` +for `i \in I` satisfying the following properties for all `i \in I`: +- for `b, b^{\prime} \in \mathcal{B}`, `f_i b^{\prime} = b` if and only if `e_i b = b^{\prime}`; - - `f_i(x)`.weight() = x.weight() - `\alpha_i`; - - `e_i(x)`.weight() = x.weight() + `\alpha_i`. +- if `e_i b \in \mathcal{B}`, then: + * `\operatorname{wt}(e_i x) = \operatorname{wt}(b) + \alpha_i`, + * `\varepsilon_i(e_i b) = \varepsilon_i(b) - 1`, + * `\varphi_i(e_i b) = \varphi_i(b) + 1`, +- if `f_i b \in \mathcal{B}`, then: -This crystal actually models a representation of a Lie algebra if -it satisfies some further local conditions due to Stembridge [St2003]_. + * `\operatorname{wt}(f_i b) = \operatorname{wt}(b) - \alpha_i`, + * `\varepsilon_i(f_i b) = \varepsilon_i(b) + 1`, + * `\varphi_i(f_i b) = \varphi_i(b) - 1`, + +- `\varphi_i(b) = \varepsilon_i(b) + \langle \alpha^{\vee}_i, + \operatorname{wt}(b) \rangle`, + +- if `\varphi_i(b) = -\infty` for `b \in \mathcal{B}`, + then `e_i b = f_i b = \emptyset`. + +Some further conditions are required to guarantee that this data +indeed models a representation of a Lie algebra. For finite simply +laced types a complete characterization is given by Stembridge's local +axioms [St2003]_. REFERENCES: @@ -91,11 +124,9 @@ sage: view(G, pdflatex=True, tightpage=True) #optional - dot2tex graphviz For rank two crystals, there is an alternative method of getting -metapost pictures. For more information see C.metapost? - -See also the categories :class:`Crystals`, :class:`ClassicalCrystals`, -:class:`FiniteCrystals`, :class:`HighestWeightCrystals`. +metapost pictures. For more information see ``C.metapost?``. +.. SEEALSO:: :ref:`The overview of crystal features in Sage` .. TODO:: @@ -111,9 +142,8 @@ - RestrictionOfCrystal -Most of the above features (except Littelmann/alcove paths) are in -MuPAD-Combinat (see lib/COMBINAT/crystals.mu), which could provide -inspiration. +The crystals library in Sage grew up from an initial implementation in +MuPAD-Combinat (see /lib/COMBINAT/crystals.mu). """ #***************************************************************************** diff --git a/src/sage/combinat/designs/__init__.py b/src/sage/combinat/designs/__init__.py index e69de29bb2d..9d965629391 100644 --- a/src/sage/combinat/designs/__init__.py +++ b/src/sage/combinat/designs/__init__.py @@ -0,0 +1,32 @@ +__doc__ = r""" +Combinatorial Designs and Incidence Structures +============================================== + +All designs can be accessed by ``designs.`` and are listed in the +design catalog: + +- :ref:`sage.combinat.designs.design_catalog` + +**Design-related classes** + +- :ref:`sage.combinat.designs.incidence_structures` +- :ref:`sage.combinat.designs.covering_design` + +**Constructions** + +- :ref:`sage.combinat.designs.block_design` +- :ref:`sage.combinat.designs.bibd` +- :ref:`sage.combinat.designs.latin_squares` +- :ref:`sage.combinat.designs.orthogonal_arrays` +- :ref:`sage.combinat.designs.orthogonal_arrays_build_recursive` +- :ref:`sage.combinat.designs.orthogonal_arrays_find_recursive` +- :ref:`sage.combinat.designs.difference_family` +- :ref:`sage.combinat.designs.difference_matrices` +- :ref:`sage.combinat.designs.steiner_quadruple_systems` +- :ref:`sage.combinat.designs.database` + +**Technical things** + +- :ref:`sage.combinat.designs.ext_rep` +- :ref:`sage.combinat.designs.designs_pyx` +""" diff --git a/src/sage/combinat/designs/all.py b/src/sage/combinat/designs/all.py index fc3b63f2563..62ccd67cf3c 100644 --- a/src/sage/combinat/designs/all.py +++ b/src/sage/combinat/designs/all.py @@ -1,3 +1,6 @@ +""" +Combinatorial design features that are imported by default in the interpreter namespace +""" from block_design import (BlockDesign) from ext_rep import (designs_from_XML, designs_from_XML_url) diff --git a/src/sage/combinat/enumerated_sets.py b/src/sage/combinat/enumerated_sets.py new file mode 100644 index 00000000000..16d24e01253 --- /dev/null +++ b/src/sage/combinat/enumerated_sets.py @@ -0,0 +1,143 @@ +""" +Enumerated sets and combinatorial objects +========================================= + +.. TODO:: Proofread / point to the main classes rather than the modules + +Categories +---------- + +- :class:`EnumeratedSets`, :class:`FiniteEnumeratedSets` + +Basic enumerated sets +--------------------- + +- :class:`~sage.combinat.subset.Subsets`, :class:`~sage.combinat.combination.Combinations` +- :class:`~sage.combinat.permutation.Arrangements`, :class:`~sage.combinat.tuple.Tuples` +- :class:`~sage.sets.finite_enumerated_set.FiniteEnumeratedSet` +- :class:`~DisjointUnionEnumeratedSets`, :class:`~CartesianProduct` + +Integer lists +------------- + +- :ref:`sage.combinat.partition` + (see also: :ref:`sage.combinat.catalog_partitions`) +- :ref:`sage.combinat.composition` +- :class:`~sage.combinat.composition_signed.SignedCompositions` + +- :class:`~sage.combinat.integer_vector.IntegerVectors` +- :func:`~sage.combinat.integer_vector_weighted.WeightedIntegerVectors` +- :class:`~sage.combinat.integer_vectors_mod_permgroup.IntegerVectorsModPermutationGroup` + +- :ref:`sage.combinat.parking_functions` +- :ref:`sage.combinat.non_decreasing_parking_function` + +- :ref:`sage.combinat.sidon_sets` + +Words +----- + +- :class:`Words` +- :ref:`sage.combinat.subword` +- :ref:`sage.combinat.necklace` +- :ref:`sage.combinat.lyndon_word` +- :ref:`sage.combinat.dyck_word` +- :ref:`sage.combinat.debruijn_sequence` +- :ref:`sage.combinat.shuffle` + +Permutations, ... +----------------- + +- :ref:`sage.combinat.permutation` +- :ref:`sage.combinat.affine_permutation` +- :class:`~sage.combinat.permutation.Arrangements` +- :ref:`sage.combinat.derangements` + +.. SEEALSO:: + + - :class:`SymmetricGroup`, :func:`PermutationGroup`, :ref:`sage.groups.perm_gps.permutation_groups_catalog` + - :class:`FiniteSetMaps` + - :ref:`sage.combinat.integer_vectors_mod_permgroup` + - :ref:`sage.combinat.rsk` + +Partitions, tableaux, ... +------------------------- + +See: :ref:`sage.combinat.catalog_partitions` + +Integer matrices, ... +--------------------- + +- :ref:`sage.combinat.integer_matrices` +- :ref:`sage.combinat.matrices.hadamard_matrix` +- :ref:`sage.combinat.matrices.latin` +- :ref:`sage.combinat.alternating_sign_matrix` +- :ref:`sage.combinat.six_vertex_model` +- :ref:`sage.combinat.similarity_class_type` +- :ref:`sage.combinat.restricted_growth` +- :ref:`sage.combinat.vector_partition` + +.. SEEALSO:: + + - :class:`MatrixSpace` + - :ref:`sage.groups.matrix_gps.catalog` + +Subsets and set partitions +-------------------------- + +- :class:`~sage.combinat.subset.Subsets`, :class:`~sage.combinat.combination.Combinations` +- :class:`~sage.combinat.subsets_pairwise.PairwiseCompatibleSubsets` +- :ref:`sage.combinat.subsets_hereditary` +- :ref:`sage.combinat.set_partition_ordered` +- :ref:`sage.combinat.set_partition` + +Trees +----- + +- :ref:`sage.combinat.abstract_tree` +- :ref:`sage.combinat.ordered_tree` +- :ref:`sage.combinat.binary_tree` + +Enumerated sets related to graphs +--------------------------------- + +- :ref:`sage.combinat.degree_sequences` +- :ref:`sage.combinat.graph_path` +- :ref:`sage.combinat.perfect_matching` + +Backtracking solvers and generic enumerated sets +------------------------------------------------ + +.. TODO:: + + Do we want a separate section, possibly more proeminent, for + backtracking solvers? + +- :class:`~sage.combinat.backtrack.GenericBacktracker` +- :class:`~sage.combinat.backtrack.TransitiveIdeal` +- :class:`~sage.combinat.backtrack.TransitiveIdealGraded` +- :func:`~sage.combinat.tools.transitive_ideal` +- :class:`~sage.combinat.backtrack.SearchForest` +- :ref:`sage.combinat.tiling` +- :ref:`sage.combinat.dlx` +- :ref:`sage.combinat.matrices.dlxcpp` +- :ref:`sage.combinat.species` +- :class:`~sage.combinat.integer_list.IntegerListsLex` +- :class:`~sage.combinat.integer_vectors_mod_permgroup.IntegerVectorsModPermutationGroup` + +Low level enumerated sets +------------------------- + +- :ref:`sage.combinat.permutation_nk` +- :ref:`sage.combinat.split_nk` +- :ref:`sage.combinat.choose_nk` +- :ref:`sage.combinat.multichoose_nk` +- :ref:`sage.combinat.gray_codes` + +Misc enumerated sets +-------------------- + +- :class:`~sage.combinat.gelfand_tsetlin_patterns.GelfandTsetlinPattern`, :class:`~sage.combinat.gelfand_tsetlin_patterns.GelfandTsetlinPatterns` +- :class:`~sage.combinat.knutson_tao_puzzles.KnutsonTaoPuzzleSolver` +- :func:`LatticePolytope` +""" diff --git a/src/sage/combinat/finite_state_machine.py b/src/sage/combinat/finite_state_machine.py index 5552d354404..35ad0e7d2e1 100644 --- a/src/sage/combinat/finite_state_machine.py +++ b/src/sage/combinat/finite_state_machine.py @@ -292,7 +292,7 @@ :: sage: fsm.graph() - Digraph on 2 vertices + Looped multi-digraph on 2 vertices To visualize a finite state machine, we can use :func:`~sage.misc.latex.latex` and run the result through LaTeX, @@ -8416,15 +8416,15 @@ def graph(self, edge_labels='words_in_out'): sage: A = FSMState('A') sage: T = Transducer() sage: T.graph() - Digraph on 0 vertices + Looped multi-digraph on 0 vertices sage: T.add_state(A) 'A' sage: T.graph() - Digraph on 1 vertex + Looped multi-digraph on 1 vertex sage: T.add_transition(('A', 'A', 0, 1)) Transition from 'A' to 'A': 0|1 sage: T.graph() - Looped digraph on 1 vertex + Looped multi-digraph on 1 vertex .. SEEALSO:: :class:`DiGraph` """ @@ -8445,7 +8445,7 @@ def graph(self, edge_labels='words_in_out'): graph_data.append((t.from_state.label(), t.to_state.label(), label_fct(t))) - G = DiGraph(graph_data) + G = DiGraph(graph_data, multiedges=True, loops=True) G.add_vertices(isolated_vertices) return G diff --git a/src/sage/combinat/interval_posets.py b/src/sage/combinat/interval_posets.py index 52d3aa0cdab..fba7a093eaa 100644 --- a/src/sage/combinat/interval_posets.py +++ b/src/sage/combinat/interval_posets.py @@ -230,7 +230,7 @@ class TamariIntervalPoset(Element): sage: TamariIntervalPoset(2,[(2,1),(1,2)]) Traceback (most recent call last): ... - ValueError: Hasse diagram contains cycles + ValueError: The graph is not directed acyclic sage: TamariIntervalPoset(3,[(1,3)]) Traceback (most recent call last): diff --git a/src/sage/combinat/matrices/__init__.py b/src/sage/combinat/matrices/__init__.py index c9fecacd721..9e3d0a7d6bb 100644 --- a/src/sage/combinat/matrices/__init__.py +++ b/src/sage/combinat/matrices/__init__.py @@ -1 +1,10 @@ +r""" +Combinatorics on matrices +========================= + +- :ref:`sage.combinat.matrices.dancing_links` +- :ref:`sage.combinat.matrices.dlxcpp` +- :ref:`sage.combinat.matrices.hadamard_matrix` +- :ref:`sage.combinat.matrices.latin` +""" import all diff --git a/src/sage/combinat/matrices/all.py b/src/sage/combinat/matrices/all.py index 84407df0159..bfbd88c7738 100644 --- a/src/sage/combinat/matrices/all.py +++ b/src/sage/combinat/matrices/all.py @@ -1,3 +1,6 @@ +r""" +Combinatorics on matrix features that are imported by default in the interpreter namespace +""" from latin import LatinSquare, LatinSquare_generator from dlxcpp import DLXCPP from dancing_links import make_dlxwrapper diff --git a/src/sage/combinat/ncsf_qsym/__init__.py b/src/sage/combinat/ncsf_qsym/__init__.py index e69de29bb2d..7813801f5aa 100644 --- a/src/sage/combinat/ncsf_qsym/__init__.py +++ b/src/sage/combinat/ncsf_qsym/__init__.py @@ -0,0 +1,10 @@ +__doc__ = r""" +Non-Commutative Symmetric Functions and Quasi-Symmetric Functions +================================================================= + +- :ref:`sage.combinat.ncsf_qsym.tutorial` + +- :class:`sage.combinat.ncsf_qsym.ncsf.NonCommutativeSymmetricFunctions` +- :class:`sage.combinat.ncsf_qsym.qsym.QuasiSymmetricFunctions` + +""" diff --git a/src/sage/combinat/ncsf_qsym/all.py b/src/sage/combinat/ncsf_qsym/all.py index 83c5e5b8524..835a4624e2f 100644 --- a/src/sage/combinat/ncsf_qsym/all.py +++ b/src/sage/combinat/ncsf_qsym/all.py @@ -1,2 +1,5 @@ +r""" +Features that are imported by default in the interpreter namespace +""" from qsym import QuasiSymmetricFunctions from ncsf import NonCommutativeSymmetricFunctions diff --git a/src/sage/combinat/ncsym/__init__.py b/src/sage/combinat/ncsym/__init__.py index e69de29bb2d..7cac63e663c 100644 --- a/src/sage/combinat/ncsym/__init__.py +++ b/src/sage/combinat/ncsym/__init__.py @@ -0,0 +1,10 @@ +__doc__ = r""" +Symmetric Functions in Non-Commuting Variables +============================================== + +- :class:`Introduction to Symmetric Functions in Non-Commuting Variables ` + +- :ref:`sage.combinat.ncsym.bases` +- :ref:`sage.combinat.ncsym.dual` +- :ref:`sage.combinat.ncsym.ncsym` +""" diff --git a/src/sage/combinat/ncsym/all.py b/src/sage/combinat/ncsym/all.py index c3bcfed76d8..e4bd21e1839 100644 --- a/src/sage/combinat/ncsym/all.py +++ b/src/sage/combinat/ncsym/all.py @@ -1,3 +1,6 @@ +""" +Features that are imported by default in the interpreter namespace +""" from ncsym import SymmetricFunctionsNonCommutingVariables from dual import SymmetricFunctionsNonCommutingVariablesDual diff --git a/src/sage/combinat/partition.py b/src/sage/combinat/partition.py index 76fe49ff5da..77daf549d38 100644 --- a/src/sage/combinat/partition.py +++ b/src/sage/combinat/partition.py @@ -1,5 +1,5 @@ r""" -Partitions +Integer partitions A partition `p` of a nonnegative integer `n` is a non-increasing list of positive integers (the *parts* of the diff --git a/src/sage/combinat/posets/__init__.py b/src/sage/combinat/posets/__init__.py index a4e4d22acb8..8b6b80ea2eb 100644 --- a/src/sage/combinat/posets/__init__.py +++ b/src/sage/combinat/posets/__init__.py @@ -1,3 +1,26 @@ -# this file shouldn't be empty :) +__doc__ = r""" +Posets + +Common posets can be accessed through ``posets.`` and are listed in the +posets catalog: + +- :ref:`Catalog of posets ` + +Poset-related classes: + +- :ref:`sage.combinat.posets.posets` +- :ref:`sage.combinat.posets.lattices` + +- :ref:`sage.combinat.posets.linear_extensions` + +- :ref:`sage.combinat.tamari_lattices` +- :ref:`sage.combinat.interval_posets` + +If you are looking for Poset-related :ref:`categories +`, see +:class:`~sage.categories.posets.Posets` and +:class:`~sage.categories.lattice_posets.LatticePosets`. + + """ import all diff --git a/src/sage/combinat/posets/all.py b/src/sage/combinat/posets/all.py index 545c68dd4fc..673095e7c19 100644 --- a/src/sage/combinat/posets/all.py +++ b/src/sage/combinat/posets/all.py @@ -1,3 +1,6 @@ +r""" +Poset features that are imported by default in the interpreter namespace +""" from posets import Poset from lattices import LatticePoset diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index 9637e9d64f9..3f9efd8d9f6 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -101,72 +101,6 @@ def is_linear_extension(self,lin_ext=None): return False return True - # Could this be achieved by adding some options to - # GenericGraph.plot, and just overriding graphics_array_defaults? - - def plot(self, label_elements=True, element_labels=None, - label_font_size=12,label_font_color='black', layout = "acyclic", **kwds): - """ - Returns a Graphics object corresponding to the Hasse diagram. - - EXAMPLES:: - - sage: uc = [[2,3], [], [1], [1], [1], [3,4]] - sage: elm_lbls = Permutations(3).list() - sage: P = Poset(uc,elm_lbls) - sage: H = P._hasse_diagram - sage: levels = H.level_sets() - sage: heights = dict([[i, levels[i]] for i in range(len(levels))]) - sage: type(H.plot(label_elements=True)) - - - :: - - sage: P = Posets.SymmetricGroupBruhatIntervalPoset([1,2,3,4], [3,4,1,2]) - sage: P._hasse_diagram.plot() - Graphics object consisting of 42 graphics primitives - """ - # Set element_labels to default to the vertex set. - if element_labels is None: - element_labels = range(self.num_verts()) - - # Create the underlying graph. - graph = DiGraph(self) - graph.relabel(element_labels) - - return graph.plot(layout = layout, **kwds) - - def show(self, label_elements=True, element_labels=None, - label_font_size=12,label_font_color='black', - vertex_size=300, vertex_colors=None,**kwds): - """ - Shows the Graphics object corresponding to the Hasse diagram. - Optionally, it is labelled. - - INPUT: - - - - ``label_elements`` - whether to display element - labels - - - ``element_labels`` - a dictionary of element - labels - - - EXAMPLES:: - - sage: uc = [[2,3], [], [1], [1], [1], [3,4]] - sage: elm_lbls = Permutations(3).list() - sage: P = Poset(uc,elm_lbls) - sage: H = P._hasse_diagram - sage: levels = H.level_sets() - sage: heights = dict([[i, levels[i]] for i in range(len(levels))]) - sage: H.show(label_elements=True) - """ - self.plot(label_elements=label_elements, element_labels=element_labels, - label_font_size=label_font_size,label_font_color=label_font_color, - vertex_size=vertex_size, vertex_colors=vertex_colors).show(**kwds) - def cover_relations_iterator(self): r""" TESTS:: diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index dc73dd915e5..a40b24d996f 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -1,6 +1,14 @@ # -*- coding: utf-8 -*- r""" Linear Extensions of Posets + +This module defines two classes: + +- :class:`LinearExtensionOfPoset` +- :class:`LinearExtensionsOfPoset` + +Classes and methods +------------------- """ #***************************************************************************** # Copyright (C) 2012 Anne Schilling diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index 81ec5e4277c..f26d3d1a160 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -1,5 +1,39 @@ r""" -A collection of posets and lattices. +A catalog of posets and lattices. + +Some common posets can be accessed through the ``posets.`` object:: + + sage: posets.PentagonPoset() + Finite lattice containing 5 elements + +Moreover, the set of all posets of order `n` is represented by ``Posets(n)``:: + + sage: Posets(5) + Posets containing 5 vertices + +**Catalog of common posets:** + +.. csv-table:: + :class: contentstable + :widths: 30, 70 + :delim: | + + :meth:`~Posets.AntichainPoset` | Return an antichain on `n` elements. + :meth:`~Posets.BooleanLattice` | Return the Boolean lattice on `2^n` elements. + :meth:`~Posets.ChainPoset` | Return a chain on `n` elements. + :meth:`~Posets.DiamondPoset` | Return the lattice of rank two on `n` elements. + :meth:`~Posets.IntegerCompositions` | Return the poset of integer compositions of `n`. + :meth:`~Posets.IntegerPartitions` | Return the poset of integer partitions of ``n``. + :meth:`~Posets.PentagonPoset` | Return the Pentagon poset. + :meth:`~Posets.RandomPoset` | Return a random poset on `n` vertices according to a probability `p`. + :meth:`~Posets.RestrictedIntegerPartitions` | Return the poset of integer partitions of `n`, ordered by restricted refinement. + :meth:`~Posets.SSTPoset` | Return the poset on semistandard tableaux of shape `s` and largest entry `f` that is ordered by componentwise comparison. + :meth:`~Posets.SymmetricGroupBruhatIntervalPoset` | The poset of permutations with respect to Bruhat order. + :meth:`~Posets.SymmetricGroupBruhatOrderPoset` | The poset of permutations with respect to Bruhat order. + :meth:`~Posets.SymmetricGroupWeakOrderPoset` | The poset of permutations of `\{ 1, 2, \ldots, n \}` with respect to the weak order. + +Constructions +------------- """ #***************************************************************************** # Copyright (C) 2008 Peter Jipsen , diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index c5747a43c28..e0a21339b58 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- r""" -Posets +Finite posets This module implements finite partially ordered sets. It defines: @@ -106,7 +106,7 @@ :meth:`~FinitePoset.relations` | Returns a list of all relations of the poset. :meth:`~FinitePoset.relations_iterator` | Returns an iterator for all the relations of the poset. :meth:`~FinitePoset.relations_number` | Returns the number of relations in the poset. - :meth:`~FinitePoset.show` | Shows the Graphics object corresponding the Hasse diagram of the poset. + :meth:`~FinitePoset.show` | Displays the Hasse diagram of the poset. :meth:`~FinitePoset.subposet` | Returns the poset containing elements with partial order induced by that of self. :meth:`~FinitePoset.top` | Returns the top element of the poset, if it exists. :meth:`~FinitePoset.unwrap` | Unwraps an element of this poset @@ -487,6 +487,13 @@ def Poset(data=None, element_labels=None, cover_relations=False, linear_extensio Traceback (most recent call last): ... ValueError: element_labels should be a dict or a list if different from None. (Did you intend data to be equal to a pair ?) + + Another kind of bad input, digraphs with oriented cycles:: + + sage: Poset(DiGraph([[1,2],[2,3],[3,4],[4,1]])) + Traceback (most recent call last): + ... + ValueError: The graph is not directed acyclic """ # Avoiding some errors from the user when data should be a pair if (element_labels is not None and @@ -549,7 +556,8 @@ def Poset(data=None, element_labels=None, cover_relations=False, linear_extensio # Determine cover relations, if necessary. if cover_relations is False: - D = D.transitive_reduction() + from sage.graphs.generic_graph_pyx import transitive_reduction_acyclic + D = transitive_reduction_acyclic(D) # Check that the digraph does not contain loops, multiple edges # and is transitively reduced. @@ -1415,15 +1423,10 @@ def list(self): return list(self._list) def plot(self, label_elements=True, element_labels=None, - vertex_size=300, vertex_colors=None, layout='acyclic', cover_labels=None, **kwds): """ - Returns a Graphic object for the Hasse diagram of the poset. - - The poset is increasing from bottom to top. - - By default, the vertices are labelled. + Return a Graphic object for the Hasse diagram of the poset. If the poset is ranked, the plot uses the rank function for the heights of the vertices. @@ -1436,8 +1439,19 @@ def plot(self, label_elements=True, element_labels=None, - ``element_labels`` (default: ``None``) - a dictionary of element labels - - ``cover_labels`` (default: ``None``) - a dictionary, list or function - representing labels of the covers of ``self`` + - ``cover_labels`` - a dictionary, list or function representing labels + of the covers of ``self``. When set to ``None`` (default) no label is + displayed on the edges of the Hasse Diagram. + + - ``layout`` -- the type of layout used to display the Diagram. Set to + ``'acyclic'`` by default (see :meth:`GenericGraph.plot + ` for more information). + + .. NOTE:: + + All options of :meth:`GenericGraph.plot + ` are also available + through this function. EXAMPLES:: @@ -1452,12 +1466,6 @@ def plot(self, label_elements=True, element_labels=None, sage: D.plot(element_labels=elm_labs) Graphics object consisting of 11 graphics primitives - Plot of the empy poset:: - - sage: P = Poset({}) - sage: P.plot() - Graphics object consisting of 0 graphics primitives - Plot of a ranked poset:: sage: P = Poset(DiGraph('E@ACA@?')) @@ -1494,6 +1502,13 @@ def plot(self, label_elements=True, element_labels=None, ['a', 'b', 'c', 'd', 'e'] sage: get_plot_labels(P2.plot(element_labels=element_labels)) ['a', 'b', 'c', 'd', 'e'] + + Plot of the empy poset:: + + sage: P = Poset({}) + sage: P.plot() + Graphics object consisting of 0 graphics primitives + """ from collections import defaultdict graph = self.hasse_diagram() @@ -1532,29 +1547,36 @@ def plot(self, label_elements=True, element_labels=None, return graph.plot(vertex_labels=label_elements, edge_labels=cover_labels, - vertex_size=vertex_size, - vertex_colors=vertex_colors, layout=layout, heights=heights, **kwds) def show(self, label_elements=True, element_labels=None, - vertex_size=300, vertex_colors=None, layout='acyclic', cover_labels=None, **kwds): """ - Shows the Graphics object corresponding the Hasse diagram of the - poset. Optionally, it is labelled. + Displays the Hasse diagram of the poset. INPUT: - - ``label_elements`` (default: ``True``) - whether to display element - labels + - ``label_elements`` (default: ``True``) - whether to display + element labels - - ``element_labels`` (default: ``None``) - a dictionary of element - labels + - ``element_labels`` (default: ``None``) - a dictionary of + element labels + + - ``cover_labels`` - a dictionary, list or function representing labels + of the covers of ``self``. When set to ``None`` (default) no label is + displayed on the edges of the Hasse Diagram. + + .. NOTE:: - - ``cover_labels`` (default: ``None``) - a dictionary, list or function - representing labels of the covers of ``self`` + This method also accepts: + + - All options of :meth:`GenericGraph.plot + ` + + - All options of :meth:`Graphics.show + ` EXAMPLES:: @@ -1569,10 +1591,19 @@ def show(self, label_elements=True, element_labels=None, sage: P = posets.PentagonPoset() sage: P.show(cover_labels=lambda a, b: a - b) + """ - self.plot(label_elements=label_elements, element_labels=element_labels, - vertex_size=vertex_size, vertex_colors=vertex_colors, - layout=layout, cover_labels=cover_labels).show(**kwds) + # We split the arguments into those meant for plot() and those meant for show() + # + # The plot_kwds dictionary only contains the options that graphplot + # understands. These options are removed from kwds at the same time. + from sage.graphs.graph_plot import graphplot_options + plot_kwds = {k:kwds.pop(k) for k in graphplot_options if k in kwds} + + self.plot(label_elements=label_elements, + element_labels=element_labels, + cover_labels=cover_labels, + **plot_kwds).show(**kwds) @combinatorial_map(name="to graph") def to_graph(self): diff --git a/src/sage/combinat/quickref.py b/src/sage/combinat/quickref.py new file mode 100644 index 00000000000..f939e8ba945 --- /dev/null +++ b/src/sage/combinat/quickref.py @@ -0,0 +1,78 @@ +r""" +Combinatorics quickref +---------------------- + +Integer Sequences:: + + sage: s = oeis([1,3,19,211]); s # optional - internet + 0: A000275: Coefficients of a Bessel function (reciprocal of J_0(z)); also pairs of permutations with rise/rise forbidden. + sage: s[0].programs() # optional - internet + 0: (PARI) a(n)=if(n<0,0,n!^2*4^n*polcoeff(1/besselj(0,x+x*O(x^(2*n))),2*n)) /* _Michael Somos_, May 17 2004 */ + +Combinatorial objects:: + + sage: S = Subsets([1,2,3,4]); S.list(); S. # not tested + sage: P = Partitions(10000); P.cardinality() + 3616...315650422081868605887952568754066420592310556052906916435144 + sage: Combinations([1,3,7]).random_element() # random + sage: Compositions(5, max_part = 3).unrank(3) + [2, 2, 1] + + sage: DyckWord([1,0,1,0,1,1,0,0]).to_binary_tree() + [., [., [[., .], .]]] + sage: Permutation([3,1,4,2]).robinson_schensted() + [[[1, 2], [3, 4]], [[1, 3], [2, 4]]] + sage: StandardTableau([[1, 4], [2, 5], [3]]).schuetzenberger_involution() + [[1, 3], [2, 4], [5]] + +Constructions and Species:: + + sage: for (p, s) in CartesianProduct(P, S): print p, s # not tested + sage: DisjointUnionEnumeratedSets(Family(lambda n: IntegerVectors(n, 3), NonNegativeIntegers)) # not tested + +Words:: + + sage: Words('abc', 4).list() + [word: aaaa, ..., word: cccc] + + sage: Word('aabcacbaa').is_palindrome() + True + sage: WordMorphism('a->ab,b->a').fixed_point('a') + word: abaababaabaababaababaabaababaabaababaaba... + +Polytopes:: + + sage: points = random_matrix(ZZ, 6, 3, x=7).rows() + sage: L = LatticePolytope(points) + sage: L.npoints(); L.plot3d() # random + +:ref:`Root systems, Coxeter and Weyl groups `:: + + sage: WeylGroup(["B",3]).bruhat_poset() + Finite poset containing 48 elements + sage: RootSystem(["A",2,1]).weight_lattice().plot() # not tested + +:ref:`Crystals `:: + + sage: CrystalOfTableaux(["A",3], shape = [3,2]).some_flashy_feature() # not tested + +:mod:`Symmetric functions and combinatorial Hopf algebras `:: + + sage: Sym = SymmetricFunctions(QQ); Sym.inject_shorthands() + ... + doctest:...: RuntimeWarning: redefining global value `e` + sage: m( ( h[2,1] * (1 + 3 * p[2,1]) ) + s[2](s[3]) ) + 3*m[1, 1, 1] + ... + 10*m[5, 1] + 4*m[6] + +:ref:`Discrete groups, Permutation groups `:: + + sage: S = SymmetricGroup(4) + sage: M = PolynomialRing(QQ, 'x0,x1,x2,x3') + sage: M.an_element() * S.an_element() + x1 + +Graph theory, posets, lattices (:ref:`sage.graphs`, :ref:`sage.combinat.posets`):: + + sage: Poset({1: [2,3], 2: [4], 3: [4]}).linear_extensions().cardinality() + 2 +""" diff --git a/src/sage/combinat/ribbon.py b/src/sage/combinat/ribbon.py index 39bc0a1f250..dcfc834a8b5 100644 --- a/src/sage/combinat/ribbon.py +++ b/src/sage/combinat/ribbon.py @@ -17,85 +17,3 @@ #***************************************************************************** from ribbon_shaped_tableau import RibbonShapedTableau, StandardRibbonShapedTableaux -def Ribbon(r): - """ - Deprecated in :trac:`14101`. Use :class:`RibbonShapedTableau` instead. - - EXAMPLES:: - - sage: sage.combinat.ribbon.Ribbon([[2,3],[1,4,5]]) - doctest:...: DeprecationWarning: this class is deprecated. Use RibbonShapedTableau instead - See http://trac.sagemath.org/14101 for details. - [[None, None, 2, 3], [1, 4, 5]] - """ - from sage.misc.superseded import deprecation - deprecation(14101, 'this class is deprecated. Use RibbonShapedTableau instead') - return RibbonShapedTableau(r) - -def StandardRibbons(shape=None): - """ - Deprecated in :trac:`14101`. Use :class:`RibbonShapedTableaux` instead. - - EXAMPLES:: - - sage: sage.combinat.ribbon.StandardRibbons([3,3,1]) - doctest:...: DeprecationWarning: this class is deprecated. Use StandardRibbonShapedTableaux instead - See http://trac.sagemath.org/14101 for details. - Standard ribbon tableaux of shape [3, 3, 1] - """ - from sage.misc.superseded import deprecation - deprecation(14101, 'this class is deprecated. Use StandardRibbonShapedTableaux instead') - return StandardRibbonShapedTableaux(shape) - -def from_shape_and_word(shape, word): - """ - This is deprecated in :trac:`14101`. Use instead - :meth:`StandardRibbonShapedTableaux.from_shape_and_word()`. - - EXAMPLES:: - - sage: sage.combinat.ribbon.from_shape_and_word([2,3],[1,2,3,4,5]) - doctest:...: DeprecationWarning: this function is deprecated. Use StandardRibbonShapedTableaux().from_shape_and_word instead - See http://trac.sagemath.org/14101 for details. - [[None, None, 1, 2], [3, 4, 5]] - """ - from sage.misc.superseded import deprecation - deprecation(14101,'this function is deprecated. Use StandardRibbonShapedTableaux().from_shape_and_word instead') - return StandardRibbonShapedTableaux().from_shape_and_word(shape, word) - -def from_permutation(p): - """ - This is deprecated in :trac:`14101`. Use instead - :meth:`StandardRibbonShapedTableaux.from_shape_and_word()`. - - EXAMPLES:: - - sage: sage.combinat.ribbon.from_permutation(Permutation([1, 2, 3])) - doctest:...: DeprecationWarning: this function is deprecated. Use StandardRibbonShapedTableaux().from_permutation instead - See http://trac.sagemath.org/14101 for details. - [[1, 2, 3]] - """ - from sage.misc.superseded import deprecation - deprecation(14101,'this function is deprecated. Use StandardRibbonShapedTableaux().from_permutation instead') - return StandardRibbonShapedTableaux().from_permutation(p) - -def StandardRibbons_shape(shape): - """ - This is deprecated in :trac:`14101`. Use instead - :class:`StandardRibbonShapedTableaux`. - - EXAMPLES:: - - sage: sage.combinat.ribbon.StandardRibbons_shape([3,3,1]) - doctest:...: DeprecationWarning: this class is deprecated. Use StandardRibbonShapedTableaux instead - See http://trac.sagemath.org/14101 for details. - Standard ribbon tableaux of shape [3, 3, 1] - """ - from sage.misc.superseded import deprecation - deprecation(14101,'this class is deprecated. Use StandardRibbonShapedTableaux instead') - return StandardRibbonShapedTableaux(shape) - -from sage.structure.sage_object import register_unpickle_override -register_unpickle_override('sage.combinat.ribbon', 'Ribbon_class', RibbonShapedTableau) -register_unpickle_override('sage.combinat.ribbon', 'StandardRibbons_shape', StandardRibbonShapedTableaux) - diff --git a/src/sage/combinat/ribbon_shaped_tableau.py b/src/sage/combinat/ribbon_shaped_tableau.py index 56c33fe5a3e..310c3251df5 100644 --- a/src/sage/combinat/ribbon_shaped_tableau.py +++ b/src/sage/combinat/ribbon_shaped_tableau.py @@ -18,7 +18,7 @@ from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation -from sage.combinat.skew_tableau import SkewTableau, StandardSkewTableaux, from_expr +from sage.combinat.skew_tableau import SkewTableau, StandardSkewTableaux from sage.combinat.tableau import TableauOptions from sage.combinat.permutation import Permutation, descents_composition_first, descents_composition_list, descents_composition_last from sage.combinat.skew_partition import SkewPartition @@ -416,4 +416,5 @@ def __iter__(self): from sage.structure.sage_object import register_unpickle_override register_unpickle_override('sage.combinat.ribbon', 'Ribbon_class', RibbonShapedTableau) +register_unpickle_override('sage.combinat.ribbon', 'StandardRibbons_shape', StandardRibbonShapedTableaux) diff --git a/src/sage/combinat/ribbon_tableau.py b/src/sage/combinat/ribbon_tableau.py index 0623a9330cb..8f0d92a05c9 100644 --- a/src/sage/combinat/ribbon_tableau.py +++ b/src/sage/combinat/ribbon_tableau.py @@ -1163,47 +1163,6 @@ def __iter__(self): restmp.append( S.from_shape_and_word(parts[i], w) ) yield self.element_class(self, restmp) -def from_expr(l): - """ - Deprecated in :trac:`14101`. Use instead :meth:`RibbonTableaux.from_expr()`. - - EXAMPLES:: - - sage: sage.combinat.ribbon_tableau.from_expr([[1,1],[[5],[3,4],[1,2]]]) - doctest:...: DeprecationWarning: from_expr is deprecated. Use RibbonTableaux().from_expr instead - See http://trac.sagemath.org/14101 for details. - [[None, 1, 2], [None, 3, 4], [5]] - """ - from sage.misc.superseded import deprecation - deprecation(14101, 'from_expr is deprecated. Use RibbonTableaux().from_expr instead') - return RibbonTableaux().from_expr(l) - -def RibbonTableaux_shapeweightlength(shape, weight, length): - """ - EXAMPLES:: - - sage: sage.combinat.ribbon_tableau.RibbonTableaux_shapeweightlength([[2,1],[]], [1,1,1], 1) - doctest:...: DeprecationWarning: this class is deprecated. Use RibbonTableaux instead - See http://trac.sagemath.org/14101 for details. - Ribbon tableaux of shape [2, 1] / [] and weight [1, 1, 1] with 1-ribbons - """ - from sage.misc.superseded import deprecation - deprecation(14101, 'this class is deprecated. Use RibbonTableaux instead') - return RibbonTableaux(shape, weight, length) - -def SemistandardMultiSkewTtableaux_shapeweight(shape, weight): - """ - EXAMPLES:: - - sage: sage.combinat.ribbon_tableau.SemistandardMultiSkewTtableaux_shapeweight([ [[2,1],[]], [[2,2],[1]] ], [2,2,2]) - doctest:...: DeprecationWarning: this class is deprecated. Use SemistandardMultiSkewTableaux instead - See http://trac.sagemath.org/14101 for details. - Semistandard multi skew tableaux of shape [[2, 1] / [], [2, 2] / [1]] and weight [2, 2, 2] - """ - from sage.misc.superseded import deprecation - deprecation(14101, 'this class is deprecated. Use SemistandardMultiSkewTableaux instead') - return SemistandardMultiSkewTableaux(shape, weight) - from sage.structure.sage_object import register_unpickle_override register_unpickle_override('sage.combinat.ribbon_tableau', 'RibbonTableau_class', RibbonTableau) register_unpickle_override('sage.combinat.ribbon_tableau', 'RibbonTableaux_shapeweightlength', RibbonTableaux) diff --git a/src/sage/combinat/rigged_configurations/__init__.py b/src/sage/combinat/rigged_configurations/__init__.py index 8b137891791..0e857ab9a17 100644 --- a/src/sage/combinat/rigged_configurations/__init__.py +++ b/src/sage/combinat/rigged_configurations/__init__.py @@ -1 +1,34 @@ +__doc__ = r""" +Rigged Configurations +===================== +.. TODO:: Proofread / point to the main classes rather than the modules? + +- :ref:`sage.combinat.rigged_configurations.rc_crystal` +- :ref:`sage.combinat.rigged_configurations.rc_infinity` + +- :ref:`sage.combinat.rigged_configurations.rigged_configurations` +- :ref:`sage.combinat.rigged_configurations.rigged_configuration_element` + +- :ref:`sage.combinat.rigged_configurations.tensor_product_kr_tableaux` +- :ref:`sage.combinat.rigged_configurations.tensor_product_kr_tableaux_element` +- :ref:`sage.combinat.rigged_configurations.kr_tableaux` + +- :ref:`sage.combinat.rigged_configurations.kleber_tree` + +- :ref:`sage.combinat.rigged_configurations.rigged_partition` + +Bijections +---------- + +- :ref:`sage.combinat.rigged_configurations.bijection` +- :ref:`sage.combinat.rigged_configurations.bij_abstract_class` +- :ref:`sage.combinat.rigged_configurations.bij_type_A` +- :ref:`sage.combinat.rigged_configurations.bij_type_B` +- :ref:`sage.combinat.rigged_configurations.bij_type_C` +- :ref:`sage.combinat.rigged_configurations.bij_type_D` +- :ref:`sage.combinat.rigged_configurations.bij_type_A2_odd` +- :ref:`sage.combinat.rigged_configurations.bij_type_A2_even` +- :ref:`sage.combinat.rigged_configurations.bij_type_A2_dual` +- :ref:`sage.combinat.rigged_configurations.bij_type_D_twisted` +""" diff --git a/src/sage/combinat/rigged_configurations/all.py b/src/sage/combinat/rigged_configurations/all.py index a8c1facb606..ee4b3ad6fa8 100644 --- a/src/sage/combinat/rigged_configurations/all.py +++ b/src/sage/combinat/rigged_configurations/all.py @@ -1,3 +1,6 @@ +r""" +Features that are imported by default in the interpreter namespace +""" from rigged_configurations import RiggedConfigurations # Deprecated classes diff --git a/src/sage/combinat/root_system/__init__.py b/src/sage/combinat/root_system/__init__.py index c338db5c640..f7408099868 100644 --- a/src/sage/combinat/root_system/__init__.py +++ b/src/sage/combinat/root_system/__init__.py @@ -1,5 +1,101 @@ -# Makes sage.combinat.root_system? equivalent to sage.combinat.root_system.root_system? -from root_system import __doc__ +__doc__=""" +Root Systems +============ + +Quickref +-------- + +- ``T = CartanType(["A", 3]), T.is_finite()`` -- Cartan types +- ``T.dynkin_diagram(), DynkinDiagram(["G",2])`` -- Dynkin diagrams +- ``T.cartan_matrix(), CartanMatrix(["F",4])`` -- Cartan matrices +- ``RootSystem(T).weight_lattice()`` -- Root systems +- ``WeylGroup(["B", 6, 1]).simple_reflections()`` -- Affine Weyl groups +- ``WeylCharacterRing(["D", 4])`` -- Weyl character rings + +Introductory material +--------------------- + +- :ref:`sage.combinat.root_system` -- This overview +- :class:`CartanType` -- An introduction to Cartan types +- :class:`RootSystem` -- An introduction to root systems +- :ref:`sage.combinat.root_system.plot` -- A root system visualization tutorial + +- The `Lie Methods and Related Combinatorics <../../../../../thematic_tutorials/lie.html>`_ thematic tutorial + + +Related material +---------------- + +- :ref:`sage.combinat.crystals` -- Crystals + +Cartan datum +------------ + +- :ref:`sage.combinat.root_system.cartan_type` +- :ref:`sage.combinat.root_system.dynkin_diagram` +- :ref:`sage.combinat.root_system.cartan_matrix` +- :ref:`sage.combinat.root_system.coxeter_matrix` + +Root systems +------------ + +- :ref:`sage.combinat.root_system.root_system` +- :ref:`sage.combinat.root_system.plot` +- :ref:`sage.combinat.root_system.root_lattice_realizations` +- :ref:`sage.combinat.root_system.root_lattice_realization_algebras` +- :ref:`sage.combinat.root_system.weight_lattice_realizations` +- :ref:`sage.combinat.root_system.root_space` +- :ref:`sage.combinat.root_system.weight_space` +- :ref:`sage.combinat.root_system.ambient_space` + +Coxeter groups +-------------- + +- :ref:`sage.combinat.root_system.coxeter_group` +- :ref:`sage.combinat.root_system.weyl_group` + +.. SEEALSO:: + + The categories :class:`CoxeterGroups` and :class:`WeylGroups` + +Representation theory +--------------------- + +- :ref:`sage.combinat.root_system.weyl_characters` +- :ref:`sage.combinat.root_system.branching_rules` +- :ref:`sage.combinat.root_system.hecke_algebra_representation` +- :ref:`sage.combinat.root_system.non_symmetric_macdonald_polynomials` + +Root system data and code for specific families of Cartan types +--------------------------------------------------------------- + +- :ref:`sage.combinat.root_system.type_affine` +- :ref:`sage.combinat.root_system.type_dual` +- :ref:`sage.combinat.root_system.type_folded` +- :ref:`sage.combinat.root_system.type_reducible` +- :ref:`sage.combinat.root_system.type_relabel` + +Root system data and code for specific Cartan types +--------------------------------------------------- + +- :ref:`sage.combinat.root_system.type_A` +- :ref:`sage.combinat.root_system.type_B` +- :ref:`sage.combinat.root_system.type_C` +- :ref:`sage.combinat.root_system.type_D` +- :ref:`sage.combinat.root_system.type_E` +- :ref:`sage.combinat.root_system.type_F` +- :ref:`sage.combinat.root_system.type_G` +- :ref:`sage.combinat.root_system.type_H` +- :ref:`sage.combinat.root_system.type_I` +- :ref:`sage.combinat.root_system.type_A_affine` +- :ref:`sage.combinat.root_system.type_B_affine` +- :ref:`sage.combinat.root_system.type_C_affine` +- :ref:`sage.combinat.root_system.type_D_affine` +- :ref:`sage.combinat.root_system.type_E_affine` +- :ref:`sage.combinat.root_system.type_F_affine` +- :ref:`sage.combinat.root_system.type_G_affine` +- :ref:`sage.combinat.root_system.type_BC_affine` +""" # currently needed to activate the backward compatibility register_unpickle_override import type_A diff --git a/src/sage/combinat/root_system/all.py b/src/sage/combinat/root_system/all.py index 82db108b1b3..69271d70073 100644 --- a/src/sage/combinat/root_system/all.py +++ b/src/sage/combinat/root_system/all.py @@ -1,3 +1,6 @@ +r""" +Root system features that are imported by default in the interpreter namespace +""" from sage.misc.lazy_import import lazy_import lazy_import('sage.combinat.root_system.associahedron', 'Associahedron') diff --git a/src/sage/combinat/root_system/cartan_type.py b/src/sage/combinat/root_system/cartan_type.py index 487c81fc51b..f26a6387344 100644 --- a/src/sage/combinat/root_system/cartan_type.py +++ b/src/sage/combinat/root_system/cartan_type.py @@ -1,6 +1,12 @@ r""" Cartan types +.. TODO:: + + Why does sphinx complain if I use sections here? + +Introduction + Loosely speaking, Dynkin diagrams (or equivalently Cartan matrices) are graphs which are used to classify root systems, Coxeter and Weyl groups, Lie algebras, Lie groups, crystals, etc. up to an @@ -383,6 +389,51 @@ 0 1 2 3 4 E6^2 sage: CartanType.global_options['notation'] = 'BC' + +.. TODO:: Should those indexes come before the introduction? + +Abstract classes for cartan types + +- :class:`CartanType_abstract` +- :class:`CartanType_crystallographic` +- :class:`CartanType_simply_laced` +- :class:`CartanType_simple` +- :class:`CartanType_finite` +- :class:`CartanType_affine` (see also :ref:`sage.combinat.root_system.type_affine`) +- :obj:`sage.combinat.root_system.cartan_type.CartanType` +- :ref:`sage.combinat.root_system.type_dual` +- :ref:`sage.combinat.root_system.type_reducible` +- :ref:`sage.combinat.root_system.type_relabel` + +Concrete classes for cartan types + +- :class:`CartanType_standard_affine` +- :class:`CartanType_standard_untwisted_affine` + +Type specific data + +The data essentially consists of a description of the Dynkin/Coxeter +diagram and, when relevant, of the natural embedding of the root +system in an Euclidean space. Everything else is reconstructed from +this data. + +- :ref:`sage.combinat.root_system.type_A` +- :ref:`sage.combinat.root_system.type_B` +- :ref:`sage.combinat.root_system.type_C` +- :ref:`sage.combinat.root_system.type_D` +- :ref:`sage.combinat.root_system.type_E` +- :ref:`sage.combinat.root_system.type_F` +- :ref:`sage.combinat.root_system.type_G` +- :ref:`sage.combinat.root_system.type_H` +- :ref:`sage.combinat.root_system.type_I` +- :ref:`sage.combinat.root_system.type_A_affine` +- :ref:`sage.combinat.root_system.type_B_affine` +- :ref:`sage.combinat.root_system.type_C_affine` +- :ref:`sage.combinat.root_system.type_D_affine` +- :ref:`sage.combinat.root_system.type_E_affine` +- :ref:`sage.combinat.root_system.type_F_affine` +- :ref:`sage.combinat.root_system.type_G_affine` +- :ref:`sage.combinat.root_system.type_BC_affine` """ #***************************************************************************** # Copyright (C) 2007 Mike Hansen , diff --git a/src/sage/combinat/root_system/pieri_factors.py b/src/sage/combinat/root_system/pieri_factors.py index 65dea8848e5..d2237ec6a08 100644 --- a/src/sage/combinat/root_system/pieri_factors.py +++ b/src/sage/combinat/root_system/pieri_factors.py @@ -34,11 +34,12 @@ class PieriFactors(UniqueRepresentation, Parent): type can be realized as an order ideal of the Bruhat order poset generated by a certain set of maximal elements. - See also: - * :meth:`WeylGroups.ParentMethods.pieri_factors` - * :meth:`WeylGroups.ElementMethods.stanley_symmetric_function` + .. SEEALSO:: - EXAMPLES:: + - :meth:`WeylGroups.ParentMethods.pieri_factors` + - :meth:`WeylGroups.ElementMethods.stanley_symmetric_function` + + EXAMPLES:: sage: W = WeylGroup(['A',4]) sage: PF = W.pieri_factors() @@ -144,10 +145,12 @@ def elements(self): sage: [w.reduced_word() for w in PF.elements()] [[3, 2, 1], [2, 1], [1], [], [3, 1], [3], [3, 2], [2]] - ..seealso:: :meth:`maximal_elements` + .. SEEALSO:: :meth:`maximal_elements` - TODO: possibly remove this method and instead have this class - inherit from :class:`TransitiveIdeal`. + .. TODO:: + + Possibly remove this method and instead have this class + inherit from :class:`TransitiveIdeal`. """ return TransitiveIdeal(attrcall('bruhat_lower_covers'), self.maximal_elements()) @@ -240,8 +243,8 @@ def _test_maximal_elements(self, **options): @cached_method def max_length(self): - """ - Returns the maximal length of a Pieri factor + r""" + Return the maximal length of a Pieri factor. EXAMPLES: @@ -328,10 +331,11 @@ class PieriFactors_affine_type(PieriFactors): def maximal_elements(self): r""" - Returns the maximal elements of ``self`` with respect to - Bruhat order. The current implementation is via a conjectural - type-free formula. Use maximal_elements_combinatorial() for - proven type-specific implementations. To compare type-free and + Return the maximal elements of ``self`` with respect to Bruhat order. + + The current implementation is via a conjectural type-free + formula. Use maximal_elements_combinatorial() for proven + type-specific implementations. To compare type-free and type-specific (combinatorial) implementations, use method :meth:`_test_maximal_elements`. @@ -370,11 +374,12 @@ def maximal_elements(self): class PieriFactors_type_A(PieriFactors_finite_type): - r""" - The set of Pieri factors for finite type A. This is the set of elements of the - Weyl group that have a reduced word that is strictly decreasing. May also be - viewed as the restriction of affine type A Pieri factors to finite Weyl group + The set of Pieri factors for finite type A. + + This is the set of elements of the Weyl group that have a reduced + word that is strictly decreasing. May also be viewed as the + restriction of affine type A Pieri factors to finite Weyl group elements. """ @@ -423,7 +428,6 @@ def stanley_symm_poly_weight(self,w): class PieriFactors_type_B(PieriFactors_finite_type): - r""" The type B finite Pieri factors are realized as the set of elements that have a reduced word that is a subword of 12...(n-1)n(n-1)...21. They are the restriction @@ -500,7 +504,7 @@ class PieriFactors_type_A_affine(PieriFactors_affine_type): @staticmethod def __classcall__(cls, W, min_length = 0, max_length = infinity, min_support = frozenset([]), max_support = None): - """ + r""" TESTS:: sage: W = WeylGroup(['A',5,1]) @@ -617,7 +621,7 @@ def maximal_elements_combinatorial(self): return self.subset(self._max_length) def _test_maximal_elements(self, **options): - """ + r""" Same as :meth:`PieriFactors._test_maximal_elements`, but skips the tests if ``self`` is not the full set of Pieri factors. @@ -868,10 +872,11 @@ class PieriFactors_type_B_affine(PieriFactors_affine_type): r""" The type B affine Pieri factors are realized as the order ideal (in Bruhat order) generated by the following elements: - * cyclic rotations of the element with reduced word 234...(n-1)n(n-1)...3210, - except for 123...n...320 and 023...n...321. - * 123...(n-1)n(n-1)...321 - * 023...(n-1)n(n-1)...320 + + - cyclic rotations of the element with reduced word 234...(n-1)n(n-1)...3210, + except for 123...n...320 and 023...n...321. + - 123...(n-1)n(n-1)...321 + - 023...(n-1)n(n-1)...320 EXAMPLES:: @@ -966,7 +971,7 @@ def stanley_symm_poly_weight(self,w): return DiGraph(DynkinDiagram(ct)).subgraph(support_complement, algorithm="delete").connected_components_number() - 1 class PieriFactors_type_D_affine(PieriFactors_affine_type): - """ + r""" The type D affine Pieri factors are realized as the order ideal (in Bruhat order) generated by the following elements: diff --git a/src/sage/combinat/root_system/root_system.py b/src/sage/combinat/root_system/root_system.py index 2462ddb333c..668f29e43c9 100644 --- a/src/sage/combinat/root_system/root_system.py +++ b/src/sage/combinat/root_system/root_system.py @@ -1,32 +1,8 @@ -""" +r""" Root systems +============ -Quickref --------- - -- ``T = CartanType(["A", 3]), T.is_finite()`` -- Cartan types -- ``T.dynkin_diagram(), DynkinDiagram(["G",2])`` -- Dynkin diagrams -- ``T.cartan_matrix(), CartanMatrix(["F",4])`` -- Cartan matrices -- ``RootSystem(T).weight_lattice()`` -- Root systems -- ``WeylGroup(["B", 6, 1]).simple_reflections()`` -- Affine Weyl groups -- ``WeylCharacterRing(["D", 4])`` -- Weyl character rings - -Documentation -------------- - -- :ref:`sage.combinat.root_system.root_system` -- This current overview -- :class:`CartanType` -- An introduction to Cartan types -- :class:`RootSystem` -- An introduction to root systems -- :ref:`sage.combinat.root_system.plot` -- A root system visualization tutorial -- The ``Lie Methods and Related Combinatorics`` thematic tutorial - -See also --------- - -- :class:`CoxeterGroups`, :class:`WeylGroups`, ...-- The categories of Coxeter and Weyl groups -- :ref:`sage.combinat.crystals.crystals` -- An introduction to crystals -- :mod:`.type_A`, :mod:`.type_B_affine`, ... -- Type specific root system data - +See :ref:`sage.combinat.root_system` for an overview. """ #***************************************************************************** # Copyright (C) 2007 Mike Hansen , diff --git a/src/sage/combinat/root_system/type_folded.py b/src/sage/combinat/root_system/type_folded.py index 7b3fbf21de6..28b388f7e2a 100644 --- a/src/sage/combinat/root_system/type_folded.py +++ b/src/sage/combinat/root_system/type_folded.py @@ -1,5 +1,5 @@ r""" -Folded Cartan Types +Root system data for folded Cartan types AUTHORS: diff --git a/src/sage/combinat/sf/__init__.py b/src/sage/combinat/sf/__init__.py index 8b137891791..9f8b1d56baf 100644 --- a/src/sage/combinat/sf/__init__.py +++ b/src/sage/combinat/sf/__init__.py @@ -1 +1,27 @@ +__doc__ = r""" +Symmetric Functions +=================== +- :class:`Introduction to Symmetric Functions ` + +- :ref:`sage.combinat.sf.sfa` +- :ref:`sage.combinat.sf.sf` +- :ref:`sage.combinat.sf.classical` +- :ref:`sage.combinat.sf.schur` +- :ref:`sage.combinat.sf.monomial` +- :ref:`sage.combinat.sf.multiplicative` +- :ref:`sage.combinat.sf.elementary` +- :ref:`sage.combinat.sf.homogeneous` +- :ref:`sage.combinat.sf.powersum` +- :ref:`sage.combinat.sf.dual` +- :ref:`sage.combinat.sf.orthotriang` +- :ref:`sage.combinat.sf.kfpoly` +- :ref:`sage.combinat.sf.hall_littlewood` +- :ref:`sage.combinat.sf.jack` +- :ref:`sage.combinat.sf.new_kschur` +- :ref:`sage.combinat.sf.k_dual` +- :ref:`sage.combinat.sf.llt` +- :ref:`sage.combinat.sf.macdonald` +- :ref:`sage.combinat.sf.ns_macdonald` +- :ref:`sage.combinat.sf.witt` +""" diff --git a/src/sage/combinat/sf/all.py b/src/sage/combinat/sf/all.py index c7c11c81ebe..d382806733e 100644 --- a/src/sage/combinat/sf/all.py +++ b/src/sage/combinat/sf/all.py @@ -1,7 +1,10 @@ -# In the long run, this will be the single entry point -# Nothing else will be exported +r""" +Symmetric function features that are imported by default in the interpreter namespace +""" from sage.misc.lazy_import import lazy_import +# In the long run, this will be the single entry point +# Nothing else will be exported from sf import SymmetricFunctions # This is deprecated: diff --git a/src/sage/combinat/sf/sf.py b/src/sage/combinat/sf/sf.py index a3007dc1a71..8a2f7385671 100644 --- a/src/sage/combinat/sf/sf.py +++ b/src/sage/combinat/sf/sf.py @@ -267,7 +267,7 @@ class SymmetricFunctions(UniqueRepresentation, Parent): and restriction, respectively. The Schur functions can also be interpreted as characters of `GL_n`, see `Partitions and Schur functions`__. - __ ../../../../thematic_tutorials/lie/lie_basics.html#partitions-and-schur-polynomials + __ ../../../../../thematic_tutorials/lie/lie_basics.html#partitions-and-schur-polynomials .. rubric:: The omega involution diff --git a/src/sage/combinat/skew_tableau.py b/src/sage/combinat/skew_tableau.py index 4a977999afd..e394d67c17f 100644 --- a/src/sage/combinat/skew_tableau.py +++ b/src/sage/combinat/skew_tableau.py @@ -2128,57 +2128,6 @@ def __iter__(self): for x in RibbonTableaux_shape_weight_length(self.p, self.mu, 1): yield self.element_class(self, x._list) -################ -# Deprecations # -################ - -def from_expr(expr): - """ - Deprecated in :trac:`14101`. Use instead :meth:`SkewTableaux.from_expr()`. - - EXAMPLES:: - - sage: sage.combinat.skew_tableau.from_expr([[1,1],[[5],[3,4],[1,2]]]) - doctest:...: DeprecationWarning: from_expr is deprecated. Use SkewTableaux().from_expr instead - See http://trac.sagemath.org/14101 for details. - [[None, 1, 2], [None, 3, 4], [5]] - """ - from sage.misc.superseded import deprecation - deprecation(14101, 'from_expr is deprecated. Use SkewTableaux().from_expr instead') - return SkewTableaux().from_expr(expr) - -def from_shape_and_word(shape, word): - """ - Deprecated in :trac:`14101`. Use instead - :meth:`SkewTableaux.from_shape_and_word()`. - - EXAMPLES:: - - sage: t = SkewTableau([[None, 1, 3], [None, 2], [4]]) - sage: shape = t.shape() - sage: word = t.to_word() - sage: sage.combinat.skew_tableau.from_shape_and_word(shape, word) - doctest:...: DeprecationWarning: from_shape_and_word is deprecated. Use SkewTableaux().from_shape_and_word instead - See http://trac.sagemath.org/14101 for details. - [[None, 1, 3], [None, 2], [4]] - """ - from sage.misc.superseded import deprecation - deprecation(14101, 'from_shape_and_word is deprecated. Use SkewTableaux().from_shape_and_word instead') - return SkewTableaux().from_shape_and_word(shape, word) - -def StandardSkewTableaux_skewpartition(skp): - """ - EXAMPLES:: - - sage: sage.combinat.skew_tableau.StandardSkewTableaux_skewpartition([[1],[]]) - doctest:...: DeprecationWarning: this class is deprecated. Use StandardSkewTableaux_shape instead - See http://trac.sagemath.org/14101 for details. - Standard skew tableaux of shape [1] / [] - """ - from sage.misc.superseded import deprecation - deprecation(14101,'this class is deprecated. Use StandardSkewTableaux_shape instead') - return StandardSkewTableaux(skp) - # October 2012: fixing outdated pickles which use the classes being deprecated from sage.structure.sage_object import register_unpickle_override register_unpickle_override('sage.combinat.skew_tableau', 'StandardSkewTableaux_n', StandardSkewTableaux_size) diff --git a/src/sage/combinat/species/__init__.py b/src/sage/combinat/species/__init__.py index c9fecacd721..36e2c2d5a5e 100644 --- a/src/sage/combinat/species/__init__.py +++ b/src/sage/combinat/species/__init__.py @@ -1 +1,54 @@ +__doc__ = r""" +Combinatorial Species +===================== + +.. TODO:: Short blurb about species + +.. TODO:: Proofread / point to the main classes rather than the modules? + +Introductory material +--------------------- + +- :ref:`section-examples-catalan` +- :ref:`section-generic-species` + +Lazy Power Series +----------------- + +- :ref:`sage.combinat.species.stream` +- :ref:`sage.combinat.species.series_order` +- :ref:`sage.combinat.species.series` +- :ref:`sage.combinat.species.generating_series` + +Basic Species +------------- + +- :ref:`sage.combinat.species.species` +- :ref:`sage.combinat.species.empty_species` +- :ref:`sage.combinat.species.recursive_species` +- :ref:`sage.combinat.species.characteristic_species` +- :ref:`sage.combinat.species.cycle_species` +- :ref:`sage.combinat.species.partition_species` +- :ref:`sage.combinat.species.permutation_species` +- :ref:`sage.combinat.species.linear_order_species` +- :ref:`sage.combinat.species.set_species` +- :ref:`sage.combinat.species.subset_species` +- :ref:`sage.combinat.species.library` + +Operations on Species +--------------------- + +- :ref:`sage.combinat.species.sum_species` +- :ref:`sage.combinat.species.product_species` +- :ref:`sage.combinat.species.composition_species` +- :ref:`sage.combinat.species.functorial_composition_species` + +Miscellaneous +------------- + +- :ref:`sage.combinat.species.structure` +- :ref:`sage.combinat.species.misc` +- :ref:`sage.combinat.species.combinatorial_logarithm` +""" + import all diff --git a/src/sage/combinat/species/all.py b/src/sage/combinat/species/all.py index 7ead1cce8b7..a8de646c206 100644 --- a/src/sage/combinat/species/all.py +++ b/src/sage/combinat/species/all.py @@ -1,3 +1,6 @@ +r""" +Combinatorial species features that are imported by default in the interpreter namespace +""" from series import LazyPowerSeriesRing from recursive_species import CombinatorialSpecies import library as species diff --git a/src/sage/combinat/tamari_lattices.py b/src/sage/combinat/tamari_lattices.py index 411b2ac992b..491b09586f1 100644 --- a/src/sage/combinat/tamari_lattices.py +++ b/src/sage/combinat/tamari_lattices.py @@ -1,5 +1,5 @@ r""" -The family of generalized Tamari lattices +Generalized Tamari lattices These lattices depend on three parameters `a`, `b` and `m`, where `a` and `b` are coprime positive integers and `m` is a nonnegative integer. @@ -7,13 +7,13 @@ The elements are :func:`Dyck paths` in the `(a \times b)`-rectangle. The order relation depends on `m`. -To use the provided functionality, you should import Tamari lattices by typing +To use the provided functionality, you should import Tamari lattices by typing:: -``from sage.combinat.tamari_lattices import TamariLattice`` + sage: from sage.combinat.tamari_lattices import TamariLattice -or +or:: -``from sage.combinat.tamari_lattices import GeneralizedTamariLattice``. + sage: from sage.combinat.tamari_lattices import GeneralizedTamariLattice EXAMPLES:: diff --git a/src/sage/combinat/words/__init__.py b/src/sage/combinat/words/__init__.py index c9fecacd721..03c960588b6 100644 --- a/src/sage/combinat/words/__init__.py +++ b/src/sage/combinat/words/__init__.py @@ -1 +1,20 @@ +__doc__ = r""" +Words +===== + +.. TODO:: + + - Check that those are the important entry points + - Add links from the module documentation to the important classes/functions + +- :func:`sage.combinat.words.alphabet.build_alphabet` +- :func:`sage.combinat.words.word.Word` +- :func:`sage.combinat.words.words.Words` +- :ref:`sage.combinat.words.word_generators` +- :class:`sage.combinat.words.shuffle_product.ShuffleProduct`, :class:`sage.combinat.words.shuffle_product.ShuffleProduct` ??? +- :ref:`sage.combinat.words.suffix_trees` +- :ref:`sage.combinat.words.morphism` +- :ref:`sage.combinat.words.paths` +""" +# Is this really needed? import all diff --git a/src/sage/combinat/words/all.py b/src/sage/combinat/words/all.py index 119377da22e..f53f3619013 100644 --- a/src/sage/combinat/words/all.py +++ b/src/sage/combinat/words/all.py @@ -1,3 +1,6 @@ +r""" +Word features that are imported by default in the interpreter namespace +""" from alphabet import Alphabet, build_alphabet from morphism import WordMorphism from paths import WordPaths diff --git a/src/sage/combinat/words/word_char.pyx b/src/sage/combinat/words/word_char.pyx index aa69849115a..5ff580d84ad 100644 --- a/src/sage/combinat/words/word_char.pyx +++ b/src/sage/combinat/words/word_char.pyx @@ -31,7 +31,7 @@ cdef size_t SIZE_T_MAX = -( 1) def reversed_word_iterator(WordDatatype_char w): r""" This function exists only because it is not possible to use yield in the - special method `__reversed__`. + special method ``__reversed__``. EXAMPLES:: diff --git a/src/sage/combinat/words/word_infinite_datatypes.py b/src/sage/combinat/words/word_infinite_datatypes.py index c576d7ed07d..9cbcd1d8978 100644 --- a/src/sage/combinat/words/word_infinite_datatypes.py +++ b/src/sage/combinat/words/word_infinite_datatypes.py @@ -533,9 +533,10 @@ def flush(self): r""" Empty the associated cache of letters. - EXAMPLES:: + EXAMPLES: + + The first 40 (by default) values are always cached:: - The first 40 (by default) values are always cached. sage: w = words.ThueMorseWord() sage: w._letter_cache {0: 0, 1: 1, 2: 1, 3: 0, 4: 1, 5: 0, 6: 0, 7: 1, 8: 1, 9: 0, 10: 0, 11: 1, 12: 0, 13: 1, 14: 1, 15: 0, 16: 1, 17: 0, 18: 0, 19: 1, 20: 0, 21: 1, 22: 1, 23: 0, 24: 0, 25: 1, 26: 1, 27: 0, 28: 1, 29: 0, 30: 0, 31: 1, 32: 1, 33: 0, 34: 0, 35: 1, 36: 0, 37: 1, 38: 1, 39: 0} diff --git a/src/sage/data_structures/bitset.pxi b/src/sage/data_structures/bitset.pxi index 00e31534d8c..bc6ac3cb647 100644 --- a/src/sage/data_structures/bitset.pxi +++ b/src/sage/data_structures/bitset.pxi @@ -12,6 +12,8 @@ AUTHORS: pickle, unpickle - Jeroen Demeyer (2014-09-05): use mpn_* functions from MPIR in the implementation (:trac`13352` and :trac:`16937`) +- Simon King (2014-10-28): ``bitset_rshift`` and ``bitset_lshift`` respecting + the size of the given bitsets (:trac:`15820`) """ #***************************************************************************** @@ -27,6 +29,7 @@ include 'sage/ext/cdefs.pxi' include 'sage/ext/stdsage.pxi' from sage.libs.gmp.mpn cimport * from sage.data_structures.bitset cimport * +from cython.operator import preincrement as preinc # Doctests for the functions in this file are in sage/data_structures/bitset.pyx @@ -63,12 +66,6 @@ cdef inline mp_limb_t limb_lower_bits_up(mp_bitcnt_t n): """ return ((-1)) >> (((-n)) % GMP_LIMB_BITS) -cdef inline void bitset_fix(bitset_t bits): - """ - Clear upper bits in upper limb which should be zero. - """ - bits.bits[bits.limbs - 1] &= limb_lower_bits_up(bits.size) - ############################################################################# # Bitset Initalization ############################################################################# @@ -143,10 +140,62 @@ cdef inline void bitset_copy(bitset_t dst, bitset_t src): """ mpn_copyi(dst.bits, src.bits, src.limbs) +cdef inline void bitset_fix(bitset_t bits): + """ + Clear upper bits in upper limb which should be zero. + """ + bits.bits[bits.limbs - 1] &= limb_lower_bits_up(bits.size) + ############################################################################# # Bitset Comparison ############################################################################# +cdef inline bint mpn_equal_bits(mp_srcptr b1, mp_srcptr b2, mp_bitcnt_t n): + """ + Return ``True`` iff the first n bits of *b1 and *b2 agree. + """ + cdef mp_size_t nlimbs = n // GMP_LIMB_BITS + cdef mp_limb_t mask = limb_lower_bits_down(n) + if nlimbs > 0 and mpn_cmp(b1, b2, nlimbs) != 0: + return False + if mask == 0: + return True + + cdef mp_limb_t b1h = b1[nlimbs] + cdef mp_limb_t b2h = b2[nlimbs] + return (b1h ^ b2h) & mask == 0 + +cdef inline bint mpn_equal_bits_shifted(mp_srcptr b1, mp_srcptr b2, mp_bitcnt_t n, mp_bitcnt_t offset): + """ + Return ``True`` iff the first n bits of *b1 and the bits ranging from + offset to offset+n of *b2 agree. + """ + cdef mp_bitcnt_t bit_offset = offset % GMP_LIMB_BITS + cdef mp_size_t i2 = offset//GMP_LIMB_BITS + if bit_offset==0: + return mpn_equal_bits(b1, b2 + i2, n) + cdef mp_size_t neg_bit_offset = GMP_LIMB_BITS-bit_offset + # limbs of b1 to be considered + cdef mp_size_t nlimbs = n // GMP_LIMB_BITS + # bits of an additional limb of b1 to be considered + cdef mp_limb_t tmp_limb + cdef mp_size_t i1 + for i1 from 0 <= i1 < nlimbs: + tmp_limb = (b2[i2] >> bit_offset) + tmp_limb |= (b2[preinc(i2)] << neg_bit_offset) + if tmp_limb != b1[i1]: + return False + cdef mp_limb_t mask = limb_lower_bits_down(n) + if mask == 0: + return True + + cdef mp_limb_t b1h = b1[nlimbs] + tmp_limb = (b2[i2] >> bit_offset) + if (n%GMP_LIMB_BITS)+bit_offset > GMP_LIMB_BITS: + # Need bits from the next limb of b2 + tmp_limb |= (b2[preinc(i2)] << neg_bit_offset) + return (b1h ^ tmp_limb) & mask == 0 + cdef inline bint bitset_isempty(bitset_t bits): """ Test whether bits is empty. Return True (i.e., 1) if the set is @@ -554,7 +603,8 @@ cdef void bitset_rshift(bitset_t r, bitset_t a, mp_bitcnt_t n): Shift the bitset ``a`` right by ``n`` bits and store the result in ``r``. - We assume ``a.size <= r.size + n``. + There are no assumptions on the sizes of ``a`` and ``r``. Bits which are + shifted outside of the resulting bitset are discarded. """ if n >= a.size: mpn_zero(r.bits, r.limbs) @@ -562,53 +612,69 @@ cdef void bitset_rshift(bitset_t r, bitset_t a, mp_bitcnt_t n): # Number of limbs on the right of a which will totally be shifted out cdef mp_size_t nlimbs = n >> index_shift + # Number of limbs to be shifted assuming r is large enough + cdef mp_size_t shifted_limbs = a.limbs - nlimbs # Number of bits to shift additionally cdef mp_bitcnt_t nbits = n % GMP_LIMB_BITS - if nbits: - # mpn_rshift only does shifts less than a limb - if a.limbs - nlimbs <= r.limbs: - mpn_rshift(r.bits, a.bits + nlimbs, a.limbs - nlimbs, nbits) + if shifted_limbs < r.limbs: + if nbits: + mpn_rshift(r.bits, a.bits + nlimbs, shifted_limbs, nbits) else: - # In this case, we must have a.limbs - nlimbs - 1 == r.limbs + mpn_copyi(r.bits, a.bits + nlimbs, shifted_limbs) + + # Clear top limbs (note that r.limbs - shifted_limbs >= 1) + mpn_zero(r.bits + (r.limbs - nlimbs), r.limbs - shifted_limbs) + else: + # Number of limbs to shift is r.limbs + if nbits: mpn_rshift(r.bits, a.bits + nlimbs, r.limbs, nbits) # Add the additional bits from top limb of a - r.bits[r.limbs-1] |= a.bits[a.limbs-1] << (GMP_LIMB_BITS - nbits) - else: - mpn_copyi(r.bits, a.bits + nlimbs, a.limbs - nlimbs) + r.bits[r.limbs-1] |= a.bits[r.limbs+nlimbs] << (GMP_LIMB_BITS - nbits) + else: + mpn_copyi(r.bits, a.bits + nlimbs, r.limbs) - # Clear top limbs - if r.limbs + nlimbs >= a.limbs + 1: - mpn_zero(r.bits + (r.limbs - nlimbs), r.limbs + nlimbs - a.limbs) + # Clear bits outside bitset in top limb + bitset_fix(r) cdef void bitset_lshift(bitset_t r, bitset_t a, mp_bitcnt_t n): """ Shift the bitset ``a`` left by ``n`` bits and store the result in ``r``. - We assume ``r.size <= a.size + n``. + There are no assumptions on the sizes of ``a`` and ``r``. Bits which are + shifted outside of the resulting bitset are discarded. """ if n >= r.size: mpn_zero(r.bits, r.limbs) return - # Number of limbs on the left of r which will totally be shifted out + # Number of limbs on the right of r which will totally be zeroed cdef mp_size_t nlimbs = n >> index_shift + # Number of limbs to be shifted assuming a is large enough + cdef mp_size_t shifted_limbs = r.limbs - nlimbs # Number of bits to shift additionally cdef mp_bitcnt_t nbits = n % GMP_LIMB_BITS - cdef mp_limb_t out - if nbits: - # mpn_lshift only does shifts less than a limb - if r.limbs - nlimbs <= a.limbs: - mpn_lshift(r.bits + nlimbs, a.bits, r.limbs - nlimbs, nbits) - else: - # In this case, we must have r.limbs - nlimbs - 1 == a.limbs + cdef mp_limb_t out = 0 + if shifted_limbs > a.limbs: + if nbits: out = mpn_lshift(r.bits + nlimbs, a.bits, a.limbs, nbits) - r.bits[r.limbs-1] = out + else: + mpn_copyd(r.bits + nlimbs, a.bits, a.limbs) + + # Clear top limbs (note that shifted_limbs - a.limbs >= 1) + mpn_zero(r.bits + a.limbs + nlimbs, shifted_limbs - a.limbs) + # Store extra limb shifted in from a + r.bits[nlimbs+a.limbs] = out else: - mpn_copyd(r.bits + nlimbs, a.bits, r.limbs - nlimbs) - bitset_fix(r) + if nbits: + mpn_lshift(r.bits + nlimbs, a.bits, shifted_limbs, nbits) + else: + mpn_copyd(r.bits + nlimbs, a.bits, shifted_limbs) + + # Clear bits outside bitset in top limb + bitset_fix(r) # Clear bottom limbs mpn_zero(r.bits, nlimbs) diff --git a/src/sage/data_structures/bounded_integer_sequences.pxd b/src/sage/data_structures/bounded_integer_sequences.pxd new file mode 100644 index 00000000000..ee819024c27 --- /dev/null +++ b/src/sage/data_structures/bounded_integer_sequences.pxd @@ -0,0 +1,57 @@ +from sage.libs.gmp.types cimport * +from sage.data_structures.bitset cimport * + +# A biseq (bounded integer sequence) is a sequence of non-negative +# integers, each fitting in "itembitsize" bits. We store the sequence +# in a bitset of length at least length*itembitsize. +ctypedef struct biseq_s: + # A bitset comprising at least length*itembitsize bits is used to + # store the items of this sequence. Note that bitset_t stores the + # data in a field mp_limb_t *bits, where mp_limb_t is defined in + # sage.libs.gmp.types. + # + # Normally, the "at least" in the first sentence above will be + # an equality, but we need the "at least" for the special case + # where the length is zero: then we will use a bitset of length 1. + # All extra bits (not in the first length*itembitsize) should be + # zero. + bitset_t data + + # Number of items in this sequence. + mp_size_t length + + # Bitsize (ranging from 1 to GMP_LIMB_BITS) of one item of this + # sequence. Note: Each item is a non-negative integer, and all + # items of this sequence satisfy an upper bound. We do not store + # the exact bound for the items of this sequence, but store the + # bitsize that is sufficient to store one item. + mp_bitcnt_t itembitsize + + # If L is a limb, then "L & mask_item" extracts the first + # itembitsize bits of it, i.e., it extracts one item. + size_t mask_item + +ctypedef biseq_s biseq_t[1] + +cdef bint biseq_init(biseq_t R, mp_size_t l, mp_bitcnt_t itemsize) except -1 +cdef void biseq_dealloc(biseq_t S) +cdef bint biseq_init_copy(biseq_t R, biseq_t S) except -1 +cdef bint biseq_init_list(biseq_t R, list data, size_t bound) except -1 +cdef bint biseq_init_concat(biseq_t R, biseq_t S1, biseq_t S2) except -1 +cdef inline bint biseq_startswith(biseq_t S1, biseq_t S2) except -1 +cdef mp_size_t biseq_contains(biseq_t S1, biseq_t S2, mp_size_t start) except -2 +cdef mp_size_t biseq_startswith_tail(biseq_t S1, biseq_t S2, mp_size_t start) except -2 +cdef mp_size_t biseq_index(biseq_t S, size_t item, mp_size_t start) except -2 +cdef size_t biseq_getitem(biseq_t S, mp_size_t index) +cdef biseq_getitem_py(biseq_t S, mp_size_t index) +cdef inline void biseq_inititem(biseq_t S, mp_size_t index, size_t item) +cdef inline void biseq_clearitem(biseq_t S, mp_size_t index) +cdef bint biseq_init_slice(biseq_t R, biseq_t S, mp_size_t start, mp_size_t stop, mp_size_t step) except -1 + +cdef class BoundedIntegerSequence: + cdef biseq_t data + cpdef bint startswith(self, BoundedIntegerSequence other) + cpdef list list(self) + cpdef BoundedIntegerSequence maximal_overlap(self, BoundedIntegerSequence other) + +cpdef BoundedIntegerSequence NewBISEQ(tuple data, mp_bitcnt_t itembitsize, mp_size_t length) diff --git a/src/sage/data_structures/bounded_integer_sequences.pyx b/src/sage/data_structures/bounded_integer_sequences.pyx new file mode 100644 index 00000000000..0ff59d82114 --- /dev/null +++ b/src/sage/data_structures/bounded_integer_sequences.pyx @@ -0,0 +1,1417 @@ +r""" +Sequences of bounded integers + +This module provides :class:`BoundedIntegerSequence`, which implements +sequences of bounded integers and is for many (but not all) operations faster +than representing the same sequence as a Python :class:`tuple`. + +The underlying data structure is similar to :class:`~sage.misc.bitset.Bitset`, +which means that certain operations are implemented by using fast shift +operations from MPIR. The following boilerplate functions can be +cimported in Cython modules: + +- ``cdef bint biseq_init(biseq_t R, mp_size_t l, mp_size_t itemsize) except -1`` + + Allocate memory for a bounded integer sequence of length ``l`` with + items fitting in ``itemsize`` bits. + +- ``cdef inline void biseq_dealloc(biseq_t S)`` + + Deallocate the memory used by ``S``. + +- ``cdef bint biseq_init_copy(biseq_t R, biseq_t S)`` + + Initialize ``R`` as a copy of ``S``. + +- ``cdef bint biseq_init_list(biseq_t R, list data, size_t bound) except -1`` + + Convert a list to a bounded integer sequence, which must not be allocated. + +- ``cdef bint biseq_init_concat(biseq_t R, biseq_t S1, biseq_t S2) except -1`` + + Concatenate ``S1`` and ``S2`` and write the result to ``R``. Does not test + whether the sequences have the same bound! + +- ``cdef inline bint biseq_startswith(biseq_t S1, biseq_t S2)`` + + Is ``S1=S2+something``? Does not check whether the sequences have the same + bound! + +- ``cdef mp_size_t biseq_contains(biseq_t S1, biseq_t S2, mp_size_t start) except -2`` + + Return the position in ``S1`` of ``S2`` as a subsequence of + ``S1[start:]``, or ``-1`` if ``S2`` is not a subsequence. Does not check + whether the sequences have the same bound! + +- ``cdef mp_size_t biseq_starswith_tail(biseq_t S1, biseq_t S2, mp_size_t start) except -2:`` + + Return the smallest number ``i`` such that the bounded integer sequence + ``S1`` starts with the sequence ``S2[i:]``, where ``start <= i < + S1.length``, or return ``-1`` if no such ``i`` exists. + +- ``cdef mp_size_t biseq_index(biseq_t S, size_t item, mp_size_t start) except -2`` + + Return the position in ``S`` of the item in ``S[start:]``, or ``-1`` if + ``S[start:]`` does not contain the item. + +- ``cdef size_t biseq_getitem(biseq_t S, mp_size_t index)`` + + Return ``S[index]``, without checking margins. + +- ``cdef size_t biseq_getitem_py(biseq_t S, mp_size_t index)`` + + Return ``S[index]`` as Python ``int`` or ``long``, without checking margins. + +- ``cdef biseq_inititem(biseq_t S, mp_size_t index, size_t item)`` + + Set ``S[index] = item``, without checking margins and assuming that ``S[index]`` + has previously been zero. + +- ``cdef inline void biseq_clearitem(biseq_t S, mp_size_t index)`` + + Set ``S[index] = 0``, without checking margins. + +- ``cdef bint biseq_init_slice(biseq_t R, biseq_t S, mp_size_t start, mp_size_t stop, mp_size_t step) except -1`` + + Initialise ``R`` with ``S[start:stop:step]``. + +AUTHORS: + +- Simon King, Jeroen Demeyer (2014-10): initial version (:trac:`15820`) + +""" +#***************************************************************************** +# Copyright (C) 2014 Simon King +# Copyright (C) 2014 Jeroen Demeyer +# +# Distributed under the terms of the GNU General Public License (GPL) +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + +include "sage/ext/cdefs.pxi" +include "sage/ext/interrupt.pxi" +include "sage/ext/stdsage.pxi" +include 'sage/data_structures/bitset.pxi' + +from cpython.slice cimport PySlice_Check, PySlice_GetIndicesEx +from sage.libs.gmp.mpn cimport mpn_rshift, mpn_lshift, mpn_copyi, mpn_ior_n, mpn_zero, mpn_copyd, mpn_cmp +from sage.libs.flint.flint cimport FLINT_BIT_COUNT as BIT_COUNT + +cdef extern from "Python.h": + cdef PyInt_FromSize_t(size_t ival) + +cimport cython + +################### +# Boilerplate +# cdef functions +################### + +# +# (De)allocation, copying +# + +@cython.overflowcheck +cdef bint biseq_init(biseq_t R, mp_size_t l, mp_bitcnt_t itemsize) except -1: + """ + Allocate memory for a bounded integer sequence of length ``l`` with + items fitting in ``itemsize`` bits. + """ + cdef mp_bitcnt_t totalbitsize + if l: + totalbitsize = l * itemsize + else: + totalbitsize = 1 + bitset_init(R.data, totalbitsize) + R.length = l + R.itembitsize = itemsize + R.mask_item = limb_lower_bits_up(itemsize) + +cdef inline void biseq_dealloc(biseq_t S): + """ + Deallocate the memory used by ``S``. + """ + bitset_free(S.data) + +cdef bint biseq_init_copy(biseq_t R, biseq_t S) except -1: + """ + Initialize ``R`` as a copy of ``S``. + """ + biseq_init(R, S.length, S.itembitsize) + sig_on() + bitset_copy(R.data, S.data) + sig_off() + +# +# Conversion +# + +cdef bint biseq_init_list(biseq_t R, list data, size_t bound) except -1: + """ + Convert a list into a bounded integer sequence and write the result + into ``R``, which must not be initialised. + + INPUT: + + - ``data`` -- a list of integers + + - ``bound`` -- a number which is the maximal value of an item + """ + cdef mp_size_t index = 0 + cdef size_t item_c + + biseq_init(R, len(data), BIT_COUNT(bound|1)) + + for item in data: + sig_check() + item_c = item + if item_c > bound: + raise OverflowError("list item {!r} larger than {}".format(item, bound) ) + biseq_inititem(R, index, item_c) + index += 1 + +# +# Arithmetics +# + +cdef bint biseq_init_concat(biseq_t R, biseq_t S1, biseq_t S2) except -1: + """ + Concatenate two bounded integer sequences ``S1`` and ``S2``. + + ASSUMPTION: + + - The two sequences must have equivalent bounds, i.e., the items on the + sequences must fit into the same number of bits. + + OUTPUT: + + The result is written into ``R``, which must not be initialised + """ + biseq_init(R, S1.length + S2.length, S1.itembitsize) + sig_on() + bitset_lshift(R.data, S2.data, S1.length * S1.itembitsize) + bitset_or(R.data, R.data, S1.data) + sig_off() + + +cdef inline bint biseq_startswith(biseq_t S1, biseq_t S2) except -1: + """ + Tests if bounded integer sequence ``S1`` starts with bounded integer + sequence ``S2``. + + ASSUMPTION: + + - The two sequences must have equivalent bounds, i.e., the items on the + sequences must fit into the same number of bits. This condition is not + tested. + + """ + if S2.length > S1.length: + return False + if S2.length == 0: + return True + sig_on() + ret = mpn_equal_bits(S1.data.bits, S2.data.bits, S2.data.size) + sig_off() + return ret + + +cdef mp_size_t biseq_index(biseq_t S, size_t item, mp_size_t start) except -2: + """ + Returns the position in ``S`` of an item in ``S[start:]``, or -1 if + ``S[start:]`` does not contain the item. + + """ + cdef mp_size_t index + sig_on() + for index from start <= index < S.length: + if biseq_getitem(S, index) == item: + sig_off() + return index + sig_off() + return -1 + + +cdef inline size_t biseq_getitem(biseq_t S, mp_size_t index): + """ + Get item ``S[index]``, without checking margins. + + """ + cdef mp_bitcnt_t limb_index, bit_index + bit_index = (index) * S.itembitsize + limb_index = bit_index // GMP_LIMB_BITS + bit_index %= GMP_LIMB_BITS + + cdef mp_limb_t out + out = (S.data.bits[limb_index]) >> bit_index + if bit_index + S.itembitsize > GMP_LIMB_BITS: + # Our item is stored using 2 limbs, add the part from the upper limb + out |= (S.data.bits[limb_index+1]) << (GMP_LIMB_BITS - bit_index) + return out & S.mask_item + +cdef biseq_getitem_py(biseq_t S, mp_size_t index): + """ + Get item ``S[index]`` as a Python ``int`` or ``long``, without + checking margins. + + """ + cdef size_t out = biseq_getitem(S, index) + return PyInt_FromSize_t(out) + +cdef inline void biseq_inititem(biseq_t S, mp_size_t index, size_t item): + """ + Set ``S[index] = item``, without checking margins. + + Note that it is assumed that ``S[index] == 0`` before the assignment. + """ + cdef mp_bitcnt_t limb_index, bit_index + bit_index = (index) * S.itembitsize + limb_index = bit_index // GMP_LIMB_BITS + bit_index %= GMP_LIMB_BITS + + S.data.bits[limb_index] |= (item << bit_index) + # Have some bits been shifted out of bound? + if bit_index + S.itembitsize > GMP_LIMB_BITS: + # Our item is stored using 2 limbs, add the part from the upper limb + S.data.bits[limb_index+1] |= (item >> (GMP_LIMB_BITS - bit_index)) + +cdef inline void biseq_clearitem(biseq_t S, mp_size_t index): + """ + Set ``S[index] = 0``, without checking margins. + + In contrast to ``biseq_inititem``, the previous content of ``S[index]`` + will be erased. + """ + cdef mp_bitcnt_t limb_index, bit_index + bit_index = (index) * S.itembitsize + limb_index = bit_index // GMP_LIMB_BITS + bit_index %= GMP_LIMB_BITS + + S.data.bits[limb_index] &= ~(S.mask_item << bit_index) + # Have some bits been shifted out of bound? + if bit_index + S.itembitsize > GMP_LIMB_BITS: + # Our item is stored using 2 limbs, add the part from the upper limb + S.data.bits[limb_index+1] &= ~(S.mask_item >> (GMP_LIMB_BITS - bit_index)) + +cdef bint biseq_init_slice(biseq_t R, biseq_t S, mp_size_t start, mp_size_t stop, mp_size_t step) except -1: + """ + Create the slice ``S[start:stop:step]`` as bounded integer sequence + and write the result to ``R``, which must not be initialised. + + """ + cdef mp_size_t length = 0 + if step > 0: + if stop > start: + length = ((stop-start-1)//step)+1 + else: + if stop < start: + length = ((stop-start+1)//step)+1 + biseq_init(R, length, S.itembitsize) + + if not length: + return 0 + + if step == 1: + # Slicing essentially boils down to a shift operation. + sig_on() + bitset_rshift(R.data, S.data, start*S.itembitsize) + sig_off() + return 0 + + # In the general case, we move item by item. + cdef mp_size_t src_index = start + cdef mp_size_t tgt_index + sig_on() + for tgt_index in range(length): + biseq_inititem(R, tgt_index, biseq_getitem(S, src_index)) + src_index += step + sig_off() + + +cdef mp_size_t biseq_contains(biseq_t S1, biseq_t S2, mp_size_t start) except -2: + """ + Tests if the bounded integer sequence ``S1[start:]`` contains a + sub-sequence ``S2``. + + INPUT: + + - ``S1``, ``S2`` -- two bounded integer sequences + - ``start`` -- integer, start index + + OUTPUT: + + The smallest index ``i >= start`` such that ``S1[i:]`` starts with + ``S2``, or ``-1`` if ``S1[start:]`` does not contain ``S2``. + + ASSUMPTION: + + - The two sequences must have equivalent bounds, i.e., the items on the + sequences must fit into the same number of bits. This condition is not + tested. + + """ + if S2.length == 0: + return start + cdef mp_size_t index + sig_on() + for index from start <= index <= S1.length-S2.length: + if mpn_equal_bits_shifted(S2.data.bits, S1.data.bits, + S2.length*S2.itembitsize, index*S2.itembitsize): + sig_off() + return index + sig_off() + return -1 + +cdef mp_size_t biseq_startswith_tail(biseq_t S1, biseq_t S2, mp_size_t start) except -2: + """ + Return the smallest index ``i`` such that the bounded integer sequence + ``S1`` starts with the sequence ``S2[i:]``, where ``start <= i < + S2.length``. + + INPUT: + + - ``S1``, ``S2`` -- two bounded integer sequences + - ``start`` -- integer, start index + + OUTPUT: + + The smallest index ``i >= start`` such that ``S1`` starts with ``S2[i:], + or ``-1`` if no such ``i < S2.length`` exists. + + ASSUMPTION: + + - The two sequences must have equivalent bounds, i.e., the items on the + sequences must fit into the same number of bits. This condition is not + tested. + + """ + # Increase start if S1 is too short to contain S2[start:] + if S1.length < S2.length - start: + start = S2.length - S1.length + cdef mp_size_t index + sig_on() + for index from start <= index < S2.length: + if mpn_equal_bits_shifted(S1.data.bits, S2.data.bits, + (S2.length - index)*S2.itembitsize, index*S2.itembitsize): + sig_off() + return index + sig_off() + return -1 + + +########################################### +# A cdef class that wraps the above, and +# behaves like a tuple + +from sage.rings.integer cimport smallInteger +cdef class BoundedIntegerSequence: + """ + A sequence of non-negative uniformely bounded integers. + + INPUT: + + - ``bound`` -- non-negative integer. When zero, a :class:`ValueError` + will be raised. Otherwise, the given bound is replaced by the + power of two that is at least the given bound. + - ``data`` -- a list of integers. + + EXAMPLES: + + We showcase the similarities and differences between bounded integer + sequences and lists respectively tuples. + + To distinguish from tuples or lists, we use pointed brackets for the + string representation of bounded integer sequences:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: S = BoundedIntegerSequence(21, [2, 7, 20]); S + <2, 7, 20> + + Each bounded integer sequence has a bound that is a power of two, such + that all its item are less than this bound:: + + sage: S.bound() + 32 + sage: BoundedIntegerSequence(16, [2, 7, 20]) + Traceback (most recent call last): + ... + OverflowError: list item 20 larger than 15 + + Bounded integer sequences are iterable, and we see that we can recover the + originally given list:: + + sage: L = [randint(0,31) for i in range(5000)] + sage: S = BoundedIntegerSequence(32, L) + sage: list(L) == L + True + + Getting items and slicing works in the same way as for lists:: + + sage: n = randint(0,4999) + sage: S[n] == L[n] + True + sage: m = randint(0,1000) + sage: n = randint(3000,4500) + sage: s = randint(1, 7) + sage: list(S[m:n:s]) == L[m:n:s] + True + sage: list(S[n:m:-s]) == L[n:m:-s] + True + + The :meth:`index` method works different for bounded integer sequences and + tuples or lists. If one asks for the index of an item, the behaviour is + the same. But we can also ask for the index of a sub-sequence:: + + sage: L.index(L[200]) == S.index(L[200]) + True + sage: S.index(S[100:2000]) # random + 100 + + Similarly, containment tests work for both items and sub-sequences:: + + sage: S[200] in S + True + sage: S[200:400] in S + True + sage: S[200]+S.bound() in S + False + + Bounded integer sequences are immutable, and thus copies are + identical. This is the same for tuples, but of course not for lists:: + + sage: T = tuple(S) + sage: copy(T) is T + True + sage: copy(S) is S + True + sage: copy(L) is L + False + + Concatenation works in the same way for lists, tuples and bounded + integer sequences:: + + sage: M = [randint(0,31) for i in range(5000)] + sage: T = BoundedIntegerSequence(32, M) + sage: list(S+T)==L+M + True + sage: list(T+S)==M+L + True + sage: (T+S == S+T) == (M+L == L+M) + True + + However, comparison works different for lists and bounded integer + sequences. Bounded integer sequences are first compared by bound, then by + length, and eventually by *reverse* lexicographical ordering:: + + sage: S = BoundedIntegerSequence(21, [4,1,6,2,7,20,9]) + sage: T = BoundedIntegerSequence(51, [4,1,6,2,7,20]) + sage: S < T # compare by bound, not length + True + sage: T < S + False + sage: S.bound() < T.bound() + True + sage: len(S) > len(T) + True + + :: + + sage: T = BoundedIntegerSequence(21, [0,0,0,0,0,0,0,0]) + sage: S < T # compare by length, not lexicographically + True + sage: T < S + False + sage: list(T) < list(S) + True + sage: len(T) > len(S) + True + + :: + + sage: T = BoundedIntegerSequence(21, [4,1,5,2,8,20,9]) + sage: T > S # compare by reverse lexicographic ordering... + True + sage: S > T + False + sage: len(S) == len(T) + True + sage: list(S) > list(T) # direct lexicographic ordering is different + True + + TESTS: + + We test against various corner cases:: + + sage: BoundedIntegerSequence(16, [2, 7, -20]) + Traceback (most recent call last): + ... + OverflowError: can't convert negative value to size_t + sage: BoundedIntegerSequence(1, [0, 0, 0]) + <0, 0, 0> + sage: BoundedIntegerSequence(1, [0, 1, 0]) + Traceback (most recent call last): + ... + OverflowError: list item 1 larger than 0 + sage: BoundedIntegerSequence(0, [0, 1, 0]) + Traceback (most recent call last): + ... + ValueError: positive bound expected + sage: BoundedIntegerSequence(2, []) + <> + sage: BoundedIntegerSequence(2, []) == BoundedIntegerSequence(4, []) # The bounds differ + False + sage: BoundedIntegerSequence(16, [2, 7, 4])[1:1] + <> + + """ + def __cinit__(self, *args, **kwds): + """ + Allocate memory for underlying data + + INPUT: + + - ``bound``, non-negative integer + - ``data``, ignored + + .. WARNING:: + + If ``bound=0`` then no allocation is done. Hence, this should + only be done internally, when calling :meth:`__new__` without :meth:`__init__`. + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: BoundedIntegerSequence(21, [4,1,6,2,7,20,9]) # indirect doctest + <4, 1, 6, 2, 7, 20, 9> + + """ + # In __init__, we'll raise an error if the bound is 0. + self.data.data.bits = NULL + + def __dealloc__(self): + """ + Free the memory from underlying data + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: S = BoundedIntegerSequence(21, [4,1,6,2,7,20,9]) + sage: del S # indirect doctest + + """ + biseq_dealloc(self.data) + + def __init__(self, bound, data): + """ + INPUT: + + - ``bound`` -- positive integer. The given bound is replaced by + the next power of two that is greater than the given bound. + + - ``data`` -- a list of non-negative integers, all less than + ``bound``. + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: L = [randint(0,26) for i in range(5000)] + sage: S = BoundedIntegerSequence(57, L) # indirect doctest + sage: list(S) == L + True + sage: S = BoundedIntegerSequence(11, [4,1,6,2,7,4,9]); S + <4, 1, 6, 2, 7, 4, 9> + sage: S.bound() + 16 + + Non-positive bounds or bounds which are too large result in errors:: + + sage: BoundedIntegerSequence(-1, L) + Traceback (most recent call last): + ... + ValueError: positive bound expected + sage: BoundedIntegerSequence(0, L) + Traceback (most recent call last): + ... + ValueError: positive bound expected + sage: BoundedIntegerSequence(2^64+1, L) + Traceback (most recent call last): + ... + OverflowError: long int too large to convert + + We are testing the corner case of the maximal possible bound:: + + sage: S = BoundedIntegerSequence(2*(sys.maxsize+1), [8, 8, 26, 18, 18, 8, 22, 4, 17, 22, 22, 7, 12, 4, 1, 7, 21, 7, 10, 10]) + sage: S + <8, 8, 26, 18, 18, 8, 22, 4, 17, 22, 22, 7, 12, 4, 1, 7, 21, 7, 10, 10> + + Items that are too large:: + + sage: BoundedIntegerSequence(100, [2^256]) + Traceback (most recent call last): + ... + OverflowError: long int too large to convert + sage: BoundedIntegerSequence(100, [100]) + Traceback (most recent call last): + ... + OverflowError: list item 100 larger than 99 + + Bounds that are too large:: + + sage: BoundedIntegerSequence(2^256, [200]) + Traceback (most recent call last): + ... + OverflowError: long int too large to convert + + """ + if bound <= 0: + raise ValueError("positive bound expected") + biseq_init_list(self.data, data, bound-1) + + def __copy__(self): + """ + :class:`BoundedIntegerSequence` is immutable, copying returns ``self``. + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: S = BoundedIntegerSequence(21, [4,1,6,2,7,20,9]) + sage: copy(S) is S + True + + """ + return self + + def __reduce__(self): + """ + Pickling of :class:`BoundedIntegerSequence` + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: L = [randint(0,26) for i in range(5000)] + sage: S = BoundedIntegerSequence(32, L) + sage: loads(dumps(S)) == S # indirect doctest + True + + TESTS: + + The discussion at :trac:`15820` explains why the following is a good test:: + + sage: X = BoundedIntegerSequence(21, [4,1,6,2,7,2,3]) + sage: S = BoundedIntegerSequence(21, [0,0,0,0,0,0,0]) + sage: loads(dumps(X+S)) + <4, 1, 6, 2, 7, 2, 3, 0, 0, 0, 0, 0, 0, 0> + sage: loads(dumps(X+S)) == X+S + True + sage: T = BoundedIntegerSequence(21, [0,4,0,1,0,6,0,2,0,7,0,2,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0]) + sage: T[1::2] + <4, 1, 6, 2, 7, 2, 3, 0, 0, 0, 0, 0, 0, 0> + sage: T[1::2] == X+S + True + sage: loads(dumps(X[1::2])) == X[1::2] + True + + """ + return NewBISEQ, (bitset_pickle(self.data.data), self.data.itembitsize, self.data.length) + + def __len__(self): + """ + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: L = [randint(0,26) for i in range(5000)] + sage: S = BoundedIntegerSequence(57, L) # indirect doctest + sage: len(S) == len(L) + True + + """ + return self.data.length + + def __nonzero__(self): + """ + A bounded integer sequence is nonzero if and only if its length is nonzero. + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: S = BoundedIntegerSequence(13, [0,0,0]) + sage: bool(S) + True + sage: bool(S[1:1]) + False + + """ + return self.data.length!=0 + + def __repr__(self): + """ + String representation. + + To distinguish it from Python tuples or lists, we use pointed brackets + as delimiters. + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: BoundedIntegerSequence(21, [4,1,6,2,7,20,9]) # indirect doctest + <4, 1, 6, 2, 7, 20, 9> + sage: BoundedIntegerSequence(21, [0,0]) + BoundedIntegerSequence(21, [0,0]) + <0, 0, 0, 0> + + """ + return "<" + ", ".join(str(x) for x in self) + ">" + + def bound(self): + """ + Return the bound of this bounded integer sequence. + + All items of this sequence are non-negative integers less than the + returned bound. The bound is a power of two. + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: S = BoundedIntegerSequence(21, [4,1,6,2,7,20,9]) + sage: T = BoundedIntegerSequence(51, [4,1,6,2,7,20,9]) + sage: S.bound() + 32 + sage: T.bound() + 64 + + """ + return smallInteger(1) << self.data.itembitsize + + def __iter__(self): + """ + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: L = [randint(0,26) for i in range(5000)] + sage: S = BoundedIntegerSequence(27, L) + sage: list(S) == L # indirect doctest + True + + TESTS:: + + sage: list(BoundedIntegerSequence(1, [])) + [] + + The discussion at :trac:`15820` explains why this is a good test:: + + sage: S = BoundedIntegerSequence(21, [0,0,0,0,0,0,0]) + sage: X = BoundedIntegerSequence(21, [4,1,6,2,7,2,3]) + sage: list(X) + [4, 1, 6, 2, 7, 2, 3] + sage: list(X+S) + [4, 1, 6, 2, 7, 2, 3, 0, 0, 0, 0, 0, 0, 0] + sage: list(BoundedIntegerSequence(21, [0,0]) + BoundedIntegerSequence(21, [0,0])) + [0, 0, 0, 0] + + """ + cdef mp_size_t index + for index in range(self.data.length): + yield biseq_getitem_py(self.data, index) + + def __getitem__(self, index): + """ + Get single items or slices. + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: S = BoundedIntegerSequence(21, [4,1,6,2,7,20,9]) + sage: S[2] + 6 + sage: S[1::2] + <1, 2, 20> + sage: S[-1::-2] + <9, 7, 6, 4> + + TESTS:: + + sage: S = BoundedIntegerSequence(10^8, range(9)) + sage: S[-1] + 8 + sage: S[8] + 8 + sage: S[9] + Traceback (most recent call last): + ... + IndexError: index out of range + sage: S[-10] + Traceback (most recent call last): + ... + IndexError: index out of range + sage: S[2^63] + Traceback (most recent call last): + ... + OverflowError: long int too large to convert to int + + :: + + sage: S[-1::-2] + <8, 6, 4, 2, 0> + sage: S[1::2] + <1, 3, 5, 7> + + :: + + sage: L = [randint(0,26) for i in range(5000)] + sage: S = BoundedIntegerSequence(27, L) + sage: S[1234] == L[1234] + True + sage: list(S[100:2000:3]) == L[100:2000:3] + True + sage: list(S[3000:10:-7]) == L[3000:10:-7] + True + sage: S[:] == S + True + sage: S[:] is S + True + + :: + + sage: S = BoundedIntegerSequence(21, [0,0,0,0,0,0,0]) + sage: X = BoundedIntegerSequence(21, [4,1,6,2,7,2,3]) + sage: (X+S)[6] + 3 + sage: (X+S)[10] + 0 + sage: (X+S)[12:] + <0, 0> + + :: + + sage: S[2:2] == X[4:2] + True + + :: + + sage: S = BoundedIntegerSequence(6, [3, 5, 3, 1, 5, 2, 2, 5, 3, 3, 4]) + sage: S[10] + 4 + + :: + + sage: B = BoundedIntegerSequence(27, [8, 8, 26, 18, 18, 8, 22, 4, 17, 22, 22, 7, 12, 4, 1, 7, 21, 7, 10, 10]) + sage: B[8:] + <17, 22, 22, 7, 12, 4, 1, 7, 21, 7, 10, 10> + + :: + + sage: B1 = BoundedIntegerSequence(8, [0,7]) + sage: B2 = BoundedIntegerSequence(8, [2,1,4]) + sage: B1[0:1]+B2 + <0, 2, 1, 4> + + """ + cdef BoundedIntegerSequence out + cdef Py_ssize_t start, stop, step, slicelength + if PySlice_Check(index): + PySlice_GetIndicesEx(index, self.data.length, &start, &stop, &step, &slicelength) + if start==0 and stop==self.data.length and step==1: + return self + out = BoundedIntegerSequence.__new__(BoundedIntegerSequence, 0, None) + biseq_init_slice(out.data, self.data, start, stop, step) + return out + cdef Py_ssize_t ind + try: + ind = index + except TypeError: + raise TypeError("Sequence index must be integer or slice") + if ind < 0: + ind += self.data.length + if ind < 0 or ind >= self.data.length: + raise IndexError("index out of range") + return biseq_getitem_py(self.data, ind) + + def __contains__(self, other): + """ + Tells whether this bounded integer sequence contains an item or a sub-sequence + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: S = BoundedIntegerSequence(21, [4,1,6,2,7,20,9]) + sage: 6 in S + True + sage: BoundedIntegerSequence(21, [2, 7, 20]) in S + True + + The bound of the sequences matters:: + + sage: BoundedIntegerSequence(51, [2, 7, 20]) in S + False + + :: + + sage: 6+S.bound() in S + False + sage: S.index(6+S.bound()) + Traceback (most recent call last): + ... + ValueError: 38 is not in sequence + + TESTS: + + The discussion at :trac:`15820` explains why the following are good tests:: + + sage: X = BoundedIntegerSequence(21, [4,1,6,2,7,2,3]) + sage: S = BoundedIntegerSequence(21, [0,0,0,0,0,0,0]) + sage: loads(dumps(X+S)) + <4, 1, 6, 2, 7, 2, 3, 0, 0, 0, 0, 0, 0, 0> + sage: loads(dumps(X+S)) == X+S + True + sage: T = BoundedIntegerSequence(21, [0,4,0,1,0,6,0,2,0,7,0,2,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0]) + sage: T[3::2]==(X+S)[1:] + True + sage: T[3::2] in X+S + True + sage: T = BoundedIntegerSequence(21, [0,4,0,1,0,6,0,2,0,7,0,2,0,3,0,0,0,16,0,0,0,0,0,0,0,0,0,0]) + sage: T[3::2] in (X+S) + False + + :: + + sage: S1 = BoundedIntegerSequence(4, [1,3]) + sage: S2 = BoundedIntegerSequence(4, [0]) + sage: S2 in S1 + False + + :: + + sage: B = BoundedIntegerSequence(27, [8, 8, 26, 18, 18, 8, 22, 4, 17, 22, 22, 7, 12, 4, 1, 7, 21, 7, 10, 10]) + sage: B.index(B[8:]) + 8 + + :: + + sage: -1 in B + False + + """ + if not isinstance(other, BoundedIntegerSequence): + try: + return biseq_index(self.data, other, 0) >= 0 + except OverflowError: + return False + cdef BoundedIntegerSequence right = other + if self.data.itembitsize!=right.data.itembitsize: + return False + return biseq_contains(self.data, right.data, 0) >= 0 + + cpdef list list(self): + """ + Converts this bounded integer sequence to a list + + NOTE: + + A conversion to a list is also possible by iterating over the + sequence. + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: L = [randint(0,26) for i in range(5000)] + sage: S = BoundedIntegerSequence(32, L) + sage: S.list() == list(S) == L + True + + The discussion at :trac:`15820` explains why the following is a good test:: + + sage: (BoundedIntegerSequence(21, [0,0]) + BoundedIntegerSequence(21, [0,0])).list() + [0, 0, 0, 0] + + """ + cdef mp_size_t i + return [biseq_getitem_py(self.data, i) for i in range(self.data.length)] + + cpdef bint startswith(self, BoundedIntegerSequence other): + """ + Tells whether ``self`` starts with a given bounded integer sequence + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: L = [randint(0,26) for i in range(5000)] + sage: S = BoundedIntegerSequence(27, L) + sage: L0 = L[:1000] + sage: T = BoundedIntegerSequence(27, L0) + sage: S.startswith(T) + True + sage: L0[-1] += 1 + sage: T = BoundedIntegerSequence(27, L0) + sage: S.startswith(T) + False + sage: L0[-1] -= 1 + sage: L0[0] += 1 + sage: T = BoundedIntegerSequence(27, L0) + sage: S.startswith(T) + False + sage: L0[0] -= 1 + + The bounds of the sequences must be compatible, or :meth:`startswith` + returns ``False``:: + + sage: T = BoundedIntegerSequence(51, L0) + sage: S.startswith(T) + False + + """ + if self.data.itembitsize != other.data.itembitsize: + return False + return biseq_startswith(self.data, other.data) + + def index(self, other): + """ + The index of a given item or sub-sequence of ``self`` + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: S = BoundedIntegerSequence(21, [4,1,6,2,6,20,9,0]) + sage: S.index(6) + 2 + sage: S.index(5) + Traceback (most recent call last): + ... + ValueError: 5 is not in sequence + sage: S.index(BoundedIntegerSequence(21, [6, 2, 6])) + 2 + sage: S.index(BoundedIntegerSequence(21, [6, 2, 7])) + Traceback (most recent call last): + ... + ValueError: not a sub-sequence + + The bound of (sub-)sequences matters:: + + sage: S.index(BoundedIntegerSequence(51, [6, 2, 6])) + Traceback (most recent call last): + ... + ValueError: not a sub-sequence + sage: S.index(0) + 7 + sage: S.index(S.bound()) + Traceback (most recent call last): + ... + ValueError: 32 is not in sequence + + TESTS:: + + sage: S = BoundedIntegerSequence(10^9, [2, 2, 2, 1, 2, 4, 3, 3, 3, 2, 2, 0]) + sage: S[11] + 0 + sage: S.index(0) + 11 + + :: + + sage: S.index(-3) + Traceback (most recent call last): + ... + ValueError: -3 is not in sequence + sage: S.index(2^100) + Traceback (most recent call last): + ... + ValueError: 1267650600228229401496703205376 is not in sequence + sage: S.index("hello") + Traceback (most recent call last): + ... + TypeError: an integer is required + + """ + cdef mp_size_t out + if not isinstance(other, BoundedIntegerSequence): + try: + out = biseq_index(self.data, other, 0) + except OverflowError: + out = -1 + if out >= 0: + return out + raise ValueError("{!r} is not in sequence".format(other)) + + cdef BoundedIntegerSequence right = other + if self.data.itembitsize != right.data.itembitsize: + out = -1 + else: + out = biseq_contains(self.data, right.data, 0) + if out >= 0: + return out + raise ValueError("not a sub-sequence") + + def __add__(self, other): + """ + Concatenation of bounded integer sequences. + + NOTE: + + There is no coercion happening, as bounded integer sequences are not + considered to be elements of an object. + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: S = BoundedIntegerSequence(21, [4,1,6,2,7,20,9]) + sage: T = BoundedIntegerSequence(21, [4,1,6,2,8,15]) + sage: S+T + <4, 1, 6, 2, 7, 20, 9, 4, 1, 6, 2, 8, 15> + sage: T+S + <4, 1, 6, 2, 8, 15, 4, 1, 6, 2, 7, 20, 9> + sage: S in S+T + True + sage: T in S+T + True + sage: BoundedIntegerSequence(21, [4,1,6,2,7,20,9,4]) in S+T + True + sage: T+list(S) + Traceback (most recent call last): + ... + TypeError: Cannot convert list to sage.data_structures.bounded_integer_sequences.BoundedIntegerSequence + sage: T+None + Traceback (most recent call last): + ... + TypeError: Cannot concatenate bounded integer sequence and None + + TESTS: + + The discussion at :trac:`15820` explains why the following are good tests:: + + sage: BoundedIntegerSequence(21, [0,0]) + BoundedIntegerSequence(21, [0,0]) + <0, 0, 0, 0> + sage: B1 = BoundedIntegerSequence(2^30, [10^9+1, 10^9+2]) + sage: B2 = BoundedIntegerSequence(2^30, [10^9+3, 10^9+4]) + sage: B1 + B2 + <1000000001, 1000000002, 1000000003, 1000000004> + + """ + cdef BoundedIntegerSequence myself, right, out + if other is None or self is None: + raise TypeError('Cannot concatenate bounded integer sequence and None') + myself = self # may result in a type error + right = other # --"-- + if right.data.itembitsize != myself.data.itembitsize: + raise ValueError("can only concatenate bounded integer sequences of compatible bounds") + out = BoundedIntegerSequence.__new__(BoundedIntegerSequence, 0, None) + biseq_init_concat(out.data, myself.data, right.data) + return out + + cpdef BoundedIntegerSequence maximal_overlap(self, BoundedIntegerSequence other): + """ + Returns ``self``'s maximal trailing sub-sequence that ``other`` starts with. + + Returns ``None`` if there is no overlap + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: X = BoundedIntegerSequence(21, [4,1,6,2,7,2,3]) + sage: S = BoundedIntegerSequence(21, [0,0,0,0,0,0,0]) + sage: T = BoundedIntegerSequence(21, [2,7,2,3,0,0,0,0,0,0,0,1]) + sage: (X+S).maximal_overlap(T) + <2, 7, 2, 3, 0, 0, 0, 0, 0, 0, 0> + sage: print (X+S).maximal_overlap(BoundedIntegerSequence(21, [2,7,2,3,0,0,0,0,0,1])) + None + sage: (X+S).maximal_overlap(BoundedIntegerSequence(21, [0,0])) + <0, 0> + sage: B1 = BoundedIntegerSequence(4,[1,2,3,2,3,2,3]) + sage: B2 = BoundedIntegerSequence(4,[2,3,2,3,2,3,1]) + sage: B1.maximal_overlap(B2) + <2, 3, 2, 3, 2, 3> + + """ + cdef mp_size_t i = biseq_startswith_tail(other.data, self.data, 0) + if i==-1: + return None + return self[i:] + + def __cmp__(self, other): + """ + Comparison of bounded integer sequences + + We compare, in this order: + + - The bound of ``self`` and ``other`` + + - The length of ``self`` and ``other`` + + - Reverse lexicographical ordering, i.e., the sequences' items + are compared starting with the last item. + + EXAMPLES: + + Comparison by bound:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: S = BoundedIntegerSequence(21, [4,1,6,2,7,20,9]) + sage: T = BoundedIntegerSequence(51, [4,1,6,2,7,20,9]) + sage: S < T + True + sage: T < S + False + sage: list(T) == list(S) + True + + Comparison by length:: + + sage: T = BoundedIntegerSequence(21, [0,0,0,0,0,0,0,0]) + sage: S < T + True + sage: T < S + False + sage: list(T) < list(S) + True + sage: len(T) > len(S) + True + + Comparison by *reverse* lexicographical ordering:: + + sage: T = BoundedIntegerSequence(21, [4,1,5,2,8,20,9]) + sage: T > S + True + sage: S > T + False + sage: list(S)> list(T) + True + + """ + cdef BoundedIntegerSequence right + cdef BoundedIntegerSequence left + if other is None: + return 1 + if self is None: + return -1 + try: + right = other + except TypeError: + return -1 + try: + left = self + except TypeError: + return 1 + cdef int c = cmp(left.data.itembitsize, right.data.itembitsize) + if c: + return c + c = cmp(left.data.length, right.data.length) + if c: + return c + return bitset_cmp(left.data.data, right.data.data) + + def __hash__(self): + """ + The hash takes into account the content and the bound of the sequence. + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: S = BoundedIntegerSequence(21, [4,1,6,2,7,20,9]) + sage: T = BoundedIntegerSequence(51, [4,1,6,2,7,20,9]) + sage: S == T + False + sage: list(S) == list(T) + True + sage: S.bound() == T.bound() + False + sage: hash(S) == hash(T) + False + sage: T = BoundedIntegerSequence(31, [4,1,6,2,7,20,9]) + sage: T.bound() == S.bound() + True + sage: hash(S) == hash(T) + True + + """ + return bitset_hash(self.data.data) + +cpdef BoundedIntegerSequence NewBISEQ(tuple bitset_data, mp_bitcnt_t itembitsize, mp_size_t length): + """ + Helper function for unpickling of :class:`BoundedIntegerSequence`. + + EXAMPLES:: + + sage: from sage.data_structures.bounded_integer_sequences import BoundedIntegerSequence + sage: L = [randint(0,26) for i in range(5000)] + sage: S = BoundedIntegerSequence(32, L) + sage: loads(dumps(S)) == S # indirect doctest + True + + TESTS: + + We test a corner case:: + + sage: S = BoundedIntegerSequence(8,[]) + sage: S + <> + sage: loads(dumps(S)) == S + True + + And another one:: + + sage: S = BoundedIntegerSequence(2*sys.maxsize, [8, 8, 26, 18, 18, 8, 22, 4, 17, 22, 22, 7, 12, 4, 1, 7, 21, 7, 10, 10]) + sage: loads(dumps(S)) + <8, 8, 26, 18, 18, 8, 22, 4, 17, 22, 22, 7, 12, 4, 1, 7, 21, 7, 10, 10> + + """ + cdef BoundedIntegerSequence out = BoundedIntegerSequence.__new__(BoundedIntegerSequence) + # bitset_unpickle assumes that out.data.data is initialised. + biseq_init(out.data, length, itembitsize) + sig_on() + bitset_unpickle(out.data.data, bitset_data) + sig_off() + return out + +def _biseq_stresstest(): + """ + This function creates many bounded integer sequences and manipulates them + in various ways, in order to try to detect random memory corruptions. + + This runs forever and must be interrupted (this means that + interrupting is also checked). + + TESTS:: + + sage: from sage.data_structures.bounded_integer_sequences import _biseq_stresstest + sage: alarm(1); _biseq_stresstest() # long time + Traceback (most recent call last): + ... + AlarmInterrupt + """ + cdef int branch + cdef Py_ssize_t x, y, z + from sage.misc.prandom import randint + cdef list L = [BoundedIntegerSequence(6, [randint(0,5) for z in range(randint(4,10))]) for y in range(100)] + cdef BoundedIntegerSequence S, T + while True: + branch = randint(0,4) + if branch == 0: + L[randint(0,99)] = L[randint(0,99)]+L[randint(0,99)] + elif branch == 1: + x = randint(0,99) + if len(L[x]): + y = randint(0,len(L[x])-1) + z = randint(y,len(L[x])-1) + L[randint(0,99)] = L[x][y:z] + else: + L[x] = BoundedIntegerSequence(6, [randint(0,5) for z in range(randint(4,10))]) + elif branch == 2: + t = list(L[randint(0,99)]) + t = repr(L[randint(0,99)]) + t = L[randint(0,99)].list() + elif branch == 3: + x = randint(0,99) + if len(L[x]): + y = randint(0,len(L[x])-1) + t = L[x][y] + try: + t = L[x].index(t) + except ValueError: + raise ValueError("{} should be in {} (bound {}) at position {}".format(t,L[x],L[x].bound(),y)) + else: + L[x] = BoundedIntegerSequence(6, [randint(0,5) for z in range(randint(4,10))]) + elif branch == 4: + S = L[randint(0,99)] + T = L[randint(0,99)] + biseq_startswith(S.data,T.data) + biseq_contains(S.data, T.data, 0) + biseq_startswith_tail(S.data, T.data, 0) diff --git a/src/sage/doctest/forker.py b/src/sage/doctest/forker.py index 6d938922a90..ec7dde01b7d 100644 --- a/src/sage/doctest/forker.py +++ b/src/sage/doctest/forker.py @@ -843,9 +843,8 @@ def compile_and_execute(self, example, compiler, globs): globs.start() example.sequence_number = len(self.history) self.history.append(example) - timer = Timer() + timer = Timer().start() try: - timer.start() compiled = compiler(example) timer.start() # reset timer exec(compiled, globs) diff --git a/src/sage/functions/all.py b/src/sage/functions/all.py index dd2650ad4a3..1534c6bcc19 100644 --- a/src/sage/functions/all.py +++ b/src/sage/functions/all.py @@ -33,7 +33,7 @@ spherical_bessel_J, spherical_bessel_Y, spherical_hankel1, spherical_hankel2, spherical_harmonic, - lngamma, error_fcn, elliptic_e, + error_fcn, elliptic_e, elliptic_f, elliptic_ec, elliptic_eu, elliptic_kc, elliptic_pi, elliptic_j, airy_ai, airy_bi) diff --git a/src/sage/functions/bessel.py b/src/sage/functions/bessel.py index d9c4b677f7e..8df019aaa68 100644 --- a/src/sage/functions/bessel.py +++ b/src/sage/functions/bessel.py @@ -308,10 +308,32 @@ def _evalf_(self, n, x, parent=None, algorithm=None): EXAMPLES:: sage: bessel_J(0.0, 1.0) - 0.765197686557966 + 0.765197686557967 sage: bessel_J(0, 1).n(digits=20) 0.76519768655796655145 + sage: bessel_J(0.5, 1.5) + 0.649838074753747 + + Check for correct rounding (:trac:`17122`):: + + sage: R = RealField(113) + sage: a = R("8.935761195587725798762818805462843676e-01") + sage: aa = RealField(200)(a) + sage: for n in [-10..10]: + ....: b = bessel_J(R(n), a) + ....: bb = R(bessel_J(n, aa)) + ....: if b != bb: + ....: print n, b-bb """ + if parent is not None: + x = parent(x) + + try: + return x.jn(Integer(n)) + except Exception: + pass + + n, x = get_coercion_model().canonical_coercion(n, x) import mpmath return mpmath_utils.call(mpmath.besselj, n, x, parent=parent) @@ -457,11 +479,33 @@ def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: + sage: bessel_Y(0.5, 1.5) + -0.0460831658930974 sage: bessel_Y(1.0+2*I, 3.0+4*I) 0.699410324467538 + 0.228917940896421*I sage: bessel_Y(0, 1).n(256) 0.08825696421567695798292676602351516282781752309067554671104384761199978932351 + + Check for correct rounding (:trac:`17122`):: + + sage: R = RealField(113) + sage: a = R("8.935761195587725798762818805462843676e-01") + sage: aa = RealField(200)(a) + sage: for n in [-10..10]: + ....: b = bessel_Y(R(n), a) + ....: bb = R(bessel_Y(n, aa)) + ....: if b != bb: + ....: print n, b-bb """ + if parent is not None: + x = parent(x) + + try: + return x.yn(Integer(n)) + except Exception: + pass + + n, x = get_coercion_model().canonical_coercion(n, x) import mpmath return mpmath_utils.call(mpmath.bessely, n, x, parent=parent) diff --git a/src/sage/functions/exp_integral.py b/src/sage/functions/exp_integral.py index 8bafb0d60ea..4c43657c566 100644 --- a/src/sage/functions/exp_integral.py +++ b/src/sage/functions/exp_integral.py @@ -42,18 +42,15 @@ #***************************************************************************** # Copyright (C) 2011 Benjamin Jones # -# Distributed under the terms of the GNU General Public License (GPL) -# -# This code is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# The full text of the GPL is available at: -# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** +from __future__ import division + from sage.symbolic.function import BuiltinFunction from sage.symbolic.expression import Expression from sage.structure.coerce import parent @@ -175,9 +172,15 @@ def _eval_(self, n, z): exp_integral_e(1.00000000000000, x) sage: exp_integral_e(x, 1.0) exp_integral_e(x, 1.00000000000000) - sage: exp_integral_e(1.0, 1.0) - 0.219383934395520 + sage: exp_integral_e(3, 0) + 1/2 + + TESTS: + + Check that Python ints work (:trac:`14766`):: + sage: exp_integral_e(int(3), 0) + 0.5 """ z_zero = False # special case: z == 0 and n > 1 @@ -212,6 +215,8 @@ def _evalf_(self, n, z, parent=None, algorithm=None): """ EXAMPLES:: + sage: exp_integral_e(1.0, 1.0) + 0.219383934395520 sage: N(exp_integral_e(1, 1+I)) 0.000281624451981418 - 0.179324535039359*I sage: exp_integral_e(1, RealField(100)(1)) diff --git a/src/sage/functions/generalized.py b/src/sage/functions/generalized.py index 1444f55aee6..86edc39daa5 100644 --- a/src/sage/functions/generalized.py +++ b/src/sage/functions/generalized.py @@ -179,9 +179,14 @@ class FunctionHeaviside(BuiltinFunction): sage: heaviside(x) heaviside(x) + TESTS:: + + sage: heaviside(x)._sympy_() + Heaviside(x) + REFERENCES: - - http://en.wikipedia.org/wiki/Heaviside_function + - :wikipedia:`Heaviside_function` """ def __init__(self): @@ -206,7 +211,9 @@ def __init__(self): H\left(x\right) """ BuiltinFunction.__init__(self, "heaviside", latex_name="H", - conversions=dict(mathematica='HeavisideTheta')) + conversions=dict(maxima='hstep', + mathematica='HeavisideTheta', + sympy='Heaviside')) def _eval_(self, x): """ @@ -419,12 +426,11 @@ class FunctionSignum(BuiltinFunction): TESTS: - Check if conversion to sympy works #11921:: + Check if conversion to sympy works :trac:`11921`:: sage: sgn(x)._sympy_() sign(x) - REFERENCES: - http://en.wikipedia.org/wiki/Sign_function diff --git a/src/sage/functions/special.py b/src/sage/functions/special.py index 283b4714fc6..0e59f120388 100644 --- a/src/sage/functions/special.py +++ b/src/sage/functions/special.py @@ -870,8 +870,14 @@ def __init__(self): sage: elliptic_ec(0.1) 1.53075763689776 + + TESTS:: + + sage: elliptic_ec(x)._sympy_() + elliptic_e(x) """ - MaximaFunction.__init__(self, "elliptic_ec", nargs=1) + MaximaFunction.__init__(self, "elliptic_ec", nargs=1, + conversions=dict(sympy='elliptic_e')) def _derivative_(self, *args, **kwds): """ @@ -943,8 +949,14 @@ def __init__(self): sage: elliptic_f (0.2, 0.1) 0.200132506747543 + + TESTS:: + + sage: elliptic_f(x, 2)._sympy_() + elliptic_f(x, 2) """ - MaximaFunction.__init__(self, "elliptic_f") + MaximaFunction.__init__(self, "elliptic_f", + conversions=dict(sympy='elliptic_f')) elliptic_f = EllipticF() @@ -972,8 +984,14 @@ def __init__(self): 1.85407467730137 sage: elliptic_f(RR(pi/2), 0.5) 1.85407467730137 + + TESTS:: + + sage: elliptic_kc(x)._sympy_() + elliptic_k(x) """ - MaximaFunction.__init__(self, "elliptic_kc", nargs=1) + MaximaFunction.__init__(self, "elliptic_kc", nargs=1, + conversions=dict(sympy='elliptic_k')) elliptic_kc = EllipticKC() @@ -1026,30 +1044,16 @@ def __init__(self): sage: elliptic_pi(0.1, 0.2, 0.3) 0.200665068220979 - """ - MaximaFunction.__init__(self, "elliptic_pi", nargs=3) -elliptic_pi = EllipticPi() - - -def lngamma(t): - r""" - This method is deprecated, please use - :meth:`~sage.functions.other.log_gamma` instead. - - See the :meth:`~sage.functions.other.log_gamma` function for ' - documentation and examples. + TESTS:: - EXAMPLES:: + sage: elliptic_pi(x, pi/4, 1)._sympy_() + elliptic_pi(x, pi/4, 1) + """ + MaximaFunction.__init__(self, "elliptic_pi", nargs=3, + conversions=dict(sympy='elliptic_pi')) - sage: lngamma(RR(6)) - doctest:...: DeprecationWarning: The method lngamma() is deprecated. Use log_gamma() instead. - See http://trac.sagemath.org/6992 for details. - 4.78749174278205 - """ - from sage.misc.superseded import deprecation - deprecation(6992, "The method lngamma() is deprecated. Use log_gamma() instead.") - return log_gamma(t) +elliptic_pi = EllipticPi() def error_fcn(t): r""" diff --git a/src/sage/functions/wigner.py b/src/sage/functions/wigner.py index e71ccdf3087..04fa72830de 100644 --- a/src/sage/functions/wigner.py +++ b/src/sage/functions/wigner.py @@ -621,16 +621,24 @@ def gaunt(l_1, l_2, l_3, m_1, m_2, m_3, prec=None): sage: gaunt(1000,1000,1200,9,3,-12).n(64) 0.00689500421922113448 - It is an error to use non-integer values for `l` and `m`:: + If the sum of the `l_i` is odd, the answer is zero, even for Python + ints (see :trac:`14766`):: + + sage: gaunt(1,2,2,1,0,-1) + 0 + sage: gaunt(int(1),int(2),int(2),1,0,-1) + 0 + + It is an error to use non-integer values for `l` or `m`:: sage: gaunt(1.2,0,1.2,0,0,0) Traceback (most recent call last): ... - ValueError: l values must be integer + TypeError: Attempt to coerce non-integral RealNumber to Integer sage: gaunt(1,0,1,1.1,0,-1.1) Traceback (most recent call last): ... - ValueError: m values must be integer + TypeError: Attempt to coerce non-integral RealNumber to Integer NOTES: @@ -681,10 +689,12 @@ def gaunt(l_1, l_2, l_3, m_1, m_2, m_3, prec=None): - Jens Rasch (2009-03-24): initial version for Sage """ - if int(l_1) != l_1 or int(l_2) != l_2 or int(l_3) != l_3: - raise ValueError("l values must be integer") - if int(m_1) != m_1 or int(m_2) != m_2 or int(m_3) != m_3: - raise ValueError("m values must be integer") + l_1 = Integer(l_1) + l_2 = Integer(l_2) + l_3 = Integer(l_3) + m_1 = Integer(m_1) + m_2 = Integer(m_2) + m_3 = Integer(m_3) bigL = (l_1 + l_2 + l_3) / 2 a1 = l_1 + l_2 - l_3 diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 1896d7a0a93..927bb45cb8b 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -1013,188 +1013,6 @@ def Vrep_generator(self): for V in self.Vrepresentation(): yield V - def facial_adjacencies(self): - r""" - Return the list of face indices (i.e. indices of - H-representation objects) and the indices of faces adjacent to - them. - - .. NOTE:: - - Instead of working with face indices, it is recommended - that you use the H-representation objects directly (see - example). - - EXAMPLES:: - - sage: p = polytopes.permutahedron(4) - sage: p.facial_adjacencies()[0:3] - doctest:...: DeprecationWarning: - This method is deprecated. - Use self.Hrepresentation(i).neighbors() instead. - See http://trac.sagemath.org/11763 for details. - [[0, [1, 2, 5, 10, 12, 13]], [1, [0, 2, 5, 7, 9, 11]], [2, [0, 1, 10, 11]]] - sage: f0 = p.Hrepresentation(0) - sage: f0.index() == 0 - True - sage: f0_adjacencies = [f0.index(), [n.index() for n in f0.neighbors()]] - sage: p.facial_adjacencies()[0] == f0_adjacencies - True - """ - from sage.misc.superseded import deprecation - deprecation(11763, 'This method is deprecated. Use self.Hrepresentation(i).neighbors() instead.') - try: - return self._facial_adjacencies - except AttributeError: - self._facial_adjacencies = \ - [ [ h.index(), - [n.index() for n in h.neighbors()] - ] for h in self.Hrepresentation() ] - return self._facial_adjacencies - - def facial_incidences(self): - """ - Return the face-vertex incidences in the form `[f_i, [v_{i_0}, v_{i_1},\dots ,v_{i_2}]]`. - - .. NOTE:: - - Instead of working with face/vertex indices, it is - recommended that you use the - H-representation/V-representation objects directly (see - examples). Or use :meth:`incidence_matrix`. - - OUTPUT: - - The face indices are the indices of the H-representation - objects, and the vertex indices are the indices of the - V-representation objects. - - EXAMPLES:: - - sage: p = Polyhedron(vertices = [[5,0,0],[0,5,0],[5,5,0],[0,0,0],[2,2,5]]) - sage: p.facial_incidences() - doctest:...: DeprecationWarning: - This method is deprecated. Use self.Hrepresentation(i).incident() instead. - See http://trac.sagemath.org/11763 for details. - [[0, [0, 1, 3, 4]], - [1, [0, 1, 2]], - [2, [0, 2, 3]], - [3, [2, 3, 4]], - [4, [1, 2, 4]]] - - sage: f0 = p.Hrepresentation(0) - sage: f0.index() == 0 - True - sage: f0_incidences = [f0.index(), [v.index() for v in f0.incident()]] - sage: p.facial_incidences()[0] == f0_incidences - True - - sage: p.incidence_matrix().column(0) - (1, 1, 0, 1, 1) - sage: p.incidence_matrix().column(1) - (1, 1, 1, 0, 0) - sage: p.incidence_matrix().column(2) - (1, 0, 1, 1, 0) - sage: p.incidence_matrix().column(3) - (0, 0, 1, 1, 1) - sage: p.incidence_matrix().column(4) - (0, 1, 1, 0, 1) - """ - from sage.misc.superseded import deprecation - deprecation(11763, 'This method is deprecated. Use self.Hrepresentation(i).incident() instead.') - try: - return self._facial_incidences - except AttributeError: - self._facial_incidences = \ - [ [ h.index(), - [v.index() for v in h.incident()] - ] for h in self.Hrepresentation() ] - return self._facial_incidences - - def vertex_adjacencies(self): - """ - Return a list of vertex indices and their adjacent vertices. - - .. NOTE:: - - Instead of working with vertex indices, you can use the - V-representation objects directly (see examples). - - Two V-representation objects are adjacent if they generate a - (1-dimensional) face of the polyhedron. Examples are two - vertices of a polytope that bound an edge, or a vertex and a - ray of a polyhedron that generate a bounding half-line of the - polyhedron. See :meth:`vertex_adjacency_matrix` for a more - detailed discussion. - - OUTPUT: - - The vertex indices are the indices of the V-representation - objects. - - EXAMPLES:: - - sage: permuta3 = Polyhedron(vertices = Permutations([1,2,3,4])) - sage: permuta3.vertex_adjacencies()[0:3] - doctest:...: DeprecationWarning: - This method is deprecated. Use self.Vrepresentation(i).neighbors() instead. - See http://trac.sagemath.org/11763 for details. - [[0, [1, 2, 6]], [1, [0, 3, 7]], [2, [0, 4, 8]]] - sage: v0 = permuta3.Vrepresentation(0) - sage: v0.index() == 0 - True - sage: list( v0.neighbors() ) - [A vertex at (1, 2, 4, 3), A vertex at (1, 3, 2, 4), A vertex at (2, 1, 3, 4)] - sage: v0_adjacencies = [v0.index(), [v.index() for v in v0.neighbors()]] - sage: permuta3.vertex_adjacencies()[0] == v0_adjacencies - True - """ - from sage.misc.superseded import deprecation - deprecation(11763, 'This method is deprecated. Use self.Vrepresentation(i).neighbors() instead.') - try: - return self._vertex_adjacencies - except AttributeError: - self._vertex_adjacencies = \ - [ [ v.index(), - [n.index() for n in v.neighbors()] - ] for v in self.Vrepresentation() ] - return self._vertex_adjacencies - - def vertex_incidences(self): - """ - Return the vertex-face incidences in the form `[v_i, [f_{i_0}, f_{i_1},\dots ,f_{i_2}]]`. - - .. NOTE:: - - Instead of working with face/vertex indices, you can use - the H-representation/V-representation objects directly - (see examples). - - EXAMPLES:: - - sage: p = polytopes.n_simplex(3) - sage: p.vertex_incidences() - doctest:...: DeprecationWarning: - This method is deprecated. Use self.Vrepresentation(i).incident() instead. - See http://trac.sagemath.org/11763 for details. - [[0, [0, 1, 2]], [1, [0, 1, 3]], [2, [0, 2, 3]], [3, [1, 2, 3]]] - sage: v0 = p.Vrepresentation(0) - sage: v0.index() == 0 - True - sage: p.vertex_incidences()[0] == [ v0.index(), [h.index() for h in v0.incident()] ] - True - """ - from sage.misc.superseded import deprecation - deprecation(11763, 'This method is deprecated. Use self.Vrepresentation(i).incident() instead.') - try: - return self._vertex_incidences - except AttributeError: - self._vertex_incidences = \ - [ [ v.index(), - [h.index() for h in v.incident()] - ] for v in self.Vrepresentation() ] - return self._vertex_incidences - def inequality_generator(self): """ Return a generator for the defining inequalities of the @@ -1273,23 +1091,6 @@ def inequalities_list(self): """ return [list(x) for x in self.inequality_generator()] - def ieqs(self): - """ - Deprecated. Alias for inequalities() - - EXAMPLES:: - - sage: p3 = Polyhedron(vertices = Permutations([1,2,3,4])) - sage: p3.ieqs() == p3.inequalities() - doctest:...: DeprecationWarning: - This method is deprecated. Use inequalities() instead. - See http://trac.sagemath.org/11763 for details. - True - """ - from sage.misc.superseded import deprecation - deprecation(11763, 'This method is deprecated. Use inequalities() instead.') - return self.inequalities() - def equation_generator(self): """ Return a generator for the linear equations satisfied by the @@ -1346,29 +1147,6 @@ def equations_list(self): """ return [list(eq) for eq in self.equation_generator()] - def linearities(self): - """ - Deprecated. Use equations() instead. - Returns the linear constraints of the polyhedron. As with - inequalities, each constraint is given as [b -a1 -a2 ... an] - where for variables x1, x2,..., xn, the polyhedron satisfies - the equation b = a1*x1 + a2*x2 + ... + an*xn. - - EXAMPLES:: - - sage: test_p = Polyhedron(vertices = [[1,2,3,4],[2,1,3,4],[4,3,2,1],[3,4,1,2]]) - sage: test_p.linearities() - doctest:...: DeprecationWarning: - This method is deprecated. Use equations_list() instead. - See http://trac.sagemath.org/11763 for details. - [[-10, 1, 1, 1, 1]] - sage: test_p.linearities() == test_p.equations_list() - True - """ - from sage.misc.superseded import deprecation - deprecation(11763, 'This method is deprecated. Use equations_list() instead.') - return self.equations_list() - def vertices_list(self): """ Return a list of vertices of the polyhedron. @@ -2262,126 +2040,6 @@ def triangulate(self, engine='auto', connected=True, fine=False, regular=None, s pc.set_engine(engine) return pc.triangulate() - def triangulated_facial_incidences(self): - """ - Return a list of the form [face_index, [v_i_0, - v_i_1,...,v_i_{n-1}]] where the face_index refers to the - original defining inequality. For a given face, the - collection of triangles formed by each list of v_i should - triangulate that face. - - In dimensions greater than 3, this is computed by randomly - lifting each face up a dimension; this does not always work! - This should eventually be fixed by using lrs or another - program that computes triangulations. - - EXAMPLES: - - If the figure is already composed of triangles, then all is well:: - - sage: Polyhedron(vertices = [[5,0,0],[0,5,0],[5,5,0],[2,2,5]] - ... ).triangulated_facial_incidences() - doctest:...: DeprecationWarning: - This method is deprecated. Use triangulate() instead. - See http://trac.sagemath.org/11634 for details. - doctest:...: DeprecationWarning: - This method is deprecated. Use self.Hrepresentation(i).incident() instead. - See http://trac.sagemath.org/11763 for details. - [[0, [0, 1, 2]], [1, [0, 1, 3]], [2, [0, 2, 3]], [3, [1, 2, 3]]] - - Otherwise some faces get split up to triangles:: - - sage: Polyhedron(vertices = [[2,0,0],[4,1,0],[0,5,0],[5,5,0], - ... [1,1,0],[0,0,1]]).triangulated_facial_incidences() - doctest:...: DeprecationWarning: - This method is deprecated. Use triangulate() instead. - See http://trac.sagemath.org/11634 for details. - doctest:...: DeprecationWarning: - This method is deprecated. Use self.Vrepresentation(i).neighbors() instead. - See http://trac.sagemath.org/11763 for details. - [[0, [1, 2, 5]], [0, [2, 5, 3]], [0, [5, 3, 4]], [1, [0, 1, 2]], - [2, [0, 2, 3]], [3, [0, 3, 4]], [4, [0, 4, 5]], [5, [0, 1, 5]]] - """ - from sage.misc.superseded import deprecation - deprecation(11634, 'This method is deprecated. Use triangulate() instead.') - try: - return self._triangulated_facial_incidences - except AttributeError: - t_fac_incs = [] - for a_face in self.facial_incidences(): - vert_number = len(a_face[1]) - if vert_number == self.dim(): - t_fac_incs.append(a_face) - elif self.dim() >= 4: - lifted_verts = [] - for vert_index in a_face[1]: - lifted_verts.append(self.vertices()[vert_index] + - [randint(-vert_index,5000+vert_index + vert_number**2)]) - temp_poly = Polyhedron(vertices = lifted_verts) - for t_face in temp_poly.facial_incidences(): - if len(t_face[1]) != self.dim(): - print 'Failed for face: ' + str(a_face) - print 'Attempted simplicial face: ' + str(t_face) - print 'Attempted lifted vertices: ' + str(lifted_verts) - raise RuntimeError("triangulation failed") - normal_fdir = temp_poly.ieqs()[t_face[0]][-1] - if normal_fdir >= 0: - t_fac_verts = [temp_poly.vertices()[i] for i in t_face[1]] - proj_verts = [q[0:self.dim()] for q in t_fac_verts] - t_fac_incs.append([a_face[0], - [self.vertices().index(q) for q in proj_verts]]) - else: - vs = a_face[1][:] - adj = dict( (a[0], [p for p in a[1] if p in a_face[1]]) - for a in self.vertex_adjacencies() if a[0] in a_face[1]) - t = vs[0] - vs.remove(t) - ts = adj[t] - for v in ts: - vs.remove(v) - t_fac_incs.append([a_face[0], [t] + ts]) - while vs: - t = ts[0] - ts = ts[1:] - for v in adj[t]: - if v in vs: - vs.remove(v) - ts.append(v) - t_fac_incs.append([a_face[0], [t] + ts]) - break - self._triangulated_facial_incidences = t_fac_incs - return t_fac_incs - - def simplicial_complex(self): - """ - Return a simplicial complex from a triangulation of the polytope. - - Warning: This first triangulates the polytope using - ``triangulated_facial_incidences``, and this function may fail - in dimensions greater than 3, although it usually doesn't. - - OUTPUT: - - A simplicial complex. - - EXAMPLES:: - - sage: p = polytopes.cuboctahedron() - sage: sc = p.simplicial_complex() - doctest:...: DeprecationWarning: - This method is deprecated. Use triangulate().simplicial_complex() instead. - See http://trac.sagemath.org/11634 for details. - doctest:...: DeprecationWarning: - This method is deprecated. Use triangulate() instead. - See http://trac.sagemath.org/11634 for details. - sage: sc - Simplicial complex with 12 vertices and 20 facets - """ - from sage.misc.superseded import deprecation - deprecation(11634, 'This method is deprecated. Use triangulate().simplicial_complex() instead.') - from sage.homology.simplicial_complex import SimplicialComplex - return SimplicialComplex([x[1] for x in self.triangulated_facial_incidences()]) - @coerce_binop def Minkowski_sum(self, other): """ @@ -3546,34 +3204,6 @@ def _volume_lrs(self, verbose=False): raise ValueError("lrs did not return a volume") - def lrs_volume(self, verbose=False): - """ - Computes the volume of a polytope using lrs. - - OUTPUT: - - The volume, cast to RDF (although lrs seems to output a - rational value this must be an approximation in some cases). - - EXAMPLES:: - - sage: polytopes.n_cube(3).lrs_volume() #optional - lrs - doctest:...: DeprecationWarning: use volume(engine='lrs') instead - See http://trac.sagemath.org/13249 for details. - 8.0 - sage: (polytopes.n_cube(3)*2).lrs_volume() #optional - lrs - 64.0 - sage: polytopes.twenty_four_cell().lrs_volume() #optional - lrs - 2.0 - - REFERENCES: - - David Avis's lrs program. - """ - from sage.misc.superseded import deprecation - deprecation(13249, "use volume(engine='lrs') instead") - return self._volume_lrs(verbose=verbose) - @cached_method def volume(self, engine='auto', **kwds): """ diff --git a/src/sage/geometry/toric_lattice.py b/src/sage/geometry/toric_lattice.py index 06bd33dc283..2bb12a197d5 100644 --- a/src/sage/geometry/toric_lattice.py +++ b/src/sage/geometry/toric_lattice.py @@ -149,7 +149,8 @@ from sage.geometry.toric_lattice_element import (ToricLatticeElement, is_ToricLatticeElement) from sage.geometry.toric_plotter import ToricPlotter -from sage.misc.all import latex, parent +from sage.misc.all import latex +from sage.structure.all import parent from sage.modules.fg_pid.fgp_element import FGP_Element from sage.modules.fg_pid.fgp_module import FGP_Module_class from sage.modules.free_module import (FreeModule_ambient_pid, diff --git a/src/sage/graphs/base/static_dense_graph.pyx b/src/sage/graphs/base/static_dense_graph.pyx index b872d51117b..11e98fe212d 100644 --- a/src/sage/graphs/base/static_dense_graph.pyx +++ b/src/sage/graphs/base/static_dense_graph.pyx @@ -41,7 +41,7 @@ Functions --------- """ -cdef dict dense_graph_init(binary_matrix_t m, g, translation = False): +cdef dict dense_graph_init(binary_matrix_t m, g, translation=False): r""" Initializes the binary matrix from a Sage (di)graph. diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index fc0c9a9450e..5bb17a9db11 100644 --- a/src/sage/graphs/digraph.py +++ b/src/sage/graphs/digraph.py @@ -512,9 +512,9 @@ def __init__(self, data=None, pos=None, loops=None, format=None, Detection of multiple edges:: - sage: DiGraph([(1, 2, 0), (1,2,1)]) + sage: DiGraph({1:{2:[0,1]}}) Multi-digraph on 2 vertices - sage: DiGraph([(1, 2, 0)]) + sage: DiGraph({1:{2:0}}) Digraph on 2 vertices An empty list or dictionary defines a simple graph (trac #10441 and #12910):: @@ -665,6 +665,11 @@ def __init__(self, data=None, pos=None, loops=None, format=None, if (multiedges is None and (v in data[u])): multiedges = True + deprecation(15706, "You created a graph with multiple "+ + "edges from a list. Please set 'multiedges' "+ + "to 'True' when you do so, as in the "+ + "future the default behaviour will "+ + "be to ignore those edges") for uu, dd in data.iteritems(): for vv, ddd in dd.iteritems(): dd[vv] = [ddd] @@ -698,6 +703,11 @@ def __init__(self, data=None, pos=None, loops=None, format=None, else: raise ValueError("Edges input must all follow the same format.") + if loops is None and any(x in dx for x,dx in data.iteritems()): + deprecation(15706, "You created a graph with loops from a list. "+ + "Please set 'loops' to 'True' when you do so, as in "+ + "the future the default behaviour will be to ignore "+ + "those edges") if format is None: import networkx data = networkx.MultiDiGraph(data) @@ -816,7 +826,8 @@ def __init__(self, data=None, pos=None, loops=None, format=None, if loops is None or loops is False: for u in data: if u in data[u]: - if loops is None: loops = True + if loops is None: + loops = True elif loops is False: raise ValueError("No loops but dict has loops.") break @@ -826,7 +837,8 @@ def __init__(self, data=None, pos=None, loops=None, format=None, for v in data[u]: if v not in verts: verts.add(v) if multiedges is not False and not isinstance(data[u][v], list): - if multiedges is None: multiedges = False + if multiedges is None: + multiedges = False if multiedges: raise ValueError("Dict of dicts for multidigraph must be in the format {v : {u : list}}") if multiedges is None and len(data) > 0: @@ -2933,7 +2945,7 @@ def topological_sort(self, implementation = "default"): sage: D.topological_sort() Traceback (most recent call last): ... - TypeError: Digraph is not acyclic-- there is no topological + TypeError: Digraph is not acyclic; there is no topological sort. .. note:: @@ -2967,7 +2979,7 @@ def topological_sort(self, implementation = "default"): if b: return ordering else: - raise TypeError('Digraph is not acyclic-- there is no topological sort.') + raise TypeError('Digraph is not acyclic; there is no topological sort.') elif implementation == "NetworkX" or implementation == "recursive": import networkx @@ -2976,7 +2988,7 @@ def topological_sort(self, implementation = "default"): else: S = networkx.topological_sort_recursive(self.networkx_graph(copy=False)) if S is None: - raise TypeError('Digraph is not acyclic-- there is no topological sort.') + raise TypeError('Digraph is not acyclic; there is no topological sort.') else: return S @@ -3026,7 +3038,7 @@ def topological_sort_generator(self): try: return LinearExtensions(self).list() except TypeError: - raise TypeError('Digraph is not acyclic-- there is no topological sort (or there was an error in sage/graphs/linearextensions.py).') + raise TypeError('Digraph is not acyclic; there is no topological sort (or there was an error in sage/graphs/linearextensions.py).') ### Visualization diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 632464aaeae..f03336b89b0 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -2091,8 +2091,6 @@ def loops(self, labels=True): INPUT: - - ``new`` -- deprecated - - ``labels`` -- whether returned edges have labels ((u,v,l)) or not ((u,v)). EXAMPLES:: @@ -2381,7 +2379,6 @@ def multiple_edges(self, to_undirected=False, labels=True): sage: G.multiple_edges(to_undirected=True) [(1, 2, 'h'), (2, 1, 'g')] """ - from sage.misc.superseded import deprecation multi_edges = [] if self._directed and not to_undirected: for v in self: @@ -3396,7 +3393,7 @@ def cycle_basis(self, output='vertex'): For undirected graphs with multiple edges:: - sage: G = Graph([(0,2,'a'),(0,2,'b'),(0,1,'c'),(1,2,'d')]) + sage: G = Graph([(0,2,'a'),(0,2,'b'),(0,1,'c'),(1,2,'d')], multiedges=True) sage: G.cycle_basis() [[0, 2], [2, 1, 0]] sage: G.cycle_basis(output='edge') @@ -3421,7 +3418,7 @@ def cycle_basis(self, output='vertex'): Not yet implemented for directed graphs with multiple edges:: - sage: G = DiGraph([(0,2,'a'),(0,2,'b'),(0,1,'c'),(1,2,'d')]) + sage: G = DiGraph([(0,2,'a'),(0,2,'b'),(0,1,'c'),(1,2,'d')], multiedges=True) sage: G.cycle_basis() Traceback (most recent call last): ... @@ -4691,8 +4688,7 @@ def is_cut_edge(self, u, v=None, label=None): sage: G.is_cut_edge((0,1)) True - sage: G = Graph([[0,1],[0,2],[1,1]]) - sage: G.allow_loops(True) + sage: G = Graph([[0,1],[0,2],[1,1]], loops = True) sage: G.is_cut_edge((1,1)) False @@ -7879,7 +7875,7 @@ def vertex_disjoint_paths(self, s, t): return paths - def dominating_set(self, independent=False, value_only=False, solver=None, verbose=0): + def dominating_set(self, independent=False, total=False, value_only=False, solver=None, verbose=0): r""" Returns a minimum dominating set of the graph represented by the list of its vertices. For more information, see the @@ -7904,6 +7900,9 @@ def dominating_set(self, independent=False, value_only=False, solver=None, verbo - ``independent`` -- boolean (default: ``False``). If ``independent=True``, computes a minimum independent dominating set. + - ``total`` -- boolean (default: ``False``). If + ``total=True``, computes a total dominating set. + - ``value_only`` -- boolean (default: ``False``) - If ``True``, only the cardinality of a minimum @@ -7942,7 +7941,15 @@ def dominating_set(self, independent=False, value_only=False, solver=None, verbo sage: len(g.dominating_set(independent=True)) 6 + The total dominating set of the Petersen graph has cardinality 4:: + + sage: G = graphs.PetersenGraph() + sage: G.dominating_set(total=True,value_only=True) + 4 """ + + self._scream_if_not_simple(allow_multiple_edges=True, allow_loops=not total) + from sage.numerical.mip import MixedIntegerLinearProgram g=self p=MixedIntegerLinearProgram(maximization=False, solver=solver) @@ -7951,7 +7958,7 @@ def dominating_set(self, independent=False, value_only=False, solver=None, verbo # For any vertex v, one of its neighbors or v itself is in # the minimum dominating set for v in g.vertices(): - p.add_constraint(b[v]+p.sum([b[u] for u in g.neighbors(v)]),min=1) + p.add_constraint(int(not total)*b[v]+p.sum([b[u] for u in g.neighbors(v)]),min=1) if independent: @@ -11537,7 +11544,7 @@ def is_circulant(self, certificate = False): (True, (1, [])) sage: Graph(0).is_circulant(certificate = True) (True, (0, [])) - sage: Graph([(0,0)]).is_circulant(certificate = True) + sage: Graph({0:[0]}).is_circulant(certificate = True) (True, (1, [0])) """ self._scream_if_not_simple(allow_loops=True) @@ -12003,7 +12010,7 @@ def clustering_average(self): import networkx return networkx.average_clustering(self.networkx_graph(copy=False)) - def clustering_coeff(self, nodes=None, weight=False, return_vertex_weights=True): + def clustering_coeff(self, nodes=None, weight=False, return_vertex_weights=None): r""" Returns the clustering coefficient for each vertex in ``nodes`` as a dictionary keyed by vertex. @@ -12031,10 +12038,6 @@ def clustering_coeff(self, nodes=None, weight=False, return_vertex_weights=True) a string it used the indicated edge property as weight. ``weight = True`` is equivalent to ``weight = 'weight'`` - - ``return_vertex_weights`` is a boolean ensuring backwards - compatibility with deprecated features of NetworkX 1.2. It - should be set to ``False`` for all production code. - EXAMPLES:: sage: (graphs.FruchtGraph()).clustering_coeff().values() @@ -12049,8 +12052,7 @@ def clustering_coeff(self, nodes=None, weight=False, return_vertex_weights=True) 7: 0.3333333333333333, 8: 0.0, 9: 0.3333333333333333, 10: 0.3333333333333333, 11: 0.0} - sage: (graphs.FruchtGraph()).clustering_coeff(weight=True, - ... return_vertex_weights=False) + sage: (graphs.FruchtGraph()).clustering_coeff(weight=True) {0: 0.3333333333333333, 1: 0.3333333333333333, 2: 0.0, 3: 0.3333333333333333, 4: 0.3333333333333333, 5: 0.3333333333333333, 6: 0.3333333333333333, @@ -12060,68 +12062,24 @@ def clustering_coeff(self, nodes=None, weight=False, return_vertex_weights=True) {0: 0.3333333333333333, 1: 0.3333333333333333, 2: 0.0} sage: (graphs.FruchtGraph()).clustering_coeff(nodes=[0,1,2], - ... weight=True, return_vertex_weights=False) + ... weight=True) {0: 0.3333333333333333, 1: 0.3333333333333333, 2: 0.0} - TESTS: - - Doctests that demonstrate the deprecation of the two-dictionary - return value due to the NetworkX API change after 1.2. The - return_vertex_weights keyword is provided with a default value - of True for backwards compatibility with older versions of Sage. - When the deprecation period has expired and the keyword is - removed, these doctests should be removed as well. :: + TESTS:: - sage: (graphs.FruchtGraph()).clustering_coeff(weight=True, - ... return_vertex_weights=True) + sage: graphs.FruchtGraph().clustering_coeff(nodes=[0,1,2], + ... weight=True, return_vertex_weights=False) doctest:...: DeprecationWarning: The option 'return_vertex_weights' - has been deprecated. Only offered for backwards compatibility with - NetworkX 1.2. - See http://trac.sagemath.org/12806 for details. - ({0: 0.3333333333333333, 1: 0.3333333333333333, 2: 0.0, - 3: 0.3333333333333333, 4: 0.3333333333333333, - 5: 0.3333333333333333, 6: 0.3333333333333333, - 7: 0.3333333333333333, 8: 0.0, 9: 0.3333333333333333, - 10: 0.3333333333333333, 11: 0.0}, {0: 0.08333333333333333, - 1: 0.08333333333333333, 2: 0.08333333333333333, - 3: 0.08333333333333333, 4: 0.08333333333333333, - 5: 0.08333333333333333, 6: 0.08333333333333333, - 7: 0.08333333333333333, 8: 0.08333333333333333, - 9: 0.08333333333333333, 10: 0.08333333333333333, - 11: 0.08333333333333333}) - - sage: (graphs.FruchtGraph()).clustering_coeff(nodes=[0, 1, 2], - ... weight=True, return_vertex_weights=True) - ({0: 0.3333333333333333, 1: 0.3333333333333333, 2: 0.0}, - {0: 0.3333333333333333, 1: 0.3333333333333333, - 2: 0.3333333333333333}) + has been deprecated and is ignored. + See http://trac.sagemath.org/17134 for details. + {0: 0.3333333333333333, 1: 0.3333333333333333, 2: 0.0} """ - import networkx - if weight and return_vertex_weights: - # Running in compatibility mode with deprecated NetworkX 1.2 features - # All this code should be removed when the deprecation warning expires + if return_vertex_weights is not None: from sage.misc.superseded import deprecation - deprecation(12806, "The option 'return_vertex_weights' has been " +\ - "deprecated. Only offered for backwards" +\ - " compatibility with NetworkX 1.2.") - G = self.networkx_graph(copy=False) - if G.is_directed(): - raise NetworkXError("Clustering algorithms are not defined for directed graphs.") - clusterc={} - weights={} - for v,d,t in networkx.cluster._triangles_and_degree_iter(G,nodes): - weights[v]=float(d*(d-1)) - if t==0: - clusterc[v]=0.0 - else: - clusterc[v]=t/float(d*(d-1)) - scale=1./sum(weights.itervalues()) - for v,w in weights.iteritems(): - weights[v]=w*scale - return clusterc,weights - - else: - return networkx.clustering(self.networkx_graph(copy=False), nodes, weight=weight) + deprecation(17134, "The option 'return_vertex_weights' has been " + + "deprecated and is ignored.") + import networkx + return networkx.clustering(self.networkx_graph(copy=False), nodes, weight=weight) def cluster_transitivity(self): r""" @@ -14575,15 +14533,9 @@ def transitive_closure(self): sage: digraphs.Path(5).copy(immutable=True).transitive_closure() Transitive closure of Path: Digraph on 5 vertices """ - from copy import copy G = self.copy(immutable=False) G.name('Transitive closure of ' + self.name()) - for v in G: - # todo optimization opportunity: we are adding edges that - # are already in the graph and we are adding edges - # one at a time. - for e in G.breadth_first_search(v): - G.add_edge((v,e)) + G.add_edges((v, e) for v in G for e in G.breadth_first_search(v)) return G def transitive_reduction(self): @@ -14602,24 +14554,27 @@ def transitive_reduction(self): EXAMPLES:: - sage: g=graphs.PathGraph(4) - sage: g.transitive_reduction()==g + sage: g = graphs.PathGraph(4) + sage: g.transitive_reduction() == g True - sage: g=graphs.CompleteGraph(5) + sage: g = graphs.CompleteGraph(5) sage: edges = g.transitive_reduction().edges(); len(edges) 4 - sage: g=DiGraph({0:[1,2], 1:[2,3,4,5], 2:[4,5]}) + sage: g = DiGraph({0:[1,2], 1:[2,3,4,5], 2:[4,5]}) sage: g.transitive_reduction().size() 5 """ - from copy import copy - from sage.rings.infinity import Infinity - G = copy(self) + if self.is_directed() and self.is_directed_acyclic(): + from sage.graphs.generic_graph_pyx import transitive_reduction_acyclic + return transitive_reduction_acyclic(self) + + G = self.copy(immutable=False) + n = G.order() for e in self.edge_iterator(): # Try deleting the edge, see if we still have a path # between the vertices. G.delete_edge(e) - if G.distance(e[0],e[1])==Infinity: + if G.distance(e[0], e[1]) > n: # oops, we shouldn't have deleted it G.add_edge(e) return G @@ -15745,7 +15700,6 @@ def show(self, method = "matplotlib", **kwds): return from graph_plot import graphplot_options - # This dictionary only contains the options that graphplot # understands. These options are removed from kwds at the same # time. @@ -17887,8 +17841,8 @@ def is_isomorphic(self, other, certify=False, verbosity=0, edge_labels=False): Ensure that isomorphic looped graphs with non-range vertex labels report correctly (:trac:`10814`, fixed by :trac:`8395`):: - sage: G1 = Graph([(0,1), (1,1)]) - sage: G2 = Graph([(0,2), (2,2)]) + sage: G1 = Graph({1:[0,1]}) + sage: G2 = Graph({2:[0,2]}) sage: G1.is_isomorphic(G2) True sage: G = Graph(multiedges = True, loops = True) @@ -17920,8 +17874,9 @@ def is_isomorphic(self, other, certify=False, verbosity=0, edge_labels=False): Ensure that :trac:`13114` is fixed :: - sage: g = Graph([(0, 0, 0), (0, 2, 0), (1, 1, 0), (1, 2, 0), (1, 2, 1), (2, 2, 0)]) - sage: gg = Graph([(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 2, 0), (2, 2, 0), (2, 2, 1)]) + + sage: g = Graph([(0, 0, 0), (0, 2, 0), (1, 1, 0), (1, 2, 0), (1, 2, 1), (2, 2, 0)], multiedges=True, loops=True) + sage: gg = Graph([(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 2, 0), (2, 2, 0), (2, 2, 1)], multiedges=True, loops=True) sage: g.is_isomorphic(gg) False @@ -18302,12 +18257,12 @@ def graph_isom_equivalent_non_edge_labeled_graph(g, partition=None, standard_lab Ensure that #14108 is fixed:: - sage: G=DiGraph([[0,0],[0,0],[0,0],[1,1],[1,1],[1,1]]) - sage: H=DiGraph([[0,0],[0,0],[0,0],[0,0],[1,1],[1,1]]) + sage: G=DiGraph({0:[0,0,0],1:[1,1,1]}) + sage: H=DiGraph({0:[0,0,0,0],1:[1,1]}) sage: G.is_isomorphic(H) False - sage: H=DiGraph([[0,0],[0,0],[0,0],[0,0],[0,0],[1,1],[1,1]]) - sage: HH=DiGraph([[0,0],[0,0],[0,0],[0,0],[1,1],[1,1],[1,1]]) + sage: H=DiGraph({0:[0,0,0,0],1:[1,1]}) + sage: HH=DiGraph({0:[0,0,0],1:[1,1,1]}) sage: H.is_isomorphic(HH) False sage: H.is_isomorphic(HH, edge_labels=True) diff --git a/src/sage/graphs/generic_graph_pyx.pyx b/src/sage/graphs/generic_graph_pyx.pyx index c456ffe29cc..3ed96a1958f 100644 --- a/src/sage/graphs/generic_graph_pyx.pyx +++ b/src/sage/graphs/generic_graph_pyx.pyx @@ -18,6 +18,7 @@ AUTHORS: include "sage/ext/interrupt.pxi" include 'sage/ext/cdefs.pxi' include 'sage/ext/stdsage.pxi' +include "sage/misc/binary_matrix.pxi" # import from Python standard library from sage.misc.prandom import random @@ -1280,3 +1281,71 @@ cpdef tuple find_hamiltonian( G, long max_iter=100000, long reset_bound=30000, l return (True,output) +def transitive_reduction_acyclic(G): + r""" + Returns the transitive reduction of an acyclic digraph + + INPUT: + + - ``G`` -- an acyclic digraph. + + EXAMPLE:: + + sage: from sage.graphs.generic_graph_pyx import transitive_reduction_acyclic + sage: G = posets.BooleanLattice(4).hasse_diagram() + sage: G == transitive_reduction_acyclic(G.transitive_closure()) + True + """ + cdef int n = G.order() + cdef dict v_to_int = {vv: i for i, vv in enumerate(G.vertices())} + cdef int u, v, i + + cdef list linear_extension + + is_acyclic, linear_extension = G.is_directed_acyclic(certificate=True) + if not is_acyclic: + raise ValueError("The graph is not directed acyclic") + + linear_extension.reverse() + + cdef binary_matrix_t closure + + # Build the transitive closure of G + # + # A point is reachable from u if it is one of its neighbours, or if it is + # reachable from one of its neighbours. + binary_matrix_init(closure, n, n) + binary_matrix_fill(closure, 0) + for uu in linear_extension: + u = v_to_int[uu] + for vv in G.neighbors_out(uu): + v = v_to_int[vv] + binary_matrix_set1(closure, u, v) + for i in range(closure.width): + closure.rows[u][i] |= closure.rows[v][i] + + # Build the transitive reduction of G + # + # An edge uv belongs to the transitive reduction of G if no outneighbor of u + # can reach v (except v itself, of course). + linear_extension.reverse() + cdef list useful_edges = [] + for uu in linear_extension: + u = v_to_int[uu] + for vv in G.neighbors_out(uu): + v = v_to_int[vv] + for i in range(closure.width): + closure.rows[u][i] &= ~closure.rows[v][i] + for vv in G.neighbors_out(uu): + v = v_to_int[vv] + if binary_matrix_get(closure, u, v): + useful_edges.append((uu, vv)) + + from sage.graphs.digraph import DiGraph + reduced = DiGraph() + reduced.add_edges(useful_edges) + reduced.add_vertices(linear_extension) + + binary_matrix_free(closure) + + return reduced diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index ca8d23a75dc..f1bb61706b4 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -528,6 +528,7 @@ #***************************************************************************** from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.misc.superseded import deprecation from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ import sage.graphs.generic_graph_pyx as generic_graph_pyx @@ -941,7 +942,7 @@ class Graph(GenericGraph): sage: g = Graph([(1,2,"Peace"),(7,-9,"and"),(77,2, "Love")]) sage: g Graph on 5 vertices - sage: g = Graph([(0, 2, '0'), (0, 2, '1'), (3, 3, '2')]) + sage: g = Graph([(0, 2, '0'), (0, 2, '1'), (3, 3, '2')], loops=True, multiedges=True) sage: g.loops() [(3, 3, '2')] @@ -1031,9 +1032,9 @@ def __init__(self, data=None, pos=None, loops=None, format=None, Loops are not counted as multiedges (see :trac:`11693`) and edges are not counted twice :: - sage: Graph([[1,1]],multiedges=False).num_edges() + sage: Graph({1:[1]}).num_edges() 1 - sage: Graph([[1,2],[1,2]],multiedges=True).num_edges() + sage: Graph({1:[2,2]}).num_edges() 2 Invalid sequence of edges given as an input (they do not all @@ -1220,6 +1221,11 @@ def __init__(self, data=None, pos=None, loops=None, format=None, if (multiedges is None and (u in data[v])): multiedges = True + deprecation(15706, "You created a graph with multiple "+ + "edges from a list. Please set 'multiedges' "+ + "to 'True' when you do so, as in the "+ + "future the default behaviour will "+ + "be to ignore those edges") for uu, dd in data.iteritems(): for vv, ddd in dd.iteritems(): dd[vv] = [ddd] @@ -1258,6 +1264,11 @@ def __init__(self, data=None, pos=None, loops=None, format=None, else: raise ValueError("Edges input must all follow the same format.") + if loops is None and any(x in dx for x,dx in data.iteritems()): + deprecation(15706, "You created a graph with loops from a list. "+ + "Please set 'loops' to 'True' when you do so, as in "+ + "the future the default behaviour will be to ignore "+ + "those edges") if format is None: import networkx data = networkx.MultiGraph(data) @@ -1453,18 +1464,21 @@ def __init__(self, data=None, pos=None, loops=None, format=None, if loops is None or loops is False: for u in data: if u in data[u]: - if loops is None: loops = True + if loops is None: + loops = True elif loops is False: raise ValueError("No loops but dict has loops.") break - if loops is None: loops = False + if loops is None: + loops = False if weighted is None: weighted = False for u in data: if len(uniq(data[u])) != len(data[u]): if multiedges is False: v = (v for v in data[u] if data[u].count(v) > 1).next() raise ValueError("Non-multigraph got several edges (%s,%s)"%(u,v)) - if multiedges is None: multiedges = True + if multiedges is None: + multiedges = True if multiedges is None: multiedges = False num_verts = len(verts) elif format == 'NX': @@ -1952,7 +1966,7 @@ def is_tree(self, certificate=False, output='vertex'): This is useful for graphs with multiple edges:: - sage: G = Graph([(1, 2, 'a'), (1, 2, 'b')]) + sage: G = Graph([(1, 2, 'a'), (1, 2, 'b')], multiedges=True) sage: G.is_tree(certificate=True) (False, [1, 2]) sage: G.is_tree(certificate=True, output='edge') @@ -6766,13 +6780,13 @@ def kirchhoff_symanzik_polynomial(self, name='t'): For the 'coffee bean' graph:: - sage: G = Graph([(0,1,'a'),(0,1,'b'),(0,1,'c')]) + sage: G = Graph([(0,1,'a'),(0,1,'b'),(0,1,'c')],multiedges=True) sage: G.kirchhoff_symanzik_polynomial() t0*t1 + t0*t2 + t1*t2 For the 'parachute' graph:: - sage: G = Graph([(0,2,'a'),(0,2,'b'),(0,1,'c'),(1,2,'d')]) + sage: G = Graph([(0,2,'a'),(0,2,'b'),(0,1,'c'),(1,2,'d')], multiedges=True) sage: G.kirchhoff_symanzik_polynomial() t0*t1 + t0*t2 + t1*t2 + t1*t3 + t2*t3 diff --git a/src/sage/groups/abelian_gps/dual_abelian_group_element.py b/src/sage/groups/abelian_gps/dual_abelian_group_element.py index a44dfbc7d57..f7bfb1dbb88 100644 --- a/src/sage/groups/abelian_gps/dual_abelian_group_element.py +++ b/src/sage/groups/abelian_gps/dual_abelian_group_element.py @@ -57,7 +57,6 @@ from sage.rings.infinity import infinity from sage.rings.arith import * from sage.misc.misc import prod -from sage.misc.functional import exp from sage.rings.complex_field import is_ComplexField from sage.groups.abelian_gps.element_base import AbelianGroupElementBase from functools import reduce @@ -162,7 +161,7 @@ def __call__(self, g): from sage.symbolic.constants import pi I = F.gen() PI = F(pi) - ans = prod([exp(2*PI*I*expsX[i]*expsg[i]/order[i]) for i in range(len(expsX))]) + ans = prod([(2*PI*I*expsX[i]*expsg[i]/order[i]).exp() for i in range(len(expsX))]) return ans ans = F(1) ## assumes F is the cyclotomic field zeta = F.gen() diff --git a/src/sage/groups/perm_gps/permutation_groups_catalog.py b/src/sage/groups/perm_gps/permutation_groups_catalog.py index 8559abcda96..2151c2cea32 100644 --- a/src/sage/groups/perm_gps/permutation_groups_catalog.py +++ b/src/sage/groups/perm_gps/permutation_groups_catalog.py @@ -1,4 +1,6 @@ r""" +Catalog of permutation groups + Type ``groups.permutation.`` to access examples of groups implemented as permutation groups. """ diff --git a/src/sage/interfaces/fricas.py b/src/sage/interfaces/fricas.py index baf87a66356..d7b8174e8db 100644 --- a/src/sage/interfaces/fricas.py +++ b/src/sage/interfaces/fricas.py @@ -1,15 +1,15 @@ r""" Interface to FriCAS -TODO: +.. TODO:: -- Evaluation using a file is not done. Any input line with more than a - few thousand characters would hang the system, so currently it - automatically raises an exception. + - Evaluation using a file is not done. Any input line with more + than a few thousand characters would hang the system, so currently it + automatically raises an exception. -- All completions of a given command. + - All completions of a given command. -- Interactive help. + - Interactive help. FriCAS is a free GPL-compatible (modified BSD license) general purpose computer algebra system based on Axiom. The FriCAS @@ -289,14 +289,14 @@ class FriCASExpectFunction(PanAxiomExpectFunction): def is_FriCASElement(x): """ - Returns True of x is of type FriCASElement. + Return True if x is of type FriCASElement. EXAMPLES:: - sage: from sage.interfaces.fricas import is_FriCASElement - sage: is_FriCASElement(fricas(2)) #optional - fricas + sage: from sage.interfaces.fricas import is_FriCASElement #optional - fricas + sage: is_FriCASElement(fricas(2)) #optional - fricas True - sage: is_FriCASElement(2) + sage: is_FriCASElement(2) #optional - fricas False """ return isinstance(x, FriCASElement) @@ -340,13 +340,13 @@ def __doctest_cleanup(): """ EXAMPLES:: - sage: from sage.interfaces.fricas import __doctest_cleanup - sage: a = FriCAS() + sage: from sage.interfaces.fricas import __doctest_cleanup #optional - fricas + sage: a = FriCAS() #optional - fricas sage: two = a(2) #optional - fricas sage: a.is_running() #optional - fricas True - sage: __doctest_cleanup() - sage: a.is_running() + sage: __doctest_cleanup() #optional - fricas + sage: a.is_running() #optional - fricas False """ import sage.interfaces.quit diff --git a/src/sage/interfaces/maxima_abstract.py b/src/sage/interfaces/maxima_abstract.py index 923ba9b17b0..0944ef36219 100644 --- a/src/sage/interfaces/maxima_abstract.py +++ b/src/sage/interfaces/maxima_abstract.py @@ -418,7 +418,7 @@ def version(self): EXAMPLES:: sage: maxima.version() - '5.34.1' + '5.35.1' """ return maxima_version() @@ -2347,7 +2347,7 @@ def maxima_version(): sage: from sage.interfaces.maxima_abstract import maxima_version sage: maxima_version() - '5.34.1' + '5.35.1' """ return os.popen('maxima --version').read().split()[-1] diff --git a/src/sage/interfaces/tides.py b/src/sage/interfaces/tides.py index c3459753b82..96073fea42c 100644 --- a/src/sage/interfaces/tides.py +++ b/src/sage/interfaces/tides.py @@ -342,7 +342,7 @@ def remove_repeated(l1, l2): for i in range(len(l1)-1): j=i+1 while j = GF(7^2) + sage: R. = F[] + sage: p = x+2*y + sage: def leak(N): + ....: before = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss + ....: gc.collect() + ....: for i in range(N): + ....: _ = p(a, a) + ....: after = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss + ....: return (after - before) * 1024 # ru_maxrss is in kilobytes + sage: _ = leak(50000) # warmup and fill up pre-allocated buckets + sage: leak(10000) + 0 """ cdef long l = len(args) cdef ideal *to_id = idInit(l,1) @@ -157,6 +178,9 @@ cdef int singular_polynomial_call(poly **ret, poly *p, ring *r, list args, poly cdef ideal *res_id = fast_map(from_id, r, to_id, r) ret[0] = res_id.m[0] + # Unsure why we have to normalize here. See #16958 + p_Normalize(ret[0], r) + from_id.m[0] = NULL res_id.m[0] = NULL diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index c9f97f84722..775664ba9b0 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -1466,7 +1466,10 @@ cdef class Matrix(matrix1.Matrix): def __abs__(self): """ - Synonym for self.determinant(...). + Deprecated. + + This function used to return the determinant. It is deprecated since + :trac:`17443`. EXAMPLES:: @@ -1474,9 +1477,179 @@ cdef class Matrix(matrix1.Matrix): [1 2] [3 4] sage: abs(a) + doctest:...: DeprecationWarning: abs(matrix) is deprecated. Use matrix.det()to + get the determinant. + See http://trac.sagemath.org/17443 for details. -2 """ - return self.determinant() + #TODO: after expiration of the one year deprecation, we should return a + # TypeError with the following kind of message: + # absolute value is not defined on matrices. If you want the + # L^1-norm use m.norm(1) and if you want the matrix obtained by + # applying the absolute value to the coefficents use + # m.apply_map(abs). + from sage.misc.superseded import deprecation + deprecation(17443, "abs(matrix) is deprecated. Use matrix.det()" + "to get the determinant.") + return self.det() + + def apply_morphism(self, phi): + """ + Apply the morphism phi to the coefficients of this dense matrix. + + The resulting matrix is over the codomain of phi. + + INPUT: + + + - ``phi`` - a morphism, so phi is callable and + phi.domain() and phi.codomain() are defined. The codomain must be a + ring. + + OUTPUT: a matrix over the codomain of phi + + EXAMPLES:: + + sage: m = matrix(ZZ, 3, range(9)) + sage: phi = ZZ.hom(GF(5)) + sage: m.apply_morphism(phi) + [0 1 2] + [3 4 0] + [1 2 3] + sage: parent(m.apply_morphism(phi)) + Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 5 + + We apply a morphism to a matrix over a polynomial ring:: + + sage: R. = QQ[] + sage: m = matrix(2, [x,x^2 + y, 2/3*y^2-x, x]); m + [ x x^2 + y] + [2/3*y^2 - x x] + sage: phi = R.hom([y,x]) + sage: m.apply_morphism(phi) + [ y y^2 + x] + [2/3*x^2 - y y] + """ + M = self.parent().change_ring(phi.codomain()) + if self.is_sparse(): + values = {(i,j): phi(z) for (i,j),z in self.dict()} + else: + values = [phi(z) for z in self.list()] + image = M(values) + if self._subdivisions is not None: + image.subdivide(*self.subdivisions()) + return image + + def apply_map(self, phi, R=None, sparse=None): + """ + Apply the given map phi (an arbitrary Python function or callable + object) to this dense matrix. If R is not given, automatically + determine the base ring of the resulting matrix. + + INPUT: + + - ``sparse`` -- True to make the output a sparse matrix; default False + + - ``phi`` - arbitrary Python function or callable object + + - ``R`` - (optional) ring + + OUTPUT: a matrix over R + + EXAMPLES:: + + sage: m = matrix(ZZ, 3, range(9)) + sage: k. = GF(9) + sage: f = lambda x: k(x) + sage: n = m.apply_map(f); n + [0 1 2] + [0 1 2] + [0 1 2] + sage: n.parent() + Full MatrixSpace of 3 by 3 dense matrices over Finite Field in a of size 3^2 + + In this example, we explicitly specify the codomain. + + :: + + sage: s = GF(3) + sage: f = lambda x: s(x) + sage: n = m.apply_map(f, k); n + [0 1 2] + [0 1 2] + [0 1 2] + sage: n.parent() + Full MatrixSpace of 3 by 3 dense matrices over Finite Field in a of size 3^2 + + If self is subdivided, the result will be as well:: + + sage: m = matrix(2, 2, srange(4)) + sage: m.subdivide(None, 1); m + [0|1] + [2|3] + sage: m.apply_map(lambda x: x*x) + [0|1] + [4|9] + + If the matrix is sparse, the result will be as well:: + + sage: m = matrix(ZZ,100,100,sparse=True) + sage: m[18,32] = -6 + sage: m[1,83] = 19 + sage: n = m.apply_map(abs, R=ZZ) + sage: n.dict() + {(1, 83): 19, (18, 32): 6} + sage: n.is_sparse() + True + + If the map sends most of the matrix to zero, then it may be useful + to get the result as a sparse matrix. + + :: + + sage: m = matrix(ZZ, 3, 3, range(1, 10)) + sage: n = m.apply_map(lambda x: 1//x, sparse=True); n + [1 0 0] + [0 0 0] + [0 0 0] + sage: n.parent() + Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring + + TESTS:: + + sage: m = matrix([]) + sage: m.apply_map(lambda x: x*x) == m + True + + sage: m.apply_map(lambda x: x*x, sparse=True).parent() + Full MatrixSpace of 0 by 0 sparse matrices over Integer Ring + """ + if self._nrows == 0 or self._ncols == 0: + if sparse is None or self.is_sparse() is sparse: + return self.__copy__() + elif sparse: + return self.sparse_matrix() + else: + return self.dense_matrix() + + if self.is_sparse(): + values = {(i,j): phi(v) for (i,j),v in self.dict().iteritems()} + if R is None: + R = sage.structure.sequence.Sequence(values.values()).universe() + else: + values = [phi(v) for v in self.list()] + if R is None: + R = sage.structure.sequence.Sequence(values).universe() + + if sparse is None or sparse is self.is_sparse(): + M = self.parent().change_ring(R) + else: + M = sage.matrix.matrix_space.MatrixSpace(R, self._nrows, + self._ncols, sparse=sparse) + image = M(values) + if self._subdivisions is not None: + image.subdivide(*self.subdivisions()) + return image def characteristic_polynomial(self, *args, **kwds): """ diff --git a/src/sage/matrix/matrix_dense.pyx b/src/sage/matrix/matrix_dense.pyx index 31fe4020211..615efaf9202 100644 --- a/src/sage/matrix/matrix_dense.pyx +++ b/src/sage/matrix/matrix_dense.pyx @@ -266,143 +266,6 @@ cdef class Matrix_dense(matrix.Matrix): prod.set_unsafe(r,c,entry) return prod - def apply_morphism(self, phi): - """ - Apply the morphism phi to the coefficients of this dense matrix. - - The resulting matrix is over the codomain of phi. - - INPUT: - - - - ``phi`` - a morphism, so phi is callable and - phi.domain() and phi.codomain() are defined. The codomain must be a - ring. - - - OUTPUT: a matrix over the codomain of phi - - EXAMPLES:: - - sage: m = matrix(ZZ, 3, range(9)) - sage: phi = ZZ.hom(GF(5)) - sage: m.apply_morphism(phi) - [0 1 2] - [3 4 0] - [1 2 3] - sage: parent(m.apply_morphism(phi)) - Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 5 - - We apply a morphism to a matrix over a polynomial ring:: - - sage: R. = QQ[] - sage: m = matrix(2, [x,x^2 + y, 2/3*y^2-x, x]); m - [ x x^2 + y] - [2/3*y^2 - x x] - sage: phi = R.hom([y,x]) - sage: m.apply_morphism(phi) - [ y y^2 + x] - [2/3*x^2 - y y] - """ - R = phi.codomain() - M = sage.matrix.matrix_space.MatrixSpace(R, self._nrows, - self._ncols, sparse=False) - image = M([phi(z) for z in self.list()]) - if self._subdivisions is not None: - image.subdivide(*self.subdivisions()) - return image - - def apply_map(self, phi, R=None, sparse=False): - """ - Apply the given map phi (an arbitrary Python function or callable - object) to this dense matrix. If R is not given, automatically - determine the base ring of the resulting matrix. - - INPUT: - sparse -- True to make the output a sparse matrix; default False - - - - ``phi`` - arbitrary Python function or callable - object - - - ``R`` - (optional) ring - - - OUTPUT: a matrix over R - - EXAMPLES:: - - sage: m = matrix(ZZ, 3, range(9)) - sage: k. = GF(9) - sage: f = lambda x: k(x) - sage: n = m.apply_map(f); n - [0 1 2] - [0 1 2] - [0 1 2] - sage: n.parent() - Full MatrixSpace of 3 by 3 dense matrices over Finite Field in a of size 3^2 - - In this example, we explicitly specify the codomain. - - :: - - sage: s = GF(3) - sage: f = lambda x: s(x) - sage: n = m.apply_map(f, k); n - [0 1 2] - [0 1 2] - [0 1 2] - sage: n.parent() - Full MatrixSpace of 3 by 3 dense matrices over Finite Field in a of size 3^2 - - If self is subdivided, the result will be as well:: - - sage: m = matrix(2, 2, srange(4)) - sage: m.subdivide(None, 1); m - [0|1] - [2|3] - sage: m.apply_map(lambda x: x*x) - [0|1] - [4|9] - - If the map sends most of the matrix to zero, then it may be useful - to get the result as a sparse matrix. - - :: - - sage: m = matrix(ZZ, 3, 3, range(1, 10)) - sage: n = m.apply_map(lambda x: 1//x, sparse=True); n - [1 0 0] - [0 0 0] - [0 0 0] - sage: n.parent() - Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring - - TESTS:: - - sage: m = matrix([]) - sage: m.apply_map(lambda x: x*x) == m - True - - sage: m.apply_map(lambda x: x*x, sparse=True).parent() - Full MatrixSpace of 0 by 0 sparse matrices over Integer Ring - """ - if self._nrows==0 or self._ncols==0: - if sparse: - return self.sparse_matrix() - else: - return self.__copy__() - v = [phi(z) for z in self.list()] - if R is None: - v = sage.structure.sequence.Sequence(v) - R = v.universe() - M = sage.matrix.matrix_space.MatrixSpace(R, self._nrows, - self._ncols, sparse=sparse) - image = M(v) - if self._subdivisions is not None: - image.subdivide(*self.subdivisions()) - return image - def _derivative(self, var=None, R=None): """ Differentiate with respect to var by differentiating each element diff --git a/src/sage/matrix/matrix_integer_dense.pyx b/src/sage/matrix/matrix_integer_dense.pyx index 0cc61a967b7..7cac5119db8 100644 --- a/src/sage/matrix/matrix_integer_dense.pyx +++ b/src/sage/matrix/matrix_integer_dense.pyx @@ -2817,7 +2817,7 @@ cdef class Matrix_integer_dense(matrix_dense.Matrix_dense): # dense or sparse Traceback (most recent call last): ... TypeError: delta must be <= 1 - sage: L = X.LLL(delta=1) + sage: L = X.LLL(delta=1) # not tested, will eat lots of ram Traceback (most recent call last): ... RuntimeError: infinite loop in LLL diff --git a/src/sage/misc/all.py b/src/sage/misc/all.py index 05cc3da8031..08b0234dc8d 100644 --- a/src/sage/misc/all.py +++ b/src/sage/misc/all.py @@ -79,7 +79,6 @@ from func_persist import func_persist from functional import (additive_order, - sqrt as numerical_sqrt, base_ring, base_field, basis, @@ -96,13 +95,10 @@ discriminant, disc, eta, - exp, - factor, fcp, gen, gens, hecke_operator, - ideal, image, integral, integrate, integral_closure, @@ -116,6 +112,7 @@ kernel, krull_dimension, lift, + log as log_b, minimal_polynomial, minpoly, multiplicative_order, @@ -138,9 +135,7 @@ squarefree_part, symbolic_sum as sum, transpose, - zero, - log as log_b, - parent) + zero) from latex import LatexExpr, latex, view, pretty_print, pretty_print_default @@ -165,6 +160,8 @@ from unknown import Unknown +lazy_import('sage.misc.inline_fortran', 'fortran') + ########################################################################## def benchmark(n=-1): """ diff --git a/src/sage/misc/dev_tools.py b/src/sage/misc/dev_tools.py index 18cdde8cadf..0d2e33ef23c 100644 --- a/src/sage/misc/dev_tools.py +++ b/src/sage/misc/dev_tools.py @@ -156,10 +156,9 @@ def load_submodules(module=None, exclude_pattern=None): EXAMPLES:: sage: sage.misc.dev_tools.load_submodules(sage.combinat) - load sage.combinat.cluster_algebra_quiver.cluster_seed... suceeded - load sage.combinat.cluster_algebra_quiver.mutation_class... suceeded + load sage.combinat.algebraic_combinatorics... succeeded ... - load sage.combinat.words.suffix_trees... suceeded + load sage.combinat.words.suffix_trees... succeeded Calling a second time has no effect (since the function does not import modules already imported):: @@ -169,15 +168,15 @@ def load_submodules(module=None, exclude_pattern=None): The second argument allows to exclude a pattern:: sage: sage.misc.dev_tools.load_submodules(sage.geometry, "database$|lattice") - load sage.geometry.fan_isomorphism... suceeded - load sage.geometry.hyperplane_arrangement.affine_subspace... suceeded + load sage.geometry.fan_isomorphism... succeeded + load sage.geometry.hyperplane_arrangement.affine_subspace... succeeded ... - load sage.geometry.riemannian_manifolds.surface3d_generators... suceeded + load sage.geometry.riemannian_manifolds.surface3d_generators... succeeded sage: sage.misc.dev_tools.load_submodules(sage.geometry) - load sage.geometry.polyhedron.lattice_euclidean_group_element... suceeded - load sage.geometry.polyhedron.palp_database... suceeded - load sage.geometry.polyhedron.ppl_lattice_polygon... suceeded + load sage.geometry.polyhedron.lattice_euclidean_group_element... succeeded + load sage.geometry.polyhedron.palp_database... succeeded + load sage.geometry.polyhedron.ppl_lattice_polygon... succeeded """ import sys import pkgutil @@ -207,7 +206,7 @@ def load_submodules(module=None, exclude_pattern=None): sys.stdout.flush() loader = importer.find_module(module_name) loader.load_module(module_name) - sys.stdout.write(" suceeded\n") + sys.stdout.write(" succeeded\n") except (ValueError,AttributeError,TypeError,ImportError): # we might get error because of cython code that has been # compiled but with source removed @@ -349,7 +348,8 @@ def find_object_modules(obj): return module_to_obj -def import_statements(*objects, **options): + +def import_statements(*objects, **kwds): r""" Print import statements for the given objects. @@ -453,11 +453,11 @@ def import_statements(*objects, **options): sage: import_statements('EnumeratedSetFromIterator') Traceback (most recent call last): ... - ValueError: no object matched by 'EnumeratedSetFromIterator' was found. + LookupError: no object named 'EnumeratedSetFromIterator' sage: from sage.misc.dev_tools import load_submodules sage: load_submodules(sage.sets) - load sage.sets.cartesian_product... suceeded - load sage.sets.set_from_iterator... suceeded + load sage.sets.cartesian_product... succeeded + load sage.sets.set_from_iterator... succeeded sage: import_statements('EnumeratedSetFromIterator') from sage.sets.set_from_iterator import EnumeratedSetFromIterator @@ -466,7 +466,7 @@ def import_statements(*objects, **options): sage: import_statements('my_tailor_is_rich') Traceback (most recent call last): ... - ValueError: no object matched by 'my_tailor_is_rich' was found. + LookupError: no object named 'my_tailor_is_rich' sage: import_statements(5) Traceback (most recent call last): ... @@ -479,6 +479,17 @@ def import_statements(*objects, **options): sage: import_statements('NN') from sage.rings.semirings.non_negative_integer_semiring import NN + Deprecated lazy imports are ignored (see :trac:`17458`):: + + sage: lazy_import('sage.all', 'RR', 'deprecated_RR', namespace=sage.__dict__, deprecation=17458) + sage: import_statements('deprecated_RR') + Traceback (most recent call last): + ... + LookupError: object named 'deprecated_RR' is deprecated (see trac ticket 17458) + sage: lazy_import('sage.all', 'RR', namespace=sage.__dict__, deprecation=17458) + sage: import_statements('RR') + from sage.rings.real_mpfr import RR + The following were fixed with :trac:`15351`:: sage: import_statements('Rationals') @@ -510,12 +521,12 @@ def import_statements(*objects, **options): # where "nameX" is an object in "module" that has to be # imported with the alias "aliasX" - lazy = options.pop("lazy", False) - verbose = options.pop("verbose", True) - answer_as_str = options.pop("answer_as_str",False) + lazy = kwds.pop("lazy", False) + verbose = kwds.pop("verbose", True) + answer_as_str = kwds.pop("answer_as_str", False) - if options: - raise ValueError("Unexpected '%s' argument"%options.keys()[0]) + if kwds: + raise TypeError("Unexpected '%s' argument"%kwds.keys()[0]) for obj in objects: name = None # the name of the object @@ -526,17 +537,21 @@ def import_statements(*objects, **options): obj = find_objects_from_name(name, 'sage') if len(obj) == 0: obj = find_objects_from_name(name) - if len(obj) == 0: - raise ValueError("no object matched by '%s' was found."%name) # remove lazy imported objects from list obj i = 0 + deprecation = None while i < len(obj): if isinstance(obj[i], LazyImport): - tmp = obj[i]._get_object() - del obj[i] - if all(u is not tmp for u in obj): - obj.append(tmp) + tmp = obj.pop(i) + # Ignore deprecated lazy imports + tmp_deprecation = tmp._get_deprecation_ticket() + if tmp_deprecation: + deprecation = tmp_deprecation + else: + tmp = tmp._get_object() + if all(u is not tmp for u in obj): + obj.append(tmp) else: i += 1 @@ -550,8 +565,13 @@ def import_statements(*objects, **options): # choose a random object among the potentially enormous list of # objects we get from "name" - obj = obj[0] - + try: + obj = obj[0] + except IndexError: + if deprecation: + raise LookupError("object named %r is deprecated (see trac ticket %s)"%(name, deprecation)) + else: + raise LookupError("no object named %r"%name) # 1'. if obj is a LazyImport we recover the real object if isinstance(obj, LazyImport): diff --git a/src/sage/misc/functional.py b/src/sage/misc/functional.py index a497908626b..dc87c66a937 100644 --- a/src/sage/misc/functional.py +++ b/src/sage/misc/functional.py @@ -15,19 +15,13 @@ #***************************************************************************** # Copyright (C) 2004 William Stein # -# Distributed under the terms of the GNU General Public License (GPL) -# -# This code is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# The full text of the GPL is available at: -# +# 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 sage.misc.latex import sage.interfaces.expect import sage.interfaces.mathematica @@ -138,25 +132,6 @@ def category(x): import sage.categories.all return sage.categories.all.Objects() -def ceil(x): - """ - Returns the ceiling (least integer) function of x. - - EXAMPLES:: - - sage: ceil(3.5) - 4 - sage: ceil(7/2) - 4 - sage: ceil(-3.5) - -3 - sage: ceil(RIF(1.3,2.3)) - 3.? - """ - try: - return x.ceil() - except AttributeError: - return sage.rings.all.ceil(x) def characteristic_polynomial(x, var='x'): """ @@ -216,61 +191,6 @@ def coerce(P, x): except AttributeError: return P(x) - -def acos(x): - """ - Returns the arc cosine of x. - - EXAMPLES:: - - sage: acos(.5) - 1.04719755119660 - sage: acos(sin(pi/3)) - arccos(1/2*sqrt(3)) - sage: acos(sin(pi/3)).simplify_full() - 1/6*pi - """ - try: return x.acos() - except AttributeError: return RDF(x).acos() - -def asin(x): - """ - Returns the arc sine of x. - - EXAMPLES:: - - sage: asin(.5) - 0.523598775598299 - sage: asin(sin(pi/3)) - arcsin(1/2*sqrt(3)) - sage: asin(sin(pi/3)).simplify_full() - 1/3*pi - """ - try: return x.asin() - except AttributeError: return RDF(x).asin() - -def atan(x): - """ - Returns the arc tangent of x. - - EXAMPLES:: - - sage: z = atan(3);z - arctan(3) - sage: n(z) - 1.24904577239825 - sage: atan(tan(pi/4)) - 1/4*pi - """ - try: return x.atan() - except AttributeError: return RDF(x).atan() - -## def cuspidal_submodule(x): -## return x.cuspidal_submodule() - -## def cuspidal_subspace(x): -## return x.cuspidal_subspace() - def cyclotomic_polynomial(n, var='x'): """ Returns the `n^{th}` cyclotomic polynomial. @@ -376,13 +296,6 @@ def discriminant(x): disc = discriminant -# This is dangerous since it gets the scoping all wrong ?? -#import __builtin__ -#def eval(x): -# try: -# return x._eval_() -# except AttributeError: -# return __builtin__.eval(x) def eta(x): r""" @@ -403,52 +316,6 @@ def eta(x): try: return x.eta() except AttributeError: return CDF(x).eta() -def exp(x): - """ - Returns the value of the exponentiation function at x. - - EXAMPLES:: - - sage: exp(3) - e^3 - sage: exp(0) - 1 - sage: exp(2.5) - 12.1824939607035 - sage: exp(pi*i) - -1 - """ - try: return x.exp() - except AttributeError: return RDF(x).exp() - -def factor(x, *args, **kwds): - """ - Returns the (prime) factorization of x. - - EXAMPLES:: - - sage: factor(factorial(10)) - 2^8 * 3^4 * 5^2 * 7 - sage: n = next_prime(10^6); n - 1000003 - sage: factor(n) - 1000003 - - Note that this depends on the type of x:: - - sage: factor(55) - 5 * 11 - sage: factor(x^2+2*x+1) - (x + 1)^2 - sage: factor(55*x^2+110*x+55) - 55*(x + 1)^2 - - """ - try: return x.factor(*args, **kwds) - except AttributeError: return sage.rings.all.factor(x, *args, **kwds) - -factorization = factor -factorisation = factor def fcp(x, var='x'): """ @@ -462,13 +329,8 @@ def fcp(x, var='x'): x * (x^2 - 15*x - 18) """ try: return x.fcp(var) - except AttributeError: return factor(charpoly(x, var)) + except AttributeError: return charpoly(x, var).factor() -## def floor(x): -## try: -## return x.floor() -## except AttributeError: -## return sage.rings.all.floor(x) def gen(x): """ @@ -517,7 +379,6 @@ def hecke_operator(x,n): """ return x.hecke_operator(n) -ideal = sage.rings.ideal.Ideal def image(x): """ @@ -910,24 +771,6 @@ def is_field(x): """ return x.is_field() -def is_noetherian(x): - """ - Returns whether or not x is a Noetherian - object (has ascending chain condition). - - EXAMPLES:: - - sage: from sage.misc.functional import is_noetherian - sage: is_noetherian(ZZ) - True - sage: is_noetherian(QQ) - True - sage: A = SteenrodAlgebra(3) - sage: is_noetherian(A) - False - """ - - return x.is_noetherian() def is_odd(x): """ @@ -947,18 +790,6 @@ def is_odd(x): """ return not is_even(x) -## def j_invariant(x): -## """ -## Return the j_invariant of x. - -## EXAMPLES: -## sage: E = EllipticCurve([0, -1, 1, -10, -20]) -## sage: E -## Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field -## sage: j_invariant(E) -## -122023936/161051 -## """ -## return x.j_invariant() def kernel(x): """ @@ -1119,11 +950,6 @@ def multiplicative_order(x): """ return x.multiplicative_order() -## def new_submodule(x): -## return x.new_submodule() - -## def new_subspace(x): -## return x.new_subspace() def ngens(x): """ @@ -1500,12 +1326,18 @@ def one(R): EXAMPLES:: + sage: one(RR) + doctest:...: DeprecationWarning: one(R) is deprecated, use R.one() or R(1) instead + See http://trac.sagemath.org/17158 for details. + 1.00000000000000 sage: R. = PolynomialRing(QQ) sage: one(R)*x == x True sage: one(R) in R True """ + from sage.misc.superseded import deprecation + deprecation(17158, 'one(R) is deprecated, use R.one() or R(1) instead') return R(1) def order(x): @@ -1699,32 +1531,7 @@ def _do_show(x): return sage.misc.latex.latex(x) from latex import view view(x, mode='display') - #raise AttributeError, "object %s does not support show."%(x, ) - -def sqrt(x): - """ - Returns a square root of x. - - This function (``numerical_sqrt``) is deprecated. Use ``sqrt(x, - prec=n)`` instead. - EXAMPLES:: - - sage: numerical_sqrt(10.1) - doctest:...: DeprecationWarning: numerical_sqrt is deprecated, use sqrt(x, prec=n) instead - See http://trac.sagemath.org/5404 for details. - 3.17804971641414 - sage: numerical_sqrt(9) - 3 - """ - from sage.misc.superseded import deprecation - deprecation(5404, "numerical_sqrt is deprecated, use sqrt(x, prec=n) instead") - try: return x.sqrt() - except (AttributeError, ValueError): - try: - return RDF(x).sqrt() - except TypeError: - return CDF(x).sqrt() def isqrt(x): """ @@ -1782,6 +1589,8 @@ def squarefree_part(x): return x.squarefree_part() except AttributeError: pass + from sage.rings.arith import factor + from sage.structure.all import parent F = factor(x) n = parent(x)(1) for p, e in F: @@ -1789,20 +1598,6 @@ def squarefree_part(x): n *= p return n * F.unit() -## def square_root(x): -## """ -## Return a square root of x with the same parent as x, if possible, -## otherwise raise a ValueError. -## EXAMPLES: -## sage: square_root(9) -## 3 -## sage: square_root(100) -## 10 -## """ -## try: -## return x.square_root() -## except AttributeError: -## raise NotImplementedError def transpose(x): """ @@ -1819,15 +1614,6 @@ def transpose(x): """ return x.transpose() -## def vector(x, R): -## r""" -## Return the \sage vector over $R$ obtained from x, if possible. -## """ -## try: -## return x._vector_(R) -## except AttributeError: -## import sage.modules.free_module_element -## return sage.modules.free_module_element.Vector(x, R) def zero(R): """ @@ -1835,33 +1621,16 @@ def zero(R): EXAMPLES:: + sage: zero(RR) + doctest:...: DeprecationWarning: zero(R) is deprecated, use R.zero() or R(0) instead + See http://trac.sagemath.org/17158 for details. + 0.000000000000000 sage: R. = PolynomialRing(QQ) sage: zero(R) in R True sage: zero(R)*x == zero(R) True """ + from sage.misc.superseded import deprecation + deprecation(17158, 'zero(R) is deprecated, use R.zero() or R(0) instead') return R(0) - - - -################################################################# -# Generic parent -################################################################# -def parent(x): - """ - Returns x.parent() if defined, or type(x) if not. - - EXAMPLE:: - - sage: Z = parent(int(5)) - sage: Z(17) - 17 - sage: Z - - """ - try: - return x.parent() - except AttributeError: - return type(x) - diff --git a/src/sage/misc/inline_fortran.py b/src/sage/misc/inline_fortran.py index 82850528944..edcd92b78c5 100644 --- a/src/sage/misc/inline_fortran.py +++ b/src/sage/misc/inline_fortran.py @@ -1,15 +1,17 @@ """ Fortran compiler """ -import __builtin__ -import os +import os, imp, shutil from sage.misc.temporary_file import tmp_dir class InlineFortran: - def __init__(self,globals): - self.globals=globals + def __init__(self, globals=None): + if globals is None: + self.globs = {} + else: + self.globs = globals # Deprecated self.library_paths=[] self.libraries=[] self.verbose = False @@ -22,15 +24,45 @@ def __call__(self, *args, **kwds): def eval(self, x, globals=None, locals=None): """ + Compile fortran code ``x`` and adds the functions in it to + ``globals``. + + INPUT: + + - ``x`` -- Fortran code + + - ``globals`` -- a dict to which to add the functions from the + fortran module + + - ``locals`` -- ignored + EXAMPLES:: - sage: from sage.misc.inline_fortran import InlineFortran, _example - sage: fortran = InlineFortran(globals()) - sage: fortran(_example) + sage: code = ''' + ....: C FILE: FIB1.F + ....: SUBROUTINE FIB(A,N) + ....: C + ....: C CALCULATE FIRST N FIBONACCI NUMBERS + ....: C + ....: INTEGER N + ....: REAL*8 A(N) + ....: DO I=1,N + ....: IF (I.EQ.1) THEN + ....: A(I) = 0.0D0 + ....: ELSEIF (I.EQ.2) THEN + ....: A(I) = 1.0D0 + ....: ELSE + ....: A(I) = A(I-1) + A(I-2) + ....: ENDIF + ....: ENDDO + ....: END + ....: C END FILE FIB1.F + ....: ''' + sage: fortran(code, globals()) sage: import numpy - sage: n = numpy.array(range(10),dtype=float) - sage: fib(n,int(10)) - sage: n + sage: a = numpy.array(range(10), dtype=float) + sage: fib(a, 10) + sage: a array([ 0., 1., 1., 2., 3., 5., 8., 13., 21., 34.]) TESTS:: @@ -44,11 +76,16 @@ def eval(self, x, globals=None, locals=None): True """ if len(x.splitlines()) == 1 and os.path.exists(x): + from sage.misc.superseded import deprecation + deprecation(2891, "Calling fortran() with a filename is deprecated, use fortran(open(f).read) instead") filename = x x = open(x).read() if filename.lower().endswith('.f90'): x = '!f90\n' + x + if globals is None: + globals = self.globs + from numpy import f2py # Create everything in a temporary directory @@ -58,9 +95,6 @@ def eval(self, x, globals=None, locals=None): old_cwd = os.getcwd() os.chdir(mytmpdir) - old_import_path = os.sys.path - os.sys.path.append(mytmpdir) - name = "fortran_module" # Python module name # if the first line has !f90 as a comment, gfortran will # treat it as Fortran 90 code @@ -84,28 +118,22 @@ def eval(self, x, globals=None, locals=None): f2py.compile(x, name, extra_args = extra_args, source_fn=fortran_file) log_string = open(log).read() - # f2py.compile() doesn't raise any exception if it fails. - # So we manually check whether the compiled file exists. - # NOTE: the .so extension is used expect on Cygwin, - # that is even on OS X where .dylib might be expected. - soname = name - uname = os.uname()[0].lower() - if uname[:6] == "cygwin": - soname += '.dll' - else: - soname += '.so' - if not os.path.isfile(soname): + # Note that f2py() doesn't raise an exception if it fails. + # In that case, the import below will fail. + try: + file, pathname, description = imp.find_module(name, [mytmpdir]) + except ImportError: raise RuntimeError("failed to compile Fortran code:\n" + log_string) + try: + m = imp.load_module(name, file, pathname, description) + finally: + file.close() if self.verbose: print(log_string) - - m = __builtin__.__import__(name) finally: - os.sys.path = old_import_path os.chdir(old_cwd) try: - import shutil shutil.rmtree(mytmpdir) except OSError: # This can fail for example over NFS @@ -113,7 +141,7 @@ def eval(self, x, globals=None, locals=None): for k, x in m.__dict__.iteritems(): if k[0] != '_': - self.globals[k] = x + globals[k] = x def add_library(self,s): self.libraries.append(s) @@ -121,24 +149,5 @@ def add_library(self,s): def add_library_path(self,s): self.library_paths.append(s) - -_example = """ -C FILE: FIB1.F - SUBROUTINE FIB(A,N) -C -C CALCULATE FIRST N FIBONACCI NUMBERS -C - INTEGER N - REAL*8 A(N) - DO I=1,N - IF (I.EQ.1) THEN - A(I) = 0.0D0 - ELSEIF (I.EQ.2) THEN - A(I) = 1.0D0 - ELSE - A(I) = A(I-1) + A(I-2) - ENDIF - ENDDO - END -C END FILE FIB1.F -""" +# An instance +fortran = InlineFortran() diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index 3dafe3962cf..62f7abf5542 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -272,6 +272,31 @@ cdef class LazyImport(object): break return self._object + def _get_deprecation_ticket(self): + """ + Return the ticket number of the deprecation, or 0 if this lazy + import is not deprecated. + + EXAMPLES:: + + sage: from sage.misc.lazy_import import LazyImport + sage: H = LazyImport('sage.categories.homsets', 'Homsets') + sage: H._get_deprecation_ticket() + 0 + sage: H = LazyImport('sage.categories.homsets', 'Homsets', deprecation=10668) + sage: H._get_deprecation_ticket() + 10668 + sage: H = LazyImport('sage.categories.homsets', 'Homsets', deprecation=(10668, "this is deprecated")) + sage: H._get_deprecation_ticket() + 10668 + """ + if self._deprecation is None: + return 0 + try: + return self._deprecation[0] + except TypeError: + return self._deprecation + def _sage_doc_(self): """ Return the docstring of the wrapped object for introspection. diff --git a/src/sage/misc/sage_input.py b/src/sage/misc/sage_input.py index b34cf97e18c..d36f7eac315 100644 --- a/src/sage/misc/sage_input.py +++ b/src/sage/misc/sage_input.py @@ -444,7 +444,7 @@ def __call__(self, x, coerced=False): # However, we don't want to assume that hashing x is always # efficient, so we only try the lookup if some value of the same # type as x has been cached. - from sage.misc.functional import parent + from sage.structure.all import parent if type(x) in self._cached_types: v = self._cache.get((parent(x), x)) @@ -655,7 +655,7 @@ def cache(self, x, sie, name): GF_101 = GF(101) GF_101(42) + GF_101(43) """ - from sage.misc.functional import parent + from sage.structure.all import parent self._cached_types.add(type(x)) self._cache[(parent(x), x)] = sie diff --git a/src/sage/modular/abvar/homspace.py b/src/sage/modular/abvar/homspace.py index a601e50777f..30d8644acb7 100644 --- a/src/sage/modular/abvar/homspace.py +++ b/src/sage/modular/abvar/homspace.py @@ -174,7 +174,7 @@ from copy import copy from sage.categories.homset import HomsetWithBase, End -from sage.misc.functional import parent +from sage.structure.all import parent from sage.misc.lazy_attribute import lazy_attribute import abvar as abelian_variety diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index b5491f8b02c..db178aece4c 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -1170,44 +1170,6 @@ cdef class FreeModuleElement(element_Vector): # abstract base class """ return vector([e.n(prec, digits, algorithm) for e in self]) - def transpose(self): - r""" - Return self as a column matrix. - - .. note:: - - The ``transpose()`` method has been deprecated as of Sage 4.6.2, - in favor of the :meth:`column` method which is functionally identical. - - EXAMPLES:: - - sage: v = vector(ZZ, [2, 12, 22]) - sage: transpose(vector(v)) - doctest:...: DeprecationWarning: The transpose() method for vectors has been deprecated, use column() instead - (or check to see if you have a vector when you really want a matrix) - See http://trac.sagemath.org/10541 for details. - [ 2] - [12] - [22] - - :: - - sage: transpose(vector(GF(7), v)) - [2] - [5] - [1] - - :: - - sage: transpose(vector(v, ZZ['x', 'y'])) - [ 2] - [12] - [22] - """ - from sage.misc.superseded import deprecation - deprecation(10541, 'The transpose() method for vectors has been deprecated, use column() instead\n(or check to see if you have a vector when you really want a matrix)') - return self._matrix_().transpose() - def row(self): r""" Return a matrix with a single row and the same entries as the vector ``self``. @@ -2595,25 +2557,6 @@ cdef class FreeModuleElement(element_Vector): # abstract base class return (~self[i]) * self return self - def normalize(self): - """ - This function is deprecated. For division by the p-norm use - 'normalized', and for division by the first nonzero entry use - 'monic' (previously the purpose of this function). - - EXAMPLES:: - - sage: v = vector(QQ, [0, 4/3, 5, 1, 2]) - sage: v.normalize() - doctest:...: DeprecationWarning: 'normalize' is deprecated... - (0, 1, 15/4, 3/4, 3/2) - """ - from sage.misc.superseded import deprecation - deprecation(13393, "'normalize' is deprecated. For division by the \ -p-norm use 'normalized', and for division by the first nonzero entry use \ -'monic'.") - return self.monic() - def normalized(self, p=sage.rings.integer.Integer(2)): """ Return the input vector divided by the p-norm. diff --git a/src/sage/monoids/string_monoid_element.py b/src/sage/monoids/string_monoid_element.py index f0734da2348..a390eb483c1 100644 --- a/src/sage/monoids/string_monoid_element.py +++ b/src/sage/monoids/string_monoid_element.py @@ -24,8 +24,6 @@ # import operator from sage.rings.integer import Integer from sage.rings.all import RealField -# from sage.structure.element import MonoidElement -from sage.probability.random_variable import DiscreteProbabilitySpace from free_monoid_element import FreeMonoidElement import string_monoid @@ -511,4 +509,5 @@ def frequency_distribution(self, length=1, prec=0): X[c] = eps # Return a dictionary of probability distribution. This should # allow for easier parsing of the dictionary. + from sage.probability.random_variable import DiscreteProbabilitySpace return DiscreteProbabilitySpace(Alph, X, RR) diff --git a/src/sage/monoids/string_ops.py b/src/sage/monoids/string_ops.py index 7c24f14911c..cab8e9b10ce 100644 --- a/src/sage/monoids/string_ops.py +++ b/src/sage/monoids/string_ops.py @@ -7,7 +7,6 @@ #***************************************************************************** from sage.rings.all import RealField -from sage.probability.random_variable import DiscreteProbabilitySpace from string_monoid_element import StringMonoidElement def strip_encoding(S): @@ -47,6 +46,7 @@ def frequency_distribution(S, n=1, field=None): P[c] += eps else: P[c] = eps + from sage.probability.random_variable import DiscreteProbabilitySpace return DiscreteProbabilitySpace(S,P,field) raise TypeError("Argument S (= %s) must be a string, list, or tuple.") diff --git a/src/sage/plot/plot3d/base.pyx b/src/sage/plot/plot3d/base.pyx index d1ff9d142fb..335bb435fe2 100644 --- a/src/sage/plot/plot3d/base.pyx +++ b/src/sage/plot/plot3d/base.pyx @@ -34,7 +34,6 @@ from cpython.list cimport * import os from functools import reduce -from math import atan2 from random import randint import zipfile from cStringIO import StringIO @@ -45,9 +44,7 @@ from sage.env import SAGE_LOCAL from sage.modules.free_module_element import vector from sage.rings.real_double import RDF -from sage.misc.functional import sqrt, atan, acos from sage.misc.temporary_file import tmp_filename, graphics_filename - from texture import Texture, is_Texture from transform cimport Transformation, point_c, face_c include "point_c.pxi" diff --git a/src/sage/plot/plot3d/transform.pyx b/src/sage/plot/plot3d/transform.pyx index e79a52a4180..e4f11db18a5 100644 --- a/src/sage/plot/plot3d/transform.pyx +++ b/src/sage/plot/plot3d/transform.pyx @@ -7,17 +7,12 @@ # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** -cdef extern from *: - double sin(double) - double cos(double) - double sqrt(double) -#from math import atan2, sin, cos, atan, sqrt, acos +from libc.math cimport sin, cos, sqrt include "point_c.pxi" from sage.rings.real_double import RDF -# from sage.misc.functional import sqrt, atan, acos from sage.matrix.constructor import matrix from sage.modules.free_module_element import vector @@ -25,7 +20,6 @@ from sage.modules.free_module_element import vector pi = RDF.pi() - cdef class Transformation: def __init__(self, scale=(1,1,1), rot=None, diff --git a/src/sage/probability/random_variable.py b/src/sage/probability/random_variable.py index ff81388cd55..68d84e634a9 100644 --- a/src/sage/probability/random_variable.py +++ b/src/sage/probability/random_variable.py @@ -16,7 +16,8 @@ #***************************************************************************** from sage.structure.parent_base import ParentWithBase -from sage.misc.functional import sqrt, log +from sage.misc.functional import log +from sage.functions.all import sqrt from sage.rings.real_mpfr import (RealField, is_RealField) from sage.rings.rational_field import is_RationalField from sage.sets.set import Set @@ -364,4 +365,3 @@ def neg_xlog2x(p): return -p*log(p,2) p = self.function() return sum([ neg_xlog2x(p[x]) for x in p.keys() ]) - diff --git a/src/sage/quadratic_forms/quadratic_form.py b/src/sage/quadratic_forms/quadratic_form.py index 4e3b1545556..f50558421f0 100644 --- a/src/sage/quadratic_forms/quadratic_form.py +++ b/src/sage/quadratic_forms/quadratic_form.py @@ -30,9 +30,10 @@ from sage.matrix.matrix import is_Matrix from sage.rings.integer_ring import IntegerRing, ZZ from sage.rings.ring import Ring -from sage.misc.functional import ideal, denominator, is_even, is_field +from sage.misc.functional import denominator, is_even, is_field from sage.rings.arith import GCD, LCM from sage.rings.principal_ideal_domain import is_PrincipalIdealDomain +from sage.rings.all import Ideal from sage.rings.ring import is_Ring from sage.matrix.matrix import is_Matrix from sage.structure.sage_object import SageObject @@ -1440,7 +1441,7 @@ def level(self): else: inv_denoms += [denominator(mat_inv[i,j])] lvl = LCM(inv_denoms) - lvl = ideal(self.base_ring()(lvl)).gen() + lvl = Ideal(self.base_ring()(lvl)).gen() ############################################################## ## To do this properly, the level should be the inverse of the ## fractional ideal (over R) generated by the entries whose @@ -1492,7 +1493,7 @@ def level_ideal(self): ## denominators we take above. =) ############################################################## - return ideal(self.base_ring()(self.level())) + return Ideal(self.base_ring()(self.level())) def bilinear_map(self,v,w): r""" diff --git a/src/sage/quadratic_forms/quadratic_form__local_normal_form.py b/src/sage/quadratic_forms/quadratic_form__local_normal_form.py index e6a19751f11..acf5b88c7da 100644 --- a/src/sage/quadratic_forms/quadratic_form__local_normal_form.py +++ b/src/sage/quadratic_forms/quadratic_form__local_normal_form.py @@ -25,10 +25,6 @@ from sage.rings.arith import GCD, valuation, is_prime -#from sage.misc.functional import ideal ## TODO: This can probably be removed! - - - def find_entry_with_minimal_scale_at_prime(self, p): """ Finds the entry of the quadratic form with minimal scale at the diff --git a/src/sage/quivers/path_semigroup.py b/src/sage/quivers/path_semigroup.py index 3ee98ee9a78..10a67a4431e 100644 --- a/src/sage/quivers/path_semigroup.py +++ b/src/sage/quivers/path_semigroup.py @@ -880,7 +880,7 @@ def all_paths(self, start=None, end=None): An example with multiple edges:: - sage: Q = DiGraph([[1,2,'abc'], [1,2,'def']]) + sage: Q = DiGraph([[1,2,'abc'], [1,2,'def']], multiedges=True) sage: PQ = Q.path_semigroup() sage: PQ.all_paths(1,2) [abc, def] diff --git a/src/sage/repl/interpreter.py b/src/sage/repl/interpreter.py index ec7c9feb826..028a0e31d2b 100644 --- a/src/sage/repl/interpreter.py +++ b/src/sage/repl/interpreter.py @@ -68,16 +68,34 @@ that shell. The bulk of this functionality is provided through :class:`InterfaceShellTransformer`. +TESTS: + +Check that Cython source code appears in tracebacks:: + + sage: from sage.repl.interpreter import get_test_shell + sage: get_test_shell().run_cell('1/0') + --------------------------------------------------------------------------- + .../sage/rings/integer_ring.pyx in sage.rings.integer_ring.IntegerRing_class._div (build/cythonized/sage/rings/integer_ring.c:...)() + ... cdef rational.Rational x = PY_NEW(rational.Rational) + ... if mpz_sgn(right.value) == 0: + ... raise ZeroDivisionError('Rational division by zero') + ... mpz_set(mpq_numref(x.value), left.value) + ... mpz_set(mpq_denref(x.value), right.value) + + ZeroDivisionError: Rational division by zero """ #***************************************************************************** # Copyright (C) 2004-2012 William Stein # -# Distributed under the terms of the GNU General Public License (GPL) -# +# 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 copy import os import re diff --git a/src/sage/rings/all.py b/src/sage/rings/all.py index 9da2e4543e0..35aa1951026 100644 --- a/src/sage/rings/all.py +++ b/src/sage/rings/all.py @@ -40,6 +40,7 @@ # Ideals from ideal import Ideal +ideal = Ideal # Quotient from quotient_ring import QuotientRing diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index 8ebd4ae7f8d..bff871f3cd6 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -4312,7 +4312,26 @@ cdef class Integer_to_IntegerMod(IntegerMod_hom): return IntegerMod_to_Integer(self._codomain) cdef class IntegerMod_to_Integer(Map): + """ + Map to lift elements to :class:`~sage.rings.integer.Integer`. + + EXAMPLES:: + + sage: ZZ.convert_map_from(GF(2)) + Lifting map: + From: Finite Field of size 2 + To: Integer Ring + """ def __init__(self, R): + """ + TESTS: + + Lifting maps are morphisms in the category of sets (see + :trac:`15618`):: + + sage: ZZ.convert_map_from(GF(2)).parent() + Set of Morphisms from Finite Field of size 2 to Integer Ring in Category of sets + """ import sage.categories.homset from sage.categories.all import Sets Morphism.__init__(self, sage.categories.homset.Hom(R, integer_ring.ZZ, Sets())) diff --git a/src/sage/rings/finite_rings/integer_mod_ring.py b/src/sage/rings/finite_rings/integer_mod_ring.py index 61e3d57abfc..a209edf24c1 100644 --- a/src/sage/rings/finite_rings/integer_mod_ring.py +++ b/src/sage/rings/finite_rings/integer_mod_ring.py @@ -661,6 +661,19 @@ def is_integral_domain(self, proof = True): """ return self.order().is_prime() + def is_unique_factorization_domain(self, proof=None): + """ + Return ``True`` if and only if the order of ``self`` is prime. + + EXAMPLES:: + + sage: Integers(389).is_unique_factorization_domain() + True + sage: Integers(389^2).is_unique_factorization_domain() + False + """ + return self.is_field(proof) + @cached_method def is_field(self, proof=None): r""" diff --git a/src/sage/rings/integer_ring.pyx b/src/sage/rings/integer_ring.pyx index 6426420afc9..bc455ab50ba 100644 --- a/src/sage/rings/integer_ring.pyx +++ b/src/sage/rings/integer_ring.pyx @@ -442,7 +442,7 @@ cdef class IntegerRing_class(PrincipalIdealDomain): """ cdef rational.Rational x = PY_NEW(rational.Rational) if mpz_sgn(right.value) == 0: - raise ZeroDivisionError, 'Rational division by zero' + raise ZeroDivisionError('Rational division by zero') mpz_set(mpq_numref(x.value), left.value) mpz_set(mpq_denref(x.value), right.value) mpq_canonicalize(x.value) diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index fa8368b647c..6202794c358 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -7373,9 +7373,10 @@ def embeddings(self, K): if K.characteristic() != 0: return Sequence([], immutable=True, check=False, universe=self.Hom(K)) - f = K['x'](self.defining_polynomial()) - r = f.roots(); r.sort() - v = [self.hom([e[0]], check=False) for e in r] + f = self.defining_polynomial() + r = f.roots(K, multiplicities=False) + r.sort() + v = [self.hom([e], check=False) for e in r] # If there is an embedding that preserves variable names # then it is most natural, so we put it first. put_natural_embedding_first(v) @@ -10117,6 +10118,24 @@ def refine_embedding(e, prec=None): From: Cyclotomic Field of order 7 and degree 6 To: Algebraic Field Defn: zeta7 |--> 0.6234898018587335? + 0.7818314824680299?*I + + When the old embedding is into the real lazy field, + then only real embeddings should be considered. + See :trac:`17495`:: + + sage: R. = QQ[] + sage: K. = NumberField(x^3 + x - 1, embedding=0.68) + sage: from sage.rings.number_field.number_field import refine_embedding + sage: refine_embedding(K.specified_complex_embedding(), 100) + Ring morphism: + From: Number Field in a with defining polynomial x^3 + x - 1 + To: Real Field with 100 bits of precision + Defn: a |--> 0.68232780382801932736948373971 + sage: refine_embedding(K.specified_complex_embedding(), Infinity) + Ring morphism: + From: Number Field in a with defining polynomial x^3 + x - 1 + To: Algebraic Real Field + Defn: a |--> 0.6823278038280193? """ K = e.domain() RC = e.codomain() @@ -10135,7 +10154,7 @@ def refine_embedding(e, prec=None): return e # We first compute all the embeddings at the new precision: - if sage.rings.real_mpfr.is_RealField(RC) or RC is RDF: + if sage.rings.real_mpfr.is_RealField(RC) or RC in (RDF, RLF): if prec == Infinity: elist = K.embeddings(sage.rings.qqbar.AA) else: diff --git a/src/sage/rings/number_field/order.py b/src/sage/rings/number_field/order.py index 43d2e252ab0..f9e58262a94 100644 --- a/src/sage/rings/number_field/order.py +++ b/src/sage/rings/number_field/order.py @@ -683,14 +683,14 @@ def ambient(self): """ return self._K - def residue_field(self, prime, name = None, check = False): + def residue_field(self, prime, names=None, check=False): """ Return the residue field of this order at a given prime, ie `O/pO`. INPUT: - ``prime`` -- a prime ideal of the maximal order in this number field. - - ``name`` -- the name of the variable in the residue field + - ``names`` -- the name of the variable in the residue field - ``check`` -- whether or not to check the primality of prime. OUTPUT: @@ -705,11 +705,15 @@ def residue_field(self, prime, name = None, check = False): sage: OK = K.maximal_order() sage: OK.residue_field(P) Residue field in abar of Fractional ideal (61, a^2 + 30) + sage: Fp. = OK.residue_field(P) + sage: Fp + Residue field in b of Fractional ideal (61, a^2 + 30) """ if self.is_maximal(): - return self.number_field().residue_field(prime, name, check) - else: - raise NotImplementedError("Residue fields of non-maximal orders are not yet supported.") + return self.number_field().residue_field(prime, names, check) + + raise NotImplementedError("Residue fields of non-maximal orders " + "are not yet supported.") def fraction_field(self): """ diff --git a/src/sage/rings/polynomial/convolution.py b/src/sage/rings/polynomial/convolution.py index 38d771d18e6..5c4dd61515a 100644 --- a/src/sage/rings/polynomial/convolution.py +++ b/src/sage/rings/polynomial/convolution.py @@ -50,7 +50,7 @@ #***************************************************************************** -from sage.misc.functional import parent +from sage.structure.all import parent from math import log, ceil diff --git a/src/sage/rings/polynomial/multi_polynomial_ideal.py b/src/sage/rings/polynomial/multi_polynomial_ideal.py index 1eb062b1a15..23dd3bdaf36 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ideal.py +++ b/src/sage/rings/polynomial/multi_polynomial_ideal.py @@ -2361,6 +2361,16 @@ def quotient(self, J): True sage: x * (y*z + x) in I True + + TEST: + + This example checks :trac:`16301`:: + + sage: R. = ZZ[] + sage: I = Ideal(R(2), x*y, x*z + x) + sage: eD = Ideal(x, z^2-1) + sage: I.quotient(eD).gens() + [2, x*z + x, x*y] """ R = self.ring() diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index c3b473e152c..636b52511b8 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -2103,7 +2103,7 @@ cdef class MPolynomial_libsingular(sage.rings.polynomial.multi_polynomial.MPolyn y += c*mul([ x[i]**m[i] for i in m.nonzero_positions()]) return y - cdef poly *res + cdef poly *res # ownership will be transferred to us in the next line singular_polynomial_call(&res, self._poly, _ring, coerced_x, MPolynomial_libsingular_get_element) res_parent = get_coercion_model().common_parent(parent._base, *x) @@ -2111,8 +2111,10 @@ cdef class MPolynomial_libsingular(sage.rings.polynomial.multi_polynomial.MPolyn return res_parent(0) if p_LmIsConstant(res, _ring): sage_res = si2sa( p_GetCoeff(res, _ring), _ring, parent._base ) + p_Delete(&res, _ring) # sage_res contains copy else: - sage_res = new_MP(parent, res) + sage_res = new_MP(parent, res) # pass on ownership of res to sage_res + if parent(sage_res) is not res_parent: sage_res = res_parent(sage_res) return sage_res diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index bbf7bf17359..3560dd95ce1 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -238,7 +238,10 @@ class of the quotient ring and its newly created elements. sage: P. = QQ[] sage: Q = P.quotient(x^2+2) sage: Q.category() - Join of Category of commutative algebras over Rational Field and Category of subquotients of monoids and Category of quotients of semigroups + Join of Category of integral domains + and Category of commutative algebras over Rational Field + and Category of subquotients of monoids + and Category of quotients of semigroups The test suite passes:: @@ -292,7 +295,7 @@ class of the category, and store the current class of the quotient """ Element = PolynomialQuotientRingElement - def __init__(self, ring, polynomial, name=None): + def __init__(self, ring, polynomial, name=None, category=None): """ TEST:: @@ -314,7 +317,8 @@ def __init__(self, ring, polynomial, name=None): self.__ring = ring self.__polynomial = polynomial - sage.rings.commutative_ring.CommutativeRing.__init__(self, ring, names=name, category=CommutativeAlgebras(ring.base_ring()).Quotients()) + category = CommutativeAlgebras(ring.base_ring()).Quotients().or_subcategory(category) + sage.rings.commutative_ring.CommutativeRing.__init__(self, ring, names=name, category=category) def __reduce__(self): """ @@ -1415,8 +1419,23 @@ class PolynomialQuotientRing_domain(PolynomialQuotientRing_generic, sage.rings.i sage: loads(xbar.dumps()) == xbar True """ - def __init__(self, ring, polynomial, name=None): - PolynomialQuotientRing_generic.__init__(self, ring, polynomial, name) + def __init__(self, ring, polynomial, name=None, category=None): + r""" + Initialize ``self``. + + TESTS:: + + sage: R. = PolynomialRing(ZZ) + sage: S. = R.quotient(x^2 + 1) + sage: TestSuite(S).run() + + Check that :trac:`17450` is fixed:: + + sage: S in IntegralDomains() + True + """ + category = CommutativeAlgebras(ring.base_ring()).Quotients().NoZeroDivisors().or_subcategory(category) + PolynomialQuotientRing_generic.__init__(self, ring, polynomial, name, category) def __reduce__(self): return PolynomialQuotientRing_domain, (self.polynomial_ring(), diff --git a/src/sage/rings/polynomial/polynomial_ring.py b/src/sage/rings/polynomial/polynomial_ring.py index d6dcafc4f31..b12899972eb 100644 --- a/src/sage/rings/polynomial/polynomial_ring.py +++ b/src/sage/rings/polynomial/polynomial_ring.py @@ -469,6 +469,17 @@ def is_integral_domain(self, proof = True): """ return self.base_ring().is_integral_domain(proof) + def is_unique_factorization_domain(self, proof = True): + """ + EXAMPLES:: + + sage: ZZ['x'].is_unique_factorization_domain() + True + sage: Integers(8)['x'].is_unique_factorization_domain() + False + """ + return self.base_ring().is_unique_factorization_domain(proof) + def is_noetherian(self): return self.base_ring().is_noetherian() diff --git a/src/sage/rings/power_series_ring_element.pyx b/src/sage/rings/power_series_ring_element.pyx index 5975639845b..7cb32a394a0 100644 --- a/src/sage/rings/power_series_ring_element.pyx +++ b/src/sage/rings/power_series_ring_element.pyx @@ -108,8 +108,6 @@ import rational_field, integer_ring from integer import Integer from sage.rings.finite_rings.integer_mod_ring import IntegerModRing from sage.libs.pari.all import pari -from sage.misc.functional import sqrt, log -from sage.rings.arith import integer_ceil as ceil from sage.misc.superseded import deprecated_function_alias from sage.categories.fields import Fields diff --git a/src/sage/rings/rational.pyx b/src/sage/rings/rational.pyx index a387396ab26..8093339bc14 100644 --- a/src/sage/rings/rational.pyx +++ b/src/sage/rings/rational.pyx @@ -3723,12 +3723,19 @@ cdef class Z_to_Q(Morphism): EXAMPLES:: - sage: QQ.coerce_map_from(ZZ).section() + sage: f = QQ.coerce_map_from(ZZ).section(); f Generic map: From: Rational Field To: Integer Ring + + This map is a morphism in the category of sets with partial + maps (see :trac:`15618`):: + + sage: f.parent() + Set of Morphisms from Rational Field to Integer Ring in Category of sets with partial maps """ - return Q_to_Z(self._codomain, self.domain()) + from sage.categories.sets_with_partial_maps import SetsWithPartialMaps + return Q_to_Z(self._codomain.Hom(self.domain(), category=SetsWithPartialMaps())) cdef class Q_to_Z(Map): r""" diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 14c6f809e5a..02d4678a24e 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -3769,7 +3769,7 @@ cdef class RealNumber(sage.structure.element.RingElement): def is_integer(self): """ - Return ``True`` if this number is a integer + Return ``True`` if this number is a integer. EXAMPLES:: @@ -3778,7 +3778,7 @@ cdef class RealNumber(sage.structure.element.RingElement): sage: RR(0.1).is_integer() False """ - return self in ZZ + return mpfr_integer_p(self.value) != 0 def __nonzero__(self): """ @@ -4991,23 +4991,6 @@ cdef class RealNumber(sage.structure.element.RingElement): if (self._parent).__prec > SIG_PREC_THRESHOLD: sig_off() return x - def lngamma(self): - r""" - This method is deprecated, please use :meth:`.log_gamma` instead. - - See the :meth:`.log_gamma` method for documentation and examples. - - EXAMPLES:: - - sage: RR(6).lngamma() - doctest:...: DeprecationWarning: The method lngamma() is deprecated. Use log_gamma() instead. - See http://trac.sagemath.org/6992 for details. - 4.78749174278205 - """ - from sage.misc.superseded import deprecation - deprecation(6992, "The method lngamma() is deprecated. Use log_gamma() instead.") - return self.log_gamma() - def log_gamma(self): """ Return the logarithm of gamma of ``self``. diff --git a/src/sage/rings/semirings/non_negative_integer_semiring.py b/src/sage/rings/semirings/non_negative_integer_semiring.py index 10c26bc5231..55fd0c4046f 100644 --- a/src/sage/rings/semirings/non_negative_integer_semiring.py +++ b/src/sage/rings/semirings/non_negative_integer_semiring.py @@ -45,7 +45,7 @@ class NonNegativeIntegerSemiring(NonNegativeIntegers): This is the Hasse diagram of the divisibility order on ``NN``. - sage: Poset(NN.cayley_graph(elements=range(13), generators=[0,1,2,3,5,7,11])).show() + sage: Poset(NN.cayley_graph(elements=[1..12], generators=[2,3,5,7,11])).show() Note: as for :class:`NonNegativeIntegers `, ``NN`` is diff --git a/src/sage/schemes/generic/divisor.py b/src/sage/schemes/generic/divisor.py index 90bec235a77..6457dcde5a5 100644 --- a/src/sage/schemes/generic/divisor.py +++ b/src/sage/schemes/generic/divisor.py @@ -442,26 +442,3 @@ def coefficient(self, P): except AttributeError: raise NotImplementedError - def coef(self,P): - r""" - Synonym for :meth:`coefficient` - - .. WARNING:: - - This method is deprecated. It will be removed in a future - release of Sage. Please use the ``coefficient(P)`` method - instead. - - EXAMPLES:: - - sage: x,y = AffineSpace(2, GF(5), names='xy').gens() - sage: C = Curve(y^2 - x^9 - x) - sage: pts = C.rational_points(); pts - [(0, 0), (2, 2), (2, 3), (3, 1), (3, 4)] - sage: D = C.divisor(pts[0]) - sage: D.coefficient(pts[0]) - 1 - """ - from sage.misc.superseded import deprecation - deprecation(9337, "This method is deprecated. It will be removed in a future release of Sage. Please use the coefficient() method instead.") - return self.coefficient(P) diff --git a/src/sage/schemes/generic/morphism.py b/src/sage/schemes/generic/morphism.py index 2e5445a26a7..6e478efb7af 100644 --- a/src/sage/schemes/generic/morphism.py +++ b/src/sage/schemes/generic/morphism.py @@ -84,6 +84,7 @@ from sage.categories.homset import Homset, Hom, End from sage.rings.all import Integer from sage.rings.commutative_ring import is_CommutativeRing +from sage.rings.fraction_field_element import FractionFieldElement from sage.rings.morphism import is_RingHomomorphism from point import is_SchemeTopologicalPoint from sage.rings.infinity import infinity @@ -1351,6 +1352,17 @@ def change_ring(self,R, check=True): To: Affine Space of dimension 2 over Rational Field Defn: Defined on coordinates by sending (x : y) to (x^2, y^2) + + :: + + sage: A.=AffineSpace(QQ,2) + sage: H=Hom(A,A) + sage: f=H([3*x^2/y,y^2/x]) + sage: f.change_ring(RR) + Scheme endomorphism of Affine Space of dimension 2 over Real Field with + 53 bits of precision + Defn: Defined on coordinates by sending (x, y) to + (3.00000000000000*x^2/y, y^2/x) """ T=self.domain().change_ring(R) @@ -1360,7 +1372,12 @@ def change_ring(self,R, check=True): S=self.codomain().change_ring(R) H=Hom(T,S) - G=[f.change_ring(R) for f in self._polys] + G = [] + for f in self._polys: + if isinstance(f,FractionFieldElement): + G.append(f.numerator().change_ring(R) / f.denominator().change_ring(R)) + else: + G.append(f.change_ring(R)) return(H(G,check)) diff --git a/src/sage/schemes/projective/projective_morphism.py b/src/sage/schemes/projective/projective_morphism.py index f9b53e8458b..070f9caad02 100644 --- a/src/sage/schemes/projective/projective_morphism.py +++ b/src/sage/schemes/projective/projective_morphism.py @@ -324,11 +324,7 @@ def __eq__(self, right): if self.parent() != right.parent(): return False n = len(self._polys) - for i in range(0, n): - for j in range(i + 1, n): - if self._polys[i] * right._polys[j] != self._polys[j] * right._polys[i]: - return False - return True + return all([self[i]*right[j] == self[j]*right[i] for i in range(0, n) for j in range(i+1, n)]) def __ne__(self, right): """ diff --git a/src/sage/schemes/projective/projective_point.py b/src/sage/schemes/projective/projective_point.py index 4c54016a6ad..9785f962c16 100644 --- a/src/sage/schemes/projective/projective_point.py +++ b/src/sage/schemes/projective/projective_point.py @@ -165,7 +165,7 @@ def __init__(self, X, v, check=True): def __eq__(self,right): """ - Tests the proejctive equality of two points. + Tests the projective equality of two points. INPUT: @@ -243,24 +243,31 @@ def __eq__(self,right): sage: P==Q True + Check that :trac:`17429` is fixed:: + + sage: R. = PolynomialRing(QQ) + sage: r = (x^2-x-3).polynomial(x).roots(ComplexIntervalField(),multiplicities = False) + sage: P. = ProjectiveSpace(ComplexIntervalField(), 1) + sage: P1 = P(r[0], 1) + sage: H = End(P) + sage: f = H([x^2-3*y^2, y^2]) + sage: Q1 = f(P1) + sage: Q1 == P1 + False """ if not isinstance(right, SchemeMorphism_point): try: right = self.codomain()(right) except TypeError: return False - if self.codomain()!=right.codomain(): + if self.codomain() != right.codomain(): return False - n=len(self._coords) - for i in range(0,n): - for j in range(i+1,n): - if self._coords[i]*right._coords[j] != self._coords[j]*right._coords[i]: - return False - return True + n = len(self._coords) + return all([self[i]*right[j] == self[j]*right[i] for i in range(0,n) for j in range(i+1, n)]) def __ne__(self,right): """ - Tests the proejctive equality of two points. + Tests the projective equality of two points. INPUT: @@ -1093,30 +1100,38 @@ def clear_denominators(self): EXAMPLES:: - sage: R.=PolynomialRing(QQ) - sage: P.=ProjectiveSpace(FractionField(R),2) - sage: Q=P([t,3/t^2,1]) + sage: R. = PolynomialRing(QQ) + sage: P. = ProjectiveSpace(FractionField(R), 2) + sage: Q = P([t, 3/t^2, 1]) sage: Q.clear_denominators(); Q (t^3 : 3 : t^2) :: - sage: R.=PolynomialRing(QQ) - sage: K.=NumberField(x^2-3) - sage: P.=ProjectiveSpace(K,2) - sage: Q=P([1/w,3,0]) + sage: R. = PolynomialRing(QQ) + sage: K. = NumberField(x^2 - 3) + sage: P. = ProjectiveSpace(K, 2) + sage: Q = P([1/w, 3, 0]) sage: Q.clear_denominators(); Q (w : 9 : 0) :: - sage: P.=ProjectiveSpace(QQ,2) - sage: X=P.subscheme(x^2-y^2); - sage: Q=X([1/2,1/2,1]); + sage: P. = ProjectiveSpace(QQ, 2) + sage: X = P.subscheme(x^2 - y^2); + sage: Q = X([1/2, 1/2, 1]); sage: Q.clear_denominators(); Q (1 : 1 : 2) + + :: + + sage: PS. = ProjectiveSpace(QQ, 1) + sage: Q = PS.point([1, 2/3], False); Q + (1 : 2/3) + sage: Q.clear_denominators(); Q + (3 : 2) """ - self.scale_by(lcm([self[i].denominator() for i in range(self.codomain().ambient_space().dimension_relative())])) + self.scale_by(lcm([t.denominator() for t in self])) class SchemeMorphism_point_projective_finite_field(SchemeMorphism_point_projective_field): diff --git a/src/sage/server/misc.py b/src/sage/server/misc.py deleted file mode 100644 index cb8d5b11414..00000000000 --- a/src/sage/server/misc.py +++ /dev/null @@ -1,150 +0,0 @@ -""" -Miscellaneous Server Functions - -.. WARNING:: - - Parts of this file are duplicated in sagenb/misc/misc.py -""" - -#***************************************************************************** -# Copyright (C) 2006, 2007 William Stein -# -# Distributed under the terms of the GNU General Public License (GPL) -# as published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** - -import socket -from sage.misc.viewer import browser - - -def print_open_msg(address, port, secure=False, path=""): - """ - Print a message on the screen suggesting that the user open their - web browser to a certain URL. - - INPUT: - - - ``address`` -- a string; a computer address or name - - - ``port`` -- an int; a port number - - - ``secure`` -- a bool (default: False); whether to prefix the URL - with 'http' or 'https' - - - ``path`` -- a string; the URL's path following the port. - - EXAMPLES:: - - sage: from sage.server.misc import print_open_msg - sage: print_open_msg('localhost', 8000, True) - **************************************************** - * * - * Open your web browser to https://localhost:8000 * - * * - **************************************************** - sage: print_open_msg('sagemath.org', 8000, False) - ****************************************************** - * * - * Open your web browser to http://sagemath.org:8000 * - * * - ****************************************************** - sage: print_open_msg('sagemath.org', 90, False) - **************************************************** - * * - * Open your web browser to http://sagemath.org:90 * - * * - **************************************************** - sage: print_open_msg('sagemath.org', 80, False) - ************************************************** - * * - * Open your web browser to http://sagemath.org * - * * - ************************************************** - """ - if port == 80: - port = '' - else: - port = ':%s' % port - s = "Open your web browser to http%s://%s%s%s" % ('s' if secure - else '', address, - port, path) - t = len(s) - if t % 2: - t += 1 - s += ' ' - n = max(t + 4, 50) - k = n - t - 1 - j = k/2 - print '*'*n - print '*'+ ' '*(n - 2) + '*' - print '*' + ' '*j + s + ' '*j + '*' - print '*'+ ' '*(n - 2) + '*' - print '*'*n - - -def find_next_available_port(host, start, max_tries=100, verbose=False): - """ - Find the next available port on a given host, that is, a port for - which a current connection attempt returns a 'Connection refused' - error message. If no port is found, raise a RuntimeError exception. - - INPUT: - - - ``host`` - address to check - - - ``start`` - an int; the starting port number for the scan - - - ``max_tries`` - an int (default: 100); how many ports to scan - - - ``verbose`` - a bool (default: True); whether to print information - about the scan - - OUTPUT: - - - an int - the port number - - EXAMPLES:: - - sage: from sage.server.misc import find_next_available_port - sage: find_next_available_port('127.0.0.1', 9000, verbose=False) # random output -- depends on network - 9002 - """ - from sage.misc.misc import alarm, cancel_alarm - alarm_count = 0 - for port in range(start, start+max_tries+1): - try: - alarm(1) - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect((host, port)) - except socket.error as msg: - if msg[1] == 'Connection refused': - if verbose: - print "Using port = %s" % port - return port - except KeyboardInterrupt: - if verbose: - print "alarm" - alarm_count += 1 - if alarm_count >= 10: - break - pass - finally: - cancel_alarm() - if verbose: - print "Port %s is already in use." % port - print "Trying next port..." - raise RuntimeError("no available port.") - - -def open_page(address, port, secure, path=""): - from os import system - if secure: - rsrc = 'https' - else: - rsrc = 'http' - - system('%s %s://%s:%s%s 1>&2 > /dev/null &' % (browser(), - rsrc, address, - port, path)) diff --git a/src/sage/server/nodoctest.py b/src/sage/server/nodoctest.py deleted file mode 100644 index 8b137891791..00000000000 --- a/src/sage/server/nodoctest.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/sage/server/support.py b/src/sage/server/support.py index 5b77ccd6487..1016c1d3e68 100644 --- a/src/sage/server/support.py +++ b/src/sage/server/support.py @@ -6,414 +6,29 @@ - William Stein (much of this code is from IPython). - Nick Alexander -""" - -import os -import string -from cPickle import PicklingError -import sage.structure.sage_object -import sage.misc.latex -import sage.misc.pager +TESTS: -import sage.misc.sageinspect as sageinspect +Test deprecation:: -from sage.repl.preparse import preparse + sage: from sage.server.support import syseval + sage: syseval(gap, "2+3") # long time + doctest:...: DeprecationWarning: + Importing syseval from here is deprecated. If you need to use it, please import it directly from sagenb.misc.support + See http://trac.sagemath.org/2891 for details. + '5' +""" -###################################################################### -# Initialization -###################################################################### EMBEDDED_MODE = False -sage_globals = None -globals_at_init = None -global_names_at_init = None - -def init(object_directory=None, globs={}): - r""" - Initialize Sage for use with the web notebook interface. - """ - global sage_globals, globals_at_init, global_names_at_init - global EMBEDDED_MODE - - os.environ['PAGER'] = 'cat' - - sage_globals = globs - #globals_at_init = set(globs.keys()) - globals_at_init = globs.values() - global_names_at_init = set(globs.keys()) - EMBEDDED_MODE = True - - import sage.plot.plot - sage.plot.plot.EMBEDDED_MODE = True - if object_directory: - sage.structure.sage_object.base=object_directory - sage.misc.latex.EMBEDDED_MODE = True - sage.misc.pager.EMBEDDED_MODE = True - sage.misc.sageinspect.EMBEDDED_MODE = True - - setup_systems(globs) - sage.misc.session.init(globs) - - -def setup_systems(globs): - from sage.misc.inline_fortran import InlineFortran - fortran = InlineFortran(globs) - globs['fortran'] = fortran - - -###################################################################### -# Introspection -###################################################################### -def help(obj): - """ - Display HTML help for ``obj``, a Python object, module, etc. This - help is often more extensive than that given by 'obj?'. This - function does not return a value --- it prints HTML as a side - effect. - - .. note:: - - This a wrapper around the built-in help. If formats the output - as HTML without word wrap, which looks better in the notebook. - - INPUT: - - - ``obj`` - a Python object, module, etc. - TESTS:: +from sage.misc.lazy_import import lazy_import +lazy_import('sagenb.misc.support', + ('sage_globals', 'globals_at_init', + 'global_names_at_init', 'init', 'setup_systems', 'help', + 'get_rightmost_identifier', 'completions', 'docstring', + 'source_code', 'syseval'), + deprecation=2891) - sage: import numpy.linalg - sage: import os, sage.misc.misc ; current_dir = os.getcwd() - sage: os.chdir(sage.misc.misc.tmp_dir('server_doctest')) - sage: sage.server.support.help(numpy.linalg.norm) -
-    Click to open help window    -
- sage: os.chdir(current_dir) - """ - from pydoc import resolve, html, describe - - print '
' - object, name = resolve(obj) - page = html.page(describe(object), html.document(object, name)) - page = page.replace('Click to open help window   "%filename - print '
' - -def get_rightmost_identifier(s): - X = string.ascii_letters + string.digits + '._' - i = len(s)-1 - while i >= 0 and s[i] in X: - i -= 1 - return s[i+1:] - -def completions(s, globs, format=False, width=90, system="None"): - """ - Return a list of completions in the given context. - - INPUT: - - - ``globs`` - a string:object dictionary; context in which to - search for completions, e.g., :func:`globals()` - - - ``format`` - a bool (default: False); whether to tabulate the - list - - - ``width`` - an int; character width of the table - - - ``system`` - a string (default: 'None'); system prefix for the - completions - """ - if system not in ['sage', 'python']: - prepend = system + '.' - s = prepend + s - else: - prepend = '' - n = len(s) - if n == 0: - return '(empty string)' - try: - if not '.' in s and not '(' in s: - v = [x for x in globs.keys() if x[:n] == s] + \ - [x for x in __builtins__.keys() if x[:n] == s] - else: - if not ')' in s: - i = s.rfind('.') - method = s[i+1:] - obj = s[:i] - n = len(method) - else: - obj = preparse(s) - method = '' - try: - O = eval(obj, globs) - D = dir(O) - try: - D += O.trait_names() - except (AttributeError, TypeError): - pass - if method == '': - v = [obj + '.'+x for x in D if x and x[0] != '_'] - else: - v = [obj + '.'+x for x in D if x[:n] == method] - except Exception as msg: - v = [] - v = sorted(set(v)) # make unique - except Exception as msg: - v = [] - - if prepend: - i = len(prepend) - v = [x[i:] for x in v] - - if format: - if len(v) == 0: - return "No completions of '%s' currently defined"%s - else: - return tabulate(v, width) - return v - -def docstring(obj_name, globs, system='sage'): - r""" - Format an object's docstring to process and display in the Sage - notebook. - - INPUT: - - - ``obj_name`` - a string; a name of an object - - - ``globs`` - a string:object dictionary; a context in which to - evaluate ``obj_name`` - - - ``system`` - a string (default: 'sage'); the system to which to - confine the search - - OUTPUT: - - - a string containing the object's file, type, definition, and - docstring or a message stating the object is not defined - - AUTHORS: - - - William Stein: partly taken from IPython for use in Sage - - - Nick Alexander: extensions - """ - if system not in ['sage', 'python']: - obj_name = system + '.' + obj_name - try: - obj = eval(obj_name, globs) - except (AttributeError, NameError, SyntaxError): - return "No object '%s' currently defined."%obj_name - s = '' - newline = "\n\n" # blank line to start new paragraph - try: - filename = sageinspect.sage_getfile(obj) - #i = filename.find('site-packages/sage/') - #if i == -1: - s += '**File:** %s'%filename - s += newline - #else: - # file = filename[i+len('site-packages/sage/'):] - # s += 'File:
%s\n'%(file,file) - except TypeError: - pass - s += '**Type:** %s'%type(obj) - s += newline - s += '**Definition:** %s'%sageinspect.sage_getdef(obj, obj_name) - s += newline - s += '**Docstring:**' - s += newline - s += sageinspect.sage_getdoc(obj, obj_name) - return s.rstrip() - -def source_code(s, globs, system='sage'): - r""" - Format an object's source code to process and display in the - Sage notebook. - - INPUT: - - - ``s`` - a string; a name of an object - - - ``globs`` - a string:object dictionary; a context in which to - evaluate ``s`` - - - ``system`` - a string (default: 'sage'); the system to which to - confine the search - - OUTPUT: - - - a string containing the object's file, starting line number, and - source code - - AUTHORS: - - - William Stein: partly taken from IPython for use in Sage - - - Nick Alexander: extensions - """ - if system not in ['sage', 'python']: - s = system + '.' + s - - try: - obj = eval(s, globs) - except NameError: - return "No object %s"%s - - try: - try: - return obj._sage_src_() - except Exception: - pass - newline = "\n\n" # blank line to start new paragraph - indent = " " # indent source code to mark it as a code block - - filename = sageinspect.sage_getfile(obj) - lines, lineno = sageinspect.sage_getsourcelines(obj, is_binary=False) - src = indent.join(lines) - from sage.misc.sagedoc import format_src - src = indent + format_src(src) - if not lineno is None: - output = "**File:** %s"%filename - output += newline - output += "**Source Code** (starting at line %s)::"%lineno - output += newline - output += src - return output - - except (TypeError, IndexError) as msg: - print msg - return "Source code for %s not available."%obj - -def tabulate(v, width=90, ncols=3): - e = len(v) - if e == 0: - return '' - while True: - col_widths = [] - nrows = e//ncols + 1 - for c in range(ncols): - m = max([0] + [len(v[r+c*nrows]) for r in range(nrows) if r+c*nrows < e]) - col_widths.append(m+3) - if ncols > 1 and max(col_widths + [0]) > width//ncols: - ncols -= 1 - else: - break - n = max(len(x) for x in v) - s = '' - for r in range(nrows): - for c in range(ncols): - i = r + c*nrows - if i < e: - w = v[i] - s += w + ' '*(col_widths[c] - len(w)) - s += '\n' - return s - -def save_session(filename): - D = {} - v = variables(with_types=False) - for k in v: - x = sage_globals[k] - try: - _ = sage.structure.sage_object.loads(sage.structure.sage_object.dumps(x)) - except (IOError, TypeError, PicklingError): - if k != 'fortran': # this is a hack to get around the inline fortran object being - # *incredibly* hackish in how it is implemented; the right - # fix is to rewrite the fortran inline to *not* be so incredibly - # hackish. See trac #2891. - print "Unable to save %s"%k - else: - D[k] = x - print "Saving variables to object %s.sobj"%filename - sage.structure.sage_object.save(D, filename) - -def load_session(v, filename, state): - D = {} - for k, x in v.iteritems(): - try: - _ = sage.structure.sage_object.loads(sage.structure.sage_object.dumps(x)) - except (IOError, TypeError): - print "Unable to save %s"%k - else: - D[k] = x - print "Saving variables to %s"%filename - sage.structure.sage_object.save(D, filename) - -def _is_new_var(x, v): - if x[:2] == '__': - return False - if not x in global_names_at_init: - return True - - # You might think this would take a long time - # since globals_at_init has several thousand entries. - # However, it takes 0.0 seconds, which is not noticeable - # given that there is at least 0.1 seconds delay - # when refreshing the web page! - for y in globals_at_init: - if v is y: - return False - return True - -def variables(with_types=True): - if with_types: - w = ['%s-%s'%(x,type(v)) for x, v in sage_globals.iteritems() if \ - _is_new_var(x, v)] - else: - w = [x for x, v in sage_globals.iteritems() if \ - _is_new_var(x, v)] - w.sort() - return tuple(w) - - - -def syseval(system, cmd, dir=None): - """ - Evaluate an input with a "system" object that can evaluate inputs - (e.g., python, gap). - - INPUT: - - - ``system`` - an object with an eval method that takes an input - - - ``cmd`` - a string input - - - ``sage_globals`` - a string:object dictionary - - - dir - a string (default: None); an optional directory to change - to before calling :func:`system.eval` - - OUTPUT: - - - :func:`system.eval`'s output - - EXAMPLES:: - - sage: from sage.misc.python import python - sage: sage.server.support.syseval(python, '2+4/3') - 3 - '' - sage: sage.server.support.syseval(python, 'import os; os.chdir(".")') - '' - sage: sage.server.support.syseval(python, 'import os; os.chdir(1,2,3)') - Traceback (most recent call last): - ... - TypeError: chdir() takes exactly 1 argument (3 given) - sage: sage.server.support.syseval(gap, "2+3") - '5' - """ - if dir: - if hasattr(system.__class__, 'chdir'): - system.chdir(dir) - return system.eval(cmd, sage_globals, locals = sage_globals) ###################################################################### # Cython diff --git a/src/sage/structure/all.py b/src/sage/structure/all.py index 834e61436ac..08e550cb45a 100644 --- a/src/sage/structure/all.py +++ b/src/sage/structure/all.py @@ -6,10 +6,11 @@ from sage_object import SageObject -from element import (\ +from element import ( canonical_coercion, get_coercion_model, - coercion_traceback + coercion_traceback, + parent ) from parent import Parent diff --git a/src/sage/structure/coerce_maps.pyx b/src/sage/structure/coerce_maps.pyx index 0e2f424f54d..8239bc53884 100644 --- a/src/sage/structure/coerce_maps.pyx +++ b/src/sage/structure/coerce_maps.pyx @@ -22,9 +22,24 @@ cdef class DefaultConvertMap(Map): passing in the codomain as the first argument. """ def __init__(self, domain, codomain, force_use=False): + """ + TESTS: + + Maps of this type are morphisms in the category of sets with + partial maps (see :trac:`15618`):: + + sage: f = GF(11).convert_map_from(GF(7)); f + Conversion map: + From: Finite Field of size 7 + To: Finite Field of size 11 + sage: f.parent() + Set of Morphisms from Finite Field of size 7 to Finite Field of size 11 in Category of sets with partial maps + """ if not PY_TYPE_CHECK(domain, Parent): domain = Set_PythonType(domain) - Map.__init__(self, domain, codomain) + from sage.categories.sets_with_partial_maps import SetsWithPartialMaps + parent = domain.Hom(codomain, category=SetsWithPartialMaps()) + Map.__init__(self, parent) self._coerce_cost = 100 self._force_use = force_use if (codomain)._element_constructor is None: diff --git a/src/sage/structure/sage_object.pyx b/src/sage/structure/sage_object.pyx index 0d078cde804..c58a53d1596 100644 --- a/src/sage/structure/sage_object.pyx +++ b/src/sage/structure/sage_object.pyx @@ -849,13 +849,15 @@ def have_same_parent(self, other): ################################################################## def load(*filename, compress=True, verbose=True): - """ + r""" Load Sage object from the file with name filename, which will have - an .sobj extension added if it doesn't have one. Or, if the input - is a filename ending in .py, .pyx, or .sage, load that file into - the current running session. Loaded files are not loaded into - their own namespace, i.e., this is much more like Python's - ``execfile`` than Python's ``import``. + an ``.sobj`` extension added if it doesn't have one. Or, if the input + is a filename ending in ``.py``, ``.pyx``, or ``.sage``, load that + file into the current running session. If the filename ends in + ``.f`` or ``.f90``, it is compiled as Fortran code and loaded. + + Loaded files are not loaded into their own namespace, i.e., this is + much more like Python's ``execfile`` than Python's ``import``. .. NOTE:: @@ -889,17 +891,27 @@ def load(*filename, compress=True, verbose=True): We test loading a file or multiple files or even mixing loading files and objects:: - sage: t=tmp_filename()+'.py'; open(t,'w').write("print 'hello world'") + sage: t = tmp_filename(ext='.py') + sage: open(t,'w').write("print 'hello world'") sage: load(t) hello world sage: load(t,t) hello world hello world - sage: t2=tmp_filename(); save(2/3,t2) + sage: t2 = tmp_filename(); save(2/3,t2) sage: load(t,t,t2) hello world hello world [None, None, 2/3] + + We can load Fortran files:: + + sage: code = ' subroutine hello\n print *, "Hello World!"\n end subroutine hello\n' + sage: t = tmp_filename(ext=".F") + sage: open(t, 'w').write(code) + sage: load(t) + sage: hello + """ import sage.repl.load if len(filename) != 1: @@ -923,7 +935,9 @@ def load(*filename, compress=True, verbose=True): filename = get_remote_file(filename, verbose=verbose) tmpfile_flag = True elif lower.endswith('.f') or lower.endswith('.f90'): - globals()['fortran'](filename) + from sage.misc.inline_fortran import fortran + with open(filename) as f: + fortran(f.read(), globals()) return else: tmpfile_flag = False diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index d914707f7dd..93430ca97bf 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -7430,23 +7430,6 @@ cdef class Expression(CommutativeRingElement): sig_off() return new_Expression_from_GEx(self._parent, x) - def lgamma(self, hold=False): - """ - This method is deprecated, please use the ``.log_gamma()`` function instead. - - Log gamma function evaluated at self. - - EXAMPLES:: - - sage: x.lgamma() - doctest:...: DeprecationWarning: The lgamma() function is deprecated. Use log_gamma() instead. - See http://trac.sagemath.org/6992 for details. - log_gamma(x) - """ - from sage.misc.superseded import deprecation - deprecation(6992, "The lgamma() function is deprecated. Use log_gamma() instead.") - return self.log_gamma(hold=hold) - def log_gamma(self, hold=False): """ Return the log gamma function evaluated at self. @@ -8005,8 +7988,10 @@ cdef class Expression(CommutativeRingElement): .. seealso:: :meth:`simplify_full`, :meth:`simplify_trig`, - :meth:`simplify_rational`, :meth:`simplify_factorial`, - :meth:`simplify_log`, :meth:`canonicalize_radical` + :meth:`simplify_rational`, :meth:`simplify_rectform` + :meth:`simplify_factorial`, :meth:`simplify_log`, + :meth:`simplify_real`, :meth:`simplify_hypergeometric`, + :meth:`canonicalize_radical` EXAMPLES:: @@ -8081,6 +8066,7 @@ cdef class Expression(CommutativeRingElement): sage: f = (1/2)*log(2*t) + (1/2)*log(1/t) sage: f.simplify_full() 1/2*log(2*t) - 1/2*log(t) + sage: forget() """ x = self @@ -8234,6 +8220,107 @@ cdef class Expression(CommutativeRingElement): return self + + def simplify_real(self): + r""" + Simplify the given expression over the real numbers. This allows + the simplification of `\sqrt{x^{2}}` into `\left|x\right|`. + + INPUT: + + - ``self`` -- the expression to convert. + + OUTPUT: + + A new expression, equivalent to the original one under the + assumption that the variables involved are real. + + EXAMPLES:: + + sage: f = sqrt(x^2) + sage: f.simplify_real() + abs(x) + + TESTS: + + We set the Maxima ``domain`` variable to 'real' before we call + out to Maxima. When we return, however, we should set the + ``domain`` back to what it was, rather than assuming that it + was 'complex':: + + sage: from sage.calculus.calculus import maxima + sage: maxima('domain: real;') + real + sage: x.simplify_real() + x + sage: maxima('domain;') + real + sage: maxima('domain: complex;') + complex + + We forget the assumptions that our variables are real after + simplification; make sure we don't forget an assumption that + existed before we were called:: + + sage: assume(x, 'real') + sage: x.simplify_real() + x + sage: assumptions() + [x is real] + sage: forget() + + We also want to be sure that we don't forget assumptions on + other variables:: + + sage: x,y,z = SR.var('x,y,z') + sage: assume(y, 'integer') + sage: assume(z, 'antisymmetric') + sage: x.simplify_real() + x + sage: assumptions() + [y is integer, z is antisymmetric] + sage: forget() + + No new assumptions should exist after the call:: + + sage: assumptions() + [] + sage: x.simplify_real() + x + sage: assumptions() + [] + + """ + from sage.symbolic.assumptions import assume, assumptions, forget + from sage.calculus.calculus import maxima + original_domain = maxima.eval('domain') + original_assumptions = assumptions() + + maxima.eval('domain: real$') + + # We might as well go all the way and tell Maxima to assume + # that all variables are real. Since we're setting the + # simplification domain (and it's indiscriminate), you'd + # better not call this unless your variables really are real + # anyway. + for v in self.variables(): + assume(v, 'real'); + + result = self.simplify(); + + # Set the domain back to what it was before we were called. + maxima.eval('domain: %s$' % original_domain) + + # Forget all assumptions, and restore the ones that existed + # when we were called. This is much simpler than the bookkeeping + # necessary otherwise. + forget() + for assumption in original_assumptions: + assume(assumption); + + return result + + def simplify_trig(self,expand=True): r""" Optionally expand and then employ identities such as diff --git a/src/sage/symbolic/expression_conversions.py b/src/sage/symbolic/expression_conversions.py index b089c2388f3..29cac928efc 100644 --- a/src/sage/symbolic/expression_conversions.py +++ b/src/sage/symbolic/expression_conversions.py @@ -507,6 +507,71 @@ def derivative(self, ex, operator): D[0](f)(x*y) sage: m.derivative(t, t.operator()) "at(diff('f(_SAGE_VAR_t0), _SAGE_VAR_t0, 1), [_SAGE_VAR_t0 = (_SAGE_VAR_x)*(_SAGE_VAR_y)])" + + TESTS: + + Most of these confirm that :trac:`7401` was fixed:: + + sage: t = var('t'); f = function('f')(t) + sage: a = 2^e^t * f.subs(t=e^t) * diff(f, t).subs(t=e^t) + 2*t + sage: solve(a == 0, diff(f, t).subs(t=e^t)) + [D[0](f)(e^t) == -2^(-e^t + 1)*t/f(e^t)] + + :: + + sage: f = function('f', x) + sage: df = f.diff(x); df + D[0](f)(x) + sage: maxima(df) + 'diff('f(_SAGE_VAR_x),_SAGE_VAR_x,1) + + :: + + sage: a = df.subs(x=exp(x)); a + D[0](f)(e^x) + sage: b = maxima(a); b + %at('diff('f(_SAGE_VAR_t0),_SAGE_VAR_t0,1),[_SAGE_VAR_t0=%e^_SAGE_VAR_x]) + sage: bool(b.sage() == a) + True + + :: + + sage: a = df.subs(x=4); a + D[0](f)(4) + sage: b = maxima(a); b + %at('diff('f(_SAGE_VAR_t0),_SAGE_VAR_t0,1),[_SAGE_VAR_t0=4]) + sage: bool(b.sage() == a) + True + + It also works with more than one variable. Note the preferred + syntax ``function('f')(x, y)`` to create a general symbolic + function of more than one variable:: + + sage: x, y = var('x y') + sage: f = function('f')(x, y) + sage: f_x = f.diff(x); f_x + D[0](f)(x, y) + sage: maxima(f_x) + 'diff('f(_SAGE_VAR_x,_SAGE_VAR_y),_SAGE_VAR_x,1) + + :: + + sage: a = f_x.subs(x=4); a + D[0](f)(4, y) + sage: b = maxima(a); b + %at('diff('f(_SAGE_VAR_t0,_SAGE_VAR_t1),_SAGE_VAR_t0,1),[_SAGE_VAR_t0=4,_SAGE_VAR_t1=_SAGE_VAR_y]) + sage: bool(b.sage() == a) + True + + :: + + sage: a = f_x.subs(x=4).subs(y=8); a + D[0](f)(4, 8) + sage: b = maxima(a); b + %at('diff('f(_SAGE_VAR_t0,_SAGE_VAR_t1),_SAGE_VAR_t0,1),[_SAGE_VAR_t0=4,_SAGE_VAR_t1=8]) + sage: bool(b.sage() == a) + True + """ #This code should probably be moved into the interface #object in a nice way. diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx index 70cd1c5d40a..53616f7098b 100644 --- a/src/sage/symbolic/function.pyx +++ b/src/sage/symbolic/function.pyx @@ -15,6 +15,7 @@ Classes for symbolic functions from ginac cimport * +from sage.rings.integer cimport smallInteger from sage.structure.sage_object cimport SageObject from expression cimport new_Expression_from_GEx, Expression from ring import SR @@ -809,6 +810,46 @@ cdef class GinacFunction(BuiltinFunction): BuiltinFunction.__init__(self, name, nargs, latex_name, conversions, evalf_params_first=evalf_params_first) + def __call__(self, *args, **kwds): + """ + Wrapper around ``BuiltinFunction.__call__()`` which converts + Python ``int``s which are returned by Ginac to Sage Integers. + + This is needed to fix :trac:`10133`, where Ginac evaluates + ``sin(0)`` to the Python int ``0``:: + + sage: from sage.symbolic.function import BuiltinFunction + sage: out = BuiltinFunction.__call__(sin, 0) + sage: out, parent(out) + (0, ) + + With this wrapper we have:: + + sage: out = sin(0) + sage: out, parent(out) + (0, Integer Ring) + + However, if all inputs are Python types, we do not convert:: + + sage: out = sin(int(0)) + sage: (out, parent(out)) + (0, ) + sage: out = arctan2(int(0), float(1)) + sage: (out, parent(out)) + (0, ) + sage: out = arctan2(int(0), RR(1)) + sage: (out, parent(out)) + (0, Integer Ring) + """ + res = super(GinacFunction, self).__call__(*args, **kwds) + + # Convert to Integer if the output was of type "int" and any of + # the inputs was a Sage Element + if isinstance(res, int) and any(isinstance(x, Element) for x in args): + return smallInteger(res) + else: + return res + cdef _is_registered(self): # Since this is function is defined in C++, it is already in # ginac's function registry diff --git a/src/sage/symbolic/relation.py b/src/sage/symbolic/relation.py index 4c7e7ada9c3..007ce114f38 100644 --- a/src/sage/symbolic/relation.py +++ b/src/sage/symbolic/relation.py @@ -393,6 +393,60 @@ def test_relation_maxima(relation): sage: test_relation_maxima(x!=1) False sage: forget() + + TESTS: + + Ensure that ``canonicalize_radical()`` and ``simplify_log`` are not + used inappropriately, :trac:`17389`. Either one would simplify ``f`` + to zero below:: + + sage: x,y = SR.var('x,y') + sage: assume(y, 'complex') + sage: f = log(x*y) - (log(x) + log(y)) + sage: f(x=-1, y=i) + -2*I*pi + sage: test_relation_maxima(f == 0) + False + sage: forget() + + Ensure that the ``sqrt(x^2)`` -> ``abs(x)`` simplification is not + performed when testing equality:: + + sage: assume(x, 'complex') + sage: f = sqrt(x^2) - abs(x) + sage: test_relation_maxima(f == 0) + False + sage: forget() + + If assumptions are made, ``simplify_rectform()`` is used:: + + sage: assume(x, 'real') + sage: f1 = ( e^(I*x) - e^(-I*x) ) / ( I*e^(I*x) + I*e^(-I*x) ) + sage: f2 = sin(x)/cos(x) + sage: test_relation_maxima(f1 - f2 == 0) + True + sage: forget() + + But not if ``x`` itself is complex:: + + sage: assume(x, 'complex') + sage: f1 = ( e^(I*x) - e^(-I*x) ) / ( I*e^(I*x) + I*e^(-I*x) ) + sage: f2 = sin(x)/cos(x) + sage: test_relation_maxima(f1 - f2 == 0) + False + sage: forget() + + If assumptions are made, then ``simplify_factorial()`` is used:: + + sage: n,k = SR.var('n,k') + sage: assume(n, 'integer') + sage: assume(k, 'integer') + sage: f1 = factorial(n+1)/factorial(n) + sage: f2 = n + 1 + sage: test_relation_maxima(f1 - f2 == 0) + True + sage: forget() + """ m = relation._maxima_() @@ -432,8 +486,18 @@ def test_relation_maxima(relation): if repr(difference) == '0': return True - #Try to apply some simplifications to see if left - right == 0 - simp_list = [difference.simplify_log, difference.simplify_rational,difference.canonicalize_radical,difference.simplify_trig] + # Try to apply some simplifications to see if left - right == 0. + # + # TODO: If simplify_log() is ever removed from simplify_full(), we + # can replace all of these individual simplifications with a + # single call to simplify_full(). That would work in cases where + # two simplifications are needed consecutively; the current + # approach does not. + # + simp_list = [difference.simplify_factorial(), + difference.simplify_rational(), + difference.simplify_rectform(), + difference.simplify_trig()] for f in simp_list: try: if repr( f() ).strip() == "0": diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index f6272898144..13b9318afce 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -623,6 +623,11 @@ cdef class SymbolicRing(CommutativeRing): Traceback (most recent call last): ... ValueError: The name "x,y" is not a valid Python identifier. + + Check that :trac:`17206` is fixed:: + + sage: var1 = var('var1', latex_name=r'\sigma^2_1'); latex(var1) + {\sigma^2_1} """ if is_Expression(name): return name @@ -645,7 +650,10 @@ cdef class SymbolicRing(CommutativeRing): if len(names_list) == 0: raise ValueError('You need to specify the name of the new variable.') if len(names_list) == 1: - return self.symbol(name, latex_name=latex_name, domain=domain) + formatted_latex_name = None + if latex_name is not None: + formatted_latex_name = '{{{0}}}'.format(latex_name) + return self.symbol(name, latex_name=formatted_latex_name, domain=domain) if len(names_list) > 1: if latex_name: raise ValueError, "cannot specify latex_name for multiple symbol names" diff --git a/src/sage/version.py b/src/sage/version.py index 1fac9fac9f6..3c47b494044 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,4 +1,4 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '6.5.beta2' -date = '2014-12-04' +version = '6.5.beta3' +date = '2014-12-18'