Compare commits

...

7 Commits

Author SHA1 Message Date
bluepython508
f2244a076a Add theorem commands 2024-09-25 10:20:49 +01:00
bluepython508
a50fc0e90f . 2024-05-01 17:43:02 +01:00
bluepython508
5bbbb4f1da OOP Assessment 2 2024-05-01 17:42:07 +01:00
bluepython508
b7b584a989 Typo 2024-04-11 12:58:08 +01:00
bluepython508
b50b42c01b . 2024-03-28 11:36:00 +00:00
bluepython508
201182156f . 2024-03-21 10:25:37 +00:00
bluepython508
bd228e9dca . 2024-02-23 11:09:21 +00:00
15 changed files with 856 additions and 15 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
*.pdf
latex.out/
.direnv
__pycache__/

Binary file not shown.

View File

@@ -0,0 +1,2 @@
export NIX_PATH="nixpkgs=flake:nixpkgs"
use nix

View File

@@ -0,0 +1,404 @@
#!/usr/bin/env python
"""Usage: `python assessment2.py {subcommand} {expressions}`
If expressions are not provided, they are taken from each line of stdin.
Documentation of subcommands is available from `python assessment2.py -h`.
Examples for marking criteria:
1. Eval: `python assessment2.py eval "(((2*(3+2))+5)/2)"`
2. Tree: `python assessment2.py render-tree "(((2*(3+2))+5)/2)"`
3. Preorder: `python assessment2.py format-prefix "(((2*(3+2))+5)/2)"`
In-order: `python assessment2.py format-infix "(((2*(3+2))+5)/2)"`
Postorder: `python assessment2.py format-postfix "(((2*(3+2))+5)/2)"`
4. Errors: `python assessment2.py eval "(4*3*2)" "(4*(2))" "(4*(3+2)*(2+1))" "(2*4)*(3+2)" "((2+3)*(4*5)" "((2+3)*(4*5)" "(2+5)*(4/(2+2)))" "(2+5)*(4/(2+2)))" "(((2+3)*(4*5))+(1(2+3)))"`
5. Tests: `python assessment2.py test`
Tests can be run with `pytest assessment2.py` or `python assessment2.py test`.
All of the formatting is implemented with post-order traversals. This is
necessary to output parenthesis in the pre- and in-order cases. It could also be
done with a buffer and a combined traversal (with callbacks before, between, and
after subtree visits), but that requires mutation.
Note: this program requires Python 3.12 due to the generic syntax used to define
`BTree.traverse`. Pytest is also required. These should be installed already
on Codio.
"""
# stdlib
from dataclasses import dataclass
from typing import Literal, Tuple, Callable, cast, override
from operator import add, sub, mul, truediv as div
from argparse import ArgumentParser
import sys
import re
from textwrap import dedent
# pytest, from https://pypi.org/project/pytest/
# authors can be found at https://github.com/pytest-dev/pytest/graphs/contributors,
import pytest
OPERATORS: dict[Literal["+", "-", "*", "/"], Callable[[float, float], float]] = {
"+": add,
"-": sub,
"*": mul,
"/": div,
}
class BTree:
value: float
def traverse[T](
self,
value: Callable[["Value", int], T],
operator: Callable[["Operator", T, T, int], T],
depth: int = 0,
) -> T:
"""Traverse the binary tree with a post-order traversal
`value` takes the value node and its depth from the root node
`operator` takes the operator node, the results of traversing the left
and right subtrees, and the depth of the node
The tree could, for example, be evaluated with `traverse`:
```
(...).traverse(
lambda node, _: node.value,
lambda node, left, right, _: OPERATORS[node.operator](left, right)
)
```
"""
raise NotImplementedError
def as_preorder_str(self) -> str:
"""Format the tree in prefix notation"""
return self.traverse(
lambda value, _: str(value.value),
lambda op, left, right, _: f"({op.operator} {left} {right})",
)
def as_inorder_str(self) -> str:
"""Format the tree as a typical parenthesized expression"""
return self.traverse(
lambda value, _: str(value.value),
lambda op, left, right, _: f"({left} {op.operator} {right})",
)
__str__ = as_inorder_str
def as_inorder_lines(self) -> str:
"""Format the tree, visually as a tree"""
return self.traverse(
lambda value, depth: " " * depth + str(value.value),
lambda op, left, right, depth: f"{left}\n{' ' * depth}{op.operator}\n{right}",
)
def as_postorder_str(self) -> str:
"""Format the tree in postfix notation (RPN)"""
return self.traverse(
lambda value, _: str(value.value),
lambda op, left, right, _: f"{left} {right} {op.operator}",
)
@dataclass(frozen=True, slots=True)
class Value(BTree):
value: float
@override
def traverse[T](
self,
value: Callable[["Value", int], T],
operator: Callable[["Operator", T, T, int], T],
depth: int = 0,
) -> T:
"""Traverse the binary tree with a post-order traversal
`value` takes the value node and its depth from the root node
`operator` takes the operator node, the results of traversing the left
and right subtrees, and the depth of the node
The tree could, for example, be evaluated with `traverse`:
```
(...).traverse(
lambda node, _: node.value,
lambda node, left, right, _: OPERATORS[node.operator](left, right)
)
```
"""
return value(self, depth)
@dataclass(frozen=True, slots=True)
class Operator(BTree):
operator: Literal["+", "-", "*", "/"]
left: BTree
right: BTree
@property
def value(self) -> float: # type: ignore - the field should be read-only
return OPERATORS[self.operator](self.left.value, self.right.value)
@override
def traverse[T](
self,
value: Callable[["Value", int], T],
operator: Callable[["Operator", T, T, int], T],
depth: int = 0,
) -> T:
"""Traverse the binary tree with a post-order traversal
`value` takes the value node and its depth from the root node
`operator` takes the operator node, the results of traversing the left
and right subtrees, and the depth of the node
The tree could, for example, be evaluated with `traverse`:
```
(...).traverse(
lambda node, _: node.value,
lambda node, left, right, _: OPERATORS[node.operator](left, right)
)
```
"""
return operator(
self,
self.left.traverse(value, operator, depth + 1),
self.right.traverse(value, operator, depth + 1),
depth,
)
def parse(expr: str) -> BTree:
"""Parse a parenthesized expression as in the spec.
Requires a single parenthesized string, potentially with whitespace
Raises ValueError on parse errors
"""
def number(expr: str) -> Tuple[BTree, str] | None:
if not expr[0].isdigit():
return None
rest = expr.lstrip("0123456789")
return Value(int(expr[: len(expr) - len(rest)])), rest.lstrip()
def parenthesized(expr: str) -> Tuple[BTree, str] | None:
if not expr.startswith("("):
return None
expr = expr[1:].lstrip()
left, expr = operand(expr)
operator, expr = expr[0], expr[1:]
if operator not in OPERATORS:
raise ValueError(f"Unknown operator {operator}")
operator = cast(Literal["+", "-", "*", "/"], operator)
right, expr = operand(expr.lstrip())
if not expr.startswith(")"):
if expr and expr[0] in OPERATORS:
raise ValueError("Too many operands in expression")
raise ValueError("Expected closing parenthesis")
return Operator(operator, left, right), expr[1:].lstrip()
def operand(expr: str) -> Tuple[BTree, str]:
v = number(expr) or parenthesized(expr)
if not v:
raise ValueError(
"Expected a number or the beginning of a parenthesized expression"
)
return v
result = parenthesized(expr.lstrip())
if not result or result[1]:
# If rest is non-empty, then something was after the parenthesis starting the expression
# i.e. the full expression was not parenthesized.
raise ValueError("Expected parenthesized expression at the top level")
return result[0]
@pytest.mark.parametrize(
("expr", "ast"),
[
("(1 + 1)", Operator("+", Value(1), Value(1))),
(
"(2*(3+ 2))",
Operator("*", Value(2), Operator("+", Value(3), Value(2))),
),
(" (1 +1) ", Operator("+", Value(1), Value(1))),
],
)
def test_parse(expr: str, ast: BTree):
"""Test parsing of expressions"""
assert parse(expr) == ast
@pytest.mark.parametrize(
("expr", "value"),
[
("(1 + 2)", 3),
("(12 + (((4 / 2) * 3) + (3 * 2)))", 24),
("(((2 * (3 + 2)) + 5) / 2)", 7.5),
],
)
def test_eval(expr: str, value: float):
"""Test evaluation"""
assert parse(expr).value == value
@pytest.mark.parametrize(
("expr", "tree"),
[
(
"(1 + 2)",
"""
1
+
2
""",
),
(
"(1 + (((4 / 2) * 3) + (3 * 2)))",
"""
1
+
4
/
2
*
3
+
3
*
2
""",
),
(
"(((2*(3+2))+5)/2)",
"""
2
*
3
+
2
+
5
/
2
"""
)
],
)
def test_inorder_lines(expr: str, tree: str):
"""Test tree rendering"""
assert parse(expr).as_inorder_lines() == dedent(tree).strip("\n")
@pytest.mark.parametrize(
("expr", "prefix"),
[
("(1 + 2)", "(+ 1 2)"),
("(1 + (((4 / 2) * 3) + (3 * 2)))", "(+ 1 (+ (* (/ 4 2) 3) (* 3 2)))"),
],
)
def test_prefix(expr: str, prefix: str):
"""Test prefix formatting"""
assert parse(expr).as_preorder_str() == prefix
@pytest.mark.parametrize(
("expr"),
[
"(1 + 2)",
"(1 + (((4 / 2) * 3) + (3 * 2)))",
"(((3 + 2) * 2) + (((7 / 3) * 5) - 3))",
],
)
def test_infix_roundtrip(expr: str):
"""Test infix formatting roundtrips"""
assert str(parse(expr)) == expr
@pytest.mark.parametrize(
("expr", "postfix"),
[
("(1 + 2)", "1 2 +"),
("(1 + (((4 / 2) * 3) + (3 * 2)))", "1 4 2 / 3 * 3 2 * + +"),
],
)
def test_postfix(expr: str, postfix: str):
"""Test postfix formatting"""
assert parse(expr).as_postorder_str() == postfix
@pytest.mark.parametrize(
("expr", "err"),
[
("(4 * 3 * 2)", "Too many operands in expression"),
("(4 * (2))", "Unknown operator )"),
("(4 * (3 + 2) * (2 + 1))", "Too many operands in expression"),
("(2 *4)*(3+2)", "Expected parenthesized expression at the top level"),
("(2+5)*(4/(2+2))", "Expected parenthesized expression at the top level"),
("(((2+3)*(4*5))+(1(2+3)))", "Unknown operator ("),
],
)
def test_error(expr: str, err: str):
"""Test error messages"""
with pytest.raises(ValueError, match=re.escape(err)):
parse(expr)
if __name__ == "__main__":
parser = ArgumentParser(usage=__doc__)
subcommands = parser.add_subparsers(title="Subcommands", required=True)
def with_expressions(parser):
parser.add_argument(
"expressions",
nargs="*",
help="The expressions to operate on. If none are provided, operate on lines of stdin.",
)
return parser
with_expressions(
subcommands.add_parser("eval", help="Evaluate the expression")
).set_defaults(func=lambda expr: expr.value)
with_expressions(
subcommands.add_parser("render-tree", help="Render the expression as a tree")
).set_defaults(func=BTree.as_inorder_lines)
with_expressions(
subcommands.add_parser(
"format-prefix", help="Format the expression in prefix notation"
)
).set_defaults(func=BTree.as_preorder_str)
with_expressions(
subcommands.add_parser(
"format-infix",
help="Format the expression in typical parenthesized infix notation",
)
).set_defaults(func=BTree.as_inorder_str)
with_expressions(
subcommands.add_parser(
"format-postfix",
help="Format the expression in postfix notation, i.e. as RPN",
)
).set_defaults(func=BTree.as_postorder_str)
subcommands.add_parser("test", help="Run tests").set_defaults(
func=lambda: pytest.main([__file__])
)
args = parser.parse_args()
if "expressions" in args:
for expression in args.expressions or sys.stdin:
if len(args.expressions) > 1:
print(expression + ":")
try:
parsed = parse(expression)
except ValueError as e:
print(f"Error: {e}")
continue
print(args.func(parsed))
else:
args.func()

