cofe_solver.v 10.1 KB
Newer Older
1
From iris.algebra Require Export ofe.
2
Set Default Proof Using "Type".
Robbert Krebbers's avatar
Robbert Krebbers committed
3

4
Record solution (F : oFunctor) := Solution {
5 6
  solution_car :> ofeT;
  solution_cofe : Cofe solution_car;
7
  solution_iso :> ofe_iso (oFunctor_apply F solution_car) solution_car;
8
}.
9
Existing Instance solution_cofe.
10 11

Module solver. Section solver.
12
Context (F : oFunctor) `{Fcontr : oFunctorContractive F}.
13 14
Context `{Fcofe :  (T : ofeT) `{!Cofe T}, Cofe (oFunctor_apply F T)}.
Context `{Finh : Inhabited (oFunctor_apply F unitO)}.
15
Notation map := (oFunctor_map F).
Robbert Krebbers's avatar
Robbert Krebbers committed
16

17 18
Fixpoint A' (k : nat) : { C : ofeT & Cofe C } :=
  match k with
19
  | 0 => existT (P:=Cofe) unitO _
20
  | S k => existT (P:=Cofe) (@oFunctor_apply F (projT1 (A' k)) (projT2 (A' k))) _
21 22 23 24
  end.
Notation A k := (projT1 (A' k)).
Local Instance A_cofe k : Cofe (A k) := projT2 (A' k).

25
Fixpoint f (k : nat) : A k -n> A (S k) :=
26
  match k with 0 => OfeMor (λ _, inhabitant) | S k => map (g k,f k) end
27
with g (k : nat) : A (S k) -n> A k :=
28
  match k with 0 => OfeMor (λ _, ()) | S k => map (f k,g k) end.
29 30 31 32 33 34
Definition f_S k (x : A (S k)) : f (S k) x = map (g k,f k) x := eq_refl.
Definition g_S k (x : A (S (S k))) : g (S k) x = map (f k,g k) x := eq_refl.
Arguments f : simpl never.
Arguments g : simpl never.

Lemma gf {k} (x : A k) : g k (f k x)  x.
35
Proof using Fcontr.
Robbert Krebbers's avatar
Robbert Krebbers committed
36
  induction k as [|k IH]; simpl in *; [by destruct x|].
37 38
  rewrite -oFunctor_map_compose -{2}[x]oFunctor_map_id.
  by apply (contractive_proper map).
Robbert Krebbers's avatar
Robbert Krebbers committed
39
Qed.
40
Lemma fg {k} (x : A (S (S k))) : f (S k) (g (S k) x) {k} x.
41
Proof using Fcontr.
42
  induction k as [|k IH]; simpl.
43
  - rewrite f_S g_S -{2}[x]oFunctor_map_id -oFunctor_map_compose.
44
    apply (contractive_0 map).
45
  - rewrite f_S g_S -{2}[x]oFunctor_map_id -oFunctor_map_compose.
46
    by apply (contractive_S map).
Robbert Krebbers's avatar
Robbert Krebbers committed
47 48 49 50
Qed.

Record tower := {
  tower_car k :> A k;
51
  g_tower k : g k (tower_car (S k))  tower_car k
Robbert Krebbers's avatar
Robbert Krebbers committed
52 53
}.
Instance tower_equiv : Equiv tower := λ X Y,  k, X k  Y k.
54
Instance tower_dist : Dist tower := λ n X Y,  k, X k {n} Y k.
55
Definition tower_ofe_mixin : OfeMixin tower.
Robbert Krebbers's avatar
Robbert Krebbers committed
56 57
Proof.
  split.
58
  - intros X Y; split; [by intros HXY n k; apply equiv_dist|].
Robbert Krebbers's avatar
Robbert Krebbers committed
59
    intros HXY k; apply equiv_dist; intros n; apply HXY.
60
  - intros k; split.
Robbert Krebbers's avatar
Robbert Krebbers committed
61 62
    + by intros X n.
    + by intros X Y ? n.
63
    + by intros X Y Z ?? n; trans (Y n).
64
  - intros k X Y HXY n; apply dist_S.
Robbert Krebbers's avatar
Robbert Krebbers committed
65
    by rewrite -(g_tower X) (HXY (S n)) g_tower.
Robbert Krebbers's avatar
Robbert Krebbers committed
66
Qed.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
Definition T : ofeT := OfeT tower tower_ofe_mixin.

Program Definition tower_chain (c : chain T) (k : nat) : chain (A k) :=
  {| chain_car i := c i k |}.
Next Obligation. intros c k n i ?; apply (chain_cauchy c n); lia. Qed.
Program Definition tower_compl : Compl T := λ c,
  {| tower_car n := compl (tower_chain c n) |}.
Next Obligation.
  intros c k; apply equiv_dist=> n.
  by rewrite (conv_compl n (tower_chain c k))
    (conv_compl n (tower_chain c (S k))) /= (g_tower (c _) k).
Qed.
Global Program Instance tower_cofe : Cofe T := { compl := tower_compl }.
Next Obligation.
  intros n c k; rewrite /= (conv_compl n (tower_chain c k)).
  apply (chain_cauchy c); lia.
Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
84 85

Fixpoint ff {k} (i : nat) : A k -n> A (i + k) :=
86
  match i with 0 => cid | S i => f (i + k)  ff i end.
Robbert Krebbers's avatar
Robbert Krebbers committed
87
Fixpoint gg {k} (i : nat) : A (i + k) -n> A k :=
88
  match i with 0 => cid | S i => gg i  g (i + k) end.
Robbert Krebbers's avatar
Robbert Krebbers committed
89
Lemma ggff {k i} (x : A k) : gg i (ff i x)  x.
90
Proof using Fcontr. induction i as [|i IH]; simpl; [done|by rewrite (gf (ff i x)) IH]. Qed.
91
Lemma f_tower k (X : tower) : f (S k) (X (S k)) {k} X (S (S k)).
92
Proof using Fcontr. intros. by rewrite -(fg (X (S (S k)))) -(g_tower X). Qed.
93
Lemma ff_tower k i (X : tower) : ff i (X (S k)) {k} X (i + S k).
94
Proof using Fcontr.
Robbert Krebbers's avatar
Robbert Krebbers committed
95
  intros; induction i as [|i IH]; simpl; [done|].
Ralf Jung's avatar
Ralf Jung committed
96
  by rewrite IH Nat.add_succ_r (dist_le _ _ _ _ (f_tower _ X)); last lia.
Robbert Krebbers's avatar
Robbert Krebbers committed
97 98
Qed.
Lemma gg_tower k i (X : tower) : gg i (X (i + k))  X k.
Robbert Krebbers's avatar
Robbert Krebbers committed
99
Proof. by induction i as [|i IH]; simpl; [done|rewrite g_tower IH]. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
100

101
Instance tower_car_ne k : NonExpansive (λ X, tower_car X k).
Robbert Krebbers's avatar
Robbert Krebbers committed
102
Proof. by intros X Y HX. Qed.
103
Definition project (k : nat) : T -n> A k := OfeMor (λ X : T, tower_car X k).
Robbert Krebbers's avatar
Robbert Krebbers committed
104 105 106 107 108 109 110 111 112

Definition coerce {i j} (H : i = j) : A i -n> A j :=
  eq_rect _ (λ i', A i -n> A i') cid _ H.
Lemma coerce_id {i} (H : i = i) (x : A i) : coerce H x = x.
Proof. unfold coerce. by rewrite (proof_irrel H (eq_refl i)). Qed.
Lemma coerce_proper {i j} (x y : A i) (H1 H2 : i = j) :
  x = y  coerce H1 x = coerce H2 y.
Proof. by destruct H1; rewrite !coerce_id. Qed.
Lemma g_coerce {k j} (H : S k = S j) (x : A (S k)) :
113
  g j (coerce H x) = coerce (Nat.succ_inj _ _ H) (g k x).
Robbert Krebbers's avatar
Robbert Krebbers committed
114 115
Proof. by assert (k = j) by lia; subst; rewrite !coerce_id. Qed.
Lemma coerce_f {k j} (H : S k = S j) (x : A k) :
116
  coerce H (f k x) = f j (coerce (Nat.succ_inj _ _ H) x).
Robbert Krebbers's avatar
Robbert Krebbers committed
117
Proof. by assert (k = j) by lia; subst; rewrite !coerce_id. Qed.
118
Lemma gg_gg {k i i1 i2 j} :  (H1: k = i + j) (H2: k = i2 + (i1 + j)) (x: A k),
Robbert Krebbers's avatar
Robbert Krebbers committed
119 120
  gg i (coerce H1 x) = gg i1 (gg i2 (coerce H2 x)).
Proof.
121
  intros ? -> x. assert (i = i2 + i1) as -> by lia. revert j x H1.
122
  induction i2 as [|i2 IH]; intros j X H1; simplify_eq/=;
Robbert Krebbers's avatar
Robbert Krebbers committed
123
    [by rewrite coerce_id|by rewrite g_coerce IH].
Robbert Krebbers's avatar
Robbert Krebbers committed
124
Qed.
125
Lemma ff_ff {k i i1 i2 j} :  (H1: i + k = j) (H2: i1 + (i2 + k) = j) (x: A k),
Robbert Krebbers's avatar
Robbert Krebbers committed
126 127
  coerce H1 (ff i x) = coerce H2 (ff i1 (ff i2 x)).
Proof.
128
  intros ? <- x. assert (i = i1 + i2) as -> by lia.
129
  induction i1 as [|i1 IH]; simplify_eq/=;
Robbert Krebbers's avatar
Robbert Krebbers committed
130
    [by rewrite coerce_id|by rewrite coerce_f IH].
Robbert Krebbers's avatar
Robbert Krebbers committed
131 132
Qed.

133
Definition embed_coerce {k} (i : nat) : A k -n> A i :=
Robbert Krebbers's avatar
Robbert Krebbers committed
134 135 136 137
  match le_lt_dec i k with
  | left H => gg (k-i)  coerce (eq_sym (Nat.sub_add _ _ H))
  | right H => coerce (Nat.sub_add k i (Nat.lt_le_incl _ _ H))  ff (i-k)
  end.
138 139
Lemma g_embed_coerce {k i} (x : A k) :
  g i (embed_coerce (S i) x)  embed_coerce i x.
140
Proof using Fcontr.
141
  unfold embed_coerce; destruct (le_lt_dec (S i) k), (le_lt_dec i k); simpl.
142 143 144
  - symmetry; by erewrite (@gg_gg _ _ 1 (k - S i)); simpl.
  - exfalso; lia.
  - assert (i = k) by lia; subst.
Robbert Krebbers's avatar
Robbert Krebbers committed
145
    rewrite (ff_ff _ (eq_refl (1 + (0 + k)))) /= gf.
Robbert Krebbers's avatar
Robbert Krebbers committed
146
    by rewrite (gg_gg _ (eq_refl (0 + (0 + k)))).
147
  - assert (H : 1 + ((i - k) + k) = S i) by lia.
Robbert Krebbers's avatar
Robbert Krebbers committed
148
    rewrite (ff_ff _ H) /= -{2}(gf (ff (i - k) x)) g_coerce.
Robbert Krebbers's avatar
Robbert Krebbers committed
149 150
    by erewrite coerce_proper by done.
Qed.
151 152 153
Program Definition embed (k : nat) (x : A k) : T :=
  {| tower_car n := embed_coerce n x |}.
Next Obligation. intros k x i. apply g_embed_coerce. Qed.
154
Instance: Params (@embed) 1 := {}.
155 156
Instance embed_ne k : NonExpansive (embed k).
Proof. by intros n x y Hxy i; rewrite /= Hxy. Qed.
157
Definition embed' (k : nat) : A k -n> T := OfeMor (embed k).
158
Lemma embed_f k (x : A k) : embed (S k) (f k x)  embed k x.
Robbert Krebbers's avatar
Robbert Krebbers committed
159
Proof.
160
  rewrite equiv_dist=> n i; rewrite /embed /= /embed_coerce.
Robbert Krebbers's avatar
Robbert Krebbers committed
161
  destruct (le_lt_dec i (S k)), (le_lt_dec i k); simpl.
162
  - assert (H : S k = S (k - i) + (0 + i)) by lia; rewrite (gg_gg _ H) /=.
Robbert Krebbers's avatar
Robbert Krebbers committed
163
    by erewrite g_coerce, gf, coerce_proper by done.
164
  - assert (S k = 0 + (0 + i)) as H by lia.
165
    rewrite (gg_gg _ H); simplify_eq/=.
Robbert Krebbers's avatar
Robbert Krebbers committed
166
    by rewrite (ff_ff _ (eq_refl (1 + (0 + k)))).
167 168
  - exfalso; lia.
  - assert (H : (i - S k) + (1 + k) = i) by lia; rewrite (ff_ff _ H) /=.
Robbert Krebbers's avatar
Robbert Krebbers committed
169 170
    by erewrite coerce_proper by done.
Qed.
171
Lemma embed_tower k (X : T) : embed (S k) (X (S k)) {k} X.
Robbert Krebbers's avatar
Robbert Krebbers committed
172
Proof.
173 174
  intros i; rewrite /= /embed_coerce.
  destruct (le_lt_dec i (S k)) as [H|H]; simpl.
175
  - rewrite -(gg_tower i (S k - i) X).
Robbert Krebbers's avatar
Robbert Krebbers committed
176
    apply (_ : Proper (_ ==> _) (gg _)); by destruct (eq_sym _).
177
  - rewrite (ff_tower k (i - S k) X). by destruct (Nat.sub_add _ _ _).
Robbert Krebbers's avatar
Robbert Krebbers committed
178 179
Qed.

180
Program Definition unfold_chain (X : T) : chain (oFunctor_apply F T) :=
181
  {| chain_car n := map (project n,embed' n) (X (S n)) |}.
Robbert Krebbers's avatar
Robbert Krebbers committed
182 183 184
Next Obligation.
  intros X n i Hi.
  assert ( k, i = k + n) as [k ?] by (exists (i - n); lia); subst; clear Hi.
185
  induction k as [|k IH]; simpl; first done.
186
  rewrite -IH -(dist_le _ _ _ _ (f_tower (k + n) _)); last lia.
187
  rewrite f_S -oFunctor_map_compose.
188
  by apply (contractive_ne map); split=> Y /=; rewrite ?g_tower ?embed_f.
Robbert Krebbers's avatar
Robbert Krebbers committed
189
Qed.
190
Definition unfold (X : T) : oFunctor_apply F T := compl (unfold_chain X).
191
Instance unfold_ne : NonExpansive unfold.
192
Proof.
Robbert Krebbers's avatar
Robbert Krebbers committed
193
  intros n X Y HXY. by rewrite /unfold (conv_compl n (unfold_chain X))
194
    (conv_compl n (unfold_chain Y)) /= (HXY (S n)).
195
Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
196

197
Program Definition fold (X : oFunctor_apply F T) : T :=
198
  {| tower_car n := g n (map (embed' n,project n) X) |}.
Robbert Krebbers's avatar
Robbert Krebbers committed
199
Next Obligation.
200
  intros X k. apply (_ : Proper (() ==> ()) (g k)).
201
  rewrite g_S -oFunctor_map_compose.
202
  apply (contractive_proper map); split=> Y; [apply embed_f|apply g_tower].
Robbert Krebbers's avatar
Robbert Krebbers committed
203
Qed.
204
Instance fold_ne : NonExpansive fold.
205
Proof. by intros n X Y HXY k; rewrite /fold /= HXY. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
206

207
Theorem result : solution F.
208
Proof using Type*.
209
  refine (Solution F T _ (OfeIso (OfeMor fold) (OfeMor unfold) _ _)).
210
  - move=> X /=. rewrite equiv_dist=> n k; rewrite /unfold /fold /=.
211
    rewrite -g_tower -(gg_tower _ n); apply (_ : Proper (_ ==> _) (g _)).
212
    trans (map (ff n, gg n) (X (S (n + k)))).
Robbert Krebbers's avatar
Robbert Krebbers committed
213
    { rewrite /unfold (conv_compl n (unfold_chain X)).
214 215
      rewrite -(chain_cauchy (unfold_chain X) n (S (n + k))) /=; last lia.
      rewrite -(dist_le _ _ _ _ (f_tower (n + k) _)); last lia.
216
      rewrite f_S -!oFunctor_map_compose; apply (contractive_ne map); split=> Y.
217 218 219 220 221 222 223 224 225
      + rewrite /embed' /= /embed_coerce.
        destruct (le_lt_dec _ _); simpl; [exfalso; lia|].
        by rewrite (ff_ff _ (eq_refl (S n + (0 + k)))) /= gf.
      + rewrite /embed' /= /embed_coerce.
        destruct (le_lt_dec _ _); simpl; [|exfalso; lia].
        by rewrite (gg_gg _ (eq_refl (0 + (S n + k)))) /= gf. }
    assert ( i k (x : A (S i + k)) (H : S i + k = i + S k),
      map (ff i, gg i) x  gg i (coerce H x)) as map_ff_gg.
    { intros i; induction i as [|i IH]; intros k' x H; simpl.
226 227
      { by rewrite coerce_id oFunctor_map_id. }
      rewrite oFunctor_map_compose g_coerce; apply IH. }
228 229
    assert (H: S n + k = n + S k) by lia.
    rewrite (map_ff_gg _ _ _ H).
230
    apply (_ : Proper (_ ==> _) (gg _)); by destruct H.
231
  - intros X; rewrite equiv_dist=> n /=.
232
    rewrite /unfold /= (conv_compl' n (unfold_chain (fold X))) /=.
233
    rewrite g_S -!oFunctor_map_compose -{2}[X]oFunctor_map_id.
234
    apply (contractive_ne map); split => Y /=.
235
    + rewrite f_tower. apply dist_S. by rewrite embed_tower.
236
    + etrans; [apply embed_ne, equiv_dist, g_tower|apply embed_tower].
Robbert Krebbers's avatar
Robbert Krebbers committed
237
Qed.
238
End solver. End solver.