bunched.analytic_completion
Analytic completion of a structural rule
From Coq Require Import ssreflect.
From bunched.algebra Require Import bi.
From bunched Require Import syntax interp prelude.sets terms.
From stdpp Require Import prelude base gmap fin_sets.
Section analytic_completion.
From bunched.algebra Require Import bi.
From bunched Require Import syntax interp prelude.sets terms.
From stdpp Require Import prelude base gmap fin_sets.
Section analytic_completion.
Variable (s : structural_rule).
Definition ren_inverse : gmap nat (gset nat) := map_preimage (linearize_bterm_ren (snd s)).
Definition transform_premise (Tz : bterm nat) : gset (bterm nat) :=
let Tz_lin := linearize_bterm Tz in
let r_Tz := linearize_bterm_ren Tz in
let ren := λ j, ren_inverse !!! (r_Tz !!! j) in
bterm_gset_fold $ ren <$> Tz_lin.
Definition analytic_completion : structural_rule :=
(mjoin $ fmap (elements ∘ transform_premise) (fst s), linearize_bterm (snd s)).
End analytic_completion.
Definition ren_inverse : gmap nat (gset nat) := map_preimage (linearize_bterm_ren (snd s)).
Definition transform_premise (Tz : bterm nat) : gset (bterm nat) :=
let Tz_lin := linearize_bterm Tz in
let r_Tz := linearize_bterm_ren Tz in
let ren := λ j, ren_inverse !!! (r_Tz !!! j) in
bterm_gset_fold $ ren <$> Tz_lin.
Definition analytic_completion : structural_rule :=
(mjoin $ fmap (elements ∘ transform_premise) (fst s), linearize_bterm (snd s)).
End analytic_completion.
Example: restricted form of weakening: a ∗ a ≤ a
and it's analytic presentation a₁ * a₂ ≤ a₁ ∨ a₂
Example rule_restr_weakn : structural_rule := ([Var 0], TComma (Var 0) (Var 0)).
Example rule_restr_weakn_a := analytic_completion rule_restr_weakn.
Eval vm_compute in rule_restr_weakn_a.
Section analytic_completion_correct.
Variable (s : structural_rule).
Context {PROP : bi}.
Implicit Type Xs Ys : nat → PROP.
Implicit Type n k m : nat.
Local Notation ren_inverse := (ren_inverse s).
Local Notation transform_premise := (transform_premise s).
Local Notation T := (snd s).
Local Notation Ts := (fst s).
Definition disj_ren_inverse Xs : nat → PROP := λ n, (∃ k, ⌜k ∈ ren_inverse !!! n⌝ ∧ Xs k)%I.
Definition linearize_bterm_ren_act Xs : nat → PROP :=
λ (n : nat), Xs (linearize_bterm_ren T !!! n).
Lemma ren_ren_inverse i j :
j ∈ ren_inverse !!! i → linearize_bterm_ren T !!! j = i.
Proof.
rewrite /ren_inverse. rewrite lookup_total_preimage.
apply lookup_total_correct.
Qed.
Lemma linearize_bterm_act Xs :
bterm_alg_act (linearize_bterm T) Xs ⊢ bterm_alg_act T (disj_ren_inverse Xs).
Proof.
rewrite /disj_ren_inverse /ren_inverse /linearize_bterm_ren /linearize_bterm.
generalize 0.
induction T as [x | T1 IHT1 T2 IHT2 | T1 IHT1 T2 IHT2 ]=>i; simpl.
- apply (bi.exist_intro' _ _ i).
rewrite map_preimage_singleton.
apply bi.and_intro; eauto. apply bi.pure_intro. rewrite lookup_total_singleton. set_solver.
- specialize (IHT1 i).
destruct (linearize_pre T1 i) as [[i1 m1] T1'] eqn:Ht1.
specialize (IHT2 i1).
destruct (linearize_pre T2 i1) as [[i2 m2] T2'] eqn:Ht2. simpl.
assert (dom (gset _) m1 = set_seq i (i1-i)) as Hm1.
{ replace i1 with (fst $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
replace m1 with (snd $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
apply linearize_pre_dom. }
assert (dom (gset _) m2 = set_seq i1 (i2-i1)) as Hm2.
{ replace i2 with (fst $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
replace m2 with (snd $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
apply linearize_pre_dom. }
assert (m1 ##ₘ m2) as Hm1m2disj.
{ apply map_disjoint_dom_2. rewrite Hm1 Hm2.
set_unfold. lia. }
f_equiv.
{ rewrite IHT1 /=.
apply bterm_alg_act_mono=>j.
apply bi.exist_mono'=>k. do 2 f_equiv.
rewrite !lookup_total_preimage.
intro. by apply lookup_union_Some_l. }
{ rewrite IHT2 /=.
apply bterm_alg_act_mono=>j.
apply bi.exist_mono'=>k. do 2 f_equiv.
rewrite !lookup_total_preimage.
intro. by apply lookup_union_Some_r. }
- specialize (IHT1 i).
destruct (linearize_pre T1 i) as [[i1 m1] T1'] eqn:Ht1.
specialize (IHT2 i1).
destruct (linearize_pre T2 i1) as [[i2 m2] T2'] eqn:Ht2. simpl.
assert (dom (gset _) m1 = set_seq i (i1-i)) as Hm1.
{ replace i1 with (fst $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
replace m1 with (snd $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
apply linearize_pre_dom. }
assert (dom (gset _) m2 = set_seq i1 (i2-i1)) as Hm2.
{ replace i2 with (fst $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
replace m2 with (snd $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
apply linearize_pre_dom. }
assert (m1 ##ₘ m2) as Hm1m2disj.
{ apply map_disjoint_dom_2. rewrite Hm1 Hm2.
set_unfold. lia. }
f_equiv.
{ rewrite IHT1 /=.
apply bterm_alg_act_mono=>j.
apply bi.exist_mono'=>k. do 2 f_equiv.
rewrite !lookup_total_preimage. intro. by apply lookup_union_Some_l. }
{ rewrite IHT2 /=.
apply bterm_alg_act_mono=>j.
apply bi.exist_mono'=>k. do 2 f_equiv.
rewrite !lookup_total_preimage. intro. by apply lookup_union_Some_r. }
Qed.
Lemma bterm_alg_act_renaming'' Tz Xs :
bterm_alg_act Tz (linearize_bterm_ren_act Xs) ≡ bterm_alg_act ((λ n, linearize_bterm_ren T !!! n) <$> Tz) Xs.
Proof.
rewrite /linearize_bterm_ren_act.
induction Tz as [x | T1 IHT1 T2 IHT2 | T1 IHT1 T2 IHT2 ]; eauto; simpl; by f_equiv.
Qed.
Lemma bterm_alg_act_disj_ren_inverse_transform Tz Xs :
bterm_alg_act Tz (disj_ren_inverse Xs) -∗ ∃ Tk, ⌜Tk ∈ transform_premise Tz⌝ ∧ bterm_alg_act Tk Xs.
Proof.
rewrite /disj_ren_inverse /transform_premise /linearize_bterm /linearize_bterm_ren.
generalize 0.
induction Tz as [x | T1 IHT1 T2 IHT2 | T1 IHT1 T2 IHT2 ]=>idx; simpl.
- apply bi.exist_elim=>k. apply bi.pure_elim_l=>Hk.
apply (bi.exist_intro' _ _ (Var k)). apply bi.and_intro; eauto.
apply bi.pure_intro. eapply elem_of_map_2. by rewrite lookup_total_singleton.
- specialize (IHT1 idx).
destruct (linearize_pre T1 idx) as [[idx1 m1] T1'] eqn:Ht1.
specialize (IHT2 idx1).
destruct (linearize_pre T2 idx1) as [[idx2 m2] T2'] eqn:Ht2.
assert (dom (gset _) m1 = set_seq idx (idx1-idx)) as Hm1.
{ replace idx1 with (fst $ fst (linearize_pre T1 idx)) by rewrite Ht1 //.
replace m1 with (snd $ fst (linearize_pre T1 idx)) by rewrite Ht1 //.
apply linearize_pre_dom. }
assert (dom (gset _) m2 = set_seq idx1 (idx2-idx1)) as Hm2.
{ replace idx2 with (fst $ fst (linearize_pre T2 idx1)) by rewrite Ht2 //.
replace m2 with (snd $ fst (linearize_pre T2 idx1)) by rewrite Ht2 //.
apply linearize_pre_dom. }
assert (m1 ##ₘ m2) as Hm1m2disj.
{ apply map_disjoint_dom_2. rewrite Hm1 Hm2.
set_unfold. lia. }
assert (term_fv T1' ⊆ set_seq idx (idx1-idx)) as Hfv1.
{ replace T1' with (snd (linearize_pre T1 idx)) by rewrite Ht1 //.
replace idx1 with (fst $ fst (linearize_pre T1 idx)) by rewrite Ht1 //.
apply linearize_pre_fv. }
assert (term_fv T2' ⊆ set_seq idx1 (idx2-idx1)) as Hfv2.
{ replace T2' with (snd (linearize_pre T2 idx1)) by rewrite Ht2 //.
replace idx2 with (fst $ fst (linearize_pre T2 idx1)) by rewrite Ht2 //.
apply linearize_pre_fv. }
rewrite IHT1 . rewrite bi.sep_exist_r. apply bi.exist_elim=>Tk1.
rewrite bi.sep_and_r. rewrite bi.pure_sep_l.
apply bi.pure_elim_l=>Hk1.
rewrite IHT2. rewrite comm. rewrite bi.sep_exist_r. apply bi.exist_elim=>Tk2.
rewrite bi.sep_and_r. rewrite bi.pure_sep_l.
apply bi.pure_elim_l=>Hk2. rewrite comm.
apply (bi.exist_intro' _ _ (TComma Tk1 Tk2)). apply bi.and_intro; simpl; last by f_equiv.
apply bi.pure_intro.
apply sets.elem_of_set_map_2. eexists _,_. repeat split; eauto.
+ simpl in Hk1.
enough ((λ j : nat, ren_inverse !!! (m1 !!! j)) <$> T1' = ((λ j : nat, ren_inverse !!! ((m1 ∪ m2) !!! j)) <$> T1'))
as <-; first done.
apply bterm_fmap_ext; last done. intros x Hx. f_equiv.
rewrite !lookup_total_alt. f_equiv.
symmetry. apply lookup_union_l. apply elem_of_dom.
set_unfold. naive_solver.
+ simpl in Hk2.
enough ((λ j : nat, ren_inverse !!! (m2 !!! j)) <$> T2' = ((λ j : nat, ren_inverse !!! ((m1 ∪ m2) !!! j)) <$> T2'))
as <-; first done.
apply bterm_fmap_ext; last done. intros x Hx. f_equiv.
rewrite !lookup_total_alt. f_equiv.
symmetry. apply lookup_union_r. apply not_elem_of_dom.
set_unfold. intros Hx'. apply Hfv2 in Hx. apply Hm1 in Hx'. lia.
- specialize (IHT1 idx).
destruct (linearize_pre T1 idx) as [[idx1 m1] T1'] eqn:Ht1.
specialize (IHT2 idx1).
destruct (linearize_pre T2 idx1) as [[idx2 m2] T2'] eqn:Ht2.
assert (dom (gset _) m1 = set_seq idx (idx1-idx)) as Hm1.
{ replace idx1 with (fst $ fst (linearize_pre T1 idx)) by rewrite Ht1 //.
replace m1 with (snd $ fst (linearize_pre T1 idx)) by rewrite Ht1 //.
apply linearize_pre_dom. }
assert (dom (gset _) m2 = set_seq idx1 (idx2-idx1)) as Hm2.
{ replace idx2 with (fst $ fst (linearize_pre T2 idx1)) by rewrite Ht2 //.
replace m2 with (snd $ fst (linearize_pre T2 idx1)) by rewrite Ht2 //.
apply linearize_pre_dom. }
assert (m1 ##ₘ m2) as Hm1m2disj.
{ apply map_disjoint_dom_2. rewrite Hm1 Hm2.
set_unfold. lia. }
assert (term_fv T1' ⊆ set_seq idx (idx1-idx)) as Hfv1.
{ replace T1' with (snd (linearize_pre T1 idx)) by rewrite Ht1 //.
replace idx1 with (fst $ fst (linearize_pre T1 idx)) by rewrite Ht1 //.
apply linearize_pre_fv. }
assert (term_fv T2' ⊆ set_seq idx1 (idx2-idx1)) as Hfv2.
{ replace T2' with (snd (linearize_pre T2 idx1)) by rewrite Ht2 //.
replace idx2 with (fst $ fst (linearize_pre T2 idx1)) by rewrite Ht2 //.
apply linearize_pre_fv. }
rewrite IHT1. rewrite bi.and_exist_r. apply bi.exist_elim=>Tk1.
rewrite -assoc.
apply bi.pure_elim_l=>Hk1.
rewrite IHT2. rewrite comm. rewrite bi.and_exist_r. apply bi.exist_elim=>Tk2.
rewrite -assoc.
apply bi.pure_elim_l=>Hk2. rewrite comm.
apply (bi.exist_intro' _ _ (TSemic Tk1 Tk2)). apply bi.and_intro; simpl; last by f_equiv.
apply bi.pure_intro.
apply sets.elem_of_set_map_2. eexists _,_. repeat split; eauto.
+ simpl in Hk1.
enough ((λ j : nat, ren_inverse !!! (m1 !!! j)) <$> T1' = ((λ j : nat, ren_inverse !!! ((m1 ∪ m2) !!! j)) <$> T1'))
as <-; first done.
apply bterm_fmap_ext; last done. intros x Hx. f_equiv.
rewrite !lookup_total_alt. f_equiv.
symmetry. apply lookup_union_l. apply elem_of_dom.
set_unfold. naive_solver.
+ simpl in Hk2.
enough ((λ j : nat, ren_inverse !!! (m2 !!! j)) <$> T2' = ((λ j : nat, ren_inverse !!! ((m1 ∪ m2) !!! j)) <$> T2'))
as <-; first done.
apply bterm_fmap_ext; last done. intros x Hx. f_equiv.
rewrite !lookup_total_alt. f_equiv.
symmetry. apply lookup_union_r. apply not_elem_of_dom.
set_unfold. intros Hx'. apply Hfv2 in Hx. apply Hm1 in Hx'. lia.
Qed.
Lemma elem_of_map_ren_ren_inverse x y :
y ∈ (set_map (C:=gset nat) (λ n, linearize_bterm_ren T !!! n) (ren_inverse !!! x) : gset nat) → y = x.
Proof.
rewrite elem_of_map.
intros [z [-> Hz]]. by apply ren_ren_inverse.
Qed.
Lemma transformed_premise_act_ren Tz' Tz Xs :
Tz' ∈ transform_premise Tz → bterm_alg_act Tz' (linearize_bterm_ren_act Xs) ≡ bterm_alg_act Tz Xs.
Proof.
rewrite /transform_premise.
intros H1.
apply (bterm_gset_fold_fmap (λ n, linearize_bterm_ren T !!! n)) in H1.
revert H1.
rewrite /bterm_gset_fmap.
rewrite -(bterm_fmap_compose (λ j : nat, ren_inverse !!! (linearize_bterm_ren Tz !!! j))).
rewrite bterm_alg_act_renaming''.
intros H1. f_equiv.
revert H1.
pose (Tz'' := (λ n, linearize_bterm_ren T !!! n) <$> Tz').
fold Tz''. intros HTz''.
assert (Tz'' ∈ bterm_gset_fold
((λ j : nat, set_map (λ n, linearize_bterm_ren T !!! n) (ren_inverse !!! (linearize_bterm_ren Tz !!! j))) <$> linearize_bterm Tz)) as HH.
{ apply HTz''. }
clear HTz''.
apply bterm_gset_fold_fmap_inv in HH; last first.
{ apply linearize_pre_linear. }
destruct HH as [g [Hg ->]].
assert (∀ i : nat,
i ∈ term_fv (linearize_bterm Tz)
→ g i = (linearize_bterm_ren Tz !!! i)) as HHH.
{ intros i Hi. apply elem_of_map_ren_ren_inverse.
by eapply Hg. }
clear Hg. revert HHH.
rewrite /(linearize_bterm_ren Tz) /(linearize_bterm Tz).
generalize 0.
induction Tz as [x | T1 IHT1 T2 IHT2 | T1 IHT1 T2 IHT2 ]=>i; simpl.
- intros H1. f_equiv.
etrans. { apply H1. by apply elem_of_singleton. }
apply lookup_total_singleton.
- intros H1.
specialize (IHT1 i).
destruct (linearize_pre T1 i) as [[i1 m1] T1'] eqn:Ht1.
specialize (IHT2 i1).
destruct (linearize_pre T2 i1) as [[i2 m2] T2'] eqn:Ht2.
assert (term_fv T1' ⊆ set_seq i (i1-i)).
{ replace T1' with (snd (linearize_pre T1 i)) by rewrite Ht1 //.
replace i1 with (fst $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
apply linearize_pre_fv. }
assert (term_fv T2' ⊆ set_seq i1 (i2-i1)).
{ replace T2' with (snd (linearize_pre T2 i1)) by rewrite Ht2 //.
replace i2 with (fst $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
apply linearize_pre_fv. }
assert (dom (gset _) m1 = set_seq i (i1-i)) as Hm1.
{ replace i1 with (fst $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
replace m1 with (snd $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
apply linearize_pre_dom. }
assert (dom (gset _) m2 = set_seq i1 (i2-i1)) as Hm2.
{ replace i2 with (fst $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
replace m2 with (snd $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
apply linearize_pre_dom. }
simpl. f_equiv.
{ apply IHT1. intros j Hj. simpl in *. trans ((m1 ∪ m2) !!! j).
- apply H1. set_solver.
- rewrite !lookup_total_alt. f_equiv.
apply lookup_union_l.
apply elem_of_dom. rewrite Hm1. naive_solver. }
{ apply IHT2. intros j Hj. simpl in *. trans ((m1 ∪ m2) !!! j).
- apply H1. set_solver.
- rewrite !lookup_total_alt. f_equiv.
apply lookup_union_r. apply not_elem_of_dom.
rewrite Hm1. set_unfold. naive_solver lia. }
- intros H1.
specialize (IHT1 i).
destruct (linearize_pre T1 i) as [[i1 m1] T1'] eqn:Ht1.
specialize (IHT2 i1).
destruct (linearize_pre T2 i1) as [[i2 m2] T2'] eqn:Ht2.
assert (term_fv T1' ⊆ set_seq i (i1-i)).
{ replace T1' with (snd (linearize_pre T1 i)) by rewrite Ht1 //.
replace i1 with (fst $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
apply linearize_pre_fv. }
assert (term_fv T2' ⊆ set_seq i1 (i2-i1)).
{ replace T2' with (snd (linearize_pre T2 i1)) by rewrite Ht2 //.
replace i2 with (fst $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
apply linearize_pre_fv. }
assert (dom (gset _) m1 = set_seq i (i1-i)) as Hm1.
{ replace i1 with (fst $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
replace m1 with (snd $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
apply linearize_pre_dom. }
assert (dom (gset _) m2 = set_seq i1 (i2-i1)) as Hm2.
{ replace i2 with (fst $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
replace m2 with (snd $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
apply linearize_pre_dom. }
simpl. f_equiv.
{ apply IHT1. intros j Hj. simpl in *. trans ((m1 ∪ m2) !!! j).
- apply H1. set_solver.
- rewrite !lookup_total_alt. f_equiv.
apply lookup_union_l.
apply elem_of_dom. rewrite Hm1. naive_solver. }
{ apply IHT2. intros j Hj. simpl in *. trans ((m1 ∪ m2) !!! j).
- apply H1. set_solver.
- rewrite !lookup_total_alt. f_equiv.
apply lookup_union_r. apply not_elem_of_dom.
rewrite Hm1. set_unfold. naive_solver lia. }
Qed.
Lemma linearize_bterm_act_ren Xs:
bterm_alg_act (linearize_bterm T) (linearize_bterm_ren_act Xs) ≡ bterm_alg_act T Xs.
Proof.
rewrite /linearize_bterm_ren_act /linearize_bterm_ren /linearize_bterm.
generalize 0.
induction T as [x | T1 IHT1 T2 IHT2 | T1 IHT1 T2 IHT2 ]=>i; simpl.
- by rewrite lookup_total_singleton.
- specialize (IHT1 i).
destruct (linearize_pre T1 i) as [[i1 m1] T1'] eqn:Ht1.
specialize (IHT2 i1).
destruct (linearize_pre T2 i1) as [[i2 m2] T2'] eqn:Ht2.
assert (term_fv T1' ⊆ set_seq i (i1-i)).
{ replace T1' with (snd (linearize_pre T1 i)) by rewrite Ht1 //.
replace i1 with (fst $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
apply linearize_pre_fv. }
assert (term_fv T2' ⊆ set_seq i1 (i2-i1)).
{ replace T2' with (snd (linearize_pre T2 i1)) by rewrite Ht2 //.
replace i2 with (fst $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
apply linearize_pre_fv. }
assert (dom (gset _) m1 = set_seq i (i1-i)) as Hm1.
{ replace i1 with (fst $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
replace m1 with (snd $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
apply linearize_pre_dom. }
assert (dom (gset _) m2 = set_seq i1 (i2-i1)) as Hm2.
{ replace i2 with (fst $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
replace m2 with (snd $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
apply linearize_pre_dom. }
simpl. repeat split; eauto.
rewrite -IHT1 -IHT2. f_equiv.
+ eapply bterm_alg_act_fv.
intros j Hj.
assert ((m1 ∪ m2) !!! j = m1 !!! j) as ->; eauto.
unfold lookup_total, map_lookup_total. f_equiv.
apply lookup_union_l, elem_of_dom. rewrite Hm1. set_solver by lia.
+ eapply bterm_alg_act_fv.
intros j Hj.
assert ((m1 ∪ m2) !!! j = m2 !!! j) as ->; eauto.
unfold lookup_total, map_lookup_total. f_equiv.
apply lookup_union_r. apply not_elem_of_dom. rewrite Hm1. set_solver by lia.
- specialize (IHT1 i).
destruct (linearize_pre T1 i) as [[i1 m1] T1'] eqn:Ht1.
specialize (IHT2 i1).
destruct (linearize_pre T2 i1) as [[i2 m2] T2'] eqn:Ht2.
assert (term_fv T1' ⊆ set_seq i (i1-i)).
{ replace T1' with (snd (linearize_pre T1 i)) by rewrite Ht1 //.
replace i1 with (fst $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
apply linearize_pre_fv. }
assert (term_fv T2' ⊆ set_seq i1 (i2-i1)).
{ replace T2' with (snd (linearize_pre T2 i1)) by rewrite Ht2 //.
replace i2 with (fst $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
apply linearize_pre_fv. }
assert (dom (gset _) m1 = set_seq i (i1-i)) as Hm1.
{ replace i1 with (fst $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
replace m1 with (snd $ fst (linearize_pre T1 i)) by rewrite Ht1 //.
apply linearize_pre_dom. }
assert (dom (gset _) m2 = set_seq i1 (i2-i1)) as Hm2.
{ replace i2 with (fst $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
replace m2 with (snd $ fst (linearize_pre T2 i1)) by rewrite Ht2 //.
apply linearize_pre_dom. }
simpl. repeat split; eauto.
rewrite -IHT1 -IHT2. f_equiv.
+ eapply bterm_alg_act_fv.
intros j Hj.
assert ((m1 ∪ m2) !!! j = m1 !!! j) as ->; eauto.
unfold lookup_total, map_lookup_total. f_equiv.
apply lookup_union_l, elem_of_dom. rewrite Hm1. set_solver by lia.
+ eapply bterm_alg_act_fv.
intros j Hj.
assert ((m1 ∪ m2) !!! j = m2 !!! j) as ->; eauto.
unfold lookup_total, map_lookup_total. f_equiv.
apply lookup_union_r. apply not_elem_of_dom. rewrite Hm1. set_solver by lia.
Qed.
End analytic_completion_correct.
Lemma analytic_completion_sound (s : structural_rule) (PROP : bi) :
rule_valid (analytic_completion s) PROP → rule_valid s PROP.
Proof.
rewrite /rule_valid /=.
set (T := snd s).
set (Ts := fst s).
intros H1 Xs.
rewrite - linearize_bterm_act_ren.
rewrite H1. apply bi.exist_elim=>Ti.
destruct Ti as [Ti HTi]. simpl.
apply elem_of_list_join in HTi.
destruct HTi as [L [HTi HL]].
apply elem_of_list_fmap_2 in HL.
destruct HL as [Tz [-> HTz]].
apply (bi.exist_intro' _ _ (Tz ↾ HTz)).
simpl in *. apply elem_of_elements in HTi.
eapply transformed_premise_act_ren in HTi.
by rewrite HTi.
Qed.
Lemma analytic_completion_complete (s : structural_rule) (PROP : bi) :
rule_valid s PROP → rule_valid (analytic_completion s) PROP.
Proof.
rewrite /rule_valid /=.
set (T := snd s).
set (Ts := fst s).
intros H1 Xs.
rewrite linearize_bterm_act.
rewrite H1. apply bi.exist_elim=>Ti.
destruct Ti as [Ti HTi]. simpl.
rewrite bterm_alg_act_disj_ren_inverse_transform.
apply bi.exist_elim=>Tk. apply bi.pure_elim_l=>Htk.
assert (Tk ∈ mjoin (fmap (elements ∘ transform_premise s) Ts)) as Tk'.
{ apply elem_of_list_join. exists (elements (transform_premise s Ti)).
split.
- by apply elem_of_elements.
- rewrite list_fmap_compose.
by do 2 apply elem_of_list_fmap_1. }
apply (bi.exist_intro' _ _ (Tk ↾ Tk')); done.
Qed.