1 Commits

Author SHA1 Message Date
df91fd9f96 Incomplete port 2025-10-02 07:56:09 -07:00
29 changed files with 1920 additions and 463 deletions

View File

@@ -26,7 +26,7 @@ jobs:
- name: "Download Typstyle" - name: "Download Typstyle"
run: | run: |
wget -q "https://github.com/Enter-tainer/typstyle/releases/download/v0.13.17/typstyle-x86_64-unknown-linux-musl" wget -q "https://github.com/Enter-tainer/typstyle/releases/download/v0.12.14/typstyle-x86_64-unknown-linux-musl"
chmod +x typstyle-x86_64-unknown-linux-musl chmod +x typstyle-x86_64-unknown-linux-musl
- name: Check typst formatting - name: Check typst formatting
@@ -62,7 +62,7 @@ jobs:
# more control anyway. # more control anyway.
- name: "Download Typst" - name: "Download Typst"
run: | run: |
wget -q "https://github.com/typst/typst/releases/download/v0.13.1/typst-x86_64-unknown-linux-musl.tar.xz" wget -q "https://github.com/typst/typst/releases/download/v0.12.0/typst-x86_64-unknown-linux-musl.tar.xz"
tar -xf "typst-x86_64-unknown-linux-musl.tar.xz" tar -xf "typst-x86_64-unknown-linux-musl.tar.xz"
mv "typst-x86_64-unknown-linux-musl/typst" . mv "typst-x86_64-unknown-linux-musl/typst" .
rm "typst-x86_64-unknown-linux-musl.tar.xz" rm "typst-x86_64-unknown-linux-musl.tar.xz"

View File

@@ -3,10 +3,13 @@
// Re-exports // Re-exports
// All functions that maybe used by client code are listed here // All functions that maybe used by client code are listed here
#import "misc.typ": * #import "misc.typ": *
#import "object.typ": definition, example, generic, problem, remark, theorem #import "object.typ": problem, definition, theorem, example, remark, generic
#import "solution.typ": ( #import "solution.typ": (
if_no_solutions, if_solutions, if_solutions_else, instructornote, if_solutions,
sample_solution, solution, if_no_solutions,
if_solutions_else,
solution,
instructornote,
) )
@@ -35,7 +38,10 @@
margin: 20mm, margin: 20mm,
width: 8.5in, width: 8.5in,
height: 11in, height: 11in,
footer: align(center, context counter(page).display()), footer: align(
center,
context counter(page).display(),
),
footer-descent: 5mm, footer-descent: 5mm,
) )
@@ -96,8 +102,8 @@
// Make handout title // Make handout title
{ {
import "header.typ": make_header, short_solution_warning, solution_warning import "header.typ": make_header, solution_warning, short_solution_warning
import "solution.typ": reset_solutions, solutions_state import "solution.typ": solutions_state, reset_solutions
reset_solutions() reset_solutions()

View File

@@ -29,7 +29,11 @@
} }
// Render the object // Render the object
block(above: 8mm, below: 2mm, text(weight: "bold", obj_content)) block(
above: 8mm,
below: 2mm,
text(weight: "bold", obj_content),
)
// Generate labeled metadata for this object. // Generate labeled metadata for this object.
// //
@@ -53,7 +57,7 @@
if not ( if not (
it.element != none it.element != none
and it.element.has("value") and it.element.has("value")
and type(it.element.value) == dictionary and type(it.element.value) == "dictionary"
and it.element.value.keys().contains(magic_key) and it.element.value.keys().contains(magic_key)
) { ) {
// This label is not attached to object metadata // This label is not attached to object metadata
@@ -96,5 +100,9 @@
#let remark = _mkobj("Remark") #let remark = _mkobj("Remark")
#let generic(obj_content) = { #let generic(obj_content) = {
block(above: 8mm, below: 2mm, text(weight: "bold", obj_content)) block(
above: 8mm,
below: 2mm,
text(weight: "bold", obj_content),
)
} }

View File

@@ -1,4 +1,4 @@
#import "misc.typ": oblue, ored #import "misc.typ": ored, oblue
/// If false, hide instructor info. /// If false, hide instructor info.
@@ -61,7 +61,10 @@
} }
#let solution(content) = { #let solution(content) = {
if_solutions(align(center, stack( if_solutions(
align(
center,
stack(
block( block(
width: 100%, width: 100%,
breakable: false, breakable: false,
@@ -80,35 +83,16 @@
inset: 3mm, inset: 3mm,
align(left, content), align(left, content),
), ),
)))
}
#let sample_solution(content) = {
align(center, stack(
block(
width: 100%,
breakable: false,
fill: oblue,
stroke: oblue + 2pt,
inset: 1.5mm,
align(left, text(fill: white, weight: "bold", [Sample Solution:])),
), ),
block(
width: 100%,
height: auto,
breakable: false,
fill: oblue.lighten(80%).desaturate(10%),
stroke: oblue + 2pt,
inset: 3mm,
align(left, content),
), ),
)) )
} }
#let instructornote(content) = { #let instructornote(content) = {
if_solutions(align(center, stack( if_solutions(
align(
center,
stack(
block( block(
width: 100%, width: 100%,
breakable: false, breakable: false,
@@ -127,5 +111,7 @@
inset: 3mm, inset: 3mm,
align(left, content), align(left, content),
), ),
))) ),
),
)
} }

View File

@@ -1,5 +1,5 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
= Floats = Floats
#definition() #definition()
@@ -33,7 +33,11 @@ Another way we can interpret a bit string is as a _signed floating-point decimal
Floats represent a subset of the real numbers, and are interpreted as follows: \ Floats represent a subset of the real numbers, and are interpreted as follows: \
#note([The following only applies to floats that consist of 32 bits. We won't encounter any others today.]) #note([The following only applies to floats that consist of 32 bits. We won't encounter any others today.])
#align(center, box(inset: 2mm, cetz.canvas({ #align(
center,
box(
inset: 2mm,
cetz.canvas({
import cetz.draw: * import cetz.draw: *
let chars = ( let chars = (
@@ -92,7 +96,9 @@ Floats represent a subset of the real numbers, and are interpreted as follows: \
line((3.10, y), (9.4, y)) line((3.10, y), (9.4, y))
content((6.3, y - 0.2), [fraction]) content((6.3, y - 0.2), [fraction])
}))) }),
),
)
- The first bit denotes the sign of the float's value - The first bit denotes the sign of the float's value
We'll label it $s$. \ We'll label it $s$. \

View File

@@ -1,6 +1,6 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
#import "@preview/cetz-plot:0.1.2": chart, plot #import "@preview/cetz-plot:0.1.0": plot, chart
= Integers and Floats = Integers and Floats
@@ -44,11 +44,19 @@ This allows us to improve the average error of our linear approximation:
{ {
let domain = (0, 1) let domain = (0, 1)
plot.add(f1, domain: domain, label: $log(1+x)$, style: ( plot.add(
stroke: ogrape, f1,
)) domain: domain,
label: $log(1+x)$,
style: (stroke: ogrape),
)
plot.add(f2, domain: domain, label: $x$, style: (stroke: oblue)) plot.add(
f2,
domain: domain,
label: $x$,
style: (stroke: oblue),
)
}, },
) )
}) })
@@ -82,11 +90,19 @@ This allows us to improve the average error of our linear approximation:
{ {
let domain = (0, 1) let domain = (0, 1)
plot.add(f1, domain: domain, label: $log(1+x)$, style: ( plot.add(
stroke: ogrape, f1,
)) domain: domain,
label: $log(1+x)$,
style: (stroke: ogrape),
)
plot.add(f2, domain: domain, label: $x$, style: (stroke: oblue)) plot.add(
f2,
domain: domain,
label: $x$,
style: (stroke: oblue),
)
}, },
) )
}) })
@@ -104,13 +120,16 @@ We won't bother with this---we'll simply leave the correction term as an opaque
#v(1fr) #v(1fr)
#note(type: "Note", [ #note(
type: "Note",
[
"Average error" above is simply the area of the region between the two graphs: "Average error" above is simply the area of the region between the two graphs:
$ $
integral_0^1 abs(#v(1mm) log(1+x)_2 - (x+epsilon) #v(1mm)) integral_0^1 abs( #v(1mm) log(1+x)_2 - (x+epsilon) #v(1mm))
$ $
Feel free to ignore this note, it isn't a critical part of this handout. Feel free to ignore this note, it isn't a critical part of this handout.
]) ],
)
#pagebreak() #pagebreak()
@@ -130,11 +149,12 @@ $
Let $E$ and $F$ be the exponent and float bits of $x_f$. \ Let $E$ and $F$ be the exponent and float bits of $x_f$. \
We then have: We then have:
$ $
log_2(x_f) & = log_2 ( 2^(E-127) times (1 + (F) / (2^23)) ) \ log_2(x_f)
& = E - 127 + log_2(1 + F / (2^23)) \ &= log_2 ( 2^(E-127) times (1 + (F) / (2^23)) ) \
&= E - 127 + log_2(1 + F / (2^23)) \
& approx E-127 + F / (2^23) + epsilon \ & approx E-127 + F / (2^23) + epsilon \
& = 1 / (2^23)(2^23 E + F) - 127 + epsilon \ &= 1 / (2^23)(2^23 E + F) - 127 + epsilon \
& = 1 / (2^23)(x_i) - 127 + epsilon &= 1 / (2^23)(x_i) - 127 + epsilon
$ $
]) ])

