Sunteți pe pagina 1din 16

Activity No.

6: Data fitting and interpolation exec('c:\scilabwork') //==========================NOTE================================= //The previous command is used to change the current working //directory to the directory (or folder) holding all the textbook //functions. The script 'c:\scilabwork', in my computer, contains //the line: // chdir('c:\Program Files\Scilab-2.6\work') //which is the directory where I keep the textbook functions. You //may want to change the previous command to the command that will //change the current working directory to the one you selected to //hold the textbook functions. //================================================================ //Type: return after each 'pause' command to continue the script pause // //SIMPLE LINEAR INTERPOLATION //See pp. 386 for the formulation of linear interpolation. //SCILAB provides function 'interpln' to perform linear interpolation //in a table of data. pause //Interpolation. For simple linear interpolation, SCILAB provides //function 'interpln'. To find more about this function use: help interpln pause //This function can be applied to a couple of vectors x and y that //represent the columns of a table, with x being the independent //or explanatory variable, and y the dependent variable. Consider //the case in which x and y are given by the following vectors: x = [1.2,2.5,3.7,4.2,6.5] y = [0.8,3.2,4.4,6.3,1.2] pause //The two columns need to be put together into a matrix of two rows, //row 1 for x, and row 2 for y, before using function 'interpln', e.g., xyTable = [x;y] pause //If we want to find the value of y corresponding to x = 4,through //linear interpolation, we use: interpln(xyTable,4) pause //Notice that the data in x is provided in increasing order. If //your data is not in increasing order you can order it by using //function 'gsort' as shown below. pause //===============================================================

//Functions 'sort' and 'gsort' //---------------------------//Function 'sort' produces a sorting of a vector or matrix in //decreasing order, e.g., x = [2 3 -1 5 6] sort(x) pause //To produce a sort in increasing order use function 'gsort' as //follows: gsort(x,'g','i') pause //The arguments 'g' and 'i' are necessary to order the vector in //increasing order. Using 'gsort(x)' only will produce the same //result as 'sort(x)'. pause //If you need to order an array x in increasing order and order //the corresponding y array in a parallel fashion, you can still //use function 'gsort' as indicated below. Suppose that the values //of x and y are the following: x = [2 3 1 5 4 6] y = [1.2 3.2 0.8 4.5 6.8 10.3] pause //First, order vector x in increasing order by using function //'gsort', but include the left-hand side vector [xx,k]: [xx,k] = gsort(x,'g','i') pause //Vector xx is the ordered version of x while vector k represents //the new location of the original indices of x after the increasing //sorting took place. Thus, xx(1) = x(3), xx(2) = x(1), and so on. //To re-order vector y so that the values of y follow the corresponding //values of x in the sorted x array (i.e., in xx), simply use: yy = y(k) pause //Now, vectors xx and yy contain the same information as vectors x and y, //except that the values of xx are in increasing order, i.e., xx yy //=============================================================== pause //A second example of linear interpolation. //---------------------------------------//This example uses data generated from a function. The values of x and //y are as shown below: x = [0:1:10]

y = sin(x) pause //Interpolation will now be produced for a vector of values of the //independent variable, vector xx: xx = [0.5 1.5 2.5 5.5] pause //Before interpolating we put together the table of values using the //vectors x and y: xyTable = [x;y] pause //The resulting vector represents the interpolated values of y for the //values of x contained in xx: interpln(xyTable,xx) //Polynomials in SCILAB. //===================== //SCILAB includes a number of functions for the creation and manipulation //of polynomials. Function 'poly', for example, can be used to define a //variable as a polynomial variable, e.g., s = poly(0,'s') pause //Having defined 's' as a polynomial variable, we can use it to define //polynomials such as: y = (s+1)^2*s pause //Function 'varn' can be used to identify the independent (or explanatory) //variable in a polynomial, e.g., varn(y) pause //Function 'degree' is used to determine the degree of a polynomial, e.g., degree(y) pause //Function 'coeff' is used to produce a vector containing the coefficients //of a polynomial. Notice that the components of the vector represent the //coefficients of the independent (or explanatory) variable corresponding //to degrees 0, 1, 2, ..., n, where n is the degree of the polynomial. coeff(y) pause //These coefficients correspond to polynomial y which is: y = (s+1)^2*s pause //Thus, we have c(0) = 0, c(1) = 1, c(2) = 2, c(3) = 3, for a polynomial

//of degree n = 3. // pause //The following statement generates a polynomial of order 2 (a quadratic //polynomial): p = (s+1)*(s-2) pause //Polynomials that have the same independent (or explanatory) variable can //be added, subtracted, multiplied, divided, raised to a power, etc: y+p y-p pause p-y p*y pause p/y y^3 pause //addition //subtraction //subtraction //multiplication //division //power

