Pella86

Bisezione vs Netwon

Feb 5th, 2019
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.61 KB | None | 0 0
  1. #include <iostream>
  2. #include <cmath>
  3. #include <iomanip>
  4. #include <stdexcept>
  5. #include <fstream>
  6. #include <vector>
  7.  
  8. using namespace std;
  9.  
  10. /*******************************************************************************
  11. * CONSTANTS
  12. *******************************************************************************/
  13. const int MAX_ITERATION = 100;
  14. const double DERIVATE_PRECISION = 0.001;
  15.  
  16. /*******************************************************************************
  17. * Functions to be analyzed
  18. *******************************************************************************/
  19.  
  20. // This function if is 0 is the solutioon of sqrt(2) - n = 0
  21. double f(double x){
  22.     return x*x - 2;
  23. }
  24.  
  25. // not used in this file but can be assigned to func in main
  26. double f2(double x){
  27.     return x*x*x*x - x*x;
  28. }
  29.  
  30. /*******************************************************************************
  31. * utils
  32. *******************************************************************************/
  33.  
  34. // function that returns the "sign" of the value -1, 0 for 0 or, 1 for positive
  35. template <typename T>
  36. int sgn(T val) {
  37.     return (T(0) < val) - (val < T(0));
  38. }
  39.  
  40. // contains the result of the function algorithms, it contains the iteration
  41. // count and the resulting number to calculate the error
  42. struct AlgResult{
  43.     int itr_count;
  44.     double result;
  45. };
  46.  
  47. // type of function pointer f(x)
  48. typedef double (*fptr_t) (double);
  49.  
  50.  
  51. // calculate the error given the expected result
  52. // 0 as expected result is a pain tho
  53. double calc_error(double expected_result, double experimental_result){
  54.     double err = (expected_result - experimental_result) / expected_result;
  55.     err = err * 100;
  56.     return err;
  57. }
  58.  
  59. // calculate the derivate of the function for newton method
  60. double prime_derivative(fptr_t fbase, double n){
  61.     double h = DERIVATE_PRECISION;
  62.     return (fbase(n + h) - fbase(n))/ h;
  63. }
  64.  
  65. /*******************************************************************************
  66. * Bisection method
  67. *******************************************************************************/
  68.  
  69. // calculates how many iterations to reach the given tolerance
  70. AlgResult bisect(double lower, double upper, double tolerance, fptr_t fx){
  71.     int itr_count = 0;
  72.     AlgResult bs_res;
  73.  
  74.     double half = (upper + lower) / 2.0;
  75.     double res;
  76.  
  77.     do{
  78.         res = fx(half);
  79.         // save the result
  80.         bs_res.result = half;
  81.         bs_res.itr_count = itr_count;
  82.  
  83.         // proceed with the algorithm
  84.         if( sgn<double>(res) == sgn<double>(f(lower)) ){
  85.             lower = half;
  86.         }
  87.         else{
  88.             upper = half;
  89.         }
  90.  
  91.         half = (lower + upper) / 2;
  92.  
  93.         ++itr_count;
  94.  
  95.         if(itr_count >= MAX_ITERATION){
  96.             throw runtime_error(
  97.                 "Function bisect: Max iteration reached without convergence");
  98.         }
  99.  
  100.     } while(abs(res) > tolerance);
  101.  
  102.     return bs_res;
  103. }
  104.  
  105. /*******************************************************************************
  106. * Newthon method
  107. *******************************************************************************/
  108.  
  109. AlgResult newton(double x0, fptr_t fx, double tolerance){
  110.     int itr_count = 0;
  111.     AlgResult bs_res;
  112.  
  113.     // condition to calculate next iteration
  114.     bool cond;
  115.  
  116.     do{
  117.  
  118.         double x1 = x0 - fx(x0) / prime_derivative(fx, x0);
  119.  
  120.         // save the results
  121.         bs_res.itr_count = itr_count;
  122.         bs_res.result = x1;
  123.  
  124.         // calculate if is necessary to go for an other round
  125.         cond = abs(x1 - x0) <= tolerance * abs(x1);
  126.  
  127.         if(itr_count >= MAX_ITERATION){
  128.             throw runtime_error(
  129.                 "Function newton: Max iteration reached without convergence");
  130.         }
  131.  
  132.         // assign the new x0
  133.         x0 = x1;
  134.         itr_count += 1;
  135.  
  136.     }while(!cond);
  137.  
  138.     return bs_res;
  139. }
  140.  
  141. /*******************************************************************************
  142. * MAIN PROGRAM
  143. *******************************************************************************/
  144.  
  145. enum AlgType{
  146.     NEWTON = 0,
  147.     BISECT = 1
  148. };
  149.  
  150. int main()
  151. {
  152.     //------------------ user inputs --------------------------------------
  153.  
  154.     // define the search interval or the x0 for the newton method
  155.     double lower = 0, upper = 2.0, x0 = 2.0;
  156.  
  157.     // chose the algorithm (AlgType.NEWTON or AlgType.BISECT)
  158.     AlgType algtype = AlgType::NEWTON;
  159.  
  160.     // function to be analyzed
  161.     fptr_t func = &f;
  162.  
  163.     // define the initial tolerance
  164.     // the tolerance step later are calculated as 1/(power of 10)
  165.     double init_tol = 0.1;
  166.  
  167.     // define the dataset size
  168.     int data_size = 10;
  169.  
  170.     // define the theoretical value the algorithm should find
  171.     double tvalue = sqrt(2);
  172.  
  173.     // variable saved to file
  174.     string filename = "data.dat";
  175.     vector<double> x(data_size);
  176.     vector<double> y(data_size);
  177.     vector<int> itr(data_size);
  178.  
  179.     //------------------ algorithm starts --------------------------------------
  180.     cout << "Algoritm starts" << endl;
  181.     string alg_name =
  182.         (algtype == AlgType::NEWTON)? "Newton method" : "Bisect method";
  183.     cout << "Method chosen: " << alg_name << endl;
  184.     AlgResult br;
  185.     for(int i = 0; i < data_size; i++){
  186.             double tolerance = init_tol / pow(10, i);
  187.  
  188.             cout << "------------------------------" << endl;
  189.             cout << "tolerance: " << tolerance << endl;
  190.  
  191.             if(algtype == AlgType::NEWTON){
  192.                 br = newton(x0, f, tolerance);
  193.             }
  194.             else{
  195.                 br = bisect(lower, upper, tolerance, func);
  196.             }
  197.  
  198.             cout << "iterations: " << br.itr_count
  199.                  << " result: " << br.result << endl;
  200.             cout << "error: " << calc_error(tvalue, br.result) << "%" << endl;
  201.  
  202.             // save the steps in the arrays
  203.             x[i] = tolerance;
  204.             y[i] = br.result;
  205.             itr[i] = br.itr_count;
  206.     }
  207.  
  208.     cout << "---- algorithme finished -----" << endl;
  209.  
  210.     // save file
  211.     ofstream file;
  212.     file.open(filename, ios::out | ios::binary);
  213.     if(file.is_open()){
  214.         // since under the vector the data are in a contigous memory
  215.         // &first_element gives the address to the memory block is pointed too
  216.         file.write(reinterpret_cast<char*>(&x[0]),   data_size*sizeof(double));
  217.         file.write(reinterpret_cast<char*>(&y[0]),   data_size*sizeof(double));
  218.         file.write(reinterpret_cast<char*>(&itr[0]), data_size*sizeof(int));
  219.         file.close();
  220.  
  221.         cout << "Data saved in file: " << filename << endl;
  222.     }
  223.     else{
  224.         throw runtime_error("File problem: can't write");
  225.     }
  226.  
  227.     return 0;
  228. }
Advertisement
Add Comment
Please, Sign In to add comment