View File

@@ -0,0 +1,35 @@
#import "@local/handout:0.1.0": *
#show: handout.with(
title: [Intro to Quantum Computing],
by: "Mark",
)
// Define quantum notation macros
#let ket(content) = $|#content angle.r$
#let bra(content) = $angle.l #content|$
#include "src/parts/01 bits.typ"
#pagebreak()
#include "src/parts/02 qubit.typ"
#pagebreak()
#include "src/parts/03 two qubits.typ"
#pagebreak()
// DONE UNTIL HERE
#include "src/parts/04 logic gates.typ"
#pagebreak()
#include "src/parts/05 quantum gates.typ"
#pagebreak()
#include "src/parts/06 hxh.typ"
#pagebreak()
#include "src/parts/07 superdense.typ"
#pagebreak()
#include "src/parts/08 teleport.typ"

View File

@@ -0,0 +1,349 @@
#import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2"
= Probabilistic Bits
#definition()
As we already know, a _classical bit_ may take the values `0` and `1`.
We can model this with a two-sided coin, one face of which is labeled `0`, and the other, `1`.
#v(2mm)
Of course, if we toss such a "bit-coin," we'll get either `0` or `1`.
We'll denote the probability of getting `0` as $p_0$, and the probability of getting `1` as $p_1$.
As with all probabilities, $p_0 + p_1$ must be equal to 1.
#v(1fr)
#definition()
Say we toss a "bit-coin" and don't observe the result. We now have a _probabilistic bit_, with a probability $p_0$ of being `0`, and a probability $p_1$ of being `1`.
#v(2mm)
We'll represent this probabilistic bit's _state_ as a vector: $mat(p_0; p_1)$
We do *not* assume this coin is fair, and thus $p_0$ might not equal $p_1$.
#note[This may seem a bit redundant: since $p_0 + p_1 = 1$, we can always calculate one probability given the other. We'll still include both probabilities in the state vector, since this provides a clearer analogy to quantum bits.]
#v(1fr)
#definition()
The simplest probabilistic bit states are of course $[0]$ and $[1]$, defined as follows:
- $[0] = mat(1; 0)$
- $[1] = mat(0; 1)$
That is, $[0]$ represents a bit that we known to be `0`, and $[1]$ represents a bit we know to be `1`.
#v(1fr)
#definition()
$[0]$ and $[1]$ form a _basis_ for all possible probabilistic bit states:
Every other probabilistic bit can be written as a _linear combination_ of $[0]$ and $[1]$:
$ mat(p_0; p_1) = p_0 mat(1; 0) + p_1 mat(0; 1) = p_0 [0] + p_1 [1] $
#v(1fr)
#pagebreak()
#problem()
Every possible state of a probabilistic bit is a two-dimensional vector.
Draw all possible states on the axis below.
#table(
columns: (1fr,),
align: center,
stroke: none,
align(center, cetz.canvas({
import cetz.draw: *
set-style(content: (frame: "rect", stroke: none, fill: none, padding: .25))
scale(200%)
line(
(0, 1.5),
(0, 0),
(1.5, 0),
stroke: black + 0.25mm,
)
mark((0, 1.5), (0, 2), symbol: ")>", fill: black)
mark((1.5, 0), (2, 0), symbol: ")>", fill: black)
content((0, 1.5), $p_1$, anchor: "south")
content((1.5, 0), $p_0$, anchor: "west")
circle((0, 0), radius: 0.6mm, fill: black, name: "00")
content("00.south", $mat(0; 0)$, anchor: "north")
circle((0, 1), radius: 0.6mm, fill: oblue, stroke: oblue, name: "00")
content("00.west", $[1]$, anchor: "east")
circle((1, 0), radius: 0.6mm, fill: oblue, stroke: oblue, name: "00")
content("00.south", $[0]$, anchor: "north")
})),
)
#solution[
#table(
columns: (1fr,),
align: center,
stroke: none,
align(center, cetz.canvas({
import cetz.draw: *
set-style(content: (
frame: "rect",
stroke: none,
fill: none,
padding: .25,
))
scale(200%)
line(
(0, 1.5),
(0, 0),
(1.5, 0),
stroke: black + 0.25mm,
)
mark((0, 1.5), (0, 2), symbol: ")>", fill: black)
mark((1.5, 0), (2, 0), symbol: ")>", fill: black)
content((0, 1.5), $p_1$, anchor: "south")
content((1.5, 0), $p_0$, anchor: "west")
line(
(1, 0),
(0, 1),
stroke: ored + 1mm,
)
circle((0, 0), radius: 0.6mm, fill: black, name: "00")
content("00.south", $mat(0; 0)$, anchor: "north")
circle((0, 1), radius: 0.6mm, fill: oblue, stroke: oblue, name: "00")
content("00.west", $[1]$, anchor: "east")
circle((1, 0), radius: 0.6mm, fill: oblue, stroke: oblue, name: "00")
content("00.south", $[0]$, anchor: "north")
})),
)
]
#v(1fr)
#pagebreak()
= Measuring Probabilistic Bits
#definition()
As we noted before, a probabilistic bit represents a coin we've tossed but haven't looked at.
We do not know whether the bit is `0` or `1`, but we do know the probability of both of these outcomes.
#v(2mm)
If we _measure_ (or _observe_) a probabilistic bit, we see either `0` or `1`—and thus our knowledge of its state is updated to either $[0]$ or $[1]$, since we now certainly know what face the coin landed on.
#v(2mm)
Since measurement changes what we know about a probabilistic bit, it changes the probabilistic bit's state. When we measure a bit, its state _collapses_ to either $[0]$ or $[1]$, and the original state of the bit vanishes. We _cannot_ recover the state $[x_0, x_1]$ from a measured probabilistic bit.
#definition("Multiple bits")
Say we have two probabilistic bits, $x$ and $y$, with states $[x] = [x_0, x_1]$ and $[y] = [y_0, y_1]$
#v(2mm)
The _compound state_ of $[x]$ and $[y]$ is exactly what it sounds like: It is the probabilistic two-bit state $|x y angle.r$, where the probabilities of the first bit are determined by $[x]$, and the probabilities of the second are determined by $[y]$.
#problem(label: "firstcompoundstate")
Say $[x] = [2/3, 1/3]$ and $[y] = [3/4, 1/4]$.
- If we measure $x$ and $y$ simultaneously, what is the probability of getting each of `00`, `01`, `10`, and `11`?
- If we measure $y$ first and observe `1`, what is the probability of getting each of `00`, `01`, `10`, and `11`?
#note[*Note:* $[x]$ and $[y]$ are column vectors, but I've written them horizontally to save space.]
#v(1fr)
#problem()
Say $[x] = [2/3, 1/3]$ and $[y] = [3/4, 1/4]$.
What is the probability that $x$ and $y$ produce different outcomes?
#v(1fr)
#pagebreak()
= Tensor Products
#definition("Tensor Products")
The _tensor product_ of two vectors is defined as follows:
$
mat(x_1; x_2) times.circle mat(y_1; y_2) = mat(x_1 mat(y_1; y_2); x_2 mat(y_1; y_2)) = mat(x_1 y_1; x_1 y_2; x_2 y_1; x_2 y_2)
$
That is, we take our first vector, multiply the second vector by each of its components, and stack the result. You could think of this as a generalization of scalar multiplication, where scalar multiplication is a tensor product with a vector in $RR^1$:
$
a mat(x_1; x_2) = mat(a_1) times.circle mat(y_1; y_2) = mat(a_1 mat(y_1; y_2)) = mat(a_1 y_1; a_1 y_2)
$
#problem()
Say $x in RR^n$ and $y in RR^m$.
What is the dimension of $x times.circle y$?
#v(1fr)
#problem(label: "basistp")
What is the following pairwise tensor product?
#v(4mm)
$
{mat(1; 0; 0), mat(0; 1; 0), mat(0; 0; 1)}
times.circle
{mat(1; 0), mat(0; 1)}
$
#v(4mm)
#hint[Distribute the tensor product between every pair of vectors.]
#v(1fr)
#problem()
What is the _span_ of the vectors we found in @basistp?
In other words, what is the set of vectors that can be written as linear combinations of the vectors above?
#v(1fr)
#pagebreak()
#problem()
Say $[x] = [2/3, 1/3]$ and $[y] = [3/4, 1/4]$.
What is $[x] times.circle [y]$? How does this relate to @firstcompoundstate?
#v(1fr)
#problem()
The compound state of two vector-form bits is their tensor product.
Compute the following. Is the result what we'd expect?
- $[0] times.circle [0]$
- $[0] times.circle [1]$
- $[1] times.circle [0]$
- $[1] times.circle [1]$
#hint[Remember that $[0] = mat(1; 0)$ and $[1] = mat(0; 1)$.]
#v(1fr)
#problem(label: "fivequant")
Writing $[0] times.circle [1]$ is a bit tedious. We'll shorten this notation to $[01]$.
In fact, we could go further: if we wanted to write the set of bits $[1] times.circle [1] times.circle [0] times.circle [1]$, \
we could write $[1101]$—but a shorter alternative is $[13]$, since $13$ is `1101` in binary.
#v(2mm)
Write $[5]$ as a three-bit probabilistic state.
#solution[
$[5] = [101] = [1] times.circle [0] times.circle [1] = [0,0,0,0,0,1,0,0]^T$ \
Notice how we're counting from the top, with $[000] = [1,0,...,0]$ and $[111] = [0, ..., 0, 1]$.
]
#v(1fr)
#problem()
Write the three-bit states $[0]$ through $[7]$ as column vectors.
#hint[You do not need to compute every tensor product. Do a few and find the pattern.]
#v(1fr)
#pagebreak()
= Operations on Probabilistic Bits
Now that we can write probabilistic bits as vectors, we can represent operations on these bits with linear transformations—in other words, as matrices.
#definition()
Consider the NOT gate, which operates as follows:
- $"NOT"[0] = [1]$
- $"NOT"[1] = [0]$
What should NOT do to a probabilistic bit $[x_0, x_1]$?
If we return to our coin analogy, we can think of the NOT operation as flipping a coin we have already tossed, without looking at its state. Thus,
$ "NOT" mat(x_0; x_1) = mat(x_1; x_0) $
#review_box("Review: Multiplying vectors by matrices")[
#v(2mm)
$
A v = mat(1, 2; 3, 4) mat(v_0; v_1) = mat(1 v_0 + 2 v_1; 3 v_0 + 4 v_1)
$
#v(2mm)
Note that each element of $A v$ is the dot product of a row in $A$ and a column in $v$.
]
#problem()
Compute the following product:
$ mat(1, 0.5; 0, 1) mat(3; 2) $
#v(1fr)
#remark()
Also, recall that every matrix is linear map, and that every linear map may be written as a matrix. We often use the terms _matrix_, _transformation_, and _linear map_ interchangeably.
#pagebreak()
#problem()
Find the matrix that represents the NOT operation on one probabilistic bit.
#solution[
$
mat(0, 1; 1, 0)
$
]
#v(1fr)
#problem("Extension by linearity")
Say we have an arbitrary operation $M$.
If we know how $M$ acts on $[1]$ and $[0]$, can we compute $M[x]$ for an arbitrary state $[x]$?
Say $[x] = [x_0, x_1]$.
- What is the probability we observe $0$ when we measure $x$?
- What is the probability that we observe $M[0]$ when we measure $M x$?
#v(1fr)
#problem(label: "linearextension")
Write $M[x_0, x_1]$ in terms of $M[0]$, $M[1]$, $x_0$, and $x_1$.
#solution[
$
M mat(x_0; x_1) = x_0 M mat(1; 0) + x_1 M mat(0; 1) = x_0 M[0] + x_1 M[1]
$
]
#v(1fr)
#remark() Every matrix represents a _linear_ map, so the following is always true:
$ A times (p x + q y) = p A x + q A y $
@linearextension is just a special case of this fact.

