Kripke And Beth Semantics In Lean


Apr 09, 2026

"As the realm of sets is for mathematicians, so logical space is a paradise for philosophers. We have only to believe in the vast realm of possibilia, and there we find what we need to advance our endeavours" - David Lewis

Kripke frames are a tool discovered in the late 1950s by Saul Kripke to describe a semantics for modal logic – those logics with modal operators, typically , read as necessarily, and , read as possibly. In this semantics, we have a set \(\mathcal{W}\) which we call the set of worlds, and a binary relation \(\mathcal{R}\), called the accessibility relation, on \(\mathcal{W}\), which is meant to denote a notion of potentiality between worlds – to say of \(\mathrm{w}_1, \mathrm{w}_2 \in \mathcal{W}\) that \(\mathrm{w}_1 \mathcal{R}\mathrm{w}_2\) can be intuitively read as saying that \(\mathrm{w}_2\) has more information than \(\mathrm{w}_1\), or that it is at a later stage of development. We then have semantics for the modal operators that read something like:

There is a vast panoply of different systems of modal logics with names like S4, S5, K etc.1. From the model-theoretic point of view, these correspond to different ordering structures \(\mathcal{R}\) gives to \(\mathcal{W}\), e.g. for S4 we have that \(\mathcal{R}\) is a pre-order, whereas for S5 we want \(\mathcal{R}\) to be an equivalence relation.

As a result of this observation, Kripke realized that such an information order gives an interpretation of intuitionistic logic. One aspect Brouwer emphasized in his account of intuitionism is the way in which mathematical knowledge unfolds over time, in a state of becoming. This was one way in which Brouwer rejected the law of excluded middle, since at any given moment our knowledge may not be sufficient to either affirm or refute a given proposition. Kripke’s observation was also influenced by earlier work of Gödel, McKinsey and Tarski, who came up with a translation from intuitionistic to modal logic:

\[\begin{aligned} t(v) &= \Box v \qquad \text{[var } v\text{]} \\ t(\bot) &= \bot \\ t(A \wedge B) &= t(A) \wedge t(B) \\ t(A \vee B) &= t(A) \vee t(B) \\ t(A \to B) &= \Box\bigl(t(A) \to t(B)\bigr) \end{aligned}\]

Here we think of \(\Box\) as a modality akin to “provability”. The important clauses then say that a primitive variable is true if it is true in all worlds, and an implication is true if in any future world in which \(A\) becomes true, \(B\) must also become true. We note that this means negation doesn’t behave like classical negation since it is a worldly notion – if we prove the negation of \(\mathcal{P}\), then \(\mathcal{P}\) cannot be true in any accessible world – we can hence read the truth of a negation as constituting a proof of a refutation.

Let us see how we can develop some of these ideas in lean:

Syntax

We will develop our semantics for intuitionistic propositional logic, and so we have the following type of terms:

inductive Tm : Type where
  | var : ℕ → Tm
  | and : TmTmTm
  | or  : TmTmTm
  | imp :  TmTmTm
  | tt  : Tm
  | ff  : Tm
Syntax.Tm

Note: we use \(\mathbb{N}\) for variables, which is merely for the sake of convenience.

We also add some standard infix abbreviations so we can, for example, write for and, for or etc. For us, a proof context2 is nothing but a list of terms3:

abbrev Ctxt := List Tm
Syntax.Ctxt

We then use a standard natural-deduction-style proof theory:

inductive Pf : (Γ : Ctxt) → TmProp where
  | assume : ∀ {Γ : Ctxt} {P : Tm} , Pf (P :: Γ ) P
  | wk : ∀ {Γ Δ : Ctxt} {P : Tm}, ΓΔPf Γ PPf Δ P
  | and_I : ∀ {Γ : Ctxt} {P Q : Tm}, Pf Γ PPf Γ QPf Γ (PQ)
  | and_E₁ : ∀ {Γ : Ctxt} {P Q : Tm}, Pf Γ (PQ) → Pf Γ P
  | and_E₂ : ∀ {Γ : Ctxt} {P Q : Tm}, Pf Γ (PQ) → Pf Γ Q

  | or_I₁ : ∀ {Γ : Ctxt} {P Q : Tm}, Pf Γ PPf Γ (PQ)
  | or_I₂ : ∀ {Γ : Ctxt} {P Q : Tm}, Pf Γ QPf Γ (PQ)
  | or_E  : ∀ {Γ : Ctxt} {P Q C : Tm}, Pf Γ (PQ) → Pf (P :: Γ) CPf (Q :: Γ) CPf Γ C
  | imp_I :  ∀ {Γ : Ctxt} {P Q : Tm}, Pf (P :: Γ) QPf Γ (PQ)
  | imp_E :  ∀ {Γ : Ctxt} {P Q : Tm}, Pf Γ (PQ) → Pf Γ PPf Γ Q
  | ff_E  : ∀ {Γ : Ctxt}{P : Tm}, Pf Γ ffPf Γ P
  | tt_I :  ∀ {Γ : Ctxt}, Pf Γ tt
Syntax.Pf

As an example, here is how a simple proof looks:

def example1 : Pf [] ((var 0var 1) ∧ var 0var 1) := by
Pf [] ((var 0 var 1) var 0 var 1)
apply Pf.imp_I
a
Pf [(var 0 var 1) var 0] (var 1)
apply Pf.imp_E
a.a
Pf [(var 0 var 1) var 0] (?a.P✝ var 1)
a.a
Pf [(var 0 var 1) var 0] ?a.P✝
a.P
Tm
·
a.a
Pf [(var 0 var 1) var 0] (?a.P✝ var 1)
apply Pf.and_E₁
a.a.a
Pf [(var 0 var 1) var 0] ((?a.P✝ var 1) ?a.a.Q✝)
a.a.Q
Tm
apply Pf.assume ·
a.a
Pf [(var 0 var 1) var 0] ?a.P✝
apply Pf.and_E₂
a.a.a
Pf [(var 0 var 1) var 0] (?a.a.P✝ var 0)
a.a.P
Tm
apply Pf.assume
Syntax.example1

We make pervasive use of three elementary syntactic results on admissibility. The first is a multi-cut principle which says that if we have a proof of P from one context Δ, and from another context Γ, we can prove each formula in Δ, then we can prove P using Γ. This is a rather wordy way of stating that substitution of contexts acts on terms:

theorem multicut {Δ : Ctxt} {P : Tm} (h : Pf Δ P) :
    ∀ {Γ : Ctxt}, (∀ QΔ, Pf Γ Q) → Pf Γ P := by
