FLOYao.FLOYaoModule

A Yao.jl backend to efficiently simulate fermionic linear optics (FLO) circuits based on Classical simulation of noninteracting-fermion quantum circuits and Disorder-assisted error correction in Majorana chains. FLO circuits are a class of quantum circuits that are closely related to non-interacting fermions and can be efficiently simulated on classical computers, similar to the way Clifford circuits can be efficiently classically simulated, as is done in YaoClifford.jl.

The goal of FLOYao.jl is that if you have code written in Yao.jl that only uses FLO gates and other primitives that are efficiently simulatable in polynomial time and space, that you can simply replace your AbstractArrayReg with a MajoranaReg and run exactly the same simulation, with the same code but exponentially faster.

A brief introduction to fermionic linear optics circuits is found in the Documentation and a more in-depth introduction in e.g. the two papers linked above.

FLOYao.MajoranaRegType
MajoranaReg{T} <: AbstractRegister{2}
MajoranaReg(state::AbstractMatrix{T<:Real})

A register holding the "state" of a Majorana operators when propagating through a FLO circuit as a 2n×2n matrix.

Warning

The MajoranaReg constructor will not initialize the state matrix. It is recommended to use FLOYao.zero_state or FLOYao.product_state to produce your initial state.

FLOYao.bitstring_probabilityMethod
bitstring_probability(reg::MajoranaReg, bit_string::BitStr)

The probability to measure a given bit_string when measuring reg

FLOYao.covariance_matrixMethod
covariance_matrix(reg::MajoranaReg)

The covariance matrix

\[ M_{pq} = \frac{i}{2} ⟨Ω|U^†[γ_p,γ_q]U|Ω⟩\]

of a FLO state $U|Ω⟩$.

FLOYao.fast_add!Method
fast_add!(A::AbstractMatrix, B::SparseMatrixCSC)

Fast implementation of A .+= B for sparse B.

FLOYao.fast_overlapMethod
fast_overlap(y::AbstractVecOrMat, A::SparseMatrixCSC, x::AbstractVecOrMat)

