Advertisement
Guest User

Untitled

a guest
Dec 14th, 2019
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.44 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <time.h>
  4. #include <math.h>
  5.  
  6. #define MAX_OUTPUT_SIZE 10
  7. #define EPS 1e-14
  8.  
  9. int input_matrix (int n, double *a, double *b);
  10.  
  11. void print_matrix (int n, double *a, double *b, int print_rhs);
  12.  
  13. void print_vector (int n, double *x);
  14.  
  15. double diff (int n, double *a, double *b, double *x);
  16.  
  17. int solve (int n, double *a, double *b, double *x, int make_decomp);
  18.  
  19. int zeydel (double *a, double *xn, int n, double *x, double *f, int norm_type);
  20.  
  21. double diff_norm_L2 (double *vec1, double *vec2, int n);
  22.  
  23. void mtx_prod_special (double *a, double *x, double *res, int n);
  24.  
  25. void inverse_mtx (int n, double *a, double *x, double *inv_a);
  26.  
  27. static double f (int i, int j)
  28. {
  29.   double a = 10., b = 10.;
  30.  
  31.   if (i == j)
  32.     return a;
  33.   if (j == i + 1 || j == i - 1)
  34.     return 1.;
  35.   if (j == i + 2)
  36.     return 1. / b;
  37.  
  38.   return 0.;
  39. }
  40.  
  41. static void mtx_mult_vector (int n, double* a, double* x, double*   res)
  42. {
  43.   int i;
  44.   int j;
  45.   double tmp;
  46.  
  47.   for (i = 0; i < n; i++)
  48.     {
  49.       tmp = 0.;
  50.       for (j = 0; j < n; j++)
  51.         tmp += a[i * n + j] * x[j];
  52.  
  53.       res[i] = tmp;
  54.     }
  55. }
  56.  
  57. static double scalar_prod (int n, double *x1, double *x2)
  58. {
  59.   int i;
  60.   double res = 0.;
  61.  
  62.   for (i = 0; i < n; i++)
  63.     res += x1[i] * x2[i];
  64.  
  65.   return res;
  66. }
  67.  
  68. static void MakeNorm (int n, double *x)
  69. {
  70.   int i;
  71.   double tmp;
  72.  
  73.   tmp = 0.;
  74.   for (i = 0; i < n; ++i)
  75.     tmp += x[i] * x[i];
  76.   tmp = sqrt(tmp);
  77.  
  78.   for (i = 0; i < n; ++i)
  79.     x[i] /= tmp;
  80. }
  81.  
  82. int find_max_val (int n, double *a, double *valueOut, double *x1, double *x2)
  83. {
  84.   int i;
  85.   int iter;
  86.   double tmp1;
  87.   double tmp2;
  88.   double value;
  89.   double valuePrev;
  90.  
  91.   x1[0] = 1.0;
  92.   for (i = 1; i < n; ++i)
  93.     x1[i] = 0.0;
  94.  
  95.   iter = 0;
  96.   valuePrev = -1e300;
  97.  
  98.   while (1)
  99.     {
  100.       iter++;
  101.  
  102.       mtx_mult_vector (n, a, x1, x2);
  103.  
  104.       tmp1 = scalar_prod (n, x1, x2);
  105.       tmp2 = scalar_prod (n, x1, x1);
  106.  
  107.       if (tmp2 > 0)
  108.         {
  109.           value = tmp1 / tmp2;
  110.  
  111.           if (fabs(value - valuePrev) < EPS)
  112.             break;
  113.  
  114.           valuePrev = value;
  115.         }
  116.  
  117.       for (i = 0; i < n; ++i)
  118.         x1[i] = x2[i];
  119.  
  120.       if (iter % 10 == 0)
  121.         MakeNorm (n, x1);
  122.     }
  123.  
  124.   MakeNorm (n, x1);
  125.   *valueOut = value;
  126.  
  127.   return iter;
  128. }
  129.  
  130.  
  131. double diff_norm_L2 (double *vec1, double *vec2, int n)
  132. {
  133.   int i;
  134.   double res = 0.;
  135.   for (i = 0; i < n; i++)
  136.     {
  137.       res += (vec1[i] - vec2[i]) * (vec1[i] - vec2[i]);
  138.     }
  139.   return sqrt (res);
  140. }
  141.  
  142. double diff_norm_Linf (double *vec1, double *vec2, int n)
  143. {
  144.   int i;
  145.   double max = -1.;
  146.   for (i = 0; i < n; i++)
  147.     {
  148.       if (fabs (vec1[i] - vec2[i]) > max)
  149.         max = fabs (vec1[i] - vec2[i]);
  150.     }
  151.   return max;
  152. }
  153.  
  154. void mtx_prod_special (double *a, double *x, double *res, int n)
  155. {
  156.   int i, j;
  157.  
  158.   for (i = 0; i < n; i++)
  159.     res[i] = 0.;
  160.  
  161.   for (i = 0; i < n; i++)
  162.     {
  163.       for (j = 0; j < n; j++)
  164.         {
  165.           if (i == j)
  166.             continue;
  167.           res[i] += a[i * n + j] * x[j];
  168.         }
  169.     }
  170. }
  171.  
  172. int zeydel (double *a, double *xn, int n, double *x, double *f, int norm_type)
  173. {
  174.   double eps = EPS;
  175.   double norm = 9999999.;
  176.   double *tmp;
  177.   int i = 0;
  178.   tmp = (double *) malloc (n * sizeof (double));
  179.  
  180.   for (i = 0; i < n; i++)
  181.     {
  182.       xn[i] = 0.;
  183.       tmp[i] = 0.;
  184.     }
  185.  
  186.   int iter = 0;
  187.   while (norm >= eps)
  188.     {
  189.       mtx_prod_special (a, xn, tmp, n);
  190.       for (i = 0; i < n; i++)
  191.         {
  192.           xn[i] = (1. / a[i * n + i]) * (-tmp[i] + f[i]);
  193.         }
  194.       if (norm_type == 1) //L2
  195.         {
  196.           norm = diff_norm_L2 (xn, x, n);
  197.         }
  198.       else if (norm_type == 2) //Linf
  199.         {
  200.           norm = diff_norm_Linf (xn, x, n);
  201.         }
  202.       else
  203.         {
  204.           break;
  205.         }
  206.       //printf ("%d: %e\n", iter,  norm);
  207.       iter++;
  208.     }
  209.  
  210.   printf ("\nSolution (Zeydel):\n");
  211.   print_vector (n, xn);
  212.   printf ("\n");
  213.   printf ("|Ax - f| = %e\n", norm);
  214.  
  215.   free (tmp);
  216.   return iter;
  217. }
  218.  
  219.  
  220. void fill_matrix (int n, double *a, double *b)
  221. {
  222.   int i, j;
  223.  
  224.   for (i = 0; i < n; i++)
  225.     {
  226.       for (j = 0; j < n; ++j)
  227.         {
  228.           a[i * n + j] = f (i, j);
  229.         }
  230.       b[i] = i + 1.;
  231.     }
  232. }
  233.  
  234. void print_matrix (int n, double *a, double *b, int print_rhs)
  235. {
  236.   int i, j;
  237.   int N = (n > MAX_OUTPUT_SIZE) ? MAX_OUTPUT_SIZE : n;
  238.  
  239.   for (i = 0; i < N; i++)
  240.     {
  241.       for (j = 0; j < N; j++)
  242.         printf(" %6.3f", a[i * n + j]);
  243.       if (print_rhs == 1)
  244.         printf("\t\t%6.3f", b[i]);
  245.       printf ("\n");
  246.     }
  247. }
  248.  
  249. void print_vector (int n, double *x)
  250. {
  251.   int i;
  252.   int nPrint = (n > MAX_OUTPUT_SIZE) ? MAX_OUTPUT_SIZE : n;
  253.  
  254.   for (i = 0; i < nPrint; i++)
  255.     printf (" %6.3f", x[i]);
  256.   printf ("\n");
  257. }
  258.  
  259. double diff (int n, double *a, double *b, double *x)
  260. {
  261.   int i, j;
  262.   double tmp;
  263.   double result = 0.0;
  264.  
  265.   for (i = 0; i < n; i++)
  266.     {
  267.       tmp = 0.0;
  268.       for (j = 0; j < n; j++)
  269.         tmp += a[i * n + j] * x[j];
  270.       tmp -= b[i];
  271.  
  272.       result += tmp * tmp;
  273.     }
  274.  
  275.   return sqrt (result);
  276. }
  277.  
  278. int solve (int n, double *a, double *b, double *x, int make_decomp)
  279. {
  280.   int i, j, k;
  281.   double tmp;
  282.  
  283.   if (make_decomp == 1)
  284.     {
  285.       for (i = 0; i < n; i++)
  286.         {
  287.           if (fabs (a[i * n + i]) < EPS)
  288.             return -1;
  289.           for (j = i; j < n; j++)
  290.             {
  291.               tmp = a[j * n + i];
  292.               for (k = 0; k < i; k++)
  293.                 tmp -= a[j * n + k] * a[k * n + i];
  294.               a[j * n + i] = tmp;
  295.             }
  296.           for (j = i + 1; j < n; j++)
  297.             {
  298.               tmp = a[i * n + j];
  299.               for (k = 0; k < i; k++)
  300.                 tmp -= a[i * n + k] * a[k * n + j];
  301.               a[i * n + j] = tmp / a[i * n + i];
  302.             }
  303.         }
  304.     }
  305.  
  306.   for (i = 0; i < n; i++)
  307.     {
  308.       tmp = b[i];
  309.       for (j = 0; j < i; j++)
  310.         tmp -= a[i * n + j] * x[j];
  311.       x[i] = tmp / a[i * n + i];
  312.     }
  313.  
  314.   for (i = n - 1; i >= 0; i--)
  315.     {
  316.       tmp = x[i];
  317.       for (j = i + 1; j < n; j++)
  318.         tmp -= a[i * n + j] * x[j];
  319.       x[i] = tmp;
  320.     }
  321.  
  322.   return 0;
  323. }
  324.  
  325. void inverse_mtx (int n, double *a, double *x, double *inv_a)
  326. {
  327.   int j = 0, i;
  328.   double *b;
  329.   b = (double *) malloc (n * sizeof (double));
  330.   for (j = 0; j < n; j++)
  331.     {
  332.       //fill_matrix (n, a, b);
  333.       for (i = 0; i < n; i++)
  334.         b[i] = 0.;
  335.       b[j] = 1.;
  336.       solve (n, a, b, x, j == 0 ? 1 : 0);
  337.       for (i = 0; i < n; i++)
  338.         inv_a[i * n + j] = x[i];
  339.     }
  340.   free (b);
  341. }
  342.  
  343. int main (void)
  344. {
  345.   int iters = 0.;
  346.   int n = 100;
  347.   int result = 0;
  348.   double *a, *inv_a, *b, *x, *xn;
  349.   double *x1, *x2;
  350.   double max_val = 0., min_val = 0.;
  351.   clock_t t;
  352.  
  353.   a = (double *) malloc (n * n * sizeof (double));
  354.   b = (double *) malloc (n * sizeof (double));
  355.   x = (double *) malloc (n * sizeof (double));
  356.  
  357.   if (!(a && b && x))
  358.     {
  359.       printf ("Not enough memory!\n");
  360.       if (a)
  361.         free (a);
  362.       if (b)
  363.         free (b);
  364.       if (x)
  365.         free (x);
  366.       return -1;
  367.     }
  368.  
  369.   fill_matrix (n, a, b);
  370.  
  371.   printf ("n = %d\n\n", n);
  372.  
  373.   printf ("Matrix A:\n");
  374.   print_matrix (n, a, b, 1);
  375.   printf ("\n");
  376.  
  377.   t = clock();
  378.   result = solve (n, a, b, x, 1);
  379.   t = clock() - t;
  380.  
  381.   if (result < 0)
  382.     {
  383.       printf ("Can't solve - matrix is deteriorated.\n");
  384.       free (a);
  385.       free (b);
  386.       free (x);
  387.       return -1;
  388.     }
  389.  
  390.   printf ("Solution (LU):\n");
  391.   print_vector (n, x);
  392.   printf ("\n");
  393.  
  394.   printf ("Elapsed: %.3f sec.\n", (double)t / CLOCKS_PER_SEC);
  395.  
  396.   fill_matrix (n, a, b);
  397.  
  398.   printf ("|Ax - f| = %e\n", diff (n, a, b, x));
  399.  
  400.   xn = (double *) malloc (n * sizeof (double));
  401.   iters = zeydel (a, xn, n, x, b, 1);
  402.  
  403.   printf ("Zeydel iterations: %d\n",iters);
  404.  
  405.   free (xn);
  406.  
  407.   x1 = (double *) malloc (n * sizeof (double));
  408.   x2 = (double *) malloc (n * sizeof (double));
  409.  
  410.   printf ("\n");
  411.   iters = find_max_val (n, a, &max_val, x1, x2);
  412.   printf ("Max lambda of A: %f\n\n", max_val);
  413.  
  414.   fill_matrix (n, a, b);
  415.  
  416.   inv_a = (double *) malloc (n * n * sizeof (double));
  417.   inverse_mtx (n, a, x, inv_a);
  418.   printf ("Matrix A^-1:\n");
  419.   print_matrix (n, inv_a, b, 0);
  420.   printf ("\n");
  421.  
  422.   printf ("\n");
  423.   iters = find_max_val (n, inv_a, &min_val, x1, x2);
  424.   printf ("Min lambda of A: %f\n\n", 1. / min_val);
  425.  
  426.   printf ("mu = %f\n", max_val * min_val);
  427.  
  428.   free (a);
  429.   free (b);
  430.   free (x);
  431.   free (inv_a);
  432.   free (x1);
  433.   free (x2);
  434.  
  435.   return 0;
  436. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement