 Okay, welcome to Intro to AI, Constraint Satisfaction Problems with Tokyo EdTech. That is me. Today we're gonna take a look at a simple type of constraint satisfaction problem, a seating chart. So constraint satisfaction problem is a problem where you have lots of different possible solutions to whatever it is and there are constraints, some limitations to which ones are acceptable. So in this case we're looking at a seating chart for three people. We're gonna add a few people later. We have Adrian Blair and Chris and so they are seated at a conference or whatever the occasion might be and we have to figure out which seating arrangements are acceptable to these people and we're gonna add some kind of constraints to limit the seating arrangements that can be possibly acceptable to those people. So you can see here, we've got a seating chart, again, three people, Adrian Blair and Chris and the first constraint is that Adrian cannot sit on the end. So for some reason Adrian does not like to sit on the end of the stage or whatever that thing is. So let's go ahead and solve that simple constraint first. Then we'll add a few other people to the mix and then we'll add a second constraint which is a bit more complicated, okay? So let's say that, well let's think about the problem first. So looking at this particular problem, let's say we have A, B and C, so Adrian, Blair and Chris, that is one possible seating chart. We have Adrian, Chris and Blair and we have B, A, C, then we have B, C and A, we have C, A, B and C, B, A. Okay now, obviously as intelligent human beings, we say, okay, well Adrian can't sit on the end, so I gotta get rid of that. Adrian can't sit on this end, so I gotta get rid of that and Adrian can't sit on the end, I have to get rid of that, okay? So we can obviously do this ourselves because there's only six possibilities but as the number of people increases, the number of seats increase, so do the number of possibilities, they're called permutations. So the number of permutations comes from the number of seats slash number of people, so three times two times one gives us six possibilities. If we increase that to four seats, that would be four times three times two times one, that would give us, so three times two times one gives us six, four times six is 24. If we go to five people now we've got, I think seven hundred, seven hundred and 20, five times two, hundred, 120, sorry, 120. If we go to six seats now we've got 720 and then if we keep going, this seven times seven is 49, so 51, 40, so you can see how the number of possible permutations increases pretty rapidly. So at this point, I don't wanna sit down and figure them all out and do this on paper, so we're gonna figure out how to do this with Python. And Python, of course, makes it very, very simple. Now again, we can't do every type of constraint satisfaction problem this way just because there's too many possibilities. But for a simple problem like this, up to a reasonable number of seats, we can do that. So let's go ahead and figure out how we're gonna do this. So first we're gonna start with what we're given. So we're given three people and I'm gonna make a list, so I'm gonna make it. I'm just gonna use A, B, and C just to make it simple, okay? So we need to find all of the possible seating charts that can be made with this particular combination of people. And to do that, we're gonna use something called iter tools, okay? So iter, I believe it means iterates, iter tools. So I'm gonna go ahead and import that, import iter tools. And the way to do this, it's very, very simple, is we do iter tools dot permutations and it's gonna be people. So let's go ahead and print that and see what happens. So seating charts. See if we get the result that we expected because we know what the result should be because we just calculated it, okay? So you'll see here, it says iter tools permutations object at blah, blah, blah, blah, blah. Okay, so that clearly is not what we expected, but the information we want is inside that object. So an easy way to get to it is to just convert this to a list, okay? By wrapping this in list. Okay, let's go ahead and try that. And now you can see we have a list of tuples and you'll see that there are six and just the way we calculated earlier. Now it might be easier, I find it easier to do this because we're gonna need this later anyway, for seating chart in seating charts. And that is a for each loop. Okay, so we wanna print each seating chart on its own line. Okay, so now this gives us what we had before, what we'd figured out on our own, okay? So now that we've found all of the possible permutations, so we'll say, you know, find all possible permutations. We need to determine which of those permutations is valid. Okay, so what I'm gonna do is I'm gonna create a method, I'm gonna create a function called is valid, go figure. And it's gonna take one seating chart and it's gonna tell us, is that seating chart valid or not? So if it is valid, if valid, return true. So we're gonna go ahead and just, let's just go ahead and return true. So for now, we'll just assume that every single chart is valid and we'll test our code. And what I wanna do here, is I'm gonna go ahead and do if is valid. So if it is, oops, if is valid seating chart, this is why we test. It's really hard to talk in code at the same time, believe it or not. What I wanna do is, I wanna find all valid seating charts. So I'm gonna go ahead and create a new list, empty list called valid seating charts. And then what I'll do is if it's valid, we will say valid seating charts dot append, the current seating chart. And then down here, I'm just gonna copy this in valid seating charts, print seating chart. All right, let's try this. Okay, so let's just make sure it works. Okay, at this point, we should see the exact same thing we saw before, okay? So what this does, let's keep that up there a little bit, is, okay, we start with what we know. We know who's involved in the seating chart and how many we have. We know we're creating a list, an empty list to hold the valid seating charts that's what we wanna find. We find all possible permutations of the seating charts. Okay, we've got a method to check. And then for each seating chart, we're gonna check, is it valid? If it is valid, we're going to append it to the list of valid seating charts. And then we'll just print out the results. So let's go ahead and try our first constraints. This one says constraint. Adring cannot sit on the end, okay? So if we look at our data here, and look at each seating chart, we have a tuple, okay? So remember, each tuple index starts at zero. In this case, one, then two. So Adrien can't sit here and Adrien can't sit here. So what we can do, we cannot sit on the end. So we can say, if seating chart zero equals a, let's just go ahead and do it this way. We'll do it separately. Return false, okay? Also, if seating chart two equals a, remember, we're looking for negative examples here. Return false, okay? So basically it has to get through each of these checks to become valid, okay? So let's go ahead and run it, okay? So you can see here, we've got BAC and CAB. So out of our seating charts, out of our six possible seating charts, it eliminated the four charts where Adrien was either in the zero-width index or index two. So this gives me a lot of confidence that my overall coding structure is correct. I've tested it with something relatively simple, okay? The other thing I wanna do is I wanna go ahead and print out the percentages, okay? So to do that, I'm just gonna say print F, you know, let's say what we call it, it's valid. Let's put a percent sign in there, okay? And what we can do in here is we can say the length of valid seating charts divided by, divided by the length of all seating charts. Let's go ahead and test that. So we got two out of six, so we should see 0.33333, okay? Now I should probably multiply that by a hundred just to, you know, because it does say percent. Let's go ahead and do that so it looks proper. Okay, so we have 33% of those seating charts are valid, okay? So now, let's go ahead and test this. Let's go ahead and add a fourth person. You can come up with a name that you like. Let's go ahead and add a fourth person and see if this code still works, okay? Now those of you that have coded before a little bit more from the coding, you realize this is not going to work correctly. Let's go ahead and run it anyway and see what happens, okay? So it says that 50% of them are valid. Now what we need to do is take a look at some of the so-called valid seating charts. Do you see anything weird here? And hopefully you have a sharp eye. You can see that there is an A here in the last seat. And the reason for that, okay, and pause the video if you wanna think about it, but the reason for that is that now we have four possible seats and the index of the end is now no longer, it's no longer two, it's three. So we would either have to change this, which is inefficient, we don't wanna do that, okay? So what we can do is we can say the length of the seating chart minus one, okay? So the length of this seating chart is four, so one, two, three, four, but the index is three, so it's the length minus one. Okay, so let's go ahead and test that again, okay? Now we still got 50%, but as you can see, there are no A's in the last column or in the first column, okay, so the first spot. So that gives me pretty good confidence that this is working as expected, okay? So that was one of our constraints coded. That's a pretty simple constraint. So the next constraint is also that Adrien and Blair cannot sit next to each other, okay? So Adrien cannot sit on the ends and Adrien cannot sit next to Blair, so clearly Adrien has some problems here. It's very difficult to satisfy. So let's go ahead and add a few more, well actually let's not add, let's do this first. And then let's think about that. Now there's a couple different ways to do this constraint. So let's say Adrien and Blair, Blair cannot sit together. All right, so what we need to do, so let's look at one example where they are next to each other. So we have A and B here are next to each other, but we know we can't have that particular situation, okay? So what we wanna look at here is the index of Adrien and the index of Blair. So to find that we're gonna do index of A for Adrien equals seating chart dot index A. And we also need index B, seating chart dot index B. Now I know a lot of you, especially my students are not gonna wanna type index out, they're just gonna type A and B, but I strongly encourage you to use good full variable names. It will help you when you come back to your code later. So what we could do, okay, one of the things we could do, is we could do something like if let's say seating chart, actually I don't actually need this part yet, we could do something like if seating chart index A plus one equals B, return false. So if the seating chart index A plus one, so in this case the index of A is actually one, one plus one is two. So if that were a B, it would not be valid, okay? And then we could do similar thing if seating chart index A minus one equals B, return false. So in this case A is one, minus one is zero, and that's B, so this would be an invalid seating chart. Let's go ahead and try this, just to see what happens. Oh, forgot the parentheses. Let's try that again, probably you guys noticed that. Okay, so in this case it does appear that it worked properly, okay? So there's no A on the ends, which is what we expected, and A and B are separated in each case. Now this, now you might wanna say okay, I've done it, hey, great, I'm a genius coder, no problem. But there's one little, this is where testing comes in, if you study computer science you'll learn a lot more about that topic. Let's say I remove this constraint, that Adrian cannot sit on the end. Let's go ahead and comment that out. Now I'm gonna go ahead and run this and see what happens, okay? And you'll see here we've got an index error. It says, tuple index out of range, okay? So what's happening is that in a case, let's scroll down here, so let's say we have like, we have B, let's say we have D, C, B, A, okay? The index of A is zero, one, two, three. Three plus one is four and there's nothing here. Okay, so we're trying to access an element that doesn't exist and that gives us an out of range error, okay? So, okay, there's a couple ways we can deal with this. All right, one of them involves index B, which you'll see in a minute. What we could do is we could say, if, you know, seeding chart, sorry, actually so we just say if index A plus one is less than length of seeding chart, we could do E and there as well. And then for this one, oops, if index A minus one is greater than negative one because we want it to be zero or higher, you can use greater than or equal to zero if you prefer. So, we only check this if it's less than length of the seeding chart, oops, minus one. Sorry, that'd be still be off by one. So, it has to be, you know, like say four, three, it has to be, so if it's the last one, oh, this actually, this might be a little bit easier so index A equals length of seeding, you only see how complicated it's getting, right? Minus one, so if it's the last item, it doesn't work. And if index A minus one equals zero, actually, I think I had that backwards anyway. Oops, control Z. All right, it should be greater than zero, sorry about that. So, it has to be greater than zero and this has to be less, so, sorry, if this, ah, it's greater than zero, we can check if this is less than the length of seeding, yeah, it's even confusing me. Let's try that, I think that's right. Let's see, let's see, charts. Yeah, see how we gotta do all kinds of stuff here now. There we go, finally. So this, I think, is good, okay? So you can see A and B are separated, A and B are separated, A and B are separated, A and B. So this, I think, is working properly and that gives us 66%, okay? But you can see how, especially while I was talking and doing this, I got a little confused about the condition under which we would test it, okay? So there is a much, much, much, much, much easier way to do this, okay? So what we can do, if, is it math.ABS? Let's try ABS, see if ABS works. Index A minus index B is not equal to one. I'm sorry, is equal to one. So if the absolute value of index A minus index B equals one, we will return false. And what I mean by that, let me come back down here. Actually just look down here. So the index of A and B, oh, actually it didn't work because that shouldn't have been printed out. So the index of A and B, I'm not redoing the video because this is my third time doing it. So yeah, I'm losing patience for this one. So A minus B, so we've got one minus zero. So if one minus zero equals one, then they are next to each other, okay? So in this case, this is zero and this is two. Zero minus two is negative two. Absolute value of negative two is two. So it doesn't equal one, okay? So that, I think that one is working. I think I can live with that one. So yeah, so in this case, we've got zero, one, two minus three is negative one. So they are next to each other because the absolute value of negative one is one, okay? So let's go ahead and undo that one and do that. Yeah, let's run it and see what happens, okay? So let's see if we have met our constraints. So we have no A's on the end, correct? And A and B are not next to each other, okay? So in that particular case, they're only 16% are valid seeding charts, okay? Let's go ahead and just add a few more people and just see, make sure we are getting about what we expected, let's go ahead and run that. So in this case, 40%. And what we could do is we could add a constraint where they must be together. So let's go ahead and just copy this. Let's go and add a constraint since, you know, if you made this far, you're probably interested in this. So let's go ahead and say that, let's say D and E, whoever they are, D and E must sit together. D and E must sit together. So let's go ahead and do the same thing. So index of D, index of E, D and E. And then D, oops. Okay, so in this case, since D and E must be next to each other, the index of D minus E must be one. So what I can do is I can say if it's not equal to one, so this distance is not one, okay? So in this case, D and E, so in this case, D is zero, one, two, three, five. Three minus five is two. That is not equal to one, so it is false. Let's go ahead and run that again. Okay, now we're down to 10%. Still a lot of possible permutations. Okay, but we can look here. Okay, no A's in the first column. No A's in the last column. Okay, I'm pretty happy with that. We said that Adrian and Blair cannot sit together. So A, B, okay, B, A, B, A. You can kind of go down through. You can see that here's B, there's no A. A, there's no B surrounding it. I think it works pretty, pretty well. And then we can just check one more time and see our D and E together. So D and E together, D and E together, D and E, D and E. Okay, you can kind of go down through. You can kind of see that yes, in every case, D and E are together, which is pretty cool. Okay, so that is that. So I know I got a little mixed up in the code there in the middle, but that is the name of the game, especially when you're talking and coding, excuses, excuses, and then I'll go ahead and put this final constraint in, constraint D and E must sit. Sit next to each other, okay. So just to review real quick, we start with what we're given. Then we create an empty list to contain what we're looking for. We find all possible permutations using iter tools.permutations. And we've created a function that tells us is a particular seeding chart valid or invalid. And what we're looking for is any false. So any violation of the constraints returns false. So once Adrian is on the end, I don't need to check and see about Adrian Blair. I don't need to check and see about D and E, okay. It's just as soon as I find one constraint that is violated, we're done, we return false. If we get through all the constraints, we return true, because then we beat the constraints. So we just iterate through, I'll put that in there. So iterate through, through all seeding charts and check and see if they are valid. If they are valid, add them to our valid seeding charts and then we just printed the results and the percentages. So that is that. Thanks again for watching. And as I like to say, keep on coding.