View File

@@ -0,0 +1,514 @@
#import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2"
// Define quantum notation macros
#let ket(content) = $|#content angle.r$
#let bra(content) = $angle.l #content|$
= One Qubit
Quantum bits (or _qubits_) are very similar to probabilistic bits, but have one major difference: probabilities are replaced with _amplitudes_.
#v(2mm)
Of course, a qubit can take the values `0` and `1`, which are denoted $#ket("0")$ and $#ket("1")$.
Like probabilistic bits, a quantum bit is written as a linear combination of $#ket("0")$ and $#ket("1")$:
$ #ket([$psi$]) = psi_0 #ket("0") + psi_1 #ket("1") $
Such linear combinations are called _superpositions_.
#v(2mm)
The $#ket("")$ you see in the expressions above is called a "ket," and denotes a column vector.
$#ket("0")$ is pronounced "ket zero," and $#ket("1")$ is pronounced "ket one." This is called bra-ket notation.
#note[*Note:* $#bra("0")$ is called a "bra," but we won't worry about that for now.]
#v(2mm)
This is very similar to the "box" $[#h(1.5mm)]$ notation we used for probabilistic bits.
As before, we will write $#ket("0") = mat(1; 0)$ and $#ket("1") = mat(0; 1)$.
#v(8mm)
Recall that probabilistic bits are subject to the restriction that $p_0 + p_1 = 1$.
Quantum bits have a similar condition: $psi_0^2 + psi_1^2 = 1$.
Note that this implies that $psi_0$ and $psi_1$ are both in $[-1, 1]$.
Quantum amplitudes may be negative, but probabilistic bit probabilities cannot.
#v(2mm)
If we plot the set of valid quantum states on our plane, we get a unit circle centered at the origin:
#table(
columns: (1fr,),
align: center,
stroke: none,
align(center, cetz.canvas({
import cetz.draw: *
set-style(content: (frame: "rect", stroke: none, fill: none, padding: .25))
scale(150%)
line(
(0, 1.5),
(0, 0),
(1.5, 0),
stroke: black + 0.25mm,
)
mark((0, 1.5), (0, 2), symbol: ")>", fill: black)
mark((1.5, 0), (2, 0), symbol: ")>", fill: black)
circle((0, 0), radius: 1, stroke: (
paint: black,
thickness: 0.25mm,
dash: "dashed",
))
content((0, 1.5), $p_1$, anchor: "south")
content((1.5, 0), $p_0$, anchor: "west")
circle((0, 1), radius: 0.6mm, fill: oblue, stroke: oblue, name: "00")
content("00.west", $#ket("1")$, anchor: "east")
circle((1, 0), radius: 0.6mm, fill: oblue, stroke: oblue, name: "00")
content("00.south", $#ket("0")$, anchor: "north")
circle((0.87, 0.5), radius: 0.6mm, fill: ored, stroke: ored, name: "00")
content("00.east", $#ket(math.psi)$, anchor: "west")
})),
)
Recall that the set of probabilistic bits forms a line instead:
#table(
columns: (1fr,),
align: center,
stroke: none,
align(center, cetz.canvas({
import cetz.draw: *
set-style(content: (frame: "rect", stroke: none, fill: none, padding: .25))
scale(150%)
line(
(0, 1.5),
(0, 0),
(1.5, 0),
stroke: black + 0.25mm,
)
mark((0, 1.5), (0, 2), symbol: ")>", fill: black)
mark((1.5, 0), (2, 0), symbol: ")>", fill: black)
line(
(1, 0),
(0, 1),
stroke: ored + 1mm,
)
content((0, 1.5), $p_1$, anchor: "south")
content((1.5, 0), $p_0$, anchor: "west")
circle((0, 0), radius: 0.6mm, fill: black, name: "00")
content("00.south", $mat(0; 0)$, anchor: "north")
circle((0, 1), radius: 0.6mm, fill: oblue, stroke: oblue, name: "00")
content("00.west", $[1]$, anchor: "east")
circle((1, 0), radius: 0.6mm, fill: oblue, stroke: oblue, name: "00")
content("00.south", $[0]$, anchor: "north")
})),
)
#problem()
In the above unit circle, the counterclockwise angle from $#ket("0")$ to $#ket([$psi$])$ is $30°$.
Write $#ket([$psi$])$ as a linear combination of $#ket("0")$ and $#ket("1")$.
#v(1fr)
#pagebreak()
#definition("Measurement I")
Just like a probabilistic bit, we must observed $#ket("0")$ or $#ket("1")$ when we measure a qubit.
If we were to measure $#ket([$psi$]) = psi_0 #ket("0") + psi_1 #ket("1")$, we'd observe either $#ket("0")$ or $#ket("1")$, with the following probabilities:
- $cal(P)(#ket("1")) = psi_1^2$
- $cal(P)(#ket("0")) = psi_0^2$
#note[Note that $cal(P)(#ket("0")) + cal(P)(#ket("1")) = 1$.]
#v(2mm)
As before, $#ket([$psi$])$ _collapses_ when it is measured: its state becomes that which we observed in our measurement, leaving no trace of the previous superposition.
#problem()
- What is the probability we observe $#ket("0")$ when we measure $#ket([$psi$])$?
- What can we observe if we measure $#ket([$psi$])$ a second time?
- What are these probabilities for $#ket([$phi$])$?
#table(
columns: (1fr,),
align: center,
stroke: none,
align(center, cetz.canvas({
import cetz.draw: *
set-style(content: (frame: "rect", stroke: none, fill: none, padding: .25))
scale(200%)
line(
(0, 1.5),
(0, 0),
(1.5, 0),
stroke: black + 0.25mm,
)
mark((0, 1.5), (0, 2), symbol: ")>", fill: black)
mark((1.5, 0), (2, 0), symbol: ")>", fill: black)
circle((0, 0), radius: 1, stroke: (
paint: black,
thickness: 0.25mm,
dash: "dashed",
))
content((0, 1.5), $p_1$, anchor: "south")
content((1.5, 0), $p_0$, anchor: "west")
circle((0, 1), radius: 0.6mm, fill: oblue, stroke: oblue, name: "00")
content("00.west", $#ket("1")$, anchor: "east")
circle((1, 0), radius: 0.6mm, fill: oblue, stroke: oblue, name: "00")
content("00.south", $#ket("0")$, anchor: "north")
circle((0.87, 0.5), radius: 0.6mm, fill: ored, stroke: ored, name: "00")
content("00.east", $#ket(math.psi)$, anchor: "west")
arc(
(0, 0),
start: 0deg,
stop: -135deg,
anchor: "origin",
radius: 0.3,
name: "a135",
stroke: gray,
)
mark(
"a135.end",
135deg,
symbol: ")>",
fill: gray,
stroke: gray,
)
content("a135.center", text(fill: gray)[$135degree$], anchor: "north")
line((0, 0), (-0.607, -0.607), stroke: (
paint: gray,
thickness: 0.4mm,
dash: "dotted",
))
mark(
(-0.627, -0.627),
(-0.708, -0.708),
symbol: ")>",
fill: gray,
stroke: gray,
)
arc(
(0, 0),
start: 0deg,
stop: 30deg,
anchor: "origin",
radius: 0.6,
name: "a30",
stroke: gray,
)
mark(
"a30.end",
120deg,
symbol: ")>",
fill: gray,
stroke: gray,
)
content("a30.end", text(fill: gray)[$30degree$], anchor: "south")
line((0, 0), (0.87, 0.5), stroke: (
paint: gray,
thickness: 0.4mm,
dash: "dotted",
))
mark(
(0.80, 0.46),
(0.87, 0.5),
symbol: ")>",
fill: gray,
stroke: gray,
)
circle(
(-0.707, -0.707),
radius: 0.6mm,
fill: ored,
stroke: ored,
name: "00",
)
content("00.west", $#ket(math.phi)$, anchor: "east")
})),
)
#v(1fr)
As you may have noticed, we don't need two coordinates to fully define a qubit's state. We can get by with one coordinate just as well.
Instead of referring to each state using its cartesian coordinates $psi_0$ and $psi_1$, we can address it using its _polar angle_ $theta$, measured from $#ket("0")$ counterclockwise:
#table(
columns: (1fr,),
align: center,
stroke: none,
align(center, cetz.canvas({
import cetz.draw: *
set-style(content: (frame: "rect", stroke: none, fill: none, padding: .25))
scale(180%)
line(
(0, 1.5),
(0, 0),
(1.5, 0),
stroke: black + 0.25mm,
)
mark((0, 1.5), (0, 2), symbol: ")>", fill: black)
mark((1.5, 0), (2, 0), symbol: ")>", fill: black)
circle((0, 0), radius: 1, stroke: (
paint: black,
thickness: 0.25mm,
dash: "dashed",
))
content((0, 1.5), $p_1$, anchor: "south")
content((1.5, 0), $p_0$, anchor: "west")
circle((0, 1), radius: 0.6mm, fill: oblue, stroke: oblue, name: "00")
content("00.west", $#ket("1")$, anchor: "east")
circle((1, 0), radius: 0.6mm, fill: oblue, stroke: oblue, name: "00")
content("00.south", $#ket("0")$, anchor: "north")
circle((0.87, 0.5), radius: 0.6mm, fill: ored, stroke: ored, name: "00")
content("00.east", $#ket(math.psi)$, anchor: "west")
arc(
(0, 0),
start: 0deg,
stop: 30deg,
anchor: "origin",
radius: 0.6,
name: "a30",
stroke: gray,
)
mark(
"a30.end",
120deg,
symbol: ")>",
fill: gray,
stroke: gray,
)
content("a30.mid", text(fill: gray)[$theta$], anchor: "west")
line((0, 0), (0.87, 0.5), stroke: (
paint: gray,
thickness: 0.4mm,
dash: "dotted",
))
mark(
(0.80, 0.46),
(0.87, 0.5),
symbol: ")>",
fill: gray,
stroke: gray,
)
})),
)
#problem()
Find $psi_0$ and $psi_1$ in terms of $theta$ for an arbitrary qubit $psi$.
#v(1fr)
#pagebreak()
#problem()
Consider the following qubit states:
#grid(
columns: (1fr, 1fr),
$ #ket("+") = (#ket("0") + #ket("1"))/sqrt(2) $,
$ #ket("-") = (#ket("0") - #ket("1"))/sqrt(2) $,
)
- Where are these on the unit circle?
- What are their polar angles?
- What are the probabilities of observing $#ket("0")$ and $#ket("1")$ when measuring $#ket("+")$ and $#ket("-")$?
#table(
columns: (1fr,),
align: center,
stroke: none,
align(center, cetz.canvas({
import cetz.draw: *
set-style(content: (frame: "rect", stroke: none, fill: none, padding: .25))
scale(300%)
line(
(0, 1.3),
(0, 0),
(1.3, 0),
stroke: black + 0.25mm,
)
mark((0, 1.3), (0, 2), symbol: ")>", fill: black)
mark((1.3, 0), (2, 0), symbol: ")>", fill: black)
circle((0, 0), radius: 1, stroke: (
paint: black,
thickness: 0.25mm,
dash: "dashed",
))
content((0, 1.3), $p_1$, anchor: "south")
content((1.3, 0), $p_0$, anchor: "west")
circle((0, 1), radius: 0.4mm, fill: oblue, stroke: oblue, name: "00")
content("00.west", $#ket("1")$, anchor: "east")
circle((1, 0), radius: 0.4mm, fill: oblue, stroke: oblue, name: "00")
content("00.south", $#ket("0")$, anchor: "north")
})),
)
#v(1fr)
#v(1fr)
#v(1fr)
#pagebreak()
= Operations on One Qubit
We may apply transformations to qubits just as we apply transformations to probabilistic bits. Again, we'll represent transformations as $2 times 2$ matrices, since we want to map one qubit state to another.
#note[In other words, we want to map elements of $RR^2$ to elements of $RR^2$.]
We will call such maps _quantum gates,_ since they are the quantum equivalent of classical logic gates.
#v(2mm)
There are two conditions a valid quantum gate $G$ must satisfy:
- For any valid state $#ket([$psi$])$, $G #ket([$psi$])$ is a valid state. Namely, $G$ must preserve the length of any vector it is applied to. Recall that the set of valid quantum states is the set of unit vectors in $RR^2$
- Any quantum gate must be _invertible_. We'll skip this condition for now, and return to it later.
In short, a quantum gate is a linear map that maps the unit circle to itself. There are only two kinds of linear maps that do this: reflections and rotations.
#problem()
The $X$ gate is the quantum analog of the `not` gate, defined by the following table:
- $X #ket("0") = #ket("1")$
- $X #ket("1") = #ket("0")$
Find the matrix $X$.
#solution[
$
mat(0, 1; 1, 0)
$
]
#v(1fr)
#problem()
What is $X #ket("+")$ and $X #ket("-")$?
#hint[Remember that all matrices are linear maps. What does this mean?]
#solution[
$X #ket("+") = #ket("+")$ and $X #ket("-") = - #ket("-")$ (that is, a negative ket-minus). \
Most notably, rememver that $G(a#ket("0") + b #ket("1")) = a G #ket("0") + b G #ket("1")$.
]
#v(1fr)
#problem()
In terms of geometric transformations, what does $X$ do to the unit circle?
#solution[
It is a reflection about the $45degree$ axis.
]
#v(1fr)
#pagebreak()
#problem()
Let $Z$ be a quantum gate defined by the following table:
- $Z #ket("0") = #ket("0")$,
- $Z #ket("1") = -#ket("1")$.
What is the matrix $Z$? What are $Z #ket("+")$ and $Z #ket("-")$?
What is $Z$ as a geometric transformation?
#v(1fr)
#problem()
Is the map $B$ defined by the table below a valid quantum gate?
- $B #ket("0") = #ket("0")$
- $B #ket("1") = #ket("+")$
#hint[Find a $#ket([$psi$])$ so that $B #ket([$psi$])$ is not a valid qubit state]
#solution[
$ B #ket("+") = (1 + sqrt(2))/(2) #ket("0") + 1/2 #ket("1") $
This has a non-unit length of
$
(sqrt(2) + 1)/(2)
$
]
#v(1fr)
#problem("Rotation")
As we noted earlier, any rotation about the center is a valid quantum gate. Let's derive all transformations of this form.
- Let $U_theta$ be the matrix that represents a counterclockwise rotation of $theta$ degrees. What is $U #ket("0")$ and $U #ket("1")$?
- Find the matrix $U_theta$ for an arbitrary $theta$.
#v(1fr)
#problem()
Say we have a qubit that is either $#ket("+")$ or $#ket("-")$. We do not know which of the two states it is in.
Using one operation and one measurement, how can we find out, for certain, which qubit we received?
#v(1fr)

View File

@@ -0,0 +1,126 @@
#import "@local/handout:0.1.0": *
// Define quantum notation macros
#let ket(content) = $|#content angle.r$
#let bra(content) = $angle.l #content|$
= Two Qubits
#definition()
Just as before, we'll represent multi-qubit states as linear combinations of multi-qubit basis states.
For example, a two-qubit state $#ket("ab")$ is the four-dimensional unit vector
$ mat(a; b; c; d) = a #ket("00") + b #ket("01") + c #ket("10") + d #ket("11") $
As always, multi-qubit states are unit vectors. Thus, $a^2 + b^2 + c^2 + d^2 = 1$ in the two-bit case above.
#problem()
Say we have two qubits $#ket([$psi$])$ and $#ket([$phi$])$.
Show that $#ket([$psi$]) times.circle #ket([$phi$])$ is always a unit vector (and is thus a valid quantum state).
#v(1fr)
#definition("Measurement II")<measureii>
Measurement of a two-qubit state works just like measurement of a one-qubit state:
If we measure $a #ket("00") + b #ket("01") + c #ket("10") + d #ket("11")$, we get one of the four basis states with the following probabilities:
- $cal(P)(#ket("00")) = a^2$
- $cal(P)(#ket("01")) = b^2$
- $cal(P)(#ket("10")) = c^2$
- $cal(P)(#ket("11")) = d^2$
As before, the sum of all the above probabilities is $1$.
#problem()
Consider the two-qubit state
$#ket([$psi$]) = 1/sqrt(2) #ket("00") + 1/2 #ket("01") + sqrt(3)/4 #ket("10") + 1/4 #ket("11")$
- If we measure both bits of $#ket([$psi$])$ simultaneously, what is the probability of getting each of $#ket("00")$, $#ket("01")$, $#ket("10")$, and $#ket("11")$?
- If we measure the ONLY the first qubit, what is the probability we get $#ket("0")$? How about $#ket("1")$?
#hint[There are two basis states in which the first qubit is $#ket("0")$.]
- Say we measured the second bit and read $#ket("1")$. If we now measure the first bit, what is the probability of getting $#ket("0")$?
#v(1fr)
#pagebreak()
#problem()
Again, consider the two-qubit state
$#ket([$psi$]) = 1/sqrt(2) #ket("00") + 1/2 #ket("01") + sqrt(3)/4 #ket("10") + 1/4 #ket("11")$
If we measure the first qubit of $#ket([$psi$])$ and get $#ket("0")$, what is the resulting state of $#ket([$psi$])$?
What would the state be if we'd measured $#ket("1")$ instead?
#v(1fr)
#problem()
Consider the three-qubit state $#ket([$psi$]) = c_0 #ket("000") + c_1 #ket("001") + ... + c_7 #ket("111")$.
Say we measure the first two qubits and get $#ket("00")$. What is the resulting state of $#ket([$psi$])$?
#solution[
We measure $#ket("00")$ with probability $c_0^2 + c_1^2$, and $#ket(math.psi)$ collapses to
#v(3mm)
$
(c_0 #ket("000") + c_1 #ket("001"))/(sqrt(c_0^2 + c_1^2))
$
]
#v(1fr)
#pagebreak()
#definition("Entanglement")
Some product states can be factored into a tensor product of individual qubit states. For example,
$
1/2 (#ket("00") + #ket("01") + #ket("10") + #ket("11")) = 1/sqrt(2) (#ket("0") + #ket("1")) times.circle 1/sqrt(2) (#ket("0") + #ket("1"))
$
Such states are called _product states._ States that aren't product states are called _entangled_ states.
#problem()
Factor the following product state:
$
1/(2sqrt(2)) (sqrt(3) #ket("00") - sqrt(3) #ket("01") + #ket("10") - #ket("11"))
$
#solution[
$
(1)/(2 sqrt(2)) (sqrt(3) #ket("00") - sqrt(3) #ket("01") + #ket("10") - #ket("11"))
= (sqrt(3)/2 #ket("0") + 1/2 #ket("1") )
times.circle
( 1/sqrt(2) #ket(0) - 1/sqrt(2) #ket("1"))
$
]
#v(1fr)
#problem()
Show that the following is an entangled state.
$ 1/sqrt(2) #ket("00") + 1/sqrt(2) #ket("11") $
#solution[
$
mat(a_0; a_1)
times.circle
mat(b_0; b_1)
=
a_0b_0 #ket(00) + a_0b_1 #ket(01) + a_1b_0 #ket(10) + a_1b_1 #ket(11)
$
#v(2mm)
So, we have that $a_1b_1 = a_0b_0 = sqrt(2)^(-1)$ \
But $a_0b_1 = a_1b_0 = 0$, so one of $a_0$ and $b_1$ must be zero. \
We thus have a contradiction.
]
#v(1fr)

View File

@@ -0,0 +1,169 @@
#import "@local/handout:0.1.0": *
// Define quantum notation macros
#let ket(content) = $|#content angle.r$
#let bra(content) = $angle.l #content|$
= Logic Gates
#definition("Matrices")
Throughout this handout, we've been using matrices. Again, recall that every linear map may be written as a matrix, and that every matrix represents a linear map. For example, if $f: RR^2 -> RR^2$ is a linear map, we can write it as follows:
$
f(#ket("x")) = mat(m_1, m_2; m_3, m_4) mat(x_1; x_2) = mat(m_1 x_1 + m_2 x_2; m_3 x_1 + m_4 x_2)
$
#definition()
Before we discussing multi-qubit quantum gates, we need to review to classical logic.
Of course, a classical logic gate is a linear map from ${0,1}^m$ to ${0,1}^n$
#problem()<notgatex>
The `not` gate is a map defined by the following table:
- $X #ket("0") = #ket("1")$
- $X #ket("1") = #ket("0")$
Write the `not` gate as a matrix that operates on single-bit vector states.
That is, find a matrix $X$ so that $X mat(1; 0) = mat(0; 1)$ and $X mat(0; 1) = mat(1; 0)$
#solution[
$
X = mat(0, 1; 1, 0)
$
]
#v(1fr)
#problem()
The `and` gate is a map $BB^2 -> BB$ defined by the following table:
#align(center, table(
columns: 3,
stroke: none,
table.hline(),
[`a`], [`b`], [`a` and `b`],
table.hline(),
[0], [0], [0],
[0], [1], [0],
[1], [0], [0],
[1], [1], [1],
table.hline(),
))
Find a matrix $A$ so that $A #ket("ab")$ works as expected.
#hint[Remember, we write bits as vectors.]
#solution[
$
A = mat(1, 1, 1, 0; 0, 0, 0, 1)
$
#instructornote[
Because of the way we represent bits here, we also have the following property: \
The columns of $A$ correspond to the output for each input---i.e, $A$ is just a table of outputs. \
#v(2mm)
For example, if we look at the first column of $A$ (which is $[1, 0]$), we see: \
$A#ket(00) = A[1,0,0,0] = [1,0] = #ket(0)$
#v(2mm)
Also with the last column (which is $[0,1]$): \
$A#ket(00) = A[0,0,0,1] = [0,1] = #ket(1)$
]
]
#v(1fr)
#pagebreak()
#remark()
The way a quantum circuit handles information is a bit different than the way a classical circuit does. We usually think of logic gates as _functions_: they consume one set of bits, and return another/
// TODO: and gate (input a, input b, output)
#v(2mm)
This model, however, won't work for quantum logic. If we want to understand quantum gates, we need to see them not as _functions_, but as _transformations_. This distinction is subtle, but significant:
- functions _consume_ a set of inputs and _produce_ a set of outputs
- transformations _change_ a set of objects, without adding or removing any elements
#v(2mm)
Our usual logic circuit notation models logic gates as functions—we thus can't use it. We'll need a different diagram to draw quantum circuits.
#v(1fr)
First, we'll need a set of bits. For this example, we'll use two, drawn in a vertical array. We'll also add a horizontal time axis, moving from left to right:
#align(center)[
// Quantum circuit diagram showing two qubits over time
#box(width: 10cm, height: 4cm)[
_[Quantum circuit diagram with time axis would go here]_
]
]
In the diagram above, we didn't change our bits—so the labels at the start match those at the end.
#v(1fr)
Thus, our circuit forms a grid, with bits ordered vertically and time horizontally. If we want to change our state, we draw transformations as vertical boxes. Every column represents a single transformation on the entire state:
#align(center)[
// Quantum circuit with transformations
#box(width: 10cm, height: 4cm)[
_[Quantum circuit with transformations $T_1$, $T_2$, $T_3$ would go here]_
]
]
Note that the transformations above span the whole state. This is important: we cannot apply transformations to individual bitswe always transform the _entire_ state.
#v(1fr)
#pagebreak()
*Setup:* Say we want to invert the first bit of a two-bit state. That is, we want a transformation $T$ so that
#align(center)[
// Circuit showing bit flip
#box(width: 8cm, height: 3cm)[
_[Circuit diagram showing first bit flip would go here]_
]
]
In other words, we want a matrix $T$ satisfying the following equalities:
- $T #ket("00") = #ket("10")$
- $T #ket("01") = #ket("11")$
- $T #ket("10") = #ket("00")$
- $T #ket("11") = #ket("01")$
#problem()
Find the matrix that corresponds to the above transformation.
#hint[Remember that $#ket("0") = mat(1; 0)$ and $#ket("1") = mat(0; 1)$. Also, we found earlier that $X = mat(0, 1; 1, 0)$, and of course $I = mat(1, 0; 0, 1)$.]
#v(1fr)
*Remark:* We could draw the above transformation as a combination $X$ and $I$ (identity) gate:
#align(center)[
// Circuit with X and I gates
#box(width: 6cm, height: 3cm)[
_[Circuit diagram with X gate on first qubit, I gate on second would go here]_
]
]
We can even omit the $I$ gate, since we now know that transformations affect the whole state:
#align(center)[
// Simplified circuit with just X gate
#box(width: 6cm, height: 3cm)[
_[Simplified circuit diagram with just X gate on first qubit would go here]_
]
]
We're now done: this is how we draw quantum circuits. Don't forget that transformations _always_ affect the whole stateeven if our diagram doesn't explicitly state this.
#pagebreak()

