Notation: lambda is the empty signal, Lambda is the tuple of empty signals, and <= is the prefix order.
Remark 1: The parallel/sequential/feedback composition of continuous functions is continuous.
Remark 2: A continuous function is monotonic.
Principle of the fix-point theorems: When looking for the behavior of a system, we are interested in the smallest behavior.
Example: The identity function I is continuous. What's the behavior of a system made of I with a feedback arc from its output to its input? There are an infinite number of behaviors: any signal is a behavior of this system. But the empty signal lambda is the smallest.
Fix-point theorem I: A continuous function F has a least fix-point which is the lub of the sequence s1 = F(Lambda), s2 = F(s1), s3 = F(s2) . . .
Example: For the identity system: I(lambda) = lambda so the sequence obtained is the infinite sequence made of lambda. The lub of this sequence is lambda so the behavior of the system is lambda.
Example: The head function H(v) adds the value
v at the head of its input: H(v)(s) =
[v].s. Consider the system made of H(v)
with a feedback arc from its output to its input. What's its
behavior? Starting from lambda, we get the following sequence:
Remark: You can't start with a non-empty signal (like in the Banach theorem), because you would not have a chain of signals. So the lub would not even be defined.
Fix-point theorem III: A monotonic function F has a least fix-point (but there is no method for finding it).
Proof of theorem I:
Let s1 = F(Lambda).
As Lambda is a prefix of every tuple, we have Lambda
<= s1.
Since F is monotonic, we get F(Lambda) <=
F(s1), which implies s1
<= s2.
We thus build a chain s1, s2,
s3 . . .
Since we are in a cpo, this chain has a lub.
Then F({s1, s2,
s3 . . .}) = {F(s1),
F(s2), F(s3) . . .}
= {s2, s3 . . .}.
Since F is continuous, F(lub {s1,
s2, s3 . . .}) = lub
F({s1, s2, s3
. . .}) = lub {s2, s3
. . .}.
The first element of the chain is irrelevant for computing the
lub, so lub {s1, s2,
s3 . . .} = lub {s2,
s3 . . .}.
So lub {s1, s2 . . .} is a
fix-point of F. Let s be this fix-point. There remains
to prove that s is the least fix-point of F.
Suppose that there exists s' such that s' =
F(s'). We then have to prove that s <=
s'.
As Lambda is a prefix of every tuple, we have Lambda
<= s'.
Since F is monotonic, we get F(Lambda) <=
F(s'), which implies s1 <=
s'.
By the same way, we get F(s1) <=
F(s'), which implies s2 <=
s'.
So for any i, we have si <=
s'.
As a consequence, s' is an upper bound of the sequence
{s1, s2 . . .}. Since s is
the lub of this sequence, it follows that s <=
s'. CQFD
Note on Kahn/McQueen processes: A process is an imperative program, so the instructions are sequential. A read is blocking whenever there is no data on the read channel. A write is never blocking.
Remark1: The fair non-deterministic merge cannot be programmed as a Kahn/McQueen process. Note that it is not a functional process, so no fix-point theorem applies.
Remark2: Kahn/McQueen processes can be implemented with UNIX, POSIX or JAVA. The important thing is to ensure that the read is blocking. Otherwise the determinacy property will not be valid (see the paper).