Gauss-Jordan-Algorithmus
Der Gauss-Jordan-Algorithmus bestimmt eine LR-Zerlegung
P A = L R
von A. Dabei ist P eine Permutationsmatrix, die durch Zeilen- bzw. Spaltenvertauschungen aus einer Einheitsmatrix hervorgeht, sowie L eine untere und R eine obere Dreiecksmatrix.
Durch Vorwärts- und Rückwärtseinsetzen erhält man aus P, L und R die zu A inverse Matrix.
Als Pseudo Code sieht das Verfahren wie folgt aus:
procedure gaussInverse(n:vectorIndex; (* Größe der Matrix n x n *)
const A:matrix; (* Matrix A (Eingabe) *)
var Ainv:matrix; (* invertiertes A (Ausgabe) *)
var losbar:boolean); (* lösbar ? *)
const epsilon=2.2e-160;
var lu:matrix;
d:vector; (* Zeilenmaxima *)
permutation:array[vectorIndex] of vectorIndex;
i,k,j,j0,m:vectorIndex;
zeilenmaximum,abslukj,lukk,piv,temp,summe:extended;
procedure tausch(a,b:vectorIndex);
var i:vectorIndex;
r:extended;
z:vector;
begin
i:=permutation[a];
permutation[a]:=permutation[b];
permutation[b]:=i;
r:=d[a];
d[a]:=d[b];
d[b]:=r;
z:=lu[a];
lu[a]:=lu[b];
lu[b]:=z;
end;
begin
losbar:=true;
lu:=A;
for k:=1 to n do begin
(* Zeilenmaximum bestimmen und Permutation initialisieren *)
permutation[k]:=k;
zeilenmaximum:=0.0;
for j:=1 to n do begin
abslukj:=abs(lu[k,j]);
if zeilenmaximum < abslukj then zeilenmaximum:=abslukj;
end;
if zeilenmaximum = 0.0 then losbar:=false; (* singulär *)
d[k]:=zeilenmaximum;
end;
if losbar then begin
k:=1;
while losbar
and (k <= pred(n)) do begin
piv:=abs(lu[k,k])/d[k];
j0:=k;
(* suche aktuelles Pivotelement *)
for j:=succ(k) to n do begin
temp:=abs(lu[j,k])/d[j];
if piv < temp then begin
piv:=temp; (* piv enthält das Pivotelement *)
j0:=j; (* j0 dessen Index *)
end;
end;
if piv < epsilon then losbar:=false
else begin
if j0 <> k then begin
tausch(j0,k);
end;
lukk:=lu[k,k];
for j:=succ(k) to n do begin
if lu[j,k] <> 0.0 then begin
lu[j,k]:=lu[j,k]/lukk;
temp:=lu[j,k];
for m:=succ(k) to n do begin
lu[j,m]:=lu[j,m]-temp*lu[k,m];
end;
end; (* if *)
end; (* for j *)
end; (* else *)
inc(k);
end; (* while *)
if abs(lu[n,n]) < epsilon then losbar:=false
else begin
for i:=1 to n do begin
for k:=1 to n do begin
if i = permutation[k] then Ainv[k,i]:=1.0 (* Einheitsmatrix *)
else Ainv[k,i]:=0.0;
if k > 1 then begin
for j:=1 to pred(k) do begin
Ainv[k,i]:=Ainv[k,i]-lu[k,j]*Ainv[j,i];
end;
end;
end;
for k:=n downto 1 do begin
summe:=0.0;
for j:=succ(k) to n do begin
summe:=summe+lu[k,j]*Ainv[j,i]
end;
Ainv[k,i]:=(Ainv[k,i]-summe)/lu[k,k];
end;
end;
end; (* else *)
end; (* if *)
end; (* gauss *)
procedure matrixVectorProduct(n:vectorIndex; (* Ordnung *)
const A:matrix; (* n x n Matrix *)
const x:vector; (* Eingabe-Vektor x *)
var y:vector); (* Ausgabe-Vektor y=Ax *)
var i,j:vectorIndex;
s:extended;
begin
for i:=1 to n do begin
s:=0;
for j:=1 to n do begin
s:=s+x[j]*A[i,j];
end;
y[i]:=s;
end;
end;
P A = L R
von A. Dabei ist P eine Permutationsmatrix, die durch Zeilen- bzw. Spaltenvertauschungen aus einer Einheitsmatrix hervorgeht, sowie L eine untere und R eine obere Dreiecksmatrix.
Durch Vorwärts- und Rückwärtseinsetzen erhält man aus P, L und R die zu A inverse Matrix.
Als Pseudo Code sieht das Verfahren wie folgt aus:
procedure gaussInverse(n:vectorIndex; (* Größe der Matrix n x n *)
const A:matrix; (* Matrix A (Eingabe) *)
var Ainv:matrix; (* invertiertes A (Ausgabe) *)
var losbar:boolean); (* lösbar ? *)
const epsilon=2.2e-160;
var lu:matrix;
d:vector; (* Zeilenmaxima *)
permutation:array[vectorIndex] of vectorIndex;
i,k,j,j0,m:vectorIndex;
zeilenmaximum,abslukj,lukk,piv,temp,summe:extended;
procedure tausch(a,b:vectorIndex);
var i:vectorIndex;
r:extended;
z:vector;
begin
i:=permutation[a];
permutation[a]:=permutation[b];
permutation[b]:=i;
r:=d[a];
d[a]:=d[b];
d[b]:=r;
z:=lu[a];
lu[a]:=lu[b];
lu[b]:=z;
end;
begin
losbar:=true;
lu:=A;
for k:=1 to n do begin
(* Zeilenmaximum bestimmen und Permutation initialisieren *)
permutation[k]:=k;
zeilenmaximum:=0.0;
for j:=1 to n do begin
abslukj:=abs(lu[k,j]);
if zeilenmaximum < abslukj then zeilenmaximum:=abslukj;
end;
if zeilenmaximum = 0.0 then losbar:=false; (* singulär *)
d[k]:=zeilenmaximum;
end;
if losbar then begin
k:=1;
while losbar
and (k <= pred(n)) do begin
piv:=abs(lu[k,k])/d[k];
j0:=k;
(* suche aktuelles Pivotelement *)
for j:=succ(k) to n do begin
temp:=abs(lu[j,k])/d[j];
if piv < temp then begin
piv:=temp; (* piv enthält das Pivotelement *)
j0:=j; (* j0 dessen Index *)
end;
end;
if piv < epsilon then losbar:=false
else begin
if j0 <> k then begin
tausch(j0,k);
end;
lukk:=lu[k,k];
for j:=succ(k) to n do begin
if lu[j,k] <> 0.0 then begin
lu[j,k]:=lu[j,k]/lukk;
temp:=lu[j,k];
for m:=succ(k) to n do begin
lu[j,m]:=lu[j,m]-temp*lu[k,m];
end;
end; (* if *)
end; (* for j *)
end; (* else *)
inc(k);
end; (* while *)
if abs(lu[n,n]) < epsilon then losbar:=false
else begin
for i:=1 to n do begin
for k:=1 to n do begin
if i = permutation[k] then Ainv[k,i]:=1.0 (* Einheitsmatrix *)
else Ainv[k,i]:=0.0;
if k > 1 then begin
for j:=1 to pred(k) do begin
Ainv[k,i]:=Ainv[k,i]-lu[k,j]*Ainv[j,i];
end;
end;
end;
for k:=n downto 1 do begin
summe:=0.0;
for j:=succ(k) to n do begin
summe:=summe+lu[k,j]*Ainv[j,i]
end;
Ainv[k,i]:=(Ainv[k,i]-summe)/lu[k,k];
end;
end;
end; (* else *)
end; (* if *)
end; (* gauss *)
procedure matrixVectorProduct(n:vectorIndex; (* Ordnung *)
const A:matrix; (* n x n Matrix *)
const x:vector; (* Eingabe-Vektor x *)
var y:vector); (* Ausgabe-Vektor y=Ax *)
var i,j:vectorIndex;
s:extended;
begin
for i:=1 to n do begin
s:=0;
for j:=1 to n do begin
s:=s+x[j]*A[i,j];
end;
y[i]:=s;
end;
end;