2015-08-23 25 views
8

Próbuję zrobić kilka symbolicznych obliczeń macierzy z sympy. Moim celem jest uzyskanie symbolicznej reprezentacji wyniku niektórych obliczeń macierzy. Natknąłem się na pewne problemy, które sprowadziłem do tego prostego przykładu, w którym próbuję ocenić wynik wykładniczej określonej macierzy i pomnożyć ją przez arbitralny wektor.sympy: "Transpose" obiekt nie ma atrybutu 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' 

Natomiast gdybym bezpośrednio utworzyć macierz tożsamości, a następnie pomnożyć przez v, wówczas nie ma problemu:

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

Jedno, co mam zwrócić uwagę jest to, że dwie macierze tożsamości są z różnych klas:

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

ja również okazało się, że wywołanie metody as_mutable() warunkiem obejście.

>>> I.as_mutable() * v 
v 

Czy zawsze konieczne, aby umieścić as_mutable() połączeń przez całe obliczeń algebry liniowej? Zgaduję, że nie, i że te błędy sugerują, że używam złej strategii, aby rozwiązać mój problem, ale nie wiem, jaka byłaaby właściwa strategia. Czy ktoś ma jakieś wskazówki?

Przeczytałem stronę z dokumentacją na , ale nadal mogłem skorzystać z pomocy w zrozumieniu, jak ważne są różnice między nimi w porównaniu ze standardowymi macierzami zmiennymi, oraz dlaczego niektóre operacje (na przykład sympy.exp) konwertują te różne klasy.

+0

FYI, błąd został naprawiony w głównej gałęzi programu sympy. – Phillip

Odpowiedz

4

bym twierdzą, że jest to błąd w Sympy:

W Pythonie można overload the multiplication operator from both sides. A*B może być obsługiwany wewnętrznie przez wywołanie A.__mul__(B) lub B.__rmul__(A). Python najpierw wywołuje A.__mul__, a jeśli ta metoda nie istnieje lub zwraca NotImplemented, wówczas Python automatycznie próbuje B.__rmul__. SymPy zamiast tego używa dekoratora o nazwie call_highest_priority, aby zdecydować, której z obu wersji użyć. Wyszukuje powiązane klasy i wywołuje funkcję implementacji o wyższym priorytecie. Priorytety w twoim przypadku to 11 dla v i I i 10.01 dla I_, więc preferowane jest I. Również podstawowa implementacja __mul__, której używa, nie zawiera dekoratora.

Krótko mówiąc, I*v kończy się zawsze dzwoni I.__mul__ i __mul__ nie może obsłużyć MatrixSymbol s ale nie zwraca NotImplemented albo. v.__rmul__(I) działa zgodnie z oczekiwaniami.

Prawidłowe ustalenie byłoby uchwycić AttributeError w matrices.py i powrót NotImplemented tj

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

Pythona będzie automatycznie awaryjny do __rmul__. Poprawką hack'ish byłoby dostosowanie _op_priority. Tak czy inaczej, powinieneś złożyć raport o błędzie: Jeśli błąd był zgodny z projektem (to znaczy, jeśli przypadkowo próbowałeś czegoś, co nie powinno działać), to komunikat o błędzie powiedziałby tak.

+0

Sam zgłosiłem błąd: https://github.com/sympy/sympy/issues/11090 – Phillip

Powiązane problemy