Skip to content
Merged
91 changes: 91 additions & 0 deletions .claude/rules/typst-drawing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
description: Use when editing Typst files — covers general patterns, CeTZ drawing, plotting, and utility functions
globs: ["*.typ"]
---

# Typst Editing Reference

Reference files: ~/Documents/private-note/notes/typst-learn/ (typst-tricks.typ, typst-drawing.typ, typst-my-utils.typ)

## General Typst Patterns

### Page Setup
- Standalone figures: `#set page(width: auto, height: auto, margin: 5pt)`
- Standard notes: `#set page(margin: 2cm)` + `#set text(size: 10pt)` + `#set heading(numbering: "1.1.")`
- Numbered equations: `#set math.equation(numbering: "(1)")`

### Common Packages
- CeTZ: `@preview/cetz:0.4.0`, `@preview/cetz-plot:0.1.2`
- Algorithms: `@preview/algorithmic:1.0.3` — `Function`, `For`, `While`, `If`, `ElseIf`, `Else`, `Assign`, `Return`, `Comment`
- Math: `@preview/physica:0.9.3` (physics notation), `@preview/ouset:0.2.0` (over/under sets)
- Theorems: `@preview/ctheorems:1.1.2` or `@preview/unequivocal-ams:0.1.2`
- Random: `@preview/suiji:0.3.0` — `gen-rng(seed)`, `uniform(rng, size: n)`, `shuffle(rng, arr)`

### Math Notation
- Bra-ket: `$|psi chevron.r$`, `$chevron.l phi|$`
- Blackboard bold: `$bb(I)$`, calligraphic: `$cal(E)$`
- Accents: `$hat(N)$`, `$tilde(H)$`, `$overline(X)$`
- Cases: `$ f(x) = cases(x^2 &"if" x > 0, 0 &"otherwise") $`
- Matrices with ellipses: `$mat(a, dots; dots.v, dots.down;)$`

### Citations
- Inline: `@Author2024`, with locator: `@Author2024[Ch. 4]`
- Prose: `#cite(<Author2024>, form: "prose")`
- Compact slides style: `#set cite(style: "author-journal-year.csl")`

### Functional Idioms
- `range(n).map(_ => 0)` — zeros array
- `a.zip(b).map(((x, y)) => ...)` — pairwise ops
- `for (k, (i, j)) in pts.enumerate() { ... }` — destructuring enumerate
- `dict.at(key, default: 0)` — dict with default

### Content Helpers
- Infobox: `rect(stroke: color, inset: 8pt, radius: 4pt, width: 100%, [*Title:*\ body])`
- Inline image alignment: `box(image(...), baseline: (size - 20pt) / 2 + offset)`
- Image clipping: `box(clip: true, img, inset: (top: -top, bottom: -bottom, ...))`
- Two columns: `grid(columns: (1fr, 1fr), gutter: 20pt, left, right)`

## CeTZ Drawing

### Core Rules
1. **Name all objects** that will be referenced later: `circle(..., name: "c")`, `line(..., name: "edge")`
2. **Connect objects by name + anchor**, never by raw coordinates: `line("a.east", "b.west")`, not `line((2, 0), (5, 0))`
3. **Use `set-origin`** for sub-figures instead of manual coordinate offsets
4. **Use `on-layer`** for layering: -1 for backgrounds, 0 for main content, 1 for labels
5. **Use `content()` with `frame: "rect"`** for labeled boxes; use `fill: white, stroke: none` for edge labels
6. **Inside CeTZ functions**, always `import draw: *` for unqualified access

### Gotchas
- **`arc`**: first parameter is the **start point** of the arc, not the center of the circle
- **`bezier`**: first two args are **start and end points**; remaining args are control points
- **Arrows**: prefer `mark: (end: "straight")` style — do NOT use `">"`
- **Stroke dict**: use `(paint: color, thickness: 1pt, dash: "dashed")` — NOT `stroke(...)` constructor

### Quick Reference
- Shapes: `circle`, `rect`, `line`, `arc`, `bezier`, `hobby`, `catmull`, `merge-path`, `grid`
- Anchors: `"name.north"`, `.south`, `.east`, `.west`, `.center`, `.start`, `.mid`, `.end`
- Coordinates: `(x, y)`, `(rel: (dx, dy), to: "name")`, `("a", 50%, "b")`, `("a", "|-", "b")`
- Marks (arrows): `"straight"`, `">"`, `"stealth"`, `"|"`, `"o"`, `"<>"`, `"hook"`, `"]"`
- Strokes: `(dash: "dashed")`, `(dash: "dotted")`, `(dash: "dash-dotted")`, `2pt + red`
- Colors: `blue.lighten(60%)`, `green.darken(20%)`, `rgb("#f0f0fe")`
- Decorations: `decorations.brace`, `.flat-brace`, `.zigzag`, `.wave`, `.coil`
- Trees: `tree.tree((...), direction: "down", grow: 1.5, spread: 1.8)`

