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

Merge branch 'robbert/sprop' into 'master'

Step-indexed propositions

See merge request iris/iris!304
parents 55aef759 9714dfdb
No related branches found
No related tags found
No related merge requests found
......@@ -42,6 +42,8 @@ Coq development, but not every API-breaking change is listed. Changes marked
* Removed `Core` type class for defining the total core; it is now always
defined in terms of the partial core. The only user of this type class was the
STS RA.
* Added the type `siProp` of "plain" step-indexed propositions, together with
basic proofmode support.
## Iris 3.2.0 (released 2019-08-29)
......
......@@ -41,6 +41,8 @@ theories/algebra/namespace_map.v
theories/algebra/lib/excl_auth.v
theories/algebra/lib/frac_auth.v
theories/algebra/lib/ufrac_auth.v
theories/si_logic/siprop.v
theories/si_logic/bi.v
theories/bi/notation.v
theories/bi/interface.v
theories/bi/derived_connectives.v
......
From iris.proofmode Require Import tactics .
From iris.si_logic Require Import bi.
Set Ltac Backtrace.
Section si_logic_tests.
Implicit Types P Q R : siProp.
Lemma test_everything_persistent P : P -∗ P.
Proof. by iIntros "#HP". Qed.
Lemma test_everything_affine P : P -∗ True.
Proof. by iIntros "_". Qed.
Lemma test_iIntro_impl P Q R : (P Q R P R)%I.
Proof. iIntros "#HP #[HQ HR]". auto. Qed.
Lemma test_iApply_impl_1 P Q R : (P (P Q) Q)%I.
Proof. iIntros "HP HPQ". by iApply "HPQ". Qed.
Lemma test_iApply_impl_2 P Q R : (P (P Q) Q)%I.
Proof. iIntros "#HP #HPQ". by iApply "HPQ". Qed.
End si_logic_tests.
From iris.bi Require Export bi.
From iris.si_logic Require Export siprop.
Import siProp_primitive.
(** BI instances for [siProp], and re-stating the remaining primitive laws in
terms of the BI interface. This file does *not* unseal. *)
(** We pick [*] and [-*] to coincide with [∧] and [→], respectively. This seems
to be the most reasonable choice to fit a "pure" higher-order logic into the
proofmode's BI framework. *)
Definition siProp_emp : siProp := siProp_pure True.
Definition siProp_sep : siProp siProp siProp := siProp_and.
Definition siProp_wand : siProp siProp siProp := siProp_impl.
Definition siProp_persistently (P : siProp) : siProp := P.
Definition siProp_plainly (P : siProp) : siProp := P.
Local Existing Instance entails_po.
Lemma siProp_bi_mixin :
BiMixin
siProp_entails siProp_emp siProp_pure siProp_and siProp_or siProp_impl
(@siProp_forall) (@siProp_exist) siProp_sep siProp_wand
siProp_persistently.
Proof.
split.
- exact: entails_po.
- exact: equiv_spec.
- exact: pure_ne.
- exact: and_ne.
- exact: or_ne.
- exact: impl_ne.
- exact: forall_ne.
- exact: exist_ne.
- exact: and_ne.
- exact: impl_ne.
- solve_proper.
- exact: pure_intro.
- exact: pure_elim'.
- exact: @pure_forall_2.
- exact: and_elim_l.
- exact: and_elim_r.
- exact: and_intro.
- exact: or_intro_l.
- exact: or_intro_r.
- exact: or_elim.
- exact: impl_intro_r.
- exact: impl_elim_l'.
- exact: @forall_intro.
- exact: @forall_elim.
- exact: @exist_intro.
- exact: @exist_elim.
- (* (P ⊢ Q) → (P' ⊢ Q') → P ∗ P' ⊢ Q ∗ Q' *)
intros P P' Q Q' H1 H2. apply and_intro.
+ by etrans; first apply and_elim_l.
+ by etrans; first apply and_elim_r.
- (* P ⊢ emp ∗ P *)
intros P. apply and_intro; last done. by apply pure_intro.
- (* emp ∗ P ⊢ P *)
intros P. apply and_elim_r.
- (* P ∗ Q ⊢ Q ∗ P *)
intros P Q. apply and_intro. apply and_elim_r. apply and_elim_l.
- (* (P ∗ Q) ∗ R ⊢ P ∗ (Q ∗ R) *)
intros P Q R. repeat apply and_intro.
+ etrans; first apply and_elim_l. by apply and_elim_l.
+ etrans; first apply and_elim_l. by apply and_elim_r.
+ apply and_elim_r.
- (* (P ∗ Q ⊢ R) → P ⊢ Q -∗ R *)
apply impl_intro_r.
- (* (P ⊢ Q -∗ R) → P ∗ Q ⊢ R *)
apply impl_elim_l'.
- (* (P ⊢ Q) → <pers> P ⊢ <pers> Q *)
done.
- (* <pers> P ⊢ <pers> <pers> P *)
done.
- (* emp ⊢ <pers> emp *)
done.
- (* (∀ a, <pers> (Ψ a)) ⊢ <pers> (∀ a, Ψ a) *)
done.
- (* <pers> (∃ a, Ψ a) ⊢ ∃ a, <pers> (Ψ a) *)
done.
- (* <pers> P ∗ Q ⊢ <pers> P *)
apply and_elim_l.
- (* <pers> P ∧ Q ⊢ P ∗ Q *)
done.
Qed.
Lemma siProp_sbi_mixin : SbiMixin
siProp_entails siProp_pure siProp_or siProp_impl
(@siProp_forall) (@siProp_exist) siProp_sep
siProp_persistently (@siProp_internal_eq) siProp_later.
Proof.
split.
- exact: later_contractive.
- exact: internal_eq_ne.
- exact: @internal_eq_refl.
- exact: @internal_eq_rewrite.
- exact: @fun_ext.
- exact: @sig_eq.
- exact: @discrete_eq_1.
- exact: @later_eq_1.
- exact: @later_eq_2.
- exact: later_mono.
- exact: later_intro.
- exact: @later_forall_2.
- exact: @later_exist_false.
- (* ▷ (P ∗ Q) ⊢ ▷ P ∗ ▷ Q *)
intros P Q.
apply and_intro; apply later_mono. apply and_elim_l. apply and_elim_r.
- (* ▷ P ∗ ▷ Q ⊢ ▷ (P ∗ Q) *)
intros P Q.
trans (siProp_forall (λ b : bool, siProp_later (if b then P else Q))).
{ apply forall_intro=> -[]. apply and_elim_l. apply and_elim_r. }
etrans; [apply later_forall_2|apply later_mono].
apply and_intro. refine (forall_elim true). refine (forall_elim false).
- (* ▷ <pers> P ⊢ <pers> ▷ P *)
done.
- (* <pers> ▷ P ⊢ ▷ <pers> P *)
done.
- exact: later_false_em.
Qed.
Canonical Structure siPropI : bi :=
{| bi_ofe_mixin := ofe_mixin_of siProp; bi_bi_mixin := siProp_bi_mixin |}.
Canonical Structure siPropSI : sbi :=
{| sbi_ofe_mixin := ofe_mixin_of siProp;
sbi_bi_mixin := siProp_bi_mixin; sbi_sbi_mixin := siProp_sbi_mixin |}.
Coercion siProp_valid (P : siProp) : Prop := bi_emp_valid P.
Lemma siProp_plainly_mixin : BiPlainlyMixin siPropSI siProp_plainly.
Proof.
split; try done.
- solve_proper.
- (* P ⊢ ■ emp *)
intros P. by apply pure_intro.
- (* ■ P ∗ Q ⊢ ■ P *)
intros P Q. apply and_elim_l.
- (* ■ ((P -∗ Q) ∧ (Q -∗ P)) ⊢ P ≡ Q *)
intros P Q. apply prop_ext_2.
Qed.
Global Instance siProp_plainlyC : BiPlainly siPropSI :=
{| bi_plainly_mixin := siProp_plainly_mixin |}.
(** extra BI instances *)
Global Instance siProp_affine : BiAffine siPropI | 0.
Proof. intros P. exact: pure_intro. Qed.
(* Also add this to the global hint database, otherwise [eauto] won't work for
many lemmas that have [BiAffine] as a premise. *)
Hint Immediate siProp_affine : core.
Global Instance siProp_plain (P : siProp) : Plain P | 0.
Proof. done. Qed.
Global Instance siProp_persistent (P : siProp) : Persistent P.
Proof. done. Qed.
Global Instance siProp_plainly_exist_1 : BiPlainlyExist siPropSI.
Proof. done. Qed.
(** Re-state/export soundness lemmas *)
Module siProp.
Section restate.
Lemma pure_soundness φ : bi_emp_valid (PROP:=siPropI) φ φ.
Proof. apply pure_soundness. Qed.
Lemma internal_eq_soundness {A : ofeT} (x y : A) : (True ⊢@{siPropI} x y) x y.
Proof. apply internal_eq_soundness. Qed.
Lemma later_soundness P : bi_emp_valid (PROP:=siPropI) ( P) bi_emp_valid P.
Proof. apply later_soundness. Qed.
End restate.
End siProp.
From iris.algebra Require Export ofe.
From iris.bi Require Import notation.
(** The type [siProp] defines "plain" step-indexed propositions, on which we
define the usual connectives of higher-order logic, and prove that these satisfy
the usual laws of higher-order logic. *)
Record siProp := SiProp {
siProp_holds :> nat Prop;
siProp_closed n1 n2 : siProp_holds n1 n2 n1 siProp_holds n2
}.
Arguments siProp_holds : simpl never.
Add Printing Constructor siProp.
Delimit Scope siProp_scope with SI.
Bind Scope siProp_scope with siProp.
Section cofe.
Inductive siProp_equiv' (P Q : siProp) : Prop :=
{ siProp_in_equiv : n, P n Q n }.
Instance siProp_equiv : Equiv siProp := siProp_equiv'.
Inductive siProp_dist' (n : nat) (P Q : siProp) : Prop :=
{ siProp_in_dist : n', n' n P n' Q n' }.
Instance siProp_dist : Dist siProp := siProp_dist'.
Definition siProp_ofe_mixin : OfeMixin siProp.
Proof.
split.
- intros P Q; split.
+ by intros HPQ n; split=> i ?; apply HPQ.
+ intros HPQ; split=> n; apply HPQ with n; auto.
- intros n; split.
+ by intros P; split=> i.
+ by intros P Q HPQ; split=> i ?; symmetry; apply HPQ.
+ intros P Q Q' HP HQ; split=> i ?.
by trans (Q i);[apply HP|apply HQ].
- intros n P Q HPQ; split=> i ?; apply HPQ; auto.
Qed.
Canonical Structure siPropC : ofeT := OfeT siProp siProp_ofe_mixin.
Program Definition siProp_compl : Compl siPropC := λ c,
{| siProp_holds n := c n n |}.
Next Obligation.
intros c n1 n2 ??; simpl in *.
apply (chain_cauchy c n2 n1); eauto using siProp_closed.
Qed.
Global Program Instance siProp_cofe : Cofe siPropC := {| compl := siProp_compl |}.
Next Obligation.
intros n c; split=>i ?; symmetry; apply (chain_cauchy c i n); auto.
Qed.
End cofe.
(** logical entailement *)
Inductive siProp_entails (P Q : siProp) : Prop :=
{ siProp_in_entails : n, P n Q n }.
Hint Resolve siProp_closed : siProp_def.
(** logical connectives *)
Program Definition siProp_pure_def (φ : Prop) : siProp :=
{| siProp_holds n := φ |}.
Solve Obligations with done.
Definition siProp_pure_aux : seal (@siProp_pure_def). by eexists. Qed.
Definition siProp_pure := unseal siProp_pure_aux.
Definition siProp_pure_eq :
@siProp_pure = @siProp_pure_def := seal_eq siProp_pure_aux.
Program Definition siProp_and_def (P Q : siProp) : siProp :=
{| siProp_holds n := P n Q n |}.
Solve Obligations with naive_solver eauto 2 with siProp_def.
Definition siProp_and_aux : seal (@siProp_and_def). by eexists. Qed.
Definition siProp_and := unseal siProp_and_aux.
Definition siProp_and_eq: @siProp_and = @siProp_and_def := seal_eq siProp_and_aux.
Program Definition siProp_or_def (P Q : siProp) : siProp :=
{| siProp_holds n := P n Q n |}.
Solve Obligations with naive_solver eauto 2 with siProp_def.
Definition siProp_or_aux : seal (@siProp_or_def). by eexists. Qed.
Definition siProp_or := unseal siProp_or_aux.
Definition siProp_or_eq: @siProp_or = @siProp_or_def := seal_eq siProp_or_aux.
Program Definition siProp_impl_def (P Q : siProp) : siProp :=
{| siProp_holds n := n', n' n P n' Q n' |}.
Next Obligation. intros P Q [|n1] [|n2]; auto with lia. Qed.
Definition siProp_impl_aux : seal (@siProp_impl_def). by eexists. Qed.
Definition siProp_impl := unseal siProp_impl_aux.
Definition siProp_impl_eq :
@siProp_impl = @siProp_impl_def := seal_eq siProp_impl_aux.
Program Definition siProp_forall_def {A} (Ψ : A siProp) : siProp :=
{| siProp_holds n := a, Ψ a n |}.
Solve Obligations with naive_solver eauto 2 with siProp_def.
Definition siProp_forall_aux : seal (@siProp_forall_def). by eexists. Qed.
Definition siProp_forall {A} := unseal siProp_forall_aux A.
Definition siProp_forall_eq :
@siProp_forall = @siProp_forall_def := seal_eq siProp_forall_aux.
Program Definition siProp_exist_def {A} (Ψ : A siProp) : siProp :=
{| siProp_holds n := a, Ψ a n |}.
Solve Obligations with naive_solver eauto 2 with siProp_def.
Definition siProp_exist_aux : seal (@siProp_exist_def). by eexists. Qed.
Definition siProp_exist {A} := unseal siProp_exist_aux A.
Definition siProp_exist_eq: @siProp_exist = @siProp_exist_def := seal_eq siProp_exist_aux.
Program Definition siProp_internal_eq_def {A : ofeT} (a1 a2 : A) : siProp :=
{| siProp_holds n := a1 {n} a2 |}.
Solve Obligations with naive_solver eauto 2 using (dist_le (A:=A)).
Definition siProp_internal_eq_aux : seal (@siProp_internal_eq_def). by eexists. Qed.
Definition siProp_internal_eq {A} := unseal siProp_internal_eq_aux A.
Definition siProp_internal_eq_eq:
@siProp_internal_eq = @siProp_internal_eq_def := seal_eq siProp_internal_eq_aux.
Program Definition siProp_later_def (P : siProp) : siProp :=
{| siProp_holds n := match n return _ with 0 => True | S n' => P n' end |}.
Next Obligation. intros P [|n1] [|n2]; eauto using siProp_closed with lia. Qed.
Definition siProp_later_aux : seal (@siProp_later_def). by eexists. Qed.
Definition siProp_later := unseal siProp_later_aux.
Definition siProp_later_eq :
@siProp_later = @siProp_later_def := seal_eq siProp_later_aux.
(** Primitive logical rules.
These are not directly usable later because they do not refer to the BI
connectives. *)
Module siProp_primitive.
Definition unseal_eqs :=
(siProp_pure_eq, siProp_and_eq, siProp_or_eq, siProp_impl_eq, siProp_forall_eq,
siProp_exist_eq, siProp_internal_eq_eq, siProp_later_eq).
Ltac unseal := rewrite !unseal_eqs /=.
Section primitive.
Arguments siProp_holds !_ _ /.
Notation "P ⊢ Q" := (siProp_entails P Q)
(at level 99, Q at level 200, right associativity).
Notation "'True'" := (siProp_pure True) : siProp_scope.
Notation "'False'" := (siProp_pure False) : siProp_scope.
Notation "'⌜' φ '⌝'" := (siProp_pure φ%type%stdpp) : siProp_scope.
Infix "∧" := siProp_and : siProp_scope.
Infix "∨" := siProp_or : siProp_scope.
Infix "→" := siProp_impl : siProp_scope.
Notation "∀ x .. y , P" := (siProp_forall (λ x, .. (siProp_forall (λ y, P%SI)) ..)) : siProp_scope.
Notation "∃ x .. y , P" := (siProp_exist (λ x, .. (siProp_exist (λ y, P%SI)) ..)) : siProp_scope.
Notation "x ≡ y" := (siProp_internal_eq x y) : siProp_scope.
Notation "▷ P" := (siProp_later P) (at level 20, right associativity) : siProp_scope.
(** Below there follow the primitive laws for [siProp]. There are no derived laws
in this file. *)
(** Entailment *)
Lemma entails_po : PreOrder siProp_entails.
Proof.
split.
- intros P; by split=> i.
- intros P Q Q' HP HQ; split=> i ?; by apply HQ, HP.
Qed.
Lemma entails_anti_symm : AntiSymm () siProp_entails.
Proof. intros P Q HPQ HQP; split=> n; by split; [apply HPQ|apply HQP]. Qed.
Lemma equiv_spec P Q : (P Q) (P Q) (Q P).
Proof.
split.
- intros HPQ; split; split=> i; apply HPQ.
- intros [??]. by apply entails_anti_symm.
Qed.
(** Non-expansiveness and setoid morphisms *)
Lemma pure_ne n : Proper (iff ==> dist n) siProp_pure.
Proof. intros φ1 φ2 . by unseal. Qed.
Lemma and_ne : NonExpansive2 siProp_and.
Proof.
intros n P P' HP Q Q' HQ; unseal; split=> n' ?.
split; (intros [??]; split; [by apply HP|by apply HQ]).
Qed.
Lemma or_ne : NonExpansive2 siProp_or.
Proof.
intros n P P' HP Q Q' HQ; split=> n' ?.
unseal; split; (intros [?|?]; [left; by apply HP|right; by apply HQ]).
Qed.
Lemma impl_ne : NonExpansive2 siProp_impl.
Proof.
intros n P P' HP Q Q' HQ; split=> n' ?.
unseal; split; intros HPQ n'' ??; apply HQ, HPQ, HP; auto with lia.
Qed.
Lemma forall_ne A n :
Proper (pointwise_relation _ (dist n) ==> dist n) (@siProp_forall A).
Proof.
by intros Ψ1 Ψ2 ; unseal; split=> n' x; split; intros HP a; apply .
Qed.
Lemma exist_ne A n :
Proper (pointwise_relation _ (dist n) ==> dist n) (@siProp_exist A).
Proof.
intros Ψ1 Ψ2 .
unseal; split=> n' ?; split; intros [a ?]; exists a; by apply .
Qed.
Lemma later_contractive : Contractive siProp_later.
Proof.
unseal; intros [|n] P Q HPQ; split=> -[|n'] ? //=; try lia.
apply HPQ; lia.
Qed.
Lemma internal_eq_ne (A : ofeT) : NonExpansive2 (@siProp_internal_eq A).
Proof.
intros n x x' Hx y y' Hy; split=> n' z; unseal; split; intros; simpl in *.
- by rewrite -(dist_le _ _ _ _ Hx) -?(dist_le _ _ _ _ Hy); auto.
- by rewrite (dist_le _ _ _ _ Hx) ?(dist_le _ _ _ _ Hy); auto.
Qed.
(** Introduction and elimination rules *)
Lemma pure_intro (φ : Prop) P : φ P φ ⌝.
Proof. intros ?. unseal; by split. Qed.
Lemma pure_elim' (φ : Prop) P : (φ True P) φ P.
Proof. unseal=> HP; split=> n ?. by apply HP. Qed.
Lemma pure_forall_2 {A} (φ : A Prop) : ( a, φ a ) a, φ a ⌝.
Proof. by unseal. Qed.
Lemma and_elim_l P Q : P Q P.
Proof. unseal; by split=> n [??]. Qed.
Lemma and_elim_r P Q : P Q Q.
Proof. unseal; by split=> n [??]. Qed.
Lemma and_intro P Q R : (P Q) (P R) P Q R.
Proof. intros HQ HR; unseal; split=> n ?; by split; [apply HQ|apply HR]. Qed.
Lemma or_intro_l P Q : P P Q.
Proof. unseal; split=> n ?; left; auto. Qed.
Lemma or_intro_r P Q : Q P Q.
Proof. unseal; split=> n ?; right; auto. Qed.
Lemma or_elim P Q R : (P R) (Q R) P Q R.
Proof. intros HP HQ. unseal; split=> n [?|?]. by apply HP. by apply HQ. Qed.
Lemma impl_intro_r P Q R : (P Q R) P Q R.
Proof.
unseal=> HQ; split=> n ? n' ??.
apply HQ; naive_solver eauto using siProp_closed.
Qed.
Lemma impl_elim_l' P Q R : (P Q R) P Q R.
Proof. unseal=> HP; split=> n [??]. apply HP with n; auto. Qed.
Lemma forall_intro {A} P (Ψ : A siProp) : ( a, P Ψ a) P a, Ψ a.
Proof. unseal; intros HPΨ; split=> n ? a; by apply HPΨ. Qed.
Lemma forall_elim {A} {Ψ : A siProp} a : ( a, Ψ a) Ψ a.
Proof. unseal; split=> n HP; apply HP. Qed.
Lemma exist_intro {A} {Ψ : A siProp} a : Ψ a a, Ψ a.
Proof. unseal; split=> n ?; by exists a. Qed.
Lemma exist_elim {A} (Φ : A siProp) Q : ( a, Φ a Q) ( a, Φ a) Q.
Proof. unseal; intros ; split=> n [a ?]; by apply with a. Qed.
(** Equality *)
Lemma internal_eq_refl {A : ofeT} P (a : A) : P (a a).
Proof. unseal; by split=> n ? /=. Qed.
Lemma internal_eq_rewrite {A : ofeT} a b (Ψ : A siProp) :
NonExpansive Ψ a b Ψ a Ψ b.
Proof.
intros Hnonexp. unseal; split=> n Hab n' ? . eapply Hnonexp with n a; auto.
Qed.
Lemma fun_ext {A} {B : A ofeT} (f g : discrete_fun B) : ( x, f x g x) f g.
Proof. by unseal. Qed.
Lemma sig_eq {A : ofeT} (P : A Prop) (x y : sig P) : `x `y x y.
Proof. by unseal. Qed.
Lemma discrete_eq_1 {A : ofeT} (a b : A) : Discrete a a b a b⌝.
Proof. unseal=> ?. split=> n. by apply (discrete_iff n). Qed.
Lemma prop_ext_2 P Q : ((P Q) (Q P)) P Q.
Proof.
unseal; split=> n /= HPQ. split=> n' ?.
move: HPQ=> [] /(_ n') ? /(_ n'). naive_solver.
Qed.
(** Later *)
Lemma later_eq_1 {A : ofeT} (x y : A) : Next x Next y (x y).
Proof. by unseal. Qed.
Lemma later_eq_2 {A : ofeT} (x y : A) : (x y) Next x Next y.
Proof. by unseal. Qed.
Lemma later_mono P Q : (P Q) P Q.
Proof. unseal=> HP; split=>-[|n]; [done|apply HP; eauto using cmra_validN_S]. Qed.
Lemma later_intro P : P P.
Proof. unseal; split=> -[|n] /= HP; eauto using siProp_closed. Qed.
Lemma later_forall_2 {A} (Φ : A siProp) : ( a, Φ a) a, Φ a.
Proof. unseal; by split=> -[|n]. Qed.
Lemma later_exist_false {A} (Φ : A siProp) :
( a, Φ a) False ( a, Φ a).
Proof. unseal; split=> -[|[|n]] /=; eauto. Qed.
Lemma later_false_em P : P False ( False P).
Proof.
unseal; split=> -[|n] /= HP; [by left|right].
intros [|n'] ?; eauto using siProp_closed with lia.
Qed.
(** Consistency/soundness statement *)
Lemma pure_soundness φ : (True φ ) φ.
Proof. unseal=> -[H]. by apply (H 0). Qed.
Lemma internal_eq_soundness {A : ofeT} (x y : A) : (True x y) x y.
Proof. unseal=> -[H]. apply equiv_dist=> n. by apply (H n). Qed.
Lemma later_soundness P : (True P) (True P).
Proof.
unseal=> -[HP]; split=> n _. apply siProp_closed with n; last done.
by apply (HP (S n)).
Qed.
End primitive.
End siProp_primitive.
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