One small theorem, seven formal readings

A reader familiar with ordinary set reasoning

The references below to original run logs and review dispositions describe the research archive. This web edition publishes the checked source files, recorded versions, hashes and portable replay instructions; it does not publish those internal records or claim a fresh native replay.

Principia’s theorem *54.43 provides a compact test of what a formal proof tells a human reader. It says that two singleton sets are disjoint exactly when their union has two elements. A singleton is a set with exactly one member; disjoint sets have no common member. The mathematics fits in a paragraph, yet translating it requires decisions about classes, equality, witnesses and the meaning of “two”. Those decisions remain visible in the six new formalizations examined here. Metamath supplies a seventh, previously published proof with a substantially different route.

The result supports a qualified answer to the question behind the research survey: each proof can be explained in ordinary mathematical language, while a claim that it certifies a particular written argument requires an additional correspondence check. Here that check is small enough to show explicitly.

Why this proposition

Whitehead and Russell place *54.43 on page 379 of the first edition of volume I (1910). Their accompanying sentence identifies it as a precursor to 1+1=2, once addition has been defined. The displayed theorem concerns singleton classes and their union; it contains no addition operation.1

In modern notation, for sets 𝑆 and 𝑇,

(One(𝑆)∧One(𝑇))⟹(𝑆∩𝑇=∅⟺Two(𝑆∪𝑇)).

Here One means “is a singleton” and Two means “has exactly two distinct members”. Principia writes membership in its classes 1 and 2 for these properties. Their eventual interpretation as cardinal numbers belongs to a larger development. For this comparison, keeping the properties explicit avoids importing arithmetic that the proposition does not yet use.

This choice exposes more than a computational proof that two natural-number numerals add to a third. It has hypotheses, a biconditional and an easily missed distinctness condition. Its printed proof also names the intermediate results, giving us something concrete to compare with modern code.

The argument in ordinary mathematics

Let 𝑆={𝑎} and 𝑇={𝑏}. The sets have a common member precisely when 𝑎=𝑏, so they are disjoint precisely when 𝑎≠𝑏. Their union consists of 𝑎 and 𝑏; it has two distinct members precisely when 𝑎≠𝑏. The two conditions are therefore equivalent. Since each singleton has such a representative, the result holds for arbitrary singleton sets 𝑆 and 𝑇.

The converse in the third sentence deserves one extra line. If 𝑎=𝑏, every member of the union equals 𝑎. Any proposed two distinct members would consequently equal one another. This contradiction uses equality and the supplied membership evidence; it does not require deciding equality for every pair of elements.

𝑆∩𝑇=∅⟺𝑎≠𝑏⟺Two(𝑆∪𝑇),
Figure 1: The shared intermediate claim after replacing the two singletons by their representatives.

The published demonstration follows these same local landmarks. The following table records correspondence at the level of named mathematical steps, rather than individual checker instructions.

Principia reference Role in the modern reconstruction
*52.1 Obtain the representative of each singleton.
*54.26 The union of the displayed singletons is Two iff their representatives differ.
*51.231 The displayed singletons are disjoint iff their representatives differ.
*13.12 Substitute equals; our predicate versions instead transport membership implications.
*11.11, *11.35, *11.54 Generalize and eliminate the two witnesses to recover the statement about arbitrary singletons.

This is a local reconstruction with newly proved helpers. Principia’s earlier derivations have their own foundational dependencies, including uses of reducibility on paths feeding this proof. Replacing those derivations with modern equality and quantification changes the foundation even when the local argument remains recognizable.2

Fix the contract before comparing syntax

All six new examples use this contract:

One(𝑆)⟺∃𝑎,𝑆={𝑎},Two(𝑆)⟺∃𝑎,𝑏,𝑎≠𝑏∧𝑆={𝑎,𝑏}.

The carrier is the common domain of elements, such as the integers or the points of a space. Union means ordinary union of memberships in that carrier. Disjointness means absence of a common member. An arbitrary carrier suffices; the theorem assumes neither an infinite universe nor two globally available distinct elements. On a one-element carrier, both sides of its biconditional are false for the two coincident singletons.

For predicate encodings, “𝑆={𝑎}” abbreviates two implications for every 𝑧: membership in 𝑆 implies 𝑧=𝑎, and 𝑧=𝑎 implies membership in 𝑆. We do not ask for equality of predicate functions. That choice avoids an unnecessary function-extensionality dependency.

Lean and Rocq express membership and existence in Prop, their sort for logical propositions. Isabelle uses its native sets, and Mizar uses sets in its set-theoretic library. Agda and Arend use explicit witness-bearing types: existence is a dependent pair, containing an element together with evidence about it. Their “iff” is a pair of functions, one in each direction. Those functions need not satisfy inverse laws. The encoding establishes the stated membership conditions; it does not assert that the witness types themselves have exactly one or two inhabitants. When two singletons coincide, a left membership proof and a right membership proof still refer to the same point 𝑎. Two counts distinct carrier points, so it remains false even with those two receipts of membership. In the later tagged-point control, left a and right a instead become different points in a new carrier. We compare the mathematical claim these presentations express, rather than claiming their proof objects are interchangeable.

What actually checked

System Tested version Check and representation
Lean 4.29.0 Kernel-checked proof; predicates in Prop.
Rocq 9.3.0 Compiled proof and separate compiled-library check; predicates in Prop.
Isabelle/HOL 2025-2 Session build; native sets.
Mizar 8.1.15; MML 5.94.1493 Article verification; native sets.
Agda 2.8.0.2 Safe-mode type checking; explicit witnesses.
Arend 1.10 Fresh type checking with output checks for errors and goals; explicit witnesses.
Metamath 0.200.pre; pinned database All 2,032 proofs in the extracted dependency closure verified.

The version column records the runtimes actually exercised, rather than a claim that each is the latest release. Lean and Rocq reused existing toolchains. The other tools ran from task-local downloads; no system installation was needed. Checking receipts, compiler output and source hashes are available in the accompanying file guide. This is one deliberately small example per system, with no comparative timing or productivity measurement.

The Lean dependency query reports no axiom dependencies. Rocq reports no postulated axioms, while its expanded receipt also exposes the prelude equality declaration’s “indices not mattering” theory setting. The predicate proofs avoid excluded middle, choice and predicate extensionality. These observations describe the proofs under their respective kernels and built-in theories; they do not show that the kernels have no trusted rules. The Isabelle and Mizar versions work within their usual classical environments. Agda’s safe mode excludes postulates and unchecked termination for this file; Arend’s example has complete bodies and declares no new axioms or extensions.34

Read the six new proofs

Each excerpt shows the decisive local steps; declarations and helper proofs remain in the expandable source panels. The annotations identify the same landmarks: obtain representatives, connect both conditions through distinctness, and compose the result. Isabelle’s encoded symbols appear as the glyphs its editor displays.

Lean: compose the two equivalences

Lean’s final proof obtains 𝑎 and 𝑏, transports the disjointness and union conditions, and composes both helper equivalences through 𝑎≠𝑏. The named intermediate facts make the paragraph above easy to recover from the code. Only the core prelude is needed. This example therefore demonstrates the language’s proof machinery without relying on Mathlib’s larger cardinality API.

  obtain ⟨a, hSa⟩ := hS
  obtain ⟨b, hTb⟩ := hT
  have hd : Disjoint S T ↔ a ≠ b :=
    (disjoint_congr hSa hTb).trans (singleton_disjoint_iff_distinct a b)
  have ht : Two (Union S T) ↔ a ≠ b :=
    (two_congr (union_congr hSa hTb)).trans
      (singleton_union_two_iff_distinct a b)
  exact hd.trans ht.symm

obtain names each representative and its membership evidence. The facts hd and ht express the two conditions through distinctness; trans joins them after symm reverses the second equivalence.

Lean source: definitions, helpers and endpoint

Open the proof source

-- Modern local reconstruction of the semantic content of PM *54.43.
-- This is not a formalization of PM's ramified type theory or class machinery.
-- Only Lean's implicit Init import; no Mathlib, Classical, choice, or new axioms.
namespace Principia
universe u
variable {X : Type u}

def EqualSets (S T : X → Prop) : Prop := ∀ z, S z ↔ T z
def Singleton (a : X) : X → Prop := fun z => z = a
def One (S : X → Prop) : Prop := ∃ a, EqualSets S (Singleton a)
def Two (S : X → Prop) : Prop :=
  ∃ a b, a ≠ b ∧ ∀ z, S z ↔ (z = a ∨ z = b)
def Union (S T : X → Prop) : X → Prop := fun z => S z ∨ T z
def Disjoint (S T : X → Prop) : Prop := ∀ z, S z → T z → False

-- Semantic analogue of *51.231: singletons are disjoint iff witnesses differ.
theorem singleton_disjoint_iff_distinct (a b : X) :
    Disjoint (Singleton a) (Singleton b) ↔ a ≠ b := by
  constructor
  · intro h hab
    exact h a rfl hab
  · intro hab z hza hzb
    exact hab (hza.symm.trans hzb)

-- Semantic analogue of *54.26: the singleton union has exactly two members
-- iff its displayed witnesses are distinct.
theorem singleton_union_two_iff_distinct (a b : X) :
    Two (Union (Singleton a) (Singleton b)) ↔ a ≠ b := by
  constructor
  · intro h hab
    obtain ⟨c, d, hcd, hmembers⟩ := h
    have hc : c = a := by
      have hc_union := (hmembers c).mpr (Or.inl rfl)
      cases hc_union with
      | inl hca => exact hca
      | inr hcb => exact hcb.trans hab.symm
    have hd : d = a := by
      have hd_union := (hmembers d).mpr (Or.inr rfl)
      cases hd_union with
      | inl hda => exact hda
      | inr hdb => exact hdb.trans hab.symm
    exact hcd (hc.trans hd.symm)
  · intro hab
    exact ⟨a, b, hab, fun _ => Iff.rfl⟩

-- Pointwise equivalence transports disjointness without predicate equality.
theorem disjoint_congr {S T A B : X → Prop}
    (hS : EqualSets S A) (hT : EqualSets T B) :
    Disjoint S T ↔ Disjoint A B := by
  constructor
  · intro h z hA hB
    exact h z ((hS z).mpr hA) ((hT z).mpr hB)
  · intro h z hS' hT'
    exact h z ((hS z).mp hS') ((hT z).mp hT')

theorem union_congr {S T A B : X → Prop}
    (hS : EqualSets S A) (hT : EqualSets T B) :
    EqualSets (Union S T) (Union A B) := by
  intro z
  constructor
  · intro h
    cases h with
    | inl hs => exact Or.inl ((hS z).mp hs)
    | inr ht => exact Or.inr ((hT z).mp ht)
  · intro h
    cases h with
    | inl ha => exact Or.inl ((hS z).mpr ha)
    | inr hb => exact Or.inr ((hT z).mpr hb)

theorem two_congr {S T : X → Prop} (hST : EqualSets S T) :
    Two S ↔ Two T := by
  constructor
  · intro h
    obtain ⟨a, b, hab, hm⟩ := h
    exact ⟨a, b, hab, fun z => (hST z).symm.trans (hm z)⟩
  · intro h
    obtain ⟨a, b, hab, hm⟩ := h
    exact ⟨a, b, hab, fun z => (hST z).trans (hm z)⟩

