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

Simplify proofs.

parent 084c4df7
Branches
Tags
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.
Please register or to comment