Library TortoiseHareAlgorithm.TortoiseHareAlgorithm
Correctness proof of Floyd's cycle-finding algorithm, also known as
the "tortoise and the hare"-algorithm
(see http://en.wikipedia.org/wiki/Floyd's_cycle-finding_algorithm)
If is a function over a finite set , then the iterations of from will ultimately cycle. The following code finds out an integer such that :
If is a function over a finite set , then the iterations of from will ultimately cycle. The following code finds out an integer such that :
let rec race m x y = if x = y then m else race (m+1) (f x) (f (f y)) in race 1 (f x0) (f (f x0))The difficulty is to prove 's termination.
Let f be a function over a set A
Parameter A : Set.
Parameter eq_A_dec : forall (x y:A), {x=y}+{~x=y}.
Parameter f : A -> A.
Parameter x0 : A.
We consider the sequence
We assume this sequence cycles after lambda+mu iterations, mu
being the length of the cycle (we actually don't require lambda and
mu to be minimal, because it is not needed for the remaining of the
proof
Parameter lambda : nat.
Parameter mu : nat.
Axiom mu_positive : mu > 0.
Axiom lambda_mu : forall i j, x (lambda+i) = x (lambda+i+j*mu).
Hilbert's epsilon operator.
The distance between x (2m) and x m defined using epsilon
Definition sep_x2m_xm m i := x (2*m+i) = x m.
Definition min P i := P i /\ forall j, P j -> i <= j.
Definition dist_x2m_xm m := epsilon (min (sep_x2m_xm m)).
Existence of this distance whenever lambda <= m
Axiom ex_min_P : forall P, (forall x, {P x}+{~(P x)}) -> ex P -> ex (min P).
Axiom div : forall a, a > 0 -> forall b, exists k, k*a >= b.
Lemma ex_dist_x2m_xm : forall m, lambda <= m -> ex (min (sep_x2m_xm m)).
Proof.
intros m hm; apply ex_min_P.
intro i; unfold sep_x2m_xm.
case (eq_A_dec (x (2 * m + i)) (x m)); auto.
generalize (div mu mu_positive m); intros (k,hk).
exists (k*mu - m); unfold sep_x2m_xm.
replace (2 * m + (k * mu - m)) with (lambda + (m-lambda)+k*mu) by omega.
rewrite <- lambda_mu.
replace (lambda+(m-lambda)) with m by omega; auto.
Qed.
Variant to prove the termination of Floyd's algorithm:
- either x m has not entered the loop yet and lambda-m is decreasing
- or bot x m and x (2m) are inside the loop and the distance between x (2m) and x m is decreasing
Definition variant m := (lambda - m, dist_x2m_xm m).
Definition lex x y := fst x < fst y \/ (fst x = fst y /\ snd x < snd y).
Correctness proof
Theorem rec_call_is_wf :
forall m, x m <> x (2*m) -> lex (variant (S m)) (variant m).
Proof.
unfold lex,variant; simpl.
intros.
assert (h: m < lambda \/ m >= lambda) by omega.
destruct h.
left; omega.
right.
split; auto with *.
unfold dist_x2m_xm.
assert (exd1: ex (min (sep_x2m_xm (S m)))).
apply ex_dist_x2m_xm; auto with *.
generalize (epsilon_spec (min (sep_x2m_xm (S m))) exd1).
assert (exd0: ex (min (sep_x2m_xm m))).
apply ex_dist_x2m_xm; auto with *.
generalize (epsilon_spec (min (sep_x2m_xm m)) exd0).
generalize (epsilon (min (sep_x2m_xm m))).
generalize (epsilon (min (sep_x2m_xm (S m)))).
intros d1 d0.
unfold min,sep_x2m_xm.
intros (h1,h2) (h3,h4).
assert (x (S(2*m+d0)) = x (S m)).
simpl; simpl in h1; congruence.
assert (d0 > 0).
assert (h: d0=0 \/ d0>0) by omega. destruct h; auto.
subst d0; absurd (x (2*m)=x m); auto.
replace (2*m+0) with (2*m) in h1; auto.
assert (d1 <= d0-1).
apply h4.
replace (2 * (S m) + (d0 - 1)) with (S (2 * m + d0)) by omega.
auto.
omega.
Save.
Definition R x y := lex (variant x) (variant y).
Axiom R_wf : well_founded R.
Definition find_cycle_rec :
forall (m:nat) (xm x2m:A), m > 0 -> xm=x m -> x2m=x (2*m) ->
{ m:nat | m > 0 /\ x m = x (2*m) }.
Proof.
induction m using (well_founded_induction R_wf).
intros xm x2m h hm h2m.
destruct (eq_A_dec xm x2m).
exists m; subst xm x2m; auto.
apply (H (S m)) with (f xm) (f (f x2m)); subst xm x2m; auto with *.
unfold R; apply rec_call_is_wf; auto.
replace (2*(S m)) with (S (S (2*m))) by omega; auto.
Defined.
Definition find_cycle : { m:nat | m > 0 /\ x m = x (2*m) }.
Proof.
apply (find_cycle_rec (S O) (f x0) (f (f x0))); auto with *.
Defined.
