Pauli functions
Pauli functions for evaluating products, commutations, weights and independence.
Single-qubit Pauli operators $I$, $X$, $Y$, $Z$ are represented by integers 0, 1, 2, 3, respectively. Correspondingly, multi-qubit Pauli operators are represented by vectors of integers; for example, $X ⊗ I ⊗ Z ⊗ Y$ is represented by [1, 0, 3, 2]
.
TensorNetworkCodes.pauli_are_commuting
— Functionpauli_are_commuting(operators) -> Bool
Return true if the Pauli operators mutually commute, or false otherwise, where operators
is an iterable of AbstractVector{Int}
.
Examples
julia> stabilizers = [[1, 3, 3, 1, 0], [0, 1, 3, 3, 1], [1, 0, 1, 3, 3], [3, 1, 0, 1, 3]];
julia> pauli_are_commuting(stabilizers) # stabilizers mutually commute
true
julia> logical_x, logical_z = [1, 1, 1, 1, 1], [3, 3, 3, 3, 3]; # XXXXX, ZZZZZ
julia> pauli_are_commuting([logical_x, logical_z]) # logicals do not commute
false
TensorNetworkCodes.pauli_are_independent
— Functionpauli_are_independent(operators) -> Bool
Return true if the Pauli operators are independent, or false otherwise, where operators
is an iterable of AbstractVector{Int}
. Here independence means that no operator can be expressed as a product of the others.
Examples
julia> pauli_are_independent([[3, 3, 0], [0, 3, 3]]) # ZZI, IZZ
true
julia> pauli_are_independent([[3, 3, 0], [0, 3, 3], [3, 0, 3]]) # ZZI, IZZ, ZIZ
false
TensorNetworkCodes.pauli_commutation
— Functionpauli_commutation(a::Int, b::Int) -> 0 or 1
pauli_commutation(a::AbstractVector{Int}, b::AbstractVector{Int}) -> 0 or 1
Return the commutation relation of two Paulis, i.e. 0 if they commute and 1 if not.
Examples
julia> pauli_commutation(1, 1) # X commutes with itself
0
julia> pauli_commutation(1, 3) # X does not commute with Z
1
julia> pauli_commutation([1, 3, 3, 1, 0], [1, 1, 1, 1, 1]) # XZZXI commutes with XXXXX
0
julia> stabilizers = [[1, 3, 3, 1, 0], [0, 1, 3, 3, 1], [1, 0, 1, 3, 3], [3, 1, 0, 1, 3]];
julia> error = [1, 1, 0, 0, 0]; # XXIII
julia> syndrome = pauli_commutation.(stabilizers, Ref(error))
4-element Vector{Int64}:
1
0
0
1
TensorNetworkCodes.pauli_pow
— Functionpauli_pow(a::Int, power::Int) -> Int
Return the Pauli raised to the given power.
Examples
julia> x_squared = pauli_pow(1, 2)
0
julia> z_inverse = pauli_pow(3, -1)
3
TensorNetworkCodes.pauli_product
— Functionpauli_product(a::Int, b::Int) -> Int
Return the product of two Paulis. Note that we are ignoring overall minus signs.
Examples
julia> pauli_product(1, 2) # X.Y -> Z
3
julia> pauli_product.([1, 0, 3, 2], [1, 1, 1, 3]) # (XIZY).(XXXZ) -> (IXYX)
4-element Vector{Int64}:
0
1
2
1
pauli_product(operators) -> Vector{Int}
Return the product of the Pauli operators, where operators
is an iterable of AbstractVector{Int}
.
See also pauli_product_pow
.
Examples
julia> ops = [[3, 3, 0], [0, 1, 1], [2, 0, 2]]; # ZZI, IXX, YIY
julia> pauli_product(ops)
3-element Vector{Int64}:
1
2
3
TensorNetworkCodes.pauli_product_pow
— Functionpauli_product_pow(operators, powers) -> Vector{Int}
Return the product of the Pauli operators each raised to the corresponding power, where operators
is an iterable of AbstractVector{Int}
and powers
is an iterable of Int
.
Note: The product is evaluated to the length of the shorter of the two iterables.
See also pauli_product
, pauli_pow
.
Examples
julia> ops = [[3, 3, 0], [0, 1, 1], [2, 0, 2]]; # ZZI, IXX, YIY
julia> pauli_product_pow(ops, [1, 0, 1])
3-element Vector{Int64}:
1
3
2
TensorNetworkCodes.pauli_random_operator
— Functionpauli_random_operator(n::Int, p::Real, rng::AbstractRNG=GLOBAL_RNG)
-> AbstractVector{Int}
Return a random Pauli operator on n
qubits with Paulis applied according to i.i.d. depolarizing noise with probability p
.
Examples
julia> using Random:MersenneTwister # use RNG for reproducible example
julia> pauli_random_operator(5, 0.2, MersenneTwister(13))
5-element Vector{Int64}:
3
3
0
2
0
TensorNetworkCodes.pauli_rep_change
— Functionpauli_rep_change(pauli::Int) -> Char
pauli_rep_change(pauli::Char) -> Int
Convert Pauli between alphabetical and numerical representation.
Examples
julia> pauli_rep_change(1)
'X': ASCII/Unicode U+0058 (category Lu: Letter, uppercase)
julia> pauli_rep_change('X')
1
julia> pauli_rep_change.((0, 1, 2, 3))
('I', 'X', 'Y', 'Z')
julia> pauli_rep_change.(('I', 'X', 'Y', 'Z'))
(0, 1, 2, 3)
TensorNetworkCodes.pauli_weight
— Functionpauli_weight(operator::AbstractVector{Int}) -> Int
Return the weight of the Pauli operator, i.e. the number of non-identity elements.
Examples
julia> pauli_weight([3, 0, 2, 0, 1]) # ZIYIX
3