2015-10-30 5 views
5

я матрица A и правая сторона вектор y выражен в терминах fractions.Fraction объектов:решения линейной системы с фракциями в 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)) 

Я хотел бы решить систему A*x = y используя предоставленные функции numpy и получить результат, выраженный в объектах фракции, но, к сожалению, основная x = np.linalg.solve(A, y) возвращает результат в стандартных значений с плавающей точкой:

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

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

Is есть способ получить точный результат с объектами фракции?


EDIT

То, что я хотел бы сделать, это просто не представляется возможным с встроенной функциональностью NumPy (как в версии 1.10 - см ответ Mad физика). То, что можно сделать, - это реализовать свой собственный линейный решатель на основе исключения Гаусса, который опирается на сумму, вычитание, умножение и деление, все из которых четко определены и выполняются точно с объектами фракции (пока числители и знаменатели подходят в типе данных, который, как мне кажется, сколь угодно длинный).

Если вы действительно заинтересованы в этом, просто реализуйте решатель самостоятельно, это будет легко и быстро сделать (следуйте одному из многочисленных руководств в Интернете). Меня это не интересует, поэтому я буду придерживаться результата с плавающей запятой.

+1

Является ли ваша матрица всегда 3x3 или это просто случайно? Если это всегда 3x3, вы можете закодировать матрицу, обратную вручную, в худшем случае. –

+0

Я действительно получаю сообщение об ошибке при попытке запустить строку 'np.linalg.solve (A, y)'. Как вы его заработали? Numpy дает следующую ошибку: 'TypeError: для ufunc solve' не найдено ни одного цикла, соответствующего указанной сигнатуре и отливке . Я пробовал аналогичный код в scipy, и он дает 'ValueError: массивы объектов не поддерживаются'. –

+0

Матрица мала, но ее размер является переменным. Скажем, не больше 10x10. Я также знаю, что он несингулярный. – Spiros

ответ

2

Невозможно инвертировать матрицу рациональных чисел с использованием чистого numpy в соответствии с this thread в списке рассылки python. The response предполагает, что вы можете использовать sympy для матриц рациональности размером до 4x4. Если по какой-либо причине вы привязаны к numpy, вы можете рассмотреть возможность использования и инверсии матрицы 3x3 «вручную». Пошаговые руководства по тому, как это сделать, можно найти на http://www.mathsisfun.com/algebra/matrix-inverse-minors-cofactors-adjugate.html, а также большое количество других руководств по инверсии матрицы.

0

ИМХО, нет надежды. Решение, которое работает во многих случаях:

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

Он использует свойство, что решение является почти дробью с небольшим числителем и знаменателем, и найти его.

+0

Ну, собственно, из размера системы и фактических знаменателей вы можете аналитически найти максимальный знаменатель результатов и использовать его вместо 6 ** 9. Но я думаю, что лучший способ по-прежнему заключается в том, чтобы самостоятельно реализовать декомпозицию LU и повторную подстановку, если вам это нужно. Но да, после прочтения референдумов, опубликованных Mad Physicist, я согласен с тем, что нет никакой надежды делать все с помощью встроенного решателя numpy. – Spiros

Смежные вопросы