functional programming - How do I prove that two Fibonacci implementations are equal in Coq? -
i've 2 fibonacci implementations, seen below, want prove functionally equivalent.
i've proved properties natural numbers, exercise requires approach cannot figure out.
the textbook i'm using have introduced following syntax of coq, should possible prove equality using notation:
<definition> ::= <keyword> <identifier> : <statement> <proof> <keyword> ::= proposition | lemma | theorem | corollary <statement> ::= {<quantifier>,}* <expression> <quantifier> ::= forall {<identifier>}+ : <type> | forall {({<identifier>}+ : <type>)}+ <proof> ::= proof. {<tactic>.}* <end-of-proof> <end-of-proof> ::= qed. | admitted. | abort.
here 2 implementations:
fixpoint fib_v1 (n : nat) : nat := match n | 0 => o | s n' => match n' | o => 1 | s n'' => (fib_v1 n') + (fib_v1 n'') end end. fixpoint visit_fib_v2 (n a1 a2 : nat) : nat := match n | 0 => a1 | s n' => visit_fib_v2 n' a2 (a1 + a2) end.
it pretty obvious these functions compute same value base case n = 0
, induction case harder?
i've tried proving following lemma, i'm stuck in induction case:
lemma about_visit_fib_v2 : forall j : nat, visit_fib_v2 (fib_v1 (s j)) ((fib_v1 j) + (fib_v1 (s j))) = (fib_v1 (add_v1 (s j))). proof. induction [| i' ihi']. intro j. rewrite -> (unfold_visit_fib_v2_0 (fib_v1 (s j)) ((fib_v1 j) + (fib_v1 (s j)))). rewrite -> (add_v1_0_n (s j)). reflexivity. intro j. rewrite -> (unfold_visit_fib_v2_s i' (fib_v1 (s j)) ((fib_v1 j) + (fib_v1 (s j)))). admitted.
where:
fixpoint add_v1 (i j : nat) : nat := match | o => j | s i' => s (add_v1 i' j) end.
a note of warning: in follows i'll try show main idea of such proof, i'm not going stick subset of coq , won't arithmetic manually. instead i'll use proof automation, viz. ring
tactic. however, feel free ask additional questions, convert proof suit purposes.
i think it's easier start generalization:
require import arith. (* `ring` tactic *) lemma fib_v1_eq_fib2_generalized n : forall a0 a1, visit_fib_v2 (s n) a0 a1 = a0 * fib_v1 n + a1 * fib_v1 (s n). proof. induction n; intros a0 a1. - simpl; ring. - change (visit_fib_v2 (s (s n)) a0 a1) (visit_fib_v2 (s n) a1 (a0 + a1)). rewrite ihn. simpl; ring. qed.
if using ring
doesn't suit needs, can perform multiple rewrite
steps using lemmas of arith
module.
now, let's our goal:
definition fib_v2 n := visit_fib_v2 n 0 1. lemma fib_v1_eq_fib2 n : fib_v1 n = fib_v2 n. proof. destruct n. - reflexivity. - unfold fib_v2. rewrite fib_v1_eq_fib2_generalized. ring. qed.
Comments
Post a Comment