Skip to content

Commit 3e7d07c

Browse files
GiggleLiuclaude
andauthored
Fix #90: Add ClosestVectorProblem model (#92)
* Add plan for #90: ClosestVectorProblem model Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update CVP plan for refactored variant system and Copilot review Changes from original plan: - Remove problem_size_names/values (removed from Problem trait) - Add declare_variants! with complexity metadata for i32/f64 variants - Add VariantParam trait bound on T parameter - Use variant_params![T] instead of variant_params![] - CLI dispatch supports both i32 and f64 via variant map (SpinGlass pattern) - Remove redundant VarBounds import in tests (super::* suffices) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add ClosestVectorProblem model (#90) Add CVP as a new optimization model parameterized by element type T (i32/f64). Implements Problem and OptimizationProblem traits, registers in CLI dispatch with "CVP" alias, and adds problem definition to paper. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove completed CVP implementation plan Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: improve CVP paper entry and add missing citations - Fix factual errors: Kannan runs in n^O(n) (not n^n), Micciancio-Voulgaris is deterministic O*(4^n) Voronoi cell (not randomized sieve O*(2^n)) - Add Aggarwal-Dadush-Stephens-Davidowitz 2015 citation for the O*(2^n) bound - Add BibTeX entries: vanemde1981, kannan1987, micciancio2010, aggarwal2015 - Add lattice visualization figure with basis vectors, target, and closest point - Add evaluation walkthrough showing distance computation - Fix Makefile: mkdir -p tests/julia before rust-export - Regenerate problem_schemas.json and reduction_graph.json Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent e4130e9 commit 3e7d07c

12 files changed

Lines changed: 699 additions & 114 deletions

File tree

