Sage 9.4 Release Tour

current development cycle (2021)

Symbolics

Extended interface with SymPy

The SymPy package has been updated to version 1.8.

SageMath has a bidirectional interface with SymPy. Symbolic expressions in Sage provide a _sympy_ method, which converts to SymPy; also, Sage attaches _sage_ methods to various SymPy classes, which provide the opposite conversion.

In Sage 9.4, several conversions have been added. Now there is a bidirectional interface as well for matrices and vectors. #31942

sage: M = matrix([[sin(x), cos(x)], [-cos(x), sin(x)]]); M
[ sin(x)  cos(x)]
[-cos(x)  sin(x)]
sage: sM = M._sympy_(); sM
Matrix([
[ sin(x), cos(x)],
[-cos(x), sin(x)]])
sage: sM.subs(x, pi/4)           # computation in SymPy
Matrix([
[ sqrt(2)/2, sqrt(2)/2],
[-sqrt(2)/2, sqrt(2)/2]])

Work is underway to make SymPy's symbolic linear algebra methods available in Sage via this route.

Callable symbolic expressions, such as those created using the Sage preparser's f(...) = ... syntax, now convert to a SymPy Lambda. #32130

sage: f(x, y) = x^2 + y^2; f
(x, y) |--> x^2 + y^2
sage: f._sympy_()
Lambda((x, y), x**2 + y**2)

Sage has added a formal set membership function element_of for use in symbolic expressions; it converts to a SymPy's Contains expression. #24171

Moreover, all sets and algebraic structures (Parents) of SageMath are now accessible to SymPy by way of a wrapper class SageSet, which implements the SymPy Set API. #31938

sage: F = Family([2, 3, 5, 7]); F
Family (2, 3, 5, 7)
sage: sF = F._sympy_(); sF
SageSet(Family (2, 3, 5, 7))          # this is how the wrapper prints
sage: sF._sage_() is F
True                                  # bidirectional
sage: bool(sF)
True
sage: len(sF)
4
sage: sF.is_finite_set                # SymPy property
True

Finite or infinite, we can wrap it:

sage: W = WeylGroup(["A",1,1])
sage: sW = W._sympy_(); sW
SageSet(Weyl Group of type ['A', 1, 1] (as a matrix group acting on the root space))
sage: sW.is_finite_set
False
sage: sW.is_iterable
True
sage: sB3 = WeylGroup(["B", 3])._sympy_(); sB3
SageSet(Weyl Group of type ['B', 3] (as a matrix group acting on the ambient space))
sage: len(sB3)
48

Some parents or constructions have a more specific conversion to SymPy. #31931, #32015

sage: ZZ3 = cartesian_product([ZZ, ZZ, ZZ])
sage: sZZ3 = ZZ3._sympy_(); sZZ3
ProductSet(Integers, Integers, Integers)
sage: (1, 2, 3) in sZZ3

sage: NN = NonNegativeIntegers()
sage: NN._sympy_()
Naturals0

sage: (RealSet(1, 2).union(RealSet.closed(3, 4)))._sympy_()
Union(Interval.open(1, 2), Interval(3, 4))

sage: X = Set(QQ).difference(Set(ZZ)); X
Set-theoretic difference of
 Set of elements of Rational Field and
 Set of elements of Integer Ring
sage: X._sympy_()
Complement(Rationals, Integers)

sage: X = Set(ZZ).difference(Set(QQ)); X
Set-theoretic difference of
 Set of elements of Integer Ring and
 Set of elements of Rational Field
sage: X._sympy_()
EmptySet

See Meta-ticket #31926: Connect Sage sets to SymPy sets

ConditionSet

Sage 9.4 introduces a class ConditionSet for subsets of a parent (or another set) consisting of elements that satisfy the logical "and" of finitely many predicates.

The name ConditionSet is borrowed from SymPy. In fact, if the given predicates (condition) are symbolic, a ConditionSet can be converted to a SymPy ConditionSet; the _sympy_ method falls back to creating a SageSet wrapper otherwise.

symbolic_expression(lambda x, y: ...)

Sage 9.4 has added a new way to create callable symbolic expressions. #32103

The global function symbolic_expression now accepts a callable such as those created by lambda expressions. The result is a callable symbolic expression, in which the formal arguments of the callable are the symbolic arguments.

Example:

symbolic_expression(lambda x,y: x^2+y^2) == (SR.var("x")^2 + SR.var("y")^2).function(SR.var("x"), SR.var("y"))

