2011-12-18 15:04:21 +01:00

288 lines
5.5 KiB
Plaintext

! gauss.tri implementiert die Gauss-Elimination
! für nicht-singuläre quadratische rationale
! Matrizen A der Größe n x n und löst ein Gleichungs-
! system der Form Ax=b.
let
const n ~ 4;
!Record zur Behandlung rationaler Zahlen
type Rational ~ record
p: Integer,
q: Integer
end;
!bei Änderung von n sollte hier die Dimension
!mit verändert werden
type Column ~ record
r: array 4 of Rational
end;
type Matrix ~ record
c: array 4 of Column
end;
!Methode zur GGT-Bestimmung
func ggt(a: Integer, b: Integer) : Integer ~
if b = 0 then a
else ggt(b, a // b);
!Kürzt einen Rational
proc reduce(var x: Rational) ~
let
var i : Integer
in begin
i := ggt(x.p,x.q);
if i = 0 then begin i := 1; end else ;
x.p := x.p / i;
x.q := x.q / i;
end;
!Methode zur Addition zweier Rationals
proc add(x: Rational, y: Rational, var temp: Rational) ~
let
var b: Integer
in begin
temp.q := x.q*y.q;
temp.p := (x.p*y.q) + (y.p*x.q);
reduce(var temp);
end;
!Methode zur Subtraktion zweier Rationals
proc sub(x: Rational, y: Rational, var temp: Rational) ~
let
var b: Integer
in begin
temp.q := y.q;
temp.p := 0 - y.p;
add(x, temp, var temp);
end;
!Multiplikation zweier Rationals
proc mul(x: Rational, y: Rational, var temp: Rational) ~
let
var b: Integer
in begin
temp.p := x.p*y.p;
temp.q := x.q*y.q;
reduce(var temp);
end;
!Teilt x durch y
proc div(x: Rational, y: Rational, var temp: Rational) ~
let
var b: Integer
in begin
temp.q := y.p;
temp.p := y.q;
mul(x,temp,var temp)
end;
!Löst Ax=b für eine nxn-Dreiecksmatrix
proc solve(a: Matrix, b: Column, var x: Column) ~
let
var i: Integer;
var j: Integer;
var temp : Rational
in begin
i := n-1;
while i >= 0 do begin
j := n-1;
x.r[i] := b.r[i];
while j > i do begin
mul(a.c[j].r[i],x.r[j],var temp);
sub(x.r[i],temp,var x.r[i]);
j := j - 1;
end;
div(x.r[i],a.c[i].r[i],var x.r[i]);
i := i - 1;
end;
end;
!Invertiert ein Rational
proc inv(var x: Rational) ~
let
var temp: Rational
in begin
temp.q := x.p;
temp.p := x.q;
x := temp;
end;
!Vertauscht die Zeilen i und j von A und b
proc switch(var a:Matrix, var b: Column, i: Integer, j: Integer) ~
let
var temp: Rational;
var k: Integer
in begin
k := 0;
!Vertausche die Zeilen der Matrix
while k < n do begin
temp := a.c[k].r[i];
a.c[k].r[i] := a.c[k].r[j];
a.c[k].r[j] := temp;
k := k + 1;
end;
!Vertausche die Zeilen des Vektors
temp := b.r[i];
b.r[i] := b.r[j];
b.r[j] := temp;
end;
!Vergleicht zwei Rationals a und b
func greater(a: Rational, b: Rational): Boolean ~
if (a.p*b.q) > (a.q*b.p) then true else false;
!Implementiert Spaltenpivotwahl für Gauss. Liefert das Inverse des Pivot-Elements sowie
!die Matrix nach Vertauschung
proc getPivot(line: Integer, var a: Matrix, var b: Column, var pivot: Rational) ~
let
var i: Integer;
var max: Rational;
var temp: Integer
in begin
i := line + 1;
max := a.c[line].r[line];
temp := line;
while i < n do begin
if greater(a.c[line].r[i],max) then begin
max := a.c[line].r[i];
temp := i;
end else ;
i := i + 1;
end;
if \ (temp = line) then begin
switch(var a, var b,temp,line);
end
else ;
pivot := max;
inv(var pivot);
end;
!Subtrahiert von der j-ten Zeile die i-te mal z
proc linesub(var a: Matrix, var b: Column, i: Integer, j: Integer, z: Rational) ~
let
var k: Integer;
var temp: Rational
in begin
k := 0;
while k < n do begin
mul(a.c[k].r[i],z,var temp);
sub(a.c[k].r[j],temp,var a.c[k].r[j]);
k := k + 1;
end;
mul(b.r[i],z,var temp);
sub(b.r[j],temp,var b.r[j]);
end;
!Berechnet aus einer nxn-Matrix eine nxn-obere Dreiecksmatrix mit Spaltenpivotwahl
proc gauss(var a:Matrix, var b: Column) ~
let
var pivot: Rational;
var temp: Rational;
var i: Integer;
var j: Integer
in begin
i := 0;
while i < n do begin
getPivot(i,var a, var b, var pivot);
j := (i+1);
!subtrahiere von den restlichen Zeilen Vielfache der Pivot-Zeile
while j < n do begin
temp := a.c[i].r[j];
if \(temp.p = 0) then begin
mul(temp,pivot,var temp);
linesub(var a, var b, i, j, temp);
end else ;
j := j + 1;
end;
i := i + 1;
end;
end;
!Liest eine Matrix ein
proc readMatrix(var a: Matrix) ~
let
var i: Integer;
var j: Integer;
var col: Column;
var rat: Rational
in begin
i := 0;
while i < n do begin
j := 0;
while j < n do begin
getint(var rat.p);
getint(var rat.q);
col.r[j] := rat;
j := j + 1;
end;
a.c[i] := col;
i := i + 1;
end
end;
!Liest den Vektor b ein
proc readVector(var b: Column) ~
let
var i: Integer;
var rat: Rational
in begin
i := 0;
while i < n do begin
getint(var rat.p);
getint(var rat.q);
b.r[i] := rat;
i := i + 1;
end;
end;
var i: Integer;
var a: Matrix;
var b: Column;
var x: Column;
var temp: Rational;
var j: Integer
in begin
readMatrix(var a);
readVector(var b);
gauss(var a, var b);
!Ausgabe von A und b nach Ausführung der
!Gauss-Elimination
! i := 0;
! while i < n do begin
! j := 0;
! while j < n do begin
! putint(a.c[i].r[j].p);
! put(chr(47));
! putint(a.c[i].r[j].q);
! put(chr(9));
! j := j + 1;
! end;
! i := i + 1;
! end;
! i := 0;
! while i < 3 do begin
! putint(b.r[i].p);
! put(chr(47));
! putint(b.r[i].q);
! put(chr(9));
! i := i + 1;
! end;
!Ausgabe von x
solve(a,b,var x);
i := 0;
while i < n do begin
putint(x.r[i].p);
put(chr(47));
putint(x.r[i].q);
put(chr(9));
i := i + 1;
end;
end