Skip to content

Commit 79be006

Browse files
committed
proof(db): EchoSelectiveProjection — σ–π commutativity (column-safe); closes #176
Relational-algebra selection/projection commutativity (Codd, subset case) as an Echo-fibre set-equality (affinescript db-theory #4). For a column-safe predicate (p factors through the projection as q), σ_p and π_S commute: ProjectSelect s ⇔ SelectProject s at every projected value. A predicate reading a projected-away column admits no column-restricted lift (no-column-safe-lift) — the non-commuting counterexample. - proofs/agda/EchoSelectiveProjection.agda: local _⇔_ (set-equality level), SelectiveProjection record (column-safe factoring), select-project-commute (K-free via refl-matching the fibre witness), column-safe-example instance, no-column-safe-lift counterexample. - Wired into All.agda; headlines pinned in Smoke.agda. - Classified in echo-kernel-note.adoc + MAP.adoc (kernel-guard Check B). --safe --without-K, zero postulates. All.agda + Smoke.agda exit 0; kernel-guard PASS. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019GiSiEfgZCte35dyykgBHs
1 parent fddb8d0 commit 79be006

5 files changed

Lines changed: 188 additions & 1 deletion

File tree

docs/echo-types/MAP.adoc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,16 @@ honest-bound matched-negative block.
261261
Honest-bound: NOT durability / isolation / commit-semantics (the
262262
dual) / savepoint-locality / runtime-memory-zeroed.
263263
`proofs/agda/EchoTransaction.agda`. `[REAL]`
264+
* *Selective projection (σ–π commutativity, issue #176)* — the Codd law
265+
σ_p(π_S(R)) = π_S(σ_p(R)) for column-safe predicates, as an Echo-fibre
266+
set-equality (`_⇔_` of the two result relations per projected value).
267+
`SelectiveProjection` carries the column-safe factoring `p b ⇔ q
268+
(projection b)`; `select-project-commute` is the commutativity;
269+
`no-column-safe-lift` is the counterexample (a projected-away-column
270+
predicate has no column-restricted lift, so σ/π do not commute).
271+
Honest-bound: `_⇔_` is set-equality (full `_↔_` would need
272+
proof-irrelevant predicates); NOT a runtime query planner.
273+
`proofs/agda/EchoSelectiveProjection.agda`. `[REAL]`
264274
* *Aggregation (general, issue #175)* — aggregation-as-fold over a
265275
`Monoid`, with a `GroupAggregator` and the monoid-homomorphism law
266276
`aggregation-as-fold` (aggregating a concatenation = combining the

docs/echo-types/echo-kernel-note.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ kernel** — the boundary is real and lives outside this core.
125125
*Application/extension modules* (also added via the same sweep):
126126
`EchoEntropy`, `EchoLLEncoding`, `EchoProvenance`, `EchoSecurity`,
127127
`EchoProbabilisticSupport`, `EchoDifferential`, `EchoDeniability`,
128-
`EchoAggregation`, `EchoVariance`, `EchoTransaction`
128+
`EchoAggregation`, `EchoVariance`, `EchoTransaction`,
129+
`EchoSelectiveProjection`
129130
are derived domain applications mapped under their own headings in
130131
MAP.adoc. `EchoDeniability` formalises residue deniability: the
131132
perfect (constant / no-section) case and the partial (injective /

proofs/agda/All.agda

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ open import EchoDifferential -- Perturbation tracking (audience-facing sensi
9797
-- IsConstantOpener boundary tying deniability to the affine mode.
9898
open import EchoDeniability
9999
open import EchoTransaction -- Transaction rollback safety (issue #174; Security instance)
100+
open import EchoSelectiveProjection -- σ–π commutativity (issue #176; relational-algebra carrier)
100101

101102
-- Narrative deliverable: curated index of "why Echo deserves a name".
102103
open import EchoCanonicalIdentitySuite
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
{-# OPTIONS --safe --without-K #-}
2+
-- SPDX-License-Identifier: MPL-2.0
3+
-- SPDX-FileCopyrightText: 2025-2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
4+
5+
-- EchoSelectiveProjection: the relational-algebra selection/projection
6+
-- commutativity (the subset case) as an Echo-fibre statement. Closes
7+
-- echo-types#174's sibling echo-types#176 (consumer: affinescript
8+
-- db-theory #4, `stdlib/Select.affine`).
9+
--
10+
-- The classical law (Codd): for selection σ_p (predicate-driven row
11+
-- filter) and projection π_S (column-subset),
12+
--
13+
-- σ_p(π_S(R)) = π_S(σ_p(R)) when p references only columns in S,
14+
-- σ_p(π_S(R)) ≠ π_S(σ_p(R)) when p references a column NOT in S.
15+
--
16+
-- *Honest level.* "=" between relations is SET equality: same rows.
17+
-- The Echo formalisation states it as a per-projected-value LOGICAL
18+
-- equivalence `_⇔_` of the two result fibres (co-membership), which is
19+
-- exactly set-equality of the result relations. A full `_↔_` (with
20+
-- round-trips) would additionally require the predicate family to be
21+
-- proof-irrelevant (`is-prop`); set-equality does not, and `_⇔_` is the
22+
-- faithful level. See the companion remark.
23+
--
24+
-- *The column-safe condition.* "p references only columns in S" is
25+
-- formalised as: p factors through the projection — there is a
26+
-- predicate `q : S → Set` on the projected columns with `p b ⇔ q
27+
-- (projection b)` for every record `b`. This `factors` field IS the
28+
-- "uses only columns in S" hypothesis.
29+
--
30+
-- *The Echo content.* With `pf = projection ∘ f` (the projected map),
31+
-- `Echo pf s` is π_S(R) at projected value `s` — the rows projecting to
32+
-- `s`. The two composites:
33+
--
34+
-- ProjectSelect s = Σ (Echo pf s) (λ e → p (f (proj₁ e)))
35+
-- -- π_S(σ_p(R)) at s: rows projecting to s that satisfy p
36+
-- SelectProject s = Σ (Echo pf s) (λ _ → q s)
37+
-- -- σ_q(π_S(R)) at s: rows projecting to s, kept iff q holds at s
38+
--
39+
-- `select-project-commute` is `∀ s → ProjectSelect s ⇔ SelectProject s`.
40+
-- The proof is K-free: pattern-matching the fibre witness `pf x ≡ s` as
41+
-- `refl` (s a free variable, so --without-K-safe) collapses the
42+
-- transport, and the predicate move is exactly the `factors` field.
43+
--
44+
-- *The counterexample.* `no-column-safe-lift` shows a predicate that
45+
-- reads a projected-away column (`proj₂`, with projection `= proj₁`)
46+
-- admits NO column-restricted lift `q` at all: the records `(true,true)`
47+
-- and `(true,false)` share projection `true` but disagree on the
48+
-- predicate, so any `q true` would be both inhabited and empty. This is
49+
-- the "≠" direction: σ and π do not commute for such a predicate.
50+
--
51+
-- Headlines (pinned in Smoke.agda):
52+
-- * SelectiveProjection -- the column-safe setup record
53+
-- * select-project-commute -- σ–π commute (column-safe), per s
54+
-- * column-safe-example -- worked column-safe instance
55+
-- * no-column-safe-lift -- counterexample (non-column-safe ⇒ ✗)
56+
57+
module EchoSelectiveProjection where
58+
59+
open import Echo using (Echo)
60+
open import Data.Product.Base using (Σ; _,_; proj₁; proj₂; _×_)
61+
open import Data.Bool.Base using (Bool; true; false)
62+
open import Relation.Binary.PropositionalEquality using (_≡_; refl)
63+
open import Relation.Nullary using (¬_)
64+
65+
----------------------------------------------------------------------
66+
-- Logical equivalence (set-equality level). Kept local and minimal —
67+
-- the σ–π law is co-membership of the two result relations, not a
68+
-- structure-carrying bijection.
69+
----------------------------------------------------------------------
70+
71+
record _⇔_ (P Q : Set) : Set where
72+
constructor equiv
73+
field
74+
to : P Q
75+
from : Q P
76+
77+
----------------------------------------------------------------------
78+
-- The column-safe selection/projection setup.
79+
----------------------------------------------------------------------
80+
81+
record SelectiveProjection {A B : Set} (f : A B) (S : Set) : Set₁ where
82+
field
83+
projection : B S -- π_S
84+
p : B Set -- σ predicate on full records
85+
q : S Set -- its restriction to the projected columns
86+
-- "p uses only columns in S": p factors through projection as q.
87+
factors : b p b ⇔ q (projection b)
88+
89+
-- The projected map; `Echo pf s` = π_S(R) at projected value s.
90+
pf : A S
91+
pf a = projection (f a)
92+
93+
-- π_S(σ_p(R)) at s : rows projecting to s that satisfy p.
94+
ProjectSelect : S Set
95+
ProjectSelect s = Σ (Echo pf s) (λ e p (f (proj₁ e)))
96+
97+
-- σ_q(π_S(R)) at s : rows projecting to s, kept iff q holds at s.
98+
SelectProject : S Set
99+
SelectProject s = Σ (Echo pf s) (λ _ q s)
100+
101+
----------------------------------------------------------------------
102+
-- σ–π commute (column-safe): the two result relations co-inhabit at
103+
-- every projected value. Set-equality of σ_p(π_S(R)) and π_S(σ_p(R)).
104+
----------------------------------------------------------------------
105+
106+
select-project-commute :
107+
{A B : Set} {f : A B} {S : Set} (sp : SelectiveProjection f S) (s : S)
108+
SelectiveProjection.ProjectSelect sp s ⇔ SelectiveProjection.SelectProject sp s
109+
select-project-commute {f = f} sp s = equiv to from
110+
where
111+
open SelectiveProjection sp
112+
to : ProjectSelect s SelectProject s
113+
to ((x , refl) , pe) = (x , refl) , _⇔_.to (factors (f x)) pe
114+
from : SelectProject s ProjectSelect s
115+
from ((x , refl) , qs) = (x , refl) , _⇔_.from (factors (f x)) qs
116+
117+
----------------------------------------------------------------------
118+
-- Worked column-safe instance: 2-column Bool records, project to
119+
-- column 0, predicate "column 0 is true" — uses only the projected
120+
-- column, so it factors (the identity equivalence).
121+
----------------------------------------------------------------------
122+
123+
column-safe-example : SelectiveProjection {Bool × Bool} {Bool × Bool} (λ b b) Bool
124+
column-safe-example = record
125+
{ projection = proj₁
126+
; p = λ b proj₁ b ≡ true
127+
; q = λ s s ≡ true
128+
; factors = λ b equiv (λ z z) (λ z z)
129+
}
130+
131+
----------------------------------------------------------------------
132+
-- Counterexample (the "≠" direction): a predicate reading a
133+
-- projected-away column has NO column-restricted lift. `(true,true)`
134+
-- and `(true,false)` share projection `true` but disagree on
135+
-- `proj₂ · ≡ true`, so any candidate `q true` is both inhabited and
136+
-- empty. Hence σ and π do not commute for such a predicate.
137+
----------------------------------------------------------------------
138+
139+
no-column-safe-lift :
140+
¬ Σ (Bool Set) (λ q b (proj₂ b ≡ true) ⇔ q (proj₁ b))
141+
no-column-safe-lift (q , fac)
142+
with _⇔_.from (fac (true , false)) (_⇔_.to (fac (true , true)) refl)
143+
... | ()
144+
145+
----------------------------------------------------------------------
146+
-- Companion remark.
147+
--
148+
-- `_⇔_` (set-equality of the result relations) is the faithful level:
149+
-- relational-algebra equality is membership equality. Upgrading to a
150+
-- structure-preserving `_↔_` would need the predicate family to be
151+
-- proof-irrelevant (an `is-prop (p b)` field); under `--safe
152+
-- --without-K` that is an extra hypothesis, not free, and it adds no
153+
-- relational-algebra content. NOT claimed: σ–π commutativity for
154+
-- arbitrary (non-column-safe) predicates (refuted by
155+
-- `no-column-safe-lift`); any runtime query-planner behaviour (the
156+
-- decision of whether a predicate is column-safe lives in the
157+
-- consumer). The carrier encodes only the property.
158+
----------------------------------------------------------------------
159+
160+
NotProved-arbitrary-predicate-commute : Set
161+
NotProved-arbitrary-predicate-commute = Bool
162+
163+
NotProved-runtime-query-planner : Set
164+
NotProved-runtime-query-planner = Bool

proofs/agda/Smoke.agda

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,17 @@ open import EchoTransaction using
863863
; rollback-no-recovery
864864
)
865865

866+
-- EchoSelectiveProjection — relational-algebra σ–π commutativity (issue
867+
-- #176). Column-safe selection commutes with projection (set-equality of
868+
-- the result relations); a projected-away-column predicate admits no
869+
-- column-restricted lift (the non-commuting counterexample).
870+
open import EchoSelectiveProjection using
871+
( SelectiveProjection
872+
; select-project-commute
873+
; column-safe-example
874+
; no-column-safe-lift
875+
)
876+
866877
-- EchoProbabilisticSupport — third audience move per GPT order.
867878
-- Abstract `Sampling` record (outcome + index + distinguishability
868879
-- witness) with four parametric headline theorems via `module

0 commit comments

Comments
 (0)