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.
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.
Section linear_carac.
Variable f: Fun → Fun.
Lemma linearfix_S: ∀ 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: ∀ 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: ∀ 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: ∀ 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: ∀ 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: ∀ 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: ∀ 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: ∀ 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.