Utilities for dealing with expressions

Parser

pymbolic.parse(expr_str: str) Expression[source]
Returns:

a pymbolic.primitives.ExpressionNode tree corresponding to expr_str.

The parser is also relatively easy to extend. See the source code of the following class.

class pymbolic.parser.Parser[source]
__call__(expr_str: str, min_precedence: int = 0) Expression[source]
Parameters:

min_precedence

??

Returns:

a pymbolic.primitives.ExpressionNode tree corresponding to expr_str.

Compiler

class pymbolic.compiler.CompileMapper[source]

Bases: StringifyMapper[()]

class pymbolic.compiler.CompiledExpression(expression: Expression, variables: Sequence[str | Variable] | None = None)[source]

This class encapsulates an expression compiled into Python bytecode for faster evaluation.

Its instances (unlike plain lambdas) are pickleable.

__call__(*args: Any) Any[source]

Call self as a function.

Interoperability with other symbolic systems

Interoperability with sympy

pymbolic.interop.sympy.make_cse(arg: Basic, prefix: str | None = None, scope: str | None = None) Function[source]

Create an expression compatible with CommonSubexpression.

This is used by the mappers (e.g. SympyToPymbolicMapper) to correctly convert a subexpression to pymbolic’s CSE.

class pymbolic.interop.sympy.SympyToPymbolicMapper[source]
__call__(expr: object, *args: ~typing.~P, **kwargs: ~typing.~P) ResultT[source]

Call self as a function.

class pymbolic.interop.sympy.PymbolicToSympyMapper(context: Mapping[str, ResultT] | None = None)[source]
__call__(expr: Expression, /, *args: ~typing.~P, **kwargs: ~typing.~P) ResultT[source]

Dispatch expr to its corresponding mapper method. Pass on *args and **kwargs unmodified.

This method is intended as the top-level dispatch entry point and may be overridden by subclasses to present a different/more convenient interface. rec() on the other hand is intended as the recursive dispatch method to be used to recurse within mapper method implementations.

Interoperability with symengine

class pymbolic.interop.symengine.SymEngineToPymbolicMapper[source]
__call__(expr: object, *args: ~typing.~P, **kwargs: ~typing.~P) ResultT[source]

Call self as a function.

class pymbolic.interop.symengine.PymbolicToSymEngineMapper(context: Mapping[str, ResultT] | None = None)[source]
__call__(expr: Expression, /, *args: ~typing.~P, **kwargs: ~typing.~P) ResultT[source]

Dispatch expr to its corresponding mapper method. Pass on *args and **kwargs unmodified.

This method is intended as the top-level dispatch entry point and may be overridden by subclasses to present a different/more convenient interface. rec() on the other hand is intended as the recursive dispatch method to be used to recurse within mapper method implementations.

Interoperability with Maxima

class pymbolic.interop.maxima.MaximaStringifyMapper[source]
class pymbolic.interop.maxima.MaximaParser[source]
class pymbolic.interop.maxima.MaximaKernel(executable: str = 'maxima', timeout: int = 30)[source]
restart() None[source]
shutdown() None[source]
reset() None[source]
exec_str(s: str, enforce_prompt_numbering: bool = True) None[source]
eval_str(s: str, enforce_prompt_numbering: bool = True) str[source]
eval_expr(expr: Expression) Expression[source]
pymbolic.interop.maxima.eval_expr_with_setup(assignments: Sequence[str | tuple[str, Expression] | Expression], expr: Expression) Expression[source]
pymbolic.interop.maxima.diff(expr: Expression, var: str | Variable, count: int = 1, assignments: Sequence[str | tuple[str, Expression] | Expression] = ()) Expression[source]

Interoperability with Python’s ast module

An example:

import ast

from pymbolic.interop.ast import ASTToPymbolic


src = """
def f():
    xx = 3*y + z * (12 if x < 13 else 13)
    yy = f(x, y=y)
"""

mod = ast.parse(src.replace("\n    ", "\n"))
print(ast.dump(mod))

