init (migrating and renaming)

This commit is contained in:
qwjyh 2024-05-07 11:11:07 +09:00
commit f772e27182
19 changed files with 2262 additions and 0 deletions

6
docs/Project.toml Normal file
View file

@ -0,0 +1,6 @@
[deps]
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
IterTools = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
Legos = "6c892f99-6e80-4382-8dc3-97545b5cb80e"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"

23
docs/make.jl Normal file
View file

@ -0,0 +1,23 @@
#! format: off
using Legos
using Documenter
DocMeta.setdocmeta!(Legos, :DocTestSetup, :(using Legos); recursive=true)
makedocs(;
modules=[Legos],
authors="",
# repo="",
sitename="Legos.jl",
format=Documenter.HTML(;
prettyurls=get(ENV, "CI", "false") == "true",
edit_link="main",
assets=String[],
),
pages=[
"Home" => "index.md",
"PauliOps" => "pauliops.md",
"checkmatrix.md",
"distance.md",
],
)

82
docs/src/checkmatrix.md Normal file
View file

@ -0,0 +1,82 @@
# Details on check matrix operations
## Basic features of check matrix
- All action on state can be represented as operations on check matrix.
- QuantumLegos which don't connect each other are represented by block diagonal check matrix.
Thus, one needs only one check matrix to represent state.
- Generated group from generators represented by check matrix is invariant under row-swap and row-multiplying transforms on the check matrix.
Thus, one can freely perform these row operations on check matrices.
## Construction of check matrices and retrieving features
Use [`CheckMatrix`](@ref) from `Matrix{Bool}` and [`checkmatrix`](@ref) from `Vector{PauliOp}`.
```@docs
CheckMatrix
checkmatrix
```
Get xpart and zpart of check matrix.
```@docs
QuantumLegos.xpart
QuantumLegos.zpart
```
Get generators from check matrix with [`generators`](@ref).
```@docs
generators
```
See also, [`GeneratedPauliGroup`](@ref) and [`Base.Set`](https://docs.julialang.org/en/v1/base/collections/#Base.Set) to get group generated by generators.
## Direct sum
Used when adding lego without edge.
```@docs
QuantumLegos.direct_sum
```
## Self-tracing
### self-tracing
```@docs
QuantumLegos.self_trace!
```
During self-tracing, pre-formatting and post-formatting described below is performed.
### pre-formatting
```@docs
QuantumLegos.eliminate_column!
```
```@docs
QuantumLegos.align_row!
```
[`QuantumLegos.align_row!`](@ref)
By this process, all columns to be traced have `1`s on only 1st to 4th rows.
So during [`QuantumLegos.self_trace!`](@ref), all stabilizers generated from top three rows are calculated and perform operator matching.
### post-formatting
Remove rows which are linear combinations of other rows.
```@docs
QuantumLegos.ref!
```
```@docs
QuantumLegos.eliminate_dependent_row!
```

236
docs/src/distance.md Normal file
View file

@ -0,0 +1,236 @@
# How to calculate code distance from the state.
!!! warning "WIP"
This document is not fully completed.
## Definition of code distance.
Let's consider encoding circuit with $1$ logical bit and $k$ physical qubits[^1].
Then this encoding has two physical basis, $\ket{0}_L$ and $\ket{1}_L$.
The **distance** of this encoding is the minimum bit flip required to convert between $\ket{0}_L$ and $\ket{1}_L$.
[^1]: Not all state can be formalized like this. TODO
## Classification of the stabilizers.
When treating `State`, the logical leg is not assigned and one can treat all stabilizers equally.
However, if logical leg is assigned to the state, these stabilizers can be classified to $4$ groups.
1. stabilizers on physical qubits
2. $\bar{X}$, which corresponds to logical $X$
3. $\bar{Z}$, which corresponds to logical $Z$
4. $\bar{Y}$, which corresponds to logical $Y$
Let $\ket{V}$ is the dual state of the channel or encoding map $[[n, 1, d]]$,
```math
distance = \min_{S \in stabilizers} \#\left\{ i \mid \bar{Z}_i ≠ S_i \right\}
```
## Calculating code distance from the check matrix.
TODO: nor required if the performance doesn't matter.
## Examples
### $[[5, 1, 3]]$ code
$[[5, 1, 3]]$ code has $4$ stabilizers generators, $XZZXI, IXZZX, XIXZZ, ZXIXZ$ and $2$ logical operators, $\bar{X} = XXXXX$ and $\bar{Z} = ZZZZZ$.
Therefore, stabilizer generators for the corresponding state $[[6, 0]]$ is $IXZZXI, IIXZZX, IXIXZZ, IZXIXZ, XXXXXX, ZZZZZZ$.
Let's construct $[[6, 0]]$ state on QuantumLegos.jl.
```jldoctest 1
julia> using QuantumLegos
julia> stab_513 = pauliop.(["IXZZXI", "IIXZZX", "IXIXZZ", "IZXIXZ", "XXXXXX", "ZZZZZZ"])
6-element Vector{StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}}:
pauliop("IXZZXI")
pauliop("IIXZZX")
pauliop("IXIXZZ")
pauliop("IZXIXZ")
pauliop("XXXXXX")
pauliop("ZZZZZZ")
julia> lego_513 = Lego(stab_513)
Lego{6}(6, StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}[pauliop("IXZZXI"), pauliop("IIXZZX"), pauliop("IXIXZZ"), pauliop("IZXIXZ"), pauliop("XXXXXX"), pauliop("ZZZZZZ")])
julia> state_513 = State([lego_513], edge.([]))
State(Lego[Lego{6}(6, StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}[pauliop("IXZZXI"), pauliop("IIXZZX"), pauliop("IXIXZZ"), pauliop("IZXIXZ"), pauliop("XXXXXX"), pauliop("ZZZZZZ")])], Tuple{LegoLeg, LegoLeg}[], CheckMatrix(Bool[0 1 … 0 0; 0 0 … 1 0; … ; 1 1 … 0 0; 0 0 … 1 1], 6, 6))
```
Then collect generators of the state.
```jldoctest 1
julia> normalizers = state_513.cmat |> generators |> GeneratedPauliGroup |> collect
64-element Vector{StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}}:
pauliop("IIIIII")
pauliop("IXZZXI")
pauliop("IIXZZX")
pauliop("IXYIYX")
pauliop("IXIXZZ")
pauliop("IIZYYZ")
pauliop("IXXYIY")
pauliop("IIYXXY")
pauliop("IZXIXZ")
pauliop("IYYZIZ")
pauliop("YYIZZI")
pauliop("YXZYZX")
pauliop("YIIXYX")
pauliop("YXYXII")
pauliop("YIXYXI")
pauliop("YIZZIY")
pauliop("YXIIXY")
pauliop("YIYIZZ")
pauliop("YXXZYZ")
```
Get stabilizer and normalizers of the $[[5, 1, 3]]$ code by assigning the first leg as logical.
```jldoctest 1
julia> stabs = filter(x -> x[1] == PauliOps.I, normalizers)
16-element Vector{StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}}:
pauliop("IIIIII")
pauliop("IXZZXI")
pauliop("IIXZZX")
pauliop("IXYIYX")
pauliop("IXIXZZ")
pauliop("IIZYYZ")
pauliop("IXXYIY")
pauliop("IIYXXY")
pauliop("IZXIXZ")
pauliop("IYYZIZ")
pauliop("IZIZYY")
pauliop("IYZIZY")
pauliop("IYXXYI")
pauliop("IZYYZI")
pauliop("IYIYXX")
pauliop("IZZXIX")
julia> norm_x = filter(x -> x[1] == PauliOps.X, normalizers)
16-element Vector{StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}}:
pauliop("XXXXXX")
pauliop("XIYYIX")
pauliop("XXIYYI")
pauliop("XIZXZI")
pauliop("XIXIYY")
pauliop("XXYZZY")
pauliop("XIIZXZ")
pauliop("XXZIIZ")
pauliop("XYIXIY")
pauliop("XZZYXY")
pauliop("XYXYZZ")
pauliop("XZYXYZ")
pauliop("XZIIZX")
pauliop("XYZZYX")
pauliop("XZXZII")
pauliop("XYYIXI")
julia> norm_y = filter(x -> x[1] == PauliOps.Y, normalizers)
16-element Vector{StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}}:
pauliop("YYYYYY")
pauliop("YZXXZY")
pauliop("YYZXXZ")
pauliop("YZIYIZ")
pauliop("YZYZXX")
pauliop("YYXIIX")
pauliop("YZZIYI")
pauliop("YYIZZI")
pauliop("YXZYZX")
pauliop("YIIXYX")
pauliop("YXYXII")
pauliop("YIXYXI")
pauliop("YIZZIY")
pauliop("YXIIXY")
pauliop("YIYIZZ")
pauliop("YXXZYZ")
julia> norm_z = filter(x -> x[1] == PauliOps.Z, normalizers)
16-element Vector{StaticArraysCore.SVector{6, QuantumLegos.PauliOps.SinglePauliOp}}:
pauliop("ZZZZZZ")
pauliop("ZYIIYZ")
pauliop("ZZYIIY")
pauliop("ZYXZXY")
pauliop("ZYZYII")
pauliop("ZZIXXI")
pauliop("ZYYXZX")
pauliop("ZZXYYX")
pauliop("ZIYZYI")
pauliop("ZXXIZI")
pauliop("ZIZIXX")
pauliop("ZXIZIX")
pauliop("ZXYYXZ")
pauliop("ZIXXIZ")
pauliop("ZXZXYY")
pauliop("ZIIYZY")
```
These normalizers are generated from one logical operator and stabilizers.
```jldoctest 1
julia> map(x -> x .* pauliop("XXXXXX"), stabs) |> Set == Set(norm_x)
true
julia> map(x -> x .* pauliop("ZZZZZZ"), stabs) |> Set == Set(norm_x)
false
julia> map(x -> x .* pauliop("ZZZZZZ"), stabs) |> Set == Set(norm_z)
true
julia> map(x -> x .* pauliop("YYYYYY"), stabs) |> Set == Set(norm_y)
true
julia> using IterTools
julia> groupby(x -> x[1], normalizers) .|> Set == Set.([stabs, norm_x, norm_z, norm_y])
true
```
Define a function to get weight of the operator.
```jldoctest 1
julia> function weight(x, i = 1)
count(x[i:end] .!= PauliOps.I)
end
weight (generic function with 2 methods)
julia> weight(pauliop("XIXIXI"))
3
julia> weight(pauliop("XIXIXI"), 2)
2
```
Calculate coefficients of enumerator polynomial.
```jldoctest 1
julia> using DataStructures
julia> stabs .|> weight |> counter
Accumulator{Int64, Int64} with 2 entries:
0 => 1
4 => 15
julia> function weight(i::Integer)
Base.Fix2(weight, i)
end
weight (generic function with 3 methods)
julia> normalizers .|> weight(2) |> counter
Accumulator{Int64, Int64} with 4 entries:
0 => 1
4 => 15
5 => 18
3 => 30
julia> [norm_x..., norm_y..., norm_z...] .|> weight(2) |> counter
Accumulator{Int64, Int64} with 2 entries:
5 => 18
3 => 30
julia> [norm_x..., norm_y..., norm_z...] .|> weight(2) |> counter |> keys |> minimum
3
```
Code distance of the encoding is the minimum degree of the non-zero term in the normalizer's polynomial($B$) and not in the stabilizer's polynomial($A$).
So the code distance of this encoding is $3$.

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

201
docs/src/index.md Normal file
View file

@ -0,0 +1,201 @@
```@meta
CurrentModule = QuantumLegos
```
# QuantumLegos
Documentation for QuantumLegos.
All contents:
```@contents
```
# Example
## CheckMatrix and defining Lego
```jldoctest
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
```
- [`pauliop`](@ref)
- [`checkmatrix`](@ref) and [`CheckMatrix`](@ref)
- [`Lego`](@ref)
## Defining and Updating State
```jldoctest
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
true
```
## 2 Lego 1 edge state
```jldoctest
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.
1. Construct `State` without edge. Just adding legos. Checkmatrix is just a direct sum of each lego's checkmatrix
2. 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
```@index
```
```@autodocs
Modules = [QuantumLegos]
Pages = ["game.jl"]
```
[^1]: [C. Cao and B. Lackey, Approximate Bacon-Shor code and holography, J. High Energ. Phys., vol. 2021, no. 5, p. 127, May 2021, doi: 10.1007/JHEP05(2021)127.](https://doi.org/10.1007/JHEP05(2021)127)

46
docs/src/pauliops.md Normal file
View file

@ -0,0 +1,46 @@
# PauliOps
submodule
## Example
```jldoctest
julia> using QuantumLegos
julia> p = PauliOps.single_pauliop('I')
I::SinglePauliOp = 0
julia> typeof(p)
Enum QuantumLegos.PauliOps.SinglePauliOp:
I = 0
X = 1
Y = 2
Z = 3
julia> pauliop("IXYZ")
4-element PauliOp:
I::SinglePauliOp = 0
X::SinglePauliOp = 1
Y::SinglePauliOp = 2
Z::SinglePauliOp = 3
julia> typeof(ans)
SVector{4, SinglePauliOp} (alias for StaticArraysCore.SArray{Tuple{4}, QuantumLegos.PauliOps.SinglePauliOp, 1, 4})
julia> PauliOps.I * PauliOps.X
X::SinglePauliOp = 1
julia> PauliOps.X * PauliOps.Z
Y::SinglePauliOp = 2
julia> pauliop("IIX") .* pauliop("XIY")
3-element PauliOp:
X::SinglePauliOp = 1
I::SinglePauliOp = 0
Z::SinglePauliOp = 3
```
## API
```@autodocs
Modules = [PauliOps]
```