2012-02-29 3 views
15

Я кодирую функцию, которая решает произвольное число одновременных уравнений. Количество уравнений задается одним из параметров функции, и каждое уравнение построено из числа символов - столько символов, сколько есть уравнений. Это означает, что я не могу просто закодировать уравнения или даже символы, необходимые для объединения уравнений; функция должна иметь возможность обрабатывать любое количество уравнений. Итак, мой вопрос: как мне составить список символов?SymPy - произвольное число символов

У меня есть одно возможное решение, но моя кишка говорит мне, что это не будет очень эффективно. Пожалуйста, дайте мне знать, если есть лучший способ сделать это.

Я новичок в 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... 

Это лучший способ сделать это, или существует более эффективный подход?

ответ

24

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

Спасибо! Это выглядит очень просто. – thornate

+1

Он также работает для букв: 'символы ('a: g')'. – asmeurer

+2

просто заметьте здесь, что в sympy это кортеж, а не список ...существует небольшая разница, в основном, одна из них не может определить вещи для элементов списка: a0 = t + 1 даст ошибку. – user836925

1

Ваш подход хорош, хотя нет необходимости хранить имена символов отдельно (вы можете получить доступ к имени символа через свой name свойство).

Кроме того, вы можете выразить создание символа немного более сжато (хотя и не более эффективно), например:

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

Однако для случая использования (временные переменные), фиктивные переменные, вероятно, способ перейти:

symbolList = map(Dummy, xrange(numEquations)) 

Это на самом деле не какой-либо более эффективным, так как внутренне Dummy класс также использует счетчик для создания уникальных имен, но это немного чище и яснее.

1

Вы могли бы сделать подкласс 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] 
7

numbered_symbols("t") возвращает генератор, который генерирует t0 , t1, t2 и т. Д. Вы можете использовать параметр start, чтобы выбрать другой стартовый вариант v ALUE. И если вы хотите использовать фиктивные переменные, используйте numbered_symbols("t", cls=Dummy).

1

С помощью 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