{"id":51428384,"url":"https://github.com/leanprover/hex-lll","last_synced_at":"2026-07-05T03:00:29.244Z","repository":{"id":367083776,"uuid":"1279160106","full_name":"leanprover/hex-lll","owner":"leanprover","description":"LLL lattice reduction for the hex project (optional fpLLL FFI). Mathlib-free.","archived":false,"fork":false,"pushed_at":"2026-07-03T21:57:58.000Z","size":447,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-03T23:27:17.188Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://kim-em.github.io/hex-dev/find/?domain=Verso.Genre.Manual.section\u0026name=hex-lll","language":"Lean","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leanprover.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-24T12:33:05.000Z","updated_at":"2026-07-03T21:58:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/leanprover/hex-lll","commit_stats":null,"previous_names":["kim-em/hex-lll","leanprover/hex-lll"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/leanprover/hex-lll","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fhex-lll","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fhex-lll/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fhex-lll/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fhex-lll/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leanprover","download_url":"https://codeload.github.com/leanprover/hex-lll/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fhex-lll/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35141966,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-05T02:00:06.290Z","response_time":100,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-05T03:00:22.656Z","updated_at":"2026-07-05T03:00:29.216Z","avatar_url":"https://github.com/leanprover.png","language":"Lean","funding_links":[],"categories":[],"sub_categories":[],"readme":"# hex-lll\n\nPart of [`hex`](https://github.com/kim-em/hex-dev), a computer algebra\nlibrary for Lean 4. The aim is fast executable code, fully verified, built\nwith spec-driven development.\n\n`hex-lll` provides executable LLL reduction of an integer lattice basis:\ngiven a basis of a lattice in `ℤᵐ`, it returns a shorter, more orthogonal\nbasis of the same lattice, with the first row a provably short vector. It\ndepends on [`hex-gram-schmidt`](https://github.com/leanprover/hex-gram-schmidt)\nfor the integer Gram-Schmidt data the algorithm carries, and is Mathlib-free.\nThe correspondence with Mathlib and the full short-vector theory live in\n[`hex-lll-mathlib`](https://github.com/leanprover/hex-lll-mathlib).\n\nOn adversarial worst-case input — fplll's Ajtai-style `gen_trg` bases, whose\nsteeply decreasing profile forces a huge swap count — the exact integer\nreducers (Lean's `lllNative` and the verified Isabelle extraction) blow up\n`~d⁷`, while the **certified path** — an `fpLLL` candidate checked by the\nverified Lean `certCheck` — stays cheap, near raw floating-point speed:\n\n![HexLLL reducers on Ajtai-style worst-case bases](reports/figures/hex-lll-comparator-ajtai.svg)\n\nThat is the design in one picture: get a verified result at close to unverified\nspeed by *certifying a fast reducer* rather than running an exact one. See\n[Performance comparison](#performance-comparison) for what each curve is, the\ninput families, and how to select the certified versus native path.\n\n# Quickstart\n\nAdd to your `lakefile.toml`:\n\n```toml\n[[require]]\nname = \"hex-lll\"\ngit = \"https://github.com/leanprover/hex-lll.git\"\nrev = \"main\"\n```\n\n```lean\nimport HexLLL\n\nopen Hex\n\n-- A small integer lattice basis, one row per basis vector.\ndef B : Matrix Int 3 3 := Matrix.ofFn fun i j =\u003e\n  match i.val, j.val with\n  | 0, 0 =\u003e 1 | 0, 1 =\u003e 1 | 0, 2 =\u003e 1\n  | 1, 0 =\u003e 1 | 1, 1 =\u003e 0 | 1, 2 =\u003e 2\n  | 2, 0 =\u003e 3 | 2, 1 =\u003e 5 | 2, 2 =\u003e 6\n  | _, _ =\u003e 0\n\n-- The verified entry point. Given a proof `hind : B.independent`, `lll` returns\n-- a `(δ, 11/20)`-reduced basis of the same lattice and `lll.firstShortVector`\n-- reads off its provably short first row. The short-vector guarantee itself is\n-- the theorem `lll_first_row_norm_sq_le` in `hex-lll-mathlib`.\n#check @lll.firstShortVector\n#check @lll\n\n-- To run the reducer on data without supplying an independence proof, use the\n-- proof-free variants. They run the exact `lllNative` directly (the body of\n-- `lll`'s native path, skipping the provider dispatch) and carry no exported\n-- short-vector theorem unless you separately prove `B.independent`.\n#eval lllNative.firstShortVector B (3 / 4) (by decide +kernel) (by decide +kernel) (by decide)\n#eval lllNative.shortVectors B (3 / 4) (by decide +kernel) (by decide +kernel) (by decide)\n\n-- The executable integer reducedness oracle.\n#eval lllReducedInt (Matrix.identity 3) (3 / 4) (1 / 2)   -- true\n```\n\n# Functionality\n\nThe public entry point is `lll`, which reduces an integer basis at a\nrational factor `δ` and returns a `(δ, 11/20)`-reduced basis of the same\nlattice. Behind that one entry point are two reducers, each of which\nproduces output correct to that same contract, so the result is correct no\nmatter which one runs. `lll` dispatches through them in order:\n\n- **External provider** (`LLLProvider.dispatch`). If an external reducer is\n  installed in the process — via the explicit loader `Hex.lll.loadProvider`\n  pointed at a built fpLLL-ffi shared library (see\n  [Performance comparison](#performance-comparison)) — `lll` runs it and\n  *certifies* the returned candidate with the integer-only checker `certCheck`.\n  An absent or rejected candidate falls through. The provider is an independent\n  artifact this library neither depends on nor names in its build; it is\n  acceleration only, loaded at runtime.\n- **Exact integer reducer** (`lllNative`). The trusted all-integer `d`/`ν`\n  reducer at the classical size-reduction bound `η = 1/2`. The native path:\n  always correct, never approximate.\n\nThe surface, by group:\n\n- `lll`, `lll.firstShortVector`, and `lll.shortVectors`: the public reducer,\n  its provably short first reduced row, and the ordered reduced rows.\n  `firstShortVector` is the short-vector entry point for downstream consumers such as\n  [`hex-berlekamp-zassenhaus`](https://github.com/leanprover/hex-berlekamp-zassenhaus).\n- `lllNative`: the exact integer reducer at the classical `η = 1/2`, with the\n  tighter short-vector constant; call it directly to get the classical\n  guarantee.\n- `lllNative.firstShortVector` and `lllNative.shortVectors`: proof-free\n  variants of the entry points for callers without an independence proof.\n- `lllReducedInt`, `lllReducedInterval`, and `lllReducedCheck`: the exact,\n  fixed-precision, and dispatched reducedness oracles; `certCheck` is the\n  integer certificate checker for an external reducer's output.\n- `Matrix.memLattice`, `Matrix.independent`, and `Vector.normSq` for stating\n  and checking the inputs and guarantees.\n\nEverything else lives under the `Hex.Internal` namespace and is not part of the\nsupported API: the integer state `LLLState` and its step/loop machinery, the\nfixed-precision interval checker kernel, the external-provider plumbing, and the\ndispatch-tuning and diagnostics constants. `open Hex` brings only the surface\nabove into scope.\n\n# Verification\n\nThe library is Mathlib-free, so the deep correctness of LLL lives in the\nMathlib bridge. What is proven here is the short-vector bound reduced to the\nsize-reduction hypothesis, and the same-lattice half of the external\ncertificate.\n\nThe short-vector bound, `short_vector_bound_of_size_bound`: a reduced,\nindependent basis has a first row whose squared norm is at most\n`(1 / (δ − η²))^(n-1)` times that of any nonzero lattice vector.\n\n```lean\ntheorem short_vector_bound_of_size_bound (b : Matrix Int n m) {δ η : Rat}\n    (hli : Matrix.independent b) (hred : isLLLReduced b δ η)\n    (hη : (1 / 2 : Rat) ≤ η) (hδη : η * η \u003c δ) (hδ' : δ ≤ 1) (hn : 1 ≤ n)\n    {v : Vector Int m} (hv : Matrix.memLattice b v) (hv' : v ≠ 0) :\n    (((b.row ⟨0, Nat.lt_of_lt_of_le Nat.zero_lt_one hn⟩).normSq : Int) : Rat) ≤\n      (1 / (δ - η * η)) ^ (n - 1) *\n        ((v.normSq : Int) : Rat)\n```\n\nThe certificate's same-lattice clause, `sameLatticeCert_sound`: when the\ninteger transforms check out, the input and candidate span the same lattice.\n\n```lean\ntheorem sameLatticeCert_sound {B B' : Matrix Int n m} {U V : Matrix Int n n} :\n    sameLatticeCert B B' U V = true →\n      ∀ v, B.memLattice v ↔ B'.memLattice v\n```\n\n**The size-reduction bound `η` and its constants.** The public `lll`\ncertifies its output `(δ, 11/20)`-reduced: every Gram-Schmidt coefficient\nsatisfies `|μ| ≤ 11/20`. Two numbers in `lll`'s signature follow from that\n`η = 11/20`. The precondition is `121/400 \u003c δ`, because `121/400 = (11/20)² =\nη²` and the bound is well-defined only when `η² \u003c δ`; and the short-vector\nconstant is `1/(δ − 121/400)`. So the `121/400` in `lll`'s signature is just\n`η²` — it stands exactly where the classical bound would put `1/4 = (1/2)²`.\n\nWhy `11/20` and not the classical `1/2`? Solely because of the external\nprovider. The exact `lllNative` already lands at `|μ| ≤ 1/2`, so on its own it\ngives the tighter `1/4 \u003c δ` contract. But a black-box external reducer cannot\nbe forced to land exactly `|μ| ≤ 1/2` (fplll's default size-reduction target\nsits slightly above `1/2`), so the certified-dispatch path accepts its\ncandidate at the looser `11/20`. That is the only reason the public contract is\nstated at `11/20` (so `η² = 121/400`) rather than `1/2` (so `η² = 1/4`). The\nexact `lllNative` keeps the classical `η = 1/2`, with the strictly better\nshort-vector theorem `lllNative_short_vector` (precondition `1/4 \u003c δ`, constant\n`1/(δ − 1/4)`): **call `lllNative` directly when you want that tighter\nguarantee**, rather than the public `lll`.\n\nIs the looser bound a concern? It is an honest weakening of the formal\nconstant, and the weakening compounds with dimension, so it is worth being\nprecise about. At `δ = 3/4` the squared-norm constant goes from\n`1/(δ − 1/4) = 2` for `lllNative` to `1/(δ − 121/400) ≈ 2.235` for `lll`, so\nthe per-vector length factor is about `5.7%` larger per dimension: modest in\nlow dimension, real in high. Tightening `η` back toward `1/2` would require a\nstricter certified checker (higher working precision, tighter requested\nmargins, or enforcing exact `|μ| ≤ 1/2`), trading run time and a higher\nfallback rate for a better constant. The dispatch's requested-parameter and\nprecision constants are internal tuning, documented at their definitions; none\nof them affects soundness.\n\nThe end-to-end guarantees of `lll` are proved in\n[`hex-lll-mathlib`](https://github.com/leanprover/hex-lll-mathlib): that its output\nis `(δ, 11/20)`-reduced, spans the same lattice, and satisfies the\nshort-vector bound, together with the certificate soundness theorem\n`certCheck_sound`.\n\n# Performance comparison\n\nHexLLL is benchmarked against the verified Isabelle `LLL_Basis_Reduction`\nextraction and the unverified floating-point `fpLLL`, across input families\nchosen to stress different parts of the algorithm. Here is a second family,\n`harsh-cubic`, where the entry bit-length grows with the dimension:\n\n![HexLLL harsh-cubic comparator](reports/figures/hex-lll-comparator-harsh-cubic.svg)\n\n**The five curves.** Each plot is log-scale wall-time per reduction against the\nfamily's dimension:\n\n- **fpLLL** — the raw floating-point reducer, unverified. The speed baseline.\n- **Lean native** — `lllNative`, HexLLL's exact all-integer `d`/`ν` reducer.\n  Correct by construction, but its exact arithmetic pays for wide operands and\n  high swap counts.\n- **Lean certified** — an `fpLLL` candidate *checked* by the verified Lean\n  `certCheck`. Inherits floating-point speed and adds only a cheap integer\n  check, so it hugs the fpLLL curve while remaining fully verified.\n- **verified Isabelle native** — the Isabelle `LLL_Basis_Reduction` extraction's\n  own reducer; the independent verified point of comparison.\n- **verified Isabelle certified** — the *same* fpLLL candidate checked by the\n  Isabelle verified checker instead of the Lean one; the apples-to-apples\n  yardstick for the Lean certified path.\n\n**The input families.** Each stresses a different cost:\n\n- **`random-bounded`** — near-orthogonal random bases; the easy baseline (few\n  swaps).\n- **`harsh-cubic`** — entries `~2^{3.3n}`; stresses exact-integer operand-width\n  growth (above).\n- **`ajtai`** — fplll `gen_trg` worst-case triangular bases; stresses the swap\n  / iteration count (`Θ(d² log B)`) — the plot at the top of this README.\n- **`q-ary`** — LWE/SIS `[[I,H],[0,qI]]` bases; the cryptographic Z-shape.\n- **`ntru`** — `[[I,Rot h],[0,qI]]` bases; a planted dense sublattice plus a\n  q-block.\n- **`knapsack`** — the rectangular `d×(d+1)` integer-relation form; the only\n  `cols ≠ rows` family.\n\nAcross every family the exact reducers are correct but climb steeply on the hard\nbases, while Lean certified stays within ~1.2–2.5× of raw fpLLL — verified\noutput at close to floating-point cost.\n\n**Selecting the certified vs native path — a runtime choice, not an import.**\n`HexLLL` always builds its FFI shim, and the *same* `lll` call picks its path by\nwhether an external provider is installed in the process:\n\n- call **`Hex.lll.loadProvider path`** with the path to a built fpLLL-ffi shared\n  library (`scripts/oracle/setup_fplll_ffi.sh` builds one and prints its path);\n  it returns `true` on success, after which `lll` takes the **certified path**\n  (the candidate is certified by `certCheck`). `Hex.lll.providerActive : IO Bool`\n  reports whether a provider is currently installed;\n- load nothing (or if certification ever failed) and `lll` runs the exact\n  **`lllNative`** directly.\n\nLoading is an explicit, discoverable Lean action next to `lll` itself — there is\nno environment variable read on the `lll` path and no implicit `dlopen`. Either\nway the result satisfies the same `(δ, 11/20)`-reduced contract. To force\nthe exact path unconditionally — and get the tighter `η = 1/2` guarantee\n(precondition `1/4 \u003c δ`, constant `1/(δ − 1/4)`; see [Verification](#verification))\n— call `lllNative` directly.\n\nFull methodology, all six per-family plots, and the asymptotic fits are in the\nreference manual's\n[performance chapter](https://kim-em.github.io/hex-dev/find/?domain=Verso.Genre.Manual.section\u0026name=hex-lll-performance)\nand in [PERFORMANCE.md](PERFORMANCE.md).\n\n# Trust boundary\n\nThe kernel proofs trust none of the acceleration machinery. The capstone\ntheorems reduce to the ordinary Lean axioms `propext`, `Classical.choice`, and\n`Quot.sound` (and Mathlib, for the `hex-lll-mathlib` results); there is no\n`sorry`, no `axiom`, and no `native_decide` anywhere in the libraries. Concretely:\n\n- **External provider.** The optional reducer is reached through an\n  `@[extern] opaque` hook. Its output is never trusted: it is certified by the\n  integer-arithmetic checker `certCheck` before use, and an absent or rejected\n  candidate falls back to the native reducer. A wrong or adversarial provider\n  cannot produce a wrong result, only a fallback.\n- **Diagnostics.** The provider and checker tallies record decision\n  counts via `@[implemented_by]` side effects in compiled code only. They are\n  definitionally identity in the logic; no theorem depends on them.\n- **Execution vs. checking.** Compiled execution may call the C FFI shim\n  (`dlopen`); kernel proof checking calls none of it.\n\nThe requested-parameter, precision, and dispatch-calibration constants are\nperformance tuning only and are outside the trusted story; none affects soundness.\n\n# Reference manual\n\nThe hex reference manual covers this library at\n\u003chttps://kim-em.github.io/hex-dev/find/?domain=Verso.Genre.Manual.section\u0026name=hex-lll\u003e.\n\n# Contributing\n\nDevelopment happens in the [`hex-dev`](https://github.com/kim-em/hex-dev)\nmonorepo, not in this published mirror. Contributions are welcome as pull\nrequests to the `SPEC/` directory: describe the behaviour you want, and\nleave the implementation to the maintainer.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleanprover%2Fhex-lll","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleanprover%2Fhex-lll","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleanprover%2Fhex-lll/lists"}