 Welcome back to our lecture series, Math 1030, Contemporary Mathematics for Students at Southern Utah University. As usual, I'll be your professor today, Dr. Andrew Missildine. In Lesson 12, we are going to conclude our unit on scheduling. So how we've been able to use digraphs to help us schedule events and tasks that take place inside of a project. Now, I'll remind you that in Lesson 11, we learned about the decreasing time algorithm. That is, we prioritize tasks based upon their priority times. And because after all, if we have a priority list, then we know how to build a schedule for the project. We've done a lot of practice about that now. So our goal is to find a good priority list for the events for the task. Decreasing time does well, but it turns out we can dramatically improve upon the decreasing time algorithm. The problem with the decreasing time algorithm is that we prioritize lengthy tasks, even if they're really not that important. So over the course of these last four lessons, we've been focusing on this Martian home project. We're trying to build a house on Mars. And one of the tasks, FW6, was given a high priority, even though it wasn't carried out until really the end of the project. And that's because it really didn't proceed any other task, but was preceded by many, many tasks. Conversely, not conversely, but in addition to that, look at our second processor, P2. P2 was often idling in the example we did with the decreasing time algorithm because it was waiting for tasks to come ready. Instead of prioritizing length, while this was a lengthy task, it shouldn't been as prioritized as it was because instead of length, instead of priority time, we should be prioritizing precedence. And that leads to the notion of critical time. We've talked about critical time before, but let's define it properly here. The critical time of a task is the length of the longest path on the project digraph from X to N. So as you search for the path from X to N, what's the longest path you could find? That path would be called the critical path. The length of that path is the critical time of that task, all right? And so the critical time is basically measuring from the start of task X, what is the shortest possible time it could take to finish the project from this moment. And it turns out the shortest possible time to finish the project from when you begin task X is this critical time. It's the longest path that's remaining towards the end there. And this critical time is related to the priority time because the critical time will be at least as big as the priority time, but oftentimes it'll be much bigger. Now, we're in the habit when we write a task on a digraph. We write it, we give the name of the of the vertex like X or something. Then you put a number next to it in parentheses that represents its priority time. How long does it take a processor to execute the task? We're going to put next to the parenthesis a bracket, a square bracket. So we might write something like X, parentheses, N, bracket T. That bracket is going to represent the critical time of our task there. What's the critical time? That is what's the longest path from X to T. Because like I said, the importance of critical time is that once you start beginning X, the very fastest you can finish the project at that moment is exactly its critical time. Now, the project might take longer than the critical time to finish from that task. It's just that's the thing is the critical time measures the bare minimum time it takes to finish the project from when we start executing this task. And that's only if you have no shortage of processors. If there's not enough processors, then maybe you have to wait to do certain tasks, but that's the bare minimum there. So we can actually talk about the whole project's critical time. We've used this language before here. In every digraph, there's this start and end vertex. They themselves have zero processing time, but while zero end will always have zero critical time because there's no the path from end to end is nothing. The start, on the other hand, will have a significant critical time. And so the critical time of the start node, we also call the critical time of the project. And likewise, the critical path of the start node will consider that the critical path of the project itself. Because after all, the critical time of start is a task will measure from when start begins, how long at a minimum will take the finished task to end, which is the whole project. That's the critical time of the project. And so that's how we use that term previously. So now we've introduced critical time to each individual task. Now, okay, so to find the critical time, we have to find the length of the critical path. How do we find the critical path? Because the critical path is the longest path from X to end. And that sounds a little bit fishy, right? How do we find the longest path? Because finding longest path is typically impossible on an undirected graph. Since a path can wind its way around a graph infinitely often, right? So if you have some type of like graph, you want to go from this vertex to this vertex to this vertex to this vertex to this vertex, something like this. So here's like A and here's B. You want to go from A to B. Well, if you use like Dijkstra's algorithm, you work backwards. Well, I mean, Dijkstra's algorithm will find the shortest path. If you're trying to like reverse Dijkstra's algorithm to find the longest path, you might get stuck in some type of loop. Ooh, loop-de-loop-de-loop-de-loop. You could say just going on that merry-go-round forever, ever, never. So the paths can get arbitrarily large, and therefore there is no like longest path necessarily. Now, the good news is in a digraph, such a thing is not possible because each of these edges is directed. If I try to follow this loop here, I can't go this way because up I'm going the wrong direction, right? If I'm trying to go against the flow, then I'd have to do something like that. So you get a long, you get a long path like that. You get a long path like that. You can't just go on and on and on and on. This is the beauty of a project digraph because the precedence relations are transitive. There are no cycles. You know, there's no cycles in America. It's like the, it's like, you know, Fifel from American Tail there. There's no cycles on a project digraph. And therefore you can't get an infinite loop with regard to longest path. So it turns out on a project digraph, there is, in fact, a largest path between any two vertices. And so we want to find it. And it turns out the way we're going to find it, well, it's called the backflow algorithm, which you can now see on the screen. But I want you to know that the backflow algorithm is really just Dijkstra's algorithm that we've learned before. But instead of trying to minimize the path, we now try to maximize the path. And in fact, what we're going to do is we're going to look for the critical path for the project. We want to look at what's the path from start to end. And as we do that, we are going to gather the critical times of each and every vertex along the way. So remember, how does Dijkstra's algorithm work? If you want to go from start to end, you start and move backwards. So we look for the critical time of end, which as this is the very last task and then it has no processing time, the critical time for end is going to be zero. And that becomes the current node that we're looking at right now. Then, step two here, you move to a node which is incidence to the current node when you're done looking at it, right? You move on to the next one here. So an end is done. You're going to look at the next vertex there. If the critical times for all nodes incidence from the current node are known, we're going to add the largest critical time among these nodes to the process and time of the current node. This is the critical time for the current node. Step four, if there is a node incident from the current node whose critical time is unknown, you're going to move the current node to this node and repeat the previous step. Step five, this is one we see all the time. We're going to repeat the previous two steps until the critical time of start is known. So you go through that algorithm really fast. Sometimes it's like, whoa, what just happened here? We got to work through an example. But the beauty here, I want you to be aware is this is just Dijkstra's algorithm. The backflow algorithm is just Dijkstra's algorithm with the small change. But we're looking for longest path instead of shortest path for which that makes sense on a project digraph. So if you make that slight modification, we're trying to make long paths and not short paths. That's how we do it. So with Dijkstra's algorithm, we cut out possibilities because we're looking for the shortest path. So if things start to get too long, then we don't care about it anymore. With the backflow algorithm, we don't cut those out. We actually look at all the possibilities because we're looking for the longest path. So let's take a look at our Martian home project. We've seen this digraph before. What I want to do is to go through this digraph and compute all of the critical times using the backflow algorithm, which is just Dijkstra's algorithm. Just so you pay attention there. So we want to figure out what's the longest path from start to end, but we do this backwards. It's actually built into the name here, the backflow algorithm. It's backflow because you're working backwards. You're going against all of the arrows as you go through this path here. So starting at the end, we have the critical time of end. That is just going to be zero itself. That's an easy way to initialize. The end vertex gets just a zero. Now we look at all of the neighbors to the end. That is, we're looking for all those vertices that flow into the end. There's going to be FW6. There's going to be PW3 and there's going to be EU2. Now, as since these are all immediate ending vertices, that is, they're immediately next to the end. The shortest path from them to the end is just going to be the edge you have right there. So this one's going to get a six. This one's going to get a three. And this one's going to get a two. So now let's pick another vertex here. So let's take, for example, IC1. IC1, the only way to get to the end is to go through FW6. So since the processing time of IC is one and FW's critical time was six, we're going to add those together. One plus six gives you seven. And that will become the critical time for IC. Now, if I look at FW, excuse me, HU, where FW is over here. If I look at HU, in terms of the backflow algorithm, I can't consider HU until all of its successors have their critical times of calculated, which now that IC is taken care of, I can do exactly that. And so I'm just kind of like working backwards to the graph, kind of going up and down, which with HU here, this edge, sorry, this processing time is going to take four. So look at the possible paths. So you have four plus seven, which is 11. You get four plus three, which is seven. And you get four plus two, which is six. We take the largest one. So the largest path is going to be the critical path. That's going to be for HU. It's that one there. Four plus seven is 11, like I said. So we're going to put 11 right here. Come, let's look at PU3. PU, honestly, the only path to the end is this one right here. So you get three plus two, which is five. That's its critical time, like so. Let's come up to PL. PL4, it flows into IC. And then from there, it has to go there. So we're going to just take four plus seven, which is also going to give us an 11, like so. Looking at IP4, its successors, HU and PU are now taking care of. So we can then look at the critical times there. You have 11 plus four. That's going to give you 15 versus four plus five, which gives you nine. So we have to take the bigger one there. So the critical time is going to be four plus 11, which is 15. Make that recording there. So then we can move on to ID. ID has a processing time of five. The only thing it proceeds is PU, whose critical time is five. So we take five plus five, which is 10. Our ID has a critical time of 10 now. Let's see, looking at IF. I actually can't do IF yet, because IF, it proceeds PL, but also proceeds IW. We don't have the critical time for IW yet. But it turns out I can do IW now. IW proceeds IP and ID. ID has a critical time of 10. IP has a critical time of 15. That's the more demanding one. So we're going to take seven plus 15, which gives us 22. It's a little crowded here. So I'm going to squeeze it in right there. Once I take care of IW, then I can do IF, because you have to have all the successors' critical time calculated before you can do the next one. So IF, you have 11 versus 22. 22 is the longer path there. So you're going to take 22 plus five, which gives you 27. That becomes the critical time of IF, like so. So then what do we have here? AP proceeds only IF. The critical time for IF is 27. So we can take seven plus 27, which is 34, like so. IF proceeds IF. So that will be five plus 27, which gives us 32. AW proceeds IW. So we're going to take six plus 22, which gives us 28. And then next one here, AW, which has a processing time of eight. It only proceeds IW, which had a critical time of 10. So we take eight plus 10, which gives us 18, like so. And so then the last vertex to consider is START itself, for which we look at all the things that proceed. So proceeds 34, 32, 28, 18. So the highest critical time there was 34. You're going to take zero plus 34. And this now gives us the critical time for the project. This project will take 34 Martian days to complete at the minimum. That's again, if we have enough processors here. That's the critical time for this project. What's the critical path? Well, if we are keeping track of it along the way, then we could just tell what it is. But let's say we forgot it because our project's too big. Well, we can actually reconstruct the critical path by just starting at the START, like here. And then we just go to the vertex, which has the highest critical time that's adjacent to our current vertex. So from START, we're going to go to AP because it has a critical time of 34. Then from there, we're going to go towards IF, which has a critical time of 27. Then from there, we're going to go from IF to IW, which has a critical time of 22. Then from IW, we go to IP, which has a critical time of 15. Then from IP, we go to HU as a critical time of 11. Then from HU, we go to IC, which has a critical time of 7. Then from IC to FW, which has a critical time of 6. And then from FW, we go to the end. And that's going to give us the longest path on this digraph and therefore is the critical path. And once we have the critical path, we know all of the critical times. And so what we're then going to do is once we've have these critical times, we know really who is the highest priority at this moment. So notice tasks like IW have a really high priority because it actually has a high critical time as opposed to like, if you're looking at like IF, like let's say you've now accomplished IF. Who's next important after IF? IF has two successors, IW and PL. Well, since PL has a much lower critical time, we probably don't want to do that one. And that's what's going to lead to the critical time algorithm which we see in the very next video.