280 likes | 439 Vues
Dr Deepak B Phatak Subrao Nilekani Chair Professor Department of CSE, Kanwal Rekhi Building IIT Bombay Lectures 10, Matrices Saturday 3 July 2010. Two-week ISTE workshop on Effective teaching/learning of computer programming. Overview. Handling matrices Multi-dimensional arrays
E N D
Dr Deepak B Phatak Subrao Nilekani Chair Professor Department of CSE, Kanwal Rekhi Building IIT Bombay Lectures 10, Matrices Saturday 3 July 2010 Two-week ISTE workshop onEffective teaching/learning of computer programming
Overview • Handling matrices • Multi-dimensional arrays • Matrix computations
Multi-dimensional arrays • We can declare and use arrays which have more than one dimension int A[50][40] • Declares a two dimensional array with 50 rows and 40 columns • Each element is now accessed by a reference requiring two index expressions to be specified A[i][j] = 37; • The row index can have a value from 0 to 49, the column index from 0 to 39 • All rules for index expression apply to index for each dimension
Matrix • Matrices arise in many applications • Represent a system of equations in multiple variables • For example, the following equations in two variables 2y + 4z = 8 eq.1 4y + 3z = 1 eq.2 can be represented as 2 4 y 8 4 3 z = 1
Gaussian elimination • This method depends upon some standard facts: The system of equations is not affected if an equation is multiplied by a constant 2 y + 4 z = 8 is same as 1 y + 2 z = 4 (multiply the equation by 0.5) • So we now have 1 y + 2 z = 4 eq.1’ 4 y + 3 z = 1 eq.2
Gaussian elimination … • Representing these equation in the form of matrices: 1 y + 2 z = 4 1 2 y 4 eq.1’ 4 y + 3 z = 1 4 3 z = 1 eq.2 Note that the original Coefficient matrix was 2 4 y 8 eq.1 4 3 z = 1 eq.2
Gaussian elimination … If an equation is replaced by a linear combination of itself and any other row, the system of equations remains the same • We replace eq.2 by subtracting from it, 4 times the first equation (eq.1’). 1 y + 2 z = 4 1 2 y 4 eq.1’ (* 4) 4 y + 3 z = 1 4 3 z = 1 eq.2 We get 1 y + 2 z = 4 1 2 y 4 eq.1’ 0 y - 5 z = -15 0 -5 z = -15 eq.2’
Gaussian elimination … • If we further divide eq.2’ by -5, we will get 1 y + 2 z = 4 1 2 y 4 eq.1’ 0 y + 1 z = 3 0 1 z = 3 eq.2’’ Starting from the last equation, and using back substitution, we get the solution for all variables. Thus 0 * y + 1 * z = 3 gives us z = 3 1 * y + 2 * 3 = 4 gives us y + 6 = 4 which gives us y = -2
Gaussian elimination … • The essence of the method is to reduce the coefficient-matrix to an upper diagonal matrix with all elements on the diagonal as 1, and then use back-substitution • The process is susceptible to round off errors • There are other variations, such as: • Gauss Jordan elimination, Pivoting • L U decomposition • A useful reference: • Numerical recipes in C, also in C++, Fortran (William H Press, Saul A Teukolsky, William T Vetterling, Brian P Flannery)
General representation In general, a system of linear equations in N variables can be represented by a11 a12 a13 ... a1n x1 b1 a21 a22 a23 ... a2n x2 = b2 a31 a32 a33 ... a3n x3 b3 . . . . . . an1 an2 an3 ... ann xn bn
General representation C style Since the matrix indices in c vary from 0 to n-1 We may use another representation: a00 a01 a02 ... a0n-1 x0 b0 a10 a11 a12 ... a1n-1 x1 = b1 . . . . . .
Diagonal matrix C style The Gaussian elimination technique essentially reduces the coefficient matrix to an upper triangular form: 1 a01 a02 ... a0n-1 x0 b0 0 1 a12 ... a1n-1 x1 = b1 0 0 1 . . . 1
General representation C style … • A general system of n equations can be written as a[][] x[] = b[] • With the coefficient matrix in upper triangular form, we now have the following system using which back substitution can be applied x[0] + a[0][1] x[1] + … + a[0][n-1] x[n-1] = b[0] x[1] + … + a[1][n-1] x[n-1] = b[1] . . . x[n-1] = b[n-1]
Example of 2 variables • Consider our example equations in two variables 2y + 4z = 20 y + 3z = 11 • Representing y by x[0] and z by x[1], this can can be represented as: a[0][0] x[0] + a[0][1] x[1] = b[0] a[1][0] x[0] + a[1][1] x[1] = b[1] Where a[0][0] is 2, a[0][1] is 4, a[1][0] is 4, a[1][1] is 3 and b[0] is 20, b[1] = 11
gauss.cpp #include<iostream> using namespace std; int main(){ int i, j, k, n; float MatA[100][100], MatB[100], X[100]; float Divisor, Factor, sum;
gauss.cpp … cin >> n; //reading matrix A for(i=0; i< n; i++){ for(j=0; j < n; j++){ cin >> MatA[i][j]; } } //reading matrix B for(i=0; i< n; i++){ cin >> MatB[i]; }
gauss.cpp … //Gauss elimination for (i=0; i< n; i++){ // divide each row by the coeffs on the diagonal Divisor = MatA[i][i]; MatA[i][i] = 1.0; // Now recalcualte all coefficients in that row for (j = i+1; j < n; j++){ MatA[i][j] = MatA[i][j]/Divisor; } //normalize the corresponding rhs element MatB[i] = MatB[i]/Divisor;
gauss.cpp … // now replace subsequent rows, by subtracting the // appropriate portion of the ith eqaution from it if (i+1 < n) { for (k=i+1; k<n; k++){ Factor = MatA[k][i]; MatA[k][i] = 0.0; for (j = i+1; j < n; j++){ MatA[k][j] = MatA[k][j]-Factor*MatA[i][j]; } MatB[k] = MatB[k] - Factor * MatB[i]; } } }
gauss.cpp … // back substitution starting with last variable X[n-1] = MatB[n-1]; for (i = n-2; i>=0; i--){ // Sum up ith row using values of X already determined sum = 0.0; for (j = i+1; j < n; j++){ sum = sum + MatA[i][j] * X[j]; } X[i] = MatB[i] - sum; }
gauss.cpp … //output the results for(i=0;i< n;i++){ for (j = 0; j < n; j++) { cout << MatA[i][j] << " "; } cout << " " << MatB[i] << "\n"; } for (i=0; i<n; i++){ cout << "X[" << i << "] is: " cout << X[i] << "\n"; } return 0; }
Useful facilities from the OS • Ordinarily, we have been using the key board to input data, and the screen to see the output values. • If we have to repeatedly execute a program during debugging trials, the same input has to be given again and again. This is wasteful of our time. • If the input values are large in number, we have seen how a ‘file’ can be used. Such a file is pre-edited to contain the required input in the prescribed format • For example: “rollmarks.txt”
Redirection • Even when we use cin >> … , for input, it is possible to ‘redirect’ the standard input file (stdin) to any other file of our choice when executing a program $ ./a.out < inputdata.txt This will read ALL input only from the named file. • It is similarly possible to redirect ALL output to a named file, instead of the standard output device (stdout) which is your terminal $./a.out > outputdatafile.txt • both redirections can be used simultaneously
Input datafile “coeffs.txt” 4 2.0 1.0 3.0 -4.0 1.0 -2.0 -2.0 3.0 5.0 3.0 -1.0 -1.0 3.0 4.0 1.0 -2.0 -3.0 3.0 4.0 6.0
Sample results $./a.out < coeffs.txt > result.txt $ cat result.txt 1 0.5 1.5 -2 -1.5 0 1 1.4 -2 -1.8 0 0 1 -1.08696 -1.34783 0 0 0 1 4 X[0] is: 1 X[1] is: 2 X[2] is: 3 X[3] is: 4
Results should look better $ cat result.txt 1 0.5 1.5 -2 -1.5 0 1 1.4 -2 -1.8 0 0 1 -1.08696 -1.34783 0 0 0 1 4 X[0] is: 1 X[1] is: 2 X[2] is: 3 X[3] is: 4
Need for debugging • When you are testing a program and are not sure of the behaviour of your algorithm • you may include output statements to print a few key variables at strategic points in your program • These will help you identify errors • Such statements are called debugging statements
Useful facilities from C (GCC) • Ordinarily, once you correct these errors, you will like to remove such instructions • In a large program, with many such debugging statements, it will amount to a lot of painful work • C (gcc) provides us with a neat option. We can write statements enclosed in a special if statement written on two separate lines: #if xxxx ----- #endif
Compiling with -D option • “xxxx” is any name-tag of our choice • for example, “notsure” #if notsure cout << i << “ “ << j << “ “ << sum[i][j]; #endif • Ordinarily, c compiler ignores the block • But if you compile your program with: $ c++ -D notsure prog.cpp these statements are compiled and are executed as part of your program