This provides a convenient syntax in particular in connection to ConditionSet.

Instead of

sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12  # preparser syntax, creates globals
sage: ConditionSet(ZZ^3, predicate)

one is now able to write

sage: ConditionSet(ZZ^3, symbolic_expression(lambda x, y, z: 
....:     sqrt(x^2 + y^2 + z^2) < 12))

Convex geometry

ABC for convex sets

Sage 9.4 has added an abstract base class ConvexSet_base (as well as abstract subclasses ConvexSet_closed, ConvexSet_compact, ConvexSet_relatively_open, ConvexSet_open) for convex subsets of finite-dimensional real vector spaces. The abstract methods and default implementations of methods provide a unifying API to the existing classes Polyhedron_base, ConvexRationalPolyhedralCone, LatticePolytope, and PolyhedronFace. #31919, #31959, #31990

As part of the API, there are new methods for point-set topology such as is_open, relative_interior, and closure. For example, taking the relative_interior of a polyhedron constructs an instance of RelativeInterior, a simple object that provides a __contains__ method and all other methods of the ConvexSet_base API. #31916

sage: P = Polyhedron(vertices=[(1,0), (-1,0)])
sage: ri_P = P.relative_interior(); ri_P
Relative interior of
 a 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices
sage: (0, 0) in ri_P
True
sage: (1, 0) in ri_P
False

ConvexSet_base is a subclass of the new abstract base class Set_base. #32013

This makes various methods that were previously only defined for sets constructed using the Set constructor available for polyhedra and other convex sets. As an example, we can now do:

sage: polytopes.cube().union(polytopes.tetrahedron())                                                                                                                                                
Set-theoretic union of 
 Set of elements of A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices and 
 Set of elements of A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices

Polyhedral geometry

Sage 9.4 defines a new subclass of GenericCellComplex for (geometric) polyhedral complexes. #31748

sage: pc = PolyhedralComplex([
....:         Polyhedron(vertices=[(1/3, 1/3), (0, 0), (1/7, 2/7)]),
....:         Polyhedron(vertices=[(1/7, 2/7), (0, 0), (0, 1/4)])])
sage: [p.Vrepresentation() for p in pc.cells_sorted()]
[(A vertex at (0, 0), A vertex at (0, 1/4), A vertex at (1/7, 2/7)),
 (A vertex at (0, 0), A vertex at (1/3, 1/3), A vertex at (1/7, 2/7)),
 (A vertex at (0, 0), A vertex at (0, 1/4)),
 ...
 (A vertex at (1/7, 2/7),),
 (A vertex at (1/3, 1/3),)]
sage: pc.plot()
Graphics object consisting of 10 graphics primitives
sage: pc.is_pure()
True
sage: pc.is_full_dimensional()
True
sage: pc.is_compact()
True
sage: pc.boundary_subcomplex()
Polyhedral complex with 4 maximal cells
sage: pc.is_convex()
True
sage: pc.union_as_polyhedron().Hrepresentation()
(An inequality (1, -4) x + 1 >= 0,
 An inequality (-1, 1) x + 0 >= 0,
 An inequality (1, 0) x + 0 >= 0)
sage: pc.face_poset()
Finite poset containing 11 elements
sage: pc.is_connected()
True
sage: pc.connected_component() == pc
True

Manifolds

Defining submanifolds and manifold subsets by pullbacks from Sage sets

Given a continuous map Φ from a topological or differentiable manifold N and a subset S of the codomain of Φ, we define the pullback (preimage) of S as the subset of N of points p with Φ(p) in S. #31688

Generically, such pullbacks are represented by instances of the new class ManifoldSubsetPullback. But because Φ is continuous, topological closures and interiors pull back accordingly. Hence, in some cases we are able to give the pullback additional structure, such as creating a submanifold rather than merely a manifold subset.

In addition to the case when Φ is a continuous map between manifolds, there are two situations that connect Sage manifolds to sets defined by other components of Sage:

In a similar direction, the new method Polyhedron.affine_hull_manifold makes the affine hull of a polyhedron available as a Riemannian submanifold embedded into the ambient Euclidean space. #31659

Families and posets of manifold subsets

In Sage 9.4, the system for declaring (named) subsets of topological and differentiable manifolds in sage.manifolds has become more general and powerful.

In addition to declare_union and declare_intersection, there are now methods declare_empty, declare_nonempty, declare_subset, declare_superset, and declare_equal.

