Expression

Expression

Expression()

A Symbolica expression.

Supports standard arithmetic operations, such as addition and multiplication.

Examples

x = S('x')
e = x**2 + 2 - x + 1 / x**4
print(e)

Attributes

Name Description
ABS The built-in absolute value function.
COEFF The built-in function that convert a rational polynomials to a coefficient.
COMPLEX_INFINITY The number that represents infinity with an unknown complex phase: .
CONJ The built-in complex conjugate function.
COS The built-in cosine function.
E Euler’s number e.
EXP The built-in exponential function.
I The mathematical constant i, where i^2 = -1.
IF The built-in function for piecewise-defined expressions
INDETERMINATE The number that represents indeterminacy: ¿.
INFINITY The number that represents infinity: .
LOG The built-in logarithm function.
PI The mathematical constant π.
SIN The built-in sine function.
SQRT The built-in square root function.

ABS

ABS: Expression

The built-in absolute value function.

COEFF

COEFF: Expression

The built-in function that convert a rational polynomials to a coefficient.

COMPLEX_INFINITY

COMPLEX_INFINITY: Expression

The number that represents infinity with an unknown complex phase: .

CONJ

CONJ: Expression

The built-in complex conjugate function.

COS

COS: Expression

The built-in cosine function.

E

E: Expression

Euler’s number e.

EXP

EXP: Expression

The built-in exponential function.

I

I: Expression

The mathematical constant i, where i^2 = -1.

IF

IF: Expression

The built-in function for piecewise-defined expressions. IF(cond, true_expr, false_expr) evaluates to true_expr if cond is non-zero and false_expr otherwise.

INDETERMINATE

INDETERMINATE: Expression

The number that represents indeterminacy: ¿.

INFINITY

INFINITY: Expression

The number that represents infinity: .

LOG

LOG: Expression

The built-in logarithm function.

PI

PI: Expression

The mathematical constant π.

SIN

SIN: Expression

The built-in sine function.

SQRT

SQRT: Expression

The built-in square root function.

Methods

Name Description
__add__ Add this expression to other, returning the result.
__call__ Create a Symbolica expression or transformer by calling the function with appropriate arguments.
__copy__ Copy the expression.
__eq__ Compare two expressions.
__ge__ Compare two expressions
__getitem__ Get the idxth component of the expression.
__gt__ Compare two expressions
__hash__ Hash the expression.
__iter__ Create an iterator over all subexpressions of the expression.
__le__ Compare two expressions
__len__ Return the number of terms in this expression.
__lt__ Compare two expressions
__mul__ Multiply this expression with other, returning the result.
__neg__ Negate the current expression, returning the result.
__neq__ Compare two expressions.
__new__ Create a new expression that represents 0.
__pow__ Take self to power exp, returning the result.
__radd__ Add this expression to other, returning the result.
__rmul__ Multiply this expression with other, returning the result.
__rpow__ Take base to power self, returning the result.
__rsub__ Subtract this expression from other, returning the result.
__rtruediv__ Divide other by this expression, returning the result.
__rxor__ Returns a warning that ** should be used instead of ^ for taking a power.
__str__ Convert the expression into a human-readable string.
__sub__ Subtract other from this expression, returning the result.
__truediv__ Divide this expression by other, returning the result.
__xor__ Returns a warning that ** should be used instead of ^ for taking a power.
abs Take the absolute value of this expression, returning the result.
apart Compute the partial fraction decomposition in x
cancel Cancel common factors between numerators and denominators
canonize_tensors Canonize (products of) tensors in the expression by relabeling repeated indices
coefficient Collect terms involving the literal occurrence of x.
coefficient_list Collect terms involving the same power of x, where x are variables or functions
collect Collect terms involving the same power of the indeterminate(s) x
collect_factors Collect common factors from (nested) sums.
collect_horner Iteratively extract the minimal common powers of an indeterminate v for every term that contains v and continue to the next indeterminate in variables
collect_num Collect numerical factors by removing the content from additions
collect_symbol Collect terms involving the same power of variables or functions with the name x
conj Take the complex conjugate of this expression, returning the result.
contains Returns true iff self contains a literally.
cos Take the cosine of this expression, returning the result.
derivative Derive the expression w.r.t the variable x.
evaluate Evaluate the expression, using a map of all the variables and user functions to a float.
evaluate_complex Evaluate the expression, using a map of all the variables and user functions to a complex number.
evaluate_with_prec Evaluate the expression, using a map of all the constants and user functions using arbitrary precision arithmetic
evaluator Create an evaluator that can evaluate (nested) expressions in an optimized fashion
evaluator_multiple Create an evaluator that can jointly evaluate (nested) expressions in an optimized fashion
exp Take the exponential of this expression, returning the result.
expand Expand the expression
expand_num Distribute numbers in the expression, for example: 2*(x+y) -> 2*x+2*y.
factor Factor the expression over the rationals.
format Convert the expression into a human-readable string, with tunable settings.
format_plain Convert the expression into a plain string, useful for importing and exporting.
get_all_indeterminates Get all symbols and functions in the current expression, optionally including function symbols
get_all_symbol_names Return all defined symbol names (function names and variables).
get_all_symbols Get all symbols in the current expression, optionally including function symbols
get_attributes Get the attributes of a variable or function if the current atom is a variable or function, otherwise throw an error.
get_byte_size Get the number of bytes that this expression takes up in memory.
get_name Get the name of a variable or function if the current atom is a variable or function, otherwise throw an error.
get_symbol_data Get the data of a variable or function if the current atom is a variable or function, otherwise throw an error
get_tags Get the tags of a variable or function if the current atom is a variable or function, otherwise throw an error.
get_type Get the type of the atom.
hold Create a held expression that delays the execution of the transformer t until the resulting held expression is called
is_constant Check if the expression is constant, i.e
is_finite Check if the expression has no infinities and is not indeterminate.
is_integer Check if the expression is integer
is_positive Check if the expression is a positive scalar
is_real Check if the expression is real
is_scalar Check if the expression is a scalar
is_type Test if the expression is of a certain type.
load Load an expression and its state from a file
log Take the logarithm of this expression, returning the result.
map Map the transformations to every term in the expression
match Return an iterator over the pattern self matching to lhs
matches Test whether the pattern is found in the expression
nsolve Find the root of an expression in x numerically over the reals using Newton’s method
nsolve_system Find a common root of multiple expressions in variables numerically over the reals using Newton’s method
num Create a new Symbolica number from an int, a float, or a string
parse Parse a Symbolica expression from a string.
rationalize Map all floating point and rational coefficients to the best rational approximation in the interval [self*(1-relative_error),self*(1+relative_error)].
replace Replace all subexpressions matching the pattern pattern by the right-hand side rhs
replace_iter Return an iterator over the replacement of the pattern self on lhs by rhs
replace_multiple Replace all atoms matching the patterns
replace_wildcards Replace all wildcards in the expression with the corresponding values in replacements
req Create a new pattern restriction that calls the function filter_fn with the matched atom that should return a boolean
req_attr Create a pattern restriction based on the attributes of a matched variable or function.
req_cmp Create a new pattern restriction that calls the function cmp_fn with another the matched atom and the match atom of the other wildcard that should return a boolean
req_cmp_ge Create a pattern restriction that passes when the wildcard is greater than or equal to another wildcard
req_cmp_gt Create a pattern restriction that passes when the wildcard is greater than another wildcard
req_cmp_le Create a pattern restriction that passes when the wildcard is smaller than or equal to another wildcard
req_cmp_lt Create a pattern restriction that passes when the wildcard is smaller than another wildcard
req_contains Create a pattern restriction that filters for expressions that contain a.
req_ge Create a pattern restriction that passes when the wildcard is greater than or equal to a number num
req_gt Create a pattern restriction that passes when the wildcard is greater than a number num
req_le Create a pattern restriction that passes when the wildcard is smaller than or equal to a number num
req_len Create a pattern restriction based on the wildcard length before downcasting.
req_lit Create a pattern restriction that treats the wildcard as a literal variable, so that it only matches to itself.
req_lt Create a pattern restriction that passes when the wildcard is smaller than a number num
req_tag Create a pattern restriction based on the tag of a matched variable or function.
req_type Create a pattern restriction that tests the type of the atom.
save Save the expression and its state to a binary file
series Series expand in x around expansion_point to depth depth.
set_coefficient_ring Set the coefficient ring to contain the variables in the vars list
sin Take the sine of this expression, returning the result.
solve_linear_system Solve a linear system in the variables variables, where each expression in the system is understood to yield 0
sqrt Take the square root of this expression, returning the result.
symbol Create new symbols from names
to_atom_tree Convert the expression to a tree.
to_canonical_string Convert the expression into a canonical string that is independent on the order of the variables and other implementation details.
to_float Convert all coefficients and built-in functions to floats with a given precision decimal_prec
to_int Convert the expression to an integer if possible
to_latex Convert the expression into a LaTeX string.
to_mathematica Convert the expression into a Mathematica-parsable string.
to_polynomial Convert the expression to a polynomial, optionally, with the variable ordering specified in vars
to_rational_polynomial Convert the expression to a rational polynomial, optionally, with the variable ordering specified in vars
to_sympy Convert the expression into a sympy-parsable string.
to_typst Convert the expression into a Typst string.
together Write the expression over a common denominator.

__add__

