State Machines — Invariants
State machines are abstract models of step-by-step processes.
We can think of a state machine as a binary relation on a set.
In this case, the elements will be called states, the relation will be called transition relation or state graph, and an arrow in the graph will be called a transition.
A transition from state
State machines also have a specific start state.
An example below is one that counts from 0 to 99 and overflows at 100. Not very useful.
Figure 5.7 State transitions for the 99-bounded counter.
From the course notes Mathematics for Computer Science.
State machines that have at most one transition out of each state is called deterministic. One example is the one above that counts from 1 to 99, and overflows after that. The only transition is from
Note: The general model of a state machine is also about responding to the inputs given, but we are not looking at this for simplicity's sake.
When we used induction the last time, we were showing that a property holds in every step of the process.
A property that is preserved through the whole process is called the preserved invariant.
The invariant principle says that:
If a preserved invariant of a state machine is true for the start state, then it is true for all reachable states.
A reachable state is a state that appears in some execution.
And, what is execution?
It's a sequence of states with the property that:
a) it begins with the start state
b) if
Realize that the invariant principle is just induction, applied to state machines.
There is a technique called fast exponentiation. Take a look at this code:
base = int(input('Enter base: '))
exp = int(input('Enter exponent: '))
def fast_exp(x, y, z):
if z < 0: return 'Nonnegative integers only!'
if z == 0: return y
if z % 2 == 0:
return fast_exp(x ** 2, y, z // 2)
if z % 2 == 1:
return fast_exp(x ** 2, x * y, z // 2)
print(fast_exp(base, 1, exp))
Notice that we assume z
(the exponent) to be an integer as we use integer division (z // 2
) like so.
Here, our start state is (base, 1, exp)
.
Transitions will be according to this rule:
And, our preserved invariant is that
One way to verify
Since we're only looking at the case when
In this transition,
In order to write
Doing a little simplifying, we get
So, the new values of
To verify a program, there are two properties to look at: partial correctness and termination.
In the fast exponential example, we've proved the correctness, so let's see if we can figure out if it terminates.
One thing to notice is that at each transition,
A derived variable is a function assigning a "value" to each state.
So, take a derived variable
If the values are natural numbers, it can be said that "