//The follwing function, 'pdiv', can be used to determine the quotient (quo) //and residual (res) of a polynomial division. The example shown represents //the division p/y: [res,quo]=pdiv(p,y) pause //The division y/p, using 'pdiv', is shown next: [res,quo]=pdiv(y,p) pause //The direct division, using the operator (/), converts the result into a //fraction having simplified any common factors in numerator and denominator: p/y pause y/p pause //Functions 'numer' and 'denom' are used to isolate the numerator //and denominator, respectively, of a fraction, e.g., z = p/y pause numer(z) denom(z) pause //Polynomials as matrix elements. //------------------------------//Polynomials can be used as elements of a matrix as illustrated

//with this example: A = [(s+1)^2,s+s^2;1+s,s-2*s^2+s^2] pause //Matrix functions such as 'det' (determinant) and 'inv' (inverse) //can be applied to matrices whose elements are polynomials as //illustrated below: det(A) pause inv(A) pause //Check the matrix property A*A^(-1) = I, where I is the identity matrix: A*inv(A) pause //Function 'coffg' is used to identify the matrix Ns and the determinant d //such that A^(-1) = Ns/d, e.g., [Ns,d]=coffg(A) pause //Thus, Ainv = Ns/d pause //which is the same result obtained earlier: inv(A) //Derivatives of polynomials. //--------------------------//Function 'derivat' can be used to obtain the derivative of //a polynomial, e.g., for polynomial 'y', defined earlier, y pause //the derivative is the polynomial: derivat(y) //The following example shows the derivative of a polynomial //fraction (recall that 's' was defined as a polynomial variable //at the beginning of our SCILAB session): derivat(1/s) pause //Derivatives of functions other than polynomials are not allowed, //e.g., //derivat(log(s)) // !--error 246 //impossible to overload this function for given argument type(s) // undefined function %p_log //Evaluating a polynomial. //------------------------

//To evaluate a polynomial in SCILAB use function 'horner', e.g., y horner(y,2) pause //Creating a polynomial. //---------------------//Given a vector of its coefficients, a polynomial can be created //by using function 'poly' as follows: a = [1 2 -3 4 5] //coefficients p4 = poly(a,'t','coeff') //polynomial pause //Notice the correspondence of the coefficients in vector 'a' and //the powers of the independent (or explanatory) variable t. //A polynomial can also be created by providing a vector of its //roots as illustrated below: r = [-1 -1 0 1 2 3] p6 = poly(r,'t') //notice that no 'root' spec is necessary pause //Including the option 'roots' produces the same result: p6 = poly(r,'t','roots') pause //To find the roots of a polynomial use function 'roots': //Example 1: roots(p6) //Example 2: u = 2*s^2+4 roots(u) pause //Integrating a polynomial. //------------------------//SCILAB does not provide a function for integrating polynomials, //however, the user-defined function 'intpoly' can be used for //that purpose: getf('intpoly') //The general call to 'intpoly' is: intpoly pause //For example, integrating the polynomial y, defined earlier, y //results in: intpoly(y) pause //Numerical methods with polynomials

//================================== //Polynomial deflation. //===================== //Polynomial deflation is used to evaluate derivatives of //polynomials. The general formula is: // P[n](x) = (x-r)*Q[n-1](x) + R //Where P[n](x) is an n-th order polynomial, r is a specific //value of x, Q[n-1](x) is a (n-1)-th order polynomial, and //R is a residual value. The derivative of P[n](x) is calculated //as follows: // P'[n](x) = (x-r)*Q'[n-1](x)+Q[n-1](x) //where the term Q'[n-1](x) represents the derivative of polynomial //Q[n-1](x). Thus, P'[n](r) = Q[n-1](r). pause //Thus, polynomial deflation can be used to obtain the derivative of //P[n](x) by evaluating Q[n-1](x) at a given value x = r. //Consider the following 5-th order polynomial: P5 = poly([-120 274 -225 85 -15 1],'x','coeff') pause //Function 'horner' is used to evaluate P5(2.5): horner(P5,2.5) pause //This value actually represents the residual value R shown in //the formula P[n](x) = (x-r)*Q[n-1](x) + R: R = horner(P5,2.5) pause //Next, we define the first-order polynomial d5 as (x-r), i.e., x=poly(0,'x') d5 = x-2.5 pause //Using function 'pdiv' we can get the residual, R4, and the //polynomial Q4: [R4,Q4] = pdiv(P5,d5) pause //The derivative of P5 at x = 2.5 is then: P5prime = horner(Q4,2.5) pause //Alternatively, we can use the function 'derivat' to //evaluate P5'(x) = P5p: P5p = derivat(P5) pause //and evaluate this derivative at x = 2.5: horner(P5p,2.5) pause //Direct fitting of a polynomial //============================== //User-defined function 'dfp' can be used to obtain the