The declared subset relations define a quasiorder on the named subsets. To visualize the subset relations, methods subset_digraph and superset_digraph are now available.

Through a sequence of subset declarations, or directly through declare_equal, several named subsets (which are distinct as Python objects) can become necessarily equal as mathematical sets. By quotienting out by this equivalence relation, we obtain a partially ordered set, which is available through the new methods subset_poset and superset_poset.

For more information, see Meta-ticket #31740.

Configuration changes

Support for system gcc/g++/gfortran 11 added

Sage can now be built using GCC 11. #31786

This enables building Sage using the default compiler on Fedora 34, and on macOS with homebrew using the default compilers. (Previously, in Sage 9.3, specific older versions of the compilers had to be installed.)

Support for system Python 3.6 dropped

It was already deprecated in Sage 9.3. #30551

It is still possible to build the Sage distribution on systems with old Python versions, but Sage will build its own copy of Python 3.9.x in this case.

Support for optional packages on systems with gcc 4.x dropped

Sage is phasing out its support for building from source using very old compilers from the gcc 4.x series.

As of Sage 9.4, on systems such as ubuntu-trusty (Ubuntu 14.04), debian-jessie (8), linuxmint-17, and centos-7 that only provide gcc from the outdated 4.x series, it is still supported to build Sage from source with the system compilers. However, building optional and experimental packages is no longer supported, and we have removed these configurations from our CI. #31526

Users in scientific computing environments using these platforms should urge their system administrators to upgrade to a newer distribution, or at least to a newer toolchain.

For developers: ./configure --prefix=SAGE_LOCAL --with-sage-venv=SAGE_VENV

Sage 9.4 makes it possible to configure the build to make a distinction between:

Package installation records are kept within each tree, and thus separately. This allows developers to switch between different system Python versions without having to rebuild the whole set of non-Python packages. See #29013 for details.

Package upgrades

For developers and packagers: Refactoring, modernization, and modularization

Using type annotations (PEP 563) in the Sage library

Dropping support for Python 3.6 has allowed us to start using language and library features introduced in Python 3.7. Meta-ticket #29756 tracks such features by Python version.

One notable new feature of Python 3.7 is type annotations for function arguments and return values. Sage 9.4 has started to make use of this feature, in the revised form that PEP 563 provides (from __future__ import annotations). A new section in the developer's manual added in #32067 provides guidance on how to use this feature. See #32058, #32128, #32164 for examples.

New location for distribution package sources: SAGE_ROOT/pkgs

The Sage source tree contains a number of source trees of Python distribution packages. In Sage 9.4, they have been moved to a new central location. #31577

SAGE_ROOT
- pkgs
  - sage-conf
    - setup.py
    - bin/
    - sage_conf.py.in
  - sage-docbuild
    - setup.py
    - sage_docbuild   -> symlinks to SAGE_ROOT/sage_docbuild/
  - sage-sws2rst
    - setup.py
    - bin/
    - sage_sws2rst/
  - sagemath-standard
    - setup.py
    - bin             -> symlinks to SAGE_ROOT/src/bin/        
    - sage            -> symlinks to SAGE_ROOT/src/sage/
    - sage_setup      -> symlinks to SAGE_ROOT/src/sage_setup/

that is, the new directory pkgs will be on the same level as

SAGE_ROOT
- src

the unchanged monolithic sagelib source tree, which will continue to contain subdirectories

  - bin/ 
  - doc/
  - sage/
  - sage_docbuild/      # was sage_setup/docbuild/ in Sage 9.2
  - sage_setup/ 

All files that contain Sage doctests (tested with sage -t or make ptest) remain in the monolithic src/ source tree; the source trees of the distributions symlink there.

Other modularization tickets will add

SAGE_ROOT
- pkgs
  - sagemath-core/
  - sagemath-brial/
  - sagemath-giac/
  - sagemath-meataxe/
  - sagemath-tdlib/

etc.; see Meta-ticket #29705 for more information.

Modern Python packaging metadata for sagemath-standard

./bootstrap now generates modern Python packaging metadata (pyproject.toml and setup.cfg, as well as requirements.txt and Pipfile) for our distribution package sagemath-standard. #30913

The version information for dependencies comes from the existing files build/pkgs/*/install-requires.txt.

Availability of Sage 9.4 and installation help

The first beta of the 9.4 series, 9.4.beta0, was tagged on 2021-05-26. The latest beta is 9.4.beta6, tagged on 2021-07-24.

More details