Expression.__add__(other: Expression | int | float | complex | Decimal) -> Expression

Add this expression to other, returning the result.

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.

__call__

__call__ has 2 variants:

Shared Notes

Create a Symbolica expression or transformer by calling the function with appropriate arguments.

Examples

x, f = S('x', 'f')
e = f(3,x)
print(e)  # f(3,x)

__call__ returning Expression

Expression.__call__(*args: Expression | int | float | complex | Decimal) -> Expression

Parameters

  • args (Expression | int | float | complex | Decimal) The arguments passed to the expression call.

__call__ returning HeldExpression

Expression.__call__(*args: HeldExpression | Expression | int | float | complex | Decimal) -> HeldExpression

Parameters

  • args (HeldExpression | Expression | int | float | complex | Decimal) The arguments passed to the expression or transformer call.

__copy__

Expression.__copy__() -> Expression

Copy the expression.

__eq__

Expression.__eq__(other: Expression | int | float | complex | Decimal) -> Condition

Compare two expressions.

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.

__ge__

Expression.__ge__(other: Expression | int | float | complex | Decimal) -> Condition

Compare two expressions. If any of the two expressions is not a rational number, an interal ordering is used.

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.

__getitem__

Expression.__getitem__(idx: int) -> Expression

Get the idxth component of the expression.

Parameters

  • idx (int) The zero-based index to access.

__gt__

Expression.__gt__(other: Expression | int | float | complex | Decimal) -> Condition

Compare two expressions. If any of the two expressions is not a rational number, an interal ordering is used.

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.

__hash__

Expression.__hash__() -> int

Hash the expression.

__iter__

Expression.__iter__() -> Iterator[Expression]

Create an iterator over all subexpressions of the expression.

__le__

Expression.__le__(other: Expression | int | float | complex | Decimal) -> Condition

Compare two expressions. If any of the two expressions is not a rational number, an interal ordering is used.

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.

__len__

Expression.__len__() -> int

Return the number of terms in this expression.

__lt__

Expression.__lt__(other: Expression | int | float | complex | Decimal) -> Condition

Compare two expressions. If any of the two expressions is not a rational number, an interal ordering is used.

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.

__mul__

Expression.__mul__(other: Expression | int | float | complex | Decimal) -> Expression

Multiply this expression with other, returning the result.

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.

__neg__

Expression.__neg__() -> Expression

Negate the current expression, returning the result.

__neq__

Expression.__neq__(other: Expression | int | float | complex | Decimal) -> Condition

Compare two expressions.

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.

__new__

Expression.__new__() -> Expression

Create a new expression that represents 0.

__pow__

Expression.__pow__(exp: Expression | int | float | complex | Decimal) -> Expression

Take self to power exp, returning the result.

Parameters

  • exp (Expression | int | float | complex | Decimal) The exponent.

__radd__

Expression.__radd__(other: Expression | int | float | complex | Decimal) -> Expression

Add this expression to other, returning the result.

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.

__rmul__

Expression.__rmul__(other: Expression | int | float | complex | Decimal) -> Expression

Multiply this expression with other, returning the result.

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.

__rpow__

Expression.__rpow__(base: Expression | int | float | complex | Decimal) -> Expression

Take base to power self, returning the result.

Parameters

  • base (Expression | int | float | complex | Decimal) The base expression.

__rsub__

Expression.__rsub__(other: Expression | int | float | complex | Decimal) -> Expression

Subtract this expression from other, returning the result.

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.

__rtruediv__

Expression.__rtruediv__(other: Expression | int | float | complex | Decimal) -> Expression

Divide other by this expression, returning the result.

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.

__rxor__

Expression.__rxor__(a: Any) -> Expression

Returns a warning that ** should be used instead of ^ for taking a power.

Parameters

  • a (Any) The operand passed with ^; use ** for exponentiation instead.

__str__

Expression.__str__() -> str

Convert the expression into a human-readable string.

__sub__

Expression.__sub__(other: Expression | int | float | complex | Decimal) -> Expression

Subtract other from this expression, returning the result.

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.

__truediv__

Expression.__truediv__(other: Expression | int | float | complex | Decimal) -> Expression

Divide this expression by other, returning the result.

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.

__xor__

Expression.__xor__(a: Any) -> Expression

Returns a warning that ** should be used instead of ^ for taking a power.

Parameters

  • a (Any) The operand passed with ^; use ** for exponentiation instead.

abs

Expression.abs() -> Expression

Take the absolute value of this expression, returning the result.

apart

Expression.apart(x: Expression | None = None) -> Expression

Compute the partial fraction decomposition in x.

If None is passed, the expression will be decomposed in all variables which involves a potentially expensive Groebner basis computation.

Examples

p = E('1/((x+y)*(x^2+x*y+1)(x+1))')
print(p.apart(S('x')))

Multivariate partial fractioning:

p = E('(2y-x)/(y*(x+y)*(y-x))')
print(p.apart())

yields 3/2*y^-1*(x+y)^-1+1/2*y^-1*(-x+y)^-1

Parameters

  • x (Expression | None) The variable with respect to which to perform the partial-fraction decomposition.

cancel

Expression.cancel() -> Expression

Cancel common factors between numerators and denominators. Any non-canceling parts of the expression will not be rewritten.

Examples

from symbolica import *
p = E('1+(y+1)^10*(x+1)/(x^2+2x+1)')
print(p.cancel())  # 1+(y+1)**10/(x+1)

canonize_tensors

Expression.canonize_tensors(contracted_indices: Sequence[tuple[Expression | int, Expression | int]]) -> tuple[Expression, list[tuple[Expression, Expression]], list[tuple[Expression, Expression]]]

Canonize (products of) tensors in the expression by relabeling repeated indices. The tensors must be written as functions, with its indices as the arguments. Subexpressions, constants and open indices are supported.

If the contracted indices are distinguishable (for example in their dimension), you can provide a group marker as the second element in the tuple of the index specification. This makes sure that an index will not be renamed to an index from a different group.

Returns the canonical expression, as well as the external indices and ordered dummy indices appearing in the canonical expression.

Examples

g = S('g', is_symmetric=True)
fc = S('fc', is_cyclesymmetric=True)
mu1, mu2, mu3, mu4, k1 = S('mu1', 'mu2', 'mu3', 'mu4', 'k1')
e = g(mu2, mu3)*fc(mu4, mu2, k1, mu4, k1, mu3)
(r, external, dummy) = e.canonize_tensors([(mu1, 0), (mu2, 0), (mu3, 0), (mu4, 0)])
print(r)

yields g(mu1, mu2)*fc(mu1, mu3, mu2, k1, mu3, k1).

Parameters

  • contracted_indices (Sequence[tuple[Expression | int, Expression | int]]) The index patterns that should be treated as contracted, optionally grouped by a marker.

coefficient

Expression.coefficient(x: Expression) -> Expression

Collect terms involving the literal occurrence of x.

Examples

from symbolica import *
x, y = S('x', 'y')
e = 5*x + x * y + x**2 + y*x**2
print(e.coefficient(x**2))

yields

y + 1

Parameters

  • x (Expression) The variable whose coefficient should be extracted.

coefficient_list

Expression.coefficient_list(*x: Expression) -> Sequence[tuple[Expression, Expression]]

Collect terms involving the same power of x, where x are variables or functions. Return the list of key-coefficient pairs.

Examples

from symbolica import *
x, y = S('x', 'y')
e = 5*x + x * y + x**2 + 5

for a in e.coefficient_list(x):
    print(a[0], a[1])

yields

x y+5 x^2 1 1 5

Parameters

  • x (Expression) The variables whose coefficient exponents should be listed.

collect

Expression.collect(
    *x: Expression,
    key_map: Callable[[Expression], Expression] | None = None,
    coeff_map: Callable[[Expression], Expression] | None = None,
) -> Expression

Collect terms involving the same power of the indeterminate(s) x. Return the list of key-coefficient pairs and the remainder that matched no key.

Both the key (the quantity collected in) and its coefficient can be mapped using key_map and coeff_map respectively.

Examples

from symbolica import *
x, y = S('x', 'y')
e = 5*x + x * y + x**2 + 5

print(e.collect(x))  # x^2+x*(y+5)+5
from symbolica import *
x, y = S('x', 'y')
var, coeff = S('var', 'coeff')
e = 5*x + x * y + x**2 + 5

print(e.collect(x, key_map=lambda x: var(x), coeff_map=lambda x: coeff(x)))

yields var(1)*coeff(5)+var(x)*coeff(y+5)+var(x^2)*coeff(1).

Parameters

  • *x (Expression) The variable(s) or function(s) to collect terms in key_map A function to be applied to the quantity collected in coeff_map A function to be applied to the coefficient

collect_factors

Expression.collect_factors() -> Expression

Collect common factors from (nested) sums.

Examples

from symbolica import *
e = E('x*(x+y*x+x^2+y*(x+x^2))')
e.collect_factors()

yields

v1^2*(1+v1+v2+v2*(1+v1))

collect_horner

Expression.collect_horner(vars: Sequence[Expression] | None = None) -> Expression

Iteratively extract the minimal common powers of an indeterminate v for every term that contains v and continue to the next indeterminate in variables. This is a generalization of Horner’s method for polynomials.

If no variables are provided, a heuristically determined variable ordering is used that minimizes the number of operations.

Examples