View File

@@ -0,0 +1,42 @@
#import "@local/handout:0.1.0": *
// Define quantum notation macros
#let ket(content) = $|#content angle.r$
#let bra(content) = $angle.l #content|$
= Quantum Gates
In the previous section, we stated that a quantum gate is a linear map. Let's complete that definition.
#definition()
A quantum gate is a _orthonormal matrix_, which means any gate $G$ satisfies $G G^T = I$.
This implies the following:
- $G$ is square. In other words, it has as many rows as it has columns.
#note[If we think of $G$ as a map, this means that $G$ has as many inputs as it has outputs. This is to be expected: we stated earlier that quantum gates do not destroy or create qubits.]
- $G$ preserves lengths; i.e $|x| = |G x|$.
#note[This ensures that $G #ket([$psi$])$ is always a valid state.]
(You will prove all these properties in any introductory linear algebra course. This isn't a lesson on linear algebra, so you may take them as given today.)
*Remark:* Let $G$ be a quantum gate. Since quantum gates are, by definition, _linear_ maps, the following holds:
$ G(a_0 #ket("0") + a_1 #ket("1")) = a_0 G #ket("0") + a_1 G #ket("1") $
#problem()<cnot>
Consider the _controlled not_ (or _cnot_) gate, defined by the following table:
- $X_c #ket("00") = #ket("00")$
- $X_c #ket("01") = #ket("01")$
- $X_c #ket("10") = #ket("11")$
- $X_c #ket("11") = #ket("10")$
In other words, the cnot gate inverts its second bit if its first bit is $#ket("1")$.
Find the matrix that applies the cnot gate.
#v(1fr)
#pagebreak()

View File

@@ -0,0 +1,53 @@
#import "@local/handout:0.1.0": *
// Define quantum notation macros
#let ket(content) = $|#content angle.r$
#let bra(content) = $angle.l #content|$
= HXH
Let's return to the quantum circuit diagrams we discussed a few pages ago. Keep in mind that we're working with quantum gates and proper qubits—not classical bits, as we were before.
#definition("Controlled Inputs")
A _control input_ or _inverted control input_ may be attached to any gate. These are drawn as filled and empty circles in our circuit diagrams:
#align(center)[
#grid(columns: (1fr, 1fr),
[
// Non-inverted control circuit diagram would go here
#box(width: 6cm, height: 4cm)[
_[Non-inverted control input circuit would go here]_
]
],
[
// Inverted control circuit diagram would go here
#box(width: 6cm, height: 4cm)[
_[Inverted control input circuit would go here]_
]
]
)]
#v(2mm)
An $X$ gate with a (non-inverted) control input behaves like an $X$ gate if _all_ its control inputs are $#ket("1")$, and like $I$ otherwise. An $X$ gate with an inverted control inputs does the opposite, behaving like $I$ if its input is $#ket("1")$ and like $X$ otherwise. The two circuits above illustrate this fact—take a look at their inputs and outputs.
#v(2mm)
Of course, we can give a gate multiple controls. An $X$ gate with multiple controls behaves like an $X$ gate if...
- all non-inverted controls are $#ket("1")$, and
- all inverted controls are $#ket("0")$
...and like $I$ otherwise.
#problem()
What are the final states of the qubits in the diagram below?
#align(center)[
// Multi-control circuit diagram would go here
#box(width: 8cm, height: 6cm)[
_[Multi-control circuit diagram would go here]_
]
]
#v(1fr)
#pagebreak()

