# devito.symbolics package¶

## devito.symbolics.extended_sympy module¶

Extended SymPy hierarchy.

class devito.symbolics.extended_sympy.FrozenExpr[source]

Bases: sympy.core.expr.Expr

Use FrozenExpr in place of sympy.Expr to make sure than an expression is no longer transformable; that is, standard manipulations such as xreplace, collect, expand, … have no effect, thus building a new expression identical to self.

At the moment, only xreplace is overridded (to prevent unpicking factorizations)

default_assumptions = {}
xreplace(rule)[source]

Replace occurrences of objects within the expression.

rule : dict-like
Expresses a replacement rule

xreplace : the result of the replacement

>>> from sympy import symbols, pi, exp
>>> x, y, z = symbols('x y z')
>>> (1 + x*y).xreplace({x: pi})
pi*y + 1
>>> (1 + x*y).xreplace({x: pi, y: 2})
1 + 2*pi


Replacements occur only if an entire node in the expression tree is matched:

>>> (x*y + z).xreplace({x*y: pi})
z + pi
>>> (x*y*z).xreplace({x*y: pi})
x*y*z
>>> (2*x).xreplace({2*x: y, x: z})
y
>>> (2*2*x).xreplace({2*x: y, x: z})
4*z
>>> (x + y + 2).xreplace({x + y: 2})
x + y + 2
>>> (x + 2 + exp(x + 2)).xreplace({x + 2: y})
x + exp(y) + 2


xreplace doesn’t differentiate between free and bound symbols. In the following, subs(x, y) would not change x since it is a bound symbol, but xreplace does:

>>> from sympy import Integral
>>> Integral(x, (x, 1, 2*x)).xreplace({x: y})
Integral(y, (y, 1, 2*y))


Trying to replace x with an expression raises an error:

>>> Integral(x, (x, 1, 2*x)).xreplace({x: 2*y})
ValueError: Invalid limits given: ((2*y, 1, 4*y),)

replace: replacement capable of doing wildcard-like matching,
parsing of match, and conditional replacements
subs: substitution of subexpressions as defined by the objects
themselves.
class devito.symbolics.extended_sympy.Eq[source]

Bases: sympy.core.relational.Equality, devito.symbolics.extended_sympy.FrozenExpr

A customized version of sympy.Eq which suppresses evaluation.

default_assumptions = {}
class devito.symbolics.extended_sympy.CondEq[source]

Bases: sympy.core.relational.Equality, devito.symbolics.extended_sympy.FrozenExpr

A customized version of sympy.Eq representing a conditional equality. It suppresses evaluation.

canonical

Return a canonical form of the relational by putting a Number on the rhs else ordering the args. No other simplification is attempted.

>>> from sympy.abc import x, y
>>> x < 2
x < 2
>>> _.reversed.canonical
x < 2
>>> (-y < x).canonical
x > -y
>>> (-y > x).canonical
x < -y

default_assumptions = {}
class devito.symbolics.extended_sympy.CondNe[source]

Bases: sympy.core.relational.Unequality, devito.symbolics.extended_sympy.FrozenExpr

A customized version of sympy.Ne representing a conditional inequality. It suppresses evaluation.

canonical

Return a canonical form of the relational by putting a Number on the rhs else ordering the args. No other simplification is attempted.

>>> from sympy.abc import x, y
>>> x < 2
x < 2
>>> _.reversed.canonical
x < 2
>>> (-y < x).canonical
x > -y
>>> (-y > x).canonical
x < -y

default_assumptions = {}
class devito.symbolics.extended_sympy.Mul[source]

Bases: sympy.core.mul.Mul, devito.symbolics.extended_sympy.FrozenExpr

default_assumptions = {}
class devito.symbolics.extended_sympy.Add[source]

Bases: sympy.core.add.Add, devito.symbolics.extended_sympy.FrozenExpr

default_assumptions = {}
class devito.symbolics.extended_sympy.Pow[source]

Bases: sympy.core.power.Pow, devito.symbolics.extended_sympy.FrozenExpr

default_assumptions = {}
class devito.symbolics.extended_sympy.IntDiv[source]

Bases: sympy.core.expr.Expr

A support type for integer division. Should only be used by the compiler for code generation purposes (i.e., not for symbolic manipulation). This works around the annoying way SymPy represents integer division, namely as a Mul between the numerator and the reciprocal of the denominator (e.g., a*3.args -> (a, 1/3)), which ends up generating “weird” C code.

default_assumptions = {}
is_Atom = True
class devito.symbolics.extended_sympy.FunctionFromPointer[source]

Bases: sympy.core.expr.Expr, devito.tools.abc.Pickable

Symbolic representation of the C notation pointer->function(params).

base
default_assumptions = {}
class devito.symbolics.extended_sympy.FieldFromPointer[source]

