We now describe a local search heuristic for the traveling salesman problem. We've already seen the main idea of the local search algorithm, but let me describe it once again. So to solve an optimization problem with a local search heuristic means the following, we usually start with some initial solution s, then we'll repeat the following procedure. For a current solution s, we look into some neighborhood of this solution and we try to find a solution in this neighborhood, if the solution [INAUDIBLE] which is better than the current solution s. If there is some solution such a solution s', and we replace s with s' and repeat this and we stop when s is the best one in its neighborhood. So first of all, the first thing to note is that this algorithm might return a sub optimal solution because the only thing which we can guarantee about the return solution it is that it is the local optimum, not the global optimum. So namely it is optimum in its neighborhood. But also, the quality and the running time of this algorithm depends on how we define the neighborhood actually. For example, we might define the neighborhood of some solution as the search of all possible solutions. Then this algorithm in one iteration will need to go through all possible candidate solutions and to find the best one. So, this is algorithm will be actually the same as the brute force algorithm. How do we define the neighborhood in case of the traveling salesman problem? Well, for this we first need to define a distance between two solutions. We call that, in case of traveling salesman, a candidate solution is a cycle that visits each vertex exactly once. So assume that we have two stage cycles, s and s'. We say that the distance between them is at most d, if we can get s' from s by first deleting the edges, at most, the edges from s, and then adding probably some other d edges to the resulting structure, okay? Then we can define a neighborhood, again, as in the case with algorithm, namely, we define a neighborhood of s with radius r as all the cycles that we can obtain from s by changing it's most r edges. To give you a specific example, consider the following graph containing of eight vertices, and, again, we assume that the vertices here are just points on a plane and the distance between any two vertices is just equal to the distance between the corresponding points on a plane. Assume that our initial solution looks as follows, It is clearly suboptimal but just changing the two edges in this solution makes it optimal. So instead of using these three edges, we use the following two edges. This gives us an optimal solution. Sometimes, however, just changing two edges is not enough to get to improve a solution. For example, consider the following situation. Again, it is not difficult to see that this solution is suboptimal. In particular, it is clear that instead of this vertex from this one, instead of using this path, it would be much better to use this part. However, changing just two edges, by changing just two edges we cannot improve this. So, in this case, to improve the solution to find a better solution in its neighborhood, we need to allow changing three edges in particular instead of this three edges, we want to use the following three edges. Right? So what we can see, there is a trade off between the quality of solution and the running time of a single iteration. Namely, when we increase the size of the bowl, the size of the neighborhood, we increase our chances to find a better solution in a current bowl, but we also need to go over all this solution inside this ball. Right? In any case, it is not excluded, the total no of iteration of your algorithm will be exponentially increase in this case. Even we use it is not excluded that from this solution we go to that, to that, to that, to that, and so on and we always improve it a little bit. And the total number of steps of iterations is exponential. And at the same time, it is not excluded that the quality of the final solution will be poor. But on the other hand, this heuristic usually works well in practice, but it probably with some additional tricks. For example, an obvious additional trick that is reasonable to use is to allow your algorithm to restart. Namely, not to use just one initial solution but to use one solution then do some local search and then to restart from some completely different point and probably to select many such points, probably a trend among other trend, and then return and then the solution which is the best one that you've seen in this process. So to conclude, the role module, let me repeat the main message. When you face an NP-complete problem in practice, don't give up. There are several possibilities. First of all, it is not excluded that all the instances of your NP-complete problem are some special cases for each, there exist an efficient algorithm. Also, it might be the case that you can implement an algorithm which have no theoretical upper bound on its running time. But still, it works well in practice because it intelligently searches for the space of all candidate solutions. And finally, you might want to implement an algorithm, which returns not an optimal solution, but something which is close to an optimal solution. For some applications, it might be good enough.