from symbolica import *
expr = E('v1 + v1*v2 + 2 v1*v2*v3 + v1^2 + v1^3*y + v1^4*z')
collected = expr.collect_horner([S('v1'), S('v2')])

yields v1*(1+v1*(1+v1*(v1*z+y))+v2*(1+2*v3)).

Parameters

  • vars (Sequence[Expression] | None) The variables treated as polynomial variables, in the given order.

collect_num

Expression.collect_num() -> Expression

Collect numerical factors by removing the content from additions. For example, -2*x + 4*x^2 + 6*x^3 will be transformed into -2*(x - 2*x^2 - 3*x^3).

The first argument of the addition is normalized to a positive quantity.

Examples

from symbolica import *
x, y = S('x', 'y')
e = (-3*x+6*y)*(2*x+2*y)
print(e.collect_num())

yields

-6*(x+y)*(x-2*y)

collect_symbol

Expression.collect_symbol(
    x: Expression,
    key_map: Callable[[Expression], Expression] | None = None,
    coeff_map: Callable[[Expression], Expression] | None = None,
) -> Expression

Collect terms involving the same power of variables or functions with the name x.

Both the key (the quantity collected in) and its coefficient can be mapped using key_map and coeff_map respectively.

Examples

from symbolica import *
x, f = S('x', 'f')
e = f(1,2) + x*f(1,2)

print(e.collect_symbol(f))  # (1+x)*f(1,2)

Parameters

  • x (Expression) The symbol to collect in key_map A function to be applied to the quantity collected in coeff_map A function to be applied to the coefficient

conj

Expression.conj() -> Expression

Take the complex conjugate of this expression, returning the result.

Examples

e = E('x+2 + 3^x + (5+2i) * (test::{real}::real) + (-2)^x')
print(e.conj())

Yields (5-2𝑖)*real+3^conj(x)+conj(x)+conj((-2)^x)+2.

contains

Expression.contains(a: Transformer | HeldExpression | Expression | int | float | Decimal) -> Condition

Returns true iff self contains a literally.

Examples

from symbolica import *
x, y, z = S('x', 'y', 'z')
e = x * y * z
e.contains(x) # True
e.contains(x*y*z) # True
e.contains(x*y) # False

Parameters

  • a (Transformer | HeldExpression | Expression | int | float | Decimal) The subexpression or pattern that should be contained literally.

cos

Expression.cos() -> Expression

Take the cosine of this expression, returning the result.

derivative

Expression.derivative(x: Expression) -> Expression

Derive the expression w.r.t the variable x.

Parameters

  • x (Expression) The variable with respect to which to differentiate.

evaluate

Expression.evaluate(
    constants: dict[Expression, float],
    functions: dict[Expression, Callable[[Sequence[float]], float]],
) -> float

Evaluate the expression, using a map of all the variables and user functions to a float.

Examples

from symbolica import *
x = S('x')
f = S('f')
e = E('cos(x)')*3 + f(x,2)
print(e.evaluate({x: 1}, {f: lambda args: args[0]+args[1]}))

Parameters

  • constants (dict[Expression, float]) The constant substitutions applied during evaluation.
  • functions (dict[Expression, Callable[[Sequence[float]], float]]) The function callback table used during evaluation.

evaluate_complex

Expression.evaluate_complex(
    constants: dict[Expression, float | complex],
    functions: dict[Expression, Callable[[Sequence[complex]], float | complex]],
) -> complex

Evaluate the expression, using a map of all the variables and user functions to a complex number.

Examples

from symbolica import *
x, y = S('x', 'y')
e = E('sqrt(x)')*y
print(e.evaluate_complex({x: 1 + 2j, y: 4 + 3j}, {}))

Parameters

  • constants (dict[Expression, float | complex]) The constant substitutions applied during evaluation.
  • functions (dict[Expression, Callable[[Sequence[complex]], float | complex]]) The function callback table used during evaluation.

evaluate_with_prec

Expression.evaluate_with_prec(
    constants: dict[Expression, float | str | Decimal],
    functions: dict[Expression, Callable[[Sequence[Decimal]], float | str | Decimal]],
    decimal_digit_precision: int,
) -> Decimal

Evaluate the expression, using a map of all the constants and user functions using arbitrary precision arithmetic. The user has to specify the number of decimal digits of precision and provide all input numbers as floats, strings or Decimal.

Examples

from symbolica import *
from decimal import Decimal, getcontext
x = S('x', 'f')
e = E('cos(x)')*3 + f(x, 2)
getcontext().prec = 100
a = e.evaluate_with_prec({x: Decimal('1.123456789')}, {
                        f: lambda args: args[0] + args[1]}, 100)

Parameters

  • constants (dict[Expression, float | str | Decimal]) The constant substitutions applied during evaluation.
  • functions (dict[Expression, Callable[[Sequence[Decimal]], float | str | Decimal]]) The function callback table used during evaluation.
  • decimal_digit_precision (int) The decimal precision used for arbitrary-precision evaluation.

evaluator

Expression.evaluator(
    constants: dict[Expression, Expression],
    functions: dict[tuple[Expression, str, Sequence[Expression]], Expression],
    params: Sequence[Expression],
    iterations: int = 1,
    cpe_iterations: int | None = None,
    n_cores: int = 4,
    verbose: bool = False,
    jit_compile: bool = True,
    direct_translation: bool = True,
    max_horner_scheme_variables: int = 500,
    max_common_pair_cache_entries: int = 1000000,
    max_common_pair_distance: int = 100,
    external_functions: dict[tuple[Expression, str], Callable[[Sequence[float | complex]], float | complex]] | None = None,
    conditionals: Sequence[Expression] | None = None,
) -> Evaluator

Create an evaluator that can evaluate (nested) expressions in an optimized fashion. All constants and functions should be provided as dictionaries, where the function dictionary has a key (name, printable name, arguments) and the value is the function body. For example the function f(x,y)=x^2+y should be provided as {(f, "f", (x, y)): x**2 + y}. All free parameters should be provided in the params list.

Additionally, external functions can be registered that will call a Python function.

If KeyboardInterrupt is triggered during the optimization, the optimization will stop and will yield the current best result.

Examples

from symbolica import *
x, y, z, pi, f, g = S(
    'x', 'y', 'z', 'pi', 'f', 'g')

e1 = E("x + pi + cos(x) + f(g(x+1),x*2)")
fd = E("y^2 + z^2*y^2")
gd = E("y + 5")

ev = e1.evaluator({pi: Expression.num(22)/7},
             {(f, "f", (y, z)): fd, (g, "g", (y, )): gd}, [x])
res = ev.evaluate([[1.], [2.], [3.]])  # evaluate at x=1, x=2, x=3
print(res)

Define an external function:

E("f(x)").evaluator({}, {}, [S("x")],
            external_functions={(S("f"), "F"): lambda args: args[0]**2 + 1})

Define an conditional function which yields x+1 when y != 0 and x+2 when y == 0:

E("if(y, x + 1, x + 2)").evaluator({}, {}, [S("x"), S("y")], conditional=[S("if")])

Parameters

  • constants (dict[Expression, Expression]) A map of expressions to constants. The constants should be numerical expressions.
  • functions (dict[tuple[Expression, str, Sequence[Expression]], Expression]) A dictionary of functions. The key is a tuple of the function name, printable name and the argument variables. The value is the function body. If the function name entry contains arguments, these are considered tags.
  • params (Sequence[Expression]) A list of free parameters.
  • iterations (int, optional) The number of Horner schemes to try.
  • cpe_iterations (int | None, optional) The number of CPE iterations to perform. The number if unbounded if None.
  • n_cores (int, optional) The number of CPU cores used for the optimization.
  • verbose (bool, optional) Print the progress of the optimization.
  • jit_compile (bool, optional) Just-in-time compile the evaluator upon first use with SymJIT. This can provide significant performance improvements.
  • direct_translation (bool, optional) If set to True, the optimized expression will be directly constructed from atoms without building a tree.
  • max_horner_scheme_variables (int, optional) The maximum number of variables in a Horner scheme.
  • max_common_pair_cache_entries (int, optional) The maximum number of entries in the common pair cache.
  • max_common_pair_distance (int, optional) The maximum distance between common pairs. Used when clearing cache entries.
  • external_functions (dict[tuple[Expression, str], Callable[[Sequence[float | complex]], float | complex]] | None) A dictionary of external functions that can be called during evaluation. The key is a tuple of the function symbol and a printable function name. The value is a callable that takes a list of arguments and returns a float or complex number. This is useful for functions that are not defined in Symbolica but are available in Python.
  • conditionals (Sequence[Expression] | None, optional) A list of conditional functions. These functions should take three argument: a condition that is tested for inequality with 0, the true branch and the false branch.

evaluator_multiple

Expression.evaluator_multiple(
    exprs: Sequence[Expression],
    constants: dict[Expression, Expression],
    functions: dict[tuple[Expression, str, Sequence[Expression]], Expression],
    params: Sequence[Expression],
    iterations: int = 1,
    cpe_iterations: int | None = None,
    n_cores: int = 4,
    verbose: bool = False,
    jit_compile: bool = True,
    direct_translation: bool = True,
    max_horner_scheme_variables: int = 500,
    max_common_pair_cache_entries: int = 1000000,
    max_common_pair_distance: int = 100,
    external_functions: dict[tuple[Expression, str], Callable[[Sequence[float | complex]], float | complex]] | None = None,
    conditionals: Sequence[Expression] | None = None,
) -> Evaluator

