 all of you are aware of matrices I believe you can calculate determinant of a matrix multiply matrices and so on. Today we shall be looking at a numerical technique to solve simultaneous equations using matrix representation. We will also introduce the notion of matrix multiplication numerically which is simple. We will elaborate it in the next lecture and we will also comment on the pitfalls in numerical computations as we go by. So this is of course given everybody knows that matrices arise in many applications they are largely used to represent a system of equations in multiple variables. So if I have an equation which is say 2y plus 4z equal to 8 and 4y plus 3z equal to 1 I call them equation 1 and equation 2 these can be represented in matrix form by putting the coefficients of y and z in both the equations here in one matrix which we will call the coefficient matrix A let us say these are the two independent variables y and z which appear in a vector and 8 in one other right hand side which will call the B matrix traditionally A and B matrices. So we represent this as A x equal to B where x is a vector multiplying elements of one row of a matrix with corresponding columns of a vector and adding these gives us the dot product. The notion of dot product is known to all of you. So basically what it means is if you look at the second row here 4 3 and multiply it with yz you will get 4 multiplied by y plus 3 multiplied by z which is nothing but the left hand side of this equation and this is equal to 1 by definition. So this in general is the matrix representation. How do we solve such equations when there are only two independent variables it is relatively simple but the mechanism that we use has been formalized typically one method that we shall see today called Gaussian elimination it depends on some simple facts about matrices. The first is that the system of equations is not affected if an equation is multiplied by a constant. So for example you look at the first equation 2 y plus 4 z equal to 8 this is same as 1 y plus 2 z equal to 4. Trivially known I just multiplied but observe that the multiplication factor that I have chosen which is 0.5 is such that it reduces the leading coefficient to 1 that will be of importance as we discussed the method further. So now we have equation 1 dash which is 1 y plus 2 z equal to 4 and we have 4 y plus 3 z equal to 1 which is the equation 2. So we now have reduced the system of equations to the same system basically but reduce the coefficient of the first row first column to 1. We shall see how it leads to identity matrix at a later stage. If we represent these equations in the form of matrices we have equation 1 dash and equation 2 dash which effectively the matrix here reduces to 1 and 2 because we have reduced this to 1 and note that the original coefficient matrix was 2 4 4 3. The point I am making here is that I need not use the independent variables y and z in the equation elimination that I do I can work entirely with the coefficient matrices and arrive at the same effect. So that is why we are saying that this coefficient matrix 1 2 4 3 and the right hand side 4 1 represents the same system of equations as 2 4 4 3 and 8 1 represented. There is no difference. This is the other fact about a system of linear equations. If any equation is replaced by linear combination of itself and any other row the system of equations remain the same. That means there is no material change in the system of equations given. Using this we replace equation 2 now by subtracting from it 4 times the first equation. So equation 1 dash which I had I multiplied equation 1 dash by 4. So I will get 4 y plus 8 z equal to 16 and I will subtract from the second equation the first equation times 4. So I will replace second equation using this. What do I get now here? Obviously I will get 0 as the coefficient of y because I am multiplying the first equation by exactly this coefficient. The idea is to get a 0 here and to get whatever coefficients I get elsewhere. Observe that 3 will get multiplied sorry 2 will get multiplied by 4 giving me 8. When I subtract 8 from 3 I will get minus 5 here and similarly when I subtract 16 from 1 I will get minus 15 here. Consequently my coefficient matrix will look like 1 2 0 minus 5 and of course the right hand side will appropriately change. So this is the next step in the Gaussian elimination. Of course what I did with the first equation namely to get this coefficient 1 here I divided the entire equation by whatever was the coefficient originally. I do the same thing here again. If I multiply equation 2 dash by minus 5 we will get 1 y plus 2 z equal to 4 0 y plus 1 z equal to 3. So essentially observe that the coefficient matrix is reduced to a sort of diagonal matrix 1 1 and then 0 here and there is 2 here of course. This is the equation now equation 1 dash and equation 2 dash. Here ends the Gaussian elimination this is the fundamental Gaussian elimination technique. I of course if I have n by n equation system then I will apply this technique to all the subsequent rows at every stage of the earth. But as far as this particular system is concerned I can now get the values for 2 variables in this case z and y by what is known as back substitution. Everybody is familiar with back substitution? Well even if you are not just look at these 2 equations the second equation 2 dash directly gives me value of z. z is equal to 3 and when I substitute z equal to 3 into first equation this second equation gives us z equal to 3 and this first equation when I put this value of z which I have calculated back into this this is what is called back substitution. I will get 1 into y plus 2 into 3 equal to 4 which gives us y plus 6 equal to 4 or y equal to minus. This process I think is well known to all of you the reason I am revisiting this is because we want to construct a computational algorithm to do this automatically. Very obviously you can solve 2 by 2 equations 3 by 3 equations even 4 by 4 equations with ease doing arithmetic calculation. But if you are 10 by 10 equations what will you do? If you are 50 by 50 equations what will you do? If you are 100 by 100 equations what will you do? If you are 1000 by 1000 equations they may not even fit into the computer's memory using matrices then what do you do? So there are specialized cases which in engineering and science you keep coming across and you need to solve these problems. There are additional squiggles such as problems of round off errors. There are problems where the system itself may be unstable. You have heard of singular systems that means the system which do not have a solution. You have n equations but one of the equations turns out to be a linear combination of some other equations. In which case you do not have as many independent equations as you have independent variables you cannot solve that problem. However given a stable system how do we automatically solve it using a computer program is what is the focus of our attention. Where we notice that the essence of the method is to reduce the coefficient matrix to an upper diagonal matrix with all elements of the diagonal as 1 and then use the back set. Upper diagonal matrix means all elements in a matrix in the lower diagonal portion are all 0. Along the diagonal you have 1 and above the diagonal you have various values which come out due to the processing that we do. So once we have a diagonal matrix we know very clearly that using back substitution we can find out the solution. This process is susceptible to round off errors. What are round off errors? Round off errors are errors which arise when during your computations you perform an operation where the result does not have as much precision as you originally had representing the two given numbers. Particularly in floating point number representation as you know you have mantissa and exponent mantissa represents the procedure. If you have values which are very similar consider 0.418295 into 10 to the power minus whatever 20 and another value 0.4198 say 7. Now when you subtract these two very like values you will of course get the correct result as well as that accuracy is concerned but instead of 4, 6 or 7 digits of precision which you had for each of the individual numbers the result will have only 1 or 2 digits of precision. Even if you shift it left as is required for floating point representation and appropriately increase or decrease the exponent you still have zeros beyond that. That means your lost procedure. A much simpler example is we had seen the quadratic equation solution where you calculate the determinant and the result is minus b plus minus under root of b square minus 4ac upon 2a. You all remember that? Imagine what would happen if square root of b square minus 4ac turns out to be very close to b. You all agree this was the formula for finding out the roots of quadratic? Now in this if the value of 4ac happens to be much smaller than that of b square then effectively this entire entity will be close to b itself because b square minus 4ac will have negligible impact on b square and square root of b square will be b. So effectively what you are doing here in such a situation is you are saying minus b plus minus b plus delta where delta is the difference between the b and b square minus 4ac. Now obviously delta will not be as accurate as you would like it to happen because you are subtracting from two like quantities b and b plus delta and therefore you will lose accuracy. So even in simplest of the calculations you can lose accuracy. You will later on most of you not all of you not computer science perhaps not chemistry but mechanical engineers, civil engineers, aerospace engineers, chemical engineers and anybody who does large system solution whether you are computer scientist or whatever you will be dealing with very large systems where the number of iterations will be very very large and the round off errors might actually. So there have to be special numerical techniques in order to counter them. As I said once you will be learning these computational techniques later but keep this in mind. What you observe is that this process of simple Gaussian elimination is susceptible to round off errors. There are other variations such as Gauss Jordan elimination. Gauss Jordan elimination is very simple extension of Gauss Jordan elimination. In Gaussian elimination you reduce the matrix to a diagonal form handling only the lower rows at any particular point. In Gauss Jordan elimination you also handle the upper rows. So basically you may not require back substitution in the fullest sense that we deploy here. There is a notion of pivoting. You remember we use in this method a division by the coefficient on the diagonal. Say A00 later on it will be A11. What if A00 or A11 happens to be a very small value? Then I might actually enhance computational errors. So I might want to exchange rows below my rows or whatever row I am looking at and I might look at a row which has the largest coefficient at the first point because then I will have maximum impact. So that is called pivoting. When you exchange rows to enhance the stability and correctness of your answer you call it pivoting. This is partial pivoting because you are exchanging rows. You can also exchange columns but when you exchange columns you have to do some tricky thing with the right hand side B matrix also because remember the large product should not be disturbed final. And if you exchange both rows and columns then that is called full pivoting. There are very complex algorithms and then subsequent iterations to enhance the value etc etc that is outside the scope of this course. I am just trying to tell you that while the simple method will give you solutions in most cases there will be peculiar cases where you might not get accurate solution. All these variations are discussed in a very useful reference called numerical recipes in C++. Actually the original book was numerical recipes in FORTRAN. Then the authors came up with numerical recipes in C and recently they came up with numerical recipes in C++. These are the names of the authors. You may not be able to read them. They are from extremely well known institutions like Smith-Sodian Harvard Center or Cornell University and what not. Accomplished numerical computations and the book is full of wonderful algorithms slightly complex for this level of understanding but some of you are interested can look at this. So in general then a system of linear equations in n variables can be represented by a normal matrix notation in this fashion. Observe that I have an immediate problem here when I talk about C++ and that is because ordinary representation in matrices starts with a11, a12, a1n, a21, a22, a2n, an1, ann and the variables are appropriately x1, x2, x3, xn. The right hand side is b1, b2, b3, bn. This is the normal representation of the matrix. However in C++ since all arrays start their index from 0 and go up to n minus 1 we shall use a representation which is a modified form. So the general representation C++ style will be of this kind. So if you have n variable, a system of linear equations in n variables you have n by n coefficient matrix and you have a n row column, a single column vector on the right hand side. But the values, indexes vary from 0 to n minus 1. That is the only thing to be remembered. What are we going to do in this case? What are going to be the calculations that we shall do on this? So I have just written here some coefficients. The starting process requires that I reduce this to 1. This is the first diagonal. So consequently I will divide this entire equation. I will divide by a00. Consequently this will become 1. This will become a01 divided by, I will call this dividing factor say d. So this will be divided by d, a02 will be divided by d and so on. And even b0 will get divided by d. You agree? That is what will happen. Now in the next level I want to reduce this to 0. So I will simply multiply the modified first equation by a10 and subtract it from the second equation. So I will get, let me write some more columns here. a20, a21, a22, etc. This is a12 and this is let's say b1 and this is b2. So when I am looking at this row, then what operation I have to do is I have to first reduce this to 1 and next reduce all these to 0 successively. So I will now operate upon the second row and reduce this to 0. How will this be reduced to 0? I have to subtract from a11. This element multiplied by a10. So I have to subtract from it a01 divided by d multiplied by a10. You agree? So basically whatever was the divisor factor d, here I have to have another multiplying factor m. I have to use that multiplying factor m to multiply this and subtract it from here. Then I will go to this row where again the multiplying factor will be this because this has to be reduced to 0. So using another multiplying factor I will do the same thing. Consequently when I am looking at first row let me say I is equal to 0 here which is the first row. Then I would have handled this as 1 and I would have got 0s here everywhere and I would have modified all other coefficients. That is what is important. It is not that you arbitrarily put 0 here but in order to get these 0s you have to modify this, this, this, etcetera, etcetera. Does it complete the task? No. What I have got now is a diagonal element only in the first row. But notice that now if I do the second iteration I equal to 1 and I will start with this. This was 0 only. This was some complicated quantity. What I have to do now? I have to reduce that to 1. Again using the same multiplication factor business I will reduce it to 1 and reduce all of these things by the appropriate divisor and then start looking at the third row, fourth row, fifth row, etcetera. Doing exactly the same thing. Then I will go to I equal to 2 and 3 and 4 and so on and when I am finished you will agree that I will have a matrix which will look like the diagonal matrix. So I will have 0s everywhere. I will have 1 on the diagonal and I will have these a 0 1, a 0 2, a 0 n minus 1 by the way are not the original values. You can say these are a 0 1 dash, a 0 2 dash, etcetera, etcetera because these all would have undergone a lot of computational change. But still the system of equation which I originally had and this system represented by this matrix are no different because we have followed the basic principle. Consequently the right hand side will also change b naught, b 1, b 2, etcetera which I have written which will actually be b naught dash, b 1 dash, b 2 dash something different from the original. And now you can see I can do back substitution easily on this. So the last value for example the value of x n minus 1 will simply be the value of b n minus 1 because the coefficient is 1. Once I get that I can back substitute I will get second variable x n minus 2. Then knowing these two I can find the third and so on all the way back up to x n. So in principle this is a very simple computation and I have written a program to do this Gauss elimination which we shall very briefly look at. This is the general representation of system of equations in C plus plus time where we say a matrix A multiplied by matrix X is equal to matrix B. B is a vector, X is a vector, A is a two dimensional area. Generally we denote coefficients by A matrix and right hand side by B matrix and variables by X or whatever. So which effectively implies for C plus plus the following A 0 0 into X 0 plus A 0 1 into X 1 plus A 0 into n minus 1 into X n minus 1 is equal to B 0 is the Gauss product of one row with that column will give you the right hand side value and so on. So this is what is implied when we represent a general system of n equations by two matrices A and B. We have to remember the notation of 0 0 0 1 1 0 1 1 n minus 1 1 0 etcetera etcetera to vary our indices proper. In this particular case I have represented 2 y plus 4 z equal to 20 and y plus 3 z equal to 11 by something and you reduce these things appropriately. Here is the program for doing the Gauss elimination I called it Gauss C P P. So here we go with the Gauss dot C P P I declare the floating point arrays. Please note that in numerical computations you do not use integers. Obviously this will be a floating point value. I have used the term mat A mat B observe the capital M and capital A. This is one technique when you are variable name or array name is very large then you actually punctuate that large name by putting one character as a capital later so that you can recognize the entire name meaningfully. So I have these two matrices mat A and mat B and I have of course X 100 which will contain the final results. I use two additional terms divisor factor and sum the divisor is the one which will be used to set the leading coefficient to 1. The factor will be used for every row subsequently to do all the modifications in the subsequent rows at every iteration and sum of course would represent we will use that sum in back substitution. We would not need it otherwise. I read the value of N. Notice that I am not saying C out give the value of N. Ordinarily you would all do that. There is a purpose behind this and I shall explain the purpose later when we see some additional facilities and facets of both C plus plus and the operating system that we use. So I read in the value of N and for 0 to N 0 to N I read all the coefficients of A mat A ij very simple. Similarly I read matrix B which is actually a vector i from 0 to N I read mat B i. I have got both the arrays read into the memory from an input device. Of course currently the input device is your keyboard that is why you give your input from. Now I start the Gauss elimination. So for i equal to 0 to less than N that means for each row what do I do? First I divide each row by the coefficients on the diagonal. So I take set divisor to be mat A i comma i. For the first row it will be 0 comma 0 etc. With this divisor when I divide the each row the i comma ith element will become 1. So consequently I need not calculate that division. I need not do divide this by the same thing. I can directly set it to 1 because I know it is going to be 1. But subsequent rows where I have to calculate all coefficients oh no sorry subsequent coefficients in that row itself I will have to calculate by dividing the corresponding coefficients by the divisor. So for row number i for column number i plus 1 to N minus 1 that is why the j varies from i plus 1 to less than N. What I do is I take every element mat A i comma j and divide it by divisor and replace that value in mat A i comma i. So consequently my first row I have got to my liking the first element is 1 and all subsequent elements have been scaled. Of course I must normalize the right hand side B matrix which I do here outside the j loop because whatever is the ith row I have to actually normalize the ith column. So I say mat B i is equal to sorry ith row in the mat B. So I say mat B i divided by divide. So how the complete equation left hand side right hand side appropriately normalize. Now I replace subsequent rows so I repeated the logic by subtracting the appropriate portion of the ith equation from it. i will be 0 to begin with then it will be first second and so on. Notice that when I am doing this with the last row N minus 1th row i is equal to N minus 1 there is no next row. So I should not arbitrarily try and access elements in an array which do not exist and that is why I must check whether there are any subsequent rows. So I have an if statement. If i plus 1 less than N then N only then you do it. What would i plus 1 less than N will mean? That there is if I am looking at ith row then there is a row which is beyond that. If there is no row I have no work to do. But if there are rows and there will be many rows if I start with i equal to 0 I want to finish of this job for all the row. The index k varies over all the rows subsequent to ith row. Since I have just normalized the ith row the row i plus 1, i plus 2, i plus 3 etc. which is where k is varying from i plus 1 all the way up to k less than N which is the last row. And for each row what do I have to do? I have to subtract a multiple of ith equation from that and substitute it there. So I calculate a factor which is mat a k comma i. Observe that this is the leading element just before i comma i that is what will get subtracted from i comma i element. So I take that as factor since if I multiply ith row by this and subtract that ith row from the current row I will always get a 0 in that position. I set it mat k i to 0 direct I do not have to do that subtraction just like I did not have to do that division for one element. But for subsequent elements which is j equal to i plus 1 to N minus 1 I have to replace every element k j by the original element minus factor times matrix A i comma j. This is the corresponding element of ith row. So I am taking the corresponding element of ith row multiplying it by the factor and subtract it from k comma j from the kth row corresponding N. If I complete this loop for k I would have replaced all the rows subsequent to the ith row. And of course I must not forget my right hand side where I set mat B k to be mat B k minus factor times mat B i which was the corresponding element. Is this clear? So this is how I will do the computations I just close all the loops. Now I start back substitution. So I start with the last variable. Last variable is X N minus 1. I get its value directly as mat B N minus 1. Why? Because the coefficient is 1. I have a diagonal matrix. Using this I will go backwards from i equal to N minus 2 to 0. Observe that instead of incrementing the index I am decrementing. So I will first find out X N minus 2. Then I will find out X N minus 3 etcetera all the way up to X 0. When I have calculated X 0 I will stop. So I start with X N minus 1 and in this iteration I will sum up the ith row using values of X which I have already determined. This is where I use the sum. I start with sum equal to 0. For j equal to i plus 1 to N minus 1 that means all the elements in that equation which is the ith equation which I am looking at back substitution. I will sum up the mat aij into xj which I already found out. Please note that the xj's which are used here are those xj's which are already determined because j starts from i plus 1 and before that I have already found out. Finally I get the xi as the right hand side minus sum. This is a simple equation by substitution. This is what I get. Effectively what I have done is a simple mechanism that we use to solve a 2 by 2 equation in two variables or a 3 by 3 equation in three variables. I have actually formalized that process in the name of Gaussian elimination which is a well recognized process which formalizes the same thing that we do. We studied the Gaussian elimination and we wrote a program to do all that automatically. After this I should simply output the results. So where are the results? The results are mat aij, j. Are these the results? Well not exactly. The results are x0, x1, x2, x3, x4, x5. But I have a diagonal matrix and it is useful to see that diagonal matrix how it looks like with the final thing. So what I am doing is I am outputting the final shape of the A matrix which is the diagonal matrix and the right hand side B matrix along the same row. So I will now know the reduced set of simultaneous equations which I begin with something. I have reduced them to some different form, an easy form. And of course I output the values of x0, x1, x2, etc. Notice the printing. I am saying this string x opening bracket, no space. Then I am outputting i. Then I am outputting another string which is just closing bracket some blank is and then I am outputting xi. So this will produce an output which will say x0 is value, x1 is value, etc. The reason I went very elaborately over this process is that the precautions that you must take in handling indices of arrays in C++. And when you implement a complex logic which requires first of all normalization of a row, then it requires reduction of all subsequent rows using some simple facts. And finally it requires back substitution. The logic has to be very crystal clear in your mind when you implement such algorithms. Yes. He is asking a question, if the element of the first diagonal is 0, then how do you divide by 0? You remember at the beginning I said that not all systems are stable systems. And even if all systems are stable, the element that you choose as a divisor, if that is 0, you have a serious problem. That is where you need to exchange either rows or columns. We are not going through that. So he is very right in pointing out that if at all I get a 0 somewhere, I cannot divide by 0 obviously. I would not get any value. And the program does not guard against such a possibility. It does not check whether the divisor is 0. If that happens obviously you cannot get the solution using this logic. But you should definitely refer to the numerical recipes. It tells you how to handle such things. As long as the system is not singular, that means the system has a solution, then there are algorithms which will determine that solution. But that is a good point and that good point should be remembered here. However, what I am trying to emphasize here is something different. Having understood the logic of our algorithm, let us look at the handling of data input and data output. There are certain facilities which our OS Dumbo provides which are important and useful, which we should know. Ordinarily when you say see in, you give your input from keyboard. And when you say see out, the output is produced on the terminal. Now if you have to repeatedly execute a program which requires large input value, usually when you are testing, you know, you might get error-free compilation, but there could be logical bugs in the program. And when you are testing, if you have to keep giving the data, assume that you are testing a program to try let us say 10 by 10 array. So you spend five minutes in looking at the error in your program, another five minutes in correcting it and 20 minutes in inputting that 10 by 10 array every time you run that program. Now that is pretty stupid. How did we solve this problem once? We had seen that if input values are large in number, we could use a file. Now such a file could be pre-edited and the same file can be used again and again. We have seen that in which case, roll number and marks. Of course in that sample, there were only some 17, 18 roll numbers, but even that would be a pen in the net if you have to input it again and again physically. And imagine if you are writing a program, let us say to calculate the grades for this class, then 837 roll numbers, all kinds of 0, 9, D, something, something, whatever. You fancy giving that input every time you test a program? No way. So it always use a file. However, the program that we had seen was explicitly opening that file in the program itself. We have not formally studied how to handle files within our program. We shall study that later, but for the time being, we are very comfortable with collecting input from C in and leaving output on C out. Ideally, we would like a substitution for that simple activity so that we do not have to change the statements in our program, but yet have the comfort of using input files and creating output files. This facility called redirection, which is provided by the operating system that you use. In fact, every decent operating system provides this facility. So even when you use C in, even when you use C in for input, it is possible to redirect the standard input file STD in to any other file of our choice. So for example, if instead of giving just a command dot slash a dot out, which is what you do to execute your program, you say dot slash a dot out less than input data dot text. What this command tells the operating system number is that when C plus plus starts executing its program, do not supply input to that program from the keyboard that users will type, but instead use this file and start reading characters from that file as if somebody is typing them and keep giving them to C plus plus them. The interesting fact is when any programming language whether it is C plus plus, Java, C, Fortran, whatever, whenever it does input output of any kind, the actual input output is handled by the back end operating system. So effectively the operating system is cheating our C plus plus them. C plus plus number still thinks that it is receiving input from keyboard, but operating system will collect that input stream from another file and keep giving it characters as it does C in. Now this is very useful to us because I can write in my program C in and I will get all the input from that file. So I don't have to type in the data every time. In exactly similar way it is possible to redirect all output to a named file. What happens when you get an output? You get it on the screen, but when you start executing that program again, the output disappears. It would be nice if you could collect such outputs into various output files which can be preserved, printed, seen again and again. Exactly the same redirection works. The command there is dot slash a dot out greater than some file name, output data file dot text. When you execute this command, an output data file dot txt is created. It need not exist. It is created and all the output which you have given in your program as C out statements will go to that file, each and every. Notice that is why in this program, the Gauss program, when I was reading N, which was the value of the number of independent variables, I did not say C out, give the value N. Why? Because if I am going to redirect, then give the value N will also go into that output file. I won't see anything on the screen anyway. So that is why when I am going to redirect my output to a file and redirect the input from a file, I will usually be not using the interaction on the screen during the program execution for input output. Data will go to the output file, data will come from an input file. But as you can see, it is extremely useful when you are handling large amounts of data. And of course, both can be used. Incidentally, if an output data file dot txt exists in your directory, then that old file will be removed and the new file will be created. So you will lose whatever you had. Consequently, if you want to preserve the results of several executions, then you might want to give different fined names. Alternately, instead of using greater than sign here, you could use greater, greater sign, which means append. So an output file can be appended too. So this particular symbol instead of simple, greater than, will actually append to a file. That means if you are earlier created a file, you keep appending it. You need not have created, if you use this for the first time and the output file does not exist, the operating system will create it for you. But you will never lose your data. So these are some useful tricks. And as I have said here, both the redirections can be used simultaneously. So here is what I have done. I have prepared an input data file coefficients dot txt. Observe that the first value is that of n representing a 4 by 4 matrix. Then I have 4 elements, 4 by 4 elements in A matrix and then I have B matrix. Observe that there is a blank line here. It does not matter when you use C in. Any number of blank lines are ignored. Just as white spaces or blank lines are considered separators between consecutive values. So it will correctly read as long as your sequence of reading is correct in your program. Here are the sample results. Then I say dot slash a dot out less than co-eps dot txt greater than result dot txt. That means this program will execute by reading data from this file and will create an output file called result dot txt. To look at result dot txt, either I can open it in my editor or simply give an operating system command called more. More means if a large file keeps showing me more in pieces is the wording. These funny wordings came when the unique operating system was designed many, many decades ago and people use some fancy terms. We have to live with that, but that's all. I would have liked print, show or some such thing or whatever. So the result dot txt will print these things. So what have you printed here? 1, 2, 3, 4 rows of the final matrix and 1, 2, 3 right hand side B matrix. And here are the values of x0, x1, x2, x3 which come out to be 1, 2, 3, 4 which incidentally are correct value. There is only one problem here. The output does not look very good. Can you immediately understand that these are two different matrices? This is A and this is B. Not very easy. You would have liked your output to look something like this. So you can discern the diagonal as all ones. This is upper diagonal matrix and you have these values. And your right hand side comes in some sort of tabulated fashion. The problem is when you see out, you have no control over formatting of different values as they will appear on the output, whether on the screen or whether in a file, directed file. But soon after mid-sem, we shall study formatting in great details whereby you can design your output to be very pretty looking, very nice looking so that people can understand. For the time being, we just leave this notion in our mind that we have to do something with output so that the output looks deset. This is not a very good output. I will introduce one more notion, which is the need for debugging. So when you are testing your program, I am not sure of the behavior of your algorithm, you want to include some output statements to print a few key variables at strategic points in your program. All of you do that? When your program doesn't work, you say see out i, see out j, see out ij, see out sum and you try to decipher it using it. She will introduce many such statements, but once such statements incidentally are called debugging statements, but once your program is okay, you will like to remove these instructions. Now in a large program where you have 20 such debugging output statements, it's a hassle to remove all 20. And suppose you remove all 20, your program is correct and tomorrow you have to modify that program to do something more, you'll again have to introduce them. Now that is a hassle. So C++ Dumbo provides a very neat option. It provides us to write special statements which are executed under one condition when I am debugging and not executed when I am normally executing the program. So the statements remain there very much. The normal practice is I don't want to delete these statements. So I'll just put a comment before those statements. And if I want to revisit those statements, I will remove those comments. But even that is not required if we use this facility. This facility is extremely useful for debugging. If inside my program, I have a block which is written like this, hash if x, x, x, x. There's a blank here. Some statements and hash endf. These hash if and hash endf are not looked at by C++ compiler normally. They are ignored. So the whole block is ignored. However, if you give a special debugging option called minus capital D, then C++ Dumbo compiles the program including these statements. And then these statements are executed whenever that order comes. x, x, x, x is any name tag of our choice. I like the word not sure. Obviously I'll use such statements when I'm not sure. So even my program, if I say hash if not sure, C out i, j, sum i, j. Endf. Let us see. Now I don't want this statement to be normally executed when my program is completely debugged. But during debugging, I want to execute this. So ordinarily C++ compiler will ignore this block. But if I compile my program with this option, C++ minus capital D, not sure. This word must be same as I have used here. Prog.cpp. That means all the blocks in my program, we start with hash if not sure and end with hash endf. All the intermediate statements will be included at the physical and logical location where they appear in the program. And the program will be compiled using this C out state. Later on, when I have corrected my program, I will simply remove this minus D, not sure option and I'll get a clean compilation without any debugging output. You agree that this is an excellent feature and a very useful feature? I would expect you to use this feature. Yeah. Okay. I'll just take three more minutes to make announcements. I will defer the discussion on matrix multiplication to the next class, but some announcements. I noticed that from the quiz performance, many of you have not had sufficient practice in solving problems, simple or difficult. Apparently, since I am not following Kuhun, nobody is looking at Kuhun and therefore nobody is looking at exercises at the end of Kuhun. While my style and approach has been slightly different, you'll find many problems in Kuhun's book which you can attempt to harm up your own logical thinking. I would suggest you strongly that you do that. In addition, I don't know how many of you have looked at the resources tab on the course homepage. Can you raise your hands if you have gone through the resources? Very, very few. I would like each and every person to visit these resources. I am sorry that I missed the point completely that without specifically pointing will not go there. That is unfortunate. The word resources should tell you that there are resources. They probably one of the richest resources existing in the country today. It contains the material that was prepared by all my predecessors. Professor Abhiram Ranade, Professor Sudarshan, Professor Soni, their lecture slides, their sample programs, their notes, they are all there. In fact, I was under the wrong assumption that you are looking at those, but the quiz performance tells me that you are not. So, therefore, I would strongly suggest you do that. Use additional books to get problems. Now, apparently, if you have not seen resources, you have not seen the online book, a beginner C++. The complete book practically is online. PDF files are online. You can just download this, read it. Arguably, the style of that book is slightly different. It introduces computer hardware, computer operating system, etc., in first five chapters, which is not what we are doing. So, my suggestion is ignore first five chapters. Start reading from the sixth chapter. You still find many useful exercises, useful examples there. Please look at them. If there are differences in style, try to follow the class style. If there are things which are discussed there, which are not discussed in the class, try to apply your mind to see, imagine what they could be, but you can safely ignore them because your understanding of whatever programming is required with the course will not be impeded by it. Last announcement, the mid-semester examination look out for announcement regarding sitting arrangements. Last time when we conducted the quiz, we had a huge hassle with several people coming late, and I had to repeat my announcements, which created a huge difficulty for others. I have already apologized for that, but I don't want to repeat of that performance. So, consequently we have decided that three batches will appear for their quiz in the IRCC building. I see one, two, and three, first, second, and third floor, and I see ground floor will be reserved for late comers. Ideally, nobody should come late, but if anybody comes late, he or she shall not disturb the ongoing exam. They will all go there, and somebody will take care of it. The most important announcement is about course projects. Remember, there is a 30% weightage for the entire course in that project. The course project shall be group projects. Your entire group, which is your tutorial batch, shall be doing one project. This group obviously will be un-building with 20, 22, 25 students, so we shall have teams. Five teams, each team will comprise of three to five students. The norm is four. Sometimes you may have three. If the total number is not divisible by four, sometimes you may have five for the same reason. But ordinarily I would expect a team of four. There should be one person amongst that team who should act as team coordinator, and I shall, after talking to the whole group, I shall allocate a group coordinator on which you will also have a set. Why I am saying this now? The projects will start from Monday immediately after mid-same, and therefore it is vital that you form your teams. The groups are formed by definition, and these groups are, as per the current allocation of lab batches, by the way. So don't go back and say, my roll number is seven, although I come on Tuesday, I would like to go back to that batch, et cetera, et cetera. The reason is simple. There is an occasion every week where your entire group will be together, and you should be able to discuss. So the reason I am making this announcement is, please form such teams and keep the names written up. Please ensure that no student opts for three teams simultaneously, where there will be chaos. We'll stop here, and we'll continue our discussion tomorrow morning. Thank you.