View File

@@ -0,0 +1,48 @@
#import "@local/handout:0.1.0": *
// Define quantum notation macros
#let ket(content) = $|#content angle.r$
#let bra(content) = $angle.l #content|$
= Superdense Coding
Consider the following entangled two-qubit states, called the _bell states_:
- $#ket([$Phi^+$]) = 1/sqrt(2) #ket("00") + 1/sqrt(2) #ket("11")$
- $#ket([$Phi^-$]) = 1/sqrt(2) #ket("00") - 1/sqrt(2) #ket("11")$
- $#ket([$Psi^+$]) = 1/sqrt(2) #ket("01") + 1/sqrt(2) #ket("10")$
- $#ket([$Psi^-$]) = 1/sqrt(2) #ket("01") - 1/sqrt(2) #ket("10")$
#problem()
The probabilistic bits we get when measuring any of the above may be called _anticorrelated bits_.
If we measure the first bit of any of these states and observe $1$, what is the resulting compound state?
What if we observe $0$ instead?
Do you see why we can call these bits anticorrelated?
#v(1fr)
#problem()
Show that the bell states are orthogonal
#hint[Dot product]
#v(1fr)
#problem()<bellmeasure>
Say we have a pair of qubits in one of the four bell states.
How can we find out which of the four states we have, with certainty?
#hint[$H #ket("+") = #ket("0")$, and $H #ket("-") = #ket("1")$]
#v(1fr)
#pagebreak()
#definition()
The $Z$ gate is defined as follows:
$ Z mat(psi_0; psi_1) = mat(psi_0; -psi_1) $
#v(1fr)
#pagebreak()

