SymPy - Arbitrary number of Symbols

谁说胖子不能爱 提交于 2019-11-28 20:27:54

The symbols function can be used to easily generate lists of symbols

In [1]: symbols('a0:3')
Out[1]: (a₀, a₁, a₂)

In [2]: numEquations = 15

In [3]: symbols('a0:%d'%numEquations)
Out[3]: (a₀, a₁, a₂, a₃, a₄, a₅, a₆, a₇, a₈, a₉, a₁₀, a₁₁, a₁₂, a₁₃, a₁₄)

numbered_symbols("t") will return a generator that generates t0, t1, t2, etc. You can use the start parameter to choose a different starting value. And if you want to use dummy variables, use numbered_symbols("t", cls=Dummy).

With locals() and dictionary comprehension, you could iteratively generate both symbols and python local variables with a similar name. For example:

>>> symbols_dict = dict(('a%d'%k, symbols('a%d'%k)) for k in range(3))
>>> locals().update(symbols_dict)

Checking that it works:

>>> print(expand((a0+a2)*(a0+a1**2)))
a0**2 + a0*a1**2 + a0*a2 + a1**2*a2

Your approach is fine, though there's no need to store the symbol names separately (you can access a symbol's name via its name property).

Also, you could express the symbol creation a little more concisely (though no more efficiently), e.g.:

symbolList = map(lambda i: Symbol('t' + str(i)), xrange(numEquations))

However, for your use case (temporary variables), dummy variables are probably the way to go:

symbolList = map(Dummy, xrange(numEquations))

This isn't really any more efficient, since internally the Dummy class is also using a counter to generate unique names, but it's a bit cleaner and clearer.

You could make a subclass of dict which automatically returns Symbols:

import sympy as sym

class SymDict(dict):
    # http://stackoverflow.com/a/3405143/190597
    def __missing__(self, key):
        self[key]=sym.Symbol(key)
        return self[key]

def solveEquations(numEquations):
    symbol = SymDict()
    symbolList = ['t'+str(i) for i in range(numEquations)]
    equationList = [sum(symbol[s]**i for s in symbolList)
                    for i in range(numEquations)]
    print(equationList)

solveEquations(3)    
# [3, t0 + t1 + t2, t0**2 + t1**2 + t2**2]

Don't know if add any more useful information to the topic, but I use the following method to create a list of symbolic variables:

x = [sympy.symbols('x%d' % i) for i in range(3)]

And then I can use it normally in an equation:

eq = x[0]**2 + x[1]*2 + x[2]
print(sympy.diff(eq,x[0]))
>>> 2*x0

I like the approach given by @j-p-sena and what I am going to suggest looks a lot like it. The difference is that you don't have to know how many symbols you are going to need -- you will just have access to as many as you need by index. Use the IndexedBase as your symbol:

>>> x = IndexedBase('x')  # you've got access to a virtual array of x values
>>> solve(x[1]**2 + 1/x[4], x[4])
[-1/x[1]**2]

For display purposes you might want to create a replacement dictionary. To create numbered symbols you could do

>>> reps = dict(zip([x[i] for i in range(n_used+1)], numbered_symbols('c')))
>>> (x[2]**2 + 1/x[4]).subs(reps)
c2**2 + 1/c4

Or, if you are using less than 26 symbols you could use letters with

>>> reps = dict(zip([x[i] for i in range(n_used+1)], symbols('a:z')))
>>> (x[2]**2 + 1/x[4]).subs(reps)
c**2 + 1/e

BTW, x is an IndexedBase and x[1] is an Indexed object whose .base is x and whose .indices are a tuple of whatever numbers appear in the brackets. Both the IndexedBase and Indexed will show up in a .free_symbols query.

>>> (x[1,2] + 3).free_symbols
{x, x[1, 2]}
>>> x[1, 2].indices
(1, 2)
>>> x[1].base
x
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!