2015-08-23 25 views
8

Sto provando a fare alcuni calcoli con la matrice simbolica con sympy. Il mio obiettivo è ottenere una rappresentazione simbolica del risultato di alcuni calcoli matriciali. Ho incontrato alcuni problemi che ho riassunto in questo semplice esempio, in cui cerco di valutare il risultato di un'esponenziazione di una matrice specificata e di moltiplicarla per un vettore arbitrario.sympy: l'oggetto 'Transpose' non ha attributo tolist

>>> import sympy 
>>> v = sympy.MatrixSymbol('v', 2, 1) 
>>> Z = sympy.zeros(2, 2) # create 2x2 zero matrix 
>>> I = sympy.exp(Z) # exponentiate zero matrix to get identity matrix 
>>> I * v 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "sympy/matrices/matrices.py", line 507, in __mul__ 
    blst = B.T.tolist() 
AttributeError: 'Transpose' object has no attribute 'tolist' 

Al contrario, se creo direttamente la matrice identità e poi moltiplicarlo per v, allora non c'è nessun problema:

>>> I_ = sympy.eye(2) # directly create the identity matrix 
>>> I_ == I # check the two matrices are equal 
True 
>>> I_ * v 
v 

Una cosa che ho notato è che le due matrici di identità sono di diverse classi:

>>> I.__class__ 
sympy.matrices.immutable.ImmutableMatrix 
>>> I_.__class__ 
sympy.matrices.dense.MutableDenseMatrix 

ho anche scoperto che la chiamata al metodo as_mutable() fornito un work-around.

>>> I.as_mutable() * v 
v 

E 'sempre necessario mettere as_mutable() chiamate per tutta la calcoli di algebra lineare? Sto indovinando no, e che invece questi errori suggeriscono che sto usando la strategia sbagliata per risolvere il mio problema, ma non riesco a capire quale sarebbe la strategia giusta. Qualcuno ha qualche indicazione?

Ho letto la pagina di documentazione su Immutable Matrices ma potrei comunque aiutarmi a capire come le loro differenze con le matrici standard mutabili siano importanti qui e perché alcune operazioni (ad es. Sympy.exp) si convertano tra queste diverse classi.

+0

FYI, il bug è stato risolto nel ramo principale di sympy ora. – Phillip

risposta

4

avrei sostengo che questo è un bug in Sympy:

In Python, è possibile overload the multiplication operator from both sides. A*B può essere gestito internamente chiamando A.__mul__(B) o B.__rmul__(A). Python chiama prima A.__mul__ e, se questo metodo non esiste o restituisce NotImplemented, Python prova automaticamente B.__rmul__. SymPy utilizza invece un decoratore chiamato call_highest_priority per decidere quale delle due implementazioni utilizzare. Cerca il _op_priority delle classi coinvolte e chiama la funzione dell'implementazione con priorità più alta. Le priorità nel tuo caso sono 11 per v e I e 10,01 per I_, quindi è preferibile I. Inoltre, l'implementazione di base di __mul__, che utilizza I, è priva del decoratore.

Per farla breve, I*v finisce sempre chiamare I.__mul__, e __mul__ non può gestire MatrixSymbol s, ma non restituisce NotImplemented neanche. v.__rmul__(I) funziona come previsto.

La correzione adeguata sarebbe quella di catturare il AttributeError in matrices.py e tornare NotImplemented, vale a dire

try: 
    blst = B.T.tolist() 
except AttributeError: 
    return NotImplemented 

Python sarebbe poi fallback automatico al __rmul__. La correzione hack'ish sarebbe quella di regolare _op_priority. Ad ogni modo, dovresti presentare un bug report: Se l'errore era di progettazione (cioè, se hai tentato accidentalmente qualcosa che non dovrebbe funzionare), allora il messaggio di errore lo direbbe.

+0

Ho segnalato personalmente il bug: https://github.com/sympy/sympy/issues/11090 – Phillip