View File

@@ -0,0 +1,31 @@
#import "@local/handout:0.1.0": *
// Define quantum notation macros
#let ket(content) = $|#content angle.r$
#let bra(content) = $angle.l #content|$
= Quantum Teleportation
Superdense coding lets us convert quantum bandwidth into classical bandwidth. Quantum teleportation does the opposite, using two classical bits and an entangled pair to transmit a quantum state.
*Setup:* Again, suppose Alice and Bob each have half of a $#ket([$Phi^+$])$ state. We'll call the state Alice wants to teleport $#ket(math.psi) = psi_0 #ket("0") + psi_1 #ket("1")$.
#problem()
What is the three-qubit state $#ket(math.psi) #ket([$Phi^+$])$ in terms of $psi_0$ and $psi_1$?
#v(1fr)
#problem()
To teleport $#ket(math.psi)$, Alice applies the following circuit to her two qubits, where $#ket([$Phi^+_"A"$])$ is her half of $#ket([$Phi^+$])$. She then measures both qubits and sends the result to Bob.
#align(center)[
// Teleportation circuit diagram would go here
#box(width: 8cm, height: 4cm)[
_[Quantum teleportation circuit diagram would go here]_
]
]
What should Bob do so that $#ket([$Phi^+_"B"$])$ takes the state $#ket(math.psi)$ had initially?
#v(1fr)
#pagebreak()

View File

@@ -1,5 +1,5 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
// Shorthand, we'll be using these a lot. // Shorthand, we'll be using these a lot.
@@ -7,15 +7,17 @@
#let tm = sym.times.circle #let tm = sym.times.circle
#let graphgrid(inner_content) = { #let graphgrid(inner_content) = {
align(center, box(inset: 3mm, cetz.canvas({ align(
center,
box(
inset: 3mm,
cetz.canvas({
import cetz.draw: * import cetz.draw: *
let x = 5.25 let x = 5.25
grid( grid(
(0, 0), (0, 0), (x, x), step: 0.75,
(x, x), stroke: luma(100) + 0.3mm
step: 0.75,
stroke: luma(100) + 0.3mm,
) )
if (inner_content != none) { if (inner_content != none) {
@@ -31,7 +33,9 @@
(x + 0.25, 0), (x + 0.25, 0),
stroke: 0.75mm + black, stroke: 0.75mm + black,
) )
}))) }),
),
)
} }
/// Adds extra padding to an equation. /// Adds extra padding to an equation.
@@ -44,16 +48,23 @@
/// Note that there are newlines between the $ and content, /// Note that there are newlines between the $ and content,
/// this gives us display math (which is what we want when using this macro) /// this gives us display math (which is what we want when using this macro)
#let eqnbox(eqn) = { #let eqnbox(eqn) = {
align(center, box( align(
center,
box(
inset: 3mm, inset: 3mm,
eqn, eqn,
)) ),
)
} }
#let dotline(a, b) = { #let dotline(a, b) = {
cetz.draw.line(a, b, stroke: ( cetz.draw.line(
a,
b,
stroke: (
dash: "dashed", dash: "dashed",
thickness: 0.5mm, thickness: 0.5mm,
paint: ored, paint: ored,
)) ),
)
} }