Create an evaluator that can jointly evaluate (nested) expressions in an optimized fashion. See Expression.evaluator() for more information.

Examples

from symbolica import *
x = S('x')
e1 = E("x^2 + 1")
e2 = E("x^2 + 2")
ev = Expression.evaluator_multiple([e1, e2], {}, {}, [x])

will recycle the x^2

Parameters

  • exprs (Sequence[Expression]) The expressions to compile into a joint evaluator.
  • constants (dict[Expression, Expression]) The symbolic substitutions applied to constant symbols when building the evaluator.
  • functions (dict[tuple[Expression, str, Sequence[Expression]], Expression]) The symbolic function implementations applied when building the evaluator.
  • params (Sequence[Expression]) The evaluator parameters, in input order.
  • iterations (int) The number of optimization passes to run.
  • cpe_iterations (int | None) The number of common subexpression elimination iterations to perform.
  • n_cores (int) The number of CPU cores used for parallel optimization.
  • verbose (bool) Whether verbose output should be enabled.
  • jit_compile (bool) Whether JIT compilation should be enabled.
  • direct_translation (bool) Whether to prefer direct translation when compiling the evaluator.
  • max_horner_scheme_variables (int) The maximum number of variables considered for Horner-scheme optimization.
  • max_common_pair_cache_entries (int) The maximum number of common-subexpression pairs to cache.
  • max_common_pair_distance (int) The maximum distance between factors when searching for common pairs.
  • external_functions (dict[tuple[Expression, str], Callable[[ Sequence[float | complex]], float | complex]] | None) The external functions to register.
  • conditionals (Sequence[Expression] | None) Expressions that should be treated as conditional branches during evaluator construction.

exp

Expression.exp() -> Expression

Take the exponential of this expression, returning the result.

expand

Expression.expand(var: Expression | None = None, via_poly: bool | None = None) -> Expression

Expand the expression. Optionally, expand in var only. var can be a variable or a function. If it is a variable, any function with that variable name is also expanded in. To expand in multiple functions at the same time, wrap them in a function with the same symbol first, using a match and replace, and then expand in that function.

Using via_poly=True may give a significant speedup for large expressions.

Examples

from symbolica import *
x, y, f, g = S('x', 'y', 'f', 'g')
e = (f(1) + g(2))*(f(3) + (y+1)**2)
print(e.expand(f))

yields f(1)*f(3)+f(3)*g(2)+(1+y)^2*f(1)+(1+y)^2*g(2).

Parameters

  • var (Expression | None) The variable to expand with respect to. If omitted, expand all variables.
  • via_poly (bool | None) Whether the operation should use an intermediate polynomial representation.

expand_num

Expression.expand_num() -> Expression

Distribute numbers in the expression, for example: 2*(x+y) -> 2*x+2*y.

Examples

from symbolica import *
x, y = S('x', 'y')
e = 3*(x+y)*(4*x+5*y)
print(e.expand_num())

yields

(3*x+3*y)*(4*x+5*y)

factor

Expression.factor() -> Expression

Factor the expression over the rationals.

Examples

from symbolica import *
p = E('(6 + x)/(7776 + 6480*x + 2160*x^2 + 360*x^3 + 30*x^4 + x^5)')
print(p.factor())  # (x+6)**-4

format

Expression.format(
    mode: PrintMode = PrintMode.Symbolica,
    max_line_length: int | None = 80,
    indentation: int = 4,
    fill_indented_lines: bool = True,
    terms_on_new_line: bool = False,
    color_top_level_sum: bool = True,
    color_builtin_symbols: bool = True,
    bracket_level_colors: Sequence[int] | None = [244, 25, 97, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60],
    print_ring: bool = True,
    symmetric_representation_for_finite_field: bool = False,
    explicit_rational_polynomial: bool = False,
    number_thousands_separator: str | None = None,
    multiplication_operator: str = '*',
    double_star_for_exponentiation: bool = False,
    square_brackets_for_function: bool = False,
    function_brackets: tuple[str, str] = ('(', ')'),
    num_exp_as_superscript: bool = True,
    show_namespaces: bool = False,
    hide_namespace: str | None = None,
    include_attributes: bool = False,
    max_terms: int | None = 100,
    custom_print_mode: int | None = None,
) -> str

Convert the expression into a human-readable string, with tunable settings.

Examples

a = E('128378127123 z^(2/3)*w^2/x/y + y^4 + z^34 + x^(x+2)+3/5+f(x,x^2)')
print(a.format(number_thousands_separator='_', multiplication_operator=' '))

Yields z³⁴+x^(x+2)+y⁴+f(x,x²)+128_378_127_123 z^(2/3) w² x⁻¹ y⁻¹+3/5.

print(E('x^2 + f(x)').format(PrintMode.Sympy))

yields x**2+f(x)

print(E('x^2 + f(x)').format(PrintMode.Mathematica))

yields x^2 + f[x]

Parameters

  • mode (PrintMode) The mode that controls how the input is interpreted or formatted.
  • max_line_length (int | None) The preferred maximum line length before wrapping.
  • indentation (int) The number of spaces used for wrapped lines.
  • fill_indented_lines (bool) Whether wrapped lines should be padded to the configured indentation.
  • terms_on_new_line (bool) Whether wrapped output should place terms on separate lines.
  • color_top_level_sum (bool) Whether top-level sums should be colorized.
  • color_builtin_symbols (bool) Whether built-in symbols should be colorized.
  • bracket_level_colors (Sequence[int] | None) The colors assigned to successive nested bracket levels.
  • print_ring (bool) Whether the coefficient ring should be included in the printed output.
  • symmetric_representation_for_finite_field (bool) Whether finite-field elements should be printed using symmetric representatives.
  • explicit_rational_polynomial (bool) Whether rational polynomials should be printed explicitly as numerator and denominator.
  • number_thousands_separator (str | None) The separator inserted between groups of digits in printed integers.
  • multiplication_operator (str) The string used to print multiplication.
  • double_star_for_exponentiation (bool) Whether exponentiation should be printed as ** instead of ^.
  • square_brackets_for_function (bool) Whether function calls should be printed with square brackets.
  • function_brackets (tuple[str, str]) The opening and closing brackets used when printing function arguments.
  • num_exp_as_superscript (bool) Whether small integer exponents should be printed as superscripts.
  • show_namespaces (bool) Whether namespaces should be included in the formatted output.
  • hide_namespace (str | None) A namespace prefix to omit from printed symbol names.
  • include_attributes (bool) Whether symbol attributes should be included in the printed output.
  • max_terms (int | None) The maximum number of terms to print before truncating the output.
  • custom_print_mode (int | None) A custom print-mode identifier passed through to custom print callbacks.

format_plain

Expression.format_plain() -> str

Convert the expression into a plain string, useful for importing and exporting.

Examples

a = E('5 + x^2')
print(a.format_plain())

Yields 5 + x^2, without any coloring.

get_all_indeterminates

Expression.get_all_indeterminates(enter_functions: bool = True) -> Sequence[Expression]

Get all symbols and functions in the current expression, optionally including function symbols. The symbols are sorted in Symbolica’s internal ordering.

Parameters

  • enter_functions (bool) Whether function arguments should be traversed when collecting indeterminates.

get_all_symbol_names

Expression.get_all_symbol_names() -> list[str]

Return all defined symbol names (function names and variables).

get_all_symbols

Expression.get_all_symbols(include_function_symbols: bool = True) -> Sequence[Expression]

Get all symbols in the current expression, optionally including function symbols. The symbols are sorted in Symbolica’s internal ordering.

Parameters

  • include_function_symbols (bool) Whether function symbols should be included in the collected symbol set.

get_attributes

Expression.get_attributes() -> list[SymbolAttribute]

Get the attributes of a variable or function if the current atom is a variable or function, otherwise throw an error.

get_byte_size

Expression.get_byte_size() -> int

Get the number of bytes that this expression takes up in memory.

get_name

Expression.get_name() -> str

Get the name of a variable or function if the current atom is a variable or function, otherwise throw an error.

get_symbol_data

Expression.get_symbol_data(key: str | int | Expression | None = None) -> str | int | Expression | bytes | dict[str | int | Expression, Any] | list[Any]

Get the data of a variable or function if the current atom is a variable or function, otherwise throw an error. Optionally, provide a key to access a specific entry in the data map, if the data is a map.

Examples

x = S('x', data={'my_tag': 'my_value'})
print(x.get_symbol_data('my_tag'))  # my_value
y = S('y', data=3)
print(y.get_symbol_data())  # 3

Parameters

  • key (str | int | Expression | None) The symbol-data key to retrieve. Omit it to return all stored data.

get_tags

Expression.get_tags() -> list[str]

Get the tags of a variable or function if the current atom is a variable or function, otherwise throw an error.

get_type

Expression.get_type() -> AtomType

Get the type of the atom.

hold

Expression.hold(t: Transformer) -> HeldExpression

Create a held expression that delays the execution of the transformer t until the resulting held expression is called. Held expressions can be composed like regular expressions and are useful for the right-hand side of pattern matching, to act a transformer on a wildcard after it has been substituted.

Examples

f, x, x_ = S('f', 'x', 'x_')
e = f((x+1)**2)
e = e.replace(f(x_), f(x_.hold(T().expand())))

