Какой самый быстрый способ найти точное решение линейной системы, Matlab - PullRequest
2 голосов
/ 10 марта 2020

Я пытаюсь решить линейную систему (A * x = B), где B - это 64-битная длина или больше. Я использовал функцию Линсольва в Matlab для решения системы уравнений. Я использовал (inv (A) * B), A \ B и ttimes (A, B), и они страдают от тех же проблем.

Я столкнулся с двумя проблемами:

  1. Функция Линслова не может найти точное решение, если (A и B) не являются символами c.
  2. Если A и B являются символами c, linsolve удается найти точное решение, но это занимает слишком много времени.

Есть ли способ найти точное решение, но быстро .

time=[]
i=50
a=magic(i);    
% B is a rendom numbers where each number is 64 bit length
B=double(bi2de(randi([0 1],i,64)));

%%****************************************
 % to make sure th matrix is not  **ill-conditioned***
        C = 1;              % desired condition number
        [u s v] = svd(a);
        s = diag(s);        % s is vector
        % ===== linear stretch of existing s
        s = s(1)*( 1-((C-1)/C)*(s(1)-s)/(s(1)-s(end)));
        % =====
        s = diag(s);           % back to matrix
        A = u*s*v';
%%****************************************
tic
x1=linsolve(A,B);
time(1,1)=toc;
%-------------------------------------
% convert A and B into symbolic 
Aa=sym(A);        Bb=sym(B);
tic
x2=linsolve(Aa,Bb);
time(1,2)=toc;
%-------------------------------------
% Show the accuracy of the first B(1), exact vs computed 
Exact=sym(double(B(1)))     
Computed=[ A(1,:)*x1  Aa(1,:)*x2]
time

x1 и x2 - это два решения. x2 является решением сумболи c A и B.

Только X2 дает нам точное решение

Exact solution =   2350911785583947776
Computed using x1= 2350911785583965184
Computed using x2= 2350911785583947776

Время, необходимое в секундах:

x1 time =    0.0007
x2 time =    6.7242

Ответы [ 2 ]

2 голосов
/ 10 марта 2020

Это не ответ на ваш вопрос, это демонстрация того, почему ваше «точное» решение не является точным: intput B является приблизительным. Попробуйте это в MATLAB:

a = randi([0 1],1,64);
a(1) = 0;
a1 = bi2de(a);
a(1) = 1;
a2 = bi2de(a);
a1-a2

Вы заметите, что a1 и a2 идентичны, хотя я перебросил младший значащий бит в обоих числах. Это связано с тем, что число с плавающей запятой двойной точности не может содержать 64 бита точности. Он содержит только 52. Другие 12 битов в 64-битном представлении должны хранить бит знака и показатель степени (который масштабирует число).

0 голосов
/ 12 марта 2020

Я построил свой собственный bi2de, который преобразует двоичный вектор в фактическое число.

Я заменил sym на vpa, и производительность повысилась.

sym (A) ----> vpa (A)

...