View File

@@ -1,18 +1,21 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "../macros.typ": * #import "../macros.typ": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
= Tropical Polynomials = Tropical Polynomials
#definition() #definition()
A _polynomial_ is an expression formed by adding and multiplying numbers and a variable $x$. \ A _polynomial_ is an expression formed by adding and multiplying numbers and a variable $x$. \
Every polynomial can be written as Every polynomial can be written as
#align(center, box( #align(
center,
box(
inset: 3mm, inset: 3mm,
$ $
c_0 + c_1 x + c_2 x^2 + ... + c_n x^n c_0 + c_1 x + c_2 x^2 + ... + c_n x^n
$, $,
)) ),
)
for some nonnegative integer $n$ and coefficients $c_0, c_1, ..., c_n$. \ for some nonnegative integer $n$ and coefficients $c_0, c_1, ..., c_n$. \
The _degree_ of a polynomial is the largest $n$ for which $c_n$ is nonzero. The _degree_ of a polynomial is the largest $n$ for which $c_n$ is nonzero.
@@ -40,12 +43,15 @@ In this section, we will analyze tropical polynomials:
#definition() #definition()
A _tropical_ polynomial is a polynomial that uses tropical addition and multiplication. \ A _tropical_ polynomial is a polynomial that uses tropical addition and multiplication. \
In other words, it is an expression of the form In other words, it is an expression of the form
#align(center, box( #align(
center,
box(
inset: 3mm, inset: 3mm,
$ $
c_0 #tp (c_1 #tm x) #tp (c_2 #tm x^2) #tp ... #tp (c_n #tm x^n) c_0 #tp (c_1 #tm x) #tp (c_2 #tm x^2) #tp ... #tp (c_n #tm x^n)
$, $,
)) ),
)
where all exponents represent repeated tropical multiplication. where all exponents represent repeated tropical multiplication.
#pagebreak() // MARK: page #pagebreak() // MARK: page
@@ -60,7 +66,7 @@ Draw a graph of the tropical polynomial $f(x) = x^2 #tp 1x #tp 4$. \
#if_no_solutions(graphgrid(none)) #if_no_solutions(graphgrid(none))
#solution([ #solution([
$f(x) = min(2x, 1+x, 4)$, which looks like: $f(x) = min(2x , 1+x, 4)$, which looks like:
#graphgrid({ #graphgrid({
import cetz.draw: * import cetz.draw: *
@@ -84,12 +90,15 @@ Draw a graph of the tropical polynomial $f(x) = x^2 #tp 1x #tp 4$. \
#problem() #problem()
Now, factor $f(x) = x^2 #tp 1x #tp 4$ into two polynomials with degree 1. \ Now, factor $f(x) = x^2 #tp 1x #tp 4$ into two polynomials with degree 1. \
In other words, find $r$ and $s$ so that In other words, find $r$ and $s$ so that
#align(center, box( #align(
center,
box(
inset: 3mm, inset: 3mm,
$ $
x^2 #tp 1x #tp 4 = (x #tp r)(x #tp s) x^2 #tp 1x #tp 4 = (x #tp r)(x #tp s)
$, $,
)) ),
)
we will call $r$ and $s$ the _roots_ of $f$. we will call $r$ and $s$ the _roots_ of $f$.
@@ -150,19 +159,15 @@ Find a factorization of $f$ in the form $a(x #tp r)(x#tp s)$.
#solution([ #solution([
We (tropically) factor out $-2$ to get We (tropically) factor out $-2$ to get
#eqnbox( #eqnbox($
$
f(x) = -2(x^2 #tp 2x #tp 10) f(x) = -2(x^2 #tp 2x #tp 10)
$, $)
)
by the same process as the previous problem, we get by the same process as the previous problem, we get
#eqnbox( #eqnbox($
$
f(x) = -2(x #tp 2)(x #tp 8) f(x) = -2(x #tp 2)(x #tp 8)
$, $)
)
]) ])
#v(1fr) #v(1fr)
@@ -231,11 +236,11 @@ Graph $f(x) = 1x^2 #tp 3x #tp 5$.
#problem() #problem()
Find a factorization of $f$ in the form $a(x #tp r)(x#tp s)$. Find a factorization of $f$ in the form $a(x #tp r)(x#tp s)$.
#solution(eqnbox( #solution(
$ eqnbox($
f(x) = 1x^2 #tp 3 x #tp 5 = 1(x #tp 2)^2 f(x) = 1x^2 #tp 3 x #tp 5 = 1(x #tp 2)^2
$, $),
)) )
#v(1fr) #v(1fr)
@@ -258,7 +263,8 @@ Graph $f(x) = 2x^2 #tp 4x #tp 4$.
#if_no_solutions(graphgrid(none)) #if_no_solutions(graphgrid(none))
#solution(graphgrid({ #solution(
graphgrid({
import cetz.draw: * import cetz.draw: *
let step = 0.75 let step = 0.75
@@ -272,7 +278,8 @@ Graph $f(x) = 2x^2 #tp 4x #tp 4$.
(7.5 * step, 4 * step), (7.5 * step, 4 * step),
stroke: 1mm + oblue, stroke: 1mm + oblue,
) )
})) }),
)
#problem() #problem()
@@ -318,7 +325,7 @@ Find a formula for $B$ in terms of $a$, $b$, and $c$. \
#solution([ #solution([
If we want to factor $a(x^2 #tp (b-a)x #tp (c-a))$, we need to find $r$ and $s$ so that If we want to factor $a(x^2 #tp (b-a)x #tp (c-a))$, we need to find $r$ and $s$ so that
- $min(r, s) = b-a$, and - $min(r,s) = b-a$, and
- $r + s = c - a$ - $r + s = c - a$
#v(2mm) #v(2mm)
@@ -334,8 +341,9 @@ Find a formula for $B$ in terms of $a$, $b$, and $c$. \
*Case 2:* If $b > (a + c #sym.div) 2$, then *Case 2:* If $b > (a + c #sym.div) 2$, then
$ $
accent(f, macron)(x) & = a x^2 #tp ((a+c)/2)x #tp c \ accent(f, macron)(x)
& = a(x #tp (c-a)/2)^2 &= a x^2 #tp ((a+c)/2)x #tp c \
&= a(x #tp (c-a)/2)^2
$ $
has the same graph as $f$, and thus $B = (a+c) #sym.div 2$ has the same graph as $f$, and thus $B = (a+c) #sym.div 2$

View File

@@ -1,6 +1,6 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "../macros.typ": * #import "../macros.typ": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
= Tropical Cubic Polynomials = Tropical Cubic Polynomials
@@ -131,12 +131,15 @@ Using the last three problems, find formulas for $B$ and $C$ in terms of $a$, $b
#problem() #problem()
What are the roots of the following polynomial? What are the roots of the following polynomial?
#align(center, box( #align(
center,
box(
inset: 3mm, inset: 3mm,
$ $
3 x^6 #tp 4 x^5 #tp 2 x^4 #tp x^3 #tp x^2 #tp 4 x #tp 5 3 x^6 #tp 4 x^5 #tp 2 x^4 #tp x^3 #tp x^2 #tp 4 x #tp 5
$, $,
)) ),
)
#solution([ #solution([
We have We have
@@ -166,8 +169,9 @@ Find a formula for each $C_i$ in terms of $c_0, c_1, ..., c_n$.
#solution([ #solution([
$ $
A_j & = min_(l<=j<k)( (a_l - a_k) / (k-l) (k-j) + a_k ) \ A_j
& = min_(l<=j<k)( a_l (k-j) / (k-l) + a_k (j-l) / (k-l) ) &= min_(l<=j<k)( (a_l - a_k) / (k-l) (k-j) + a_k ) \
&= min_(l<=j<k)( a_l (k-j) / (k-l) + a_k (j-l) / (k-l) )
$ $
#v(2mm) #v(2mm)

View File

@@ -1,5 +1,5 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
= Wallpaper Symmetries = Wallpaper Symmetries

View File

@@ -1,5 +1,5 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
= Mirror Symmetry = Mirror Symmetry

View File

@@ -1,5 +1,5 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
= Rotational Symmetry = Rotational Symmetry

View File

@@ -1,5 +1,5 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
#let pat(img, sol) = { #let pat(img, sol) = {
problem() problem()

View File

@@ -1,5 +1,5 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
= The Signature-Cost Theorem = The Signature-Cost Theorem
@@ -7,7 +7,9 @@
First, we'll associate a _cost_ to each type of symmetry in orbifold notation: First, we'll associate a _cost_ to each type of symmetry in orbifold notation:
#v(4mm) #v(4mm)
#align(center, table( #align(
center,
table(
stroke: (1pt, 1pt), stroke: (1pt, 1pt),
align: center, align: center,
columns: (auto, auto, auto, auto), columns: (auto, auto, auto, auto),
@@ -20,7 +22,8 @@ First, we'll associate a _cost_ to each type of symmetry in orbifold notation:
[$(n-1) / n$], [$(n-1) / n$],
[#sym.convolve`n`], [#sym.convolve`n`],
[$(n-1) / (2n)$], [$(n-1) / (2n)$],
)) ),
)
We then calculate the total "cost" of a signature by adding up the costs of each component. We then calculate the total "cost" of a signature by adding up the costs of each component.