-- Both input existentials are eliminated locally; no witness choice function.
theorem pm_54_43 (S T : X → Prop) :
    One S → One T → (Disjoint S T ↔ Two (Union S T)) := by
  intro hS hT
  obtain ⟨a, hSa⟩ := hS
  obtain ⟨b, hTb⟩ := hT
  have hd : Disjoint S T ↔ a ≠ b :=
    (disjoint_congr hSa hTb).trans (singleton_disjoint_iff_distinct a b)
  have ht : Two (Union S T) ↔ a ≠ b :=
    (two_congr (union_congr hSa hTb)).trans
      (singleton_union_two_iff_distinct a b)
  exact hd.trans ht.symm

-- Checked negative control: dropping disjointness/distinctness is false,
-- already for one chosen element of any inhabited carrier.
theorem equal_singletons_not_two (a : X) :
    ¬ Two (Union (Singleton a) (Singleton a)) := by
  intro h
  exact ((singleton_union_two_iff_distinct a a).mp h) rfl

#print axioms singleton_disjoint_iff_distinct
#print axioms singleton_union_two_iff_distinct
#print axioms disjoint_congr
#print axioms union_congr
#print axioms two_congr
#print axioms pm_54_43
#print axioms equal_singletons_not_two
end Principia

Rocq: the same logical decomposition

Rocq uses the same predicate contract and witness elimination, with explicit proof steps for equality and membership cases. Existential elimination stays within Prop. The additional compiled-library check verifies the saved proof artifact using Rocq’s checking command; it supplies a second checking pass within the Rocq toolchain, not an unrelated implementation of its logic.

  intros [a hSa] [b hTb].
  pose proof (disjoint_congr hSa hTb) as hd.
  pose proof (two_congr (union_congr hSa hTb)) as ht.
  split.
  - intro h. apply (proj2 ht).
    apply (proj2 (singleton_union_two_iff_distinct a b)).
    apply (proj1 (singleton_disjoint_iff_distinct a b)).
    exact (proj1 hd h).
  - intro h. apply (proj2 hd).
    apply (proj2 (singleton_disjoint_iff_distinct a b)).
    apply (proj1 (singleton_union_two_iff_distinct a b)).
    exact (proj1 ht h).

intros extracts the representatives; hd and ht record the transported conditions. split starts the two directions. The projections proj1 and proj2 select directions of a proved biconditional.

Rocq source: definitions, helpers and endpoint

Open the proof source

(* Modern local reconstruction of the semantic content of PM *54.43.
   This does not formalize PM's ramified type theory or class machinery.
   Only the default Rocq prelude; no imports, Classical, choice, or axioms. *)
Set Implicit Arguments.
Section PrincipiaProof.
Context {X : Type}.

Definition EqualSets (S T : X -> Prop) : Prop := forall z, S z <-> T z.
Definition Singleton (a : X) : X -> Prop := fun z => z = a.
Definition One (S : X -> Prop) : Prop := exists a, EqualSets S (Singleton a).
Definition Two (S : X -> Prop) : Prop :=
  exists a b, a <> b /\ forall z, S z <-> (z = a \/ z = b).
Definition Union (S T : X -> Prop) : X -> Prop := fun z => S z \/ T z.
Definition Disjoint (S T : X -> Prop) : Prop :=
  forall z, S z -> T z -> False.

(* Semantic analogue of *51.231. *)
Theorem singleton_disjoint_iff_distinct (a b : X) :
  Disjoint (Singleton a) (Singleton b) <-> a <> b.
Proof.
  split.
  - intros h hab. exact (h a eq_refl hab).
  - intros hab z hza hzb. apply hab.
    exact (eq_trans (eq_sym hza) hzb).
Qed.

(* Semantic analogue of *54.26. *)
Theorem singleton_union_two_iff_distinct (a b : X) :
  Two (Union (Singleton a) (Singleton b)) <-> a <> b.
Proof.
  split.
  - intros [c [d [hcd hm]]] hab.
    assert (hc : c = a).
    { destruct (proj2 (hm c) (or_introl eq_refl)) as [hca | hcb].
      - exact hca.
      - exact (eq_trans hcb (eq_sym hab)). }
    assert (hd : d = a).
    { destruct (proj2 (hm d) (or_intror eq_refl)) as [hda | hdb].
      - exact hda.
      - exact (eq_trans hdb (eq_sym hab)). }
    exact (hcd (eq_trans hc (eq_sym hd))).
  - intro hab. exists a, b. split.
    + exact hab.
    + intro z. unfold Union, Singleton. split; intro h; exact h.
Qed.

Theorem disjoint_congr (S T A B : X -> Prop)
  (hS : EqualSets S A) (hT : EqualSets T B) :
  Disjoint S T <-> Disjoint A B.
Proof.
  split.
  - intros h z hA hB.
    exact (h z (proj2 (hS z) hA) (proj2 (hT z) hB)).
  - intros h z hS' hT'.
    exact (h z (proj1 (hS z) hS') (proj1 (hT z) hT')).
Qed.

Theorem union_congr (S T A B : X -> Prop)
  (hS : EqualSets S A) (hT : EqualSets T B) :
  EqualSets (Union S T) (Union A B).
Proof.
  intro z. split.
  - intros [h | h].
    + left. exact (proj1 (hS z) h).
    + right. exact (proj1 (hT z) h).
  - intros [h | h].
    + left. exact (proj2 (hS z) h).
    + right. exact (proj2 (hT z) h).
Qed.

Theorem two_congr (S T : X -> Prop) (hST : EqualSets S T) :
  Two S <-> Two T.
