BQN's Quantum Noise

Preamble

We will implement and test a Schrödinger-style1 quantum simulator in the BQN2 programming language. Initially, we import the necessary system functions and define a 1-modifier for handling complex-valued matrix products. Next, we define a namespace containing various quantum gates:

Sin‿Cos‿GCD ← •math
U ← •rand.Range
_cp ← {(-´𝔽¨)⋈(+´𝔽¨)⟜⌽}

g ← {
  IM ← (⊢⋈≢⥊⟜0⊢)¨
  x‿id‿h ⇐ (⌽‿⊢{𝕎𝕩}¨<=⌜˜↕2) ∾○IM <-⌾(1‿1⊸⊑)2‿2⥊÷√2
  swap‿cnot ⇐ IM ⟨1‿2, 2‿3⟩ {⌽⌾(𝕨⊸⊏)𝕩}¨ <=⌜˜↕4
  P ⇐ {⟨=⌜˜↕4,  4‿4⥊0⟩ {𝕨⌾(3‿3⊸⊑) 𝕩}¨˜ Sin⊸⋈⟜Cos 𝕩}
}

Interpreter

The (400 chars3) quantum interpreter is based on references arXiv:1711.02086 and arXiv:1608.03355. For simplicity, we always measure at the end of the execution:

Q ← {𝕊qb‿sc‿r:
  wf ← (1⌾⊑⋈⊢)⥊⟜0 2⋆qb
  M‿K ← ⟨+˝∘×⎉1‿∞ _cp, {1𝕊𝕩:𝕩; 𝕨𝕊1:𝕨; 𝕨∾∘×⟜<_cp𝕩}⟩
  E ← {0𝕊𝕩:1; K⍟(𝕨-1)˜𝕩}
  L ← {K´ ⟨(qb-𝕨+⌊2⋆⁼≠⊑𝕩) E g.id, 𝕩, 𝕨 E g.id⟩}
  T ← ∾↕∘≠{a←𝕩, i←𝕨{𝕩⊑a}•_while_{𝕩<𝕨}𝕨⊑a, 𝕨<◶⟨⟩‿{(⊢∾1⊸↓∘⌽)𝕨+↕𝕩-𝕨}i}¨<
  A ← {qs‿gs𝕊v:
    1⊸=◶{𝕊𝕩: ui ← 0 L gs
      v M˜ {𝕊⟨⟩:ui; (M˜´M⟜ui⟜M˜M´) L⟜g.swap¨ 𝕩} T qs (⌽∘⊢∾¬∘∊/⊣)˜ ↕qb
    }‿(v M˜ gs L˜ ⊑qs) ≠qs}
  »⊸<∨` 0>r-`>+○(ט)˝ wf A´ ⌽sc
}

Shor's algorithm

As a test case, we employ the quantum circuit of Shor's algorithm for the number fifteen and base eleven, following references arXiv:1804.03719 and arXiv:2306.09122. The resulting compiled circuit uses five qubits, three of which serve as control. To enhance statistical accuracy, the experiment is repeated multiple times. Additionally, we define a classical post-processing function:

n‿a‿qb‿r ← ⟨15, 11, 5, 0 U˜ 2⋆3⟩

sc ← ⟨
  ⟨0⟩‿g.h ⋄ ⟨1⟩‿g.h ⋄ ⟨2⟩‿g.h
  ⟨2, 3⟩‿g.cnot ⋄ ⟨2, 4⟩‿g.cnot ⋄ ⟨1⟩‿g.h
  ⟨⟨1, 0⟩, g.P π÷2⟩ ⋄ ⟨0⟩‿g.h
  ⟨⟨1, 2⟩, g.P π÷4⟩ ⋄ ⟨⟨0, 2⟩, g.P π÷2⟩ ⋄ ⟨2⟩‿g.h
⟩

C ← {n (⊣≡×´∘GCD) +‿-{𝕩𝕎1}¨ <a⋆(≠÷2×⊑∘⍒) 0⌾⊑+˝∘‿(2⋆qb-2)⥊𝕩}

Wir müssen wissen, wir werden wissen!4

C >+˝{Q qb‿sc‿𝕩}¨ r
1

Compare the result with that from a real quantum computer.

Epilogue