View File

@@ -1,5 +1,5 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
#show: handout.with( #show: handout.with(
title: [Warm-Up: Big-Tac-Toe], title: [Warm-Up: Big-Tac-Toe],
@@ -75,7 +75,9 @@ How does your strategy change? \
#if extra_boards { #if extra_boards {
pagebreak() pagebreak()
align(center, grid( align(
center,
grid(
stroke: none, stroke: none,
align: center, align: center,
columns: (1fr, 1fr), columns: (1fr, 1fr),
@@ -83,5 +85,6 @@ How does your strategy change? \
btt(0.35), btt(0.35), btt(0.35), btt(0.35),
btt(0.35), btt(0.35), btt(0.35), btt(0.35),
btt(0.35), btt(0.35), btt(0.35), btt(0.35),
)) ),
)
} }

View File

@@ -1,5 +1,5 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
#show: handout.with( #show: handout.with(
@@ -43,7 +43,10 @@ Now, consider the set of six-sided dice below:
- Die $E$: $0, 5, 5, 5, 5, 5$ - Die $E$: $0, 5, 5, 5, 5, 5$
On average, which die beats each of the others? Draw a diagram. On average, which die beats each of the others? Draw a diagram.
#solution(align(center, cetz.canvas({ #solution(
align(
center,
cetz.canvas({
import cetz.draw: * import cetz.draw: *
let s = 0.8 // Scale let s = 0.8 // Scale
@@ -92,7 +95,9 @@ On average, which die beats each of the others? Draw a diagram.
content(c, text(fill: white, size: t, [*C*])) content(c, text(fill: white, size: t, [*C*]))
content(d, text(fill: white, size: t, [*D*])) content(d, text(fill: white, size: t, [*D*]))
content(e, text(fill: white, size: t, [*E*])) content(e, text(fill: white, size: t, [*E*]))
}))) }),
),
)
#v(1fr) #v(1fr)

View File

@@ -1,5 +1,5 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
#show: handout.with( #show: handout.with(
title: [Warm-Up: What's an AST?], title: [Warm-Up: What's an AST?],
@@ -18,7 +18,9 @@ You may detach the string as you hang the painting, but it must be re-attached o
#v(2mm) #v(2mm)
#align(center, cetz.canvas({ #align(
center,
cetz.canvas({
import cetz.draw: * import cetz.draw: *
let s = 2.5 let s = 2.5
@@ -67,7 +69,8 @@ You may detach the string as you hang the painting, but it must be re-attached o
) )
circle((0.66 * s, 0.66 * s), radius: 0.07 * s, fill: white) circle((0.66 * s, 0.66 * s), radius: 0.07 * s, fill: white)
})) }),
)
#solution([ #solution([
Say we have a left nail and a right nail. The path of the string is as follows: Say we have a left nail and a right nail. The path of the string is as follows:

View File

@@ -1,5 +1,5 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
#show: handout.with( #show: handout.with(
title: [Warm-Up: Passing Balls], title: [Warm-Up: Passing Balls],
@@ -78,7 +78,10 @@ Participant 1 has a black ball. Which balls are held by participants 2, 3, and 4
let i = 1 let i = 1
for p in pts { for p in pts {
circle(p, radius: radius * s, fill: if i == 1 { circle(
p,
radius: radius * s,
fill: if i == 1 {
ored ored
} else if i == 2 { } else if i == 2 {
ogreen ogreen
@@ -86,9 +89,12 @@ Participant 1 has a black ball. Which balls are held by participants 2, 3, and 4
oorange oorange
} else if i == 4 { } else if i == 4 {
oblue oblue
} else { white }) } else { white },
)
content(p, text( content(
p,
text(
fill: if i <= 4 { fill: if i <= 4 {
white white
} else { } else {
@@ -96,7 +102,8 @@ Participant 1 has a black ball. Which balls are held by participants 2, 3, and 4
}, },
size: t, size: t,
[*#i*], [*#i*],
)) ),
)
i = i + 1 i = i + 1
} }
}), }),
@@ -111,7 +118,10 @@ Participant 1 has a black ball. Which balls are held by participants 2, 3, and 4
let l = calc.rem(((i - 1) * 5), 12) + 1 let l = calc.rem(((i - 1) * 5), 12) + 1
circle(p, radius: radius * s, fill: if l == 1 { circle(
p,
radius: radius * s,
fill: if l == 1 {
ored ored
} else if l == 2 { } else if l == 2 {
ogreen ogreen
@@ -119,9 +129,12 @@ Participant 1 has a black ball. Which balls are held by participants 2, 3, and 4
oorange oorange
} else if l == 4 { } else if l == 4 {
oblue oblue
} else { white }) } else { white },
)
content(p, text( content(
p,
text(
fill: if l <= 4 { fill: if l <= 4 {
white white
} else { } else {
@@ -129,7 +142,8 @@ Participant 1 has a black ball. Which balls are held by participants 2, 3, and 4
}, },
size: t, size: t,
[*#l*], [*#l*],
)) ),
)
i = i + 1 i = i + 1
} }
}), }),
@@ -144,7 +158,10 @@ Participant 1 has a black ball. Which balls are held by participants 2, 3, and 4
let l = calc.rem(((i - 1) * 5), 12) + 1 let l = calc.rem(((i - 1) * 5), 12) + 1
circle(p, radius: radius * s, fill: if l == 1 { circle(
p,
radius: radius * s,
fill: if l == 1 {
oblue oblue
} else if l == 2 { } else if l == 2 {
oorange oorange
@@ -152,9 +169,12 @@ Participant 1 has a black ball. Which balls are held by participants 2, 3, and 4
ored ored
} else if l == 4 { } else if l == 4 {
ogreen ogreen
} else { white }) } else { white },
)
content(p, text( content(
p,
text(
fill: if l <= 4 { fill: if l <= 4 {
white white
} else { } else {
@@ -162,7 +182,8 @@ Participant 1 has a black ball. Which balls are held by participants 2, 3, and 4
}, },
size: t, size: t,
[*#l*], [*#l*],
)) ),
)
i = i + 1 i = i + 1
} }
}), }),

View File

@@ -1,5 +1,5 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
#show: handout.with( #show: handout.with(
title: [Warm-Up: What's an AST?], title: [Warm-Up: What's an AST?],
@@ -24,7 +24,9 @@ respecting the order of operations $[and, times, div, +, -]$.
#v(2mm) #v(2mm)
#align(center, cetz.canvas({ #align(
center,
cetz.canvas({
import cetz.draw: * import cetz.draw: *
// spell:off // spell:off
@@ -68,4 +70,5 @@ respecting the order of operations $[and, times, div, +, -]$.
line("bb", "bba") line("bb", "bba")
line("bb", "bbb") line("bb", "bbb")
// spell:on // spell:on
})) }),
)

View File

@@ -1,12 +1,14 @@
#import "@local/handout:0.1.0": * #import "@local/handout:0.1.0": *
#import "@preview/cetz:0.4.2" #import "@preview/cetz:0.3.1"
#show: handout.with( #show: handout.with(
title: [Warm-Up: Wild Tic-Tac-Toe], title: [Warm-Up: Wild Tic-Tac-Toe],
by: "Mark", by: "Mark",
) )
#let ttt = align(center, cetz.canvas({ #let ttt = align(
center,
cetz.canvas({
import cetz.draw: * import cetz.draw: *
let s = 0.7 // scale let s = 0.7 // scale
@@ -15,7 +17,8 @@
line((1 * s, 3 * s), (1 * s, -3 * s)) line((1 * s, 3 * s), (1 * s, -3 * s))
line((3 * s, -1 * s), (-3 * s, -1 * s)) line((3 * s, -1 * s), (-3 * s, -1 * s))
line((3 * s, 1 * s), (-3 * s, 1 * s)) line((3 * s, 1 * s), (-3 * s, 1 * s))
})) }),
)
#problem() #problem()