2012-02-29 8 views
15

Sto codificando una funzione che risolve un numero arbitrario di equazioni simultanee. Il numero di equazioni è impostato da uno dei parametri della funzione e ogni equazione è costruita da un numero di simboli - come molti simboli quante sono le equazioni. Ciò significa che non posso semplicemente codificare le equazioni, o anche i simboli necessari per mettere insieme le equazioni; la funzione deve essere in grado di gestire qualsiasi numero di equazioni. Quindi, la mia domanda è, come faccio a produrre una lista di simboli?SymPy - Numero arbitrario di simboli

Ho una soluzione possibile, ma il mio istinto mi dice che non sarà molto efficiente. Per favore fatemi sapere se c'è un modo migliore per farlo.

Sono nuovo di SymPy e mi sento ancora a mio agio. Per quanto posso vedere, i simboli devono essere definiti con una stringa. Pertanto, posso produrre stringhe di serie aggiungendo un numero incrementale a una lettera (ad esempio 't0', 't1', ecc.), Aggiungerli a una lista e quindi creare i simboli utilizzando tali stringhe come parametri. Questi simboli verrebbero archiviati in una lista e sarebbero usati per produrre le equazioni.

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

È questo il modo migliore per farlo oppure esiste un approccio più efficiente?

risposta

24

La funzione symbols può essere utilizzata per generare facilmente gli elenchi dei simboli

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

Grazie! Sembra molto semplice. – thornate

+1

Funziona anche per le lettere: 'simboli ('a: g')'. – asmeurer

+2

solo una nota qui, che in sympy questa è una tupla e non una lista ...c'è una leggera differenza, principalmente, non è possibile definire le cose agli elementi di una lista: a0 = t + 1 darà un errore. – user836925

1

L'approccio è corretto, anche se non è necessario memorizzare separatamente i nomi dei simboli (è possibile accedere al nome di un simbolo tramite la proprietà name).

Inoltre, è possibile esprimere la creazione simbolo un po 'più conciso (anche se non in modo più efficiente), ad esempio:

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

Tuttavia, per il vostro caso d'uso (variabili temporanee), variabili dummy sono probabilmente la strada da andare:

symbolList = map(Dummy, xrange(numEquations)) 

Questo non è davvero più efficiente, dal momento che all'interno della classe Dummy è anche utilizzando un contatore per generare nomi unici, ma è un po 'più pulito e più chiara.

1

Si potrebbe fare una sottoclasse di dict che restituisce automaticamente 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") restituirà un generatore che genera t0 , t1, t2, ecc. È possibile utilizzare il parametro start per scegliere una diversa v iniziale alue. E se si desidera utilizzare variabili dummy, utilizzare numbered_symbols("t", cls=Dummy).

1

Con locals() e la comprensione del dizionario, è possibile generare in modo iterativo sia simboli che variabili locali python con un nome simile. Per esempio:

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

Controllo che funziona:

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