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_commutingFunction
pauli_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
source
TensorNetworkCodes.pauli_are_independentFunction
pauli_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
source
TensorNetworkCodes.pauli_commutationFunction
pauli_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
source
TensorNetworkCodes.pauli_powFunction
pauli_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
source
TensorNetworkCodes.pauli_productFunction
pauli_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
source
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
source
TensorNetworkCodes.pauli_product_powFunction
pauli_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
source
TensorNetworkCodes.pauli_random_operatorFunction
pauli_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
source
TensorNetworkCodes.pauli_rep_changeFunction
pauli_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)
source
TensorNetworkCodes.pauli_weightFunction
pauli_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
source