home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / spezial / 15 / linit / linit.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-12-15  |  9.6 KB  |  296 lines

  1. PROGRAM Gauss_Seidel;
  2.  
  3. { Löst ein lineares Gleichungssystem iterativ nach dem Verfahren von }
  4. { Gauß - Seidel.       Copyright (c) 1989 DMV - Verlag               }
  5. {                            und Heinz Hagemeyer                     }
  6.  
  7. USES Crt; { bei Turbo Pascal 3.0 muß diese Zeile entfernt werden     }
  8.  
  9. CONST Nmax = 50;   { Max. Anzahl der Gleichungen / Unbekannten       }
  10.  
  11. TYPE Index = 1 .. Nmax;
  12.      Matrix = ARRAY [1 .. Nmax,1 .. Nmax] OF Real;
  13.      Vektor = ARRAY [1 .. Nmax] OF Real;
  14.  
  15. { ------------------------------------------------------------------ }
  16.  
  17. { TURBO 3.0 benötigt noch diese Procedure :
  18.  
  19. FUNCTION Readkey : Char;
  20. VAR c : Char;
  21. BEGIN
  22.      Read (kbd,c) ;
  23.      ReadKey := c ;
  24. END;
  25.  
  26.  ------------------------------------------------------------------- }
  27.  
  28. FUNCTION Konvergent (VAR A : Matrix; N : Index) : BOOLEAN;
  29.  
  30. {         Überprüft Spalten - und Zeilensummenkriterium              }
  31. {                     siehe Begleittext                              }
  32.  
  33. VAR i,k          : Index   ;
  34.     Zeilensumme,
  35.     Spaltensumme : Real    ;
  36.     K1,K2        : BOOLEAN ;
  37.     c            : Char    ;
  38.  
  39. BEGIN
  40.      K1 := TRUE; K2 := TRUE;          { Annahme : Konvergent        }
  41.      i := 1;
  42.  
  43.      REPEAT                           { Für jedes i von 1 .. n      }
  44.            Zeilensumme :=  0 ;        { Vorbesetzen der Variablen   }
  45.            Spaltensumme := 0;
  46.  
  47.            FOR k := 1 TO N DO         { Berechnung der Summen       }
  48.            BEGIN
  49.                 Spaltensumme := Spaltensumme + Abs (A[k,i]);
  50.                 Zeilensumme  := Zeilensumme  + Abs (A[i,k]);
  51.            END;
  52.  
  53.            IF A[i,i] = 0 THEN         { Bestimmt nicht konvergent   }
  54.            BEGIN
  55.                 K1 := FALSE; K2 := FALSE;
  56.            END ELSE
  57.                                { Bestimmung der Konvergenzkriterien }
  58.            BEGIN
  59.                 Spaltensumme := Spaltensumme            ;
  60.                 Zeilensumme  := Zeilensumme             ;
  61.                 IF Spaltensumme >= Abs (A[i,i] + A[i,i])
  62.                                 THEN K1 := FALSE        ;
  63.                 IF Zeilensumme  >= Abs (A[i,i] + A[i,i])
  64.                                 THEN K2 := FALSE        ;
  65.            END;
  66.            i := Succ (i);              { nächstes i                }
  67.      UNTIL (i > n) OR NOT (K1 OR K2);
  68.                                        { Bestimmung der Konvergenz }
  69.  
  70.      IF K1 OR K2 THEN Konvergent := TRUE
  71.      ELSE                                 { Warnung ausgeben       }
  72.      BEGIN
  73.        WriteLn ('W A R N U N G   :   Gleichungssytem warscheinlich divergent');
  74.        Write   ('=============       trotzdem versuchen <J/N> ? ');
  75.        REPEAT c := Upcase (Readkey); UNTIL (c='J') OR (c='N');
  76.        Write (c);
  77.        Konvergent :=  c = 'J';       { Kovergenz per Tastatur ! }
  78.      END;
  79. END { Konvergent };
  80.  
  81. { ------------------------------------------------------------------------ }
  82.  
  83. FUNCTION Fehler (VAR Xalt, Xneu : Vektor ; n : Index ) : Real;
  84.  
  85. {                  Berechnet den Fehler aller  X - Werte                   }
  86. {     kann auf die speziellen Bedürfnisse des Anwenders angepaßt werden    }
  87. {         hier wird die Abweichung der Norm des Vektors berechnet          }
  88.  
  89. { ------------------------------------------------------------------------ }
  90.  
  91. FUNCTION Norm (VAR X : Vektor ; n : Index) : Real ;
  92.  
  93. {                  Norm des Vektors X                                      }
  94.  
  95. VAR No : Real ;
  96.      i : Index;
  97.  
  98. BEGIN
  99.      No := 0;
  100.      FOR i := 1 TO n DO No := No + Sqr (X[i]);
  101.      Norm := Sqrt (No);
  102. END;
  103.  
  104. BEGIN
  105.      Fehler := Abs (Norm (Xalt,n) - Norm (Xneu,n));
  106. END;
  107.  
  108. { -------------------------------------------------------------------------- }
  109.  
  110. PROCEDURE Ausgabe (VAR X : Vektor; n : Index);
  111. VAR Format : Byte;
  112. {       Format gibt an, ob ein- oder zweispaltig ausgegeben werden soll      }
  113. BEGIN
  114.      IF n > 30 THEN Format := 20 ELSE Format := 60;
  115.      WriteLn;
  116.      FOR n := 1 TO n DO
  117.      BEGIN
  118.           Write ('X':4,n:2,'=':3,X[n]:11:5,'':Format);
  119.      END;
  120.      WriteLn;
  121. END;
  122.  
  123. { ------------------------------------------------------------------------- }
  124.  
  125. PROCEDURE Iteration (VAR A : Matrix; VAR B : Vektor ; n : Index;
  126.                      VAR X : Vektor );
  127.  
  128. { 1 Schritt des Verfahrens nach Gauß - Seidel }
  129.  
  130. { ------------------------------------------------------------------------- }
  131.  
  132. FUNCTION ProduktSumme (VAR A : Matrix; VAR X : Vektor; i,n : Index) : Real;
  133. {            Berechnet die Summe Ai,k * Xk, k = 1, .. ,n                    }
  134. VAR k     : Index ;
  135.     Summe : Real  ;
  136.  
  137. BEGIN
  138.      Summe := 0;
  139.      FOR k := 1 TO n DO Summe := Summe + A[i,k] * X[k];
  140.      ProduktSumme := Summe;
  141. END;
  142.  
  143. { ------------------------------------------------------------------------- }
  144.  
  145. VAR i : Index;
  146.  
  147. BEGIN   { Iteration }
  148.      FOR i := 1 TO n DO
  149.          X[i] := (B[i] - ProduktSumme (A,X,i,n) + A[i,i] * X[i]) / A[i,i];
  150.                  {               siehe Begleittext                         }
  151. END     { Iteration } ;
  152.  
  153. { ------------------------------------------------------------------------ }
  154.  
  155. PROCEDURE Berechnung (VAR A : Matrix; VAR B : Vektor;
  156.                       VAR X : Vektor; n : Index; i : Byte);
  157.  
  158. { Führt i Iterationen durch }
  159. BEGIN
  160.      FOR i := 1 TO i DO Iteration (A,B,n,X);
  161. END;
  162.  
  163. { ----------------------------------------------------------------------- }
  164.  
  165. PROCEDURE BesetzeX (VAR A : Matrix; VAR B,X : Vektor; n : Index );
  166. {   Vorbesetzen des Lösungsvektors X durch Xi := Aii  und i = 1 .. n      }
  167. VAR i : Index;
  168. BEGIN
  169.      FOR i := 1 TO n DO
  170.          IF A [i,i] <> 0
  171.             THEN x[i] := B[i] / A[i,i]
  172.             ELSE
  173.             BEGIN
  174.                  WriteLn ;
  175.                  WriteLn ('Das Gleichungssystem kann mit diesem Verfahren',
  176.                           ' nicht gelöst werden,');
  177.                  WriteLn ('da A [',i:2,',',i:2,'] = 0 ist!');
  178.                  HALT;
  179.             END;
  180. END;
  181.  
  182. { ----------------------------------------------------------------------- }
  183.  
  184. PROCEDURE Eingabe (VAR A : Matrix; VAR B      : Vektor ;
  185.                    VAR n : Index ; VAR Wieoft : Byte    );
  186.  
  187. { Die Eingabe kann sowohl über die Tastatur erfolgen, als auch aus einer }
  188. {         Datei, da Pascal die Tastatur wie eine Datei behandelt.        }
  189. CONST  Tab       = 10;
  190.  
  191. VAR    Datei     : Text;
  192.        Antwort   : Char;
  193.        DateiName : String [20];
  194.        i,k       : Index;
  195.        Tastatur  : Boolean;
  196.        Offset    : Byte;
  197.  
  198. BEGIN
  199.      ClrScr;
  200.      WriteLn ('Iterative Berechnung eines linearen Gleichungssystem''s nach',
  201.               ' Gauß - Seidel.');
  202.      WriteLn ('============================================================',
  203.               '===============');
  204.      Write ('Dateiname - für Tastatur "CON" - eingeben : ');
  205.      ReadLn (DateiName);
  206.      WriteLn;
  207.  
  208.      {              Umwandlung in Großbuchstaben zum Vergleichen          }
  209.  
  210.      FOR i := 1 TO Length (Dateiname)
  211.              DO DateiName [i] := Upcase (DateiName [i]);
  212.      Tastatur := Dateiname = 'CON';
  213.      IF Tastatur THEN Offset := 1 ELSE Offset := 0;
  214.  
  215.      Assign (Datei, Dateiname);        { Datei versuchsweise öffnen und  }
  216.      {$I-}                             { auf Erfolg überprüfen.          }
  217.           Reset (Datei);
  218.      {$I+}
  219.  
  220.      IF (IOResult <> 0) THEN
  221.      BEGIN
  222.          WriteLn ('Datei existiert nicht, Programm wird abgebrochen ! ');
  223.          HALT;
  224.      END;
  225.  
  226.      Write   ('Anzahl der Gleichungen    : '); ReadLn (Datei,n);
  227.  
  228.     { Wird nicht von der Tastatur sondern aus einer anderen Datei        }
  229.     { gelesen, so werden die eingelesenen Daten auf dem Bildschirm aus-  }
  230.     { gegeben. Die Koeffizienten aber nur, wenn eine Zeile des LGS in    }
  231.     { eine Bildschirmzeile paßt. (siehe weiter unten)                    }
  232.  
  233.      IF NOT Tastatur THEN Write (n);
  234.      WriteLn;
  235.      IF n < 7 THEN WriteLn ('Und nun die Koeffizienten :');
  236.      WriteLn; WriteLn;
  237.  
  238.      FOR i := 1 TO N DO
  239.      BEGIN
  240.           FOR k := 1 TO N DO
  241.           BEGIN
  242.                IF Tastatur THEN GotoXY (Tab*(k-1)+1, WhereY - Offset);
  243.                Read (Datei, A [i,k]);
  244.                IF NOT Tastatur AND (n < 7) THEN Write (A [i,k]:Tab:3);
  245.           END;
  246.           IF Tastatur THEN GotoXY (Tab*n+1,WhereY - Offset);
  247.           ReadLn (Datei, B [i]);
  248.           IF NOT Tastatur AND (n<7) THEN WriteLn (B [i]:Tab:3);
  249.           IF     Tastatur THEN WriteLn;
  250.      END;
  251.      Close (Datei);
  252.      WriteLn;
  253.      Write ('Nach wieviel Schritten wünschen Sie eine Lösungsausgabe . ');
  254.      ReadLn (Wieoft);
  255. END; { Einlesen }
  256.  
  257. { ----------------------------------------------------------------------- }
  258.  
  259. FUNCTION Abbruch : Boolean;
  260. {                Wird nach i Iterationen aufgerufen.                      }
  261. VAR c : Char;
  262. BEGIN
  263.      WriteLn;
  264.      Write ('Noch eine Iteration ? <J/N> : ');
  265.      REPEAT c := Upcase (ReadKey); UNTIL (c='J') OR (c='N');
  266.      WriteLn (c:3);
  267.      Abbruch := c = 'N';
  268. END;
  269.  
  270. { =================== H A U P T P R O G R A M M =========================== }
  271.  
  272. VAR
  273.     X,B,Xalt : Vektor  ;
  274.     A        : Matrix  ;
  275.     n        : Index   ;
  276.     WieOft   : Byte    ;
  277.  
  278. BEGIN
  279.      ClrScr;
  280.      Eingabe (A,B,n,Wieoft);
  281.      BesetzeX (A,B,X,n);
  282.      Window (1,3,80,25);
  283.      ClrScr;
  284.      IF Konvergent (A,n) THEN
  285.      REPEAT
  286.           GotoXY (1,1);
  287.           WriteLn ('---- bitte warten ----');
  288.           Berechnung (A,B,X,n,Wieoft);
  289.           Xalt := X;
  290.           Iteration  (A,B,n,X);
  291.           ClrScr;
  292.           Ausgabe (X,n);
  293.           WriteLn;
  294.           WriteLn ('Abweichung der Norm von Xi = ',Fehler (X,Xalt,n));
  295.     UNTIL Abbruch;
  296. END.