### Drawing Patterns
- **Graph rendering**: name vertices as `str(k)`, connect with `line(str(k), str(l))`
- **Circular layout**: use `vrotate(v, theta)` helper to place vertices on a circle
- **Edge labels**: `content("edge.mid", label, fill: white, frame: "rect", padding: 0.08, stroke: none)`
- **Data-driven diagrams**: store layout as list of tuples, iterate with `for` loops
- **Tensor networks**: `tensor` (circle + label), `deltatensor` (small filled dot), `labeledge` (line + midpoint label)
- **Intersections**: `intersections("ix", { ...shapes... })` then reference `"ix.0"`, `"ix.1"`

## CeTZ Plotting
- `plot.plot(size: (w, h), axis-style: "scientific", x-tick-step: 1, y-tick-step: 2, { ... })`
- Line: `plot.add(domain: (a, b), x => f(x), label: $f$, style: (stroke: blue))`
- Data: `plot.add(data, mark: "o", line: "spline")` — line types: `"linear"`, `"spline"`, `"vh"`, `"hv"`
- Scatter marks: `"*"`, `"o"`, `"square"`, `"triangle"`, `"+"`, `"|"`, `"-"`, `"<>"`
- Fill between: `plot.add-fill-between(f, g, domain: (a, b))`
- Reference lines: `plot.add-hline(y)`, `plot.add-vline(x)`
- Annotations: `plot.add-anchor("name", (x, y))`, `plot.annotate({ ... })`
- Bar chart: `chart.barchart(data, size: ..., mode: "clustered", labels: (...))`
- Pie chart: `chart.piechart(data, inner-radius: 0.5, outer-label: (content: auto, radius: 130%))`
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ cli:
GRAPHS := diamond bull house petersen
MODES := unweighted weighted triangular
rust-export:
@mkdir -p tests/julia
@for graph in $(GRAPHS); do \
for mode in $(MODES); do \
echo "Exporting $$graph ($$mode)..."; \
Expand Down
44 changes: 44 additions & 0 deletions docs/paper/reductions.typ
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"PaintShop": [Paint Shop],
"BicliqueCover": [Biclique Cover],
"BinPacking": [Bin Packing],
"ClosestVectorProblem": [Closest Vector Problem],
)

// Definition label: "def:<ProblemName>" — each definition block must have a matching label
Expand Down Expand Up @@ -637,6 +638,49 @@ Integer Linear Programming is a universal modeling framework: virtually every NP
) <fig:ilp-example>
]

#problem-def("ClosestVectorProblem")[
Given a lattice basis $bold(B) in RR^(m times n)$ (columns $bold(b)_1, dots, bold(b)_n in RR^m$ spanning lattice $cal(L)(bold(B)) = {bold(B) bold(x) : bold(x) in ZZ^n}$) and target $bold(t) in RR^m$, find $bold(x) in ZZ^n$ minimizing $norm(bold(B) bold(x) - bold(t))_2$.
][
The Closest Vector Problem is a fundamental lattice problem, proven NP-hard by van Emde Boas @vanemde1981. CVP appears in lattice-based cryptography, coding theory, and integer programming @lenstra1983. Kannan's enumeration algorithm @kannan1987 solves CVP in $n^(O(n))$ time; Micciancio and Voulgaris @micciancio2010 improved this to deterministic $O^*(4^n)$ using Voronoi cell computations, and Aggarwal, Dadush, and Stephens-Davidowitz @aggarwal2015 achieved randomized $O^*(2^n)$.

*Example.* Consider the 2D lattice with basis $bold(b)_1 = (2, 0)^top$, $bold(b)_2 = (1, 2)^top$ and target $bold(t) = (2.8, 1.5)^top$. The lattice points near $bold(t)$ include $bold(B)(1, 0)^top = (2, 0)^top$, $bold(B)(0, 1)^top = (1, 2)^top$, and $bold(B)(1, 1)^top = (3, 2)^top$. The closest is $bold(B)(1, 1)^top = (3, 2)^top$ with distance $norm(bold(B)(1,1)^top - bold(t))_2 = norm((0.2, 0.5))_2 = sqrt(0.04 + 0.25) approx 0.539$.

#figure(
canvas(length: 0.8cm, {
import draw: *
// Lattice points: B*(x1,x2) = x1*(2,0) + x2*(1,2)
for x1 in range(0, 3) {
for x2 in range(0, 3) {
let px = x1 * 2 + x2 * 1
let py = x2 * 2
let is-closest = (x1 == 1 and x2 == 1)
let nm = "p" + str(x1) + str(x2)
circle(
(px, py),
radius: if is-closest { 0.15 } else { 0.08 },
fill: if is-closest { graph-colors.at(0) } else { luma(180) },
stroke: if is-closest { 0.8pt + graph-colors.at(0) } else { 0.4pt + luma(120) },
name: nm,
)
}
}
// Target vector
circle((2.8, 1.5), radius: 0.1, fill: graph-colors.at(1), stroke: none, name: "target")
content((rel: (0, -0.45), to: "target"), text(7pt)[$bold(t)$])
// Dashed line from target to closest point
line("target", "p11", stroke: (paint: graph-colors.at(0), thickness: 0.8pt, dash: "dashed"))
// Basis vectors as arrows from origin
line("p00", "p10", mark: (end: "straight"), stroke: 0.8pt + luma(100), name: "b1")
content((rel: (0, -0.35), to: "b1.mid"), text(7pt)[$bold(b)_1$])
line("p00", "p01", mark: (end: "straight"), stroke: 0.8pt + luma(100), name: "b2")
content((rel: (-0.3, 0), to: "b2.mid"), text(7pt)[$bold(b)_2$])
// Label closest point
content((rel: (0.45, 0.3), to: "p11"), text(7pt)[$bold(B)(1,1)^top$])
}),
caption: [2D lattice with basis $bold(b)_1 = (2, 0)^top$, $bold(b)_2 = (1, 2)^top$. Target $bold(t) = (2.8, 1.5)^top$ (red) and closest lattice point $bold(B)(1,1)^top = (3, 2)^top$ (blue). Distance $norm(bold(B)(1,1)^top - bold(t))_2 approx 0.539$.],
) <fig:cvp-example>
]

== Satisfiability Problems

#problem-def("Satisfiability")[
Expand Down
37 changes: 37 additions & 0 deletions docs/paper/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,43 @@ @article{epping2004
doi = {10.1016/S0166-218X(03)00442-6}
}

@techreport{vanemde1981,
author = {Peter van Emde Boas},
title = {Another NP-complete Problem and the Complexity of Computing Short Vectors in a Lattice},
institution = {Mathematisch Instituut, Universiteit van Amsterdam},
number = {81-04},
year = {1981}
}

@article{kannan1987,
author = {Ravi Kannan},
title = {Minkowski's Convex Body Theorem and Integer Programming},
journal = {Mathematics of Operations Research},
volume = {12},
number = {3},
pages = {415--440},
year = {1987},
doi = {10.1287/moor.12.3.415}
}

@inproceedings{micciancio2010,
author = {Daniele Micciancio and Panagiotis Voulgaris},
title = {A Deterministic Single Exponential Time Algorithm for Most Lattice Problems Based on {V}oronoi Cell Computations},
booktitle = {Proceedings of the 42nd ACM Symposium on Theory of Computing (STOC)},
pages = {351--358},
year = {2010},
doi = {10.1145/1806689.1806739}
}

@inproceedings{aggarwal2015,
author = {Divesh Aggarwal and Daniel Dadush and Noah Stephens-Davidowitz},
title = {Solving the Closest Vector Problem in $2^n$ Time -- The Discrete {G}aussian Strikes Again!},
booktitle = {Proceedings of the 56th IEEE Symposium on Foundations of Computer Science (FOCS)},
pages = {563--580},
year = {2015},
doi = {10.1109/FOCS.2015.41}
}

@article{shannon1956,
author = {Claude E. Shannon},
title = {The zero error capacity of a noisy channel},
Expand Down
21 changes: 21 additions & 0 deletions docs/src/reductions/problem_schemas.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,27 @@
}
]
},
{
"name": "ClosestVectorProblem",
"description": "Find the closest lattice point to a target vector",
"fields": [
{
"name": "basis",
"type_name": "Vec<Vec<T>>",
"description": "Basis matrix B as column vectors"
},
{
"name": "target",
"type_name": "Vec<f64>",
"description": "Target vector t"
},
{
"name": "bounds",
"type_name": "Vec<VarBounds>",
"description": "Integer bounds per variable"
}
]
},
{
"name": "Factoring",
"description": "Factor a composite integer into two factors",
Expand Down
Loading