 Today we're going to talk about how to actually try to find short or close vectors in a lattice even if we won't get the actual shortest or closest. Alright, well that's hopefully warming up again. Two quick announcements. Some people asked if I could post the PDF for the slides, so that just got done. And it wasn't really feasible to do them one at a time. So all five lectures are up there now. If you want to read ahead you'll, I mean spoilers, up to you. The other thing is, especially after going to Drew's talk yesterday, I should have included this as a problem, I didn't, so it's not an extra problem. We're going to talk about the LLL algorithm today. And one thing you can do is try implementing it yourself. You'll learn a lot doing that, even if it's not the most efficient version. The other thing you can do is every computer package that Drew mentioned has the L-Cubed algorithm built into it. So learn how to access it, try throwing in vectors, see what kind of vectors come out, experiment. Throw the vectors in in different orders, see if it makes a difference. Okay, lots of different sorts of things you can do. As I hope you've all learned by now, a lot of mathematics in some sense is like kindergarten. You have a bunch of toys and you play with them and see what comes out. Look for patterns, that's sort of the, I mean eventually you want to prove theorems, or at least I like to prove theorems, but very seldom do I get there without a lot of examples. Okay, so today's going to be fairly complicated and I apologize, but the algorithms have been complicated. This will be more complicated than the other three lectures, okay? So if this seems a bit much, don't worry about it. Just try to get an overall impression. Then you can look at it more during the problem session. And you're not irretrievably lost for the other three lectures, even if you don't understand any of this. But it's really important and useful stuff, so okay. So just to remind you from yesterday, the two important lattice problems that we're going to be looking at are the shortest vector problem, trying to find the shortest non-zero vector in a lattice. And the closest vector problem where I hand you a target and you try to find the closest lattice point to that target. They're closely related, usually, I guess if you have a CVP algorithm, you can use it to create an SVP algorithm. If you have an SVP algorithm, you can use it to create something that generally will solve a CVP in just with a slight dimension shift. They're both known to be hard problems in general. So we don't expect to be able to solve them exactly, but as I said, we often want to solve them approximately. So I'll introduce some notation for that. We'll say that the kappa shortest vector problem or kappa approximates the shortest vector problem is not to find the shortest vector, but to find a vector that's no more than kappa longer than the shortest vector, okay? And you can probably guess what the kappa approximate closest vector problem is. Same thing. You want to find not necessarily the closest lattice point, but something that's no more than off by a factor of kappa. The idea is that kappa shouldn't be too large. Usually, kappa will depend on the dimension in some way. Ideally, it would be a small polynomial in the dimension, maybe like the square root of the dimension. Practically, it's often exponential in the dimension. So our goal is to solve these problems. The best methods that are currently known are, we'll trace back to an algorithm called the LLL algorithm, which is due to Lenshtra-Lenshtra-Argin-Lenshtra-Hendricks here and is giving lectures next week. So if you really want details of how this thing works, he's the expert, not me. But anyway, it appeared in the early 1980s. Again, you can ask Hendrick for the history, but I don't think the idea was to create this general purpose computer algebra algorithm that would have an immense number of uses. They were trying to find an algorithm to factor polynomials in polynomial time, which it can be used for, so they developed this algorithm. It finds moderately short vectors, or if you sort of shift a little bit, moderately close vectors, in polynomial time in the dimension. And as we'll see, if the dimension's n, it takes roughly time that's proportional to n squared. Not that bad, right? I mean, dimension 100, that's 10,000, computers are fast. The problem is it doesn't solve the shortest vector problem really tightly. The factor you're off by is, well, in the worst cases, is exponential in n. Roughly 2 to the n over 2. It does tend to do better than this in practice. So this is one of the things to experiment with. It's really fun. Feed in some vectors and see, especially if you know what the shortest vector is. You can compare how well L cubed does. So finding very short or very close vectors where the factor you're off by is polynomial in the dimension rather than exponential still seems, well, these algorithms take exponential time. I want to stress every time I say, the best we can do, this is the best we know how to do. Tomorrow someone might invent a faster algorithm. But hard to plan for sort of breakthroughs like that. So another property of L cubed is that it's quite sequential. So I mean, I don't know how much people know about factorization algorithms. But sieve methods, you can basically, you have this huge number you want to factor. You can send it to 100,000 different computers and they can chunk away, chunk away on their own and then send data back. L cubed doesn't really work like that. It can be parallelized to some extent, but you can't have it running on 100,000 different computers that aren't communicating with each other and really get very far, as far as I know. Okay, so great. L cubed is practical. It runs in polynomial time. It gives you a fairly short factor that's off by something that, well, the dimensions big, it's not that great, but okay. So people have tried to improve it and there have been lots and lots of different methods that have kind of fancy names, deep insertion, early, not early exit, but something like that. Early abort, I think. Anyway, later I'm going to show you the L cubed algorithm exactly. I'm not going to describe these improvements, but I want to give you an idea of how they work, okay? These are things you probably don't want to program yourself, because you wouldn't program them efficiently. People have spent years making efficient implementations of these, but it's good to know what's under the hood, even if you couldn't build your own engine. So the one that sort of, well, because it's used a lot, it's called this block, Corkin-Zolotarov reduction, abbreviated BKZ. So two people, one block. And again, I haven't described L cubed to you. I will in a few minutes, but roughly speaking, L cubed tends to work on two vectors at a time. It'll take two vectors, and if it can't really improve them, but one of them's, but the angle between them isn't reasonably big, it'll kind of swap the two vectors. So in some sense, it's working with two-dimensional subspaces at a time, and then it swaps them around and goes down and goes up, as you'll see. BKZ, instead of working with two-dimensional subspaces, works with higher-dimensional subspaces. People usually use beta for the dimension of the subspace. So it will take a subspace, say, of ten dimensions, and in that ten-dimensional subspace of the lattice, it will literally find a really, really good basis for that little sublattice. And then if that's good, great. If it's not, it might swap that entire ten-dimensional, so those ten basis vectors for ten other basis vectors. So you're swapping more vectors at a time, and again, up and down. The bigger you make beta, the better your output. So why not make beta as big as possible, which would be n, the dimension? Well, the answer is the bigger beta is the longer the running time. It's always a trade-off. So, as I said here, the advantage, you increase beta, you get a better output, but it takes longer. If you take beta equals n, then the output is what's called a complete BKZ reduced basis. The first vector in a BKZ reduced basis is the shortest vector in that lattice. So if you take beta equals n, you've solved SVP, but of course you'll take exponential time. All right, so later we'll create crypto systems based on lattice problems, solving CVP. And to analyze the security of such a system, you have to know, well, how long will it take to actually find a close enough vector to break the system if you don't know it ahead of time, right, if you don't know the secret? So you need to know how fast L cubed runs. Well, I just told you pretty fast. But L cubed by itself doesn't usually return a good enough vector. So you use BKZ, the BKZ variant of L cubed, and you start increasing the block size, and eventually you'll get a block size where you will break the crypto system. And the question is then, how long does it take to run BKZ using that block size? And there are all sorts of estimates in the literature, some based on theory, some based on experiment, various formulas. This is actually just a, well, yeah, the actual formula is a little more complicated than this. So anyway, so this is, all right, this isn't the running time. I'll get to that in a second. This is how good the output is. So lambda 1 of L is the length of the shortest vector. If you can find a vector of that length you've solved SVP, the factor you're off by, well, you can see there's a, as you increase the block size, I mean, whoops, this works better if it's turned on. If you increase the block size, I mean there's this beta here that's increasing, but you've got a 1 over beta in the exponent, and we, as we try to convince our calculus students, right, X to the 1 over X power, that's one of those indeterminate forms. If X goes to infinity, it goes to 1. So if you take beta big enough, you'll get very close to the shortest vector. Roughly speaking, you can see up here you're going to need beta to be at least some fraction of n, but then it's going to take a long time to run, if you want to get it, anyway. So the running time cost, this is how good your output is. This is how long it takes to run, okay? And that's not so great if you take beta to be like half the dimension, then it's already exponential in n. So all these trade-offs. So experimentally, for a fixed small constant, if you want to solve SVP to a polynomial approximation factor, then it's going to take time that's exponential in n. That seems to be what happens. And again, this is fun to experiment with. I'm not sure these computer algebra systems that Drew was mentioning have BKZ built into them. I must admit I've never checked. They all have L cubed, the basic L cubed algorithm. You might check. Perry definitely does not, because that's the one I use mostly, but I don't know about Sage and Magma. Anyway, okay. So here's your problem. I've given you n vectors that are a basis for lattice, and you want to start playing with them to find a new basis that's better, in particular with a short vector or so all of them are somewhat orthogonal. So let me give you an easier problem. So first or second-year undergrad problem. If I give you these n vectors, convert them into a basis for Rn that's orthogonal. You don't have to stay in the lattice anymore. You can use real coefficients, real linear things. And of course that's the algorithm that we teach all the students. This doesn't work. It's Gram-Schmidt. Now, usually Gram-Schmidt, when it's presented, you end up showing the students how to find an orthonormal basis, which means the vectors have length one. I do not want to do that. I don't want the length one part, okay? But if you just do Gram-Schmidt ignoring, dividing every vector by its length, you get this. And it's important to understand Gram-Schmidt, so I'm going to review it for you, because in some sense L cubed is just Gram-Schmidt except you're not allowed to use arbitrary linear combinations. Okay. So how do you do Gram-Schmidt? You take the first vector in your lattice v1, and you'll just make that the first vector in your new basis, v1 star. How do I create my second vector? Well, I take the first vector and I subtract off a multiple... I'm sorry, I take the second vector in my list and I subtract off a multiple of the first vector. And this multiple looks complicated, but you probably recognize what I've done here is I've subtracted off the part of v2 that's pointing in the v1 direction. So what's left over is the part of v2 that's perpendicular to v1. And you can check that this v2 star is perpendicular to v1 star. And then so on, for v3 I subtract off the part that's in the plane that v1 and v2 span and what's left is perpendicular to that plane, so it's perpendicular to v1 and v2. Okay. And of course Gram-Schmidt's really fast. Right? I mean, I've written it mathematically. It's probably even faster ways to implement it. But it's certainly taking no more than n squared iterations. Right? Roughly. A bunch of dot products. So, good. Okay. Now, suppose I try to do the same thing, but I want to stay in the lattice. The problem is all these pesky denominators. Actually, let's suppose that our vectors have integer coefficients. Okay? So, yeah. So these denominators mean that I've taken the vector in the lattice and subtracted off a rational multiple of the vector in the lattice. I'm not in the lattice anymore. So the best I could do is take this scalar and round it to the nearest integer. And then maybe, I'm not going to get something orthogonal, but maybe I'll get something more orthogonal, more quasi-orthogonal. And that's the idea. Okay. So the intuition, as I mentioned, the vi star is you take the span of the previous vectors, look at its orthogonal complement and project vi into that orthogonal complement so you get something perpendicular. And that's the intuition behind Gram-Schmidt. You should be able to start with the intuition and come up, you know, right down the algorithm. All right. So now let's try to do the same thing with lattices. And a lesson that you've probably learned, although I always forget it, and I start trying to do the most general case of a theorem in nowhere and then realize it would start with, you know, a special case, do a special case. So let's look at two-dimensional lattices. And lattice reduction for two-dimensional lattices goes all the way back to Gauss. So let's start with a lattice span by v1 and v2. And what I'm going to do is I'd like the first vector in my list to be the shorter vector. So if it's not, I'll simply swap the two vectors. Then I'm going to let m be that factor, the Gram-Schmidt factor, that if I subtracted, you know, that multiple would get me something perpendicular. Unfortunately, this m is not an integer, normally. But I'll ignore this step for a second. What I'll do is I'll round it to the nearest integer. So people are familiar with this notation, maybe. It's kind of like floor-on-ceiling. It was rounded to the closest integer, which will be no more than one-half away from your real number. And this will replace v2 by something that's more orthogonal than it had been to v1, unless this rounded m is zero, in which case I haven't changed anything. And in that case, there's no improvement possible, and I'll just output v1 and v2. Okay? So this just repeats what I just said. If you remove the closest integer sign, you actually get an orthogonal basis, but it's not in the lattice, so we're doing as well as we can. A theorem that I'm not going to prove, but it's fun for you to try to prove, is that this actually, the v1 you get actually will be the shortest nonzero vector in the lattice. In two dimensions, this works perfectly, and it's really fast. And the angle between the two vectors will be pretty big. You can't get perpendicular necessarily, but you can at least get between, with 60 degrees, 120 degrees. And that's the best you can do, by the way. If you take a lattice that you take e1 and you take a unit vector that's 60 degrees from that, you can't do better. You can't improve that. Okay? And here's a little picture where this v2 star, I didn't round the m, and you see I get something that's actually perpendicular to v1. When I round the m, I get something that's not quite perpendicular, but it's a lot better than the perpendicularity that I started with. So, hopefully the picture helps there. And this just repeats everything that I just said. Okay, question? Do I actually use the shortest vector problem in one dimension? I do have a lattice of all the integers on the real line. You're finding the... Yeah, in some sense we do it inductively. In one dimension, this rounding for nearest integer is doing a one-dimensional thing. Yeah, that's a nice way to think about it. Okay. So, suppose we want to do this in higher dimensions. I don't know if you can visualize that Graham-Schmidt algorithm again that I had up earlier. You're taking the new vector that you're trying to modify, and you're subtracting off multiples of the previous vectors that you got. And this quantity here, but without the absolute value sign, is the quantity, is the scalar you're putting in front? So, if it's bigger than a half in magnitude, then when you round it to nearest integer, you get something non-zero, and things will get better. If it's smaller than a half, when you round it to nearest integer, it rounds to zero, so there's no change. Okay? So, what you do is you just keep basically doing the Graham-Schmidt process with rounding until it doesn't help anymore. Okay? And at that point, all of the vectors, so the VI's are the vectors you started with.