//direct fitting of a polynomial. In this case, the //order of the polynomial is one less than the number of //data points. To load the function use: getf('dfp') pause// //The general call to function 'dfp' is: dfp pause //Let's use functipon 'dfp' to fit a second-order polynomial //to the data set given by vectors x and y: x = [3.4 3.5 3.6] y = [0.294118 0.285714 0.277778] pause //The coefficients of the fitted polynomial are calculated by: [a] = dfp(x,y) pause //The polynomial itself is obtained by using function 'poly': p = poly(a,'s','coeff') pause //Lagrange polynomials. //===================== //To evaluate Lagrange polynomials use the user-defined function 'lagpol'. //For example, for the following data x,y we use Lagrange polynomial //fitting: x = [0,1.2,3.5,4.2,6.2,8.1,11.2] y = [15,29,13.3,-6.4,2.9,17.1,-8] pause //To load function 'lagpol': getf('lagpol') pause //The general call to the function is: lagpol pause //The following call to function 'lagpol' is used to evaluate the //Lagrangian polynomial at x = 1.8: //lagpol(1.8,x,y,8) // //polynomial degree = // // 8. // //vector size= // // 7. // !--error 9999 //use smaller polynomial degree n //at line 18 of function lagpol called by : //lagpol(1.8,x,y,8)

pause //This call to function 'lagpol' produced an error because Lagrange //polynomials can only fit polynomials of degrees one size smaller //than the number of data points available. For example, the following //call to 'lagpol' fits a Lagrange polynomial of order 6: lagpol(1.8,x,y,6) pause //The following for-loop evaluates Lagrange polynomials of order k = //1,2,...,6, for x = 1.8: for k = 1:6 lagpol(1.8,x,y,k) end pause //Consider another example involving the following data vectors: x = [0:1:6] y = 3.5*x^3-2.8*x^2+5 pause //The Lagrange polynomial fitting for x = 3.5 and polynomial orders k = //1,2,...,6, are: for k = 1:6 lagpol(3.5,x,y,k) end //SCILAB function mtlb_diff(x) //============================ //This function is used to obtain the increment in consecutive //elements of a vector, e.g., for the following value of x: x pause mtlb_diff(x) pause //For the vector y defined earlier, mtlb_diff(y) pause //Difference tables. //================== //The user-defined function 'Difference_Table' can be used to //generate difference tables of x,y tables in which x is equally //spaced. To load the function use: getf('Difference_Table') pause //The general call to the function is: Difference_Table pause

//First, we generate a table of values of x and y in which the values of x //are equally spaced: x = [1.0:0.1:2] y = exp(-0.5*x).*cos(2*x) pause //The input vector must be a column vector, thus, in the following call to //function 'Difference_Table' we use y' instead of y, and produce a difference //table up to the 4-th difference (5 columns in the table): [DTable] = Difference_Table(y',5) pause //Least-square method for polynomial fitting //========================================== //User-defined functin 'PolyFit' can be used to fit a polynomial of //a given degree to a data set (x,y). To load the function use: getf('polyfit') pause //The general call to this function is: polyfit pause //The input vectors x,y are column vectors, thus, in the following //call to function 'PolyFit' we use vectors x' and y'. The call //corresponds to a polynomial of order 3: [b] = polyfit(x,y,3) //The resulting polynomial is put together by using: p = poly(b','s','coef') pause //CUBIC SPLINE INTERPOLATION //========================== //Sometimes, to interpolate data from a data set we use cubic //spline interpolation. These cubic splines are cubic functions //describing the variation of y = f(x), selected so that continuity //of the function, and of its first and second derivatives, is //ensured. pause //SCILAB provides functions 'splin' and 'interp' to calculate spline //interpolation. For example, consider the following data vectors //x and y: x = [0.0 1.2 3.5 4.2 6.2 8.1 11.2] y = [15 29 13.3 -6.4 2.9 17.1 -8.0] pause //To visualize the data use (assuming 'plotlib' is installed in your //SCILAB software): plot(x,y,'+') pause //To produce the spline interpolation, first use function 'splin' to //produce a vector of derivatives, d, of the splines:

d = splin(x,y) pause //To interpolate data, generate a vector xx that includes values //of x in the range [0-11.2]: xx = [0:0.1:11.2]; pause //then, use the following call to function 'interp' to obtain //vectors y0, y1, y2, and y3: [y0,y1,y2,y3] = interp(xx,x,y,d); pause //The // y0 // y1 // y2 // y3 pause vectors thus produced represent the following: = interpolated values of the function = first derivative = second derivative = third derivative

//To visualize the interpolation we use the following commands: plot(x,y,'+') //Then, use function 'hold' to allow plotting additional data: hold() //To plot the interpolated data use: plot(xx,y0) //In the same plot you can show the derivatives: plot(xx,y1,'--') plot(xx,y2,'r') plot(xx,y3,'g5') hold() //The last call to 'hold' actually releases the plot. pause //To show the original data and the interpolation in a different //graphics window [window number 2] use the following commands: fig(2) plot(xx,y0,'r') hold() plot(x,y,'+m') hold() pause //Use of function 'smooth'. //========================= //Function 'smooth' is used to interpolate data using cubic //splines in a manner analog to function 'interp', except that //with 'smooth' we use matrices rather than vectors. pause //To illustrate the use of 'smooth', we will use the vectors //x and y previously defined, i.e., x y pause //First, we put together a table of the original data so that //the values of x are located in the first row and the values

//of y in the second row: xy_Original_Table = [x;y] pause //The following call to function 'smooth' produces a table of //interpolated values of y for values of x starting at the first //value of x in the original table and increasing by and amount //of 0.1. The resulting interpolated values are given in the //form of table, with x in the first row and y in the second row: xy_Fitted_Data = smooth(xy_Original_Table,0.1); pause //To separate the data into vectors xx and yy use: xx = xy_Fitted_Data(1,:); yy = xy_Fitted_Data(2,:); pause //Produce a plot of the original and fitted data in Scilab Graphics //Window number 3: fig(3) plot(xx,yy) hold() plot(x,y,'o') hold() pause //User-defined function 'splinepol'. //================================== //This function produces expressions for the cubic polynomials that //make up the spline interpolation. We will use the vectors x and //y defined earlier, as well as the vector of derivatives d found //before: x y d pause //To load function 'splinepol' use: getf('splinepol') pause //The following call to 'splinepol', with independent variable 's', //produces a column vector whose elements are the 6 cubic spline //functions that fit the data: ps = splinepol(x,y,d,'s') pause //Associated with function 'splinepol' is function 'intersplin' that //permits interpolation of data using the polynomials found above. //To load function 'intersplin' use: getf('intersplin') pause //Interpolation of data using the existing value of xx, the polynomials //in ps, and the original set of values of x, is accomplished by using: yy0 = intersplin(xx,x,ps); pause

//To show the interpolation in Scilab Graphics Window Number 4 we use: fig(4) plot(xx,yy0) hold() plot(x,y,'xg') //Method of least squares for data fitting. //========================================= //The method of least squares consists in finding a number of //parameters, p(1), p(2), ..., p(m), that define a function //yp = f(p(1),p(2),...,p(m),x(1),x(2),...,x(n)) //that we will try to fit to the data set represented in the //following table: pause // // ================================ // x(1) x(2) ... x(n) y // ================================ // x(1,1) x(1,2) ... x(1,n) y(1) // x(2,1) x(2,2) ... x(2,n) y(2) // . . . . // . . . . // . . . . // x(k,1) x(k,2) ... x(k,n) y(n) // ================================= pause //The error, e(i), is the difference between the actual //value y(i) and the fitted value yp(i), i.e., // e(i) = y(i) - yp(i) pause //The method of least squares seeks to find the values of //p = [p(1), p(2), ..., p(m)] that minimize the Sum of //Squared Errors function, SSE(p(1), p(2), ..., p(m)), //defined as pause // n n // ____ ____ // \ \ // SSE(p) = \ e(i)^2 = = \ (y(i)-yp(i))^2 // / / // /____ /____ // i = 1 i = 1 pause //To solve for p(1), p(2), ... ,p(m), we form the m equations //d(SSE)/dp(1) = 0, d(SSE)/dp(2) = 0, ..., d(SSE)/dp(m) = 0, //and solve them simultaneously [See Chapter 17, Volume 2 of //the textbook "Numerical and Statistical Methods with SCILAB //for Science and Engineering" for details of this method for //the cases of simple linear and mutiple linear functions. //See also pages 440-445 for applications of the method of //least squares to bi-linear and bi-quadratic fittings]. pause //Function 'datafit' //==================