Symbolic representation of the C notation pointer->field.

default_assumptions = {}
field
class devito.symbolics.extended_sympy.FieldFromComposite[source]

Symbolic representation of the C notation composite.field, where composite is a struct/union/…

composite
default_assumptions = {}
field
class devito.symbolics.extended_sympy.ListInitializer[source]

Bases: sympy.core.expr.Expr, devito.tools.abc.Pickable

Symbolic representation of the C++ list initializer notation {a, b, ...}.

default_assumptions = {}
class devito.symbolics.extended_sympy.Byref[source]

Bases: sympy.core.symbol.Symbol, devito.tools.abc.Pickable

Symbolic representation of the C++ notation &symbol.

default_assumptions = {}
class devito.symbolics.extended_sympy.Macro[source]

Bases: sympy.core.symbol.Symbol

Symbolic representation of a C++ macro.

default_assumptions = {}
class devito.symbolics.extended_sympy.taylor_sin[source]

Bases: sympy.functions.elementary.trigonometric.TrigonometricFunction

Approximation of the sine function using a Taylor polynomial.

default_assumptions = {}
classmethod eval(arg)[source]

Returns a canonical form of cls applied to arguments args.

The eval() method is called when the class cls is about to be instantiated and it should return either some simplified instance (possible of some other class), or if the class cls should be unmodified, return None.

@classmethod
def eval(cls, arg):
if arg is S.NaN:
return S.NaN
if arg is S.Zero: return S.Zero
if arg.is_positive: return S.One
if arg.is_negative: return S.NegativeOne
if isinstance(arg, Mul):
coeff, terms = arg.as_coeff_Mul(rational=True)
if coeff is not S.One:
return cls(coeff) * cls(terms)

class devito.symbolics.extended_sympy.taylor_cos[source]

Bases: sympy.functions.elementary.trigonometric.TrigonometricFunction

Approximation of the cosine function using a Taylor polynomial.

default_assumptions = {}
classmethod eval(arg)[source]

Returns a canonical form of cls applied to arguments args.

The eval() method is called when the class cls is about to be instantiated and it should return either some simplified instance (possible of some other class), or if the class cls should be unmodified, return None.

@classmethod
def eval(cls, arg):
if arg is S.NaN:
return S.NaN
if arg is S.Zero: return S.Zero
if arg.is_positive: return S.One
if arg.is_negative: return S.NegativeOne
if isinstance(arg, Mul):
coeff, terms = arg.as_coeff_Mul(rational=True)
if coeff is not S.One:
return cls(coeff) * cls(terms)

class devito.symbolics.extended_sympy.bhaskara_sin[source]

Bases: sympy.functions.elementary.trigonometric.TrigonometricFunction

Approximation of the sine function using a Bhaskara polynomial.

default_assumptions = {}
classmethod eval(arg)[source]

Returns a canonical form of cls applied to arguments args.

The eval() method is called when the class cls is about to be instantiated and it should return either some simplified instance (possible of some other class), or if the class cls should be unmodified, return None.

@classmethod
def eval(cls, arg):
if arg is S.NaN:
return S.NaN
if arg is S.Zero: return S.Zero
if arg.is_positive: return S.One
if arg.is_negative: return S.NegativeOne
if isinstance(arg, Mul):
coeff, terms = arg.as_coeff_Mul(rational=True)
if coeff is not S.One:
return cls(coeff) * cls(terms)

class devito.symbolics.extended_sympy.bhaskara_cos[source]

Bases: sympy.functions.elementary.trigonometric.TrigonometricFunction

Approximation of the cosine function using a Bhaskara polynomial.

default_assumptions = {}
classmethod eval(arg)[source]

Returns a canonical form of cls applied to arguments args.

The eval() method is called when the class cls is about to be instantiated and it should return either some simplified instance (possible of some other class), or if the class cls should be unmodified, return None.

@classmethod
def eval(cls, arg):
if arg is S.NaN:
return S.NaN
if arg is S.Zero: return S.Zero
if arg.is_positive: return S.One
if arg.is_negative: return S.NegativeOne
if isinstance(arg, Mul):
coeff, terms = arg.as_coeff_Mul(rational=True)
if coeff is not S.One:
return cls(coeff) * cls(terms)


## devito.symbolics.inspection module¶

devito.symbolics.inspection.count(exprs, query)[source]

Return a mapper {(k, v)} where k is a sub-expression in exprs matching query and v is the number of its occurrences.

devito.symbolics.inspection.estimate_cost(handle, estimate_functions=False)[source]

Estimate the operation count of handle.

Parameters: handle – a SymPy expression or an iterator of SymPy expressions. estimate_functions – approximate the operation count of known functions (eg, sin, cos).

## devito.symbolics.manipulation module¶

devito.symbolics.manipulation.freeze_expression(expr)[source]