Parameters

  • t (Transformer) The transformer to bind to the expression.

is_constant

Expression.is_constant() -> bool

Check if the expression is constant, i.e. contains no user-defined symbols or functions.

Examples

e = E('cos(2 + exp(3)) + 5')
print(e.is_constant())  # True

is_finite

Expression.is_finite() -> bool

Check if the expression has no infinities and is not indeterminate.

Examples

e = E('1/x + x^2 + log(0)')
print(e.is_finite())  # False

is_integer

Expression.is_integer() -> bool

Check if the expression is integer. Symbols must have the integer attribute.

Examples

x = S('x', is_integer=True)
e = (x + 1)**2 + 5
print(e.is_integer())  # True

is_positive

Expression.is_positive() -> bool

Check if the expression is a positive scalar. Symbols must have the positive attribute.

Examples

x = S('x', is_positive=True)
e = (x + 1)**2 + 5
print(e.is_positive())  # True

is_real

Expression.is_real() -> bool

Check if the expression is real. Symbols must have the real attribute.

Examples

x = S('x', is_real=True)
e = (x + 1)**2 / 2 + 5
print(e.is_real())  # True

is_scalar

Expression.is_scalar() -> bool

Check if the expression is a scalar. Symbols must have the scalar attribute.

Examples

x = S('x', is_scalar=True)
e = (x + 1)**2 + 5
print(e.is_scalar())  # True

is_type

Expression.is_type(atom_type: AtomType) -> Condition

Test if the expression is of a certain type.

Parameters

  • atom_type (AtomType) The atom type to test or require.

load

Expression.load(filename: str, conflict_fn: Callable[[str], str] | None = None) -> Expression

Load an expression and its state from a file. The state will be merged with the current one. If a symbol has conflicting attributes, the conflict can be resolved using the renaming function conflict_fn.

Expressions can be saved using Expression.save.

Examples

If export.dat contains a serialized expression: f(x)+f(y):

e = Expression.load('export.dat')

whill yield f(x)+f(y).

If we have defined symbols in a different order:

y, x = S('y', 'x')
e = Expression.load('export.dat')

we get f(y)+f(x).

If we define a symbol with conflicting attributes, we can resolve the conflict using a renaming function:

x = S('x', is_symmetric=True)
e = Expression.load('export.dat', lambda x: x + '_new')
print(e)

will yield f(x_new)+f(y).

Parameters

  • filename (str) The file path to load from or save to.
  • conflict_fn (Callable[[str], str] | None) A callback that resolves symbol conflicts during loading.

log

Expression.log() -> Expression

Take the logarithm of this expression, returning the result.

map

Expression.map(
    transformations: Transformer,
    n_cores: int | None = 1,
    stats_to_file: str | None = None,
) -> Expression

Map the transformations to every term in the expression. The execution happens in parallel using n_cores.

Examples

x, x_ = S('x', 'x_')
e = (1+x)**2
r = e.map(T().expand().replace(x, 6))
print(r)

Parameters

  • transformations (Transformer) The transformations to apply.
  • n_cores (int, optional) The number of CPU cores used for parallel execution.
  • stats_to_file (str, optional) If set, the output of the stats transformer will be written to a file in JSON format.

match

Expression.match(
    lhs: Expression | int | float | complex | Decimal,
    cond: PatternRestriction | Condition | None = None,
    min_level: int = 0,
    max_level: int | None = None,
    level_range: tuple[int, int | None] | None = None,
    level_is_tree_depth: bool = False,
    partial: bool = True,
    allow_new_wildcards_on_rhs: bool = False,
) -> MatchIterator

Return an iterator over the pattern self matching to lhs. Restrictions on the pattern can be supplied through cond.

The level_range specifies the [min,max] level at which the pattern is allowed to match. The first level is 0 and the level is increased when going into a function or one level deeper in the expression tree, depending on level_is_tree_depth.

Examples

x, x_ = S('x','x_')
f = S('f')
e = f(x)*f(1)*f(2)*f(3)
for match in e.match(f(x_)):
   for map in match:
       print(map[0],'=', map[1])

Parameters

  • lhs (Expression | int | float | complex | Decimal) The expression to match against.
  • cond (PatternRestriction | Condition | None) An additional restriction that a match or replacement must satisfy.
  • min_level (int) The minimum level at which a match is allowed.
  • max_level (int | None) The maximum level at which a match is allowed.
  • level_range (tuple[int, int | None] | None) The (min_level, max_level) range in which matches are allowed.
  • level_is_tree_depth (bool) Whether levels should be measured by tree depth instead of function nesting.
  • partial (bool) Whether matches are allowed inside larger expressions instead of only at the top level.
  • allow_new_wildcards_on_rhs (bool) Whether wildcards that appear only on the right-hand side are allowed.

matches

Expression.matches(
    lhs: Expression | int | float | complex | Decimal,
    cond: PatternRestriction | Condition | None = None,
    min_level: int = 0,
    max_level: int | None = None,
    level_range: tuple[int, int | None] | None = None,
    level_is_tree_depth: bool = False,
    partial: bool = True,
    allow_new_wildcards_on_rhs: bool = False,
) -> Condition

Test whether the pattern is found in the expression. Restrictions on the pattern can be supplied through cond.

Examples

f = S('f')
if f(1).matches(f(2)):
   print('match')

Parameters

  • lhs (Expression | int | float | complex | Decimal) The expression to match against.
  • cond (PatternRestriction | Condition | None) An additional restriction that a match or replacement must satisfy.
  • min_level (int) The minimum level at which a match is allowed.
  • max_level (int | None) The maximum level at which a match is allowed.
  • level_range (tuple[int, int | None] | None) The (min_level, max_level) range in which matches are allowed.
  • level_is_tree_depth (bool) Whether levels should be measured by tree depth instead of function nesting.
  • partial (bool) Whether matches are allowed inside larger expressions instead of only at the top level.
  • allow_new_wildcards_on_rhs (bool) Whether wildcards that appear only on the right-hand side are allowed.

nsolve

nsolve has 2 variants:

Shared Notes

Find the root of an expression in x numerically over the reals using Newton’s method. Use init as the initial guess for the root. This method uses the same precision as init.

nsolve returning float

Expression.nsolve(
    variable: Expression,
    init: float,
    prec: float = 0.0001,
    max_iter: int = 10000,
) -> float

Examples

from symbolica import *
a = E("x^2-2").nsolve(E("x"), 1., 0.0001, 1000000)

Parameters

  • variable (Expression) The variable to solve for.
  • init (float) The initial guess for Newton’s method.
  • prec (float) The numerical tolerance for the Newton iteration.
  • max_iter (int) The maximum number of Newton iterations.

nsolve returning Decimal

Expression.nsolve(
    variable: Expression,
    init: Decimal,
    prec: float = 0.0001,
    max_iter: int = 10000,
) -> Decimal

Examples

from symbolica import *
a = E("x^2-2").nsolve(E("x"),
              Decimal("1.000000000000000000000000000000000000000000000000000000000000000000000000"), 1e-74, 1000000)

Parameters

  • variable (Expression) The variable to solve for.
  • init (Decimal) The initial guess for Newton’s method.
  • prec (float) The numerical tolerance for the Newton iteration.
  • max_iter (int) The maximum number of Newton iterations.

nsolve_system

nsolve_system has 2 variants:

Shared Notes

Find a common root of multiple expressions in variables numerically over the reals using Newton’s method. Use init as the initial guess for the root. This method uses the same precision as init.

nsolve_system returning Sequence[float]

Expression.nsolve_system(
    system: Sequence[Expression],
    variables: Sequence[Expression],
    init: Sequence[float],
    prec: float = 0.0001,
    max_iter: int = 10000,
) -> Sequence[float]

Examples

from symbolica import *
a = Expression.nsolve_system([E("5x^2+x*y^2+sin(2y)^2 - 2"), E("exp(2x-y)+4y - 3")], [S("x"), S("y")],
                     [1., 1.], 1e-20, 1000000)

Parameters

  • system (Sequence[Expression]) The equations or polynomials that define the system.
  • variables (Sequence[Expression]) The variables to solve for, in order.
  • init (Sequence[float]) The initial guess for Newton’s method.
  • prec (float) The numerical tolerance for the Newton iteration.
  • max_iter (int) The maximum number of Newton iterations.

nsolve_system returning Sequence[Decimal]

Expression.nsolve_system(
    system: Sequence[Expression],
    variables: Sequence[Expression],
    init: Sequence[Decimal],
    prec: float = 0.0001,
    max_iter: int = 10000,
) -> Sequence[Decimal]

Examples

from symbolica import *
a = Expression.nsolve_system([E("5x^2+x*y^2+sin(2y)^2 - 2"), E("exp(2x-y)+4y - 3")], [S("x"), S("y")],
                     [Decimal("1.00000000000000000"), Decimal("1.00000000000000000")], 1e-20, 1000000)

Parameters

  • system (Sequence[Expression]) The equations or polynomials that define the system.
  • variables (Sequence[Expression]) The variables to solve for, in order.
  • init (Sequence[Decimal]) The initial guess for Newton’s method.
  • prec (float) The numerical tolerance for the Newton iteration.
  • max_iter (int) The maximum number of Newton iterations.

num

Expression.num(
    num: int | float | complex | str | Decimal,
    relative_error: float | None = None,
) -> Expression