.claude/rules/typst-drawing.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
description: Use when editing Typst files — covers general patterns, CeTZ drawing, plotting, and utility functions
3+
globs: ["*.typ"]
4+
---
5+
6+
# Typst Editing Reference
7+
8+
Reference files: ~/Documents/private-note/notes/typst-learn/ (typst-tricks.typ, typst-drawing.typ, typst-my-utils.typ)
9+
10+
## General Typst Patterns
11+
12+
### Page Setup
13+
- Standalone figures: `#set page(width: auto, height: auto, margin: 5pt)`
14+
- Standard notes: `#set page(margin: 2cm)` + `#set text(size: 10pt)` + `#set heading(numbering: "1.1.")`
15+
- Numbered equations: `#set math.equation(numbering: "(1)")`
16+
17+
### Common Packages
18+
- CeTZ: `@preview/cetz:0.4.0`, `@preview/cetz-plot:0.1.2`
19+
- Algorithms: `@preview/algorithmic:1.0.3``Function`, `For`, `While`, `If`, `ElseIf`, `Else`, `Assign`, `Return`, `Comment`
20+
- Math: `@preview/physica:0.9.3` (physics notation), `@preview/ouset:0.2.0` (over/under sets)
21+
- Theorems: `@preview/ctheorems:1.1.2` or `@preview/unequivocal-ams:0.1.2`
22+
- Random: `@preview/suiji:0.3.0``gen-rng(seed)`, `uniform(rng, size: n)`, `shuffle(rng, arr)`
23+
24+
### Math Notation
25+
- Bra-ket: `$|psi chevron.r$`, `$chevron.l phi|$`
26+
- Blackboard bold: `$bb(I)$`, calligraphic: `$cal(E)$`
27+
- Accents: `$hat(N)$`, `$tilde(H)$`, `$overline(X)$`
28+
- Cases: `$ f(x) = cases(x^2 &"if" x > 0, 0 &"otherwise") $`
29+
- Matrices with ellipses: `$mat(a, dots; dots.v, dots.down;)$`
30+
31+
### Citations
32+
- Inline: `@Author2024`, with locator: `@Author2024[Ch. 4]`
33+
- Prose: `#cite(<Author2024>, form: "prose")`
34+
- Compact slides style: `#set cite(style: "author-journal-year.csl")`
35+
36+
### Functional Idioms
37+
- `range(n).map(_ => 0)` — zeros array
38+
- `a.zip(b).map(((x, y)) => ...)` — pairwise ops
39+
- `for (k, (i, j)) in pts.enumerate() { ... }` — destructuring enumerate
40+
- `dict.at(key, default: 0)` — dict with default
41+
42+
### Content Helpers
43+
- Infobox: `rect(stroke: color, inset: 8pt, radius: 4pt, width: 100%, [*Title:*\ body])`
44+
- Inline image alignment: `box(image(...), baseline: (size - 20pt) / 2 + offset)`
45+
- Image clipping: `box(clip: true, img, inset: (top: -top, bottom: -bottom, ...))`
46+
- Two columns: `grid(columns: (1fr, 1fr), gutter: 20pt, left, right)`
47+
48+
## CeTZ Drawing
49+
50+
### Core Rules
51+
1. **Name all objects** that will be referenced later: `circle(..., name: "c")`, `line(..., name: "edge")`
52+
2. **Connect objects by name + anchor**, never by raw coordinates: `line("a.east", "b.west")`, not `line((2, 0), (5, 0))`
53+
3. **Use `set-origin`** for sub-figures instead of manual coordinate offsets
54+
4. **Use `on-layer`** for layering: -1 for backgrounds, 0 for main content, 1 for labels
55+
5. **Use `content()` with `frame: "rect"`** for labeled boxes; use `fill: white, stroke: none` for edge labels
56+
6. **Inside CeTZ functions**, always `import draw: *` for unqualified access
57+
58+
### Gotchas
59+
- **`arc`**: first parameter is the **start point** of the arc, not the center of the circle
60+
- **`bezier`**: first two args are **start and end points**; remaining args are control points
61+
- **Arrows**: prefer `mark: (end: "straight")` style — do NOT use `">"`
62+
- **Stroke dict**: use `(paint: color, thickness: 1pt, dash: "dashed")` — NOT `stroke(...)` constructor
63+
64+
### Quick Reference
65+
- Shapes: `circle`, `rect`, `line`, `arc`, `bezier`, `hobby`, `catmull`, `merge-path`, `grid`
66+
- Anchors: `"name.north"`, `.south`, `.east`, `.west`, `.center`, `.start`, `.mid`, `.end`
67+
- Coordinates: `(x, y)`, `(rel: (dx, dy), to: "name")`, `("a", 50%, "b")`, `("a", "|-", "b")`
68+
- Marks (arrows): `"straight"`, `">"`, `"stealth"`, `"|"`, `"o"`, `"<>"`, `"hook"`, `"]"`
69+
- Strokes: `(dash: "dashed")`, `(dash: "dotted")`, `(dash: "dash-dotted")`, `2pt + red`
70+
- Colors: `blue.lighten(60%)`, `green.darken(20%)`, `rgb("#f0f0fe")`
71+
- Decorations: `decorations.brace`, `.flat-brace`, `.zigzag`, `.wave`, `.coil`
72+
- Trees: `tree.tree((...), direction: "down", grow: 1.5, spread: 1.8)`
73+
74+
### Drawing Patterns
75+
- **Graph rendering**: name vertices as `str(k)`, connect with `line(str(k), str(l))`
76+
- **Circular layout**: use `vrotate(v, theta)` helper to place vertices on a circle
77+
- **Edge labels**: `content("edge.mid", label, fill: white, frame: "rect", padding: 0.08, stroke: none)`
78+
- **Data-driven diagrams**: store layout as list of tuples, iterate with `for` loops
79+
- **Tensor networks**: `tensor` (circle + label), `deltatensor` (small filled dot), `labeledge` (line + midpoint label)
80+
- **Intersections**: `intersections("ix", { ...shapes... })` then reference `"ix.0"`, `"ix.1"`
81+
82+
## CeTZ Plotting
83+
- `plot.plot(size: (w, h), axis-style: "scientific", x-tick-step: 1, y-tick-step: 2, { ... })`
84+
- Line: `plot.add(domain: (a, b), x => f(x), label: $f$, style: (stroke: blue))`
85+
- Data: `plot.add(data, mark: "o", line: "spline")` — line types: `"linear"`, `"spline"`, `"vh"`, `"hv"`
86+
- Scatter marks: `"*"`, `"o"`, `"square"`, `"triangle"`, `"+"`, `"|"`, `"-"`, `"<>"`
87+
- Fill between: `plot.add-fill-between(f, g, domain: (a, b))`
88+
- Reference lines: `plot.add-hline(y)`, `plot.add-vline(x)`
89+
- Annotations: `plot.add-anchor("name", (x, y))`, `plot.annotate({ ... })`
90+
- Bar chart: `chart.barchart(data, size: ..., mode: "clustered", labels: (...))`
91+
- Pie chart: `chart.piechart(data, inner-radius: 0.5, outer-label: (content: auto, radius: 130%))`

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ cli:
153153
GRAPHS := diamond bull house petersen
154154
MODES := unweighted weighted triangular
155155
rust-export:
156+
@mkdir -p tests/julia
156157
@for graph in $(GRAPHS); do \
157158
for mode in $(MODES); do \
158159
echo "Exporting $$graph ($$mode)..."; \

docs/paper/reductions.typ

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"PaintShop": [Paint Shop],
5151
"BicliqueCover": [Biclique Cover],
5252
"BinPacking": [Bin Packing],
53+
"ClosestVectorProblem": [Closest Vector Problem],
5354
)
5455

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

