Technical Solutions

A deep dive into Fanal's architecture, language design, type system, and automation pipeline for verified quantum programming.

1Architecture — Five-Layer Design

1
Parsing Syntax
User-facing Lean macros
Supportive
AI-generated
2
Syntax (AST)
Term constructors
3
Typing (Relations)
Deterministic & decidable
4
Semantics (Matrices)
Denotational interpretation
Descriptive
Human-maintained
5
Automation (Tactics)
Certified rewriting & decision
Supportive
AI-generated

2Module Dependencies

Dependency Graph

CExprLabelSetDiracLDiracProgramAssertionCurrentFuture
ModulePurposeComponents
CExprClassical expressions, data types, arithmeticSyntax, Typing, Semantics
LabelRegister labels for quantum register annotationSyntax, Typing, Semantics
SetSummation domains (e.g., univ)Syntax, Typing, Semantics
DiracPlain Dirac notationSyntax, Typing, Semantics, EqDef
LDiracRegister-annotated Dirac notationSyntax, Typing, Semantics, EqDef

3Language Design

DataType — Foundation for Register Dimensions

fin  n\texttt{fin}\;n — Finite {0, ..., n-1}
tuple  [t1,,tk]\texttt{tuple}\;[t_1, \ldots, t_k]— Product type
array  n  t\texttt{array}\;n\;t— Fixed-size array
fin  n=Fin  n\llbracket \texttt{fin}\;n \rrbracket = \text{Fin}\;n
tuple  [t1,]=t1×\llbracket \texttt{tuple}\;[t_1, \ldots] \rrbracket = \llbracket t_1 \rrbracket \times \cdots
array  n  t=Fin  nt\llbracket \texttt{array}\;n\;t \rrbracket = \text{Fin}\;n \to \llbracket t \rrbracket

DiracTerm — 16 Constructors

Primitives

  • t|t\rangle ket, t\langle t| bra
  • δ[i,j]\delta[i,j] Kronecker delta
  • Complex scalar, zero, identity

Operations

  • Addition, negation, scalar multiplication
  • Matrix multiplication, tensor product
  • Adjoint, big sum, big tensor product

DiracSort — (ketType, braType)

Every Dirac term has a sort (α,β)(\alpha, \beta) describing its matrix dimensions:

scalar
(unit,unit)(\texttt{unit}, \texttt{unit})
ket \alpha
(α,unit)(\alpha, \texttt{unit})
bra \alpha
(unit,α)(\texttt{unit}, \alpha)
op \;\alpha\;\beta
(α,β)(\alpha, \beta)
sort  (α,β)=Matrix  α  β  C\llbracket \text{sort}\;(\alpha, \beta) \rrbracket = \text{Matrix}\;\llbracket\alpha\rrbracket\;\llbracket\beta\rrbracket\;\mathbb{C}

4Labelled Dirac Notation

Why Labels?

Plain Dirac notation does not track which registers an operator acts on. Labelled Dirac extends each term with register patterns (ket label, bra label), enabling compositional reasoning about multi-register quantum systems.

Access Path Model

Labels resolve to register atoms via root + path of AccessSteps, reaching leaf dimensions that determine matrix indices.

q : tuple [array 3 (fin 2), fin 4]
q
tupleProj 0
array 3 (fin 2)
arrayElem 1
fin 2
tupleProj 1
fin 4
Atom: <q, [tupleProj 0, arrayElem 1]> resolves to fin  2\texttt{fin}\;2

LDirac Operations

labelAttach register annotations to a plain Dirac term
⊗ₗTensor — requires disjoint atoms
+ₗAddition — requires matching dims/atoms
·ₗMultiply — requires contraction compatible
Design principle: Typing is decidable. Undecidable premises (disjointness, dimension matching) are deferred to evaluation time, returning Option.

5Type System

Three Variable Categories, One Unified Context

ctype dt
Classical variable
x : Fin n, index, flag
dtype (α,β)
Dirac variable
A : Hα → Hβ
qtype dt
Register variable
q : quantum register

Key Typing Principles

(1) Deterministic(2) Decidable(3) Deferred checks

Sort Operations

(α1,β1)(α2,β2)=(tuple[α1,α2],  tuple[β1,β2])(\alpha_1, \beta_1) \otimes (\alpha_2, \beta_2) = (\texttt{tuple}[\alpha_1, \alpha_2],\; \texttt{tuple}[\beta_1, \beta_2])
(α,β)=(β,α)(\alpha, \beta)^\dagger = (\beta, \alpha)
(α,γ)(γ,β)=(α,β)(contraction on γ)(\alpha, \gamma) \cdot (\gamma, \beta) = (\alpha, \beta) \quad \text{(contraction on } \gamma \text{)}

6Automation Pipeline

Pipeline Overview

Goal
t₁ ≈ t₂
Phase 1
Normalization (rewrite rules on AST)
Phase 2
Comparison (syntactic equality)
Phase 3
Close goal (rfl or native_decide)
QED
Proof complete

dirac_eq Tactic — 7-Strategy Fallback

1Untyped norm → rfl~90% of goals
1bUntyped norm → native_decide
1eExpanded untyped (BKB, congr, id) → rfl
1ebExpanded untyped → native_decide
2Typed normalizer → rfl
3Typed + proof irrelevance → rfl
3bTyped + proof irrel → native_decidelast resort

ldirac_eq — Labelled Dirac Automation

Reduces labelled Dirac goals to plain Dirac, then reuses dirac_eq. Key reduction rules:

Absorption: same labels mergeTensor combine: disjoint fuse
Lean 4
example : gateX ⫍ k0 ≈ₕ k1 := by dirac_eq

example : ⟦ A ⟧_(a,a) ·ₗ ⟦ B ⟧_(a,a) ≈ₗ ⟦ A·B ⟧_(a,a) := by ldirac_eq

7Challenges & Solutions

ChallengeSolution
ℂ lacks DecidableEq — blocks native_decideConservative BEq: fails (never unsound) on non-concrete values
Register disjointness undecidable at type levelDeferred evaluation: typing stays decidable; disjointness checked at eval time via Option
Heterogeneous equality (different sorts)HSemEq (≈ₕ) with SortIso: reindex matrices along isomorphisms
Lean 4 kernel timeout on large normalizationsMulti-strategy fallback: try rfl first, escalate to native_decide
Descriptive code readability vs proof complexityPhysical separation: Descriptive/ (human) vs Supportive/ (AI)