Proof.
  split.
  - intros [a [b [hab hm]]]. exists a, b. split.
    + exact hab.
    + intro z. split.
      * intro ht. exact (proj1 (hm z) (proj2 (hST z) ht)).
      * intro hz. exact (proj1 (hST z) (proj2 (hm z) hz)).
  - intros [a [b [hab hm]]]. exists a, b. split.
    + exact hab.
    + intro z. split.
      * intro hs. exact (proj1 (hm z) (proj1 (hST z) hs)).
      * intro hz. exact (proj2 (hST z) (proj2 (hm z) hz)).
Qed.

(* Eliminate the given singleton witnesses within Prop. *)
Theorem pm_54_43 (S T : X -> Prop) :
  One S -> One T -> (Disjoint S T <-> Two (Union S T)).
Proof.
  intros [a hSa] [b hTb].
  pose proof (disjoint_congr hSa hTb) as hd.
  pose proof (two_congr (union_congr hSa hTb)) as ht.
  split.
  - intro h. apply (proj2 ht).
    apply (proj2 (singleton_union_two_iff_distinct a b)).
    apply (proj1 (singleton_disjoint_iff_distinct a b)).
    exact (proj1 hd h).
  - intro h. apply (proj2 hd).
    apply (proj2 (singleton_disjoint_iff_distinct a b)).
    apply (proj1 (singleton_union_two_iff_distinct a b)).
    exact (proj1 ht h).
Qed.

(* Checked negative control: coincident singletons cannot have two members. *)
Theorem equal_singletons_not_two (a : X) :
  ~ Two (Union (Singleton a) (Singleton a)).
Proof.
  intro h.
  exact (proj1 (singleton_union_two_iff_distinct a a) h eq_refl).
Qed.
End PrincipiaProof.

Set Printing All Assumptions.
Print Typing Flags.
Print Assumptions singleton_disjoint_iff_distinct.
Print Assumptions singleton_union_two_iff_distinct.
Print Assumptions disjoint_congr.
Print Assumptions union_congr.
Print Assumptions two_congr.
Print Assumptions pm_54_43.
Print Assumptions equal_singletons_not_two.

Isabelle: named facts about ordinary sets

The Isabelle/HOL version keeps familiar singleton, union and intersection notation. Its Isar proof extracts representatives and assembles named helper facts. Automation proves some local set and equality obligations. The visible script thus preserves the mathematical landmarks while delegating smaller deductions to Isabelle’s checked proof machinery. The amount of automation used here is an authoring choice, not a mandatory feature of Isar.

  from assms(1) obtain a where s: "S = {a}"
    unfolding One_def by blast
  from assms(2) obtain b where t: "T = {b}"
    unfolding One_def by blast
  have "Disjoint S T ⟷ a ≠ b"
    using PM51_231[of a b] s t by simp
  also have "... ⟷ Two (S ∪ T)"
    using PM54_26[of a b] s t by simp
  finally show ?thesis .

obtain extracts representatives. have and also have build the chain through distinctness; finally returns its combined conclusion.

Isabelle source: definitions, helpers and endpoint

Open the proof source

theory Principia
  imports Main
begin

text \<open>Local semantic reconstruction of PM *54.43, not its ramified type theory.\<close>

definition One :: "'a set \<Rightarrow> bool" where
  "One S \<longleftrightarrow> (\<exists>a. S = {a})"
definition Two :: "'a set \<Rightarrow> bool" where
  "Two S \<longleftrightarrow> (\<exists>a b. a \<noteq> b \<and> S = {a,b})"
definition Disjoint :: "'a set \<Rightarrow> 'a set \<Rightarrow> bool" where
  "Disjoint S T \<longleftrightarrow> S \<inter> T = {}"

lemma PM51_231:
  "Disjoint {a} {b} \<longleftrightarrow> a \<noteq> b"
  unfolding Disjoint_def by auto

lemma PM54_26:
  "Two ({a} \<union> {b}) \<longleftrightarrow> a \<noteq> b"
proof
  assume two: "Two ({a} \<union> {b})"
  then obtain c d where distinct: "c \<noteq> d"
    and pair: "{a} \<union> {b} = {c,d}"
    unfolding Two_def by blast
  show "a \<noteq> b"
  proof
    assume "a = b"
    with pair have "c = a" and "d = a" by auto
    with distinct show False by simp
  qed
next
  assume "a \<noteq> b"
  moreover have "{a} \<union> {b} = {a,b}" by auto
  ultimately show "Two ({a} \<union> {b})"
    unfolding Two_def by blast
qed

theorem PM54_43:
  assumes "One S" and "One T"
  shows "Disjoint S T \<longleftrightarrow> Two (S \<union> T)"
proof -
  from assms(1) obtain a where s: "S = {a}"
    unfolding One_def by blast
  from assms(2) obtain b where t: "T = {b}"
    unfolding One_def by blast
  have "Disjoint S T \<longleftrightarrow> a \<noteq> b"
    using PM51_231[of a b] s t by simp
  also have "... \<longleftrightarrow> Two (S \<union> T)"
    using PM54_26[of a b] s t by simp
  finally show ?thesis .
qed

text \<open>Checked negative control: without distinctness, a repeated singleton
satisfies the weakened Two predicate while disjointness fails.\<close>
definition TwoWeak :: "'a set \<Rightarrow> bool" where
  "TwoWeak S \<longleftrightarrow> (\<exists>a b. S = {a,b})"
lemma distinctness_counterexample:
  "One ({()} :: unit set) \<and> TwoWeak ({()} \<union> {()})
   \<and> \<not> Disjoint {()} {()} \<and> \<not> Two ({()} \<union> {()})"
  unfolding One_def TwoWeak_def Two_def Disjoint_def by auto

end

Mizar: a set-theoretic article

