Compare commits

...

9 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
bluepython508
846f4e00b7 Assessment 1 CS1527 2024-02-23 11:08:49 +00:00
bluepython508
7dedef5665 . 2024-02-14 20:59:32 +00:00
19 changed files with 1161 additions and 3 deletions

1
.gitignore vendored
View File

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

View File

@@ -0,0 +1,268 @@
# The following is a template of the design.
# you will need to complete the definition of each class, including class attributes,
# instance attributes, and instance methods. However, please do not change the class
# names provided below.
# IMPORTANT: In order to get your program pass the test, make sure your class constructors
# use exactly the same parameter names as in the test examples provided at the end of this template.
# ================Your codes start here=============
# Notes:
# - Should a motorboat (or eboat) really *be* an engine?
# - Why are the keyword arguments abbreviated?
def class_bases(cls):
"""Generator of the base classes of a class (including the given class).
Depth-first, post-order, may yield duplicates
"""
for cls_ in cls.__bases__:
yield from class_bases(cls_)
yield cls
def field_repr(obj) -> str:
"""String representation of an object
Lists fields with type annotations in object's class and superclasses"""
classes = class_bases(obj.__class__)
attrs = (
attr for cls in classes for attr in getattr(cls, "__annotations__", {}).keys()
)
attrs_vals = ",".join(f"{attr}={getattr(obj, attr, None)!r}" for attr in attrs)
return f"{obj.__class__.__name__}({attrs_vals})"
class Boat:
"""A boat
Attributes:
- `color`: color of boat
- `brand`: boat brand
- `year`: manufacture year
Class Attributes:
- `all_boats`: a list of all boats ever constructed
"""
all_boats = []
color: str
brand: str
year: int
def __init__(
self,
*,
co: str,
br: str,
yr: int,
**kwargs,
):
"""Initialize a `Boat`.
Takes keyword-only arguments `co` (color), `br` (brand), and `yr` (year)
as described in class docstring
"""
Boat.all_boats.append(self)
super().__init__(**kwargs)
self.color = co
self.brand = br
self.year = yr
def __str__(self):
return field_repr(self)
def get_boat_age(self, current_year: int) -> int:
"""Get the age of this boat given the current year"""
return current_year - self.year
class Engine:
"""An Engine
Attributes:
- `tech`: Technology used by the engine.
Either 'gas' or 'electric'
- `engine_speed`: maximum speed in miles per hour
determined by `tech` - gas engines have speed 80mph, electric 20mph
Class Attributes:
- `speeds`: mapping of engine tech to speed
"""
speeds = {"gas": 80, "electric": 20}
engine_speed: float
tech: str
def __init__(self, *, tech: str, **kwargs):
"""Initialize an `Engine`
Takes keyword-only argument `tech` (see class docstring)
"""
super().__init__(**kwargs)
self.tech = tech
self.engine_speed = Engine.speeds[tech]
def __str__(self):
return field_repr(self)
def get_engine_speed(self) -> float:
"""Get the engine speed for this engine in miles per hour"""
return self.engine_speed
class Motorboat(Boat, Engine):
"""A Motorboat
Always uses 'gas' engine tech
Attributes:
- `fuel_level`: remaining level of fuel in gallons
- `fuel_efficiency`: range with a certain amount of fuel in miles per gallon
"""
fuel_level: float
fuel_efficiency: float
def __init__(self, *, fl: float, fe: float, **kwargs):
"""Initialize a `Motorboat`
Takes keyword-only arguments `fl` (fuel level) and `fe` (fuel efficiency)
as described in class docstring, in addition to the arguments described in `Boat`
"""
super().__init__(**kwargs, tech="gas")
self.fuel_level = fl
self.fuel_efficiency = fe
def get_max_speed(self) -> float:
"""Get the max speed of the motorboat"""
return self.engine_speed
def cal_travel_time(self, distance: float) -> float:
"""Calculate the time to travel `distance` miles
Prints a message and returns max engine runtime
if the engine would run out of fuel before the destination
"""
range = self.fuel_level * self.fuel_efficiency
if range < distance:
print(
f"This motorboat runs out of fuel {distance - range} miles away from the destination."
)
return min(range, distance) / self.engine_speed
class Pedalboat(Boat):
"""A Pedalboat
Attributes:
- `pedal_speed`: speed attainable by pedalling in miles per hour
Generally in range [10, 20]
"""
pedal_speed: float
def __init__(self, *, ps: float, **kwargs):
"""Initialize a `Pedalboat`
Clamps `pedal_speed` to `10 <= pedal_speed <= 20`
Takes keyword-only argument `ps` (pedal speed), as described in the class docstring,
in addition to the arguments described in `Boat`
"""
super().__init__(**kwargs)
self.pedal_speed = ps
self.check_speed()
def get_pedal_speed(self) -> float:
"""Get the pedalling speed of the boat in miles per hour"""
return self.pedal_speed
def cal_travel_time(self, distance: float) -> float:
"""Calculate the time to travel `distance` miles
"""
return distance / self.pedal_speed
def check_speed(self):
"""Clamps `pedal_speed` to `10 <= pedal_speed <= 20`
Returns whether the speed was already in this range
"""
if 10 <= self.pedal_speed <= 20:
return True
self.pedal_speed = min(20, max(self.pedal_speed, 10))
return False
class Eboat(Pedalboat, Engine):
"""An `Eboat`
Always has engine tech 'electric'
Attributes:
- `battery_time`: remaining battery running time in hours
"""
battery_time: float
def __init__(self, *, bt: float, **kwargs):
"""Initialize an `Eboat`
Takes keyword-only argument `bt` (battery time), as described in the class docstring,
in addition to the arguments described in `Pedalboat`
"""
super().__init__(**kwargs, tech="electric")
self.battery_time = bt
def get_max_speed(self) -> float:
"""The maximum speed attainable in this boat by running the engine and pedalling"""
return self.pedal_speed + self.engine_speed
def cal_travel_time(self, distance: float) -> float:
"""Calculate the time to travel `distance` miles
"""
battery_range = self.get_max_speed() * self.battery_time
return (
min(distance, battery_range) / self.get_max_speed()
+ max(distance - battery_range, 0) / self.pedal_speed
)
# ============ End of your codes here ==================
# ============No modification beyond here =============
# the following is a list of test instances, please do not modify them
if __name__ == "__main__":
# arguments: co - color, br - brand, yr - year, tech - technology used in engine
boat1 = Boat(co="Black", br="Trek", yr=2012)
engine1 = Engine(tech="gas")
print(engine1.get_engine_speed())
# arguments: co - color, br - brand, yr - year, ps - pedal speed
pedalboat1 = Pedalboat(co="Red", br="GIANT", yr=2015, ps=15)
pedalboat2 = Pedalboat(co="Red", br="GIANT", yr=2015, ps=30)
print(pedalboat1.get_pedal_speed())
print(pedalboat2.get_pedal_speed())
print(pedalboat1.cal_travel_time(300))
# arguments: co - color, br - brand, yr - year, ps - pedal speed, bt - battery time
eboat1 = Eboat(co="Blue", br="Basis", yr=2018, ps=15, bt=10)
print(eboat1.get_max_speed())
print(eboat1.cal_travel_time(350))
print(eboat1.cal_travel_time(650))
# arguments: co - color, br - brand, yr - year, fl - fuel level, fe - fuel efficiency
motorboat1 = Motorboat(co="Silver", br="YAMAHA", yr=2013, fl=40, fe=12)
print(motorboat1.get_max_speed())
print(motorboat1.cal_travel_time(300))
print(motorboat1.cal_travel_time(600))
# get the age of all bikes created
for b in Boat.all_boats:
print(b.get_boat_age(2023))

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

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -9,6 +9,7 @@
\author{} \author{}
\newcommand{\paren}[1]{\left(#1\right)} \newcommand{\paren}[1]{\left(#1\right)}
\newcommand{\powerset}[1]{\mathcal{P}\paren{#1}}
\renewcommand{\Re}[1]{\operatorname{\mathbb{R}e}\paren{#1}} \renewcommand{\Re}[1]{\operatorname{\mathbb{R}e}\paren{#1}}
\renewcommand{\Im}[1]{\operatorname{\mathbb{{I}}m}\paren{#1}} \renewcommand{\Im}[1]{\operatorname{\mathbb{{I}}m}\paren{#1}}
\newcommand{\C}{\mathbb{C}} \newcommand{\C}{\mathbb{C}}
@@ -21,9 +22,17 @@
\newcommand{\abs}[1]{\left|#1\right|} \newcommand{\abs}[1]{\left|#1\right|}
\newcommand{\polar}[2]{#1\paren{\cos{\paren{#2}} + i\sin{\paren{#2}}}} \newcommand{\polar}[2]{#1\paren{\cos{\paren{#2}} + i\sin{\paren{#2}}}}
\newcommand{\adj}[1]{\operatorname{adj}#1} \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 \makeatletter
\renewcommand*\env@matrix[1][*\c@MaxMatrixCols c]{% \renewcommand*{\env@matrix}[1][*\c@MaxMatrixCols c]{%
\hskip -\arraycolsep \hskip -\arraycolsep
\let\@ifnextchar\new@ifnextchar \let\@ifnextchar\new@ifnextchar
\array{#1}} \array{#1}}

View File

@@ -9,6 +9,7 @@
\author{} \author{}
\newcommand{\paren}[1]{\left(#1\right)} \newcommand{\paren}[1]{\left(#1\right)}
\newcommand{\powerset}[1]{\mathcal{P}\paren{#1}}
\renewcommand{\Re}[1]{\operatorname{\mathbb{R}e}\paren{#1}} \renewcommand{\Re}[1]{\operatorname{\mathbb{R}e}\paren{#1}}
\renewcommand{\Im}[1]{\operatorname{\mathbb{{I}}m}\paren{#1}} \renewcommand{\Im}[1]{\operatorname{\mathbb{{I}}m}\paren{#1}}
\newcommand{\C}{\mathbb{C}} \newcommand{\C}{\mathbb{C}}
@@ -21,9 +22,17 @@
\newcommand{\abs}[1]{\left|#1\right|} \newcommand{\abs}[1]{\left|#1\right|}
\newcommand{\polar}[2]{#1\paren{\cos{\paren{#2}} + i\sin{\paren{#2}}}} \newcommand{\polar}[2]{#1\paren{\cos{\paren{#2}} + i\sin{\paren{#2}}}}
\newcommand{\adj}[1]{\operatorname{adj}#1} \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 \makeatletter
\renewcommand*\env@matrix[1][*\c@MaxMatrixCols c]{% \renewcommand*{\env@matrix}[1][*\c@MaxMatrixCols c]{%
\hskip -\arraycolsep \hskip -\arraycolsep
\let\@ifnextchar\new@ifnextchar \let\@ifnextchar\new@ifnextchar
\array{#1}} \array{#1}}

View File

@@ -2,7 +2,8 @@
\title{Sets} \title{Sets}
\begin{document} \begin{document}
\maketitle \maketitle
Set comprehensions can be written $\{ x | x \in \N \}$ or $\{ x : x \in \N \}$ - '$:$' or '$|$' Set comprehensions can be written $\{ x | x \in \N \}$ or $\{ x : x \in \N \}$ - '$:$' or '$|$' \\
Sets are defined entirely by the values of $x$ for which $x \in A$
\begin{description} \begin{description}
\item[Axiom of Extensionality / Set Equality] $A = B \iff \forall x. (x \in A \iff x \in B)$ \item[Axiom of Extensionality / Set Equality] $A = B \iff \forall x. (x \in A \iff x \in B)$
\item[$A \subseteq B$] \quad $\forall x \in A. x \in B$ \\ \item[$A \subseteq B$] \quad $\forall x \in A. x \in B$ \\
@@ -13,5 +14,349 @@ Set comprehensions can be written $\{ x | x \in \N \}$ or $\{ x : x \in \N \}$ -
\item[$\cup$] Union \item[$\cup$] Union
\item[$\cap$] Intersection \item[$\cap$] Intersection
\item[$A \setminus B$] \quad $\{ x \in A : x \not\in B \}$ \item[$A \setminus B$] \quad $\{ x \in A : x \not\in B \}$
\item[$A^\complement$]\quad $U \setminus A$
\item[$[a, b)$] \quad $\{ x \in \R : a \leq x < b \}$
\end{description} \end{description}
\begin{align*}
C \setminus (A \cup B) \equiv & ~ (C \setminus A) \cap (C \setminus B) \\
C \setminus (A \cap B) \equiv & ~ (C \setminus A) \cup (C \setminus B) \\
(A^\complement)^\complement \equiv & ~ A \\
A^\complement \cup B^\complement \equiv & ~ (A \cap B)^\complement \\
A^\complement \cap B^\complement \equiv & ~ (A \cup B)^\complement
\end{align*}
\section*{Families of Sets}
A family of sets indexed by a set $I$ (the indexing set): $A_i ~~\forall~i\in I (\equiv (A_i)_{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
\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)
\end{align*}
\section*{Cartesian Products}
Ordered pairs can be represented as $(x, y) \equiv \{x, \{x, y\}\}$ \\
$X \times Y = \{ (x, y) |~ \forall x, y.~x \in X \land y \in Y\}$ for sets $X$, $Y$ \\
$X^n$ is $X\times X^{n-1}$ for set $X$ and natural $n$ \\
$\card{X\times Y} = \card{X} \times \card{Y}$ (for finite $X$, $Y$)
\section*{Functions}
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 } 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[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} \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}