Advertisement
m4ly

Metoda Choleskiego. Rozkład macierzy L i U Doolittle

Jan 24th, 2014
337
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.07 KB | None | 0 0
  1. /*
  2.  
  3. Autor: Dawid Mocek
  4.  
  5. 2014-01-05
  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ą Doolittle), 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. #include <iostream>
  37. #include <string>
  38. #include <vector>
  39. #include <fstream>
  40. #include <iomanip>
  41. using namespace std;
  42. // Dla czytelniejszego kodu
  43. typedef vector<vector<double>> Macierz;
  44. typedef vector<double> Wektor;
  45. /*
  46. a) Funkcja czytająca macierz A i wektor B z pliku oraz rozmiar n macierzy A i wektorów B i X z
  47. klawiatury
  48. Tu modyfikujemy domyślne Macierze A i B utworzone w main()
  49. Zwraca: rozmiar 'N' macierzy - potrzebne dla pętli w następnych funkcjach
  50. */
  51. int Czytaj(string plik_zestawu, Macierz &A, Wektor& B)
  52. {
  53.     int n = 0;
  54.     cout << "Podaj rozmiar 'N' macierzy A i wektorow B i X: ";
  55.     cin >> n;
  56.     // Poszerzamy wektor B i macierz A do rozmiaru N;
  57.     A.resize(n);
  58.     for (int i = 0; i < n; i++)
  59.         A[i].resize(n);
  60.     B.resize(n);
  61.     // Czytamy wartości macierzy i wektora z pliku
  62.     ifstream ifs_zestaw = ifstream(plik_zestawu, ios::in);
  63.     for (int i = 0; i < n; ++i)
  64.     {
  65.         // Przesuwamy o +1 dla pobrania wartości Wektora - ostatnie liczby w liniach w
  66.         pliku zestawu
  67.         for (int j = 0; j < n + 1; ++j)
  68.         {
  69.             if (j < n)
  70.             {
  71.                 // Ładujemy wartości do macierz
  72.                 ifs_zestaw >> A[i][j];
  73.             }
  74.             else
  75.             {
  76.                 // Ładujemy wartości wektora
  77.                 ifs_zestaw >> B[i];
  78.             }
  79.         }
  80.     }
  81.     ifs_zestaw.close();
  82.     // Zwaracamy n-kę
  83.     return n;
  84. }
  85. /*
  86. b) Funkcja tworząca macierze L i U (metodą Dolittle) oraz sprawdzającą warunek utworzenia tych
  87. elementów (kontrola operacji dzielenia przez 0)
  88. Wyznaczamy macierze L i U (utworzone w main()) które w tej funkcji musimy nadpisać - &
  89. Dbamy o nie nadpisanie czegokolwiek w Macierzy A - const
  90. Funkcja zwraca TRUE jeśli wszystko poszło dobrze, FALSE jeśli doszło do dzielenia przez zero.
  91. */
  92. bool LU(int n, const Macierz A, Macierz &L, Macierz &U)
  93. {
  94.     // Nasze kochane macierze L i U
  95.     L.resize(n);
  96.     for (int i = 0; i < n; i++)
  97.         L[i].resize(n);
  98.     U.resize(n);
  99.     for (int i = 0; i < n; i++)
  100.         U[i].resize(n);
  101.     // tmp - suma iloczynów L[][] i U[][]
  102.     double tmp = 0;
  103.     for (int i = 0; i < n; i++)
  104.         L[i][i] = 1;
  105.     for (int j = 0; j < n; j++)
  106.         U[0][j] = A[0][j];
  107.     // Dzielenie przez zero
  108.     if (U[0][0] == 0)
  109.     {
  110.         return false;
  111.     }
  112.     for (int i = 1; i < n; i++)
  113.         L[i][0] = (A[i][0] / U[0][0]);
  114.     for (int i = 1; i < n; i++)
  115.     {
  116.         for (int j = i; j < n; j++)
  117.         {
  118.             tmp = 0;
  119.             for (int k = 0; k < i; k++)
  120.                 tmp = tmp + (L[i][k] * U[k][j]);
  121.             U[i][j] = A[i][j] - tmp;
  122.             // Dzielenie przez zero
  123.             if (U[i][i] == 0)
  124.             {
  125.                 return false;
  126.             }
  127.             if (i != j)
  128.             {
  129.                 tmp = 0;
  130.                 for (int k = 0; k < i; k++)
  131.                     tmp = tmp + L[j][k] * U[k][i];
  132.                 L[j][i] = (A[j][i] - tmp) / U[i][i];
  133.             }
  134.         }
  135.     }
  136.     return true;
  137. }
  138. /*
  139. c) Funkcja rozwiązuje dwa układy równań z macierzami trójkątnymi
  140. Dbamy o nie nadpisywanie czegokolwiek w L, U i B - const
  141. */
  142. void XY(int n, const Macierz L, const Macierz U, const Wektor B, Wektor& X, Wektor& Y)
  143. {
  144.     // X i Y poszerzamy
  145.     X.resize(n);
  146.     Y.resize(n);
  147.     // tmp - przechowuje przy wyznaczaniu X i Y sumę iloczynów L[][] z Y[] oraz U[][] z X[]
  148.     double tmp = 0;
  149.     Y[0] = B[0];
  150.     for (int i = 0; i < n; i++)
  151.     {
  152.         tmp = 0;
  153.         for (int k = 0; k < i; k++)
  154.         {
  155.             tmp = tmp + (L[i][k] * Y[k]);
  156.         }
  157.         Y[i] = B[i] - tmp;
  158.     }
  159.     X[n - 1] = Y[n - 1] / U[n - 1][n - 1];
  160.     for (int i = (n - 2); i >= 0; i--)
  161.     {
  162.         tmp = 0;
  163.         for (int k = i; k < n; k++)
  164.         {
  165.             tmp = tmp + (U[i][k] * X[k]);
  166.         }
  167.         X[i] = (Y[i] - tmp) / U[i][i];
  168.     }
  169. }
  170. /*
  171. d) Funkcja generująca raport do pliku. Raport ma zawierać dane wejściowe (macierz A, wektor
  172. B), dane pośrednie (macierze L i U)
  173. oraz wyniki obliczeń wektorów Y i X. Obydwa wektory mają mieć postać wykładniczą(mantysa i
  174. cecha), a mantysa ma mieć 10 cyfr znaczących.
  175. */
  176. void GenerujRaport(string plik_raportu, int N, const Macierz A, const Wektor B, const Macierz
  177.     L, const Macierz U, const Wektor X, const Wektor Y)
  178. {
  179.     ofstream ofs_raport;
  180.     ofs_raport.open(plik_raportu);
  181.     ofs_raport << "--> Macierz A <--" << endl;
  182.     for (int i = 0; i < N; i++)
  183.     {
  184.         for (int j = 0; j < N; j++)
  185.         {
  186.             ofs_raport << A[i][j] << " ";
  187.         }
  188.         ofs_raport << endl;
  189.     }
  190.     ofs_raport << endl;
  191.     ofs_raport << "--> Wektor B <--" << endl;
  192.     for (int i = 0; i < N; i++)
  193.     {
  194.         ofs_raport << B[i] << endl;
  195.     }
  196.     ofs_raport << endl;
  197.     ofs_raport << "--> Macierz L <--" << endl;
  198.     for (int i = 0; i < N; i++)
  199.     {
  200.         for (int j = 0; j < N; j++)
  201.         {
  202.             ofs_raport << L[i][j] << " ";
  203.         }
  204.         ofs_raport << endl;
  205.     }
  206.     ofs_raport << endl;
  207.     ofs_raport << "--> Macierz U <--" << endl;
  208.     for (int i = 0; i < N; i++)
  209.     {
  210.         for (int j = 0; j < N; j++)
  211.         {
  212.             ofs_raport << U[i][j] << " ";
  213.         }
  214.         ofs_raport << endl;
  215.     }
  216.     ofs_raport << endl;
  217.     // 10 cyfr znaczących
  218.     ofs_raport.precision(10);
  219.     // Ustawmy notacje wykładniczą dla wektorów
  220.     ofs_raport.setf(ios::scientific);
  221.     ofs_raport << "--> Wektor X <--" << endl;
  222.     if (X.empty())
  223.     {
  224.         ofs_raport << "Nie istnieje z powodu bledu dzielenia" << endl;
  225.     }
  226.     else
  227.     {
  228.         for (int i = 0; i < N; i++)
  229.         {
  230.             ofs_raport << X[i] << endl;
  231.         }
  232.         ofs_raport << endl;
  233.     }
  234.     ofs_raport << "--> Wektor Y <--" << endl;
  235.     if (Y.empty())
  236.     {
  237.         ofs_raport << "Nie istnieje z powodu bledu dzielenia" << endl;
  238.     }
  239.     else
  240.     {
  241.         for (int i = 0; i < N; i++)
  242.         {
  243.             ofs_raport << Y[i] << endl;
  244.         }
  245.         ofs_raport << endl;
  246.     }
  247.     ofs_raport.close();
  248. }
  249. int main(void)
  250. {
  251.     // Plik z zestawem
  252.     string plik_zestawu = "D:\\Choleski\\Zestawy\\Zestaw1.txt";
  253.     // Plik raportu - trzeba go ręcznie utworzyć z powodu praw
  254.     string plik_raportu = "D:\\Choleski\\Raporty\\Raport_zestaw1.txt";
  255.     // Nasza Macierz i Wektor
  256.     Macierz A;
  257.     Wektor B;
  258.     // Czytamy z pliku
  259.     int N = Czytaj(plik_zestawu, A, B);
  260.     Macierz L;
  261.     Macierz U;
  262.     bool blad = LU(N, A, L, U);
  263.     // Wektory X i Y ustawiamy na puste(0) - na wypadek zwrócenia FALSE przez funkcje LU.
  264.     // Dzięki temu możemy łatwo sprawdzić w funkcji GenerujRaport
  265.     // czy wektory dalej są puste i zapisać do pliku raportu błąd dzielenia przez zero.
  266.     Wektor X(0);
  267.     Wektor Y(0);
  268.     // Jeśli wystąpił błąd dzielenia przez zero - XY się nie wykona
  269.     if (blad)
  270.     {
  271.         XY(N, L, U, B, X, Y);
  272.     }
  273.     GenerujRaport(plik_raportu, N, A, B, L, U, X, Y);
  274.     return 0;
  275. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement