Pick a depth. Each prompt opens in your AI pre-loaded with the lesson. Click a row to preview the prompt.
A quantum gate is a unitary matrix — a complex matrix with — that acts on the state vector by ordinary matrix multiplication. That single sentence is the entire kinematic content of gate-based quantum computing. The reason this matters for cryptography is that every attack a quantum adversary mounts is a circuit of unitaries on inputs you control; Shor's algorithm is one specific such circuit, and Grover's is another. Understanding which transformations are unitary (and which are not — like cloning or measurement) tells you what an adversary can and cannot do. The Hadamard gate creates uniform superposition (the input layer of almost every quantum algorithm), the Pauli gates implement bit-flips and phase-flips (the algebra of single-qubit errors), and CNOT is the canonical entangling gate (the only place 'quantum-ness' really differs from 'classical probabilistic').
The Hadamard gate , the three Pauli gates , and the two-qubit CNOT gate are the workhorses. maps and ; is a bit-flip (); is a phase-flip (); CNOT flips its target qubit when its control qubit is .
np.kron(ket1, ket0). Apply CNOT and verify the output is . Now apply CNOT to — it should be unchanged.// main.go
// run: go run main.go
package main
import (
"fmt"
"math"
"math/cmplx"
)
type Matrix [][]complex128
func matMul(a, b Matrix) Matrix {
n := len(a)
m := len(b[0])
p := len(b)
c := make(Matrix, n)
for i := range c {
c[i] = make([]complex128, m)
for j := 0; j < m; j++ {
for k := 0; k < p; k++ {
c[i][j] += a[i][k] * b[k][j]
}
}
}
return c
}
func conjT(a Matrix) Matrix {
n := len(a)
m := len(a[0])
b := make(Matrix, m)
for i := range b {
b[i] = make([]complex128, n)
for j := 0; j < n; j++ {
b[i][j] = cmplx.Conj(a[j][i])
}
}
return b
}
func eye(n int) Matrix {
e := make(Matrix, n)
for i := range e {
e[i] = make([]complex128, n)
e[i][i] = 1
}
return e
}
func normFro(a Matrix) float64 {
var s float64
for _, row := range a {
for _, v := range row {
s += real(v*cmplx.Conj(v))
}
}
return math.Sqrt(s)
}
func matvec(m Matrix, v []complex128) []complex128 {
n := len(m)
out := make([]complex128, n)
for i := 0; i < n; i++ {
for j, x := range v {
out[i] += m[i][j] * x
}
}
return out
}
func subMat(a, b Matrix) Matrix {
n := len(a)
c := make(Matrix, n)
for i := range a {
c[i] = make([]complex128, len(a[i]))
for j := range a[i] {
c[i][j] = a[i][j] - b[i][j]
}
}
return c
}
func main() {
s := 1 / math.Sqrt(2)
H := Matrix{
{complex(s, 0), complex(s, 0)},
{complex(s, 0), complex(-s, 0)},
}
X := Matrix{{0, 1}, {1, 0}}
Y := Matrix{{0, -1i}, {1i, 0}}
Z := Matrix{{1, 0}, {0, -1}}
CNOT := Matrix{
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 0, 1},
{0, 0, 1, 0},
}
ket0 := []complex128{1, 0}
// Apply H to |0>
plus := matvec(H, ket0)
var norm float64
for _, v := range plus {
norm += real(v * cmplx.Conj(v))
}
fmt.Printf("H|0> = %v norm = %.6f\n", plus, norm)
// Verify unitarity: U^dagger U = I
gates := []struct {
name string
u Matrix
}{
{"H", H}, {"X", X}, {"Y", Y}, {"Z", Z}, {"CNOT", CNOT},
}
for _, g := range gates {
product := matMul(conjT(g.u), g.u)
err := normFro(subMat(product, eye(len(g.u))))
fmt.Printf("%-4s ||U^dagger U - I|| = %.2e\n", g.name, err)
}
}go run main.go