Reconstruct expr turning all sympy.Mul and sympy.Add into, respectively, devito.Mul and devito.Add.

devito.symbolics.manipulation.xreplace_constrained(exprs, make, rule=None, costmodel=<function <lambda>>, repeat=False)[source]

Unlike xreplace, which replaces all objects specified in a mapper, this function replaces all objects satisfying two criteria:

* The "matching rule" -- a function returning True if a node within expr
satisfies a given property, and as such should be replaced;
* A "cost model" -- a function triggering replacement only if a certain
cost (e.g., operation count) is exceeded. This function is optional.


Note that there is not necessarily a relationship between the set of nodes for which the matching rule returns True and those nodes passing the cost model check. It might happen for example that, given the expression a + b, all of a, b, and a + b satisfy the matching rule, but only a + b satisfies the cost model.

Parameters: exprs – The target SymPy expression, or a collection of SymPy expressions. make – Either a mapper M: K -> V, indicating how to replace an expression in K with a symbol in V, or a function with internal state that, when called, returns unique symbols. rule – The matching rule (a lambda function). May be left unspecified if make is a mapper. costmodel – The cost model (a lambda function, optional). repeat – Repeatedly apply xreplace until no more replacements are possible (optional, defaults to False).
devito.symbolics.manipulation.xreplace_indices(exprs, mapper, key=None, only_rhs=False)[source]

Replace indices in SymPy equations.

Parameters: exprs – The target SymPy expression, or a collection of SymPy expressions. mapper – A dictionary containing the index substitution rules. key – (Optional) either an iterable or a function. In the former case, all objects whose name does not appear in key are ruled out. Likewise, if a function, all objects for which key(obj) gives False are ruled out. only_rhs – (Optional) apply the substitution rules to right-hand sides only.
devito.symbolics.manipulation.pow_to_mul(expr)[source]
devito.symbolics.manipulation.as_symbol(expr)[source]

Extract the “main” symbol from a SymPy object.

devito.symbolics.manipulation.indexify(expr)[source]

Given a SymPy expression, return a new SymPy expression in which all AbstractFunction objects have been converted into Indexed objects.

devito.symbolics.manipulation.convert_to_SSA(exprs)[source]

Convert an iterable of :class:Eqs into Static Single Assignment form.

devito.symbolics.manipulation.split_affine(expr)[source]

Split an affine scalar function into its three components, namely variable, coefficient, and translation from origin.

Raises: ValueError – If expr is non affine.

## devito.symbolics.queries module¶

devito.symbolics.queries.q_leaf(expr)[source]
devito.symbolics.queries.q_indexed(expr)[source]
devito.symbolics.queries.q_terminal(expr)[source]
devito.symbolics.queries.q_trigonometry(expr)[source]
devito.symbolics.queries.q_op(expr)[source]
devito.symbolics.queries.q_terminalop(expr)[source]
devito.symbolics.queries.q_sum_of_product(expr)[source]
devito.symbolics.queries.q_indirect(expr)[source]

Return True if indexed has indirect accesses, False otherwise.

a[i] –> False a[b[i]] –> True

devito.symbolics.queries.q_timedimension(expr)[source]
devito.symbolics.queries.q_affine(expr, vars)[source]

Return True if expr is (separately) affine in the variables vars, False otherwise.

devito.symbolics.queries.q_linear(expr, vars)[source]

Return True if expr is (separately) linear in the variables vars, False otherwise.

devito.symbolics.queries.q_identity(expr, var)[source]

Return True if expr is the identity function in var, modulo a constant (that is, a function affine in var in which the value of the coefficient of var is 1), False otherwise.

3x -> False 3x + 1 -> False x + 2 -> True

devito.symbolics.queries.q_inc(expr)[source]
devito.symbolics.queries.q_scalar(expr)[source]
devito.symbolics.queries.iq_timeinvariant(graph)[source]
devito.symbolics.queries.iq_timevarying(graph)[source]

## devito.symbolics.search module¶

devito.symbolics.search.retrieve_indexed(expr, mode='unique', deep=False)[source]

Shorthand to retrieve Indexed objects in expr.

devito.symbolics.search.retrieve_functions(expr, mode='unique')[source]

Shorthand to retrieve sympy.Function objects in expr.

devito.symbolics.search.retrieve_terminals(expr, mode='unique', deep=False)[source]

Shorthand to retrieve Indexed and Symbol objects in expr.

devito.symbolics.search.retrieve_ops(expr)[source]

Shorthand to retrieve arithmetic operations rooted in expr.

devito.symbolics.search.retrieve_trigonometry(expr)[source]

Shorthand to retrieve trigonometric function objects in expr.

devito.symbolics.search.search(expr, query, mode='unique', visit='dfs', deep=False)[source]

Interface to Search.