Documentation | |
Continuous integration | |
Code coverage | |
Static analysis with |
A Julia package for working with quantum stabilizer states and Clifford circuits that act on them. Graphs states are also supported. The package is already very fast for the majority of common operations, but there are still many low-hanging fruits performance-wise. See the detailed suggested readings & references page for background on the various algorithms.
To install it use:
] add QuantumClifford
Works efficiently with pure and mixed stabilizer states of thousands of qubits as well as sparse or dense Clifford operations acting upon them.
Provides canonicalization, projection, and generation operations, as well as partial traces.
julia> P"X" * P"Z"
-iY
julia> P"X" ⊗ P"Z"
+ XZ
julia> S"-XX
+ZZ"
- XX
+ ZZ
julia> tCNOT * S"-XX
+ZZ"
- X_
+ _Z
The code is vectorized and multithreaded.
Fast, in-place, allocation free implementations.
Quick Benchmarks (click to expand)
The only other simulator of similar performance I know of is Stim. In particular, Stim implements convenient tracking of Pauli frames, that makes simulating the performance of error correcting codes blazingly fast (which are possible in QuantumClifford.jl, but no convenient interface is provided for that yet).
The "low level" functionality is of similar performance in Stim and QuantumClifford but different tradeoffs are made at the higher levels: to multiply in-place 1M-qubit Pauli operators Stim needs 16μs while QuantumClifford.jl needs 14μs. The difference is inconsequential and depends on compilers and hardware.
Of note is that Stim achieved this performance through high-quality C++ SIMD code of significant sophistication, while QuantumClifford.jl is implemented in pure Julia.
julia> a = random_pauli(1_000_000_000);
julia> b = random_pauli(1_000_000_000);
julia> @benchmark QuantumClifford.mul_left!(a,b)
BenchmarkTools.Trial: 155 samples with 1 evaluation.
Range (min … max): 32.074 ms … 32.425 ms ┊ GC (min … max): 0.00% … 0.00%
Time (median): 32.246 ms ┊ GC (median): 0.00%
Time (mean ± σ): 32.247 ms ± 63.427 μs ┊ GC (mean ± σ): 0.00% ± 0.00%
▃ ▃▃ ▄ ▆▄▄▄██▃ ▃▄▁▆█▃▃ ▃ ▁
▄▁▁▄▁▁▄▆▁▁▄▆▄▆▇▇█▄▄██▄█▆███████▇███████▆█▆▄▄▄▁▄█▁▄▄▁▄▁▁▁▁▁▄ ▄
32.1 ms Histogram: frequency by time 32.4 ms <
Memory estimate: 0 bytes, allocs estimate: 0.
julia> @benchmark canonicalize!(s) setup=(s=random_stabilizer(1000))
BenchmarkTools.Trial: 226 samples with 1 evaluation.
Range (min … max): 21.938 ms … 22.680 ms ┊ GC (min … max): 0.00% … 0.00%
Time (median): 22.025 ms ┊ GC (median): 0.00%
Time (mean ± σ): 22.057 ms ± 115.247 μs ┊ GC (mean ± σ): 0.00% ± 0.00%
▂▂ █▃▃▂
▄▇███████▆▇▆█▆▄▄▄▄▄▅▄▃▃▁▄▃▃▃▃▃▃▁▁▁▁▁▃▁▁▁▁▁▃▁▃▁▁▁▁▃▁▁▁▁▁▁▁▁▃▃ ▃
21.9 ms Histogram: frequency by time 22.6 ms <
Memory estimate: 32 bytes, allocs estimate: 1.
julia> @benchmark apply!(s, gate) setup=(s=random_stabilizer(1000); gate=tensor_pow(tCNOT,500))
BenchmarkTools.Trial: 931 samples with 1 evaluation.
Range (min … max): 4.902 ms … 9.070 ms ┊ GC (min … max): 0.00% … 0.00%
Time (median): 5.097 ms ┊ GC (median): 0.00%
Time (mean ± σ): 5.172 ms ± 319.591 μs ┊ GC (mean ± σ): 0.00% ± 0.00%
▃▇█▄▁▂▁▃▁
▃▇█████████▆▆▃▆▄▄▃▃▂▃▂▂▂▂▂▂▂▂▂▂▂▁▂▂▂▂▁▂▂▁▂▂▁▁▁▁▁▁▁▃▁▁▂▁▁▁▁▂ ▃
4.9 ms Histogram: frequency by time 6.6 ms <
Memory estimate: 6.89 KiB, allocs estimate: 49.
julia> @benchmark apply!(s, sCNOT(32,504)) setup=(s=random_stabilizer(1000))
BenchmarkTools.Trial: 10000 samples with 9 evaluations.
Range (min … max): 2.602 μs … 12.860 μs ┊ GC (min … max): 0.00% … 0.00%
Time (median): 2.934 μs ┊ GC (median): 0.00%
Time (mean ± σ): 3.048 μs ± 595.358 ns ┊ GC (mean ± σ): 0.00% ± 0.00%
▂▆█▅
▁▁▂▅█████▅▃▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▂
2.6 μs Histogram: frequency by time 5.53 μs <
Memory estimate: 112 bytes, allocs estimate: 2.
julia> s=random_destabilizer(1000); p=random_pauli(1000);
julia> @benchmark project!(_s,_p) setup=(_s=copy(s);_p=copy(p)) evals=1
BenchmarkTools.Trial: 10000 samples with 1 evaluation.
Range (min … max): 52.930 μs … 112.682 μs ┊ GC (min … max): 0.00% … 0.00%
Time (median): 67.628 μs ┊ GC (median): 0.00%
Time (mean ± σ): 67.100 μs ± 5.624 μs ┊ GC (mean ± σ): 0.00% ± 0.00%
▂▁ ▃▄ ▆▆▄▁▁▂▃▃▃▄█▇▃▂▂▂▁▁▃▃▁ ▁ ▁▂ ▂
██▆▅▅▇▆▄██▇▅▅▄▄▄▆██████████████████████▇▇▇▇▇▆▇███▇▇█▇▇▇▆▇▇██ █
52.9 μs Histogram: log(frequency) by time 85 μs <
Memory estimate: 480 bytes, allocs estimate: 4.
julia> s=MixedDestabilizer(random_destabilizer(1000));
julia> @benchmark projectY!(_s,42) setup=(_s=copy(s)) evals=1
BenchmarkTools.Trial: 10000 samples with 1 evaluation.
Range (min … max): 40.356 μs … 151.946 μs ┊ GC (min … max): 0.00% … 0.00%
Time (median): 49.203 μs ┊ GC (median): 0.00%
Time (mean ± σ): 49.992 μs ± 6.442 μs ┊ GC (mean ± σ): 0.00% ± 0.00%
▃▁▄▄ ▄▇▅██▄▄▃▃▄▂ ▁ ▁▂▁ ▂
████▇▅▅▄▅▄▅▅█████████████▇▇█▇▇▇████████▆▇▅▆▆▆▆▅▄▄▅▄▄▅▅▄▆▆▄▅▆ █
40.4 μs Histogram: log(frequency) by time 73.8 μs <
Memory estimate: 432 bytes, allocs estimate: 3.
Benchmarks executed on a Ryzen Zen1 8-core CPU.
More detailed benchmarks can be seen at github.com/Krastanov/QuantumCliffordBenchmarksLog.