Library RelationAlgebra.powerfix
powerfix: bounded fixpoint operator
Require Import common.
Set Implicit Arguments.
Section powerfix.
Variables A B: Type.
Notation Fun := (A -> B).
the three following functions "iterate" their f argument lazily:
iteration stops whenever f no longer makes recursive calls.
- powerfix' n f k iterates f at most (2^n-1) times and then yields to k
- powerfix n f k iterates f at most (2^n) times and then yields to k
- linearfix n f k iterates f at most n times and then yields to k
Fixpoint powerfix' n (f: Fun -> Fun) (k: Fun): Fun :=
fun a => match n with O => k a | S n => f (powerfix' n f (powerfix' n f k)) a end.
Definition powerfix n f k a := f (powerfix' n f k) a.
Fixpoint linearfix n (f: Fun -> Fun) (k: Fun): Fun :=
fun a => match n with O => k a | S n => f (linearfix n f k) a end.
fun a => match n with O => k a | S n => f (powerfix' n f (powerfix' n f k)) a end.
Definition powerfix n f k a := f (powerfix' n f k) a.
Fixpoint linearfix n (f: Fun -> Fun) (k: Fun): Fun :=
fun a => match n with O => k a | S n => f (linearfix n f k) a end.
simple lemmas about 2^n
Lemma pow2_S n: pow2 n = S (pred (pow2 n)).
Proof. induction n. reflexivity. simpl. now rewrite IHn. Qed.
Lemma pred_pow2_Sn n: pred (pow2 (S n)) = S (double (pred (pow2 n))).
Proof. simpl. now rewrite pow2_S. Qed.
Proof. induction n. reflexivity. simpl. now rewrite IHn. Qed.
Lemma pred_pow2_Sn n: pred (pow2 (S n)) = S (double (pred (pow2 n))).
Proof. simpl. now rewrite pow2_S. Qed.
characterisation of powerfix with linearfix
Section linear_carac.
Variable f: Fun -> Fun.
Lemma linearfix_S: forall n k,
f (linearfix n f k) = linearfix n f (f k).
Proof. induction n; intros k; simpl. reflexivity. now rewrite IHn. Qed.
Lemma linearfix_double: forall n k,
linearfix n f (linearfix n f k) = linearfix (double n) f k.
Proof.
induction n; intros k. reflexivity. simpl linearfix.
now rewrite <-IHn, <-linearfix_S.
Qed.
Lemma powerfix'_linearfix: forall n k,
powerfix' n f k = linearfix (pred (pow2 n)) f k.
Proof.
induction n; intros. reflexivity.
rewrite pred_pow2_Sn. simpl.
now rewrite <-linearfix_double, 2IHn.
Qed.
Theorem powerfix_linearfix: forall n k,
powerfix n f k = linearfix (pow2 n) f k.
Proof. intros. unfold powerfix. now rewrite powerfix'_linearfix, pow2_S. Qed.
End linear_carac.
Variable f: Fun -> Fun.
Lemma linearfix_S: forall n k,
f (linearfix n f k) = linearfix n f (f k).
Proof. induction n; intros k; simpl. reflexivity. now rewrite IHn. Qed.
Lemma linearfix_double: forall n k,
linearfix n f (linearfix n f k) = linearfix (double n) f k.
Proof.
induction n; intros k. reflexivity. simpl linearfix.
now rewrite <-IHn, <-linearfix_S.
Qed.
Lemma powerfix'_linearfix: forall n k,
powerfix' n f k = linearfix (pred (pow2 n)) f k.
Proof.
induction n; intros. reflexivity.
rewrite pred_pow2_Sn. simpl.
now rewrite <-linearfix_double, 2IHn.
Qed.
Theorem powerfix_linearfix: forall n k,
powerfix n f k = linearfix (pow2 n) f k.
Proof. intros. unfold powerfix. now rewrite powerfix'_linearfix, pow2_S. Qed.
End linear_carac.
powerfix_invariant gives an induction principle for powerfix,
that does not care about the number of iterations -- in particular,
the trivial "emptyfix" function : (fun f k a => k a) satisfies
the same induction principle, so that this can only be used to
reason about partial correctness.