Create a new Symbolica number from an int, a float, or a string. A floating point number is kept as a float with the same precision as the input, but it can also be converted to the smallest rational number given a relative_error.

Examples

e = Expression.num(1) / 2
print(e)  # 1/2
print(Expression.num(1/3))
print(Expression.num(0.33, 0.1))
print(Expression.num('0.333`3'))
print(Expression.num(Decimal('0.1234')))
3.3333333333333331e-1
1/3
3.33e-1
1.2340e-1

Parameters

  • num (int | float | complex | str | Decimal) The value to convert into a Symbolica number.
  • relative_error (float | None) The maximum relative error used when converting floating-point input to a rational number.

parse

Expression.parse(
    input: str,
    mode: ParseMode = ParseMode.Symbolica,
    default_namespace: str | None = None,
) -> Expression

Parse a Symbolica expression from a string.

Examples

e = E('x^2+y+y*4')
print(e) # x^2+5*y

Parse a Mathematica expression:

e = E('Cos[test`x] (2 + 3 I)', mode=ParseMode.Mathematica)
print(e) # cos(test::x)(2+3i)

Parameters

  • input (str) An input string. UTF-8 characters are allowed.
  • mode (ParseMode) The parsing mode. Use ParseMode.Mathematica to parse Mathematica expressions.
  • default_namespace (str) The namespace assumed for unqualified symbols during parsing.

Raises

  • ValueError: If the input is not a valid expression.

rationalize

Expression.rationalize(relative_error: float = 0.01) -> Expression

Map all floating point and rational coefficients to the best rational approximation in the interval [self*(1-relative_error),self*(1+relative_error)].

Parameters

  • relative_error (float) The maximum relative error used when converting floating-point input to a rational number.

replace

Expression.replace(
    pattern: Expression | int | float | complex | Decimal,
    rhs: HeldExpression | Expression | Callable[[dict[Expression, Expression]], Expression] | int | float | complex | Decimal,
    cond: PatternRestriction | Condition | None = None,
    non_greedy_wildcards: Sequence[Expression] | None = None,
    min_level: int = 0,
    max_level: int | None = None,
    level_range: tuple[int, int | None] | None = None,
    level_is_tree_depth: bool = False,
    partial: bool = True,
    allow_new_wildcards_on_rhs: bool = False,
    rhs_cache_size: int | None = None,
    repeat: bool = False,
    once: bool = False,
    bottom_up: bool = False,
    nested: bool = False,
) -> Expression

Replace all subexpressions matching the pattern pattern by the right-hand side rhs. The right-hand side can be an expression with wildcards, a held expression (see :meth:Expression.hold) or a function that maps a dictionary of wildcards to an expression.

Examples

x, w1_, w2_ = S('x','w1_','w2_')
f = S('f')
e = f(3,x)
r = e.replace(f(w1_,w2_), f(w1_ - 1, w2_**2), w1_ >= 1)
print(r)

Parameters

  • self The expression to match and replace on.
  • pattern The pattern to match.
  • rhs The right-hand side to replace the matched subexpression with. Can be a transformer, expression or a function that maps a dictionary of wildcards to an expression.
  • cond (PatternRestriction | Condition, optional) Conditions on the pattern.
  • non_greedy_wildcards (Sequence[Expression], optional) Wildcards that try to match as little as possible.
  • min_level (int, optional) The minimum level at which the pattern is allowed to match. The first level is 0 and the level is increased when going into a function or one level deeper in the expression tree, depending on level_is_tree_depth.
  • max_level (int | None, optional) The maximum level at which the pattern is allowed to match. None means no maximum.
  • level_range Specifies the [min,max] level at which the pattern is allowed to match. The first level is 0 and the level is increased when going into a function or one level deeper in the expression tree, depending on level_is_tree_depth. Prefer setting min_level and max_level directly over level_range, as this argument will be deprecated in the future.
  • level_is_tree_depth (bool, optional) If set to True, the level is increased when going one level deeper in the expression tree.
  • partial (bool, optional) If set to True, allow the pattern to match to a part of a term. For example, with partial=True, the pattern x+y matches to x+2+y.
  • allow_new_wildcards_on_rhs (bool, optional) If set to True, allow wildcards that do not appear in the pattern on the right-hand side.
  • rhs_cache_size (int, optional) Cache the first rhs_cache_size substituted patterns. If set to None, an internally determined cache size is used. Warning: caching should be disabled (rhs_cache_size=0) if the right-hand side contains side effects, such as updating a global variable.
  • repeat (bool, optional) If set to True, the entire operation will be repeated until there are no more matches.
  • once (bool, optional) If set to True, only the first match will be replaced, instead of all non-overlapping matches.
  • bottom_up (bool, optional) Replace deepest nested matches first instead of replacing the outermost matches first. For example, replacing f(x_) with x_^2 in f(f(x)) would yield f(x)^2 with the default settings and f(x^2) with bottom-up replacement.
  • nested (bool, optional) Replace nested matches, starting from the deepest first and acting on the result of that replacement. For example, replacing f(x_) with x_^2 in f(f(x)) would yield f(x)^2 with the default settings and f(x^2)^2 with nested replacement.

replace_iter

Expression.replace_iter(
    lhs: Expression | int | float | complex | Decimal,
    rhs: HeldExpression | Expression | Callable[[dict[Expression, Expression]], Expression] | int | float | complex | Decimal,
    cond: PatternRestriction | Condition | None = None,
    min_level: int = 0,
    max_level: int | None = None,
    level_range: tuple[int, int | None] | None = None,
    level_is_tree_depth: bool = False,
    partial: bool = True,
    allow_new_wildcards_on_rhs: bool = False,
) -> ReplaceIterator

Return an iterator over the replacement of the pattern self on lhs by rhs. Restrictions on pattern can be supplied through cond.

Examples

from symbolica import *
x_ = S('x_')
f = S('f')
e = f(1)*f(2)*f(3)
for r in e.replace_iter(f(x_), f(x_ + 1)):
    print(r)

Yields:

f(2)*f(2)*f(3) f(1)*f(3)*f(3) f(1)*f(2)*f(4)

Parameters

  • lhs The pattern to match.
  • rhs The right-hand side to replace the matched subexpression with. Can be a transformer, expression or a function that maps a dictionary of wildcards to an expression.
  • cond Conditions on the pattern.
  • min_level (int, optional) The minimum level at which the pattern is allowed to match. The first level is 0 and the level is increased when going into a function or one level deeper in the expression tree, depending on level_is_tree_depth.
  • max_level (int | None, optional) The maximum level at which the pattern is allowed to match. None means no maximum.
  • level_range Specifies the [min,max] level at which the pattern is allowed to match. The first level is 0 and the level is increased when going into a function or one level deeper in the expression tree, depending on level_is_tree_depth. Prefer setting min_level and max_level directly over level_range, as this argument will be deprecated in the future.
  • level_is_tree_depth (bool, optional) If set to True, the level is increased when going one level deeper in the expression tree.
  • partial (bool, optional) If set to True, allow the pattern to match to a part of a term. For example, with partial=True, the pattern x+y matches to x+2+y.
  • allow_new_wildcards_on_rhs (bool, optional) If set to True, allow wildcards that do not appear in the pattern on the right-hand side.

replace_multiple

Expression.replace_multiple(
    replacements: Sequence[Replacement],
    repeat: bool = False,
    once: bool = False,
    bottom_up: bool = False,
    nested: bool = False,
) -> Expression

Replace all atoms matching the patterns. See replace for more information.

The entire operation can be repeated until there are no more matches using repeat=True.

Examples

x, y, f = S('x', 'y', 'f')
e = f(x,y)
r = e.replace_multiple([Replacement(x, y), Replacement(y, x)])
print(r)  # f(y,x)

Parameters

  • replacements (Sequence[Replacement]) The list of replacements to apply.
  • repeat (bool, optional) If set to True, the entire operation will be repeated until there are no more matches.

replace_wildcards

Expression.replace_wildcards(replacements: dict[Expression, Expression]) -> Expression

Replace all wildcards in the expression with the corresponding values in replacements. This function can be used to substitute the result from (see :meth:Expression.match) into its pattern.

Examples

x, x_, f= S('x', 'x_', 'f')
e = 1 + x + f(2)
p = f(x_)
r = next(e.match(p))
p.replace_wildcards(r)
f(2)

Parameters

  • replacements (dict[Expression, Expression]) A map of wildcards to their replacements.

req

Expression.req(filter_fn: Callable[[Expression], bool | Condition]) -> PatternRestriction

Create a new pattern restriction that calls the function filter_fn with the matched atom that should return a boolean. If true, the pattern matches.

Examples

from symbolica import *
x_ = S('x_')
f = S('f')
e = f(1)*f(2)*f(3)
e = e.replace(f(x_), 1, x_.req(lambda m: m == 2 or m == 3))

Parameters

  • filter_fn (Callable[[Expression], bool | Condition]) A callback that filters partially constructed graphs.

req_attr

Expression.req_attr(tag: SymbolAttribute) -> PatternRestriction

Create a pattern restriction based on the attributes of a matched variable or function.

Examples

from symbolica import *
x = S('f', is_linear=True)
x_ = S('x_')
print(E('f(x)').replace(E('x_(x)'), 1, ~S('x_').req_attr(SymbolAttribute.Linear)))
print(e)  # f(x)

