---
title: "满足关系表的 Δ₀ 描述"
module: L.GCH.SatisfactionDescription
lang: zh
site: "Bedrock"
description: "满足表的 Δ₀ 描述"
stage: "证明 GCH"
reading_order: 100
canonical: https://bedrock.institute/zh/L.GCH.SatisfactionDescription.html
html: L.GCH.SatisfactionDescription.html
agda_source: https://github.com/BedrockInstitute/Bedrock/blob/main/src/L/GCH/SatisfactionDescription.lagda.md
prerequisites: [Base.Prelude, Base.Classical, FOL.ZFStructure, FOL.Syntax, FOL.LevyHierarchy, FOL.Absoluteness, V.Hierarchy, V.Coding, L.Constructible, L.Coding.EnvironmentSet, L.Coding.CodeSet, L.Coding.UniformSatisfaction, L.Coding.PinnedRecursion, L.Coding.Quantification, L.Coding.CodeAlphabet, L.Coding.CodeDomain, L.Coding.CodeDomainAdequacy, L.Coding.EnvironmentTower, L.Coding.SatisfactionClauses, L.Coding.SatisfactionClauseSemantics, L.Coding.SatisfactionGraphSet]
routes: [gch-descriptions]
translations: [https://bedrock.institute/en/L.GCH.SatisfactionDescription.md, https://bedrock.institute/ja/L.GCH.SatisfactionDescription.md]
agent_guide: /llms.txt
license: CC-BY-NC-SA-4.0
---
# 满足关系表的 Δ₀ 描述

外部语义递归已经构造出统一满足关系表。现在的问题是，在 `L` 中解释的公式如何把一个候选集合识别为同一张图。我们将把环境塔、公式码域、表的两条定义域条件与十条递归构造子子句封装成一条有界描述，供后续公式量化。

```agda
{-# OPTIONS --cubical --safe --guardedness #-}
```

这一构造仍以层级 `ℓ-suc ℓ` 上的排中律为条件。该假设支撑下文使用的编码与满足关系构造，但不会变成候选表的一项额外性质，而是始终显式携带。

```agda
open import Base.Prelude
open import Base.Classical using ( LEM )
```

固定宇宙层级 `ℓ` 与这一条经典假设。描述中使用的每个对象，从可构造集合到编码后的公式键，都处在相应层级，因此结论不引入更强的经典假设。

```agda
module L.GCH.SatisfactionDescription {ℓ : Level} (lem : LEM (ℓ-suc ℓ)) where
```

最终描述由三个公式合取而成。其句法目标是一个 `Δ₀` 证书，也就是描述中的每个量词都保持有界。正是这一有界性，使后文能够比较 `L` 内部与外围层级中的满足关系。

```agda
open import FOL.ZFStructure using ( module hPropStructure )
open import FOL.Syntax using
  ( Formula; _∧̇_ )
open import FOL.LevyHierarchy using ( Δ₀; δ-∧ )
import FOL.Absoluteness
```

三类编码数据必须彼此一致。公式键属于典范集合 `AllCodes W`；元数 `k` 指向环境集 `envSet W k`；有序对则把键与其语义值包装在一起。`AllCodes W` 的成员只能在命题截断下显露为某个公式键，后面的每一步解码都保留这一边界。

```agda
open import V.Hierarchy {ℓ} using ( 𝒮ᵥ )
open import V.Coding {ℓ} using ( pr; pr-inj )
open import L.Constructible {ℓ} using ( 𝒮ʟ; isL; isL-trans )
open import L.Coding.EnvironmentSet {ℓ} lem using ( envSet )
open import L.Coding.CodeSet {ℓ} lem using ( AllCodes; AllCodes-out; key∈AllCodes; keyS )
```

对每个真实公式键，语义递归产生满足集 `SatW ψ`，函数表则记录相应取值。有界描述并不在内部重新运行这项递归，而是列出十条局部构造子子句，再用结构论证表明：任何满足这些子句的候选表，在每个真实键处都被钉扎到外部定义的取值。

```agda
open import L.Coding.UniformSatisfaction {ℓ} lem using ( module Table; val-at )
open import L.Coding.PinnedRecursion {ℓ} lem using ( module Match ) public
open import L.Coding.PinnedRecursion {ℓ} lem using ( module SatSoundC; module SatHoldsC )
open import L.Coding.Quantification {ℓ} using ( f0; down )
open import L.Coding.CodeAlphabet {ℓ} using ( module Alphabet )
```

只有先控制定义域，才能读取构造子子句。候选码域必须包含全部真实公式键，并且只容纳这样的键；环境塔则把每个自然数元数与该长度的环境联系起来。这两项描述恰好为归纳提供所需的子公式键与环境。

```agda
open import L.Coding.CodeDomain {ℓ} using ( Tags; codesAt; Δ₀-codesAt )
open import L.Coding.CodeDomainAdequacy {ℓ} lem
  using ( module CodesSound; module CodesComplete; module CodesHolds )
open import L.Coding.EnvironmentTower {ℓ} lem
  using ( towerAt; Δ₀-towerAt; module Tower; module TowerRead; module TowerHolds )
```

剩下的对象是统一满足关系表的图。它的条目是由公式键与满足集组成的编码对。十条有界子句描述第二分量如何依赖第一分量所编码的构造子，而真实图将为这些子句提供完备性见证。

```agda
open import L.Coding.SatisfactionClauses {ℓ} using ( tableAt; Δ₀-tableAt )
open import L.Coding.SatisfactionClauseSemantics {ℓ} lem using ( module Frame; module Bridge )
open import L.Coding.SatisfactionGraphSet {ℓ} lem using ( module SatGraph )
```

解释环境是可构造集合组成的有限向量，其中的索引标识表、工作集、码域、塔与数码标签。依赖对表达各读式返回的见证。只要见证处在命题截断下，它就只能用于证明另一个命题，不能成为全局选定的数据。

```agda
open import Cubical.Data.Vec using ( lookup )
open import Cubical.Data.Sigma using ( _×_ )
open import Cubical.Foundations.HLevels using ( isPropΣ )
import Cubical.HITs.PropositionalTruncation as PT
open PT using ( ∥_∥₁; ∣_∣₁ )
```

自然数元数在累积层级内部表示为数码 `# k`。因此环境塔的条目被编码为 `# k` 与 `envSet W k` 的有序对。这里的等式始终陈述于底层的层级集合之间，这正是编码定理工作的层面。

```agda
open import Cubical.HITs.CumulativeHierarchy.Base using ( V; _∈_; setIsSet )
open import Cubical.HITs.CumulativeHierarchy.Constructions using ( module InfinitySet )
open InfinitySet {ℓ} using ( #_ )
```

以 `S` 表示可构造结构的载体。`S` 的元素由一个底层层级集合及其可构造性证据组成。表的读式比较的是底层集合，并不主张随附的可构造性证据相等。

```agda
open hPropStructure 𝒮ʟ using ( S )
```

本章的公式在 `L` 内部解释，其有限环境取值于 `S`。这些公式的有界性使后文能够与外围层级比较，但眼下的可靠性论证首先完全在这一内部满足关系中进行。

```agda
module AbsL = FOL.Absoluteness.Single 𝒮ᵥ isL isL-trans using ( _^_; _⊨ᵐ_ )
open AbsL using ( _^_ ) renaming ( _⊨ᵐ_ to _⊨_ )
```

## 有界描述的可靠性

为证明可靠性，固定候选集合 `T`、`C`、`E`、工作集 `W`、十个数码标签，以及读取它们的环境。分别假设塔、码域与表的描述成立，并且只把工作集槽与 `W` 对齐。这三项描述假设中，没有一项由另外两项推出。

```agda
module SatSound {m : ℕ} (T w C E : Fin m) (N : Fin 10 → Fin m) (γ : S ^ m) (W : S)
  (qw : fst (lookup w γ) ≡ fst W) (tg : Tags γ N)
  (hE : ⟨ γ ⊨ towerAt E w (N f0) ⟩) (hC : ⟨ γ ⊨ codesAt C w E N ⟩)
  (hT : ⟨ γ ⊨ tableAt T w C E N ⟩) where
  open Alphabet W
```

用 `Tv`、`Cv`、`Ev` 表示候选表、码域与环境塔所呈现的底层集合。子句语义提供一座桥，把关于这些集合的有界公式转换为结构论证所需的外围隶属与等式事实。

```agda
  open Bridge W
  private
    Tv = fst (lookup T γ)
    Cv = fst (lookup C γ)
    Ev = fst (lookup E γ)
```

设 `Ev` 的一个条目已经呈现为 `n` 与 `F` 的编码对。读取环境塔会在命题截断下给出元数 `k` 及等式 `n = # k`；忘去同时得到的 `F = envSet W k`，便得到分析候选公式键恰好所需的元数事实。反向的塔读式把每个真实元数条目放入 `Ev`，因而也能把真实键插入 `Cv`。

```agda
    module TR = TowerRead E w (N f0) γ W qw (tg f0) hE
    arity : (n F : S) → ⟨ pr (fst n) (fst F) ∈ Ev ⟩ → ∥ Σ[ k ∈ ℕ ] (fst n ≡ # k) ∥₁
    arity n F q∈ = PT.map (λ { (k , (qk , _)) → k , qk }) (TR.entry-out n F q∈)
    module CS = CodesSound C w E N γ W qw tg arity (hC .fst)
    module CC = CodesComplete C w E N γ W qw tg TR.entry-in (hC .snd)
```

前提 `hT` 由全定义性、定义域条件与十条构造子子句组成，`Frame` 则提供它们的语义读式。`SatSoundC` 中的钉扎论证把全定义性和十条子句与环境塔事实、候选码域的封闭性结合起来。该论证不需要定义域条件，因为要被钉扎的表项已经作为真实公式键处的一个配对给出；后面读取任意已呈现的表配对时，才会使用定义域条件。

```agda
    module Fr = Frame T w C E N γ tg
    module SC = SatSoundC T w C E N γ W qw tg hE CS.closed hT
```

两条定义域条件具有互补的形式。全定义性对 `Cv` 中每个 `c` 仅给出经命题截断的存在性：有某个 `y` 使 `pr c y` 属于 `Tv`。定义域条件则从 `Tv` 的任意成员 `e` 出发，同样在命题截断下把它分解为 `pr c y`，并给出 `c` 属于 `Cv`。两者都不在全局选定取值或配对分量，单凭其中任何一条也不能使该表成为单值关系。

```agda
    hTot = hT .fst
    hOn = hT .snd .fst
```

利用码域完备性把公式 `a` 的真实键放入 `Cv`，再对此键应用全域性。结论仅仅说某个值与该键组成的对属于 `Tv`，见证仍处在命题截断下。这里没有选定值，也没有解码函数；后文只会把它消去到命题中。

```agda
    sub : ∀ {n} (a : Formula Ab n) → ∥ Σ[ ya ∈ S ] ⟨ pr (fst (keyS W a)) (fst ya) ∈ Tv ⟩ ∥₁
    sub a = Fr.total-out hTot (keyS W a) (CC.key-in a)
```

钉扎谓词说：只要值 `y` 与 `ψ` 的键组成的对属于候选表，`y` 的底层集就等于 `ψ` 的递归满足集。它只钉扎底层集；`y` 的可构造性证书与公式本身都不由它固定。

```agda
  Pinned : ∀ {n} (ψ : Formula Ab n) → Type (ℓ-suc ℓ)
  Pinned ψ = (y : S) → ⟨ pr (fst (keyS W ψ)) (fst y) ∈ Tv ⟩ → fst y ≡ fst (SatW ψ)
```

证明对 `ψ` 作结构递归。`Cv` 的封闭性给出直接子公式的键，全定义性则只在命题截断下给出这些键处的表取值。递归假设钉扎这些子取值；相应的构造子子句随后给出与语义递归相同的外延条件，因此外延性钉扎父公式的取值。事实 `CC.key-in ψ` 则提供从 `ψ` 的键开始这项论证所需的候选码域隶属。

```agda
  pinned : ∀ {n} (ψ : Formula Ab n) → Pinned ψ
  pinned ψ = SC.pinned ψ (CC.key-in ψ)
```

候选码域的每个成员都属于典范码集。候选键读式只在命题截断下显露元数、公式与键等式。由于目标的典范隶属是命题，可以把见证消去到该目标，并沿等式搬运隶属；这一论证没有选定公式。

```agda
  C-out : (c : S) → ⟨ fst c ∈ Cv ⟩ → ⟨ fst c ∈ fst (AllCodes W) ⟩
  C-out c c∈ = PT.rec (snd (fst c ∈ fst (AllCodes W)))
    (λ { (k , ψ , e) → subst (λ u → ⟨ u ∈ fst (AllCodes W) ⟩) (sym e) (key∈AllCodes W ψ) })
    (CS.key-out c c∈)
```

反过来，典范码集的每个成员都属于 `Cv`。典范隶属在命题截断下给出公式键的呈现，码域完备性再把该键插入候选域。这里仍只用见证证明隶属，而不据此定义解码器。

```agda
  C-in : (c : S) → ⟨ fst c ∈ fst (AllCodes W) ⟩ → ⟨ fst c ∈ Cv ⟩
  C-in c c∈ = PT.rec (snd (fst c ∈ Cv))
    (λ { (k , ψ , e) → subst (λ u → ⟨ u ∈ Cv ⟩) (sym e) (CC.key-in ψ) })
    (AllCodes-out W c c∈)
```

环境塔的向外读式只处理已经呈现为 `pr n F` 的条目。它在命题截断下给出自然数 `k`，使 `n = # k` 且 `F = envSet W k`。它既不全局选定 `k`，也不声称仅凭本引理就能把 `Ev` 的任意成员呈现为编码对。

```agda
  E-out : (n F : S) → ⟨ pr (fst n) (fst F) ∈ Ev ⟩
        → ∥ Σ[ k ∈ ℕ ] ((fst n ≡ # k) × (fst F ≡ fst (envSet W k))) ∥₁
  E-out = TR.entry-out
```

环境塔的向内读式给出互补事实，而且无需命题截断：对每个给定的自然数 `k`，标准条目 `pr (# k) (envSet W k)` 都属于 `Ev`。它与上一条读式共同双向控制标准编码条目，但不主张为塔的每个任意成员选定元数。

```agda
  E-in : (k : ℕ) → ⟨ pr (# k) (fst (envSet W k)) ∈ Ev ⟩
  E-in = TR.entry-in
```

表的读取是可靠性方向的核心。它只对已经呈现为 `x` 与 `y` 的有序对的成员陈述；候选表的任意成员不在本引理覆盖范围内。

```agda
  T-out : (x y : S) → ⟨ pr (fst x) (fst y) ∈ Tv ⟩
        → Σ[ mx ∈ ⟨ fst x ∈ fst (AllCodes W) ⟩ ] (fst y ≡ fst (Table.val W W x mx))
  T-out x y h = PT.rec (isPropΣ (snd (fst x ∈ fst (AllCodes W))) (λ mx → setIsSet _ _))
    (λ { (c , yc , (ee , c∈)) → PT.rec (isPropΣ (snd (fst x ∈ fst (AllCodes W))) (λ mx → setIsSet _ _))
      (λ { (k , ψ , e) →
```

配对等式拆分出两侧的第一分量，码等式把被记录的键认同为某条解码公式的键；该公式键属于典范码集则由搬运得到。

```agda
        let q = pr-inj ee
            qx : fst x ≡ fst (keyS W ψ)
            qx = q .fst ∙ e
            mx : ⟨ fst x ∈ fst (AllCodes W) ⟩
            mx = subst (λ u → ⟨ u ∈ fst (AllCodes W) ⟩) (sym qx) (key∈AllCodes W ψ)
```

钉扎先把被记录值与递归满足集认同，`val-at` 再把该集合与同一键处的函数表取值认同。结论由典范码集隶属及底层集合等式组成。虽然它本身没有命题截断，但整个依赖对本身是命题，所以可以从命题截断下的解码中得到；这并不是计算性的解码。

```agda
        in mx , ( pinned ψ y (subst (λ u → ⟨ u ∈ Tv ⟩) (cong (λ a → pr a (fst y)) qx) h)
                ∙ sym (cong fst (val-at W W ψ x mx qx)) ) })
      (CS.key-out c c∈) })
    (Fr.onC-out hOn (down (lookup T γ) (pr (fst x) (fst y)) h) h)
```

为得到表的反向读式，从一个指定的典范码 `x` 出发。它在 `AllCodes W` 中的隶属在命题截断下给出公式 `ψ`，其键就是 `x`。全域性随后再次在命题截断下给出该公式键处记录的某个候选值。

```agda
  T-in : (x : S) (mx : ⟨ fst x ∈ fst (AllCodes W) ⟩) → ⟨ pr (fst x) (fst (Table.val W W x mx)) ∈ Tv ⟩
  T-in x mx = PT.rec (snd (pr (fst x) (fst (Table.val W W x mx)) ∈ Tv))
    (λ { (k , ψ , e) → PT.rec (snd (pr (fst x) (fst (Table.val W W x mx)) ∈ Tv))
      (λ { (y , my) →
        subst (λ u → ⟨ u ∈ Tv ⟩)
```

候选值被钉扎到递归满足集，值引理把它与函数表值对齐；隶属随即沿有序对等式搬运。两次消去都落在表隶属这一命题上。

```agda
          (cong₂ pr (sym e) (pinned ψ y my ∙ sym (cong fst (val-at W W ψ x mx e))))
          my })
      (sub ψ) })
    (AllCodes-out W x mx)
```

## 完备性与两种读法

完备性从具体的语义对象出发，而不是从任意候选出发。环境中的四个槽分别与 `W`、真实图 `SatGraph.pairs W`、典范码集 `AllCodes W`、真实塔 `Tower.tower W` 对齐，十个标签也被固定。这些对齐是前提，不是有界子句的结论。

```agda
module SatHolds {m : ℕ} (T w C E : Fin m) (N : Fin 10 → Fin m) (γ : S ^ m) (W : S)
  (qw : fst (lookup w γ) ≡ fst W) (qT : fst (lookup T γ) ≡ fst (SatGraph.pairs W))
  (qC : fst (lookup C γ) ≡ fst (AllCodes W)) (qE : fst (lookup E γ) ≡ fst (Tower.tower W))
  (tg : Tags γ N) where
  open Alphabet W
```

记表槽与码域槽中的底层集合为 `Tv` 与 `Cv`。对齐 `qT` 与 `qC` 把它们的隶属事实分别搬运到真实图与典范码集中。因此，已呈现的表配对可以用真实图的读式处理，而公式码的解码仍只在命题截断下成立。下面每条等式依然只比较底层层级集合。

```agda
  open Bridge W
  private
    Tv = fst (lookup T γ)
    Cv = fst (lookup C γ)
```

在与公式键同一视的码处的表值，等于该公式的递归满足集。证明从真实满足图读出该对，沿「被呈现键与公式键」的同一视搬运第二分量，最后以值引理收尾。

```agda
    val≡ : ∀ {n} (ψ : Formula Ab n) (c yc : S) → fst c ≡ fst (keyS W ψ)
         → ⟨ pr (fst c) (fst yc) ∈ Tv ⟩ → fst yc ≡ fst (SatW ψ)
    val≡ ψ c yc qc h =
      let p = SatGraph.pairs-out W c yc (subst (λ u → ⟨ pr (fst c) (fst yc) ∈ u ⟩) qT h)
      in p .snd ∙ cong fst (SatGraph.valOf≡ W c (p .fst)) ∙ cong fst (val-at W W ψ c (p .fst) qc)
```

若码域成员呈现为 `pr (# n) z`，把它搬入 `AllCodes W` 后便可在命题截断下解码：存在某条公式 `ψ : Formula Ab n`，其载荷为 `z`。这里既没有选定公式，也没有解码唯一性，因而没有定义出解码函数。

```agda
    decode : (c : S) → ⟨ fst c ∈ Cv ⟩ → (n : ℕ) (z : V ℓ) → fst c ≡ pr (# n) z
           → ∥ Σ[ ψ ∈ Formula Ab n ] (z ≡ cd ψ) ∥₁
    decode c c∈ = Match.decodeAll W c (subst (λ u → ⟨ fst c ∈ u ⟩) qC c∈)
```

对候选码 `c`，它与典范码集的对齐使 `c` 成为真实图的合法输入。真实图在此码处的取值给出一个表项，再沿 `Tv` 与 `SatGraph.pairs W` 的对齐搬回。所得存在陈述仍处在命题截断下，恰好符合全域性子句的要求。

```agda
    tot : (c : S) → ⟨ fst c ∈ Cv ⟩ → ∥ Σ[ yc ∈ S ] ⟨ pr (fst c) (fst yc) ∈ Tv ⟩ ∥₁
    tot c c∈ =
      let mx = subst (λ u → ⟨ fst c ∈ u ⟩) qC c∈
      in ∣ SatGraph.valOf W c mx , subst (λ u → ⟨ pr (fst c) (fst (SatGraph.valOf W c mx)) ∈ u ⟩) (sym qT) (SatGraph.pairs-in W c mx) ∣₁
```

真实图还给出任意表成员所需的形状。在命题截断下，每个这样的成员都是某个码与其图取值组成的编码对，而且该码属于 `Cv`。这只是存在性的分解，并没有为每个成员选定分量。

```agda
    onc : (e : S) → ⟨ fst e ∈ Tv ⟩
        → ∥ Σ[ c ∈ S ] Σ[ yc ∈ S ] ((fst e ≡ pr (fst c) (fst yc)) × ⟨ fst c ∈ Cv ⟩) ∥₁
    onc e e∈ = PT.map
      (λ { (x , mx , ee) → x , SatGraph.valOf W x mx , (ee , subst (λ u → ⟨ fst x ∈ u ⟩) (sym qC) mx) })
      (SatGraph.pairs-shape W e (subst (λ u → ⟨ fst e ∈ u ⟩) qT e∈))
```

`SatHoldsC.holds` 的各项输入分工明确。真实环境塔提供环境行，`val≡` 识别真实公式键处的取值，`decode` 只从具有指定形状的码中解出经命题截断的公式，`tot` 与 `onc` 则建立两条定义域条件。结构论证随后验证全部十条构造子子句。它每次使用经命题截断的元数、公式或分解时，都只把见证消去到「相应子句得到满足」这一命题中，不会产生全局解码器或表取值的选择。

```agda
  holds : ⟨ γ ⊨ tableAt T w C E N ⟩
  holds = SatHoldsC.holds W T w C E N γ qw tg
    (TowerHolds.holds E w (N f0) γ W qw qE (tg f0)) val≡ decode tot onc
```

密封公式 `satAt` 封装三条彼此独立的描述：`towerAt`、`codesAt` 与 `tableAt`。环境塔分量接收标签槽 `N f0`，`Tags` 把该槽识别为数码零；码域分量与表分量则接收完整的十槽族 `N`。这项合取本身不会给出候选对象与典范环境塔、码集或满足关系图之间的等式。

```agda
opaque
  satAt : ∀ {m} → Fin m → Fin m → Fin m → Fin m → (Fin 10 → Fin m) → Formula S m
  satAt T w C E N = towerAt E w (N f0) ∧̇ (codesAt C w E N ∧̇ tableAt T w C E N)
```

后续论证可以把 `satAt` 当作一个完整的有界谓词，无需反复展开它的三个分量。检查它是否属于 Lévy 层级等句法性质时，定义只在受控范围内展开；语义上的使用则通过下面的投影与完备性结果进行。不透明性只标出这道证明边界，并不增加任何模型论性质。

```agda
opaque
  unfolding satAt
```

证书 `Δ₀-satAt` 利用有界片段对合取的封闭性，把三个分量的证书组合起来。它只建立 `satAt` 的句法有界性，尚未说明哪些集合满足该公式。后面的 `SatRead` 与 `sat-complete` 才分别提供语义上的两个方向。

```agda
  Δ₀-satAt : ∀ {m} (T w C E : Fin m) (N : Fin 10 → Fin m) → Δ₀ (satAt T w C E N)
  Δ₀-satAt T w C E N = δ-∧ (Δ₀-towerAt E w (N f0)) (δ-∧ (Δ₀-codesAt C w E N) (Δ₀-tableAt T w C E N))
```

从 `satAt` 的证明中可以取回可靠性所需的三项精确前提：环境塔描述、码域描述与表描述。这一投影不增加语义结论，也不给出候选对象与典范对象的等式。

```agda
  satAt-out : ∀ {m} (T w C E : Fin m) (N : Fin 10 → Fin m) (γ : S ^ m)
            → ⟨ γ ⊨ satAt T w C E N ⟩
            → ⟨ γ ⊨ towerAt E w (N f0) ⟩ × (⟨ γ ⊨ codesAt C w E N ⟩ × ⟨ γ ⊨ tableAt T w C E N ⟩)
  satAt-out T w C E N γ h = h
```

反过来，这三项描述的证明组合起来便得到 `satAt`。这一构造只是合取：每个分量都必须独立给出，表子句不能补偿缺失的塔子句或码域子句。

```agda
  satAt-in : ∀ {m} (T w C E : Fin m) (N : Fin 10 → Fin m) (γ : S ^ m)
           → ⟨ γ ⊨ towerAt E w (N f0) ⟩ → ⟨ γ ⊨ codesAt C w E N ⟩ → ⟨ γ ⊨ tableAt T w C E N ⟩
           → ⟨ γ ⊨ satAt T w C E N ⟩
  satAt-in T w C E N γ hE hC hT = hE , (hC , hT)
```

`SatRead` 是面向可靠性方向的候选对象接口。只有工作集槽已与 `W` 对齐、`Tags` 已校准数码槽且候选对象满足 `satAt` 时，它才适用，并公开上文证得的六条精确向外与向内规则。这些规则保留原有的结论形状：该接口既不把它们改写成笼统的集合等式，也不暴露选定的解码结果或见证。

```agda
module SatRead {m : ℕ} (T w C E : Fin m) (N : Fin 10 → Fin m) (γ : S ^ m) (W : S)
  (qw : fst (lookup w γ) ≡ fst W) (tg : Tags γ N) (h : ⟨ γ ⊨ satAt T w C E N ⟩) where
  private
    module SS = SatSound T w C E N γ W qw tg
      (satAt-out T w C E N γ h .fst) (satAt-out T w C E N γ h .snd .fst) (satAt-out T w C E N γ h .snd .snd)
```

对码而言，两个方向比较其与 `AllCodes W` 的隶属。对塔条目而言，两个方向读取或插入标准有序对 `pr (# k) (envSet W k)`。对表项而言，它们把一个已呈现的有序对与典范码处的函数表取值比较。保持这三类结论的形状彼此有别，可以避免无依据的更强唯一性主张。

```agda
  open SS public using ( C-out; C-in; E-out; E-in; T-out; T-in )
```

反向定理假设四个槽已经呈现预定对象：`W`、它的满足关系图、完整码集与环境塔；同时还假设十个正确的数码标签。这些对齐是完备性的输入数据，并不是从 `satAt` 中恢复出来的。

```agda
sat-complete : ∀ {m} (T w C E : Fin m) (N : Fin 10 → Fin m) (γ : S ^ m) (W : S)
             → fst (lookup w γ) ≡ fst W
             → fst (lookup T γ) ≡ fst (SatGraph.pairs W)
             → fst (lookup C γ) ≡ fst (AllCodes W)
             → fst (lookup E γ) ≡ fst (Tower.tower W)
```

结论是这个已对齐环境对 `satAt` 的满足证明。证明先由 `qw`、`qE`、`qC` 与已校准的标签填入环境塔分量和码域分量；这些对齐在整个论证中始终是前提。此步不会引入新环境塔、码集或图的存在见证，也不主张每个满足 `satAt` 的四元组都唯一地等于典范四元组。

```agda
             → Tags γ N → ⟨ γ ⊨ satAt T w C E N ⟩
sat-complete T w C E N γ W qw qT qC qE tg =
  satAt-in T w C E N γ
    (TowerHolds.holds E w (N f0) γ W qw qE (tg f0))
    (CodesHolds.holds C w E N γ W qw qC qE tg)
```

最后一行重用 `SatHolds.holds` 来填入表这一合取项。如上所证，它建立的是 `tableAt` 的全部内容，即两条定义域条件与十条构造子子句，而不只是后十条子句。`satAt-in` 再把它与环境塔合取项、码域合取项组合起来。因此，`sat-complete` 是把已对齐的典范数据写入有界描述的方向；表证明内部使用的命题截断解码不会对外给出全局解码器或选定取值。

```agda
    (SatHolds.holds T w C E N γ W qw qT qC qE tg)
```
