【问题标题】:SymPy - Arbitrary number of SymbolsSymPy - 任意数量的符号
【发布时间】:2012-03-18 13:47:02
【问题描述】:

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

我有一个可能的解决方案,但我的直觉告诉我它不会很有效。请让我知道是否有更好的方法来做到这一点。

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

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

【问题讨论】:

    标签: python symbols sympy equation-solving


    【解决方案1】:

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

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

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

    但是,对于您的用例(临时变量),虚拟变量可能是可行的方法:

    symbolList = map(Dummy, xrange(numEquations))
    

    这实际上并没有提高效率,因为在内部 Dummy 类也使用计数器来生成唯一名称,但它更简洁明了。

    【讨论】:

      【解决方案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】:

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

        【讨论】:

        • 这里只是一个注释,在 sympy 中这是一个元组,而不是一个列表......有一点不同,主要是,不能为列表的元素定义事物:a0 = t+1会报错。
        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            【解决方案6】:

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

            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
            

            【讨论】:

              【解决方案7】:

              我喜欢@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 和 Indexed 都将显示在 .free_symbols 查询中。

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多