Search This Blog

Sunday 31 July 2011

Best Line(Curve) Fitting - Least Square Method

          Curve fitting is very fun with our own coding that fits a best curve for a given set of points. Although it is fun, it is also an essential friend for students for plotting their readings. Most of the engineering stream students have to submit their observation with well plotted graph. But what they actually do is draw the graph and adjust the readings according to the their graph. I hope this program will help them to plot their graph more appropriately.


Theory
        The name least square denote the squares of the errors are the least possible values. What are the errors? The difference between our actual reading and the value of the chosen equation.
        Let us assume we are going to fit a straight line for the given set of readings. The equation of the line is : y = mx+c. This equation has two parameters x and y thus it has it own (x,y) values and we have our own set of (x,y) values observed from the experiment. The difference between these y (from equation) and y (from experiment) is called error.


Our Expt: Ohm's Law.

The circuit on the left is to prove the Ohm's Law V = IR.
Definition: Ohm's law states that the current through a conductor between two points is directly proportional to the potential difference across the two points, and inversely proportional to the resistance between them.


Assume that this is the set of readings we have:    


X ( Current ) Y (Voltage )
1 2.3
2 4.6
3 5.8
4 7.5
5 9.8
                                            
        This plot is not a perfect straight line. So we try to fit a straight line such that it is nearer to all of the points. What we are going to do is place a scale on the graph sheet and adjust it until it becomes nearer to all points and then we draw the line. Mathematically we fit a line y = mx+c, then we find the values of 'm' and 'c' so that it resemble the line we draw using the experimental values. For more theory google for it.
Coding:          
       We use the matrix library that was discussed in my previous post


File: lsm.h
   #include<matrix.h>
   typedef struct readings {
     float *x;
     float *y;
     int len;
   }Readings;
   typedef struct lsm_line {
     float *x;
     float *y;
     float *x2;
     float *xy;
     float X , Y , XY , X2;
     float *newy;
     float Dev;
     int len;
   }LsmLine;
   Readings* lsm_new_Readings(int n);
   LsmLine* lsm_new_LsmLine(Readings *Read);
   int lsm_del_Readings(Readings *anchor);
   int lsm_Read_farray(float *array,int len);
   int lsm_Print_farray(float *array,int len);
   int lsm_Calc_LsmLine(LsmLine* line);
   int lsm_Print_LsmLine(LsmLine* line); 