Parameters

  • tag (SymbolAttribute) The tag to test or require.

req_cmp

Expression.req_cmp(
    other: Expression | int | float | complex | Decimal,
    cmp_fn: Callable[[Expression, Expression], bool | Condition],
) -> PatternRestriction

Create a new pattern restriction that calls the function cmp_fn with another the matched atom and the match atom of the other wildcard that should return a boolean. If true, the pattern matches.

Examples

from symbolica import *
x_, y_ = S('x_', 'y_')
f = S('f')
e = f(1)*f(2)*f(3)
e = e.replace(f(x_)*f(y_), 1, x_.req_cmp(y_, lambda m1, m2: m1 + m2 == 4))

Parameters

  • other (Expression | int | float | complex | Decimal) The other operand to combine or compare with.
  • cmp_fn (Callable[[Expression, Expression], bool | Condition]) The comparison callback applied to the matched values.

req_cmp_ge

Expression.req_cmp_ge(num: Expression, cmp_any_atom = False) -> PatternRestriction

Create a pattern restriction that passes when the wildcard is greater than or equal to another wildcard. If the matched wildcards are not a numbers, the pattern fails.

When the option cmp_any_atom is set to True, this function compares atoms of any type. The result depends on the internal ordering and may change between different Symbolica versions.

Examples

from symbolica import *
x_, y_ = S('x_', 'y_')
f = S('f')
e = f(1,2)
e = e.replace(f(x_,y_), 1, x_.req_cmp_ge(y_))

Parameters

  • num (Expression) The expression that the match is compared against.
  • cmp_any_atom (Any) Whether the comparison may be satisfied by any atom in the expression instead of only the whole match.

req_cmp_gt

Expression.req_cmp_gt(num: Expression, cmp_any_atom = False) -> PatternRestriction

Create a pattern restriction that passes when the wildcard is greater than another wildcard. If the matched wildcards are not a numbers, the pattern fails.

When the option cmp_any_atom is set to True, this function compares atoms of any type. The result depends on the internal ordering and may change between different Symbolica versions.

Examples

from symbolica import *
x_, y_ = S('x_', 'y_')
f = S('f')
e = f(1,2)
e = e.replace(f(x_,y_), 1, x_.req_cmp_gt(y_))

Parameters

  • num (Expression) The expression that the match is compared against.
  • cmp_any_atom (Any) Whether the comparison may be satisfied by any atom in the expression instead of only the whole match.

req_cmp_le

Expression.req_cmp_le(num: Expression, cmp_any_atom = False) -> PatternRestriction

Create a pattern restriction that passes when the wildcard is smaller than or equal to another wildcard. If the matched wildcards are not a numbers, the pattern fails.

When the option cmp_any_atom is set to True, this function compares atoms of any type. The result depends on the internal ordering and may change between different Symbolica versions.

Examples

from symbolica import *
x_, y_ = S('x_', 'y_')
f = S('f')
e = f(1,2)
e = e.replace(f(x_,y_), 1, x_.req_cmp_le(y_))

Parameters

  • num (Expression) The expression that the match is compared against.
  • cmp_any_atom (Any) Whether the comparison may be satisfied by any atom in the expression instead of only the whole match.

req_cmp_lt

Expression.req_cmp_lt(num: Expression, cmp_any_atom = False) -> PatternRestriction

Create a pattern restriction that passes when the wildcard is smaller than another wildcard. If the matched wildcards are not a numbers, the pattern fails.

When the option cmp_any_atom is set to True, this function compares atoms of any type. The result depends on the internal ordering and may change between different Symbolica versions.

Examples

from symbolica import *
x_, y_ = S('x_', 'y_')
f = S('f')
e = f(1,2)
e = e.replace(f(x_,y_), 1, x_.req_cmp_lt(y_))

Parameters

  • num (Expression) The expression that the match is compared against.
  • cmp_any_atom (Any) Whether the comparison may be satisfied by any atom in the expression instead of only the whole match.

req_contains

Expression.req_contains(a: Expression) -> PatternRestriction

Create a pattern restriction that filters for expressions that contain a.

Parameters

  • a (Expression) The expression that must occur inside the match.

req_ge

Expression.req_ge(
    num: Expression | int | float | complex | Decimal,
    cmp_any_atom = False,
) -> PatternRestriction

Create a pattern restriction that passes when the wildcard is greater than or equal to a number num. If the matched wildcard is not a number, the pattern fails.

When the option cmp_any_atom is set to True, this function compares atoms of any type. The result depends on the internal ordering and may change between different Symbolica versions.

Examples

from symbolica import *
x_ = S('x_')
f = S('f')
e = f(1)*f(2)*f(3)
e = e.replace(f(x_), 1, x_.req_ge(2))

Parameters

  • num (Expression | int | float | complex | Decimal) The value that the match is compared against.
  • cmp_any_atom (Any) Whether the comparison may be satisfied by any atom in the expression instead of only the whole match.

req_gt

Expression.req_gt(
    num: Expression | int | float | complex | Decimal,
    cmp_any_atom = False,
) -> PatternRestriction

Create a pattern restriction that passes when the wildcard is greater than a number num. If the matched wildcard is not a number, the pattern fails.

When the option cmp_any_atom is set to True, this function compares atoms of any type. The result depends on the internal ordering and may change between different Symbolica versions.

Examples

from symbolica import *
x_ = S('x_')
f = S('f')
e = f(1)*f(2)*f(3)
e = e.replace(f(x_), 1, x_.req_gt(2))

Parameters

  • num (Expression | int | float | complex | Decimal) The value that the match is compared against.
  • cmp_any_atom (Any) Whether the comparison may be satisfied by any atom in the expression instead of only the whole match.

req_le

Expression.req_le(
    num: Expression | int | float | complex | Decimal,
    cmp_any_atom = False,
) -> PatternRestriction

Create a pattern restriction that passes when the wildcard is smaller than or equal to a number num. If the matched wildcard is not a number, the pattern fails.

When the option cmp_any_atom is set to True, this function compares atoms of any type. The result depends on the internal ordering and may change between different Symbolica versions.

Examples

from symbolica import *
x_ = S('x_')
f = S('f')
e = f(1)*f(2)*f(3)
e = e.replace(f(x_), 1, x_.req_le(2))

Parameters

  • num (Expression | int | float | complex | Decimal) The value that the match is compared against.
  • cmp_any_atom (Any) Whether the comparison may be satisfied by any atom in the expression instead of only the whole match.

req_len

Expression.req_len(min_length: int, max_length: int | None) -> PatternRestriction

Create a pattern restriction based on the wildcard length before downcasting.

Parameters

  • min_length (int) The minimum required match length.
  • max_length (int | None) The maximum allowed match length.

req_lit

Expression.req_lit() -> PatternRestriction

Create a pattern restriction that treats the wildcard as a literal variable, so that it only matches to itself.

req_lt

Expression.req_lt(
    num: Expression | int | float | complex | Decimal,
    cmp_any_atom = False,
) -> PatternRestriction

Create a pattern restriction that passes when the wildcard is smaller than a number num. If the matched wildcard is not a number, the pattern fails.

When the option cmp_any_atom is set to True, this function compares atoms of any type. The result depends on the internal ordering and may change between different Symbolica versions.

Examples

from symbolica import *
x_ = S('x_')
f = S('f')
e = f(1)*f(2)*f(3)
e = e.replace(f(x_), 1, x_.req_lt(2))

Parameters

  • num (Expression | int | float | complex | Decimal) The value that the match is compared against.
  • cmp_any_atom (Any) Whether the comparison may be satisfied by any atom in the expression instead of only the whole match.

req_tag

Expression.req_tag(tag: str) -> PatternRestriction

Create a pattern restriction based on the tag of a matched variable or function.

Examples

from symbolica import *
x = S('x', tags=['a', 'b'])
x_ = S('x_')
e = x.replace(x_, 1, x_.req_tag('b'))
print(e)  # 1

Parameters

  • tag (str) The tag to test or require.

req_type

Expression.req_type(atom_type: AtomType) -> PatternRestriction

Create a pattern restriction that tests the type of the atom.

Examples

from symbolica import *
x, x_ = S('x', 'x_')
f = S('f')
e = f(x)*f(2)*f(f(3))
e = e.replace(f(x_), 1, x_.req_type(AtomType.Num))
print(e)  # f(x)*f(1)

Parameters

  • atom_type (AtomType) The atom type to test or require.

save

Expression.save(filename: str, compression_level: int = 9)

Save the expression and its state to a binary file. The data is compressed and the compression level can be set between 0 and 11.

The data can be loaded using Expression.load.

Examples

e = E("f(x)+f(y)").expand()
e.save('export.dat')

Parameters

  • filename (str) The file path to load from or save to.
  • compression_level (int) The compression level for serialized output.

series

Expression.series(
    x: Expression,
    expansion_point: Expression | int | float | complex | Decimal,
    depth: int,
    depth_denom: int = 1,
    depth_is_absolute: bool = True,
) -> Series

Series expand in x around expansion_point to depth depth.

Examples

p = E('cos(x)/(x+1)')
print(p.series(S('x'), 0, 3))

yields -1-x-1/2*x^2-1/2*x^3+𝒪(x^4)

