--- title: "Mirror proof" breaks: false --- # Proof **Claim.** For any tree $t : \alpha \ \mathsf{tree}$, we have $\mathsf{mirror} (\mathsf{mirror} \ t) \cong t$. ```graphviz graph btree { 1 -- 2; 1 -- 3; 2 -- 4; 2 -- 5; 3 -- 6; 3 -- 7; } ``` ## Idiomatic Structural Induction Definition of Mirror: ```ocaml let rec mirror (t : 'a tree) : 'a tree = match t with | Leaf -> Leaf | Node(a, x, b) -> Node((mirror b), x, (mirror a)) ;; ``` **Proof.** By structural induction, we will show that $\forall t$ where $t$ is an $\alpha \ tree$, it holds that $mirror(mirror(t)) \cong t$: - If $t$ is a $Leaf$, it is clear that $mirror(t) \cong t$, by definition of $mirror$. Applying $mirror$ to $t$, we can see by substitution that $mirror(mirror(t)) \cong t$. Therefore, the base case holds. - If $t$ is a $Node(L, x, R)$, when evaluating $mirror(t)$ we observe that $mirror$ is recursively applied to $L$ and $R$, yielding $Node(mirror(R), x, mirror(L))$. Therefore, applying $mirror(mirror(Node(L,x,R)))$ gives us $Node(mirror(mirror(L)), x, mirror(mirror(R)))$. By Inductive Hypothesis, $mirror(mirror(L))$ and $mirror(mirror(R))$ give us $L$ and $R$, respectively. The expression then reduces to $Node(L,x,R)$. Thus, the induction proceeds, so the claim holds for all $t : \alpha \ tree$. We see that our claim is proven $\forall t$ where $t$ is an $\alpha \ tree$. --- - If $t$ is a $Leaf$, it is clear that $mirror(Leaf) \cong Leaf$, by definition of $mirror$. Thus, $mirror(mirror(t)) = t$ as well, so the base case holds. - If $t \cong Leaf$, then the claim holds trivially. --- ```ocaml (* data type with two variants *) type 'a tree = Leaf | Node of 'a tree * 'a * 'a tree type expr = Const of int | Sum of expr * expr | Mul of expr * expr Sum (Mul (Const 3, Const 5), Const 7) (* (3 * 5) + 7) val eval : expr -> int ``` show something about like $\mathsf{eval} \ x$ for all expressions $x$ *Proof.* By structural induction on $x$: - If $x \cong \mathsf{Const}(n)$ for some $n$, then .... - If $x \cong \mathsf{Sum}(a, b)$ where $a, b: \mathsf{expr}$, thnen suppose inductively that ... and then ... - If $x \cong \mathsf{Mul}(a, b)$ where $a, b: \mathsf{expr}$, thnen suppose inductively that ... and then ... ## Original Structural Induction Definition of Mirror: ```ml let rec mirror (t : 'a tree) : 'a tree = match t with | Leaf -> Leaf | Node(a, x, b) -> Node((mirror b), x, (mirror a)) ;; ``` $Case: T = Leaf$. Note that \begin{align} mirror(Leaf) = Leaf\\ \therefore \ mirror(mirror(Leaf)) = Leaf \end{align} $Case: T = Node(L, x, R)$ For some trees $L$ and $R$. Note that $$ \begin{align} mirror(mirror(Node(L,x,R))) & = mirror(Node(mirror(R), x, mirror(L))) &&\text{Definition of mirror}\\ & = Node(mirror(mirror(L)), x, mirror(mirror(R)))) &&\text{Definition of mirror}\\ & = Node(L, x, R) &&\text{Inductive Hypothesis} \end{align} $$ Thus the assertion $mirror(mirror(T)) = T \ \forall \ T$ is proven by structural induction. created with some help from: [University of Washington](https://courses.cs.washington.edu/courses/cse311/17au/sections/07/section07-solutions.pdf) ## Bad Mathematical Induction Given a binary tree of nodes `1` to `n`, where `1` identifies the root node, it is possible to find the position of the node within a given level of the tree with the following relation: $$ p(n) = n - 2^{floor(\log_2 n)} + 1 $$ where $p(4) = 1$, $p(7) = 4$, $p(3) = 2$ etc. The maximum index of node n within it's current level can be defined as follows: $$ i_{max}(n) = 2^{floor(\log_2n + 1)} $$ where $i_{max}(4) = i_{max}(5) = i_{max}(6) = i_{max}(7) = 7$ A function that creates a mirror of an existing tree effectively translates all nodes across the tree's center axis. The length and direction of this translation can be calculated as a function of the max index at the current depth relative to the node's position: $$ reverse(n) = i_{max}(n) - p(n) $$ Put in terms of n and simplified, we get $$ reverse(n) = 3*2^{floor(\log_2n)} - n - 1 $$ ### Base Case For a tree of a single leaf node $$ reverse(1) = 1 $$ therefore $$ reverse(reverse(1)) = 1 $$ for our base case. ## Structural-mathematical induction ### Covered - $\forall a. \phi(a)$ is a "universal quantification" - to prove a universal quantification, pick some arbitrary $a$ and show that $\phi(a)$ holds - congruence, as distinct from equality - "recursive proofs", "unwinding/unrolling" - mathematical notation: lambdas, function types, "Currying" (functions of multiple arguments are the same thing as nested functions), $\mathbb Z$/$\mathbb R$ - structure of a proof - we didn't really get to the different kinds of induction **Theorem.** For any tree $t : \alpha \ \mathsf{tree}$, it holds that $\mathsf{reverse}(\mathsf{reverse} \ t) \cong t$. Let $(\cong)$ be the smallest relation such that: - if $x$ and $y$ are numbers and $x = y$, then $x \cong y$ - likewise bool, str, array; types that have $(=)$ - let's ignore floats for now - if $f : \alpha \to \beta$, and $x : \alpha$, then $f \ x \cong \text{the thing that you get when you evaluate \(f\) at \(x\)}$ - if $\alpha$ and $\beta$ are types, and $f, g : \alpha \to \beta$, and $f$ and $g$ are pure total functions, and (**for all** $a : \alpha$, it holds that $f \ a \cong g \ a$), then $f \cong g$. **Claim:** $(\lambda (x : \mathbb Z). x \cdot 2) \cong (\lambda (x : \mathbb Z). x + x)$ **Proof:** Let $f = (\lambda (x : \mathbb Z). x \cdot 2)$, and $g = (\lambda (x : \mathbb Z). x + x)$. Then $f, g : \mathbb Z \to \mathbb Z$. (`f : int -> int`, `g : int -> int`) And $f$ and $g$ are pure and total. Now, want to show: $\forall (a : \mathbb Z). \ f \ a = g \ a$. (We want to prove this universal quantification.) Let $a$ be any element of $\mathbb Z$. Then show that $f \ a = g \ a$. $f \ a = (\lambda (x : \mathbb Z). x \cdot 2) \ a = a \cdot 2$. $g \ a = (\lambda (x : \mathbb Z). x + x) \ a = a + a$. By arithmetic, $a \cdot 2 = a + a$. So, $f \ a = g \ a$. So, by the definition of universal quantification, $\forall (a : \mathbb Z). \ f \ a = g \ a$. So, $f \cong g$, by definition of $\cong$. ' --- Question: $(\lambda x. (\lambda y. x + y)) \overset?\cong (\lambda x. \lambda y. y + x)$ let $f = (\lambda x. (\lambda y. x + y))$. what's the type of $f$? $f : \mathbb R \to (\mathbb R \to \mathbb R)$ > - if $\alpha$ and $\beta$ are types, and $f, g : \alpha \to \beta$, and $f$ and $g$ are pure total functions, and (**for all** $a : \alpha$, it holds that $f \ a = g \ a$), then $f \cong g$. Define $\alpha = \mathbb R$, $\beta = (\mathbb R \to \mathbb R)$. Then, $f : \alpha \to \beta$. Assume pure, total. Now, want to show: $\forall (a : \mathbb R). \ f \ a = g \ a$. Pick some arbitrary $a : \mathbb R$. $f \ a \cong (\lambda x. (\lambda y. x + y))a \cong (\lambda y.a + y)$ $g \ a \cong (\lambda x. (\lambda y. y + x))a \cong (\lambda y.y + a)$ Want to show: $f \ a \cong g \ a$. How do we show that? Well, $f \ a$ is a function... Want to show: $\forall (b: \mathbb R). f\ a\ b \cong g\ a\ b$. For some arbitrary $b: \mathbb R$ $f \ a = (\lambda y.a + y)$ $(f \ a) \ b \cong (\lambda y.a + y) \ b \cong a + b$ $(g \ a) \ b \cong (\lambda y.y + a) \ b \cong b + a$ by arithmetic, $a+b = b+a$ $(f \ a) \ b \cong (g \ a) \ b$ so, by defn of congruence, $f \ a \cong g \ a$ Again, by defn of congruence, $f \cong g$ - "Is $f\ a = g\ a$?" Not well defined, since $f\ a$ and $g\ a$ are functions, which aren't equality types. - "Is $f\ a \cong g\ a$?" Maybe! We have a defn. for that. > proof sketch: > "is `(x) => (y) => x + y` congruent to `x=>y=>y+x`?" > well, for some fixed `a`, is `(y) => a+y` cong to `(y) => y+a`? > well again, for some fixed `b`, is `a+b` cong to `b+a`? > yes! > so yes! > so yes! ``` f = (x, y) => x + y f = (x) => ((y) => x + y) ``` --- different proof $\forall (x : \mathbf{Bool}). \ x = \lnot \lnot x$. Let $b$ be any element of **Bool**. Then we want to show that $b = \lnot \lnot b$. Because **Bool** is a finite type, either $b = \top$ or $b = \bot$. Proof by cases: - if true, $\top = \lnot \bot = \lnot \lnot \top$. thus it holds for $b$ - if false, .... thus, it still holds for $b$ in any case, it holds that $b = \lnot\lnot b$. Thus, $\forall (x : \mathbf{Bool}). \ x = \lnot \lnot x$. ## Take Home Proofs **Claim 1:** For all trees $t : \alpha \ \mathsf{tree}$ If $t : \alpha \ \mathsf{tree}$, then $$\mathsf{treeMap} \ \mathsf{id} \ t \cong t.$$ where $$\mathsf{id} \cong (\lambda x.x)$$ $$\mathsf{id} : \forall \alpha. \alpha \to \alpha$$ and <!-- $$\mathsf{treeMap} \cong (\lambda(\lambda x.y). (\lambda x \ tree.y \ tree))$$ --> $$\mathsf{treeMap} : \forall \alpha. \forall \beta. (\alpha \to \beta) \to \alpha \ T \to \beta \ T$$ ```ocaml type 'a tree = Leaf | Node of 'a tree * 'a * 'a tree;; let rec treeMap (f : 'a -> 'b) (t : 'a tree) : 'b tree = match t with | Leaf -> Leaf | Node(x,a,y) -> Node((treeMap f x),f a, (treeMap f y)) ;; ``` $\lambda \_. \square$: function, value, expression --- not a function interface, type, type family $(\lambda y. y)$: second $y$ is the output, sometimes it's a simple math operation, sometimes it's an abstract symbol that may be different from the input. in general, this is an expression that may depend on the input parameter. $\lambda x. \texttt{fetch("http://example.com/" + \(x\)).json().field}$ ```javascript (f) => fetch("..." + x).json().field ``` ```javascript f = (x) => x/2 g = () => 7 array.map(f) array.map(g) array.map((x) => x/2) array.map( (x + 1) => 7 ) ``` ``` function f(x) { return 7 } ``` ``` f = lambda (lambda y. y). 7 f(1) ``` $\lambda x. x \cong \lambda y. y$ thoughts: - lambda defines a named input - specific application of an abstract output - $\lambda \alpha. \beta$: valid lambda, but we don't know much about what it does - $\alpha$-substitution: "renaming" - $\beta$-reduction: substitution - $\alpha$ and $\beta$ represent classes of inputs (types?) - substitute with concrete input to get a concrete output - "$\lambda$-abstraction": something like $\lambda x. \text{something using \(x\)}$ - sub: take a $\lambda$-abstraction and a concrete value (argument), compute the output $[v/x] e$ read as "substitute the value $v$ for occurrences of the name $x$ in the expression $e$" ``` function f(x) { const y = x + 1; return y * x; } f(7) // let's perform beta-reduction here => { const y = 7 + 1; return y * 7; } [7/x] { const y = x + 1; return y * x; } => { const y = 7 + 1; return y * 7; } ``` To evaluate an expression of the form $(\lambda x. e) v$, perform $[v/x]e$, and that's your result of the first step of evaluation. STEPS FOR SUBSTITUTION/BETA-REDUCTION 1. "the function" and "the argument": `f(v)` 2. "the function" itself is like `lambda(x) { e }`: "the name" and "the body" (which is an expression) 3. DECLARATION: substition occurs given a **name** (a name), a **body** (expr), and an **argument** (value) 4. Take the body (discard the lambda skeleton), and replace occurrences of the name with the argument. ``` (\lambda x. 7 + x) 12 function: \lambda x. 7 + x name: x body: 7 + x argument: 12 result: 7 + 12 (\lambda (\lambda y. y). 7) 12 function: \lambda (\lambda y. y). 7 name: \lambda y. y, x + 1 body: 7 argument: 12 result: 7 (function(function(y) { return y }) { return 7 })(12) f = (\lambda x. x) g = (\lambda y. y) f(g) [KIND OF THING: fn application] (\lambda x. x) (\lambda y. y) [KIND OF THING: lambda expression (value)] (\lambda y. y) 4. Take the body (discard the lambda skeleton), and replace occurrences of the name with the argument. [KIND OF THING: fn application] (\lambda f. f f) (\lambda g. g g) (\lambda g. g g) (\lambda g. g g) function: (\lambda g. g g) name: g body: g g argument: \lambda g. g g result: (\lambda g. g g) (\lambda g. g g) (\lambda g. g g) (\lambda g. g g) (\lambda g. g g) (\lambda g. g g) (\lambda g. g g) (\lambda g. g g) (\lambda g. g g) (\lambda g. g g) ... let foo = getTheFoo(); let foo = process(foo); let foo = process2(foo); let foo = frobnicate(foo); return foo; (function(foo) { return (function(foo) { return process2(foo); })(process(foo)); }) ``` $\omega = \lambda x. \ x \ x$ ``` k = (x) => ((x) => x); function k(x) { function z(x) { return x; } } k(7)(12) k(7)(12) = ((x) => x)(12) = 7 // friendGroups: [["kevin", "wc"], ["kevin", "dl"]] function renderAllTheThings(friendGroups) { return friendsGroups.map((x) => { // x: ["kevin", "wc"] const n = x.length; return <span>{n}{x.map((x2) => { <span> friend named {x2} </span> } )}</span> }) } [] ``` Substitution that supports shadowing be like: - "take the Body, traverse the expression, and replace any occurrence of the Name with the Argument, BUT if you ever enter a lambda expression whose parameter is ALSO the Name, then don't enter the lambda" ``` f1 = (x) => x + 1 f2 = (x) => x * 2 PI = 3.14 function() { return PI } (\lambda \lambda \lambda . . . x y) 3.15 = 3.14 function(PI) { return PI } \lambda y.7 (\lambda x. (\lambda y. (x))) 7 12 1. (\lambda y.7) 12 2. 7 (\lambda (\lambda y. y). 7) 12 \lambda z. (\lambda x. (\lambda y. (x))) ``` beta reduction returns an expression but it may or may not return a value (\lambda x. x + 1)(7) 7 + 1 => 8 **Proof:** Let $t: \alpha \ tree$ and $\mathsf{id} = (\lambda x.x)$ and $f = \lambda\alpha.\beta$ $\mathsf{treeMap} = \lambda(\lambda a.b).(\lambda \ at.bt)$. In $\mathsf{treeMap}$, $\beta$ is an abstraction and $\alpha$ may intersect with $\beta$. We are free to apply $\mathsf{id}$ to $\mathsf{treeMap}$ by definition of $b$ as $a$ in this case. Through substitution, we get ```ocaml= let id (a) = a let rec treeMap id (t : 'a tree): 'a tree = match t with | Leaf -> Leaf | Node(x,a,y) -> Node((treeMap id x),id a, (treeMap id y)) ;; ``` Because $\mathsf{id}$ is substituted for $f$, the resultant $\mathsf{idMap}$ returns $a$ trees. This is due to the way treeMap is defined. The output of $f$ defines the type of tree that is returned from $\mathsf{treemap}$. This leaves us with the task of walking through this function definition. $Case: T = Leaf$. by definition \begin{align} idMap(Leaf) & = Leaf \end{align} $Case: T = Node(L, x, R)$ For some trees $L$ and $R$. Note that $$ \begin{align} idMap(Node(L,x,R))) & = Node(treeMap \ id \ L, id \ x, treeMap \ id \ R)) &&\text{Definition of treeMap}\\ & = Node( treeMap \ L, x, treeMap \ R )) &&\text{Definition of identity}\\ & = Node(L, x, R) &&\text{Inductive Hypothesis} \end{align} $$ Because both cases reduce to the inputs, we have shown that: $$\mathsf{treeMap} \ \mathsf{id} \ t \cong t.$$ **Proof Plan:** Let $t: \alpha \ tree$, any tree. Plan: - show what `treeMap id` looks like - assume that `t` is a leaf - reduce `(treeMap id) t` to show that it's congruent to `t` ``` (fn t -> (match t with Leaf -> Leaf Node(x,a,y) -> Node((treeMap id x),id a,(treeMap id y)) )) t ``` Consider cases: axioms: if $a \cong b$ and $b \cong c$, then $a \cong c$ (transitivity) symm - *case 1*: if $t$ is `Leaf`. then the `match` expr enters the `Leaf ->` pattern, and evaluates to `Leaf`. so $\mathsf{treeMap} \ \mathsf{id} \ t \cong \mathsf{Leaf}$. and we also know that $t \cong \mathsf{Leaf}$, so $\mathsf{Leaf} \cong t$. therefore, by symemtry and transitivty of $\cong$, $\mathsf{treeMap} \ \mathsf{id} \ t \cong t$. - *case 2*: if $t$ is `Node`, then the `match` expr enters the `Node(x,a,y) ->` pattern. Starting with the second element, we can apply `id` to `a`, which evaluates to `a`. For the first and third elements, we will inductively show that they evaluate to `x` and `y` respectively. - what if neither of those? impossible, because we assumed that it's an $\alpha \ \mathsf{tree}$ If we apply $\mathsf{id}$ as an argument in $\mathsf{treeMap}$ and then apply that to $t$ we have $$ \mathsf{treeMap \ id} \ t \cong (\lambda(\lambda x.x).(\lambda x \ tree.x \ tree))$$ ```ocaml let outer = treeMap (* just the whole thing *) let inner = treeMap id (* application of outer function to our particular mapper *) (* the actual function that operates on trees *) ``` We observe that that $\mathsf{treeMap}$ contains two functions that conform to the definition of the identity. We therefore are able to apply both functions and are left with $$ \mathsf{treeMap \ id} \ t \cong \alpha \ tree $$ and therefore have $$ \mathsf{treeMap \ id} \ t \cong t $$ --- **Claim 2:** If $f : \alpha \to \beta$ and $g : \beta \to \gamma$, and $t : \alpha \ \mathsf{tree}$, then $$\mathsf{cart} \ g \ (\mathsf{cart} \ f \ t) \cong \mathsf{cart} \ (\mathsf{swish} \ f \ g) \ t.$$ where $$\mathsf{swish} = (\lambda((\lambda\alpha.\beta).(\lambda\beta.\gamma).(\lambda \alpha.\gamma)))$$ **Proof:** Evaluating $\mathsf{cart} \ g \ (\mathsf{cart} \ f \ t)$ as a lambda yields $$ \mathsf{cart} \ g \ (\mathsf{cart} \ f \ t) \cong $$