Fast implementation of tr(y' * A * x) for sparse A.

FLOYao.kron2majoranaindicesMethod
kron2majoranaindices(k::KronBlock)

Get the indices of majorana operators from a kronecker product of pauli operators

FLOYao.majorana2arrayregMethod
majorana2arrayreg(reg::MajoranaReg)

Converts a 2n×2n MajoranaReg reg into a 2^n ArrayReg.

Note

This implementation is not very clever and should mainly be used for debugging purposes with small numbers of qubits. It pipes a random state $|ψ⟩$ through the projector $U|Ω⟩⟨Ω|U^†$ which may give inaccurate results if $⟨ψ|U|ψ⟩$ is very small.

FLOYao.majorana_expectMethod
majorana_expect(block::AbstractMatrix, locs, reg::MajoranaReg)

Calculate ⟨reg|block|reg⟩ where block is a hamiltonian written as the coefficients in a sum of squares of Majorana operators and reg a MajoranaReg.

FLOYao.majoranaopMethod

Majorana operator in a system with n on site Majorana site i

FLOYao.majoranasquares2qubitbasisMethod
majoranasquares2qubitbasis(H::AbstractMatrix)

Converts an $2n×2n$ Majorana hamiltonian H into the full $2^n×2^n$ hamiltonian in the qubit basis.

FLOYao.one_state!Method
one_state!(reg::MajoranaReg)

Put reg into the all ones state

FLOYao.one_stateMethod
one_state([T=Float64,] n)

Create a Majorana register on n qubits in the all one state $|1 ⋯ 1⟩$ with storage type T.

FLOYao.paulibasis2majoranasquaresFunction
paulibasis2majoranasquares(P::AbstractVector, locs=1:log4(length(P)))

Convert an operator written in the Pauli basis as a $4^n$-element vector to the corresponding $2n×2n$ matrix of coefficients of products of two Majorana operators.

Throws a NonFLOException if P contains terms that are not corresponding to the product of two Majorana operators.

FLOYao.paulibasis2qubitopMethod
paulibasis2qubitop(P::AbstractVector)

Converts an operator to in the pauli basis to a matrix in the computational basis. Inverse to qubit2paulibasis.

FLOYao.product_state!Method
product_state!(reg::MajoranaReg, bit_str::BitStr)

Put reg into the product state described by bit_str

FLOYao.product_stateMethod
product_state([T=Float64,] bit_str::DitStr{2})
product_state([T=Float64,] bit_configs::AbstractVector)
product_state([T=Float64,] nbits::Int, val::Int)

Create an MajoranaReg of a product state.

The state can be specified as a bit string, as an array of Integers or Booleans or with nbits and val.

FLOYao.qubit2majoranaevolutionMethod
qubit2majoranaevolution(U::AbstractMatrix, locs)

Turns a $n$ qubit unitary U on the $n$ qubits in locs into the corresponding $SO(2n×2n)$ matrix for the evolution of the Majorana operators.

FLOYao.qubit2paulibasisMethod
qubit2paulibasis(A::AbstractMatrix)

Converts a $2^n×2^n$ matrix A in the standard qubit basis into a $4^n$ vector representing the same operator in the Pauli basis.

The ordering is as follows: Let $σ^0 = I, σ^1 = X, σ^2 = Y$ and $σ^3 = Z$.

Todo

Creating the dense pauli tensor product via kron and inner product via dot is much slower than neccessary, since the pauli tensor product matrix is very sparse. Much faster would be to compute the inner product directly.

FLOYao.rand_stateMethod
rand_state([Float64,] n)

Create a Haar random MajoranaReg on n qubits.

FLOYao.random_unit_vectorMethod
random_unit_vector([Float64, ] n, N=n)

Generate a uniformly random vector on the n-sphere embedded in ℝ^N and return it and the sign of its first entry.

FLOYao.reducedmatMethod
reducedmat(::Type{T}, k::KronBlock)

Matrix representation of k with only the qubits k acts on non-trivially in the tensor product. (As opposed to Yao.mat(k) which gives the full 2^n×2^n matrix)

FLOYao.sampleFunction
sample!(covmat, locs=1:size(covmat,1)÷2, ids=sortperm(locs), rng=GLOBAL_RNG)

Take a computational basis state sample from a FLO state with given covarianvematrix

Arguments

  • covmat: The 2n×2n covariance matrix $M_{ij} = i ⟨ψ|γ_i γ_j|ψ⟩ - i δ_{ij}$. This matrix will be overwritten by the function!
  • locs=1:size(covmat,1)÷2: The list of qubits to measure
  • ids=sortperm(locs): The sorting permutation for locs. You don't need to pass this, but precomputing it can make this faster
  • rng=Random.GLOBAL_RNG: The random number generator to use for sampling.

Warning

This function works inplace on the covmat argument to avoid allocations. If you need multiple samples from the same covmat, make sure to pass a copy in.

FLOYao.update_covariance_matrix!Method

Updates the covariance matrix M, given that the ith qubit was measured in the state ni with probability pi.

Warning

After this procedure only the entries M[p,q] with 2i-1 < p < q will be correct. This is sufficient to calculate measurement probabilities for j > i.

FLOYao.yaoham2majoranasquaresMethod
yaoham2majoranasquares(::Type{T}=Float64, yaoham::AbstracBlock{2})

Convert a hamiltonian written as a YaoBlock into the corresponding $2n×2n$ majorana hamiltonian.

FLOYao.zero_state!Method
zero_state!(reg::MajoranaReg)

Put reg into the computational zero state

FLOYao.zero_stateMethod
zero_state([T=Float64,] n)

Create a Majorana register on n qubits in the vacuum state $|Ω⟩$ with storage type T.

FLOYao.zero_state_likeMethod
zero_state_like(reg::AbstractRegister)

Create a Majorana register in the zero state with the same element type and number of qubits as reg.

YaoAPI.expectMethod
expect(op::AbstractBlock, reg::MajoranaReg)
expect(op::AbstractBlock, (reg => circuit)::Pair{<:MajoranaReg,<:AbstractBlock})

Get the expectation value of an operator, the second parameter can be a register reg or a pair of input register and circuit reg => circuit.

expect'(op::AbstractBlock, reg => circuit::) -> Pair{<:MajoranaReg,<:AbstractVector}
expect'(op::AbstractBlock, reg::MajoranaReg) -> MajoranaReg

Obtain the gradient with respect to registers and circuit parameters. For pair input, the second return value is a pair of gψ => gparams, with the gradient of input state and gparams the gradients of circuit parameters. For register input, the return value is a register.

YaoAPI.fidelityMethod
fidelity(reg1::MajoranaReg, reg2::MajoranaReg)

The fidelity $|⟨ψ|φ⟩|$ between the FLO states $|ψ⟩$ and $|φ⟩$ defined by reg1 and reg2.

Note

This definition differs from the standard definition $|⟨φ|ψ⟩|²$ by a square root, but is consistent with the one used in Yao.jl

Note

Computing gradients of the fidelity via fidelity'(pair_or_reg1, pair_or_reg2) is not yet supported for MajoranaRegs.

YaoAPI.measure!Method
measure!([postprocess::Union{NoPostProcess, ResetTo},] reg::MajoranaReg; rng=Random.GLOBAL_RNG)

Measure a Majorana register in the computational basis and return the resulting BitStr.

Arguments

  • postprocess: Is the post processing method
    • NoPostProcess() (the default) will collapse the state to the measurement outcome state.
    • ResetTo(bit_str) will reset the state to the product state specified by bit_str
  • reg::MajoranaReg: The quantum register
  • rng::Random.GLOBAL_RNG: The RNG to use
YaoAPI.measureMethod
measure(reg::MajoranaReg[, locs]; nshots=1, rng=Random.GLOBAL_RNG) -> Vector{BitStr}

Measure a MajoranaReg and return the results as a vector of BitStrings. This is a cheating version of measure! that does not need to recompute the reg for each new sample and also does not alter it.

Arguments

  • reg::MajoranaReg: The state register
  • locs: The list of qubits to measure. Defaults to all qubits.
  • nshots=1: The number of samples to take
  • rng=Random.GLOBAL_RNG: The random number generator to use