Δ : Ctxt
P : Tm
h : Pf Δ P
∀ {Γ : Ctxt}, (∀ QΔ, Pf Γ Q) → Pf Γ P
induction h with | assume =>
assume
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ P✝
intro Γ
assume
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Γ : Ctxt
: QP✝ :: Γ✝, Pf Γ Q
Pf Γ P✝
exact _ (by
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Γ : Ctxt
: QP✝ :: Γ✝, Pf Γ Q
P✝ P✝ :: Γ✝
simp) | wk hP ih =>
wk
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
Δ✝ : Ctxt
P✝ : Tm
: Γ✝ Δ✝
hP : Pf Γ✝ P✝
ih : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ P✝
∀ {Γ : Ctxt}, (∀ QΔ✝, Pf Γ Q) → Pf Γ P✝
intro Γ
wk
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
Δ✝ : Ctxt
P✝ : Tm
: Γ✝ Δ✝
hP : Pf Γ✝ P✝
ih : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ P✝
Γ : Ctxt
: QΔ✝, Pf Γ Q
Pf Γ P✝
apply ih
wk.a
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
Δ✝ : Ctxt
P✝ : Tm
: Γ✝ Δ✝
hP : Pf Γ✝ P✝
ih : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ P✝
Γ : Ctxt
: QΔ✝, Pf Γ Q
QΓ✝, Pf Γ Q
intro Q hQ
wk.a
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
Δ✝ : Ctxt
P✝ : Tm
: Γ✝ Δ✝
hP : Pf Γ✝ P✝
ih : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ P✝
Γ : Ctxt
: QΔ✝, Pf Γ Q
Q : Tm
hQ : Q Γ✝
Pf Γ Q
exact Q (.sublist.subset hQ) | and_I hP hQ ihP ihQ =>
and_I
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hP : Pf Γ✝ P✝
hQ : Pf Γ✝ Q✝
ihP : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ P✝
ihQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ Q✝
∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
intro Γ
and_I
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hP : Pf Γ✝ P✝
hQ : Pf Γ✝ Q✝
ihP : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ P✝
ihQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ Q✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
Pf Γ (P✝ Q✝)
exact Pf.and_I (ihP ) (ihQ ) | and_E₁ hPQ ih =>
and_E₁
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
ih : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ P✝
intro Γ
and_E₁
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
ih : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
Γ : Ctxt
: QΓ✝, Pf Γ Q
Pf Γ P✝
exact Pf.and_E₁ (ih ) | and_E₂ hPQ ih =>
and_E₂
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
ih : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ Q✝
intro Γ
and_E₂
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
ih : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
Γ : Ctxt
: QΓ✝, Pf Γ Q
Pf Γ Q✝
exact Pf.and_E₂ (ih ) | or_I₁ hP ih =>
or_I₁
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hP : Pf Γ✝ P✝
ih : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ P✝
∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
intro Γ
or_I₁
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hP : Pf Γ✝ P✝
ih : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ P✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
Pf Γ (P✝ Q✝)
exact Pf.or_I₁ (ih ) | or_I₂ hQ ih =>
or_I₂
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hQ : Pf Γ✝ Q✝
ih : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ Q✝
∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
intro Γ
or_I₂
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hQ : Pf Γ✝ Q✝
ih : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ Q✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
Pf Γ (P✝ Q✝)
exact Pf.or_I₂ (ih ) | or_E hPQ hPC hQC ihPQ ihPC ihQC =>
or_E
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
C✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
hPC : Pf (P✝ :: Γ✝) C✝
hQC : Pf (Q✝ :: Γ✝) C✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
ihPC : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
ihQC : ∀ {Γ : Ctxt}, (∀ QQ✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ C✝
intro Γ
or_E
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
C✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
hPC : Pf (P✝ :: Γ✝) C✝
hQC : Pf (Q✝ :: Γ✝) C✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
ihPC : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
ihQC : ∀ {Γ : Ctxt}, (∀ QQ✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
Pf Γ C✝
exact Pf.or_E (ihPQ ) (ihPC (Γ := _ :: Γ) (fun R hR => by
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
C✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
hPC : Pf (P✝ :: Γ✝) C✝
hQC : Pf (Q✝ :: Γ✝) C✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
ihPC : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
ihQC : ∀ {Γ : Ctxt}, (∀ QQ✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hR : R P✝ :: Γ✝
Pf (P✝ :: Γ) R
simp at hR
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
C✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
hPC : Pf (P✝ :: Γ✝) C✝
hQC : Pf (Q✝ :: Γ✝) C✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
ihPC : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
ihQC : ∀ {Γ : Ctxt}, (∀ QQ✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hR : R = P✝ R Γ✝
Pf (P✝ :: Γ) R
rcases hR with rfl | hR
inl
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
Q✝ : Tm
C✝ : Tm
hQC : Pf (Q✝ :: Γ✝) C✝
ihQC : ∀ {Γ : Ctxt}, (∀ QQ✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hPQ : Pf Γ✝ (R Q✝)
hPC : Pf (R :: Γ✝) C✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (R Q✝)
ihPC : ∀ {Γ : Ctxt}, (∀ QR :: Γ✝, Pf Γ Q) → Pf Γ C✝
Pf (R :: Γ) R
inr
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
C✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
hPC : Pf (P✝ :: Γ✝) C✝
hQC : Pf (Q✝ :: Γ✝) C✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
ihPC : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
ihQC : ∀ {Γ : Ctxt}, (∀ QQ✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hR : R Γ✝
Pf (P✝ :: Γ) R
·
inl
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
Q✝ : Tm
C✝ : Tm
hQC : Pf (Q✝ :: Γ✝) C✝
ihQC : ∀ {Γ : Ctxt}, (∀ QQ✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hPQ : Pf Γ✝ (R Q✝)
hPC : Pf (R :: Γ✝) C✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (R Q✝)
ihPC : ∀ {Γ : Ctxt}, (∀ QR :: Γ✝, Pf Γ Q) → Pf Γ C✝
Pf (R :: Γ) R
exact Pf.assume ·
inr
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
C✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
hPC : Pf (P✝ :: Γ✝) C✝
hQC : Pf (Q✝ :: Γ✝) C✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
ihPC : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
ihQC : ∀ {Γ : Ctxt}, (∀ QQ✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hR : R Γ✝
Pf (P✝ :: Γ) R
exact Pf.wk (List.suffix_cons _ Γ) ( R hR))) (ihQC (Γ := _ :: Γ) (fun R hR => by
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
C✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
hPC : Pf (P✝ :: Γ✝) C✝
hQC : Pf (Q✝ :: Γ✝) C✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
ihPC : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
ihQC : ∀ {Γ : Ctxt}, (∀ QQ✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hR : R Q✝ :: Γ✝
Pf (Q✝ :: Γ) R
simp at hR
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
C✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
hPC : Pf (P✝ :: Γ✝) C✝
hQC : Pf (Q✝ :: Γ✝) C✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
ihPC : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
ihQC : ∀ {Γ : Ctxt}, (∀ QQ✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hR : R = Q✝ R Γ✝
Pf (Q✝ :: Γ) R
rcases hR with rfl | hR
inl
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
C✝ : Tm
hPC : Pf (P✝ :: Γ✝) C✝
ihPC : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hPQ : Pf Γ✝ (P✝ R)
hQC : Pf (R :: Γ✝) C✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ R)
ihQC : ∀ {Γ : Ctxt}, (∀ QR :: Γ✝, Pf Γ Q) → Pf Γ C✝
Pf (R :: Γ) R
inr
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
C✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
hPC : Pf (P✝ :: Γ✝) C✝
hQC : Pf (Q✝ :: Γ✝) C✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
ihPC : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
ihQC : ∀ {Γ : Ctxt}, (∀ QQ✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hR : R Γ✝
Pf (Q✝ :: Γ) R
·
inl
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
C✝ : Tm
hPC : Pf (P✝ :: Γ✝) C✝
ihPC : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hPQ : Pf Γ✝ (P✝ R)
hQC : Pf (R :: Γ✝) C✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ R)
ihQC : ∀ {Γ : Ctxt}, (∀ QR :: Γ✝, Pf Γ Q) → Pf Γ C✝
Pf (R :: Γ) R
exact Pf.assume ·
inr
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
C✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
hPC : Pf (P✝ :: Γ✝) C✝
hQC : Pf (Q✝ :: Γ✝) C✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
ihPC : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
ihQC : ∀ {Γ : Ctxt}, (∀ QQ✝ :: Γ✝, Pf Γ Q) → Pf Γ C✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hR : R Γ✝
Pf (Q✝ :: Γ) R
exact Pf.wk (List.suffix_cons _ Γ) ( R hR))) | imp_I hPQ ih =>
imp_I
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hPQ : Pf (P✝ :: Γ✝) Q✝
ih : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ Q✝
∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
intro Γ
imp_I
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hPQ : Pf (P✝ :: Γ✝) Q✝
ih : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ Q✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
Pf Γ (P✝ Q✝)
exact Pf.imp_I (ih (Γ := _ :: Γ) (fun R hR => by
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hPQ : Pf (P✝ :: Γ✝) Q✝
ih : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ Q✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hR : R P✝ :: Γ✝
Pf (P✝ :: Γ) R
simp at hR
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hPQ : Pf (P✝ :: Γ✝) Q✝
ih : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ Q✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hR : R = P✝ R Γ✝
Pf (P✝ :: Γ) R
rcases hR with rfl | hR
inl
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
Q✝ : Tm
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hPQ : Pf (R :: Γ✝) Q✝
ih : ∀ {Γ : Ctxt}, (∀ QR :: Γ✝, Pf Γ Q) → Pf Γ Q✝
Pf (R :: Γ) R
inr
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hPQ : Pf (P✝ :: Γ✝) Q✝
ih : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ Q✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hR : R Γ✝
Pf (P✝ :: Γ) R
·
inl
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
Q✝ : Tm
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hPQ : Pf (R :: Γ✝) Q✝
ih : ∀ {Γ : Ctxt}, (∀ QR :: Γ✝, Pf Γ Q) → Pf Γ Q✝
Pf (R :: Γ) R
exact Pf.assume ·
inr
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hPQ : Pf (P✝ :: Γ✝) Q✝
ih : ∀ {Γ : Ctxt}, (∀ QP✝ :: Γ✝, Pf Γ Q) → Pf Γ Q✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
R : Tm
hR : R Γ✝
Pf (P✝ :: Γ) R
exact Pf.wk (List.suffix_cons _ Γ) ( R hR))) | imp_E hPQ hP ihPQ ihP =>
imp_E
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
hP : Pf Γ✝ P✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
ihP : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ P✝
∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ Q✝
intro Γ
imp_E
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
Q✝ : Tm
hPQ : Pf Γ✝ (P✝ Q✝)
hP : Pf Γ✝ P✝
ihPQ : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ (P✝ Q✝)
ihP : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ P✝
Γ : Ctxt
: QΓ✝, Pf Γ Q
Pf Γ Q✝
exact Pf.imp_E (ihPQ ) (ihP ) | ff_E hff ih =>
ff_E
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
hff : Pf Γ✝ ff
ih : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ ff
∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ P✝
intro Γ
ff_E
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
P✝ : Tm
hff : Pf Γ✝ ff
ih : ∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ ff
Γ : Ctxt
: QΓ✝, Pf Γ Q
Pf Γ P✝
exact Pf.ff_E (ih ) | tt_I =>
tt_I
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
∀ {Γ : Ctxt}, (∀ QΓ✝, Pf Γ Q) → Pf Γ tt
intro Γ
tt_I
Δ : Ctxt
P : Tm
Γ✝ : Ctxt
Γ : Ctxt
: QΓ✝, Pf Γ Q
Pf Γ tt
exact Pf.tt_I
Syntax.Pf.multicut

The second is a generalized assumption rule, stating that if a term is a member of the context, then it can be proven:

theorem of_mem {Γ : Ctxt} {P : Tm} (h : PΓ) : Pf Γ P := by
Γ : Ctxt
P : Tm
h : P Γ
Pf Γ P
induction Γ with | nil =>
nil
P : Tm
h : P []
Pf [] P
cases h | cons Q Γ ih =>
cons
P : Tm
Q : Tm
Γ : List Tm
ih : P ΓPf Γ P
h : P Q :: Γ
Pf (Q :: Γ) P
simp at h
cons
P : Tm
Q : Tm
Γ : List Tm
ih : P ΓPf Γ P
h : P = Q P Γ
Pf (Q :: Γ) P
rcases h with rfl | h
cons.inl
P : Tm
Γ : List Tm
ih : P ΓPf Γ P
Pf (P :: Γ) P
cons.inr
P : Tm
Q : Tm
Γ : List Tm
ih : P ΓPf Γ P
h : P Γ
Pf (Q :: Γ) P
·
cons.inl
P : Tm
Γ : List Tm
ih : P ΓPf Γ P
Pf (P :: Γ) P
exact Pf.assume ·
cons.inr
P : Tm
Q : Tm
Γ : List Tm
ih : P ΓPf Γ P
h : P Γ
Pf (Q :: Γ) P
exact Pf.wk (List.suffix_cons Q Γ) (ih h)
Syntax.Pf.of_mem

The third is a generalized weakening principle stating that if one context is a sub-sequence of another, then anything provable using the first context is provable with respect to the second:

theorem monotone_mem (Γ Δ : Ctxt) {P : Tm} (hmem : ∀ QΓ, QΔ) :
    Pf Γ PPf Δ P := by
Γ : Ctxt
Δ : Ctxt
P : Tm
hmem : QΓ, Q Δ
Pf Γ PPf Δ P
intro hP
Γ : Ctxt
Δ : Ctxt
P : Tm
hmem : QΓ, Q Δ
hP : Pf Γ P
Pf Δ P
exact hP.multicut (fun Q hQ => of_mem (hmem Q hQ))
Syntax.Pf.monotone_mem

Kripke Semantics

Our semantics take values in a structure called Kripke Frame, just the same as is used for the model theory of S4 modal logic. This means we require a set W which has the structure of a Preorder, and we supply a valuation telling us which worlds \(\mathrm{w}\) each of the atomic propositions (variables) \(\mathcal{P}\) is true at4, which we denote \(\mathrm{w}\vDash_{\mathcal{W}} \mathcal{P}\). Finally, we have a functoriality constraint our valuation must satisfy: if we have \(\mathrm{w}\vDash_{\mathcal{W}} \mathcal{P}\), and \(\mathrm{v}\) is accessible from \(\mathrm{w}\), i.e. \(\mathrm{w}\leq \mathrm{v}\), then \(\mathrm{v}\vDash_{\mathcal{W}} \mathcal{P}\). The categorist will note that this constraint means we can think of val as a Prop-valued functor on the preorder W considered as a category. In some of what is to follow, it would be more natural if we were instead to set things up so val is a contravariant functor on W, or in other words, we were to consider the inverse information order where \(\mathrm{w}\leq \mathrm{v}\) can be intuitively read as stating that \(\mathrm{w}\) is more informative than \(\mathrm{v}\). Alas, we stick to the logicians’ convention. Here is how we encode this in lean:

class Frame (W : Type u) extends Preorder W where
  val : W → ℕ → Prop
  le_val : ∀ {w w' : W}{i : ℕ}, ww'val w ival w' i
Kripke.Frame

Now we have to extend the valuation to give the forcing conditions for when a general term holds at a given world:

def at_world {W : Type u} [Frame W] (w : W) (tm : Tm) : Prop :=
  match tm with
  | var v => val w v
  | Tm.and p q => at_world w pat_world w q
  | Tm.or p q => at_world w pat_world w q
  | imp p q => ∀ (w' : W), ww'at_world w' pat_world w' q
  | tt => True
  | ff => False
Kripke.at_world

As discussed previously, the interesting case for us is implication. We take this to be necessary implication and so, if the antecedent is true at any accessible world, then the consequent must also be true at that world.

We then need to prove a standard monotonicity lemma, extending our functoriality condition on val from variables to all of Tm:

def mono_at {W : Type u} [Frame W] {w w' : W} {t : Tm} (le : ww') (t_at_w : at_world w t)
    : at_world w' t :=
  match t with
  | var _n => le_val le t_at_w
  | Tm.and _p _q => ⟨mono_at le t_at_w.1, mono_at le t_at_w.2⟩
  | Tm.or _p _q => match t_at_w with
      | Or.inl l => Or.inl (mono_at le l)
      | Or.inr r => Or.inr (mono_at le r)
  | Tm.imp _p _q => fun w'' w'_le_w'' p_at_w'' => t_at_w w'' (le_trans le w'_le_w'') p_at_w''
  | tt => trivial
  | ff => False.elim t_at_w
Kripke.mono_at

Next, since we want to semantically interpret not just terms, but our proof judgments, we have to say what it means for a proof context to be forced at a given world – \(\mathrm{w}\vDash_{\mathcal{W}} \Gamma\). This is nothing but the conjunction of the truth of each term at the given world:

def all_at_world {W : Type u} [Frame W] (w : W) : CtxtProp
  | [] => True
  | (t :: ts) => at_world w tall_at_world w ts
Kripke.all_at_world

We then similarly have a monotonicity theorem for contexts:

def mono_all {W : Type u} [Frame W] {w w' : W} {Γ : Ctxt} (w_le_w' : ww')
    (Γ_at_w : all_at_world w Γ) : all_at_world w' Γ :=
  match Γ, Γ_at_w with
  | [], _ => trivial
  | _ :: _, ⟨h, t⟩ => ⟨mono_at w_le_w' h, mono_all w_le_w' t
Kripke.mono_all

Now that we have what it means for a term or context to be forced at a particular world, we can say what it means for a judgment to be true – \(\Gamma \vDash_{\mathcal{W}} \mathcal{P}\). This is the case precisely if in all the worlds where the premises (i.e. context) are true, the conclusion is true:

def Entails (W : Type u) [Frame W] (Γ : Ctxt) (t : Tm) : Prop :=
  ∀ (w : W), all_at_world w Γat_world w t
Kripke.Entails

Finally, we can state what it means that a term holds semantically by quantifying over all frames – \(\Gamma \vDash_{\mathrm{Kripke}} \mathcal{P}\):

def SemEntails (Γ : Ctxt) (t : Tm) : Prop :=
  ∀ (W : Type u) [Frame W] (w : W), all_at_world w Γat_world w t
Kripke.SemEntails

Soundness for Kripke Frames

It is fairly easy for us to show that each of our natural deduction rules holds in our semantics:

  def assumption : Entails W (p :: Γ) p := fun _w all => all.1
  def wk : ΓΔEntails W Γ tEntails W Δ t :=
    fun hΓΔ Γ_to_t w all => Γ_to_t w (all_at_of_suffix hΓΔ all)
  def and_I : Entails W Γ pEntails W Γ qEntails W Γ (pq) :=
    fun p_holds q_holds w all => p_holds w all, q_holds w all
  def and_E₁ : Entails W Γ (pq) → Entails W Γ p :=
    fun pq_holds w all => (pq_holds w all).1
  def and_E₂ : Entails W Γ (pq) → Entails W Γ q :=
    fun pq_holds w all => (pq_holds w all).2
  def or_I₁ : Entails W Γ pEntails W Γ (pq) :=
    fun p_holds w all => Or.inl (p_holds w all)
  def or_I₂ : Entails W Γ qEntails W Γ (pq) :=
    fun q_holds w all => Or.inr (q_holds w all)
  def or_E : Entails W Γ (pq) → Entails W (p :: Γ) cEntails W (q :: Γ) cEntails W Γ c :=
    fun p_or_q c_ass_p c_ass_q w all => match p_or_q w all with
      | Or.inl p_at_w => c_ass_p w p_at_w, all
      | Or.inr q_at_w => c_ass_q w q_at_w, all
  def imp_I : Entails W (p :: Γ) qEntails W Γ (pq) :=
    fun q_ass_p _w all w' w_le_w' p_at_w' =>
      q_ass_p w' p_at_w', mono_all w_le_w' all
  def imp_E : Entails W Γ (pq) → Entails W Γ pEntails W Γ q :=
    fun q_if_p p_holds w all =>
      q_if_p w all w (le_refl w) (p_holds w all)
  def tt_I : Entails W Γ tt := fun _ _ => trivial
  def ff_E : Entails W Γ ffEntails W Γ p := by
W : Type u
inst✝ : Frame W
w : W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
Δ : Ctxt
Entails W Γ ffEntails W Γ p
intro ff_at_w w
W : Type u
inst✝ : Frame W
w✝ : W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
Δ : Ctxt
ff_at_w : Entails W Γ ff
w : W
all_at_world w Γat_world w p
all_w
W : Type u
inst✝ : Frame W
w✝ : W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
Δ : Ctxt
ff_at_w : Entails W Γ ff
w : W
all_w : all_at_world w Γ
at_world w p
exfalso
W : Type u
inst✝ : Frame W
w✝ : W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
Δ : Ctxt
ff_at_w : Entails W Γ ff
w : W
all_w : all_at_world w Γ
False
apply ff_at_w w all_w
Kripke.Semantics

This allows us to prove soundness by rule induction on the proof term:

def soundness {W : Type u}[Frame W] {Γ : Ctxt}{tm : Tm} : Pf Γ tmEntails W Γ tm
  | Pf.assume =>
W : Type u
inst✝ : Frame W
Γ : Ctxt
tm✝ : Tm
tm : Tm
Γ✝ : Ctxt
Entails W (tm :: Γ✝) tm
by
W : Type u
inst✝ : Frame W
Γ : Ctxt
tm✝ : Tm
tm : Tm
Γ✝ : Ctxt
Entails W (tm :: Γ✝) tm
apply Semantics.assumption | Pf.wk h pf =>
W : Type u
inst✝ : Frame W
Γ✝¹ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Γ✝ : Ctxt
h : Γ✝ Γ
pf : Pf Γ✝ tm
Entails W Γ tm
by
W : Type u
inst✝ : Frame W
Γ✝¹ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Γ✝ : Ctxt
h : Γ✝ Γ
pf : Pf Γ✝ tm
Entails W Γ tm
exact Semantics.wk (Γ := _) (Δ := _) (t := _) h (soundness pf) | Pf.and_I p q =>
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
q : Pf Γ Q✝
Entails W Γ (P✝ Q✝)
by
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
q : Pf Γ Q✝
Entails W Γ (P✝ Q✝)
apply Semantics.and_I
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
q : Pf Γ Q✝
Entails W Γ P✝
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
q : Pf Γ Q✝
Entails W Γ Q✝
apply soundness p
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
q : Pf Γ Q✝
Entails W Γ Q✝
apply soundness q | Pf.and_E₁ p =>
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Q✝ : Tm
p : Pf Γ (tm Q✝)
Entails W Γ tm
by
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Q✝ : Tm
p : Pf Γ (tm Q✝)
Entails W Γ tm
apply Semantics.and_E₁
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Q✝ : Tm
p : Pf Γ (tm Q✝)
Entails W Γ (tm ?q)
q
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Q✝ : Tm
p : Pf Γ (tm Q✝)
Tm
apply soundness p | Pf.and_E₂ p =>
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
Entails W Γ tm
by
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
Entails W Γ tm
apply Semantics.and_E₂
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
Entails W Γ (?p tm)
p
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
Tm
apply soundness p | or_I₁ p =>
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
Entails W Γ (P✝ Q✝)
by
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
Entails W Γ (P✝ Q✝)
apply Semantics.or_I₁
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
Entails W Γ P✝
apply soundness p | or_I₂ q =>
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
q : Pf Γ Q✝
Entails W Γ (P✝ Q✝)
by
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
q : Pf Γ Q✝
Entails W Γ (P✝ Q✝)
apply Semantics.or_I₂
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
q : Pf Γ Q✝
Entails W Γ Q✝
apply soundness q | or_E p_or_q c_ass_p c_ass_q =>
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W Γ tm
by
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W Γ tm
apply Semantics.or_E
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W Γ (?p ?q)
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W (?p :: Γ) tm
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W (?q :: Γ) tm
p
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Tm
q
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Tm
apply soundness p_or_q
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W (?p :: Γ) tm
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W (?q :: Γ) tm
apply soundness c_ass_p
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W (?q :: Γ) tm
apply soundness c_ass_q | Pf.imp_I p =>
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf (P✝ :: Γ) Q✝
Entails W Γ (P✝ Q✝)
by
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf (P✝ :: Γ) Q✝
Entails W Γ (P✝ Q✝)
apply Semantics.imp_I
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf (P✝ :: Γ) Q✝
Entails W (P✝ :: Γ) Q✝
apply soundness p | Pf.imp_E p q =>
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
q : Pf Γ P✝
Entails W Γ tm
by
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
q : Pf Γ P✝
Entails W Γ tm
apply Semantics.imp_E
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
q : Pf Γ P✝
Entails W Γ (?p tm)
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
q : Pf Γ P✝
Entails W Γ ?p
p
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
q : Pf Γ P✝
Tm
apply soundness p
a
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
q : Pf Γ P✝
Entails W Γ ?p
apply soundness q | Pf.tt_I => fun _ _ => trivial | Pf.ff_E p =>
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
p : Pf Γ Tm.ff
Entails W Γ tm
by
W : Type u
inst✝ : Frame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
p : Pf Γ Tm.ff
Entails W Γ tm
exact Semantics.ff_E (Γ := _) (p := _) (soundness p)
Kripke.soundness

Soundness gives us a means to show what terms are not provable in our proof theory. For instance, if we were to take a model with a single world, we would be unable to prove False at this world, and thus we can show that our proof theory doesn’t prove ff – in other words, this gives us consistency for this version of constructive logic5:

/-- A trivial boolean Kripke frame
    w0 []
 -/
inductive Triv where
  | w0
instance : LE Triv where
  le _x _y := True
instance : Preorder Triv where
  le_refl x := by
x : Triv
x x
simp [LE.le] le_trans x y z := by
x : Triv
y : Triv
z : Triv
x yy zx z
simp [LE.le]
instance : Frame Triv where
  val _w _i := False
  le_val := by
∀ {w w' : Triv} {i : }, w w'FalseFalse
intro w w'
w : Triv
w' : Triv
∀ {i : }, w w'FalseFalse
i
w : Triv
w' : Triv
i :
w w'FalseFalse
hle
w : Triv
w' : Triv
i :
hle : w w'
FalseFalse
hval
w : Triv
w' : Triv
i :
hle : w w'
hval : False
False
assumption
open Triv
def consistency : ¬ Pf [] Tm.ff := by
  intro pf
pf : Pf [] Tm.ff
False
change at_world w0 Tm.ff apply soundness pf w0 simp
Kripke.Consistency

In just the same way, we can also show that certain classical principles do not hold by constructing models in which they fail. For instance, we can construct a Kripke frame where one world splits into two to show that excluded middle cannot be derived constructively:

/-- A Kripke frame that refutes the Law of Excluded Middle.

                w1 [P]
               /
              /
             w0 []
              \
               \
                w2 [¬P]
 -/
inductive EMFrame where
  | w0 | w1 | w2
instance : LE EMFrame where
  le x y := match x, y with
    | .w0, _ => True
    | .w1, .w1 => True
    | .w2, .w2 => True
    | _, _ => False
instance : Preorder EMFrame where
  le_refl x := by
x x
cases x <;> simp [LE.le] le_trans x y z := by
x yy zx z
cases x
w0
EMFrame.w0 yy zEMFrame.w0 z
w1
EMFrame.w1 yy zEMFrame.w1 z
w2
EMFrame.w2 yy zEMFrame.w2 z
<;>
w0
EMFrame.w0 yy zEMFrame.w0 z
w1
EMFrame.w1 yy zEMFrame.w1 z
w2
EMFrame.w2 yy zEMFrame.w2 z
cases y <;> cases z <;> simp [LE.le]
instance : Frame EMFrame where
  val w i := match w, i with
    | .w1, 0 => True
    | _, _ => False
  le_val := by
∀ {w w' : EMFrame} {i : }, w w' → (match w, i with | EMFrame.w1, 0 => True | x, x_1 => False) → match w', i with | EMFrame.w1, 0 => True | x, x_1 => False
intro w w'
∀ {i : }, w w' → (match w, i with | EMFrame.w1, 0 => True | x, x_1 => False) → match w', i with | EMFrame.w1, 0 => True | x, x_1 => False
i
w' : EMFrame
i :
w w' → (match w, i with | EMFrame.w1, 0 => True | x, x_1 => False) → match w', i with | EMFrame.w1, 0 => True | x, x_1 => False
hle
w' : EMFrame
i :
hle : w w'
(match w, i with | EMFrame.w1, 0 => True | x, x_1 => False) → match w', i with | EMFrame.w1, 0 => True | x, x_1 => False
hval
w' : EMFrame
i :
hle : w w'
hval : match w, i with | EMFrame.w1, 0 => True | x, x_1 => False
match w', i with | EMFrame.w1, 0 => True | x, x_1 => False
cases w
w0
w' : EMFrame
i :
hle : EMFrame.w0 w'
hval : match EMFrame.w0, i with | EMFrame.w1, 0 => True | x, x_1 => False
match w', i with | EMFrame.w1, 0 => True | x, x_1 => False
w1
w' : EMFrame
i :
hle : EMFrame.w1 w'
hval : match EMFrame.w1, i with | EMFrame.w1, 0 => True | x, x_1 => False
match w', i with | EMFrame.w1, 0 => True | x, x_1 => False
w2
w' : EMFrame
i :
hle : EMFrame.w2 w'
hval : match EMFrame.w2, i with | EMFrame.w1, 0 => True | x, x_1 => False
match w', i with | EMFrame.w1, 0 => True | x, x_1 => False
<;>
w0
w' : EMFrame
i :
hle : EMFrame.w0 w'
hval : match EMFrame.w0, i with | EMFrame.w1, 0 => True | x, x_1 => False
match w', i with | EMFrame.w1, 0 => True | x, x_1 => False
w1
w' : EMFrame
i :
hle : EMFrame.w1 w'
hval : match EMFrame.w1, i with | EMFrame.w1, 0 => True | x, x_1 => False
match w', i with | EMFrame.w1, 0 => True | x, x_1 => False
w2
w' : EMFrame
i :
hle : EMFrame.w2 w'
hval : match EMFrame.w2, i with | EMFrame.w1, 0 => True | x, x_1 => False
match w', i with | EMFrame.w1, 0 => True | x, x_1 => False
cases w'
w2.w0
i :
hval : match EMFrame.w2, i with | EMFrame.w1, 0 => True | x, x_1 => False
match EMFrame.w0, i with | EMFrame.w1, 0 => True | x, x_1 => False
w2.w1
i :
hval : match EMFrame.w2, i with | EMFrame.w1, 0 => True | x, x_1 => False
match EMFrame.w1, i with | EMFrame.w1, 0 => True | x, x_1 => False
w2.w2
i :
hval : match EMFrame.w2, i with | EMFrame.w1, 0 => True | x, x_1 => False
match EMFrame.w2, i with | EMFrame.w1, 0 => True | x, x_1 => False
<;>
w0.w0
i :
hval : match EMFrame.w0, i with | EMFrame.w1, 0 => True | x, x_1 => False
match EMFrame.w0, i with | EMFrame.w1, 0 => True | x, x_1 => False
w0.w1
i :
hval : match EMFrame.w0, i with | EMFrame.w1, 0 => True | x, x_1 => False
match EMFrame.w1, i with | EMFrame.w1, 0 => True | x, x_1 => False
w0.w2
i :
hval : match EMFrame.w0, i with | EMFrame.w1, 0 => True | x, x_1 => False
match EMFrame.w2, i with | EMFrame.w1, 0 => True | x, x_1 => False
w1.w0
i :
hval : match EMFrame.w1, i with | EMFrame.w1, 0 => True | x, x_1 => False
match EMFrame.w0, i with | EMFrame.w1, 0 => True | x, x_1 => False
w1.w1
i :
hval : match EMFrame.w1, i with | EMFrame.w1, 0 => True | x, x_1 => False
match EMFrame.w1, i with | EMFrame.w1, 0 => True | x, x_1 => False
w1.w2
i :
hval : match EMFrame.w1, i with | EMFrame.w1, 0 => True | x, x_1 => False
match EMFrame.w2, i with | EMFrame.w1, 0 => True | x, x_1 => False
w2.w0
i :
hval : match EMFrame.w2, i with | EMFrame.w1, 0 => True | x, x_1 => False
match EMFrame.w0, i with | EMFrame.w1, 0 => True | x, x_1 => False
w2.w1
i :
hval : match EMFrame.w2, i with | EMFrame.w1, 0 => True | x, x_1 => False
match EMFrame.w1, i with | EMFrame.w1, 0 => True | x, x_1 => False
w2.w2
i :
hval : match EMFrame.w2, i with | EMFrame.w1, 0 => True | x, x_1 => False
match EMFrame.w2, i with | EMFrame.w1, 0 => True | x, x_1 => False
simp [LE.le] at * exact hval
open Tm
open EMFrame
theorem em_not_provable : ¬ Pf [] (var 0 ∨ (var 0ff)) := by
  intro h
False
-- EM for P := var 0, is neither probable nor refutable at w0 let EM_pf_at_w := soundness (W := EMFrame) h w0 (by simp [all_at_world]) simp [at_world] at EM_pf_at_w
EM_pf_at_w : Frame.val w0 0 ∀ (w' : EMFrame), w0 w'¬Frame.val w' 0
False
rcases EM_pf_at_w with pf_p | pf_not_p
inl
pf_p : Frame.val w0 0
False
inr
pf_not_p : ∀ (w' : EMFrame), w0 w'¬Frame.val w' 0
False
·
inl
pf_p : Frame.val w0 0
False
-- case 1: w0 forced at p, -- But by def of val it is not forced here simp [Frame.val] at pf_p ·
inr
pf_not_p : ∀ (w' : EMFrame), w0 w'¬Frame.val w' 0
False
-- Case 2: w0 forces p -> ⊥ -- At every world accessible from w0, if p is true, then ⊥ is true. -- But w1 is accessible from w0, and p is true at w1 while ⊥ is never true. have w0_le_w1 : w0w1 := by simp [LE.le] have p_at_w1 : at_world w1 (var 0) := by simp [at_world, Frame.val] exact pf_not_p w1 w0_le_w1 p_at_w1
Kripke.ExcludedMiddle

Completeness for Kripke Frames

As well as soundness, we can also prove completeness for Kripke frames, but the details, as is typical for completeness proofs, are significantly more intricate. The proof is standard, and similar to proofs of the completeness of truth tables for classical logic6. Since we are working classically, we don’t give a direct argument that if a term is true in all models, then we can reconstruct a derivation for it. Instead, we give a proof by contradiction. Let us suppose then that we have a term A for which we cannot give a derivation: \(\neg \Gamma \vdash \mathcal{A}\). The idea of our proof is to construct, from this assumption that we cannot prove A, a bespoke Kripke frame which contradicts that \(\mathcal{A}\) holds in all models. In such a frame, the collection of worlds is taken to be certain theories – that is, sets of terms – which are:

structure World where
  carrier : Theory
  closed : Closed carrier
  consistent : Consistent carrier
  prime : Prime carrier
Kripke.Canonical.World

We will not cover the precise details of the proof here7, but we shall give an outline of the main ideas. If we have some theory T from which we can’t prove A, then we may gradually extend the theory so that at each point we maintain both the invariant that the theory still doesn’t prove A, and the invariant that the theory is still consistent. To begin with, we can take the (deductive) closure of T and show that this is consistent and still doesn’t prove A. We may then consider the set of all such theories satisfying these properties and show, using Zorn’s lemma, that we may construct a maximal such closed theory. We then show that such a maximal admissible theory is prime. With such a theory in hand, we may then show the main technical result – the truth lemma8:

theorem truth_lemma (w : World) : ∀ φ : Tm, at_world w φφw.carrier
  | Tm.var i => Iff.rfl
  | Tm.and φ ψ =>
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
constructor
mp
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ)(φ ψ) w.carrier
mpr
w : World
φ : Tm
ψ : Tm
(φ ψ) w.carrierat_world w (φ ψ)
·
mp
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ)(φ ψ) w.carrier
intro at_w_and
mp
w : World
φ : Tm
ψ : Tm
at_w_and : at_world w (φ ψ)
(φ ψ) w.carrier
have : φw.carrier := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
rw [<- truth_lemma w φ]
w : World
φ : Tm
ψ : Tm
at_w_and : at_world w (φ ψ)
at_world w φ
apply And.left
self
w : World
φ : Tm
ψ : Tm
at_w_and : at_world w (φ ψ)
at_world w φ ?b
b
w : World
φ : Tm
ψ : Tm
at_w_and : at_world w (φ ψ)
Prop
apply at_w_and have : ψw.carrier := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
rw [<- truth_lemma w ψ]
w : World
φ : Tm
ψ : Tm
at_w_and : at_world w (φ ψ)
: φ w.carrier
at_world w ψ
apply And.right
self
w : World
φ : Tm
ψ : Tm
at_w_and : at_world w (φ ψ)
: φ w.carrier
?a at_world w ψ
a
w : World
φ : Tm
ψ : Tm
at_w_and : at_world w (φ ψ)
: φ w.carrier
Prop
apply at_w_and -- use that w is deductively closed apply w.closed
mp.a
w : World
φ : Tm
ψ : Tm
at_w_and : at_world w (φ ψ)
: φ w.carrier
: ψ w.carrier
exists [φ, ψ]
mp.a
w : World
φ : Tm
ψ : Tm
at_w_and : at_world w (φ ψ)
: φ w.carrier
: ψ w.carrier
(∀ ψ_1[φ, ψ], ψ_1 w.carrier) Pf [φ, ψ] (φ ψ)
constructor
mp.a.left
w : World
φ : Tm
ψ : Tm
at_w_and : at_world w (φ ψ)
: φ w.carrier
: ψ w.carrier
ψ_1[φ, ψ], ψ_1 w.carrier
mp.a.right
w : World
φ : Tm
ψ : Tm
at_w_and : at_world w (φ ψ)
: φ w.carrier
: ψ w.carrier
Pf [φ, ψ] (φ ψ)
·
mp.a.left
w : World
φ : Tm
ψ : Tm
at_w_and : at_world w (φ ψ)
: φ w.carrier
: ψ w.carrier
ψ_1[φ, ψ], ψ_1 w.carrier
aesop ·
mp.a.right
w : World
φ : Tm
ψ : Tm
at_w_and : at_world w (φ ψ)
: φ w.carrier
: ψ w.carrier
Pf [φ, ψ] (φ ψ)
have hφmem : φ ∈ [φ, ψ] := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
simp have hψmem : ψ ∈ [φ, ψ] := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
simp exact Pf.and_I (Pf.of_mem hφmem) (Pf.of_mem hψmem) ·
mpr
w : World
φ : Tm
ψ : Tm
(φ ψ) w.carrierat_world w (φ ψ)
intro both_in_w
mpr
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
at_world w (φ ψ)
constructor
mpr.left
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
at_world w φ
mpr.right
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
at_world w ψ
·
mpr.left
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
at_world w φ
rw [truth_lemma w φ]
mpr.left
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
φ w.carrier
apply w.closed
mpr.left.a
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
exists [φψ]
mpr.left.a
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
(∀ ψ_1[φ ψ], ψ_1 w.carrier) Pf [φ ψ] φ
constructor
mpr.left.a.left
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
ψ_1[φ ψ], ψ_1 w.carrier
mpr.left.a.right
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
Pf [φ ψ] φ
·
mpr.left.a.left
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
ψ_1[φ ψ], ψ_1 w.carrier
simpa using both_in_w ·
mpr.left.a.right
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
Pf [φ ψ] φ
have hmem : (φψ) ∈ [φψ] := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
simp exact Pf.and_E₁ (Pf.of_mem hmem) ·
mpr.right
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
at_world w ψ
rw [truth_lemma w ψ]
mpr.right
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
ψ w.carrier
apply w.closed
mpr.right.a
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
exists [φψ]
mpr.right.a
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
(∀ ψ_1[φ ψ], ψ_1 w.carrier) Pf [φ ψ] ψ
constructor
mpr.right.a.left
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
ψ_1[φ ψ], ψ_1 w.carrier
mpr.right.a.right
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
Pf [φ ψ] ψ
·
mpr.right.a.left
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
ψ_1[φ ψ], ψ_1 w.carrier
simpa using both_in_w ·
mpr.right.a.right
w : World
φ : Tm
ψ : Tm
both_in_w : (φ ψ) w.carrier
Pf [φ ψ] ψ
have hmem : (φψ) ∈ [φψ] := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
simp exact Pf.and_E₂ (Pf.of_mem hmem) | Tm.or φ ψ =>
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
constructor
mp
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ)(φ ψ) w.carrier
mpr
w : World
φ : Tm
ψ : Tm
(φ ψ) w.carrierat_world w (φ ψ)
·
mp
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ)(φ ψ) w.carrier
intro or_at_w
mp
w : World
φ : Tm
ψ : Tm
or_at_w : at_world w (φ ψ)
(φ ψ) w.carrier
rcases or_at_w with φ_at_w | ψ_at_w
mp.inl
w : World
φ : Tm
ψ : Tm
φ_at_w : at_world w φ
(φ ψ) w.carrier
mp.inr
w : World
φ : Tm
ψ : Tm
ψ_at_w : at_world w ψ
(φ ψ) w.carrier
·
mp.inl
w : World
φ : Tm
ψ : Tm
φ_at_w : at_world w φ
(φ ψ) w.carrier
apply w.closed
mp.inl.a
w : World
φ : Tm
ψ : Tm
φ_at_w : at_world w φ
exists [φ]
mp.inl.a
w : World
φ : Tm
ψ : Tm
φ_at_w : at_world w φ
(∀ ψ[φ], ψ w.carrier) Pf [φ] (φ ψ)
constructor
mp.inl.a.left
w : World
φ : Tm
ψ : Tm
φ_at_w : at_world w φ
ψ[φ], ψ w.carrier
mp.inl.a.right
w : World
φ : Tm
ψ : Tm
φ_at_w : at_world w φ
Pf [φ] (φ ψ)
·
mp.inl.a.left
w : World
φ : Tm
ψ : Tm
φ_at_w : at_world w φ
ψ[φ], ψ w.carrier
simp
mp.inl.a.left
w : World
φ : Tm
ψ : Tm
φ_at_w : at_world w φ
φ w.carrier
rw [<- truth_lemma w φ]
mp.inl.a.left
w : World
φ : Tm
ψ : Tm
φ_at_w : at_world w φ
at_world w φ
exact φ_at_w ·
mp.inl.a.right
w : World
φ : Tm
ψ : Tm
φ_at_w : at_world w φ
Pf [φ] (φ ψ)
have hmem : φ ∈ [φ] := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
simp exact Pf.or_I₁ (Pf.of_mem hmem) ·
mp.inr
w : World
φ : Tm
ψ : Tm
ψ_at_w : at_world w ψ
(φ ψ) w.carrier
apply w.closed
mp.inr.a
w : World
φ : Tm
ψ : Tm
ψ_at_w : at_world w ψ
exists [ψ]
mp.inr.a
w : World
φ : Tm
ψ : Tm
ψ_at_w : at_world w ψ
(∀ ψ_1[ψ], ψ_1 w.carrier) Pf [ψ] (φ ψ)
constructor
mp.inr.a.left
w : World
φ : Tm
ψ : Tm
ψ_at_w : at_world w ψ
ψ_1[ψ], ψ_1 w.carrier
mp.inr.a.right
w : World
φ : Tm
ψ : Tm
ψ_at_w : at_world w ψ
Pf [ψ] (φ ψ)
·
mp.inr.a.left
w : World
φ : Tm
ψ : Tm
ψ_at_w : at_world w ψ
ψ_1[ψ], ψ_1 w.carrier
simp
mp.inr.a.left
w : World
φ : Tm
ψ : Tm
ψ_at_w : at_world w ψ
ψ w.carrier
rw [<- truth_lemma w ψ]
mp.inr.a.left
w : World
φ : Tm
ψ : Tm
ψ_at_w : at_world w ψ
at_world w ψ
exact ψ_at_w ·
mp.inr.a.right
w : World
φ : Tm
ψ : Tm
ψ_at_w : at_world w ψ
Pf [ψ] (φ ψ)
have hmem : ψ ∈ [ψ] := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
simp exact Pf.or_I₂ (Pf.of_mem hmem) ·
mpr
w : World
φ : Tm
ψ : Tm
(φ ψ) w.carrierat_world w (φ ψ)
intro or_in_w
mpr
w : World
φ : Tm
ψ : Tm
or_in_w : (φ ψ) w.carrier
at_world w (φ ψ)
rcases w.prime or_in_w with φ_in_w | ψ_in_w
mpr.inl
w : World
φ : Tm
ψ : Tm
or_in_w : (φ ψ) w.carrier
φ_in_w : φ w.carrier
at_world w (φ ψ)
mpr.inr
w : World
φ : Tm
ψ : Tm
or_in_w : (φ ψ) w.carrier
ψ_in_w : ψ w.carrier
at_world w (φ ψ)
·
mpr.inl
w : World
φ : Tm
ψ : Tm
or_in_w : (φ ψ) w.carrier
φ_in_w : φ w.carrier
at_world w (φ ψ)
simp
mpr.inl
w : World
φ : Tm
ψ : Tm
or_in_w : (φ ψ) w.carrier
φ_in_w : φ w.carrier
at_world w φ at_world w ψ
rw [truth_lemma w φ]
mpr.inl
w : World
φ : Tm
ψ : Tm
or_in_w : (φ ψ) w.carrier
φ_in_w : φ w.carrier
φ w.carrier at_world w ψ
apply Or.inl
mpr.inl.h
w : World
φ : Tm
ψ : Tm
or_in_w : (φ ψ) w.carrier
φ_in_w : φ w.carrier
φ w.carrier
assumption ·
mpr.inr
w : World
φ : Tm
ψ : Tm
or_in_w : (φ ψ) w.carrier
ψ_in_w : ψ w.carrier
at_world w (φ ψ)
simp
mpr.inr
w : World
φ : Tm
ψ : Tm
or_in_w : (φ ψ) w.carrier
ψ_in_w : ψ w.carrier
at_world w φ at_world w ψ
rw [truth_lemma w ψ]
mpr.inr
w : World
φ : Tm
ψ : Tm
or_in_w : (φ ψ) w.carrier
ψ_in_w : ψ w.carrier
at_world w φ ψ w.carrier
apply Or.inr
mpr.inr.h
w : World
φ : Tm
ψ : Tm
or_in_w : (φ ψ) w.carrier
ψ_in_w : ψ w.carrier
ψ w.carrier
assumption | Tm.imp φ ψ =>
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
constructor
mp
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ)(φ ψ) w.carrier
mpr
w : World
φ : Tm
ψ : Tm
(φ ψ) w.carrierat_world w (φ ψ)
·
mp
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ)(φ ψ) w.carrier
intro imp_at_w
mp
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
(φ ψ) w.carrier
by_contra imp_not_in_w
mp
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
False
have ψ_not_in_clos : ψclosure (Set.insert φ w.carrier) := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
intro ψ_in_clos
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_in_clos : ψ closure (Set.insert φ w.carrier)
False
apply imp_not_in_w
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_in_clos : ψ closure (Set.insert φ w.carrier)
(φ ψ) w.carrier
apply closure_insert_imp
T_closed
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_in_clos : ψ closure (Set.insert φ w.carrier)
htm
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_in_clos : ψ closure (Set.insert φ w.carrier)
apply w.closed
htm
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_in_clos : ψ closure (Set.insert φ w.carrier)
exact ψ_in_clos have w'_consistent : Consistent (closure (Set.insert φ w.carrier)) := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
intro ff_in_w'
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
ff_in_w' : Tm.ff closure (Set.insert φ w.carrier)
False
have not_φ_in_w : (φTm.ff) ∈ w.carrier := closure_insert_imp w.closed ff_in_w'
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
ff_in_w' : Tm.ff closure (Set.insert φ w.carrier)
not_φ_in_w : (φ Tm.ff) w.carrier
False
apply imp_not_in_w
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
ff_in_w' : Tm.ff closure (Set.insert φ w.carrier)
not_φ_in_w : (φ Tm.ff) w.carrier
(φ ψ) w.carrier
apply w.closed
a
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
ff_in_w' : Tm.ff closure (Set.insert φ w.carrier)
not_φ_in_w : (φ Tm.ff) w.carrier
exists [φTm.ff]
a
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
ff_in_w' : Tm.ff closure (Set.insert φ w.carrier)
not_φ_in_w : (φ Tm.ff) w.carrier
(∀ ψ[φ Tm.ff], ψ w.carrier) Pf [φ Tm.ff] (φ ψ)
constructor
a.left
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
ff_in_w' : Tm.ff closure (Set.insert φ w.carrier)
not_φ_in_w : (φ Tm.ff) w.carrier
ψ[φ Tm.ff], ψ w.carrier
a.right
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
ff_in_w' : Tm.ff closure (Set.insert φ w.carrier)
not_φ_in_w : (φ Tm.ff) w.carrier
Pf [φ Tm.ff] (φ ψ)
·
a.left
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
ff_in_w' : Tm.ff closure (Set.insert φ w.carrier)
not_φ_in_w : (φ Tm.ff) w.carrier
ψ[φ Tm.ff], ψ w.carrier
simpa using not_φ_in_w ·
a.right
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
ff_in_w' : Tm.ff closure (Set.insert φ w.carrier)
not_φ_in_w : (φ Tm.ff) w.carrier
Pf [φ Tm.ff] (φ ψ)
exact Pf.quodlibet φ ψ -- construct a world containing w and φ, which extends w, and where -- φ holds but ψ doesn't obtainT, T_adm, T_prime⟩ := prime_extension_avoiding (closure_closed _) w'_consistent ψ_not_in_clos
mp
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
w'_consistent : Consistent (closure (Set.insert φ w.carrier))
T : Theory
T_adm : Admissible (closure (Set.insert φ w.carrier)) ψ T
T_prime : Prime T
False
let v : World := T, T_adm.closed, T_adm.consistent, T_prime
mp
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
w'_consistent : Consistent (closure (Set.insert φ w.carrier))
T : Theory
T_adm : Admissible (closure (Set.insert φ w.carrier)) ψ T
T_prime : Prime T
v : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
False
have w_le_v : wv := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
intro χ
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
w'_consistent : Consistent (closure (Set.insert φ w.carrier))
T : Theory
T_adm : Admissible (closure (Set.insert φ w.carrier)) ψ T
T_prime : Prime T
v : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
χ : Tm
: χ w.carrier
χ v.carrier
exact T_adm.base (subset_closure (Or.inr )) have φ_at_v : at_world v φ := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
apply (truth_lemma v φ).2
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
w'_consistent : Consistent (closure (Set.insert φ w.carrier))
T : Theory
T_adm : Admissible (closure (Set.insert φ w.carrier)) ψ T
T_prime : Prime T
v : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
w_le_v : w v
φ v.carrier
exact T_adm.base (subset_closure (Or.inl rfl)) have not_ψ_at_v : ¬ at_world v ψ := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
intro hψv
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
w'_consistent : Consistent (closure (Set.insert φ w.carrier))
T : Theory
T_adm : Admissible (closure (Set.insert φ w.carrier)) ψ T
T_prime : Prime T
v : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
w_le_v : w v
φ_at_v : at_world v φ
hψv : at_world v ψ
False
exact T_adm.avoids ((truth_lemma v ψ).1 hψv) apply not_ψ_at_v
mp
w : World
φ : Tm
ψ : Tm
imp_at_w : at_world w (φ ψ)
imp_not_in_w : (φ ψ)w.carrier
ψ_not_in_clos : ψclosure (Set.insert φ w.carrier)
w'_consistent : Consistent (closure (Set.insert φ w.carrier))
T : Theory
T_adm : Admissible (closure (Set.insert φ w.carrier)) ψ T
T_prime : Prime T
v : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
w_le_v : w v
φ_at_v : at_world v φ
not_ψ_at_v : ¬at_world v ψ
at_world v ψ
apply imp_at_w v w_le_v φ_at_v ·
mpr
w : World
φ : Tm
ψ : Tm
(φ ψ) w.carrierat_world w (φ ψ)
intro imp_in_w v
mpr
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w vat_world v φat_world v ψ
w_le_v
mpr
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
at_world v φat_world v ψ
φ_at_v
mpr
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
φ_at_v : at_world v φ
at_world v ψ
have imp_in_v : (φψ) ∈ v.carrier := w_le_v imp_in_w
mpr
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
φ_at_v : at_world v φ
imp_in_v : (φ ψ) v.carrier
at_world v ψ
have φ_in_v : φv.carrier := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
rw [<- truth_lemma v φ]
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
φ_at_v : at_world v φ
imp_in_v : (φ ψ) v.carrier
at_world v φ
exact φ_at_v have ψ_in_v : ψv.carrier := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
apply v.closed
a
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
φ_at_v : at_world v φ
imp_in_v : (φ ψ) v.carrier
φ_in_v : φ v.carrier
exists [φψ, φ]
a
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
φ_at_v : at_world v φ
imp_in_v : (φ ψ) v.carrier
φ_in_v : φ v.carrier
(∀ ψ_1[φ ψ, φ], ψ_1 v.carrier) Pf [φ ψ, φ] ψ
constructor
a.left
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
φ_at_v : at_world v φ
imp_in_v : (φ ψ) v.carrier
φ_in_v : φ v.carrier
ψ_1[φ ψ, φ], ψ_1 v.carrier
a.right
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
φ_at_v : at_world v φ
imp_in_v : (φ ψ) v.carrier
φ_in_v : φ v.carrier
Pf [φ ψ, φ] ψ
·
a.left
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
φ_at_v : at_world v φ
imp_in_v : (φ ψ) v.carrier
φ_in_v : φ v.carrier
ψ_1[φ ψ, φ], ψ_1 v.carrier
intro tm tm_in_ctx
a.left
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
φ_at_v : at_world v φ
imp_in_v : (φ ψ) v.carrier
φ_in_v : φ v.carrier
tm : Tm
tm_in_ctx : tm [φ ψ, φ]
tm v.carrier
simp at tm_in_ctx
a.left
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
φ_at_v : at_world v φ
imp_in_v : (φ ψ) v.carrier
φ_in_v : φ v.carrier
tm : Tm
tm_in_ctx : tm = (φ ψ) tm = φ
tm v.carrier
rcases tm_in_ctx with rfl | rfl
a.left.inl
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
φ_at_v : at_world v φ
imp_in_v : (φ ψ) v.carrier
φ_in_v : φ v.carrier
(φ ψ) v.carrier
a.left.inr
w : World
ψ : Tm
v : World
w_le_v : w v
tm : Tm
imp_in_w : (tm ψ) w.carrier
φ_at_v : at_world v tm
imp_in_v : (tm ψ) v.carrier
φ_in_v : tm v.carrier
tm v.carrier
·
a.left.inl
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
φ_at_v : at_world v φ
imp_in_v : (φ ψ) v.carrier
φ_in_v : φ v.carrier
(φ ψ) v.carrier
exact imp_in_v ·
a.left.inr
w : World
ψ : Tm
v : World
w_le_v : w v
tm : Tm
imp_in_w : (tm ψ) w.carrier
φ_at_v : at_world v tm
imp_in_v : (tm ψ) v.carrier
φ_in_v : tm v.carrier
tm v.carrier
exact φ_in_v ·
a.right
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
φ_at_v : at_world v φ
imp_in_v : (φ ψ) v.carrier
φ_in_v : φ v.carrier
Pf [φ ψ, φ] ψ
have imp_mem : (φψ) ∈ [φψ, φ] := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
simp have φ_mem: φ ∈ [φψ, φ] := by
w : World
φ : Tm
ψ : Tm
at_world w (φ ψ) (φ ψ) w.carrier
simp exact Pf.imp_E (Pf.of_mem imp_mem) (Pf.of_mem φ_mem) rw [truth_lemma v ψ]
mpr
w : World
φ : Tm
ψ : Tm
imp_in_w : (φ ψ) w.carrier
v : World
w_le_v : w v
φ_at_v : at_world v φ
imp_in_v : (φ ψ) v.carrier
φ_in_v : φ v.carrier
ψ_in_v : ψ v.carrier
ψ v.carrier
exact ψ_in_v | Tm.tt => by constructor
mp
w : World
mpr
w : World
·
mp
w : World
intro _
mp
w : World
a✝ : at_world w Tm.tt
exact w.closed [], by
w : World
a✝ : at_world w Tm.tt
ψ[], ψ w.carrier
simp, Pf.tt_I ·
mpr
w : World
aesop | Tm.ff => by constructor
mp
w : World
mpr
w : World
·
mp
w : World
intro ff_at_w
mp
w : World
ff_at_w : at_world w Tm.ff
exact False.elim ff_at_w ·
mpr
w : World
intro ff_in_w
mpr
w : World
ff_in_w : Tm.ff w.carrier
exfalso
mpr
w : World
ff_in_w : Tm.ff w.carrier
False
exact w.consistent ff_in_w
Kripke.Canonical.truth_lemma

It is then easy to use this to construct a countermodel in this Kripke frame assuming we can’t give a deduction of A:

theorem countermodel {Γ : Ctxt} {tm : Tm} (neg_pf : ¬ Pf Γ tm) :
    ¬ Kripke.SemEntails.{0} Γ tm := by
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
¬SemEntails Γ tm
have tm_avoids_T : tmtheoryOf Γ := by
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
¬SemEntails Γ tm
intro htm
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
htm : tm theoryOf Γ
False
apply neg_pf
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
htm : tm theoryOf Γ
Pf Γ tm
rw [<- mem_theoryOf]
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
htm : tm theoryOf Γ
tm theoryOf Γ
assumption have ΓT_Cons : Consistent (theoryOf Γ) := by
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
¬SemEntails Γ tm
intro hff
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
hff : Tm.ff theoryOf Γ
False
apply neg_pf
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
hff : Tm.ff theoryOf Γ
Pf Γ tm
apply Pf.ff_E
a
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
hff : Tm.ff theoryOf Γ
Pf Γ Tm.ff
rw [<- mem_theoryOf]
a
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
hff : Tm.ff theoryOf Γ
assumption obtainT, T_admissible, T_prime⟩ := prime_extension_avoiding (closure_closed _) ΓT_Cons tm_avoids_T
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
¬SemEntails Γ tm
let w : World := T, T_admissible.closed, T_admissible.consistent, T_prime
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
¬SemEntails Γ tm
have all_in_T : ∀ Δ : Ctxt, (∀ φΔ, φT) → all_at_world w Δ := by
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
¬SemEntails Γ tm
intro Δ
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
Δ : Ctxt
: φΔ, φ T
all_at_world w Δ
induction Δ with | nil =>
nil
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
: φ[], φ T
simp | cons φ Δ ih =>
cons
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
φ : Tm
Δ : List Tm
ih : (∀ φΔ, φ T) → all_at_world w Δ
: φ_1φ :: Δ, φ_1 T
all_at_world w (φ :: Δ)
constructor
cons.left
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
φ : Tm
Δ : List Tm
ih : (∀ φΔ, φ T) → all_at_world w Δ
: φ_1φ :: Δ, φ_1 T
at_world w φ
cons.right
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
φ : Tm
Δ : List Tm
ih : (∀ φΔ, φ T) → all_at_world w Δ
: φ_1φ :: Δ, φ_1 T
all_at_world w Δ
·
cons.left
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
φ : Tm
Δ : List Tm
ih : (∀ φΔ, φ T) → all_at_world w Δ
: φ_1φ :: Δ, φ_1 T
at_world w φ
rw [truth_lemma w φ]
cons.left
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
φ : Tm
Δ : List Tm
ih : (∀ φΔ, φ T) → all_at_world w Δ
: φ_1φ :: Δ, φ_1 T
φ w.carrier
apply φ
cons.left
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
φ : Tm
Δ : List Tm
ih : (∀ φΔ, φ T) → all_at_world w Δ
: φ_1φ :: Δ, φ_1 T
φ φ :: Δ
simp ·
cons.right
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
φ : Tm
Δ : List Tm
ih : (∀ φΔ, φ T) → all_at_world w Δ
: φ_1φ :: Δ, φ_1 T
all_at_world w Δ
apply ih
cons.right
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
φ : Tm
Δ : List Tm
ih : (∀ φΔ, φ T) → all_at_world w Δ
: φ_1φ :: Δ, φ_1 T
φΔ, φ T
intro ψ
cons.right
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
φ : Tm
Δ : List Tm
ih : (∀ φΔ, φ T) → all_at_world w Δ
: φ_1φ :: Δ, φ_1 T
ψ : Tm
: ψ Δ
ψ T
apply ψ
cons.right
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
φ : Tm
Δ : List Tm
ih : (∀ φΔ, φ T) → all_at_world w Δ
: φ_1φ :: Δ, φ_1 T
ψ : Tm
: ψ Δ
ψ φ :: Δ
simp [] have all_at_Γ : all_at_world w Γ := by
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
¬SemEntails Γ tm
apply all_in_T Γ
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
all_in_T : ∀ (Δ : Ctxt), (∀ φΔ, φ T) → all_at_world w Δ
φΓ, φ T
intro φ φ_in_Γ
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
all_in_T : ∀ (Δ : Ctxt), (∀ φΔ, φ T) → all_at_world w Δ
φ : Tm
φ_in_Γ : φ Γ
φ T
apply T_admissible.base (contextSet_mem φ_in_Γ) have not_tm_at_w : ¬ at_world w tm := by
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
¬SemEntails Γ tm
intro tm_at_w
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
all_in_T : ∀ (Δ : Ctxt), (∀ φΔ, φ T) → all_at_world w Δ
all_at_Γ : all_at_world w Γ
tm_at_w : at_world w tm
False
apply T_admissible.avoids
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
all_in_T : ∀ (Δ : Ctxt), (∀ φΔ, φ T) → all_at_world w Δ
all_at_Γ : all_at_world w Γ
tm_at_w : at_world w tm
tm T
rw [<- truth_lemma w tm]
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
all_in_T : ∀ (Δ : Ctxt), (∀ φΔ, φ T) → all_at_world w Δ
all_at_Γ : all_at_world w Γ
tm_at_w : at_world w tm
at_world w tm
apply tm_at_w intro sem_tm
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
all_in_T : ∀ (Δ : Ctxt), (∀ φΔ, φ T) → all_at_world w Δ
all_at_Γ : all_at_world w Γ
not_tm_at_w : ¬at_world w tm
sem_tm : SemEntails Γ tm
False
apply not_tm_at_w
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
all_in_T : ∀ (Δ : Ctxt), (∀ φΔ, φ T) → all_at_world w Δ
all_at_Γ : all_at_world w Γ
not_tm_at_w : ¬at_world w tm
sem_tm : SemEntails Γ tm
at_world w tm
apply sem_tm
a
Γ : Ctxt
tm : Tm
neg_pf : ¬Pf Γ tm
tm_avoids_T : tmtheoryOf Γ
ΓT_Cons : Consistent (theoryOf Γ)
T : Theory
T_admissible : Admissible (Canonical.closure (contextSet Γ)) tm T
T_prime : Canonical.Prime T
w : World := { carrier := T, closed :=, consistent :=, prime := T_prime }
all_in_T : ∀ (Δ : Ctxt), (∀ φΔ, φ T) → all_at_world w Δ
all_at_Γ : all_at_world w Γ
not_tm_at_w : ¬at_world w tm
sem_tm : SemEntails Γ tm
all_at_world w Γ
apply all_at_Γ
Kripke.countermodel

We then use the countermodel to give a proof by contradiction of completeness:

theorem completeness {Γ : Ctxt} {tm : Tm} : Kripke.SemEntails.{0} Γ tmPf Γ tm := by
Γ : Ctxt
tm : Tm
SemEntails Γ tmPf Γ tm
contrapose!
Γ : Ctxt
tm : Tm
¬Pf Γ tm¬SemEntails Γ tm
exact countermodel
Kripke.completeness

Beth Semantics

Traditionally Beth semantics arose from Beth’s work seeking to explain and unify Brouwer’s account of choice sequences, along with his notion that the fan theorem gives a constructively acceptable compactness result in intuitionistic mathematics. In particular, for the theory of choice sequences, Brouwer emphasized that we are to think of a sequence \(\mathrm{f}: \mathbb{N} \rightarrow \mathbb{N}\) as something perhaps unconstrained or un-law-like which is unfolding over time, or actively in a state of becoming as our knowledge proceeds. As such, those properties of sequences that are intuitionistically acceptable are the ones we can verify within finite time, or in other words, those which can be checked on some initial sub-sequence of \(\mathrm{f}\). Classically, this means that instead of considering all set-theoretical properties \(\phi : \mathbb{N}^{\mathbb{N}} \rightarrow \mathbb{2}\), we consider only those that are continuous with respect to the product topology9.

Inspired by these considerations, Beth studied abstract trees, i.e. sets of finite sequences (in this case with values drawn from \(\mathbb{N}\)), which are closed under taking prefixes. If we have a node in such a tree \(\mathcal{T}= \langle t_1,\ldots, t_n \rangle\) – which we might think of as denoting a path in the tree recording each of the prior nodes – then we can think of this as a description of the initial segment of how a choice sequence has unfolded thus far, and hence we can think of descendant nodes of \(\mathcal{T}\) as the potential future unfoldings of the choice sequence. Because of these considerations, it was typical that the trees Beth studied were finitely-branching – meaning each tree node has only finitely many children – and pruned – meaning every node always has at least one child node.

If we are to prove an intuitionistically acceptable property of such a sequence represented as a given node, then Beth considered the principle whereby we prove that the property holds for a subset which bars the given node, meaning every path proceeding from the given node eventually hits the given subset. If we can prove a property holds for such a bar, and that the property is stable under immediate prefixes10, then we can show that it holds for the given sequence. This reasoning principle is called bar induction. Beth used this idea to give an interpretation of constructive logic in which the nodes of the tree were labelled by sets of formulas, and where the branching of the tree essentially followed the rules of semantic tableaux.

Rather than focus too closely on Beth’s particular example of abstract trees with bar induction, we would like to emphasize that we can take a more abstract view that places (generalized) Beth semantics as a direct topological generalization of Kripke frames – topological in just the sense that spaces generalize sets, or that sheaf categories generalize presheaf categories. In what follows, then, we will want to think of the structure provided by the bars in a Beth tree as a kind of topological structure on the tree, and the induction principle as a kind of sheaf property. For this to make sense, we need to take a brief detour into Grothendieck topologies.

Grothendieck Topologies

A Grothendieck topology is a certain kind of structure one can place upon a category. Many have remarked that it is something of a misnomer to call it a topology – suggesting it generalizes the notion of a topology on a space – and that we’d be better off with a name like a coverage, since it really abstracts the concept of a collection of open sets covering another set. We will therefore follow this naming in our actual development.

In our setting, we only contend with defining coverages for preorders considered as a category, minimizing some of the difficulties of the theory. We start with the idea of a sieve11. Given a preorder \(\mathcal{P}\) and \(\mathrm{p}\in \mathcal{P}\), a sieve on p is a sub-functor of \(\operatorname{Hom}(\mathrm{p}, -)\) – in other words, it is an upward closed set which is bounded below by \(\mathrm{p}\):

structure Sieve {P : Type u}[Preorder P] (p : P) : Type u where
  carrier : Set P
  bounded : ∀ {q : P}, qcarrierpq
  upward_closed : ∀ {q r : P}, (rcarrier) → rqqcarrier
Beth.Sieve

We note that the principal upward closed set \(\uparrow \mathrm{p}:= \{\mathrm{q}| \mathrm{p}\leq \mathrm{q}\}\) always gives us a sieve:

def maximal_sieve [Preorder.{u} P] (p : P) : Sieve p := by
P : Type u
inst✝ : Preorder P
p : P
Sieve p
refine {carrier := ?_, bounded := ?_, upward_closed := ?_}
refine_1
P : Type u
inst✝ : Preorder P
p : P
Set P
refine_2
P : Type u
inst✝ : Preorder P
p : P
∀ {q : P}, q ?refine_1 → p q
refine_3
P : Type u
inst✝ : Preorder P
p : P
∀ {q r : P}, r ?refine_1 → r qq ?refine_1
·
refine_1
P : Type u
inst✝ : Preorder P
p : P
Set P
exact {q | pq} ·
refine_2
P : Type u
inst✝ : Preorder P
p : P
∀ {q : P}, q ?refine_1 → p q
intro q h
refine_2
P : Type u
inst✝ : Preorder P
p : P
q : P
h : q {q | p q}
p q
; exact h ·
refine_3
P : Type u
inst✝ : Preorder P
p : P
∀ {q r : P}, r ?refine_1 → r qq ?refine_1
intro q r
refine_3
P : Type u
inst✝ : Preorder P
p : P
q : P
r : P
r {q | p q}r qq {q | p q}
hgr
refine_3
P : Type u
inst✝ : Preorder P
p : P
q : P
r : P
hgr : r {q | p q}
r qq {q | p q}
hqr
refine_3
P : Type u
inst✝ : Preorder P
p : P
q : P
r : P
hgr : r {q | p q}
hqr : r q
q {q | p q}
exact le_trans hgr hqr
Beth.maximal_sieve

Also, if we are given a sieve \(\mathcal{S}\) on \(\mathrm{p}\) and we have \(\mathrm{p}\leq \mathrm{q}\), then we can consider the subset of the sieve that is greater than \(\mathrm{q}\): \(\; \mathcal{S}\uparrow \mathrm{q}:= \{ \mathrm{r}\; | \; \mathrm{r}\in \mathcal{S}, \mathrm{q}\leq \mathrm{r}\}\) – and this gives us a sieve on \(\mathrm{q}\). We call this, rather dubiously, the pullback12:

-- We use the terminology pullback even though this goes forward in our set up
def pullback [Preorder P] {p q : P} (_h : pq) (S : Sieve p) : Sieve q where
    carrier := {r | rS.carrierqr}
    bounded  := fun ⟨_, hr⟩ => hr
    upward_closed := funr'_in_S, q_le_r'r'_le_r => S.upward_closed r'_in_S r'_le_r, le_trans q_le_r' r'_le_r
Beth.pullback

A coverage (Grothendieck topology) on \(\mathcal{P}\) is then, for each \(\mathrm{p}: \mathcal{P}\), a collection of sieves on \(\mathrm{p}\) which abstractly “cover” \(\mathrm{p}\). In particular, a coverage satisfies the axioms:

We can read stability as stating that covers can be ‘restricted’ to a sub-object, and transitivity as stating that if a sieve is locally covering with respect to another cover, then it itself is covering. Here is how it looks in lean:

structure Coverage (P : Type u) [Preorder P] : Type u where
  covers : (p : P) → Set (Sieve p)
  maximal : ∀ (p : P), covers p (maximal_sieve p)
  transitive : ∀ (p : P) (U V : Sieve p), covers p U → (∀ (q : U.carrier),
    (covers (q : P) (pullback (U.bounded q.property) V))) -> covers p V
  stability :  ∀ {p q : P} {U : Sieve p} (_U_Cov : covers p U) (p_le_q : pq), covers q (pullback p_le_q U)
Beth.Coverage

Beth Frames

A Beth frame, our terminology13, is an extension of a Kripke frame, where we ask that we have a Coverage on the underlying preorder W, and that the valuation now satisfies the sheaf condition with respect to it. This says that if we have a world w with a covering sieve S on w, and a variable v is true on the covering sieve, i.e. true for each world in the covering sieve, then the variable must be true at w. We might think, as an intuitionist, that this condition is giving an account not of the usual BHK semantics, but instead is a semantics of assertibility. We think of \(\mathcal{S}\) as giving a “bar” of the current world – meaning any of the future ways in which the present world might develop will be through one of the worlds in \(\mathcal{S}\) – and think of this condition as stating that we will in finite time be able to verify the truth of a given atomic proposition P, and thus that we are already justified in asserting P.

We also require that each of the covering sieves is non-empty. This is analogous to the pruning condition, requiring that each bar is non-empty. The reason this is necessary is that if we have a world with an empty cover, then we can use the sheaf condition on this cover to prove False at this world. For an ordinary topological space, the only set that has an empty cover is the empty set, and so we can think of this as requiring that our semantics is only on non-empty open domains.

class BethFrame (W : Type u) extends HasCoverage W, Kripke.Frame W where
  sheaf_condition : ∀ {i : ℕ} {w : W} {S : Sieve w} (_S_covers : covers w S), (∀ qS , val q i) → val w i
  nonempty_covers : ∀ {w : W} {S : Sieve w}, covers w SNonempty S.carrier
Beth.BethFrame

The semantical clauses for truth, or assertibility, at a world, in a Beth frame, are almost identical to those for Kripke frames except for the account they give of disjunction. To say that a disjunction P ∨ Q is assertible is not to say that we know the truth of either component of the disjunction at the present world, but that we have a cover upon which we will be able to verify either that P holds or that Q holds:

def at_world {W : Type u} [BethFrame W] (w : W) (tm : Tm) : Prop :=
  match tm with
  | var v => val w v
  | Tm.and p q => at_world w pat_world w q
  | Tm.or p q =>
      ∃ (S : Sieve w), covers w S ∧ (∀ w'S, at_world w' pat_world w' q)
  | imp p q => ∀ (w' : W), ww'at_world w' pat_world w' q
  | tt => True
  | ff => False
Beth.at_world

Our clauses for entailment and semantic entailment are then identical to those for Kripke frames:

def Entails (W : Type u) [BethFrame W] (Γ : Ctxt) (t : Tm) : Prop :=
  ∀ (w : W), all_at_world w Γat_world w t
Beth.Entails
def SemEntails (Γ : Ctxt) (t : Tm) : Prop :=
  ∀ (W : Type u) [BethFrame W] (w : W), all_at_world w Γat_world w t
Beth.SemEntails

A final twist is that just as we showed a monotonicity lemma – that extending val to the evaluation of all formulas at a world remains monotonic with respect to accessibility – in Beth semantics we also need to show that the sheaf condition on atomic propositions extends to all terms:

def sheaf_term {W : Type u} [BethFrame W] {w : W} {S : Sieve w} (S_covers : covers w S) (tm : Tm) : (∀ w'S , at_world w' tm) → at_world w tm :=
  match tm with
  | var n => sheaf_condition S_covers
  | Tm.and p q =>
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
(∀ w'S, at_world w' (p q)) → at_world w (p q)
by
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
(∀ w'S, at_world w' (p q)) → at_world w (p q)
intro pq_on_S
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
pq_on_S : w'S, at_world w' (p q)
at_world w (p q)
constructor
left
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
pq_on_S : w'S, at_world w' (p q)
at_world w p
right
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
pq_on_S : w'S, at_world w' (p q)
at_world w q
·
left
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
pq_on_S : w'S, at_world w' (p q)
at_world w p
apply sheaf_term S_covers p
left
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
pq_on_S : w'S, at_world w' (p q)
w'S, at_world w' p
intro s s_in_S
left
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
pq_on_S : w'S, at_world w' (p q)
s : W
s_in_S : s S
at_world s p
exact (pq_on_S s s_in_S).1 ·
right
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
pq_on_S : w'S, at_world w' (p q)
at_world w q
apply sheaf_term S_covers q
right
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
pq_on_S : w'S, at_world w' (p q)
w'S, at_world w' q
intro s s_in_S
right
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
pq_on_S : w'S, at_world w' (p q)
s : W
s_in_S : s S
at_world s q
exact (pq_on_S s s_in_S).2 | Tm.or p q =>
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
(∀ w'S, at_world w' (p q)) → at_world w (p q)
by
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
(∀ w'S, at_world w' (p q)) → at_world w (p q)
intro p_or_q_on_S
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
p_or_q_on_S : w'S, at_world w' (p q)
at_world w (p q)
have h_ex (w' : S.carrier) : ∃ (S' : Sieve (w' : W)), covers (w' : W) S' ∧ (∀ vS', at_world v pat_world v q) := p_or_q_on_S w' w'.property
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
p_or_q_on_S : w'S, at_world w' (p q)
h_ex : ∀ (w' : ↑S.carrier), ∃ S', covers (↑w') S' vS', at_world v p at_world v q
at_world w (p q)
choose f_sieve f_spec using h_ex
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
p_or_q_on_S : w'S, at_world w' (p q)
f_sieve : (w' : ↑S.carrier) → Sievew'
f_spec : ∀ (w' : ↑S.carrier), covers (↑w') (f_sieve w') vf_sieve w', at_world v p at_world v q
at_world w (p q)
let S_gl := glue_sieves S f_sieve
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
p_or_q_on_S : w'S, at_world w' (p q)
f_sieve : (w' : ↑S.carrier) → Sievew'
f_spec : ∀ (w' : ↑S.carrier), covers (↑w') (f_sieve w') vf_sieve w', at_world v p at_world v q
S_gl : Sieve w := glue_sieves S f_sieve
at_world w (p q)
simp
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
p_or_q_on_S : w'S, at_world w' (p q)
f_sieve : (w' : ↑S.carrier) → Sievew'
f_spec : ∀ (w' : ↑S.carrier), covers (↑w') (f_sieve w') vf_sieve w', at_world v p at_world v q
S_gl : Sieve w := glue_sieves S f_sieve
S, covers w S w'S, at_world w' p at_world w' q
exists S_gl
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
p_or_q_on_S : w'S, at_world w' (p q)
f_sieve : (w' : ↑S.carrier) → Sievew'
f_spec : ∀ (w' : ↑S.carrier), covers (↑w') (f_sieve w') vf_sieve w', at_world v p at_world v q
S_gl : Sieve w := glue_sieves S f_sieve
covers w S_gl w'S_gl, at_world w' p at_world w' q
constructor
left
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
p_or_q_on_S : w'S, at_world w' (p q)
f_sieve : (w' : ↑S.carrier) → Sievew'
f_spec : ∀ (w' : ↑S.carrier), covers (↑w') (f_sieve w') vf_sieve w', at_world v p at_world v q
S_gl : Sieve w := glue_sieves S f_sieve
covers w S_gl
right
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
p_or_q_on_S : w'S, at_world w' (p q)
f_sieve : (w' : ↑S.carrier) → Sievew'
f_spec : ∀ (w' : ↑S.carrier), covers (↑w') (f_sieve w') vf_sieve w', at_world v p at_world v q
S_gl : Sieve w := glue_sieves S f_sieve
w'S_gl, at_world w' p at_world w' q
·
left
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
p_or_q_on_S : w'S, at_world w' (p q)
f_sieve : (w' : ↑S.carrier) → Sievew'
f_spec : ∀ (w' : ↑S.carrier), covers (↑w') (f_sieve w') vf_sieve w', at_world v p at_world v q
S_gl : Sieve w := glue_sieves S f_sieve
covers w S_gl
apply covers_glue f_sieve S_covers (fun q => (f_spec q).1) ·
right
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
p_or_q_on_S : w'S, at_world w' (p q)
f_sieve : (w' : ↑S.carrier) → Sievew'
f_spec : ∀ (w' : ↑S.carrier), covers (↑w') (f_sieve w') vf_sieve w', at_world v p at_world v q
S_gl : Sieve w := glue_sieves S f_sieve
w'S_gl, at_world w' p at_world w' q
intro v hv
right
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
p_or_q_on_S : w'S, at_world w' (p q)
f_sieve : (w' : ↑S.carrier) → Sievew'
f_spec : ∀ (w' : ↑S.carrier), covers (↑w') (f_sieve w') vf_sieve w', at_world v p at_world v q
S_gl : Sieve w := glue_sieves S f_sieve
v : W
hv : v S_gl
at_world v p at_world v q
letq, hgv⟩ := hv
right
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q✝ : Tm
p_or_q_on_S : w'S, at_world w' (p q)
f_sieve : (w' : ↑S.carrier) → Sievew'
f_spec : ∀ (w' : ↑S.carrier), covers (↑w') (f_sieve w') vf_sieve w', at_world v p at_world v q
S_gl : Sieve w := glue_sieves S f_sieve
v : W
hv : v S_gl
q : S.carrier
hgv : v (f_sieve q).carrier
at_world v p at_world v q✝
exact (f_spec q).2 v hgv | Tm.imp p q =>
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
(∀ w'S, at_world w' (p q)) → at_world w (p q)
by
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
(∀ w'S, at_world w' (p q)) → at_world w (p q)
intro hS w'
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
hS : w'S, at_world w' (p q)
w' : W
w w'at_world w' pat_world w' q
w_le_w'
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
hS : w'S, at_world w' (p q)
w' : W
w_le_w' : w w'
at_world w' pat_world w' q
p_at_w'
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
hS : w'S, at_world w' (p q)
w' : W
w_le_w' : w w'
p_at_w' : at_world w' p
at_world w' q
have pullback_covers : covers w' (pullback w_le_w' S) := by
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
(∀ w'S, at_world w' (p q)) → at_world w (p q)
apply covers_stable
hU
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
hS : w'S, at_world w' (p q)
w' : W
w_le_w' : w w'
p_at_w' : at_world w' p
covers w S
exact S_covers apply sheaf_term pullback_covers q
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
hS : w'S, at_world w' (p q)
w' : W
w_le_w' : w w'
p_at_w' : at_world w' p
pullback_covers : covers w' (pullback w_le_w' S)
w'_1pullback w_le_w' S, at_world w'_1 q
intro w'' hw''
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
hS : w'S, at_world w' (p q)
w' : W
w_le_w' : w w'
p_at_w' : at_world w' p
pullback_covers : covers w' (pullback w_le_w' S)
w'' : W
hw'' : w'' pullback w_le_w' S
at_world w'' q
simp [pullback] at hw''
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
hS : w'S, at_world w' (p q)
w' : W
w_le_w' : w w'
p_at_w' : at_world w' p
pullback_covers : covers w' (pullback w_le_w' S)
w'' : W
hw'' : w'' { carrier := {r | r S.carrier w' r}, bounded :=, upward_closed :=}
at_world w'' q
apply hS w'' hw''.1 w'' (le_refl w'')
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
p : Tm
q : Tm
hS : w'S, at_world w' (p q)
w' : W
w_le_w' : w w'
p_at_w' : at_world w' p
pullback_covers : covers w' (pullback w_le_w' S)
w'' : W
hw'' : w'' { carrier := {r | r S.carrier w' r}, bounded :=, upward_closed :=}
at_world w'' p
apply mono_at hw''.2 p_at_w' | tt =>
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
(∀ w'S, at_world w' tt) → at_world w tt
by
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
(∀ w'S, at_world w' tt) → at_world w tt
intro _
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
a✝ : w'S, at_world w' tt
at_world w tt
trivial | ff =>
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
(∀ w'S, at_world w' ff) → at_world w ff
by
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
(∀ w'S, at_world w' ff) → at_world w ff
intro ff_on_S
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
ff_on_S : w'S, at_world w' ff
at_world w ff
obtain ⟨⟨w', hw'⟩⟩ := nonempty_covers S_covers
W : Type u
inst✝ : BethFrame W
w : W
S : Sieve w
S_covers : covers w S
tm : Tm
ff_on_S : w'S, at_world w' ff
w' : W
hw' : w' S.carrier
at_world w ff
exact ff_on_S w' hw'
Beth.sheaf_term

Kripke Frames as Beth Frames

Although Beth frames give a generalization of Kripke frames, we can define a discrete coverage for any preorder in which the covers are just the maximal sieves:

def maximalSieveCoverage (W : Type u) [Preorder W] : Coverage W where
  covers w S := S.carrier = (maximal_sieve w).carrier
  maximal _w := rfl
  transitive := by
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
∀ (p : W) (U V : Sieve p), U.carrier = (maximal_sieve p).carrier → (∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier) → V.carrier = (maximal_sieve p).carrier
intro p U
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
∀ (V : Sieve p), U.carrier = (maximal_sieve p).carrier → (∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier) → V.carrier = (maximal_sieve p).carrier
V
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
U.carrier = (maximal_sieve p).carrier → (∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier) → V.carrier = (maximal_sieve p).carrier
hU
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
(∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier) → V.carrier = (maximal_sieve p).carrier
hV
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
hV : ∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier
have p_in_U : pU.carrier := by
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
∀ (p : W) (U V : Sieve p), U.carrier = (maximal_sieve p).carrier → (∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier) → V.carrier = (maximal_sieve p).carrier
rw [hU]
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
hV : ∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier
; exact le_refl p have pullback_maximal := hV p, p_in_U
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
hV : ∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier
p_in_U : p U.carrier
pullback_maximal : (pullbackV).carrier = (maximal_sievep, p_in_U).carrier
ext s
h
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
hV : ∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier
p_in_U : p U.carrier
pullback_maximal : (pullbackV).carrier = (maximal_sievep, p_in_U).carrier
s : W
simp only [maximal_sieve, Set.mem_setOf_eq]
h
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
hV : ∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier
p_in_U : p U.carrier
pullback_maximal : (pullbackV).carrier = (maximal_sievep, p_in_U).carrier
s : W
s V.carrier p s
constructor
h.mp
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
hV : ∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier
p_in_U : p U.carrier
pullback_maximal : (pullbackV).carrier = (maximal_sievep, p_in_U).carrier
s : W
s V.carrierp s
h.mpr
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
hV : ∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier
p_in_U : p U.carrier
pullback_maximal : (pullbackV).carrier = (maximal_sievep, p_in_U).carrier
s : W
p ss V.carrier
·
h.mp
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
hV : ∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier
p_in_U : p U.carrier
pullback_maximal : (pullbackV).carrier = (maximal_sievep, p_in_U).carrier
s : W
s V.carrierp s
intro hr
h.mp
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
hV : ∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier
p_in_U : p U.carrier
pullback_maximal : (pullbackV).carrier = (maximal_sievep, p_in_U).carrier
s : W
hr : s V.carrier
p s
; exact V.bounded hr ·
h.mpr
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
hV : ∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier
p_in_U : p U.carrier
pullback_maximal : (pullbackV).carrier = (maximal_sievep, p_in_U).carrier
s : W
p ss V.carrier
intro hr
h.mpr
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
hV : ∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier
p_in_U : p U.carrier
pullback_maximal : (pullbackV).carrier = (maximal_sievep, p_in_U).carrier
s : W
hr : p s
s V.carrier
have hmem : s ∈ (pullback (U.bounded p_in_U) V).carrier := by
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
∀ (p : W) (U V : Sieve p), U.carrier = (maximal_sieve p).carrier → (∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier) → V.carrier = (maximal_sieve p).carrier
rw [pullback_maximal]
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
hV : ∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier
p_in_U : p U.carrier
pullback_maximal : (pullbackV).carrier = (maximal_sievep, p_in_U).carrier
s : W
hr : p s
s (maximal_sievep, p_in_U).carrier
; assumption simp only [pullback, Set.mem_setOf_eq] at hmem
h.mpr
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
U : Sieve p
V : Sieve p
hV : ∀ (q : ↑U.carrier), (pullbackV).carrier = (maximal_sieveq).carrier
p_in_U : p U.carrier
pullback_maximal : (pullbackV).carrier = (maximal_sievep, p_in_U).carrier
s : W
hr : p s
hmem : s V.carrier p s
s V.carrier
exact hmem.1 stability := by
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
∀ {p q : W} {U : Sieve p}, U.carrier = (maximal_sieve p).carrier → ∀ (p_le_q : p q), (pullback p_le_q U).carrier = (maximal_sieve q).carrier
intro p q
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
q : W
∀ {U : Sieve p}, U.carrier = (maximal_sieve p).carrier → ∀ (p_le_q : p q), (pullback p_le_q U).carrier = (maximal_sieve q).carrier
U
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
q : W
U : Sieve p
U.carrier = (maximal_sieve p).carrier → ∀ (p_le_q : p q), (pullback p_le_q U).carrier = (maximal_sieve q).carrier
hU
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
q : W
U : Sieve p
∀ (p_le_q : p q), (pullback p_le_q U).carrier = (maximal_sieve q).carrier
h
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
q : W
U : Sieve p
h : p q
ext r
h
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
q : W
U : Sieve p
h : p q
r : W
simp only [pullback, maximal_sieve, Set.mem_setOf_eq]
h
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
q : W
U : Sieve p
h : p q
r : W
r U.carrier q r q r
constructor
h.mp
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
q : W
U : Sieve p
h : p q
r : W
r U.carrier q rq r
h.mpr
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
q : W
U : Sieve p
h : p q
r : W
q rr U.carrier q r
·
h.mp
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
q : W
U : Sieve p
h : p q
r : W
r U.carrier q rq r
rintro ⟨_, hr
h.mp
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
q : W
U : Sieve p
h : p q
r : W
left✝ : r U.carrier
hr : q r
q r
; exact hr ·
h.mpr
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
q : W
U : Sieve p
h : p q
r : W
q rr U.carrier q r
intro hr
h.mpr
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
q : W
U : Sieve p
h : p q
r : W
hr : q r
r U.carrier q r
exact by
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
q : W
U : Sieve p
h : p q
r : W
hr : q r
r U.carrier
rw [hU]
P : Type u
inst✝¹ : HasCoverage P
W : Type u
inst✝ : Preorder W
p : W
q : W
U : Sieve p
h : p q
r : W
hr : q r
; exact le_trans h hr, hr
Beth.maximalSieveCoverage

We can then construe any Kripke frame as a discrete Beth frame:

instance bethFrameOfKripke (W : Type u) [F : Kripke.Frame W] : BethFrame W where
  coverage := maximalSieveCoverage W
  val      := F.val
  le_val   := F.le_val
  sheaf_condition := by
W : Type u
∀ {i : } {w : W} {S : Sieve w}, covers w S → (∀ qS, Kripke.Frame.val q i) → Kripke.Frame.val w i
intro i w
W : Type u
i :
w : W
∀ {S : Sieve w}, covers w S → (∀ qS, Kripke.Frame.val q i) → Kripke.Frame.val w i
S
W : Type u
i :
w : W
S : Sieve w
covers w S → (∀ qS, Kripke.Frame.val q i) → Kripke.Frame.val w i
hS
W : Type u
i :
w : W
S : Sieve w
hS : covers w S
(∀ qS, Kripke.Frame.val q i) → Kripke.Frame.val w i
hval
W : Type u
i :
w : W
S : Sieve w
hS : covers w S
hval : qS, Kripke.Frame.val q i
apply hval w
W : Type u
i :
w : W
S : Sieve w
hS : covers w S
hval : qS, Kripke.Frame.val q i
w S
show wS.carrier
W : Type u
i :
w : W
S : Sieve w
hS : covers w S
hval : qS, Kripke.Frame.val q i
w S.carrier
rw [hS]
W : Type u
i :
w : W
S : Sieve w
hS : covers w S
hval : qS, Kripke.Frame.val q i
; exact le_refl w nonempty_covers := by
W : Type u
∀ {w : W} {S : Sieve w}, covers w SNonemptyS.carrier
intro w S
W : Type u
w : W
S : Sieve w
covers w SNonemptyS.carrier
hS
W : Type u
w : W
S : Sieve w
hS : covers w S
NonemptyS.carrier
exact w, by
W : Type u
w : W
S : Sieve w
hS : covers w S
w S.carrier
rw [hS]
W : Type u
w : W
S : Sieve w
hS : covers w S
; exact le_refl w
Beth.Examples.bethFrameOfKripke

It is easy to see that in this case, Beth semantics reduces to the previous Kripke semantics. For example, suppose P ∨ Q holds at w. We then must have a cover S on which either P holds or on which Q holds. But the only cover is maximal, which includes w itself, and thus we have that either P holds at w or Q does.

Soundness for Beth Frames

Just as for Kripke semantics, it is straightforward to show that each of the proof rules preserves validity in a Beth frame:

  def assumption : Entails W (p :: Γ) p := fun _ all => all.1
  def wk : ΓΔEntails W Γ tEntails W Δ t :=
    fun hΓΔ Γ_to_t w all => Γ_to_t w (all_at_of_suffix hΓΔ all)
  def and_I : Entails W Γ pEntails W Γ qEntails W Γ (pq) :=
    fun p_holds q_holds w' all => p_holds w' all, q_holds w' all
  def and_E₁ : Entails W Γ (pq) → Entails W Γ p :=
    fun pq_holds w' all => (pq_holds w' all).1
  def and_E₂ : Entails W Γ (pq) → Entails W Γ q :=
    fun pq_holds w' all => (pq_holds w' all).2
  def or_I₁ : Entails W Γ pEntails W Γ (pq) := by
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
Entails W Γ pEntails W Γ (p q)
intro p_holds w'
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_holds : Entails W Γ p
w' : W
all_at_world w' Γat_world w' (p q)
all_w'
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_holds : Entails W Γ p
w' : W
all_w' : all_at_world w' Γ
at_world w' (p q)
simp
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_holds : Entails W Γ p
w' : W
all_w' : all_at_world w' Γ
S, covers w' S w'_1S, at_world w'_1 p at_world w'_1 q
exists maximal_sieve w'
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_holds : Entails W Γ p
w' : W
all_w' : all_at_world w' Γ
covers w' (maximal_sieve w') w'_1maximal_sieve w', at_world w'_1 p at_world w'_1 q
constructor
left
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_holds : Entails W Γ p
w' : W
all_w' : all_at_world w' Γ
covers w' (maximal_sieve w')
right
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_holds : Entails W Γ p
w' : W
all_w' : all_at_world w' Γ
w'_1maximal_sieve w', at_world w'_1 p at_world w'_1 q
·
left
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_holds : Entails W Γ p
w' : W
all_w' : all_at_world w' Γ
covers w' (maximal_sieve w')
apply covers_maximal ·
right
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_holds : Entails W Γ p
w' : W
all_w' : all_at_world w' Γ
w'_1maximal_sieve w', at_world w'_1 p at_world w'_1 q
intro v hv
right
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_holds : Entails W Γ p
w' : W
all_w' : all_at_world w' Γ
v : W
hv : v maximal_sieve w'
at_world v p at_world v q
have le : w'v := hv
right
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_holds : Entails W Γ p
w' : W
all_w' : all_at_world w' Γ
v : W
hv : v maximal_sieve w'
le : w' v
at_world v p at_world v q
left
right.h
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_holds : Entails W Γ p
w' : W
all_w' : all_at_world w' Γ
v : W
hv : v maximal_sieve w'
le : w' v
at_world v p
apply p_holds v
right.h
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_holds : Entails W Γ p
w' : W
all_w' : all_at_world w' Γ
v : W
hv : v maximal_sieve w'
le : w' v
all_at_world v Γ
apply mono_all le all_w'
  def or_I₂ : Entails W Γ qEntails W Γ (pq) := by
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
Entails W Γ qEntails W Γ (p q)
intro q_holds w'
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
q_holds : Entails W Γ q
w' : W
all_at_world w' Γat_world w' (p q)
all_w'
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
q_holds : Entails W Γ q
w' : W
all_w' : all_at_world w' Γ
at_world w' (p q)
simp
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
q_holds : Entails W Γ q
w' : W
all_w' : all_at_world w' Γ
S, covers w' S w'_1S, at_world w'_1 p at_world w'_1 q
exists maximal_sieve w'
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
q_holds : Entails W Γ q
w' : W
all_w' : all_at_world w' Γ
covers w' (maximal_sieve w') w'_1maximal_sieve w', at_world w'_1 p at_world w'_1 q
constructor
left
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
q_holds : Entails W Γ q
w' : W
all_w' : all_at_world w' Γ
covers w' (maximal_sieve w')
right
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
q_holds : Entails W Γ q
w' : W
all_w' : all_at_world w' Γ
w'_1maximal_sieve w', at_world w'_1 p at_world w'_1 q
·
left
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
q_holds : Entails W Γ q
w' : W
all_w' : all_at_world w' Γ
covers w' (maximal_sieve w')
apply covers_maximal ·
right
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
q_holds : Entails W Γ q
w' : W
all_w' : all_at_world w' Γ
w'_1maximal_sieve w', at_world w'_1 p at_world w'_1 q
intro v hv
right
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
q_holds : Entails W Γ q
w' : W
all_w' : all_at_world w' Γ
v : W
hv : v maximal_sieve w'
at_world v p at_world v q
have le : w'v := hv
right
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
q_holds : Entails W Γ q
w' : W
all_w' : all_at_world w' Γ
v : W
hv : v maximal_sieve w'
le : w' v
at_world v p at_world v q
right
right.h
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
q_holds : Entails W Γ q
w' : W
all_w' : all_at_world w' Γ
v : W
hv : v maximal_sieve w'
le : w' v
at_world v q
apply q_holds v
right.h
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
q_holds : Entails W Γ q
w' : W
all_w' : all_at_world w' Γ
v : W
hv : v maximal_sieve w'
le : w' v
all_at_world v Γ
apply mono_all le all_w'
  def or_E : Entails W Γ (pq) → Entails W (p :: Γ) cEntails W (q :: Γ) cEntails W Γ c := by
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
Entails W Γ (p q)Entails W (p :: Γ) cEntails W (q :: Γ) cEntails W Γ c
intro p_or_q c_ass_p
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
Entails W (q :: Γ) cEntails W Γ c
c_ass_q
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
Entails W Γ c
w'
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_at_world w' Γat_world w' c
all_w'
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
at_world w' c
letS, S_cov, pq_sem⟩ := p_or_q w' all_w'
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
at_world w' c
apply sheaf_term S_cov
a
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
w'_1S, at_world w'_1 c
intro v hv
a
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
v : W
hv : v S
at_world v c
let le : w'v := S.bounded hv
a
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
v : W
hv : v S
le : w' v := ···
at_world v c
match pq_sem v hv with | Or.inl p_holds =>
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
v : W
hv : v S
le : w' v := ···
p_holds : at_world v p
at_world v c
apply c_ass_p v
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
v : W
hv : v S
le : w' v := ···
p_holds : at_world v p
all_at_world v (p :: Γ)
constructor
left
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
v : W
hv : v S
le : w' v := ···
p_holds : at_world v p
at_world v p
right
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
v : W
hv : v S
le : w' v := ···
p_holds : at_world v p
all_at_world v Γ
·
left
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
v : W
hv : v S
le : w' v := ···
p_holds : at_world v p
at_world v p
exact p_holds ·
right
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
v : W
hv : v S
le : w' v := ···
p_holds : at_world v p
all_at_world v Γ
exact (mono_all le all_w') | Or.inr q_holds =>
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
v : W
hv : v S
le : w' v := ···
q_holds : at_world v q
at_world v c
apply c_ass_q v
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
v : W
hv : v S
le : w' v := ···
q_holds : at_world v q
all_at_world v (q :: Γ)
constructor
left
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
v : W
hv : v S
le : w' v := ···
q_holds : at_world v q
at_world v q
right
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
v : W
hv : v S
le : w' v := ···
q_holds : at_world v q
all_at_world v Γ
·
left
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
v : W
hv : v S
le : w' v := ···
q_holds : at_world v q
at_world v q
exact q_holds ·
right
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
p_or_q : Entails W Γ (p q)
c_ass_p : Entails W (p :: Γ) c
c_ass_q : Entails W (q :: Γ) c
w' : W
all_w' : all_at_world w' Γ
S : Sieve w'
S_cov : covers w' S
pq_sem : w'_1S, at_world w'_1 p at_world w'_1 q
v : W
hv : v S
le : w' v := ···
q_holds : at_world v q
all_at_world v Γ
exact (mono_all le all_w')
  def imp_I : Entails W (p :: Γ) qEntails W Γ (pq) :=
    fun q_ass_p _w' all_w' v w_le_v p_at_v =>
      q_ass_p v p_at_v, mono_all w_le_v all_w'
  def imp_E : Entails W Γ (pq) → Entails W Γ pEntails W Γ q :=
    fun q_if_p p_holds w' all_w' =>
      q_if_p w' all_w' w' (le_refl w') (p_holds w' all_w')
  def tt_I : Entails W Γ tt := fun _ _ => trivial
  def ff_E : Entails W Γ ffEntails W Γ p := by
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
Entails W Γ ffEntails W Γ p
intro ff_at_w w
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
ff_at_w : Entails W Γ ff
w : W
all_at_world w Γat_world w p
all_w
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
ff_at_w : Entails W Γ ff
w : W
all_w : all_at_world w Γ
at_world w p
exfalso
W : Type u
inst✝ : BethFrame W
t : Tm
p : Tm
q : Tm
c : Tm
Γ : Ctxt
ff_at_w : Entails W Γ ff
w : W
all_w : all_at_world w Γ
False
exact ff_at_w w all_w
Beth.Semantics

The only cases of interest are those of or, where for or-introduction we choose the maximal sieve to witness that if P is true, then P ∨ Q is true, and in the or-elimination principle we have to make use of the sheaf property for terms.

With these proof rules having been shown, the proof of soundness is identical to that for Kripke frames:

def soundness {W : Type u}[BethFrame W] {Γ : Ctxt}{tm : Tm} : Pf Γ tmEntails W Γ tm
  | Pf.assume =>
W : Type u
inst✝ : BethFrame W
Γ : Ctxt
tm✝ : Tm
tm : Tm
Γ✝ : Ctxt
Entails W (tm :: Γ✝) tm
by
W : Type u
inst✝ : BethFrame W
Γ : Ctxt
tm✝ : Tm
tm : Tm
Γ✝ : Ctxt
Entails W (tm :: Γ✝) tm
apply Semantics.assumption | Pf.wk le pf =>
W : Type u
inst✝ : BethFrame W
Γ✝¹ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Γ✝ : Ctxt
le : Γ✝ Γ
pf : Pf Γ✝ tm
Entails W Γ tm
by
W : Type u
inst✝ : BethFrame W
Γ✝¹ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Γ✝ : Ctxt
le : Γ✝ Γ
pf : Pf Γ✝ tm
Entails W Γ tm
apply Semantics.wk
a
W : Type u
inst✝ : BethFrame W
Γ✝¹ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Γ✝ : Ctxt
le : Γ✝ Γ
pf : Pf Γ✝ tm
Γ
a
W : Type u
inst✝ : BethFrame W
Γ✝¹ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Γ✝ : Ctxt
le : Γ✝ Γ
pf : Pf Γ✝ tm
Entails Wtm
Γ
W : Type u
inst✝ : BethFrame W
Γ✝¹ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Γ✝ : Ctxt
le : Γ✝ Γ
pf : Pf Γ✝ tm
Ctxt
exact le
a
W : Type u
inst✝ : BethFrame W
Γ✝¹ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Γ✝ : Ctxt
le : Γ✝ Γ
pf : Pf Γ✝ tm
Entails Wtm
apply soundness pf | Pf.and_I p q =>
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
q : Pf Γ Q✝
Entails W Γ (P✝ Q✝)
by
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
q : Pf Γ Q✝
Entails W Γ (P✝ Q✝)
apply Semantics.and_I
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
q : Pf Γ Q✝
Entails W Γ P✝
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
q : Pf Γ Q✝
Entails W Γ Q✝
apply soundness p
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
q : Pf Γ Q✝
Entails W Γ Q✝
apply soundness q | Pf.and_E₁ p =>
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Q✝ : Tm
p : Pf Γ (tm Q✝)
Entails W Γ tm
by
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Q✝ : Tm
p : Pf Γ (tm Q✝)
Entails W Γ tm
apply Semantics.and_E₁
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Q✝ : Tm
p : Pf Γ (tm Q✝)
Entails W Γ (tm ?q)
q
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
Q✝ : Tm
p : Pf Γ (tm Q✝)
Tm
apply soundness p | Pf.and_E₂ p =>
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
Entails W Γ tm
by
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
Entails W Γ tm
apply Semantics.and_E₂
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
Entails W Γ (?p tm)
p
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
Tm
apply soundness p | or_I₁ p =>
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
Entails W Γ (P✝ Q✝)
by
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
Entails W Γ (P✝ Q✝)
apply Semantics.or_I₁
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf Γ P✝
Entails W Γ P✝
apply soundness p | or_I₂ q =>
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
q : Pf Γ Q✝
Entails W Γ (P✝ Q✝)
by
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
q : Pf Γ Q✝
Entails W Γ (P✝ Q✝)
apply Semantics.or_I₂
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
q : Pf Γ Q✝
Entails W Γ Q✝
apply soundness q | or_E p_or_q c_ass_p c_ass_q =>
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W Γ tm
by
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W Γ tm
apply Semantics.or_E
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W Γ (?p ?q)
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W (?p :: Γ) tm
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W (?q :: Γ) tm
p
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Tm
q
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Tm
apply soundness p_or_q
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W (?p :: Γ) tm
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W (?q :: Γ) tm
apply soundness c_ass_p
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p_or_q : Pf Γ (P✝ Q✝)
c_ass_p : Pf (P✝ :: Γ) tm
c_ass_q : Pf (Q✝ :: Γ) tm
Entails W (?q :: Γ) tm
apply soundness c_ass_q | Pf.imp_I p =>
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf (P✝ :: Γ) Q✝
Entails W Γ (P✝ Q✝)
by
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf (P✝ :: Γ) Q✝
Entails W Γ (P✝ Q✝)
apply Semantics.imp_I
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm : Tm
Γ : Ctxt
P✝ : Tm
Q✝ : Tm
p : Pf (P✝ :: Γ) Q✝
Entails W (P✝ :: Γ) Q✝
apply soundness p | Pf.imp_E p q =>
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
q : Pf Γ P✝
Entails W Γ tm
by
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
q : Pf Γ P✝
Entails W Γ tm
apply Semantics.imp_E
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
q : Pf Γ P✝
Entails W Γ (?p tm)
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
q : Pf Γ P✝
Entails W Γ ?p
p
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
q : Pf Γ P✝
Tm
apply soundness p
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
P✝ : Tm
p : Pf Γ (P✝ tm)
q : Pf Γ P✝
Entails W Γ ?p
apply soundness q | Pf.tt_I => fun _ _ => trivial | Pf.ff_E pf =>
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
pf : Pf Γ Tm.ff
Entails W Γ tm
by
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
pf : Pf Γ Tm.ff
Entails W Γ tm
apply Semantics.ff_E
a
W : Type u
inst✝ : BethFrame W
Γ✝ : Ctxt
tm✝ : Tm
tm : Tm
Γ : Ctxt
pf : Pf Γ Tm.ff
Entails W Γ Tm.ff
apply soundness pf
Beth.soundness

Completeness for Beth Frames

Since Kripke frames are already complete for constructive logic, and each gives rise to a Beth frame, we already have a proof of completeness for Beth frames. However, one thing that is pleasing about this approach is that we can use the coverage of the frame to give a particularly elegant construction of countermodels. In particular, for our frame we now consider as worlds all contexts which are consistent:

structure World where
  carrier : Ctxt
  consistent : ¬ Pf carrier Tm.ff
Beth.Completeness.World

What makes us no longer need to consider prime theories is that we make use of a “Beth” topology, which gives us the truth lemma for disjunctions. Suppose we have a context \(\Gamma\), a term \(\mathrm{L}= \mathcal{P}_1 \lor \ldots \lor \mathcal{P}_{\mathrm{n}}\), and suppose further that we have a derivation \(\Gamma \vdash \mathcal{P}_1 \lor \ldots \lor \mathcal{P}_{\mathrm{n}}\); we then consider the coverage freely generated by the sets which decide which particular disjunct we have proven \(\{\Gamma : \mathcal{P}_{\mathrm{i}} \}_{i \in I}\).

We first give a way to construct generalized disjunctions:

def mk_disjunction : CtxtTm
  | [] => Tm.ff
  | t :: ts => Tm.or t (mk_disjunction ts)
Beth.Completeness.mk_disjunction

We also prove that the corresponding introduction and elimination rules for such generalized disjunctions are admissible in our proof theory:

theorem disjunction_intro {t : Tm} {Γ Δ : Ctxt}
    (t_in : tΔ) (pf : Pf Γ t) : Pf Γ (mk_disjunction Δ) := by
t : Tm
Γ : Ctxt
Δ : Ctxt
t_in : t Δ
pf : Pf Γ t
Pf Γ (mk_disjunction Δ)
induction Δ with | nil =>
nil
t : Tm
Γ : Ctxt
pf : Pf Γ t
t_in : t []
cases t_in | cons a Δ ih =>
cons
t : Tm
Γ : Ctxt
pf : Pf Γ t
a : Tm
Δ : List Tm
ih : t ΔPf Γ (mk_disjunction Δ)
t_in : t a :: Δ
Pf Γ (mk_disjunction (a :: Δ))
simp at t_in
cons
t : Tm
Γ : Ctxt
pf : Pf Γ t
a : Tm
Δ : List Tm
ih : t ΔPf Γ (mk_disjunction Δ)
t_in : t = a t Δ
Pf Γ (mk_disjunction (a :: Δ))
rcases t_in with rfl | ht
cons.inl
t : Tm
Γ : Ctxt
pf : Pf Γ t
Δ : List Tm
ih : t ΔPf Γ (mk_disjunction Δ)
Pf Γ (mk_disjunction (t :: Δ))
cons.inr
t : Tm
Γ : Ctxt
pf : Pf Γ t
a : Tm
Δ : List Tm
ih : t ΔPf Γ (mk_disjunction Δ)
ht : t Δ
Pf Γ (mk_disjunction (a :: Δ))
·
cons.inl
t : Tm
Γ : Ctxt
pf : Pf Γ t
Δ : List Tm
ih : t ΔPf Γ (mk_disjunction Δ)
Pf Γ (mk_disjunction (t :: Δ))
exact Pf.or_I₁ pf ·
cons.inr
t : Tm
Γ : Ctxt
pf : Pf Γ t
a : Tm
Δ : List Tm
ih : t ΔPf Γ (mk_disjunction Δ)
ht : t Δ
Pf Γ (mk_disjunction (a :: Δ))
simpa [mk_disjunction] using Pf.or_I₂ (ih ht)
Beth.Completeness.disjunction_intro
theorem disjunction_elim {p : Tm} {Γ : Ctxt} (Δ : Ctxt) :
    (∀ {t : Tm}, tΔPf (t :: Γ) p) →
    Pf Γ (mk_disjunction Δ) → Pf Γ p := by
p : Tm
Γ : Ctxt
Δ : Ctxt
(∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
intro htcase
p : Tm
Γ : Ctxt
Δ : Ctxt
htcase : ∀ {t : Tm}, t ΔPf (t :: Γ) p
: Pf Γ (mk_disjunction Δ)
Pf Γ p
induction Δ generalizing Γ with | nil =>
nil
p : Tm
Γ : Ctxt
htcase : ∀ {t : Tm}, t []Pf (t :: Γ) p
: Pf Γ (mk_disjunction [])
Pf Γ p
simp [mk_disjunction] at
nil
p : Tm
Γ : Ctxt
htcase : ∀ {t : Tm}, t []Pf (t :: Γ) p
: Pf Γ Tm.ff
Pf Γ p
exact Pf.ff_E | cons a Δ ih =>
cons
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (mk_disjunction (a :: Δ))
Pf Γ p
simp [mk_disjunction] at
cons
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
Pf Γ p
apply Pf.or_E
cons.a
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
Pf (a :: Γ) p
cons.a
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
Pf (mk_disjunction Δ :: Γ) p
·
cons.a
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
Pf (a :: Γ) p
exact htcase (by
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
a a :: Δ
simp) ·
cons.a
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
Pf (mk_disjunction Δ :: Γ) p
have htail : ∀ {t : Tm}, tΔPf (t :: mk_disjunction Δ :: Γ) p := by
p : Tm
Γ : Ctxt
Δ : Ctxt
(∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
intro t ht
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
t : Tm
ht : t Δ
Pf (t :: mk_disjunction Δ :: Γ) p
apply Syntax.Pf.monotone_mem (Γ := t :: Γ) (Δ := t :: mk_disjunction Δ :: Γ) (P := p)
hmem
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
t : Tm
ht : t Δ
Qt :: Γ, Q t :: mk_disjunction Δ :: Γ
a
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
t : Tm
ht : t Δ
Pf (t :: Γ) p
·
hmem
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
t : Tm
ht : t Δ
Qt :: Γ, Q t :: mk_disjunction Δ :: Γ
intro Q hQ
hmem
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
t : Tm
ht : t Δ
Q : Tm
hQ : Q t :: Γ
Q t :: mk_disjunction Δ :: Γ
have : Q = tQΓ := by
p : Tm
Γ : Ctxt
Δ : Ctxt
(∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
simpa using hQ rcases this with rfl | hmem
hmem.inl
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
Q : Tm
ht : Q Δ
hQ : Q Q :: Γ
Q Q :: mk_disjunction Δ :: Γ
hmem.inr
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
t : Tm
ht : t Δ
Q : Tm
hQ : Q t :: Γ
hmem : Q Γ
Q t :: mk_disjunction Δ :: Γ
·
hmem.inl
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
Q : Tm
ht : Q Δ
hQ : Q Q :: Γ
Q Q :: mk_disjunction Δ :: Γ
simp ·
hmem.inr
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
t : Tm
ht : t Δ
Q : Tm
hQ : Q t :: Γ
hmem : Q Γ
Q t :: mk_disjunction Δ :: Γ
simp [hmem] ·
a
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
t : Tm
ht : t Δ
Pf (t :: Γ) p
exact htcase (by
p : Tm
a : Tm
Δ : List Tm
ih : ∀ {Γ : Ctxt}, (∀ {t : Tm}, t ΔPf (t :: Γ) p) → Pf Γ (mk_disjunction Δ) → Pf Γ p
Γ : Ctxt
htcase : ∀ {t : Tm}, t a :: ΔPf (t :: Γ) p
: Pf Γ (a.or (mk_disjunction Δ))
t : Tm
ht : t Δ
t a :: Δ
simpa using Or.inr ht) exact ih htail Pf.assume
Beth.Completeness.disjunction_elim
theorem disjunction_two {Γ : Ctxt} {φ ψ : Tm} :
    Pf Γ (Tm.or φ ψ) → Pf Γ (mk_disjunction [φ, ψ]) := by
Γ : Ctxt
φ : Tm
ψ : Tm
Pf Γ (φ.or ψ) → Pf Γ (mk_disjunction [φ, ψ])
intro h
Γ : Ctxt
φ : Tm
ψ : Tm
h : Pf Γ (φ.or ψ)
Pf Γ (mk_disjunction [φ, ψ])
simp [mk_disjunction]
Γ : Ctxt
φ : Tm
ψ : Tm
h : Pf Γ (φ.or ψ)
Pf Γ (φ.or (ψ.or Tm.ff))
apply Pf.or_E h
a
Γ : Ctxt
φ : Tm
ψ : Tm
h : Pf Γ (φ.or ψ)
Pf (φ :: Γ) (φ.or (ψ.or Tm.ff))
a
Γ : Ctxt
φ : Tm
ψ : Tm
h : Pf Γ (φ.or ψ)
Pf (ψ :: Γ) (φ.or (ψ.or Tm.ff))
·
a
Γ : Ctxt
φ : Tm
ψ : Tm
h : Pf Γ (φ.or ψ)
Pf (φ :: Γ) (φ.or (ψ.or Tm.ff))
exact Pf.or_I₁ Pf.assume ·
a
Γ : Ctxt
φ : Tm
ψ : Tm
h : Pf Γ (φ.or ψ)
Pf (ψ :: Γ) (φ.or (ψ.or Tm.ff))
exact Pf.or_I₂ (Pf.or_I₁ Pf.assume)
Beth.Completeness.disjunction_two

Here is how we encode covering sieves proving one of the disjuncts (where we give the disjuncts as a list of proof terms L):

def context_sieve (Γ : World) (L : List Tm) : Sieve Γ where
  carrier := { Δ : World | (Γ.carrierΔ.carrier) ∧ (∃ AL, Pf Δ.carrier A) }
  bounded := by
Γ : World
L : List Tm
∀ {q : World}, q {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}Γ q
intro Δ
Γ : World
L : List Tm
Δ : World
: Δ {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}
Γ Δ
exact .1 upward_closed := by
Γ : World
L : List Tm
∀ {q r : World}, r {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}r qq {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}
intro Δ Θ
Γ : World
L : List Tm
Δ : World
Θ : World
Θ {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}Θ ΔΔ {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}
Γ : World
L : List Tm
Δ : World
Θ : World
: Θ {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}
Θ ΔΔ {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}
hle
Γ : World
L : List Tm
Δ : World
Θ : World
: Θ {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}
hle : Θ Δ
Δ {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}
constructor
left
Γ : World
L : List Tm
Δ : World
Θ : World
: Θ {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}
hle : Θ Δ
Γ.carrier Δ.carrier
right
Γ : World
L : List Tm
Δ : World
Θ : World
: Θ {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}
hle : Θ Δ
AL, Pf Δ.carrier A
·
left
Γ : World
L : List Tm
Δ : World
Θ : World
: Θ {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}
hle : Θ Δ
Γ.carrier Δ.carrier
exact List.IsSuffix.trans .1 hle ·
right
Γ : World
L : List Tm
Δ : World
Θ : World
: Θ {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}
hle : Θ Δ
AL, Pf Δ.carrier A
rcases .2 withA, hA, hPf
right
Γ : World
L : List Tm
Δ : World
Θ : World
: Θ {Δ | Γ.carrier Δ.carrier AL, Pf Δ.carrier A}
hle : Θ Δ
A : Tm
hA : A L
hPf : Pf Θ.carrier A
AL, Pf Δ.carrier A
exact A, hA, Pf.wk hle hPf
Beth.Completeness.context_sieve

Our coverage is then freely generated, under the closure conditions for a coverage, by these generating disjunction sieves:

inductive ContextCovers : (Γ : World) → Sieve ΓProp where
  | basic (Γ : World) (L : List Tm) {S : Sieve Γ} :
      Pf Γ.carrier (mk_disjunction L) →
      (context_sieve Γ L).carrierS.carrierContextCovers Γ S
  | maximal (Γ : World) :
      ContextCovers Γ (maximal_sieve Γ)
  | trans (Γ : World) (U V : Sieve Γ) :
      ContextCovers Γ U →
      (∀ q : U.carrier, ContextCovers (q : World) (pullback (U.bounded q.property) V)) →
      ContextCovers Γ V
Beth.Completeness.ContextCovers

We note that we don’t build in stability, as this already follows from the given closure conditions:

theorem ContextCovers.stable {Γ Δ : World} {U : Sieve Γ} (h : ΓΔ) :
    ContextCovers Γ UContextCovers Δ (pullback h U) := by
Γ : World
Δ : World
U : Sieve Γ
h : Γ Δ
ContextCovers Γ UContextCovers Δ (pullback h U)
intro hU
Γ : World
Δ : World
U : Sieve Γ
h : Γ Δ
hU : ContextCovers Γ U
ContextCovers Δ (pullback h U)
induction hU with | basic Γ L hpf hsub =>
basic
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
ContextCovers Δ (pullback h S✝)
apply ContextCovers.basic Δ L
basic.a
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
basic.a
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
·
basic.a
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
exact Pf.wk h hpf ·
basic.a
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
intro Θ
basic.a
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
Θ : World
: Θ (context_sieve Δ L).carrier
Θ (pullback h S✝).carrier
constructor
basic.a.left
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
Θ : World
: Θ (context_sieve Δ L).carrier
Θ S✝.carrier
basic.a.right
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
Θ : World
: Θ (context_sieve Δ L).carrier
Δ Θ
·
basic.a.left
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
Θ : World
: Θ (context_sieve Δ L).carrier
Θ S✝.carrier
apply hsub
basic.a.left.a
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
Θ : World
: Θ (context_sieve Δ L).carrier
Θ (context_sieve Γ L).carrier
constructor
basic.a.left.a.left
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
Θ : World
: Θ (context_sieve Δ L).carrier
Γ.carrier Θ.carrier
basic.a.left.a.right
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
Θ : World
: Θ (context_sieve Δ L).carrier
AL, Pf Θ.carrier A
·
basic.a.left.a.left
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
Θ : World
: Θ (context_sieve Δ L).carrier
Γ.carrier Θ.carrier
exact List.IsSuffix.trans h .1 ·
basic.a.left.a.right
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
Θ : World
: Θ (context_sieve Δ L).carrier
AL, Pf Θ.carrier A
exact .2 ·
basic.a.right
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
L : List Tm
S✝ : Sieve Γ
hsub : (context_sieve Γ L).carrier S✝.carrier
h : Γ Δ
Θ : World
: Θ (context_sieve Δ L).carrier
Δ Θ
exact .1 | maximal Γ =>
maximal
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
h : Γ Δ
have hEq : pullback h (maximal_sieve Γ) = maximal_sieve Δ := by
Γ : World
Δ : World
U : Sieve Γ
h : Γ Δ
ContextCovers Γ UContextCovers Δ (pullback h U)
apply Sieve.ext
h
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
h : Γ Δ
funext Θ
h.h
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
h : Γ Δ
Θ : World
apply propext
h.h.a
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
h : Γ Δ
Θ : World
constructor
h.h.a.mp
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
h : Γ Δ
Θ : World
(pullback h (maximal_sieve Γ)).carrier Θ → (maximal_sieve Δ).carrier Θ
h.h.a.mpr
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
h : Γ Δ
Θ : World
(maximal_sieve Δ).carrier Θ → (pullback h (maximal_sieve Γ)).carrier Θ
·
h.h.a.mp
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
h : Γ Δ
Θ : World
(pullback h (maximal_sieve Γ)).carrier Θ → (maximal_sieve Δ).carrier Θ
intro
h.h.a.mp
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
h : Γ Δ
Θ : World
: (pullback h (maximal_sieve Γ)).carrier Θ
exact .2 ·
h.h.a.mpr
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
h : Γ Δ
Θ : World
(maximal_sieve Δ).carrier Θ → (pullback h (maximal_sieve Γ)).carrier Θ
intro
h.h.a.mpr
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
h : Γ Δ
Θ : World
: (maximal_sieve Δ).carrier Θ
constructor
h.h.a.mpr.left
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
h : Γ Δ
Θ : World
: (maximal_sieve Δ).carrier Θ
h.h.a.mpr.right
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
h : Γ Δ
Θ : World
: (maximal_sieve Δ).carrier Θ
Δ Θ
·
h.h.a.mpr.left
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
h : Γ Δ
Θ : World
: (maximal_sieve Δ).carrier Θ
exact List.IsSuffix.trans h ·
h.h.a.mpr.right
Γ✝ : World
Δ : World
U : Sieve Γ
Γ : World
h : Γ Δ
Θ : World
: (maximal_sieve Δ).carrier Θ
Δ Θ
exact simpa [hEq] using ContextCovers.maximal Δ | trans Γ U V hU hV ihU ihV =>
trans
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
ContextCovers Δ (pullback h V)
apply ContextCovers.trans Δ (pullback h U)
trans.a
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
ContextCovers Δ (pullback h U)
trans.a
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
∀ (q : ↑(pullback h U).carrier), ContextCovers (↑q) (pullback ⋯ (pullback h V))
·
trans.a
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
ContextCovers Δ (pullback h U)
exact ihU h ·
trans.a
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
∀ (q : ↑(pullback h U).carrier), ContextCovers (↑q) (pullback ⋯ (pullback h V))
intro q
trans.a
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
ContextCovers (↑q) (pullback ⋯ (pullback h V))
have hq : (q : World) ∈ U.carrier := q.property.1
trans.a
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
ContextCovers (↑q) (pullback ⋯ (pullback h V))
have q_le : Δq := q.property.2
trans.a
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
ContextCovers (↑q) (pullback ⋯ (pullback h V))
have hEq : pullback ((pullback h U).bounded q.property) (pullback h V) = pullback (U.bounded hq) V := by
Γ : World
Δ : World
U : Sieve Γ
h : Γ Δ
ContextCovers Γ UContextCovers Δ (pullback h U)
apply Sieve.ext
h
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
(pullback ⋯ (pullback h V)).carrier = (pullbackV).carrier
funext r
h.h
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
r : World
(pullback ⋯ (pullback h V)).carrier r = (pullbackV).carrier r
apply propext
h.h.a
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
r : World
(pullback ⋯ (pullback h V)).carrier r (pullbackV).carrier r
constructor
h.h.a.mp
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
r : World
(pullback ⋯ (pullback h V)).carrier r → (pullbackV).carrier r
h.h.a.mpr
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
r : World
(pullbackV).carrier r → (pullback ⋯ (pullback h V)).carrier r
·
h.h.a.mp
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
r : World
(pullback ⋯ (pullback h V)).carrier r → (pullbackV).carrier r
intro hr
h.h.a.mp
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
r : World
hr : (pullback ⋯ (pullback h V)).carrier r
(pullbackV).carrier r
exact hr.1.1, hr.2 ·
h.h.a.mpr
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
r : World
(pullbackV).carrier r → (pullback ⋯ (pullback h V)).carrier r
intro hr
h.h.a.mpr
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
r : World
hr : (pullbackV).carrier r
(pullback ⋯ (pullback h V)).carrier r
simp [pullback] at hr
h.h.a.mpr
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
r : World
hr : {r | r V.carrier q r} r
(pullback ⋯ (pullback h V)).carrier r
constructor
h.h.a.mpr.left
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
r : World
hr : {r | r V.carrier q r} r
r (pullback h V).carrier
h.h.a.mpr.right
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
r : World
hr : {r | r V.carrier q r} r
q r
·
h.h.a.mpr.left
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
r : World
hr : {r | r V.carrier q r} r
r (pullback h V).carrier
simp [pullback]
h.h.a.mpr.left
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
r : World
hr : {r | r V.carrier q r} r
r V.carrier Δ r
exact hr.1, List.IsSuffix.trans q_le hr.2 ·
h.h.a.mpr.right
Γ✝ : World
Δ : World
U✝ : Sieve Γ
Γ : World
U : Sieve Γ
V : Sieve Γ
hU : ContextCovers Γ U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
ihU : ∀ (h : Γ Δ), ContextCovers Δ (pullback h U)
ihV : ∀ (q : ↑U.carrier) (h : ↑q Δ), ContextCovers Δ (pullback h (pullbackV))
h : Γ Δ
q : ↑(pullback h U).carrier
hq : q U.carrier
q_le : Δ q
r : World
hr : {r | r V.carrier q r} r
q r
exact hr.2 simpa [hEq] using hV (q : World), hq
Beth.Completeness.ContextCovers.stable

Hence we get a coverage on our worlds:

def contextCoverage : Coverage World where
  covers := ContextCovers
  maximal := ContextCovers.maximal
  transitive := by
∀ (p : World) (U V : Sieve p), ContextCovers p U → (∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)) → ContextCovers p V
intro p U
p : World
U : Sieve p
∀ (V : Sieve p), ContextCovers p U → (∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)) → ContextCovers p V
V
p : World
U : Sieve p
V : Sieve p
ContextCovers p U → (∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)) → ContextCovers p V
hU
p : World
U : Sieve p
V : Sieve p
hU : ContextCovers p U
(∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)) → ContextCovers p V
hV
p : World
U : Sieve p
V : Sieve p
hU : ContextCovers p U
hV : ∀ (q : ↑U.carrier), ContextCovers (↑q) (pullbackV)
exact ContextCovers.trans p U V hU hV stability := by
∀ {p q : World} {U : Sieve p}, ContextCovers p U → ∀ (p_le_q : p q), ContextCovers q (pullback p_le_q U)
intro p q
p : World
q : World
∀ {U : Sieve p}, ContextCovers p U → ∀ (p_le_q : p q), ContextCovers q (pullback p_le_q U)
U
p : World
q : World
U : Sieve p
ContextCovers p U → ∀ (p_le_q : p q), ContextCovers q (pullback p_le_q U)
hU
p : World
q : World
U : Sieve p
hU : ContextCovers p U
∀ (p_le_q : p q), ContextCovers q (pullback p_le_q U)
hpq
p : World
q : World
U : Sieve p
hU : ContextCovers p U
hpq : p q
ContextCovers q (pullback hpq U)
exact ContextCovers.stable hpq hU
Beth.Completeness.contextCoverage

The key lemma we then show is that if we have a covering sieve \(\mathcal{S}\) of \(\Gamma\), and for each context in the covering sieve we can prove some particular formula, then we can prove the formula at \(\Gamma\). In other words, provability forms a sheaf with respect to this model:

theorem pf_sheaf {Γ : World} {S : Sieve Γ} {r : Tm} :
    ContextCovers Γ S →
    (∀ ΔS.carrier, Pf Δ.carrier r) →
    Pf Γ.carrier r := by
Γ : World
S : Sieve Γ
r : Tm
ContextCovers Γ S → (∀ ΔS.carrier, Pf Δ.carrier r) → Pf Γ.carrier r
intro hCov hS
Γ : World
S : Sieve Γ
r : Tm
hCov : ContextCovers Γ S
hS : ΔS.carrier, Pf Δ.carrier r
Pf Γ.carrier r
induction hCov
basic
Γ : World
S : Sieve Γ
r : Tm
Γ✝ : World
L✝ : List Tm
S✝ : Sieve Γ✝
a✝¹ : Pf Γ✝.carrier (mk_disjunction L✝)
a✝ : (context_sieve Γ✝ L✝).carrier S✝.carrier
hS : ΔS✝.carrier, Pf Δ.carrier r
Pf Γ✝.carrier r
maximal
Γ : World
S : Sieve Γ
r : Tm
Γ✝ : World
hS : Δ ∈ (maximal_sieve Γ✝).carrier, Pf Δ.carrier r
Pf Γ✝.carrier r
trans
Γ : World
S : Sieve Γ
r : Tm
Γ✝ : World
U✝ : Sieve Γ✝
V✝ : Sieve Γ✝
a✝¹ : ContextCovers Γ✝ U✝
a✝ : ∀ (q : ↑U✝.carrier), ContextCovers (↑q) (pullbackV✝)
a_ih✝¹ : (∀ ΔU✝.carrier, Pf Δ.carrier r) → Pf Γ✝.carrier r
a_ih✝ : ∀ (q : ↑U✝.carrier), (∀ Δ ∈ (pullbackV✝).carrier, Pf Δ.carrier r) → Pf (↑q).carrier r
hS : ΔV✝.carrier, Pf Δ.carrier r
Pf Γ✝.carrier r
case basic Γ0 L S0 hPf hSub =>
Γ : World
S : Sieve Γ
r : Tm
Γ0 : World
L : List Tm
S0 : Sieve Γ✝
hPf : Pf Γ✝.carrier (mk_disjunction L✝)
hSub : (context_sieve Γ✝ L✝).carrier S✝.carrier
hS : ΔS✝.carrier, Pf Δ.carrier r
Pf Γ✝.carrier r
refine disjunction_elim (Γ := Γ0.carrier) L ?_ hPf
Γ : World
S : Sieve Γ
r : Tm
Γ0 : World
L : List Tm
S0 : Sieve Γ✝
hPf : Pf Γ✝.carrier (mk_disjunction L✝)
hSub : (context_sieve Γ✝ L✝).carrier S✝.carrier
hS : ΔS✝.carrier, Pf Δ.carrier r
∀ {t : Tm}, t LPf (t :: Γ0.carrier) r
intro t ht
Γ : World
S : Sieve Γ
r : Tm
Γ0 : World
L : List Tm
S0 : Sieve Γ✝
hPf : Pf Γ✝.carrier (mk_disjunction L✝)
hSub : (context_sieve Γ✝ L✝).carrier S✝.carrier
hS : ΔS✝.carrier, Pf Δ.carrier r
t : Tm
ht : t L
Pf (t :: Γ0.carrier) r
by_cases hff : Pf (t :: Γ0.carrier) Tm.ff
pos
Γ : World
S : Sieve Γ
r : Tm
Γ0 : World
L : List Tm
S0 : Sieve Γ✝
hPf : Pf Γ✝.carrier (mk_disjunction L✝)
hSub : (context_sieve Γ✝ L✝).carrier S✝.carrier
hS : ΔS✝.carrier, Pf Δ.carrier r
t : Tm
ht : t L
hff : Pf (t :: Γ0.carrier) Tm.ff
Pf (t :: Γ0.carrier) r
neg
Γ : World
S : Sieve Γ
r : Tm
Γ0 : World
L : List Tm
S0 : Sieve Γ✝
hPf : Pf Γ✝.carrier (mk_disjunction L✝)
hSub : (context_sieve Γ✝ L✝).carrier S✝.carrier
hS : ΔS✝.carrier, Pf Δ.carrier r
t : Tm
ht : t L
hff : ¬Pf (t :: Γ0.carrier) Tm.ff
Pf (t :: Γ0.carrier) r
·
pos
Γ : World
S : Sieve Γ
r : Tm
Γ0 : World
L : List Tm
S0 : Sieve Γ✝
hPf : Pf Γ✝.carrier (mk_disjunction L✝)
hSub : (context_sieve Γ✝ L✝).carrier S✝.carrier
hS : ΔS✝.carrier, Pf Δ.carrier r
t : Tm
ht : t L
hff : Pf (t :: Γ0.carrier) Tm.ff
Pf (t :: Γ0.carrier) r
exact Pf.ff_E hff ·
neg
Γ : World
S : Sieve Γ
r : Tm
Γ0 : World
L : List Tm
S0 : Sieve Γ✝
hPf : Pf Γ✝.carrier (mk_disjunction L✝)
hSub : (context_sieve Γ✝ L✝).carrier S✝.carrier
hS : ΔS✝.carrier, Pf Δ.carrier r
t : Tm
ht : t L
hff : ¬Pf (t :: Γ0.carrier) Tm.ff
Pf (t :: Γ0.carrier) r
let Δ : World := t :: Γ0.carrier, hff
neg
Γ : World
S : Sieve Γ
r : Tm
Γ0 : World
L : List Tm
S0 : Sieve Γ✝
hPf : Pf Γ✝.carrier (mk_disjunction L✝)
hSub : (context_sieve Γ✝ L✝).carrier S✝.carrier
hS : ΔS✝.carrier, Pf Δ.carrier r
t : Tm
ht : t L
hff : ¬Pf (t :: Γ0.carrier) Tm.ff
Δ : World := { carrier := t :: Γ0.carrier, consistent := hff }
Pf (t :: Γ0.carrier) r
have hin : Δ ∈ (context_sieve Γ0 L).carrier := by
Γ : World
S : Sieve Γ
r : Tm
ContextCovers Γ S → (∀ ΔS.carrier, Pf Δ.carrier r) → Pf Γ.carrier r
constructor
left
Γ : World
S : Sieve Γ
r : Tm
Γ0 : World
L : List Tm
S0 : Sieve Γ✝
hPf : Pf Γ✝.carrier (mk_disjunction L✝)
hSub : (context_sieve Γ✝ L✝).carrier S✝.carrier
hS : ΔS✝.carrier, Pf Δ.carrier r
t : Tm
ht : t L
hff : ¬Pf (t :: Γ0.carrier) Tm.ff
Δ : World := { carrier := t :: Γ0.carrier, consistent := hff }
Γ0.carrier Δ.carrier
right
Γ : World
S : Sieve Γ
r : Tm
Γ0 : World
L : List Tm
S0 : Sieve Γ✝
hPf : Pf Γ✝.carrier (mk_disjunction L✝)
hSub : (context_sieve Γ✝ L✝).carrier S✝.carrier
hS : ΔS✝.carrier, Pf Δ.carrier r
t : Tm
ht : t L
hff : ¬Pf (t :: Γ0.carrier) Tm.ff
Δ : World := { carrier := t :: Γ0.carrier, consistent := hff }
AL, Pf Δ.carrier A
·
left
Γ : World
S : Sieve Γ
r : Tm
Γ0 : World
L : List Tm
S0 : Sieve Γ✝
hPf : Pf Γ✝.carrier (mk_disjunction L✝)
hSub : (context_sieve Γ✝ L✝).carrier S✝.carrier
hS : ΔS✝.carrier, Pf Δ.carrier r
t : Tm
ht : t L
hff : ¬Pf (t :: Γ0.carrier) Tm.ff
Δ : World := { carrier := t :: Γ0.carrier, consistent := hff }
Γ0.carrier Δ.carrier
exact List.suffix_cons t Γ0.carrier ·
right
Γ : World
S : Sieve Γ
r : Tm
Γ0 : World
L : List Tm
S0 : Sieve Γ✝
hPf : Pf Γ✝.carrier (mk_disjunction L✝)
hSub : (context_sieve Γ✝ L✝).carrier S✝.carrier
hS : ΔS✝.carrier, Pf Δ.carrier r
t : Tm
ht : t L
hff : ¬Pf (t :: Γ0.carrier) Tm.ff
Δ : World := { carrier := t :: Γ0.carrier, consistent := hff }
AL, Pf Δ.carrier A
exact t, ht, Pf.assume exact hS Δ (hSub hin) case maximal Γ =>
Γ✝ : World
S : Sieve Γ
r : Tm
Γ : World
hS : Δ ∈ (maximal_sieve Γ✝).carrier, Pf Δ.carrier r
Pf Γ✝.carrier r
exact hS Γ (show ΓΓ from le_rfl) case trans Γ U V hU hV ihU ihV =>
Γ✝ : World
S : Sieve Γ
r : Tm
Γ : World
U : Sieve Γ✝
V : Sieve Γ✝
hU : ContextCovers Γ✝ U✝
hV : ∀ (q : ↑U✝.carrier), ContextCovers (↑q) (pullbackV✝)
ihU : (∀ ΔU✝.carrier, Pf Δ.carrier r) → Pf Γ✝.carrier r
ihV : ∀ (q : ↑U✝.carrier), (∀ Δ ∈ (pullbackV✝).carrier, Pf Δ.carrier r) → Pf (↑q).carrier r
hS : ΔV✝.carrier, Pf Δ.carrier r
Pf Γ✝.carrier r
apply ihU
Γ✝ : World
S : Sieve Γ
r : Tm
Γ : World
U : Sieve Γ✝
V : Sieve Γ✝
hU : ContextCovers Γ✝ U✝
hV : ∀ (q : ↑U✝.carrier), ContextCovers (↑q) (pullbackV✝)
ihU : (∀ ΔU✝.carrier, Pf Δ.carrier r) → Pf Γ✝.carrier r
ihV : ∀ (q : ↑U✝.carrier), (∀ Δ ∈ (pullbackV✝).carrier, Pf Δ.carrier r) → Pf (↑q).carrier r
hS : ΔV✝.carrier, Pf Δ.carrier r
ΔU.carrier, Pf Δ.carrier r
intro Δ
Γ✝ : World
S : Sieve Γ
r : Tm
Γ : World
U : Sieve Γ✝
V : Sieve Γ✝
hU : ContextCovers Γ✝ U✝
hV : ∀ (q : ↑U✝.carrier), ContextCovers (↑q) (pullbackV✝)
ihU : (∀ ΔU✝.carrier, Pf Δ.carrier r) → Pf Γ✝.carrier r
ihV : ∀ (q : ↑U✝.carrier), (∀ Δ ∈ (pullbackV✝).carrier, Pf Δ.carrier r) → Pf (↑q).carrier r
hS : ΔV✝.carrier, Pf Δ.carrier r
Δ : World
: Δ U.carrier
Pf Δ.carrier r
exact ihV Δ, (fun Θ => hS Θ .1)
Beth.Completeness.pf_sheaf

With that, we can then again prove the corresponding truth lemma by induction on the term:

theorem truth_lemma (w : World) : ∀ φ : Tm, at_world w φPf w.carrier φ
  | Tm.var i =>
w : World
i :
by
w : World
i :
rfl | Tm.and φ ψ =>
w : World
φ : Tm
ψ : Tm
at_world w (φ.and ψ) Pf w.carrier (φ.and ψ)
by
w : World
φ : Tm
ψ : Tm
at_world w (φ.and ψ) Pf w.carrier (φ.and ψ)
constructor
mp
w : World
φ : Tm
ψ : Tm
at_world w (φ.and ψ) → Pf w.carrier (φ.and ψ)
mpr
w : World
φ : Tm
ψ : Tm
Pf w.carrier (φ.and ψ) → at_world w (φ.and ψ)
·
mp
w : World
φ : Tm
ψ : Tm
at_world w (φ.and ψ) → Pf w.carrier (φ.and ψ)
intro h
mp
w : World
φ : Tm
ψ : Tm
h : at_world w (φ.and ψ)
Pf w.carrier (φ.and ψ)
exact Pf.and_I ((truth_lemma w φ).1 h.1) ((truth_lemma w ψ).1 h.2) ·
mpr
w : World
φ : Tm
ψ : Tm
Pf w.carrier (φ.and ψ) → at_world w (φ.and ψ)
intro h
mpr
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.and ψ)
at_world w (φ.and ψ)
constructor
mpr.left
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.and ψ)
at_world w φ
mpr.right
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.and ψ)
at_world w ψ
·
mpr.left
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.and ψ)
at_world w φ
rw [truth_lemma w φ]
mpr.left
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.and ψ)
Pf w.carrier φ
exact Pf.and_E₁ h ·
mpr.right
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.and ψ)
at_world w ψ
rw [truth_lemma w ψ]
mpr.right
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.and ψ)
Pf w.carrier ψ
exact Pf.and_E₂ h | Tm.or φ ψ =>
w : World
φ : Tm
ψ : Tm
at_world w (φ.or ψ) Pf w.carrier (φ.or ψ)
by
w : World
φ : Tm
ψ : Tm
at_world w (φ.or ψ) Pf w.carrier (φ.or ψ)
constructor
mp
w : World
φ : Tm
ψ : Tm
at_world w (φ.or ψ) → Pf w.carrier (φ.or ψ)
mpr
w : World
φ : Tm
ψ : Tm
Pf w.carrier (φ.or ψ) → at_world w (φ.or ψ)
·
mp
w : World
φ : Tm
ψ : Tm
at_world w (φ.or ψ) → Pf w.carrier (φ.or ψ)
intro h
mp
w : World
φ : Tm
ψ : Tm
h : at_world w (φ.or ψ)
Pf w.carrier (φ.or ψ)
rcases h withS, hS, hLocal
mp
w : World
φ : Tm
ψ : Tm
S : Sieve w
hS : covers w S
hLocal : w'S, at_world w' φ at_world w' ψ
Pf w.carrier (φ.or ψ)
change ContextCovers w S at hS
mp
w : World
φ : Tm
ψ : Tm
S : Sieve w
hLocal : w'S, at_world w' φ at_world w' ψ
hS : ContextCovers w S
Pf w.carrier (φ.or ψ)
apply pf_sheaf hS
mp
w : World
φ : Tm
ψ : Tm
S : Sieve w
hLocal : w'S, at_world w' φ at_world w' ψ
hS : ContextCovers w S
ΔS.carrier, Pf Δ.carrier (φ.or ψ)
intro Δ
mp
w : World
φ : Tm
ψ : Tm
S : Sieve w
hLocal : w'S, at_world w' φ at_world w' ψ
hS : ContextCovers w S
Δ : World
: Δ S.carrier
Pf Δ.carrier (φ.or ψ)
rcases hLocal Δ with |
mp.inl
w : World
φ : Tm
ψ : Tm
S : Sieve w
hLocal : w'S, at_world w' φ at_world w' ψ
hS : ContextCovers w S
Δ : World
: Δ S.carrier
: at_world Δ φ
Pf Δ.carrier (φ.or ψ)
mp.inr
w : World
φ : Tm
ψ : Tm
S : Sieve w
hLocal : w'S, at_world w' φ at_world w' ψ
hS : ContextCovers w S
Δ : World
: Δ S.carrier
: at_world Δ ψ
Pf Δ.carrier (φ.or ψ)
·
mp.inl
w : World
φ : Tm
ψ : Tm
S : Sieve w
hLocal : w'S, at_world w' φ at_world w' ψ
hS : ContextCovers w S
Δ : World
: Δ S.carrier
: at_world Δ φ
Pf Δ.carrier (φ.or ψ)
apply Pf.or_I₁
mp.inl.a
w : World
φ : Tm
ψ : Tm
S : Sieve w
hLocal : w'S, at_world w' φ at_world w' ψ
hS : ContextCovers w S
Δ : World
: Δ S.carrier
: at_world Δ φ
Pf Δ.carrier φ
rw [<- truth_lemma Δ φ]
mp.inl.a
w : World
φ : Tm
ψ : Tm
S : Sieve w
hLocal : w'S, at_world w' φ at_world w' ψ
hS : ContextCovers w S
Δ : World
: Δ S.carrier
: at_world Δ φ
at_world Δ φ
exact ·
mp.inr
w : World
φ : Tm
ψ : Tm
S : Sieve w
hLocal : w'S, at_world w' φ at_world w' ψ
hS : ContextCovers w S
Δ : World
: Δ S.carrier
: at_world Δ ψ
Pf Δ.carrier (φ.or ψ)
apply Pf.or_I₂
mp.inr.a
w : World
φ : Tm
ψ : Tm
S : Sieve w
hLocal : w'S, at_world w' φ at_world w' ψ
hS : ContextCovers w S
Δ : World
: Δ S.carrier
: at_world Δ ψ
Pf Δ.carrier ψ
rw [<- truth_lemma Δ ψ]
mp.inr.a
w : World
φ : Tm
ψ : Tm
S : Sieve w
hLocal : w'S, at_world w' φ at_world w' ψ
hS : ContextCovers w S
Δ : World
: Δ S.carrier
: at_world Δ ψ
at_world Δ ψ
exact ·
mpr
w : World
φ : Tm
ψ : Tm
Pf w.carrier (φ.or ψ) → at_world w (φ.or ψ)
intro h
mpr
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
at_world w (φ.or ψ)
refine context_sieve w [φ, ψ], ?_, ?_
mpr.refine_1
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
covers w (context_sieve w [φ, ψ])
mpr.refine_2
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
w'context_sieve w [φ, ψ], at_world w' φ at_world w' ψ
·
mpr.refine_1
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
covers w (context_sieve w [φ, ψ])
change ContextCovers w (context_sieve w [φ, ψ])
mpr.refine_1
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
apply ContextCovers.basic w [φ, ψ]
mpr.refine_1.a
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
mpr.refine_1.a
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
·
mpr.refine_1.a
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
exact disjunction_two h ·
mpr.refine_1.a
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
apply subset_rfl ·
mpr.refine_2
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
w'context_sieve w [φ, ψ], at_world w' φ at_world w' ψ
intro Δ
mpr.refine_2
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
Δ : World
: Δ context_sieve w [φ, ψ]
at_world Δ φ at_world Δ ψ
rcases .2 withA, hA, hPf
mpr.refine_2
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
Δ : World
: Δ context_sieve w [φ, ψ]
A : Tm
hA : A [φ, ψ]
hPf : Pf Δ.carrier A
at_world Δ φ at_world Δ ψ
simp at hA
mpr.refine_2
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
Δ : World
: Δ context_sieve w [φ, ψ]
A : Tm
hPf : Pf Δ.carrier A
hA : A = φ A = ψ
at_world Δ φ at_world Δ ψ
rcases hA with hA | hA
mpr.refine_2.inl
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
Δ : World
: Δ context_sieve w [φ, ψ]
A : Tm
hPf : Pf Δ.carrier A
hA : A = φ
at_world Δ φ at_world Δ ψ
mpr.refine_2.inr
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
Δ : World
: Δ context_sieve w [φ, ψ]
A : Tm
hPf : Pf Δ.carrier A
hA : A = ψ
at_world Δ φ at_world Δ ψ
·
mpr.refine_2.inl
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
Δ : World
: Δ context_sieve w [φ, ψ]
A : Tm
hPf : Pf Δ.carrier A
hA : A = φ
at_world Δ φ at_world Δ ψ
subst A
mpr.refine_2.inl
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
Δ : World
: Δ context_sieve w [φ, ψ]
hPf : Pf Δ.carrier φ
at_world Δ φ at_world Δ ψ
apply Or.inl
mpr.refine_2.inl.h
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
Δ : World
: Δ context_sieve w [φ, ψ]
hPf : Pf Δ.carrier φ
at_world Δ φ
rw [truth_lemma Δ φ]
mpr.refine_2.inl.h
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
Δ : World
: Δ context_sieve w [φ, ψ]
hPf : Pf Δ.carrier φ
Pf Δ.carrier φ
exact hPf ·
mpr.refine_2.inr
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
Δ : World
: Δ context_sieve w [φ, ψ]
A : Tm
hPf : Pf Δ.carrier A
hA : A = ψ
at_world Δ φ at_world Δ ψ
subst A
mpr.refine_2.inr
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
Δ : World
: Δ context_sieve w [φ, ψ]
hPf : Pf Δ.carrier ψ
at_world Δ φ at_world Δ ψ
apply Or.inr
mpr.refine_2.inr.h
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
Δ : World
: Δ context_sieve w [φ, ψ]
hPf : Pf Δ.carrier ψ
at_world Δ ψ
rw [truth_lemma Δ ψ]
mpr.refine_2.inr.h
w : World
φ : Tm
ψ : Tm
h : Pf w.carrier (φ.or ψ)
Δ : World
: Δ context_sieve w [φ, ψ]
hPf : Pf Δ.carrier ψ
Pf Δ.carrier ψ
exact hPf | Tm.imp φ ψ =>
w : World
φ : Tm
ψ : Tm
at_world w (φ.imp ψ) Pf w.carrier (φ.imp ψ)
by
w : World
φ : Tm
ψ : Tm
at_world w (φ.imp ψ) Pf w.carrier (φ.imp ψ)
constructor
mp
w : World
φ : Tm
ψ : Tm
at_world w (φ.imp ψ) → Pf w.carrier (φ.imp ψ)
mpr
w : World
φ : Tm
ψ : Tm
Pf w.carrier (φ.imp ψ) → at_world w (φ.imp ψ)
·
mp
w : World
φ : Tm
ψ : Tm
at_world w (φ.imp ψ) → Pf w.carrier (φ.imp ψ)
intro hImp
mp
w : World
φ : Tm
ψ : Tm
hImp : at_world w (φ.imp ψ)
Pf w.carrier (φ.imp ψ)
by_cases hff : Pf (φ :: w.carrier) Tm.ff
pos
w : World
φ : Tm
ψ : Tm
hImp : at_world w (φ.imp ψ)
hff : Pf (φ :: w.carrier) Tm.ff
Pf w.carrier (φ.imp ψ)
neg
w : World
φ : Tm
ψ : Tm
hImp : at_world w (φ.imp ψ)
hff : ¬Pf (φ :: w.carrier) Tm.ff
Pf w.carrier (φ.imp ψ)
·
pos
w : World
φ : Tm
ψ : Tm
hImp : at_world w (φ.imp ψ)
hff : Pf (φ :: w.carrier) Tm.ff
Pf w.carrier (φ.imp ψ)
exact Pf.imp_I (Pf.ff_E hff) ·
neg
w : World
φ : Tm
ψ : Tm
hImp : at_world w (φ.imp ψ)
hff : ¬Pf (φ :: w.carrier) Tm.ff
Pf w.carrier (φ.imp ψ)
let v : World := φ :: w.carrier, hff
neg
w : World
φ : Tm
ψ : Tm
hImp : at_world w (φ.imp ψ)
hff : ¬Pf (φ :: w.carrier) Tm.ff
Pf w.carrier (φ.imp ψ)
have hwv : wv := List.suffix_cons φ w.carrier
neg
w : World
φ : Tm
ψ : Tm
hImp : at_world w (φ.imp ψ)
hff : ¬Pf (φ :: w.carrier) Tm.ff
hwv : w v
Pf w.carrier (φ.imp ψ)
have hφv : at_world v φ := (truth_lemma v φ).2 Pf.assume
neg
w : World
φ : Tm
ψ : Tm
hImp : at_world w (φ.imp ψ)
hff : ¬Pf (φ :: w.carrier) Tm.ff
hwv : w v
hφv : at_world v φ
Pf w.carrier (φ.imp ψ)
have hψv : at_world v ψ := hImp v hwv hφv
neg
w : World
φ : Tm
ψ : Tm
hImp : at_world w (φ.imp ψ)
hff : ¬Pf (φ :: w.carrier) Tm.ff
hwv : w v
hφv : at_world v φ
hψv : at_world v ψ
Pf w.carrier (φ.imp ψ)
exact Pf.imp_I ((truth_lemma v ψ).1 hψv) ·
mpr
w : World
φ : Tm
ψ : Tm
Pf w.carrier (φ.imp ψ) → at_world w (φ.imp ψ)
intro hImp v
mpr
w : World
φ : Tm
ψ : Tm
hImp : Pf w.carrier (φ.imp ψ)
v : World
w vat_world v φat_world v ψ
hwv
mpr
w : World
φ : Tm
ψ : Tm
hImp : Pf w.carrier (φ.imp ψ)
v : World
hwv : w v
at_world v φat_world v ψ
hφv
mpr
w : World
φ : Tm
ψ : Tm
hImp : Pf w.carrier (φ.imp ψ)
v : World
hwv : w v
hφv : at_world v φ
at_world v ψ
have hImpv : Pf v.carrier (Tm.imp φ ψ) := Pf.wk hwv hImp
mpr
w : World
φ : Tm
ψ : Tm
hImp : Pf w.carrier (φ.imp ψ)
v : World
hwv : w v
hφv : at_world v φ
hImpv : Pf v.carrier (φ.imp ψ)
at_world v ψ
have hφp : Pf v.carrier φ := (truth_lemma v φ).1 hφv
mpr
w : World
φ : Tm
ψ : Tm
hImp : Pf w.carrier (φ.imp ψ)
v : World
hwv : w v
hφv : at_world v φ
hImpv : Pf v.carrier (φ.imp ψ)
hφp : Pf v.carrier φ
at_world v ψ
exact (truth_lemma v ψ).2 (Pf.imp_E hImpv hφp) | Tm.tt => by constructor
mp
w : World
mpr
w : World
·
mp
w : World
intro _
mp
w : World
a✝ : at_world w Tm.tt
exact Pf.tt_I ·
mpr
w : World
intro _
mpr
w : World
a✝ : Pf w.carrier Tm.tt
trivial | Tm.ff => by constructor
mp
w : World
mpr
w : World
·
mp
w : World
intro h exact False.elim h ·
mpr
w : World
intro h
mpr
exact False.elim (w.consistent h)
Beth.Completeness.truth_lemma

Now, suppose we cannot prove \(\Gamma \vdash \mathcal{P}\), but we have that \(\mathcal{P}\) holds in all Beth frames \(\Gamma \Vdash_{\mathrm{Beth}} \mathcal{P}\). We can then take \(\Gamma\) as our world, noting that if it doesn’t prove \(\mathcal{P}\), then it must be consistent. So, in order to get a contradiction, we only need to show that all the terms in \(\Gamma\) hold at \(\Gamma\), which readily follows by applying the truth lemma:

theorem all_at_world_self : ∀ w : World, all_at_world w w.carrier := by
∀ (w : World), all_at_world w w.carrier
intro w cases w with | mk carrier consistent =>
mk
carrier : Ctxt
consistent : ¬Pf carrier Tm.ff
all_at_world { carrier := carrier, consistent := consistent } { carrier := carrier, consistent := consistent }.carrier
induction carrier with | nil =>
mk.nil
consistent : ¬Pf [] Tm.ff
simp | cons φ Γ ih =>
mk.cons
φ : Tm
Γ : List Tm
ih : ∀ (consistent : ¬Pf Γ Tm.ff), all_at_world { carrier := Γ, consistent := consistent } { carrier := Γ, consistent := consistent }.carrier
consistent : ¬Pf (φ :: Γ) Tm.ff
all_at_world { carrier := φ :: Γ, consistent := consistent } { carrier := φ :: Γ, consistent := consistent }.carrier
have htail : ¬ Pf Γ Tm.ff := by
∀ (w : World), all_at_world w w.carrier
intro hff
φ : Tm
Γ : List Tm
ih : ∀ (consistent : ¬Pf Γ Tm.ff), all_at_world { carrier := Γ, consistent := consistent } { carrier := Γ, consistent := consistent }.carrier
consistent : ¬Pf (φ :: Γ) Tm.ff
hff : Pf Γ Tm.ff
False
exact consistent (Pf.wk (List.suffix_cons φ Γ) hff) constructor
mk.cons.left
φ : Tm
Γ : List Tm
ih : ∀ (consistent : ¬Pf Γ Tm.ff), all_at_world { carrier := Γ, consistent := consistent } { carrier := Γ, consistent := consistent }.carrier
consistent : ¬Pf (φ :: Γ) Tm.ff
htail : ¬Pf Γ Tm.ff
at_world { carrier := φ :: Γ, consistent := consistent } φ
mk.cons.right
φ : Tm
Γ : List Tm
ih : ∀ (consistent : ¬Pf Γ Tm.ff), all_at_world { carrier := Γ, consistent := consistent } { carrier := Γ, consistent := consistent }.carrier
consistent : ¬Pf (φ :: Γ) Tm.ff
htail : ¬Pf Γ Tm.ff
all_at_world { carrier := φ :: Γ, consistent := consistent } Γ
·
mk.cons.left
φ : Tm
Γ : List Tm
ih : ∀ (consistent : ¬Pf Γ Tm.ff), all_at_world { carrier := Γ, consistent := consistent } { carrier := Γ, consistent := consistent }.carrier
consistent : ¬Pf (φ :: Γ) Tm.ff
htail : ¬Pf Γ Tm.ff
at_world { carrier := φ :: Γ, consistent := consistent } φ
rw [truth_lemma φ :: Γ, consistent φ]
mk.cons.left
φ : Tm
Γ : List Tm
ih : ∀ (consistent : ¬Pf Γ Tm.ff), all_at_world { carrier := Γ, consistent := consistent } { carrier := Γ, consistent := consistent }.carrier
consistent : ¬Pf (φ :: Γ) Tm.ff
htail : ¬Pf Γ Tm.ff
Pf { carrier := φ :: Γ, consistent := consistent }.carrier φ
apply Pf.assume ·
mk.cons.right
φ : Tm
Γ : List Tm
ih : ∀ (consistent : ¬Pf Γ Tm.ff), all_at_world { carrier := Γ, consistent := consistent } { carrier := Γ, consistent := consistent }.carrier
consistent : ¬Pf (φ :: Γ) Tm.ff
htail : ¬Pf Γ Tm.ff
all_at_world { carrier := φ :: Γ, consistent := consistent } Γ
have Γ_le : Γφ :: Γ := by
∀ (w : World), all_at_world w w.carrier
apply List.suffix_cons have w_le : (Γ, htail : World) ≤ (φ :: Γ), consistent := by
∀ (w : World), all_at_world w w.carrier
exact Γ_le apply mono_all w_le
mk.cons.right
φ : Tm
Γ : List Tm
ih : ∀ (consistent : ¬Pf Γ Tm.ff), all_at_world { carrier := Γ, consistent := consistent } { carrier := Γ, consistent := consistent }.carrier
consistent : ¬Pf (φ :: Γ) Tm.ff
htail : ¬Pf Γ Tm.ff
Γ_le : Γ φ :: Γ
w_le : { carrier := Γ, consistent := htail } { carrier := φ :: Γ, consistent := consistent }
apply ih htail
Beth.Completeness.all_at_world_self

In our proof of completeness, we then split on whether \(\Gamma\) is consistent. As we noted, if it is not consistent, then we can use false elimination to immediately prove \(\mathcal{P}\), which is a contradiction. Otherwise, we may assume that \(\Gamma\) is consistent and so use our model at world \(\Gamma\). In this world we have that each of the premises hold by all_at_world_self, and so we have that \(\mathcal{P}\) is forced at this world. But then the truth lemma shows that \(\mathcal{P}\) must be provable:

theorem completeness {Γ : Ctxt} {P : Tm} : Beth.SemEntails.{0} Γ PPf Γ P := by
Γ : Ctxt
P : Tm
SemEntails Γ PPf Γ P
intro hsem
Γ : Ctxt
P : Tm
hsem : SemEntails Γ P
Pf Γ P
by_cases hff : Pf Γ Tm.ff
pos
Γ : Ctxt
P : Tm
hsem : SemEntails Γ P
hff : Pf Γ Tm.ff
Pf Γ P
neg
Γ : Ctxt
P : Tm
hsem : SemEntails Γ P
hff : ¬Pf Γ Tm.ff
Pf Γ P
·
pos
Γ : Ctxt
P : Tm
hsem : SemEntails Γ P
hff : Pf Γ Tm.ff
Pf Γ P
exact Pf.ff_E hff ·
neg
Γ : Ctxt
P : Tm
hsem : SemEntails Γ P
hff : ¬Pf Γ Tm.ff
Pf Γ P
let w : World := Γ, hff
neg
Γ : Ctxt
P : Tm
hsem : SemEntails Γ P
hff : ¬Pf Γ Tm.ff
w : World := { carrier := Γ, consistent := hff }
Pf Γ P
have : all_at_world w Γ := all_at_world_self w
neg
Γ : Ctxt
P : Tm
hsem : SemEntails Γ P
hff : ¬Pf Γ Tm.ff
w : World := { carrier := Γ, consistent := hff }
: all_at_world w Γ
Pf Γ P
have hP : at_world w P := hsem World w
neg
Γ : Ctxt
P : Tm
hsem : SemEntails Γ P
hff : ¬Pf Γ Tm.ff
w : World := { carrier := Γ, consistent := hff }
: all_at_world w Γ
hP : at_world w P
Pf Γ P
rw [<- truth_lemma w P]
neg
Γ : Ctxt
P : Tm
hsem : SemEntails Γ P
hff : ¬Pf Γ Tm.ff
w : World := { carrier := Γ, consistent := hff }
: all_at_world w Γ
hP : at_world w P
at_world w P
exact hP
Beth.Completeness.completeness

Revisiting Beth Trees

Let us lastly return to show that Beth trees can be given the structure of a Beth frame, with a topology generated by bars. We encode the conditions for a Beth tree as follows:

structure BethTree (α : Type u) where
  tree_node   : SnocList αProp
  root        : tree_node .nil
  prefix_closed : ∀ l a, tree_node (l :> a) → tree_node l
  pruned      : ∀ l, tree_node l → ∃ a, tree_node (l :> a)
Beth.BethTrees.BethTree

In order to define the notion of a bar, we first need a preliminary definition for the initial segment of a choice sequence:

def initial {α : Type u} (f : ℕ → α) : ℕ → SnocList α
  | 0     => .nil
  | n + 1 => initial f n :> f n
Beth.BethTrees.initial

A bar of a tree node T is then an intensional subset (i.e. a subset given as a property) whereby any choice sequence extending our given node eventually hits the bar:

def IsBar {α : Type u} (T : BethTree α) (l : SnocList α) (S : SnocList αProp) : Prop :=
  ∀ f : ℕ → α,
    T.tree_node l →
    (∀ n, T.tree_node (l ++ initial f n)) →
    ∃ n, S (l ++ initial f n)
Beth.BethTrees.IsBar

This then allows us to define a coverage on Beth trees:

def BethTreeCoverage {α : Type u} (T : BethTree α) :
    Coverage {l : SnocList α // T.tree_node l} where
  covers w S := IsBar T w.1 (nodeBar S)
  maximal := by
α : Type u
T : BethTree α
∀ (p : { l // T.tree_node l }), IsBar T (↑p) (nodeBar (maximal_sieve p))
introl, hlf
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
f : α
T.tree_nodel, hl → (∀ (n : ), T.tree_node (l, hl ++ initial f n)) → ∃ n, nodeBar (maximal_sieve l, hl) (l, hl ++ initial f n)
hl'
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
f : α
hl' : T.tree_nodel, hl
(∀ (n : ), T.tree_node (l, hl ++ initial f n)) → ∃ n, nodeBar (maximal_sieve l, hl) (l, hl ++ initial f n)
hpaths
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
f : α
hl' : T.tree_nodel, hl
hpaths : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n, nodeBar (maximal_sieve l, hl) (l, hl ++ initial f n)
refine 0, ?_
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
f : α
hl' : T.tree_nodel, hl
hpaths : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
simp only [initial, SnocList.append_nil, nodeBar, maximal_sieve, Set.mem_setOf_eq]
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
f : α
hl' : T.tree_nodel, hl
hpaths : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
∃ (h : T.tree_node l), l, hl l,
exact hl', le_refl _ stability := by
α : Type u
T : BethTree α
∀ {p q : { l // T.tree_node l }} {U : Sieve p}, IsBar T (↑p) (nodeBar U) → ∀ (p_le_q : p q), IsBar T (↑q) (nodeBar (pullback p_le_q U))
introps, hpsqs, hqs
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
qs : SnocList α
hqs : T.tree_node qs
∀ {U : Sieve ps, hps}, IsBar T (↑ps, hps) (nodeBar U) → ∀ (p_le_q : ps, hps qs, hqs), IsBar T (↑qs, hqs) (nodeBar (pullback p_le_q U))
S
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
qs : SnocList α
hqs : T.tree_node qs
S : Sieve ps, hps
IsBar T (↑ps, hps) (nodeBar S) → ∀ (p_le_q : ps, hps qs, hqs), IsBar T (↑qs, hqs) (nodeBar (pullback p_le_q S))
bar_in_S
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
qs : SnocList α
hqs : T.tree_node qs
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
∀ (p_le_q : ps, hps qs, hqs), IsBar T (↑qs, hqs) (nodeBar (pullback p_le_q S))
p_le_q
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
qs : SnocList α
hqs : T.tree_node qs
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
p_le_q : ps, hps qs, hqs
IsBar T (↑qs, hqs) (nodeBar (pullback p_le_q S))
f_qs
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
qs : SnocList α
hqs : T.tree_node qs
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
p_le_q : ps, hps qs, hqs
f_qs : α
T.tree_nodeqs, hqs → (∀ (n : ), T.tree_node (qs, hqs ++ initial f_qs n)) → ∃ n, nodeBar (pullback p_le_q S) (qs, hqs ++ initial f_qs n)
in_T
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
qs : SnocList α
hqs : T.tree_node qs
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
p_le_q : ps, hps qs, hqs
f_qs : α
in_T : T.tree_nodeqs, hqs
(∀ (n : ), T.tree_node (qs, hqs ++ initial f_qs n)) → ∃ n, nodeBar (pullback p_le_q S) (qs, hqs ++ initial f_qs n)
f_in_T
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
qs : SnocList α
hqs : T.tree_node qs
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
p_le_q : ps, hps qs, hqs
f_qs : α
in_T : T.tree_nodeqs, hqs
f_in_T : ∀ (n : ), T.tree_node (qs, hqs ++ initial f_qs n)
n, nodeBar (pullback p_le_q S) (qs, hqs ++ initial f_qs n)
haveI : Nonempty α := T.nonempty
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
qs : SnocList α
hqs : T.tree_node qs
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
p_le_q : ps, hps qs, hqs
f_qs : α
in_T : T.tree_nodeqs, hqs
f_in_T : ∀ (n : ), T.tree_node (qs, hqs ++ initial f_qs n)
this : Nonempty α
n, nodeBar (pullback p_le_q S) (qs, hqs ++ initial f_qs n)
obtainf_ps, n_ps, rfl⟩ := le_init ps qs p_le_q
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
n, nodeBar (pullback p_le_q S) (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
let f_total (i : ℕ) := if h : i < n_ps then f_ps i else f_qs (i - n_ps)
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
n, nodeBar (pullback p_le_q S) (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
have f_total_low : ∀ i < n_ps, f_total i = f_ps i := fun i hi => by
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
i :
hi : i < n_ps
f_total i = f_ps i
simp [f_total, hi] have f_total_high : ∀ i, f_total (n_ps + i) = f_qs i := fun i => by
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
i :
f_total (n_ps + i) = f_qs i
simp [f_total, show ¬ (n_ps + i < n_ps) from Nat.not_lt_of_le (Nat.le_add_right _ _)] have h_total_init : ∀ mn_ps, initial f_total m = initial f_ps m := fun m hm => initial_eq_of_agree (fun i hi => f_total_low i (Nat.lt_of_lt_of_le hi hm))
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
n, nodeBar (pullback p_le_q S) (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
have h_total_split : initial f_total n_ps = initial f_ps n_ps := h_total_init n_ps (le_refl _)
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
n, nodeBar (pullback p_le_q S) (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
have hpath_total : ∀ n, T.tree_node (ps ++ initial f_total n) := by
α : Type u
T : BethTree α
∀ {p q : { l // T.tree_node l }} {U : Sieve p}, IsBar T (↑p) (nodeBar U) → ∀ (p_le_q : p q), IsBar T (↑q) (nodeBar (pullback p_le_q U))
intro n
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
n :
T.tree_node (ps ++ initial f_total n)
by_cases h : nn_ps
pos
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
n :
h : n n_ps
T.tree_node (ps ++ initial f_total n)
neg
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
n :
h : ¬n n_ps
T.tree_node (ps ++ initial f_total n)
·
pos
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
n :
h : n n_ps
T.tree_node (ps ++ initial f_total n)
rw [h_total_init n h]
pos
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
n :
h : n n_ps
T.tree_node (ps ++ initial f_ps n)
exact T.prefix_closed' (SnocList.le_of_initial_le ps h) in_T ·
neg
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
n :
h : ¬n n_ps
T.tree_node (ps ++ initial f_total n)
push Not at h
neg
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
n :
h : n_ps < n
T.tree_node (ps ++ initial f_total n)
obtaink, rfl⟩ := Nat.exists_eq_add_of_le (Nat.le_of_lt h)
neg
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
k :
h : n_ps < n_ps + k
T.tree_node (ps ++ initial f_total (n_ps + k))
rw [initial_add, ← SnocList.append_assoc, h_total_split, initial_eq_of_agree (fun i _ => f_total_high i)]
neg
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
k :
h : n_ps < n_ps + k
T.tree_node (ps ++ initial f_ps n_ps ++ initial f_qs k)
exact f_in_T k obtainm, hm_bar⟩ := bar_in_S f_total hps hpath_total
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
m :
hm_bar : nodeBar S (ps, hps ++ initial f_total m)
n, nodeBar (pullback p_le_q S) (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
obtainhm_node, hm_mem⟩ := hm_bar
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
m :
hm_node : T.tree_node (ps, hps ++ initial f_total m)
hm_mem : ps, hps ++ initial f_total m, hm_node S.carrier
n, nodeBar (pullback p_le_q S) (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
by_cases hmle : n_psm
pos
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
m :
hm_node : T.tree_node (ps, hps ++ initial f_total m)
hm_mem : ps, hps ++ initial f_total m, hm_node S.carrier
hmle : n_ps m
n, nodeBar (pullback p_le_q S) (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
neg
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
m :
hm_node : T.tree_node (ps, hps ++ initial f_total m)
hm_mem : ps, hps ++ initial f_total m, hm_node S.carrier
hmle : ¬n_ps m
n, nodeBar (pullback p_le_q S) (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
·
pos
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
m :
hm_node : T.tree_node (ps, hps ++ initial f_total m)
hm_mem : ps, hps ++ initial f_total m, hm_node S.carrier
hmle : n_ps m
n, nodeBar (pullback p_le_q S) (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
obtaink, rfl⟩ := Nat.exists_eq_add_of_le hmle
pos
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
k :
hm_node : T.tree_node (ps, hps ++ initial f_total (n_ps + k))
hm_mem : ps, hps ++ initial f_total (n_ps + k), hm_node S.carrier
hmle : n_ps n_ps + k
n, nodeBar (pullback p_le_q S) (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
refine k, ?_
pos
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
k :
hm_node : T.tree_node (ps, hps ++ initial f_total (n_ps + k))
hm_mem : ps, hps ++ initial f_total (n_ps + k), hm_node S.carrier
hmle : n_ps n_ps + k
nodeBar (pullback p_le_q S) (ps ++ initial f_ps n_ps, hqs ++ initial f_qs k)
simp only [nodeBar, pullback, Set.mem_setOf_eq]
pos
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
k :
hm_node : T.tree_node (ps, hps ++ initial f_total (n_ps + k))
hm_mem : ps, hps ++ initial f_total (n_ps + k), hm_node S.carrier
hmle : n_ps n_ps + k
∃ (h : T.tree_node (ps ++ initial f_ps n_ps ++ initial f_qs k)), ps ++ initial f_ps n_ps ++ initial f_qs k, S.carrier ps ++ initial f_ps n_ps, hqs ps ++ initial f_ps n_ps ++ initial f_qs k,
have heq : ps ++ initial f_total (n_ps + k) = ps ++ initial f_ps n_ps ++ initial f_qs k := by
α : Type u
T : BethTree α
∀ {p q : { l // T.tree_node l }} {U : Sieve p}, IsBar T (↑p) (nodeBar U) → ∀ (p_le_q : p q), IsBar T (↑q) (nodeBar (pullback p_le_q U))
rw [initial_add, ← SnocList.append_assoc, h_total_split, initial_eq_of_agree (fun i _ => f_total_high i)] have hm_node' : T.tree_node (ps ++ initial f_ps n_ps ++ initial f_qs k) := heqhm_node
pos
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
k :
hm_node : T.tree_node (ps, hps ++ initial f_total (n_ps + k))
hm_mem : ps, hps ++ initial f_total (n_ps + k), hm_node S.carrier
hmle : n_ps n_ps + k
heq : ps ++ initial f_total (n_ps + k) = ps ++ initial f_ps n_ps ++ initial f_qs k
hm_node' : T.tree_node (ps ++ initial f_ps n_ps ++ initial f_qs k)
∃ (h : T.tree_node (ps ++ initial f_ps n_ps ++ initial f_qs k)), ps ++ initial f_ps n_ps ++ initial f_qs k, S.carrier ps ++ initial f_ps n_ps, hqs ps ++ initial f_ps n_ps ++ initial f_qs k,
have helem : (ps ++ initial f_total (n_ps + k), hm_node : {l : SnocList α // T.tree_node l}) = ps ++ initial f_ps n_ps ++ initial f_qs k, hm_node' := Subtype.ext heq
pos
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
k :
hm_node : T.tree_node (ps, hps ++ initial f_total (n_ps + k))
hm_mem : ps, hps ++ initial f_total (n_ps + k), hm_node S.carrier
hmle : n_ps n_ps + k
heq : ps ++ initial f_total (n_ps + k) = ps ++ initial f_ps n_ps ++ initial f_qs k
hm_node' : T.tree_node (ps ++ initial f_ps n_ps ++ initial f_qs k)
helem : ps ++ initial f_total (n_ps + k), hm_node = ps ++ initial f_ps n_ps ++ initial f_qs k, hm_node'
∃ (h : T.tree_node (ps ++ initial f_ps n_ps ++ initial f_qs k)), ps ++ initial f_ps n_ps ++ initial f_qs k, S.carrier ps ++ initial f_ps n_ps, hqs ps ++ initial f_ps n_ps ++ initial f_qs k,
exact hm_node', helemhm_mem, SnocList.is_prefix_append _ _ ·
neg
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
m :
hm_node : T.tree_node (ps, hps ++ initial f_total m)
hm_mem : ps, hps ++ initial f_total m, hm_node S.carrier
hmle : ¬n_ps m
n, nodeBar (pullback p_le_q S) (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
push Not at hmle
neg
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
m :
hm_node : T.tree_node (ps, hps ++ initial f_total m)
hm_mem : ps, hps ++ initial f_total m, hm_node S.carrier
hmle : m < n_ps
n, nodeBar (pullback p_le_q S) (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
refine 0, ?_
neg
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
m :
hm_node : T.tree_node (ps, hps ++ initial f_total m)
hm_mem : ps, hps ++ initial f_total m, hm_node S.carrier
hmle : m < n_ps
nodeBar (pullback p_le_q S) (ps ++ initial f_ps n_ps, hqs ++ initial f_qs 0)
simp only [initial, SnocList.append_nil, nodeBar, pullback, Set.mem_setOf_eq]
neg
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
m :
hm_node : T.tree_node (ps, hps ++ initial f_total m)
hm_mem : ps, hps ++ initial f_total m, hm_node S.carrier
hmle : m < n_ps
∃ (h : T.tree_node (ps ++ initial f_ps n_ps)), ps ++ initial f_ps n_ps, S.carrier ps ++ initial f_ps n_ps, hqs ps ++ initial f_ps n_ps,
have hm_le : mn_ps := Nat.le_of_lt hmle
neg
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
m :
hm_node : T.tree_node (ps, hps ++ initial f_total m)
hm_mem : ps, hps ++ initial f_total m, hm_node S.carrier
hmle : m < n_ps
hm_le : m n_ps
∃ (h : T.tree_node (ps ++ initial f_ps n_ps)), ps ++ initial f_ps n_ps, S.carrier ps ++ initial f_ps n_ps, hqs ps ++ initial f_ps n_ps,
have hle_qs : ps ++ initial f_total mps ++ initial f_ps n_ps := by
α : Type u
T : BethTree α
∀ {p q : { l // T.tree_node l }} {U : Sieve p}, IsBar T (↑p) (nodeBar U) → ∀ (p_le_q : p q), IsBar T (↑q) (nodeBar (pullback p_le_q U))
rw [h_total_init m hm_le]
α : Type u
T : BethTree α
ps : SnocList α
hps : T.tree_node ps
S : Sieve ps, hps
bar_in_S : IsBar T (↑ps, hps) (nodeBar S)
f_qs : α
this : Nonempty α
f_ps : α
n_ps :
hqs : T.tree_node (ps ++ initial f_ps n_ps)
p_le_q : ps, hps ps ++ initial f_ps n_ps, hqs
in_T : T.tree_nodeps ++ initial f_ps n_ps, hqs
f_in_T : ∀ (n : ), T.tree_node (ps ++ initial f_ps n_ps, hqs ++ initial f_qs n)
f_total : α := fun i => if h : i < n_ps then f_ps i else f_qs (i - n_ps)
f_total_low : i < n_ps, f_total i = f_ps i
f_total_high : ∀ (i : ), f_total (n_ps + i) = f_qs i
h_total_init : mn_ps, initial f_total m = initial f_ps m
h_total_split : initial f_total n_ps = initial f_ps n_ps
hpath_total : ∀ (n : ), T.tree_node (ps ++ initial f_total n)
m :
hm_node : T.tree_node (ps, hps ++ initial f_total m)
hm_mem : ps, hps ++ initial f_total m, hm_node S.carrier
hmle : m < n_ps
hm_le : m n_ps
ps ++ initial f_ps m ps ++ initial f_ps n_ps
; exact SnocList.le_of_initial_le ps hm_le exact hqs, S.upward_closed hm_mem hle_qs, le_refl _ transitive := by
α : Type u
T : BethTree α
∀ (p : { l // T.tree_node l }) (U V : Sieve p), IsBar T (↑p) (nodeBar U) → (∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))) → IsBar T (↑p) (nodeBar V)
introl, hlU
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
∀ (V : Sieve l, hl), IsBar T (↑l, hl) (nodeBar U) → (∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))) → IsBar T (↑l, hl) (nodeBar V)
V
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
IsBar T (↑l, hl) (nodeBar U) → (∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))) → IsBar T (↑l, hl) (nodeBar V)
bar_in_U
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
(∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))) → IsBar T (↑l, hl) (nodeBar V)
h_UV
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
IsBar T (↑l, hl) (nodeBar V)
f
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
T.tree_nodel, hl → (∀ (n : ), T.tree_node (l, hl ++ initial f n)) → ∃ n, nodeBar V (l, hl ++ initial f n)
in_T
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
(∀ (n : ), T.tree_node (l, hl ++ initial f n)) → ∃ n, nodeBar V (l, hl ++ initial f n)
f_in_T
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
f_in_T : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n, nodeBar V (l, hl ++ initial f n)
obtainn1, hn1_bar⟩ := bar_in_U f hl f_in_T
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
f_in_T : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n1 :
hn1_bar : nodeBar U (l, hl ++ initial f n1)
n, nodeBar V (l, hl ++ initial f n)
obtainhn1_node, hn1_mem⟩ := hn1_bar
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
f_in_T : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n1 :
hn1_node : T.tree_node (l, hl ++ initial f n1)
hn1_mem : l, hl ++ initial f n1, hn1_node U.carrier
n, nodeBar V (l, hl ++ initial f n)
let q := l ++ initial f n1
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
f_in_T : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n1 :
hn1_node : T.tree_node (l, hl ++ initial f n1)
hn1_mem : l, hl ++ initial f n1, hn1_node U.carrier
q : SnocList α := l ++ initial f n1
n, nodeBar V (l, hl ++ initial f n)
let f_tail (i : ℕ) := f (n1 + i)
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
f_in_T : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n1 :
hn1_node : T.tree_node (l, hl ++ initial f n1)
hn1_mem : l, hl ++ initial f n1, hn1_node U.carrier
q : SnocList α := l ++ initial f n1
f_tail : α := fun i => f (n1 + i)
n, nodeBar V (l, hl ++ initial f n)
have f_tail_in_T : ∀ n, T.tree_node (q ++ initial f_tail n) := fun n => by
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
f_in_T : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n1 :
hn1_node : T.tree_node (l, hl ++ initial f n1)
hn1_mem : l, hl ++ initial f n1, hn1_node U.carrier
q : SnocList α := l ++ initial f n1
f_tail : α := fun i => f (n1 + i)
n :
T.tree_node (q ++ initial f_tail n)
simpa [q, f_tail, initial_add, SnocList.append_assoc] using f_in_T (n1 + n) have h_cov_q := h_UV q, hn1_node, hn1_mem
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
f_in_T : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n1 :
hn1_node : T.tree_node (l, hl ++ initial f n1)
hn1_mem : l, hl ++ initial f n1, hn1_node U.carrier
q : SnocList α := l ++ initial f n1
f_tail : α := fun i => f (n1 + i)
f_tail_in_T : ∀ (n : ), T.tree_node (q ++ initial f_tail n)
h_cov_q : IsBar T (↑↑q, hn1_node, hn1_mem) (nodeBar (pullbackV))
n, nodeBar V (l, hl ++ initial f n)
obtainn2, hn2_bar⟩ := h_cov_q f_tail hn1_node f_tail_in_T
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
f_in_T : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n1 :
hn1_node : T.tree_node (l, hl ++ initial f n1)
hn1_mem : l, hl ++ initial f n1, hn1_node U.carrier
q : SnocList α := l ++ initial f n1
f_tail : α := fun i => f (n1 + i)
f_tail_in_T : ∀ (n : ), T.tree_node (q ++ initial f_tail n)
h_cov_q : IsBar T (↑↑q, hn1_node, hn1_mem) (nodeBar (pullbackV))
n2 :
hn2_bar : nodeBar (pullbackV) (↑↑q, hn1_node, hn1_mem ++ initial f_tail n2)
n, nodeBar V (l, hl ++ initial f n)
obtainhn2_node, hn2_mem⟩ := hn2_bar
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
f_in_T : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n1 :
hn1_node : T.tree_node (l, hl ++ initial f n1)
hn1_mem : l, hl ++ initial f n1, hn1_node U.carrier
q : SnocList α := l ++ initial f n1
f_tail : α := fun i => f (n1 + i)
f_tail_in_T : ∀ (n : ), T.tree_node (q ++ initial f_tail n)
h_cov_q : IsBar T (↑↑q, hn1_node, hn1_mem) (nodeBar (pullbackV))
n2 :
hn2_node : T.tree_node (↑↑q, hn1_node, hn1_mem ++ initial f_tail n2)
hn2_mem : ↑↑q, hn1_node, hn1_mem ++ initial f_tail n2, hn2_node (pullbackV).carrier
n, nodeBar V (l, hl ++ initial f n)
simp only [pullback, Set.mem_setOf_eq] at hn2_mem
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
f_in_T : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n1 :
hn1_node : T.tree_node (l, hl ++ initial f n1)
hn1_mem : l, hl ++ initial f n1, hn1_node U.carrier
q : SnocList α := l ++ initial f n1
f_tail : α := fun i => f (n1 + i)
f_tail_in_T : ∀ (n : ), T.tree_node (q ++ initial f_tail n)
h_cov_q : IsBar T (↑↑q, hn1_node, hn1_mem) (nodeBar (pullbackV))
n2 :
hn2_node : T.tree_node (↑↑q, hn1_node, hn1_mem ++ initial f_tail n2)
hn2_mem : q ++ initial f_tail n2, hn2_node V.carrier q, hn1_node q ++ initial f_tail n2, hn2_node
n, nodeBar V (l, hl ++ initial f n)
refine n1 + n2, ?_
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
f_in_T : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n1 :
hn1_node : T.tree_node (l, hl ++ initial f n1)
hn1_mem : l, hl ++ initial f n1, hn1_node U.carrier
q : SnocList α := l ++ initial f n1
f_tail : α := fun i => f (n1 + i)
f_tail_in_T : ∀ (n : ), T.tree_node (q ++ initial f_tail n)
h_cov_q : IsBar T (↑↑q, hn1_node, hn1_mem) (nodeBar (pullbackV))
n2 :
hn2_node : T.tree_node (↑↑q, hn1_node, hn1_mem ++ initial f_tail n2)
hn2_mem : q ++ initial f_tail n2, hn2_node V.carrier q, hn1_node q ++ initial f_tail n2, hn2_node
nodeBar V (l, hl ++ initial f (n1 + n2))
simp only [nodeBar]
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
f_in_T : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n1 :
hn1_node : T.tree_node (l, hl ++ initial f n1)
hn1_mem : l, hl ++ initial f n1, hn1_node U.carrier
q : SnocList α := l ++ initial f n1
f_tail : α := fun i => f (n1 + i)
f_tail_in_T : ∀ (n : ), T.tree_node (q ++ initial f_tail n)
h_cov_q : IsBar T (↑↑q, hn1_node, hn1_mem) (nodeBar (pullbackV))
n2 :
hn2_node : T.tree_node (↑↑q, hn1_node, hn1_mem ++ initial f_tail n2)
hn2_mem : q ++ initial f_tail n2, hn2_node V.carrier q, hn1_node q ++ initial f_tail n2, hn2_node
∃ (h : T.tree_node (l ++ initial f (n1 + n2))), l ++ initial f (n1 + n2), V.carrier
have heq : q ++ initial f_tail n2 = l ++ initial f (n1 + n2) := by
α : Type u
T : BethTree α
∀ (p : { l // T.tree_node l }) (U V : Sieve p), IsBar T (↑p) (nodeBar U) → (∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))) → IsBar T (↑p) (nodeBar V)
simp [q, f_tail, initial_add, SnocList.append_assoc] have hn2_node' : T.tree_node (l ++ initial f (n1 + n2)) := heqhn2_node
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
f_in_T : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n1 :
hn1_node : T.tree_node (l, hl ++ initial f n1)
hn1_mem : l, hl ++ initial f n1, hn1_node U.carrier
q : SnocList α := l ++ initial f n1
f_tail : α := fun i => f (n1 + i)
f_tail_in_T : ∀ (n : ), T.tree_node (q ++ initial f_tail n)
h_cov_q : IsBar T (↑↑q, hn1_node, hn1_mem) (nodeBar (pullbackV))
n2 :
hn2_node : T.tree_node (↑↑q, hn1_node, hn1_mem ++ initial f_tail n2)
hn2_mem : q ++ initial f_tail n2, hn2_node V.carrier q, hn1_node q ++ initial f_tail n2, hn2_node
heq : q ++ initial f_tail n2 = l ++ initial f (n1 + n2)
hn2_node' : T.tree_node (l ++ initial f (n1 + n2))
∃ (h : T.tree_node (l ++ initial f (n1 + n2))), l ++ initial f (n1 + n2), V.carrier
have helem : (q ++ initial f_tail n2, hn2_node : {l : SnocList α // T.tree_node l}) = l ++ initial f (n1 + n2), hn2_node' := Subtype.ext heq
α : Type u
T : BethTree α
l : SnocList α
hl : T.tree_node l
U : Sieve l, hl
V : Sieve l, hl
bar_in_U : IsBar T (↑l, hl) (nodeBar U)
h_UV : ∀ (q : ↑U.carrier), IsBar T (↑↑q) (nodeBar (pullbackV))
f : α
in_T : T.tree_nodel, hl
f_in_T : ∀ (n : ), T.tree_node (l, hl ++ initial f n)
n1 :
hn1_node : T.tree_node (l, hl ++ initial f n1)
hn1_mem : l, hl ++ initial f n1, hn1_node U.carrier
q : SnocList α := l ++ initial f n1
f_tail : α := fun i => f (n1 + i)
f_tail_in_T : ∀ (n : ), T.tree_node (q ++ initial f_tail n)
h_cov_q : IsBar T (↑↑q, hn1_node, hn1_mem) (nodeBar (pullbackV))
n2 :
hn2_node : T.tree_node (↑↑q, hn1_node, hn1_mem ++ initial f_tail n2)
hn2_mem : q ++ initial f_tail n2, hn2_node V.carrier q, hn1_node q ++ initial f_tail n2, hn2_node
heq : q ++ initial f_tail n2 = l ++ initial f (n1 + n2)
hn2_node' : T.tree_node (l ++ initial f (n1 + n2))
helem : q ++ initial f_tail n2, hn2_node = l ++ initial f (n1 + n2), hn2_node'
∃ (h : T.tree_node (l ++ initial f (n1 + n2))), l ++ initial f (n1 + n2), V.carrier
exact hn2_node', helemhn2_mem.1
Beth.BethTrees.BethTreeCoverage

We can then finally construct a concrete example of the full binary bit tree as a Beth frame. In our valuation we have that the variable \(\mathcal{P}:= \mathrm{var}\; 0\) is forced on the left false branch, and \(\mathcal{Q}:= \mathrm{var}\; 1\) is forced on the right true branch. As such, unlike Kripke semantics, we have that \(\mathcal{P}\lor \mathcal{Q}\) is forced at the root, by the bar of depth 1, despite neither \(\mathcal{P}\) nor \(\mathcal{Q}\) being forced at the root:

def binaryBranchVal : BethVal fullBinaryTree where
  val l i := match i with
    | 0 => (SnocList.nil :> false) ≤ l
    | 1 => (SnocList.nil :> true) ≤ l
    | _ => False
  mono_val := by
∀ {l m : SnocList Bool} {i : }, l mfullBinaryTree.tree_node m → (match i with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False) → match i with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False
intro l m
∀ {i : }, l mfullBinaryTree.tree_node m → (match i with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False) → match i with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False
i
l mfullBinaryTree.tree_node m → (match i with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False) → match i with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False
hle
i :
hle : l m
fullBinaryTree.tree_node m → (match i with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False) → match i with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False
_
(match i with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False) → match i with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False
hval
i :
hle : l m
hval : match i with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
match i with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False
match i with | 0 =>
i :
hle : l m
hval : match 0 with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
match 0 with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False
exact SnocList.is_prefix_trans hval hle | 1 =>
i :
hle : l m
hval : match 1 with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
match 1 with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False
exact SnocList.is_prefix_trans hval hle | _ + 2 =>
i :
hle : l m
n✝ :
hval : match n✝ + 2 with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
match n✝ + 2 with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False
exact hval.elim sheaf_val := by
∀ {l : SnocList Bool} {i : }, fullBinaryTree.tree_node lIsBar fullBinaryTree l {m | match i with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False}match i with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
intro l i
fullBinaryTree.tree_node lIsBar fullBinaryTree l {m | match i with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False}match i with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
_
IsBar fullBinaryTree l {m | match i with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False}match i with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
hbar
i :
hbar : IsBar fullBinaryTree l {m | match i with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False}
match i with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
match i with | 0 =>
i :
hbar : IsBar fullBinaryTree l {m | match 0 with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False}
match 0 with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
by_contra h
i :
hbar : IsBar fullBinaryTree l {m | match 0 with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False}
h : ¬match 0 with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
False
simp at h
i :
hbar : IsBar fullBinaryTree l {m | match 0 with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False}
False
simp at hbar -- If ¬ εₛ :> ff ≤ l, then the l ++ initial (fun _ => tt) is not barred obtainn, hn⟩ := hbar (fun _ => true) trivial (fun _ => trivial) apply not_prefix_false_of_const_true l n h hn | 1 =>
i :
hbar : IsBar fullBinaryTree l {m | match 1 with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False}
match 1 with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
by_contra h
i :
hbar : IsBar fullBinaryTree l {m | match 1 with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False}
h : ¬match 1 with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
False
simp at h
i :
hbar : IsBar fullBinaryTree l {m | match 1 with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False}
False
simp at hbar -- If ¬ εₛ :> tt ≤ l, then the l ++ initial (fun _ => ff) is not barred obtainn, hn⟩ := hbar (fun _ => false) trivial (fun _ => trivial) exact not_prefix_true_of_const_false l n h hn | i + 2 =>
i✝ :
i :
hbar : IsBar fullBinaryTree l {m | match i + 2 with | 0 => (εₛ :> false) m | 1 => (εₛ :> true) m | x => False}
match i + 2 with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
simp at hbar
match i + 2 with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
obtain ⟨_, hm, _⟩ := IsBar.nonempty fullBinaryTree hbar trivial
i✝ :
i :
w✝ : SnocList Bool
hm : w✝
right✝ : l w✝
match i + 2 with | 0 => (εₛ :> false) l | 1 => (εₛ :> true) l | x => False
exact hm.elim
abbrev root :  {l : SnocList Bool // fullBinaryTree.tree_node l} := ⟨.nil, trivial
example : at_world root (Tm.or (Tm.var 0) (Tm.var 1)) := by
  simp only [at_world]
S, covers root S w'S, BethFrame.val w' 0 BethFrame.val w' 1
let S : Sieve root := { carrier := {w | (εₛ :> false : SnocList Bool) ≤ w.1 ∨ (εₛ :> true : SnocList Bool) ≤ w.1}, bounded := fun _ => nil_prefix _, upward_closed := by
∀ {q r : { l // fullBinaryTree.tree_node l }}, r {w | (εₛ :> false) w (εₛ :> true) w}r qq {w | (εₛ :> false) w (εₛ :> true) w}
intro q r hmem r_le_q
hmem : r {w | (εₛ :> false) w (εₛ :> true) w}
r_le_q : r q
q {w | (εₛ :> false) w (εₛ :> true) w}
simp at hmem
hmem : (εₛ :> false) r (εₛ :> true) r
r_le_q : r q
q {w | (εₛ :> false) w (εₛ :> true) w}
apply hmem.imp
f
hmem : (εₛ :> false) r (εₛ :> true) r
r_le_q : r q
(εₛ :> false) r(εₛ :> false) q
g
hmem : (εₛ :> false) r (εₛ :> true) r
r_le_q : r q
(εₛ :> true) r(εₛ :> true) q
·
f
hmem : (εₛ :> false) r (εₛ :> true) r
r_le_q : r q
(εₛ :> false) r(εₛ :> false) q
exact (fun h => SnocList.is_prefix_trans h r_le_q) ·
g
hmem : (εₛ :> false) r (εₛ :> true) r
r_le_q : r q
(εₛ :> true) r(εₛ :> true) q
exact (fun h => SnocList.is_prefix_trans h r_le_q) } refine S, ?_, ?_
refine_2
w'S, BethFrame.val w' 0 BethFrame.val w' 1
· -- The sieve is a bar at nil: at depth 1, f 0 is false or true. intro f _
refine_1
(∀ (n : ), fullBinaryTree.tree_node (root ++ initial f n)) → ∃ n, nodeBar S (root ++ initial f n)
_
refine_1
n, nodeBar S (root ++ initial f n)
refine 1, trivial, ?_ -- Reduce nil ++ initial f 1 = nil :> f 0 and unfold set membership simp only [initial, SnocList.append_snoc, SnocList.append_nil]
refine_1
εₛ :> f 0, S.carrier
-- Goal: nil :> false ≤ nil :> f 0 ∨ nil :> true ≤ nil :> f 0 simp [S] exact Bool.casesOn (f 0) (Or.inl (Or.inl rfl)) (Or.inr (Or.inl rfl)) ·
refine_2
w'S, BethFrame.val w' 0 BethFrame.val w' 1
-- Every element of the sieve forces var 0 or var 1. introm, _⟩ hm
refine_2
property✝ : fullBinaryTree.tree_node m
hm : m, property✝ S
BethFrame.val m, property✝ 0 BethFrame.val m, property✝ 1
rcases hm with h | h
refine_2.inl
BethFrame.val m, property✝ 0 BethFrame.val m, property✝ 1
refine_2.inr
BethFrame.val m, property✝ 0 BethFrame.val m, property✝ 1
·
refine_2.inl
BethFrame.val m, property✝ 0 BethFrame.val m, property✝ 1
exact Or.inl h ·
refine_2.inr
BethFrame.val m, property✝ 0 BethFrame.val m, property✝ 1
exact Or.inr h
Beth.Examples.BinaryBitsTree

  1. One sometimes wonders which governmental agency is responsible for such names↩︎

  2. Analogous to a typing context↩︎

  3. We would be better off in a more long-lived implementation using a snoc-list here to fit with our typical spatial intuitions for contexts growing on the right↩︎

  4. We sometimes say the variable is forced at that world, because of the tight connection with Cohen’s use of forcing in set theory↩︎

  5. This is only consistency with respect to the background theory, in this case the type theory of lean↩︎

  6. Both are fundamentally connected to the compactness theorem and thus to the concept of ultrafilters↩︎

  7. They can be perused in all their details here for those who are curious↩︎

  8. One will note that we require our world to be prime, precisely in order to prove the case of the truth lemma↩︎

  9. This is typically called The Baire Space↩︎

  10. meaning that if it holds of a sequence, then it holds of its parent node↩︎

  11. As noted above, we would be better off using the dual preorder, and so throughout this section our terminology is regrettably non-standard. What we call a sieve is more typically now called a co-sieve. Similarly, we will later use the term pullback for something that evidently goes in the wrong direction.↩︎

  12. As noted, if we were considering sub-functors of \(\operatorname{Hom}(-, \mathcal{A})\) – and so set up our semantics as contravariant functors – as is much more typical in the literature on Grothendieck topologies, then this is indeed a kind of pullback↩︎

  13. I learned of this concept from Jeremy Avigad’s excellent book Mathematical Logic and Computation, but he calls this concept a “generalized Beth model”↩︎