S
S
S has 2 variants:
Shared Notes
Create new symbols from names. Symbols can have attributes, such as symmetries. If no attributes are specified and the symbol was previously defined, the attributes are inherited. Once attributes are defined on a symbol, they cannot be redefined later.
S returning Expression
S(
name: str,
/,
*,
is_symmetric: bool | None = None,
is_antisymmetric: bool | None = None,
is_cyclesymmetric: bool | None = None,
is_linear: bool | None = None,
is_flat: bool | None = None,
is_scalar: bool | None = None,
is_real: bool | None = None,
is_integer: bool | None = None,
is_positive: bool | None = None,
tags: Sequence[str] | None = None,
aliases: Sequence[str] | None = None,
normalization: Transformer | Callable[[Expression], Expression] | None = None,
print: Callable[..., str | None] | dict[str, str] | dict[PrintMode, str] | dict[str | PrintMode, str] | None = None,
derivative: Callable[[Expression, int], Expression] | None = None,
series: Callable[[Sequence[Series]], tuple[Expression, Expression] | None] | None = None,
eval: dict[str, Any] | None = None,
data: str | int | Expression | bytes | list[Any] | dict[str | int | Expression, Any] | None = None,
) -> ExpressionExamples
Define a regular symbol and use it as a variable:
x = S('x')
e = x**2 + 5
print(e) # x**2 + 5Define a regular symbol and use it as a function:
f = S('f')
e = f(1,2)
print(e) # f(1,2)Define a symmetric function:
f = S('f', is_symmetric=True)
e = f(2,1)
print(e) # f(1,2)Define a linear and symmetric function:
p1, p2, p3, p4 = ES('p1', 'p2', 'p3', 'p4')
dot = S('dot', is_symmetric=True, is_linear=True)
e = dot(p2+2*p3,p1+3*p2-p3)Output
dot(p1,p2)+2*dot(p1,p3)+3*dot(p2,p2)-dot(p2,p3)+6*dot(p2,p3)-2*dot(p3,p3)
Define a custom normalization function:
e = S('real_log', normalization=T().replace(E("x_(exp(x1_))"), E("x1_")))
E("real_log(exp(x)) + real_log(5)")Define a custom print function:
def print_mu(mu: Expression, mode: PrintMode, **kwargs) -> str | None:
if mode == PrintMode.Latex:
if mu.get_type() == AtomType.Fn:
return "\mu_{" + ",".join(a.format() for a in mu) + "}"
else:
return "\mu"
mu = S("mu", print=print_mu)
expr = E("mu + mu(1,2)")
print(expr.to_latex())If the function returns None, the default print function is used.
Define a custom derivative function:
tag = S('tag', derivative=lambda f, index: f)
x = S('x')
tag(3, x).derivative(x)Define a custom series function that returns the principal part and the regular part, or None if a standard construction through the derivative can be used:
def inv_series(args: Sequence[Series]) -> tuple[Expression, Expression] | None:
return (N(0), args[0].pow(-1).to_expression())
t = S('t')
inv = S('inv', series=inv_series)Define a function with a custom evaluation:
cosh = S(
"my_cosh",
eval={
"float": lambda args: math.cosh(args[0]),
"complex": lambda args: cmath.cosh(args[0]),
"cpp": "template<typename T> T python_my_cosh(T a) { return std::cosh(a); }",
},
)Add custom data to a symbol:
x = S('x', data={'my_tag': 'my_value'})
r = x.get_symbol_data('my_tag')sParameters
name(str) The name of the symbolis_symmetric(bool | None) Set to true if the symbol is symmetric.is_antisymmetric(bool | None) Set to true if the symbol is antisymmetric.is_cyclesymmetric(bool | None) Set to true if the symbol is cyclesymmetric.is_linear(bool | None) Set to true if the symbol is linear.is_flat(bool | None) Set to true if the symbol is flat (associative). A flat function removes nesting.is_scalar(bool | None) Set to true if the symbol is a scalar. It will be moved out of linear functions.is_real(bool | None) Set to true if the symbol is a real number.is_integer(bool | None) Set to true if the symbol is an integer.is_positive(bool | None) Set to true if the symbol is a positive number.tags(Sequence[str] | None = None) A list of tags to associate with the symbol.aliases(Sequence[str] | None = None) A list of aliases to associate with the symbol.normalization(Transformer | None) A transformer that is called after every normalization. Note that the symbol name cannot be used in the transformer as this will lead to a definition of the symbol. Use a wildcard with the same attributes instead.print(Callable[..., str | None] | dict[str | PrintMode, str] | None:) A function that is called when printing the variable/function, which is provided as its first argument. This function should return a string, orNoneif the default print function should be used. The custom print function takes in keyword arguments that are the same as the arguments of theformatfunction. Alternatively, provide a dictionary mapping mode names (case-insensitive strings orPrintModevalues) to strings, e.g.{'latex': r'\overline{a}', PrintMode.Typst: '#overline(a)'}. Values replace the entire variable or function call verbatim. Missing modes use default printing. The dictionary is copied when the symbol is defined; duplicate modes are rejected.derivative(Callable[[Expression, int], Expression] | None:) A function that is called when computing the derivative of a function in a given argument.series(Callable[[Sequence[Series]], tuple[Expression, Expression] | None] | None:) A function that is called for custom series expansion. It receives the argument series and can return the singular factor and regularized expression, orNoneto use the default series expansion.eval(dict[str, Any] | None:) Numeric evaluation function(s). The dictionary may contain: -tag_count: int: the number of leading symbolic tag arguments. -cpp: str: a C++ function definition inserted into exported C++ code for this symbol. For arbitrary precision evaluation of constant functions, register a function that maps the tags and the requested decimal precision to a number: -constant: (Sequence[Expression], int) -> Float | ComplexFloat | Decimal | float | complex | tuple[Decimal, Decimal] Evaluators for non-constant functions whentag_count = 0: -float: Sequence[float] -> float -complex: Sequence[complex] -> complex -decimal: Sequence[Float] -> Float -decimal_complex: Sequence[ComplexFloat] -> ComplexFloat Evaluators for non-constant functions whentag_count > 0are generators: -float: Sequence[Expression] -> (Sequence[float] -> float) -complex: Sequence[Expression] -> (Sequence[complex] -> complex) -decimal: Sequence[Expression] -> (Sequence[Float] -> Float) -decimal_complex: Sequence[Expression] -> (Sequence[ComplexFloat] -> ComplexFloat)data(str | int | Expression | bytes | list | dict | None = None) Custom user data to associate with the symbol.
S returning list[Expression]
S(
name0: str,
name1: str,
/,
*names: str,
is_symmetric: bool | None = None,
is_antisymmetric: bool | None = None,
is_cyclesymmetric: bool | None = None,
is_linear: bool | None = None,
is_flat: bool | None = None,
is_scalar: bool | None = None,
is_real: bool | None = None,
is_integer: bool | None = None,
is_positive: bool | None = None,
tags: Sequence[str] | None = None,
aliases: Sequence[str] | None = None,
normalization: Transformer | Callable[[Expression], Expression] | None = None,
print: Callable[..., str | None] | dict[str, str] | dict[PrintMode, str] | dict[str | PrintMode, str] | None = None,
derivative: Callable[[Expression, int], Expression] | None = None,
series: Callable[[Sequence[Series]], tuple[Expression, Expression] | None] | None = None,
eval: dict[str, Any] | None = None,
data: str | int | Expression | bytes | list[Any] | dict[str | int | Expression, Any] | None = None,
) -> list[Expression]Examples
Define two regular symbols:
x, y = S('x', 'y')Define two symmetric functions:
f, g = S('f', 'g', is_symmetric=True)
e = f(2,1)
print(e) # f(1,2)Parameters
names(str) The names of the symbols.is_symmetric(bool | None) Set to true if the symbol is symmetric.is_antisymmetric(bool | None) Set to true if the symbol is antisymmetric.is_cyclesymmetric(bool | None) Set to true if the symbol is cyclesymmetric.is_linear(bool | None) Set to true if the symbol is multilinear.is_flat(bool | None) Set to true if the symbol is flat (associative).is_scalar(bool | None) Set to true if the symbol is a scalar. It will be moved out of linear functions.is_real(bool | None) Set to true if the symbol is a real number.is_integer(bool | None) Set to true if the symbol is an integer.is_positive(bool | None) Set to true if the symbol is a positive number.tags(Sequence[str] | None = None) A list of tags to associate with the symbol.