File : lsm.c
     #include "lsm.h"
     Readings* lsm_new_Readings(int len)
     {
        Readings *newRead = (Readings*)malloc(sizeof(Readings));
        newRead->x = (float*)malloc(sizeof(float)*len);
        newRead->y = (float*)malloc(sizeof(float)*len);
        newRead->len = len;
        return newRead;
     }

     LsmLine* lsm_new_LsmLine(Readings *read)
     {
        LsmLine *newLine = (LsmLine*)malloc(sizeof(LsmLine));
        int len = read->len;
        newLine->x = (float*)malloc(sizeof(float)*len);
        newLine->y = (float*)malloc(sizeof(float)*len);
        newLine->xy = (float*)malloc(sizeof(float)*len);
        newLine->x2= (float*)malloc(sizeof(float)*len);
        newLine->newy= (float*)malloc(sizeof(float)*len);
        newLine->len = len;
        newLine->X  = 0;
        newLine->Y  = 0;
        newLine->XY = 0;
        newLine->X2 = 0;
        newLine->Dev=0;
        int i;
        newLine->len = read->len;
        for(i = 0;i<newLine->len;i++){
            newLine->x[i]=read->x[i];
            newLine->y[i]=read->y[i];
            newLine->xy[i]=read->x[i]*read->y[i];
            newLine->x2[i]=read->x[i]*read->x[i];
            newLine->X +=  newLine->x[i];
            newLine->Y +=  newLine->y[i];
            newLine->XY +=  newLine->xy[i];
            newLine->X2 +=  newLine->x2[i];
        }
        return newLine;
  }
  
  int lsm_Calc_LsmLine(LsmLine *Line)
  {
     int i;
     Matrix *lhs = matrix_new_Matrix(2,2);
     Matrix *rhs = matrix_new_Matrix(2,1);
     Assuming Eqn is y=ax+b
     lhs->mat[0][0] = Line->X;
     lhs->mat[0][1] = Line->len;
     lhs->mat[1][0] = Line->X2;
     lhs->mat[1][2] = Line->X;
     rhs->mat[0][0]=Line->Y;
     rhs->mat[1][0]=Line->XY;
     MatrixEqn *Eqn = matrix_new_MatrixEqn(lhs,rhs);
     matrix_Solve_Det(Eqn);
     float a = Eqn->Soln->mat[0][0];
     float b = Eqn->Soln->mat[1][0] ;
     for(i=0;i<Line->len;i++){
       Line->newy[i] =  a*Line->x[i]+b;
       Line->Dev += (Line->y[i]-Line->newy[i])*(Line->y[i]-Line->newy[i]);
     }
 }


 int lsm_Print_LsmLine(LsmLine* line)
 {
    printf("\nS.No\tX\t\tY\t\tX2\t\tXY\t\tNewY\n");
    int i;
    for (i=0;i<line->len;i++){
       printf("\n%d",i+1);
       printf("\t%0.3f",line->x[i]);
       printf("\t\t%0.3f",line->y[i]);
       printf("\t\t%0.3f",line->x2[i]);
       printf("\t%0.3f",line->xy[i]);
       printf("\t\t%0.3f",line->newy[i]);
    }
    printf("\n\nTotal");
    printf("\t%0.3f",line->X);
    printf("\t\t%0.3f",line->Y);
    printf("\t\t%0.3f",line->X2);
    printf("\t%0.3f",line->XY);
    printf("\n\n%0.3f = %0.3fa + %db ",line->Y,line->X,line->len);
    printf("\n%0.3f = %0.3fa + %0.3fb ",line->XY,line->X2,line->X);
    printf("\n\nDeviation = %0.3f",line->Dev);
    return 0;
  }
  
  void lsm_Read_farray(float *array,int len)
  {
     int i=0;
     for(i=0;i<len;i++){
        scanf("%f",&array[i]);
     }
     return 0;
  }
  
   lsm_Print_farray(float *array,int len)
   {
      int i=0;
      for(i=0;i<len;i++){
         printf("%0.3f",array[i]);
      }
      return 0;
   }
