Advertisement
m4ly

Aproksymacja średniokwadratowa punktowa wielomianowa

Jan 22nd, 2014
287
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.55 KB | None | 0 0
  1. /*
  2. Dawid Mocek
  3.  
  4. Działa pod VS 2013 lub kompilatorem z C++11
  5. Ten kod w 100% działa pod windows
  6. Program wygeneruje od groma plików - lepiej je poprzenosic w osobne katalogi. Nazwy plików są schematyczne
  7.  
  8. Aproksymacja średniokwadratowa punktowa wielomianowa funkcji:
  9. y = sinx * cos3x
  10.  
  11. Ogólna treść zadania:
  12. Przeprowadzić aproksymację średniokwadratową punktowąw ielomianową
  13. funkcji y = sinx * cos3x x w przedziale <-2,2> dla 50 węzłów.
  14. Zwiększyć stopień wielomianu aproksymacyjnego od 1 do 20 i szukać najmniejszego błędu aproksymacji.
  15. Zrobić również doświadczenia na innych wartościach.
  16.  
  17. Co trzeba zmienic:
  18. string katalog_wynikowy
  19.  
  20. Co można zmienic:
  21.  
  22. DELIMITER
  23. DIR_DELIMITER
  24.  
  25. string katalog_wynikowy
  26. int liczbawezlow
  27. vector<int> stopienie
  28. vector<vector<double>> granice
  29.  
  30. Pliki CSV można otworzyć bezpośrednio w Excelu
  31. */
  32.  
  33. #include <iostream>
  34. #include <cmath>
  35. #include <fstream>
  36. #include <string>
  37. #include <vector>
  38. #include <sstream>
  39. #include <algorithm>
  40.  
  41. // Excel potrzebuje dla naszego jezyka(locale) takiego rozdzielacza dla pików csv:
  42. #define DELIMITER ';'
  43.  
  44. // Windows - pod Linuksem stosować "/"
  45. #define DIR_DELIMITER "\\"
  46.  
  47. using namespace std;
  48.  
  49. // Dla czytelniejszego kodu
  50. typedef vector<double> Wektor;
  51. typedef vector<vector<double>> Macierz;
  52.  
  53. // Struktura przechowuje dane-logi po każdej iteracji
  54. // Zastosowanie: łatwe znalezienie najmniejszego błędu apro. w plikach
  55. // raportów
  56. struct DaneLog
  57. {
  58.     double blad_aproksymacji;
  59.     double granica_prawa;
  60.     double granica_lewa;
  61.     int stopien;
  62.     string plik_raportu;
  63.     string plik_excela;
  64.  
  65.     DaneLog();
  66.     DaneLog(double blad_aproksymacji, double granica_prawa, double granica_lewa, int stopien, string plik_raportu, string plik_excela);
  67.     bool operator< (const DaneLog& org) const;
  68.     bool operator> (const DaneLog& org) const;
  69.     bool operator== (const DaneLog& org) const;
  70.     bool operator!= (const DaneLog& org) const;
  71.     friend ostream& operator<< (ostream& out, const DaneLog& org);
  72. };
  73.  
  74. DaneLog::DaneLog()
  75. : blad_aproksymacji(0.0), granica_prawa(0.0), granica_lewa(0.0), stopien(0), plik_excela(""), plik_raportu("")
  76. {
  77.  
  78. };
  79.  
  80. DaneLog::DaneLog(double blad_aproksymacji, double granica_prawa, double granica_lewa, int stopien, string plik_raportu, string plik_excela)
  81. : blad_aproksymacji(blad_aproksymacji), granica_prawa(granica_prawa), granica_lewa(granica_lewa), stopien(stopien), plik_raportu(plik_raportu), plik_excela(plik_excela)
  82. {
  83.  
  84. };
  85.  
  86. bool DaneLog::operator< (const DaneLog& org) const
  87. {
  88.     return blad_aproksymacji < org.blad_aproksymacji;
  89. };
  90. bool DaneLog::operator> (const DaneLog& org) const
  91. {
  92.     return !DaneLog::operator<(org);
  93. };
  94. bool DaneLog::operator== (const DaneLog& org) const
  95. {
  96.     return blad_aproksymacji == org.blad_aproksymacji;
  97. };
  98. bool DaneLog::operator!= (const DaneLog& org) const
  99. {
  100.     return !DaneLog::operator==(org);
  101. };
  102. ostream& operator<< (ostream& out, const DaneLog& org)
  103. {
  104.     return out << "Blad (st. = " << org.stopien << " ) = " << org.blad_aproksymacji << " w raporcie: \"" << org.plik_raportu << "\" i Excelu: \"" << org.plik_excela << "\", dla g.l. " << org.granica_lewa
  105.         << " i g.p. " << org.granica_prawa;
  106. }
  107.  
  108. ///////////////////////////////////////////////////////////////// Glowne funkcje /////////////////////////////////////////////////////////////////
  109.  
  110. // Liczy G
  111. Macierz * _G(const Wektor *wezly, const int stopien, const int liczbawezlow)
  112. {
  113.     Macierz *G = new Macierz();
  114.     G->resize(stopien + 1);
  115.     for (int z = 0; z <= stopien; z++)
  116.         (*G)[z].resize(stopien + 1);
  117.  
  118.     for (int j = 0; j <= stopien; ++j)
  119.     for (int k = 0; k <= stopien; ++k)
  120.     {
  121.         (*G)[k][j] = 0;
  122.  
  123.         for (int i = 0; i < liczbawezlow; ++i)
  124.             (*G)[k][j] += pow((*wezly)[i], k + j);
  125.  
  126.     }
  127.  
  128.     return G;
  129. }
  130.  
  131. // Liczy R
  132. Wektor * _R(const Wektor *wezly, const Wektor * fx, const int stopien, const int liczbawezlow)
  133. {
  134.     Wektor *R = new Wektor();
  135.     R->resize(stopien + 1);
  136.     for (int i = 0; i <= stopien; ++i)
  137.     {
  138.         (*R)[i] = 0;
  139.         for (int j = 0; j < liczbawezlow; ++j)
  140.             (*R)[i] += (*fx)[j] * pow((*wezly)[j], i);
  141.     }
  142.     return R;
  143. }
  144.  
  145. // Przygotowuje wezly oraz wartość f(x)
  146. void _Przygotuj(Wektor *fx, Wektor *wezly, const int liczbawezlow, const double granica_lewa, const double granica_prawa)
  147. {
  148.     fx->resize(liczbawezlow);
  149.     wezly->resize(liczbawezlow);
  150.  
  151.     double tmp = (granica_prawa - granica_lewa) / (liczbawezlow - 1);
  152.     for (int i = 0; i < liczbawezlow; ++i)
  153.     {
  154.         double x = granica_lewa + (i * tmp);
  155.         // y = sinx * cos3x
  156.         (*fx)[i] = sin(x)*(cos(3 * (x)));
  157.         (*wezly)[i] = x;
  158.     }
  159. }
  160.  
  161. // Macierz trójątna - zwraca false jesli dojdzie do dzielenia przez zero
  162. bool _MacierzTrj(Wektor *R, Macierz *G, const int stopien)
  163. {
  164.  
  165.     for (int k = 0; k <= stopien; ++k)
  166.     {
  167.         for (int i = k + 1; i <= stopien; ++i)
  168.         {
  169.             (*R)[i] -= ((*G)[i][k] * (*R)[k]) / (*G)[k][k];
  170.             for (int j = k + 1; j <= stopien; ++j)
  171.             {
  172.                 if ((*G)[k][k] == 0) return false;
  173.                 (*G)[i][j] -= ((*G)[i][k] * (*G)[k][j]) / (*G)[k][k];
  174.             }
  175.             (*G)[i][k] = 0;
  176.         }
  177.     }
  178.     return true;
  179. }
  180.  
  181. // Wyznaczamy niewiadomoe
  182. Wektor * _A(const Wektor *R, const Macierz *G, const int stopien)
  183. {
  184.     double suma;
  185.     Wektor *A = new Wektor();
  186.     A->resize(stopien + 1);
  187.  
  188.     (*A)[stopien] = (*R)[stopien] / (*G)[stopien][stopien];
  189.     for (int i = stopien - 1; i >= 0; --i)
  190.     {
  191.         suma = 0.0;
  192.         for (int j = i + 1; j <= stopien; ++j)
  193.             suma += (*G)[i][j] * (*A)[j];
  194.  
  195.         (*A)[i] = ((*R)[i] - suma) / (*G)[i][i];
  196.     }
  197.     return A;
  198. }
  199.  
  200. // Wyznacza wartości funkcji aproksymujacej
  201. Wektor * _Qx(const Wektor *A, const Wektor *_wezly, const int stopien, const int liczbawezlow)
  202. {
  203.     Wektor *Qx = new Wektor();
  204.     Qx->resize(liczbawezlow);
  205.     for (int i = 0; i < liczbawezlow; ++i)
  206.     for (int j = 0; j <= stopien; ++j)
  207.         (*Qx)[i] += (*A)[j] * pow((*_wezly)[i], j);
  208.  
  209.     return Qx;
  210. }
  211.  
  212. // Oblicza błąd aproksymacji
  213. double _Blad(const Wektor *Qx, const Wektor *Fx, const int liczbawezlow)
  214. {
  215.     double tmp = 0;
  216.     double blad_aproksymacji = 0;
  217.     for (int i = 0; i < liczbawezlow; ++i)
  218.         tmp += pow((*Qx)[i] - (*Fx)[i], 2);
  219.  
  220.     return (sqrt(tmp / liczbawezlow));
  221.  
  222. }
  223. //
  224. ////////////////////////////////////// Koniec głównych funkcji //////////////////////////////
  225.  
  226. // Raport do pliku
  227. string  _Raport(const string dir, const Wektor *wezly, const Wektor *fx, const Wektor *qx, const Wektor *A, const int liczbawezlow, const int stopien, const double granica_lewa, const double granica_prawa, const double blad)
  228. {
  229.     ostringstream  ss_file;
  230.     ss_file << "Raport_Stopien_" << stopien << "-liczbaWezlow_" << liczbawezlow << "-granicaL_" << granica_lewa << "-granicaP_" << granica_prawa << ".txt";
  231.     string plik = ss_file.str();
  232.     fstream file(dir + (string)DIR_DELIMITER + plik, ios::out | ios::trunc);
  233.     file.precision(20);
  234.     file.imbue(locale(""));
  235.     file << "+-------------------------------------------------------------------------------------------------------+" << endl;
  236.     file << "| Przedzial: [" << granica_lewa << ", " << granica_prawa << "]" << endl;
  237.     file << "| Stopien: " << stopien << endl;
  238.     file << "| Liczba wezlow: " << liczbawezlow << endl;
  239. //  file.setf(ios::scientific);
  240.     file << "| Blad aproksymacji: " << blad << endl;
  241.  
  242.     file.setf(ios::right, ios::adjustfield);
  243.     file.setf(ios::fixed, ios::floatfield);
  244.     file << "| Tabela wartości funkcji stablicowanej i aproksymujacej w wezlach:" << endl << endl;
  245.     file << "| \t\tWezel" << "\t\t\t\t\tWartosc dokladna" << "\t\tWartosc funkcji aproksymujacej" << endl;
  246.  
  247.     for (int i = 0; i < liczbawezlow; ++i)
  248.     {
  249.         file << "|\t\t";
  250.         file << (*wezly)[i];
  251.         file << "\t\t\t";
  252.         file << (*fx)[i];
  253.         file << "\t\t\t";
  254.         file << (*qx)[i] << endl;
  255.     }
  256.  
  257.  
  258.     file.unsetf(ios::fixed);
  259.     file.setf(ios::scientific);
  260.  
  261.     file << "| Wspolczynniki A" << endl;
  262.  
  263.     for (int i = 0; i <= stopien; ++i)
  264.         file << "| " << i << ": " << (*A)[i] << endl;
  265.     file << "+-------------------------------------------------------------------------------------------------------+" << endl << endl;
  266.     file.close();
  267.     return plik;
  268. }
  269.  
  270. // Tworzy Excelowskie pliki dla kazdego przypadku stopnia
  271. // Zwraca nazwę pliku
  272. string _ToExcel(const string dir, const Wektor *wezly, const Wektor *fx, const Wektor *qx, const int liczbawezlow, const int stopien, const double granica_lewa, const double granica_prawa)
  273. {
  274.     ostringstream  ss_file;
  275.     ss_file << "Stopien_" << stopien << "-liczbaWezlow_" << liczbawezlow << "-granicaL_" << granica_lewa << "-granicaP_" << granica_prawa << ".csv";
  276.     string plik = ss_file.str();
  277.     fstream file(dir + (string)DIR_DELIMITER + plik, ios::out | ios::trunc);
  278.  
  279.     // Precyzja
  280.     file.precision(10);
  281.  
  282.     // Kropka na przecinki w liczbach double:
  283.     file.imbue(locale(""));
  284.  
  285.     file << "\"x\"" << DELIMITER << "\"F(x)\"" << DELIMITER << "\"Q(x)\"" << endl;
  286.     for (int i = 0; i < liczbawezlow; ++i)
  287.         file << (*wezly)[i] << DELIMITER << (*fx)[i] << DELIMITER << (*qx)[i] << endl;
  288.  
  289.     file.close();
  290.     return plik;
  291.  
  292. }
  293.  
  294. // Zapisuje posortowane bledy apro. wraz z całą resztą informacji
  295. void _SaveLog(const string dir, const vector<DaneLog> logi)
  296. {
  297.  
  298.     fstream file(dir + (string)DIR_DELIMITER + "bledy_apro_posortowane.txt", ios::out | ios::trunc);
  299.     file.imbue(locale(""));
  300.     file.precision(10);
  301.     for (vector<DaneLog>::const_iterator it = logi.begin(); it != logi.end(); ++it)
  302.         file << *it << endl;
  303.     file.close();
  304. }
  305.  
  306. int main()
  307. {
  308.     char breakout;
  309.  
  310.     // Pod Windowsem  koniecznie dwa: "D:" + "\\" + "katalog"
  311.     string katalog_wynikowy = "D:" + (string)DIR_DELIMITER + "apro";
  312.  
  313.     // To można zmienić
  314.     int liczbawezlow = 50;
  315.     vector<int> stopienie = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
  316.     vector<vector<double>> granice = { { -1, 1 }, { -2, 2 }, { -3, 3 }, { -4, 4 }, { -5, 5 }, { -10, 10 }, { -20, 20 } };
  317.  
  318.     //vector<int> stopienie = { 19 };
  319.     //vector<vector<double>> granice = { { -1, 1 }, { -2, 2 }, { -3, 3 }, { -4, 4 }, { -5, 5 }, { -10, 10 }, { -20, 20 } };
  320.  
  321.  
  322.     // Nie modyfikowac - tymczasowe zmienne:
  323.     double granica_lewa;
  324.     double granica_prawa;
  325.     double blad;
  326.     int stopien;
  327.     string plik_raportu;
  328.     string plik_excela;
  329.  
  330.     // Nasz Log
  331.     vector<DaneLog> log;
  332.  
  333.     for (vector<vector<double>>::iterator it = granice.begin(); it != granice.end(); ++it)
  334.     {
  335.         vector<double> granice_tmp = *it;
  336.  
  337.          granica_lewa = granice_tmp[0];
  338.          granica_prawa = granice_tmp[1];
  339.  
  340.         for each (stopien in stopienie)
  341.         {
  342.             blad = 0.0;
  343.             Wektor *Fx = new Wektor();
  344.             Wektor *Wezly = new Wektor();
  345.  
  346.             _Przygotuj(Fx, Wezly, liczbawezlow, granica_lewa, granica_prawa);
  347.  
  348.             Macierz *G = _G(Wezly, stopien, liczbawezlow);
  349.             Wektor *R = _R(Wezly, Fx, stopien, liczbawezlow);
  350.  
  351.             Wektor *A = nullptr;
  352.             Wektor *Qx = nullptr;
  353.  
  354.  
  355.             if (!_MacierzTrj(R, G, stopien))
  356.             {
  357.                 delete Fx, Wezly, G, R;
  358.                 cout << "Dzielenie przez zero przy stopniu: "<< stopien << ", granicy l.: "<< granica_lewa << " i p.: "<< granica_prawa << ". Wychodze..." << endl;
  359.                 cin >> breakout;
  360.                 exit(1);
  361.             }
  362.  
  363.             A = _A(R, G, stopien);
  364.             Qx = _Qx(A, Wezly, stopien, liczbawezlow);
  365.             blad = _Blad(Qx, Fx, liczbawezlow);
  366.  
  367.  
  368.             plik_raportu =_Raport(katalog_wynikowy, Wezly, Fx, Qx, A, liczbawezlow, stopien, granica_lewa, granica_prawa, blad);
  369.             plik_excela = _ToExcel(katalog_wynikowy, Wezly, Fx, Qx, liczbawezlow, stopien, granica_lewa, granica_prawa);
  370.        
  371.             // Zapisujemy log
  372.             DaneLog danelog(blad, granica_prawa, granica_lewa, stopien, plik_raportu, plik_excela);
  373.             log.push_back(danelog);
  374.  
  375.             // Przygotowujemy się do następnej iteracji
  376.             delete Fx, Wezly, G, R, A, Qx;
  377.  
  378.             Fx = NULL;
  379.             Wezly = NULL;
  380.             G = NULL;
  381.             R = NULL;
  382.             A = NULL;
  383.             Qx = NULL;
  384.  
  385.         }
  386.     }
  387.    
  388.     // sortujemy
  389.     sort(log.begin(), log.end());
  390.  
  391.     // zapisujemy
  392.     _SaveLog(katalog_wynikowy, log);
  393.  
  394.  
  395.     return 0;
  396. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement