QuantumLegos
Documentation for QuantumLegos.
All contents:
- Details on check matrix operations
- How to calculate code distance from the state.
- QuantumLegos
- Example
- Internal(how it works)
- API
- PauliOps
Example
CheckMatrix and defining Lego
julia> using QuantumLegos
julia> stabilizers = pauliop.(["IIXXXX", "IIZZZZ", "ZIZZII", "IZZIZI", "IXXXII", "XIXIXI"])
6-element Vector{StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}}:
pauliop("IIXXXX")
pauliop("IIZZZZ")
pauliop("ZIZZII")
pauliop("IZZIZI")
pauliop("IXXXII")
pauliop("XIXIXI")
julia> cmat = checkmatrix(stabilizers)
CheckMatrix with 6 generators, 6 legs:
0 0 1 1 1 1 | 0 0 0 0 0 0
0 0 0 0 0 0 | 0 0 1 1 1 1
0 0 0 0 0 0 | 1 0 1 1 0 0
0 0 0 0 0 0 | 0 1 1 0 1 0
0 1 1 1 0 0 | 0 0 0 0 0 0
1 0 1 0 1 0 | 0 0 0 0 0 0
julia> cmat.nlegs
6
julia> cmat.ngens
6
julia> cmat.cmat
6×12 Matrix{Bool}:
0 0 1 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 1
0 0 0 0 0 0 1 0 1 1 0 0
0 0 0 0 0 0 0 1 1 0 1 0
0 1 1 1 0 0 0 0 0 0 0 0
1 0 1 0 1 0 0 0 0 0 0 0
julia> # define lego
julia> lego = Lego(stabilizers)
Lego{6}(6, StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}[pauliop("IIXXXX"), pauliop("IIZZZZ"), pauliop("ZIZZII"), pauliop("IZZIZI"), pauliop("IXXXII"), pauliop("XIXIXI")])
julia> lego.stabgens |> checkmatrix
CheckMatrix with 6 generators, 6 legs:
0 0 1 1 1 1 | 0 0 0 0 0 0
0 0 0 0 0 0 | 0 0 1 1 1 1
0 0 0 0 0 0 | 1 0 1 1 0 0
0 0 0 0 0 0 | 0 1 1 0 1 0
0 1 1 1 0 0 | 0 0 0 0 0 0
1 0 1 0 1 0 | 0 0 0 0 0 0
Defining and Updating State
julia> using QuantumLegos
julia> stabilizers = pauliop.(["IIXXXX", "IIZZZZ", "ZIZZII", "IZZIZI", "IXXXII", "XIXIXI"])
6-element Vector{StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}}:
pauliop("IIXXXX")
pauliop("IIZZZZ")
pauliop("ZIZZII")
pauliop("IZZIZI")
pauliop("IXXXII")
pauliop("XIXIXI")
julia> lego = Lego(stabilizers)
Lego{6}(6, StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}[pauliop("IIXXXX"), pauliop("IIZZZZ"), pauliop("ZIZZII"), pauliop("IZZIZI"), pauliop("IXXXII"), pauliop("XIXIXI")])
julia> # state with 1 lego, 0 leg
julia> st = State([lego, ], Tuple{LegoLeg, LegoLeg}[])
State(Lego[Lego{6}(6, StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}[pauliop("IIXXXX"), pauliop("IIZZZZ"), pauliop("ZIZZII"), pauliop("IZZIZI"), pauliop("IXXXII"), pauliop("XIXIXI")])], Tuple{LegoLeg, LegoLeg}[], CheckMatrix(Bool[0 0 … 0 0; 0 0 … 1 1; … ; 0 1 … 0 0; 1 0 … 0 0], 6, 6))
julia> st.cmat.cmat
6×12 Matrix{Bool}:
0 0 1 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 1
0 0 0 0 0 0 1 0 1 1 0 0
0 0 0 0 0 0 0 1 1 0 1 0
0 1 1 1 0 0 0 0 0 0 0 0
1 0 1 0 1 0 0 0 0 0 0 0
julia> add_lego!(st, lego)
State(Lego[Lego{6}(6, StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}[pauliop("IIXXXX"), pauliop("IIZZZZ"), pauliop("ZIZZII"), pauliop("IZZIZI"), pauliop("IXXXII"), pauliop("XIXIXI")]), Lego{6}(6, StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}[pauliop("IIXXXX"), pauliop("IIZZZZ"), pauliop("ZIZZII"), pauliop("IZZIZI"), pauliop("IXXXII"), pauliop("XIXIXI")])], Tuple{LegoLeg, LegoLeg}[], CheckMatrix(Bool[0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0], 12, 12))
julia> st.cmat.cmat
12×24 Matrix{Bool}:
0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0
0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
julia> # state with 2 legos, 0 leg
julia> st2 = State([lego, lego], Tuple{LegoLeg, LegoLeg}[])
State(Lego[Lego{6}(6, StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}[pauliop("IIXXXX"), pauliop("IIZZZZ"), pauliop("ZIZZII"), pauliop("IZZIZI"), pauliop("IXXXII"), pauliop("XIXIXI")]), Lego{6}(6, StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}[pauliop("IIXXXX"), pauliop("IIZZZZ"), pauliop("ZIZZII"), pauliop("IZZIZI"), pauliop("IXXXII"), pauliop("XIXIXI")])], Tuple{LegoLeg, LegoLeg}[], CheckMatrix(Bool[0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0], 12, 12))
julia> st == st2
true2 Lego 1 edge state
julia> using QuantumLegos
julia> stabilizers = pauliop.(["IIXXXX", "IIZZZZ", "ZIZZII", "IZZIZI", "IXXXII", "XIXIXI"])
6-element Vector{StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}}:
pauliop("IIXXXX")
pauliop("IIZZZZ")
pauliop("ZIZZII")
pauliop("IZZIZI")
pauliop("IXXXII")
pauliop("XIXIXI")
julia> lego = Lego(stabilizers)
Lego{6}(6, StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}[pauliop("IIXXXX"), pauliop("IIZZZZ"), pauliop("ZIZZII"), pauliop("IZZIZI"), pauliop("IXXXII"), pauliop("XIXIXI")])
julia> state = State([lego, lego], edge.([((1, 3), (2, 3))]))
State(Lego[Lego{6}(6, StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}[pauliop("IIXXXX"), pauliop("IIZZZZ"), pauliop("ZIZZII"), pauliop("IZZIZI"), pauliop("IXXXII"), pauliop("XIXIXI")]), Lego{6}(6, StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}[pauliop("IIXXXX"), pauliop("IIZZZZ"), pauliop("ZIZZII"), pauliop("IZZIZI"), pauliop("IXXXII"), pauliop("XIXIXI")])], Tuple{LegoLeg, LegoLeg}[(LegoLeg(1, 3), LegoLeg(2, 3))], CheckMatrix(Bool[1 0 … 0 0; 0 1 … 0 0; … ; 0 0 … 1 1; 0 0 … 0 1], 10, 10))
julia> state.cmat
CheckMatrix with 10 generators, 10 legs:
1 0 1 0 1 0 0 0 0 0 | 0 0 0 0 0 0 0 0 0 0
0 1 0 1 1 0 0 0 0 0 | 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 0 0 1 1 1 | 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 1 0 1 | 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 1 1 | 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 | 1 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 | 0 1 1 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 | 0 0 1 1 1 0 0 1 1 1
0 0 0 0 0 0 0 0 0 0 | 0 0 0 0 0 1 0 0 1 1
0 0 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 1 1 0 1
julia> pg = state.cmat |> generators |> GeneratedPauliGroup
GeneratedPauliGroup{10}(StaticArraysCore.SVector{10, QuantumLegos.PauliOps.SinglePauliOp}[pauliop("XIXIXIIIII"), pauliop("IXIXXIIIII"), pauliop("IIXXXIIXXX"), pauliop("IIIIIXIXIX"), pauliop("IIIIIIXIXX"), pauliop("ZIIZZIIIII"), pauliop("IZZIZIIIII"), pauliop("IIZZZIIZZZ"), pauliop("IIIIIZIIZZ"), pauliop("IIIIIIZZIZ")], IterTools.Subsets{Vector{StaticArraysCore.SVector{N, QuantumLegos.PauliOps.SinglePauliOp} where N}}(StaticArraysCore.SVector{N, QuantumLegos.PauliOps.SinglePauliOp} where N[pauliop("XIXIXIIIII"), pauliop("IXIXXIIIII"), pauliop("IIXXXIIXXX"), pauliop("IIIIIXIXIX"), pauliop("IIIIIIXIXX"), pauliop("ZIIZZIIIII"), pauliop("IZZIZIIIII"), pauliop("IIZZZIIZZZ"), pauliop("IIIIIZIIZZ"), pauliop("IIIIIIZZIZ")]))
julia> pauliop("XIIXIXIIXI") in pg
true
Internal(how it works)
Notes on Overall flow
Details on [1]
- state is translated to a single check matrix
- the size is ≤ $N \times 2N$ where $N$ is maximum number of lego logs.
- any contraction can be performed on this single check matrix
- if the check matrix can be represented as direct sum of matrices with $k N$ columns where $k ∈ ℕ$, then they are not contracted
Construction of State
Construction of State is completed by calling State constructor recursively.
- Construct
Statewithout edge. Just adding legos. Checkmatrix is just a direct sum of each lego's checkmatrix - Concatenate each edges. During this operation, self tracing of checkmatrix is evaluated.
Each constructor calls action function (which is a map from State to State). Therefore, action functions can be used both for direct construction of State and action application to State during the game.
API
QuantumLegos.PauliOpsQuantumLegos.CheckMatrixQuantumLegos.LegoQuantumLegos.LegoLegQuantumLegos.PauliOps.GeneratedPauliGroupQuantumLegos.PauliOps.PauliOpQuantumLegos.PauliOps.SinglePauliOpQuantumLegos.StateQuantumLegos.PauliOps.pauliopQuantumLegos.PauliOps.single_pauliopQuantumLegos.PauliOps.weightQuantumLegos.PauliOps.xweightQuantumLegos.PauliOps.zweightQuantumLegos._naive_distanceQuantumLegos.add_edge!QuantumLegos.add_lego!QuantumLegos.align_row!QuantumLegos.checkmatrixQuantumLegos.cmat_indexQuantumLegos.direct_sumQuantumLegos.distanceQuantumLegos.edgeQuantumLegos.edgeQuantumLegos.edgeQuantumLegos.edgeQuantumLegos.eliminate_column!QuantumLegos.eliminate_dependent_row!QuantumLegos.generatorsQuantumLegos.is_connected_to_firstlegoQuantumLegos.ref!QuantumLegos.self_trace!QuantumLegos.xpartQuantumLegos.zpart
QuantumLegos.Lego — TypeQuantum lego with N legs.
Fields
nlegs::Int64: number of legs, equalsNstabgens::SVector{N, PauliOp{N}}: stabilizer generators. vector ofPauliOp
Constructor
Lego([nlegs::Integer], stabgens::AbstractVector{PauliOp{N}})Constructor for Lego. nlegs is optional (default is length of the first stabilizer generator).
Example
julia> stabgens = pauliop.(["II", "XX"])
2-element Vector{StaticArraysCore.SVector{2, QuantumLegos.PauliOps.SinglePauliOp}}:
pauliop("II")
pauliop("XX")
julia> Lego(stabgens)
Lego{2}(2, StaticArraysCore.SVector{2, QuantumLegos.PauliOps.SinglePauliOp}[pauliop("II"), pauliop("XX")])QuantumLegos.LegoLeg — Typemutable struct StateTo be used in State.
Fields
lego_id::Int64: index inlegosinStateedge_id::Int64: index inLegoinlegosinState. No validation check included inLegoLeg.
Example
julia> x = LegoLeg.([(2, 1), (1, 1), (1, 0)])
3-element Vector{LegoLeg}:
LegoLeg(2, 1)
LegoLeg(1, 1)
LegoLeg(1, 0)
julia> sort(x)
3-element Vector{LegoLeg}:
LegoLeg(1, 0)
LegoLeg(1, 1)
LegoLeg(2, 1)QuantumLegos.State — Typemutable struct StateState (in p.4)
Fields
legos:Vector{Lego}edges: Vector of ((lego_i, leg_n), (lego_j, leg_m)). Each element is sorted (i.e.lego_i < lego_jorlego_i == lego_j && leg_n < leg_m). This feature is used inis_connected_to_firstlego.cmat::CheckMatrix: CheckMatrix
Constructor
State(legos::Vector{Lego{N}}, edges::Vector{Tuple{LegoLeg, LegoLeg}})Methods with
Example
TODO
QuantumLegos._naive_distance — MethodCalculate distance. Use minimum distance of all generated normalizers.
QuantumLegos.add_edge! — Methodadd_edge!(state::State, leg_1::LegoLeg, leg_2::LegoLeg)::StateAdd a new edge between leg_1 and leg_2, updating state.
QuantumLegos.add_lego! — Methodadd_lego!(state::State, lego::Lego) -> StateAdd a new lego, updating state.
QuantumLegos.cmat_index — Methodcmat_index(state::State, leg::LegoLeg)::Int64Get column index corresponds to leg in check matrix of state. If given leg is already connected, it throws ArgumentError. If given lego_id of leg is out of state.legos, throws ArgumentError.
QuantumLegos.distance — Methoddistance(state::State) -> IntCalculate code distance when the first leg of state is assigned as logical.
QuantumLegos.edge — FunctionHelper function to create Tuple{LegoLeg, LegoLeg} to represent edge.
QuantumLegos.edge — Methodedge(t::Tuple{T, T, T, T}) where {T <: Integer}QuantumLegos.edge — Methodedge(t::Tuple{T, T}) where {T <: Tuple{Integer, Integer}}QuantumLegos.edge — Methodedge(x::T, y::T, z::T, w::T) where {T <: Integer}QuantumLegos.is_connected_to_firstlego — Methodis_connected_to_firstlego(state::State)::BitVectorReturns vector which stores whether each lego is connected to the first lego.