Why the hieroglyphs, you may ask? The tacit and functional style, coupled with numerous combinators, makes programming feel like solving a fun algebraic puzzle rather than drafting a manifesto. BQN is the epitome of minimalism's power:

Primitive's stats

The prog string contains the full source code. We used:

prog (+´⊸≍⟜≠∊)˜ ⊑¨•primitives
⟨ 44 64 ⟩

With this distribution:

⍉>(⍷∾≠)¨∘(⊐⊸⊔∊/⊣)⟜(⊑¨•primitives)˜ prog
┌─                                                                                                                                                                                 
╵ '-' '´' '¨' '⋈' '+' '⟜' '⌽' '⊢' '≢' '⥊' '<' '=' '⌜' '˜' '↕' '∾' '○' '⌾' '⊸' '⊑' '÷' '√' '⊏' '⋆' '˝' '∘' '×' '⎉' '≡' '⊣' '⌊' '⁼' '≠' '⍟' '◶' '↓' '¬' '∊' '/' '»' '∨' '`' '>' '⍒'  
  8   8   10  5   8   3   6   7   1   5   9   6   3   12  6   5   2   5   7   9   5   1   1   5   4   8   5   1   3   3   1   1   5   1   2   1   1   1   1   1   1   2   3   1    
                                                                                                                                                                                  ┘

BQN is also fast:

Benchmarks

While the interpreter's performance is not particularly optimized, here is a comparison with the equivalent Common Lisp code:

Benchmark 1: cbqn -f ./bqn/q.bqn
  Time (mean ± σ):      5.468 s ±  0.077 s    [User: 5.427 s, System: 0.005 s]
  Range (min … max):    5.358 s …  5.535 s    5 runs
 
Benchmark 2: sbcl --script ../supp/perf_qi/q.lisp
  Time (mean ± σ):     37.114 s ±  0.893 s    [User: 37.544 s, System: 0.207 s]
  Range (min … max):   36.457 s … 38.634 s    5 runs
 
Summary
  cbqn -f ./bqn/q.bqn ran
    6.79 ± 0.19 times faster than sbcl --script ../supp/perf_qi/q.lisp

And here is a full program's profile. All time is spent in the Kronecker and matrix products:

)profile C >+˝{Q qb‿sc‿𝕩}¨ r
Got 25361 samples
(REPL): 25361 samples:
     2│  Q ← {𝕊qb‿sc‿r:
     1│    wf ← (1⌾⊑⋈⊢)⥊⟜0 2⋆qb
  2471│    M‿K ← ⟨+˝∘×⎉1‿∞ _cp, {1𝕊𝕩:𝕩; 𝕨𝕊1:𝕨; 𝕨∾∘×⟜<_cp𝕩}⟩
    26│    E ← {0𝕊𝕩:1; K⍟(𝕨-1)˜𝕩}
    39│    L ← {K´ ⟨(qb-𝕨+⌊2⋆⁼≠⊑𝕩) E g.id, 𝕩, 𝕨 E g.id⟩}
    16│    T ← ∾↕∘≠{a←𝕩, i←𝕨{𝕩⊑a}•_while_{𝕩<𝕨}𝕨⊑a, 𝕨<◶⟨⟩‿{(⊢∾1⊸↓∘⌽)𝕨+↕𝕩-𝕨}i}¨<
     1│    A ← {qs‿gs𝕊v:
     4│      1⊸=◶{𝕊𝕩: ui ← 0 L gs
 22430│        v M˜ {𝕊⟨⟩:ui; (M˜´M⟜ui⟜M˜M´) L⟜g.swap¨ 𝕩} T qs (⌽∘⊢∾¬∘∊/⊣)˜ ↕qb
   366│      }‿(v M˜ gs L˜ ⊑qs) ≠qs}
     5│    »⊸<∨` 0>r-`>+○(ט)˝ wf A´ ⌽sc
      │  }

Try running the simulation in the BQN repl and explore it! If you are an Emacs user, the org-mode computational notebook in the blog's repository provides the best experience.

Footnotes:

1

Although conceptually straightforward, a Hilbert space of size 2⋆n makes this type of simulation a true computational challenge. For an efficient implementation, see arXiv:1710.05867.

2

This post's title is a playful recursive acronym that employs quantum computing terminology, without any specific significance beyond that.

3

I optimized it up to this number, but I wasn't targeting the Kolmogorov complexity.

4

Hilbert's radio address in 1930.