641+
#problem-def("ClosestVectorProblem")[
642+
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$.
643+
][
644+
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)$.
645+
646+
*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$.
647+
648+
#figure(
649+
canvas(length: 0.8cm, {
650+
import draw: *
651+
// Lattice points: B*(x1,x2) = x1*(2,0) + x2*(1,2)
652+
for x1 in range(0, 3) {
653+
for x2 in range(0, 3) {
654+
let px = x1 * 2 + x2 * 1
655+
let py = x2 * 2
656+
let is-closest = (x1 == 1 and x2 == 1)
657+
let nm = "p" + str(x1) + str(x2)
658+
circle(
659+
(px, py),
660+
radius: if is-closest { 0.15 } else { 0.08 },
661+
fill: if is-closest { graph-colors.at(0) } else { luma(180) },
662+
stroke: if is-closest { 0.8pt + graph-colors.at(0) } else { 0.4pt + luma(120) },
663+
name: nm,
664+
)
665+
}
666+
}
667+
// Target vector
668+
circle((2.8, 1.5), radius: 0.1, fill: graph-colors.at(1), stroke: none, name: "target")
669+
content((rel: (0, -0.45), to: "target"), text(7pt)[$bold(t)$])
670+
// Dashed line from target to closest point
671+
line("target", "p11", stroke: (paint: graph-colors.at(0), thickness: 0.8pt, dash: "dashed"))
672+
// Basis vectors as arrows from origin
673+
line("p00", "p10", mark: (end: "straight"), stroke: 0.8pt + luma(100), name: "b1")
674+
content((rel: (0, -0.35), to: "b1.mid"), text(7pt)[$bold(b)_1$])
675+
line("p00", "p01", mark: (end: "straight"), stroke: 0.8pt + luma(100), name: "b2")
676+
content((rel: (-0.3, 0), to: "b2.mid"), text(7pt)[$bold(b)_2$])
677+
// Label closest point
678+
content((rel: (0.45, 0.3), to: "p11"), text(7pt)[$bold(B)(1,1)^top$])
679+
}),
680+
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$.],
681+
) <fig:cvp-example>
682+
]
683+
640684
== Satisfiability Problems
641685

642686
#problem-def("Satisfiability")[

docs/paper/references.bib

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,43 @@ @article{epping2004
307307
doi = {10.1016/S0166-218X(03)00442-6}
308308
}
309309

310+
@techreport{vanemde1981,
311+
author = {Peter van Emde Boas},
312+
title = {Another NP-complete Problem and the Complexity of Computing Short Vectors in a Lattice},
313+
institution = {Mathematisch Instituut, Universiteit van Amsterdam},
314+
number = {81-04},
315+
year = {1981}
316+
}
317+
318+
@article{kannan1987,
319+
author = {Ravi Kannan},
320+
title = {Minkowski's Convex Body Theorem and Integer Programming},
321+
journal = {Mathematics of Operations Research},
322+
volume = {12},
323+
number = {3},
324+
pages = {415--440},
325+
year = {1987},
326+
doi = {10.1287/moor.12.3.415}
327+
}
328+
329+
@inproceedings{micciancio2010,
330+
author = {Daniele Micciancio and Panagiotis Voulgaris},
331+
title = {A Deterministic Single Exponential Time Algorithm for Most Lattice Problems Based on {V}oronoi Cell Computations},
332+
booktitle = {Proceedings of the 42nd ACM Symposium on Theory of Computing (STOC)},
333+
pages = {351--358},
334+
year = {2010},
335+
doi = {10.1145/1806689.1806739}
336+
}
337+
338+
@inproceedings{aggarwal2015,
339+
author = {Divesh Aggarwal and Daniel Dadush and Noah Stephens-Davidowitz},
340+
title = {Solving the Closest Vector Problem in $2^n$ Time -- The Discrete {G}aussian Strikes Again!},
341+
booktitle = {Proceedings of the 56th IEEE Symposium on Foundations of Computer Science (FOCS)},
342+
pages = {563--580},
343+
year = {2015},
344+
doi = {10.1109/FOCS.2015.41}
345+
}
346+
310347
@article{shannon1956,
311348
author = {Claude E. Shannon},
312349
title = {The zero error capacity of a noisy channel},

docs/src/reductions/problem_schemas.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,27 @@
8383
}
8484
]
8585
},
86+
{
87+
"name": "ClosestVectorProblem",
88+
"description": "Find the closest lattice point to a target vector",
89+
"fields": [
90+
{
91+
"name": "basis",
92+
"type_name": "Vec<Vec<T>>",
93+
"description": "Basis matrix B as column vectors"
94+
},
95+
{
96+
"name": "target",
97+
"type_name": "Vec<f64>",
98+
"description": "Target vector t"
99+
},
100+
{
101+
"name": "bounds",
102+
"type_name": "Vec<VarBounds>",
103+
"description": "Integer bounds per variable"
104+
}
105+
]
106+
},
86107
{
87108
"name": "Factoring",
88109
"description": "Factor a composite integer into two factors",

0 commit comments

Comments
 (0)