Each child has a countdown of the number of times it tosses balloons. Each time a child tosses a balloon it decrements its countdown value. After a child's countdown reaches 0 the child pops balloons that it receives (and doesn't toss popped balloons).
Initial State: Channel (X, Y) has one balloon and channel (Y, X) has
one balloon. And the countdown for X is 2 and the countdown for Y is
3. We represent this state by:
nX = 1, nY = 2, (X, Y) = 1, (Y, X) = 1
The sequence of steps from the initial state are as follows.
Event: X receives a balloon for the first time
This event is specified by the 4-tuple:The execution of this event causes a transition from the initial state to a state shown in the following diagram:
Some states (e.g. State 2) in the first example of a computation don't occur in the second example, and vice versa.
Number of balloons is at most 2
which is equivalent to: (X, Y) + (Y, X) <= 2
(Here we are abusing notation using (X, Y) for a channel and also for the state of the channel.)
Initially: (X, Y) = 1
and (Y, X) = 1
So, the predicate holds initially.
A state transition in which a balloon is returned does not change the value
of (X, Y) + (Y, X)
.
A state transition in which a balloon is popped decreases (X, Y)
+ (Y, X)
.
Therefore if the predicate holds before a state transition then it holds after the transition.
((X, Y) + (Y, X) = 2) or (nX = 0) or (nY = 0)
To prove that this predicate is an invariant we prove that (1) it holds initially and (2) and for all state transitions, if the invariant holds in the state before the transition then it holds in the state after the transition.
Initially, (X, Y) = 1
and (Y, X) = 1
.
Therefore the predicate holds initially.
Let S be the state before a transition to a state S'. We will prove that if the predicate holds in S then the predicate holds in S'.
Consider two cases:
Because nX and nY do not increase, and nX and nY do not become negative, in the execution of an event, it follows that nX = 0 or nY = 0 in S'. Therefore the predicate holds in S'.
Because the invariant holds in S it follows that (X, Y) + (Y,
X) = 2
in S.
Because nY > 0 the execution of an event in which Y receives a
balloon leaves (X, Y) + (Y, X)
unchanged.
Because nX > 0 the execution of an event in which X receives a
balloon leaves (X, Y) + (Y, X)
unchanged.
Therefore (X, Y) + (Y, X) = 2
in S'.
So, the predicate holds in S'.
nX + nY + (X, Y) + (Y, X)
The loop variant is a function of the state (i.e. variables) of the system. In this example, the loop variant maps states of the program to integers.
We must show that (1) the loop variant is bounded below and we can carry out induction on the values of the loop variant, i.e., it can decrease only a finite number of times before it reaches a lower bound, and (2) the executions of all steps in all computations that start at initial states reduce the value of the loop variant. The specific lower bound is irrelevant for the proof of termination.
In this example, 0 is (obviously) a lower bound. Next we show that the execution of any event in any state reduces the value of the loop variant.
When Y receives a balloon if nY is positive then nY decreases which the loop variant, and if nY is 0 then (X, Y) which decreases the loop variant.
Similarly every event in which X receives a balloon also reduces the loop variant. Thus the executions of all events reduce the loop variant.
Therefore the algorithm terminates execution.
At termination all channels are empty. Let's prove that nX or nY is 0 at termination.
From the invariants if:
(X, Y) + (Y, X)
\(\neq\) 2 then nX
or nY is 0.
At termination, (X, Y) + (Y, X)
\(=\) 0, and the result follows.
while
loops, by using invariants and loop variants.
gcd(x, y) = gcd(X, Y)
.
x, y = X, Y while x != y: # assertion: gcd(x, y) = gcd(X, Y) if x > y: x = x - y else: y = y - x
Inv
is shown
as an assertion in the body of the loop.
while there exists a nonempty input channel in the system: # assertion: Inv select a nonempty channel (u, v) in the system let the head of channel (u, v) be msg v executes receive(msg, u)
n
, which is initialized
as a positive integer.
Let GCD be the gcd (greatest commond divisor) of the
initial values of X.n
of all agents X.n
.
The following distributed algorithm terminates and at termination
X.n = GCD
for all agents X.n
.
In the code, successors
is the list of successor agents
in a network of agents, and the agent only sends messages to its
successors.
def receive(message, sender): if n != message: n = gcd(n, message) for successor in successors: send(n, successor)An invariant of the distributed algorithm is as follows. The gcd of:
X.n
for all agents X
Proof
The proof that the assertion holds initially is trivial. Prove that if the assertion holds before any event then it continues to hold after the event.
Let the event be agent A
receiving a message
m
.
After the event, m
is no longer in the channel;
n = gcd(n, m)
; and messages with the new value of
n
are in the output channels from A
.
The proof that the assertion continues to hold in the post-event state
is straightforward.
(X, Y)
in the network:
(X, Y)
is empty and X.n
is a
multiple of Y.n
, or
(X, Y)
is m
where m = X.n
.
Proof
The assertion holds initially because the second condition holds. Prove that if the assertion holds before any event then it continues to hold after the event.
When agent X
executes a receive that changes
X.n
the agent sends a message m
to
Y
where m = X.n
, and so the second condition
holds.
When agent Y
receives m
the agent sets
Y.n = gcd(Y.n, m)
, and so m
is a multiple of
the new value of Y.n
.
If channel (X, Y)
remains nonempty then the second
condition holds.
If (X, Y)
becomes empty then the first condition holds
because m = X.n
and m
is a multiple of
Y.n
.
x, y = X, Y while x != y: # assertion: gcd(x, y) = gcd(X, Y) if x > y: x = x - y else: y = y - x
f(x, y) = x + y
is an example of a loop variant for the
following reasons.
f
is a function of the state of the program.
f
has integer values.
f
is bounded below. The bound is 2 because x
and y
are bounded below because of the invariants
x
\(\geq\) 1, and y
\(\geq\) 1.
The precise bounds don't matter.
f
.
f
because f
has integer values and is bounded below.
We are given a strongly connected network of agents -- i.e.,
there is a path from each agent to every other agent.
Each agent has a local variable n
, which is initialized
as a positive integer.
Let GCD be the gcd (greatest commond divisor) of the
initial values of X.n
of all agents X.n
.
In the code, successors
is the list of successor agents
in a network of agents, and the agent only sends messages to its
successors.
def receive(message, sender): if n != message): n = gcd(n, message) for successor in successors: send(n, successor)
f
be the tuple (N, M)
where
N
is the sum of X.n
for all agents
X
, and M
is the total number of messages in
channels.
Comparisons of tuples are made lexicographically. For example (2, 1) > (1, 10), and (2, 1) < (2, 2).
f
is bounded below by (0, 0).
An induction can be carried out on a tuple of integers.
Next we show that the execution of each event reduces f
.
When an agent X
receives a message m
,
X.n
\(\neq\) m
then X.n
becomes gcd(X.n, m)
, and so the new value of
X.n
is less than its previous value, and so execution
of the event decreases N
which decreases f
.
X.n
\(=\) m
then the event removes
message m
from a channel and does not add messages to
channels. So the event decreases M
which decreases
f
.
x, y = X, Y while x != y: # assertion: gcd(x, y) = gcd(X, Y) if x > y: x = x - y else: y = y - xThe while loop terminates when
x = y
.
From the invariant, at termination:
gcd(x, y) = gcd(x, x) = x = gcd(X, Y)Therefore
x
and y
are gcd(X, Y)
at termination of the while loop.
receive
of each agent is as follows?
def receive(message, sender): if n != message: n = gcd(n, message) for successor in successors: send(n, successor)At termination all channels are empty. From the invariant, if channel (X, Y) is empty then X.n is a multiple of Y.n.
Therefore when all channels are empty, for every channel (X, Y) in the
system X.n is a multiple of Y.n.
Because the directed graph of agents and edges specified as
successors
of agents is strongly
connected:
for all agents X, Y in the system: X.n is a multiple of Y.n
Therefore X.n = Y.n for all agents X, Y. From the invariant, X.n is GCD.
The next webpage discusses data flow in computations.
K. Mani Chandy, Emeritus Simon Ramo Professor, California Institute of Technology