SymPy - 任意数量的符号

时间:2012-02-29 02:52:20

标签: python symbols sympy equation-solving

我编写的函数可以解决任意数量的联立方程。方程的数量由函数的一个参数设置,每个方程由许多符号构成 - 与方程一样多的符号。这意味着我不能简单地对方程式进行硬编码,甚至不需要将方程组合在一起所需的符号;该函数需要能够处理任意数量的方程。所以,我的问题是,如何生成符号列表?

我有一个可能的解决方案,但我的直觉告诉我它不会非常有效。如果有更好的方法,请告诉我。

我是SymPy的新手,我仍然在摸索着。据我所知,符号需要用字符串定义。因此,我可以通过在字母上添加递增数字(例如't0','t1'等)来生成一系列字符串,将它们添加到列表中,然后使用这些字符串作为参数创建符号。这些符号本身将存储在列表中,并用于生成方程式。

def solveEquations(numEquations):
    symbolNameList = []
    symbolList = []
    equationList = []
    for i in range(numEquations):
        name = 't' + str(i)
        symbolNameList.append(name)
        symbolList.append(Symbol(name))

    for i in range(numEquations):
        equation = 0
        for sym in symbolList:
            equation += sym ** i # Or whatever structure the equation needs
        equationList.append(equation)


    #Then go on to solve the equations...

这是最好的方法,还是有更有效的方法?

7 个答案:

答案 0 :(得分:31)

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₁₄)

答案 1 :(得分:7)

numbered_symbols("t")将返回生成t0t1t2等的生成器。您可以使用start参数选择不同的起始值。如果您想使用虚拟变量,请使用numbered_symbols("t", cls=Dummy)

答案 2 :(得分:2)

您可以创建dict的子类,该子类会自动返回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]

答案 3 :(得分:2)

使用locals()和字典理解,您可以迭代生成具有相似名称的符号和python局部变量。例如:

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

检查它是否有效:

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

答案 4 :(得分:1)

您的方法很好,但不需要单独存储符号名称(您可以通过其name属性访问符号的名称)。

此外,您可以更简洁地表达符号创建(尽管不会更有效),例如:

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

但是,对于您的用例(临时变量),虚拟变量可能是要走的路:

symbolList = map(Dummy, xrange(numEquations))

这实际上并没有更高效,因为Dummy类内部也使用计数器生成唯一名称,但它更清晰,更清晰。

答案 5 :(得分:1)

不知道是否向该主题添加更多有用的信息,但是我使用以下方法来创建符号变量列表:

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

然后我可以在等式中正常使用它:

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

答案 6 :(得分:0)

我喜欢@ j-p-sena给出的方法,我建议的内容看起来很像。区别在于您不必知道将需要多少个符号-您将可以按索引访问任意数量的符号。使用IndexedBase作为符号:

>>> 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]

出于显示的目的,您可能想要创建替换字典。要创建编号符号,您可以

>>> 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

或者,如果您使用的符号少于26个,则可以将字母与

一起使用
>>> 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

顺便说一句,x是IndexedBase,x[1]是Indexed对象,其.basex,而.indices是其中出现的任何数字的元组括号。 IndexedBase和IndexedBase都将显示在.free_symbols查询中。

>>> (x[1,2] + 3).free_symbols
{x, x[1, 2]}
>>> x[1, 2].indices
(1, 2)
>>> x[1].base
x