KM.Sequent.Sequents
Sequent calculus G4KM
Reserved Notation "Γ ⊢ Δ" (at level 99, no associativity, Δ at level 90).
Inductive Provable : env -> env -> Type :=
| Atom : ∀ Γ Δ p, Γ • Var p ⊢ Δ • Var p
| ExFalso : ∀ Γ Δ, Γ • ⊥ ⊢ Δ
| AndR : ∀ Γ Δ φ ψ,
Γ ⊢ Δ • φ -> Γ ⊢ Δ • ψ ->
Γ ⊢ Δ • φ ∧ ψ
| AndL : ∀ Γ Δ φ ψ,
Γ • φ • ψ ⊢ Δ ->
Γ • φ ∧ ψ ⊢ Δ
| OrR : ∀ Γ Δ φ ψ,
Γ ⊢ Δ • φ • ψ ->
Γ ⊢ Δ • φ ∨ ψ
| OrL : ∀ Γ Δ φ ψ,
Γ • φ ⊢ Δ -> Γ • ψ ⊢ Δ ->
Γ • φ ∨ ψ ⊢ Δ
| ImpR : ∀ Γ Δ φ ψ,
Γ • φ ⊢ Δ • ψ -> (⊗ Γ) • φ ⊢ ∅ • ψ ->
Γ ⊢ Δ • (φ → ψ)
| ImpLVar : ∀ Γ Δ p φ,
Γ • Var p • φ ⊢ Δ ->
Γ • Var p • (Var p → φ) ⊢ Δ
| ImpLAnd : ∀ Γ Δ φ1 φ2 φ3,
Γ • (φ1 → φ2 → φ3) ⊢ Δ ->
Γ • ((φ1 ∧ φ2) → φ3) ⊢ Δ
| ImpLOr : ∀ Γ Δ φ1 φ2 φ3,
Γ • (φ1 → φ3) • (φ2 → φ3) ⊢ Δ ->
Γ • ((φ1 ∨ φ2) → φ3) ⊢ Δ
| ImpLImp : ∀ Γ Δ φ1 φ2 φ3,
Γ • (φ2 → φ3) • φ1 ⊢ Δ • φ2 -> ⊗ Γ • (φ2 → φ3) • φ1 ⊢ ∅ • φ2 -> Γ • φ3 ⊢ Δ ->
Γ • ((φ1 → φ2) → φ3) ⊢ Δ
| ImpLBox : ∀ Γ Δ φ1 φ2,
(⊗ Γ) • □ φ1 • φ2 ⊢ ∅ • φ1 ->
Γ • φ2 ⊢ Δ ->
Γ • ((□ φ1) → φ2) ⊢ Δ
| BoxR : ∀ Γ Δ φ, (⊗ Γ) • □ φ ⊢ ∅ • φ -> Γ ⊢ Δ • □ φ
where "Γ ⊢ Δ" := (Provable Γ Δ).
Notation "Γ ⊢KM Δ" := (Provable Γ Δ) (at level 99, no associativity, Δ at level 90).
Global Hint Constructors Provable : proof.
Inductive Provable : env -> env -> Type :=
| Atom : ∀ Γ Δ p, Γ • Var p ⊢ Δ • Var p
| ExFalso : ∀ Γ Δ, Γ • ⊥ ⊢ Δ
| AndR : ∀ Γ Δ φ ψ,
Γ ⊢ Δ • φ -> Γ ⊢ Δ • ψ ->
Γ ⊢ Δ • φ ∧ ψ
| AndL : ∀ Γ Δ φ ψ,
Γ • φ • ψ ⊢ Δ ->
Γ • φ ∧ ψ ⊢ Δ
| OrR : ∀ Γ Δ φ ψ,
Γ ⊢ Δ • φ • ψ ->
Γ ⊢ Δ • φ ∨ ψ
| OrL : ∀ Γ Δ φ ψ,
Γ • φ ⊢ Δ -> Γ • ψ ⊢ Δ ->
Γ • φ ∨ ψ ⊢ Δ
| ImpR : ∀ Γ Δ φ ψ,
Γ • φ ⊢ Δ • ψ -> (⊗ Γ) • φ ⊢ ∅ • ψ ->
Γ ⊢ Δ • (φ → ψ)
| ImpLVar : ∀ Γ Δ p φ,
Γ • Var p • φ ⊢ Δ ->
Γ • Var p • (Var p → φ) ⊢ Δ
| ImpLAnd : ∀ Γ Δ φ1 φ2 φ3,
Γ • (φ1 → φ2 → φ3) ⊢ Δ ->
Γ • ((φ1 ∧ φ2) → φ3) ⊢ Δ
| ImpLOr : ∀ Γ Δ φ1 φ2 φ3,
Γ • (φ1 → φ3) • (φ2 → φ3) ⊢ Δ ->
Γ • ((φ1 ∨ φ2) → φ3) ⊢ Δ
| ImpLImp : ∀ Γ Δ φ1 φ2 φ3,
Γ • (φ2 → φ3) • φ1 ⊢ Δ • φ2 -> ⊗ Γ • (φ2 → φ3) • φ1 ⊢ ∅ • φ2 -> Γ • φ3 ⊢ Δ ->
Γ • ((φ1 → φ2) → φ3) ⊢ Δ
| ImpLBox : ∀ Γ Δ φ1 φ2,
(⊗ Γ) • □ φ1 • φ2 ⊢ ∅ • φ1 ->
Γ • φ2 ⊢ Δ ->
Γ • ((□ φ1) → φ2) ⊢ Δ
| BoxR : ∀ Γ Δ φ, (⊗ Γ) • □ φ ⊢ ∅ • φ -> Γ ⊢ Δ • □ φ
where "Γ ⊢ Δ" := (Provable Γ Δ).
Notation "Γ ⊢KM Δ" := (Provable Γ Δ) (at level 99, no associativity, Δ at level 90).
Global Hint Constructors Provable : proof.
We show that equivalent multisets prove the same things.
Global Instance proper_Provable : Proper ((≡@{env}) ==> (≡@{env}) ==> (=)) Provable.
Proof. intros Γ Γ' Heq Δ Δ' Heq'. ms. Qed.
Global Ltac equiv_tac :=
repeat rewrite <- list_to_set_disj_rm;
repeat rewrite <- list_to_set_disj_env_add;
repeat (rewrite <- difference_singleton; trivial);
try rewrite <- list_to_set_disj_rm;
try (rewrite union_difference_L by trivial);
try (rewrite union_difference_R by trivial);
try ms.
Proof. intros Γ Γ' Heq Δ Δ' Heq'. ms. Qed.
Global Ltac equiv_tac :=
repeat rewrite <- list_to_set_disj_rm;
repeat rewrite <- list_to_set_disj_env_add;
repeat (rewrite <- difference_singleton; trivial);
try rewrite <- list_to_set_disj_rm;
try (rewrite union_difference_L by trivial);
try (rewrite union_difference_R by trivial);
try ms.
We introduce a tactic "peapply" which allows for application of a G4ip rule
even in case the left environment needs to be reordered. The tactic "rpeapply"
does the same thing on the right.
Ltac peapply th :=
(erewrite proper_Provable; [| |reflexivity]); [eapply th|auto with proof; try ms].
Ltac rpeapply th :=
(erewrite proper_Provable; [| reflexivity |]); [eapply th| auto with proof; try ms].
(erewrite proper_Provable; [| |reflexivity]); [eapply th|auto with proof; try ms].
Ltac rpeapply th :=
(erewrite proper_Provable; [| reflexivity |]); [eapply th| auto with proof; try ms].
Tactics
Ltac exchl n := match n with
| O => match goal with |- ?a • ?b • ?c ⊢ _ =>
rewrite (proper_Provable _ _ (env_add_comm a b c) _ _ (env_refl _)) end
| S O => rewrite (proper_Provable _ _ (equiv_disj_union_compat_r (env_add_comm _ _ _)) _ _ (env_refl _))
| S (S O) => rewrite (proper_Provable _ _ (equiv_disj_union_compat_r(equiv_disj_union_compat_r (env_add_comm _ _ _))) _ _ (env_refl _))
| S (S (S O)) => rewrite (proper_Provable _ _ (equiv_disj_union_compat_r(equiv_disj_union_compat_r(equiv_disj_union_compat_r (env_add_comm _ _ _)))) _ _ (env_refl _))
end.
Ltac exchr n := match n with
| O => match goal with |- _ ⊢ (?a • ?b • ?c) =>
rewrite (proper_Provable _ _ (env_refl _) _ _ (env_add_comm a b c)) end
| S O => rewrite (proper_Provable _ _ (env_refl _) _ _ (equiv_disj_union_compat_r (env_add_comm _ _ _)))
| S (S O) => rewrite (proper_Provable _ _ (env_refl _) _ _ (equiv_disj_union_compat_r(equiv_disj_union_compat_r (env_add_comm _ _ _))))
| S (S (S O)) => rewrite (proper_Provable _ _ (env_refl _) _ _ (equiv_disj_union_compat_r(equiv_disj_union_compat_r(equiv_disj_union_compat_r (env_add_comm _ _ _)))))
end.
The tactic "exhibit" exhibits an element that is in the environment on the left or right hand side.
Ltac exhibit Hin n := match n with
| 0 => rewrite (proper_Provable _ _ (env_refl _) _ _
(symmetry (difference_singleton _ _ Hin)))
|| rewrite (proper_Provable _ _
(symmetry (difference_singleton _ _ Hin)) _ _ (env_refl _))
| 1 => rewrite (proper_Provable _ _ (env_refl _) _ _
(equiv_disj_union_compat_r (symmetry (difference_singleton _ _ Hin))))
|| rewrite (proper_Provable _ _ (equiv_disj_union_compat_r
(symmetry (difference_singleton _ _ Hin))) _ _ (env_refl _))
| 2 => rewrite (proper_Provable _ _ (env_refl _) _ _
(equiv_disj_union_compat_r (equiv_disj_union_compat_r
(symmetry (difference_singleton _ _ Hin)))))
|| rewrite (proper_Provable _ _ (equiv_disj_union_compat_r
(equiv_disj_union_compat_r (symmetry (difference_singleton _ _ Hin)))) _ _ (env_refl _))
| 3 => rewrite (proper_Provable _ _ (env_refl _) _ _
(equiv_disj_union_compat_r(equiv_disj_union_compat_r
(equiv_disj_union_compat_r (symmetry (difference_singleton _ _ Hin))))))
end.
| 0 => rewrite (proper_Provable _ _ (env_refl _) _ _
(symmetry (difference_singleton _ _ Hin)))
|| rewrite (proper_Provable _ _
(symmetry (difference_singleton _ _ Hin)) _ _ (env_refl _))
| 1 => rewrite (proper_Provable _ _ (env_refl _) _ _
(equiv_disj_union_compat_r (symmetry (difference_singleton _ _ Hin))))
|| rewrite (proper_Provable _ _ (equiv_disj_union_compat_r
(symmetry (difference_singleton _ _ Hin))) _ _ (env_refl _))
| 2 => rewrite (proper_Provable _ _ (env_refl _) _ _
(equiv_disj_union_compat_r (equiv_disj_union_compat_r
(symmetry (difference_singleton _ _ Hin)))))
|| rewrite (proper_Provable _ _ (equiv_disj_union_compat_r
(equiv_disj_union_compat_r (symmetry (difference_singleton _ _ Hin)))) _ _ (env_refl _))
| 3 => rewrite (proper_Provable _ _ (env_refl _) _ _
(equiv_disj_union_compat_r(equiv_disj_union_compat_r
(equiv_disj_union_compat_r (symmetry (difference_singleton _ _ Hin))))))
end.
The tactic "forwardl" tries to change a goal of the form :
((Γ•φ ∖ {ψ}•…) ⊢ …
into
((Γ ∖ {ψ}•…•φ) ⊢ … ,
by first proving that ψ ∈ Γ. The tactic "forwardr" does the same thing
on the right.
Ltac forwardl := match goal with
| |- (?Γ•?φ) ∖ {[?ψ]} ⊢ _ =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Γ) by ms;
rewrite (proper_Provable _ _ (env_replace φ Hin) _ _ (env_refl _))
| |- (?Γ•?φ) ∖ {[?ψ]}•_ ⊢ _ =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Γ) by ms;
rewrite (proper_Provable _ _ (equiv_disj_union_compat_r (env_replace φ Hin)) _ _ (env_refl _));
exchl 0
| |- (?Γ•?φ) ∖ {[?ψ]}•_•_ ⊢ _ =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Γ) by ms;
rewrite (proper_Provable _ _ (equiv_disj_union_compat_r
(equiv_disj_union_compat_r (env_replace φ Hin))) _ _ (env_refl _));
exchl 1; exchl 0
| |- (?Γ•?φ) ∖ {[?ψ]}•_•_•_ ⊢ _ =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Γ) by ms;
rewrite (proper_Provable _ _ (equiv_disj_union_compat_r
(equiv_disj_union_compat_r(equiv_disj_union_compat_r (env_replace φ Hin)))) _ _ (env_refl _));
exchl 2; exchl 1; exchl 0
| |- (?Γ•?φ) ∖ {[?ψ]}•_•_•_•_ ⊢ _ =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Γ) by ms;
rewrite (proper_Provable _ _ (equiv_disj_union_compat_r
(equiv_disj_union_compat_r(equiv_disj_union_compat_r(equiv_disj_union_compat_r
(env_replace φ Hin))))) _ _ (env_refl _));
exchl 3; exchl 2; exchl 1; exchl 0
end.
Ltac forwardr := match goal with
| |- _ ⊢ ((?Δ•?φ) ∖ {[?ψ]}) =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Δ) by ms;
rewrite (proper_Provable _ _ (env_refl _) _ _ (env_replace φ Hin))
| |- _ ⊢ ((?Δ•?φ) ∖ {[?ψ]}•_) =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Δ) by ms;
rewrite (proper_Provable _ _ (env_refl _) _ _
(equiv_disj_union_compat_r (env_replace φ Hin)));
exchr 0
| |- _ ⊢ ((?Δ•?φ) ∖ {[?ψ]}•_•_) =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Δ) by ms;
rewrite (proper_Provable _ _ (env_refl _) _ _
(equiv_disj_union_compat_r(equiv_disj_union_compat_r (env_replace φ Hin))));
exchr 1; exchr 0
| |- _ ⊢ ((?Δ•?φ) ∖ {[?ψ]}•_•_•_) =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Δ) by ms;
rewrite (proper_Provable _ _ (env_refl _) _ _
(equiv_disj_union_compat_r(equiv_disj_union_compat_r(equiv_disj_union_compat_r (env_replace φ Hin)))));
exchr 2; exchr 1; exchr 0
| |- _ ⊢ ((?Δ•?φ) ∖ {[?ψ]}•_•_•_•_) =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Δ) by ms;
rewrite (proper_Provable _ _ (env_refl _) _ _ (equiv_disj_union_compat_r
(equiv_disj_union_compat_r(equiv_disj_union_compat_r*
(equiv_disj_union_compat_r (env_replace φ Hin))))));
exchr 3; exchr 2; exchr 1; exchr 0
end.
The tactic "backwardl" changes a goal of the form :
((Γ ∖ {ψ}•…•φ) ⊢ …
into
((Γ•φ ∖ {ψ}•…) ⊢ …,
by first proving that ψ ∈ Γ. The tactic "backwardr" does the
same thing on the right.
Ltac backwardl := match goal with
| |- ?Γ ∖ {[?ψ]}•?φ ⊢ _ =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Γ) by (eauto with proof || ms);
rewrite (proper_Provable _ _ (symmetry(env_replace _ Hin)) _ _ (env_refl _))
| |- ?Γ ∖ {[?ψ]}•_•?φ ⊢ _ =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Γ) by (eauto with proof || ms); try exchl 0;
rewrite (proper_Provable _ _ (symmetry(equiv_disj_union_compat_r
(env_replace _ Hin))) _ _ (env_refl _))
| |- ?Γ ∖ {[?ψ]}•_•_•?φ ⊢ _ =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Γ) by (eauto with proof || ms); try exchl 0; exchl 1;
rewrite (proper_Provable _ _ (symmetry(equiv_disj_union_compat_r
(equiv_disj_union_compat_r (env_replace φ Hin)))) _ _ (env_refl _))
| |- ?Γ ∖ {[?ψ]}•_•_•_•?φ ⊢ _ =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Γ) by (eauto with proof || ms); try exchl 0; exchl 1; exchl 2;
rewrite (proper_Provable _ _ (symmetry(equiv_disj_union_compat_r
(equiv_disj_union_compat_r(equiv_disj_union_compat_r (env_replace φ Hin))))) _ _ (env_refl _))
| |- ?Γ ∖ {[?ψ]}•_•_•_•_•?φ ⊢ _ =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Γ) by (eauto with proof || ms); try exchl 0; exchl 1; exchl 2; exchl 3;
rewrite (proper_Provable _ _ (symmetry(equiv_disj_union_compat_r
(equiv_disj_union_compat_r(equiv_disj_union_compat_r(equiv_disj_union_compat_r (env_replace φ Hin)))))) _ _ (env_refl _))
end.
Ltac backwardr := match goal with
| |- _ ⊢ (?Δ ∖ {[?ψ]}•?φ) =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Δ) by (eauto with proof || ms);
rewrite (proper_Provable _ _ (env_refl _) _ _ (symmetry(env_replace _ Hin)))
| |- _ ⊢ (?Δ ∖ {[?ψ]}•_•?φ) =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Δ) by (eauto with proof || ms); try exchr 0;
rewrite (proper_Provable _ _ (env_refl _) _ _
(symmetry(equiv_disj_union_compat_r (env_replace _ Hin))))
| |- _ ⊢ (?Δ ∖ {[?ψ]}•_•_•?φ) =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Δ) by (eauto with proof || ms); try exchr 0; exchr 1;
rewrite (proper_Provable _ _ (env_refl _) _ _ (symmetry(equiv_disj_union_compat_r
(equiv_disj_union_compat_r (env_replace φ Hin)))))
| |- _ ⊢ (?Δ ∖ {[?ψ]}•_•_•_•?φ) =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Δ) by (eauto with proof || ms); try exchr 0; exchr 1; exchr 2;
rewrite (proper_Provable _ _ (env_refl _) _ _ (symmetry(equiv_disj_union_compat_r
(equiv_disj_union_compat_r(equiv_disj_union_compat_r (env_replace φ Hin))))))
| |- _ ⊢ (?Δ ∖ {[?ψ]}•_•_•_•_•?φ) =>
let Hin := fresh "Hin" in
assert(Hin : ψ ∈ Δ) by (eauto with proof || ms); try exchr 0; exchr 1; exchr 2; exchr 3;
rewrite (proper_Provable _ _ (env_refl _) _ _ (symmetry(equiv_disj_union_compat_r
(equiv_disj_union_compat_r(equiv_disj_union_compat_r
(equiv_disj_union_compat_r (env_replace φ Hin)))))))
end.
The tactic "rwl" rewrites the left environment equivalence Heq in the premise.
The tactic "rwr" does the same thing on the conclusion.
Ltac rwl Heq :=
erewrite proper_Provable; [|now rewrite Heq| reflexivity].
Ltac rwr Heq :=
erewrite proper_Provable; [|reflexivity|now rewrite Heq].
Ltac box_tac :=
let rec box_tac_aux Γ n := lazymatch Γ with
|⊗(?Γ'' • ?φ) => rewrite (open_boxes_add Γ'' φ)
|⊗(?Γ' ∖ {[?ψ]}) => match goal with |H: ψ ∈ Γ' |- _ => rwl (open_boxes_remove Γ' ψ H) end
| ?Γ'' • ?φ => box_tac_aux Γ'' (S n) end
in
try match goal with | |- ?Γ ⊢ _ => box_tac_aux Γ 0 end; simpl.
Ltac lazy_apply th:=
((erewrite proper_Provable; [| |reflexivity]); [eapply th|]) ||
((erewrite proper_Provable; [|reflexivity|]); [eapply th|]).
erewrite proper_Provable; [|now rewrite Heq| reflexivity].
Ltac rwr Heq :=
erewrite proper_Provable; [|reflexivity|now rewrite Heq].
Ltac box_tac :=
let rec box_tac_aux Γ n := lazymatch Γ with
|⊗(?Γ'' • ?φ) => rewrite (open_boxes_add Γ'' φ)
|⊗(?Γ' ∖ {[?ψ]}) => match goal with |H: ψ ∈ Γ' |- _ => rwl (open_boxes_remove Γ' ψ H) end
| ?Γ'' • ?φ => box_tac_aux Γ'' (S n) end
in
try match goal with | |- ?Γ ⊢ _ => box_tac_aux Γ 0 end; simpl.
Ltac lazy_apply th:=
((erewrite proper_Provable; [| |reflexivity]); [eapply th|]) ||
((erewrite proper_Provable; [|reflexivity|]); [eapply th|]).