2024-11-20 07:37:57 -08:00
|
|
|
-- --------------------------------------------------------------------------------------------------------------
|
|
|
|
|
-- | BASIC LOGIC |
|
|
|
|
|
-- --------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
2024-11-22 10:36:51 -08:00
|
|
|
@include logic.pg
|
2024-11-20 07:37:57 -08:00
|
|
|
|
|
|
|
|
-- --------------------------------------------------------------------------------------------------------------
|
|
|
|
|
-- | BASIC DEFINITIONS |
|
|
|
|
|
-- --------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
2024-12-06 15:59:22 -08:00
|
|
|
section BasicDefinitions
|
2024-11-20 07:37:57 -08:00
|
|
|
|
2024-12-06 15:59:22 -08:00
|
|
|
-- note we leave off the type ascriptions for most of these, as the type isn't
|
|
|
|
|
-- very interesting
|
|
|
|
|
-- I'd always strongly recommend including the type ascriptions for theorems
|
2024-11-20 07:37:57 -08:00
|
|
|
|
2024-12-06 15:59:22 -08:00
|
|
|
-- Fix some set A
|
|
|
|
|
variable (A : *);
|
2024-11-20 07:37:57 -08:00
|
|
|
|
2024-12-06 15:59:22 -08:00
|
|
|
-- a unary operation is a function `A -> A`
|
|
|
|
|
def unop := A -> A;
|
2024-11-20 07:37:57 -08:00
|
|
|
|
2024-12-06 15:59:22 -08:00
|
|
|
-- a binary operation is a function `A -> A -> A`
|
|
|
|
|
def binop := A -> A -> A;
|
2024-11-20 07:37:57 -08:00
|
|
|
|
2024-12-06 15:59:22 -08:00
|
|
|
-- fix some binary operation `op`
|
|
|
|
|
variable (op : binop);
|
2024-11-20 07:37:57 -08:00
|
|
|
|
2024-12-06 15:59:22 -08:00
|
|
|
-- it is associative if ...
|
|
|
|
|
def assoc := forall (a b c : A), eq A (op a (op b c)) (op (op a b) c);
|
2024-11-20 07:37:57 -08:00
|
|
|
|
2024-12-06 15:59:22 -08:00
|
|
|
-- fix some element `e`
|
|
|
|
|
variable (e : A);
|
2024-11-20 07:37:57 -08:00
|
|
|
|
2024-12-06 15:59:22 -08:00
|
|
|
-- it is a left identity with respect to binop `op` if `∀ a, e * a = a`
|
|
|
|
|
def id_l := forall (a : A), eq A (op e a) a;
|
2024-11-20 07:37:57 -08:00
|
|
|
|
2024-12-06 15:59:22 -08:00
|
|
|
-- likewise for right identity
|
|
|
|
|
def id_r := forall (a : A), eq A (op a e) a;
|
|
|
|
|
|
|
|
|
|
-- an element is an identity element if it is both a left and right identity
|
|
|
|
|
def id := and id_l id_r;
|
|
|
|
|
|
|
|
|
|
-- b is a left inverse for a if `b * a = e`
|
|
|
|
|
-- NOTE: we don't require `e` to be an identity in this definition.
|
|
|
|
|
-- this definition is purely for convenience's sake
|
|
|
|
|
def inv_l (a b : A) := eq A (op b a) e;
|
|
|
|
|
|
|
|
|
|
-- likewise for right inverse
|
|
|
|
|
def inv_r (a b : A) := eq A (op a b) e;
|
|
|
|
|
|
|
|
|
|
-- and full-on inverse
|
|
|
|
|
def inv (a b : A) := and (inv_l a b) (inv_r a b);
|
|
|
|
|
|
|
|
|
|
end BasicDefinitions
|
2024-11-20 07:37:57 -08:00
|
|
|
|
|
|
|
|
-- --------------------------------------------------------------------------------------------------------------
|
|
|
|
|
-- | ALGEBRAIC STRUCTURES |
|
|
|
|
|
-- --------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
-- a set `S` with binary operation `op` is a semigroup if its operation is associative
|
2024-12-01 15:29:05 -08:00
|
|
|
def semigroup (S : *) (op : binop S) : * := assoc S op;
|
2024-11-20 07:37:57 -08:00
|
|
|
|
2024-12-06 15:59:22 -08:00
|
|
|
section Monoid
|
|
|
|
|
|
|
|
|
|
variable (M : *) (op : binop M) (e : M);
|
|
|
|
|
|
|
|
|
|
-- a set `M` with binary operation `op` and element `e` is a monoid
|
|
|
|
|
def monoid : * := and (semigroup M op) (id M op e);
|
|
|
|
|
|
|
|
|
|
hypothesis (Hmonoid : monoid);
|
|
|
|
|
|
|
|
|
|
-- some "getters" for `monoid` so we don't have to do a bunch of very verbose
|
|
|
|
|
-- and-eliminations every time we want to use something
|
2024-12-08 17:40:37 -08:00
|
|
|
def id_lm : id_l M op e :=
|
2024-12-06 15:59:22 -08:00
|
|
|
and_elim_l (id_l M op e) (id_r M op e)
|
|
|
|
|
(and_elim_r (semigroup M op) (id M op e) Hmonoid);
|
|
|
|
|
|
|
|
|
|
def id_rm : id_r M op e :=
|
|
|
|
|
and_elim_r (id_l M op e) (id_r M op e)
|
|
|
|
|
(and_elim_r (semigroup M op) (id M op e) Hmonoid);
|
|
|
|
|
|
|
|
|
|
def assoc_m : assoc M op := and_elim_l (semigroup M op) (id M op e) Hmonoid;
|
|
|
|
|
|
|
|
|
|
-- now we can prove that, for any monoid, if `a` is a left identity, then it
|
|
|
|
|
-- must be "the" identity
|
|
|
|
|
def monoid_id_l_implies_identity (a : M) (H : id_l M op a) : eq M a e :=
|
|
|
|
|
-- WTS a = a * e = e
|
|
|
|
|
-- we can use `eq_trans` to glue proofs of `a = a * e` and `a * e = e` together
|
|
|
|
|
eq_trans M a (op a e) e
|
|
|
|
|
|
|
|
|
|
-- first, `a = a * e`, but we'll use `eq_sym` to flip it around
|
|
|
|
|
(eq_sym M (op a e) a
|
|
|
|
|
-- now the goal is to show `a * e = a`, which follows immediately from `id_r`
|
|
|
|
|
(id_rm a))
|
|
|
|
|
|
|
|
|
|
-- now we need to show that `a * e = e`, but this immediately follows from `H`
|
|
|
|
|
(H e);
|
|
|
|
|
|
|
|
|
|
-- the analogous result for right identities
|
|
|
|
|
def monoid_id_r_implies_identity (a : M) (H : id_r M op a) : eq M a e :=
|
|
|
|
|
-- this time, we'll show `a = e * a = e`
|
|
|
|
|
eq_trans M a (op e a) e
|
|
|
|
|
|
|
|
|
|
-- first, `a = e * a`
|
|
|
|
|
(eq_sym M (op e a) a
|
|
|
|
|
-- this time, it immediately follows from `id_l`
|
|
|
|
|
(id_lm a))
|
|
|
|
|
|
|
|
|
|
-- and `e * a = e`
|
|
|
|
|
(H e);
|
|
|
|
|
|
|
|
|
|
end Monoid
|
|
|
|
|
|
|
|
|
|
section Group
|
|
|
|
|
|
|
|
|
|
variable (G : *) (op : binop G) (e : G) (i : unop G);
|
|
|
|
|
|
|
|
|
|
-- groups are just monoids with inverses
|
|
|
|
|
def has_inverses : * := forall (a : G), inv G op e a (i a);
|
|
|
|
|
|
|
|
|
|
def group : * := and (monoid G op e) has_inverses;
|
|
|
|
|
|
|
|
|
|
hypothesis (Hgroup : group);
|
|
|
|
|
|
|
|
|
|
-- more "getters"
|
|
|
|
|
def monoid_g : monoid G op e := and_elim_l (monoid G op e) has_inverses Hgroup;
|
|
|
|
|
def assoc_g : assoc G op := assoc_m G op e monoid_g;
|
|
|
|
|
def id_lg : id_l G op e := id_lm G op e (and_elim_l (monoid G op e) has_inverses Hgroup);
|
|
|
|
|
def id_rg : id_r G op e := id_rm G op e (and_elim_l (monoid G op e) has_inverses Hgroup);
|
|
|
|
|
def inv_g : forall (a : G), inv G op e a (i a) := and_elim_r (monoid G op e) has_inverses Hgroup;
|
|
|
|
|
def left_inverse (a b : G) := inv_l G op e a b;
|
|
|
|
|
def right_inverse (a b : G) := inv_r G op e a b;
|
|
|
|
|
def inv_lg (a : G) : left_inverse a (i a) := and_elim_l (inv_l G op e a (i a)) (inv_r G op e a (i a)) (inv_g a);
|
|
|
|
|
def inv_rg (a : G) : right_inverse a (i a) := and_elim_r (inv_l G op e a (i a)) (inv_r G op e a (i a)) (inv_g a);
|
|
|
|
|
|
|
|
|
|
-- An interesting theorem: left inverses are unique, i.e. if b * a = e, then b = a^-1
|
|
|
|
|
def left_inv_unique (a b : G) (h : left_inverse a b) : eq G b (i a) :=
|
|
|
|
|
-- b = b * e
|
|
|
|
|
-- = b * (a * a^-1)
|
|
|
|
|
-- = (b * a) * a^-1
|
|
|
|
|
-- = e * a^-1
|
|
|
|
|
-- = a^-1
|
|
|
|
|
eq_trans G b (op b e) (i a)
|
|
|
|
|
-- b = b * e
|
|
|
|
|
(eq_sym G (op b e) b (id_rg b))
|
|
|
|
|
-- b * e = a^-1
|
|
|
|
|
(eq_trans G (op b e) (op b (op a (i a))) (i a)
|
|
|
|
|
--b * e = b * (a * a^-1)
|
|
|
|
|
(eq_cong G G e (op a (i a)) (op b)
|
|
|
|
|
-- e = a * a^-1
|
|
|
|
|
(eq_sym G (op a (i a)) e (inv_rg a)))
|
|
|
|
|
-- b * (a * a^-1) = a^-1
|
|
|
|
|
(eq_trans G (op b (op a (i a))) (op (op b a) (i a)) (i a)
|
|
|
|
|
-- b * (a * a^-1) = (b * a) * a^-1
|
|
|
|
|
(assoc_g b a (i a))
|
|
|
|
|
-- (b * a) * a^-1 = a^-1
|
|
|
|
|
(eq_trans G (op (op b a) (i a)) (op e (i a)) (i a)
|
|
|
|
|
-- (b * a) * a^-1 = e * a^-1
|
|
|
|
|
(eq_cong G G (op b a) e (fun (x : G) => op x (i a)) h)
|
|
|
|
|
-- e * a^-1 = a^-1
|
|
|
|
|
(id_lg (i a)))));
|
|
|
|
|
|
2024-12-06 16:30:44 -08:00
|
|
|
-- And so are right inverses
|
|
|
|
|
def right_inv_unique (a b : G) (h : right_inverse a b) : eq G b (i a) :=
|
|
|
|
|
-- b = e * b
|
|
|
|
|
-- = (a^-1 * a) * b
|
|
|
|
|
-- = a^-1 * (a * b)
|
|
|
|
|
-- = a^-1 * e
|
|
|
|
|
-- = a^-1
|
|
|
|
|
eq_trans G b (op e b) (i a)
|
|
|
|
|
-- b = e * b
|
|
|
|
|
(eq_sym G (op e b) b (id_lg b))
|
|
|
|
|
-- e * b = a^-1
|
|
|
|
|
(eq_trans G (op e b) (op (op (i a) a) b) (i a)
|
|
|
|
|
-- e * b = (a^-1 * a) * b
|
|
|
|
|
(eq_cong G G e (op (i a) a) (fun (x : G) => op x b)
|
|
|
|
|
-- e = (a^-1 * a)
|
|
|
|
|
(eq_sym G (op (i a) a) e (inv_lg a)))
|
|
|
|
|
|
|
|
|
|
-- (a^-1 * a) * b = a^-1
|
|
|
|
|
(eq_trans G (op (op (i a) a) b) (op (i a) (op a b)) (i a)
|
|
|
|
|
-- (a^-1 * a) * b = a^-1 * (a * b)
|
|
|
|
|
(eq_sym G (op (i a) (op a b)) (op (op (i a) a) b) (assoc_g (i a) a b))
|
|
|
|
|
|
|
|
|
|
-- a^-1 * (a * b) = a^-1
|
|
|
|
|
(eq_trans G (op (i a) (op a b)) (op (i a) e) (i a)
|
|
|
|
|
-- a^-1 * (a * b) = a^-1 * e
|
|
|
|
|
(eq_cong G G (op a b) e (op (i a)) h)
|
|
|
|
|
|
|
|
|
|
-- a^-1 * e = a^-1
|
|
|
|
|
(id_rg (i a)))));
|
|
|
|
|
|
2024-12-08 17:40:37 -08:00
|
|
|
-- the classic shoes and socks theorem, namely that (a * b)^-1 = b^-1 * a^-1
|
|
|
|
|
def shoes_and_socks (a b : G) : eq G (i (op a b)) (op (i b) (i a)) :=
|
|
|
|
|
eq_sym G (op (i b) (i a)) (i (op a b))
|
|
|
|
|
(right_inv_unique (op a b) (op (i b) (i a))
|
|
|
|
|
-- WTS: (a * b) * (b^-1 * a^-1) = e
|
|
|
|
|
(let
|
|
|
|
|
-- some abbreviations for common terms
|
|
|
|
|
(ab := op a b)
|
|
|
|
|
(biai := op (i b) (i a))
|
|
|
|
|
(ab_bi := op (op a b) (i b))
|
|
|
|
|
(a_bbi := op a (op b (i b)))
|
|
|
|
|
|
|
|
|
|
-- helper function to prove that x * a^-1 = y * a^-1 given x = y
|
|
|
|
|
(under_ai (x y : G) (h : eq G x y) := eq_cong G G x y (fun (z : G) => op z (i a)) h)
|
|
|
|
|
in
|
|
|
|
|
-- (a * b) * (b^-1 * a^-1) = ((a * b) * b^-1) * a^-1
|
|
|
|
|
-- = (a * (b * b^-1)) * a^-1
|
|
|
|
|
-- = (a * e) * a^-1
|
|
|
|
|
-- = a * a^-1
|
|
|
|
|
-- = e
|
|
|
|
|
eq_trans G (op ab biai) (op ab_bi (i a)) e
|
|
|
|
|
-- (a * b) * (b^-1 * a^-1) = ((a * b) * b^-1) * a^-1
|
|
|
|
|
(assoc_g ab (i b) (i a))
|
|
|
|
|
-- ((a * b) * b^-1) * a^-1 = e
|
|
|
|
|
(eq_trans G (op ab_bi (i a)) (op a_bbi (i a)) e
|
|
|
|
|
-- ((a * b) * b^-1) * a^-1 = (a * (b * b^-1)) * a^-1
|
|
|
|
|
(under_ai ab_bi a_bbi (eq_sym G a_bbi ab_bi (assoc_g a b (i b))))
|
|
|
|
|
|
|
|
|
|
-- (a * (b * b^-1)) * a^-1 = e
|
|
|
|
|
(eq_trans G (op a_bbi (i a)) (op (op a e) (i a)) e
|
|
|
|
|
-- (a * (b * b^-1)) * a^-1 = (a * e) * a^-1
|
|
|
|
|
(eq_cong G G (op b (i b)) e (fun (x : G) => (op (op a x) (i a))) (inv_rg b))
|
|
|
|
|
|
|
|
|
|
-- (a * e) * a^-1 = e
|
|
|
|
|
(eq_trans G (op (op a e) (i a)) (op a (i a)) e
|
|
|
|
|
-- (a * e) * a^-1 = a * a^-1
|
|
|
|
|
(under_ai (op a e) a (id_rg a))
|
|
|
|
|
|
|
|
|
|
-- a * a^-1 = e
|
|
|
|
|
(inv_rg a))))
|
|
|
|
|
end));
|
|
|
|
|
|
2024-12-06 15:59:22 -08:00
|
|
|
end Group
|