Parameters

  • x (Expression) The variable to expand in.
  • expansion_point (Expression | int | float | complex | Decimal) The point around which to expand.
  • depth (int) The depth of the expansion.
  • depth_denom (int, optional) The denominator of the depth (for a rational depth), by default 1.
  • depth_is_absolute (bool, optional) If True, depth is the absolute depth in x; if False, depth is the relative to the lowest order encountered in the expression.

set_coefficient_ring

Expression.set_coefficient_ring(vars: Sequence[Expression]) -> Expression

Set the coefficient ring to contain the variables in the vars list. This will move all variables into a rational polynomial function.

Parameters

  • vars (Sequence[Expression]) A list of variables

sin

Expression.sin() -> Expression

Take the sine of this expression, returning the result.

solve_linear_system

Expression.solve_linear_system(
    system: Sequence[Expression],
    variables: Sequence[Expression],
    warn_if_underdetermined: bool = True,
) -> Sequence[Expression]

Solve a linear system in the variables variables, where each expression in the system is understood to yield 0.

If the system is underdetermined, a partial solution is returned where each bound variable is a linear combination of the free variables. The free variables are chosen such that they have the highest index in the vars list.

Examples

from symbolica import *
x, y, c = S('x', 'y', 'c')
f = S('f')
x_r, y_r = Expression.solve_linear_system([f(c)*x + y/c - 1, y-c/2], [x, y])
print('x =', x_r, ', y =', y_r)

Parameters

  • system (Sequence[Expression]) The equations or polynomials that define the system.
  • variables (Sequence[Expression]) The variables to solve for, in order.
  • warn_if_underdetermined (bool) Whether to warn when the system is underdetermined.

sqrt

Expression.sqrt() -> Expression

Take the square root of this expression, returning the result.

symbol

symbol 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.

symbol returning Expression

Expression.symbol(
    name: str,
    is_symmetric: bool | None = None,
    is_antisymmetric: bool | None = None,
    is_cyclesymmetric: bool | None = None,
    is_linear: 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,
    custom_normalization: Transformer | None = None,
    custom_print: Callable[..., str | None] | None = None,
    custom_derivative: Callable[[Expression, int], Expression] | None = None,
    data: str | int | Expression | bytes | list[Any] | dict[str | int | Expression, Any] | None = None,
) -> Expression

Examples

Define a regular symbol and use it as a variable:

x = S('x')
e = x**2 + 5
print(e)  # x**2 + 5

Define 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 = S('p1', 'p2', 'p3', 'p4')
dot = S('dot', is_symmetric=True, is_linear=True)
e = dot(p2+2*p3,p1+3*p2-p3)
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', custom_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, latex: bool, **kwargs) -> str | None:
    if latex:
        if mu.get_type() == AtomType.Fn:
            return "\mu_{" + ",".join(a.format() for a in mu) + "}"
        else:
            return "\mu"
mu = S("mu", custom_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', custom_derivative=lambda f, index: f)
x = S('x')
tag(3, x).derivative(x)

Add custom data to a symbol:

x = S('x', data={'my_tag': 'my_value'})
r = x.get_symbol_data('my_tag')

Parameters

  • name (str) The name of the symbol
  • 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 linear.
  • 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) A list of tags to associate with the symbol.
  • aliases (Sequence[str] | None) A list of aliases to associate with the symbol.
  • custom_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.
  • custom_print (Callable[…, str | None] | None:) A function that is called when printing the variable/function, which is provided as its first argument. This function should return a string, or None if the default print function should be used. The custom print function takes in keyword arguments that are the same as the arguments of the format function.
  • custom_derivative (Callable[[Expression, int], Expression] | None:) A function that is called when computing the derivative of a function in a given argument.
  • data (str | int | Expression | bytes | list | dict | None = None) Custom user data to associate with the symbol.

symbol returning Sequence[Expression]

Expression.symbol(
    *names: str,
    is_symmetric: bool | None = None,
    is_antisymmetric: bool | None = None,
    is_cyclesymmetric: bool | None = None,
    is_linear: bool | None = None,
    is_real: bool | None = None,
    is_scalar: bool | None = None,
    is_integer: bool | None = None,
    is_positive: bool | None = None,
    tags: Sequence[str] | None = None,
) -> Sequence[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

  • name (str) The name of the symbol
  • 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_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) A list of tags to associate with the symbol.

to_atom_tree

Expression.to_atom_tree() -> AtomTree

Convert the expression to a tree.

to_canonical_string

Expression.to_canonical_string() -> str

Convert the expression into a canonical string that is independent on the order of the variables and other implementation details.

to_float

Expression.to_float(decimal_prec: int = 16) -> Expression

Convert all coefficients and built-in functions to floats with a given precision decimal_prec. The precision of floating point coefficients in the input will be truncated to decimal_prec.

Parameters

  • decimal_prec (int) The decimal precision used during numerical evaluation.

to_int

Expression.to_int() -> int

Convert the expression to an integer if possible. Raises a ValueError if the expression is not an integer.

Examples

e = E('7')
n = e.to_int()

to_latex

Expression.to_latex() -> str

Convert the expression into a LaTeX string.

Examples

a = E('128378127123 z^(2/3)*w^2/x/y + y^4 + z^34 + x^(x+2)+3/5+f(x,x^2)')
print(a.to_latex())

Yields $$z^{34}+x^{x+2}+y^{4}+f(x,x^{2})+128378127123 z^{\frac{2}{3}} w^{2} \frac{1}{x} \frac{1}{y}+\frac{3}{5}$$.

to_mathematica

Expression.to_mathematica(show_namespaces: bool = True) -> str

Convert the expression into a Mathematica-parsable string.

Examples

a = E('cos(x+2i + 3)+sqrt(conj(x)) + test::y')
print(a.to_mathematica(show_namespaces=True))

Yields test`y+Cos[x+3+2I]+Sqrt[Conjugate[x]].

Parameters

  • show_namespaces (bool) Whether namespaces should be included in the formatted output.

to_polynomial

to_polynomial has 3 variants:

to_polynomial returning Polynomial

Expression.to_polynomial(vars: Sequence[Expression] | None = None) -> Polynomial

Convert the expression to a polynomial, optionally, with the variable ordering specified in vars. All non-polynomial parts will be converted to new, independent variables.

Parameters

  • vars (Sequence[Expression] | None) The variables treated as polynomial variables, in the given order.

to_polynomial returning NumberFieldPolynomial

Expression.to_polynomial(
    minimal_poly: Polynomial,
    vars: Sequence[Expression] | None = None,
) -> NumberFieldPolynomial

Convert the expression to a polynomial, optionally, with the variables and the ordering specified in vars. All non-polynomial elements will be converted to new independent variables.

The coefficients will be converted to a number field with the minimal polynomial minimal_poly. The minimal polynomial must be a monic, irreducible univariate polynomial.

Parameters

  • minimal_poly (Polynomial) The minimal polynomial that defines the algebraic extension.
  • vars (Sequence[Expression] | None) The variables treated as polynomial variables, in the given order.

to_polynomial returning FiniteFieldPolynomial

Expression.to_polynomial(
    modulus: int,
    power: tuple[int, Expression] | None = None,
    minimal_poly: Polynomial | None = None,
    vars: Sequence[Expression] | None = None,
) -> FiniteFieldPolynomial

Convert the expression to a polynomial, optionally, with the variables and the ordering specified in vars. All non-polynomial elements will be converted to new independent variables.

The coefficients will be converted to finite field elements modulo modulus. If on top a power is provided, for example (2, a), the polynomial will be converted to the Galois field GF(modulus^2) where a is the variable of the minimal polynomial of the field.

If a minimal_poly is provided, the Galois field will be created with minimal_poly as the minimal polynomial.

Parameters

  • modulus (int) The modulus that defines the finite field.
  • power (tuple[int, Expression] | None) The extension degree and generator that define the finite field.
  • minimal_poly (Polynomial | None) The minimal polynomial that defines the algebraic extension.
  • vars (Sequence[Expression] | None) The variables treated as polynomial variables, in the given order.

to_rational_polynomial

Expression.to_rational_polynomial(vars: Sequence[Expression] | None = None) -> RationalPolynomial

Convert the expression to a rational polynomial, optionally, with the variable ordering specified in vars. The latter is useful if it is known in advance that more variables may be added in the future to the rational polynomial through composition with other rational polynomials.

All non-rational polynomial parts are converted to new, independent variables.

Examples

a = E('(1 + 3*x1 + 5*x2 + 7*x3 + 9*x4 + 11*x5 + 13*x6 + 15*x7)^2 - 1').to_rational_polynomial()
print(a)

Parameters

  • vars (Sequence[Expression] | None) The variables treated as polynomial variables, in the given order.

to_sympy

Expression.to_sympy() -> str

Convert the expression into a sympy-parsable string.

Examples

from sympy import *
s = sympy.parse_expr(E('x^2+f((1+x)^y)').to_sympy())

to_typst

Expression.to_typst(show_namespaces: bool = False) -> str

Convert the expression into a Typst string.

Examples

a = E('f(x+2i + 3) * 2 / x')
print(a.to_typst())

Yields (2 op("f")(3+2𝑖+"x"))/"x".

Parameters

  • show_namespaces (bool) Whether namespaces should be included in the formatted output.

together

Expression.together() -> Expression

Write the expression over a common denominator.

Examples

from symbolica import *
p = E('v1^2/2+v1^3/v4*v2+v3/(1+v4)')
print(p.together())