//SCILAB provides function 'datafit' to produce least-square //fittings for any type of functions. The general call to this //function, in its simplest form, is: //[p,SSE] = datafit(G,Z,p0) //where p is a column vector containing the fitted parameters; //SSE is the sum of square errors corresponding to the fitted //parameters; G is a function representing the error, i.e., pause //e = G(p,z) = y - f(p,x) = z(n+1) - f(p,z(1),z(2),...,z(n)), //z is a vector of variables, with z(1) = x(1), z(2) = x(2), //..., z(n) = x(n), and z(n+1) = y; Z is a matrix whose rows //are the lists of values of x(1), x(2), ..., x(n), and y; pause //i.e.,(from the table shown above) with //x1 = [x(1,1), x(2,1), ..., x(k,1)] //x2 = [x(1,2), x(2,2), ..., x(k,2)] // . // . // . //xn = [x(1,n), x(2,n), ..., x(k,n)], //y = [y(1), y(2), ..., y(n)], pause //form //Z = [x1;x2;...;y]; //and, p0 is a vector with initial guesses of the parameters p. pause //To find additional information on function 'datafit' use: help datafit pause //Function 'datafit' Example 1 - quadratic function //================================================= //To illustrate the use of function 'datafit', we first generate //data based on the quadratic equation Y = 20+30*X+50*X^2: X = [0:0.1:10]; Y = 20+30*X+50*X^2; pause //Next, we add a random component given by: E = 1000*(rand(1,length(X))-0.5); pause //The y-data to be used is calculated as: Y1 = Y+E; pause //A plot of the data set (X,Y1) is shown against the original //function (X,Y): plot(X,Y,'-',X,Y1,'+') pause //To use 'datafit', we first form matrix Z: Z = [X;Y1]; pause //and define the error function as follows: deff('[e]=G(a,z)','e=z(2)-a(1)-a(2)*z(1)-a(3)*z(1)^2')

pause //Use as initial guess of the parameters: a0 = [1;1;1] pause //Calling function 'datafit': note, it takes a couple of minutes //to produce a result: [aa,er] = datafit(G,Z,a0) pause //The result shows the SSE for the fitted parameters. To check //how well the fitted data follows the original data put together //the function f(x): deff('[y]=f(x)','y=aa(1)+aa(2)*x+aa(3)*x^2') pause //and calculate the corresponding values: YY = f(X); pause //The following plot shows the fitted data and the original data //points: fig(2);plot(X,YY,'-',X,Y1,'+') pause //Function 'datafit' Example 2 - cubic function //============================================= //Here we produce a cubic polynomial fitting using the same data X,Y1, //that we used earlier. The error function is now: deff('[e]=G(a,z)','e=z(2)-a(1)-a(2)*z(1)-a(3)*z(1)^2-a(4)*z(1)^3') //and the initial guess for the parameters gets changed to: a0 = [15;25; 49; 10] pause //Calling function 'datafit' produces, after a few minutes, the //the following results: [aa,er] = datafit(G,Z,a0) pause //Next, we generate data from the fitted function to compare //to the original data by defining the function f(x): deff('[y]=f(x)','y=aa(1)+aa(2)*x+aa(3)*x^2+aa(4)*x^3') pause //and generating vector YYY: YYY = f(X); pause //A plot of the cubic fitted data and the original data is //shown next: fig(3);plot(X,YYY,'-',X,Y1,'+') pause //The following commands repeat the graph just produced, but //also add the quadratic fitting found earlier:

fig(4);plot(X,YYY,'-',X,Y1,'+') hold() plot(X,YY,'r-') hold() pause //Function 'datafit' Example 3 - exponential function //=================================================== //In this exercise we use an exponential function to fit the original //data set X,Y1. First, define the error function: deff('[e]=G(a,z)','e=z(2)-a(1)-a(2)*exp(a(3)*z(1))') //Re-define the initial guess for the parameters: a0 = [5;1;2] //Call function 'datafit' to obtain the fitted parameters: [aa,er] = datafit(G,Z,a0) pause //Define the exponential function using the parameters found //with 'datafit': deff('[y]=f(x)','y=aa(1)+aa(2)*exp(aa(3)*x)') pause //Calculate the vector of fitted values: YYYY = f(X); pause //Plot the exponentially-fitted data and the original data in //the same set of axes: fig(5);plot(X,YYYY,'-',X,Y1,'+') pause //Produce a graph comparing the original data and the three //fittings calculated above: fig(6);plot(X,YYYY,'-',X,Y1,'+') hold() plot(X,YY,'g--',X,YYY,'r-') hold() //End Script