Mizar expresses One and Two as predicates on sets, then supplies a structured article with named facts about singletons and unordered pairs. Its extensional set representation fits the printed theorem closely. The article still depends on modern MML definitions and lemmas, rather than Principia’s hierarchy of class expressions. Its prose-like surface helps expose which conclusions depend on which assumptions.

 consider a being object such that A2: S = {a} by A1;
 consider b being object such that A3: T = {b} by A1;
 Disjoint[S,T] iff a <> b by A2,A3,PM51231;
 hence thesis by A2,A3,PM5426;

consider selects representatives already guaranteed by the hypotheses. The by clauses cite the evidence, and hence thesis joins the two helper facts to conclude the announced proposition.

Mizar source: definitions, helpers and endpoint

Open the proof source

:: Local semantic reconstruction of PM *54.43 (1910, p. 379).
:: This article uses ordinary Mizar sets, not PM's ramified type theory.
environ
 vocabularies TARSKI, XBOOLE_0;
 notations TARSKI, XBOOLE_0;
 constructors TARSKI, XBOOLE_0;
 registrations XBOOLE_0;
 requirements BOOLE;
 theorems TARSKI, XBOOLE_0;
 definitions TARSKI, XBOOLE_0;

begin

defpred One[set] means ex a being object st $1 = {a};
defpred Two[set] means
  ex a,b being object st a <> b & $1 = {a,b};
defpred Disjoint[set,set] means $1 /\ $2 = {};

PM51231: for a,b being object holds Disjoint[{a},{b}] iff a <> b
proof
 let a,b be object;
 thus Disjoint[{a},{b}] implies a <> b
 proof
  assume A1: {a} /\ {b} = {};
  assume a = b;
  then a in {a} & a in {b} by TARSKI:def 1;
  then a in {} by A1,XBOOLE_0:def 4;
  hence contradiction;
 end;
 assume A2: a <> b;
 for x being object holds not x in {a} /\ {b}
 proof
  let x be object;
  assume x in {a} /\ {b};
  then x in {a} & x in {b} by XBOOLE_0:def 4;
  then x = a & x = b by TARSKI:def 1;
  hence contradiction by A2;
 end;
 hence Disjoint[{a},{b}] by XBOOLE_0:def 1;
end;

SingletonUnion: for a,b being object holds {a} \/ {b} = {a,b}
proof
 let a,b be object;
 now
  let x be object;
  x in {a} \/ {b} iff x in {a} or x in {b} by XBOOLE_0:def 3;
  then x in {a} \/ {b} iff x = a or x = b by TARSKI:def 1;
  hence x in {a} \/ {b} iff x in {a,b} by TARSKI:def 2;
 end;
 hence thesis by TARSKI:2;
end;

PM5426: for a,b being object holds Two[{a} \/ {b}] iff a <> b
proof
 let a,b be object;
 thus Two[{a} \/ {b}] implies a <> b
 proof
  given c,d being object such that
  A1: c <> d and A2: {a} \/ {b} = {c,d};
  assume A3: a = b;
  c in {c,d} & d in {c,d} by TARSKI:def 2;
  then c in {a} & d in {a} by A2,A3;
  then c = a & d = a by TARSKI:def 1;
  hence contradiction by A1;
 end;
 assume A4: a <> b;
 {a} \/ {b} = {a,b} by SingletonUnion;
 hence Two[{a} \/ {b}] by A4;
end;

PM5443: for S,T being set st One[S] & One[T]
 holds Disjoint[S,T] iff Two[S \/ T]
proof
 let S,T be set;
 assume A1: One[S] & One[T];
 consider a being object such that A2: S = {a} by A1;
 consider b being object such that A3: T = {b} by A1;
 Disjoint[S,T] iff a <> b by A2,A3,PM51231;
 hence thesis by A2,A3,PM5426;
end;

:: Checked counterexample after removing distinctness from Two.
defpred TwoWeak[set] means ex a,b being object st $1 = {a,b};

DistinctnessCounterexample:
 One[{{}}] & TwoWeak[{{}} \/ {{}}] &
 not Disjoint[{{}},{{}}] & not Two[{{}} \/ {{}}]
proof
 thus One[{{}}];
 {{}} \/ {{}} = {{},{}} by SingletonUnion;
 hence TwoWeak[{{}} \/ {{}}];
 thus not Disjoint[{{}},{{}}] by PM51231;
 thus not Two[{{}} \/ {{}}] by PM5426;
end;

Agda: return evidence in both directions

Agda’s forward function uses disjointness evidence to produce distinct representatives and membership maps for the union. Its backward function turns any supplied Two witness into a disjointness function. Dependent pairs retain the representatives in the returned evidence. The proof implements the same reasoning as functions, without using cubical features or univalence. Calling the two functions an “iff” records their logical role; it does not identify the types by a bijection of proofs.

  pm54-43 : {S T : Subset} → One S → One T → Disjoint S T ↔ Two (Union S T)
  pm54-43 {S} {T} (a , e) (b , f) = forward , backward
    where
    forward : Disjoint S T → Two (Union S T)
    forward d = two_map (same_sym (union_map e f))
      (snd (singleton_union_two_iff_distinct a b)
        (fst (singleton_disjoint_iff_distinct a b) (disjoint_map e f d)))
    backward : Two (Union S T) → Disjoint S T
    backward t = disjoint_map (same_sym e) (same_sym f)
      (snd (singleton_disjoint_iff_distinct a b)
        (fst (singleton_union_two_iff_distinct a b) (two_map (union_map e f) t)))

The patterns (a , e) and (b , f) extract representatives and membership maps. The returned pair contains forward and backward; fst and snd choose directions from the helper pairs.

Agda source: definitions, helpers and endpoint

Open the proof source

