m4ly

Metoda Choleskiego. Rozkład macierzy L i U Gauss

Jan 20th, 2014
285
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.97 KB | None | 0 0
  1. /*
  2.  
  3. Autor: Dawid Mocek
  4.  
  5. 2014-01-19
  6.  
  7. Testowane pod MS VS Express 2013
  8.  
  9. Napisać program rozwiązujący układ równań AX=B metodą Choleskiego
  10. Program ma zawierać:
  11. a) funk. czytającą macierz A i wektor B z pliku oraz rozmiar n macierzy A i wektorów B i X z kalawiatury
  12. b) funk. tworzącą macierze Li U (metodą Gaussa), oraz sprawdzającą warunek utworzenia tych elementów (kontrola dzielenia przez 0)
  13. c) funkcję rozwiązującą dwa układy równań z macierzami trójkątnymi
  14. d) funkcję generująca raport do pliku....
  15.  
  16.  
  17. Obsługa:
  18.  
  19. Plik tekstowy z zestawem ma mieć  tak poukładane wartość:
  20.  
  21. --- Zesta1.txt /Start/ ----
  22. 10 1 1 1 2 15
  23. 3 20 4 2 1 30
  24. 5 1 40 9 5 60
  25. 3 0 1 10 1 15
  26. 6 2 1 1 20 30
  27. ---- /End/ ------
  28.  
  29. Pierwsze 5 kolumn to macierz A a ostatnia Kolumna to wektor B
  30.  
  31. czyli dla takiego zestawu przy uruchomieniu programu(tak został zaprojketowany) podajemy liczbę 5 i program wygeneruje raport - a jak nie wygeneruje plik raportu utworzyc recznie
  32.  
  33. plik wynikowy-raportu oraz zestawu nalezy ustawić w funkcji main()
  34.  
  35. */
  36.  
  37. #include <iostream>
  38. #include <string>
  39. #include <vector>
  40. #include <fstream>
  41. #include <iomanip>
  42.  
  43. // Dla funkcji GenerujRaport() - gdziekolwiek indziej stosować z rozwagą !
  44. #define for_loop(a, b, c) for (int a = b; a < c; a++)
  45. #define for_i_loop for_loop(i, 0, n)
  46. #define for_j_loop for_loop(j, 0, n)
  47.  
  48. using namespace std;
  49.  
  50. // Czytelniejszy kod
  51. typedef vector<vector<double>> Macierz;
  52. typedef vector<double> Wektor;
  53.  
  54.  
  55. /*
  56. a) Funkcja czytjąca macierz A i wektor B z pliku oraz rozmiar n macierzy A i wektorów B i X z klawiatury
  57.  
  58. Tu modyfikujemy domyślne Macierze A i B utowrzone w main() także potrzebne są &
  59. Zwraca: rozmiar 'N' macierzy - potrzebne dla pętli w następych funkcjach
  60. */
  61. int Czytaj(string plik_zestawu, Macierz &A, Wektor& B)
  62. {
  63.  
  64.     int n = 0;
  65.     cout << "Podaj rozmiar 'N' macierzy A i wektorow B i X: ";
  66.     cin >> n;
  67.  
  68.     // Poszerzamy wektor B i macierz A do rozmiaru N;
  69.     A.resize(n);
  70.     for (int i = 0; i < n; i++)
  71.         A[i].resize(n);
  72.  
  73.     B.resize(n);
  74.  
  75.     // Czytamy wartości macierzy i wektoru z pliku
  76.     ifstream ifs_zestaw = ifstream(plik_zestawu, ios::in);
  77.  
  78.     for (int i = 0; i < n; i++)
  79.     {
  80.         // Przesuwamy o +1 dla pobrania wartości Wektora - ostatnie liczby w liniach w pliku zestawu
  81.         for(int j = 0; j < n + 1; ++j)
  82.         {
  83.  
  84.             if (j < n)
  85.                 // Ładujemy wartości do macierzy
  86.                 ifs_zestaw >> A[i][j];
  87.             else
  88.                 // Ładujemy wartości wektora
  89.                 ifs_zestaw >> B[i];
  90.         }
  91.     }
  92.  
  93.     ifs_zestaw.close();
  94.  
  95.     // Zwaracamy n-kę
  96.     return n;
  97. }
  98.  
  99. /*
  100. b) Funkcja tworząca macierze L i U  (metodą Gaussa) oraz sprawdzającą warunek utworzenia tych elementów (kontrola operacji dzielenia przez 0)
  101.  
  102. Wyznaczamy macierze L i Y (utworzone w main()) które w tej funkcji musimy nadpisać - &
  103. Dbamy o nie nadpisanie czegokolwiek w Macierzy A - const
  104.  
  105. Funkcja zwraca TRUE jeśli wszystko poszło dobrze, FALSE jeśli doszło do dzielenia przez zero.
  106. */
  107. bool LU(int n, const Macierz A, Macierz &L, Macierz &U)
  108. {
  109.     // Nasze kochane macierze L i U
  110.     L.resize(n);
  111.     U.resize(n);
  112.  
  113.     for (int i = 0; i < n; i++)
  114.     {
  115.         L[i].resize(n);
  116.         U[i].resize(n);
  117.  
  118.         for (int j = 0; j < n; j++)
  119.         {
  120.             U[i][j] = A[i][j];
  121.             L[i][j] = 0;
  122.         }
  123.     }
  124.  
  125.     // Jedynki po przekątnej
  126.     for (int i = 0; i < n; i++)
  127.         L[i][i] = 1;
  128.    
  129.     for (int k = 0; k < n; k++)
  130.     {
  131.         for (int i = k + 1; i < n; i++)
  132.         {  
  133.             // Sprawdź dzielenie
  134.             if (U[k][k] == 0)
  135.                 return false;
  136.  
  137.             // Obliczamy marzcierz L
  138.             L[i][k] = U[i][k] / U[k][k];
  139.            
  140.             for (int j = k + 1; j < n; j++)
  141.             {
  142.                 // Obliczamy macierzy U
  143.                 U[i][j] -= ((U[i][k] * U[k][j]) / U[k][k]);
  144.             }
  145.  
  146.             // Zerowanie U
  147.             U[i][k] = 0;
  148.         }
  149.     }
  150.  
  151.     return true;
  152. }
  153.  
  154. /*
  155. c) Funkcja rozwiązuje dwa układy równań z macierzami trjókątnymi
  156.  
  157. Dbamy o nie nadpisywanie czegokolwiek w L, U i B - const
  158.  
  159. */
  160. void XY(int n, const Macierz L, const Macierz U, const Wektor B, Wektor& X, Wektor& Y)
  161. {
  162.     // X i Y poszerzamy
  163.     X.resize(n);
  164.     Y.resize(n);
  165.  
  166.     // tmp - przeochwuje przy wyznaczaniu X i Y sumę iloczynów L[][] z Y[] oraz U[][] z X[]
  167.     double tmp;
  168.  
  169.     for (int i = 0; i < n; i++)
  170.     {
  171.         tmp = 0;
  172.         for (int j = 0; j < n; j++)
  173.         {
  174.             tmp += (L[i][j] * Y[j]);
  175.         }
  176.         Y[i] = B[i] - tmp;
  177.     }
  178.  
  179.  
  180.     X[n - 1] = Y[n - 1] / U[n - 1][n - 1];
  181.  
  182.     for (int i = (n - 2); i >= 0; i--)
  183.     {
  184.             tmp = 0;
  185.  
  186.         for (int k = i; k < n; k++)
  187.         {
  188.             tmp += (U[i][k] * X[k]);
  189.         }
  190.  
  191.         X[i] = (Y[i] - tmp) / U[i][i];
  192.     }
  193. }
  194. /*
  195. d) Funkcja generująca raport do pliku. Raport ma zawierać dane wejściowe (macierz A, wektor B), dane pośrednie (macierze L i U)
  196. oraz wyniki obliczeń wektorów Y i X. Obydwa wektory mają mieć postać wykładniczą(mantysa i cecha), a mantysa ma mieć 10 cyfr znaczących.
  197. */
  198. void GenerujRaport(string plik_raportu, int n, const Macierz A, const Wektor B, const Macierz L, const Macierz U, const Wektor X, const Wektor Y)
  199. {
  200.     ofstream ofs_raport;
  201.     ofs_raport.open(plik_raportu);
  202.  
  203.    
  204.     ofs_raport << "--> Macierz A <--" << endl;
  205.     for_i_loop
  206.     {
  207.         for_j_loop { ofs_raport << A[i][j] << " "; }
  208.        
  209.         ofs_raport << endl;
  210.     }
  211.     ofs_raport << endl;
  212.  
  213.  
  214.     ofs_raport << "--> Wektor B <--" << endl;
  215.     for_i_loop { ofs_raport << B[i] << endl; }
  216.     ofs_raport << endl;
  217.  
  218.     ofs_raport << "--> Macierz L <--" << endl;
  219.     for_i_loop
  220.     {
  221.         for_j_loop { ofs_raport << L[i][j] << " "; }
  222.        
  223.         ofs_raport << endl;
  224.     }
  225.     ofs_raport << endl;
  226.  
  227.     ofs_raport << "--> Macierz U <--" << endl;
  228.     for_i_loop
  229.     {
  230.         for_j_loop { ofs_raport << U[i][j] << " "; }
  231.         ofs_raport << endl;
  232.     }
  233.     ofs_raport << endl;
  234.  
  235.     // 10 cyfr znaczących
  236.     ofs_raport.precision(10);
  237.  
  238.     // Ustawmy notacje wykładniczą dla wektorów
  239.     //ofs_raport.setf(ios::scientific);
  240.  
  241.     ofs_raport << "--> Wektor X <--" << endl;
  242.     if (X.empty())
  243.     {
  244.  
  245.         ofs_raport << "Nie istnieje z powodu bledu dzielenia" << endl;
  246.     }
  247.     else
  248.     {
  249.         for_i_loop{ ofs_raport << fixed << X[i] << endl; }
  250.         ofs_raport << endl;
  251.     }
  252.  
  253.  
  254.     ofs_raport << "--> Wektor Y <--" << endl;
  255.     if (Y.empty())
  256.         ofs_raport << "Nie istnieje z powodu bledu dzielenia" << endl;
  257.     else
  258.     {
  259.         for_i_loop{ ofs_raport << fixed  << Y[i] << endl; }
  260.         ofs_raport << endl;
  261.     }
  262.    
  263.     ofs_raport.close();
  264.  
  265. }
  266.  
  267. int main(void)
  268. {
  269.  
  270.     // Plik z zestawem
  271.     string plik_zestawu = "D:\\Choleski\\Zestawy\\Zestaw4.txt";
  272.    
  273.     // Plik raportu - trzeba go ręcznie utowrzyć z powodu praw
  274.     string plik_raportu = "D:\\Choleski\\Raporty\\Raport_zestaw4.txt";
  275.    
  276.     // Nasza Macierz i Wektor
  277.     Macierz A;
  278.     Wektor B;
  279.    
  280.     // Czytamy z pliku
  281.     int N = Czytaj(plik_zestawu, A, B);
  282.  
  283.     Macierz L;
  284.     Macierz U;
  285.  
  286.     bool blad = LU(N, A, L, U);
  287.  
  288.     //  Wektory X i Y ustawiamy na puste(0) - na wypadek zwrócenia FALSE przez funkcje LU.
  289.     //  Dzięki temu możemy łatwo srawdzić w funkcji GenerujRaport
  290.     //  czy wektory dalej są puste i zapisać  do pliku raportu bląd dzielenia przez zero.
  291.     Wektor X(0);
  292.     Wektor Y(0);
  293.  
  294.     // Jesli wystąpił błąd dzielenia przez zero - XY się nie wykona
  295.     if (blad)
  296.     {
  297.         XY(N, L, U, B, X, Y);
  298.     }
  299.  
  300.     GenerujRaport(plik_raportu, N, A, B, L, U, X, Y);
  301.  
  302.     return 0;
  303. }
Advertisement
Add Comment
Please, Sign In to add comment