2015-10-30 16 views
5

Ich habe Matrix A und eine rechtsseitige Vektor y hinsichtlich fractions.Fraction Objekte ausgedrückt:Linear Systemlösung mit Fraktionen in numpy

import random, fractions, numpy as np 

A = np.zeros((3, 3), dtype=fractions.Fraction) 
y = np.zeros((3, 1), dtype=fractions.Fraction) 
for i in range(3): 
    for j in range(3): 
     A[i, j] = fractions.Fraction(np.random.randint(0, 4), np.random.randint(1, 6)) 
    y[i] = fractions.Fraction(np.random.randint(0, 4), np.random.randint(1, 6)) 

Ich möchte das System A*x = y unter Verwendung der bereitgestellten Funktionen lösen, in numpy und ein Ergebnis in der Fraktion Objekte ausgedrückt, aber leider ist der Grund x = np.linalg.solve(A, y) gibt das Ergebnis in Standardwerte Gleitkomma:

>>> np.linalg.solve(A, y) 

array([[-1.5245283 ], 
     [ 2.36603774], 
     [ 0.56352201]]) 

Ist gibt es eine Möglichkeit, das genaue Ergebnis mit Fraktionsobjekten zu erhalten? einfach nicht machbar mit den integrierten Funktionen von numpy


EDIT

Was würde ich tun (ab Version 1.10 - siehe Mad Physikers Antwort). Man könnte seinen eigenen linearen Löser implementieren, der auf der Gauß-Eliminierung basiert, die auf Summe, Subtraktion, Multiplikation und Division beruht, die alle genau definiert sind und genau mit Bruchstücken ausgeführt werden (solange die Zähler und Nenner passen) in dem Datentyp, der meiner Meinung nach beliebig lang ist).

Wenn Sie wirklich daran interessiert sind, dies zu implementieren, implementieren Sie einfach einen Solver selbst, es wird einfach und schnell zu tun sein (folgen Sie einem der vielen Tutorials online). Ich bin nicht so interessiert, also bleibe ich beim Fließkomma-Ergebnis.

+1

Ist Ihre Matrix immer 3x3 oder ist das nur zufällig? Wenn es immer 3x3 ist, können Sie die Matrix umgekehrt im schlimmsten Fall von Hand nach oben codieren. –

+0

Ich bekomme tatsächlich einen Fehler, wenn ich versuche, die Zeile 'np.linalg.solve (A, y)' auszuführen. Wie hast du es zur Arbeit gebracht? Numpy gibt den folgenden Fehler aus: 'TypeError: Keine Schleife, die der angegebenen Signatur entspricht, und das Casting wurde für ufunc solve gefunden. Ich habe versucht, ähnlichen Code in scipy und es gibt 'ValueError: Objekt-Arrays werden nicht unterstützt'. –

+0

Die Matrix ist klein, aber ihre Größe ist variabel. Sagen Sie nicht größer als 10x10. Ich weiß auch, dass es nicht singulär ist. – Spiros

Antwort

2

Es scheint nicht möglich zu sein, eine Matrix von rationals mit purem numpy nach this thread auf der Python-Mailingliste zu invertieren. The response schlägt vor, dass Sie sympy für Matrizen von rationals bis zur Größe 4x4 verwenden können. Wenn Sie aus irgendwelchen Gründen an numpy gebunden sind, können Sie überlegen, die Inverse einer 3x3-Matrix "manuell" zu verwenden. Schritt für Schritt Tutorials dazu finden Sie auf http://www.mathsisfun.com/algebra/matrix-inverse-minors-cofactors-adjugate.html, sowie eine große Vielzahl anderer Tutorials zur Matrixinversion.

0

IMHO, gibt es keine Hoffnung. Eine Lösung, die in vielen Fällen arbeiten:

y = np.zeros(3, dtype=fractions.Fraction) 
.... 
X= np.linalg.solve(A,y) 
s=[fractions.Fraction.from_float(x).limit_denominator(6**9) for x in X] 
print(s,y==dot(A,s)) 

Es nutzt die Eigenschaft, dass die Lösung fast eine Fraktion mit wenig Zähler und Nenner ist, und finden Sie es.

+0

Nun, eigentlich von der Größe des Systems und den tatsächlichen Nennern können Sie den maximalen Nenner der Ergebnisse analytisch finden und es anstelle von 6 ** 9 verwenden. Aber ich denke, der beste Weg ist immer noch, eine LU-Zerlegung und eine Rückwärtsersatzsubstitution selbst zu implementieren, wenn Sie das brauchen. Aber ja, nachdem ich die von Mad Physicist geposteten Referenzen gelesen habe, stimme ich zu, dass es keine Hoffnung gibt, alles mit dem numply eingebauten Solver zu machen. – Spiros