{-# OPTIONS --safe --without-K #-}
module Principia where

open import Agda.Builtin.Equality
open import Agda.Builtin.Sigma

data Empty : Set where

data _+_ (A B : Set) : Set where
  left : A → A + B
  right : B → A + B

infixr 2 _+_

_×_ : Set → Set → Set
A × B = Σ A (λ _ → B)

_↔_ : Set → Set → Set
A ↔ B = (A → B) × (B → A)

sym : {A : Set} {a b : A} → a ≡ b → b ≡ a
sym refl = refl

trans : {A : Set} {a b c : A} → a ≡ b → b ≡ c → a ≡ c
trans refl q = q

module Contract (X : Set) where
  Subset = X → Set
  Singleton : X → Subset
  Singleton a z = z ≡ a

  Same : Subset → Subset → Set
  Same S T = (z : X) → (S z → T z) × (T z → S z)

  One : Subset → Set
  One S = Σ X (λ a → Same S (Singleton a))

  Union : Subset → Subset → Subset
  Union S T z = S z + T z

  Disjoint : Subset → Subset → Set
  Disjoint S T = (z : X) → S z → T z → Empty

  Distinct : X → X → Set
  Distinct a b = a ≡ b → Empty

  Two : Subset → Set
  Two S = Σ X (λ a → Σ X (λ b → Distinct a b × Same S (Union (Singleton a) (Singleton b))))

  same_refl : (S : Subset) → Same S S
  same_refl S z = (λ x → x) , (λ x → x)

  same_sym : {S T : Subset} → Same S T → Same T S
  same_sym e z = snd (e z) , fst (e z)

  same_trans : {S T U : Subset} → Same S T → Same T U → Same S U
  same_trans e f z = (λ s → fst (f z) (fst (e z) s)) , (λ u → snd (e z) (snd (f z) u))

  union_map : {S T U V : Subset} → Same S U → Same T V → Same (Union S T) (Union U V)
  union_map {S} {T} {U} {V} e f z = forward , backward
    where
    forward : S z + T z → U z + V z
    forward (left s) = left (fst (e z) s)
    forward (right t) = right (fst (f z) t)
    backward : U z + V z → S z + T z
    backward (left u) = left (snd (e z) u)
    backward (right v) = right (snd (f z) v)

  two_map : {S T : Subset} → Same S T → Two S → Two T
  two_map e (a , (b , (d , f))) = a , (b , (d , same_trans (same_sym e) f))

  disjoint_map : {S T U V : Subset} → Same S U → Same T V → Disjoint S T → Disjoint U V
  disjoint_map e f d z u v = d z (snd (e z) u) (snd (f z) v)

  singleton_disjoint_iff_distinct : (a b : X) → Disjoint (Singleton a) (Singleton b) ↔ Distinct a b
  singleton_disjoint_iff_distinct a b = (λ d p → d a refl p) , (λ d z p q → d (trans (sym p) q))

  collapse : {a b z : X} → a ≡ b → (z ≡ a) + (z ≡ b) → z ≡ a
  collapse p (left q) = q
  collapse p (right q) = trans q (sym p)

  union_two_implies_distinct : {a b : X} → Two (Union (Singleton a) (Singleton b)) → Distinct a b
  union_two_implies_distinct (c , (d , (neq , e))) p = neq (trans ca (sym da))
    where
    ca = collapse p (snd (e c) (left refl))
    da = collapse p (snd (e d) (right refl))

  singleton_union_two_iff_distinct : (a b : X) → Two (Union (Singleton a) (Singleton b)) ↔ Distinct a b
  singleton_union_two_iff_distinct a b = union_two_implies_distinct , (λ d → a , (b , (d , same_refl _)))

  pm54-43 : {S T : Subset} → One S → One T → Disjoint S T ↔ Two (Union S T)
  pm54-43 {S} {T} (a , e) (b , f) = forward , backward
    where
    forward : Disjoint S T → Two (Union S T)
    forward d = two_map (same_sym (union_map e f))
      (snd (singleton_union_two_iff_distinct a b)
        (fst (singleton_disjoint_iff_distinct a b) (disjoint_map e f d)))
    backward : Two (Union S T) → Disjoint S T
    backward t = disjoint_map (same_sym e) (same_sym f)
      (snd (singleton_disjoint_iff_distinct a b)
        (fst (singleton_union_two_iff_distinct a b) (two_map (union_map e f) t)))

  -- The tagged carrier retains the side even when the original points coincide.
  Tagged : Set
  Tagged = X + X
  tagged_left_ne_right : (a b : X) → left a ≡ right b → Empty
  tagged_left_ne_right a b ()



module NegativeControl (X : Set) where
  module C = Contract X
  module T = Contract C.Tagged
  tagged_coproduct_two : (a b : X) → T.Two (T.Union (T.Singleton (left a)) (T.Singleton (right b)))
  tagged_coproduct_two a b = left a , (right b , (C.tagged_left_ne_right a b , T.same_refl _))
  equal_points_still_two : (a : X) → T.Two (T.Union (T.Singleton (left a)) (T.Singleton (right a)))
  equal_points_still_two a = tagged_coproduct_two a a

module EvidenceRelevant (X : Set) where
  open Contract X
  ordinary_equal_not_two : (a : X) → Two (Union (Singleton a) (Singleton a)) → Empty
  ordinary_equal_not_two a t = union_two_implies_distinct t refl

  -- A coincident ordinary union still has two different membership witnesses.
  coincident_membership_tags_distinct : (a : X) →
    left {a ≡ a} {a ≡ a} refl ≡ right refl → Empty
  coincident_membership_tags_distinct a ()

Arend: explicit equality transport

Arend gives a similar pair of functions, using paths for equality and transport to move evidence along those paths. The carrier can be an arbitrary type in the universe used by the file; a set-level restriction is unnecessary for this chosen contract. The membership maps compare inhabitation conditions, even when equality itself carries higher structure. This makes the representation caveat material: Two describes distinct points covering membership, rather than a homotopy equivalence of the whole evidence type with a two-element type.

\func pm54_43 {X : \Type0} {S T : X -> \Type0} (s : One S) (t : One T) : Iff (Disjoint S T) (Two (Union S T))
  => (\lam d => two_map (same_sym (union_map s.2 t.2))
        ((singleton_union_two_iff_distinct s.1 t.1).2
          ((singleton_disjoint_iff_distinct s.1 t.1).1 (disjoint_map s.2 t.2 d))),
      \lam v => disjoint_map (same_sym s.2) (same_sym t.2)
        ((singleton_disjoint_iff_distinct s.1 t.1).2
          ((singleton_union_two_iff_distinct s.1 t.1).1 (two_map (union_map s.2 t.2) v))))

s.1 and t.1 are the representatives, while s.2 and t.2 supply membership maps. Each \lam introduces an input to one direction; the surrounding pair returns both directions.

Arend source: definitions, helpers and endpoint

Open the proof source

-- Explicit witnesses; Same and Iff contain maps, not homotopy inverse laws.
\data Empty
\data Sum (A B : \Type0)
  | inl A
  | inr B
\open Sum

\func Product (A B : \Type0) => \Sigma A B
\func Iff (A B : \Type0) => Product (A -> B) (B -> A)

\func transport {A : \Type0} (B : A -> \Type0) {a b : A} (p : a = b) (v : B a) : B b \elim p
  | idp => v
\func sym {A : \Type0} {a b : A} (p : a = b) : b = a
  => transport (\lam z => z = a) p idp
\func trans {A : \Type0} {a b c : A} (p : a = b) (q : b = c) : a = c
  => transport (\lam z => a = z) q p

\func Singleton {X : \Type0} (a z : X) => z = a
\func Same {X : \Type0} (S T : X -> \Type0) => \Pi (z : X) -> Product (S z -> T z) (T z -> S z)
\func One {X : \Type0} (S : X -> \Type0) => \Sigma (a : X) (Same S (Singleton a))
\func Union {X : \Type0} (S T : X -> \Type0) (z : X) => Sum (S z) (T z)
\func Disjoint {X : \Type0} (S T : X -> \Type0) => \Pi (z : X) -> S z -> T z -> Empty
\func Distinct {X : \Type0} (a b : X) => a = b -> Empty
\func Two {X : \Type0} (S : X -> \Type0) => \Sigma (a b : X) (Product (Distinct a b) (Same S (Union (Singleton a) (Singleton b))))

\func same_refl {X : \Type0} (S : X -> \Type0) : Same S S
  => \lam z => (\lam s => s, \lam s => s)
\func same_sym {X : \Type0} {S T : X -> \Type0} (e : Same S T) : Same T S
  => \lam z => ((e z).2, (e z).1)
\func same_trans {X : \Type0} {S T U : X -> \Type0} (e : Same S T) (f : Same T U) : Same S U
  => \lam z => (\lam s => (f z).1 ((e z).1 s), \lam u => (e z).2 ((f z).2 u))
\func sum_map {A B C D : \Type0} (f : A -> C) (g : B -> D) (v : Sum A B) : Sum C D \elim v
  | inl a => inl (f a)
  | inr b => inr (g b)
\func union_map {X : \Type0} {S T U V : X -> \Type0} (e : Same S U) (f : Same T V) : Same (Union S T) (Union U V)
  => \lam z => (sum_map ((e z).1) ((f z).1), sum_map ((e z).2) ((f z).2))
\func two_map {X : \Type0} {S T : X -> \Type0} (e : Same S T) (v : Two S) : Two T
  => (v.1, v.2, (v.3.1, same_trans (same_sym e) v.3.2))
\func disjoint_map {X : \Type0} {S T U V : X -> \Type0} (e : Same S U) (f : Same T V) (d : Disjoint S T) : Disjoint U V
  => \lam z u v => d z ((e z).2 u) ((f z).2 v)

-- PM *51.231 local analogue.
\func singleton_disjoint_iff_distinct {X : \Type0} (a b : X) : Iff (Disjoint (Singleton a) (Singleton b)) (Distinct a b)
  => (\lam d p => d a idp p, \lam d z p q => d (trans (sym p) q))
\func collapse {X : \Type0} {a b z : X} (p : a = b) (v : Sum (z = a) (z = b)) : z = a \elim v
  | inl q => q
  | inr q => trans q (sym p)
\func union_two_implies_distinct {X : \Type0} {a b : X} (v : Two (Union (Singleton a) (Singleton b))) : Distinct a b
  => \lam p => v.3.1 (trans (collapse p ((v.3.2 v.1).2 (inl idp))) (sym (collapse p ((v.3.2 v.2).2 (inr idp)))))
-- PM *54.26 local analogue.
\func singleton_union_two_iff_distinct {X : \Type0} (a b : X) : Iff (Two (Union (Singleton a) (Singleton b))) (Distinct a b)
  => (union_two_implies_distinct, \lam d => (a, b, (d, same_refl (Union (Singleton a) (Singleton b)))))

-- PM *54.43 semantic endpoint, abstract carrier; no set constraint.
\func pm54_43 {X : \Type0} {S T : X -> \Type0} (s : One S) (t : One T) : Iff (Disjoint S T) (Two (Union S T))
  => (\lam d => two_map (same_sym (union_map s.2 t.2))
        ((singleton_union_two_iff_distinct s.1 t.1).2
          ((singleton_disjoint_iff_distinct s.1 t.1).1 (disjoint_map s.2 t.2 d))),
      \lam v => disjoint_map (same_sym s.2) (same_sym t.2)
        ((singleton_disjoint_iff_distinct s.1 t.1).2
          ((singleton_union_two_iff_distinct s.1 t.1).1 (two_map (union_map s.2 t.2) v))))

-- Tags separate elements even when the underlying point is identical.
\func tagged_left_ne_right {X : \Type0} (a b : X) (p : inl {X} {X} a = inr b) : Empty \elim p
  | ()
\func tagged_coproduct_two {X : \Type0} (a b : X) : Two (Union (Singleton (inl {X} {X} a)) (Singleton (inr b)))
  => (inl a, inr b, (tagged_left_ne_right a b, same_refl (Union (Singleton (inl a)) (Singleton (inr b)))))
\func equal_points_still_two {X : \Type0} (a : X) : Two (Union (Singleton (inl {X} {X} a)) (Singleton (inr a)))
  => tagged_coproduct_two a a

\func ordinary_equal_not_two {X : \Type0} (a : X) (v : Two (Union (Singleton a) (Singleton a))) : Empty
  => union_two_implies_distinct v idp
\func coincident_membership_tags_distinct {X : \Type0} (a : X)
  (p : inl {a = a} {a = a} idp = inr idp) : Empty \elim p
  | ()

Metamath supplies a different proof of the endpoint

Metamath’s existing pm54.43, contributed by Norman Megill in 2007, expresses singletonhood by equinumerosity with a one-element ordinal and the conclusion by equinumerosity with a two-element ordinal. Its published description explicitly acknowledges that several Principia lemmas are unavailable in that library.5

The forward direction combines bijections between disjoint sets and suitable ordinal representatives. The reverse direction argues that coincident representatives collapse the union to a singleton, which cannot be equinumerous with two. This validates a modern interpretation of the endpoint through a different route. It does not preserve the same helper-by-helper reconstruction used by our six examples.

I extracted the target’s transitive dependency closure from a pinned set.mm revision and verified every proof in it with a pinned Metamath executable built locally. The closure contains 2,032 proved statements, including the target, plus its syntax, definitions and axioms. This larger dependency count reflects that proof and its library route; it does not measure the theorem’s inherent difficulty. The compressed self-contained database and receipt permit inspection and replay.6

Two controls reveal what checking alone misses

Remove distinctness. If 𝑆=𝑇={𝑎}, their ordinary union has one member. Each new example checks that a coincident singleton union fails the proper Two condition. Isabelle and Mizar additionally check the counterexample after removing distinctness from Two; the four type-theoretic lanes reject attempted false proofs of distinctness. The Lean and Rocq failures specifically reject reflexivity as evidence that 𝑎≠𝑎. This establishes that those test files exercised the distinctness obligation. It is a useful control, not a general soundness audit.

Change ordinary union to tagged copies. In a coproduct, a left-tagged copy of 𝑎 differs from a right-tagged copy of the same 𝑎. Those two tagged points form a two-element subset even when the original points coincide. Agda and Arend check this contrast alongside the ordinary-union counterexample. The tagged construction is valid mathematics, but it changes the statement’s carrier and representation. A checker can accept it without certifying a faithful translation of Principia.

There is a second practical control on the checking process. The tested Arend CLI exits successfully even when a file contains an unsolved goal. Metamath likewise exits with code zero after reporting an incomplete proof. Our acceptance rules inspect the output and source, rather than treating exit status alone as proof completion. The retained incomplete-proof controls document both behaviors.

What this says about translation

For this case, explaining the checked proofs in ordinary mathematics is straightforward. The explanation identifies the witnesses, the distinctness claim and the two implications. No system creates a mathematical obstacle to that explanation.

A literal one-to-one correspondence is a stronger requirement. One printed citation can expand into many equality transports or library deductions. Conversely, an automated command can compress several human steps. The useful correspondence here is between claims and their dependencies: each named local landmark has a matching statement, and the endpoint composes those landmarks in the advertised way.

The six new proofs satisfy that local contract by construction and inspection. Their foundational machinery differs from Principia’s. Metamath illustrates the separate case of a checked endpoint reached through a changed argument. Neither fact discredits the mathematics; each determines the precise claim that can accompany the artifact.

The Navier–Stokes dispute concerns whether a much larger formal development supports particular manuscript statements, including quantitative estimates.7 This tiny reconstruction demonstrates an audit method, not evidence resolving that dispute. For a research proof, the corresponding work is to align definitions, quantifiers and estimates, then record where the formal derivation preserves or changes the manuscript’s dependencies. Readable syntax helps that inspection; no language substitutes for it.

Problem space

  • MEMY-2018 · complete comparison. The proposition, its local argument and seven formal readings are now inspectable.

    • Possible deeper test. Follow a single analytical estimate from manuscript assumptions to its formal dependency chain.
    • Possible historical test. Reconstruct one of Principia’s foundational class-elimination dependencies in its original theory.
  • Terminus. No further work is required to read or replay this example under the recorded runtimes.

Sources

  1. Whitehead and Russell, Principia Mathematica I, first edition, p. 379. Consulted 11 October 2026. ↩
  2. Principia I, numbered propositions 11, 12, 13, 20, 51, 52 and 54. Consulted 11 October 2026. ↩
  3. Rocq: assumption and typing queries. Consulted 11 October 2026. ↩
  4. Agda: safe mode. Consulted 11 October 2026. ↩
  5. Metamath Proof Explorer: pm54.43. Consulted 11 October 2026. ↩
  6. Pinned Metamath set.mm source. Consulted 11 October 2026. ↩
  7. Bastounis, Circelli and Hansen, Navier-Stokes lost in translation. Consulted 11 October 2026. ↩