Швидке явне рішення для


9

Я шукаю швидке (смію сказати оптимальне?) Чітке рішення лінійної реальної задачі 3x3, , . Ax=bAR3×3,bR3

Матриця загальна, але близька до матриці ідентичності з числом умови, близькою до 1. Оскільки насправді сенсорні вимірювання з приблизно 5 цифрами точності, я не проти втратити кілька цифр через числову питань.Ab

Звичайно, не важко придумати чітке рішення, засноване на будь-якій кількості методів, але якщо є щось, що було б оптимальним з точки зору підрахунку FLOPS, це було б ідеально (адже вся проблема швидше за все, вписується в регістри FP!).

(Так, цю процедуру часто називають . Я вже позбувся фруктів, що звисають, і це далі в моєму профільному списку ...)


Чи кожен використовується лише один раз, або є кілька лінійних систем з однаковою матрицею? Це змінило б витрати. A
Федеріко Полоні

У цьому випадку A використовується лише один раз.
Демієн

Відповіді:


14

Ви не можете перемогти явну формулу. На аркуші паперу можна записати формули для рішення . Нехай компілятор оптимізує речі для вас. Будь-який інший метод майже неминуче має висловлювання або цикли (наприклад, для ітеративних методів), які зроблять ваш код повільніше, ніж будь-який прямий код.x=A1biffor


9

Оскільки матриця наближена до тотожності, наступні серії Неймана будуть сходитися дуже швидко:

A1=k=0(IA)k

Залежно від необхідної точності, це може бути навіть досить хорошим для врізання через 2 умови:

A1I+(IA)=2IA.

Це може бути трохи швидше, ніж пряма формула (як це пропонується у відповіді Вольфганга Бангерта), хоча з значно меншою точністю.


Ви можете отримати більшу точність за допомогою 3 доданків:

A1I+(IA)+(IA)2=3I3A+A2

але якщо ви формулу введення за входом для , ви дивитеся на порівнянну кількість операцій з плаваючою комою, як пряму формулу зворотної матриці 3x3 (не потрібно робити поділ, хоча, який трохи допомагає).(3I3A+A2)b


Є дивізії все ж дорожчі, ніж інші флопи? Я думав, що це пережиток минулого.
Федеріко Полоні

Підрозділи не впорядковують одна архітектура (ARM - сучасний приклад)
Damien

@FedericoPoloni З Cuda ви можете побачити пропускну здатність інструкцій тут , це в шість разів більше для множень / додавань, ніж для поділів.
Кирило

@Damien та Kirill Я бачу, дякую за покажчики.
Федеріко Полоні

5

Підрахунок FLOPS виходячи з пропозицій, наведених вище:

  • LU, немає повороту:

    • Mul = 11, Div / Recip = 6, Add / Sub = 11, Всього = 28; або
    • Mul = 16, Div / Recip = 3, Add / Sub = 11, Всього = 30
  • Усунення Гаусса із зворотною підміною, без повороту:

    • Mul = 11, Div / Recip = 6, Add / Sub = 11, Всього = 28; або
    • Mul = 16, Div / Recip = 3, Add / Sub = 11, Всього = 30
  • Правило Крамера через розширення кофактора

    • Mul = 24, Div = 3, Add / Sub = 15, Total = 42; або
    • Mul = 27, Div = 1, Add / Sub = 15, Total = 43
  • Явне зворотне, а потім помножити:

    • Mul = 30, Div = 3, Add / Sub = 17, Total = 50; або
    • Mul = 33, Div = 1, Add / Sub = 17, Total = 51

Концепції підтвердження MATLAB:

Правило Креймера через розширення Cofactor :

function k = CramersRule(A, m)
%
% FLOPS:
%
% Multiplications:        24
% Subtractions/Additions: 15
% Divisions:               3
%
% Total:                  42

a = A(1,1);
b = A(1,2);
c = A(1,3);

d = A(2,1);
e = A(2,2);
f = A(2,3);

g = A(3,1);
h = A(3,2);
i = A(3,3);

x = m(1);
y = m(2);
z = m(3);

ei = e*i;
fh = f*h;

di = d*i;
fg = f*g;

dh = d*h;
eg = e*g;

ei_m_fh = ei - fh;
di_m_fg = di - fg;
dh_m_eg = dh - eg;

yi = y*i;
fz = f*z;

yh = y*h;
ez = e*z;

yi_m_fz = yi - fz;
yh_m_ez = yh - ez;

dz = d*z;
yg = y*g;

dz_m_yg = dz - yg;
ez_m_yh = ez - yh;


det_a = a*ei_m_fh - b*di_m_fg + c*dh_m_eg;
det_1 = x*ei_m_fh - b*yi_m_fz + c*yh_m_ez;
det_2 = a*yi_m_fz - x*di_m_fg + c*dz_m_yg;
det_3 = a*ez_m_yh - b*dz_m_yg + x*dh_m_eg;


p = det_1 / det_a;
q = det_2 / det_a;
r = det_3 / det_a;

k = [p;q;r];

LU (відсутність повороту) та зворотна заміна:

function [x, y, L, U] = LUSolve(A, b)
% Total FLOPS count:     (w/ Mods)
%
% Multiplications:  11    16
% Divisions/Recip:   6     3
% Add/Subtractions: 11    11
% Total =           28    30
%

A11 = A(1,1);
A12 = A(1,2);
A13 = A(1,3);

A21 = A(2,1);
A22 = A(2,2);
A23 = A(2,3);

