Now we're going to take a look at the use of generating functions to address the
important tasks that we brought up in the last lecture.
programs many of which can be casts as recursive programs or algorithms
immediately lead to mathematical models of their behavior called recurrence
relations and so we need to be able to solve recurrence relations in order to be
able to analyze algorithms. And so now, I'll take a look at how you
use generating functions to solve recurrence relations.
and it's pretty much a algorithmic process that is we want to we want hate
to use a meat grinder, but it gives the idea.
We want to put in a recurrence relation and we want to turn the crank and we
want to get out a sequence. We want to get out of a simple expression
for what it represents. and it's pretty much a general procedure
that we can always follow. I'll give many examples.
So first thing is we're going to make the recurrence valid for all values of N and
the, it's easy to do that and I'll show you in many, in the examples.
Then, multiply both sides of the recurrence by z to the n and sum on n.
so it's an equation that's valid for all n so that we can do that.
And usually, we make it just for nonnegative n.
then that'll give us some sums but some of those sums will involve the, an, an
unknown generating function and maybe some well-known generating functions.
the end result will be an equation that's the OGF corresponding the recurrence has
to satisfy. so then, what we need to do is to solve
that equation to get an explicit formula for the OGF.
a lot of times we can go ahead and do that and we'll get plenty of examples.
the initial conditions play a role. and then we'll expand the OGF to find the
coefficients. So, the recurrence corresponds to a
sequence. the OGF is a way to represent the
sequence. We'll use the refer, recurrence to find
out what the OGF is and then we'll expand to get the coefficients which is the
goal. That's, that's what we're trying to find.
so let's look at the example. Now, in the case of linear recurrences
with constant coefficients the procedure really is an algorithm.
We always can get a solution and actually people have implemented this in symbolic
mass systems. So so here's an example from the previous
lecture. so that's a recurrence that is defined
for n bigger than 2 with the initial conditions a 0 to 0 and a1 = 1.
so the first thing is make it valid for all n and so it's all n greater equal to
0. And so, all we do is use a kronecker
delta notation. so for one this thing and you assume that
for negative indices of 0. so a0 = 0 so that would be 0, that'd be
0. So for a1, we'd have to add a1, so, when
n is 1 we want to add 1. That's what that kronecker delta is at,
the right there. A0 is expressed then in terms of a's with
negative indices which is 0, so its okay a0 = 0.
So that's how recurrence is valid for all n greater equal 0.
So now, we multiply by z to the n and sum on n.
Sum n greater than equal to 0, A to the n, z to the n.
That's our generating function, A(z), that we're going to use to represent this
sequence a sub n. For the first term on the right-hand side
it's sum an - 1, z to the n. Change n to n1 + 1 throws out A(z).
So that's 5zA(z). And for the second term we change n to n
plus 2 in the, in the sum and throw out Az^2 that's minus 6z^2, a of z.
And the kronecker delta term, that's sum all n but that thing is only
one when n = 1. So, that's z to the n, in that case, is just z.
So that's an equation that generating function has to satisfy.
and that's a, [COUGH] easy equation to solve with some
algebra. so that is, it's just A of z is just z
over 1 minus 1 - 5z + 6z^2. that's again equation that, that generic
function has to satisfy. so, that's generating function, now we
want to extract coefficients because our goal is to find an expression for an.
so how we are going to extract coefficients?
Well, in the case of ratio of two polynomials, it's not difficult it's
technique knows as partial fractions where we factor the polynomial and the
denominator. and we know that our solution must be at
this form, because if you cross multiply then in the denominator, you get the
right polynomial because you've factored it.
And then, the numerator you've got two equations and two unknowns you have to
have c0 + c1 = 0 and you have to have the 2c0 + 3c1 = -1.
So that is, those unknowns have to satisfy those two simultaneous equations
and that's just what we got before and the solution is z0 = 1 and z1 = -1.
and so, that now expresses the generating function as a difference between two
geometric sums and those we know how to expand, it's 3 to the N minus two to the
N. So that's step by step given a recurrence
we can get the solution that is a simple expression for the coefficients and
that's going to work in every case. Now, there's complications that arise.
Let's look at a more complicated example. sometimes and, and this works for
actually any linear recurrence, because you get a polynomial and you can always
factor a polynomial. So, so let's look at this one, 5 an minus
1 minus 8 an-2 plus 4n-3. Same procedure to make these initial
conditions satified. I start at 0 and work up and find that I
have to add a delta n1 and a minus delta n2 in order to make it valid for all
that. Then, when you multiply by z to the n and
sum on end you get this equation on the generating function.
5zA(z) - 8z^2A(z) + 4z^3A(z)3 + z - z^2.2.
And again, now just using algebra, now we have an explicit expression for the
generating function. It's the ratio of two polynomials.
And ratio of two polynomials, partial fractions works, you have multiple terms.
in this case, there's the [COUGH] the root 1/2 has multiplicity 2
and that means just that, that polynomial
is I got three roots and then actually in this case one of the roots cancels with
the numerator so we have A(z) = z / (1-2z)^2 but that's one that we know,
that's a generating function that we already derived by differentiating the
geometrican scaling and that says that a sub n = n2^n-1.
Again, just algebra to find an explicit representation for the generating
function and then expand. now, it turns out that if you have roots
of multiplicity 3, you'll get terms of the form n^22, something to the n and so
forth. and there's other things that can happen,
but it's just properties of polynomials. so, for example, you could get complex
roots. So here's an example where the roots are
complex. Again, this is the same set up we have a third order linear equation
constant coefficients. we've got three initial conditions.
apply, do the deltas to make it valid for all n multiply by z^n n and sum on n and
then do algebra and then that gives a again a ratio of two polynomials.
The degree of the polynomial is equal to the degree of the recurrence.
in this case what happens is there is +z z^2 is one of the roots, one of the
factors of the [COUGH] denominator.
And again the numerator cancels so what do we do with 1 + z^2?
well, we can factor it with complex and find out that A(z) is a half, 1 / 1 - i
of z plus 1 over 1 plus i of z and we can go ahead and expand that and get this
representation. It's i to the n plus minus i to the n or
you can factor out an i to the n. and even though, i appears in this
solution if, when you do the math the
i never appears as a member of the sequence.
because when i is odd this thing cancels and when n is odd, this thing cancels to
0. and when n is even, then you go between 1
and -1 between because of the i^22 or i^4.4.
so that's a rather strange oscillating sequence, but it comes out immediately
from our process of our algorithmic process of finding sequence corresponding
to a given recurrence. It's a nice example, because it shows the
origin of the oscillations that we often see when we're studying algorithms or
combinatorial structure. Those oscillations are modeled in
mathematics really, in this case, by just the square root of -1.
square root of -1^2 is -1, and to the fourth power is +1, and that's
really reflected in this sequence. and it's going to be maybe not so easy to
uncover oscillations without using complex and as we'll see complex analysis
plays a fundamental role in analytic combinatorics when we get into advanced
methods. [COUGH] okay.
So here's a summary. and then, this is just a math with
unknowns just so we can state a theorem. And it's kind of a complicated looking
theorem, but next time we'll show that we don't really need all this detail.
but it's worthwhile to fully state this theorem, because the method that we've
talked about really leads right to a proof of this theorem that's not that
abstract. it's just a matter of turning the crank.
So what we know is that if you've got a [INAUDIBLE] order linear recurrence with
constant coefficients so that you just have [INAUDIBLE] terms on the right-hand
side. It's going to be a linear combination of
t terms. and it depends on the roots of the
polynomial that's induced by what happens when you get, when you multiply by
[INAUDIBLE] and do the algebra. You're always going to get this
polynomial, 1 - x1 minus like that in the
denominator. and it depends on the multiplicity of
those roots so if you've got r roots, where the multiplicity is m sub i.
So if you add up all the multiplicities you get t, then your solution is
depending on the multiplicity it's going to be, for every root you got a the, that
root to a power plus n times that root to a power all the way up to the, the
multiplicity and that has a total of t terms.
and again I'm not expect, not expecting people to follow really every detail of
this, but, you, you can get the idea that we can, actually write down a full
solution to linear recurrence and generating functions give us this proof.
And the constants involved can always be determined from the initial conditions
and that's using partial fractions and solving simultaneous equations.
And again, this is all automatic and people have implemented this process in
symbolic algebra systems. so actually, nowadays you can type in
recurrences and get the solution. and don't forget, your solution might
introduce, might involve periodic behavior that's introduced by the complex
roots, so it might not be the case to prove to be able to prove that even a
recurrence like this converges to a limit.
but it's all very straightforward and well understood mathematically.
Now, what about the analysis of algorithms?
For quicksort, we had this rather complex recurrence that was our starting point
for the analysis of quicksort. Can we use generating functions to solve
the quick sort recurrence? and, and the answer of course is that we
can. to make life easiest, we'll first
multiply both sides by n, although you can get it done without doing that.
so now we have a recurrence where we're not dividing by n and then multiply by Z
to the N, and sum. over now we sum for N bigger than or
equal to 1 and that's just because the CK-1 to
save us a few terms. so that's multiplying by Z to the N and sum and now
we got to look at each one of the terms and see what we have.
what do, what do we have on the left there? well, if we define the generating
function for the sequence of interest to be C of Z equals sum C sub n, Z to the N.
That is if you differentiate that multiplied by Z, that's what you get.
So that one is C prime of Z and there's a factor of Z all the way through that's
divided out. This one is two
[COUGH] 2z over 1-EQ. and again that's right out of the table.
and then a factor of z divides out. And this one is a convolution, it's 1 / 1
- z * z of z. so I, I skipped just a very few steps
here involving indexes that go to 0 and involving dividing by z.
But you can convince yourself quite easily that that ordinary differential
equation is the result of the [COUGH] simply evaluating the sums to get the
equation that the generating function has to satisfy.
So, that's ordinary differential equation and it's completely well, well-defined
and so now we need to know about solving differential equations, to get this
solved, and I don't want to give a course on solving differential equations.
I just point this out as an example for people who do know that
it's possible to solve it just by considering the equation without the
extra term. and figuring out that, what you need to
do is, solve that prob, that problem. in that case, that problem, the solution
is 1 / 1 - z^2.2. so if we didn't have this constant term,
the solution would be 1 / 1 - z^2. [INAUDIBLE] differentiate that, it's the
same thing as if you multiply by one over one - z and multiply by 2.
and then, what you do is multiply, by that, or divide by that factor, which
wides up by multiplying. and it's really, actually analogous, and
it is totally analogous to what we did when solving for sorted linear
reccurences, where we try to find something to multiply it by to make it
that a telescope, this is kind of similar. and this comes out to be a
simple equation in terms of the function, 1 / 1.
z^2, c of z. so if you differentiate that you get this
thing so and that's then equivalent to our equation.
so two that's 2 over 1-z and now, we can just integrate that simple thing if that
shows that c of z times order 1-c squared is equal of n of all of that which is two
log over 1-z and that's a solution. and so that's solving the differential
equation to get an explicit representation for the generating
function. not too bad.
It's a standard differential equation. And now, we want to extract coefficients
to find the number of compares taken by quicksort, but that's easily done. we've
seen that one that's the example that we did for an
exercise. It's 2 N plus 1, H N plus 1 minus 1.
So, OGFs can solve recurrences even as
complicated as the quicksort recurrence. there's many other examples of solutions
of recurrences using OGFs in the book.