View File

@@ -0,0 +1,3 @@
{ pkgs ? import <nixpkgs> {} }: pkgs.mkShell {
packages = [(pkgs.python312.withPackages (p: with p; [ python-lsp-server pytest pytest-watch black ])) pkgs.nodePackages.pyright];
}

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -9,6 +9,7 @@
\author{}
\newcommand{\paren}[1]{\left(#1\right)}
\newcommand{\powerset}[1]{\mathcal{P}\paren{#1}}
\renewcommand{\Re}[1]{\operatorname{\mathbb{R}e}\paren{#1}}
\renewcommand{\Im}[1]{\operatorname{\mathbb{{I}}m}\paren{#1}}
\newcommand{\C}{\mathbb{C}}
@@ -22,9 +23,16 @@
\newcommand{\polar}[2]{#1\paren{\cos{\paren{#2}} + i\sin{\paren{#2}}}}
\newcommand{\adj}[1]{\operatorname{adj}#1}
\newcommand{\card}[1]{\left|#1\right|}
\newcommand{\littletaller}{\mathchoice{\vphantom{\big|}}{}{}{}}
\newcommand{\restr}[2]{{% we make the whole thing an ordinary symbol
\left.\kern-\nulldelimiterspace % automatically resize the bar with \right
#1 % the function
\littletaller % pretend it's a little taller at normal size
\right|_{#2} % this is the delimiter
}}
\makeatletter
\renewcommand*\env@matrix[1][*\c@MaxMatrixCols c]{%
\renewcommand*{\env@matrix}[1][*\c@MaxMatrixCols c]{%
\hskip -\arraycolsep
\let\@ifnextchar\new@ifnextchar
\array{#1}}

View File

@@ -9,6 +9,7 @@
\author{}
\newcommand{\paren}[1]{\left(#1\right)}
\newcommand{\powerset}[1]{\mathcal{P}\paren{#1}}
\renewcommand{\Re}[1]{\operatorname{\mathbb{R}e}\paren{#1}}
\renewcommand{\Im}[1]{\operatorname{\mathbb{{I}}m}\paren{#1}}
\newcommand{\C}{\mathbb{C}}
@@ -22,9 +23,16 @@
\newcommand{\polar}[2]{#1\paren{\cos{\paren{#2}} + i\sin{\paren{#2}}}}
\newcommand{\adj}[1]{\operatorname{adj}#1}
\newcommand{\card}[1]{\left|#1\right|}
\newcommand{\littletaller}{\mathchoice{\vphantom{\big|}}{}{}{}}
\newcommand{\restr}[2]{{% we make the whole thing an ordinary symbol
\left.\kern-\nulldelimiterspace % automatically resize the bar with \right
#1 % the function
\littletaller % pretend it's a little taller at normal size
\right|_{#2} % this is the delimiter
}}
\makeatletter
\renewcommand*\env@matrix[1][*\c@MaxMatrixCols c]{%
\renewcommand*{\env@matrix}[1][*\c@MaxMatrixCols c]{%
\hskip -\arraycolsep
\let\@ifnextchar\new@ifnextchar
\array{#1}}

View File

@@ -29,18 +29,18 @@ A family of sets indexed by a set $I$ (the indexing set): $A_i ~~\forall~i\in I
$A_i$ is a set for every element $i \in I$ \\
A family of sets indexed by $\N$ is called a sequence of sets. Also written $(B_i)^{\inf}_{i=0}$ or $(B_i)_{i \geq 0}$
\begin{align*}
\bigcup_{i \in I}~A_i \equiv \{x | \exists i \in I. x \in A_i \} \\
\bigcap_{i \in I}~A_i \equiv \{x | \forall i \in I. x \in A_i \} & \text{ Exists iff } \exists~i\in I
\bigcup_{i \in I}~A_i \equiv \{x | \exists i \in I. x \in A_i \} \\
\bigcap_{i \in I}~A_i \equiv \{x | \forall i \in I. x \in A_i \} & \text{ Exists iff } \exists~i\in I
\end{align*}
\begin{align*}
& \forall i \in I. A_i \subseteq \cup_{j \in I}A_j \\
& \forall i \in I. A_i \subseteq B \implies \cup_{j \in I}A_j \subseteq B \\
& \forall i \in I.\cap_{j \in I}A_j \subseteq A_i \\
& \forall i \in I. B \subseteq A_i \implies B \subseteq \cap_{j \in I}A_j \\ \\
& B \cup \cap_{i \in I}A_i = \cup_{i \in I}(B \cap A_i) \\
& B \cap \cup_{i \in I}A_i = \cap_{i \in I}(B \cup A_i) \\
& B \setminus \cup_{i \in I}A_i = \cap_{i\in I}(B\setminus A_i) \\
& B \setminus \cap_{i \in I}A_i = \cup_{i\in I}(B \setminus A_i)
& \forall i \in I. A_i \subseteq \cup_{j \in I}A_j \\
& \forall i \in I. A_i \subseteq B \implies \cup_{j \in I}A_j \subseteq B \\
& \forall i \in I.\cap_{j \in I}A_j \subseteq A_i \\
& \forall i \in I. B \subseteq A_i \implies B \subseteq \cap_{j \in I}A_j \\ \\
& B \cup \cap_{i \in I}A_i = \cup_{i \in I}(B \cap A_i) \\
& B \cap \cup_{i \in I}A_i = \cap_{i \in I}(B \cup A_i) \\
& B \setminus \cup_{i \in I}A_i = \cap_{i\in I}(B\setminus A_i) \\
& B \setminus \cap_{i \in I}A_i = \cup_{i\in I}(B \setminus A_i)
\end{align*}
\section*{Cartesian Products}
Ordered pairs can be represented as $(x, y) \equiv \{x, \{x, y\}\}$ \\
@@ -51,9 +51,312 @@ $\card{X\times Y} = \card{X} \times \card{Y}$ (for finite $X$, $Y$)
For sets $X$, $Y$:
\begin{description}
\item[A function $F: X \to Y$] $\subseteq X\times Y$ \text { where } \\
$\forall x \in X.~\exists \text{ a unique } y \in Y.~ (x, y) \in F$ \\
$F(x)$ denotes the unique element $y \in Y$ for which $(x, F(x)) \in F$
$\forall x \in X.~\exists \text{ a unique } F(x) \in Y.~ (x, F(x)) \in F$ \\
There exist $\card{Y}^{\card{X}}$ functions $F: X \to Y$
\item[$\operatorname{dom}(F)$] The domain of $F$, i.e. $X$
\item[$\operatorname{incl}^{X}_{A} : A \to X$] $= a \quad \forall A X. \text{ where } A \subseteq X$
\item[$\operatorname{incl}^X_A : A \to X$] $= a \quad \forall A,X. \text{ where } A \subseteq X$
\item[Constant function] $\exists y_0 \in Y.~\forall x \in X.~ f(x) = y_0$
\item[Characteristic Function of a set $A \subseteq X$: $\chi_A: X \to \{0, 1\}$]
\[
\chi_A: X \to \{0, 1\} = \left\{\begin{array}{lr}
0 & \text{ if } x \not\in A \\
1 & \text{ if } x \in A
\end{array} \right.
\]
\item[Restriction of a function $f: X \to Y$] $\restr{f}{A}$ is $f$ specialized contravariantly to $A \subseteq X$
\item[$f(A)$: Image of $A$ under $f$] $f$ mapped over $A$ \quad for function $f: X \to Y$, $A \subseteq X$
\item[$\operatorname{ran}(f)$ / image of $f$ / range of $f$] $\{ f(x) | x \in X \}$, $f(X)$, i.e. all possible values of $f(x)$
\item[Preimage of $B$ under $f$] $\{ x \in X ~|~ f(x) \in B \}$ \\
written $f^{-1}(B)$, but is \emph{not} the inverse of f
\end{description}
For $f: X \to Y$, $A \subseteq A' \subseteq X$, $B \subseteq B' \subseteq Y$:
\begin{align*}
f(A) \subseteq~ & f(A') \\
f^{-1}(B) \subseteq ~ & f^{-1}(B') \\
f^{-1}(f(A)) \supseteq ~ & A \\
f(f^{-1}(B)) \subseteq ~ & B
\end{align*}
For set families $(A_i \subseteq X)_{i \in I}, (B_j \subseteq Y)_{j \in J}$:
\begin{align*}
f(\cup_{i \in I} A_i) = ~ & \cup_{i \in I}f(A_i) \\
f(\cap_{i \in I} A_i) \subseteq ~ & \cap_{i \in I}f(A_i) \\
f^{-1}(\cup_{j \in J} B_j) = ~ & \cup_{j \in J} f^{-1}(B_j) \\
f^{-1}(\cap_{j \in J} B_j) = ~ & \cap_{j \in J} f^{-1}(B_j)
\end{align*}
\section*{Function Composition}
For functions $f: X \to Y$, $g: Y \to Z$:
\begin{align*}
& (g \circ f): X \to Z \\
& (g\circ f)(x) = g(f(x)) & \forall x \in X \\ \\
\end{align*}
\section*{Surjection and Injection}
For $f: X \to Y$, $f$ is
\begin{description}
\item[surjective] iff $f(X) = Y$, i.e. $\forall y \in Y.~ \exists x \in X.~ f(x) = y$ \\
Range is codomain, 'onto'
\item[injective] iff $\forall x, x' \in X. ~ f(x) = f(x') \implies x = x'$
\item[bijective] iff $f$ is injective and $f$ is surjective \\
one-to-one
\end{description}
Given $f: X \to Y$, $g: Y \to Z$: \\
\quad If f and g are injective, so is $g\circ f$ \\
\quad If f and g are surjective, so is $g \circ f$ \\
\quad If $g \circ f$ is injective, so is $f$ \\
\quad If $g \circ f$ is surjective, so is $g$
\section*{Inverse Functions}
The inverse function $f^{-1}$ of $f: X \to Y$ exists iff $f$ is bijective, and is defined by \[f^{-1}(y) = x \text{ where } \exists! x \in X. f(x) = y \qquad \forall y \in Y\]
\begin{align*}
(f \circ f^{-1}) = \operatorname{Id} \\
(f^{-1} \circ f) = \operatorname{Id}
\end{align*}
\section*{Power Sets}
Powerset of S: $\powerset{S}$ has $2^{\card{S}}$ elements is the set of all subsets of $S$ \\
$Fun(X, \{0, 1\})$ is the set of functions $X \to \{0, 1\}$ \\
$\Phi: Fun(X, \{0, 1\}) \to \powerset{X}$ \\
$\Phi(f) = \{ x \in X | f(x) = 1 \}$ \\
$\Phi$ is bijective.
\section*{Binary Operators}
A binary operator is $X^2 \to X$ \\
Union is $\powerset{X}^2 \to \powerset{X}$ \\
$\square$ is the unknown or indeterminate binop sigil \\
Unital: $\forall x \in X. \exists u \in X. u \square x = x \square u = x$
\section*{Construction of the Natural Numbers}
\begin{align*}
x^{+} & = x \cup \{x\} & \text{successor of $x$}
\end{align*}
A set $X$ is \emph{inductive} if $\varnothing \in X \land (a \in X \implies a^+ \in X)$ \\
Axiom: There exists an inductive set. \\
Definition: A natural number is a set that is an element of all inductive sets. \\
Theorem: There exists a set whose elements are the natural numbers. \\
\begin{align*}
& \text{Given an inductive set $A$} \\
& \omega = \{ x \in A | x \text{ is a natural number}\} \\
& \text{any natural number is in $A$ (since $A$ is inductive), and therefore in $\omega$} \\
& \omega \text{ is the natural numbers}
\end{align*}
\\
Define:
\begin{align*}
0 & = \varnothing \\
1 & = 0^+ \\
2 & = 1^+ \\
\ldots
\end{align*}
$\in$ is an ordering over $\omega$, as is $\subseteq$ \\
$\omega$ is an inductive set. Proof: \\
$\varnothing$ is a natural number.
$x \in \omega$ implies $x^+ \in \omega$, as $x$ is natural and is therefore in
every inductive set, and so $x^+$ is in every inductive set and is therefore a
natural number.
\subsection*{Principle of Induction}
If $A \subseteq \omega$ and $A$ is inductive, $A = \omega$.
Since $A$ is inductive, it contains every natural number, so $\omega \subseteq A$. \\
Since $A \subseteq \omega \land \omega \subseteq A$, $A = \omega$
\section*{Recursion on $\omega$}
\subsection*{Principle of Recursion}
For a set $X$, $x_0 \in X$, $h: X \to X$, there exists a unique function $f: \omega \to X$ where $f(0) = x_0$, $f(n^+) = h(f(n))$.
\section*{Relations}
Total order: $(X, \prec)$, requires $\forall x, y, z \in X$: \\
\begin{align*}
& x \prec y \land y \prec z \implies x \prec z \\
& x = y \oplus x \prec y \oplus y \prec x & \text{ (where $\oplus$ denotes XOR) }
\end{align*}
Lexicographic order $x <_L y$ on $\N\times\N = x_0 < y_0 \lor (x_0 = y_0 \land x_1 < y_1)$ \\
For a non-empty subset $A$ of $X$ given a total order $(X, \prec)$, a minimum/least element $a_0 \in A$
exists where $\forall a \in A.~a_0 \preceq a$.
\section*{Ordering on $\omega$}
$(\omega, \in)$ and $(\omega, \subset)$ are both total orderings on $\omega$, such that $\varnothing$ is the minimum and $\forall x \in \omega.~x < x^+$
\section*{Strong Induction}
Every non-empty subset of $\N$ has a minimum. \\ \\
Let $\phi(x)$ be a predicate over $\N$ where $\forall n\in \N.~ (\forall m \in \N.~ m < n \implies \phi(m)) \implies \phi(n)$. \\
Then $\phi(0)$ holds, as $\neg\exists n \in \N.~n<0$, $\phi(1)$ holds as $\phi(0)$ holds, etc.
\begin{align*}
& \neg\exists x \in \N.~\neg\phi(x) \\
& \text{Let } A \text{ be a subset of }N\text{ such that }\phi(n)\text{ is false }\forall n \in A \\
& \text{If not, $\exists a_0 \in A$} \\
& \forall n \in N.~n < a_0 \implies n \not\in A \implies \phi(n) \\
& \text{Then $\phi(n)$ holds $\forall n < a_0$, so $\phi(a_0)$, then $a_0 \not\in A$, which is a contradiction, so $A = \varnothing$}
\end{align*}
\section*{Fibonacci}
Fibonacci Sequence: $F_n$ \\
Roots of $x^2 - x - 1$ are $\phi = \frac{1 + \sqrt{5}}{2}$ and $\psi = \frac{1 - \sqrt{5}}{2}$ \\
$F_n = \frac{\phi^{n+1} - \psi^{n+1}}{\sqrt{5}}$ \\
For $n=0$:
$F_0 = 1 = \frac{\frac{1 + \sqrt{5}}{2} - \frac{1-\sqrt{5}}{2}} = \frac{2\sqrt{5}}{2} = 1$ \\
For $n=1$: \\
$F_1 = 1 = \frac{\paren{\frac{1 + \sqrt{5}}{2}}^2 - \paren{\frac{1 - \sqrt{5}}{2}}^2}{\sqrt{5}} = \frac{\phi + 1 - \psi - 1}{\sqrt{5}}$ \\
For $n\geq 2$:
\begin{align*}
& F_n = F_{n-1} + F_{n-2} = \frac{\phi^n - \psi^n}{\sqrt{5}} + \frac{\phi^{n-1} - \psi^{n-1}}{\sqrt{5}} \\
& = \frac{\phi^{n-1}\paren{\phi + 1} - \psi^{n-1}\paren{\psi + 1}}{\sqrt{5}} \\
& = \frac{\phi^{n-1}\phi^2 - \psi^{n-1}\psi^2}{\sqrt{5}} \\
& = \frac{\phi^{n+1} - \psi^{n+1}}{\sqrt{5}} & \text{as required}
\end{align*}
\subsection*{Zeckendorff's Theorem}
Every natural number can be written as a sum of non-adjacent Fibonacci numbers in a unique way (excluding $F_0$). \\
A finite subset $I$ of $\N^+$ is \emph{Zeckendorff} if it contains no adjacent elements ($\forall x \in I.~x^+ \not\in I$) \\
Define $\mathcal{Z}$ as the set of all Zeckendorff sets, and $\sigma: \mathcal{Z} \to \N^+$ by $\sigma(I) = \sum_{i \in I}F_i$.
The theorem claims $\sigma$ is bijective. \\ \\
For nonempty $I \in \mathcal{Z}$ with largest element $k$:
\begin{align*}
& \text{Let } J = I \setminus \{k\} \\
& \sigma(I) = F_k + \sigma(J) \geq F_k \\
& \text{If } J = \varnothing\text{, } \sigma(I) = F_k \leq F_{k + 1} \\
& \text{Otherwise, we must show } \sigma(I) < F_{k + 1} \\
& \equiv F_k + \sigma(J) < F_{k + 1} \\
& \equiv \sigma(J) < F_{k + 1} - F_k = F_{k-1} \\
& \text{But if $k' = \operatorname{max}(J)$, } \\
& \sigma(J) < F_{k' + 1} \land k' < k - 2 \text{ (since $I$ is \emph{Zeckendorff})} \\
& \sigma(J) < F_{k - 1} \text{ as required.}
\end{align*}
Proof of theorem: $\forall n \in N.~ \sigma$ is bijective.
\begin{align*}
n = 0: \quad & I = \varnothing \\
n > 0: \quad & \text{Let } F_k \leq n < F_{k + 1},~ m = n - F_k \\
& m = \sigma(J) \text{ for some } J \\
& \text{If } J = \varnothing, I = \{k\}. \\
& \text{Otherwise, } k' = \operatorname{max}(J). \\
& \text{If } k' \leq k - 2, I = J \cup \{k\} \\
\end{align*}
\section*{Equivalence Relations}
Reflexive, Symmetric, Transitive \\
Equivalence relations are usually called $\sim$ \\
In a set $X$,
\[ [x] = \{ y \in X | x \sim y \} \]
\[ [x] = [y] \equiv x \sim y \]
Any two equivalence classes of $X$ are either disjoint or equal. \\
\subsection*{Quotient Sets}
$X/\sim~ = \{[x] | x \in X \} \subset \powerset{X}$ \\
A complete set of representatives is a subset $A$ of $X$ where $\forall x \in X. \exists! a \in A. a \in [x].$ \\
I.E. a complete set of representatives contains exactly one element from each element of $X/\sim$ \\
$f: A \to X/\sim$ defined by $f(a) = [a]$
\\\\\\
A function $f: X \to Y$ is \emph{compatible} iff $x \sim y \implies f(x) = f(y)~\forall x, y \in X$ \\
For a \emph{compatible} function, $\Bar{f}: X/\sim~\to Y$ exists and is defined by $\Bar{f}([x]) = f(x)$
\subsection*{Integers modulo $k$}
Fix some $k \in \N^+$ \\
Define $\sim$ on $\Z$ by $n \sim m \iff n - m$ is a multiple of $k$ \\
$\sim$ is an equivalence relation \\
$[0, k)\cap\N$ is a complete set of representatives for $\sim$ \\
$Z/k$ is the set of integers modulo $k$, $n \equiv m~(\operatorname{mod} k) \iff n \sim m$ \\
\([m] = [m]_k\) \\
$+$ and $\times$ on $\Z/k$:
\begin{align*}
[n] + [m] = [n + m] \\
[n][m] = [nm]
\end{align*}
\section*{Countable Sets}
A set $X$ is finite if $\exists n \geq 0. $ a bijection $\{1, ...n\} \to X$ \\
Pigeonhole Principle: for finite $X$, any injective $f: X \to X$ is also surjective. \\
$\N$ is infinite. Proof: $f: \N \to \N $ defined by $ f(x) = x + 1$ is trivially injective, and $\neg\exists x.~f(x) = 0$, and so not surjective. \\
By the inverse of the Pigeonhole Principle, $\N$ is infinite.\\
A set $X$ is \emph{countably infinite} iff there exists a bijection $\N \to X$. \\
A set is \emph{countable} iff it is finite or countably infinite. \\
Any subset of $\N$ is countable. Proof: Let $X \subseteq \N$.\\
If $X$ is finite, it's trivially countable.
Otherwise, $X$ is infinite and it must be shown that $X$ is countably infinite. \\
For $k \in \N$, $X_{>k} = \{ n \in X | n > k \}$. Then $X_{>k} \not= \varnothing$, as $X$ would be a subset of $\{1..k\}$ and would be finite. \\
Then $min(X_{>k})$ exists, and $h: X \to X$ can be defined by $h(x) = min(X_{>x})$, and $f: \N \to X$ by recursion on $h$ with $f(0) = min(X)$. \\
\\
If an injection $f: A \to X$ exists, $A$ is countable if $X$ is. Proof: \\
If $A$ is finite, it's countable. Otherwise, \\
Since $X$ is countable, there exists a bijection $g: X \to \N$, and $g \circ f: A \to \N$
exists and is a composite of 2 injective functions, and therefore is itsself injective. \\
\\
Any subset of a countable set is countable, by above with the inclusion function.
$N^2$ is countable. Proof: \\
Take $f: \N^2 \to \N$ defined by $f(a, b) = 2^a3^b$. \\
$f$ is injective. Proof is simple -- prime factor decompositions are unique. \\
If a function $f: X \to Y$ exists where $X$ is countable, $f(X)$ is countable. Proof: \\
For $y \in f(X)$, \emph{choose} an $x_y \in f^{-1}(\{y\})$ and define $g: f(X) \to X$ by $g(y) = x_y$. \\
$g$ is injective, so $f(X)$ injects into the countable set $X$ and is itself countable. \\
In particular, for any surjection $f: X \to Y$, $Y$ is countable if $X$ is \\
\\
The union over a countable set of countable sets is countable. Proof: For family $X_{i \in I}$, $X_i$ countable, $I$ countable \\
There is an injection $h: I \to \N$, and $f_i: X_i \to \N \forall i \in I$, as these are countable sets. \\
Define $Y = \bigcup_{i \in I}X_i$, and $g: Y \to \N$ by $g(y) = (h(i), f_i(y))$ where $i \in I$ is chosen so that $y \in X_i$.
Then $g$ is injective because equality distributes over pairs, and $h$ and $f_i$ are injective.\\
If $X$ and $Y$ are countable, so is $X\times Y$. Proof: \\
Define for $x \in X$ a subset $Y_x = \{(x, y) | y \in Y\}$ of $X \times Y$, then $\{Y_x\}_{x \in X}$ is a countable family of countable sets.
\\
$\Z$ is countable, as a union of $\N$ and $(\times {-1})(\N^+)$, or $\N \times \{0, 1\}$ \\
$\Q$ is countable. Proof:
\begin{align*}
& \text{Define } f: \Z\times (\Z \setminus \{ 0 \}) \text{ by } f(a, b) = \frac{a}{b} \\
& f \text{ is surjective, by definition of } \Q. \\
& \Z \text{ is countable, as above } \\
& \Z \setminus \{ 0 \} \text{ is countable, as a subset of a countable set } \Z \\
& \Z\times (\Z \setminus \{ 0 \}) \text{ is countable, as a product of countable sets } \\
& \text{Since } f \text{ is surjective with a countable domain, } \Q \text{ is countable }
\end{align*}
For set family $X_{n \in \N^+}$, $\times_{n \in \N^+} X_n$ is countable if $\forall n \in \N.~X_n$ is countable. Proof: \\
Base Case: $n = 1$: $X_1$ is countable, since $X_1$ is countable. \\
Induction: Assume $\times_{n \in \N^+, \leq k} X_n$ is countable. \\
Then the result for $k + 1$ is $\times_{n \in \N^+, \leq k + 1} X_n$, which is $(\times_{n \in \N^+, \leq k} X_n) \times X_{k + 1}$, which is the product of countable sets and is therefore countable. \\
By induction, the result holds for $n \in N^+$ \\
This generalizes to all countable indexing sets $I$, by constructing an injection $f: I \to \N$.
\\ \\
Let $X$ be countable. Define $\mathbb{P}_{<\infty}\paren{X}$ as the set of all finite subsets of $X$. $\mathbb{P}_{<\infty}\paren{X}$ is countable. Proof: \\
For $n \in \N$, let $\mathbb{P}_{\leq n}(X)$ denote the set of all nonempty subsets of $X$ with $n$ elements or less. \\
The function $p_n: X^n \to \mathbb{P}_{\leq n}(X)$ defined by $p_n(x_1, x_2, ... x_n) = \{ x_1, x_2, ... x_n\}$ is surjective. \\
Then, since $X$ is countable, so is $\mathbb{P}_{\leq n}(X)$ (as $X^n$ is countable and there exists a surjection $X^n \to \mathbb{P}_{\leq n}(X)$) \\
\[\mathbb{P}_{\leq\infty}(X) = \bigcup_{n \in \N^+}\mathbb{P}_{\leq n}(X) \cup \{\varnothing\} \]
This is a countably-sized union of countable sets and so is itself countable, as required.
\subsection*{Cantor's Theorem}
Let $X$ be a set. Then there exists no surjective function $f: X \to \powerset{X}$. Proof: \\
Let $f: X \to \powerset{X}$ be a function. We will prove that $f$ is not surjective. \\
Define $D \subseteq X$ by $\{ x \in X | x \not\in f(x) \}$ \\
Then $D \in \powerset{X}$, and we will show that there is no element of $X$ for which $f(x) = D$. \\
Suppose there was such an $x$. Either: \\
$x \in D$. Then $x \in f(x)$, but by definition of $D$, $x \not\in f(x)$, which is a contradiction.
$x \not\in D$. Then $x \not\in f(x)$, so $x \in D$ by definition of $D$, which is a contradiction. \\\\
Since both cases give a contradiction, there exists no such $x$, and $f$ is not surjective. \\
This is the less famous diagonal argument. \\
\\
$\R$ is uncountable. Proof:
Define $f: \powerset{\N} \to \R$ by $f(A) = \sum_{n \in A} 2(3^{-n}) \quad \forall A \subseteq \N$.
Then $f$ is injective: \\
Take $\alpha, \beta \in \powerset{\N}$, where $\alpha \not = \beta$, and we will show $f(\alpha) \not = f(\beta)$. \\
Then, take $k \in \N$ as the smallest natural number in exactly one of $\alpha$, $\beta$, and assume it's in $\beta$ WLOG. \\
Then
\begin{align*}
f(\alpha) & = \sum_{n \in \alpha}\frac{2}{3^n} \\
& = \sum_{n \in \alpha, < k} \frac{2}{3^n} + \sum_{n \in \alpha, > k} \frac{2}{3^n} \\
& \leq \sum_{n \in \alpha, < k} \frac{2}{3^n} + \sum_{n > k} \frac{2}{3^n} \\
& = \sum_{n \in \alpha, < k} \frac{2}{3^n} + \frac{1}{3^k} \\
& = \sum_{n \in \beta, < k} \frac{2}{3^n} + \frac{2}{3^k} \\
& < \sum_{n \in \beta, < k} \frac{2}{3^n} + \frac{2}{3^k} + \sum_{n \in \beta, > k} \frac{2}{3^n} \\
& = f(\beta) \\ \\
f(\alpha) < f(\beta) & \implies f(\alpha) \neq f(\beta)
\end{align*}
Then there is no surjection $\N \to \powerset{\N}$ and so $\powerset{\N}$ is uncountable.
Since there's an injection $\powerset{\N} \to \R$, $\R$ is uncountable, as if $\R$ was countable, $\powerset{\N}$ would be countable
\\ \\
The set of all polynomials with rational coefficients is countable. Proof:
Let $P$ be the set of all polynomials with rational coefficients, $P_n$ be the set of all polynomials with rational coefficients and degree $\leq$ n.
Then $P = \bigcup_{n \in \N} P_n$, $\N$ is countable, and $P_n$ is countable as there exists a surjection $\Q^n \to P_n$ by assigning each element of the tuple to a coefficient. \\
\subsection*{Algebraic Numbers}
The algebraic numbers ($\mathcal{A}$) are the real numbers which are roots of polynomials with rational coefficients.
$\mathcal{A}$ is countable, as \[ \mathcal{A} = \bigcup_{p \in P} \{ x \in \R |~p(x) = 0 \} \] is a countable union of finite sets. \\
Then $\R\setminus\mathcal{A}$ is uncountable, as if it were, $\R = (\R \setminus \mathcal{A}) \cup \mathcal{A}$, a union of countable sets.
\end{document}

1
MA2008/2024-09-24 Normal file
View File

@@ -0,0 +1 @@

76
MA2008/decls.tex Normal file
View File

@@ -0,0 +1,76 @@
\documentclass[fleqn]{article}
\usepackage{amsmath,amssymb,amsthm}
\usepackage[margin=0.25in]{geometry}
\usepackage{enumitem}
\usepackage{systeme}
\usepackage{mathtools}
\date{}
\author{}
\newcommand{\paren}[1]{\left(#1\right)}
\newcommand{\powerset}[1]{\mathcal{P}\paren{#1}}
\renewcommand{\Re}[1]{\operatorname{\mathbb{R}e}\paren{#1}}
\renewcommand{\Im}[1]{\operatorname{\mathbb{{I}}m}\paren{#1}}
\newcommand{\C}{\mathbb{C}}
\newcommand{\N}{\mathbb{N}}
\newcommand{\Z}{\mathbb{Z}}
\newcommand{\Q}{\mathbb{Q}}
\newcommand{\R}{\mathbb{R}}
\newcommand{\conj}[1]{\overline{#1}}
\renewcommand{\mod}[1]{\left|#1\right|}
\newcommand{\abs}[1]{\left|#1\right|}
\newcommand{\polar}[2]{#1\paren{\cos{\paren{#2}} + i\sin{\paren{#2}}}}
\newcommand{\adj}[1]{\operatorname{adj}#1}
\newcommand{\card}[1]{\left|#1\right|}
\newcommand{\littletaller}{\mathchoice{\vphantom{\big|}}{}{}{}}
\newcommand{\restr}[2]{{% we make the whole thing an ordinary symbol
\left.\kern-\nulldelimiterspace % automatically resize the bar with \right
#1 % the function
\littletaller % pretend it's a little taller at normal size
\right|_{#2} % this is the delimiter
}}
\makeatletter
\renewcommand*{\env@matrix}[1][*\c@MaxMatrixCols c]{%
\hskip -\arraycolsep
\let\@ifnextchar\new@ifnextchar
\array{#1}}
\makeatother
% https://gitlab.com/jim.hefferon/linear-algebra/-/blob/master/src/sty/linalgjh.sty
\newlength{\grsteplength}
\setlength{\grsteplength}{1.5ex plus .1ex minus .1ex}
\newcommand{\grstep}[2][\relax]{%
\ensuremath{\mathrel{
\hspace{\grsteplength}\mathop{\longrightarrow}\limits^{#2\mathstrut}_{
\begin{subarray}{l} #1 \end{subarray}}\hspace{\grsteplength}}}}
\newcommand{\repeatedgrstep}[2][\relax]{\hspace{-\grsteplength}\grstep[#1]{#2}}
\newcommand{\swap}{\leftrightarrow}
% https://tex.stackexchange.com/a/198806
\makeatletter
\newcommand{\subalign}[1]{%
\vcenter{%
\Let@ \restore@math@cr \default@tag
\baselineskip\fontdimen10 \scriptfont\tw@
\advance\baselineskip\fontdimen12 \scriptfont\tw@
\lineskip\thr@@\fontdimen8 \scriptfont\thr@@
\lineskiplimit\lineskip
\ialign{\hfil$\m@th\scriptstyle##$&$\m@th\scriptstyle{}##$\hfil\crcr
#1\crcr
}%
}%
}
\makeatother
\theoremstyle{definition}
\newtheorem*{theorem}{Theorem}
\newtheorem*{lemma}{Lemma}
\newtheorem*{corollary}{Corollary}
\theoremstyle{remark}
\newtheorem*{note}{Note}

View File

@@ -0,0 +1,27 @@
\input{decls.tex}
\title{Vector Spaces and Linear Transformations}
\begin{document}
\maketitle
\begin{description}
\item[Linear Transformation] A function $\phi: V \to W$ between vector spaces $V$ and $W$ (over some field $K$), such that
\begin{align*}
\phi(v + w) & \equiv \phi(v) + \phi(w) \\
\phi(x \cdot v) & \equiv x \cdot \phi(v) \tag{For $x \in K$}
\end{align*}
\end{description}
Differentiation is a linear transformation.
Solutions to $f'' + f = 0$ for function $f$ are a vector space.
\begin{theorem}
For any scalars $\lambda, \mu \in \R$, there is a unique solution such that $f(0) = \mu$ and $f'(0) = \lambda$
\end{theorem}
The vector space is then two-dimensional, with basis $sin(x), cos(x)$
\subsection*{}
Vector spaces are used over finite fields in \emph{Algebraic Coding Theory}. The field is $\mathbb{F}_2 = \{0, 1\}$ - the integers mod 2.
Binary strings of length $n$ are then a vector space over $\mathbb{F}_2^n$.
ECC can be based on vector subspaces of $F_2^n$. (Vector subspaces are closed subsets of a vector space).
\end{document}

6
MA2008/tmpl.tex Normal file
View File

@@ -0,0 +1,6 @@
\input{decls.tex}
\title{}
\begin{document}
\maketitle
\end{document}