mirror of
https://github.com/qwjyh/QuantumLegos.jl.git
synced 2025-06-29 16:19:19 +09:00
init (migrating and renaming)
This commit is contained in:
commit
f772e27182
19 changed files with 2262 additions and 0 deletions
26
test/pauliops.jl
Normal file
26
test/pauliops.jl
Normal file
|
@ -0,0 +1,26 @@
|
|||
@testset "SinglePauliOp" begin
|
||||
@test PauliOps.single_pauliop('I') == PauliOps.I
|
||||
@test_throws ArgumentError PauliOps.single_pauliop('a')
|
||||
end
|
||||
|
||||
@testset "SinglePauliOp Product" begin
|
||||
using QuantumLegos.PauliOps: I, X, Y, Z
|
||||
@test I * X == X
|
||||
@test Z * I == Z
|
||||
@test X * Y == Z
|
||||
@test Z * X == Y
|
||||
@test X * X == I
|
||||
end
|
||||
|
||||
@testset "PauliOp" begin
|
||||
@test pauliop("IXYZ") == [PauliOps.I, PauliOps.X, PauliOps.Y, PauliOps.Z]
|
||||
@test pauliop("IIXXZZ") ==
|
||||
[PauliOps.I, PauliOps.I, PauliOps.X, PauliOps.X, PauliOps.Z, PauliOps.Z]
|
||||
end
|
||||
|
||||
@testset "weight" begin
|
||||
p = pauliop("IXYZIXYZ")
|
||||
@test weight(p) == 6
|
||||
@test QuantumLegos.xweight(p) == 4
|
||||
@test QuantumLegos.zweight(p) == 4
|
||||
end
|
405
test/runtests.jl
Normal file
405
test/runtests.jl
Normal file
|
@ -0,0 +1,405 @@
|
|||
# for language server completion
|
||||
# must be removed for test
|
||||
true || include("../src/QuantumLegos.jl")
|
||||
|
||||
using QuantumLegos
|
||||
using Test
|
||||
using Documenter
|
||||
using Aqua
|
||||
using JET
|
||||
|
||||
@testset "QuantumLegos.jl" begin
|
||||
@testset "PauliOps" begin
|
||||
include("pauliops.jl")
|
||||
end
|
||||
|
||||
@testset "Lego" begin
|
||||
stabilizers = pauliop.(["II", "XX"])
|
||||
wrong_stabilizers = pauliop.(["I", "XX"]) # not SVector
|
||||
@info stabilizers
|
||||
@test_throws ArgumentError QuantumLegos.Lego(3, stabilizers)
|
||||
@test_throws MethodError QuantumLegos.Lego(2, wrong_stabilizers)
|
||||
end
|
||||
|
||||
@testset "CheckMatrix" begin
|
||||
@test_throws ArgumentError QuantumLegos.CheckMatrix([true false; false true], 2, 2)
|
||||
@test_throws ArgumentError QuantumLegos.CheckMatrix([true false; false true], 1, 1)
|
||||
@test QuantumLegos.CheckMatrix([true false; false true]) ==
|
||||
QuantumLegos.CheckMatrix(Bool[1 0; 0 1], 1, 2)
|
||||
@test_throws ArgumentError QuantumLegos.CheckMatrix([true false true; false true true])
|
||||
|
||||
@test_throws MethodError QuantumLegos.checkmatrix(pauliop.(["I", "IX"]))
|
||||
@test_throws ArgumentError QuantumLegos.checkmatrix(PauliOps.PauliOp[])
|
||||
@test QuantumLegos.checkmatrix(pauliop.(["IIXX", "IZZI"])) ==
|
||||
QuantumLegos.CheckMatrix(Bool[0 0 1 1 0 0 0 0; 0 0 0 0 0 1 1 0])
|
||||
@test QuantumLegos.checkmatrix(pauliop.(["YIXX", "IZYI"])) ==
|
||||
QuantumLegos.CheckMatrix(Bool[1 0 1 1 1 0 0 0; 0 0 1 0 0 1 1 0])
|
||||
|
||||
let
|
||||
gens = pauliop.(["IIXX", "IZZI"])
|
||||
cmat_1 = QuantumLegos.checkmatrix(gens)
|
||||
@test QuantumLegos.xpart(cmat_1) == Bool[0 0 1 1; 0 0 0 0]
|
||||
@test QuantumLegos.zpart(cmat_1) == Bool[0 0 0 0; 0 1 1 0]
|
||||
@test generators(cmat_1) == gens
|
||||
end
|
||||
let
|
||||
gens = pauliop.(["YIXX", "IZYI"])
|
||||
cmat_2 = QuantumLegos.checkmatrix(gens)
|
||||
@test QuantumLegos.xpart(cmat_2) == Bool[1 0 1 1; 0 0 1 0]
|
||||
@test QuantumLegos.zpart(cmat_2) == Bool[1 0 0 0; 0 1 1 0]
|
||||
@test generators(cmat_2) == gens
|
||||
end
|
||||
|
||||
@testset "eliminate_column!" begin
|
||||
let
|
||||
cmat = QuantumLegos.CheckMatrix(Bool[
|
||||
1 0 0 1
|
||||
1 0 1 1
|
||||
])
|
||||
@test QuantumLegos.eliminate_column!(cmat, 1, Int64[]) == 1
|
||||
@test cmat.cmat == Bool[
|
||||
1 0 0 1
|
||||
0 0 1 0
|
||||
]
|
||||
end
|
||||
let
|
||||
cmat = QuantumLegos.CheckMatrix(Bool[
|
||||
1 0 0 1
|
||||
1 0 1 1
|
||||
])
|
||||
@test QuantumLegos.eliminate_column!(cmat, 1, Int64[1]) == 2
|
||||
@test cmat.cmat == Bool[
|
||||
0 0 1 0
|
||||
1 0 1 1
|
||||
]
|
||||
end
|
||||
let
|
||||
cmat = QuantumLegos.CheckMatrix(
|
||||
Bool[
|
||||
1 1 0 1 0 0 1 1
|
||||
0 0 1 1 0 1 0 1
|
||||
0 1 1 0 1 0 1 1
|
||||
0 1 0 1 0 1 0 1
|
||||
],
|
||||
)
|
||||
@test QuantumLegos.eliminate_column!(cmat, 2, [1]) == 3
|
||||
@test cmat.cmat == Bool[
|
||||
1 0 1 1 1 0 0 0
|
||||
0 0 1 1 0 1 0 1
|
||||
0 1 1 0 1 0 1 1
|
||||
0 0 1 1 1 1 1 0
|
||||
]
|
||||
end
|
||||
let
|
||||
cmat = QuantumLegos.CheckMatrix(
|
||||
Bool[
|
||||
1 1 0 1 0 0 1 1
|
||||
0 0 1 1 0 1 0 1
|
||||
0 1 1 0 1 0 1 1
|
||||
0 1 0 1 0 1 0 1
|
||||
],
|
||||
)
|
||||
@test QuantumLegos.eliminate_column!(cmat, 2, [1, nothing]) == 3
|
||||
@test cmat.cmat == Bool[
|
||||
1 0 1 1 1 0 0 0
|
||||
0 0 1 1 0 1 0 1
|
||||
0 1 1 0 1 0 1 1
|
||||
0 0 1 1 1 1 1 0
|
||||
]
|
||||
end
|
||||
let
|
||||
cmat = QuantumLegos.CheckMatrix(
|
||||
Bool[
|
||||
1 0 0 0 1 1 0 1
|
||||
0 1 0 1 0 1 1 0
|
||||
0 1 0 0 0 1 0 0
|
||||
1 1 0 1 0 0 0 1
|
||||
],
|
||||
)
|
||||
@test QuantumLegos.eliminate_column!(cmat, 3, Int[]) === nothing
|
||||
end
|
||||
let
|
||||
# random test (robustness)
|
||||
function random_test()::Bool
|
||||
test_mat = rand(Bool, (8, 16))
|
||||
cmat = QuantumLegos.CheckMatrix(copy(test_mat))
|
||||
keep_indices = (1:8)[rand(1:8, rand(0:8))]
|
||||
keep_index = rand(1:16)
|
||||
try
|
||||
QuantumLegos.eliminate_column!(cmat, keep_index, keep_indices)
|
||||
return true
|
||||
catch e
|
||||
# unexpected error
|
||||
@error "Error on eliminate_column! with keep_index: $(keep_index), avoid: $(keep_indices), matrix:" cmat
|
||||
@error "error: " e
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
for i in 1:100
|
||||
# @info i
|
||||
@test random_test()
|
||||
end
|
||||
end
|
||||
@testset "ArgumentError" begin
|
||||
cmat = CheckMatrix(rand(Bool, (6, 12)))
|
||||
@test_throws ArgumentError QuantumLegos.eliminate_column!(cmat, 3, [1, 7])
|
||||
end
|
||||
end
|
||||
@testset "swap_row!" begin
|
||||
let
|
||||
m = rand(Bool, (10, 10))
|
||||
m_copy = copy(m)
|
||||
QuantumLegos.swap_row!(m, 3, 7)
|
||||
QuantumLegos.swap_row!(m, 3, 7)
|
||||
@test m == m_copy
|
||||
end
|
||||
let
|
||||
m = rand(Bool, (10, 10))
|
||||
m = BitMatrix(m)
|
||||
m_copy = copy(m)
|
||||
QuantumLegos.swap_row!(m, 4, 2)
|
||||
QuantumLegos.swap_row!(m, 4, 2)
|
||||
@test m == m_copy
|
||||
end
|
||||
end
|
||||
@testset "align_row!" begin
|
||||
mat = Bool[
|
||||
1 0 1 1 0 0 1 0
|
||||
0 1 0 1 0 1 0 0
|
||||
1 1 1 0 0 1 0 0
|
||||
1 0 0 1 0 1 0 0
|
||||
]
|
||||
mat_1 = copy(mat)
|
||||
@test 1 == QuantumLegos.align_row!(mat_1, 3, Int64[])
|
||||
@test mat_1 == Bool[
|
||||
1 1 1 0 0 1 0 0
|
||||
0 1 0 1 0 1 0 0
|
||||
1 0 1 1 0 0 1 0
|
||||
1 0 0 1 0 1 0 0
|
||||
]
|
||||
mat_1 = copy(mat)
|
||||
@test 1 == QuantumLegos.align_row!(mat_1, 3, [nothing])
|
||||
@test mat_1 == Bool[
|
||||
1 1 1 0 0 1 0 0
|
||||
0 1 0 1 0 1 0 0
|
||||
1 0 1 1 0 0 1 0
|
||||
1 0 0 1 0 1 0 0
|
||||
]
|
||||
mat_2 = copy(mat)
|
||||
@test 2 == QuantumLegos.align_row!(mat_2, 3, [1])
|
||||
@test mat_2 == Bool[
|
||||
1 0 1 1 0 0 1 0
|
||||
1 1 1 0 0 1 0 0
|
||||
0 1 0 1 0 1 0 0
|
||||
1 0 0 1 0 1 0 0
|
||||
]
|
||||
mat_3 = copy(mat)
|
||||
@test 3 == QuantumLegos.align_row!(mat_3, 3, [1, nothing, 3])
|
||||
@test mat_3 == Bool[
|
||||
1 0 1 1 0 0 1 0
|
||||
0 1 0 1 0 1 0 0
|
||||
1 1 1 0 0 1 0 0 # 3
|
||||
1 0 0 1 0 1 0 0 # 4
|
||||
]
|
||||
mat_3_2 = copy(mat_3)
|
||||
@test 4 == QuantumLegos.align_row!(mat_3, 4, [1, nothing, 3])
|
||||
@test mat_3 == mat_3_2
|
||||
@test nothing === QuantumLegos.align_row!(mat_3, nothing, [1, 2])
|
||||
@test nothing === QuantumLegos.align_row!(mat_3, nothing, [1, 2, nothing])
|
||||
@test nothing === QuantumLegos.align_row!(mat_3, nothing, [nothing])
|
||||
end
|
||||
@testset "ref!" begin
|
||||
@testset "compare with AbstractAlgebra" begin
|
||||
# test using existing package
|
||||
using AbstractAlgebra
|
||||
F₂ = GF(2) # finite field
|
||||
|
||||
"""
|
||||
Compare self-implemented `ref!` with AbstractAlgebra's `rref!` or `rank`.
|
||||
"""
|
||||
function random_test(size::Tuple{T, T}) where {T <: Integer}
|
||||
mat = rand(Bool, size)
|
||||
cmat = CheckMatrix(mat)
|
||||
S = matrix_space(F₂, size...)
|
||||
cmat_aa = S(F₂.(mat))
|
||||
# r_aa, A_aa = AbstractAlgebra.rref(cmat_aa)
|
||||
# cmat_aa = A_aa.entries .|> ==(1) |> Matrix{Bool} |> CheckMatrix
|
||||
r_aa = rank(cmat_aa)
|
||||
r = QuantumLegos.ref!(cmat)
|
||||
# @info "compare cmat" cmat cmat_aa
|
||||
@test r == r_aa
|
||||
end
|
||||
for _ in 1:10
|
||||
random_test((2, 4))
|
||||
random_test((4, 8))
|
||||
random_test((100, 200))
|
||||
end
|
||||
end
|
||||
@testset "manual sample" begin
|
||||
import LinearAlgebra
|
||||
mat =
|
||||
Bool[1 0 0 1 1 0 0 0; 0 1 0 0 1 1 0 1; 0 0 1 1 0 1 0 1; 0 1 0 0 1 0 0 1]
|
||||
cmat = CheckMatrix(mat)
|
||||
@test QuantumLegos.ref!(cmat) == LinearAlgebra.rank(mat)
|
||||
@test cmat == CheckMatrix(
|
||||
Bool[
|
||||
1 0 0 1 1 0 0 0
|
||||
0 1 0 0 1 1 0 1
|
||||
0 0 1 1 0 1 0 1
|
||||
0 0 0 0 0 1 0 0
|
||||
],
|
||||
4,
|
||||
4,
|
||||
)
|
||||
let
|
||||
mat = copy(mat)
|
||||
dependent_row = reduce(.⊻, eachrow(mat)[[1, 2]])
|
||||
mat[4, :] = dependent_row
|
||||
cmat = CheckMatrix(mat)
|
||||
@test QuantumLegos.ref!(cmat) == LinearAlgebra.rank(mat) == 3
|
||||
end
|
||||
let
|
||||
mat = copy(mat)
|
||||
dependent_row = reduce(.⊻, eachrow(mat)[[1, 2]])
|
||||
mat = vcat(mat, dependent_row')
|
||||
dependent_row = reduce(.⊻, eachrow(mat)[[1, 2, 3]])
|
||||
mat = vcat(mat, dependent_row')
|
||||
dependent_row = reduce(.⊻, eachrow(mat)[[2, 4]])
|
||||
mat = vcat(mat, dependent_row')
|
||||
cmat = CheckMatrix(mat)
|
||||
@test QuantumLegos.ref!(cmat) == rank(mat) == 3
|
||||
end
|
||||
end
|
||||
@testset "generated group is invariant under ref!" begin
|
||||
for _ in 1:10
|
||||
cmat = CheckMatrix(rand(Bool, (8, 12)))
|
||||
before = cmat |> generators |> GeneratedPauliGroup |> Set
|
||||
QuantumLegos.ref!(cmat)
|
||||
@test cmat |> generators |> GeneratedPauliGroup |> Set |> ==(before)
|
||||
end
|
||||
end
|
||||
end
|
||||
@testset "eliminate_dependent_row!" begin
|
||||
@testset "trivial" begin
|
||||
cmat = CheckMatrix(
|
||||
Bool[
|
||||
1 0 0 1 0 1 0 1
|
||||
0 1 1 0 0 1 1 0
|
||||
0 0 0 1 1 0 1 0
|
||||
0 0 0 0 0 0 0 0
|
||||
],
|
||||
)
|
||||
@test QuantumLegos.eliminate_dependent_row!(cmat) == CheckMatrix(
|
||||
Bool[1 0 0 1 0 1 0 1; 0 1 1 0 0 1 1 0; 0 0 0 1 1 0 1 0],
|
||||
4,
|
||||
3,
|
||||
)
|
||||
end
|
||||
@testset "less trivial" begin
|
||||
cmat = CheckMatrix(
|
||||
Bool[
|
||||
1 0 0 1 0 1 0 1
|
||||
0 1 1 0 0 1 1 0
|
||||
0 0 0 1 1 0 1 0
|
||||
1 1 1 1 0 0 1 1
|
||||
],
|
||||
)
|
||||
@test QuantumLegos.eliminate_dependent_row!(cmat) == CheckMatrix(
|
||||
Bool[1 0 0 1 0 1 0 1; 0 1 1 0 0 1 1 0; 0 0 0 1 1 0 1 0],
|
||||
4,
|
||||
3,
|
||||
)
|
||||
end
|
||||
# TODO: add more?
|
||||
end
|
||||
@testset "self_trace!" begin
|
||||
cmat = CheckMatrix(rand(Bool, (8, 16)))
|
||||
@test_throws ArgumentError QuantumLegos.self_trace!(cmat, 16, 17)
|
||||
@test_throws ArgumentError QuantumLegos.self_trace!(cmat, 18, 17)
|
||||
end
|
||||
end
|
||||
|
||||
@testset "State" begin
|
||||
@testset "LegoLeg" begin
|
||||
@test LegoLeg(0, 1) < LegoLeg(1, 0)
|
||||
@test LegoLeg(2, 1) > LegoLeg(1, 0)
|
||||
@test LegoLeg(1, 0) < LegoLeg(1, 1)
|
||||
@test LegoLeg(1, 1) == LegoLeg(1, 1)
|
||||
|
||||
@test sort(LegoLeg.([(1, 2), (2, 3), (0, 2), (0, 1)])) ==
|
||||
LegoLeg[LegoLeg(0, 1), LegoLeg(0, 2), LegoLeg(1, 2), LegoLeg(2, 3)]
|
||||
end
|
||||
@testset "edge" begin
|
||||
@test edge(1, 2, 3, 4) == (LegoLeg(1, 2), LegoLeg(3, 4))
|
||||
@test edge((1, 2, 3, 4)) == (LegoLeg(1, 2), LegoLeg(3, 4))
|
||||
@test edge(((1, 2), (3, 4))) == (LegoLeg(1, 2), LegoLeg(3, 4))
|
||||
end
|
||||
@testset "0 lego, 0 leg" begin
|
||||
@test_throws ArgumentError QuantumLegos.State(Lego{6}[], Tuple{LegoLeg, LegoLeg}[])
|
||||
end
|
||||
@testset "1 lego, 0 leg" begin
|
||||
stabgens = pauliop.(["IIXX", "XXII", "IZZI", "ZIIZ"])
|
||||
lego = QuantumLegos.Lego(stabgens)
|
||||
state = QuantumLegos.State([lego], Tuple{LegoLeg, LegoLeg}[])
|
||||
cmat = QuantumLegos.checkmatrix(stabgens)
|
||||
@test state == QuantumLegos.State([lego], Tuple{LegoLeg, LegoLeg}[])
|
||||
@test state.legos == [lego]
|
||||
@test state.edges == Tuple{LegoLeg, LegoLeg}[]
|
||||
@test state.cmat == cmat
|
||||
end
|
||||
@testset "2+ legos, 0 leg" begin
|
||||
stabgens = pauliop.(["IIXX", "XXII", "IZZI", "ZIIZ"])
|
||||
lego = QuantumLegos.Lego(stabgens)
|
||||
state_1 = QuantumLegos.State([lego], Tuple{LegoLeg, LegoLeg}[])
|
||||
add_lego!(state_1, lego)
|
||||
@test state_1.legos == [lego, lego]
|
||||
@test state_1.edges == Tuple{LegoLeg, LegoLeg}[]
|
||||
@test state_1.cmat.ngens == 8
|
||||
@test state_1.cmat.nlegs == 8
|
||||
state_2 = QuantumLegos.State([lego, lego], Tuple{LegoLeg, LegoLeg}[])
|
||||
@test state_1 == state_2
|
||||
@test all(state_2.cmat.cmat[5:8, 1:4] .== false) # block diagonal
|
||||
end
|
||||
@testset "2+ legos, 1+ legs" begin
|
||||
stabgens = pauliop.(["IIXX", "XXII", "IZZI", "ZIIZ"])
|
||||
lego = QuantumLegos.Lego(stabgens)
|
||||
@test_throws ArgumentError State([lego, lego], edge.([(1, 1, 1, 1)]))
|
||||
end
|
||||
@testset "is_connected_to_firstlego" begin
|
||||
stabilizers = pauliop.(["IIXXXX", "IIZZZZ", "ZIZIZI", "IZIZIZ", "IXIIXX", "XIXXII"])
|
||||
lego = Lego(stabilizers)
|
||||
let
|
||||
state =
|
||||
State(fill(lego, 6), edge.([(3, 2, 1, 5), (5, 2, 3, 3), (4, 1, 5, 1)]))
|
||||
@test QuantumLegos.is_connected_to_firstlego(state) ==
|
||||
BitVector([1, 0, 1, 1, 1, 0])
|
||||
end
|
||||
let
|
||||
state = State(
|
||||
fill(lego, 7),
|
||||
edge.([(3, 2, 1, 5), (5, 2, 3, 3), (4, 1, 5, 1), (2, 2, 3, 1)]),
|
||||
)
|
||||
@test QuantumLegos.is_connected_to_firstlego(state) ==
|
||||
BitVector([1, 1, 1, 1, 1, 0, 0])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@testset "Doctest" begin
|
||||
DocMeta.setdocmeta!(
|
||||
QuantumLegos,
|
||||
:DocTestSetup,
|
||||
:(using QuantumLegos; ENV["JULIA_DEBUG"] = "");
|
||||
recursive = true,
|
||||
)
|
||||
doctest(QuantumLegos)
|
||||
end
|
||||
|
||||
# @testset "Code quality (Aqua.jl)" begin
|
||||
# Aqua.test_all(QuantumLegos)
|
||||
# end
|
||||
# @testset "Code linting (JET.jl)" begin
|
||||
# JET.test_package(QuantumLegos; target_defined_modules = true)
|
||||
# end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue