Skip to content
Snippets Groups Projects
Commit 2004c366 authored by Robbert Krebbers's avatar Robbert Krebbers
Browse files

Simplify proofs.

parent 084c4df7
No related branches found
No related tags found
No related merge requests found
...@@ -126,167 +126,134 @@ Section proof. ...@@ -126,167 +126,134 @@ Section proof.
Qed. Qed.
Section array_init. Section array_init.
Context {A : Type} (g : A val) (Q : nat A iProp Σ). Context (Q : nat val iProp Σ).
Implicit Types xs : list A. Implicit Types (f v : val) (i j : nat).
Implicit Types f : val.
Local Lemma wp_array_init_loop xs i n l f stk E : Local Lemma wp_array_init_loop stk E l i n k f :
0 < n n = Z.of_nat (i + k)
length xs = i {{{
i n (l + i) ↦∗ replicate k #()
([ list] kxxs, Q k x) -∗ [ list] j seq i k, WP f #(j : nat) @ stk; E {{ Q j }}
([ list] j seq i (n-i), WP f #(j : nat) @ stk; E {{ v, x : A, v = g x Q j x }}) -∗ }}}
l ↦∗ ((g <$> xs) ++ replicate (n - i) #()) -∗ array_init_loop #l #i #n f @ stk; E
WP array_init_loop #l #i #n f @ stk; E {{ _, ys, {{{ vs, RET #();
l ↦∗ (g <$> (xs ++ ys)) length (xs++ys) = n ([ list] kx(xs++ys), Q k x) }}. length vs = k (l + i) ↦∗ vs [ list] jv vs, Q (i + j) v }}}.
Proof. Proof.
iIntros (Hn Hxs Hi) "Hxs Hf Hl". iRevert (Hxs Hi). iIntros (Hn Φ) "[Hl Hf] HΦ".
iLöb as "IH" forall (xs i). iIntros (Hxs Hi). iInduction k as [|k] "IH" forall (i Hn); simplify_eq/=; wp_rec; wp_pures.
wp_rec. wp_pures. case_bool_decide; simplify_eq/=; wp_pures. { rewrite bool_decide_eq_true_2; last (repeat f_equal; lia).
- iExists []. iFrame. wp_pures. iApply ("HΦ" $! []). auto. }
assert (length xs - length xs = 0) as -> by lia. rewrite bool_decide_eq_false_2; last naive_solver lia.
rewrite !app_nil_r. eauto with iFrame. iDestruct (array_cons with "Hl") as "[Hl HSl]".
- wp_bind (f #(length xs)). iDestruct "Hf" as "[Hf HSf]".
destruct n as [|n]; first by lia. wp_apply (wp_wand with "Hf"); iIntros (v) "Hv". wp_store. wp_pures.
assert (length xs S n) by congruence. rewrite Z.add_1_r -Nat2Z.inj_succ.
rewrite Nat.sub_succ_l; last by lia. iApply ("IH" with "[%] [HSl] HSf"); first lia.
iSimpl in "Hf". iDestruct "Hf" as "[H Hf]". { by rewrite loc_add_assoc Z.add_1_r -Nat2Z.inj_succ. }
iApply (wp_wand with "H"). iIntros "!>" (vs). iDestruct 1 as (<-) "[HSl Hvs]".
iIntros (v). iDestruct 1 as (x) "[-> Hx]". iApply ("HΦ" $! (v :: vs)). iSplit; [naive_solver|]. iSplitL "Hl HSl".
wp_apply (wp_store_offset with "Hl"). - iFrame "Hl". by rewrite loc_add_assoc Z.add_1_r -Nat2Z.inj_succ.
{ apply lookup_lt_is_Some_2. - iEval (rewrite /= Nat.add_0_r; setoid_rewrite Nat.add_succ_r). iFrame.
rewrite app_length. Qed.
assert (S n - length xs > 0) by lia. Local Lemma twp_array_init_loop stk E l i n k f :
rewrite fmap_length replicate_length. lia. } n = Z.of_nat (i + k)
iIntros "Hl". wp_pures. [[{
assert ((Z.of_nat (length xs) + 1)%Z = Z.of_nat (length xs + 1)) as -> by lia. (l + i) ↦∗ replicate k #()
iSpecialize ("IH" $! (xs++[x]) (length xs + 1) with "[Hx Hxs] [Hf] [Hl] [%] [%]"). [ list] j seq i k, WP f #(j : nat) @ stk; E [{ Q j }]
{ rewrite big_sepL_app /= Nat.add_0_r. by iFrame. } }]]
{ by rewrite Nat.add_1_r Nat.sub_succ. } array_init_loop #l #i #n f @ stk; E
{ assert (length xs = length xs + 0) as Hlen1 by lia. [[{ vs, RET #();
rewrite {1}Hlen1. length vs = k (l + i) ↦∗ vs [ list] jv vs, Q (i + j) v }]].
rewrite -{1}(fmap_length g xs).
rewrite insert_app_r fmap_app /=.
rewrite app_assoc_reverse /=.
by rewrite Nat.add_1_r Nat.sub_succ. }
{ by rewrite app_length. }
{ lia. }
iApply (wp_wand with "IH").
iIntros (_). iDestruct 1 as (ys) "(Hys & Hlen & HQs)".
iDestruct "Hlen" as %Hlen.
rewrite -app_assoc.
iExists ([x] ++ ys). iFrame. iPureIntro.
by rewrite app_assoc.
Qed.
Local Lemma twp_array_init_loop xs i n l f stk E :
0 < n
length xs = i
i n
([ list] kxxs, Q k x) -∗
([ list] j seq i (n-i), WP f #(j : nat) @ stk; E [{ v, x : A, v = g x Q j x }]) -∗
l ↦∗ ((g <$> xs) ++ replicate (n - i) #()) -∗
WP array_init_loop #l #i #n f @ stk; E [{ _, ys,
l ↦∗ (g <$> (xs ++ ys)) length (xs++ys) = n ([ list] kx(xs++ys), Q k x) }].
Proof. Proof.
iIntros (Hn Hxs Hi) "Hxs Hf Hl". iRevert (Hxs Hi). iIntros (Hn Φ) "[Hl Hf] HΦ".
remember (n - i) as k. iRevert (Heqk). iInduction k as [|k] "IH" forall (i Hn); simplify_eq/=; wp_rec; wp_pures.
iInduction k as [|k] "IH" forall (xs i); iIntros (Heqk Hxs Hi). { rewrite bool_decide_eq_true_2; last (repeat f_equal; lia).
- wp_rec. wp_pures. case_bool_decide; simplify_eq/=; wp_pures. wp_pures. iApply ("HΦ" $! []). auto. }
+ iExists []. iFrame. rewrite bool_decide_eq_false_2; last naive_solver lia.
rewrite !app_nil_r. eauto with iFrame. iDestruct (array_cons with "Hl") as "[Hl HSl]".
+ assert (length xs n) by congruence. lia. iDestruct "Hf" as "[Hf HSf]".
- wp_rec. wp_pures. case_bool_decide; simplify_eq/=; wp_pures. wp_apply (twp_wand with "Hf"); iIntros (v) "Hv". wp_store. wp_pures.
+ exfalso. lia. rewrite Z.add_1_r -Nat2Z.inj_succ.
+ wp_bind (f #(length xs)). iApply ("IH" with "[%] [HSl] HSf"); first lia.
iSimpl in "Hf". iDestruct "Hf" as "[H Hf]". { by rewrite loc_add_assoc Z.add_1_r -Nat2Z.inj_succ. }
iApply (twp_wand with "H"). iIntros (vs). iDestruct 1 as (<-) "[HSl Hvs]".
iIntros (v). iDestruct 1 as (x) "[-> Hx]". iApply ("HΦ" $! (v :: vs)). iSplit; [naive_solver|]. iSplitL "Hl HSl".
wp_apply (twp_store_offset with "Hl"). - iFrame "Hl". by rewrite loc_add_assoc Z.add_1_r -Nat2Z.inj_succ.
{ apply lookup_lt_is_Some_2. - iEval (rewrite /= Nat.add_0_r; setoid_rewrite Nat.add_succ_r). iFrame.
rewrite app_length /=.
assert (S n - length xs > 0) by lia.
rewrite fmap_length replicate_length. lia. }
iIntros "Hl". wp_pures.
assert ((Z.of_nat (length xs) + 1)%Z = Z.of_nat (length xs + 1)) as -> by lia.
iSpecialize ("IH" $! (xs++[x]) (length xs+1) with "[Hx Hxs] [Hf] [Hl] [%] [%] [%]").
{ rewrite big_sepL_app /= Nat.add_0_r. by iFrame. }
{ by rewrite Nat.add_1_r. }
{ assert (length xs = length xs + 0) as Hlen1 by lia.
rewrite {1}Hlen1.
rewrite -{1}(fmap_length g xs).
rewrite insert_app_r fmap_app /=.
rewrite app_assoc_reverse /= //. }
{ lia. }
{ by rewrite app_length. }
{ lia. }
iApply (twp_wand with "IH").
iIntros (_). iDestruct 1 as (ys) "(Hys & Hlen & HQs)".
iDestruct "Hlen" as %Hlen.
rewrite -app_assoc.
iExists ([x] ++ ys). iFrame. iPureIntro.
by rewrite app_assoc.
Qed. Qed.
Theorem wp_array_init n f stk E : Lemma wp_array_init stk E n f :
(0 < n)%Z (0 < n)%Z
{{{ [ list] i seq 0 (Z.to_nat n), WP f #(i : nat) @ stk; E {{ v, x : A, v = g x Q i x }} }}} {{{ [ list] i seq 0 (Z.to_nat n), WP f #(i : nat) @ stk; E {{ Q i }} }}}
array_init #n f @ stk; E array_init #n f @ stk; E
{{{ l xs, RET #l; l ↦∗ (g <$> xs) Z.of_nat (length xs) = n ([ list] kxxs, Q k x) }}}. {{{ l vs, RET #l;
Z.of_nat (length vs) = n l ↦∗ vs [ list] kv vs, Q k v }}}.
Proof. Proof.
intros Hn. iIntros (Φ) "Hf HΦ". iIntros (Hn Φ) "Hf HΦ". wp_lam. wp_alloc l as "Hl"; first done.
wp_rec. wp_pures. wp_alloc l as "Hl"; first done. wp_apply (wp_array_init_loop _ _ _ 0 n (Z.to_nat n)
wp_pures. with "[Hl $Hf] [HΦ]"); first lia.
iPoseProof (wp_array_init_loop [] 0 (Z.to_nat n) with "[//] [Hf] [Hl]") as "H"; try by (simpl; lia). { by rewrite loc_add_0. }
{ simpl. assert (Z.to_nat n - 0 = Z.to_nat n) as -> by lia. done. } iIntros "!>" (vs). iDestruct 1 as (?) "[Hl Hvs]". wp_pures.
{ simpl. assert (Z.to_nat n - 0 = Z.to_nat n) as -> by lia. done. } iApply ("HΦ" $! _ vs). iSplit; [iPureIntro; lia|].
assert (Z.of_nat 0%nat = 0%Z) as -> by lia. rewrite loc_add_0. iFrame.
assert (Z.of_nat (Z.to_nat n) = n) as -> by lia.
wp_apply (wp_wand with "H").
iIntros (?). iDestruct 1 as (vs) "(Hl & % & HQs)".
wp_pures. iApply "HΦ".
iFrame "Hl HQs". iPureIntro. lia.
Qed. Qed.
Theorem twp_array_init n f stk E : Lemma twp_array_init stk E n f :
(0 < n)%Z (0 < n)%Z
[[{ [ list] i seq 0 (Z.to_nat n), WP f #(i : nat) @ stk; E [{ v, x : A, v = g x Q i x }] }]] [[{ [ list] i seq 0 (Z.to_nat n), WP f #(i : nat) @ stk; E [{ Q i }] }]]
array_init #n f @ stk; E array_init #n f @ stk; E
[[{ l xs, RET #l; l ↦∗ (g <$> xs) Z.of_nat (length xs) = n ([ list] kxxs, Q k x) }]]. [[{ l vs, RET #l;
Z.of_nat (length vs) = n l ↦∗ vs [ list] kv vs, Q k v }]].
Proof. Proof.
intros Hn. iIntros (Φ) "Hf HΦ". iIntros (Hn Φ) "Hf HΦ". wp_lam. wp_alloc l as "Hl"; first done.
wp_rec. wp_pures. wp_alloc l as "Hl"; first done. wp_apply (twp_array_init_loop _ _ _ 0 n (Z.to_nat n)
wp_pures. with "[Hl $Hf] [HΦ]"); first lia.
iPoseProof (twp_array_init_loop [] 0 (Z.to_nat n) with "[//] [Hf] [Hl]") as "H"; try by (simpl; lia). { by rewrite loc_add_0. }
{ simpl. assert (Z.to_nat n - 0 = Z.to_nat n) as -> by lia. done. } iIntros (vs). iDestruct 1 as (?) "[Hl Hvs]". wp_pures.
{ simpl. assert (Z.to_nat n - 0 = Z.to_nat n) as -> by lia. done. } iApply ("HΦ" $! _ vs). iSplit; [iPureIntro; lia|].
assert (Z.of_nat 0%nat = 0%Z) as -> by lia. rewrite loc_add_0. iFrame.
assert (Z.of_nat (Z.to_nat n) = n) as -> by lia.
wp_apply (twp_wand with "H").
iIntros (?). iDestruct 1 as (vs) "(Hl & % & HQs)".
wp_pures. iApply "HΦ".
iFrame "Hl HQs". iPureIntro. lia.
Qed. Qed.
End array_init. End array_init.
(* Version of [wp_array_init] with the auxiliary type [A] set to Section array_init_fmap.
[val], and with the persistent assumption on the function [f]. *) Context {A} (g : A val) (Q : nat A iProp Σ).
Lemma wp_array_init' (Q : nat val iProp Σ) n (f : val) stk E : Implicit Types (xs : list A) (f : val).
(0 < n)%Z
{{{ ( i : nat, WP f #i @ stk; E {{ v, Q i v }}) }}} Local Lemma big_sepL_exists_eq vs :
array_init #n f @ stk; E ([ list] kv vs, x, v = g x Q k x) -∗
{{{ l xs, RET #l; l ↦∗ xs Z.of_nat (length xs) = n ([ list] kxxs, Q k x) }}}. xs, vs = g <$> xs [ list] kx xs, Q k x.
Proof. Proof.
intros Hn. iIntros (Φ) "#Hf HΦ". iIntros "Hvs". iInduction vs as [|v vs] "IH" forall (Q); simpl.
iApply (wp_array_init id Q with "[Hf]"); try done. { iExists []. by auto. }
{ generalize 0. intros j. iDestruct "Hvs" as "[Hv Hvs]"; iDestruct "Hv" as (x ->) "Hv".
iInduction (Z.to_nat n) as [|k] "IH" forall (j); eauto. iDestruct ("IH" with "Hvs") as (xs ->) "Hxs".
simpl. iSplitL "Hf". iExists (x :: xs). by iFrame.
- iApply (wp_wand with "Hf"). Qed.
iIntros (v) "Hv". iExists v; eauto with iFrame.
- iApply "IH". }
iNext. iIntros (l xs). by rewrite list_fmap_id.
Qed.
Lemma wp_array_init_fmap stk E n f :
(0 < n)%Z
{{{ [ list] i seq 0 (Z.to_nat n),
WP f #(i : nat) @ stk; E {{ v, x, v = g x Q i x }} }}}
array_init #n f @ stk; E
{{{ l xs, RET #l;
Z.of_nat (length xs) = n l ↦∗ (g <$> xs) [ list] kx xs, Q k x }}}.
Proof.
iIntros (Hn Φ) "Hf HΦ". iApply (wp_array_init with "Hf"); first done.
iIntros "!>" (l vs). iDestruct 1 as (<-) "[Hl Hvs]".
iDestruct (big_sepL_exists_eq with "Hvs") as (xs ->) "Hxs".
iApply "HΦ". iFrame "Hl Hxs". by rewrite fmap_length.
Qed.
Lemma twp_array_init_fmap stk E n f :
(0 < n)%Z
[[{ [ list] i seq 0 (Z.to_nat n),
WP f #(i : nat) @ stk; E [{ v, x, v = g x Q i x }] }]]
array_init #n f @ stk; E
[[{ l xs, RET #l;
Z.of_nat (length xs) = n l ↦∗ (g <$> xs) [ list] kx xs, Q k x }]].
Proof.
iIntros (Hn Φ) "Hf HΦ". iApply (twp_array_init with "Hf"); first done.
iIntros (l vs). iDestruct 1 as (<-) "[Hl Hvs]".
iDestruct (big_sepL_exists_eq with "Hvs") as (xs ->) "Hxs".
iApply "HΦ". iFrame "Hl Hxs". by rewrite fmap_length.
Qed.
End array_init_fmap.
End proof. End proof.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment