2012-02-29 27 views
15

Koduję funkcję, która rozwiązuje dowolną liczbę równoczesnych równań. Liczba równań jest ustawiana przez jeden z parametrów funkcji, a każde równanie jest zbudowane z wielu symboli - tyle symboli, ile jest równań. Oznacza to, że nie mogę po prostu zakodować kodów równań, a nawet symboli potrzebnych do ułożenia równań; funkcja musi być w stanie obsłużyć dowolną liczbę równań. Moje pytanie brzmi: jak utworzyć listę symboli?SymPy - dowolna liczba symboli

Mam jedno możliwe rozwiązanie, ale moje jelito mówi mi, że to nie będzie bardzo wydajne. Proszę dać mi znać, jeśli jest lepszy sposób na zrobienie tego.

Jestem nowy w firmie SymPy i nadal czuję się o niej dobrze. O ile widzę, symbole muszą być zdefiniowane za pomocą ciągu znaków. W związku z tym mogę utworzyć ciągi szeregowe poprzez dodanie numeru zwiększającego do litery (np. "T0", "t1" itp.), Dodać je do listy, a następnie utworzyć symbole, używając tych ciągów jako parametrów. Symbole te byłyby przechowywane na liście i byłyby wykorzystywane do tworzenia równań.

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

Czy to najlepszy sposób na zrobienie tego, czy też jest bardziej efektywne podejście?

Odpowiedz

24

Funkcja symbols może być używany do łatwo wygenerować listę symboli

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

Dzięki! To wygląda naprawdę prosto. – thornate

+1

Działa również dla liter: 'symbols ('a: g')'. – asmeurer

+2

tylko jedna uwaga tutaj, że w sympy to jest krotka, a nie lista ...istnieje niewielka różnica, głównie jedna przechyłka definiująca rzeczy do elementów listy: a0 = t + 1 spowoduje błąd. – user836925

1

Twoje podejście jest w porządku, chociaż nie ma potrzeby przechowywania nazw symboli oddzielnie (możesz uzyskać dostęp do nazwy symbolu za pomocą jej właściwości name).

Ponadto, można wyrazić tworzenie symboli trochę bardziej zwięzły (choć nie bardziej efektywnie), np:

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

Jednak dla przypadku użycia (zmienne tymczasowe), zmienne fikcyjne są prawdopodobnie sposobem przejść:

symbolList = map(Dummy, xrange(numEquations)) 

to naprawdę nie jest bardziej wydajny, ponieważ wewnętrznie klasa Dummy jest również za pomocą licznika do generowania unikalnych nazw, ale to nieco czystsze i jaśniejsze.

1

Można zrobić podklasę dict który automatycznie powraca 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") powróci generator, który generuje t0 , t1, t2 itp. Możesz użyć parametru start, aby wybrać inny początek v Alue. A jeśli chcesz używać zmiennych fikcyjnych, użyj numbered_symbols("t", cls=Dummy).

1

Dzięki kompresji locals() i słownikowemu można generować zarówno symbole, jak i zmienne lokalne Pythona o podobnej nazwie. Na przykład:

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

Sprawdzenie, że działa:

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