ast2p = ASTToPymbolic()
for f in mod.body:
    if not isinstance(f, ast.FunctionDef):
        continue

    for stmt in f.body:
        if not isinstance(stmt, ast.Assign):
            continue

        lhs, = stmt.targets
        lhs = ast2p(lhs)
        rhs = ast2p(stmt.value)

        print(lhs, rhs)
class pymbolic.interop.ast.ASTToPymbolic[source]
__call__(expr: object, *args: ~typing.~P, **kwargs: ~typing.~P) ResultT[source]

Call self as a function.

class pymbolic.interop.ast.PymbolicToASTMapper(*args: object)[source]
__call__(expr: Expression, *args: ~typing.~P, **kwargs: ~typing.~P) ResultT[source]

Dispatch expr to its corresponding mapper method. Pass on *args and **kwargs unmodified.

This method is intended as the top-level dispatch entry point and may be overridden by subclasses to present a different/more convenient interface. rec() on the other hand is intended as the recursive dispatch method to be used to recurse within mapper method implementations.

pymbolic.interop.ast.to_python_ast(expr: Expression) expr[source]

Maps expr to ast.expr.

pymbolic.interop.ast.to_evaluatable_python_function(expr: Expression, fn_name: str) str[source]

Returns a str of the Python code with a single function fn_name that takes in the variables in expr as keyword-only arguments and returns the evaluated value of expr.

>>> expr = parse("S//32 + E%32")
>>> print(to_evaluatable_python_function(expr, "foo"))
def foo(*, E, S):
    return S // 32 + E % 32

Interoperability with matchpy.functions module

Interoperability with matchpy.functions for pattern-matching and term-rewriting.

pymbolic.interop.matchpy.match(subject: ExpressionNode, pattern: ExpressionNode, to_matchpy_expr: ToMatchpyT | None = None, from_matchpy_expr: FromMatchpyT | None = None) Iterator[Mapping[str, Expression]][source]
pymbolic.interop.matchpy.match_anywhere(subject: ExpressionNode, pattern: ExpressionNode, to_matchpy_expr: ToMatchpyT | None = None, from_matchpy_expr: FromMatchpyT | None = None) Iterator[tuple[Mapping[str, Expression], Expression]][source]
pymbolic.interop.matchpy.replace_all(expression: Expression, rules: Iterable[ReplacementRule], to_matchpy_expr: ToMatchpyT | None = None, from_matchpy_expr: FromMatchpyT | None = None) Expression[source]
pymbolic.interop.matchpy.make_replacement_rule(pattern: Expression, replacement: Callable[..., Expression], to_matchpy_expr: ToMatchpyT | None = None, from_matchpy_expr: FromMatchpyT | None = None) ReplacementRule[source]

Returns a matchpy.functions.ReplacementRule from the objects declared via pymbolic.primitives instances.

Internal API

pymbolic.interop.matchpy.ToMatchpyT

alias of Callable[[_Expression], MatchpyExpression]

pymbolic.interop.matchpy.FromMatchpyT

alias of Callable[[MatchpyExpression], _Expression]

class pymbolic.interop.matchpy.PymbolicOp(*operands: Expression, variable_name=None)[source]

A base class for all pymbolic-like operations.

class pymbolic.interop.matchpy.Wildcard(min_count: int, fixed_size: bool, variable_name=None, optional=None)[source]

Visualizing Expressions

pymbolic.imperative.utils.get_dot_dependency_graph(statements, use_stmt_ids=None, preamble_hook=<function _default_preamble_hook>, additional_lines_hook=<class 'list'>, statement_stringifier=None, use_insn_ids=None)[source]

Return a string in the dot language depicting dependencies among kernel statements.

Parameters:
  • statements – A sequence of statements, each of which is stringified by calling statement_stringifier.

  • statement_stringifier – The function to use for stringifying the statements. The default stringifier uses str and escapes all double quotes (") in the string representation.

  • preamble_hook – A function that returns an iterable of lines to add at the beginning of the graph

  • additional_lines_hook – A function that returns an iterable of lines to add at the end of the graph