What does `S` signify in SymPy?

Question:

I am new to SymPy, and I can’t figure out

from sympy.core import S

What is S actually? And what does S.true mean?

Asked By: Yathartha Joshi

||

Answers:

As many have linked, S is for accessing singletons. Per the source, S is an instance of class SingletonRegistry. S does two things:

  • gives you access to instances such as S.One and S.Zero, which represent fundamental constants
  • lets you create or access singletons representing constants based on their values (e.g., S(1)).

The reason to use a singleton is so that you can compare objects with is rather than ==. is is faster, but only works if you know for sure that your 1 is the same as the 1 you are testing against. The code gives an example:

>>> Basic() is Basic()
False
>>> MySingleton() is MySingleton()
True
 >>> S.MySingleton is MySingleton()
True
Answered By: cxw

There’s a bit of confusion because S is actually two things.

The first thing it is is the SingletonRegistry. Several classes in SymPy appear so often that they are singletonized, that is, using some metaprogramming they are made so that they can only be instantiated once. For instance, every time you create Integer(0), this will return the same instance, Zero. All singleton instances are attributes of the S object, so Integer(0) can also be accessed as S.Zero.

Singletonization offers two advantages: it saves memory, and it allows fast comparison. It saves memory because no matter how many times the singletonized objects appear in expressions in memory, they all point to the same single instance in memory. The fast comparison comes from the fact that you can use is to compare exact instances in Python (usually, you need to use == to compare things). Hence, you can test a is S.Zero to check if a is the Integer(0) instance.

For the most part, the fact that certain objects are singletonized is an implementation detail that you shouldn’t need to worry about. The primary advantage of S for end users is the convenient access to certain instances that are otherwise difficult to type, like S.Half (instead of Rational(1, 2)), or S.true (side note: S.true is the SymPy version of True. Unlike True, it does not subclass from int, so you can write things like ~S.true (not true) and it will give S.false (contrast that with ~True, which gives -2, which isn’t false as a boolean).

The second thing it is is a shortcut for sympify. sympify is the function that converts Python objects such as int(1) into SymPy objects such as Integer(1). It also converts the string form of an expression into a SymPy expression like sympify(x**2) -> Symbol("x")**2. S(1) is the same thing as sympify(1) (basically, S.__call__ has been defined to call sympify).

This is for convenience, since S is a single letter. It’s mostly useful for defining rational numbers. Consider an expression like x + 1/2. If you enter this directly in Python, it will evaluate the 1/2 and give 0.5 (or just 0 in Python 2, because of integer division), because both arguments are ints. However, in SymPy, you usually want the quotient of two integers to give an exact rational number. The way Python’s evaluation works, at least one side of an operator needs to be a SymPy object for the SymPy evaluation to take over. You could write this as x + Rational(1, 2), but this is a lot more typing. A shorter version is x + S(1)/2. Since S(1) returns Integer(1), the division will return a Rational type, since it will call Integer.__div__, which knows how to return a Rational.

Answered By: asmeurer

In short

S.true is a singleton used by SymPy to represent true, and there is a difference with Python True:

print(f'The inverse of True is {~S.true}, not {~True}')

prints:

The inverse of True is False, not -2

However, such a difference is usually hidden to the user, and in most cases there isn’t any need to use S.true directly as SymPy takes care of that for us, using the function S() internally, a shorthand for sympify().

This function and the associated singletons are part of S, the singleton registry.

Details follow.


S is the registry for singletons

In your context, S is the regular shortcut for singleton registry (sympy.core.singleton.SingletonRegistry). This class is itself created by SymPy based on metaclass Singleton.

A singleton relies on object uniqueness instead of value equality, e.g., the singleton S.Half is used for rational value 1/2, whatever the way it has been obtained, e.g., by dividing 2/4 or as the result of cos(5*pi/3). Using this singleton allows equality checks to be based on the singleton ID/address rather than on a value, operator is is used. Such comparison is easier and quicker. More on singleton pattern.

For practical purposes, SingletonRegistry holds references for constants like 0, 1, False, True, EmptySet, etc. in the form of singletons, and can be accessed using its shortcut S.

S is also the shortcut for simpify

Note S, used as a function, is also the shortcut for function sympify which is used by SymPy to make everything used by the program compatible with SymPy, e.g. it identifies strings associated with symbols and give them the correct type. Part of this sympyfication task is to convert constants into their singleton equivalent, when one exists, and True is automatically converted into S.true when encountered.

S.true is the singleton holding True

Therefore S.true (lowercase t) accesses the singleton used by SymPy to represent a True value. Normally there isn’t any need to use the singleton instead of the Boolean value as in SymPy True anyway evaluates to S.true when sympify() is called. However there are exceptions detailed in the documentation about SymPy Boolean functions:

SymPy version of True, a singleton that can be accessed via S.true.

This is the SymPy version of True, for use in the logic module. The primary advantage of using true instead of True is that shorthand Boolean operations like ~ and >> will work as expected on this class, whereas with True they act bitwise on 1. Functions in the logic module will return this class when they evaluate to true.

When to use S.true?

From the same page:

There is liable to be some confusion as to when True should be used and when S.true should be used in various contexts throughout SymPy. An important thing to remember is that sympify(True) returns S.true. This means that for the most part, you can just use True and it will automatically be converted to S.true when necessary, similar to how you can generally use 1 instead of S.One.

The rule of thumb is:

“If the boolean in question can be replaced by an arbitrary symbolic Boolean, like Or(x, y) or x > 1, use S.true. Otherwise, use True

Answered By: mins
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.