Skip to content

Better array indexing support in pystr_to_symbolic #2052

@alexnick83

Description

@alexnick83

When using sympy.sympify without context, SymPy considers all names to be scalar symbols. This means that if you try to sympify, e.g., A[i, j, k], the following error will occur: TypeError: 'Symbol' object is not subscriptable. However, SymPy has support for array expressions, as described here: https://docs.sympy.org/latest/modules/tensor/array_expressions.html
A minimal example is the following:

import sympy
from sympy.tensor.array.expressions import ArraySymbol

A = ArraySymbol("A", (3, 2, 4))
sym = sympy.sympify("A[i, j, k]", locals={'A': A})

In DaCe, a crucial utility method is dace.symbolic.pystr_to_symbolic, which converts a Python-compatible string expression to a SymPy-compatible symbolic expression. To enable the parsing of strings that contain array subscripts without special context, we currently utilize the following hack. We replace brackets with parentheses, which makes SymPy think that the array names correspond to functions. Specifically, in dace/symbolic.py and line 1327, we do the following:

    try:
        return sympy_to_dace(sympy.sympify(expr, locals, evaluate=simplify), symbol_map)
    except (TypeError, sympy.SympifyError):  # Symbol object is not subscriptable
        # Replace subscript expressions with function calls
        expr = expr.replace('[', '(')
        expr = expr.replace(']', ')')
        return sympy_to_dace(sympy.sympify(expr, locals, evaluate=simplify), symbol_map)

Although this works well for simple expressions, it may fail with indirect accesses or more complicated expressions, e.g., when the array subscript is nested inside a comparison.

To address those issues, we want to update pystr_to_symbolic to use SymPy's ArraySymbols. We should amend the method to, when accepting a string as input, detect array subscripts, count the number of dimensions, create appropriate ArraySymbols, and pass the context to sympy.sympify through the locals dictionary parameter. To ensure that the updated method works properly, we should generate tests where the conditions in InterstateEdges or the branches of ConditionalBlocks are such complicated expressions, e.g., ztp1[tmp_index_224, tmp_index_225] - v_ydcst_var_1_rtt > 0.0.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions