So the plan for this video is to develop a greedy algorithm that always minimizes
the waited sum of completion times of a given set of in jobs.
But more than the specific problem, more than the specific algorithm I want you to
focus on the process by which we arrive. At this greedy algorithm.
because I think this process is really something which you can use yourself, in
your own applications. The process we're going to use is we're
going to first look at just a special case in the problem, where it's
reasonably intuitive what should be the optimal thing to do.
Looking at these special cases will then motivate a couple of natural greedy
algorithms. Then, we'll figure out how to narrow a
couple of greedy algorithms down to just a single candidate, and that in fact, as
we will prove in the following lectures, will always be correct.
So let's just briefly recall what is it we're trying to do.
The computational problem and instant to specify by end jobs which come along with
waits and links, and among all end factorial ways that we can sequence the
jobs, we want to somehow home in on the one that minimizes the sum of waited
completion times. Recall from the previous video that the
completion time of a job is just the amount of time that elapses before it's
done. So that's going to be the length of all
the previous jobs plus the length of job J itself.
What we're hoping is going to work out is that we can devise a greedy algorithm
that always solves this problem. So maybe I should take a step back and
ask, you know why do greedy algorithms seem like a sensible way to approach this
scheduling problem? Well, you know.
In general, greedy algorithms are not guaranteed to work.
You may have to do something more complicated.
But scheduling still seems like a good place to try them out.
Remember what a greedy algorithm does, it iteratively makes myopic decisions.
An then you hope you have a, a reasonably good result at the end.
Now, what are we doing? We're studying a sequencing problem.
The definition of the problem is to schedule a job then another job then
another job all the way up to the last job and so this iterative nature of the
solution suggests that at least if you're lucky if the problem is simple enough
maybe there's a greedy algorithm which simply schedules the jobs in the correct
order one at a time. So, we're going to see if that works for
minimizing the sum of waited completion times.
So let's start by thinking positive, being optimistic.
So let's pause it that the greedy algorithm does exist for this problem.
Given that we're in the greedy algortihm section of the course you're, probably
you'll going to find this hard to believe.
But suppose one existed, how would we discover what it is?
Well a useful technique not just for this problem but, you know more generally in
real life, first focus on some special cases of the problem, where it's
relatively clear how you should proceed. And the two special cases I want you to
think about for this problem are first of all, suppose I told you all of the jobs
had exactly the same length but they had different weights, then, what order do
you think it makes sense to schedule the jobs in?
Secondly, suppose that I told you, that all of the jobs had exactly the same
weight, but they had different lengths. Then, what order do you think you should
schedule the jobs in? So first if all the jobs have the same
length, you should prefer jobs with larger weights.
Certainely, eh, this intuitively jives with our semantics of weights, that says
more importance, which suggest that higher weight jobs should go first, if
you look at the actual formula of minimizing the sum of weight and
completion times, if the jobs all have the same length.
Then the completion times are going to be the same your going to see the same set
of them. If all the jobs have length one, then the
completion times of the jobs are going to be one, two, three, four all the way up
to N. No matter what sequence you use.
So to make this as small as possible, you want the highest waits to be associated
with the smallest completion times that is, you want them upfront as early as
possible. The second special case where jobs have
equal waits but varying lengths, I think is a little more subtle.
Here what you want to do is you always want to favor small jobs, jobs with the
smallest lengths, everything else being equal.
The reason for that is that scheduling a job at a given position forces all the
other jobs to wait for that job to complete.
So all the, so whatever job you schedule first has a negative impact on all of the
rest of the N minus one jobs. So I'll.
Things being equal, you want the smallest job there that minimizes the consequences
for the jobs that are to follow. If you find this a little unintuitive, I
suggest just looking at a very simple example.
Two jobs. Both have weight one, one has length one,
one has length two. If you schedule the small job first
you'll have completion times of one and three for a total of four but if you
schedule the bigger job first you get completion times of two and three for the
bigger sum of completion times of five. So the next step is to move beyond
special cases, which we understand well. To the general case, which perhaps we
don't understand. So suppose all of the weights are
different, and all of the lengths are different.
Well, if we have two jobs, and both of these rules of thumb give us the same
advice, we're good. If there's one job which is both higher
weight, and smaller than another job, then clearly that job should go first.
But what if our two rules of thumb to prefer high weight jobs and to prefer
small jobs, give us conflicting advice. What if we have a pair of jobs, where one
of them is on the one hand higher weight, higher priority but on the other hand,
bigger than the other one. Which one should go first?
Well let's again stay positive, and let's try to think about the simplest kind of
algorithm that could conceivably work. It won't be a guarantee that it works,
but it might work. So we have these two different
parameters, length and weights. Maybe we can aggregate these two
parameters into a single one, into a single sort of score for each of the jobs
so that if we schedule the jobs from high score to low score, we'll always be
optimal. That would be great.
If we could compile these two numbers into one for each job, and then just sort
and be done. There is of course the question of
exactly how do we choose this aggregation function.
How do we compile length and weight into a single number.
Well as guidelines we should recall our special case and make sure we respect our
two rules of thumb. So all else being equal we should prefer
jobs with higher weight. So that says higher weight should meet
the higher scores if we're going to schedule the job from high score to low
score. And then also if a length is bigger that
should decrease the score. We should prefer jobs that have a small
length. So this idea leaves open the question of
exactly how do we aggregate the length and the weight of a job into a single
number. So what I want you to do now is I want
you to think for a minute about what kind of simplest possible functions you could
use. So again, these are mathematical
functions. They take as input two numbers, a length
and a weight of a job, and they output a single number, a score.
And the function should have the properties that it's increasing in the
job's weight, and it's decreasing in the job's length.
So there's more than one answer to this question but just sort of dream some sort
of ideas of what this function might look like.
Alright so there is certainly any number of functions that have these properties,
but I'm just going to write down for concreteness two of what I think are of
the simplest functions that have these properties.
So one is going to be based on taking the difference of the two numbers and one is
going to be based on taking the ratio of the two numbers.
So if you're going to use a function based on the difference, then you're want
to be increasing in the way of decreasing the length.
Then of course, the obvious difference to use is weight minus length, this can be
negative sometimes but that doesn't bother us the algorithm is still well
defined. And if you're going to use a ratio and
you want it to be increasing in weight, decreasing in length, then the sensible
ratio to use is, the weight of a job, divided by the length of a job.
It is of course possible that you have ties for either one of these scoring
functions, so let's just allow ties to be broken arbitrarely.
Now, what we're seeing here is a concrete instantiation of something I promised you
in our high level discussion of greedy algorithms, namely, it's both a strength
and a weakness of them that they're really easy to come up with and propose.
So here we have just, you know, this one simple problem, and we now have two
different, competing greedy algorithms for the problem.
Now, because these two algorithms don't do the same thing.
Only one of them, at most, can be always correct.
At least one of them has to be wrong sometimes.
So, as the algorithm designer, what the process now is.
Maybe we can rule out at least one of these two proposed greedy algorithms, by
showing an example where it doesn't do the right thing.
So I want to emphasize this is the type of scenario that's very likely to arise
in your own algorithm designed adventures.
You might have some problem. You're not sure how to solve it yet.
You've brainstormed up a couple of proposed algorithms.
And a good thing to do, a good time saver is too quickly rule out some of those
algorithms as not the right way to go as a poor approach to the problem.
So in this context we have these two greedy algorithms.
Let's quickly break one of them. Show that's it's not always correct.
How do we do that? Well, a smart way to go would be to come
up with an input where the two algorithms do different things.
If they do different things, at most one of them is going to be correct.
At least one of them is going to be incorrect so that's the plan.
Now to execute this goal, as usual we want to keep things as simple as possible
but no simpler. So, what's the simplest possible instance
that could lead to different behavior by two algorithms?
Well, obviously one job is not enough because there's only one possible
feasible solution. But already with two jobs we might be
able to have one algorithm flip them one way and the other algorithm schedule them
in the opposite order. In fact it is not difficult to come up
with an instance with two jobs where they do different things.
let me just go ahead and write such an instance down for you now.
So suppose I give you two jobs, the first one is both longer and more important
than the other one, specifically, its length is five, its weight is three.
The second job, its length is merely two but its weight is merely one.
So what I want you to do is I want you to take our two proposed greedy algorithms,
the first one which orders by difference, the second one which orders by ratio.
I want you to execute them on this 2-job input and compute the sum of weighted
completion times. And then answer what is the sum of
weighted completion times of the corresponding two schedules.
Alright, so the correct answer, is answer B.
Let's just briefly go through why. So first let's just make sure we
understand which algorithm produces which schedule.
So the first job has the better ratio. It's ratio is five 3rds, where as the
ratio of the second job is one-half which is smaller.
Where as the second job has the larger difference, it has a difference of -1
where as the first job has the more negative difference of -2/ So, the first
algorithm which orders by difference will schedule the second job first then the
first job. The second algorithm will schedule the
first job first and then the second one. So it just remains to compute the
objective function value of those two schedules.
So for the first schedule, with the second job first, while we're, the second
job has waits of one, has a completion time of two.
The second job has a weight of three and a completion time of seven.
So that gives us a total of 23. Whereas the schedule produced by the
second algorithm we have the weight three job first.
It's completion time, now that it's first, is only five and then the second
job with weight one get the completion time of seven for a total of 22.
So ordering by difference gives us a value of 23.
Ordering by ratio gives a value of 22. So in this case the ratio does better
than the difference. So certainly the difference is not
optimal for this specific example. So what have we accomplished?
Well, what we've done is we very quickly ruled out one of our natural proposed
greedy algorithms. We know that ordering by difference is
not always correct. Again, it's going to be correct in
special cases like when all the lengths are equal, where all weights are equal
but it is not correct in general. That said, please remember the warning I
gave you in the high level discussion of greedy algorithms which is greedy
algorithms are very often wrong. Just because we know algorithm number one
is incorrect sometimes does not at all imply that algorithm number two is
guaranteed to be correct. It's really easy to come up with multiple
incorrect greedy algorithms for the same problem.
It does, however, turn out. In this case for this greedy algorithm,
algorithm number two driven by ratio it is happily always correct.
But you certainly shouldn't believe this claim until I provide you with a proof.
A rigorous argument explaining the correctness.
Always maintain healthy skepticism about the performance of a greedy algorithm
until you learn otherwise. So, this fulfills another promise I gave
you in the high-level discussion of greedy algorithms.
Namely, when they're correct it's often quite difficult to prove it.
So this would be the topic of the next couple videos the correctness proof for
this greedy heuristic. The third and final thing we discussed
about greedy algorithms typically is that their running time is not difficult to
analyze. So that's a break that we catch relative
to divide and conquer algorithms, and again that's certainly true here,
right? So, what does this algorithm do? All it does is compute these ratios and
then sort the jobs by ratio, so essentially the algorithm reduces to a
single sorting computation and of course from part one, we know very well, how to
sort in N log N time.