Index src

Well formed formulas, or propositions - true or false.

strict provable sort wff;

Implication: if p, then q.

term im (p q: wff): wff;
infixr im: $->$ prec 25;

Negation: p is false.

term not (p: wff): wff;
prefix not: $~$ prec 41;

Axiom 1 of Lukasiewicz' axioms for classical propositional logic.

axiom ax_1 (a b: wff): $ a -> b -> a $;

Axiom 2 of Lukasiewicz' axioms for classical propositional logic.

axiom ax_2 (a b c: wff): $ (a -> b -> c) -> (a -> b) -> a -> c $;

Axiom 3 of Lukasiewicz' axioms for classical propositional logic.

axiom ax_3 (a b: wff): $ (~a -> ~b) -> b -> a $;

Modus ponens: from a -> b and a, infer b.

axiom ax_mp (a b: wff): $ a -> b $ > $ a $ > $ b $;
theorem a1i (a b: wff): $ b $ > $ a -> b $;
theorem a2i (a b c: wff): $ a -> b -> c $ > $ (a -> b) -> a -> c $;
theorem mpd (a b c: wff): $ a -> b $ > $ a -> b -> c $ > $ a -> c $;
theorem mpi (a b c: wff): $ b $ > $ a -> b -> c $ > $ a -> c $;
theorem id (a: wff): $ a -> a $;
theorem idd (a b: wff): $ a -> b -> b $;
theorem syl (a b c: wff): $ b -> c $ > $ a -> b $ > $ a -> c $;
theorem rsyl (a b c: wff): $ a -> b $ > $ b -> c $ > $ a -> c $;
theorem a1d (a b c: wff): $ a -> b $ > $ a -> c -> b $;
theorem a2d (a b c d: wff): $ a -> b -> c -> d $ > $ a -> (b -> c) -> b -> d $;
theorem a3d (a b c: wff): $ a -> ~b -> ~c $ > $ a -> c -> b $;
theorem sylc (a b c d: wff): $ b -> c -> d $ > $ a -> b $ > $ a -> c $ > $ a -> d $;
theorem syld (a b c d: wff): $ a -> b -> c $ > $ a -> c -> d $ > $ a -> b -> d $;
theorem syl5 (a b c d: wff): $ b -> c $ > $ a -> c -> d $ > $ a -> b -> d $;
theorem syl6 (a b c d: wff): $ c -> d $ > $ a -> b -> c $ > $ a -> b -> d $;
theorem imim2 (a b c: wff): $ (b -> c) -> (a -> b) -> a -> c $;
theorem imim2i (a b c: wff): $ b -> c $ > $ (a -> b) -> a -> c $;
theorem imim2d (a b c d: wff): $ a -> c -> d $ > $ a -> (b -> c) -> b -> d $;
theorem absurd (a b: wff): $ ~a -> a -> b $;
theorem com12 (a b c: wff): $ a -> b -> c $ > $ b -> a -> c $;
theorem mpcom (a b: wff): $ a -> (a -> b) -> b $;
theorem com23 (a b c d: wff): $ a -> b -> c -> d $ > $ a -> c -> b -> d $;
theorem eimd (a b c d: wff): $ a -> b $ > $ a -> c -> d $ > $ a -> (b -> c) -> d $;
theorem absurdr (a b: wff): $ a -> ~a -> b $;
theorem imim1 (a b c: wff): $ (a -> b) -> (b -> c) -> a -> c $;
theorem imim1i (a b c: wff): $ a -> b $ > $ (b -> c) -> a -> c $;
theorem imim1d (a b c d: wff): $ a -> b -> c $ > $ a -> (c -> d) -> b -> d $;
theorem imimd (a b c d e: wff): $ a -> b -> c $ > $ a -> d -> e $ > $ a -> (c -> d) -> b -> e $;
theorem imim (a b c d: wff): $ (a -> b) -> (c -> d) -> (b -> c) -> a -> d $;
theorem imidm (a b: wff): $ (a -> a -> b) -> a -> b $;
theorem eim (a b c: wff): $ a -> (b -> c) -> (a -> b) -> c $;
theorem contra (a: wff): $ (~a -> a) -> a $;
theorem dne (a: wff): $ ~~a -> a $;
theorem inot (a: wff): $ (a -> ~a) -> ~a $;
theorem con2 (a b: wff): $ (a -> ~b) -> b -> ~a $;
theorem notnot1 (a: wff): $ a -> ~~a $;
theorem con3 (a b: wff): $ (a -> b) -> ~b -> ~a $;
theorem con1 (a b: wff): $ (~a -> b) -> ~b -> a $;
theorem cases (a b: wff): $ a -> b $ > $ ~a -> b $ > $ b $;
theorem casesd (a b c: wff): $ a -> b -> c $ > $ a -> ~b -> c $ > $ a -> c $;
theorem con1d (a b c: wff): $ a -> ~b -> c $ > $ a -> ~c -> b $;
theorem con2d (a b c: wff): $ a -> b -> ~c $ > $ a -> c -> ~b $;
theorem con3d (a b c: wff): $ a -> b -> c $ > $ a -> ~c -> ~b $;
theorem con4d (a b c: wff): $ a -> ~b -> ~c $ > $ a -> c -> b $;
theorem mt (a b: wff): $ b -> a $ > $ ~a $ > $ ~b $;
theorem mt2 (a b: wff): $ b -> ~a $ > $ a $ > $ ~b $;
theorem mtd (a b c: wff): $ a -> ~b $ > $ a -> c -> b $ > $ a -> ~c $;
theorem mti (a b c: wff): $ ~b $ > $ a -> c -> b $ > $ a -> ~c $;
theorem mt2d (a b c: wff): $ a -> c $ > $ a -> b -> ~c $ > $ a -> ~b $;

Conjunction: a and b are both true.

def an (a b: wff): wff = $ ~(a -> ~b) $;
infixl an: $/\$ prec 34;
theorem anl (a b: wff): $ a /\ b -> a $;
theorem anr (a b: wff): $ a /\ b -> b $;
theorem anli (a b: wff): $ a /\ b $ > $ a $;
theorem anri (a b: wff): $ a /\ b $ > $ b $;
theorem ian (a b: wff): $ a -> b -> a /\ b $;
theorem iand (a b c: wff): $ a -> b $ > $ a -> c $ > $ a -> b /\ c $;
theorem anld (a b c: wff): $ a -> b /\ c $ > $ a -> b $;
theorem anrd (a b c: wff): $ a -> b /\ c $ > $ a -> c $;
theorem iani (a b: wff): $ a $ > $ b $ > $ a /\ b $;
theorem anwl (a b c: wff): $ a -> c $ > $ a /\ b -> c $;
theorem anwr (a b c: wff): $ b -> c $ > $ a /\ b -> c $;
theorem anll (a b c: wff): $ a /\ b /\ c -> a $;
theorem anlr (a b c: wff): $ a /\ b /\ c -> b $;
theorem anrl (a b c: wff): $ a /\ (b /\ c) -> b $;
theorem anrr (a b c: wff): $ a /\ (b /\ c) -> c $;
theorem anwll (a b c d: wff): $ a -> d $ > $ a /\ b /\ c -> d $;
theorem anw3l (a b c d e: wff): $ a -> e $ > $ a /\ b /\ c /\ d -> e $;
theorem anw4l (a b c d e f: wff): $ a -> f $ > $ a /\ b /\ c /\ d /\ e -> f $;
theorem anw5l (a b c d e f g: wff): $ a -> g $ > $ a /\ b /\ c /\ d /\ e /\ f -> g $;
theorem anw6l (a b c d e f g h: wff): $ a -> h $ > $ a /\ b /\ c /\ d /\ e /\ f /\ g -> h $;
theorem anw7l (a b c d e f g h i: wff): $ a -> i $ > $ a /\ b /\ c /\ d /\ e /\ f /\ g /\ h -> i $;
theorem anllr (a b c d: wff): $ a /\ b /\ c /\ d -> b $;
theorem an3l (a b c d: wff): $ a /\ b /\ c /\ d -> a $;
theorem an3lr (a b c d e: wff): $ a /\ b /\ c /\ d /\ e -> b $;
theorem an4l (a b c d e: wff): $ a /\ b /\ c /\ d /\ e -> a $;
theorem an4lr (a b c d e f: wff): $ a /\ b /\ c /\ d /\ e /\ f -> b $;
theorem an5l (a b c d e f: wff): $ a /\ b /\ c /\ d /\ e /\ f -> a $;
theorem an5lr (a b c d e f g: wff): $ a /\ b /\ c /\ d /\ e /\ f /\ g -> b $;
theorem an6l (a b c d e f g: wff): $ a /\ b /\ c /\ d /\ e /\ f /\ g -> a $;
theorem an6lr (a b c d e f g h: wff): $ a /\ b /\ c /\ d /\ e /\ f /\ g /\ h -> b $;
theorem imp (a b c: wff): $ a -> b -> c $ > $ a /\ b -> c $;
theorem exp (a b c: wff): $ a /\ b -> c $ > $ a -> b -> c $;
theorem impcom (a b c: wff): $ a -> b -> c $ > $ b /\ a -> c $;
theorem expcom (a b c: wff): $ a /\ b -> c $ > $ b -> a -> c $;
theorem syla (a b c d: wff): $ (b -> c) -> d $ > $ a /\ b -> c $ > $ a -> d $;
theorem sylan (a b c d: wff): $ b /\ c -> d $ > $ a -> b $ > $ a -> c $ > $ a -> d $;
theorem animd (a b c d e: wff): $ a -> b -> c $ > $ a -> d -> e $ > $ a -> b /\ d -> c /\ e $;
theorem anim1d (a b c d: wff): $ a -> b -> c $ > $ a -> b /\ d -> c /\ d $;
theorem anim2d (a b c d: wff): $ a -> c -> d $ > $ a -> b /\ c -> b /\ d $;
theorem anim1 (a b c: wff): $ (a -> b) -> a /\ c -> b /\ c $;
theorem anim2 (a b c: wff): $ (b -> c) -> a /\ b -> a /\ c $;
theorem anim (a b c d: wff): $ (a -> b) -> (c -> d) -> a /\ c -> b /\ d $;
theorem anim2a (a b c: wff): $ (a -> b -> c) -> a /\ b -> a /\ c $;
theorem ancom (a b: wff): $ a /\ b -> b /\ a $;
theorem anrasss (a b c d: wff): $ a /\ b /\ c -> d $ > $ a /\ c /\ b -> d $;
theorem anim1a (a b c: wff): $ (a -> b -> c) -> b /\ a -> c /\ a $;
theorem casesda (a b c: wff): $ a /\ b -> c $ > $ a /\ ~b -> c $ > $ a -> c $;
theorem inotda (a b: wff): $ a /\ b -> ~b $ > $ a -> ~b $;
theorem mpand (a b c: wff): $ a -> b $ > $ a /\ b -> c $ > $ a -> c $;
theorem mtand (a b c: wff): $ a -> ~b $ > $ a /\ c -> b $ > $ a -> ~c $;
theorem mtani (a b c: wff): $ ~b $ > $ a /\ c -> b $ > $ a -> ~c $;

If and only if: a implies b, and b implies a.

def iff (a b: wff): wff = $ (a -> b) /\ (b -> a) $;
infixl iff: $<->$ prec 20;
theorem bi1 (a b: wff): $ (a <-> b) -> a -> b $;
theorem bi1i (a b: wff): $ a <-> b $ > $ a -> b $;
theorem bi1d (a b c: wff): $ a -> (b <-> c) $ > $ a -> b -> c $;
theorem bi1a (a b c: wff): $ a -> (b <-> c) $ > $ a /\ b -> c $;
theorem bi2 (a b: wff): $ (a <-> b) -> b -> a $;
theorem bi2i (a b: wff): $ a <-> b $ > $ b -> a $;
theorem bi2d (a b c: wff): $ a -> (b <-> c) $ > $ a -> c -> b $;
theorem bi2a (a b c: wff): $ a -> (b <-> c) $ > $ a /\ c -> b $;
theorem ibii (a b: wff): $ a -> b $ > $ b -> a $ > $ a <-> b $;
theorem ibid (a b c: wff): $ a -> b -> c $ > $ a -> c -> b $ > $ a -> (b <-> c) $;
theorem ibida (a b c: wff): $ a /\ b -> c $ > $ a /\ c -> b $ > $ a -> (b <-> c) $;
theorem biid (a: wff): $ a <-> a $;
theorem biidd (a b: wff): $ a -> (b <-> b) $;
theorem mpbi (a b: wff): $ a <-> b $ > $ a $ > $ b $;
theorem mpbir (a b: wff): $ b <-> a $ > $ a $ > $ b $;
theorem mpbid (a b c: wff): $ a -> (b <-> c) $ > $ a -> b $ > $ a -> c $;
theorem mpbird (a b c: wff): $ a -> (c <-> b) $ > $ a -> b $ > $ a -> c $;
theorem mpbii (a b c: wff): $ b $ > $ a -> (b <-> c) $ > $ a -> c $;
theorem mpbiri (a b c: wff): $ b $ > $ a -> (c <-> b) $ > $ a -> c $;
theorem mtbi (a b: wff): $ a <-> b $ > $ ~a $ > $ ~b $;
theorem mtbir (a b: wff): $ b <-> a $ > $ ~a $ > $ ~b $;
theorem mtbid (a b c: wff): $ a -> (b <-> c) $ > $ a -> ~b $ > $ a -> ~c $;
theorem mtbird (a b c: wff): $ a -> (c <-> b) $ > $ a -> ~b $ > $ a -> ~c $;
theorem con1b (a b: wff): $ (~a <-> b) -> (~b <-> a) $;
theorem con2b (a b: wff): $ (a <-> ~b) -> (b <-> ~a) $;
theorem con3b (a b: wff): $ (a <-> b) -> (~a <-> ~b) $;
theorem con4b (a b: wff): $ (~a <-> ~b) -> (a <-> b) $;
theorem con1bb (a b: wff): $ ~a <-> b <-> (~b <-> a) $;
theorem con2bb (a b: wff): $ a <-> ~b <-> (b <-> ~a) $;
theorem con3bb (a b: wff): $ a <-> b <-> (~a <-> ~b) $;
theorem con1bi (a b: wff): $ ~a -> b <-> ~b -> a $;
theorem con2bi (a b: wff): $ a -> ~b <-> b -> ~a $;
theorem con3bi (a b: wff): $ a -> b <-> ~b -> ~a $;
theorem notnot (a: wff): $ a <-> ~~a $;
theorem bithd (a b c: wff): $ a -> b $ > $ a -> c $ > $ a -> (b <-> c) $;
theorem binthd (a b c: wff): $ a -> ~b $ > $ a -> ~c $ > $ a -> (b <-> c) $;
theorem bith (a b: wff): $ a -> b -> (a <-> b) $;
theorem binth (a b: wff): $ ~a -> ~b -> (a <-> b) $;
theorem bicom (a b: wff): $ (a <-> b) -> (b <-> a) $;
theorem bicomb (a b: wff): $ a <-> b <-> (b <-> a) $;
theorem bicomd (a b c: wff): $ a -> (b <-> c) $ > $ a -> (c <-> b) $;
theorem bitrd (a b c d: wff): $ a -> (b <-> c) $ > $ a -> (c <-> d) $ > $ a -> (b <-> d) $;
theorem bitr2d (a b c d: wff): $ a -> (b <-> c) $ > $ a -> (c <-> d) $ > $ a -> (d <-> b) $;
theorem bitr3d (a b c d: wff): $ a -> (c <-> b) $ > $ a -> (c <-> d) $ > $ a -> (b <-> d) $;
theorem bitr4d (a b c d: wff): $ a -> (b <-> c) $ > $ a -> (d <-> c) $ > $ a -> (b <-> d) $;
theorem bitr (a b c: wff): $ (a <-> b) -> (b <-> c) -> (a <-> c) $;
theorem bitr2 (a b c: wff): $ (a <-> b) -> (b <-> c) -> (c <-> a) $;
theorem bitr3 (a b c: wff): $ (b <-> a) -> (b <-> c) -> (a <-> c) $;
theorem bitr4 (a b c: wff): $ (a <-> b) -> (c <-> b) -> (a <-> c) $;
theorem sylib (a b c: wff): $ b <-> c $ > $ a -> b $ > $ a -> c $;
theorem sylibr (a b c: wff): $ c <-> b $ > $ a -> b $ > $ a -> c $;
theorem sylbi (a b c: wff): $ a <-> b $ > $ b -> c $ > $ a -> c $;
theorem sylbir (a b c: wff): $ b <-> a $ > $ b -> c $ > $ a -> c $;
theorem syl5bb (a b c d: wff): $ b <-> c $ > $ a -> (c <-> d) $ > $ a -> (b <-> d) $;
theorem syl5bbr (a b c d: wff): $ c <-> b $ > $ a -> (c <-> d) $ > $ a -> (b <-> d) $;
theorem syl6bb (a b c d: wff): $ c <-> d $ > $ a -> (b <-> c) $ > $ a -> (b <-> d) $;
theorem syl6bbr (a b c d: wff): $ d <-> c $ > $ a -> (b <-> c) $ > $ a -> (b <-> d) $;
theorem syl5bi (a b c d: wff): $ b <-> c $ > $ a -> c -> d $ > $ a -> b -> d $;
theorem syl5bir (a b c d: wff): $ c <-> b $ > $ a -> c -> d $ > $ a -> b -> d $;
theorem syl6ib (a b c d: wff): $ c <-> d $ > $ a -> b -> c $ > $ a -> b -> d $;
theorem syl6ibr (a b c d: wff): $ d <-> c $ > $ a -> b -> c $ > $ a -> b -> d $;
theorem syl5ibrcom (a b c d: wff): $ c -> (b <-> d) $ > $ a -> d $ > $ a -> c -> b $;
theorem sylbid (a b c d: wff): $ a -> (b <-> c) $ > $ a -> c -> d $ > $ a -> b -> d $;
theorem sylibd (a b c d: wff): $ a -> b -> c $ > $ a -> (c <-> d) $ > $ a -> b -> d $;
theorem sylbird (a b c d: wff): $ a -> (c <-> b) $ > $ a -> c -> d $ > $ a -> b -> d $;
theorem sylibrd (a b c d: wff): $ a -> b -> c $ > $ a -> (d <-> c) $ > $ a -> b -> d $;
theorem bitr3g (a b c d e: wff): $ b <-> d $ > $ c <-> e $ > $ a -> (b <-> c) $ > $ a -> (d <-> e) $;
theorem bitr4g (a b c d e: wff): $ d <-> b $ > $ e <-> c $ > $ a -> (b <-> c) $ > $ a -> (d <-> e) $;
theorem bitr3gi (a b c d: wff): $ a <-> c $ > $ b <-> d $ > $ a <-> b $ > $ c <-> d $;
theorem bitr4gi (a b c d: wff): $ c <-> a $ > $ d <-> b $ > $ a <-> b $ > $ c <-> d $;
theorem impbi (a b c: wff): $ a -> (b <-> c) $ > $ a /\ b -> c $;
theorem impbir (a b c: wff): $ a -> (c <-> b) $ > $ a /\ b -> c $;
theorem ancomb (a b: wff): $ a /\ b <-> b /\ a $;
theorem anass (a b c: wff): $ a /\ b /\ c <-> a /\ (b /\ c) $;
theorem bian2a (a b: wff): $ (a -> b) -> (a /\ b <-> a) $;
theorem bian1a (a b: wff): $ (b -> a) -> (a /\ b <-> b) $;
theorem bian1 (a b: wff): $ a -> (a /\ b <-> b) $;
theorem bian2 (a b: wff): $ b -> (a /\ b <-> a) $;
theorem bibi1 (a b: wff): $ a -> (a <-> b <-> b) $;
theorem bibi2 (a b: wff): $ b -> (a <-> b <-> a) $;
theorem noteq (a b: wff): $ (a <-> b) -> (~a <-> ~b) $;
theorem noteqi (a b: wff): $ a <-> b $ > $ ~a <-> ~b $;
theorem noteqd (a b c: wff): $ a -> (b <-> c) $ > $ a -> (~b <-> ~c) $;
theorem imeqd (a b c d e: wff): $ a -> (b <-> c) $ > $ a -> (d <-> e) $ > $ a -> (b -> d <-> c -> e) $;
theorem bibin1 (a b: wff): $ ~a -> (a <-> b <-> ~b) $;
theorem bibin2 (a b: wff): $ ~b -> (a <-> b <-> ~a) $;
theorem imeq1d (a b c d: wff): $ a -> (b <-> c) $ > $ a -> (b -> d <-> c -> d) $;
theorem imeq2d (a b c d: wff): $ a -> (c <-> d) $ > $ a -> (b -> c <-> b -> d) $;
theorem imeq1i (a b c: wff): $ a <-> b $ > $ a -> c <-> b -> c $;
theorem imeq2i (a b c: wff): $ b <-> c $ > $ a -> b <-> a -> c $;
theorem imeqi (a b c d: wff): $ a <-> b $ > $ c <-> d $ > $ a -> c <-> b -> d $;
theorem aneqd (a b c d e: wff): $ a -> (b <-> c) $ > $ a -> (d <-> e) $ > $ a -> (b /\ d <-> c /\ e) $;
theorem imeq2a (a b c: wff): $ (a -> (b <-> c)) -> (a -> b <-> a -> c) $;
theorem imeq1a (a b c: wff): $ (~c -> (a <-> b)) -> (a -> c <-> b -> c) $;
theorem imeq2da (G a b c: wff): $ G /\ a -> (b <-> c) $ > $ G -> (a -> b <-> a -> c) $;
theorem aneq1d (a b c d: wff): $ a -> (b <-> c) $ > $ a -> (b /\ d <-> c /\ d) $;
theorem aneq2d (a b c d: wff): $ a -> (c <-> d) $ > $ a -> (b /\ c <-> b /\ d) $;
theorem aneq (a b c d: wff): $ (a <-> b) -> (c <-> d) -> (a /\ c <-> b /\ d) $;
theorem aneq1i (a b c: wff): $ a <-> b $ > $ a /\ c <-> b /\ c $;
theorem aneq2i (a b c: wff): $ b <-> c $ > $ a /\ b <-> a /\ c $;
theorem aneq2a (a b c: wff): $ (a -> (b <-> c)) -> (a /\ b <-> a /\ c) $;
theorem aneq1a (a b c: wff): $ (c -> (a <-> b)) -> (a /\ c <-> b /\ c) $;
theorem aneq1da (G a b c: wff): $ G /\ c -> (a <-> b) $ > $ G -> (a /\ c <-> b /\ c) $;
theorem aneq2da (G a b c: wff): $ G /\ a -> (b <-> c) $ > $ G -> (a /\ b <-> a /\ c) $;
theorem anlass (a b c: wff): $ a /\ (b /\ c) <-> b /\ (a /\ c) $;
theorem anrass (a b c: wff): $ a /\ b /\ c <-> a /\ c /\ b $;
theorem an4 (a b c d: wff): $ a /\ b /\ (c /\ d) <-> a /\ c /\ (b /\ d) $;
theorem anroti (a b c d: wff): $ a -> b /\ d $ > $ a /\ c -> b /\ c /\ d $;
theorem anrotri (a b c d: wff): $ b /\ d -> a $ > $ b /\ c /\ d -> a /\ c $;
theorem bian11i (a b c d: wff): $ a <-> b /\ c $ > $ a /\ d <-> b /\ (c /\ d) $;
theorem bian21i (a b c d: wff): $ a <-> b /\ c $ > $ a /\ d <-> b /\ d /\ c $;
theorem bian12i (a b c d: wff): $ a <-> b /\ c $ > $ d /\ a <-> b /\ (d /\ c) $;
theorem bian22i (a b c d: wff): $ a <-> b /\ c $ > $ d /\ a <-> d /\ b /\ c $;
theorem bian11d (G a b c d: wff): $ G -> (a <-> b /\ c) $ > $ G -> (a /\ d <-> b /\ (c /\ d)) $;
theorem bian21d (G a b c d: wff): $ G -> (a <-> b /\ c) $ > $ G -> (a /\ d <-> b /\ d /\ c) $;
theorem bian12d (G a b c d: wff): $ G -> (a <-> b /\ c) $ > $ G -> (d /\ a <-> b /\ (d /\ c)) $;
theorem bian22d (G a b c d: wff): $ G -> (a <-> b /\ c) $ > $ G -> (d /\ a <-> d /\ b /\ c) $;
theorem bian11da (G a b c d: wff): $ G /\ d -> (a <-> b /\ c) $ > $ G -> (a /\ d <-> b /\ (c /\ d)) $;
theorem bian21da (G a b c d: wff): $ G /\ d -> (a <-> b /\ c) $ > $ G -> (a /\ d <-> b /\ d /\ c) $;
theorem bian12da (G a b c d: wff): $ G /\ d -> (a <-> b /\ c) $ > $ G -> (d /\ a <-> b /\ (d /\ c)) $;
theorem bian22da (G a b c d: wff): $ G /\ d -> (a <-> b /\ c) $ > $ G -> (d /\ a <-> d /\ b /\ c) $;
theorem anidm (a: wff): $ a /\ a <-> a $;
theorem anandi (a b c: wff): $ a /\ (b /\ c) <-> a /\ b /\ (a /\ c) $;
theorem anandir (a b c: wff): $ a /\ b /\ c <-> a /\ c /\ (b /\ c) $;
theorem imandi (a b c: wff): $ a -> b /\ c <-> (a -> b) /\ (a -> c) $;
theorem imancom (a b c: wff): $ a /\ (b -> c) -> b -> a /\ c $;
theorem rbida (a b c d: wff): $ a /\ c -> b $ > $ a /\ d -> b $ > $ a /\ b -> (c <-> d) $ > $ a -> (c <-> d) $;
theorem rbid (a b c: wff): $ b -> a $ > $ c -> a $ > $ a -> (b <-> c) $ > $ b <-> c $;
theorem bieqd (a b c d e: wff): $ a -> (b <-> c) $ > $ a -> (d <-> e) $ > $ a -> (b <-> d <-> (c <-> e)) $;
theorem bieq1d (a b c d: wff): $ a -> (b <-> c) $ > $ a -> (b <-> d <-> (c <-> d)) $;
theorem bieq2d (a b c d: wff): $ a -> (c <-> d) $ > $ a -> (b <-> c <-> (b <-> d)) $;
theorem bieq (a b c d: wff): $ (a <-> b) -> (c <-> d) -> (a <-> c <-> (b <-> d)) $;
theorem bieq1 (a b c: wff): $ (a <-> b) -> (a <-> c <-> (b <-> c)) $;
theorem bieq2 (a b c: wff): $ (b <-> c) -> (a <-> b <-> (a <-> c)) $;
theorem impexp (a b c: wff): $ a /\ b -> c <-> a -> b -> c $;
theorem impd (a b c d: wff): $ a -> b -> c -> d $ > $ a -> b /\ c -> d $;
theorem expd (a b c d: wff): $ a -> b /\ c -> d $ > $ a -> b -> c -> d $;
theorem com12b (a b c: wff): $ a -> b -> c <-> b -> a -> c $;

Disjunction: either a is true or b is true.

def or (a b: wff): wff = $ ~a -> b $;
infixl or: $\/$ prec 30;
theorem oreqd (_G _a1 _a2 _b1 _b2: wff): $ _G -> (_a1 <-> _a2) $ > $ _G -> (_b1 <-> _b2) $ > $ _G -> (_a1 \/ _b1 <-> _a2 \/ _b2) $;
theorem oreq (_a1 _a2 _b1 _b2: wff): $ (_a1 <-> _a2) -> (_b1 <-> _b2) -> (_a1 \/ _b1 <-> _a2 \/ _b2) $;
theorem oreq1d (_G _a1 _a2 b: wff): $ _G -> (_a1 <-> _a2) $ > $ _G -> (_a1 \/ b <-> _a2 \/ b) $;
theorem oreq1 (_a1 _a2 b: wff): $ (_a1 <-> _a2) -> (_a1 \/ b <-> _a2 \/ b) $;
theorem oreq2d (_G a _b1 _b2: wff): $ _G -> (_b1 <-> _b2) $ > $ _G -> (a \/ _b1 <-> a \/ _b2) $;
theorem oreq2 (a _b1 _b2: wff): $ (_b1 <-> _b2) -> (a \/ _b1 <-> a \/ _b2) $;
theorem orl (a b: wff): $ a -> a \/ b $;
theorem orr (a b: wff): $ b -> a \/ b $;
theorem eori (a b c: wff): $ a -> c $ > $ b -> c $ > $ a \/ b -> c $;
theorem eord (a b c d: wff): $ a -> b -> d $ > $ a -> c -> d $ > $ a -> b \/ c -> d $;
theorem eorda (a b c d: wff): $ a /\ b -> d $ > $ a /\ c -> d $ > $ a -> b \/ c -> d $;
theorem orld (a b c: wff): $ a -> b $ > $ a -> b \/ c $;
theorem orrd (a b c: wff): $ a -> c $ > $ a -> b \/ c $;
theorem eor (a b c: wff): $ (a -> c) -> (b -> c) -> a \/ b -> c $;
theorem orimd (a b c d e: wff): $ a -> b -> c $ > $ a -> d -> e $ > $ a -> b \/ d -> c \/ e $;
theorem orim1d (a b c d: wff): $ a -> b -> c $ > $ a -> b \/ d -> c \/ d $;
theorem orim2d (a b c d: wff): $ a -> c -> d $ > $ a -> b \/ c -> b \/ d $;
theorem orim1 (a b c: wff): $ (a -> b) -> a \/ c -> b \/ c $;
theorem orim2 (a b c: wff): $ (b -> c) -> a \/ b -> a \/ c $;
theorem oreq1i (a b c: wff): $ a <-> b $ > $ a \/ c <-> b \/ c $;
theorem oreq2i (a b c: wff): $ b <-> c $ > $ a \/ b <-> a \/ c $;
theorem orim (a b c d: wff): $ (a -> b) -> (c -> d) -> a \/ c -> b \/ d $;
theorem oreqi (a b c d: wff): $ a <-> b $ > $ c <-> d $ > $ a \/ c <-> b \/ d $;
theorem orcom (a b: wff): $ a \/ b -> b \/ a $;
theorem orcomb (a b: wff): $ a \/ b <-> b \/ a $;
theorem or12 (a b c: wff): $ a \/ (b \/ c) <-> b \/ (a \/ c) $;
theorem orass (a b c: wff): $ a \/ b \/ c <-> a \/ (b \/ c) $;
theorem or4 (a b c d: wff): $ a \/ b \/ (c \/ d) <-> a \/ c \/ (b \/ d) $;
theorem oridm (a: wff): $ a \/ a <-> a $;
theorem notan2 (a b: wff): $ ~(a /\ b) <-> a -> ~b $;
theorem notan (a b: wff): $ ~(a /\ b) <-> ~a \/ ~b $;
theorem notor (a b: wff): $ ~(a \/ b) <-> ~a /\ ~b $;
theorem iman (a b: wff): $ a -> b <-> ~(a /\ ~b) $;
theorem imor (a b c: wff): $ a \/ b -> c <-> (a -> c) /\ (b -> c) $;
theorem andi (a b c: wff): $ a /\ (b \/ c) <-> a /\ b \/ a /\ c $;
theorem andir (a b c: wff): $ (a \/ b) /\ c <-> a /\ c \/ b /\ c $;
theorem ordi (a b c: wff): $ a \/ b /\ c <-> (a \/ b) /\ (a \/ c) $;
theorem ordir (a b c: wff): $ a /\ b \/ c <-> (a \/ c) /\ (b \/ c) $;
theorem oreq2a (a b c: wff): $ (~a -> (b <-> c)) -> (a \/ b <-> a \/ c) $;
theorem oreq1a (a b c: wff): $ (~c -> (a <-> b)) -> (a \/ c <-> b \/ c) $;
theorem biim1a (a b: wff): $ (~a -> b) -> (a -> b <-> b) $;
theorem biim2a (a b: wff): $ (b -> ~a) -> (a -> b <-> ~a) $;
theorem bior1a (a b: wff): $ (a -> b) -> (a \/ b <-> b) $;
theorem bior2a (a b: wff): $ (b -> a) -> (a \/ b <-> a) $;
theorem biim1 (a b: wff): $ a -> (a -> b <-> b) $;
theorem biim2 (a b: wff): $ ~b -> (a -> b <-> ~a) $;
theorem bior1 (a b: wff): $ ~a -> (a \/ b <-> b) $;
theorem bior2 (a b: wff): $ ~b -> (a \/ b <-> a) $;
theorem em (p: wff): $ p \/ ~p $;
theorem emr (p: wff): $ ~p \/ p $;

Selection: ifp p a b is equivalent to a if p is true, and equivalent to b if p is false.

abstract def ifp (p a b: wff): wff = $ p /\ a \/ ~p /\ b $;
theorem ifpeqd (_G _p1 _p2 _a1 _a2 _b1 _b2: wff):
  $ _G -> (_p1 <-> _p2) $ >
  $ _G -> (_a1 <-> _a2) $ >
  $ _G -> (_b1 <-> _b2) $ >
  $ _G -> (ifp _p1 _a1 _b1 <-> ifp _p2 _a2 _b2) $;
theorem ifpeq (_p1 _p2 _a1 _a2 _b1 _b2: wff): $ (_p1 <-> _p2) -> (_a1 <-> _a2) -> (_b1 <-> _b2) -> (ifp _p1 _a1 _b1 <-> ifp _p2 _a2 _b2) $;
theorem ifpeq1d (_G _p1 _p2 a b: wff): $ _G -> (_p1 <-> _p2) $ > $ _G -> (ifp _p1 a b <-> ifp _p2 a b) $;
theorem ifpeq1 (_p1 _p2 a b: wff): $ (_p1 <-> _p2) -> (ifp _p1 a b <-> ifp _p2 a b) $;
theorem ifpeq2d (_G p _a1 _a2 b: wff): $ _G -> (_a1 <-> _a2) $ > $ _G -> (ifp p _a1 b <-> ifp p _a2 b) $;
theorem ifpeq2 (p _a1 _a2 b: wff): $ (_a1 <-> _a2) -> (ifp p _a1 b <-> ifp p _a2 b) $;
theorem ifpeq3d (_G p a _b1 _b2: wff): $ _G -> (_b1 <-> _b2) $ > $ _G -> (ifp p a _b1 <-> ifp p a _b2) $;
theorem ifpeq3 (p a _b1 _b2: wff): $ (_b1 <-> _b2) -> (ifp p a _b1 <-> ifp p a _b2) $;
pub theorem ifppos (p a b: wff): $ p -> (ifp p a b <-> a) $;
pub theorem ifpneg (p a b: wff): $ ~p -> (ifp p a b <-> b) $;
theorem ifpid (a p: wff): $ ifp p a a <-> a $;
theorem ifpnot (a b p: wff): $ ifp (~p) a b <-> ifp p b a $;
theorem ifpan1 (a b c p: wff): $ ifp p a b /\ c <-> ifp p (a /\ c) (b /\ c) $;
theorem ifpan2 (a b c p: wff): $ c /\ ifp p a b <-> ifp p (c /\ a) (c /\ b) $;
theorem ifpor (a b c d p: wff): $ ifp p (a \/ b) (c \/ d) <-> ifp p a c \/ ifp p b d $;
theorem ifpeq2a (a1 a2 b p: wff): $ (p -> (a1 <-> a2)) -> (ifp p a1 b <-> ifp p a2 b) $;
theorem ifpeq3a (a b1 b2 p: wff): $ (~p -> (b1 <-> b2)) -> (ifp p a b1 <-> ifp p a b2) $;
theorem ifptreq (G a p p0 p1 q0 q1: wff): $ G -> (p <-> ifp a p0 p1) $ > $ G /\ a -> (p0 <-> q0) $ > $ G /\ ~a -> (p1 <-> q1) $ > $ G -> (p <-> ifp a q0 q1) $;
theorem ifppos2 (a b c: wff): $ b -> (ifp a b c <-> a \/ c) $;
theorem ifppos3 (a b c: wff): $ c -> (ifp a b c <-> ~a \/ b) $;
theorem ifpneg3 (a b c: wff): $ ~c -> (ifp a b c <-> a /\ b) $;
theorem ifpneg2 (a b c: wff): $ ~b -> (ifp a b c <-> ~a /\ c) $;

The constant true.

term tru: wff;
prefix tru: $T.$ prec max;

true is true.

axiom itru: $ T. $;

The constant false.

def fal: wff = $ ~T. $;
prefix fal: $F.$ prec max;
theorem trud (a: wff): $ T. -> a $ > $ a $;
theorem eqtru (a: wff): $ a <-> T. <-> a $;
theorem notfal: $ ~F. $;
theorem efal (a: wff): $ F. -> a $;
theorem imfal (a: wff): $ a -> F. <-> ~a $;
theorem eqfal (a: wff): $ a <-> F. <-> ~a $;
theorem neqfal (a: wff): $ ~a <-> F. <-> a $;

The sort of natural numbers, or nonnegative integers. In Peano Arithmetic this is the domain of discourse, the basic sort over which quantifiers range.

sort nat;

The for-all quantifier. A. x p means "for all natural numbers x, p holds", where (p: wff x) in the declaration indicates that p may contain free occurrences of variable x that are bound by this quantifier.

term al {x: nat} (p: wff x): wff;
prefix al: $A.$ prec 41;

The exists quantifier. E. x p means "there is a natural number x, such that p holds", where (p: wff x) in the declaration indicates that p may contain free occurrences of variable x that are bound by this quantifier.

def ex {x: nat} (p: wff x): wff = $ ~A. x ~p $;
prefix ex: $E.$ prec 41;

Equality of natural numbers: a = b means that a and b have the same value.

term eq (a b: nat): wff;
infixl eq: $=$ prec 50;

The axiom of generalization. If |- p is derivable (the lack of a precondition means this is a proof in the empty context), then p is universally true, so |- A. x p is also true.

axiom ax_gen {x: nat} (p: wff x): $ p $ > $ A. x p $;

Axiom 4 for predicate logic: forall distributes over implication.

axiom ax_4 {x: nat} (p q: wff x): $ A. x (p -> q) -> A. x p -> A. x q $;
theorem alim {x: nat} (p q: wff x): $ A. x (p -> q) -> A. x p -> A. x q $;

Axiom 5 for predicate logic: If p does not contain an occurrence of x (note that (p: wff) in contrast to (p: wff x) means that p cannot depend on variable x), then p implies A. x p because the quantifier is trivial.

axiom ax_5 {x: nat} (p: wff): $ p -> A. x p $;
theorem ial {x: nat} (p: wff): $ p -> A. x p $;

Axiom 6 for predicate logic: for any term a (which cannot depend on x), there exists an x which is equal to a.

axiom ax_6 (a: nat) {x: nat}: $ E. x x = a $;

Axiom 7 for predicate logic: equality satisfies the euclidean property (which implies symmetry and transitivity, and reflexivity given axiom 6).

axiom ax_7 (a b c: nat): $ a = b -> a = c -> b = c $;
theorem eqtr3 (a b c: nat): $ b = a -> b = c -> a = c $;

Axiom 10 for predicate logic: x is bound in ~(A. x p), so we can safely introduce a A. x quantifier. (This axiom is used to internalize the notion of "bound in" when axiom 5 does not apply.)

axiom ax_10 {x: nat} (p: wff x): $ ~A. x p -> A. x ~A. x p $;

Axiom 11 for predicate logic: forall quantifiers commute.

axiom ax_11 {x y: nat} (p: wff x y): $ A. x A. y p -> A. y A. x p $;
theorem alcom {x y: nat} (p: wff x y): $ A. x A. y p -> A. y A. x p $;

Axiom 12 for predicate logic: If x is some fixed a and p(x) holds, then for all x which are equal to a, p(x) holds. This expresses the substitution property of =, but the name shadowing on x allows us to express this without changing p, because we haven't defined proper substitution yet.

axiom ax_12 {x: nat} (a: nat) (p: wff x): $ x = a -> p -> A. x (x = a -> p) $;
theorem alimi {x: nat} (a b: wff x): $ a -> b $ > $ A. x a -> A. x b $;
theorem iald {x: nat} (a: wff) (b: wff x): $ a -> b $ > $ a -> A. x b $;
theorem eex {x: nat} (a: wff x) (b: wff): $ a -> b $ > $ E. x a -> b $;
theorem eqid (a: nat): $ a = a $;
theorem eqcom (a b: nat): $ a = b -> b = a $;
theorem eqtr (a b c: nat): $ a = b -> b = c -> a = c $;
theorem eqtr2 (a b c: nat): $ a = b -> b = c -> c = a $;
theorem eqtr4 (a b c: nat): $ a = b -> c = b -> a = c $;
theorem eqcomb (a b: nat): $ a = b <-> b = a $;
theorem eqeq1 (a b c: nat): $ a = b -> (a = c <-> b = c) $;
theorem eqeq2 (a b c: nat): $ b = c -> (a = b <-> a = c) $;
theorem eqeq1d (G: wff) (a b c: nat): $ G -> a = b $ > $ G -> (a = c <-> b = c) $;
theorem eqeq2d (G: wff) (a b c: nat): $ G -> b = c $ > $ G -> (a = b <-> a = c) $;
theorem eqeqd (G: wff) (a b c d: nat): $ G -> a = b $ > $ G -> c = d $ > $ G -> (a = c <-> b = d) $;
theorem eqeq (a b c d: nat): $ a = b -> c = d -> (a = c <-> b = d) $;
theorem eqtr2d (G: wff) (a b c: nat): $ G -> a = b $ > $ G -> b = c $ > $ G -> c = a $;
theorem eqtr3d (G: wff) (a b c: nat): $ G -> b = a $ > $ G -> b = c $ > $ G -> a = c $;
theorem eqidd (G: wff) (a: nat): $ G -> a = a $;
theorem eqcomi (a b: nat): $ a = b $ > $ b = a $;
theorem eqcomd (G: wff) (a b: nat): $ G -> a = b $ > $ G -> b = a $;
theorem eqtrd (G: wff) (a b c: nat): $ G -> a = b $ > $ G -> b = c $ > $ G -> a = c $;
theorem eqtr4i (a b c: nat): $ a = b $ > $ c = b $ > $ a = c $;
theorem eqtr4d (G: wff) (a b c: nat): $ G -> a = b $ > $ G -> c = b $ > $ G -> a = c $;
theorem syl5eq (G: wff) (a b c: nat): $ a = b $ > $ G -> b = c $ > $ G -> a = c $;
theorem syl5eqr (G: wff) (a b c: nat): $ b = a $ > $ G -> b = c $ > $ G -> a = c $;
theorem syl6eq (G: wff) (a b c: nat): $ b = c $ > $ G -> a = b $ > $ G -> a = c $;
theorem syl6eqr (G: wff) (a b c: nat): $ c = b $ > $ G -> a = b $ > $ G -> a = c $;
theorem eqtr3g (G: wff) (a b c d: nat): $ a = c $ > $ b = d $ > $ G -> a = b $ > $ G -> c = d $;
theorem eqtr4g (G: wff) (a b c d: nat): $ c = a $ > $ d = b $ > $ G -> a = b $ > $ G -> c = d $;
theorem aleq {x: nat} (a b: wff x): $ A. x (a <-> b) -> (A. x a <-> A. x b) $;
theorem aleqi {x: nat} (a b: wff x): $ a <-> b $ > $ A. x a <-> A. x b $;
theorem alimd {x: nat} (G: wff) (a b: wff x): $ G -> a -> b $ > $ G -> A. x a -> A. x b $;
theorem raleqi {x: nat} (p a b: wff x): $ a <-> b $ > $ A. x (p -> a) <-> A. x (p -> b) $;
theorem al2imi {x: nat} (a b c: wff x): $ a -> b -> c $ > $ A. x a -> A. x b -> A. x c $;
theorem aleqd (G: wff) {x: nat} (a b: wff x): $ G -> (a <-> b) $ > $ G -> (A. x a <-> A. x b) $;
theorem ialda {x: nat} (G: wff) (a b: wff x): $ G /\ a -> b $ > $ G -> A. x (a -> b) $;
theorem alcomb {x y: nat} (a: wff x y): $ A. x A. y a <-> A. y A. x a $;
theorem alan {x: nat} (a b: wff x): $ A. x (a /\ b) <-> A. x a /\ A. x b $;
theorem ralan {x: nat} (a b c: wff x): $ A. x (a -> b /\ c) <-> A. x (a -> b) /\ A. x (a -> c) $;
theorem exim {x: nat} (a b: wff x): $ A. x (a -> b) -> E. x a -> E. x b $;
theorem eximi {x: nat} (a b: wff x): $ a -> b $ > $ E. x a -> E. x b $;
theorem exeq {x: nat} (a b: wff x): $ A. x (a <-> b) -> (E. x a <-> E. x b) $;
theorem exeqd (G: wff) {x: nat} (a b: wff x): $ G -> (a <-> b) $ > $ G -> (E. x a <-> E. x b) $;
theorem exeqi {x: nat} (a b: wff x): $ a <-> b $ > $ E. x a <-> E. x b $;
theorem rexeqi {x: nat} (p a b: wff x): $ a <-> b $ > $ E. x (p /\ a) <-> E. x (p /\ b) $;
theorem rexeqa {x: nat} (p a b: wff x): $ p -> (a <-> b) $ > $ E. x (p /\ a) <-> E. x (p /\ b) $;
theorem rexeqd (G: wff) {x: nat} (p a b: wff x): $ G -> (a <-> b) $ > $ G -> (E. x (p /\ a) <-> E. x (p /\ b)) $;
theorem rexeqda (G: wff) {x: nat} (p a b: wff x): $ G /\ p -> (a <-> b) $ > $ G -> (E. x (p /\ a) <-> E. x (p /\ b)) $;
theorem iex {x: nat} (a: wff x): $ a -> E. x a $;
theorem alanex {x: nat} (a b: wff x): $ A. x a /\ E. x b -> E. x (a /\ b) $;
theorem exanal {x: nat} (a b: wff x): $ E. x a /\ A. x b -> E. x (a /\ b) $;
theorem alnex {x: nat} (a: wff x): $ A. x ~a <-> ~E. x a $;
theorem ngen {x: nat} (a: wff x): $ ~a $ > $ ~E. x a $;
theorem alex {x: nat} (a: wff x): $ A. x a <-> ~E. x ~a $;
theorem exnal {x: nat} (a: wff x): $ E. x ~a <-> ~A. x a $;
theorem eal {x: nat} (a: wff x): $ A. x a -> a $;
theorem albi (a: wff) {x: nat}: $ A. x a <-> a $;
theorem exbi (a: wff) {x: nat}: $ E. x a <-> a $;
theorem alan1 (a: wff) {x: nat} (b: wff x): $ A. x (a /\ b) <-> a /\ A. x b $;
theorem alan2 (b: wff) {x: nat} (a: wff x): $ A. x (a /\ b) <-> A. x a /\ b $;
theorem exor {x: nat} (a b: wff x): $ E. x (a \/ b) <-> E. x a \/ E. x b $;
theorem eximd {x: nat} (G: wff) (a b: wff x): $ G -> a -> b $ > $ G -> E. x a -> E. x b $;
theorem excomb {x y: nat} (a: wff x y): $ E. x E. y a <-> E. y E. x a $;
theorem excom {x y: nat} (a: wff x y): $ E. x E. y a -> E. y E. x a $;
theorem nexi {x: nat} (a: wff x): $ ~a $ > $ ~E. x a $;
theorem nexd (G: wff) {x: nat} (a: wff x): $ G -> ~a $ > $ G -> ~E. x a $;
theorem exim1 {x: nat} (a: wff) (b: wff x): $ E. x (a -> b) -> a -> E. x b $;
local def nf {x: nat} (a: wff x): wff = $ A. x (a -> A. x a) $;
prefix nf: $F/$ prec 10;
theorem nfeqd (_G: wff) {x: nat} (_a1 _a2: wff x): $ _G -> (_a1 <-> _a2) $ > $ _G -> ((F/ x _a1) <-> (F/ x _a2)) $;
theorem nfv (a: wff) {x: nat}: $ F/ x a $;
theorem nfi {x: nat} (a: wff x): $ F/ x a $ > $ a -> A. x a $;
theorem nfri {x: nat} (a: wff x): $ a -> A. x a $ > $ F/ x a $;
theorem nfeqi {x: nat} (a b: wff x): $ a <-> b $ > $ (F/ x a) <-> (F/ x b) $;
theorem nfx {x: nat} (a b: wff x): $ a <-> b $ > $ F/ x b $ > $ F/ x a $;
theorem nfal {x y: nat} (a: wff x y): $ F/ x a $ > $ F/ x A. y a $;
theorem nfnot {x: nat} (a: wff x): $ F/ x a $ > $ F/ x ~a $;
theorem nfim {x: nat} (a b: wff x): $ F/ x a $ > $ F/ x b $ > $ F/ x a -> b $;
theorem nfan {x: nat} (a b: wff x): $ F/ x a $ > $ F/ x b $ > $ F/ x a /\ b $;
theorem nfor {x: nat} (a b: wff x): $ F/ x a $ > $ F/ x b $ > $ F/ x a \/ b $;
theorem nfbi {x: nat} (a b: wff x): $ F/ x a $ > $ F/ x b $ > $ F/ x a <-> b $;
theorem nfex1 {x: nat} (a: wff x): $ F/ x E. x a $;
theorem nfex {x y: nat} (a: wff x y): $ F/ x a $ > $ F/ x E. y a $;
theorem nfal1 {x: nat} (a: wff x): $ F/ x A. x a $;
theorem ialdh {x: nat} (a b: wff x): $ F/ x a $ > $ a -> b $ > $ a -> A. x b $;
theorem eexh {x: nat} (a b: wff x): $ F/ x b $ > $ a -> b $ > $ E. x a -> b $;
theorem eexdh {x: nat} (a b c: wff x): $ F/ x a $ > $ F/ x c $ > $ a -> b -> c $ > $ a -> E. x b -> c $;
theorem alimdh {x: nat} (a b c: wff x): $ F/ x a $ > $ a -> b -> c $ > $ a -> A. x b -> A. x c $;
theorem aleqdh {x: nat} (G a b: wff x): $ F/ x G $ > $ G -> (a <-> b) $ > $ G -> (A. x a <-> A. x b) $;
theorem eexd {x: nat} (a: wff) (b: wff x) (c: wff): $ a -> b -> c $ > $ a -> E. x b -> c $;
theorem eexda {x: nat} (a: wff) (b: wff x) (c: wff): $ a /\ b -> c $ > $ a -> E. x b -> c $;
theorem eexb {x: nat} (a: wff x) (b: wff): $ E. x a -> b <-> A. x (a -> b) $;
theorem erexb {x: nat} (a b: wff x) (c: wff): $ E. x (a /\ b) -> c <-> A. x (a -> b -> c) $;
theorem iexeh {x: nat} (a: nat) (b c: wff x): $ F/ x c $ > $ x = a -> (b <-> c) $ > $ c -> E. x b $;
theorem ealeh {x: nat} (a: nat) (b c: wff x): $ F/ x c $ > $ x = a -> (b <-> c) $ > $ A. x b -> c $;
theorem alim1 {x: nat} (a: wff) (b: wff x): $ A. x (a -> b) <-> a -> A. x b $;
theorem ralim1 {x: nat} (a: wff) (p b: wff x): $ A. x (p -> a -> b) <-> a -> A. x (p -> b) $;
theorem ralalcomb {x y: nat} (p: wff x) (a: wff x y): $ A. x (p -> A. y a) <-> A. y A. x (p -> a) $;
theorem ralcomb {x y: nat} (p: wff x) (q: wff y) (a: wff x y): $ A. x (p -> A. y (q -> a)) <-> A. y (q -> A. x (p -> a)) $;
theorem exal {x y: nat} (a: wff x y): $ E. x A. y a -> A. y E. x a $;
theorem exral {x y: nat} (a: wff y) (b: wff x y): $ E. x A. y (a -> b) -> A. y (a -> E. x b) $;
theorem rexal {x y: nat} (a: wff x) (b: wff x y): $ E. x (a /\ A. y b) -> A. y E. x (a /\ b) $;
theorem rexim1 (b: wff) {x: nat} (a c: wff x): $ E. x (a /\ (b -> c)) -> b -> E. x (a /\ c) $;
theorem rexral {x y: nat} (a: wff x) (b: wff y) (c: wff x y): $ E. x (a /\ A. y (b -> c)) -> A. y (b -> E. x (a /\ c)) $;
theorem eqerd (G: wff) (a: nat) (p: wff) {x: nat}: $ G -> a = x -> p $ > $ G -> p $;
theorem eale {x: nat} (a: nat) (b: wff x) (c: wff): $ x = a -> (b <-> c) $ > $ A. x b -> c $;
theorem iexdeh {x: nat} (a: nat) (G b: wff x): $ F/ x G $ > $ G /\ x = a -> b $ > $ G -> E. x b $;
theorem iexde {x: nat} (G: wff) (a: nat) (b: wff x): $ G /\ x = a -> b $ > $ G -> E. x b $;
theorem iexdde {x: nat} (G b: wff) (a: nat) (c: wff x): $ G /\ x = a -> b -> c $ > $ G -> b -> E. x c $;
theorem iexie {x: nat} (a: nat) (b: wff x): $ x = a -> b $ > $ E. x b $;
theorem iexe {x: nat} (a: nat) (b: wff x) (c: wff): $ x = a -> (b <-> c) $ > $ c -> E. x b $;
theorem ealdeh {x: nat} (a: nat) (G b c: wff x): $ F/ x G $ > $ F/ x c $ > $ G /\ x = a -> b -> c $ > $ G -> A. x b -> c $;
theorem ealieh (c: wff) {x: nat} (a: nat) (b: wff x): $ F/ x c $ > $ x = a -> b -> c $ > $ A. x b -> c $;
theorem ealde (c: wff) {x: nat} (G: wff) (a: nat) (b: wff x): $ G /\ x = a -> b -> c $ > $ G -> A. x b -> c $;
theorem ealie (c: wff) {x: nat} (a: nat) (b: wff x): $ x = a -> b -> c $ > $ A. x b -> c $;
theorem exan1 {x: nat} (a: wff) (b: wff x): $ E. x (a /\ b) <-> a /\ E. x b $;
theorem exan2 {x: nat} (a: wff x) (b: wff): $ E. x (a /\ b) <-> E. x a /\ b $;
theorem bian1exi (b: wff) {x: nat} (a c: wff x): $ a <-> b /\ c $ > $ E. x a <-> b /\ E. x c $;
theorem bian2exi (c: wff) {x: nat} (a b: wff x): $ a <-> b /\ c $ > $ E. x a <-> E. x b /\ c $;
theorem bian1exd (G b: wff) {x: nat} (a c: wff x): $ G -> (a <-> b /\ c) $ > $ G -> (E. x a <-> b /\ E. x c) $;
theorem bian2exd (G c: wff) {x: nat} (a b: wff x): $ G -> (a <-> b /\ c) $ > $ G -> (E. x a <-> E. x b /\ c) $;
theorem biexexi {x y: nat} (a b: wff x y): $ a <-> E. y b $ > $ E. x a <-> E. y E. x b $;
theorem biexan1a (c: wff) {x: nat} (a b: wff x): $ c -> (a <-> E. x b) $ > $ a /\ c <-> E. x (b /\ c) $;
theorem biexan2a (a: wff) {x: nat} (b c: wff x): $ a -> (b <-> E. x c) $ > $ a /\ b <-> E. x (a /\ c) $;
theorem biexan1i (c: wff) {x: nat} (a b: wff x): $ a <-> E. x b $ > $ a /\ c <-> E. x (b /\ c) $;
theorem biexan2i (a: wff) {x: nat} (b c: wff x): $ b <-> E. x c $ > $ a /\ b <-> E. x (a /\ c) $;
theorem rexexcomb {x y: nat} (p: wff x) (a: wff x y): $ E. x (p /\ E. y a) <-> E. y E. x (p /\ a) $;
theorem birexexi {x y: nat} (a b: wff x y) (q: wff y): $ a <-> E. y (q /\ b) $ > $ E. x a <-> E. y (q /\ E. x b) $;
theorem biexrexa {x y: nat} (p: wff x) (a b: wff x y): $ p -> (a <-> E. y b) $ > $ E. x (p /\ a) <-> E. y E. x (p /\ b) $;
theorem biexrexi {x y: nat} (p: wff x) (a b: wff x y): $ a <-> E. y b $ > $ E. x (p /\ a) <-> E. y E. x (p /\ b) $;
theorem rexcomb {x y: nat} (p: wff x) (q: wff y) (a: wff x y): $ E. x (p /\ E. y (q /\ a)) <-> E. y (q /\ E. x (p /\ a)) $;
theorem birexan1a (c: wff) {x: nat} (p a b: wff x): $ c -> (a <-> E. x (p /\ b)) $ > $ a /\ c <-> E. x (p /\ (b /\ c)) $;
theorem birexan2a (a: wff) {x: nat} (p b c: wff x): $ a -> (b <-> E. x (p /\ c)) $ > $ a /\ b <-> E. x (p /\ (a /\ c)) $;
theorem birexrexa {x y: nat} (q: wff y) (p: wff x) (a b: wff x y): $ p -> (a <-> E. y (q /\ b)) $ > $ E. x (p /\ a) <-> E. y (q /\ E. x (p /\ b)) $;
theorem birexan1i (c: wff) {x: nat} (p a b: wff x): $ a <-> E. x (p /\ b) $ > $ a /\ c <-> E. x (p /\ (b /\ c)) $;
theorem birexan2i (a: wff) {x: nat} (p b c: wff x): $ b <-> E. x (p /\ c) $ > $ a /\ b <-> E. x (p /\ (a /\ c)) $;
theorem birexrexi {x y: nat} (q: wff y) (p: wff x) (a b: wff x y): $ a <-> E. y (q /\ b) $ > $ E. x (p /\ a) <-> E. y (q /\ E. x (p /\ b)) $;
theorem rexan1 {x: nat} (a: wff) (p b: wff x): $ E. x (p /\ (a /\ b)) <-> a /\ E. x (p /\ b) $;
theorem rexan2 {x: nat} (p a: wff x) (b: wff): $ E. x (p /\ (a /\ b)) <-> E. x (p /\ a) /\ b $;
theorem bian1rexa (b: wff) {x: nat} (p a c: wff x): $ p -> (a <-> b /\ c) $ > $ E. x (p /\ a) <-> b /\ E. x (p /\ c) $;
theorem bian2rexa (c: wff) {x: nat} (p a b: wff x): $ p -> (a <-> b /\ c) $ > $ E. x (p /\ a) <-> E. x (p /\ b) /\ c $;
theorem bian1rexi (b: wff) {x: nat} (p a c: wff x): $ a <-> b /\ c $ > $ E. x (p /\ a) <-> b /\ E. x (p /\ c) $;
theorem bian2rexi (c: wff) {x: nat} (p a b: wff x): $ a <-> b /\ c $ > $ E. x (p /\ a) <-> E. x (p /\ b) /\ c $;
theorem alexan {x: nat} (a b: wff x): $ A. x a -> E. x b -> E. x (a /\ b) $;
theorem exifp (p: wff) {x: nat} (a b: wff x): $ E. x ifp p a b <-> ifp p (E. x a) (E. x b) $;
theorem cbvalh {x y: nat} (p q: wff x y): $ F/ y p $ > $ F/ x q $ > $ x = y -> (p <-> q) $ > $ A. x p <-> A. y q $;
theorem cbval {x y: nat} (p: wff x) (q: wff y): $ x = y -> (p <-> q) $ > $ A. x p <-> A. y q $;
theorem cbvexh {x y: nat} (p q: wff x y): $ F/ y p $ > $ F/ x q $ > $ x = y -> (p <-> q) $ > $ E. x p <-> E. y q $;
theorem cbvex {x y: nat} (p: wff x) (q: wff y): $ x = y -> (p <-> q) $ > $ E. x p <-> E. y q $;

Not sure what to call this, let's say "positive implication". It quantifies both p and q and asserts that p implies q, but not vacuously.

local def pim {x: nat} (p q: wff x): wff = $ E. x p /\ A. x (p -> q) $;
notation pim {x: nat} (p q: wff x): wff = ($P.$:10) x p ($->$:25) q;
theorem pimex {x: nat} (p q: wff x): $ (P. x p -> q) -> E. x p $;
theorem pimal {x: nat} (p q: wff x): $ (P. x p -> q) -> A. x (p -> q) $;
theorem pimex2 {x: nat} (p q: wff x): $ (P. x p -> q) -> E. x q $;
theorem pimex12 {x: nat} (p q: wff x): $ (P. x p -> q) -> E. x (p /\ q) $;
theorem pimeq (p q: wff) {x: nat}: $ (P. x p -> q) -> A. x (p -> q) $;
theorem pimeq1 {x: nat} (p1 p2 q: wff x): $ A. x (p1 <-> p2) -> ((P. x p1 -> q) <-> (P. x p2 -> q)) $;
theorem pimim2 {x: nat} (p q1 q2: wff x): $ A. x (q1 -> q2) -> (P. x p -> q1) -> (P. x p -> q2) $;
theorem pimim2i {x: nat} (p q1 q2: wff x): $ q1 -> q2 $ > $ (P. x p -> q1) -> (P. x p -> q2) $;
theorem pimim2d (G: wff) {x: nat} (p q1 q2: wff x): $ G -> q1 -> q2 $ > $ G -> (P. x p -> q1) -> (P. x p -> q2) $;
theorem pimeq2a {x: nat} (p q1 q2: wff x): $ A. x (p -> (q1 <-> q2)) -> ((P. x p -> q1) <-> (P. x p -> q2)) $;
theorem pimeq2 {x: nat} (p q1 q2: wff x): $ A. x (q1 <-> q2) -> ((P. x p -> q1) <-> (P. x p -> q2)) $;
theorem pimeq1d (G: wff) {x: nat} (p1 p2 q: wff x): $ G -> (p1 <-> p2) $ > $ G -> ((P. x p1 -> q) <-> (P. x p2 -> q)) $;
theorem pimeq2d (G: wff) {x: nat} (p q1 q2: wff x): $ G -> (q1 <-> q2) $ > $ G -> ((P. x p -> q1) <-> (P. x p -> q2)) $;
theorem pimeq1i {x: nat} (p1 p2 q: wff x): $ p1 <-> p2 $ > $ (P. x p1 -> q) <-> (P. x p2 -> q) $;
theorem pimeq2i {x: nat} (p q1 q2: wff x): $ q1 <-> q2 $ > $ (P. x p -> q1) <-> (P. x p -> q2) $;
theorem pimeqd (G: wff) {x: nat} (p1 p2 q1 q2: wff x): $ G -> (p1 <-> p2) $ > $ G -> (q1 <-> q2) $ > $ G -> ((P. x p1 -> q1) <-> (P. x p2 -> q2)) $;
theorem cbvpimh {x y: nat} (p1 p2 q1 q2: wff x y):
  $ F/ y p1 $ >
  $ F/ y q1 $ >
  $ F/ x p2 $ >
  $ F/ x q2 $ >
  $ x = y -> (p1 <-> p2) $ >
  $ x = y -> (q1 <-> q2) $ >
  $ (P. x p1 -> q1) <-> (P. y p2 -> q2) $;
theorem cbvpim {x y: nat} (p1 q1: wff x) (p2 q2: wff y): $ x = y -> (p1 <-> p2) $ > $ x = y -> (q1 <-> q2) $ > $ (P. x p1 -> q1) <-> (P. y p2 -> q2) $;
theorem piman {x: nat} (a b c: wff x): $ (P. x a -> b) /\ (P. x a -> c) -> (P. x a -> b /\ c) $;
theorem impim (b: wff) {x: nat} (a c: wff x): $ (P. x a -> b -> c) -> b -> (P. x a -> c) $;
theorem expim {x y: nat} (p: wff x) (q: wff x y): $ E. y (P. x p -> q) -> (P. x p -> E. y q) $;
theorem rexpim {x y: nat} (a: wff y) (p: wff x) (q: wff x y): $ E. y (a /\ (P. x p -> q)) -> (P. x p -> E. y (a /\ q)) $;
theorem rexpim1 {x y: nat} (a: wff x) (b: wff y) (c: wff x y): $ E. x (a /\ (P. y b -> c)) -> (P. y b -> E. x (a /\ c)) $;
theorem pim2im {x y: nat} (p1 q1: wff x) (p2 q2: wff y): $ A. x (p1 -> (P. y p2 -> q1 -> q2)) -> (P. x p1 -> q1) -> (P. y p2 -> q2) $;
theorem pimtr {x y: nat} (p: wff x) (q a: wff x y) (b: wff y): $ (P. x p -> a) -> A. x (a -> (P. y q -> b)) -> (P. y E. x (p /\ q) -> b) $;

Not equal: a != b means a and b are distinct natural numbers.

def ne (a b: nat): wff = $ ~a = b $;
infixl ne: $!=$ prec 50;
theorem neeqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> (_a1 != _b1 <-> _a2 != _b2) $;
theorem neeq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> (_a1 != _b1 <-> _a2 != _b2) $;
theorem neeq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> (_a1 != b <-> _a2 != b) $;
theorem neeq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> (_a1 != b <-> _a2 != b) $;
theorem neeq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> (a != _b1 <-> a != _b2) $;
theorem neeq2 (a _b1 _b2: nat): $ _b1 = _b2 -> (a != _b1 <-> a != _b2) $;
theorem necom (a b: nat): $ a != b -> b != a $;

Proper substitution. [a / x] p is p, with free occurrences of x in p replaced by a. If we write p(x), this may also be denoted as p(a). (Note that this is only provably equivalent to p(a); [0 / x] (x < x + y) is equivalent but not syntactically identical to 0 < 0 + y, and it requires a rewriting/substitution proof to show.)

def sb (a: nat) {x: nat} (p: wff x): wff = $ A. y (y = a -> A. x (x = y -> p)) $;
notation sb (a: nat) {x: nat} (p: wff x): wff = ($[$:41) a ($/$:0) x ($]$:0) p;
theorem sbq {x: nat} (a: nat) (b: wff x): $ x = a -> (b <-> [a / x] b) $;
theorem sbqcom {x: nat} (a: nat) (b: wff x): $ a = x -> ([a / x] b <-> b) $;
theorem nfsb1 {x: nat} (a: nat) (b: wff x): $ F/ x [a / x] b $;
theorem nfsb {x y: nat} (a: nat y) (b: wff x y): $ F/ x b $ > $ F/ x [a / y] b $;
theorem sbeq1 {x: nat} (a b: nat x) (c: wff x): $ a = b -> ([a / x] c <-> [b / x] c) $;
theorem sbeq1d {x: nat} (G: wff x) (a b: nat x) (c: wff x): $ G -> a = b $ > $ G -> ([a / x] c <-> [b / x] c) $;
theorem sbeqd (_G: wff) {x: nat} (_a1 _a2: nat x) (_p1 _p2: wff x): $ _G -> _a1 = _a2 $ > $ _G -> (_p1 <-> _p2) $ > $ _G -> ([_a1 / x] _p1 <-> [_a2 / x] _p2) $;
theorem sbeq2d (_G: wff) {x: nat} (a: nat x) (_p1 _p2: wff x): $ _G -> (_p1 <-> _p2) $ > $ _G -> ([a / x] _p1 <-> [a / x] _p2) $;
theorem sbeq2i {x: nat} (a: nat x) (b c: wff x): $ b <-> c $ > $ [a / x] b <-> [a / x] c $;
theorem sbeht {x: nat} (a: nat) (b c: wff x): $ F/ x c $ > $ A. x (x = a -> (b <-> c)) -> ([a / x] b <-> c) $;
theorem sbeh {x: nat} (a: nat) (b c: wff x): $ F/ x c $ > $ x = a -> (b <-> c) $ > $ [a / x] b <-> c $;
theorem sbet {x: nat} (a: nat) (b: wff x) (c: wff): $ A. x (x = a -> (b <-> c)) -> ([a / x] b <-> c) $;
theorem sbe {x: nat} (a: nat) (b: wff x) (c: wff): $ x = a -> (b <-> c) $ > $ [a / x] b <-> c $;
theorem sbed (G: wff) {x: nat} (a: nat) (b: wff x) (c: wff): $ G /\ x = a -> (b <-> c) $ > $ G -> ([a / x] b <-> c) $;
theorem dfsb2 {x: nat} (a: nat) (b: wff x): $ [a / x] b <-> A. x (x = a -> b) $;
theorem dfsb3 {x: nat} (a: nat) (b: wff x): $ [a / x] b <-> E. x (x = a /\ b) $;
theorem sbco {x y: nat} (a: nat x) (b: wff x): $ [a / y] [y / x] b <-> [a / x] b $;
theorem sbid {x: nat} (a: wff x): $ [x / x] a <-> a $;
theorem sbcom (a b: nat) {x y: nat} (p: wff x y): $ [a / x] [b / y] p <-> [b / y] [a / x] p $;
theorem sbth {x: nat} (a: nat x) (p: wff x): $ p $ > $ [a / x] p $;
theorem sbthd (G: wff) (a: nat) {x: nat} (p: wff x): $ G /\ x = a -> p $ > $ G -> [a / x] p $;
theorem sbeth (a: nat) (q: wff) {x: nat} (p: wff x): $ p $ > $ x = a -> (p <-> q) $ > $ q $;
theorem sbethh (a: nat) {x: nat} (p q: wff x): $ F/ x q $ > $ p $ > $ x = a -> (p <-> q) $ > $ q $;
theorem cbvsbh {x y: nat} (a: nat) (p q: wff x y): $ F/ y p $ > $ F/ x q $ > $ x = y -> (p <-> q) $ > $ [a / x] p <-> [a / y] q $;
theorem cbvsb {x y: nat} (a: nat) (p: wff x) (q: wff y): $ x = y -> (p <-> q) $ > $ [a / x] p <-> [a / y] q $;
theorem aleqe {x: nat} (a: nat) (p: wff x) (q: wff): $ x = a -> (p <-> q) $ > $ A. x (x = a -> p) <-> q $;
theorem aleqed (G: wff) {x: nat} (a: nat) (p: wff x) (q: wff): $ G /\ x = a -> (p <-> q) $ > $ G -> (A. x (x = a -> p) <-> q) $;
theorem exeqe {x: nat} (a: nat) (p: wff x) (q: wff): $ x = a -> (p <-> q) $ > $ E. x (x = a /\ p) <-> q $;
theorem exeqed (G: wff) {x: nat} (a: nat) (p: wff x) (q: wff): $ G /\ x = a -> (p <-> q) $ > $ G -> (E. x (x = a /\ p) <-> q) $;
theorem pimeqed (G: wff) {x: nat} (a: nat) (p: wff x) (q: wff): $ G /\ x = a -> (p <-> q) $ > $ G -> ((P. x x = a -> p) <-> q) $;
theorem pimeqe {x: nat} (a: nat) (p: wff x) (q: wff): $ x = a -> (p <-> q) $ > $ (P. x x = a -> p) <-> q $;
theorem cbvals {x y: nat} (p: wff x): $ A. x p <-> A. y [y / x] p $;
theorem cbvexs {x y: nat} (p: wff x): $ E. x p <-> E. y [y / x] p $;
theorem cbvald {x y: nat} (G: wff) (p: wff x) (q: wff y): $ G /\ x = y -> (p <-> q) $ > $ G -> (A. x p <-> A. y q) $;
theorem cbvexd {x y: nat} (G: wff) (p: wff x) (q: wff y): $ G /\ x = y -> (p <-> q) $ > $ G -> (E. x p <-> E. y q) $;
theorem pimexeqed (G: wff) {x y: nat} (a: nat) (p: wff x y) (q: wff x) (p2 q2: wff y):
  $ G /\ x = a -> (p <-> p2) $ >
  $ G /\ x = a -> (q <-> q2) $ >
  $ G -> ((P. x E. y (x = a /\ p) -> q) <-> (P. y p2 -> q2)) $;

The sort of sets of natural numbers. Because we are working in Peano Arithmetic, we cannot quantify over variables of this type, and these should be thought of only as sugar for formulas with one free variable. This is a conservative extension of PA.

strict sort set;

A "class abstraction" {x | p(x)} is the set of natural numbers x such that p(x) holds.

term ab {x: nat} (p: wff x): set;
notation ab {x: nat} (p: wff x): set = (${$:max) x ($|$:0) p ($}$:0);

Given a natural number a and a set A, a e. A (read e. as epsilon) means a is in the set A.

term el (a: nat) (A: set): wff;
infixl el: $e.$ prec 50;

a is in {x | p(x)} iff p(a) holds.

axiom elab (a: nat) {x: nat} (p: wff x): $ a e. {x | p} <-> [a / x] p $;

Elementhood respects equality. This is a theorem for most definitions but has to be axiomatized for primitive term constructors like e. This is Axiom 8 of predicate logic (which has an instance for every primitive predicate in the language).

axiom ax_8 (a b: nat) (A: set): $ a = b -> a e. A -> b e. A $;

A == B is equality for sets. Two sets are equal if they have the same elements.

def eqs (A B: set): wff = $ A. x (x e. A <-> x e. B) $;
infixl eqs: $==$ prec 50;
theorem eqsid (A: set): $ A == A $;
theorem eqscom (A B: set): $ A == B -> B == A $;
theorem eqscomb (A B: set): $ A == B <-> B == A $;
theorem eqstr (A B C: set): $ A == B -> B == C -> A == C $;
theorem eqstr2 (A B C: set): $ A == B -> B == C -> C == A $;
theorem eqstr3 (A B C: set): $ B == A -> B == C -> A == C $;
theorem eqstr4 (A B C: set): $ A == B -> C == B -> A == C $;
theorem eqstr3d (A B C: set) (G: wff): $ G -> B == A $ > $ G -> B == C $ > $ G -> A == C $;
theorem eqsidd (G: wff) (A: set): $ G -> A == A $;
theorem eqscomd (A B: set) (G: wff): $ G -> A == B $ > $ G -> B == A $;
theorem eqstrd (A B C: set) (G: wff): $ G -> A == B $ > $ G -> B == C $ > $ G -> A == C $;
theorem eqstr4d (A B C: set) (G: wff): $ G -> A == B $ > $ G -> C == B $ > $ G -> A == C $;
theorem syl5eqs (A B C: set) (G: wff): $ A == B $ > $ G -> B == C $ > $ G -> A == C $;
theorem syl5eqsr (A B C: set) (G: wff): $ B == A $ > $ G -> B == C $ > $ G -> A == C $;
theorem syl6eqs (A B C: set) (G: wff): $ B == C $ > $ G -> A == B $ > $ G -> A == C $;
theorem syl6eqsr (A B C: set) (G: wff): $ C == B $ > $ G -> A == B $ > $ G -> A == C $;
theorem eqstr3g (A B C D: set) (G: wff): $ A == C $ > $ B == D $ > $ G -> A == B $ > $ G -> C == D $;
theorem eqstr4g (A B C D: set) (G: wff): $ C == A $ > $ D == B $ > $ G -> A == B $ > $ G -> C == D $;
theorem eleq1 (A: set) (a b: nat): $ a = b -> (a e. A <-> b e. A) $;
theorem eleq2 (A B: set) (a: nat): $ A == B -> (a e. A <-> a e. B) $;
theorem eleq1d (A: set) (G: wff) (a b: nat): $ G -> a = b $ > $ G -> (a e. A <-> b e. A) $;
theorem eleq2d (A B: set) (G: wff) (a: nat): $ G -> A == B $ > $ G -> (a e. A <-> a e. B) $;
theorem eleqd (G: wff) (a b: nat) (A B: set): $ G -> a = b $ > $ G -> A == B $ > $ G -> (a e. A <-> b e. B) $;
theorem eqseqd (_G: wff) (_A1 _A2 _B1 _B2: set): $ _G -> _A1 == _A2 $ > $ _G -> _B1 == _B2 $ > $ _G -> (_A1 == _B1 <-> _A2 == _B2) $;
theorem eqseq (_A1 _A2 _B1 _B2: set): $ _A1 == _A2 -> _B1 == _B2 -> (_A1 == _B1 <-> _A2 == _B2) $;
theorem eqseq1d (_G: wff) (_A1 _A2 B: set): $ _G -> _A1 == _A2 $ > $ _G -> (_A1 == B <-> _A2 == B) $;
theorem eqseq1 (_A1 _A2 B: set): $ _A1 == _A2 -> (_A1 == B <-> _A2 == B) $;
theorem eqseq2d (_G: wff) (A _B1 _B2: set): $ _G -> _B1 == _B2 $ > $ _G -> (A == _B1 <-> A == _B2) $;
theorem eqseq2 (A _B1 _B2: set): $ _B1 == _B2 -> (A == _B1 <-> A == _B2) $;
theorem abeq {x: nat} (p q: wff x): $ A. x (p <-> q) -> {x | p} == {x | q} $;
theorem abeqd (G: wff) {x: nat} (p q: wff x): $ G -> (p <-> q) $ > $ G -> {x | p} == {x | q} $;
theorem abeqi {x: nat} (p q: wff x): $ p <-> q $ > $ {x | p} == {x | q} $;
theorem eqri (A B: set) {x: nat}: $ x e. A <-> x e. B $ > $ A == B $;
theorem eqrd (A B: set) (G: wff) {x: nat}: $ G -> (x e. A <-> x e. B) $ > $ G -> A == B $;
theorem cbvabh {x y: nat} (p q: wff x y): $ F/ y p $ > $ F/ x q $ > $ x = y -> (p <-> q) $ > $ {x | p} == {y | q} $;
theorem cbvab {x y: nat} (p: wff x) (q: wff y): $ x = y -> (p <-> q) $ > $ {x | p} == {y | q} $;
theorem cbvabs {x y: nat} (p: wff x): $ {x | p} == {y | [y / x] p} $;
theorem cbvabd {x y: nat} (G: wff) (p: wff x) (q: wff y): $ G /\ x = y -> (p <-> q) $ > $ G -> {x | p} == {y | q} $;
theorem elab2 {x: nat} (a: nat x) (p: wff x): $ a e. {x | p} <-> [a / x] p $;
theorem elabe {x: nat} (a: nat) (p: wff x) (q: wff): $ x = a -> (p <-> q) $ > $ a e. {x | p} <-> q $;
theorem elabed (G: wff) {x: nat} (a: nat) (p: wff x) (q: wff): $ G /\ x = a -> (p <-> q) $ > $ G -> (a e. {x | p} <-> q) $;
theorem ssabed (G: wff) {x: nat} (a: nat) (p: wff x) (q: wff): $ G /\ x = a -> p -> q $ > $ G -> a e. {x | p} -> q $;
theorem eelabd (G: wff) {x: nat} (a: nat x) (p: wff x) (q: wff): $ G -> p -> q $ > $ G -> a e. {x | p} -> q $;
theorem ssabeled (A: set) (G: wff) {x: nat} (a: nat) (p: wff x) (q: wff): $ G /\ x = a -> p -> q /\ x e. A $ > $ G -> a e. {x | p} -> q /\ a e. A $;
theorem abid {x: nat} (p: wff x): $ x e. {x | p} <-> p $;
theorem abid2 (A: set) {x: nat}: $ {x | x e. A} == A $;

A C_ B means A is a subset of B.

def subset (A B: set): wff = $ A. x (x e. A -> x e. B) $;
infixl subset: $C_$ prec 50;
theorem sseqd (_G: wff) (_A1 _A2 _B1 _B2: set): $ _G -> _A1 == _A2 $ > $ _G -> _B1 == _B2 $ > $ _G -> (_A1 C_ _B1 <-> _A2 C_ _B2) $;
theorem sseq (_A1 _A2 _B1 _B2: set): $ _A1 == _A2 -> _B1 == _B2 -> (_A1 C_ _B1 <-> _A2 C_ _B2) $;
theorem sseq1d (_G: wff) (_A1 _A2 B: set): $ _G -> _A1 == _A2 $ > $ _G -> (_A1 C_ B <-> _A2 C_ B) $;
theorem sseq1 (_A1 _A2 B: set): $ _A1 == _A2 -> (_A1 C_ B <-> _A2 C_ B) $;
theorem sseq2d (_G: wff) (A _B1 _B2: set): $ _G -> _B1 == _B2 $ > $ _G -> (A C_ _B1 <-> A C_ _B2) $;
theorem sseq2 (A _B1 _B2: set): $ _B1 == _B2 -> (A C_ _B1 <-> A C_ _B2) $;
theorem dfss (A B: set) {x: nat}: $ A C_ B <-> A. x (x e. A -> x e. B) $;
theorem ssel (A B: set) (a: nat): $ A C_ B -> a e. A -> a e. B $;
theorem sseld (A B: set) (G: wff) (a: nat): $ G -> A C_ B $ > $ G -> a e. A $ > $ G -> a e. B $;
theorem ssid (A: set): $ A C_ A $;
theorem sstr (A B C: set): $ A C_ B -> B C_ C -> A C_ C $;
theorem eqss (A B: set): $ A == B -> A C_ B $;
theorem eqssr (A B: set): $ A == B -> B C_ A $;
theorem ssasym (A B: set): $ A C_ B -> B C_ A -> A == B $;
theorem ssasymd (A B: set) (G: wff): $ G -> A C_ B $ > $ G -> B C_ A $ > $ G -> A == B $;
theorem ssasymb (A B: set): $ A == B <-> A C_ B /\ B C_ A $;

A i^i B is the intersection of sets A and B.

def Inter (A B: set): set = $ {x | x e. A /\ x e. B} $;
infixl Inter: $i^i$ prec 70;
theorem ineqd (_G: wff) (_A1 _A2 _B1 _B2: set): $ _G -> _A1 == _A2 $ > $ _G -> _B1 == _B2 $ > $ _G -> _A1 i^i _B1 == _A2 i^i _B2 $;
theorem ineq (_A1 _A2 _B1 _B2: set): $ _A1 == _A2 -> _B1 == _B2 -> _A1 i^i _B1 == _A2 i^i _B2 $;
theorem ineq1d (_G: wff) (_A1 _A2 B: set): $ _G -> _A1 == _A2 $ > $ _G -> _A1 i^i B == _A2 i^i B $;
theorem ineq1 (_A1 _A2 B: set): $ _A1 == _A2 -> _A1 i^i B == _A2 i^i B $;
theorem ineq2d (_G: wff) (A _B1 _B2: set): $ _G -> _B1 == _B2 $ > $ _G -> A i^i _B1 == A i^i _B2 $;
theorem ineq2 (A _B1 _B2: set): $ _B1 == _B2 -> A i^i _B1 == A i^i _B2 $;
theorem elin (A B: set) (a: nat): $ a e. A i^i B <-> a e. A /\ a e. B $;
theorem incom (A B: set): $ A i^i B == B i^i A $;
theorem inass (A B C: set): $ A i^i B i^i C == A i^i (B i^i C) $;
theorem inss1 (A B: set): $ A i^i B C_ A $;
theorem inss2 (A B: set): $ A i^i B C_ B $;
theorem ssin (A B C: set): $ A C_ B i^i C <-> A C_ B /\ A C_ C $;
theorem ssin1 (A B C: set): $ A C_ B -> A i^i C C_ B i^i C $;
theorem ssin2 (A B C: set): $ B C_ C -> A i^i B C_ A i^i C $;
theorem eqin1 (A B: set): $ A C_ B <-> A i^i B == A $;
theorem eqin2 (A B: set): $ A C_ B <-> B i^i A == A $;

A u. B is the union of sets A and B.

def Union (A B: set): set = $ {x | x e. A \/ x e. B} $;
infixl Union: $u.$ prec 64;
theorem uneqd (_G: wff) (_A1 _A2 _B1 _B2: set): $ _G -> _A1 == _A2 $ > $ _G -> _B1 == _B2 $ > $ _G -> _A1 u. _B1 == _A2 u. _B2 $;
theorem uneq (_A1 _A2 _B1 _B2: set): $ _A1 == _A2 -> _B1 == _B2 -> _A1 u. _B1 == _A2 u. _B2 $;
theorem uneq1d (_G: wff) (_A1 _A2 B: set): $ _G -> _A1 == _A2 $ > $ _G -> _A1 u. B == _A2 u. B $;
theorem uneq1 (_A1 _A2 B: set): $ _A1 == _A2 -> _A1 u. B == _A2 u. B $;
theorem uneq2d (_G: wff) (A _B1 _B2: set): $ _G -> _B1 == _B2 $ > $ _G -> A u. _B1 == A u. _B2 $;
theorem uneq2 (A _B1 _B2: set): $ _B1 == _B2 -> A u. _B1 == A u. _B2 $;
theorem elun (A B: set) (a: nat): $ a e. A u. B <-> a e. A \/ a e. B $;
theorem uncom (A B: set): $ A u. B == B u. A $;
theorem unass (A B C: set): $ A u. B u. C == A u. (B u. C) $;
theorem indi (A B C: set): $ A i^i (B u. C) == A i^i B u. A i^i C $;
theorem indir (A B C: set): $ (A u. B) i^i C == A i^i C u. B i^i C $;
theorem inindi (A B C: set): $ A i^i (B i^i C) == A i^i B i^i (A i^i C) $;
theorem undi (A B C: set): $ A u. B i^i C == (A u. B) i^i (A u. C) $;
theorem undir (A B C: set): $ A i^i B u. C == (A u. C) i^i (B u. C) $;
theorem ssun1 (A B: set): $ A C_ A u. B $;
theorem ssun2 (A B: set): $ B C_ A u. B $;
theorem elun1 (A B: set) (a: nat): $ a e. A -> a e. A u. B $;
theorem elun2 (A B: set) (a: nat): $ a e. B -> a e. A u. B $;
theorem unss (A B C: set): $ A u. B C_ C <-> A C_ C /\ B C_ C $;
theorem unss1 (A B C: set): $ A C_ B -> A u. C C_ B u. C $;
theorem unss2 (A B C: set): $ B C_ C -> A u. B C_ A u. C $;
theorem equn1 (A B: set): $ A C_ B <-> A u. B == B $;
theorem equn2 (A B: set): $ A C_ B <-> B u. A == B $;

Compl A is the complement of A, the set of all elements not in A.

def Compl (A: set): set = $ {x | ~x e. A} $;
theorem cpleqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> Compl _A1 == Compl _A2 $;
theorem cpleq (_A1 _A2: set): $ _A1 == _A2 -> Compl _A1 == Compl _A2 $;
theorem elcpl (A: set) (a: nat): $ a e. Compl A <-> ~a e. A $;
theorem sscpl (A B: set): $ B C_ A <-> Compl A C_ Compl B $;
theorem cplcpl (A: set): $ Compl (Compl A) == A $;
theorem cplinj (A B: set): $ A == B <-> Compl A == Compl B $;
theorem cplin (A B: set): $ Compl (A i^i B) == Compl A u. Compl B $;
theorem cplun (A B: set): $ Compl (A u. B) == Compl A i^i Compl B $;

Univ, or _V is the set of all natural numbers.

def Univ: set = $ {x | T.} $;
prefix Univ: $_V$ prec max;
theorem elv (a: nat): $ a e. _V $;
theorem inv1 (A: set): $ _V i^i A == A $;
theorem inv2 (A: set): $ A i^i _V == A $;
theorem uncpl2 (A: set): $ A u. Compl A == _V $;
theorem uncpl1 (A: set): $ Compl A u. A == _V $;
theorem ssv2 (A: set): $ A C_ _V $;
theorem ssv1 (A: set): $ _V C_ A <-> A == _V $;
local def nfs {x: nat} (A: set x): wff = $ A. y (F/ x y e. A) $;
prefix nfs: $FS/$ prec 10;
local def nfn {x: nat} (a: nat x): wff = $ A. y (F/ x y = a) $;
prefix nfn: $FN/$ prec 10;
theorem nfsbid (G: wff) {x: nat} (A B: set x): $ G -> A == B $ > $ G -> ((FS/ x A) <-> (FS/ x B)) $;
theorem nfnbid (G: wff) {x: nat} (a b: nat x): $ G -> a = b $ > $ G -> ((FN/ x a) <-> (FN/ x b)) $;
theorem nfsv (A: set) {x: nat}: $ FS/ x A $;
theorem nfnv (a: nat) {x: nat}: $ FN/ x a $;
theorem nfsri {x y: nat} (A: set x): $ F/ x y e. A $ > $ FS/ x A $;
theorem nfnri {x y: nat} (a: nat x): $ F/ x y = a $ > $ FN/ x a $;
theorem nfel2 {x: nat} (a: nat) (A: set x): $ FS/ x A $ > $ F/ x a e. A $;
theorem nfsx {x: nat} (A B: set x): $ A == B $ > $ FS/ x B $ > $ FS/ x A $;
theorem nf_eq {x: nat} (a b: nat x): $ FN/ x a $ > $ FN/ x b $ > $ F/ x a = b $;
theorem nfeq2 (a: nat) {x: nat} (b: nat x): $ FN/ x b $ > $ F/ x a = b $;
theorem nfsb1h {x: nat} (a: nat x) (b: wff x): $ FN/ x a $ > $ F/ x [a / x] b $;
theorem nfsbh {x y: nat} (a: nat x y) (b: wff x y): $ FN/ x a $ > $ F/ x b $ > $ F/ x [a / y] b $;
theorem nfel {x: nat} (a: nat x) (A: set x): $ FN/ x a $ > $ FS/ x A $ > $ F/ x a e. A $;
theorem nfab1 {x: nat} (p: wff x): $ FS/ x {x | p} $;
theorem nfab {x y: nat} (p: wff x y): $ F/ x p $ > $ FS/ x {y | p} $;
theorem nfeqs {x: nat} (A B: set x): $ FS/ x A $ > $ FS/ x B $ > $ F/ x A == B $;
theorem nfnx {x: nat} (a b: nat x): $ a = b $ > $ FN/ x b $ > $ FN/ x a $;
theorem nfin {x: nat} (A B: set x): $ FS/ x A $ > $ FS/ x B $ > $ FS/ x A i^i B $;
theorem nfss {x: nat} (A B: set x): $ FS/ x A $ > $ FS/ x B $ > $ F/ x A C_ B $;
theorem abeqb {x: nat} (p q: wff x): $ A. x (p <-> q) <-> {x | p} == {x | q} $;
theorem eqab2d (A: set) (G: wff) {x: nat} (p: wff x): $ G -> (x e. A <-> p) $ > $ G -> A == {x | p} $;
theorem eqab2i (A: set) {x: nat} (p: wff x): $ x e. A <-> p $ > $ A == {x | p} $;
theorem eqab1d (A: set) (G: wff) {x: nat} (p: wff x): $ G -> (p <-> x e. A) $ > $ G -> {x | p} == A $;
theorem eqab1i (A: set) {x: nat} (p: wff x): $ p <-> x e. A $ > $ {x | p} == A $;
theorem ssab {x: nat} (p q: wff x): $ A. x (p -> q) <-> {x | p} C_ {x | q} $;
theorem ssabi {x: nat} (p q: wff x): $ p -> q $ > $ {x | p} C_ {x | q} $;
theorem ssabd (G: wff) {x: nat} (p q: wff x): $ G -> p -> q $ > $ G -> {x | p} C_ {x | q} $;
theorem ssab1 (A: set) {x: nat} (p: wff x): $ A. x (p -> x e. A) <-> {x | p} C_ A $;
theorem ssab2 (A: set) {x: nat} (p: wff x): $ A. x (x e. A -> p) <-> A C_ {x | p} $;
theorem elabed1 (A: set) (G P: wff) (a: nat) {x: nat} (p: wff x): $ G /\ x = a -> (a e. A <-> p) -> P $ > $ G -> A == {x | p} -> P $;
theorem elabed2 (A: set) (G: wff) (a: nat) (q: wff) {x: nat} (p: wff x): $ G /\ x = a -> (p <-> q) $ > $ G -> A == {x | p} -> (a e. A <-> q) $;

Substitution for sets. S[a / x] A is the set A when free variable x is evaluated at a.

def sbs (a: nat) {x: nat} (A: set x): set = $ {y | [a / x] y e. A} $;
notation sbs (a: nat) {x: nat} (A: set x): set = ($S[$:99) a ($/$:0) x ($]$:0) A;
theorem elsbs {x: nat} (a: nat x) (b: nat) (A: set x): $ b e. S[a / x] A <-> [a / x] b e. A $;
theorem sbsq {x: nat} (a: nat) (A: set x): $ x = a -> A == S[a / x] A $;
theorem nfsbs1h {x: nat} (a: nat x) (A: set x): $ FN/ x a $ > $ FS/ x S[a / x] A $;
theorem nfsbs1 {x: nat} (a: nat) (A: set x): $ FS/ x S[a / x] A $;
theorem nfsbsh {x y: nat} (a: nat x) (A: set x y): $ FN/ x a $ > $ FS/ x A $ > $ FS/ x S[a / y] A $;
theorem nfsbs {x y: nat} (a: nat) (A: set x y): $ FS/ x A $ > $ FS/ x S[a / y] A $;
theorem sbseq1d {x: nat} (G: wff) (a b: nat) (A: set x): $ G -> a = b $ > $ G -> S[a / x] A == S[b / x] A $;
theorem sbseq2d {x: nat} (G: wff) (a: nat x) (A B: set x): $ G -> A == B $ > $ G -> S[a / x] A == S[a / x] B $;
theorem sbseqd (G: wff) {x: nat} (a b: nat) (A B: set x): $ G -> a = b $ > $ G -> A == B $ > $ G -> S[a / x] A == S[b / x] B $;
theorem sbseht {x: nat} (a: nat) (A B: set x): $ FS/ x B $ > $ A. x (x = a -> A == B) -> S[a / x] A == B $;
theorem sbsco {x y: nat} (a: nat) (A: set x): $ S[a / y] S[y / x] A == S[a / x] A $;
theorem sbseh {x: nat} (a: nat) (A B: set x): $ FS/ x B $ > $ x = a -> A == B $ > $ S[a / x] A == B $;
theorem sbset {x: nat} (a: nat) (A: set x) (B: set): $ A. x (x = a -> A == B) -> S[a / x] A == B $;
theorem sbse {x: nat} (a: nat) (A: set x) (B: set): $ x = a -> A == B $ > $ S[a / x] A == B $;
theorem sbsed (G: wff) {x: nat} (a: nat) (A: set x) (B: set): $ G /\ x = a -> A == B $ > $ G -> S[a / x] A == B $;
theorem sbsid {x: nat} (A: set x): $ S[x / x] A == A $;
theorem nfslem {x y: nat} (A: set y) (a: nat x) (B: set x): $ y = a -> A == B $ > $ FN/ x a $ > $ FS/ x B $;
local def If (p: wff) (A B: set): set = $ {n | ifp p (n e. A) (n e. B)} $;
theorem Ifeqd (_G _p1 _p2: wff) (_A1 _A2 _B1 _B2: set):
  $ _G -> (_p1 <-> _p2) $ >
  $ _G -> _A1 == _A2 $ >
  $ _G -> _B1 == _B2 $ >
  $ _G -> If _p1 _A1 _B1 == If _p2 _A2 _B2 $;
theorem Ifeq (_p1 _p2: wff) (_A1 _A2 _B1 _B2: set): $ (_p1 <-> _p2) -> _A1 == _A2 -> _B1 == _B2 -> If _p1 _A1 _B1 == If _p2 _A2 _B2 $;
theorem Ifeq1d (_G _p1 _p2: wff) (A B: set): $ _G -> (_p1 <-> _p2) $ > $ _G -> If _p1 A B == If _p2 A B $;
theorem Ifeq1 (_p1 _p2: wff) (A B: set): $ (_p1 <-> _p2) -> If _p1 A B == If _p2 A B $;
theorem Ifeq2d (_G p: wff) (_A1 _A2 B: set): $ _G -> _A1 == _A2 $ > $ _G -> If p _A1 B == If p _A2 B $;
theorem Ifeq2 (p: wff) (_A1 _A2 B: set): $ _A1 == _A2 -> If p _A1 B == If p _A2 B $;
theorem Ifeq3d (_G p: wff) (A _B1 _B2: set): $ _G -> _B1 == _B2 $ > $ _G -> If p A _B1 == If p A _B2 $;
theorem Ifeq3 (p: wff) (A _B1 _B2: set): $ _B1 == _B2 -> If p A _B1 == If p A _B2 $;
theorem Ifpos (A B: set) (p: wff): $ p -> If p A B == A $;
theorem Ifneg (A B: set) (p: wff): $ ~p -> If p A B == B $;
theorem Ifid (A: set) (p: wff): $ If p A A == A $;
theorem Ifeq2a (A B C: set) (p: wff): $ (p -> A == B) -> If p A C == If p B C $;
theorem Ifeq3a (A B C: set) (p: wff): $ (~p -> B == C) -> If p A B == If p A C $;
local def eu {x: nat} (p: wff x): wff = $ E. y A. x (p <-> x = y) $;
theorem eueqd (_G: wff) {x: nat} (_p1 _p2: wff x): $ _G -> (_p1 <-> _p2) $ > $ _G -> (eu x _p1 <-> eu x _p2) $;

0 is a natural number.

term d0: nat;
prefix d0: $0$ prec max;

The successor operation: suc n is a natural number when n is.

term suc (n: nat): nat;
def d1: nat = $ suc 0 $;
prefix d1: $1$ prec max;
def d2: nat = $ suc 1 $;
prefix d2: $2$ prec max;
def d3: nat = $ suc 2 $;
prefix d3: $3$ prec max;
def d4: nat = $ suc 3 $;
prefix d4: $4$ prec max;
def d5: nat = $ suc 4 $;
prefix d5: $5$ prec max;
def d6: nat = $ suc 5 $;
prefix d6: $6$ prec max;
def d7: nat = $ suc 6 $;
prefix d7: $7$ prec max;
def d8: nat = $ suc 7 $;
prefix d8: $8$ prec max;
def d9: nat = $ suc 8 $;
prefix d9: $9$ prec max;
def d10: nat = $ suc 9 $;
prefix d10: $10$ prec max;

Zero is not a successor. Axiom 1 of Peano Arithmetic.

axiom peano1 (a: nat): $ suc a != 0 $;

The successor function is injective. Axiom 2 of Peano Arithmetic.

axiom peano2 (a b: nat): $ suc a = suc b <-> a = b $;

The induction axiom of Peano Arithmetic. If p(0) is true, and p(x) implies p(suc x) for all x, then p(x) is true for all x.

axiom peano5 {x: nat} (p: wff x): $ [0 / x] p -> A. x (p -> [suc x / x] p) -> A. x p $;
theorem d1ne0: $ 1 != 0 $;
theorem d2ne0: $ 2 != 0 $;
theorem suceq (a b: nat): $ a = b -> suc a = suc b $;
theorem suceqd (G: wff) (a b: nat): $ G -> a = b $ > $ G -> suc a = suc b $;
theorem ind {x y: nat} (a: nat y) (px: wff x) (p0 pa py ps: wff y):
  $ x = a -> (px <-> pa) $ >
  $ x = 0 -> (px <-> p0) $ >
  $ x = y -> (px <-> py) $ >
  $ x = suc y -> (px <-> ps) $ >
  $ p0 $ >
  $ py -> ps $ >
  $ pa $;
theorem indd (G: wff) {x y: nat} (a: nat y) (px: wff x) (p0 pa py ps: wff y):
  $ x = a -> (px <-> pa) $ >
  $ x = 0 -> (px <-> p0) $ >
  $ x = y -> (px <-> py) $ >
  $ x = suc y -> (px <-> ps) $ >
  $ G -> p0 $ >
  $ G /\ py -> ps $ >
  $ G -> pa $;
theorem sucne0 (a b: nat): $ a = suc b -> a != 0 $;
theorem exsuc {x: nat} (a: nat): $ a != 0 <-> E. x a = suc x $;
theorem eqsucext (a b: nat) {x: nat}: $ a = b <-> A. x (a = suc x <-> b = suc x) $;

The definite description operator: the A is the value a such that A = {a}, if there is such a value, otherwise 0.

term the (A: set): nat;

The positive case of definite description: A = {a} then the A = a.

axiom theid {x: nat} (A: set) (a: nat): $ A == {x | x = a} -> the A = a $;

The negative case of definite description: if A is not a singleton then the A = 0.

axiom the0 {x y: nat} (A: set): $ ~E. y A == {x | x = y} -> the A = 0 $;
theorem theeqd (G: wff) (A B: set): $ G -> A == B $ > $ G -> the A = the B $;
theorem theeq (A B: set): $ A == B -> the A = the B $;
theorem eqthed (A: set) (G: wff) (a: nat) {x: nat}: $ G -> (x e. A <-> x = a) $ > $ G -> the A = a $;
theorem eqtheabd (G: wff) (a: nat) {x: nat} (p: wff x): $ G -> (p <-> x = a) $ > $ G -> the {x | p} = a $;
theorem eqthe0d (A: set) (G: wff) {x: nat}: $ G -> x e. A -> x = 0 $ > $ G -> the A = 0 $;
theorem eqthe0abd (G: wff) {x: nat} (p: wff x): $ G -> p -> x = 0 $ > $ G -> the {x | p} = 0 $;
theorem eqtheb (A: set) (a: nat) {x y: nat}: $ a = the A <-> A == {x | x = a} \/ ~E. y A == {x | x = y} /\ a = 0 $;
theorem nfthe {x: nat} (A: set x): $ FS/ x A $ > $ FN/ x the A $;

Variation on "the" that returns an optional value. theo A = suc a if A = {a} and theo A = 0 otherwise

local def theo (A: set): nat = $ the {x | E. y (x = suc y /\ y e. A)} $;
theorem theoeqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> theo _A1 = theo _A2 $;
theorem theoeq (_A1 _A2: set): $ _A1 == _A2 -> theo _A1 = theo _A2 $;
theorem theoid1 {x: nat} (A: set) (a: nat): $ A == {x | x = a} -> theo A = suc a $;
theorem theo01 {y x: nat} (A: set): $ ~E. y A == {x | x = y} -> theo A = 0 $;
theorem theoid {x: nat} (A: set) (a: nat): $ A == {x | x = a} <-> theo A = suc a $;
theorem theo0 {x y: nat} (A: set): $ ~E. y A == {x | x = y} <-> theo A = 0 $;
local def subsn (A: set): wff = $ A. x A. y (x e. A -> y e. A -> x = y) $;
theorem subsneqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> (subsn _A1 <-> subsn _A2) $;
theorem subsneq (_A1 _A2: set): $ _A1 == _A2 -> (subsn _A1 <-> subsn _A2) $;
theorem subsni (A: set) (G: wff) (a b: nat): $ G -> subsn A $ > $ G -> a e. A $ > $ G -> b e. A $ > $ G -> a = b $;
theorem subsnss (A B: set): $ A C_ B -> subsn B -> subsn A $;
theorem subsnsn2 (a: nat) {x: nat}: $ subsn {x | x = a} $;
theorem eqsubsnd (A: set) (G: wff) (a: nat) {x: nat}: $ G -> x e. A -> x = a $ > $ G -> subsn A $;
theorem eqsubsnabd (G: wff) (a: nat) {x: nat} (p: wff x): $ G -> p -> x = a $ > $ G -> subsn {x | p} $;
theorem subsnthe (A: set) (a: nat): $ subsn A -> a e. A -> the A = a $;
theorem subsnex (A: set) {a x: nat}: $ subsn A <-> E. a A. x (x e. A -> x = a) $;
theorem subsntheo (A: set) (a: nat): $ subsn A -> (theo A = suc a <-> a e. A) $;

Substitution for numbers. If b(x) is an expression denoting a natural number, with free x, then N[a / x] b is the term b(a).

def sbn (a: nat) {x: nat} (b: nat x): nat = $ the {y | [a / x] y = b} $;
notation sbn (a: nat) {x: nat} (b: nat x): nat = ($N[$:99) a ($/$:0) x ($]$:0) b;
theorem sbneqd (_G: wff) {x: nat} (_a1 _a2 _b1 _b2: nat x): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> N[_a1 / x] _b1 = N[_a2 / x] _b2 $;
theorem sbnq {x: nat} (a: nat) (b: nat x): $ x = a -> b = N[a / x] b $;
theorem nfsbn1h {x: nat} (a b: nat x): $ FN/ x a $ > $ FN/ x N[a / x] b $;
theorem nfsbn1 {x: nat} (a: nat) (b: nat x): $ FN/ x N[a / x] b $;
theorem nfsbnh {x y: nat} (a b: nat x y): $ FN/ x a $ > $ FN/ x b $ > $ FN/ x N[a / y] b $;
theorem nfsbn {x y: nat} (a: nat) (b: nat x y): $ FN/ x b $ > $ FN/ x N[a / y] b $;
theorem sbneq2d {x: nat} (G: wff) (a b c: nat x): $ G -> b = c $ > $ G -> N[a / x] b = N[a / x] c $;
theorem sbneht {x: nat} (a: nat) (b c: nat x): $ FN/ x c $ > $ A. x (x = a -> b = c) -> N[a / x] b = c $;
theorem sbneh {x: nat} (a: nat) (b c: nat x): $ FN/ x c $ > $ x = a -> b = c $ > $ N[a / x] b = c $;
theorem sbnet {x: nat} (a: nat) (b: nat x) (c: nat): $ A. x (x = a -> b = c) -> N[a / x] b = c $;
theorem sbne {x: nat} (a: nat) (b: nat x) (c: nat): $ x = a -> b = c $ > $ N[a / x] b = c $;
theorem sbned (G: wff) {x: nat} (a: nat) (b: nat x) (c: nat): $ G /\ x = a -> b = c $ > $ G -> N[a / x] b = c $;
theorem sbneq1 {x: nat} (a b c: nat x): $ a = b -> N[a / x] c = N[b / x] c $;
theorem sbneq1d {x: nat} (G: wff x) (a b c: nat x): $ G -> a = b $ > $ G -> N[a / x] c = N[b / x] c $;
theorem sbnid {x: nat} (a: nat x): $ N[x / x] a = a $;
theorem nfnlem {x y: nat} (b: nat y) (a c: nat x): $ y = a -> b = c $ > $ FN/ x a $ > $ FN/ x c $;
theorem nfnlem2 {x y z: nat} (c: nat y z) (a b d: nat x): $ y = a /\ z = b -> c = d $ > $ FN/ x a $ > $ FN/ x b $ > $ FN/ x d $;
theorem nfsuc {x: nat} (a: nat x): $ FN/ x a $ > $ FN/ x suc a $;

Addition of natural numbers, a primitive term constructor in PA.

term add (a b: nat): nat;
infixl add: $+$ prec 64;

Multiplication of natural numbers, a primitive term constructor in PA.

term mul (a b: nat): nat;
infixl mul: $*$ prec 70;

Addition respects equalty.

axiom addeq (a b c d: nat): $ a = b -> c = d -> a + c = b + d $;

Multiplication respects equalty.

axiom muleq (a b c d: nat): $ a = b -> c = d -> a * c = b * d $;

The base case in the definition of addition.

axiom add0 (a: nat): $ a + 0 = a $;

The successor case in the definition of addition.

axiom addS (a b: nat): $ a + suc b = suc (a + b) $;

The base case in the definition of multiplication.

axiom mul0 (a: nat): $ a * 0 = 0 $;

The successor case in the definition of multiplication.

axiom mulS (a b: nat): $ a * suc b = a * b + a $;
theorem addeqd (G: wff) (a b c d: nat): $ G -> a = b $ > $ G -> c = d $ > $ G -> a + c = b + d $;
theorem muleqd (G: wff) (a b c d: nat): $ G -> a = b $ > $ G -> c = d $ > $ G -> a * c = b * d $;
theorem addeq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> _a1 + b = _a2 + b $;
theorem addeq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> _a1 + b = _a2 + b $;
theorem addeq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> a + _b1 = a + _b2 $;
theorem addeq2 (a _b1 _b2: nat): $ _b1 = _b2 -> a + _b1 = a + _b2 $;
theorem muleq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> _a1 * b = _a2 * b $;
theorem muleq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> _a1 * b = _a2 * b $;
theorem muleq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> a * _b1 = a * _b2 $;
theorem muleq2 (a _b1 _b2: nat): $ _b1 = _b2 -> a * _b1 = a * _b2 $;
theorem nfadd {x: nat} (a b: nat x): $ FN/ x a $ > $ FN/ x b $ > $ FN/ x a + b $;
theorem nfmul {x: nat} (a b: nat x): $ FN/ x a $ > $ FN/ x b $ > $ FN/ x a * b $;
theorem add02 (a: nat): $ a + 0 = a $;
theorem add01 (a: nat): $ 0 + a = a $;
theorem addS2 (a b: nat): $ a + suc b = suc (a + b) $;
theorem addS1 (a b: nat): $ suc a + b = suc (a + b) $;
theorem addSass (a b: nat): $ suc a + b = a + suc b $;
theorem add12 (a: nat): $ a + 1 = suc a $;
theorem add11 (a: nat): $ 1 + a = suc a $;
theorem add22 (a: nat): $ a + 2 = suc (suc a) $;
theorem addcom (a b: nat): $ a + b = b + a $;
theorem addass (a b c: nat): $ a + b + c = a + (b + c) $;
theorem addlass (a b c: nat): $ a + (b + c) = b + (a + c) $;
theorem addrass (a b c: nat): $ a + b + c = a + c + b $;
theorem add4 (a b c d: nat): $ a + b + (c + d) = a + c + (b + d) $;
theorem addcan1 (a b c: nat): $ a + c = b + c <-> a = b $;
theorem addcan2 (a b c: nat): $ a + b = a + c <-> b = c $;
theorem mul02 (a: nat): $ a * 0 = 0 $;
theorem mul01 (a: nat): $ 0 * a = 0 $;
theorem mulS2 (a b: nat): $ a * suc b = a * b + a $;
theorem mulS1 (a b: nat): $ suc a * b = a * b + b $;
theorem mulcom (a b: nat): $ a * b = b * a $;
theorem mul12 (a: nat): $ a * 1 = a $;
theorem mul11 (a: nat): $ 1 * a = a $;
theorem mul22 (a: nat): $ a * 2 = a + a $;
theorem mul21 (a: nat): $ 2 * a = a + a $;
theorem muladd (a b c: nat): $ a * (b + c) = a * b + a * c $;
theorem addmul (a b c: nat): $ (a + b) * c = a * c + b * c $;
theorem mulass (a b c: nat): $ a * b * c = a * (b * c) $;
theorem mullass (a b c: nat): $ a * (b * c) = b * (a * c) $;
theorem mulrass (a b c: nat): $ a * b * c = a * c * b $;

(Truncated) subtraction of natural numbers. Note that a - b = 0 when a < b.

def sub (a b: nat): nat = $ the {x | b + x = a} $;
infixl sub: $-$ prec 64;
theorem subeqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> _a1 - _b1 = _a2 - _b2 $;
theorem subeq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> _a1 - _b1 = _a2 - _b2 $;
theorem subeq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> _a1 - b = _a2 - b $;
theorem subeq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> _a1 - b = _a2 - b $;
theorem subeq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> a - _b1 = a - _b2 $;
theorem subeq2 (a _b1 _b2: nat): $ _b1 = _b2 -> a - _b1 = a - _b2 $;
theorem eqsub2 (a b c: nat): $ a + b = c -> c - a = b $;
theorem eqsub1 (a b c: nat): $ a + b = c -> c - b = a $;
theorem pncan (a b: nat): $ a + b - b = a $;
theorem pncan2 (a b: nat): $ a + b - a = b $;
theorem sub02 (a: nat): $ a - 0 = a $;
theorem subid (a: nat): $ a - a = 0 $;
theorem sucsub1 (a: nat): $ suc a - 1 = a $;

a <= b means a is less than or equal to b.

def le (a b: nat): wff = $ E. x a + x = b $;
infixl le: $<=$ prec 50;
theorem leeqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> (_a1 <= _b1 <-> _a2 <= _b2) $;
theorem leeq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> (_a1 <= _b1 <-> _a2 <= _b2) $;
theorem leeq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> (_a1 <= b <-> _a2 <= b) $;
theorem leeq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> (_a1 <= b <-> _a2 <= b) $;
theorem leeq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> (a <= _b1 <-> a <= _b2) $;
theorem leeq2 (a _b1 _b2: nat): $ _b1 = _b2 -> (a <= _b1 <-> a <= _b2) $;
theorem dfle (a b: nat) {x: nat}: $ a <= b <-> E. x a + x = b $;
theorem leid (a: nat): $ a <= a $;
theorem eqle (a b: nat): $ a = b -> a <= b $;
theorem eqler (a b: nat): $ a = b -> b <= a $;
theorem pncan3 (a b: nat): $ a <= b -> a + (b - a) = b $;
theorem npcan (a b: nat): $ b <= a -> a - b + b = a $;
theorem subadd (a b c: nat): $ b <= a -> (a - b = c <-> b + c = a) $;
theorem addsub (a b c: nat): $ c <= a -> a + b - c = a - c + b $;
theorem leaddid1 (a b: nat): $ a <= a + b $;
theorem leaddid2 (a b: nat): $ a <= b + a $;
theorem lesucid (a: nat): $ a <= suc a $;
theorem le01 (a: nat): $ 0 <= a $;
theorem leadd1 (a b c: nat): $ a <= b <-> a + c <= b + c $;
theorem leadd2 (a b c: nat): $ b <= c <-> a + b <= a + c $;
theorem lesuc (a b: nat): $ a <= b <-> suc a <= suc b $;
theorem letrd (G: wff) (a b c: nat): $ G -> a <= b $ > $ G -> b <= c $ > $ G -> a <= c $;
theorem letr (a b c: nat): $ a <= b -> b <= c -> a <= c $;
theorem leasymd (G: wff) (a b: nat): $ G -> a <= b $ > $ G -> b <= a $ > $ G -> a = b $;
theorem leasym (a b: nat): $ a <= b -> b <= a -> a = b $;
theorem eqlele (a b: nat): $ a = b <-> a <= b /\ b <= a $;
theorem le02 (a: nat): $ a <= 0 <-> a = 0 $;
theorem le11 (a: nat): $ 1 <= a <-> a != 0 $;
theorem addeq0 (a b: nat): $ a + b = 0 <-> a = 0 /\ b = 0 $;
theorem sub1can (a: nat): $ a != 0 -> suc (a - 1) = a $;
theorem leaddd (G: wff) (a b c d: nat): $ G -> a <= b $ > $ G -> c <= d $ > $ G -> a + c <= b + d $;
theorem leadd (a b c d: nat): $ a <= b -> c <= d -> a + c <= b + d $;
theorem lemul1a (a b c: nat): $ a <= b -> a * c <= b * c $;
theorem lemul2a (a b c: nat): $ b <= c -> a * b <= a * c $;
theorem lemuld (G: wff) (a b c d: nat): $ G -> a <= b $ > $ G -> c <= d $ > $ G -> a * c <= b * d $;

a < b means a is strictly less than b.

def lt (a b: nat): wff = $ suc a <= b $;
infixl lt: $<$ prec 50;
theorem lteqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> (_a1 < _b1 <-> _a2 < _b2) $;
theorem lteq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> (_a1 < _b1 <-> _a2 < _b2) $;
theorem lteq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> (_a1 < b <-> _a2 < b) $;
theorem lteq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> (_a1 < b <-> _a2 < b) $;
theorem lteq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> (a < _b1 <-> a < _b2) $;
theorem lteq2 (a _b1 _b2: nat): $ _b1 = _b2 -> (a < _b1 <-> a < _b2) $;
theorem ltletr (a b c: nat): $ a < b -> b <= c -> a < c $;
theorem ltletrd (G: wff) (a b c: nat): $ G -> a < b $ > $ G -> b <= c $ > $ G -> a < c $;
theorem ltle (a b: nat): $ a < b -> a <= b $;
theorem ltlei (a b: nat): $ a < b $ > $ a <= b $;
theorem ltled (G: wff) (a b: nat): $ G -> a < b $ > $ G -> a <= b $;
theorem lelttr (a b c: nat): $ a <= b -> b < c -> a < c $;
theorem lelttrd (G: wff) (a b c: nat): $ G -> a <= b $ > $ G -> b < c $ > $ G -> a < c $;
theorem lttr (a b c: nat): $ a < b -> b < c -> a < c $;
theorem lttri (a b c: nat): $ a < b $ > $ b < c $ > $ a < c $;
theorem lttrd (G: wff) (a b c: nat): $ G -> a < b $ > $ G -> b < c $ > $ G -> a < c $;
theorem ltsucid (a: nat): $ a < suc a $;
theorem lt01 (a: nat): $ 0 < a <-> a != 0 $;
theorem lt02 (a: nat): $ ~a < 0 $;
theorem lt01S (a: nat): $ 0 < suc a $;
theorem le11S (a: nat): $ 1 <= suc a $;
theorem ltadd1 (a b c: nat): $ a < b <-> a + c < b + c $;
theorem ltadd2 (a b c: nat): $ b < c <-> a + b < a + c $;
theorem ltsuc (a b: nat): $ a < b <-> suc a < suc b $;
theorem leltsuc (a b: nat): $ a <= b <-> a < suc b $;
theorem leltaddd (G: wff) (a b c d: nat): $ G -> a <= b $ > $ G -> c < d $ > $ G -> a + c < b + d $;
theorem ltleaddd (G: wff) (a b c d: nat): $ G -> a < b $ > $ G -> c <= d $ > $ G -> a + c < b + d $;
theorem ltirr (a: nat): $ ~a < a $;
theorem ltne (a b: nat): $ a < b -> a != b $;
theorem ltner (a b: nat): $ a < b -> b != a $;
theorem ltnei (a b: nat): $ a < b $ > $ a != b $;
theorem ltneri (a b: nat): $ a < b $ > $ b != a $;
theorem d0lt1: $ 0 < 1 $;
theorem d0lt2: $ 0 < 2 $;
theorem d1lt2: $ 1 < 2 $;
theorem lt12 (a: nat): $ a < 1 <-> a = 0 $;
theorem nlesubeq0 (a b: nat): $ ~b <= a -> a - b = 0 $;
theorem subleid (a b: nat): $ a - b <= a $;
theorem subltid (a b: nat): $ 0 < a /\ 0 < b -> a - b < a $;
theorem lesub1i (a b c: nat): $ a <= b -> a - c <= b - c $;
theorem leloe (a b: nat): $ a <= b <-> a < b \/ a = b $;
theorem ltlene (a b: nat): $ a < b <-> a <= b /\ a != b $;
theorem ltlenle (a b: nat): $ a < b <-> a <= b /\ ~b <= a $;
theorem ltorle (a b: nat): $ a < b \/ b <= a $;
theorem leorlt (a b: nat): $ a <= b \/ b < a $;
theorem ltnle (a b: nat): $ a < b <-> ~b <= a $;
theorem lenlt (a b: nat): $ a <= b <-> ~b < a $;
theorem ltnlt (a b: nat): $ a < b -> ~b < a $;
theorem leorle (a b: nat): $ a <= b \/ b <= a $;
theorem neltlt (a b: nat): $ a != b <-> a < b \/ b < a $;
theorem eqalle2 (a b: nat) {i: nat}: $ a = b <-> A. i (a <= i <-> b <= i) $;
theorem eqallt1 (a b: nat) {i: nat}: $ a = b <-> A. i (i < a <-> i < b) $;
theorem ltsubeq0 (a b: nat): $ a < b -> a - b = 0 $;
theorem lesubeq0 (a b: nat): $ a <= b <-> a - b = 0 $;
theorem subpos (a b: nat): $ a < b <-> 0 < b - a $;
theorem lesubadd2 (a b c: nat): $ a - b <= c <-> a <= b + c $;
theorem lesubadd (a b c: nat): $ a - b <= c <-> a <= c + b $;
theorem ltaddsub (a b c: nat): $ a + b < c <-> a < c - b $;
theorem ltaddsub2 (a b c: nat): $ a + b < c <-> b < c - a $;
theorem ltsubadd (a b c: nat): $ b <= a -> (a - b < c <-> a < c + b) $;
theorem ltsubadd2 (a b c: nat): $ b <= a -> (a - b < c <-> a < b + c) $;
theorem leaddsub (a b c: nat): $ b <= c -> (a + b <= c <-> a <= c - b) $;
theorem leaddsub2 (a b c: nat): $ a <= c -> (a + b <= c <-> b <= c - a) $;
theorem leaddsubi (a b c: nat): $ a + b <= c -> a <= c - b $;
theorem leaddsub2i (a b c: nat): $ a + b <= c -> b <= c - a $;
theorem mulsub (a b c: nat): $ a * (b - c) = a * b - a * c $;
theorem submul (a b c: nat): $ (a - b) * c = a * c - b * c $;
theorem ltmul1 (a b c: nat): $ 0 < c -> (a < b <-> a * c < b * c) $;
theorem ltmul2 (a b c: nat): $ 0 < a -> (b < c <-> a * b < a * c) $;
theorem lemul1 (a b c: nat): $ 0 < c -> (a <= b <-> a * c <= b * c) $;
theorem lemul2 (a b c: nat): $ 0 < a -> (b <= c <-> a * b <= a * c) $;
theorem ltmuld (G: wff) (a b c d: nat): $ G -> a < b $ > $ G -> c < d $ > $ G -> a * c < b * d $;
theorem mulcan1 (a b c: nat): $ c != 0 -> (a * c = b * c <-> a = b) $;
theorem mulcan2 (a b c: nat): $ a != 0 -> (a * b = a * c <-> b = c) $;
theorem mulpos (a b: nat): $ 0 < a * b <-> 0 < a /\ 0 < b $;
theorem mulne0 (a b: nat): $ a * b != 0 <-> a != 0 /\ b != 0 $;
theorem sub01 (a: nat): $ 0 - a = 0 $;
theorem pnpcan2 (a b c: nat): $ a + c - (b + c) = a - b $;
theorem pnpcan1 (a b c: nat): $ a + b - (a + c) = b - c $;
theorem subSS (a b: nat): $ suc a - suc b = a - b $;
theorem subsub (a b c: nat): $ a - b - c = a - (b + c) $;
theorem indlt (G: wff) {x y: nat} (a: nat) (px: wff x) (p0 pa py ps: wff y):
  $ x = a -> (px <-> pa) $ >
  $ x = 0 -> (px <-> p0) $ >
  $ x = y -> (px <-> py) $ >
  $ x = suc y -> (px <-> ps) $ >
  $ G -> p0 $ >
  $ G /\ y < a /\ py -> ps $ >
  $ G -> pa $;
theorem indstr (G: wff) {x y: nat} (a: nat y) (px: wff x) (pa py: wff y):
  $ x = a -> (px <-> pa) $ >
  $ x = y -> (px <-> py) $ >
  $ G /\ A. x (x < y -> px) -> py $ >
  $ G -> pa $;

finite A means A is a finite set (here defined as one that is upper bounded by some natural number).

def finite (A: set): wff = $ E. n A. x (x e. A -> x < n) $;
theorem fineqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> (finite _A1 <-> finite _A2) $;
theorem fineq (_A1 _A2: set): $ _A1 == _A2 -> (finite _A1 <-> finite _A2) $;
theorem nffin {x: nat} (A: set x): $ FS/ x A $ > $ F/ x finite A $;
theorem finss (A B: set): $ A C_ B -> finite B -> finite A $;
theorem ltfin (n: nat) {x: nat}: $ finite {x | x < n} $;
theorem lefin (n: nat) {x: nat}: $ finite {x | x <= n} $;
theorem snfin (n: nat) {x: nat}: $ finite {x | x = n} $;
theorem infin1 (A B: set): $ finite A -> finite (A i^i B) $;
theorem infin2 (A B: set): $ finite B -> finite (A i^i B) $;

if p a b is the if-then-else construct: if p is true then a, else b.

abstract def if (p: wff) (a b: nat): nat = $ the {n | ifp p (n = a) (n = b)} $;
theorem ifeqd (_G _p1 _p2: wff) (_a1 _a2 _b1 _b2: nat):
  $ _G -> (_p1 <-> _p2) $ >
  $ _G -> _a1 = _a2 $ >
  $ _G -> _b1 = _b2 $ >
  $ _G -> if _p1 _a1 _b1 = if _p2 _a2 _b2 $;
theorem ifeq (_p1 _p2: wff) (_a1 _a2 _b1 _b2: nat): $ (_p1 <-> _p2) -> _a1 = _a2 -> _b1 = _b2 -> if _p1 _a1 _b1 = if _p2 _a2 _b2 $;
theorem ifeq1d (_G _p1 _p2: wff) (a b: nat): $ _G -> (_p1 <-> _p2) $ > $ _G -> if _p1 a b = if _p2 a b $;
theorem ifeq1 (_p1 _p2: wff) (a b: nat): $ (_p1 <-> _p2) -> if _p1 a b = if _p2 a b $;
theorem ifeq2d (_G p: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> if p _a1 b = if p _a2 b $;
theorem ifeq2 (p: wff) (_a1 _a2 b: nat): $ _a1 = _a2 -> if p _a1 b = if p _a2 b $;
theorem ifeq3d (_G p: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> if p a _b1 = if p a _b2 $;
theorem ifeq3 (p: wff) (a _b1 _b2: nat): $ _b1 = _b2 -> if p a _b1 = if p a _b2 $;
pub theorem ifpos (p: wff) (a b: nat): $ p -> if p a b = a $;
pub theorem ifneg (p: wff) (a b: nat): $ ~p -> if p a b = b $;
theorem ifid (a: nat) (p: wff): $ if p a a = a $;
theorem ifeq2a (a b c: nat) (p: wff): $ (p -> a = b) -> if p a c = if p b c $;
theorem ifeq3a (a b c: nat) (p: wff): $ (~p -> b = c) -> if p a b = if p a c $;
theorem ifbothd (G: wff) (a b: nat) (p q qa qb: wff):
  $ if p a b = a -> (q <-> qa) $ >
  $ if p a b = b -> (q <-> qb) $ >
  $ G /\ p -> qa $ >
  $ G /\ ~p -> qb $ >
  $ G -> q $;
theorem ifT (A: set) (a b: nat) (p: wff): $ a e. A /\ b e. A -> if p a b e. A $;

true n means n is "truthy", that is, nonzero.

def true (n: nat): wff = $ n != 0 $;
theorem trueeqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> (true _n1 <-> true _n2) $;
theorem trueeq (_n1 _n2: nat): $ _n1 = _n2 -> (true _n1 <-> true _n2) $;

bool n means n is "boolean", that is, 0 or 1.

def bool (n: nat): wff = $ n < 2 $;
theorem booleqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> (bool _n1 <-> bool _n2) $;
theorem booleq (_n1 _n2: nat): $ _n1 = _n2 -> (bool _n1 <-> bool _n2) $;

nat p turns wff p into a natural number: if p is true then 1, else 0.

def nat (p: wff): nat = $ if p 1 0 $;
theorem nateqd (_G _p1 _p2: wff): $ _G -> (_p1 <-> _p2) $ > $ _G -> nat _p1 = nat _p2 $;
theorem nateq (_p1 _p2: wff): $ (_p1 <-> _p2) -> nat _p1 = nat _p2 $;
theorem true1: $ true 1 $;
theorem true0: $ ~true 0 $;
theorem letrue (a b: nat): $ a <= b -> true a -> true b $;
theorem truemul (a b: nat): $ true (a * b) <-> true a /\ true b $;
theorem bool0: $ bool 0 $;
theorem bool1: $ bool 1 $;
theorem bool01 (n: nat): $ bool n <-> n = 0 \/ n = 1 $;
theorem boolle1 (n: nat): $ bool n <-> n <= 1 $;
theorem lebool (a b: nat): $ a <= b -> bool b -> bool a $;
theorem letrueb (a b: nat): $ bool a -> (a <= b <-> true a -> true b) $;
theorem dftrue2 (n: nat): $ bool n -> (true n <-> n = 1) $;
theorem boolnat (p: wff): $ bool (nat p) $;
theorem truenat (p: wff): $ true (nat p) <-> p $;
theorem nateq1 (p: wff): $ nat p = 1 <-> p $;
theorem nateq0 (p: wff): $ nat p = 0 <-> ~p $;
theorem nat1: $ nat T. = 1 $;
theorem nat0: $ nat F. = 0 $;
theorem nattrue (n: nat): $ bool n -> nat (true n) = n $;
theorem natle (p q: wff): $ p -> q <-> nat p <= nat q $;
theorem natinj (p q: wff): $ p <-> q <-> nat p = nat q $;
theorem natle1 (p: wff): $ nat p <= 1 $;
theorem nattruele (n: nat): $ nat (true n) <= n $;
theorem boolext (a b: nat): $ bool a -> bool b -> (true a <-> true b <-> a = b) $;

min a b is the smaller of a and b.

def min (a b: nat): nat = $ if (a < b) a b $;
theorem mineqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> min _a1 _b1 = min _a2 _b2 $;
theorem mineq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> min _a1 _b1 = min _a2 _b2 $;
theorem mineq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> min _a1 b = min _a2 b $;
theorem mineq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> min _a1 b = min _a2 b $;
theorem mineq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> min a _b1 = min a _b2 $;
theorem mineq2 (a _b1 _b2: nat): $ _b1 = _b2 -> min a _b1 = min a _b2 $;

max a b is the larger of a and b.

def max (a b: nat): nat = $ if (a < b) b a $;
theorem maxeqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> max _a1 _b1 = max _a2 _b2 $;
theorem maxeq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> max _a1 _b1 = max _a2 _b2 $;
theorem maxeq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> max _a1 b = max _a2 b $;
theorem maxeq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> max _a1 b = max _a2 b $;
theorem maxeq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> max a _b1 = max a _b2 $;
theorem maxeq2 (a _b1 _b2: nat): $ _b1 = _b2 -> max a _b1 = max a _b2 $;
theorem nfmax {x: nat} (a b: nat x): $ FN/ x a $ > $ FN/ x b $ > $ FN/ x max a b $;
theorem eqmin1 (a b: nat): $ a <= b -> min a b = a $;
theorem eqmax2 (a b: nat): $ a <= b -> max a b = b $;
theorem mincom (a b: nat): $ min a b = min b a $;
theorem maxcom (a b: nat): $ max a b = max b a $;
theorem eqmin2 (a b: nat): $ b <= a -> min a b = b $;
theorem eqmax1 (a b: nat): $ b <= a -> max a b = a $;
theorem minle1 (a b: nat): $ min a b <= a $;
theorem minle2 (a b: nat): $ min a b <= b $;
theorem lemin (a b c: nat): $ a <= min b c <-> a <= b /\ a <= c $;
theorem ltmin (a b c: nat): $ a < min b c <-> a < b /\ a < c $;
theorem subaddmin (a b: nat): $ a - b + min a b = a $;
theorem minaddsub (a b: nat): $ min a b + (a - b) = a $;
theorem submin (a b: nat): $ a - min a b = a - b $;
theorem lemax1 (a b: nat): $ a <= max a b $;
theorem lemax2 (a b: nat): $ b <= max a b $;
theorem maxle (a b c: nat): $ max a b <= c <-> a <= c /\ b <= c $;
theorem ltmax (a b c: nat): $ a < max b c <-> a < b \/ a < c $;
theorem minadd1 (a b c: nat): $ min a b + c = min (a + c) (b + c) $;
theorem maxadd1 (a b c: nat): $ max a b + c = max (a + c) (b + c) $;
theorem minS (a b: nat): $ suc (min a b) = min (suc a) (suc b) $;
theorem maxS (a b: nat): $ suc (max a b) = max (suc a) (suc b) $;
theorem maxlt (a b c: nat): $ max a b < c <-> a < c /\ b < c $;
theorem lemax (a b c: nat): $ a <= max b c <-> a <= b \/ a <= c $;
theorem unfin (A B: set): $ finite A -> finite B -> finite (A u. B) $;

a // b is the quotient on dividing a by b. (The double slash is used as in python to remind the reader that this is a rounding-down division, not exact division.) Division by 0 is defined and equal to 0.

abstract def div (a b: nat): nat = $ the {q | E. r (r < b /\ b * q + r = a)} $;
infixl div: $//$ prec 70;
theorem diveqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> _a1 // _b1 = _a2 // _b2 $;
theorem diveq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> _a1 // _b1 = _a2 // _b2 $;
theorem diveq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> _a1 // b = _a2 // b $;
theorem diveq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> _a1 // b = _a2 // b $;
theorem diveq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> a // _b1 = a // _b2 $;
theorem diveq2 (a _b1 _b2: nat): $ _b1 = _b2 -> a // _b1 = a // _b2 $;

a % b is the remainder on dividing a by b. Modulus by 0 is defined and a % 0 = a.

abstract def mod (a b: nat): nat = $ a - b * (a // b) $;
infixl mod: $%$ prec 70;
theorem modeqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> _a1 % _b1 = _a2 % _b2 $;
theorem modeq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> _a1 % _b1 = _a2 % _b2 $;
theorem modeq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> _a1 % b = _a2 % b $;
theorem modeq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> _a1 % b = _a2 % b $;
theorem modeq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> a % _b1 = a % _b2 $;
theorem modeq2 (a _b1 _b2: nat): $ _b1 = _b2 -> a % _b1 = a % _b2 $;
pub theorem div0 (a: nat): $ a // 0 = 0 $;
theorem mod0 (a: nat): $ a % 0 = a $;
theorem divlem1 (G: wff) (b q1 q2 r1 r2: nat): $ G -> r1 < b $ > $ G -> r2 < b $ > $ G -> b * q1 + r1 <= b * q2 + r2 $ > $ G -> q1 <= q2 $;
theorem divlem2 (G: wff) (Q R a b q: nat) {r: nat}: $ G -> R < b $ > $ G -> b * Q + R = a $ > $ G -> (E. r (r < b /\ b * q + r = a) <-> q = Q) $;
theorem divlem3 (a b: nat) {q r: nat}: $ b != 0 -> E. q E. r (r < b /\ b * q + r = a) $;
theorem eqdivmod (G: wff) (Q R a b: nat): $ G -> R < b $ > $ G -> b * Q + R = a $ > $ G -> a // b = Q /\ a % b = R $;
pub theorem divmod (a b: nat): $ b * (a // b) + a % b = a $;
pub theorem modlt (a b: nat): $ b != 0 -> a % b < b $;
theorem modle1 (a b: nat): $ a % b <= a $;
theorem div01 (a: nat): $ 0 // a = 0 $;
theorem mod01 (a: nat): $ 0 % a = 0 $;
theorem mod12 (a: nat): $ a % 1 = 0 $;
theorem div12 (a: nat): $ a // 1 = a $;
theorem muladddiv2 (a b c: nat): $ b != 0 -> (b * a + c) // b = a + c // b $;
theorem muladddiv1 (a b c: nat): $ b != 0 -> (a * b + c) // b = a + c // b $;
theorem muladdmod2 (a b c: nat): $ b != 0 -> (b * a + c) % b = c % b $;
theorem muladdmod1 (a b c: nat): $ b != 0 -> (a * b + c) % b = c % b $;
theorem muladddiv2lt (a b c: nat): $ b != 0 /\ c < b -> (b * a + c) // b = a $;
theorem muladddiv1lt (a b c: nat): $ b != 0 /\ c < b -> (a * b + c) // b = a $;
theorem muladdmod2lt (a b c: nat): $ b != 0 /\ c < b -> (b * a + c) % b = c $;
theorem muladdmod1lt (a b c: nat): $ b != 0 /\ c < b -> (a * b + c) % b = c $;
theorem muldiv2 (a b: nat): $ b != 0 -> b * a // b = a $;
theorem muldiv1 (a b: nat): $ b != 0 -> a * b // b = a $;
theorem mulmod1 (a b: nat): $ b * a % b = 0 $;
theorem mulmod2 (a b: nat): $ a * b % b = 0 $;
theorem divid (a: nat): $ a != 0 -> a // a = 1 $;
theorem modid (a: nat): $ a % a = 0 $;
theorem divlteq0 (a b: nat): $ a < b -> a // b = 0 $;
theorem modltid (a b: nat): $ a < b -> a % b = a $;
theorem lediv1 (a b c: nat): $ a <= b -> a // c <= b // c $;
theorem muldivle (a b: nat): $ b * (a // b) <= a $;
theorem divleid (a b: nat): $ a // b <= a $;
theorem ledivmul1 (a b c: nat): $ c != 0 -> (a <= b // c <-> c * a <= b) $;
theorem ledivmul2 (a b c: nat): $ c != 0 -> (a <= b // c <-> a * c <= b) $;
theorem divltmul1 (a b c: nat): $ b != 0 -> (a // b < c <-> a < b * c) $;
theorem divltmul2 (a b c: nat): $ b != 0 -> (a // b < c <-> a < c * b) $;
theorem divlemul1r (a b c: nat): $ b != 0 -> a <= b * c -> a // b <= c $;
theorem divlemul2r (a b c: nat): $ b != 0 -> a <= c * b -> a // b <= c $;
theorem diveq0 (a b: nat): $ b != 0 -> (a // b = 0 <-> a < b) $;
theorem divdiv (a b c: nat): $ a // b // c = a // (b * c) $;
theorem divmod1 (a b c: nat): $ a // b % c = a % (b * c) // b $;
theorem divmod2 (a b c: nat): $ a // b % c = a % (c * b) // b $;
theorem divmoddilem (a b c: nat): $ a != 0 -> a * b // (a * c) = b // c /\ a * b % (a * c) = a * (b % c) $;
theorem mdmcan1 (a b c: nat): $ a != 0 -> a * b // (a * c) = b // c $;
theorem mdmcan2 (a b c: nat): $ c != 0 -> a * c // (b * c) = a // b $;
theorem mulmoddi (a b c: nat): $ a * (b % c) = a * b % (a * c) $;
theorem mulmoddir (a b c: nat): $ a % b * c = a * c % (b * c) $;

a || b means that a divides b, or equivalently, b is a multiple of a.

def dvd (a b: nat): wff = $ E. c c * a = b $;
infixl dvd: $||$ prec 50;
theorem dvdeqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> (_a1 || _b1 <-> _a2 || _b2) $;
theorem dvdeq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> (_a1 || _b1 <-> _a2 || _b2) $;
theorem dvdeq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> (_a1 || b <-> _a2 || b) $;
theorem dvdeq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> (_a1 || b <-> _a2 || b) $;
theorem dvdeq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> (a || _b1 <-> a || _b2) $;
theorem dvdeq2 (a _b1 _b2: nat): $ _b1 = _b2 -> (a || _b1 <-> a || _b2) $;
theorem idvd (a b c: nat): $ c * a = b -> a || b $;
theorem idvd2 (a b c: nat): $ a * c = b -> a || b $;
theorem divmul (a b: nat): $ b || a -> a // b * b = a $;
theorem muldiv3 (a b: nat): $ b || a -> b * (a // b) = a $;
theorem dvdadd1 (a b n: nat): $ n || a -> (n || b <-> n || a + b) $;
theorem dvdadd2 (a b n: nat): $ n || a -> (n || b <-> n || b + a) $;
theorem dvdmul1 (a b: nat): $ a || b * a $;
theorem dvdmul2 (a b: nat): $ a || a * b $;
theorem dvdtr (a b c: nat): $ a || b -> b || c -> a || c $;
theorem dvdmul12 (a b c: nat): $ a || b -> a || c * b $;
theorem dvdmul11 (a b c: nat): $ a || b -> a || b * c $;
theorem modeq0 (a n: nat): $ a % n = 0 <-> n || a $;
theorem dvd02 (a: nat): $ a || 0 $;
theorem dvd01 (a: nat): $ 0 || a <-> a = 0 $;
theorem dvdid (a: nat): $ a || a $;
theorem dvdle (G: wff) (a b: nat): $ G -> b != 0 $ > $ G -> a || b $ > $ G -> a <= b $;
theorem dvdasymd (G: wff) (a b: nat): $ G -> a || b $ > $ G -> b || a $ > $ G -> a = b $;
theorem dvd11 (a: nat): $ 1 || a $;
theorem dvd12 (a: nat): $ a || 1 <-> a = 1 $;
theorem d2dvd1: $ ~2 || 1 $;
theorem d2dvdS (n: nat): $ 2 || suc n <-> ~2 || n $;
theorem modlteq (a n: nat): $ a < n -> a % n = a $;
theorem modmodid (a n: nat): $ a % n % n = a % n $;
theorem dvdsubmod (a n: nat): $ n || a - a % n $;
theorem div2lt (n: nat): $ 0 < n -> n // 2 < n $;
theorem boolmod2 (n: nat): $ bool (n % 2) $;
local def eqm (n a b: nat): wff = $ a % n = b % n $;
notation eqm (n a b: nat): wff = ($mod($:50) n ($):$:50) a ($=$:50) b;
theorem eqmeqd (_G: wff) (_n1 _n2 _a1 _a2 _b1 _b2: nat):
  $ _G -> _n1 = _n2 $ >
  $ _G -> _a1 = _a2 $ >
  $ _G -> _b1 = _b2 $ >
  $ _G -> (mod(_n1): _a1 = _b1 <-> mod(_n2): _a2 = _b2) $;
theorem eqmeq (_n1 _n2 _a1 _a2 _b1 _b2: nat): $ _n1 = _n2 -> _a1 = _a2 -> _b1 = _b2 -> (mod(_n1): _a1 = _b1 <-> mod(_n2): _a2 = _b2) $;
theorem eqmeq1d (_G: wff) (_n1 _n2 a b: nat): $ _G -> _n1 = _n2 $ > $ _G -> (mod(_n1): a = b <-> mod(_n2): a = b) $;
theorem eqmeq1 (_n1 _n2 a b: nat): $ _n1 = _n2 -> (mod(_n1): a = b <-> mod(_n2): a = b) $;
theorem eqmeq2d (_G: wff) (n _a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> (mod(n): _a1 = b <-> mod(n): _a2 = b) $;
theorem eqmeq2 (n _a1 _a2 b: nat): $ _a1 = _a2 -> (mod(n): _a1 = b <-> mod(n): _a2 = b) $;
theorem eqmeq3d (_G: wff) (n a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> (mod(n): a = _b1 <-> mod(n): a = _b2) $;
theorem eqmeq3 (n a _b1 _b2: nat): $ _b1 = _b2 -> (mod(n): a = _b1 <-> mod(n): a = _b2) $;
theorem eqmid (a n: nat): $ mod(n): a = a $;
theorem eqmtr (a b c n: nat): $ mod(n): a = b -> mod(n): b = c -> mod(n): a = c $;
theorem eqmcom (a b n: nat): $ mod(n): a = b -> mod(n): b = a $;
theorem eqmcomb (a b n: nat): $ mod(n): a = b <-> mod(n): b = a $;
theorem eqeqm (a b n: nat): $ a = b -> mod(n): a = b $;
theorem eqeqmd (G: wff) (a b n: nat): $ G -> a = b $ > $ G -> mod(n): a = b $;
theorem eqmeq23d (G: wff) (a b c d n: nat): $ G -> a = b $ > $ G -> c = d $ > $ G -> (mod(n): a = c <-> mod(n): b = d) $;
theorem eqmeqm23d (G: wff) (a b c d n: nat): $ G -> mod(n): a = b $ > $ G -> mod(n): c = d $ > $ G -> (mod(n): a = c <-> mod(n): b = d) $;
theorem eqmmod (a n: nat): $ mod(n): a % n = a $;
theorem eqm03 (a n: nat): $ mod(n): a = 0 <-> n || a $;
theorem eqmid0 (n: nat): $ mod(n): n = 0 $;
theorem eqmdvdsub (a b n: nat): $ a <= b -> (mod(n): a = b <-> n || b - a) $;
theorem eqmaddlem (a b c n: nat): $ a <= b -> (mod(n): a + c = b + c <-> mod(n): a = b) $;
theorem eqmadd1 (a b c n: nat): $ mod(n): a + c = b + c <-> mod(n): a = b $;
theorem eqmadd2 (a b c n: nat): $ mod(n): a + b = a + c <-> mod(n): b = c $;
theorem eqmsuc (a b n: nat): $ mod(n): suc a = suc b <-> mod(n): a = b $;
theorem eqmadd1d (G: wff) (a b c n: nat): $ G -> mod(n): a = b $ > $ G -> mod(n): a + c = b + c $;
theorem eqmadd2d (G: wff) (a b c n: nat): $ G -> mod(n): b = c $ > $ G -> mod(n): a + b = a + c $;
theorem eqmaddd (G: wff) (a b c d n: nat): $ G -> mod(n): a = b $ > $ G -> mod(n): c = d $ > $ G -> mod(n): a + c = b + d $;
theorem eqmdvd (a b n: nat): $ mod(n): a = b -> (n || a <-> n || b) $;
theorem eqmaddn (a n: nat): $ mod(n): a + n = a $;
theorem dvdeqm (G: wff) (a b m n: nat): $ G -> m || n $ > $ G -> mod(n): a = b $ > $ G -> mod(m): a = b $;
theorem modmod (a m n: nat): $ m || n -> a % n % m = a % m $;
theorem eqm11 (a b: nat): $ mod(1): a = b $;
theorem eqm01 (a b: nat): $ mod(0): a = b <-> a = b $;

b0 n is n * 2. It is named for "bit 0" as in binary representation of numbers.

b0 is also used as left injection when creating disjoint unions.

def b0 (n: nat): nat = $ n + n $;
theorem b0eqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> b0 _n1 = b0 _n2 $;
theorem b0eq (_n1 _n2: nat): $ _n1 = _n2 -> b0 _n1 = b0 _n2 $;

b1 n is n * 2 + 1. It is named for "bit 1" as in binary representation of numbers.

b1 is also used as right injection when creating disjoint unions.

def b1 (n: nat): nat = $ suc (b0 n) $;
theorem b1eqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> b1 _n1 = b1 _n2 $;
theorem b1eq (_n1 _n2: nat): $ _n1 = _n2 -> b1 _n1 = b1 _n2 $;

odd n means n is odd, not divisible by 2.

def odd (n: nat): wff = $ n % 2 = 1 $;
theorem oddeqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> (odd _n1 <-> odd _n2) $;
theorem oddeq (_n1 _n2: nat): $ _n1 = _n2 -> (odd _n1 <-> odd _n2) $;
theorem b00: $ b0 0 = 0 $;
theorem b10: $ b1 0 = 1 $;
theorem b0mul21 (n: nat): $ 2 * n = b0 n $;
theorem b0mul22 (n: nat): $ n * 2 = b0 n $;
theorem b0ne0 (n: nat): $ b0 n != 0 <-> n != 0 $;
theorem b1ne0 (n: nat): $ b1 n != 0 $;
theorem b1mul21 (n: nat): $ 2 * n + 1 = b1 n $;
theorem b0dvd2 (n: nat): $ 2 || b0 n $;
theorem b1dvd2 (n: nat): $ ~2 || b1 n $;
theorem dfodd2 (n: nat): $ odd n <-> true (n % 2) $;
theorem odddvd (n: nat): $ odd n <-> ~2 || n $;
theorem boolodd (n: nat): $ bool n -> (odd n <-> true n) $;
theorem b0odd (n: nat): $ ~odd (b0 n) $;
theorem b1odd (n: nat): $ odd (b1 n) $;
theorem oddnat (p: wff): $ odd (nat p) <-> p $;
theorem b0mod2 (n: nat): $ b0 n % 2 = 0 $;
theorem b1mod2 (n: nat): $ b1 n % 2 = 1 $;
theorem b0div2 (n: nat): $ b0 n // 2 = n $;
theorem b1div2 (n: nat): $ b1 n // 2 = n $;
theorem b0can (a b: nat): $ b0 a = b0 b <-> a = b $;
theorem b1can (a b: nat): $ b1 a = b1 b <-> a = b $;
theorem b1neb0 (a b: nat): $ b1 a != b0 b $;
theorem b0neb1 (a b: nat): $ b0 a != b1 b $;
theorem sucb0 (a: nat): $ suc (b0 a) = b1 a $;
theorem sucb1 (a: nat): $ suc (b1 a) = b0 (suc a) $;
theorem addb00 (a b: nat): $ b0 a + b0 b = b0 (a + b) $;
theorem addb01 (a b: nat): $ b0 a + b1 b = b1 (a + b) $;
theorem addb10 (a b: nat): $ b1 a + b0 b = b1 (a + b) $;
theorem addb11 (a b: nat): $ b1 a + b1 b = b0 (suc (a + b)) $;
theorem b0le (a b: nat): $ a <= b <-> b0 a <= b0 b $;
theorem b1le (a b: nat): $ a <= b <-> b1 a <= b1 b $;
theorem b0lt (a b: nat): $ a < b <-> b0 a < b0 b $;
theorem b1lt (a b: nat): $ a < b <-> b1 a < b1 b $;
theorem b0ltb1 (a b: nat): $ b0 a < b1 b <-> a <= b $;
theorem b1ltb0 (a b: nat): $ b1 a < b0 b <-> a < b $;
theorem b0leb1 (a b: nat): $ b0 a <= b1 b <-> a <= b $;
theorem b1leb0 (a b: nat): $ b1 a <= b0 b <-> a < b $;
theorem b0orb1 (n: nat): $ n = b0 (n // 2) \/ n = b1 (n // 2) $;
theorem b0leid (n: nat): $ n <= b0 n $;
theorem b1ltid (n: nat): $ n < b1 n $;
theorem b1leid (n: nat): $ n <= b1 n $;
theorem b0ltid (n: nat): $ n != 0 <-> n < b0 n $;
theorem ltb0tr (a b: nat): $ a < b $ > $ a < b0 b $;
theorem ltb1tr (a b: nat): $ a <= b $ > $ a < b1 b $;
theorem leb0tr (a b: nat): $ a <= b $ > $ a <= b0 b $;
theorem leb1tr (a b: nat): $ a <= b $ > $ a <= b1 b $;
theorem eqb0 (n: nat): $ ~odd n <-> n = b0 (n // 2) $;
theorem eqb1 (n: nat): $ odd n <-> n = b1 (n // 2) $;
theorem splitb (G: wff) (a: nat) (p: wff): $ G -> a = b0 (a // 2) -> p $ > $ G -> a = b1 (a // 2) -> p $ > $ G -> p $;
theorem splitb0 (G: wff) (a b c: nat) (p: wff): $ G -> a = b0 c -> p $ > $ G -> b = c -> a = b0 b -> p $;
theorem splitb1 (G: wff) (a b c: nat) (p: wff): $ G -> a = b1 c -> p $ > $ G -> b = c -> a = b1 b -> p $;
theorem odd0: $ ~odd 0 $;
theorem oddS (n: nat): $ odd (suc n) <-> ~odd n $;
theorem odd1: $ odd 1 $;

a, b is the pairing operator on natural numbers (or anything that is being encoded as a natural number). It is defined using the Cantor pairing function. It is right associative, i.e. a, b, c means (a, (b, c)).

def pr (a b: nat): nat = $ (a + b) * suc (a + b) // 2 + b $;
infixr pr: $,$ prec 55;
theorem preqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> _a1, _b1 = _a2, _b2 $;
theorem preq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> _a1, _b1 = _a2, _b2 $;
theorem preq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> _a1, b = _a2, b $;
theorem preq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> _a1, b = _a2, b $;
theorem preq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> a, _b1 = a, _b2 $;
theorem preq2 (a _b1 _b2: nat): $ _b1 = _b2 -> a, _b1 = a, _b2 $;
theorem nfpr {x: nat} (a b: nat x): $ FN/ x a $ > $ FN/ x b $ > $ FN/ x a, b $;
theorem preqadd (a b: nat): $ a, b = (a + b, 0) + b $;
theorem prlem1 (n: nat): $ 2 || n * suc n $;
theorem prlem2 (a b c d: nat): $ a, c <= b, d -> a + c <= b + d $;
theorem prth (a b c d: nat): $ a, c = b, d <-> a = b /\ c = d $;
theorem prltsuc (a b: nat): $ a, b < suc (a + b), 0 $;
theorem addlepr (a b: nat): $ a + b <= a, b $;
theorem leprid1 (a b: nat): $ a <= a, b $;
theorem leprid2 (a b: nat): $ b <= a, b $;
theorem lepr1tr (a b c: nat): $ a <= b $ > $ a <= b, c $;
theorem lepr2tr (a b c: nat): $ a <= c $ > $ a <= b, c $;
theorem ltpr1tr (a b c: nat): $ a < b $ > $ a < b, c $;
theorem ltpr2tr (a b c: nat): $ a < c $ > $ a < b, c $;
theorem lepr1 (a b c: nat): $ a <= b <-> a, c <= b, c $;
theorem lepr2 (a b c: nat): $ b <= c <-> a, b <= a, c $;
theorem ltpr1 (a b c: nat): $ a < b <-> a, c < b, c $;
theorem ltpr2 (a b c: nat): $ b < c <-> a, b < a, c $;

The first component of a pair.

abstract def fst (a: nat): nat = $ the {x | E. y a = x, y} $;
theorem fsteqd (_G: wff) (_a1 _a2: nat): $ _G -> _a1 = _a2 $ > $ _G -> fst _a1 = fst _a2 $;
theorem fsteq (_a1 _a2: nat): $ _a1 = _a2 -> fst _a1 = fst _a2 $;

The second component of a pair.

abstract def snd (a: nat): nat = $ the {y | E. x a = x, y} $;
theorem sndeqd (_G: wff) (_a1 _a2: nat): $ _G -> _a1 = _a2 $ > $ _G -> snd _a1 = snd _a2 $;
theorem sndeq (_a1 _a2: nat): $ _a1 = _a2 -> snd _a1 = snd _a2 $;
pub theorem pr0: $ 0, 0 = 0 $;
theorem expr (a: nat) {x y: nat}: $ E. x E. y a = x, y $;
theorem splitpr (G: wff) (a: nat) (p: wff) {x y: nat}: $ G -> a = x, y -> p $ > $ G -> p $;
theorem splitpr1 (G: wff) (a b: nat) (p: wff) (x y: nat): $ G -> a = x, y -> p $ > $ G -> b = x -> a = b, y -> p $;
theorem splitpr2 (G: wff) (a b: nat) (p: wff) (x y: nat): $ G -> a = x, y -> p $ > $ G -> b = y -> a = x, b -> p $;
theorem splitopt (G: wff) (a: nat) (p: wff): $ G -> a = 0 -> p $ > $ G -> a = suc (a - 1) -> p $ > $ G -> p $;
theorem splitoptS (G: wff) (a b c: nat) (p: wff): $ G -> a = suc c -> p $ > $ G -> b = c -> a = suc b -> p $;
pub theorem fstpr (a b: nat): $ fst (a, b) = a $;
pub theorem sndpr (a b: nat): $ snd (a, b) = b $;
pub theorem fstsnd (a: nat): $ fst a, snd a = a $;
theorem fstleid (a: nat): $ fst a <= a $;
theorem sndleid (a: nat): $ snd a <= a $;
theorem axext2 (A B: set) {x y: nat}: $ A == B <-> A. x A. y (x, y e. A <-> x, y e. B) $;
theorem eqrd2 (A B: set) (G: wff) {x y: nat}: $ G -> (x, y e. A <-> x, y e. B) $ > $ G -> A == B $;
theorem eqri2 (A B: set) {x y: nat}: $ x, y e. A <-> x, y e. B $ > $ A == B $;
theorem ssal2 (A B: set) {x y: nat}: $ A C_ B <-> A. x A. y (x, y e. A -> x, y e. B) $;
theorem ssrd2 (A B: set) (G: wff) {x y: nat}: $ G -> x, y e. A -> x, y e. B $ > $ G -> A C_ B $;
theorem ssri2 (A B: set) {x y: nat}: $ x, y e. A -> x, y e. B $ > $ A C_ B $;
theorem fst0: $ fst 0 = 0 $;
theorem snd0: $ snd 0 = 0 $;

pi11 ((a, b), c) = a

def pi11 (n: nat): nat = $ fst (fst n) $;
theorem pi11eqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> pi11 _n1 = pi11 _n2 $;
theorem pi11eq (_n1 _n2: nat): $ _n1 = _n2 -> pi11 _n1 = pi11 _n2 $;

pi12 ((a, b), c) = b

def pi12 (n: nat): nat = $ snd (fst n) $;
theorem pi12eqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> pi12 _n1 = pi12 _n2 $;
theorem pi12eq (_n1 _n2: nat): $ _n1 = _n2 -> pi12 _n1 = pi12 _n2 $;

pi21 (a, (b, c)) = b

def pi21 (n: nat): nat = $ fst (snd n) $;
theorem pi21eqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> pi21 _n1 = pi21 _n2 $;
theorem pi21eq (_n1 _n2: nat): $ _n1 = _n2 -> pi21 _n1 = pi21 _n2 $;

pi22 (a, (b, c)) = c

def pi22 (n: nat): nat = $ snd (snd n) $;
theorem pi22eqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> pi22 _n1 = pi22 _n2 $;
theorem pi22eq (_n1 _n2: nat): $ _n1 = _n2 -> pi22 _n1 = pi22 _n2 $;

pi221 (a, (b, (c, d))) = c

def pi221 (n: nat): nat = $ fst (pi22 n) $;
theorem pi221eqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> pi221 _n1 = pi221 _n2 $;
theorem pi221eq (_n1 _n2: nat): $ _n1 = _n2 -> pi221 _n1 = pi221 _n2 $;

pi222 (a, (b, (c, d))) = d

def pi222 (n: nat): nat = $ snd (pi22 n) $;
theorem pi222eqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> pi222 _n1 = pi222 _n2 $;
theorem pi222eq (_n1 _n2: nat): $ _n1 = _n2 -> pi222 _n1 = pi222 _n2 $;
theorem pi11pr (a b c: nat): $ pi11 ((a, b), c) = a $;
theorem pi12pr (a b c: nat): $ pi12 ((a, b), c) = b $;
theorem pi21pr (a b c: nat): $ pi21 (a, b, c) = b $;
theorem pi22pr (a b c: nat): $ pi22 (a, b, c) = c $;
theorem pi221pr (a b c d: nat): $ pi221 (a, b, c, d) = c $;
theorem pi222pr (a b c d: nat): $ pi222 (a, b, c, d) = d $;

isfun A means A is a function, i.e. if (x,y) and (x,z) are in A then y = z.

def isfun (A: set): wff = $ A. a A. b A. b2 (a, b e. A -> a, b2 e. A -> b = b2) $;
theorem isfeqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> (isfun _A1 <-> isfun _A2) $;
theorem isfeq (_A1 _A2: set): $ _A1 == _A2 -> (isfun _A1 <-> isfun _A2) $;
theorem nfisf {x: nat} (F: set x): $ FS/ x F $ > $ F/ x isfun F $;
theorem isfd (F: set) (G: wff) (a b b2: nat): $ G -> isfun F $ > $ G -> a, b e. F $ > $ G -> a, b2 e. F $ > $ G -> b = b2 $;
theorem isfbd (F: set) (G: wff) (a b b2: nat): $ G -> isfun F $ > $ G -> a, b e. F $ > $ G -> (a, b2 e. F <-> b = b2) $;
theorem isfss (A B: set): $ A C_ B -> isfun B -> isfun A $;

S\ x, A is "lambda for relations": a, b e. S\ x, A(x) if b e. A(a). It can be iterated to produce n-ary relations. S\ x, S\ y, {z | p(x,y,z)} is the set S such that x, y, z e. S iff p(x,y,z).

def sab {x: nat} (A: set x): set = $ {z | snd z e. S[fst z / x] A} $;
notation sab {x: nat} (A: set x): set = ($S\$:100) x ($,$:55) A;
theorem sabeqd (_G: wff) {x: nat} (_A1 _A2: set x): $ _G -> _A1 == _A2 $ > $ _G -> S\ x, _A1 == S\ x, _A2 $;
theorem nfsab {x y: nat} (A: set x y): $ FS/ y A $ > $ FS/ y S\ x, A $;
theorem nfsab1 {x: nat} (A: set x): $ FS/ x S\ x, A $;
theorem sabeq {x: nat} (A B: set x): $ A. x A == B -> S\ x, A == S\ x, B $;
theorem sabeqi {x: nat} (A B: set x): $ A == B $ > $ S\ x, A == S\ x, B $;
theorem cbvsabs {x y: nat} (A: set x): $ S\ x, A == S\ y, (S[y / x] A) $;
theorem elsabs (a b: nat) {x: nat} (A: set x): $ a, b e. S\ x, A <-> b e. S[a / x] A $;
theorem elsab (B: set) (a b: nat) {x: nat} (A: set x): $ x = a -> A == B $ > $ a, b e. S\ x, A <-> b e. B $;
theorem elsabed (G: wff) (a b: nat) (p: wff) {x: nat} (A: set x): $ G /\ x = a -> (b e. A <-> p) $ > $ G -> (a, b e. S\ x, A <-> p) $;
theorem elsabe (a b: nat) (p: wff) {x: nat} (A: set x): $ x = a -> (b e. A <-> p) $ > $ a, b e. S\ x, A <-> p $;
theorem eexsabd (G p: wff) {x z: nat} (y: nat x z) (A: set x): $ G -> z e. A -> p $ > $ G -> y e. S\ x, A -> p $;
theorem sabss {x: nat} (A B: set x): $ S\ x, A C_ S\ x, B <-> A. x A C_ B $;
theorem sabssi {x: nat} (A B: set x): $ A C_ B $ > $ S\ x, A C_ S\ x, B $;
theorem sabssd (G: wff) {x: nat} (A B: set x): $ G -> A C_ B $ > $ G -> S\ x, A C_ S\ x, B $;

Indexed disjoint union, a restricted version of S\. a, b e. X\ x e. A, B(x) iff a e. A and b e. B(a).

def xab {x: nat} (A: set) (B: set x): set = $ {z | fst z e. A /\ snd z e. S[fst z / x] B} $;
notation xab {x: nat} (A: set) (B: set x): set = ($X\$:100) x ($e.$:50) A ($,$:55) B;
theorem xabeqd (_G: wff) {x: nat} (_A1 _A2 _B1 _B2: set x): $ _G -> _A1 == _A2 $ > $ _G -> _B1 == _B2 $ > $ _G -> X\ x e. _A1, _B1 == X\ x e. _A2, _B2 $;
theorem xabeq1d (_G: wff) {x: nat} (_A1 _A2 B: set x): $ _G -> _A1 == _A2 $ > $ _G -> X\ x e. _A1, B == X\ x e. _A2, B $;
theorem xabeq2d (_G: wff) {x: nat} (A _B1 _B2: set x): $ _G -> _B1 == _B2 $ > $ _G -> X\ x e. A, _B1 == X\ x e. A, _B2 $;
theorem nfxab {x y: nat} (A B: set x y): $ FS/ y A $ > $ FS/ y B $ > $ FS/ y X\ x e. A, B $;
theorem nfxab1 {x: nat} (A B: set x): $ FS/ x A $ > $ FS/ x X\ x e. A, B $;
theorem xabeq2da (A: set) (G: wff) {x: nat} (B C: set x): $ G /\ x e. A -> B == C $ > $ G -> X\ x e. A, B == X\ x e. A, C $;
theorem cbvxabs (A: set) {x y: nat} (B: set x): $ X\ x e. A, B == X\ y e. A, (S[y / x] B) $;
theorem elxabs (A: set) (a b: nat) {x: nat} (B: set x): $ a, b e. X\ x e. A, B <-> a e. A /\ b e. S[a / x] B $;
theorem elxab (A C: set) (a b: nat) {x: nat} (B: set x): $ x = a -> B == C $ > $ a, b e. X\ x e. A, B <-> a e. A /\ b e. C $;
theorem elxabed (A: set) (G: wff) (a b: nat) (p: wff) {x: nat} (B: set x): $ G /\ x = a -> (b e. B <-> p) $ > $ G -> (a, b e. X\ x e. A, B <-> a e. A /\ p) $;
theorem elxabe (A: set) (a b: nat) (p: wff) {x: nat} (B: set x): $ x = a -> (b e. B <-> p) $ > $ a, b e. X\ x e. A, B <-> a e. A /\ p $;
theorem elxabe2 (A: set) (a: nat) (p: wff) {x: nat} (B: set x): $ x = fst a -> (snd a e. B <-> p) $ > $ a e. X\ x e. A, B <-> fst a e. A /\ p $;
theorem xabssd (A: set) (G: wff) {x: nat} (B C: set x): $ G /\ x e. A -> B C_ C $ > $ G -> X\ x e. A, B C_ X\ x e. A, C $;
theorem sabxab (A: set) (G: wff) {x y: nat} (B: set x): $ G -> y e. B -> x e. A $ > $ G -> S\ x, B == X\ x e. A, B $;

Xp A B is the cartesian product of sets: (a,b) e. Xp A B iff a e. A and b e. B.

def Xp (A B: set): set = $ X\ x e. A, B $;
theorem xpeqd (_G: wff) (_A1 _A2 _B1 _B2: set): $ _G -> _A1 == _A2 $ > $ _G -> _B1 == _B2 $ > $ _G -> Xp _A1 _B1 == Xp _A2 _B2 $;
theorem xpeq (_A1 _A2 _B1 _B2: set): $ _A1 == _A2 -> _B1 == _B2 -> Xp _A1 _B1 == Xp _A2 _B2 $;
theorem xpeq1d (_G: wff) (_A1 _A2 B: set): $ _G -> _A1 == _A2 $ > $ _G -> Xp _A1 B == Xp _A2 B $;
theorem xpeq1 (_A1 _A2 B: set): $ _A1 == _A2 -> Xp _A1 B == Xp _A2 B $;
theorem xpeq2d (_G: wff) (A _B1 _B2: set): $ _G -> _B1 == _B2 $ > $ _G -> Xp A _B1 == Xp A _B2 $;
theorem xpeq2 (A _B1 _B2: set): $ _B1 == _B2 -> Xp A _B1 == Xp A _B2 $;
theorem nfxp {x: nat} (A B: set x): $ FS/ x A $ > $ FS/ x B $ > $ FS/ x Xp A B $;
theorem prelxp (A B: set) (a b: nat): $ a, b e. Xp A B <-> a e. A /\ b e. B $;
theorem elxp (A B: set) (a: nat): $ a e. Xp A B <-> fst a e. A /\ snd a e. B $;
theorem xpvv: $ Xp _V _V == _V $;
theorem cplxpv1 (A: set): $ Compl (Xp _V A) == Xp _V (Compl A) $;
theorem cplxpv2 (A: set): $ Compl (Xp A _V) == Xp (Compl A) _V $;
theorem xpss1 (A B C: set): $ A C_ B -> Xp A C C_ Xp B C $;
theorem xpss2 (A B C: set): $ B C_ C -> Xp A B C_ Xp A C $;
theorem xpundi (A B C: set): $ Xp (A u. B) C == Xp A C u. Xp B C $;
theorem xpundir (A B C: set): $ Xp A (B u. C) == Xp A B u. Xp A C $;
theorem xpindi (A B C: set): $ Xp (A i^i B) C == Xp A C i^i Xp B C $;
theorem xpindir (A B C: set): $ Xp A (B i^i C) == Xp A B i^i Xp A C $;
theorem xpfst (A B: set) (a: nat): $ a e. Xp A B -> fst a e. A $;
theorem xpsnd (A B: set) (a: nat): $ a e. Xp A B -> snd a e. B $;
theorem prelxp1 (A B: set) (a b: nat): $ a, b e. Xp A B -> a e. A $;
theorem prelxp2 (A B: set) (a b: nat): $ a, b e. Xp A B -> b e. B $;
theorem xpTd (A B: set) (G: wff) (a b: nat): $ G -> a e. A $ > $ G -> b e. B $ > $ G -> a, b e. Xp A B $;
theorem xppi11 (A B C: set) (a: nat): $ a e. Xp (Xp A B) C -> pi11 a e. A $;
theorem xppi12 (A B C: set) (a: nat): $ a e. Xp (Xp A B) C -> pi12 a e. B $;
theorem xppi21 (A B C: set) (a: nat): $ a e. Xp A (Xp B C) -> pi21 a e. B $;
theorem xppi22 (A B C: set) (a: nat): $ a e. Xp A (Xp B C) -> pi22 a e. C $;
theorem xppi221 (A B C D: set) (a: nat): $ a e. Xp A (Xp B (Xp C D)) -> pi221 a e. C $;
theorem xppi222 (A B C D: set) (a: nat): $ a e. Xp A (Xp B (Xp C D)) -> pi222 a e. D $;
theorem xpfin (A B: set): $ finite A -> finite B -> finite (Xp A B) $;
theorem xabconst (A B: set) {x: nat}: $ X\ x e. A, B == Xp A B $;
theorem sabssxped (A C: set) (G: wff) (a: nat) (p: wff) {x: nat} (B: set x):
  $ G /\ x = fst a -> snd a e. B -> p /\ x e. A /\ snd a e. C $ >
  $ G -> a e. S\ x, B -> p /\ a e. Xp A C $;
theorem sabssxpe (A C: set) (a: nat) {x: nat} (B: set x): $ x = fst a -> snd a e. B -> x e. A /\ snd a e. C $ > $ a e. S\ x, B -> a e. Xp A C $;

The domain of a binary relation: x e. Dom A if there exists y such that (x,y) e. A.

def Dom (A: set): set = $ {x | E. y x, y e. A} $;
theorem dmeqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> Dom _A1 == Dom _A2 $;
theorem dmeq (_A1 _A2: set): $ _A1 == _A2 -> Dom _A1 == Dom _A2 $;

The range of a binary relation: y e. Ran A if there exists x such that (x,y) e. A.

def Ran (A: set): set = $ {y | E. x x, y e. A} $;
theorem rneqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> Ran _A1 == Ran _A2 $;
theorem rneq (_A1 _A2: set): $ _A1 == _A2 -> Ran _A1 == Ran _A2 $;

The image of a relation under a set: y e. F '' A if there exists x e. A such that (x,y) e. F.

def Im (F A: set): set = $ {y | E. x (x e. A /\ x, y e. F)} $;
infixl Im: $''$ prec 80;
theorem imaeqd (_G: wff) (_F1 _F2 _A1 _A2: set): $ _G -> _F1 == _F2 $ > $ _G -> _A1 == _A2 $ > $ _G -> _F1 '' _A1 == _F2 '' _A2 $;
theorem imaeq (_F1 _F2 _A1 _A2: set): $ _F1 == _F2 -> _A1 == _A2 -> _F1 '' _A1 == _F2 '' _A2 $;
theorem imaeq1d (_G: wff) (_F1 _F2 A: set): $ _G -> _F1 == _F2 $ > $ _G -> _F1 '' A == _F2 '' A $;
theorem imaeq1 (_F1 _F2 A: set): $ _F1 == _F2 -> _F1 '' A == _F2 '' A $;
theorem imaeq2d (_G: wff) (F _A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> F '' _A1 == F '' _A2 $;
theorem imaeq2 (F _A1 _A2: set): $ _A1 == _A2 -> F '' _A1 == F '' _A2 $;
theorem nfdm {x: nat} (A: set x): $ FS/ x A $ > $ FS/ x Dom A $;
theorem nfrn {x: nat} (A: set x): $ FS/ x A $ > $ FS/ x Ran A $;
theorem eldm (A: set) (a: nat) {y: nat}: $ a e. Dom A <-> E. y a, y e. A $;
theorem elrn (A: set) (a: nat) {x: nat}: $ a e. Ran A <-> E. x x, a e. A $;
theorem preldm (A: set) (a b: nat): $ a, b e. A -> a e. Dom A $;
theorem prelrn (A: set) (a b: nat): $ a, b e. A -> b e. Ran A $;
theorem fsteldm (A: set) (p: nat): $ p e. A -> fst p e. Dom A $;
theorem sndelrn (A: set) (p: nat): $ p e. A -> snd p e. Ran A $;
theorem dmun (A B: set): $ Dom (A u. B) == Dom A u. Dom B $;
theorem rnun (A B: set): $ Ran (A u. B) == Ran A u. Ran B $;
theorem dmss (A B: set): $ A C_ B -> Dom A C_ Dom B $;
theorem rnss (A B: set): $ A C_ B -> Ran A C_ Ran B $;
theorem ssdm (A R: set): $ Dom R C_ A <-> R C_ Xp A _V $;
theorem ssrn (A R: set): $ Ran R C_ A <-> R C_ Xp _V A $;
theorem dmfin (A: set): $ finite A -> finite (Dom A) $;
theorem rnfin (A: set): $ finite A -> finite (Ran A) $;
theorem elima (A F: set) (b: nat) {x: nat}: $ b e. F '' A <-> E. x (x e. A /\ x, b e. F) $;
theorem elimai (A F: set) (a b: nat): $ a, b e. F -> a e. A -> b e. F '' A $;
theorem imv (F: set): $ F '' _V == Ran F $;

The converse of a relation: (x,y) e. cnv A if (y,x) e. A.

def cnv (A: set): set = $ S\ x, {y | y, x e. A} $;
theorem cnveqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> cnv _A1 == cnv _A2 $;
theorem cnveq (_A1 _A2: set): $ _A1 == _A2 -> cnv _A1 == cnv _A2 $;
theorem prcnv (A: set) (x y: nat): $ x, y e. cnv A <-> y, x e. A $;
theorem cnvopab {x y: nat} (p: wff x y): $ cnv (S\ x, {y | p}) == S\ y, {x | p} $;

The relational composition: (x,z) e. F o> G if there exists y such that (x,y) e. F and (y,z) e. G. Warning: This is also applicable for functions, but it does not match the more conventional right-to-left composition order. (F o> G) @ x = G @ (F @ x). We use an arrow like notation o> to remind the reader of this: we apply F then G.

def comp (F G: set): set = $ S\ x, {z | E. y (x, y e. F /\ y, z e. G)} $;
infixr comp: $o>$ prec 91;
theorem coeqd (_G: wff) (_F1 _F2 _G1 _G2: set): $ _G -> _F1 == _F2 $ > $ _G -> _G1 == _G2 $ > $ _G -> _F1 o> _G1 == _F2 o> _G2 $;
theorem coeq (_F1 _F2 _G1 _G2: set): $ _F1 == _F2 -> _G1 == _G2 -> _F1 o> _G1 == _F2 o> _G2 $;
theorem coeq1d (_G: wff) (_F1 _F2 G: set): $ _G -> _F1 == _F2 $ > $ _G -> _F1 o> G == _F2 o> G $;
theorem coeq1 (_F1 _F2 G: set): $ _F1 == _F2 -> _F1 o> G == _F2 o> G $;
theorem coeq2d (_G: wff) (F _G1 _G2: set): $ _G -> _G1 == _G2 $ > $ _G -> F o> _G1 == F o> _G2 $;
theorem coeq2 (F _G1 _G2: set): $ _G1 == _G2 -> F o> _G1 == F o> _G2 $;
theorem prco (A B: set) (x: nat) {y: nat} (z: nat): $ x, z e. A o> B <-> E. y (x, y e. A /\ y, z e. B) $;

The restriction of a relation to a set: A | Bis the set of(x,y) e. Asuch thaty e. B`.

def res (A B: set): set = $ A i^i Xp B _V $;
infixl res: $|`$ prec 54;
theorem reseqd (_G: wff) (_A1 _A2 _B1 _B2: set): $ _G -> _A1 == _A2 $ > $ _G -> _B1 == _B2 $ > $ _G -> _A1 |` _B1 == _A2 |` _B2 $;
theorem reseq (_A1 _A2 _B1 _B2: set): $ _A1 == _A2 -> _B1 == _B2 -> _A1 |` _B1 == _A2 |` _B2 $;
theorem reseq1d (_G: wff) (_A1 _A2 B: set): $ _G -> _A1 == _A2 $ > $ _G -> _A1 |` B == _A2 |` B $;
theorem reseq1 (_A1 _A2 B: set): $ _A1 == _A2 -> _A1 |` B == _A2 |` B $;
theorem reseq2d (_G: wff) (A _B1 _B2: set): $ _G -> _B1 == _B2 $ > $ _G -> A |` _B1 == A |` _B2 $;
theorem reseq2 (A _B1 _B2: set): $ _B1 == _B2 -> A |` _B1 == A |` _B2 $;
theorem nfres {x: nat} (A B: set x): $ FS/ x A $ > $ FS/ x B $ > $ FS/ x A |` B $;
theorem elres (A B: set) (a: nat): $ a e. A |` B <-> a e. A /\ fst a e. B $;
theorem prelres (A B: set) (a b: nat): $ a, b e. A |` B <-> a, b e. A /\ a e. B $;
theorem resss (A B: set): $ A |` B C_ A $;
theorem resv (F: set): $ F |` _V == F $;
theorem resfin (A F: set): $ finite F -> finite (F |` A) $;
theorem resisf (A F: set): $ isfun F -> isfun (F |` A) $;
theorem dmres (A F: set): $ Dom (F |` A) == Dom F i^i A $;
theorem rnres (A F: set): $ Ran (F |` A) == F '' A $;
theorem unres (A F G: set): $ F u. G |` A == (F |` A) u. (G |` A) $;
theorem resun (A B F: set): $ F |` A u. B == (F |` A) u. (F |` B) $;
theorem eqres (A F: set): $ Dom F C_ A <-> F |` A == F $;
theorem resdm (F: set): $ F |` Dom F == F $;
theorem resres (A B F: set): $ F |` A |` B == F |` A i^i B $;

The lambda operator: \ x, v(x) is the set of pairs (x, v(x)) over all natural numbers x.

def lam {x: nat} (a: nat x): set = $ {p | E. x p = x, a} $;
notation lam {x: nat} (a: nat x): set = ($\$:53) x ($,$:55) a;
theorem lameqd (_G: wff) {x: nat} (_a1 _a2: nat x): $ _G -> _a1 = _a2 $ > $ _G -> \ x, _a1 == \ x, _a2 $;
theorem ellam (p: nat) {x: nat} (a: nat x): $ p e. \ x, a <-> E. x p = x, a $;
theorem prellams (a b: nat) {x: nat} (v: nat x): $ a, b e. \ x, v <-> b = N[a / x] v $;
theorem prellame (b: nat) {x: nat} (y z: nat) (a: nat x): $ x = y -> a = b $ > $ y, z e. \ x, a <-> z = b $;
theorem lameq {x: nat} (a b: nat x): $ A. x a = b -> \ x, a == \ x, b $;
theorem lameqi {x: nat} (a b: nat x): $ a = b $ > $ \ x, a == \ x, b $;
theorem nflam1 {x: nat} (a: nat x): $ FS/ x \ x, a $;
theorem nflam {x y: nat} (a: nat x y): $ FN/ x a $ > $ FS/ x \ y, a $;
theorem cbvlamh {x y: nat} (a b: nat x y): $ FN/ y a $ > $ FN/ x b $ > $ x = y -> a = b $ > $ \ x, a == \ y, b $;
theorem cbvlam {x y: nat} (a: nat x) (b: nat y): $ x = y -> a = b $ > $ \ x, a == \ y, b $;
theorem cbvlams {x y: nat} (a: nat x): $ \ x, a == \ y, N[y / x] a $;
theorem cbvlamd {x y: nat} (G: wff) (a: nat x) (b: nat y): $ G /\ x = y -> a = b $ > $ G -> \ x, a == \ y, b $;
theorem lamisf {x: nat} (a: nat x): $ isfun (\ x, a) $;
theorem finlam (A: set) {x: nat} (v: nat x): $ finite A -> finite ((\ x, v) |` A) $;
theorem finlamh {x: nat} (A: set x) (v: nat x): $ finite A -> finite ((\ x, v) |` A) $;
theorem ellamima (A: set) (a: nat) {x: nat} (v: nat x): $ a e. (\ x, v) '' A <-> E. x (x e. A /\ a = v) $;
theorem ellamimaab (a: nat) {x: nat} (v: nat x) (p: wff x): $ a e. (\ x, v) '' {x | p} <-> E. x (p /\ a = v) $;
theorem finlamima (A: set) {x: nat} (v: nat x): $ finite A -> finite ((\ x, v) '' A) $;
theorem lameqb {x: nat} (a b: nat x): $ A. x a = b <-> \ x, a == \ x, b $;
theorem reslameq (A: set) {x: nat} (a b: nat x): $ A. x (x e. A -> a = b) -> (\ x, a) |` A == (\ x, b) |` A $;
theorem dmlam {x: nat} (a: nat x): $ Dom (\ x, a) == _V $;
theorem dmreslam {x: nat} (A: set x) (a: nat x): $ Dom ((\ x, a) |` A) == A $;
local def rapp (F: set) (x: nat): set = $ {y | x, y e. F} $;
infixl rapp: $@'$ prec 200;
theorem rappeqd (_G: wff) (_F1 _F2: set) (_x1 _x2: nat): $ _G -> _F1 == _F2 $ > $ _G -> _x1 = _x2 $ > $ _G -> _F1 @' _x1 == _F2 @' _x2 $;
theorem rappeq (_F1 _F2: set) (_x1 _x2: nat): $ _F1 == _F2 -> _x1 = _x2 -> _F1 @' _x1 == _F2 @' _x2 $;
theorem rappeq1d (_G: wff) (_F1 _F2: set) (x: nat): $ _G -> _F1 == _F2 $ > $ _G -> _F1 @' x == _F2 @' x $;
theorem rappeq1 (_F1 _F2: set) (x: nat): $ _F1 == _F2 -> _F1 @' x == _F2 @' x $;
theorem rappeq2d (_G: wff) (F: set) (_x1 _x2: nat): $ _G -> _x1 = _x2 $ > $ _G -> F @' _x1 == F @' _x2 $;
theorem rappeq2 (F: set) (_x1 _x2: nat): $ _x1 = _x2 -> F @' _x1 == F @' _x2 $;
theorem nfrapp {x: nat} (F: set x) (a: nat x): $ FS/ x F $ > $ FN/ x a $ > $ FS/ x F @' a $;
theorem elrapp (F: set) (a b: nat): $ b e. F @' a <-> a, b e. F $;
theorem rappsabs (a: nat) {x: nat} (A: set x): $ (S\ x, A) @' a == S[a / x] A $;
theorem rappsab {x: nat} (A: set x): $ (S\ x, A) @' x == A $;
theorem rappsabed (B: set) (G: wff) (a: nat) {x: nat} (A: set x): $ G /\ x = a -> A == B $ > $ G -> (S\ x, A) @' a == B $;
theorem rappsabe (B: set) (a: nat) {x: nat} (A: set x): $ x = a -> A == B $ > $ (S\ x, A) @' a == B $;
theorem rappsabed1 (F: set) (G P: wff) (a: nat) {x: nat} (A: set x): $ G /\ x = a -> F @' a == A -> P $ > $ G -> F == S\ x, A -> P $;
theorem rappsabed2 (B F: set) (G: wff) (a: nat) {x: nat} (A: set x): $ G /\ x = a -> A == B $ > $ G -> F == S\ x, A -> F @' a == B $;
theorem rappss (A B: set) (a: nat): $ A C_ B -> A @' a C_ B @' a $;
theorem rappssb (A B: set) {x: nat}: $ A C_ B <-> A. x A @' x C_ B @' x $;
theorem eqrappb (A B: set) {x: nat}: $ A == B <-> A. x A @' x == B @' x $;

The application operator. If F is a function and x is a natural number then F @ x is F evaluated at x. That is, it is the value y for which (x,y) e. F, if there is a unique such number.

def app (F: set) (x: nat): nat = $ the {y | x, y e. F} $;
infixl app: $@$ prec 200;
theorem appeqd (_G: wff) (_F1 _F2: set) (_x1 _x2: nat): $ _G -> _F1 == _F2 $ > $ _G -> _x1 = _x2 $ > $ _G -> _F1 @ _x1 = _F2 @ _x2 $;
theorem appeq (_F1 _F2: set) (_x1 _x2: nat): $ _F1 == _F2 -> _x1 = _x2 -> _F1 @ _x1 = _F2 @ _x2 $;
theorem appeq1d (_G: wff) (_F1 _F2: set) (x: nat): $ _G -> _F1 == _F2 $ > $ _G -> _F1 @ x = _F2 @ x $;
theorem appeq1 (_F1 _F2: set) (x: nat): $ _F1 == _F2 -> _F1 @ x = _F2 @ x $;
theorem appeq2d (_G: wff) (F: set) (_x1 _x2: nat): $ _G -> _x1 = _x2 $ > $ _G -> F @ _x1 = F @ _x2 $;
theorem appeq2 (F: set) (_x1 _x2: nat): $ _x1 = _x2 -> F @ _x1 = F @ _x2 $;
theorem nfapp {x: nat} (F: set x) (a: nat x): $ FS/ x F $ > $ FN/ x a $ > $ FN/ x F @ a $;
theorem isfappd (F: set) (G: wff) (a b: nat): $ G -> isfun F $ > $ G -> a, b e. F $ > $ G -> F @ a = b $;
theorem isfappb (F: set) (a b: nat): $ isfun F -> (a, b e. F <-> a e. Dom F /\ F @ a = b) $;
theorem eqapp (F G: set) (a: nat) {y: nat}: $ A. y (a, y e. F <-> a, y e. G) -> F @ a = G @ a $;
theorem ndmapp (F: set) (a: nat): $ ~a e. Dom F -> F @ a = 0 $;
theorem appelrn (F: set) (a: nat): $ isfun F -> a e. Dom F -> F @ a e. Ran F $;
theorem isfrn (F: set) {x: nat} (y: nat): $ isfun F -> (y e. Ran F <-> E. x (x e. Dom F /\ F @ x = y)) $;
theorem isfrnss (A F: set) {x: nat}: $ isfun F -> (Ran F C_ A <-> A. x (x e. Dom F -> F @ x e. A)) $;
theorem eqisf (F G: set) {x: nat}: $ isfun F /\ isfun G -> (F == G <-> Dom F == Dom G /\ A. x (x e. Dom F -> F @ x = G @ x)) $;
theorem resapp (A F: set) (a: nat): $ a e. A -> (F |` A) @ a = F @ a $;
theorem appelima (A F: set) (G: wff) (a: nat): $ G -> isfun F $ > $ G -> a e. Dom F $ > $ G -> a e. A $ > $ G -> F @ a e. F '' A $;
theorem applams {x: nat} (a b: nat x): $ (\ x, a) @ b = N[b / x] a $;
theorem applam {x: nat} (a: nat x): $ (\ x, a) @ x = a $;
theorem applame (b c: nat) {x: nat} (a: nat x): $ x = b -> a = c $ > $ (\ x, a) @ b = c $;
theorem applamed (G: wff) (b c: nat) {x: nat} (a: nat x): $ G /\ x = b -> a = c $ > $ G -> (\ x, a) @ b = c $;
theorem applamed1 (F: set) (G P: wff) (b: nat) {x: nat} (a: nat x): $ G /\ x = b -> F @ b = a -> P $ > $ G -> F == \ x, a -> P $;
theorem applamed2 (F: set) (G: wff) (b c: nat) {x: nat} (a: nat x): $ G /\ x = b -> a = c $ > $ G -> F == \ x, a -> F @ b = c $;
theorem lamapp2 (A F: set) {x: nat}: $ (\ x, F @ x) |` A == F <-> isfun F /\ Dom F == A $;
theorem lamapp (F: set) {x: nat}: $ (\ x, F @ x) |` Dom F == F <-> isfun F $;

Define a function by cases on a disjoint union. case A B is the function such that

  • case A B @ b0 n = A @ n
  • case A B @ b1 n = B @ n
def case (A B: set): set = $ \ n, if (odd n) (B @ (n // 2)) (A @ (n // 2)) $;
theorem caseeqd (_G: wff) (_A1 _A2 _B1 _B2: set): $ _G -> _A1 == _A2 $ > $ _G -> _B1 == _B2 $ > $ _G -> case _A1 _B1 == case _A2 _B2 $;
theorem caseeq (_A1 _A2 _B1 _B2: set): $ _A1 == _A2 -> _B1 == _B2 -> case _A1 _B1 == case _A2 _B2 $;
theorem caseeq1d (_G: wff) (_A1 _A2 B: set): $ _G -> _A1 == _A2 $ > $ _G -> case _A1 B == case _A2 B $;
theorem caseeq1 (_A1 _A2 B: set): $ _A1 == _A2 -> case _A1 B == case _A2 B $;
theorem caseeq2d (_G: wff) (A _B1 _B2: set): $ _G -> _B1 == _B2 $ > $ _G -> case A _B1 == case A _B2 $;
theorem caseeq2 (A _B1 _B2: set): $ _B1 == _B2 -> case A _B1 == case A _B2 $;
pub theorem casel (A B: set) (n: nat): $ case A B @ b0 n = A @ n $;
pub theorem caser (A B: set) (n: nat): $ case A B @ b1 n = B @ n $;

Disjoint union of sets; also case for wff-valued functions.

  • b0 n e. Sum A B <-> n e. A
  • b1 n e. Sum A B <-> n e. B
abstract def Sum (A B: set): set = $ {n | ifp (odd n) (n // 2 e. B) (n // 2 e. A)} $;
theorem Sumeqd (_G: wff) (_A1 _A2 _B1 _B2: set): $ _G -> _A1 == _A2 $ > $ _G -> _B1 == _B2 $ > $ _G -> Sum _A1 _B1 == Sum _A2 _B2 $;
theorem Sumeq (_A1 _A2 _B1 _B2: set): $ _A1 == _A2 -> _B1 == _B2 -> Sum _A1 _B1 == Sum _A2 _B2 $;
theorem Sumeq1d (_G: wff) (_A1 _A2 B: set): $ _G -> _A1 == _A2 $ > $ _G -> Sum _A1 B == Sum _A2 B $;
theorem Sumeq1 (_A1 _A2 B: set): $ _A1 == _A2 -> Sum _A1 B == Sum _A2 B $;
theorem Sumeq2d (_G: wff) (A _B1 _B2: set): $ _G -> _B1 == _B2 $ > $ _G -> Sum A _B1 == Sum A _B2 $;
theorem Sumeq2 (A _B1 _B2: set): $ _B1 == _B2 -> Sum A _B1 == Sum A _B2 $;
pub theorem Suml (A B: set) (n: nat): $ b0 n e. Sum A B <-> n e. A $;
pub theorem Sumr (A B: set) (n: nat): $ b1 n e. Sum A B <-> n e. B $;
theorem Sumld (A B: set) (G: wff) (a: nat): $ G -> a e. A $ > $ G -> b0 a e. Sum A B $;
theorem Sumrd (A B: set) (G: wff) (b: nat): $ G -> b e. B $ > $ G -> b1 b e. Sum A B $;

With Sum as a pairing operator for classes, this is the first projection.

local def Fst (A: set): set = $ {n | b0 n e. A} $;
theorem Fsteqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> Fst _A1 == Fst _A2 $;
theorem Fsteq (_A1 _A2: set): $ _A1 == _A2 -> Fst _A1 == Fst _A2 $;

With Sum as a pairing operator for classes, this is the second projection.

local def Snd (A: set): set = $ {n | b1 n e. A} $;
theorem Sndeqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> Snd _A1 == Snd _A2 $;
theorem Sndeq (_A1 _A2: set): $ _A1 == _A2 -> Snd _A1 == Snd _A2 $;
theorem elFst (A: set) (a: nat): $ a e. Fst A <-> b0 a e. A $;
theorem elSnd (A: set) (a: nat): $ a e. Snd A <-> b1 a e. A $;
theorem FstSum (A B: set): $ Fst (Sum A B) == A $;
theorem SndSum (A B: set): $ Snd (Sum A B) == B $;
theorem FstSnd (A: set): $ Sum (Fst A) (Snd A) == A $;
local def slam {x: nat} (A: set x): set = $ S\ p, {y | snd p, y e. S[fst p / x] A} $;
notation slam {x: nat} (A: set x): set = ($\\$:30) x ($,$:55) A;
theorem slameqd (_G: wff) {x: nat} (_A1 _A2: set x): $ _G -> _A1 == _A2 $ > $ _G -> (\\ x, _A1) == (\\ x, _A2) $;
theorem prelslams (a b: nat) {x: nat} (y: nat) (A: set x): $ (a, b), y e. (\\ x, A) <-> b, y e. S[a / x] A $;
theorem appslams (a b: nat) {x: nat} (A: set x): $ (\\ x, A) @ (a, b) = (S[a / x] A) @ b $;
theorem appslam (B: set) (a b: nat) {x: nat} (A: set x): $ x = a -> A == B $ > $ (\\ x, A) @ (a, b) = B @ b $;
theorem appslamed (G: wff) (a b c: nat) {x: nat} (A: set x): $ G /\ x = a -> A @ b = c $ > $ G -> (\\ x, A) @ (a, b) = c $;
theorem appslame (a b c: nat) {x: nat} (A: set x): $ x = a -> A @ b = c $ > $ (\\ x, A) @ (a, b) = c $;
local def least (A: set): nat = $ the {x | x e. A /\ A. y (y e. A -> x <= y)} $;
theorem leasteqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> least _A1 = least _A2 $;
theorem leasteq (_A1 _A2: set): $ _A1 == _A2 -> least _A1 = least _A2 $;
theorem leastlem (A: set) (a: nat) {z: nat}: $ a e. A -> least A e. A /\ A. z (z e. A -> least A <= z) $;
theorem leastel (A: set) (a: nat): $ a e. A -> least A e. A $;
theorem leastle (A: set) (a: nat): $ a e. A -> least A <= a $;
theorem least0 (A: set) {x: nat}: $ ~E. x x e. A -> least A = 0 $;
theorem subsnfin (A: set): $ subsn A -> finite A $;
local def sapp (F: set) (x: nat): set = $ S\ y, F @' (x, y) $;
infixl sapp: $@@$ prec 200;
theorem sappeqd (_G: wff) (_F1 _F2: set) (_x1 _x2: nat): $ _G -> _F1 == _F2 $ > $ _G -> _x1 = _x2 $ > $ _G -> _F1 @@ _x1 == _F2 @@ _x2 $;
theorem sappeq (_F1 _F2: set) (_x1 _x2: nat): $ _F1 == _F2 -> _x1 = _x2 -> _F1 @@ _x1 == _F2 @@ _x2 $;
theorem sappeq1d (_G: wff) (_F1 _F2: set) (x: nat): $ _G -> _F1 == _F2 $ > $ _G -> _F1 @@ x == _F2 @@ x $;
theorem sappeq1 (_F1 _F2: set) (x: nat): $ _F1 == _F2 -> _F1 @@ x == _F2 @@ x $;
theorem sappeq2d (_G: wff) (F: set) (_x1 _x2: nat): $ _G -> _x1 = _x2 $ > $ _G -> F @@ _x1 == F @@ _x2 $;
theorem sappeq2 (F: set) (_x1 _x2: nat): $ _x1 = _x2 -> F @@ _x1 == F @@ _x2 $;
theorem nfsapp {x: nat} (F: set x) (a: nat x): $ FS/ x F $ > $ FN/ x a $ > $ FS/ x F @@ a $;
theorem sapprapp (F: set) (a b: nat): $ F @@ a @' b == F @' (a, b) $;
theorem sappapp (F: set) (a b: nat): $ F @@ a @ b = F @ (a, b) $;
theorem prelsapp (F: set) (a b y: nat): $ b, y e. F @@ a <-> (a, b), y e. F $;
theorem sappslams (a: nat) {x: nat} (A: set x): $ (\\ x, A) @@ a == S[a / x] A $;
theorem sappslam (B: set) (a: nat) {x: nat} (A: set x): $ x = a -> A == B $ > $ (\\ x, A) @@ a == B $;
theorem sappslamed (B: set) (G: wff) (a: nat) {x: nat} (A: set x): $ G /\ x = a -> A == B $ > $ G -> (\\ x, A) @@ a == B $;
theorem sappslame (B: set) (a: nat) {x: nat} (A: set x): $ x = a -> A == B $ > $ (\\ x, A) @@ a == B $;
local def znsub (m n: nat): nat = $ if (m < n) (b1 (n - suc m)) (b0 (m - n)) $;
infixl znsub: $-ZN$ prec 64;
theorem znsubeqd (_G: wff) (_m1 _m2 _n1 _n2: nat): $ _G -> _m1 = _m2 $ > $ _G -> _n1 = _n2 $ > $ _G -> _m1 -ZN _n1 = _m2 -ZN _n2 $;
theorem znsubeq (_m1 _m2 _n1 _n2: nat): $ _m1 = _m2 -> _n1 = _n2 -> _m1 -ZN _n1 = _m2 -ZN _n2 $;
theorem znsubeq1d (_G: wff) (_m1 _m2 n: nat): $ _G -> _m1 = _m2 $ > $ _G -> _m1 -ZN n = _m2 -ZN n $;
theorem znsubeq1 (_m1 _m2 n: nat): $ _m1 = _m2 -> _m1 -ZN n = _m2 -ZN n $;
theorem znsubeq2d (_G: wff) (m _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> m -ZN _n1 = m -ZN _n2 $;
theorem znsubeq2 (m _n1 _n2: nat): $ _n1 = _n2 -> m -ZN _n1 = m -ZN _n2 $;
theorem znsubneg (m n: nat): $ m < n -> m -ZN n = b1 (n - suc m) $;
theorem znsubpos (m n: nat): $ n <= m -> m -ZN n = b0 (m - n) $;
theorem znsubid (m: nat): $ m -ZN m = 0 $;
theorem znsub02 (a: nat): $ a -ZN 0 = b0 a $;
theorem znsubodd (a b: nat): $ odd (a -ZN b) <-> a < b $;
local def zfst (n: nat): nat = $ case (\ mpos, mpos) (\ mneg, 0) @ n $;
theorem zfsteqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> zfst _n1 = zfst _n2 $;
theorem zfsteq (_n1 _n2: nat): $ _n1 = _n2 -> zfst _n1 = zfst _n2 $;
local def zsnd (n: nat): nat = $ case (\ mpos, 0) (\ mneg, suc mneg) @ n $;
theorem zsndeqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> zsnd _n1 = zsnd _n2 $;
theorem zsndeq (_n1 _n2: nat): $ _n1 = _n2 -> zsnd _n1 = zsnd _n2 $;
theorem zfstb0 (n: nat): $ zfst (b0 n) = n $;
theorem zfstb1 (n: nat): $ zfst (b1 n) = 0 $;
theorem zsndb0 (n: nat): $ zsnd (b0 n) = 0 $;
theorem zsndb1 (n: nat): $ zsnd (b1 n) = suc n $;
theorem zfst0: $ zfst 0 = 0 $;
theorem zsnd0: $ zsnd 0 = 0 $;
theorem zfstsnd (n: nat): $ zfst n -ZN zsnd n = n $;
theorem zfstsndeq0 (n: nat): $ zfst n = 0 /\ zsnd n = 0 <-> n = 0 $;
theorem zfstznsub (m n: nat): $ zfst (m -ZN n) = m - n $;
theorem zfstsnd0 (n: nat): $ zfst n = 0 \/ zsnd n = 0 $;
theorem zfstsubsnd (n: nat): $ zfst n - zsnd n = zfst n $;
theorem zneqb (a b c d: nat): $ a -ZN c = b -ZN d <-> a + d = b + c $;
theorem znpnpcan1 (a b c: nat): $ a + c -ZN (b + c) = a -ZN b $;
theorem znpnpcan2 (a b c: nat): $ a + b -ZN (a + c) = b -ZN c $;
local def zneg (n: nat): nat = $ zsnd n -ZN zfst n $;
prefix zneg: $-uZ$ prec 100;
theorem znegeqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> -uZ _n1 = -uZ _n2 $;
theorem znegeq (_n1 _n2: nat): $ _n1 = _n2 -> -uZ _n1 = -uZ _n2 $;
theorem znegzn (a b: nat): $ -uZ (a -ZN b) = b -ZN a $;
theorem znegneg (n: nat): $ -uZ -uZ n = n $;
theorem zfstneg (n: nat): $ zfst (-uZ n) = zsnd n $;
theorem zsndneg (n: nat): $ zsnd (-uZ n) = zfst n $;
theorem zneg0: $ -uZ 0 = 0 $;
theorem zsndznsub (m n: nat): $ zsnd (m -ZN n) = n - m $;
theorem znegb1 (n: nat): $ -uZ b1 n = b0 (suc n) $;
local def zadd (m n: nat): nat = $ zfst m + zfst n -ZN (zsnd m + zsnd n) $;
infixl zadd: $+Z$ prec 64;
theorem zaddeqd (_G: wff) (_m1 _m2 _n1 _n2: nat): $ _G -> _m1 = _m2 $ > $ _G -> _n1 = _n2 $ > $ _G -> _m1 +Z _n1 = _m2 +Z _n2 $;
theorem zaddeq (_m1 _m2 _n1 _n2: nat): $ _m1 = _m2 -> _n1 = _n2 -> _m1 +Z _n1 = _m2 +Z _n2 $;
theorem zaddeq1d (_G: wff) (_m1 _m2 n: nat): $ _G -> _m1 = _m2 $ > $ _G -> _m1 +Z n = _m2 +Z n $;
theorem zaddeq1 (_m1 _m2 n: nat): $ _m1 = _m2 -> _m1 +Z n = _m2 +Z n $;
theorem zaddeq2d (_G: wff) (m _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> m +Z _n1 = m +Z _n2 $;
theorem zaddeq2 (m _n1 _n2: nat): $ _n1 = _n2 -> m +Z _n1 = m +Z _n2 $;
theorem zaddzn (a b c d: nat): $ a -ZN c +Z (b -ZN d) = a + b -ZN (c + d) $;
theorem zaddb0 (m n: nat): $ b0 m +Z b0 n = b0 (m + n) $;
theorem zaddcom (a b: nat): $ a +Z b = b +Z a $;
theorem zaddass (a b c: nat): $ a +Z b +Z c = a +Z (b +Z c) $;
theorem zaddlass (a b c: nat): $ a +Z (b +Z c) = b +Z (a +Z c) $;
theorem zaddrass (a b c: nat): $ a +Z b +Z c = a +Z c +Z b $;
theorem zadd02 (a: nat): $ a +Z 0 = a $;
theorem zadd01 (a: nat): $ 0 +Z a = a $;
theorem znegid (a: nat): $ a +Z -uZ a = 0 $;
theorem znegid1 (a: nat): $ -uZ a +Z a = 0 $;
local def zsub (m n: nat): nat = $ m +Z -uZ n $;
infixl zsub: $-Z$ prec 64;
theorem zsubeqd (_G: wff) (_m1 _m2 _n1 _n2: nat): $ _G -> _m1 = _m2 $ > $ _G -> _n1 = _n2 $ > $ _G -> _m1 -Z _n1 = _m2 -Z _n2 $;
theorem zsubeq (_m1 _m2 _n1 _n2: nat): $ _m1 = _m2 -> _n1 = _n2 -> _m1 -Z _n1 = _m2 -Z _n2 $;
theorem zsubeq1d (_G: wff) (_m1 _m2 n: nat): $ _G -> _m1 = _m2 $ > $ _G -> _m1 -Z n = _m2 -Z n $;
theorem zsubeq1 (_m1 _m2 n: nat): $ _m1 = _m2 -> _m1 -Z n = _m2 -Z n $;
theorem zsubeq2d (_G: wff) (m _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> m -Z _n1 = m -Z _n2 $;
theorem zsubeq2 (m _n1 _n2: nat): $ _n1 = _n2 -> m -Z _n1 = m -Z _n2 $;
theorem zsubb0 (m n: nat): $ b0 m -Z b0 n = m -ZN n $;
theorem zsubpos (m n: nat): $ n <= m -> b0 m -Z b0 n = b0 (m - n) $;
theorem zsubid (a: nat): $ a -Z a = 0 $;
theorem zsub01 (a: nat): $ 0 -Z a = -uZ a $;
theorem zsub02 (a: nat): $ a -Z 0 = a $;
theorem zpncan (a b: nat): $ a +Z b -Z b = a $;
theorem zpncan2 (a b: nat): $ a +Z b -Z a = b $;
theorem znpcan (a b: nat): $ a -Z b +Z b = a $;
theorem zpncan3 (a b: nat): $ a +Z (b -Z a) = b $;
theorem zaddsubass (a b c: nat): $ a +Z b -Z c = a +Z (b -Z c) $;
theorem zaddsub (a b c: nat): $ a +Z b -Z c = a -Z c +Z b $;
theorem zaddcan1 (a b c: nat): $ a +Z c = b +Z c <-> a = b $;
theorem zaddcan2 (a b c: nat): $ a +Z b = a +Z c <-> b = c $;
theorem eqzsub (a b c: nat): $ a -Z c = b <-> b +Z c = a $;
theorem eqzsub2 (a b c: nat): $ a -Z b = c <-> b +Z c = a $;
theorem eqzneg (a b: nat): $ -uZ a = b <-> a +Z b = 0 $;
theorem znegeqcom (a b: nat): $ -uZ a = b <-> -uZ b = a $;
theorem eqznegcom (a b: nat): $ a = -uZ b <-> b = -uZ a $;
theorem zsubeq0 (a b: nat): $ a -Z b = 0 <-> a = b $;
theorem znegadd2 (a b: nat): $ -uZ (a +Z b) = -uZ a -Z b $;
theorem znegadd (a b: nat): $ -uZ (a +Z b) = -uZ a +Z -uZ b $;
theorem zsubsub (a b c: nat): $ a -Z b -Z c = a -Z (b +Z c) $;
theorem znpncan (a b c: nat): $ a -Z b +Z (b -Z c) = a -Z c $;
theorem znpncan2 (a b c: nat): $ b -Z c +Z (a -Z b) = a -Z c $;
theorem zpnpcan2 (a b c: nat): $ a +Z b -Z (a +Z c) = b -Z c $;
theorem zpnpcan1 (a b c: nat): $ a +Z c -Z (b +Z c) = a -Z b $;
theorem znegsub (a b: nat): $ -uZ (a -Z b) = b -Z a $;
theorem zsubsub2 (a b c: nat): $ a -Z (b -Z c) = a +Z (c -Z b) $;
theorem zsubadd (a b c: nat): $ a -Z b +Z c = a -Z (b -Z c) $;
theorem zsubneg2 (a b: nat): $ a -Z -uZ b = a +Z b $;
theorem znegsub2 (a b: nat): $ -uZ a -Z -uZ b = b -Z a $;
theorem znegb0S (n: nat): $ -uZ b0 (suc n) = b1 n $;
local def zlt (m n: nat): wff = $ odd (m -Z n) $;
infixr zlt: $<Z$ prec 50;
theorem zlteqd (_G: wff) (_m1 _m2 _n1 _n2: nat): $ _G -> _m1 = _m2 $ > $ _G -> _n1 = _n2 $ > $ _G -> (_m1 <Z _n1 <-> _m2 <Z _n2) $;
theorem zlteq (_m1 _m2 _n1 _n2: nat): $ _m1 = _m2 -> _n1 = _n2 -> (_m1 <Z _n1 <-> _m2 <Z _n2) $;
theorem zlteq1d (_G: wff) (_m1 _m2 n: nat): $ _G -> _m1 = _m2 $ > $ _G -> (_m1 <Z n <-> _m2 <Z n) $;
theorem zlteq1 (_m1 _m2 n: nat): $ _m1 = _m2 -> (_m1 <Z n <-> _m2 <Z n) $;
theorem zlteq2d (_G: wff) (m _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> (m <Z _n1 <-> m <Z _n2) $;
theorem zlteq2 (m _n1 _n2: nat): $ _n1 = _n2 -> (m <Z _n1 <-> m <Z _n2) $;
local def zle (m n: nat): wff = $ ~n <Z m $;
infixr zle: $<=Z$ prec 50;
theorem zleeqd (_G: wff) (_m1 _m2 _n1 _n2: nat): $ _G -> _m1 = _m2 $ > $ _G -> _n1 = _n2 $ > $ _G -> (_m1 <=Z _n1 <-> _m2 <=Z _n2) $;
theorem zleeq (_m1 _m2 _n1 _n2: nat): $ _m1 = _m2 -> _n1 = _n2 -> (_m1 <=Z _n1 <-> _m2 <=Z _n2) $;
theorem zleeq1d (_G: wff) (_m1 _m2 n: nat): $ _G -> _m1 = _m2 $ > $ _G -> (_m1 <=Z n <-> _m2 <=Z n) $;
theorem zleeq1 (_m1 _m2 n: nat): $ _m1 = _m2 -> (_m1 <=Z n <-> _m2 <=Z n) $;
theorem zleeq2d (_G: wff) (m _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> (m <=Z _n1 <-> m <=Z _n2) $;
theorem zleeq2 (m _n1 _n2: nat): $ _n1 = _n2 -> (m <=Z _n1 <-> m <=Z _n2) $;
theorem zlenlt (a b: nat): $ a <=Z b <-> ~b <Z a $;
theorem zltnle (a b: nat): $ a <Z b <-> ~b <=Z a $;
theorem zlt01 (a: nat): $ a <Z 0 <-> odd a $;
theorem zle02 (a: nat): $ 0 <=Z a <-> ~odd a $;
theorem zle0b0 (a: nat): $ 0 <=Z b0 a $;
theorem zltb10 (a: nat): $ b1 a <Z 0 $;
theorem zle0b1 (a: nat): $ ~0 <=Z b1 a $;
theorem zltb00 (a: nat): $ ~b0 a <Z 0 $;
theorem zlt01eq (a: nat): $ a <Z 0 <-> a = b1 (a // 2) $;
theorem zle02eq (a: nat): $ 0 <=Z a <-> a = b0 (a // 2) $;
theorem zltb0 (a b: nat): $ b0 a <Z b0 b <-> a < b $;
theorem zleb0 (a b: nat): $ b0 a <=Z b0 b <-> a <= b $;
theorem zltadd1 (a b c: nat): $ a <Z b <-> a +Z c <Z b +Z c $;
theorem zltadd2 (a b c: nat): $ b <Z c <-> a +Z b <Z a +Z c $;
theorem zleadd1 (a b c: nat): $ a <=Z b <-> a +Z c <=Z b +Z c $;
theorem zleadd2 (a b c: nat): $ b <=Z c <-> a +Z b <=Z a +Z c $;
theorem zltaddsub (a b c: nat): $ a +Z b <Z c <-> a <Z c -Z b $;
theorem zltsubadd (a b c: nat): $ a -Z b <Z c <-> a <Z c +Z b $;
theorem zlt0neg (a: nat): $ 0 <Z -uZ a <-> a <Z 0 $;
theorem zltneg0 (a: nat): $ -uZ a <Z 0 <-> 0 <Z a $;
theorem zle0neg (a: nat): $ 0 <=Z -uZ a <-> a <=Z 0 $;
theorem zleneg0 (a: nat): $ -uZ a <=Z 0 <-> 0 <=Z a $;
theorem zlt0sub (a b: nat): $ 0 <Z a -Z b <-> b <Z a $;
theorem zltsub0 (a b: nat): $ a -Z b <Z 0 <-> a <Z b $;
theorem zle0sub (a b: nat): $ 0 <=Z a -Z b <-> b <=Z a $;
theorem zlesub0 (a b: nat): $ a -Z b <=Z 0 <-> a <=Z b $;
theorem zlt0znsub (a b: nat): $ 0 <Z a -ZN b <-> b < a $;
theorem zltznsub0 (a b: nat): $ a -ZN b <Z 0 <-> a < b $;
theorem zle0znsub (a b: nat): $ 0 <=Z a -ZN b <-> b <= a $;
theorem zleznsub0 (a b: nat): $ a -ZN b <=Z 0 <-> a <= b $;
theorem zsndeq0 (a: nat): $ zsnd a = 0 <-> 0 <=Z a $;
theorem zfsteq0 (a: nat): $ zfst a = 0 <-> a <=Z 0 $;
theorem zleorle (a b: nat): $ a <=Z b \/ b <=Z a $;
theorem zltle (a b: nat): $ a <Z b -> a <=Z b $;
theorem zleasymb (a b: nat): $ a = b <-> a <=Z b /\ b <=Z a $;
theorem zleasym (a b: nat): $ a <=Z b -> b <=Z a -> a = b $;
theorem zaddpos (a b: nat): $ 0 <=Z a -> 0 <=Z b -> 0 <=Z a +Z b $;
theorem zletr (a b c: nat): $ a <=Z b -> b <=Z c -> a <=Z c $;
theorem zlelttr (a b c: nat): $ a <=Z b -> b <Z c -> a <Z c $;
theorem zltletr (a b c: nat): $ a <Z b -> b <=Z c -> a <Z c $;
theorem zlttr (a b c: nat): $ a <Z b -> b <Z c -> a <Z c $;
theorem zb0orb0div (a: nat): $ a = b0 (a // 2) \/ a = -uZ b0 (-uZ a // 2) $;
local def zmul (m n: nat): nat = $ zfst m * zfst n + zsnd m * zsnd n -ZN (zfst m * zsnd n + zsnd m * zfst n) $;
infixl zmul: $*Z$ prec 70;
theorem zmuleqd (_G: wff) (_m1 _m2 _n1 _n2: nat): $ _G -> _m1 = _m2 $ > $ _G -> _n1 = _n2 $ > $ _G -> _m1 *Z _n1 = _m2 *Z _n2 $;
theorem zmuleq (_m1 _m2 _n1 _n2: nat): $ _m1 = _m2 -> _n1 = _n2 -> _m1 *Z _n1 = _m2 *Z _n2 $;
theorem zmuleq1d (_G: wff) (_m1 _m2 n: nat): $ _G -> _m1 = _m2 $ > $ _G -> _m1 *Z n = _m2 *Z n $;
theorem zmuleq1 (_m1 _m2 n: nat): $ _m1 = _m2 -> _m1 *Z n = _m2 *Z n $;
theorem zmuleq2d (_G: wff) (m _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> m *Z _n1 = m *Z _n2 $;
theorem zmuleq2 (m _n1 _n2: nat): $ _n1 = _n2 -> m *Z _n1 = m *Z _n2 $;
theorem zmulznlem (a1 b1 c1 d1 a2 b2 c2 d2: nat):
  $ a1 + c2 = a2 + c1 $ >
  $ b1 + d2 = b2 + d1 $ >
  $ a1 * b1 + c1 * d1 + (a2 * d2 + b2 * c2) = a2 * b2 + c2 * d2 + (a1 * d1 + c1 * b1) $;
theorem zmulzn (a b c d: nat): $ (a -ZN c) *Z (b -ZN d) = a * b + c * d -ZN (a * d + b * c) $;
theorem zmulcom (a b: nat): $ a *Z b = b *Z a $;
theorem zmulass (a b c: nat): $ a *Z b *Z c = a *Z (b *Z c) $;
theorem zmuladd (a b c: nat): $ a *Z (b +Z c) = a *Z b +Z a *Z c $;
theorem zaddmul (a b c: nat): $ (a +Z b) *Z c = a *Z c +Z b *Z c $;
theorem zmulsub (a b c: nat): $ a *Z (b -Z c) = a *Z b -Z a *Z c $;
theorem zsubmul (a b c: nat): $ (a -Z b) *Z c = a *Z c -Z b *Z c $;
theorem zmul01 (a: nat): $ 0 *Z a = 0 $;
theorem zmul02 (a: nat): $ a *Z 0 = 0 $;
theorem zmul11 (a: nat): $ b0 1 *Z a = a $;
theorem zmul12 (a: nat): $ a *Z b0 1 = a $;
theorem zmulneg1 (a b: nat): $ -uZ a *Z b = -uZ (a *Z b) $;
theorem zmulneg2 (a b: nat): $ a *Z -uZ b = -uZ (a *Z b) $;
theorem zmul2neg (a b: nat): $ -uZ a *Z -uZ b = a *Z b $;
theorem zmulb0 (a b: nat): $ b0 a *Z b0 b = b0 (a * b) $;
local def zabs (n: nat): nat = $ zfst n + zsnd n $;
theorem zabseqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> zabs _n1 = zabs _n2 $;
theorem zabseq (_n1 _n2: nat): $ _n1 = _n2 -> zabs _n1 = zabs _n2 $;
theorem zabsb0 (n: nat): $ zabs (b0 n) = n $;
theorem zabsneg (n: nat): $ zabs (-uZ n) = zabs n $;
theorem zabszn (m n: nat): $ zabs (m -ZN n) = m - n + (n - m) $;
theorem lezabszn (m n: nat): $ n <= m -> zabs (m -ZN n) = m - n $;
theorem zabscom (m n: nat): $ zabs (m -ZN n) = zabs (n -ZN m) $;
theorem zabseq0 (n: nat): $ zabs n = 0 <-> n = 0 $;
theorem b0zabs (a: nat): $ b0 (zabs a) = a <-> 0 <=Z a $;
theorem zb0orb0 (a: nat): $ a = b0 (zabs a) \/ a = -uZ b0 (zabs a) $;
theorem zabsmul (m n: nat): $ zabs (m *Z n) = zabs m * zabs n $;
theorem eqmdvdsub2 (a b n: nat): $ mod(n): a = b <-> n || zabs (b -ZN a) $;
theorem eqmdvdsub3 (a n: nat): $ mod(n): zfst a = zsnd a <-> n || zabs a $;
local def zdvd (m n: nat): wff = $ zabs m || zabs n $;
infixl zdvd: $|Z$ prec 50;
theorem zdvdeqd (_G: wff) (_m1 _m2 _n1 _n2: nat): $ _G -> _m1 = _m2 $ > $ _G -> _n1 = _n2 $ > $ _G -> (_m1 |Z _n1 <-> _m2 |Z _n2) $;
theorem zdvdeq (_m1 _m2 _n1 _n2: nat): $ _m1 = _m2 -> _n1 = _n2 -> (_m1 |Z _n1 <-> _m2 |Z _n2) $;
theorem zdvdeq1d (_G: wff) (_m1 _m2 n: nat): $ _G -> _m1 = _m2 $ > $ _G -> (_m1 |Z n <-> _m2 |Z n) $;
theorem zdvdeq1 (_m1 _m2 n: nat): $ _m1 = _m2 -> (_m1 |Z n <-> _m2 |Z n) $;
theorem zdvdeq2d (_G: wff) (m _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> (m |Z _n1 <-> m |Z _n2) $;
theorem zdvdeq2 (m _n1 _n2: nat): $ _n1 = _n2 -> (m |Z _n1 <-> m |Z _n2) $;
theorem zdvdid (a: nat): $ a |Z a $;
theorem zdvdtr (a b c: nat): $ a |Z b -> b |Z c -> a |Z c $;
theorem zdvdb0 (a b: nat): $ b0 a |Z b0 b <-> a || b $;
theorem zdvdb01 (a b: nat): $ b0 a |Z b <-> a || zabs b $;
theorem zdvdb02 (a b: nat): $ a |Z b0 b <-> zabs a || b $;
theorem zdvdneg1 (a b: nat): $ -uZ a |Z b <-> a |Z b $;
theorem zdvdneg2 (a b: nat): $ a |Z -uZ b <-> a |Z b $;
theorem eqmzdvdsub (a b n: nat): $ mod(n): a = b <-> b0 n |Z b -ZN a $;
theorem zdvd01 (a: nat): $ 0 |Z a <-> a = 0 $;
theorem zdvd02 (a: nat): $ a |Z 0 $;
theorem zdvd11 (a: nat): $ b0 1 |Z a $;
theorem zdvd12 (a: nat): $ a |Z b0 1 <-> zabs a = 1 $;
theorem zdvdmul1 (a b: nat): $ a |Z b *Z a $;
theorem zdvdmul2 (a b: nat): $ a |Z a *Z b $;
theorem izdvd (a b c: nat): $ c *Z a = b -> a |Z b $;
theorem izdvd2 (a b c: nat): $ a *Z c = b -> a |Z b $;
theorem zdvddef (a b: nat) {c: nat}: $ a |Z b <-> E. c c *Z a = b $;
theorem zdvdadd1 (a b n: nat): $ n |Z a -> (n |Z b <-> n |Z a +Z b) $;
theorem zdvdadd2 (a b n: nat): $ n |Z a -> (n |Z b <-> n |Z b +Z a) $;
theorem zdvdmul12 (a b c: nat): $ a |Z b -> a |Z c *Z b $;
theorem zdvdmul11 (a b c: nat): $ a |Z b -> a |Z b *Z c $;
local def zmod (a n: nat): nat = $ zabs (zfst a + n -ZN zsnd a % n) % n $;
infixl zmod: $%Z$ prec 70;
theorem zmodeqd (_G: wff) (_a1 _a2 _n1 _n2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _n1 = _n2 $ > $ _G -> _a1 %Z _n1 = _a2 %Z _n2 $;
theorem zmodeq (_a1 _a2 _n1 _n2: nat): $ _a1 = _a2 -> _n1 = _n2 -> _a1 %Z _n1 = _a2 %Z _n2 $;
theorem zmodeq1d (_G: wff) (_a1 _a2 n: nat): $ _G -> _a1 = _a2 $ > $ _G -> _a1 %Z n = _a2 %Z n $;
theorem zmodeq1 (_a1 _a2 n: nat): $ _a1 = _a2 -> _a1 %Z n = _a2 %Z n $;
theorem zmodeq2d (_G: wff) (a _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> a %Z _n1 = a %Z _n2 $;
theorem zmodeq2 (a _n1 _n2: nat): $ _n1 = _n2 -> a %Z _n1 = a %Z _n2 $;
theorem zmod02 (a: nat): $ a %Z 0 = zabs a $;
theorem zmodb00 (a: nat): $ b0 a %Z 0 = a $;
theorem zmodn02 (a n: nat): $ n != 0 -> a %Z n = (zfst a + n - zsnd a % n) % n $;
theorem zmodb0 (a n: nat): $ b0 a %Z n = a % n $;
theorem zmodb1 (a n: nat): $ a < n -> b1 a %Z n = n - suc a $;
theorem zmod01 (a: nat): $ 0 %Z a = 0 $;
theorem zmodmodid (a n: nat): $ a %Z n % n = a %Z n $;
theorem zmodeq0 (a n: nat): $ a %Z n = 0 <-> b0 n |Z a $;
local def zeqm (n a b: nat): wff = $ b0 n |Z a -Z b $;
notation zeqm (n a b: nat): wff = ($modZ($:50) n ($):$:50) a ($=$:50) b;
theorem zeqmeqd (_G: wff) (_n1 _n2 _a1 _a2 _b1 _b2: nat):
  $ _G -> _n1 = _n2 $ >
  $ _G -> _a1 = _a2 $ >
  $ _G -> _b1 = _b2 $ >
  $ _G -> (modZ(_n1): _a1 = _b1 <-> modZ(_n2): _a2 = _b2) $;
theorem zeqmeq (_n1 _n2 _a1 _a2 _b1 _b2: nat): $ _n1 = _n2 -> _a1 = _a2 -> _b1 = _b2 -> (modZ(_n1): _a1 = _b1 <-> modZ(_n2): _a2 = _b2) $;
theorem zeqmeq1d (_G: wff) (_n1 _n2 a b: nat): $ _G -> _n1 = _n2 $ > $ _G -> (modZ(_n1): a = b <-> modZ(_n2): a = b) $;
theorem zeqmeq1 (_n1 _n2 a b: nat): $ _n1 = _n2 -> (modZ(_n1): a = b <-> modZ(_n2): a = b) $;
theorem zeqmeq2d (_G: wff) (n _a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> (modZ(n): _a1 = b <-> modZ(n): _a2 = b) $;
theorem zeqmeq2 (n _a1 _a2 b: nat): $ _a1 = _a2 -> (modZ(n): _a1 = b <-> modZ(n): _a2 = b) $;
theorem zeqmeq3d (_G: wff) (n a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> (modZ(n): a = _b1 <-> modZ(n): a = _b2) $;
theorem zeqmeq3 (n a _b1 _b2: nat): $ _b1 = _b2 -> (modZ(n): a = _b1 <-> modZ(n): a = _b2) $;
theorem zeqmid (a n: nat): $ modZ(n): a = a $;
theorem zeqmidd (G: wff) (a n: nat): $ G -> modZ(n): a = a $;
theorem zeqmtr (a b c n: nat): $ modZ(n): a = b -> modZ(n): b = c -> modZ(n): a = c $;
theorem zeqmtrd (G: wff) (a b c n: nat): $ G -> modZ(n): a = b $ > $ G -> modZ(n): b = c $ > $ G -> modZ(n): a = c $;
theorem zeqmcomb (a b n: nat): $ modZ(n): a = b <-> modZ(n): b = a $;
theorem zeqmcom (a b n: nat): $ modZ(n): a = b -> modZ(n): b = a $;
theorem zeqmcomd (G: wff) (a b n: nat): $ G -> modZ(n): a = b $ > $ G -> modZ(n): b = a $;
theorem zeqmtr4d (G: wff) (a b c n: nat): $ G -> modZ(n): a = b $ > $ G -> modZ(n): c = b $ > $ G -> modZ(n): a = c $;
theorem zeqmtr3d (G: wff) (a b c n: nat): $ G -> modZ(n): b = a $ > $ G -> modZ(n): b = c $ > $ G -> modZ(n): a = c $;
theorem eqzeqm (a b n: nat): $ a = b -> modZ(n): a = b $;
theorem eqzeqmd (G: wff) (a b n: nat): $ G -> a = b $ > $ G -> modZ(n): a = b $;
theorem zeqmeqm (a b n: nat): $ modZ(n): b0 a = b0 b <-> mod(n): a = b $;
theorem zeqm03 (a n: nat): $ modZ(n): a = 0 <-> b0 n |Z a $;
theorem zeqmznsub (a b n: nat): $ modZ(n): a -ZN b = 0 <-> mod(n): a = b $;
theorem zeqmsub (a b n: nat): $ modZ(n): a -Z b = 0 <-> modZ(n): a = b $;
theorem zeqmid0 (n: nat): $ modZ(n): b0 n = 0 $;
theorem zeqm01 (a b: nat): $ modZ(0): a = b <-> a = b $;
theorem zeqmeqm23d (G: wff) (a b c d n: nat): $ G -> modZ(n): a = b $ > $ G -> modZ(n): c = d $ > $ G -> (modZ(n): a = c <-> modZ(n): b = d) $;
theorem zeqmeqm2 (a b c n: nat): $ modZ(n): a = b -> (modZ(n): a = c <-> modZ(n): b = c) $;
theorem zeqmeqm3 (a b c n: nat): $ modZ(n): b = c -> (modZ(n): a = b <-> modZ(n): a = c) $;
theorem zeqmadd1 (a b c n: nat): $ modZ(n): a +Z c = b +Z c <-> modZ(n): a = b $;
theorem zeqmadd2 (a b c n: nat): $ modZ(n): a +Z b = a +Z c <-> modZ(n): b = c $;
theorem zeqmadd1d (G: wff) (a b c n: nat): $ G -> modZ(n): a = b $ > $ G -> modZ(n): a +Z c = b +Z c $;
theorem zeqmadd2d (G: wff) (a b c n: nat): $ G -> modZ(n): b = c $ > $ G -> modZ(n): a +Z b = a +Z c $;
theorem zeqmaddd (G: wff) (a b c d n: nat): $ G -> modZ(n): a = b $ > $ G -> modZ(n): c = d $ > $ G -> modZ(n): a +Z c = b +Z d $;
theorem zeqmneg (a b n: nat): $ modZ(n): -uZ a = -uZ b <-> modZ(n): a = b $;
theorem zeqmsub1 (a b c n: nat): $ modZ(n): a -Z c = b -Z c <-> modZ(n): a = b $;
theorem zeqmsub2 (a b c n: nat): $ modZ(n): a -Z b = a -Z c <-> modZ(n): b = c $;
theorem zeqmsubd (G: wff) (a b c d n: nat): $ G -> modZ(n): a = b $ > $ G -> modZ(n): c = d $ > $ G -> modZ(n): a -Z c = b -Z d $;
theorem zeqmznsub1 (a b c n: nat): $ modZ(n): a -ZN c = b -ZN c <-> mod(n): a = b $;
theorem zeqmznsub2 (a b c n: nat): $ modZ(n): a -ZN b = a -ZN c <-> mod(n): b = c $;
theorem zeqmznsubd (G: wff) (a b c d n: nat): $ G -> mod(n): a = b $ > $ G -> mod(n): c = d $ > $ G -> modZ(n): a -ZN c = b -ZN d $;
theorem zeqmaddn (a n: nat): $ modZ(n): a +Z b0 n = a $;
theorem zeqmmod (a n: nat): $ n != 0 -> modZ(n): b0 (a %Z n) = a $;
theorem zmodeqmod (a b n: nat): $ n != 0 -> (a %Z n = b %Z n <-> modZ(n): a = b) $;
theorem dvdzeqm (G: wff) (a b m n: nat): $ G -> m || n $ > $ G -> modZ(n): a = b $ > $ G -> modZ(m): a = b $;
theorem zeqm11 (a b: nat): $ modZ(1): a = b $;
local def gcd (a b: nat): nat = $ the {d | A. x (x || d <-> x || a /\ x || b)} $;
theorem gcdeqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> gcd _a1 _b1 = gcd _a2 _b2 $;
theorem gcdeq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> gcd _a1 _b1 = gcd _a2 _b2 $;
theorem gcdeq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> gcd _a1 b = gcd _a2 b $;
theorem gcdeq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> gcd _a1 b = gcd _a2 b $;
theorem gcdeq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> gcd a _b1 = gcd a _b2 $;
theorem gcdeq2 (a _b1 _b2: nat): $ _b1 = _b2 -> gcd a _b1 = gcd a _b2 $;
theorem gcdcom (a b: nat): $ gcd a b = gcd b a $;
theorem eqgcd (G: wff) (a b d: nat) {x: nat}: $ G -> (x || d <-> x || a /\ x || b) $ > $ G -> gcd a b = d $;
theorem gcd00: $ gcd 0 0 = 0 $;
local def bgcd (a b: nat): nat = $ least {d | 0 < d /\ E. x E. y x * a = y * b + d} $;
theorem bgcdeqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> bgcd _a1 _b1 = bgcd _a2 _b2 $;
theorem bgcdeq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> bgcd _a1 _b1 = bgcd _a2 _b2 $;
theorem bgcdeq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> bgcd _a1 b = bgcd _a2 b $;
theorem bgcdeq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> bgcd _a1 b = bgcd _a2 b $;
theorem bgcdeq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> bgcd a _b1 = bgcd a _b2 $;
theorem bgcdeq2 (a _b1 _b2: nat): $ _b1 = _b2 -> bgcd a _b1 = bgcd a _b2 $;
theorem dfbgcd (a b: nat) {d x y: nat}: $ bgcd a b = least {d | 0 < d /\ E. x E. y x * a = y * b + d} $;
theorem bgcd01 (b: nat): $ bgcd 0 b = 0 $;
theorem bgcdlem (a b: nat) {x y: nat}: $ a != 0 -> 0 < bgcd a b /\ E. x E. y x * a = y * b + bgcd a b $;
theorem bgcdpos (a b: nat): $ a != 0 -> 0 < bgcd a b $;
theorem bgcdbezout (a b: nat) {x y: nat}: $ E. x E. y x * a = y * b + bgcd a b $;
theorem bgcdled (G: wff) (a b d x y: nat): $ G -> 0 < d $ > $ G -> x * a = y * b + d $ > $ G -> bgcd a b <= d $;
theorem bgcd02 (a: nat): $ bgcd a 0 = a $;
theorem dvdbgcd (a b d: nat): $ d || a /\ d || b -> d || bgcd a b $;
theorem bgcddvd1lem (G: wff) (a b d q r u x y: nat):
  $ G -> a != 0 $ >
  $ G -> x * a = y * b + d $ >
  $ G -> b != 0 $ >
  $ G -> d * q + r = a $ >
  $ G -> x <= u $ >
  $ G -> y <= u $ >
  $ G -> suc ((u * b - x) * q) * a = (u * a - y) * q * b + r $;
theorem bgcddvd2lem (G: wff) (a b d q r u x y: nat):
  $ G -> a != 0 $ >
  $ G -> x * a = y * b + d $ >
  $ G -> b != 0 $ >
  $ G -> d * q + r = b $ >
  $ G -> x * q <= u $ >
  $ G -> y * q < u $ >
  $ G -> (u * b - x * q) * a = (u * a - suc (y * q)) * b + r $;
theorem bgcddvd1 (a b: nat): $ bgcd a b || a $;
theorem bgcddvd2 (a b: nat): $ a != 0 -> bgcd a b || b $;
theorem dvdbgcdb (a b d: nat): $ a != 0 -> (d || bgcd a b <-> d || a /\ d || b) $;
theorem gcdbgcd (a b: nat): $ a != 0 -> gcd a b = bgcd a b $;
theorem gcd01 (b: nat): $ gcd 0 b = b $;
theorem dvdgcdlem (G: wff) (a b c d: nat) {x: nat}: $ G -> (x || d <-> x || a /\ x || b) $ > $ G -> (c || gcd a b <-> c || a /\ c || b) $;
theorem dvdgcd (a b d: nat): $ d || gcd a b <-> d || a /\ d || b $;
theorem gcddvd1 (a b: nat): $ gcd a b || a $;
theorem gcddvd2 (a b: nat): $ gcd a b || b $;
theorem gcd02 (a: nat): $ gcd a 0 = a $;
theorem bezout (a b: nat) {x y: nat}: $ a != 0 -> E. x E. y x * a = y * b + gcd a b $;
local def coprime (a b: nat): wff = $ gcd a b = 1 $;
theorem coprimeeqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> (coprime _a1 _b1 <-> coprime _a2 _b2) $;
theorem coprimeeq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> (coprime _a1 _b1 <-> coprime _a2 _b2) $;
theorem coprimeeq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> (coprime _a1 b <-> coprime _a2 b) $;
theorem coprimeeq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> (coprime _a1 b <-> coprime _a2 b) $;
theorem coprimeeq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> (coprime a _b1 <-> coprime a _b2) $;
theorem coprimeeq2 (a _b1 _b2: nat): $ _b1 = _b2 -> (coprime a _b1 <-> coprime a _b2) $;
theorem copcom (a b: nat): $ coprime a b <-> coprime b a $;
theorem dvdcop (G: wff) (a b d: nat): $ G -> coprime a b $ > $ G -> d || a $ > $ G -> d || b $ > $ G -> d = 1 $;
theorem dfcop2 (a b: nat) {x: nat}: $ coprime a b <-> A. x (x || a -> x || b -> x = 1) $;
theorem copbezout (G: wff) (a b: nat) {x y: nat}: $ G -> coprime a b $ > $ G -> a != 0 $ > $ G -> E. x E. y x * a = y * b + 1 $;
theorem copdvdmul2 (G: wff) (a b c: nat): $ G -> coprime a b $ > $ G -> a || b * c $ > $ G -> a || c $;
theorem copdvdmul1 (G: wff) (a b c: nat): $ G -> coprime a c $ > $ G -> a || b * c $ > $ G -> a || b $;
local def invm (a n: nat): nat = $ least {b | mod(n): a * b = 1} $;
theorem invmeqd (_G: wff) (_a1 _a2 _n1 _n2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _n1 = _n2 $ > $ _G -> invm _a1 _n1 = invm _a2 _n2 $;
theorem invmeq (_a1 _a2 _n1 _n2: nat): $ _a1 = _a2 -> _n1 = _n2 -> invm _a1 _n1 = invm _a2 _n2 $;
theorem invmeq1d (_G: wff) (_a1 _a2 n: nat): $ _G -> _a1 = _a2 $ > $ _G -> invm _a1 n = invm _a2 n $;
theorem invmeq1 (_a1 _a2 n: nat): $ _a1 = _a2 -> invm _a1 n = invm _a2 n $;
theorem invmeq2d (_G: wff) (a _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> invm a _n1 = invm a _n2 $;
theorem invmeq2 (a _n1 _n2: nat): $ _n1 = _n2 -> invm a _n1 = invm a _n2 $;
theorem mulinvmlem (G: wff) (a b n: nat): $ G -> mod(n): a * b = 1 $ > $ G -> mod(n): a * invm a n = 1 $;
theorem mulinvm (G: wff) (a n: nat): $ G -> coprime a n $ > $ G -> mod(n): a * invm a n = 1 $;
local def pset (a: nat): set = $ {n | 0 < fst a /\ 0 < snd a /\ A. x (0 < x /\ x <= n -> x || fst a) /\ suc (fst a * suc n) || snd a} $;
theorem pseteqd (_G: wff) (_a1 _a2: nat): $ _G -> _a1 = _a2 $ > $ _G -> pset _a1 == pset _a2 $;
theorem pseteq (_a1 _a2: nat): $ _a1 = _a2 -> pset _a1 == pset _a2 $;
theorem elpset (m n v: nat) {x: nat}: $ n e. pset (m, v) <-> 0 < m /\ 0 < v /\ A. x (0 < x /\ x <= n -> x || m) /\ suc (m * suc n) || v $;
theorem elpset1 (m n: nat): $ ~n e. pset (m, 1) $;
theorem psetSlem1 (G: wff) (i j m n: nat) {x: nat}:
  $ G -> A. x (0 < x /\ x < n -> x || m) $ >
  $ G -> i < j $ >
  $ G -> j < n $ >
  $ G -> coprime (suc (m * suc i)) (suc (m * suc j)) $;
theorem psetSlem2 (G: wff) (a b m n: nat) {x: nat}:
  $ G -> A. x (0 < x /\ x < n -> x || m) $ >
  $ G -> a != b $ >
  $ G -> a < n $ >
  $ G -> b < n $ >
  $ G -> coprime (suc (m * suc a)) (suc (m * suc b)) $;
theorem psetS (G: wff) (a m n v: nat) {x: nat}:
  $ G -> 0 < m $ >
  $ G -> 0 < v $ >
  $ G -> A. x (0 < x /\ x <= n -> x || m) $ >
  $ G -> (a e. pset (m, v * suc (m * suc n)) <-> a e. pset (m, v) \/ a = n) $;
theorem lcmex {m: nat} (n: nat) {x: nat}: $ E. m (0 < m /\ A. x (0 < x /\ x <= n -> x || m)) $;
theorem psetsep {b: nat} (n: nat) {x: nat} (p: wff x): $ E. b pset b == {x | x < n /\ p} $;
theorem expset (A: set) {a: nat}: $ finite A <-> E. a pset a == A $;
theorem psetfn {a x: nat} (p: wff x) (v: nat x): $ finite {x | p} -> E. a A. x (p -> pset a @ x = v) $;

Simple recursion operator:

  • rec 0 = z
  • rec (n+1) = S (rec n)
abstract def rec (z: nat) (S: set) (n: nat): nat = $ the {v | E. a (pset a @ 0 = z /\ pset a @ n = v /\ A. i (i < n -> pset a @ suc i = S @ (pset a @ i)))} $;
theorem receqd (_G: wff) (_z1 _z2: nat) (_S1 _S2: set) (_n1 _n2: nat):
  $ _G -> _z1 = _z2 $ >
  $ _G -> _S1 == _S2 $ >
  $ _G -> _n1 = _n2 $ >
  $ _G -> rec _z1 _S1 _n1 = rec _z2 _S2 _n2 $;
theorem receq (_z1 _z2: nat) (_S1 _S2: set) (_n1 _n2: nat): $ _z1 = _z2 -> _S1 == _S2 -> _n1 = _n2 -> rec _z1 _S1 _n1 = rec _z2 _S2 _n2 $;
theorem receq1d (_G: wff) (_z1 _z2: nat) (S: set) (n: nat): $ _G -> _z1 = _z2 $ > $ _G -> rec _z1 S n = rec _z2 S n $;
theorem receq1 (_z1 _z2: nat) (S: set) (n: nat): $ _z1 = _z2 -> rec _z1 S n = rec _z2 S n $;
theorem receq2d (_G: wff) (z: nat) (_S1 _S2: set) (n: nat): $ _G -> _S1 == _S2 $ > $ _G -> rec z _S1 n = rec z _S2 n $;
theorem receq2 (z: nat) (_S1 _S2: set) (n: nat): $ _S1 == _S2 -> rec z _S1 n = rec z _S2 n $;
theorem receq3d (_G: wff) (z: nat) (S: set) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> rec z S _n1 = rec z S _n2 $;
theorem receq3 (z: nat) (S: set) (_n1 _n2: nat): $ _n1 = _n2 -> rec z S _n1 = rec z S _n2 $;
theorem reclem (G: wff) (S: set) (a n v z: nat) {i: nat}:
  $ G -> pset a @ 0 = z $ >
  $ G -> pset a @ n = v $ >
  $ G -> A. i (i < n -> pset a @ suc i = S @ (pset a @ i)) $ >
  $ G -> rec z S n = v $;
pub theorem rec0 (z: nat) (S: set): $ rec z S 0 = z $;
pub theorem recS (z: nat) (S: set) (n: nat): $ rec z S (suc n) = S @ rec z S n $;
local def recnaux (z: nat) (S: set) (n: nat): nat = $ rec (0, z) (\ p, suc (fst p), S @ p) n $;
theorem recnauxeqd (_G: wff) (_z1 _z2: nat) (_S1 _S2: set) (_n1 _n2: nat):
  $ _G -> _z1 = _z2 $ >
  $ _G -> _S1 == _S2 $ >
  $ _G -> _n1 = _n2 $ >
  $ _G -> recnaux _z1 _S1 _n1 = recnaux _z2 _S2 _n2 $;
theorem recnauxeq (_z1 _z2: nat) (_S1 _S2: set) (_n1 _n2: nat): $ _z1 = _z2 -> _S1 == _S2 -> _n1 = _n2 -> recnaux _z1 _S1 _n1 = recnaux _z2 _S2 _n2 $;
theorem recnauxeq1d (_G: wff) (_z1 _z2: nat) (S: set) (n: nat): $ _G -> _z1 = _z2 $ > $ _G -> recnaux _z1 S n = recnaux _z2 S n $;
theorem recnauxeq1 (_z1 _z2: nat) (S: set) (n: nat): $ _z1 = _z2 -> recnaux _z1 S n = recnaux _z2 S n $;
theorem recnauxeq2d (_G: wff) (z: nat) (_S1 _S2: set) (n: nat): $ _G -> _S1 == _S2 $ > $ _G -> recnaux z _S1 n = recnaux z _S2 n $;
theorem recnauxeq2 (z: nat) (_S1 _S2: set) (n: nat): $ _S1 == _S2 -> recnaux z _S1 n = recnaux z _S2 n $;
theorem recnauxeq3d (_G: wff) (z: nat) (S: set) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> recnaux z S _n1 = recnaux z S _n2 $;
theorem recnauxeq3 (z: nat) (S: set) (_n1 _n2: nat): $ _n1 = _n2 -> recnaux z S _n1 = recnaux z S _n2 $;
theorem recnaux0 (S: set) (z: nat): $ recnaux z S 0 = 0, z $;
theorem recnauxS2 (S: set) (n z: nat): $ recnaux z S (suc n) = suc (fst (recnaux z S n)), S @ recnaux z S n $;
theorem recnauxfst (S: set) (n z: nat): $ fst (recnaux z S n) = n $;

Recursion operator with iteration variable:

  • recn 0 = z
  • recn (n+1) = S (n, recn n)
local def recn (z: nat) (S: set) (n: nat): nat = $ snd (recnaux z S n) $;
theorem recneqd (_G: wff) (_z1 _z2: nat) (_S1 _S2: set) (_n1 _n2: nat):
  $ _G -> _z1 = _z2 $ >
  $ _G -> _S1 == _S2 $ >
  $ _G -> _n1 = _n2 $ >
  $ _G -> recn _z1 _S1 _n1 = recn _z2 _S2 _n2 $;
theorem recneq (_z1 _z2: nat) (_S1 _S2: set) (_n1 _n2: nat): $ _z1 = _z2 -> _S1 == _S2 -> _n1 = _n2 -> recn _z1 _S1 _n1 = recn _z2 _S2 _n2 $;
theorem recneq1d (_G: wff) (_z1 _z2: nat) (S: set) (n: nat): $ _G -> _z1 = _z2 $ > $ _G -> recn _z1 S n = recn _z2 S n $;
theorem recneq1 (_z1 _z2: nat) (S: set) (n: nat): $ _z1 = _z2 -> recn _z1 S n = recn _z2 S n $;
theorem recneq2d (_G: wff) (z: nat) (_S1 _S2: set) (n: nat): $ _G -> _S1 == _S2 $ > $ _G -> recn z _S1 n = recn z _S2 n $;
theorem recneq2 (z: nat) (_S1 _S2: set) (n: nat): $ _S1 == _S2 -> recn z _S1 n = recn z _S2 n $;
theorem recneq3d (_G: wff) (z: nat) (S: set) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> recn z S _n1 = recn z S _n2 $;
theorem recneq3 (z: nat) (S: set) (_n1 _n2: nat): $ _n1 = _n2 -> recn z S _n1 = recn z S _n2 $;
theorem recn0 (S: set) (z: nat): $ recn z S 0 = z $;
theorem recnS (S: set) (n z: nat): $ recn z S (suc n) = S @ (n, recn z S n) $;
local def ocase (z: nat) (S: set): set = $ \ n, recn z (\ i, S @ fst i) n $;
theorem ocaseeqd (_G: wff) (_z1 _z2: nat) (_S1 _S2: set): $ _G -> _z1 = _z2 $ > $ _G -> _S1 == _S2 $ > $ _G -> ocase _z1 _S1 == ocase _z2 _S2 $;
theorem ocaseeq (_z1 _z2: nat) (_S1 _S2: set): $ _z1 = _z2 -> _S1 == _S2 -> ocase _z1 _S1 == ocase _z2 _S2 $;
theorem ocaseeq1d (_G: wff) (_z1 _z2: nat) (S: set): $ _G -> _z1 = _z2 $ > $ _G -> ocase _z1 S == ocase _z2 S $;
theorem ocaseeq1 (_z1 _z2: nat) (S: set): $ _z1 = _z2 -> ocase _z1 S == ocase _z2 S $;
theorem ocaseeq2d (_G: wff) (z: nat) (_S1 _S2: set): $ _G -> _S1 == _S2 $ > $ _G -> ocase z _S1 == ocase z _S2 $;
theorem ocaseeq2 (z: nat) (_S1 _S2: set): $ _S1 == _S2 -> ocase z _S1 == ocase z _S2 $;
theorem ocaseval (S: set) {i: nat} (n z: nat): $ ocase z S @ n = recn z (\ i, S @ fst i) n $;
theorem ocase0 (S: set) (z: nat): $ ocase z S @ 0 = z $;
theorem ocaseS (S: set) (n z: nat): $ ocase z S @ suc n = S @ n $;
local def ocasep (z: wff) (S: set): set = $ {n | ifp (n = 0) z (n - 1 e. S)} $;
theorem ocasepeqd (_G _z1 _z2: wff) (_S1 _S2: set): $ _G -> (_z1 <-> _z2) $ > $ _G -> _S1 == _S2 $ > $ _G -> ocasep _z1 _S1 == ocasep _z2 _S2 $;
theorem ocasepeq (_z1 _z2: wff) (_S1 _S2: set): $ (_z1 <-> _z2) -> _S1 == _S2 -> ocasep _z1 _S1 == ocasep _z2 _S2 $;
theorem ocasepeq1d (_G _z1 _z2: wff) (S: set): $ _G -> (_z1 <-> _z2) $ > $ _G -> ocasep _z1 S == ocasep _z2 S $;
theorem ocasepeq1 (_z1 _z2: wff) (S: set): $ (_z1 <-> _z2) -> ocasep _z1 S == ocasep _z2 S $;
theorem ocasepeq2d (_G z: wff) (_S1 _S2: set): $ _G -> _S1 == _S2 $ > $ _G -> ocasep z _S1 == ocasep z _S2 $;
theorem ocasepeq2 (z: wff) (_S1 _S2: set): $ _S1 == _S2 -> ocasep z _S1 == ocasep z _S2 $;
theorem ocasep0 (S: set) (z: wff): $ 0 e. ocasep z S <-> z $;
theorem ocasepS (S: set) (n: nat) (z: wff): $ suc n e. ocasep z S <-> n e. S $;
local def Tail (S: set): set = $ {n | suc n e. S} $;
theorem Taileqd (_G: wff) (_S1 _S2: set): $ _G -> _S1 == _S2 $ > $ _G -> Tail _S1 == Tail _S2 $;
theorem Taileq (_S1 _S2: set): $ _S1 == _S2 -> Tail _S1 == Tail _S2 $;
theorem elTail (S: set) (n: nat): $ n e. Tail S <-> suc n e. S $;
theorem Tail_ocasep (S: set) (z: wff): $ Tail (ocasep z S) == S $;
theorem ocasep_Tail (S: set): $ ocasep (0 e. S) (Tail S) == S $;

The "bind" operator for the option monad, obind : Option A -> (A -> Option B) -> Option B.

  • obind none F = none
  • obind (some a) F = F a
abstract def obind (a: nat) (F: set): nat = $ ocase 0 F @ a $;
theorem obindeqd (_G: wff) (_a1 _a2: nat) (_F1 _F2: set): $ _G -> _a1 = _a2 $ > $ _G -> _F1 == _F2 $ > $ _G -> obind _a1 _F1 = obind _a2 _F2 $;
theorem obindeq (_a1 _a2: nat) (_F1 _F2: set): $ _a1 = _a2 -> _F1 == _F2 -> obind _a1 _F1 = obind _a2 _F2 $;
theorem obindeq1d (_G: wff) (_a1 _a2: nat) (F: set): $ _G -> _a1 = _a2 $ > $ _G -> obind _a1 F = obind _a2 F $;
theorem obindeq1 (_a1 _a2: nat) (F: set): $ _a1 = _a2 -> obind _a1 F = obind _a2 F $;
theorem obindeq2d (_G: wff) (a: nat) (_F1 _F2: set): $ _G -> _F1 == _F2 $ > $ _G -> obind a _F1 = obind a _F2 $;
theorem obindeq2 (a: nat) (_F1 _F2: set): $ _F1 == _F2 -> obind a _F1 = obind a _F2 $;
pub theorem obind0 (F: set): $ obind 0 F = 0 $;
pub theorem obindS (n: nat) (F: set): $ obind (suc n) F = F @ n $;
theorem obindS2 (n: nat) {x: nat}: $ obind n (\ x, suc x) = n $;
theorem obindeqS (F: set) (a: nat) {m: nat} (n: nat): $ obind n F = suc a <-> E. m (n = suc m /\ F @ m = suc a) $;

The power function on natural numbers.

  • a ^ 0 = 1
  • a ^ suc b = a * a ^ b
abstract def pow (a b: nat): nat = $ rec 1 (\ n, a * n) b $;
infixr pow: $^$ prec 81;
theorem poweqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> _a1 ^ _b1 = _a2 ^ _b2 $;
theorem poweq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> _a1 ^ _b1 = _a2 ^ _b2 $;
theorem poweq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> _a1 ^ b = _a2 ^ b $;
theorem poweq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> _a1 ^ b = _a2 ^ b $;
theorem poweq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> a ^ _b1 = a ^ _b2 $;
theorem poweq2 (a _b1 _b2: nat): $ _b1 = _b2 -> a ^ _b1 = a ^ _b2 $;
pub theorem pow0 (a: nat): $ a ^ 0 = 1 $;
pub theorem powS (a b: nat): $ a ^ suc b = a * a ^ b $;
theorem powS2 (a b: nat): $ a ^ suc b = a ^ b * a $;
theorem pow12 (a: nat): $ a ^ 1 = a $;
theorem pow22 (a: nat): $ a ^ 2 = a * a $;
theorem pow11 (b: nat): $ 1 ^ b = 1 $;
theorem powpos (a b: nat): $ 0 < a -> 0 < a ^ b $;
theorem powne0 (a b: nat): $ a != 0 -> a ^ b != 0 $;
theorem pow2ne0 (b: nat): $ 2 ^ b != 0 $;
theorem powltid2 (a b: nat): $ 1 < a -> b < a ^ b $;
theorem powadd (a b c: nat): $ a ^ (b + c) = a ^ b * a ^ c $;
theorem powmul (a b c: nat): $ a ^ (b * c) = (a ^ b) ^ c $;
theorem powdvd (a b c: nat): $ b <= c -> a ^ b || a ^ c $;
theorem powdvd1 (a b: nat): $ 0 < b -> a || a ^ b $;
theorem lepow2a (a b c: nat): $ a != 0 -> b <= c -> a ^ b <= a ^ c $;
theorem ltpow2 (a b c: nat): $ 1 < a -> (b < c <-> a ^ b < a ^ c) $;
theorem lepow2 (a b c: nat): $ 1 < a -> (b <= c <-> a ^ b <= a ^ c) $;

Left shift for natural numbers: shl a n = a * 2 ^ n.

def shl (a n: nat): nat = $ a * 2 ^ n $;
theorem shleqd (_G: wff) (_a1 _a2 _n1 _n2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _n1 = _n2 $ > $ _G -> shl _a1 _n1 = shl _a2 _n2 $;
theorem shleq (_a1 _a2 _n1 _n2: nat): $ _a1 = _a2 -> _n1 = _n2 -> shl _a1 _n1 = shl _a2 _n2 $;
theorem shleq1d (_G: wff) (_a1 _a2 n: nat): $ _G -> _a1 = _a2 $ > $ _G -> shl _a1 n = shl _a2 n $;
theorem shleq1 (_a1 _a2 n: nat): $ _a1 = _a2 -> shl _a1 n = shl _a2 n $;
theorem shleq2d (_G: wff) (a _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> shl a _n1 = shl a _n2 $;
theorem shleq2 (a _n1 _n2: nat): $ _n1 = _n2 -> shl a _n1 = shl a _n2 $;

Right shift for natural numbers: shr a n = a // 2 ^ n.

def shr (a n: nat): nat = $ a // 2 ^ n $;
theorem shreqd (_G: wff) (_a1 _a2 _n1 _n2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _n1 = _n2 $ > $ _G -> shr _a1 _n1 = shr _a2 _n2 $;
theorem shreq (_a1 _a2 _n1 _n2: nat): $ _a1 = _a2 -> _n1 = _n2 -> shr _a1 _n1 = shr _a2 _n2 $;
theorem shreq1d (_G: wff) (_a1 _a2 n: nat): $ _G -> _a1 = _a2 $ > $ _G -> shr _a1 n = shr _a2 n $;
theorem shreq1 (_a1 _a2 n: nat): $ _a1 = _a2 -> shr _a1 n = shr _a2 n $;
theorem shreq2d (_G: wff) (a _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> shr a _n1 = shr a _n2 $;
theorem shreq2 (a _n1 _n2: nat): $ _n1 = _n2 -> shr a _n1 = shr a _n2 $;
theorem shl01 (b: nat): $ shl 0 b = 0 $;
theorem shl02 (a: nat): $ shl a 0 = a $;
theorem shl11 (b: nat): $ shl 1 b = 2 ^ b $;
theorem shl12 (a: nat): $ shl a 1 = b0 a $;
theorem shlshl (a b c: nat): $ shl (shl a b) c = shl a (b + c) $;
theorem shladd (a b c: nat): $ shl (a + b) c = shl a c + shl b c $;
theorem shlpow2dvd (a b: nat): $ 2 ^ b || shl a b $;
theorem shl2dvd (a b: nat): $ 0 < b -> 2 || shl a b $;
theorem shr01 (b: nat): $ shr 0 b = 0 $;
theorem shr02 (a: nat): $ shr a 0 = a $;
theorem shr12 (a: nat): $ shr a 1 = a // 2 $;
theorem shrshr (a b c: nat): $ shr (shr a b) c = shr a (b + c) $;
theorem shrmodadd1 (a b c: nat): $ shr (a % 2 ^ (b + c)) b = shr a b % 2 ^ c $;
theorem shrmodadd2 (a b c: nat): $ shr (a % 2 ^ (b + c)) c = shr a c % 2 ^ b $;
theorem shrmodsub (a b c: nat): $ c <= b -> shr (a % 2 ^ b) c = shr a c % 2 ^ (b - c) $;
theorem shrshladd (a b c: nat): $ shr (shl a b + c) b = a + shr c b $;
theorem shrshladdid (a b c: nat): $ c < 2 ^ b -> shr (shl a b + c) b = a $;
theorem shrshlid (a b: nat): $ shr (shl a b) b = a $;
theorem shrshl1 (a b c: nat): $ c <= b -> shr (shl a b) c = shl a (b - c) $;
theorem shrshl2 (a b c: nat): $ b <= c -> shr (shl a b) c = shr a (c - b) $;
theorem shreq0 (a b: nat): $ shr a b = 0 <-> a < 2 ^ b $;

Lift a natural number to a set, via a ~> {x | odd (shr a x)}. That is, x e. a if the x'th bit of a is 1. This mapping is injective, and surjective onto finite sets, so we can view the sort nat as a subtype of set consisting of the finite sets.

def ns (a: nat): set = $ {x | odd (shr a x)} $;
coercion ns: nat > set;
theorem nseqd (_G: wff) (_a1 _a2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _a1 == _a2 $;
theorem nseq (_a1 _a2: nat): $ _a1 = _a2 -> _a1 == _a2 $;
theorem elnel (a b: nat): $ a e. b <-> odd (shr b a) $;
theorem elneqd (G: wff) (a b c d: nat): $ G -> a = b $ > $ G -> c = d $ > $ G -> (a e. c <-> b e. d) $;
theorem elneq2d (G: wff) (a b c: nat): $ G -> b = c $ > $ G -> (a e. b <-> a e. c) $;
theorem elneq2 (a b c: nat): $ b = c -> (a e. b <-> a e. c) $;
theorem elneq (a b c d: nat): $ a = b -> c = d -> (a e. c <-> b e. d) $;
theorem appneq1d (G: wff) (f g x: nat): $ G -> f = g $ > $ G -> f @ x = g @ x $;
theorem appneq1 (f g x: nat): $ f = g -> f @ x = g @ x $;
theorem nfns {x: nat} (a: nat x): $ FN/ x a $ > $ FS/ x a $;
theorem el01 (a: nat): $ 0 e. a <-> odd a $;
theorem elshr (a b c: nat): $ a e. shr b c <-> a + c e. b $;
theorem elshl (a b c: nat): $ a e. shl b c <-> c <= a /\ a - c e. b $;
theorem elmodpow2 (a n x: nat): $ x e. a % 2 ^ n <-> x < n /\ x e. a $;
theorem shrss (a b n: nat): $ a C_ b -> shr a n C_ shr b n $;
theorem shlss (a b n: nat): $ a C_ b <-> shl a n C_ shl b n $;
theorem eldiv2 (a b: nat): $ a e. b // 2 <-> suc a e. b $;
theorem elb0 (a b: nat): $ a e. b0 b <-> 0 < a /\ a - 1 e. b $;
theorem elb1 (a b: nat): $ a e. b1 b <-> a = 0 \/ a - 1 e. b $;
theorem elb00 (b: nat): $ ~0 e. b0 b $;
theorem elb10 (b: nat): $ 0 e. b1 b $;
theorem elb0S (a b: nat): $ suc a e. b0 b <-> a e. b $;
theorem elb1S (a b: nat): $ suc a e. b1 b <-> a e. b $;
theorem bndextle (a b n: nat) {x: nat}: $ A. x (x < n -> x e. a -> x e. b) -> a % 2 ^ n <= b % 2 ^ n $;
theorem bndext (a b n: nat) {x: nat}: $ A. x (x < n -> (x e. a <-> x e. b)) -> mod(2 ^ n): a = b $;
theorem ssle (a b: nat): $ a C_ b -> a <= b $;
pub theorem axext (a b: nat): $ a == b -> a = b $;
theorem nsinj (a b: nat): $ a == b <-> a = b $;
pub theorem ellt (a b: nat): $ a e. b -> a < b $;
theorem el02 (a: nat): $ ~a e. 0 $;
pub theorem nel0 (a: nat): $ ~a e. 0 $;
theorem ss01 (A: set): $ 0 C_ A $;
theorem ss02 (A: set): $ A C_ 0 <-> A == 0 $;
theorem eq0al (A: set) {x: nat}: $ A == 0 <-> A. x ~x e. A $;
theorem sseq0 (A B: set): $ A C_ B -> B == 0 -> A == 0 $;
theorem in01 (A: set): $ 0 i^i A == 0 $;
theorem in02 (A: set): $ A i^i 0 == 0 $;
theorem inidm (A: set): $ A i^i A == A $;
theorem un01 (A: set): $ 0 u. A == A $;
theorem un02 (A: set): $ A u. 0 == A $;
theorem unidm (A: set): $ A u. A == A $;
theorem uneq0 (A B: set): $ A u. B == 0 <-> A == 0 /\ B == 0 $;
theorem cplv: $ Compl _V == 0 $;
theorem cpl0: $ Compl 0 == _V $;
theorem incpl2 (A: set): $ A i^i Compl A == 0 $;
theorem incpl1 (A: set): $ Compl A i^i A == 0 $;
theorem incpleq0 (A B: set): $ A i^i Compl B == 0 <-> A C_ B $;
theorem ineq0 (A B: set): $ A i^i B == 0 <-> A C_ Compl B $;
theorem ineq0r (A B: set): $ A i^i B == 0 <-> B C_ Compl A $;
theorem sscpl2 (A B: set): $ A C_ Compl B <-> B C_ Compl A $;
theorem inincpl (A B: set): $ A i^i (B i^i Compl A) == 0 $;
theorem unincpl (A B: set): $ A u. B i^i Compl A == A u. B $;
theorem xp01 (A: set): $ Xp 0 A == 0 $;
theorem xp02 (A: set): $ Xp A 0 == 0 $;
theorem dmeq0 (A: set): $ Dom A == 0 <-> A == 0 $;
theorem rneq0 (A: set): $ Ran A == 0 <-> A == 0 $;
theorem dm0: $ Dom 0 == 0 $;
theorem rn0: $ Ran 0 == 0 $;
theorem isf0: $ isfun 0 $;
theorem app01 (a: nat): $ 0 @ a = 0 $;
theorem disjne (A B: set) (G: wff) (x y: nat): $ G -> A i^i B == 0 $ > $ G -> x e. A $ > $ G -> y e. B $ > $ G -> x != y $;
theorem unisf (A B: set): $ Dom A i^i Dom B == 0 -> (isfun (A u. B) <-> isfun A /\ isfun B) $;
theorem reseq0 (A F: set): $ Dom F i^i A == 0 <-> F |` A == 0 $;
theorem dmdisj1 (A B: set): $ Dom A i^i Dom B == 0 -> A i^i B == 0 $;
theorem dmdisj (A B: set): $ isfun (A u. B) -> (Dom A i^i Dom B == 0 <-> A i^i B == 0) $;
theorem appleid1 (f x: nat): $ f @ x <= f $;
theorem elobind (F: set) (n x: nat) {y: nat}: $ x e. obind n F <-> E. y (n = suc y /\ x e. F @ y) $;
theorem el12 (a: nat): $ a e. 1 <-> a = 0 $;
theorem elpow2 (a n: nat): $ a e. 2 ^ n <-> a = n $;
theorem finns (a: nat): $ finite a $;

Convert a finite set to a natural number with the same elements. We use this when we wish to construct a natural number from a set expression. It returns a garbage value 0 if the set is not finite. This is the inverse to the ns coercion.

def lower (A: set): nat = $ the {n | n == A} $;
theorem lowereqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> lower _A1 = lower _A2 $;
theorem lowereq (_A1 _A2: set): $ _A1 == _A2 -> lower _A1 = lower _A2 $;
theorem nflower {x: nat} (A: set x): $ FS/ x A $ > $ FN/ x lower A $;
pub theorem eqlower (A: set): $ finite A <-> A == lower A $;
theorem ellower (A: set) (a: nat): $ finite A -> (a e. lower A <-> a e. A) $;
theorem lowerns (a: nat): $ lower a = a $;
theorem eqlower1 (A: set) (a: nat): $ finite A -> (A == a <-> lower A = a) $;
theorem eqlower2 (A: set) (a: nat): $ finite A -> (a == A <-> a = lower A) $;
theorem lowerinj (A B: set): $ finite A -> finite B -> (A == B <-> lower A = lower B) $;

A singleton set {a}, as a nat because it is always finite.

abstract def sn (a: nat): nat = $ 2 ^ a $;
theorem sneqd (_G: wff) (_a1 _a2: nat): $ _G -> _a1 = _a2 $ > $ _G -> sn _a1 = sn _a2 $;
theorem sneq (_a1 _a2: nat): $ _a1 = _a2 -> sn _a1 = sn _a2 $;
pub theorem elsn (a b: nat): $ a e. sn b <-> a = b $;
theorem snid (a: nat): $ a e. sn a $;
theorem snss (A: set) (a: nat): $ sn a C_ A <-> a e. A $;
theorem sndisj (A: set) (a: nat): $ sn a i^i A == 0 <-> ~a e. A $;
theorem subsnsn (a: nat): $ subsn (sn a) $;
theorem thesn (a: nat): $ the (sn a) = a $;
theorem sninj (a b: nat): $ sn a = sn b <-> a = b $;
theorem subsnsssn (A: set) {a: nat}: $ subsn A <-> E. a A C_ sn a $;
theorem isfsn (x: nat): $ isfun (sn x) $;
theorem dmsn (x y: nat): $ Dom (sn (x, y)) == sn x $;
theorem rnsn (x y: nat): $ Ran (sn (x, y)) == sn y $;

ins a b or a ; b is the set {a} u. b, the set containing a and the elements of b. It is finite because b is.

abstract def ins (a b: nat): nat = $ lower {x | x = a \/ x e. b} $;
infixr ins: $;$ prec 85;
theorem inseqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> _a1 ; _b1 = _a2 ; _b2 $;
theorem inseq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> _a1 ; _b1 = _a2 ; _b2 $;
theorem inseq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> _a1 ; b = _a2 ; b $;
theorem inseq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> _a1 ; b = _a2 ; b $;
theorem inseq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> a ; _b1 = a ; _b2 $;
theorem inseq2 (a _b1 _b2: nat): $ _b1 = _b2 -> a ; _b1 = a ; _b2 $;
pub theorem elins (a b c: nat): $ a e. b ; c <-> a = b \/ a e. c $;
theorem inscom (a b c: nat): $ a ; b ; c = b ; a ; c $;
theorem b0ins (a b: nat): $ b0 (a ; b) = suc a ; b0 b $;
theorem b1ins (n: nat): $ b1 n = 0 ; b0 n $;
theorem insdiv2 (a b: nat): $ suc a ; b // 2 = a ; (b // 2) $;
theorem insunsn (a b: nat): $ a ; b == sn a u. b $;
theorem ins02 (a: nat): $ a ; 0 = sn a $;
theorem insss (A: set) (a b: nat): $ a ; b C_ A <-> a e. A /\ b C_ A $;
theorem ssins (A: set) (a b: nat): $ A C_ a ; b -> a e. A \/ A C_ b $;

upto n = {x | x < n} is the set of numbers less than n.

def upto (n: nat): nat = $ 2 ^ n - 1 $;
theorem uptoeqd (_G: wff) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> upto _n1 = upto _n2 $;
theorem uptoeq (_n1 _n2: nat): $ _n1 = _n2 -> upto _n1 = upto _n2 $;
theorem upto0: $ upto 0 = 0 $;
theorem uptoadd1 (n: nat): $ upto n + 1 = 2 ^ n $;
theorem sucupto (n: nat): $ suc (upto n) = 2 ^ n $;
theorem uptoS (n: nat): $ upto (suc n) = b1 (upto n) $;
theorem uptolem (a n: nat): $ shr (upto n) a = upto (n - a) /\ upto n % 2 ^ a = upto (min n a) $;
theorem shrupto (a n: nat): $ shr (upto n) a = upto (n - a) $;
theorem shlupto (a n: nat): $ shl (upto n) a + upto a = upto (n + a) $;
pub theorem elupto (k n: nat): $ k e. upto n <-> k < n $;
theorem uptoss (a b: nat): $ upto a C_ upto b <-> a <= b $;
theorem uptoS_ins (a: nat): $ upto (suc a) = a ; upto a $;
theorem upto1_sn: $ upto 1 = sn 0 $;
theorem leupto (a b: nat): $ a <= b <-> upto a <= upto b $;
theorem dffin2 (A: set) {n: nat}: $ finite A <-> E. n A C_ upto n $;
local def size (A: set): nat = $ least {k | A C_ upto k} $;
theorem sizeeqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> size _A1 = size _A2 $;
theorem sizeeq (_A1 _A2: set): $ _A1 == _A2 -> size _A1 = size _A2 $;
theorem sssize (A: set): $ finite A <-> A C_ upto (size A) $;
theorem sizess1 (A: set) (k: nat): $ A C_ upto k -> size A <= k $;
theorem sizess (A: set) (k: nat): $ finite A -> (A C_ upto k <-> size A <= k) $;
theorem sizeupto (n: nat): $ size (upto n) = n $;

Bool = {x | bool x} is the set of boolean values (0 and 1).

def Bool: nat = $ 0 ; sn 1 $;
theorem elBool (n: nat): $ n e. Bool <-> bool n $;
theorem Bool0: $ 0 e. Bool $;
theorem Bool1: $ 1 e. Bool $;
theorem Bool0d (G: wff): $ G -> 0 e. Bool $;
theorem Bool1d (G: wff): $ G -> 1 e. Bool $;
theorem boolfin: $ finite Bool $;

Option A is the set A disjointly extended with an additional element. We use 0 and suc in place of the none and some constructors.

def Option (A: set): set = $ {n | n = 0 \/ n - 1 e. A} $;
theorem Optioneqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> Option _A1 == Option _A2 $;
theorem Optioneq (_A1 _A2: set): $ _A1 == _A2 -> Option _A1 == Option _A2 $;
theorem elopt (A: set) (a: nat): $ a e. Option A <-> a = 0 \/ a - 1 e. A $;
theorem opt0 (A: set): $ 0 e. Option A $;
theorem optS (A: set) (a: nat): $ suc a e. Option A <-> a e. A $;
theorem opt0d (A: set) (G: wff): $ G -> 0 e. Option A $;
theorem optSd (A: set) (G: wff) (a: nat): $ G -> a e. A $ > $ G -> suc a e. Option A $;
theorem optss (A B: set): $ Option A C_ Option B <-> A C_ B $;
theorem optfin (A: set): $ finite A -> finite (Option A) $;
theorem optns (n: nat): $ Option n == b1 n $;
theorem optupto (n: nat): $ Option (upto n) == upto (suc n) $;

Power A is the set of all (finite) subsets of A.

def Power (A: set): set = $ {x | x C_ A} $;
theorem Powereqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> Power _A1 == Power _A2 $;
theorem Powereq (_A1 _A2: set): $ _A1 == _A2 -> Power _A1 == Power _A2 $;
theorem elPower (A: set) (a: nat): $ a e. Power A <-> a C_ A $;
theorem powerfin (A: set): $ finite A -> finite (Power A) $;

power a is the finite set of all subsets of the finite set a.

def power (a: nat): nat = $ lower (Power a) $;
theorem powereqd (_G: wff) (_a1 _a2: nat): $ _G -> _a1 = _a2 $ > $ _G -> power _a1 = power _a2 $;
theorem powereq (_a1 _a2: nat): $ _a1 = _a2 -> power _a1 = power _a2 $;
theorem elpower (a b: nat): $ a e. power b <-> a C_ b $;
theorem powerupto (a: nat): $ power (upto a) = upto (2 ^ a) $;

sUnion A is the set union: the union of all the elements of A.

def sUnion (A: set): set = $ {x | E. y (x e. y /\ y e. A)} $;
theorem unieqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> sUnion _A1 == sUnion _A2 $;
theorem unieq (_A1 _A2: set): $ _A1 == _A2 -> sUnion _A1 == sUnion _A2 $;
theorem eluni (A: set) (a: nat) {x: nat}: $ a e. sUnion A <-> E. x (a e. x /\ x e. A) $;
theorem elunii (A: set) (a b: nat): $ a e. A -> b e. a -> b e. sUnion A $;
theorem elssuni (A: set) (a: nat): $ a e. A -> a C_ sUnion A $;
theorem finuni (A: set): $ finite A -> finite (sUnion A) $;
theorem xabfin (A: set) (G: wff) {x: nat} (B: set x): $ G -> finite A $ > $ G /\ x e. A -> finite B $ > $ G -> finite (X\ x e. A, B) $;
theorem sabfin (A: set) (G: wff) {x y: nat} (B: set x): $ G -> y e. B -> x e. A $ > $ G -> finite A $ > $ G /\ x e. A -> finite B $ > $ G -> finite (S\ x, B) $;

cons a b, or a : b, is the list cons operator: cons : A -> List A -> List A

def cons (a b: nat): nat = $ suc (a, b) $;
infixr cons: $:$ prec 91;
theorem conseqd (_G: wff) (_a1 _a2 _b1 _b2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _b1 = _b2 $ > $ _G -> _a1 : _b1 = _a2 : _b2 $;
theorem conseq (_a1 _a2 _b1 _b2: nat): $ _a1 = _a2 -> _b1 = _b2 -> _a1 : _b1 = _a2 : _b2 $;
theorem conseq1d (_G: wff) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> _a1 : b = _a2 : b $;
theorem conseq1 (_a1 _a2 b: nat): $ _a1 = _a2 -> _a1 : b = _a2 : b $;
theorem conseq2d (_G: wff) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> a : _b1 = a : _b2 $;
theorem conseq2 (a _b1 _b2: nat): $ _b1 = _b2 -> a : _b1 = a : _b2 $;
theorem consne0 (a b: nat): $ a : b != 0 $;
theorem ltconsid1 (a b: nat): $ a < a : b $;
theorem ltconsid2 (a b: nat): $ b < a : b $;
theorem consfstsnd (a: nat): $ a != 0 -> fst (a - 1) : snd (a - 1) = a $;
theorem excons (a: nat) {x y: nat}: $ a != 0 <-> E. x E. y a = x : y $;
theorem consinj (a b c d: nat): $ a : c = b : d <-> a = b /\ c = d $;
theorem conscan1 (a b c: nat): $ a : c = b : c <-> a = b $;
theorem conscan2 (a b c: nat): $ a : b = a : c <-> b = c $;
theorem consfst (a b: nat): $ fst (a : b - 1) = a $;
theorem conssnd (a b: nat): $ snd (a : b - 1) = b $;
theorem lecons1 (a b c: nat): $ a <= b <-> a : c <= b : c $;
theorem lecons2 (a b c: nat): $ b <= c <-> a : b <= a : c $;
theorem ltcons1 (a b c: nat): $ a < b <-> a : c < b : c $;
theorem ltcons2 (a b c: nat): $ b < c <-> a : b < a : c $;

sep n {x | p(x)} is {x e. n | p(x)}, the set of elements of n such that p(x). Because it is a subset of an existing finite set n, it is also finite. This is analogous to the separation axiom of ZFC.

abstract def sep (n: nat) (A: set): nat = $ lower (n i^i A) $;
theorem sepeqd (_G: wff) (_n1 _n2: nat) (_A1 _A2: set): $ _G -> _n1 = _n2 $ > $ _G -> _A1 == _A2 $ > $ _G -> sep _n1 _A1 = sep _n2 _A2 $;
theorem sepeq (_n1 _n2: nat) (_A1 _A2: set): $ _n1 = _n2 -> _A1 == _A2 -> sep _n1 _A1 = sep _n2 _A2 $;
theorem sepeq1d (_G: wff) (_n1 _n2: nat) (A: set): $ _G -> _n1 = _n2 $ > $ _G -> sep _n1 A = sep _n2 A $;
theorem sepeq1 (_n1 _n2: nat) (A: set): $ _n1 = _n2 -> sep _n1 A = sep _n2 A $;
theorem sepeq2d (_G: wff) (n: nat) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> sep n _A1 = sep n _A2 $;
theorem sepeq2 (n: nat) (_A1 _A2: set): $ _A1 == _A2 -> sep n _A1 = sep n _A2 $;
pub theorem elsep (n: nat) (A: set) (a: nat): $ a e. sep n A <-> a e. n /\ a e. A $;
local def func (F A B: set): wff = $ isfun F /\ Dom F == A /\ Ran F C_ B $;
theorem funceqd (_G: wff) (_F1 _F2 _A1 _A2 _B1 _B2: set):
  $ _G -> _F1 == _F2 $ >
  $ _G -> _A1 == _A2 $ >
  $ _G -> _B1 == _B2 $ >
  $ _G -> (func _F1 _A1 _B1 <-> func _F2 _A2 _B2) $;
theorem funceq (_F1 _F2 _A1 _A2 _B1 _B2: set): $ _F1 == _F2 -> _A1 == _A2 -> _B1 == _B2 -> (func _F1 _A1 _B1 <-> func _F2 _A2 _B2) $;
theorem funceq1d (_G: wff) (_F1 _F2 A B: set): $ _G -> _F1 == _F2 $ > $ _G -> (func _F1 A B <-> func _F2 A B) $;
theorem funceq1 (_F1 _F2 A B: set): $ _F1 == _F2 -> (func _F1 A B <-> func _F2 A B) $;
theorem funceq2d (_G: wff) (F _A1 _A2 B: set): $ _G -> _A1 == _A2 $ > $ _G -> (func F _A1 B <-> func F _A2 B) $;
theorem funceq2 (F _A1 _A2 B: set): $ _A1 == _A2 -> (func F _A1 B <-> func F _A2 B) $;
theorem funceq3d (_G: wff) (F A _B1 _B2: set): $ _G -> _B1 == _B2 $ > $ _G -> (func F A _B1 <-> func F A _B2) $;
theorem funceq3 (F A _B1 _B2: set): $ _B1 == _B2 -> (func F A _B1 <-> func F A _B2) $;
theorem nffunc {x: nat} (F A B: set x): $ FS/ x F $ > $ FS/ x A $ > $ FS/ x B $ > $ F/ x func F A B $;
theorem funcisf (A B F: set): $ func F A B -> isfun F $;
theorem funcdm (A B F: set): $ func F A B -> Dom F == A $;
theorem funcrn (A B F: set): $ func F A B -> Ran F C_ B $;
theorem funcss3 (A B C F: set): $ B C_ C -> func F A B -> func F A C $;
theorem funcal (A B F: set) {x: nat}: $ func F A B <-> isfun F /\ Dom F == A /\ A. x (x e. A -> F @ x e. B) $;
theorem funcres (A B C F: set): $ func F A B /\ C C_ A -> func (F |` C) C B $;
theorem funcssxp (A B F: set): $ func F A B -> F C_ Xp A B $;
theorem funcfin (A B F: set): $ func F A B -> finite A -> finite B -> finite F $;
theorem funcT (A B F: set) (x: nat): $ func F A B /\ x e. A -> F @ x e. B $;
theorem eqfunc (A B C F G: set) {x: nat}: $ func F A B /\ func G A C -> (F == G <-> A. x (x e. A -> F @ x = G @ x)) $;
theorem funceq0 (A B F: set): $ func F A B -> (F == 0 <-> A == 0) $;
theorem func02 (B F: set): $ func F 0 B <-> F == 0 $;
theorem func03 (A F: set): $ func F A 0 <-> F == 0 /\ A == 0 $;
theorem unfunc (A1 A2 B F1 F2: set) (G: wff): $ G -> A1 i^i A2 == 0 $ > $ G -> func F1 A1 B $ > $ G -> func F2 A2 B $ > $ G -> func (F1 u. F2) (A1 u. A2) B $;
theorem funcappb (A B F: set) (a b: nat): $ func F A B -> (a, b e. F <-> a e. A /\ F @ a = b) $;

Arrow A B (which has no notation but is denoted A -> B in comments) is the set of all (finite) functions from A to B.

def Arrow (A B: set): set = $ {f | isfun f /\ Dom f == A /\ Ran f C_ B} $;
theorem Arroweqd (_G: wff) (_A1 _A2 _B1 _B2: set): $ _G -> _A1 == _A2 $ > $ _G -> _B1 == _B2 $ > $ _G -> Arrow _A1 _B1 == Arrow _A2 _B2 $;
theorem Arroweq (_A1 _A2 _B1 _B2: set): $ _A1 == _A2 -> _B1 == _B2 -> Arrow _A1 _B1 == Arrow _A2 _B2 $;
theorem Arroweq1d (_G: wff) (_A1 _A2 B: set): $ _G -> _A1 == _A2 $ > $ _G -> Arrow _A1 B == Arrow _A2 B $;
theorem Arroweq1 (_A1 _A2 B: set): $ _A1 == _A2 -> Arrow _A1 B == Arrow _A2 B $;
theorem Arroweq2d (_G: wff) (A _B1 _B2: set): $ _G -> _B1 == _B2 $ > $ _G -> Arrow A _B1 == Arrow A _B2 $;
theorem Arroweq2 (A _B1 _B2: set): $ _B1 == _B2 -> Arrow A _B1 == Arrow A _B2 $;
theorem elArrow (A B: set) (f: nat): $ f e. Arrow A B <-> func f A B $;
theorem Arrowisf (A B: set) (f: nat): $ f e. Arrow A B -> isfun f $;
theorem Arrowdm (A B: set) (f: nat): $ f e. Arrow A B -> Dom f == A $;
theorem Arrowrn (A B: set) (f: nat): $ f e. Arrow A B -> Ran f C_ B $;
theorem Arrowssxp (A B: set): $ Arrow A B C_ Power (Xp A B) $;
theorem Arrowfin (A B: set): $ finite A -> finite B -> finite (Arrow A B) $;
theorem appT (A B: set) (f x: nat): $ f e. Arrow A B /\ x e. A -> f @ x e. B $;
theorem Arrow01 (B: set): $ Arrow 0 B == sn 0 $;
theorem Arrow02 (A: set): $ ~A == 0 -> Arrow A 0 == 0 $;

\. x e. a, v(x) is the finite (restricted) lambda: the regular lambda \ x, v(x) restricted to the finite set a. Since it is finite, we make it manifestly finite here.

def rlam {x: nat} (a: nat) (v: nat x): nat = $ lower ((\ x, v) |` a) $;
notation rlam {x: nat} (a: nat) (v: nat x): nat = ($\.$:53) x ($e.$:50) a ($,$:55) v;
theorem rlameqd (_G: wff) {x: nat} (_a1 _a2 _v1 _v2: nat x): $ _G -> _a1 = _a2 $ > $ _G -> _v1 = _v2 $ > $ _G -> \. x e. _a1, _v1 = \. x e. _a2, _v2 $;
theorem rlameq1d (_G: wff) {x: nat} (_a1 _a2 v: nat x): $ _G -> _a1 = _a2 $ > $ _G -> \. x e. _a1, v = \. x e. _a2, v $;
theorem rlameq2d (_G: wff) {x: nat} (a _v1 _v2: nat x): $ _G -> _v1 = _v2 $ > $ _G -> \. x e. a, _v1 = \. x e. a, _v2 $;
theorem rlameq1 {x: nat} (a b c: nat x): $ a = b -> \. x e. a, c = \. x e. b, c $;
theorem rlameqs {x: nat} (a b: nat x): $ \. x e. a, b == (\ x, b) |` a $;
theorem elrlam (p: nat) {x: nat} (a: nat) (b: nat x): $ p e. \. x e. a, b <-> E. x (x e. a /\ p = x, b) $;
theorem rlameq2a (a: nat) {x: nat} (v w: nat x): $ A. x (x e. a -> v = w) -> \. x e. a, v = \. x e. a, w $;
theorem rlameq2da (G: wff) (a: nat) {x: nat} (v w: nat x): $ G /\ x e. a -> v = w $ > $ G -> \. x e. a, v = \. x e. a, w $;
theorem nfrlam1 {x: nat} (a b: nat x): $ FN/ x a $ > $ FN/ x \. x e. a, b $;
theorem nfrlam {x y: nat} (a b: nat x y): $ FN/ x a $ > $ FN/ x b $ > $ FN/ x \. y e. a, b $;
theorem cbvrlamh {x y: nat} (a b c: nat x y): $ FN/ y b $ > $ FN/ x c $ > $ x = y -> b = c $ > $ \. x e. a, b = \. y e. a, c $;
theorem cbvrlam {x y: nat} (a: nat x y) (b: nat x) (c: nat y): $ x = y -> b = c $ > $ \. x e. a, b = \. y e. a, c $;
theorem cbvrlams {x y: nat} (a: nat x y) (b: nat x): $ \. x e. a, b = \. y e. a, N[y / x] b $;
theorem cbvrlamd {x y: nat} (G: wff) (a: nat x y) (b: nat x) (c: nat y): $ G /\ x = y -> b = c $ > $ G -> \. x e. a, b = \. y e. a, c $;
theorem rlamss {x: nat} (a b: nat x): $ \. x e. a, b C_ \ x, b $;
theorem rlamisf {x: nat} (a b: nat x): $ isfun (\. x e. a, b) $;
theorem dmrlam {x: nat} (a b: nat x): $ Dom (\. x e. a, b) == a $;
theorem rnrlam (a: nat) {x: nat} (b: nat x): $ Ran (\. x e. a, b) == (\ x, b) '' a $;
theorem rlamrnss (B: set) (a: nat) {x: nat} (b: nat x): $ Ran (\. x e. a, b) C_ B <-> A. x (x e. a -> b e. B) $;
theorem rlamfunc (B: set) (a: nat) {x: nat} (b: nat x): $ func (\. x e. a, b) a B <-> A. x (x e. a -> b e. B) $;
theorem rlamfunc2 (A B: set) (a: nat) {x: nat} (b: nat x): $ A == a -> (func (\. x e. a, b) A B <-> A. x (x e. A -> b e. B)) $;
theorem rlamArrow (B: set) (a: nat) {x: nat} (b: nat x): $ \. x e. a, b e. Arrow a B <-> A. x (x e. a -> b e. B) $;
theorem unrlam (a b c: nat) {x: nat} (v: nat x): $ (\. x e. a, v) u. (\. x e. b, v) == \. x e. c, v <-> a u. b == c $;
theorem apprlams (a: nat) {x: nat} (b c: nat x): $ c e. a -> (\. x e. a, b) @ c = N[c / x] b $;
theorem apprlam (a: nat) {x: nat} (b: nat x): $ x e. a -> (\. x e. a, b) @ x = b $;
theorem apprlame (a c d: nat) {x: nat} (b: nat x): $ x = c -> b = d $ > $ c e. a -> (\. x e. a, b) @ c = d $;
theorem apprlamed (G: wff) (a c d: nat) {x: nat} (b: nat x): $ G /\ x = c -> b = d $ > $ G -> c e. a $ > $ G -> (\. x e. a, b) @ c = d $;
theorem apprlamed1 (G P: wff) (a c f: nat) {x: nat} (b: nat x): $ G -> c e. a $ > $ G /\ x = c -> f @ c = b -> P $ > $ G -> f = \. x e. a, b -> P $;
theorem apprlamed2 (G: wff) (a c d: nat) {x: nat} (f b: nat x): $ G -> c e. a $ > $ G /\ x = c -> b = d $ > $ G -> f = \. x e. a, b -> f @ c = d $;
theorem rlameq2b (a: nat) {x: nat} (v w: nat x): $ \. x e. a, v = \. x e. a, w <-> A. x (x e. a -> v = w) $;
theorem apprlam0 (a: nat) {x: nat} (b c: nat x): $ ~c e. a -> (\. x e. a, b) @ c = 0 $;
theorem rlamrcl (a d: nat) {x: nat} (b c: nat x): $ d e. (\. x e. a, b) @ c -> c e. a $;
theorem rlamapp (F: set) (a: nat) {x: nat}: $ \. x e. a, F @ x == F <-> isfun F /\ Dom F == a $;
theorem eqsrlam (F: set) (a: nat) {x: nat} (b: nat x): $ F == \. x e. a, b <-> isfun F /\ Dom F == a /\ A. x (x e. a -> F @ x = b) $;
theorem eqrlam (a f: nat) {x: nat} (b: nat x): $ f = \. x e. a, b <-> isfun f /\ Dom f == a /\ A. x (x e. a -> f @ x = b) $;
theorem funcsn2 (F: set) (a b: nat) {x: nat}: $ func F a (sn b) <-> F == \. x e. a, b $;
theorem Arrowsn2 (a b: nat) {x: nat}: $ Arrow a (sn b) == sn (\. x e. a, b) $;

write F a b, sometimes denoted F[a -> b] is the function which is b at a and returns F @ x for x != a.

def write (F: set) (a b: nat): set = $ S\ x, {y | ifp (x = a) (y = b) (x, y e. F)} $;
theorem writeeqd (_G: wff) (_F1 _F2: set) (_a1 _a2 _b1 _b2: nat):
  $ _G -> _F1 == _F2 $ >
  $ _G -> _a1 = _a2 $ >
  $ _G -> _b1 = _b2 $ >
  $ _G -> write _F1 _a1 _b1 == write _F2 _a2 _b2 $;
theorem writeeq (_F1 _F2: set) (_a1 _a2 _b1 _b2: nat): $ _F1 == _F2 -> _a1 = _a2 -> _b1 = _b2 -> write _F1 _a1 _b1 == write _F2 _a2 _b2 $;
theorem writeeq1d (_G: wff) (_F1 _F2: set) (a b: nat): $ _G -> _F1 == _F2 $ > $ _G -> write _F1 a b == write _F2 a b $;
theorem writeeq1 (_F1 _F2: set) (a b: nat): $ _F1 == _F2 -> write _F1 a b == write _F2 a b $;
theorem writeeq2d (_G: wff) (F: set) (_a1 _a2 b: nat): $ _G -> _a1 = _a2 $ > $ _G -> write F _a1 b == write F _a2 b $;
theorem writeeq2 (F: set) (_a1 _a2 b: nat): $ _a1 = _a2 -> write F _a1 b == write F _a2 b $;
theorem writeeq3d (_G: wff) (F: set) (a _b1 _b2: nat): $ _G -> _b1 = _b2 $ > $ _G -> write F a _b1 == write F a _b2 $;
theorem writeeq3 (F: set) (a _b1 _b2: nat): $ _b1 = _b2 -> write F a _b1 == write F a _b2 $;
theorem elwrite (F: set) (a b x y: nat): $ x, y e. write F a b <-> ifp (x = a) (y = b) (x, y e. F) $;
pub theorem writeEq (F: set) (a b: nat): $ write F a b @ a = b $;
pub theorem writeNe (F: set) (a b x: nat): $ x != a -> write F a b @ x = F @ x $;
theorem writeisf (F: set) (a b: nat): $ isfun F -> isfun (write F a b) $;
theorem writeres (F: set) (a b: nat) {x: nat}: $ write F a b == (F |` {x | x != a}) u. sn (a, b) $;
theorem writefin (F: set) (a b: nat): $ finite F -> finite (write F a b) $;
theorem dmwrite (F: set) (a b: nat): $ Dom (write F a b) == Dom F u. sn a $;
theorem rnwrite (F: set) (a b: nat): $ Ran (write F a b) C_ Ran F u. sn b $;
theorem writeArrow (A B: set) (G: wff) (a b f g: nat):
  $ G -> f e. Arrow A B $ >
  $ G -> a e. A $ >
  $ G -> b e. B $ >
  $ G -> write f a b == g $ >
  $ G -> g e. Arrow A B $;
local def srecaux (S: set) (n: nat): nat = $ recn 0 (\\ a, \ b, lower (write b a (S @ b))) n $;
theorem srecauxeqd (_G: wff) (_S1 _S2: set) (_n1 _n2: nat): $ _G -> _S1 == _S2 $ > $ _G -> _n1 = _n2 $ > $ _G -> srecaux _S1 _n1 = srecaux _S2 _n2 $;
theorem srecauxeq (_S1 _S2: set) (_n1 _n2: nat): $ _S1 == _S2 -> _n1 = _n2 -> srecaux _S1 _n1 = srecaux _S2 _n2 $;
theorem srecauxeq1d (_G: wff) (_S1 _S2: set) (n: nat): $ _G -> _S1 == _S2 $ > $ _G -> srecaux _S1 n = srecaux _S2 n $;
theorem srecauxeq1 (_S1 _S2: set) (n: nat): $ _S1 == _S2 -> srecaux _S1 n = srecaux _S2 n $;
theorem srecauxeq2d (_G: wff) (S: set) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> srecaux S _n1 = srecaux S _n2 $;
theorem srecauxeq2 (S: set) (_n1 _n2: nat): $ _n1 = _n2 -> srecaux S _n1 = srecaux S _n2 $;
theorem srecaux0 (S: set): $ srecaux S 0 = 0 $;
theorem srecauxS (S: set) (n: nat): $ srecaux S (suc n) == write (srecaux S n) n (S @ srecaux S n) $;
theorem dmsrecaux (S: set) (n: nat): $ Dom (srecaux S n) == upto n $;
theorem srecauxisf (S: set) (n: nat): $ isfun (srecaux S n) $;

Strong recursion operator:

  • srec n = S (srec 0, ..., srec (n-1))
abstract def srec (S: set) (n: nat): nat = $ srecaux S (suc n) @ n $;
theorem sreceqd (_G: wff) (_S1 _S2: set) (_n1 _n2: nat): $ _G -> _S1 == _S2 $ > $ _G -> _n1 = _n2 $ > $ _G -> srec _S1 _n1 = srec _S2 _n2 $;
theorem sreceq (_S1 _S2: set) (_n1 _n2: nat): $ _S1 == _S2 -> _n1 = _n2 -> srec _S1 _n1 = srec _S2 _n2 $;
theorem sreceq1d (_G: wff) (_S1 _S2: set) (n: nat): $ _G -> _S1 == _S2 $ > $ _G -> srec _S1 n = srec _S2 n $;
theorem sreceq1 (_S1 _S2: set) (n: nat): $ _S1 == _S2 -> srec _S1 n = srec _S2 n $;
theorem sreceq2d (_G: wff) (S: set) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> srec S _n1 = srec S _n2 $;
theorem sreceq2 (S: set) (_n1 _n2: nat): $ _n1 = _n2 -> srec S _n1 = srec S _n2 $;
theorem srecauxapp (S: set) (a n: nat): $ a < n -> srecaux S n @ a = srec S a $;
theorem srecval2 (S: set) (n: nat): $ srec S n = S @ srecaux S n $;
theorem srecres (S: set) {i: nat} (n: nat): $ (\ i, srec S i) |` upto n == srecaux S n $;
theorem srecrlam (S: set) {i: nat} (n: nat): $ \. i e. upto n, srec S i = srecaux S n $;
theorem sreclem (f n: nat) {x: nat} (a: nat x): $ f = \. x e. upto n, a -> size (Dom f) = n $;
theorem sreclem2 (f n: nat) {x: nat} (a b: nat x): $ f = \. x e. upto n, a -> b < n -> f @ b = N[b / x] a $;
pub theorem srecval {i: nat} (S: set) (n: nat): $ srec S n = S @ (\. i e. upto n, srec S i) $;
local def srecpaux (A: set) (n: nat): nat = $ srec (\ f, nat (size (Dom f), lower {x | true (f @ x)} e. A)) n $;
theorem srecpauxeqd (_G: wff) (_A1 _A2: set) (_n1 _n2: nat): $ _G -> _A1 == _A2 $ > $ _G -> _n1 = _n2 $ > $ _G -> srecpaux _A1 _n1 = srecpaux _A2 _n2 $;
theorem srecpauxeq (_A1 _A2: set) (_n1 _n2: nat): $ _A1 == _A2 -> _n1 = _n2 -> srecpaux _A1 _n1 = srecpaux _A2 _n2 $;
theorem srecpauxeq1d (_G: wff) (_A1 _A2: set) (n: nat): $ _G -> _A1 == _A2 $ > $ _G -> srecpaux _A1 n = srecpaux _A2 n $;
theorem srecpauxeq1 (_A1 _A2: set) (n: nat): $ _A1 == _A2 -> srecpaux _A1 n = srecpaux _A2 n $;
theorem srecpauxeq2d (_G: wff) (A: set) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> srecpaux A _n1 = srecpaux A _n2 $;
theorem srecpauxeq2 (A: set) (_n1 _n2: nat): $ _n1 = _n2 -> srecpaux A _n1 = srecpaux A _n2 $;

Strong recursion operator (for wffs):

  • srecp n <-> (srecp 0, ..., srecp (n-1)) e. A
abstract def srecp (A: set) (n: nat): wff = $ true (srecpaux A n) $;
theorem srecpeqd (_G: wff) (_A1 _A2: set) (_n1 _n2: nat): $ _G -> _A1 == _A2 $ > $ _G -> _n1 = _n2 $ > $ _G -> (srecp _A1 _n1 <-> srecp _A2 _n2) $;
theorem srecpeq (_A1 _A2: set) (_n1 _n2: nat): $ _A1 == _A2 -> _n1 = _n2 -> (srecp _A1 _n1 <-> srecp _A2 _n2) $;
theorem srecpeq1d (_G: wff) (_A1 _A2: set) (n: nat): $ _G -> _A1 == _A2 $ > $ _G -> (srecp _A1 n <-> srecp _A2 n) $;
theorem srecpeq1 (_A1 _A2: set) (n: nat): $ _A1 == _A2 -> (srecp _A1 n <-> srecp _A2 n) $;
theorem srecpeq2d (_G: wff) (A: set) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> (srecp A _n1 <-> srecp A _n2) $;
theorem srecpeq2 (A: set) (_n1 _n2: nat): $ _n1 = _n2 -> (srecp A _n1 <-> srecp A _n2) $;
theorem srecpauxval (A: set) {i: nat} (n: nat): $ srecpaux A n = nat (n, sep (upto n) {i | srecp A i} e. A) $;
pub theorem srecpval {i: nat} (A: set) (n: nat): $ srecp A n <-> n, sep (upto n) {i | srecp A i} e. A $;

The cardinality (number of elements) of a finite set.

abstract def card (s: nat): nat = $ srec (\ f, f @ (size (Dom f) // 2) + size (Dom f) % 2) s $;
theorem cardeqd (_G: wff) (_s1 _s2: nat): $ _G -> _s1 = _s2 $ > $ _G -> card _s1 = card _s2 $;
theorem cardeq (_s1 _s2: nat): $ _s1 = _s2 -> card _s1 = card _s2 $;
theorem cardvallem {i: nat} (n: nat): $ card n = ((\ i, card i) |` upto n) @ (n // 2) + n % 2 $;
pub theorem card0: $ card 0 = 0 $;
theorem cardval (n: nat): $ n != 0 -> card n = card (n // 2) + n % 2 $;
theorem cardb0 (n: nat): $ card (b0 n) = card n $;
theorem cardb1 (n: nat): $ card (b1 n) = suc (card n) $;
pub theorem cardS (a s: nat): $ ~a e. s -> card (a ; s) = suc (card s) $;

List recursion operator:

  • lrec 0 = z
  • lrec (a : l) = S (a, l, lrec l)
abstract def lrec (z: nat) (S: set) (n: nat): nat = $ srec (\ f, N[size (Dom f) / i] if (i = 0) z (S @ (fst (i - 1), snd (i - 1), f @ snd (i - 1)))) n $;
theorem lreceqd (_G: wff) (_z1 _z2: nat) (_S1 _S2: set) (_n1 _n2: nat):
  $ _G -> _z1 = _z2 $ >
  $ _G -> _S1 == _S2 $ >
  $ _G -> _n1 = _n2 $ >
  $ _G -> lrec _z1 _S1 _n1 = lrec _z2 _S2 _n2 $;
theorem lreceq (_z1 _z2: nat) (_S1 _S2: set) (_n1 _n2: nat): $ _z1 = _z2 -> _S1 == _S2 -> _n1 = _n2 -> lrec _z1 _S1 _n1 = lrec _z2 _S2 _n2 $;
theorem lreceq1d (_G: wff) (_z1 _z2: nat) (S: set) (n: nat): $ _G -> _z1 = _z2 $ > $ _G -> lrec _z1 S n = lrec _z2 S n $;
theorem lreceq1 (_z1 _z2: nat) (S: set) (n: nat): $ _z1 = _z2 -> lrec _z1 S n = lrec _z2 S n $;
theorem lreceq2d (_G: wff) (z: nat) (_S1 _S2: set) (n: nat): $ _G -> _S1 == _S2 $ > $ _G -> lrec z _S1 n = lrec z _S2 n $;
theorem lreceq2 (z: nat) (_S1 _S2: set) (n: nat): $ _S1 == _S2 -> lrec z _S1 n = lrec z _S2 n $;
theorem lreceq3d (_G: wff) (z: nat) (S: set) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> lrec z S _n1 = lrec z S _n2 $;
theorem lreceq3 (z: nat) (S: set) (_n1 _n2: nat): $ _n1 = _n2 -> lrec z S _n1 = lrec z S _n2 $;
theorem lrecval (S: set) (n z: nat): $ lrec z S n = if (n = 0) z (S @ (fst (n - 1), snd (n - 1), lrec z S (snd (n - 1)))) $;
pub theorem lrec0 (z: nat) (S: set): $ lrec z S 0 = z $;
pub theorem lrecS (z: nat) (S: set) (a b: nat): $ lrec z S (a : b) = S @ (a, b, lrec z S b) $;
theorem listindd (G: wff) {x a l: nat} (n: nat) (px: wff x) (p0 pn: wff) (pl: wff l) (ps: wff a l):
  $ x = n -> (px <-> pn) $ >
  $ x = 0 -> (px <-> p0) $ >
  $ x = l -> (px <-> pl) $ >
  $ x = a : l -> (px <-> ps) $ >
  $ G -> p0 $ >
  $ G /\ pl -> ps $ >
  $ G -> pn $;
theorem listind {x a l: nat} (n: nat) (px: wff x) (p0 pn: wff) (pl: wff l) (ps: wff a l):
  $ x = n -> (px <-> pn) $ >
  $ x = 0 -> (px <-> p0) $ >
  $ x = l -> (px <-> pl) $ >
  $ x = a : l -> (px <-> ps) $ >
  $ p0 $ >
  $ pl -> ps $ >
  $ pn $;

The set of members of list l: lmems [a, b, c] = {a, b, c}.

lmems : List A -> Power A

abstract def lmems (l: nat): nat = $ lrec 0 (\\ x, \\ z, \ y, x ; y) l $;
theorem lmemseqd (_G: wff) (_l1 _l2: nat): $ _G -> _l1 = _l2 $ > $ _G -> lmems _l1 = lmems _l2 $;
theorem lmemseq (_l1 _l2: nat): $ _l1 = _l2 -> lmems _l1 = lmems _l2 $;
pub theorem lmems0: $ lmems 0 = 0 $;
pub theorem lmemsS (a l: nat): $ lmems (a : l) = a ; lmems l $;

a IN l means a e. lmems l, that is, a is a member of the list l.

lmem : A -> List A -> Bool

def lmem (a l: nat): wff = $ a e. lmems l $;
infixl lmem: $IN$ prec 50;
theorem lmemeqd (_G: wff) (_a1 _a2 _l1 _l2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _l1 = _l2 $ > $ _G -> (_a1 IN _l1 <-> _a2 IN _l2) $;
theorem lmemeq (_a1 _a2 _l1 _l2: nat): $ _a1 = _a2 -> _l1 = _l2 -> (_a1 IN _l1 <-> _a2 IN _l2) $;
theorem lmemeq1d (_G: wff) (_a1 _a2 l: nat): $ _G -> _a1 = _a2 $ > $ _G -> (_a1 IN l <-> _a2 IN l) $;
theorem lmemeq1 (_a1 _a2 l: nat): $ _a1 = _a2 -> (_a1 IN l <-> _a2 IN l) $;
theorem lmemeq2d (_G: wff) (a _l1 _l2: nat): $ _G -> _l1 = _l2 $ > $ _G -> (a IN _l1 <-> a IN _l2) $;
theorem lmemeq2 (a _l1 _l2: nat): $ _l1 = _l2 -> (a IN _l1 <-> a IN _l2) $;
theorem lmem0 (a: nat): $ ~a IN 0 $;
theorem lmemS (a b l: nat): $ a IN b : l <-> a = b \/ a IN l $;
theorem lmem1 (a b: nat): $ a IN b : 0 <-> a = b $;
theorem lmemconsid (a l: nat): $ a IN a : l $;
theorem lmemlt (a l: nat): $ a IN l -> a < l $;

all {x | p(x)} l means every element of the list l satisfies p(x).

def all (A: set) (l: nat): wff = $ lmems l C_ A $;
theorem alleqd (_G: wff) (_A1 _A2: set) (_l1 _l2: nat): $ _G -> _A1 == _A2 $ > $ _G -> _l1 = _l2 $ > $ _G -> (all _A1 _l1 <-> all _A2 _l2) $;
theorem alleq (_A1 _A2: set) (_l1 _l2: nat): $ _A1 == _A2 -> _l1 = _l2 -> (all _A1 _l1 <-> all _A2 _l2) $;
theorem alleq1d (_G: wff) (_A1 _A2: set) (l: nat): $ _G -> _A1 == _A2 $ > $ _G -> (all _A1 l <-> all _A2 l) $;
theorem alleq1 (_A1 _A2: set) (l: nat): $ _A1 == _A2 -> (all _A1 l <-> all _A2 l) $;
theorem alleq2d (_G: wff) (A: set) (_l1 _l2: nat): $ _G -> _l1 = _l2 $ > $ _G -> (all A _l1 <-> all A _l2) $;
theorem alleq2 (A: set) (_l1 _l2: nat): $ _l1 = _l2 -> (all A _l1 <-> all A _l2) $;
theorem all0 (A: set): $ all A 0 $;
theorem allS (A: set) (a b: nat): $ all A (a : b) <-> a e. A /\ all A b $;
theorem all1 (A: set) (a: nat): $ all A (a : 0) <-> a e. A $;
theorem allal2 (A: set) (l: nat) {x: nat}: $ all A l <-> A. x (x IN l -> x e. A) $;
theorem allal (l: nat) {x: nat} (p: wff x): $ all {x | p} l <-> A. x (x IN l -> p) $;
theorem elall (A: set) (l x: nat): $ all A l -> x IN l -> x e. A $;
theorem ssall (A B: set) (l: nat): $ A C_ B -> all A l -> all B l $;

List A is the type of lists with elements of type A. It is inductively generated by the clauses:

  • 0 e. List A
  • a e. A -> l e. List A -> a : l e. List A
def List (A: set): set = $ {n | all A n} $;
theorem Listeqd (_G: wff) (_A1 _A2: set): $ _G -> _A1 == _A2 $ > $ _G -> List _A1 == List _A2 $;
theorem Listeq (_A1 _A2: set): $ _A1 == _A2 -> List _A1 == List _A2 $;
theorem elList (A: set) (l: nat): $ l e. List A <-> all A l $;
theorem elList0 (A: set): $ 0 e. List A $;
theorem elListS (A: set) (a b: nat): $ a : b e. List A <-> a e. A /\ b e. List A $;
theorem elListHd (A: set) (G: wff) (a b: nat): $ G -> a : b e. List A $ > $ G -> a e. A $;
theorem elListTl (A: set) (G: wff) (a b: nat): $ G -> a : b e. List A $ > $ G -> b e. List A $;
theorem elList1 (A: set) (a: nat): $ a : 0 e. List A <-> a e. A $;

len l is the length of the list l.

len : List A -> nat

abstract def len (l: nat): nat = $ lrec 0 (\\ x, \\ z, \ y, suc y) l $;
theorem leneqd (_G: wff) (_l1 _l2: nat): $ _G -> _l1 = _l2 $ > $ _G -> len _l1 = len _l2 $;
theorem leneq (_l1 _l2: nat): $ _l1 = _l2 -> len _l1 = len _l2 $;
pub theorem len0: $ len 0 = 0 $;
pub theorem lenS (a b: nat): $ len (a : b) = suc (len b) $;
theorem len1 (a: nat): $ len (a : 0) = 1 $;
theorem leneq0 (n: nat): $ len n = 0 <-> n = 0 $;
theorem lenleid (l: nat): $ len l <= l $;

Array A n is the subtype of lists which have length n.

  • 0 e. Array A 0
  • a e. A -> l e. Array A n -> a : l e. Array A (n+1)
def Array (A: set) (n: nat): set = $ {l | l e. List A /\ len l = n} $;
theorem Arrayeqd (_G: wff) (_A1 _A2: set) (_n1 _n2: nat): $ _G -> _A1 == _A2 $ > $ _G -> _n1 = _n2 $ > $ _G -> Array _A1 _n1 == Array _A2 _n2 $;
theorem Arrayeq (_A1 _A2: set) (_n1 _n2: nat): $ _A1 == _A2 -> _n1 = _n2 -> Array _A1 _n1 == Array _A2 _n2 $;
theorem Arrayeq1d (_G: wff) (_A1 _A2: set) (n: nat): $ _G -> _A1 == _A2 $ > $ _G -> Array _A1 n == Array _A2 n $;
theorem Arrayeq1 (_A1 _A2: set) (n: nat): $ _A1 == _A2 -> Array _A1 n == Array _A2 n $;
theorem Arrayeq2d (_G: wff) (A: set) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> Array A _n1 == Array A _n2 $;
theorem Arrayeq2 (A: set) (_n1 _n2: nat): $ _n1 = _n2 -> Array A _n1 == Array A _n2 $;
theorem elArray (A: set) (l n: nat): $ l e. Array A n <-> l e. List A /\ len l = n $;
theorem elArrayList (A: set) (l n: nat): $ l e. Array A n -> l e. List A $;
theorem elArraylen (A: set) (l n: nat): $ l e. Array A n -> len l = n $;
theorem elArray02 (A: set) (l: nat): $ l e. Array A 0 <-> l = 0 $;
theorem elArray0 (A: set): $ 0 e. Array A 0 $;
theorem elArrayS (A: set) (a b n: nat): $ a : b e. Array A (suc n) <-> a e. A /\ b e. Array A n $;
theorem elArray1 (A: set) (a: nat): $ a : 0 e. Array A 1 <-> a e. A $;
theorem elArraySne0 (A: set) (l n: nat): $ l e. Array A (suc n) -> l != 0 $;
theorem elArrayS2 (A: set) {a b: nat} (l n: nat): $ l e. Array A (suc n) <-> E. a E. b (a e. A /\ b e. Array A n /\ l = a : b) $;
theorem Arrayfin (A: set) (n: nat): $ finite A -> finite (Array A n) $;

append l1 l2, or l1 ++ l2, is the result of concatenating lists l1 and l2.

  • 0 ++ l = l
  • (a : l) ++ r = a : (l ++ r)

append : List A -> List A -> List A

abstract def append (l1 l2: nat): nat = $ lrec l2 (\\ x, \\ z, \ y, x : y) l1 $;
infixr append: $++$ prec 85;
theorem appendeqd (_G: wff) (_l11 _l12 _l21 _l22: nat): $ _G -> _l11 = _l12 $ > $ _G -> _l21 = _l22 $ > $ _G -> _l11 ++ _l21 = _l12 ++ _l22 $;
theorem appendeq (_l11 _l12 _l21 _l22: nat): $ _l11 = _l12 -> _l21 = _l22 -> _l11 ++ _l21 = _l12 ++ _l22 $;
theorem appendeq1d (_G: wff) (_l11 _l12 l2: nat): $ _G -> _l11 = _l12 $ > $ _G -> _l11 ++ l2 = _l12 ++ l2 $;
theorem appendeq1 (_l11 _l12 l2: nat): $ _l11 = _l12 -> _l11 ++ l2 = _l12 ++ l2 $;
theorem appendeq2d (_G: wff) (l1 _l21 _l22: nat): $ _G -> _l21 = _l22 $ > $ _G -> l1 ++ _l21 = l1 ++ _l22 $;
theorem appendeq2 (l1 _l21 _l22: nat): $ _l21 = _l22 -> l1 ++ _l21 = l1 ++ _l22 $;
pub theorem append0 (l: nat): $ 0 ++ l = l $;
pub theorem appendS (a l r: nat): $ a : l ++ r = a : (l ++ r) $;
theorem appendSi (a b c x: nat): $ a ++ b = c $ > $ x : a ++ b = x : c $;
theorem append1 (a l: nat): $ a : 0 ++ l = a : l $;
theorem append02 (a: nat): $ a ++ 0 = a $;
theorem appendass (l1 l2 l3: nat): $ (l1 ++ l2) ++ l3 = l1 ++ l2 ++ l3 $;
theorem appendlen (l1 l2: nat): $ len (l1 ++ l2) = len l1 + len l2 $;
theorem leappend2 (a b c: nat): $ b <= c <-> a ++ b <= a ++ c $;
theorem ltappend2 (a b c: nat): $ b < c <-> a ++ b < a ++ c $;
theorem appendcan1 (a b c: nat): $ a ++ b = a ++ c <-> b = c $;
theorem leappendid1 (a b: nat): $ a <= a ++ b $;
theorem leappendid2 (a b: nat): $ a <= b ++ a $;
theorem ltappendid1 (a b: nat): $ b != 0 <-> a < a ++ b $;
theorem ltappendid2 (a b: nat): $ b != 0 <-> a < b ++ a $;
theorem appendeq0 (a b: nat): $ a ++ b = 0 <-> a = 0 /\ b = 0 $;
theorem lmemappend (a b x: nat): $ x IN a ++ b <-> x IN a \/ x IN b $;
theorem allappend (A: set) (a b: nat): $ all A (a ++ b) <-> all A a /\ all A b $;
theorem appendT (A: set) (a b: nat): $ a ++ b e. List A <-> a e. List A /\ b e. List A $;
theorem appendArray (A: set) (a b m n: nat): $ a e. Array A m -> b e. Array A n -> a ++ b e. Array A (m + n) $;

snoc l a (cons written backwards) or l |> a is the result of putting a at the end of the list l:

  • l |> a = l ++ (a : 0).

snoc : List A -> A -> List A

abstract def snoc (l a: nat): nat = $ l ++ a : 0 $;
infixl snoc: $|>$ prec 84;
theorem snoceqd (_G: wff) (_l1 _l2 _a1 _a2: nat): $ _G -> _l1 = _l2 $ > $ _G -> _a1 = _a2 $ > $ _G -> _l1 |> _a1 = _l2 |> _a2 $;
theorem snoceq (_l1 _l2 _a1 _a2: nat): $ _l1 = _l2 -> _a1 = _a2 -> _l1 |> _a1 = _l2 |> _a2 $;
theorem snoceq1d (_G: wff) (_l1 _l2 a: nat): $ _G -> _l1 = _l2 $ > $ _G -> _l1 |> a = _l2 |> a $;
theorem snoceq1 (_l1 _l2 a: nat): $ _l1 = _l2 -> _l1 |> a = _l2 |> a $;
theorem snoceq2d (_G: wff) (l _a1 _a2: nat): $ _G -> _a1 = _a2 $ > $ _G -> l |> _a1 = l |> _a2 $;
theorem snoceq2 (l _a1 _a2: nat): $ _a1 = _a2 -> l |> _a1 = l |> _a2 $;
pub theorem snoc0 (a: nat): $ 0 |> a = a : 0 $;
pub theorem snocS (a b c: nat): $ a : b |> c = a : (b |> c) $;
pub theorem snoclt (a b: nat): $ a < a |> b $;
theorem lesnoc2 (a b c: nat): $ b <= c <-> a |> b <= a |> c $;
theorem appendsnoc (b l1 l2: nat): $ l1 ++ (l2 |> b) = l1 ++ l2 |> b $;
theorem conssnoc (a b l: nat): $ a : (l |> b) = a : l |> b $;
theorem snoclen (a b: nat): $ len (a |> b) = suc (len a) $;
theorem lmemsnoc (a b x: nat): $ x IN a |> b <-> x IN a \/ x = b $;
theorem lmemsnocid (a l: nat): $ a IN l |> a $;
theorem allsnoc (A: set) (a b: nat): $ all A (a |> b) <-> all A a /\ b e. A $;
theorem snocne0 (a b: nat): $ a |> b != 0 $;
theorem snocT (A: set) (a b: nat): $ a |> b e. List A <-> a e. List A /\ b e. A $;
local def listfn (l: nat): nat = $ lrec 0 (\\ a, \\ z, \ f, \. i e. upto (suc (size (Dom f))), if (i = 0) a (f @ (i - 1))) l $;
theorem listfneqd (_G: wff) (_l1 _l2: nat): $ _G -> _l1 = _l2 $ > $ _G -> listfn _l1 = listfn _l2 $;
theorem listfneq (_l1 _l2: nat): $ _l1 = _l2 -> listfn _l1 = listfn _l2 $;
theorem listfn0: $ listfn 0 = 0 $;
theorem listfnS2 (a: nat) {i: nat} (l: nat): $ listfn (a : l) = \. i e. upto (suc (size (Dom (listfn l)))), if (i = 0) a (listfn l @ (i - 1)) $;
theorem dmlistfn (l: nat): $ Dom (listfn l) == upto (len l) $;
theorem listfnisf (l: nat): $ isfun (listfn l) $;
theorem listfnS (a: nat) {i: nat} (l: nat): $ listfn (a : l) = \. i e. upto (suc (len l)), if (i = 0) a (listfn l @ (i - 1)) $;
theorem listfnSval (a l n: nat): $ n < suc (len l) -> listfn (a : l) @ n = if (n = 0) a (listfn l @ (n - 1)) $;
theorem listfnS0 (a l: nat): $ listfn (a : l) @ 0 = a $;
theorem listfnSS (a l n: nat): $ listfn (a : l) @ suc n = listfn l @ n $;

nth n l is the element of list l at position n, returning 0 (i.e. none) if the index is out of range.

  • nth n 0 = none
  • nth 0 (a : l) = some a
  • nth (n+1) (a : l) = nth n l

nth : nat -> List A -> Option A

abstract def nth (n l: nat): nat = $ if (n < len l) (suc (listfn l @ n)) 0 $;
theorem ntheqd (_G: wff) (_n1 _n2 _l1 _l2: nat): $ _G -> _n1 = _n2 $ > $ _G -> _l1 = _l2 $ > $ _G -> nth _n1 _l1 = nth _n2 _l2 $;
theorem ntheq (_n1 _n2 _l1 _l2: nat): $ _n1 = _n2 -> _l1 = _l2 -> nth _n1 _l1 = nth _n2 _l2 $;
theorem ntheq1d (_G: wff) (_n1 _n2 l: nat): $ _G -> _n1 = _n2 $ > $ _G -> nth _n1 l = nth _n2 l $;
theorem ntheq1 (_n1 _n2 l: nat): $ _n1 = _n2 -> nth _n1 l = nth _n2 l $;
theorem ntheq2d (_G: wff) (n _l1 _l2: nat): $ _G -> _l1 = _l2 $ > $ _G -> nth n _l1 = nth n _l2 $;
theorem ntheq2 (n _l1 _l2: nat): $ _l1 = _l2 -> nth n _l1 = nth n _l2 $;
pub theorem nth0 (n: nat): $ nth n 0 = 0 $;
pub theorem nthZ (a l: nat): $ nth 0 (a : l) = suc a $;
pub theorem nthS (n a l: nat): $ nth (suc n) (a : l) = nth n l $;
theorem nthne0 (l n: nat): $ nth n l != 0 <-> n < len l $;
theorem ntheq0 (l n: nat): $ nth n l = 0 <-> len l <= n $;
theorem lmemnth (a l: nat) {n: nat}: $ a IN l <-> E. n nth n l = suc a $;
theorem allnth (A: set) (l: nat) {n x: nat}: $ all A l <-> A. n A. x (nth n l = suc x -> x e. A) $;
theorem nthlmem (a l n: nat): $ nth n l = suc a -> a IN l $;
theorem appendnth1 (i l1 l2: nat): $ i < len l1 -> nth i (l1 ++ l2) = nth i l1 $;
theorem appendnth2_ (i l1 l2: nat): $ nth (len l1 + i) (l1 ++ l2) = nth i l2 $;
theorem appendnth2 (i l1 l2: nat): $ len l1 <= i -> nth i (l1 ++ l2) = nth (i - len l1) l2 $;

repeat a n is the list of n repetitions of a.

repeat : A -> nat -> List A

abstract def repeat (a n: nat): nat = $ rec 0 (\ x, a : x) n $;
theorem repeateqd (_G: wff) (_a1 _a2 _n1 _n2: nat): $ _G -> _a1 = _a2 $ > $ _G -> _n1 = _n2 $ > $ _G -> repeat _a1 _n1 = repeat _a2 _n2 $;
theorem repeateq (_a1 _a2 _n1 _n2: nat): $ _a1 = _a2 -> _n1 = _n2 -> repeat _a1 _n1 = repeat _a2 _n2 $;
theorem repeateq1d (_G: wff) (_a1 _a2 n: nat): $ _G -> _a1 = _a2 $ > $ _G -> repeat _a1 n = repeat _a2 n $;
theorem repeateq1 (_a1 _a2 n: nat): $ _a1 = _a2 -> repeat _a1 n = repeat _a2 n $;
theorem repeateq2d (_G: wff) (a _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> repeat a _n1 = repeat a _n2 $;
theorem repeateq2 (a _n1 _n2: nat): $ _n1 = _n2 -> repeat a _n1 = repeat a _n2 $;
pub theorem repeat0 (a: nat): $ repeat a 0 = 0 $;
pub theorem repeatS (a n: nat): $ repeat a (suc n) = a : repeat a n $;
theorem repeat1 (a: nat): $ repeat a 1 = a : 0 $;
theorem repeatlen (a n: nat): $ len (repeat a n) = n $;
theorem repeatadd (a m n: nat): $ repeat a (m + n) = repeat a m ++ repeat a n $;
theorem repeatT (A: set) (a n: nat): $ a e. A -> repeat a n e. List A $;
theorem repeatArray (A: set) (a n: nat): $ a e. A -> repeat a n e. Array A n $;
local def grecaux1 (K: set) (x z n: nat): nat = $ recn z (\\ u, \ i, K @ (x - suc u, i)) n $;
theorem grecaux1eqd (_G: wff) (_K1 _K2: set) (_x1 _x2 _z1 _z2 _n1 _n2: nat):
  $ _G -> _K1 == _K2 $ >
  $ _G -> _x1 = _x2 $ >
  $ _G -> _z1 = _z2 $ >
  $ _G -> _n1 = _n2 $ >
  $ _G -> grecaux1 _K1 _x1 _z1 _n1 = grecaux1 _K2 _x2 _z2 _n2 $;
theorem grecaux1eq (_K1 _K2: set) (_x1 _x2 _z1 _z2 _n1 _n2: nat):
  $ _K1 == _K2 -> _x1 = _x2 -> _z1 = _z2 -> _n1 = _n2 -> grecaux1 _K1 _x1 _z1 _n1 = grecaux1 _K2 _x2 _z2 _n2 $;
theorem grecaux1eq1d (_G: wff) (_K1 _K2: set) (x z n: nat): $ _G -> _K1 == _K2 $ > $ _G -> grecaux1 _K1 x z n = grecaux1 _K2 x z n $;
theorem grecaux1eq1 (_K1 _K2: set) (x z n: nat): $ _K1 == _K2 -> grecaux1 _K1 x z n = grecaux1 _K2 x z n $;
theorem grecaux1eq2d (_G: wff) (K: set) (_x1 _x2 z n: nat): $ _G -> _x1 = _x2 $ > $ _G -> grecaux1 K _x1 z n = grecaux1 K _x2 z n $;
theorem grecaux1eq2 (K: set) (_x1 _x2 z n: nat): $ _x1 = _x2 -> grecaux1 K _x1 z n = grecaux1 K _x2 z n $;
theorem grecaux1eq3d (_G: wff) (K: set) (x _z1 _z2 n: nat): $ _G -> _z1 = _z2 $ > $ _G -> grecaux1 K x _z1 n = grecaux1 K x _z2 n $;
theorem grecaux1eq3 (K: set) (x _z1 _z2 n: nat): $ _z1 = _z2 -> grecaux1 K x _z1 n = grecaux1 K x _z2 n $;
theorem grecaux1eq4d (_G: wff) (K: set) (x z _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> grecaux1 K x z _n1 = grecaux1 K x z _n2 $;
theorem grecaux1eq4 (K: set) (x z _n1 _n2: nat): $ _n1 = _n2 -> grecaux1 K x z _n1 = grecaux1 K x z _n2 $;
theorem grecaux10 (K: set) (k x: nat): $ grecaux1 K x k 0 = k $;
theorem grecaux1S (K: set) (k n x: nat): $ grecaux1 K x k (suc n) = K @ (x - suc n, grecaux1 K x k n) $;
theorem grecaux1Sx (K: set) (k n x: nat): $ grecaux1 K (suc x) k (suc n) = grecaux1 K x (K @ (x, k)) n $;
local def grecaux2 (z: nat) (K F: set) (x n k: nat): nat = $ recn z (\\ u, \ i, F @ (u, grecaux1 K x k (x - suc u), i)) n $;
theorem grecaux2eqd (_G: wff) (_z1 _z2: nat) (_K1 _K2 _F1 _F2: set) (_x1 _x2 _n1 _n2 _k1 _k2: nat):
  $ _G -> _z1 = _z2 $ >
  $ _G -> _K1 == _K2 $ >
  $ _G -> _F1 == _F2 $ >
  $ _G -> _x1 = _x2 $ >
  $ _G -> _n1 = _n2 $ >
  $ _G -> _k1 = _k2 $ >
  $ _G -> grecaux2 _z1 _K1 _F1 _x1 _n1 _k1 = grecaux2 _z2 _K2 _F2 _x2 _n2 _k2 $;
theorem grecaux2eq (_z1 _z2: nat) (_K1 _K2 _F1 _F2: set) (_x1 _x2 _n1 _n2 _k1 _k2: nat):
  $ _z1 = _z2 -> _K1 == _K2 -> _F1 == _F2 -> _x1 = _x2 -> _n1 = _n2 -> _k1 = _k2 -> grecaux2 _z1 _K1 _F1 _x1 _n1 _k1 = grecaux2 _z2 _K2 _F2 _x2 _n2 _k2 $;
theorem grecaux2eq1d (_G: wff) (_z1 _z2: nat) (K F: set) (x n k: nat): $ _G -> _z1 = _z2 $ > $ _G -> grecaux2 _z1 K F x n k = grecaux2 _z2 K F x n k $;
theorem grecaux2eq1 (_z1 _z2: nat) (K F: set) (x n k: nat): $ _z1 = _z2 -> grecaux2 _z1 K F x n k = grecaux2 _z2 K F x n k $;
theorem grecaux2eq2d (_G: wff) (z: nat) (_K1 _K2 F: set) (x n k: nat): $ _G -> _K1 == _K2 $ > $ _G -> grecaux2 z _K1 F x n k = grecaux2 z _K2 F x n k $;
theorem grecaux2eq2 (z: nat) (_K1 _K2 F: set) (x n k: nat): $ _K1 == _K2 -> grecaux2 z _K1 F x n k = grecaux2 z _K2 F x n k $;
theorem grecaux2eq3d (_G: wff) (z: nat) (K _F1 _F2: set) (x n k: nat): $ _G -> _F1 == _F2 $ > $ _G -> grecaux2 z K _F1 x n k = grecaux2 z K _F2 x n k $;
theorem grecaux2eq3 (z: nat) (K _F1 _F2: set) (x n k: nat): $ _F1 == _F2 -> grecaux2 z K _F1 x n k = grecaux2 z K _F2 x n k $;
theorem grecaux2eq4d (_G: wff) (z: nat) (K F: set) (_x1 _x2 n k: nat): $ _G -> _x1 = _x2 $ > $ _G -> grecaux2 z K F _x1 n k = grecaux2 z K F _x2 n k $;
theorem grecaux2eq4 (z: nat) (K F: set) (_x1 _x2 n k: nat): $ _x1 = _x2 -> grecaux2 z K F _x1 n k = grecaux2 z K F _x2 n k $;
theorem grecaux2eq5d (_G: wff) (z: nat) (K F: set) (x _n1 _n2 k: nat): $ _G -> _n1 = _n2 $ > $ _G -> grecaux2 z K F x _n1 k = grecaux2 z K F x _n2 k $;
theorem grecaux2eq5 (z: nat) (K F: set) (x _n1 _n2 k: nat): $ _n1 = _n2 -> grecaux2 z K F x _n1 k = grecaux2 z K F x _n2 k $;
theorem grecaux2eq6d (_G: wff) (z: nat) (K F: set) (x n _k1 _k2: nat): $ _G -> _k1 = _k2 $ > $ _G -> grecaux2 z K F x n _k1 = grecaux2 z K F x n _k2 $;
theorem grecaux2eq6 (z: nat) (K F: set) (x n _k1 _k2: nat): $ _k1 = _k2 -> grecaux2 z K F x n _k1 = grecaux2 z K F x n _k2 $;
theorem grecaux20 (F K: set) (k x z: nat): $ grecaux2 z K F x 0 k = z $;
theorem grecaux2S (F K: set) (k n x z: nat): $ grecaux2 z K F x (suc n) k = F @ (n, grecaux1 K x k (x - suc n), grecaux2 z K F x n k) $;
theorem grecaux2Sx (F K: set) (k n x z: nat): $ n <= x -> grecaux2 z K F (suc x) n k = grecaux2 z K F x n (K @ (x, k)) $;

General recursion operator:

  • grec 0 k = z
  • grec (n+1) k = F n k (grec n (K n k))
local def grec (z: nat) (K F: set) (n k: nat): nat = $ grecaux2 z K F n n k $;
theorem greceqd (_G: wff) (_z1 _z2: nat) (_K1 _K2 _F1 _F2: set) (_n1 _n2 _k1 _k2: nat):
  $ _G -> _z1 = _z2 $ >
  $ _G -> _K1 == _K2 $ >
  $ _G -> _F1 == _F2 $ >
  $ _G -> _n1 = _n2 $ >
  $ _G -> _k1 = _k2 $ >
  $ _G -> grec _z1 _K1 _F1 _n1 _k1 = grec _z2 _K2 _F2 _n2 _k2 $;
theorem greceq (_z1 _z2: nat) (_K1 _K2 _F1 _F2: set) (_n1 _n2 _k1 _k2: nat):
  $ _z1 = _z2 -> _K1 == _K2 -> _F1 == _F2 -> _n1 = _n2 -> _k1 = _k2 -> grec _z1 _K1 _F1 _n1 _k1 = grec _z2 _K2 _F2 _n2 _k2 $;
theorem greceq1d (_G: wff) (_z1 _z2: nat) (K F: set) (n k: nat): $ _G -> _z1 = _z2 $ > $ _G -> grec _z1 K F n k = grec _z2 K F n k $;
theorem greceq1 (_z1 _z2: nat) (K F: set) (n k: nat): $ _z1 = _z2 -> grec _z1 K F n k = grec _z2 K F n k $;
theorem greceq2d (_G: wff) (z: nat) (_K1 _K2 F: set) (n k: nat): $ _G -> _K1 == _K2 $ > $ _G -> grec z _K1 F n k = grec z _K2 F n k $;
theorem greceq2 (z: nat) (_K1 _K2 F: set) (n k: nat): $ _K1 == _K2 -> grec z _K1 F n k = grec z _K2 F n k $;
theorem greceq3d (_G: wff) (z: nat) (K _F1 _F2: set) (n k: nat): $ _G -> _F1 == _F2 $ > $ _G -> grec z K _F1 n k = grec z K _F2 n k $;
theorem greceq3 (z: nat) (K _F1 _F2: set) (n k: nat): $ _F1 == _F2 -> grec z K _F1 n k = grec z K _F2 n k $;
theorem greceq4d (_G: wff) (z: nat) (K F: set) (_n1 _n2 k: nat): $ _G -> _n1 = _n2 $ > $ _G -> grec z K F _n1 k = grec z K F _n2 k $;
theorem greceq4 (z: nat) (K F: set) (_n1 _n2 k: nat): $ _n1 = _n2 -> grec z K F _n1 k = grec z K F _n2 k $;
theorem greceq5d (_G: wff) (z: nat) (K F: set) (n _k1 _k2: nat): $ _G -> _k1 = _k2 $ > $ _G -> grec z K F n _k1 = grec z K F n _k2 $;
theorem greceq5 (z: nat) (K F: set) (n _k1 _k2: nat): $ _k1 = _k2 -> grec z K F n _k1 = grec z K F n _k2 $;
theorem grec0 (F K: set) (k z: nat): $ grec z K F 0 k = z $;
theorem grecS (F K: set) (k n z: nat): $ grec z K F (suc n) k = F @ (n, k, grec z K F n (K @ (n, k))) $;
local def rev (l: nat): nat = $ lrec 0 (\\ a, \\ z, \ ih, ih |> a) l $;
theorem reveqd (_G: wff) (_l1 _l2: nat): $ _G -> _l1 = _l2 $ > $ _G -> rev _l1 = rev _l2 $;
theorem reveq (_l1 _l2: nat): $ _l1 = _l2 -> rev _l1 = rev _l2 $;
theorem rev0: $ rev 0 = 0 $;
theorem revS (a l: nat): $ rev (a : l) = rev l |> a $;
theorem revsn (a: nat): $ rev (a : 0) = a : 0 $;
theorem revappend (l1 l2: nat): $ rev (l1 ++ l2) = rev l2 ++ rev l1 $;
theorem revsnoc (a l: nat): $ rev (l |> a) = a : rev l $;
theorem revrev (l: nat): $ rev (rev l) = l $;
theorem revinj (l l2: nat): $ rev l = rev l2 <-> l = l2 $;
theorem reveq0 (l: nat): $ rev l = 0 <-> l = 0 $;
theorem exsnoc {a: nat} (l: nat) {l2: nat}: $ l != 0 <-> E. l2 E. a l = l2 |> a $;
theorem snocinj (a b l1 l2: nat): $ l1 |> a = l2 |> b <-> l1 = l2 /\ a = b $;
theorem appendcan2 (a b c: nat): $ a ++ c = b ++ c <-> a = b $;

map F l is the list obtained by applying the function F to every element of the list l to get another of the same length.

  • map F 0 = 0
  • map F (a : l) = F a : map F l

map : (A -> B) -> list A -> list B

abstract def map (F: set) (l: nat): nat = $ lrec 0 (\\ a, \\ z, \ ih, F @ a : ih) l $;
theorem mapeqd (_G: wff) (_F1 _F2: set) (_l1 _l2: nat): $ _G -> _F1 == _F2 $ > $ _G -> _l1 = _l2 $ > $ _G -> map _F1 _l1 = map _F2 _l2 $;
theorem mapeq (_F1 _F2: set) (_l1 _l2: nat): $ _F1 == _F2 -> _l1 = _l2 -> map _F1 _l1 = map _F2 _l2 $;
theorem mapeq1d (_G: wff) (_F1 _F2: set) (l: nat): $ _G -> _F1 == _F2 $ > $ _G -> map _F1 l = map _F2 l $;
theorem mapeq1 (_F1 _F2: set) (l: nat): $ _F1 == _F2 -> map _F1 l = map _F2 l $;
theorem mapeq2d (_G: wff) (F: set) (_l1 _l2: nat): $ _G -> _l1 = _l2 $ > $ _G -> map F _l1 = map F _l2 $;
theorem mapeq2 (F: set) (_l1 _l2: nat): $ _l1 = _l2 -> map F _l1 = map F _l2 $;
pub theorem map0 (F: set): $ map F 0 = 0 $;
pub theorem mapS (F: set) (a l: nat): $ map F (a : l) = F @ a : map F l $;
theorem maplen (F: set) (l: nat): $ len (map F l) = len l $;
theorem mapnth (F: set) (a l n: nat): $ nth n l = suc a -> nth n (map F l) = suc (F @ a) $;
theorem mapnthb (F: set) {a: nat} (b l n: nat): $ nth n (map F l) = suc b <-> E. a (nth n l = suc a /\ b = F @ a) $;
theorem lmemmapi (F: set) (a l: nat): $ a IN l -> F @ a IN map F l $;
theorem lmemmap (F: set) {a: nat} (b l: nat): $ b IN map F l <-> E. a (a IN l /\ b = F @ a) $;

ljoin L is the "join" operation of the list monad: it appends all the elements of the list of lists L.

  • ljoin 0 = 0
  • ljoin (l : L) = l ++ ljoin L

ljoin : list (list A) -> list A

abstract def ljoin (L: nat): nat = $ lrec 0 (\\ a, \\ z, \ ih, a ++ ih) L $;
theorem ljoineqd (_G: wff) (_L1 _L2: nat): $ _G -> _L1 = _L2 $ > $ _G -> ljoin _L1 = ljoin _L2 $;
theorem ljoineq (_L1 _L2: nat): $ _L1 = _L2 -> ljoin _L1 = ljoin _L2 $;
pub theorem ljoin0: $ ljoin 0 = 0 $;
pub theorem ljoinS (l L: nat): $ ljoin (l : L) = l ++ ljoin L $;
local def nztails (L: nat): nat = $ lrec 0 (\\ a, \\ z, \ ih, (a, z) : ih) L $;
theorem nztailseqd (_G: wff) (_L1 _L2: nat): $ _G -> _L1 = _L2 $ > $ _G -> nztails _L1 = nztails _L2 $;
theorem nztailseq (_L1 _L2: nat): $ _L1 = _L2 -> nztails _L1 = nztails _L2 $;
theorem nztails0: $ nztails 0 = 0 $;
theorem nztailsS (l L: nat): $ nztails (l : L) = (l, L) : nztails L $;
local def lfnaux (F: set) (k n: nat): nat = $ grec 0 (\\ _1, \ x, suc x) (\\ _2, \\ i, \ ih, F @ i : ih) n k $;
theorem lfnauxeqd (_G: wff) (_F1 _F2: set) (_k1 _k2 _n1 _n2: nat):
  $ _G -> _F1 == _F2 $ >
  $ _G -> _k1 = _k2 $ >
  $ _G -> _n1 = _n2 $ >
  $ _G -> lfnaux _F1 _k1 _n1 = lfnaux _F2 _k2 _n2 $;
theorem lfnauxeq (_F1 _F2: set) (_k1 _k2 _n1 _n2: nat): $ _F1 == _F2 -> _k1 = _k2 -> _n1 = _n2 -> lfnaux _F1 _k1 _n1 = lfnaux _F2 _k2 _n2 $;
theorem lfnauxeq1d (_G: wff) (_F1 _F2: set) (k n: nat): $ _G -> _F1 == _F2 $ > $ _G -> lfnaux _F1 k n = lfnaux _F2 k n $;
theorem lfnauxeq1 (_F1 _F2: set) (k n: nat): $ _F1 == _F2 -> lfnaux _F1 k n = lfnaux _F2 k n $;
theorem lfnauxeq2d (_G: wff) (F: set) (_k1 _k2 n: nat): $ _G -> _k1 = _k2 $ > $ _G -> lfnaux F _k1 n = lfnaux F _k2 n $;
theorem lfnauxeq2 (F: set) (_k1 _k2 n: nat): $ _k1 = _k2 -> lfnaux F _k1 n = lfnaux F _k2 n $;
theorem lfnauxeq3d (_G: wff) (F: set) (k _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> lfnaux F k _n1 = lfnaux F k _n2 $;
theorem lfnauxeq3 (F: set) (k _n1 _n2: nat): $ _n1 = _n2 -> lfnaux F k _n1 = lfnaux F k _n2 $;
theorem lfnaux0 (F: set) (k: nat): $ lfnaux F k 0 = 0 $;
theorem lfnauxS (F: set) (k n: nat): $ lfnaux F k (suc n) = F @ k : lfnaux F (suc k) n $;
theorem lfnauxshift (F1 F2: set) {i: nat} (k1 k2 n: nat): $ A. i F1 @ (k1 + i) = F2 @ (k2 + i) -> lfnaux F1 k1 n = lfnaux F2 k2 n $;
theorem lfnauxlen (F: set) (k n: nat): $ len (lfnaux F k n) = n $;
theorem lfnauxnth (F: set) (i k n: nat): $ i < n -> nth i (lfnaux F k n) = suc (F @ (k + i)) $;
local def lfn (F: set) (n: nat): nat = $ lfnaux F 0 n $;
theorem lfneqd (_G: wff) (_F1 _F2: set) (_n1 _n2: nat): $ _G -> _F1 == _F2 $ > $ _G -> _n1 = _n2 $ > $ _G -> lfn _F1 _n1 = lfn _F2 _n2 $;
theorem lfneq (_F1 _F2: set) (_n1 _n2: nat): $ _F1 == _F2 -> _n1 = _n2 -> lfn _F1 _n1 = lfn _F2 _n2 $;
theorem lfneq1d (_G: wff) (_F1 _F2: set) (n: nat): $ _G -> _F1 == _F2 $ > $ _G -> lfn _F1 n = lfn _F2 n $;
theorem lfneq1 (_F1 _F2: set) (n: nat): $ _F1 == _F2 -> lfn _F1 n = lfn _F2 n $;
theorem lfneq2d (_G: wff) (F: set) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> lfn F _n1 = lfn F _n2 $;
theorem lfneq2 (F: set) (_n1 _n2: nat): $ _n1 = _n2 -> lfn F _n1 = lfn F _n2 $;
theorem lfn0 (F: set): $ lfn F 0 = 0 $;
theorem lfnS (F: set) {i: nat} (n: nat): $ lfn F (suc n) = F @ 0 : lfn (\ i, F @ suc i) n $;
theorem lenlfn (F: set) (n: nat): $ len (lfn F n) = n $;
theorem nthlfn (F: set) (i n: nat): $ i < n -> nth i (lfn F n) = suc (F @ i) $;
theorem lfnnth {i: nat} (l: nat): $ lfn (\ i, nth i l - 1) (len l) = l $;
theorem nthext2d (G: wff) (l1 l2 n: nat) {i: nat}: $ G -> len l1 = n $ > $ G -> len l2 = n $ > $ G /\ i < n -> nth i l1 = nth i l2 $ > $ G -> l1 = l2 $;
theorem nthext2 (l1 l2 n: nat) {i: nat}: $ len l1 = n $ > $ len l2 = n $ > $ i < n -> nth i l1 = nth i l2 $ > $ l1 = l2 $;
theorem nthext (l1 l2: nat) {n: nat}: $ l1 = l2 <-> A. n nth n l1 = nth n l2 $;
local def zip (l1 l2: nat): nat = $ lfn (\ i, nth i l1 - 1, nth i l2 - 1) (min (len l1) (len l2)) $;
theorem zipeqd (_G: wff) (_l11 _l12 _l21 _l22: nat): $ _G -> _l11 = _l12 $ > $ _G -> _l21 = _l22 $ > $ _G -> zip _l11 _l21 = zip _l12 _l22 $;
theorem zipeq (_l11 _l12 _l21 _l22: nat): $ _l11 = _l12 -> _l21 = _l22 -> zip _l11 _l21 = zip _l12 _l22 $;
theorem zipeq1d (_G: wff) (_l11 _l12 l2: nat): $ _G -> _l11 = _l12 $ > $ _G -> zip _l11 l2 = zip _l12 l2 $;
theorem zipeq1 (_l11 _l12 l2: nat): $ _l11 = _l12 -> zip _l11 l2 = zip _l12 l2 $;
theorem zipeq2d (_G: wff) (l1 _l21 _l22: nat): $ _G -> _l21 = _l22 $ > $ _G -> zip l1 _l21 = zip l1 _l22 $;
theorem zipeq2 (l1 _l21 _l22: nat): $ _l21 = _l22 -> zip l1 _l21 = zip l1 _l22 $;
theorem ziplen (l1 l2: nat): $ len (zip l1 l2) = min (len l1) (len l2) $;
theorem zipnth (G: wff) (a b i l1 l2: nat): $ G -> nth i l1 = suc a $ > $ G -> nth i l2 = suc b $ > $ G -> nth i (zip l1 l2) = suc (a, b) $;
theorem zip01 (l: nat): $ zip 0 l = 0 $;
theorem zip02 (l: nat): $ zip l 0 = 0 $;
theorem zipS (a b l1 l2: nat): $ zip (a : l1) (b : l2) = (a, b) : zip l1 l2 $;
local def take (l n: nat): nat = $ lfn (\ i, nth i l - 1) (min (len l) n) $;
theorem takeeqd (_G: wff) (_l1 _l2 _n1 _n2: nat): $ _G -> _l1 = _l2 $ > $ _G -> _n1 = _n2 $ > $ _G -> take _l1 _n1 = take _l2 _n2 $;
theorem takeeq (_l1 _l2 _n1 _n2: nat): $ _l1 = _l2 -> _n1 = _n2 -> take _l1 _n1 = take _l2 _n2 $;
theorem takeeq1d (_G: wff) (_l1 _l2 n: nat): $ _G -> _l1 = _l2 $ > $ _G -> take _l1 n = take _l2 n $;
theorem takeeq1 (_l1 _l2 n: nat): $ _l1 = _l2 -> take _l1 n = take _l2 n $;
theorem takeeq2d (_G: wff) (l _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> take l _n1 = take l _n2 $;
theorem takeeq2 (l _n1 _n2: nat): $ _n1 = _n2 -> take l _n1 = take l _n2 $;
local def drop (l n: nat): nat = $ lfn (\ i, nth (i + n) l - 1) (len l - n) $;
theorem dropeqd (_G: wff) (_l1 _l2 _n1 _n2: nat): $ _G -> _l1 = _l2 $ > $ _G -> _n1 = _n2 $ > $ _G -> drop _l1 _n1 = drop _l2 _n2 $;
theorem dropeq (_l1 _l2 _n1 _n2: nat): $ _l1 = _l2 -> _n1 = _n2 -> drop _l1 _n1 = drop _l2 _n2 $;
theorem dropeq1d (_G: wff) (_l1 _l2 n: nat): $ _G -> _l1 = _l2 $ > $ _G -> drop _l1 n = drop _l2 n $;
theorem dropeq1 (_l1 _l2 n: nat): $ _l1 = _l2 -> drop _l1 n = drop _l2 n $;
theorem dropeq2d (_G: wff) (l _n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> drop l _n1 = drop l _n2 $;
theorem dropeq2 (l _n1 _n2: nat): $ _n1 = _n2 -> drop l _n1 = drop l _n2 $;
theorem takelen (l n: nat): $ len (take l n) = min (len l) n $;
theorem droplen (l n: nat): $ len (drop l n) = len l - n $;
theorem takenth (i l n: nat): $ i < n -> nth i (take l n) = nth i l $;
theorem takenth0 (i l n: nat): $ n <= i -> nth i (take l n) = 0 $;
theorem dropnth (i l n: nat): $ nth i (drop l n) = nth (i + n) l $;
theorem takedrop (l n: nat): $ take l n ++ drop l n = l $;
theorem takeArray (A: set) (l m n: nat): $ m <= n /\ l e. Array A n -> take l m e. Array A m $;
theorem dropArray (A: set) (l m n: nat): $ l e. Array A (m + n) -> drop l m e. Array A n $;
theorem take0 (l: nat): $ take l 0 = 0 $;
theorem drop0 (l: nat): $ drop l 0 = l $;
theorem dropall (l n: nat): $ len l <= n -> drop l n = 0 $;
theorem takeall (l n: nat): $ len l <= n -> take l n = l $;
theorem takemin (l n: nat): $ take l (min (len l) n) = take l n $;
theorem takeappend1 (l1 l2 n: nat): $ n <= len l1 -> take (l1 ++ l2) n = take l1 n $;
theorem appendinj1 (l1 l2 r1 r2: nat): $ len l1 = len r1 -> (l1 ++ l2 = r1 ++ r2 <-> l1 = r1 /\ l2 = r2) $;
theorem appendinj2 (l1 l2 r1 r2: nat): $ len l2 = len r2 -> (l1 ++ l2 = r1 ++ r2 <-> l1 = r1 /\ l2 = r2) $;
theorem eqappendlem {a: nat} (l1 l2 r1 r2: nat): $ len r1 <= len l1 /\ l1 ++ l2 = r1 ++ r2 -> E. a (l1 = r1 ++ a /\ r2 = a ++ l2) $;
theorem eqappend {a: nat} (l1 l2 r1 r2: nat): $ l1 ++ l2 = r1 ++ r2 <-> E. a (r1 = l1 ++ a /\ l2 = a ++ r2 \/ l1 = r1 ++ a /\ r2 = a ++ l2) $;

sublistAt n L1 L2 means that L2 = L1[n..n+a] where a is the length of L2.

sublistAt : nat -> List A -> List A -> Bool

def sublistAt (n L1 L2: nat): wff = $ E. l E. r (L1 = l ++ L2 ++ r /\ len l = n) $;
theorem sublistAteqd (_G: wff) (_n1 _n2 _L11 _L12 _L21 _L22: nat):
  $ _G -> _n1 = _n2 $ >
  $ _G -> _L11 = _L12 $ >
  $ _G -> _L21 = _L22 $ >
  $ _G -> (sublistAt _n1 _L11 _L21 <-> sublistAt _n2 _L12 _L22) $;
theorem sublistAteq (_n1 _n2 _L11 _L12 _L21 _L22: nat): $ _n1 = _n2 -> _L11 = _L12 -> _L21 = _L22 -> (sublistAt _n1 _L11 _L21 <-> sublistAt _n2 _L12 _L22) $;
theorem sublistAteq1d (_G: wff) (_n1 _n2 L1 L2: nat): $ _G -> _n1 = _n2 $ > $ _G -> (sublistAt _n1 L1 L2 <-> sublistAt _n2 L1 L2) $;
theorem sublistAteq1 (_n1 _n2 L1 L2: nat): $ _n1 = _n2 -> (sublistAt _n1 L1 L2 <-> sublistAt _n2 L1 L2) $;
theorem sublistAteq2d (_G: wff) (n _L11 _L12 L2: nat): $ _G -> _L11 = _L12 $ > $ _G -> (sublistAt n _L11 L2 <-> sublistAt n _L12 L2) $;
theorem sublistAteq2 (n _L11 _L12 L2: nat): $ _L11 = _L12 -> (sublistAt n _L11 L2 <-> sublistAt n _L12 L2) $;
theorem sublistAteq3d (_G: wff) (n L1 _L21 _L22: nat): $ _G -> _L21 = _L22 $ > $ _G -> (sublistAt n L1 _L21 <-> sublistAt n L1 _L22) $;
theorem sublistAteq3 (n L1 _L21 _L22: nat): $ _L21 = _L22 -> (sublistAt n L1 _L21 <-> sublistAt n L1 _L22) $;
theorem sublistAtT (A: set) (L1 L2 n: nat): $ sublistAt n L1 L2 -> L1 e. List A -> L2 e. List A $;
theorem sublistAt_append (l l1 l2 n: nat): $ sublistAt n l (l1 ++ l2) <-> sublistAt n l l1 /\ sublistAt (n + len l1) l l2 $;
theorem sublistAt_len_le (L1 L2 n: nat): $ sublistAt n L1 L2 -> n + len L2 <= len L1 $;
theorem sublistAt_left (L1 L2 l n: nat): $ sublistAt n L1 L2 -> sublistAt n (L1 ++ l) L2 $;
theorem sublistAt_right (L1 L2 l n: nat): $ sublistAt n L1 L2 -> sublistAt (len l + n) (l ++ L1) L2 $;
theorem sublistAt_id (L: nat): $ sublistAt 0 L L $;

L1, L2 e. all2 R means that L1 and L2 are lists of the same length that are pairwise related by R.

all2 : (A -> B -> Bool) -> (list A -> list B -> Bool)

def all2 (R: set): set = $ S\ l1, {l2 | len l1 = len l2 /\ A. n A. x A. y (nth n l1 = suc x -> nth n l2 = suc y -> x, y e. R)} $;
theorem all2eqd (_G: wff) (_R1 _R2: set): $ _G -> _R1 == _R2 $ > $ _G -> all2 _R1 == all2 _R2 $;
theorem all2eq (_R1 _R2: set): $ _R1 == _R2 -> all2 _R1 == all2 _R2 $;
theorem elall2 (R: set) (l1 l2: nat) {n x y: nat}:
  $ l1, l2 e. all2 R <-> len l1 = len l2 /\ A. n A. x A. y (nth n l1 = suc x -> nth n l2 = suc y -> x, y e. R) $;
theorem elall22 (R: set) (l1 l2: nat) {n x y: nat}:
  $ l1, l2 e. all2 R <-> len l1 = len l2 /\ A. n A. x (nth n l1 = suc x -> A. y (nth n l2 = suc y -> x, y e. R)) $;
theorem all2ssg (R S: set) (l1 l2: nat) {x y: nat}: $ A. x A. y (x IN l1 /\ y IN l2 -> x, y e. R -> x, y e. S) -> l1, l2 e. all2 R -> l1, l2 e. all2 S $;
theorem all2ss (R S: set): $ R C_ S -> all2 R C_ all2 S $;
theorem all2eqg (R S: set) (l1 l2: nat) {x y: nat}: $ A. x A. y (x IN l1 /\ y IN l2 -> (x, y e. R <-> x, y e. S)) -> (l1, l2 e. all2 R <-> l1, l2 e. all2 S) $;
theorem all2len (R: set) (l1 l2: nat): $ l1, l2 e. all2 R -> len l1 = len l2 $;
theorem all2i (G: wff) (R: set) (a b l1 l2 n: nat): $ G -> nth n l1 = suc a $ > $ G -> nth n l2 = suc b $ > $ G -> l1, l2 e. all2 R $ > $ G -> a, b e. R $;
theorem all2com (R: set) (l1 l2: nat): $ l1, l2 e. all2 (cnv R) <-> l2, l1 e. all2 R $;
theorem all2cnv (R: set): $ all2 (cnv R) == cnv (all2 R) $;
theorem all20 (R: set): $ 0, 0 e. all2 R $;
theorem all201 (R: set) (l: nat): $ 0, l e. all2 R <-> l = 0 $;
theorem all202 (R: set) (l: nat): $ l, 0 e. all2 R <-> l = 0 $;
theorem all2S (R: set) (a b l1 l2: nat): $ a : l1, b : l2 e. all2 R <-> a, b e. R /\ l1, l2 e. all2 R $;
theorem all2S1 (R: set) (a: nat) {b: nat} (l1 l2: nat) {l2_: nat}: $ a : l1, l2 e. all2 R <-> E. b E. l2_ (l2 = b : l2_ /\ (a, b e. R /\ l1, l2_ e. all2 R)) $;
theorem all2all2 (A: set) (l1 l2: nat) {x: nat}: $ l1, l2 e. all2 (S\ x, A) -> all A l2 $;
theorem all2all1 (A: set) (l1 l2: nat) {x y: nat}: $ l1, l2 e. all2 (S\ x, {y | x e. A}) -> all A l1 $;

L1, L2 e. ex2 R means that L1 and L2 are lists of the same length for which some pair is related by R.

ex2 : (A -> B -> Bool) -> (list A -> list B -> Bool)

def ex2 (R: set): set = $ S\ l1, {l2 | len l1 = len l2 /\ E. n E. x E. y (nth n l1 = suc x /\ nth n l2 = suc y /\ x, y e. R)} $;
theorem ex2eqd (_G: wff) (_R1 _R2: set): $ _G -> _R1 == _R2 $ > $ _G -> ex2 _R1 == ex2 _R2 $;
theorem ex2eq (_R1 _R2: set): $ _R1 == _R2 -> ex2 _R1 == ex2 _R2 $;
theorem elex2 (R: set) (l1 l2: nat) {n x y: nat}: $ l1, l2 e. ex2 R <-> len l1 = len l2 /\ E. n E. x E. y (nth n l1 = suc x /\ nth n l2 = suc y /\ x, y e. R) $;
theorem elex22 (R: set) (l1 l2: nat) {n x y: nat}:
  $ l1, l2 e. ex2 R <-> len l1 = len l2 /\ E. n E. x (nth n l1 = suc x /\ E. y (nth n l2 = suc y /\ x, y e. R)) $;
theorem ex2ssg (R S: set) (l1 l2: nat) {x y: nat}: $ A. x A. y (x IN l1 /\ y IN l2 -> x, y e. R -> x, y e. S) -> l1, l2 e. ex2 R -> l1, l2 e. ex2 S $;
theorem ex2eqg (R S: set) (l1 l2: nat) {x y: nat}: $ A. x A. y (x IN l1 /\ y IN l2 -> (x, y e. R <-> x, y e. S)) -> (l1, l2 e. ex2 R <-> l1, l2 e. ex2 S) $;
theorem ex2ss (R S: set): $ R C_ S -> ex2 R C_ ex2 S $;
theorem ex2len (R: set) (l1 l2: nat): $ l1, l2 e. ex2 R -> len l1 = len l2 $;
theorem ex2com (R: set) (l1 l2: nat): $ l1, l2 e. ex2 (cnv R) <-> l2, l1 e. ex2 R $;
theorem ex2cnv (R: set): $ ex2 (cnv R) == cnv (ex2 R) $;
theorem ex201 (R: set) (l: nat): $ ~0, l e. ex2 R $;
theorem ex202 (R: set) (l: nat): $ ~l, 0 e. ex2 R $;
theorem all2nex (R: set) (l1 l2: nat): $ l1, l2 e. all2 (Compl R) <-> len l1 = len l2 /\ ~l1, l2 e. ex2 R $;
theorem dfex2_2 (R: set) (l1 l2: nat): $ l1, l2 e. ex2 R <-> len l1 = len l2 /\ ~l1, l2 e. all2 (Compl R) $;
theorem ex2nal (R: set) (l1 l2: nat): $ l1, l2 e. ex2 (Compl R) <-> len l1 = len l2 /\ ~l1, l2 e. all2 R $;
theorem mapeqg (F G: set) (l: nat) {x: nat}: $ all {x | F @ x = G @ x} l -> map F l = map G l $;
local def rlrec (z: nat) (S: set) (n: nat): nat = $ lrec z (\\ a, \\ l, \ ih, S @ (rev l, a, ih)) (rev n) $;
theorem rlreceqd (_G: wff) (_z1 _z2: nat) (_S1 _S2: set) (_n1 _n2: nat):
  $ _G -> _z1 = _z2 $ >
  $ _G -> _S1 == _S2 $ >
  $ _G -> _n1 = _n2 $ >
  $ _G -> rlrec _z1 _S1 _n1 = rlrec _z2 _S2 _n2 $;
theorem rlreceq (_z1 _z2: nat) (_S1 _S2: set) (_n1 _n2: nat): $ _z1 = _z2 -> _S1 == _S2 -> _n1 = _n2 -> rlrec _z1 _S1 _n1 = rlrec _z2 _S2 _n2 $;
theorem rlreceq1d (_G: wff) (_z1 _z2: nat) (S: set) (n: nat): $ _G -> _z1 = _z2 $ > $ _G -> rlrec _z1 S n = rlrec _z2 S n $;
theorem rlreceq1 (_z1 _z2: nat) (S: set) (n: nat): $ _z1 = _z2 -> rlrec _z1 S n = rlrec _z2 S n $;
theorem rlreceq2d (_G: wff) (z: nat) (_S1 _S2: set) (n: nat): $ _G -> _S1 == _S2 $ > $ _G -> rlrec z _S1 n = rlrec z _S2 n $;
theorem rlreceq2 (z: nat) (_S1 _S2: set) (n: nat): $ _S1 == _S2 -> rlrec z _S1 n = rlrec z _S2 n $;
theorem rlreceq3d (_G: wff) (z: nat) (S: set) (_n1 _n2: nat): $ _G -> _n1 = _n2 $ > $ _G -> rlrec z S _n1 = rlrec z S _n2 $;
theorem rlreceq3 (z: nat) (S: set) (_n1 _n2: nat): $ _n1 = _n2 -> rlrec z S _n1 = rlrec z S _n2 $;
theorem rlrec0 (S: set) (z: nat): $ rlrec z S 0 = z $;
theorem rlrecS (S: set) (a l z: nat): $ rlrec z S (l |> a) = S @ (l, a, rlrec z S l) $;
theorem rlistindd (G: wff) {x l a: nat} (n: nat) (px: wff x) (p0 pn: wff) (pl: wff l) (ps: wff l a):
  $ x = n -> (px <-> pn) $ >
  $ x = 0 -> (px <-> p0) $ >
  $ x = l -> (px <-> pl) $ >
  $ x = l |> a -> (px <-> ps) $ >
  $ G -> p0 $ >
  $ G /\ pl -> ps $ >
  $ G -> pn $;
theorem rlistind {x l a: nat} (n: nat) (px: wff x) (p0 pn: wff) (pl: wff l) (ps: wff l a):
  $ x = n -> (px <-> pn) $ >
  $ x = 0 -> (px <-> p0) $ >
  $ x = l -> (px <-> pl) $ >
  $ x = l |> a -> (px <-> ps) $ >
  $ p0 $ >
  $ pl -> ps $ >
  $ pn $;