 So the key to starting algebraic coding theory is to understand how we can take these problems and information in computer science and turn them into algebraic problems. The first step is gonna be the following. If we have m bits of information, and we're gonna read these left to right, so we have the first bit called b1, b2, all the way up to bm. If we have m bits of information, we can identify this sequence with an m tuple. That is, you can identify it with the vector b1, b2, up to bm, where we can visualize this as a vector in the vector space z2m, where I want you to be aware, this is something we'll talk about some future day here. z2 is an example for what we call a field. And you can construct a vector space by taking column vectors whose scalars come from a field. And so z2m is a vector space very much like the vector space rn that you might have seen in a previous linear algebra course. So we're gonna be doing linear algebra on this field. Now this is the field, which only has two elements. It only contains the elements zero and one. But in terms of the field, I want to tell you how the arithmetic is gonna work here. The arithmetic is just gonna work mod two. So thinking of the Cayley tables, when you add these things together, you're gonna take zero, one, zero, one. You get zero, one, one, zero. That's how addition works mod two. In terms of multiplication, similar thing is gonna happen here. Zero times anything is zero, one times one is one. So we're gonna do addition and multiplication mod two. Which to be aware, the only significant difference as opposed to just addition and multiplication of the number zero, one, if we think of them as real numbers, really just comes down to this observation here. When we work mod two, one plus one is zero, not two. Because two doesn't exist. I mean, it does, it's just two is zero when you work mod two. So we can do linear algebra over this arithmetic field right here. That is, we just change the arithmetic from real numbers to mod two. And all of the stuff from linear algebra will apply. We can add some column vectors. We can scale them. We can multiply them by matrices. We can compute null spaces. The idea keeps on going there. So I'm gonna make a lot of connections to linear algebra as we go through this. So with that connection to linear algebra, let's define what we mean by a code block. An N by M code block, which we're gonna call it C, or I should say block code, excuse me. An N by M block code C. This is gonna be a subset of the vector space Z two N. So notice the connection here that the first bit of the first number there, the N, that is gonna be the dimension of this vector space Z two N. This is gonna be paired. This is gonna be a pair of two functions. There's the first function, which we call the encoding function. So what this is gonna do, it's gonna take a vector from Z two M. Notice this is the second number here. It's gonna take a vector from Z two M and it will identify it with a vector in Z two N, okay? And in practice here, M will be less than or equal to N. So we are basically gonna be adding more bits to the original message. So the original message is gonna correspond to M like we talked about before. The encoding process is we're gonna take an M bit message and turn it into an N bit message. The reason why we do that will become more clear in the future. So there's two functions. There's the encoding function, but there's also the decoding function, which is a map from Z two N to Z two M. And you wanna think of these things essentially as inverses of each other, right? So when you take the composite of D and E right here, so if you encode your message and then you subsequently decode the message, this will be the identity function on Z two M. So if you encode then decode a message, you're gonna get back the original message, okay? And then the other thing that I want you to be aware here is that when you take the image of Z two M under the encoding map, this is equal to the set C. So that's what we mean by this block code right here. The code is the set of vectors in Z two N that correspond to these original vectors from Z two M. The elements of C are called the code words. So C is gonna be a set of code words. And so the set is called a code or we can call it an NM block code to be more specific on the parameters there. But C is the code and the elements of it are the code words. So I wanna show you this diagram here. Let me zoom out a little bit to illustrate the basic idea behind this encoding process. So there's gonna be over here some message that we need to send from one part of the computer to a different part of the computer. We're gonna call that original message W, for a word. There's a word using only the alphabet zero and one that one computer part needs to tell another computer part. So this, it's gonna be a message, a word of length M. So it's in Z two M. And so before we send it, we're gonna encode it. So it goes through this encoding process. So we'll encode it. And so the word W turns into E of W, which this is a code word C, which belongs to the vector space Z two N. So we've added, we've added N minus M many bits to the message. Well, it's a little bit more sophisticated than that, but we're gonna associate a code word to the original message W. And the reason why we associate a code word to W, why don't we just send W itself? It's because of our channel right here. As we transmit the message from the sender to the receiver, we anticipate that this function T, it's kind of like a random function. It'll randomly change the number because it's random, it's not truly a function because the same input could actually have different outputs. But nonetheless, the transmitter will randomly change parts of the code word. And so then the transmitted code word is what is gonna be received T of C. Now, in general, we don't anticipate that C will equal T of C. We often anticipate there could be an error of some kind. If it were equal, that would be great. So the transmitted code word is gonna come over and then it has to be decoded right here. Why is there nothing there to decode it? We need to be decoding D of T of C. So that's what needs to happen. And so then what you see is the following idea. What we want is the following. We want that if you do the encoding process, then the transmission process, then the decoding process, we want this to be the identity on Z2M, okay? But the big problem really comes down to T right here. T is kind of random. And so it will not be possible to be for this to be perfect, perhaps, because T itself is not a function. And so T of C is determined by chance, not by input. It's, I mean, it's affected by input, but it's not determined by input alone. Therefore, it's not truly a function. And so the composition of these three relationships might not be the identity function. And so what we want to then introduce is the idea of an error detecting code. So is it possible that the decoding map D, also equipped with E, is it possible that we can detect when E composed with T, composed with D is not the identity? Can we just recognize when that happens? And the thing is I should mention is we have to do this on the tail end. The receiver doesn't know what the original message is, but is there a way to decode the original message so that we can detect that we don't have the right message, even if we don't know what the message is? That sounds like a very difficult problem, but turns out we will have a very nice solution to that. And even better, is it possible that we can choose the function D so that even though you have this random process, T in the middle, that the composition of these things is still the identity? That is, can we correct the codes? And so our goal in this unit is to use group theory to develop error detecting and error correcting codes. So a K error detecting code is a code that can detect up to K many errors in transmission, accurately. And an L error correcting code is a code that can correctly fix up to L mistakes in transmission. So you don't actually have to ask for a retransmission. And we're gonna see how that works in this unit here. I wanna give you two examples of very simple codes to kind of show you how this could be possible. And then we will improve upon these in future lectures. So the first one I wanna mention, it's actually a very famous code. It's the ASCII code. That's an abbreviation, acronym for American Standard Code for Information Interchange. The ASCII code is actually an eight, seven block code. So what that means is we are gonna encode seven bits of information using eight bits. So we have to add an extra bit of information in order to encode our message. So the significance of course of this is, is that two to the eighth is actually 256. And why that matters is that 256, that's how many, that's 16 squared. It's 16 squared. And so ASCII, the ASCII code here is basically just two hexadecimals. So hexadecimals is a number system where you can take zero, one, two, up to nine. And then you take letters A, B, C, you know, up to F. Should be F, right? I have to count these out loud now. A, B, C, D, E, F, yep, that's 16. So you write a hexadecimal, something like, oh, the number 20A. That would be acceptable right there. And so 20A, what that means is you're gonna take two times 16 plus A, which A here would be 11. So we can convert this to the usual number system. And we could go from there. The exact details don't matter, but that's why 256 is the magic number right here. That's a two-digit hexadecimal number. Okay, so we're gonna use two-digit hexadecimals to encode 128 characters. Now, the ASCII code is gonna do all of your standard letters, so like A, B, C, D, uppercase, lowercase. It gets most of the special keyboard characters, plus maybe a few others. So we don't need to go into all the detail of that, but we have seven-bit messages, and we're gonna encode them with an extra bit. How are we gonna do that? Now, to give you a little bit of idea of what's gonna happen here, so if you just take the alphabetic letters A, B, C, this is capital A, B, C, the ASCII code identifies A with the number 65, B is 66, and C is 67. So we can think of those in hexadecimals. I'm not gonna bother with that. We're gonna put this as the binary expansion. So this is something we did earlier when we talked about the repeated squares algorithm in this course. So 65 can be written in the binary as 1-0-0-0-0-1. The idea is 65, of course, is 64 plus one. 64 is two to the eighth. One is two to the zero-eth. So you get something like that. And so you get these seven bits. This can kind of be hard to read sometimes, so something you'll often see is we sometimes will put artificial spaces just to make it a little bit easier to see. So we are overpatting the message. So 100 and then 001. We might say something like that. The human eye can kind of identify up to, basically you can count up to five instantaneously. Beyond that, it gets kind of difficult to count in your head. That's when you pull out your fingers and toes and such. So we often will pad long sequences, long binary sequences into groups of four, three, five, kind of the biggest, because that gets really difficult to recognize six or bigger with just the naked eye. So you might see me putting spaces in there. It's kind of the same reason why we often write a million, right? Why do we put commas in there? That's because if we put them into periods of three, it's much easier to read the number that way. We'll often do the same thing with the binaries, although I won't be putting commas. And so the associated ASCII code for the code word for A is gonna be this one right here, 01000001, okay? We do the same thing for B. B had the decimal number 66, which a binary expansion, you get this one right here, for which we're gonna write the following right here. So you get 010000010, okay? And as a hexadecimal, this would be what we call 41, 42, 43. Now be aware that 42 here means four times 16 plus two, okay? And this is four times 16 plus three. So it's not really 42, 43, but in hexadecimals, that's what we're doing right now. And so basically what happened, as you'll notice here, is that we're adding an extra number, we're adding an extra number to the front, right? So A, we added the number zero in front. B, we glued the number zero in front. And for C, we glued the number one in front. I'll explain in a moment why we chose those numbers in just a second. So if this is a block code, an eight, seven block code, the encoding process will send a seven-bit word into an eight-bit code word, okay? And so what we're gonna do is the following, you have your seven bits. The last seven bits are just gonna be the original bits. So B1, B2, B3, up to B7 will go unfazed. This is actually evidence that this encoding map is going to be a one-to-one, which in order for DTE to be the identity, this does have to be, the encoding map does have to be one-to-one, okay? So we're gonna see that. So the last seven bits are the exact same. The first bit is actually gonna be the sum of the seven bits we're transmitting, mod two. And so this is often what one calls as like a check bit right here, this first information, that's a check bit, while these last ones right here are sometimes called information bits. So the last seven bits actually have the information we want to transmit, but we're adding an extra bit to transmission for checking. I'll show you why in a second while we do that. The decoding process is then pretty simple. If you have an eight-bit message, then to create the original message, you just used to raise the first bit. So you take the last seven bits and that'll be then the code, or that was the word. That's how we decode it. But in decoding also has to have built into it some idea of error detection or error correction. And so what we can see here is gonna be the ASCII code is actually an error detecting code. It's a one, it's gonna be one error detecting. And so how do we do that as the following? So we have this parity check bit. Like I said, it's the sum of all the bits. So imagine, imagine we have the following. Let's take, what do I wanna say here? So okay, so if we have a message that we wanna transmit, so let's make it simple, we'll take one, one, one, one. I don't actually know what that is off the top of my head, but let's say that's the one we want. This is our original word. So to encode this E of w is gonna equal, well the sum of seven, that's gonna be one, so you're gonna get one, one, one, one, one. That's what we're gonna send. And then it's gonna be sent to the other part of the computer. But let's say there was an error in transmission. So what's received, so this is our code word, right? So what's received is TFC, which turns out to be one, one, zero, one, one, one. So maybe that was the error. It was in that third bit right here. Well, what's gonna happen is our decoder is gonna do the following. It's like, okay, I know that this first bit, the one, is gonna be the sum of the other seven bits. And so if I take one plus zero plus one, that's a zero. And then if you take one plus one, plus one, plus one, that's gonna be four, which is also zero, zero, plus zero, zero. So, oh, so the check bit, this should be a zero, but it actually is a one. They don't match up, that's weird. That actually means error, error, error. Our computer recognizes an error occurred. And therefore it detects the error and then it'll request a retransmission. Great, so it detected the error using the check bit. But it's only a one error detection level, because what if there were two errors, right? Let's say that instead our word TFC turned out to be one, one, zero, zero, one, one, one. In this situation, we'll see that when you add up the bits, you're gonna get five, which is one mod two. And in this situation, you're like, oh, the check bit should be one, so we're good to go. Because there were too many errors, it actually couldn't detect it. It's kind of like that situation when your mom tells you two rights don't make a wrong. Well, actually in this situation, two wrongs are detected as being right. What did I say about the mom said two rights don't make a wrong? I don't know if your mom said that. She probably said two wrongs don't make a right. That makes more sense. And that's what I was trying to go with here. In this situation, actually, two wrongs do make a right in terms of the parity check. And so the computer in this situation would think the message was transmitted correctly, but in fact, it wasn't. And so it's just a one detection there. Let's do one more example before we sign off on this lecture right here. So this is an example of an error correcting code. Actually, an error correcting code. And this is gonna be called the triple repetition code. So what we're gonna do is you can take a message of any length. So we're gonna take an M bit message. We're gonna send S or Z to M to Z to three M. That's where the triple repetition comes into play. So we're gonna take the message B1 up to BM. And what we're gonna do is we're gonna repeat it three times. So it's kind of like night lock, night lock, night lock. We just have to say it three times and that's then how we transmit the message. How do you decode the process? Well, if you receive the triple repetition, just take the first time you heard it. Oh, she said night lock. Okay, I heard that. And so that's how you decode it. But the decoding process also has error checking and error correcting built into it. And so we're gonna basically play minority report for a little bit. So the idea is we have our three precogs right here, which are gonna give us a vision of the future, right? And so the first two, let's say, are in agreement. But then the third one disagrees with it, right? So this is our minority report right now. And so, okay, if there's a disagreement, if there was an error, then it turns out that the more popular choice was probably the right choice. This was the correct choice right here. And so then we can get rid of this one right here. On the other hand, let's say that the second one disagreed from the first and second, or the first and third one then, then we'd be like, oh, okay, I see that there was an error in the second transmission. So we'll take the first one, something like that. So we can then, we can't just, we don't just detect the error, we can also correct the error because we have all this into extra information. Now this is a very simple one error correcting code. So we can accurately correct up to one error with this code. But the problem is that is a lot of extra information. We have to slow down the transmission of information by a factor of three, which is extremely slow. And so do we want to retard transmission that much just to gain one level of error correction? Well, it turns out we can do much better with this in group theory, but I just wanted to kind of explain to us why we're interested in this idea of error detecting and error correction and how one actually might be able to do that using tools from group theory and linear algebra.