-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Kind system
Kind system was first introduced in version 1.8 by PR #20549. Its purpose is to separate the mathematical type and Python type
of a SymPy object.
In SymPy, objects with different mathematical types have different Python types. For example, Symbol
class represents arbitrary scalar and Add
represents addition between scalars, while MatrixSymbol
represents arbitrary matrix and MatAdd
represents addition between matrices.
The problem of this approach is that the number of classes grows in square order. Currently, numerous classes (e.g. Integral
, Piecewise
) supports only scalar, and in order to support matrix we need matrix versions of them (e.g. MatIntegral
, MatPiecewise
). And if we want to support another type like tensor, we need to implement new versions of these classes all over again.
This restriction can be alleviated by using kind system. In this new design, mathematical type of an object is distinguished by kind
attribute, instead of its Python class. For example, a numerical object has singleton NumberKind
instance as its kind, and matrix object has MatrixKind
.
In the kind system, the class of an object merely represents its Python implementation. A single Add
class can represent scalar addition and matrix addition depending on the kind
of its arguments, since these two are both algebraic group operations. However, Symbol
and MatrixSymbol
need to be distinguished because the latter needs shape information.
In order to support the evaluation of Add
with different kinds, the evaluation logic must be defined by the kind instance. For example, we need to define methods such as NumberKind._eval_Add()
which treats 0 as identity element, and MatrixKind._eval_Add()
which treats zero matrix as identity element. Add
class should call one of these methods by the kind of its elements.
One major obstacle in this approach is that we cannot use kind-dependent attributes (i.e. MatAdd.shape
) anymore. This can be resolved by defining a shape()
function which returns the shape of any matrix-kind object, and replace the shape
attribute with this function over entire SymPy codebase.
One more important point for kind system is that we need to support the operations between different kinds. Currently, a single MatMul
class deals with matrix-matrix multiplication and scalar-matrix multiplication altogether. (Perhaps this is an design error and we need two separate ScalarMul
and BilinearProduct
classes.) In order to make Mul
do this, we need to define the NumberKind x MatrixKind -> MatrixKind
rule. This can be done by kind dispatching system, which is already supported.
Finally, it must be stressed that Kind
should not be combined with complicated set theory logic. This is to facilitate the determination of the kind of associative operation with very large number of arguments. For example, integer, irrational number and complex number should have just NumberKind
.
Please refer to the mailing list for further discussion on this topic.