One recursion, run from rest and then with numbers stored. Watch the stored values add a second term on top of the input’s part, which does not move.
Stored values add their own term
y[n] = y[n−1] − 0.5y[n−2] + x[n], with a step x[n] = u[n] switched on at n = 0.
From rest, y[−1] = y[−2] = 0: only the input acts. The output climbs to 2.5, rings, and settles at 2.
Describe this picture
The recursion , with a step switched on at . One panel, with sample from −2 to 14 against , and a key row naming the marks. A large open square, “stored”, shows and at and . From , the zero-input part is a stem with an open-circle head, the zero-state part a bare stem stacked on top of it, and the total a diamond. A dashed line at 2 is labelled “final value 2”. Three readouts follow the picture: , on its own row, then and .
The clip plays for 13 seconds and has no control until it ends; each caption appears while its frame holds, and between holds the caption area is blank. The first frame has both stored values at 0 (readouts 0, 0, then 1.00 and 2.00): “From rest, y[−1] = y[−2] = 0: only the input acts. The output climbs to 2.5, rings, and settles at 2.” Then eases up to 2 (2, 0, then 3.00 and 3.00): “Store y[−1] = 2: the zero-input part starts at 2 and rings away to 0, with the same poles. It adds on top of the input’s part.” Then eases up to 2 as well (2, 2, then 2.00 and 2.00): “Store 2 in both: the zero-input part exactly cancels the climb, and the total is 2 from the start. The stored values were already the final value.”
When the clip ends, dragging a stored square up or down, or the arrow keys, set each stored value from −1 to 3, and Tab moves between the two. The hint says “Drag a stored value up or down, or use the arrow keys (−1 to 3).” With and the caption says “y[−1] = 1.0, y[−2] = 0.0: the zero-input part starts at 1.00; the total starts at 2.00.”
Starting a recursion at n = 0
On Difference equations (6.1) you ran a recursion with a number already sitting in its delay box. You split the result into the zero-input response, made by the stored value alone, and the zero-state response, made by the input alone. There you did the algebra by hand. This page puts both through one transform.
The bilateral transform of The z-transform (16.1) adds up a signal over every . A recursion switched on at does not fit that. The equation holds from onward, and before that I only know the stored numbers, and . They are the past, not part of the equation.
So I use the unilateral transform, which sums from only:
It is the same letter as before, and this page says “unilateral” when it matters. For a signal that is zero before the two transforms are the same function.
What changes is the delay rule. Take and split off its first term, at , which is . The rest is times the transform of . Doing the same for gives two terms before the pattern starts:
The extra terms are the samples that slide in from before . This is the same job that did in Properties and the inverse Laplace transform (9.2): the stored values enter the algebra through the delay rule.
Now apply it to with a step input, , switched on at . Transform every term and collect the terms on the left:
Write . Dividing by shows that has two parts. The input’s part is , which is the zero-state response . The stored values’ part is , which is the zero-input response . The total is , as on page 6.1.
Both parts share the denominator , so both are made by the same poles. They are the roots of , which are . Each has radius 0.7071 and angle (45°), which is 8 samples per cycle.
SciPy turns stored values into the state that lfilter starts from: zi = lfiltic(b, a, [y[-1], y[-2]]), then lfilter(b, a, x, zi=zi). I use it below to check every number.
Stored values add their own term
The picture at the top of this page runs this recursion. From rest, with , only the input acts: the output climbs to 2.5, rings, and settles at 2. The zero-state samples are 1, 2, 2.5, 2.5, 2.25, 2, 1.875, 1.875, 1.9375, 2 for to .
Store , and a zero-input part starts at 2 and rings away to 0, with the same poles, on top of the input’s part. The total starts at 3 and 3. The input’s part did not change; a second term came in.
Store 2 in both, and the zero-input part exactly cancels the climb: the total is 2 from the start. The stored values were already the final value.
When the clip ends, drag the stored squares to set the stored values yourself. Try doubling both stored values: the zero-input stems double, and the zero-state stems stay where they were.
What the algebra predicts
Each frame follows from the algebra above. With and , the stored values’ part of is
Its samples are 2, 1, 0, −0.5, −0.5, −0.25, 0, 0.125 for to . The inverse transform of 16.2 gives a closed form, with the weight 1 at each of the two poles:
At it gives , as the stems show.
The zero-state part is . Partial fractions (16.2) give three terms. One is at the step’s pole, 1. The other two are a pair at that dies away:
The weight 2 is the final value, and the dashed line in the instrument. Written in real terms, . The total for is 3, 3, 2.5, 2, 1.75, 1.75 for to .
The last frame can be solved exactly. With , the stored values’ numerator is . The input’s term is . Adding them and using gives
That is for every . You can check it without a transform: if every value is 2, the equation reads . The two stored values were already the output the equation settles at.
Switched on: a part that dies, a part that stays
The second split is about where the poles come from. For a system and an input with transform , the output is from rest. Its partial fractions have terms at the poles of and terms at the poles of .
Take a sine switched on at , . Its transform has poles on the unit circle, at and . The terms at those poles make the steady state, . It is the sine that Frequency response of discrete-time systems (12.4) taught you to expect: the same frequency, scaled by and shifted by , both read at :
The terms at the poles of make the transient, . For a stable system those poles are inside the unit circle (Stability and causality, 16.4), so this part dies away. The output is the sum, .
The system here has one pole: , so . Its gain at is 1. The transient is . The output starts from rest, so , and the constant must cancel the steady state at : .
Watch the transient’s open circles shrink by 0.8 each sample, until only the steady sine is left.
Switched on: a part that dies, a part that stays
y[n] = 0.8y[n−1] + 0.2x[n], from rest, with x[n] = sin(0.25πn) switched on at n = 0.
At n = 0 the input is 0, and so is the output: the steady sine would be −0.222 there, so the transient starts at +0.222 to cancel it.
Describe this picture
The system , from rest, with switched on at . Two panels share the axis sample , from 0 to 30. The short upper panel is the input , as stems with dot heads. The lower panel is the output : at each the steady state is a stem with a square head, the transient a stem with an open-circle head, and the total a diamond on , labelled “steady state”, “transient” and “total y[n]”. The readouts are the sample , then the transient and the steady state at that .
The whole input shows from the start, and the output is drawn in over 14 seconds. At (readouts 0, 0.222, −0.222): “At n = 0 the input is 0, and so is the output: the steady sine would be −0.222 there, so the transient starts at +0.222 to cancel it.” At (6, 0.058, −0.171): “n = 6: the transient has shrunk to 0.058, by 0.8 each sample; the total is mostly the steady sine.” At (15, 0.008, −0.278): “n = 15: the transient is 0.008. What is left is 0.280 sin(0.25πn − 52.5°): 12.4’s gain and phase for this test.” At the end (30, 0.000, −0.171): “By n = 30 the transient is gone. The system’s pole made the part that dies; the input’s poles made the part that stays.”
When the clip ends, a slider named “Input frequency Ω₁” chooses from to in steps of ; its hint says “Drag across the output, or use the arrow keys, to choose the input’s frequency.” The readouts then follow a cursor fixed at . At the caption says “Ω₁ = 0.10π: the steady sine has size 0.581 and phase −45.9°; the transient starts at 0.418.”
At the input is 0, and so is the output. The steady sine would be there, so the transient starts at to cancel it.
By the transient has shrunk to 0.058, by 0.8 each sample, and the total is mostly the steady sine.
By the transient is 0.008. What is left is , 12.4’s gain and phase for this test. Here and rad, which is −52.5°.
By the transient is gone. The system’s pole made the part that dies; the input’s poles made the part that stays. The transient first falls below 0.01 at : it is 0.0122 at and 0.0098 at .
When the clip ends, drag across the output to choose yourself, from to . At the steady sine has size 0.581 and phase −45.9°, and the transient starts at 0.418.
Try and then . The transient still shrinks by 0.8 each sample, since that is the pole’s doing, but its starting size changes. At it starts at 0.008, and at at 0.419. The start is set by the phase: a steady sine with phase near zero already starts near 0, so little needs cancelling.
I chose a sine so that the transient is big enough to see. A switched-on cosine at gives instead, because the output starts at 0.2 and the steady cosine starts near 0.171.
What the split tells you
A stable system’s transient dies away, because its poles are inside the circle. What remains is the steady state, and the steady state is all that a measurement of and ever sees. Frequency response of discrete-time systems (12.4) said “after the sine has played for a long time”. This is what that phrase meant.
The same split gives a rule for a step input. A step has one pole, at 1, so the steady part is a constant. Its size is , and for a stable
For the system of the first instrument, , the dashed line. For the system of the second, .
The maths behind it · the initial state vector
The stored values form the initial state vector , and the zero-input response is . It is linear in , so doubling both stored values doubles the zero-input part. That is what the first instrument’s ease shows.
The maths behind it · autoregressive forecasting
Forecasting with an autoregressive model is the zero-input response: set the stored values to the last observations, switch the noise off, and run the recursion. The forecast decays toward the mean at the rate of the model’s poles.
Worked example
Take the first system, , with and .
- Stored values’ numerator. . In SciPy,
lfiltic([1], [1, -1, 0.5], [1, 0])returnszi = [1, -0.5]. - Zero-input part. This is half of the case, by linearity: 1, 0.5, 0, −0.25, −0.25, −0.125, 0, 0.0625 for to .
- Zero-state part. The same as before: 1, 2, 2.5, 2.5, 2.25, 2.
- Total. Add them: 2, 2.5, 2.5, 2.25, 2, 1.875 for to .
Iterate the equation directly as a check. . . . . These match the total.
For the second system, find the steady state at by hand. . Since , the denominator is , with magnitude 0.7132 and angle rad. So and rad .
The transient size is . At the transient is and the steady state is , so . The output to from lfilter is 0.141, 0.313, 0.392, 0.314.
Where you’ll meet this
Every streaming filter carries its stored values from one block to the next. The code calls them the filter’s state, and lfilter_zi and zi are how SciPy sets them up. Real-time processing (21.4) picks this up. The transient is also what you hear and see when a notch or a resonator is switched on, which Resonators, notches and combs (17.4) returns to.
Reference card
| Quantity | Formula | Notes |
|---|---|---|
| Unilateral transform | for signals and recursions started at 0 | |
| Delay by one | the stored value slides in | |
| Delay by two | ||
| Total response | stored values; input from rest (6.1) | |
| Transient and steady state | the system’s poles; the input’s poles | |
| Steady state of a sine | at (12.4) | |
| Final value (stable, step in) | ||
| SciPy | zi = lfiltic(b, a, [y[-1], y[-2]]), then lfilter(b, a, x, zi=zi) |