A31 = A(3,1);
A32 = A(3,2);
A33 = A(3,3);

b1 = b(1);
b2 = b(2);
b3 = b(3);

L11 = 1;
L22 = 1;
L33 = 1;

U11 = A11;
U12 = A12;
U13 = A13;

L21 = A21 / U11;
L31 = A31 / U11;

U22 = (A22 - L21*U12);
L32 = (A32 - L31*U12) / U22;

U23 = (A23 - L21*U13);

U33 = (A33 - L31*U13 - L32*U23);

y1 = b1;
y2 = b2 - L21*y1;
y3 = b3 - L31*y1 - L32*y2;

x3 = (y3                  ) / U33;
x2 = (y2 -          U23*x3) / U22;
x1 = (y1 - U12*x2 - U13*x3) / U11;

L = [ ...
    L11,   0,   0;
    L21, L22,   0;
    L31, L32, L33];

U = [ ...
    U11, U12, U13;
      0, U22, U23;
      0,   0, U33];

x = [x1;x2;x3];
y = [y1;y2;y3];

Явне зворотне, а потім помножити:

function x = ExplicitInverseMultiply(A, m)
%
% FLOPS count:                  Alternative
%
% Multiplications:        30            33
% Divisions:               3             1
% Additions/Subtractions: 17            17
% Total:                  50            51


a = A(1,1);
b = A(1,2);
c = A(1,3);

d = A(2,1);
e = A(2,2);
f = A(2,3);

g = A(3,1);
h = A(3,2);
i = A(3,3);

ae = a*e;
af = a*f;
ah = a*h;
ai = a*i;

bd = b*d;
bf = b*f;
bg = b*g;
bi = b*i;

cd = c*d;
ce = c*e;
cg = c*g;
ch = c*h;

dh = d*h;
di = d*i;

eg = e*g;
ei = e*i;

fg = f*g;
fh = f*h;

dh_m_eg = (dh - eg);
ei_m_fh = (ei - fh);
fg_m_di = (fg - di);

A = ei_m_fh;
B = fg_m_di;
C = dh_m_eg;
D = (ch - bi);
E = (ai - cg);
F = (bg - ah);
G = (bf - ce);
H = (cd - af);
I = (ae - bd);

det_A = a*ei_m_fh + b*fg_m_di + c*dh_m_eg;

x1 =  (A*m(1) + D*m(2) + G*m(3)) / det_A;
x2 =  (B*m(1) + E*m(2) + H*m(3)) / det_A;
x3 =  (C*m(1) + F*m(2) + I*m(3)) / det_A;

x = [x1;x2;x3];

Гауссова ліквідація:

function x = GaussianEliminationSolve(A, m)
%
% FLOPS Count:      Min   Alternate
%
% Multiplications:  11    16
% Divisions:         6     3
% Add/Subtractions: 11    11
% Total:            28    30
%

a = A(1,1);
b = A(1,2);
c = A(1,3);

d = A(2,1);
e = A(2,2);
f = A(2,3);

g = A(3,1);
h = A(3,2);
i = A(3,3);

b1 = m(1);
b2 = m(2);
b3 = m(3);

% Get to echelon form

op1 = d/a;

e_dash  = e  - op1*b;
f_dash  = f  - op1*c;
b2_dash = b2 - op1*b1;

op2 = g/a;

h_dash  = h  - op2*b;
i_dash  = i  - op2*c;
b3_dash = b3 - op2*b1; 

op3 = h_dash / e_dash;

i_dash2  = i_dash  - op3*f_dash;
b3_dash2 = b3_dash - op3*b2_dash;

% Back substitution

x3 = (b3_dash2                  ) / i_dash2;
x2 = (b2_dash        - f_dash*x3) / e_dash;
x1 = (b1      - b*x2 -      c*x3) / a;

x = [x1 ; x2 ; x3];

Примітка. Будь ласка, додайте свої власні методи та рахунки до цієї публікації.


Чи обчислювали ви час, який потрібно було вирішити двома методами?
nicoguaro

Ні. Код, наведений вище, взагалі не буде швидко виконуватись. Сенс полягав у тому, щоб отримати явний підрахунок FLOPS та надати код для огляду, якщо я щось пропустив,
Дамієн

У LU 5 підрозділів можна перетворити на 5 MUL за рахунок 2 додаткових взаємних операцій (тобто 1 / U11 та 1 / U22). Це буде специфічно для арки щодо того, чи є там прибуток.
Демієн

2
Припускаючи, що я не неправильно підрахував, наближаючи A1b від 2bAbвимагатиме 12 множення, 9 додавання / віднімання, і жодних ділень. АпроксимаційнаA1b від 3(bAb)+A2bвимагатиме 21 множення та 18 додавання / віднімання. РозрахунокA1bза допомогою цієї явної формули виглядає 33 множення, 17 додавання / віднімання та 1 поділ. Як я вже говорив, мої номери можуть бути вимкнені, тому ви можете перевірити ще раз.
Джефф Оксберрі

@GeoffOxberry, я перегляну його і доповіду.
Демієн

4

Можливо, правило Крамера. Якщо ви можете уникнути повороту, можливо LU-факторизація; це матриця 3x3, тому розгортати петлі вручну було б просто. Будь-яке інше, ймовірно, передбачає розгалуження, і я сумніваюся, що метод підпростору Крилова досить часто сходиться в 1 або 2 ітераціях, щоб він того вартував.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.