Sample program to test.
       #include<stdio.h>
   #include"lsm.h"
   int main()
   {
       printf("\n\n\t\t\tLEAST SQUARE METHOD FOR BEST LINE");
       int n,choice;
       printf("\n\nEnter the number of readings\t:");
       scanf("%d",&n);
       Readings *read = lsm_new_Readings(n);
       printf("\nEnter the type of Variation of X:");
       printf("\n\t1.Constant Steps of X");
       printf("\n\t2.Variable Steps of X\n");
       printf("\nEnter the Choice\t:");
       scanf("%d",&choice);
       switch(choice){
         case 1:   printf("\nEnter First : Step : Last of X\t:") ;
                   float first , step , last;
                   scanf("%f %f %f",&first,&step,&last);
                   int i;
                   float value;
                   for( i=0,value=first;value<=last; value +=step,i++){
                       read->x[i] = value;
                   }
                   break;
         case 2:   printf("\nEnter X\t:\n");
                   lsm_Read_farray(read->x,n);
                   break;
         default: printf("\nWrong Option Restart the program!!!");
                   break;
      }
      printf("\nEnter Y\t:\n");
      lsm_Read_farray(read->y,n);
      LsmLine *line = lsm_new_LsmLine(read);
      lsm_Calc_LsmLine(line);
      lsm_Print_LsmLine(line);
      return 0;
}
         We can extend these project to various curves, and choose the curve which has least summation of error 'S', since all set of points will not be as above.

    Tuesday 19 July 2011

    Matrix Manipulation Using C

                Matrix  is a great invention of Mathematics. It is very useful in solving system of equations through computer. Of course famous numerical computing platform, MATLAB is the well known application of matrix.
                In MATLAB everything is matrix. The images are also represented as a matrix in ease. It is easy to perform operations over matrices. This is why the matrix manipulation is an important.
    Download the code here
                Here is my matrix library. It may be inefficient, since it is indented for educational purpose. I want to keep things simple so that the beginner also be able to understand. This article is also helpful for learning memory allocation in C, Pointer and its applications, recursion,  modularity.
                                                                    
    CodeListing
    1. /*----------------------------------------*/
    2. /* Program: matrix.h                      */
    3. /* Author: Vanangamudi                    */
    4. /* Date: 15/05/2011                       */
    5. /*----------------------------------------*/
    6. #include<stdio.h>
    7. #ifndef _MATRIX_H_
    8. #define _MATRIX_H_

    9. typedef struct matrix {
    10. float **mat;
    11. int m,n;
    12. }Matrix;

    13. typedef struct matrixEquation {
    14. Matrix *lhs;
    15. Matrix *rhs;
    16. Matrix *Soln;
    17.  }MatrixEqn;

    18. Matrix * matrix_new_Matrix(int m,int n);
    19. MatrixEqn * matrix_new_MatrixEqn(Matrix* lhs,Matrix *rhs);

    20. float matrix_Det(Matrix *matA);
    21. Matrix* matrix_Cofactor(Matrix *matA);
    22. Matrix* matrix_Minor(Matrix *matA, int m, int n);
    23. Matrix* matrix_Adjoint(Matrix *matA);
    24. Matrix* matrix_Inverse(Matrix *matA);

    25. int matrix_Solve_Det(MatrixEqn *matEqn);
    26. int matrix_Solve_Inv(MatrixEqn *matEqn);

    27. Matrix* matrix_Mult(Matrix *matA , Matrix *matB);
    28. Matrix* matrix_Add(Matrix *matA , Matrix *matB);
    29. Matrix* matrix_Sub(Matrix *matA , Matrix *matB);
    30. Matrix* matrix_tran(Matrix *matA);
    31. Matrix* matrix_ScalarMultiply(float X , Matrix *matA);
    32. Matrix* matrix_Duplicate(Matrix *matA);
    33. Matrix* matrix_ColumnReplace(Matrix *matA, Matrix* matB ,int IndA,int IndB );

    34. int matrix_Print(Matrix *matA);
    35. int matrix_Read(Matrix *matA);

    36. #endif       //_MATRIX_H_

    1. /*-----------------------------------------------*/
    2. /* Program: matrix.c                             */
    3. /* Author: Vanangamudi                           */
    4. /* Date: 15/05/2011                              */
    5. /*-----------------------------------------------*/

    6. #include "matrix.h"
    7. #include<malloc.h>
    8. #include<stdio.h>

    9. //Constructors
    10. Matrix* matrix_new_Matrix(int m, int n)
    11. {
    12.        Matrix *newMat = (Matrix*)malloc(sizeof(float));
    13.        newMat->mat = (float*)malloc(sizeof(float)*m);
    14.     int i = 0;
    15.     for(i =0 ; i < m ; i++){
    16.           newMat->mat[i] = (float*)malloc(sizeof(float)*n);
    17.     }
    18.       newMat->m = m;
    19.       newMat->n = n;
    20.     return newMat;
    21. }

    22. MatrixEqn * matrix_new_MatrixEqn(Matrix *lhs,Matrix *rhs)
    23. {
    24.       MatrixEqn* newEqn = (MatrixEqn*)malloc(sizeof(float));
    25.       newEqn->lhs = matrix_Duplicate(lhs); 
    26.       newEqn->rhs = matrix_Duplicate(rhs);
    27.       newEqn->Soln = matrix_new_Matrix(rhs->m,1);
    28.     return newEqn;
    29. }

    30. // Matrix Operations
    31. Matrix* matrix_Minor(Matrix *matA, int m, int n)
    32. {
    33.     int i,j;
    34.     int p,q;
    35.     Matrix *minor = matrix_new_Matrix(matA->m-1,matA->n-1);
    36.     for(i = 0,p = 0; i < matA->m , p < minor->m; i++){
    37.       if( i != m-1){
    38.          for(j=0, q=0; j <matA->n , q < minor->n; j++){
    39.             if(j != n-1){
    40.               minor->mat[p][q] = matA->mat[i][j];
    41.               q++;
    42.             }
    43.          }
    44.          p++;
    45.       }
    46.     }
    47.     return minor;
    48. }

    49. float matrix_Det(Matrix *matA)
    50. {
    51.     float det=0;
    52.     if((matA->m==1)&&(matA->n==1)){
    53.           det = matA->mat[0][0];
    54.     }else {
    55.       int i;
    56.       int sign=1;
    57.       for(i = 0; i<matA->m ; i++){
    58.          det += sign*matA->mat[0][i]*matrix_Det(matrix_Minor(matA,0,i));
    59.           sign = -1*sign;
    60.       }
    61.     }
    62.     return det;
    63. }

    64. Matrix* matrix_Cofactor(Matrix *matA)
    65. {
    66.     Matrix *Cofact = matrix_new_Matrix(matA->m,matA->n);
    67.     int i,j;
    68.     int sign =1;
    69.     for(i =0 ; i<matA->m;i++){
    70.        for(j=0 ; j<matA->n ; j++){
    71.           Cofact->mat[i][j] = sign*matrix_Det(matrix_Minor(matA,i,j));
    72.           sign = sign * (-1);
    73.        }
    74.        if(matA->m%2 == 0){
    75.               sign = (-1)*sign;
    76.        }
    77.     }
    78.     return Cofact;
    79. }

    80. Matrix* matrix_Adjoint(Matrix *matA)
    81. {
    82.      Matrix *Cofact = matrix_Cofactor(matA);
    83.      Matrix *Adj = matrix_tran(Cofact);
    84.      return Adj;
    85. }

    86. Matrix* matrix_Inverse(Matrix *matA)
    87. {
    88.     Matrix *Inv = matrix_Adjoint(matA);
    89.     float Det = matrix_Det(matA);
    90.     Inv = matrix_ScalarMultiply(1/Det, Inv);
    91.     return Inv;
    92. }

    93. //Arithmetics
    94. Matrix* matrix_Mult(Matrix *matA , Matrix *matB)
    95. {
    96.      if(matA->n != matB->m){
    97.         printf("\nMatrices cannot be multiplied");
    98.         return NULL;
    99.      }else{
    100.              Matrix *matC = matrix_new_Matrix(matA->m,matB->n);
    101.         int i,j,k;
    102.         for(i = 0 ;i< matB->m; i++){
    103.            for(j=0; j < matB->n ; j++){
    104.               matC->mat[i][j] = 0;
    105.               for( k =0;k < matA->n;k++){
    106.                  matC->mat[i][j]+=matA->mat[i][k]*matB->mat[k][j];
    107.               }
    108.             }
    109.          }
    110.         return matC;
    111.      }
    112. }

    113. Matrix* matrix_ScalarMultiply(float X , Matrix *matA)
    114. {
    115.         Matrix *matB = matrix_new_Matrix(matA->m,matA->n);
    116.      int i,j;
    117.      for(i = 0 ;i< matA->m; i++){
    118.         for(j=0; j < matA->n ; j++){
    119.            matB->mat[i][j] = X * matA->mat[i][j];
    120.         }
    121.      }
    122.      return matB;
    123. }

    124. Matrix* matrix_Add(Matrix *matA , Matrix *matB)
    125. {
    126.         Matrix *matC = matrix_new_Matrix(matA->m,matA->n);
    127.      int i,j;
    128.      for(i = 0 ;i< matA->m; i++){
    129.         for(j=0; j < matA->n ; j++){
    130.           matC->mat[i][j] = matA->mat[i][j]+matB->mat[i][j];
    131.         }
    132.      }
    133.       return matC;
    134. }

    135. Matrix* matrix_Sub(Matrix *matA , Matrix *matB)
    136. {
    137.         Matrix *matC = matrix_new_Matrix(matA->m,matA->n);
    138.      int i,j;
    139.      for(i = 0 ;i< matA->m; i++){
    140.         for(j=0; j < matA->n ; j++){
    141.            matC->mat[i][j] = matA->mat[i][j]-matB->mat[i][j];
    142.         }
    143.      }
    144.      return matC;
    145. }

    146. Matrix* matrix_tran(Matrix *matA)
    147. {
    148.     Matrix *matB = matrix_new_Matrix(matA->n,matA->m);
    149.     int i,j;
    150.     for(i = 0 ;i< matB->m; i++){
    151.        for(j=0; j < matB->n ; j++){
    152.           matB->mat[i][j] = matA->mat[j][i];
    153.        }
    154.     }
    155.     return matB;
    156. }

    157. //Matrix Eqn Solvers
    158. int matrix_Solve_Inv(MatrixEqn *matEqn)
    159. {
    160.     Matrix* Inv = matrix_Inverse(matEqn->lhs);
    161.     matEqn->Soln = matrix_Mult(Inv,matEqn->rhs);
    162. }

    163. int matrix_Solve_Det(MatrixEqn *matEqn)
    164. {
    165.     float Det = matrix_Det(matEqn->lhs);
    166.     Matrix* matA;
    167.     float DetXYZ;
    168.     int i;
    169.     for(i = 0;i <matEqn->Soln->m;i++){
    170.       matA = matrix_ColumnReplace(matEqn->lhs,matEqn->rhs,i+1,1);
    171.       DetXYZ = matrix_Det(matA);
    172.       matEqn->Soln->mat[i][0] = DetXYZ/Det;
    173.     }
    174. }

    175. //Misc
    176. Matrix* matrix_ColumnReplace(Matrix *matA, Matrix* matB ,int IndA,int IndB )
    177. {
    178.        Matrix* matC = matrix_Duplicate(matA);
    179.     int i;
    180.     for(i = 0;i<matA->n; i++){
    181.             matC->mat[i][IndA-1] = matB->mat[i][IndB-1];
    182.     }
    183.     return matC;
    184. }

    185. Matrix* matrix_Duplicate(Matrix *matA)
    186. {
    187.        Matrix *matB = matrix_new_Matrix(matA->m,matA->n);
    188.     int i,j;
    189.     for(i = 0 ;i< matB->m; i++){
    190.        for(j=0; j < matB->n ; j++){
    191.                 matB->mat[i][j] = matA->mat[i][j];
    192.        }
    193.     }
    194.     return matB;
    195. }

    196. //IO Operations
    197. int matrix_Read(Matrix *matA)
    198. {
    199.      int i=0 , j=0;
    200.         printf("\nEnter the Elements:\n");
    201.      for(i = 0; i < matA->m; i++){
    202.         for(j = 0; j < matA->n; j++ ){
    203.                  scanf("%f",&matA->mat[i][j]);
    204.         }
    205.      }
    206. }

    207. int matrix_Print(Matrix *matA)
    208. {
    209.      int i=0 , j=0;
    210.         printf("\n");
    211.      for(i = 0; i < matA->m; i++){
    212.         for(j = 0; j < matA->n; j++ ){
    213.                  printf("%0.3f\t",matA->mat[i][j]);
    214.         }
    215.              printf("\n\n");
    216.      }
    217.      return 0;
    218. }

    Sample Program to Test
    1. /*-----------------------------------------------------*/
    2. /* Program: matrix_test.c                              */
    3. /* Author  : Vanangamudi                               */
    4. /* Date     :15/05/2011                                */
    5. /*-----------------------------------------------------*/

    6. #include "matrix.h"
    7. #include<stdio.h>

    8. int main()
    9. {
    10.     Matrix *matA  = matrix_new_Matrix(3,3);
    11.     Matrix *matB  = matrix_new_Matrix(3,3);

    12.     printf("\t\t|--------------------------|");
    13.     printf("\n\t\t|**************************|");
    14.     printf("\n\t\t|*** MATRIX ILLUSTRATION **|\n");
    15.     printf("\t\t|**************************|\n");
    16.     printf("\t\t|--------------------------|\n\n");

    17.     matrix_Read(matA);
    18.     matrix_Read(matB);

    19.     printf("\nmatA + matB:\n");
    20.     matrix_Print(matrix_Add(matA,matB));

    21.     printf("\nmatA - matB:\n");
    22.     matrix_Print(matrix_Sub(matA,matB));

    23.     printf("\nmatA * matB:\n");
    24.     matrix_Print(matrix_Mult(matA,matB));

    25.     printf("\n5 * matA:\n");
    26.     matrix_Print(matrix_ScalarMultiply(5,matA));

    27.     printf("\nTranspose ofmatA :\n");
    28.     matrix_Print(matrix_tran(matA));

    29.     printf("\nDeterminant of matA:\t");
    30.     printf("%f",matrix_Det(matA));

    31.     printf("\nCofactor matrix of matA :\n");
    32.     matrix_Print(matrix_Cofactor(matA));
    33.     printf("\nInverse matrix of matA:\n");
    34.     matrix_Print(matrix_Inverse(matA));
    35.     printf("\nMinor matrix of ( i , j) = (1,1) of matA:\n");
    36.     matrix_Print(matrix_Minor(matA,1,1));

    37.     return 0;
    38. }
            Once we wrote a library with generic functions, it easy to develop some projects easily based on our own library. Even though, there are many efficient scientific and mathematical libraries available free of charge.  We learn Programming easily through writing programs like this. 
    Happy coding!!!