Substitute numerical constants with symbols in sympy

Viewed 64

I have a question similar to this one: How to substitute multiple symbols in an expression in sympy? but in reverse.

I have a sympy expression with numerical values and symbols alike. I would like to substitute all numerical values with symbolic constants. I appreciate that such query is uncommon for sympy. What can I try next?

For example, I have:

-0.5967695*sin(0.15280747*x0 + 0.89256966) + 0.5967695*sin(sin(0.004289882*x0 - 1.5390939)) and would like to replace all numbers with a, b, c etc. ideally in a batch type of way.

The goal is to then apply trig identities to simplify the expression.

2 Answers

I'm not sure if there is already such a function. If there is not, it's quite easy to build one. For example:

import string

def num2symbols(expr):
    # wild symbol to select all numbers
    w = Wild("w", properties=[lambda t: isinstance(t, Number)])
    # extract the numbers from the expression
    n = expr.find(w)
    # get a lowercase alphabet
    alphabet = list(string.ascii_lowercase)
    # create a symbol for each number
    s = symbols(" ".join(alphabet[:len(n)]))
    # create a dictionary mapping a number to a symbol
    d = {k: v for k, v in zip(n, s)}
    return d, expr.subs(d)

x0 = symbols("x0")
expr = -0.5967695*sin(0.15280747*x0 + 0.89256966) + 0.5967695*sin(sin(0.004289882*x0 - 1.5390939))
d, new_expr = num2symbols(expr)
print(new_expr)
# out: b*sin(c + d*x0) - b*sin(sin(a + f*x0))
print(d):
# {-1.53909390000000: a, -0.596769500000000: b, 0.892569660000000: c, 0.152807470000000: d, 0.596769500000000: e, 0.00428988200000000: f}

I feel like dict.setdefault was made for this purpose in Python :-)

>>> c = numbered_symbols('c',cls=Dummy)
>>> d = {}
>>> econ = expr.replace(lambda x:x.is_Float, lambda x: sign(x)*d.setdefault(abs(x),next(c)))
>>> undo = {v:k for k,v in d.items()}

Do what you want with econ and when done (after saving results to econ)

>>> econ.xreplace(undo) == expr
True

(But if you change econ the exact equivalence may no longer hold.) This uses abs to store symbols so if the expression has constants that differ by a sign they will appear in econ with +/-ci instead of ci and cj.

Related