Python SymPy-任意数量的符号

Python SymPy-任意数量的符号,python,symbols,sympy,equation-solving,Python,Symbols,Sympy,Equation Solving,我正在编写一个函数,它可以解任意数量的联立方程组。方程的数量由函数的一个参数设置,每个方程都是由一系列符号构成的,这些符号的数量与方程的数量相同。这意味着我不能简单地硬编码方程,甚至不能硬编码组合方程所需的符号;该函数需要能够处理任意数量的方程。所以,我的问题是,如何生成符号列表 我有一个可能的解决方案,但我的直觉告诉我,它不会非常有效。如果有更好的方法,请告诉我 我对SymPy还不熟悉,现在仍在摸索。就我所见,符号需要用字符串来定义。因此,我可以通过在字母“t0”、“t1”等后面添加递增的数字

我正在编写一个函数,它可以解任意数量的联立方程组。方程的数量由函数的一个参数设置,每个方程都是由一系列符号构成的,这些符号的数量与方程的数量相同。这意味着我不能简单地硬编码方程,甚至不能硬编码组合方程所需的符号;该函数需要能够处理任意数量的方程。所以,我的问题是,如何生成符号列表

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

我对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...

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

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

此外,您可以更简洁地表达符号创建,但效率不高,例如:

symbolList = map(lambda i: Symbol('t' + str(i)), xrange(numEquations))
但是,对于您的用例临时变量,虚拟变量可能是一种方法:

symbolList = map(Dummy, xrange(numEquations))

这实际上并不是更有效,因为在内部,虚拟类也使用计数器来生成唯一的名称,但它更干净、更清晰。

您可以创建dict的子类,该子类自动返回符号:

符号功能可用于轻松生成符号列表

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₁₄)
编号的symbolst将返回生成t0、t1、t2等的生成器。您可以使用start参数选择不同的启动值。如果要使用虚拟变量,请使用带编号的_symbolst,cls=dummy。

使用局部变量和字典理解,可以迭代生成具有类似名称的符号和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

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

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

我喜欢@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是一个索引数据库,x[1]是一个索引对象,其.base是x,其.index是括号中出现的任何数字的元组。IndexedBase和Indexed都将显示在.free_符号查询中


这里需要注意的是,在sympy中,这是一个元组,而不是一个列表……有一个细微的区别,主要是不能定义列表元素的内容:a0=t+1将给出一个错误。
>>> 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[1,2] + 3).free_symbols
{x, x[1, 2]}
>>> x[1, 2].indices
(1, 2)
>>> x[1].base
x