Utilities
Quples
CtrlVQE.Quples — ModuleQuplesQubit tuples: simple types to represent couplings within a device.
CtrlVQE.Quples.Quple — TypeQuple(q1,q2)A (symmetric) coupling between qubits indexed by q1 and q2.
The order is irrelevant: Quple(q1,q2) === Quple(q2,q1).
LinearAlgebraTools
CtrlVQE.LinearAlgebraTools — ModuleLinearAlgebraToolsImplement some frequently-used linear-algebraic operations.
Consider this to be a shallow extension of Julia's standard LinearAlgebra module, taking advantage of Allocations whenever possible.
Note that this module does not export anything. This is intentional - the risk of name collisions is very high with this module, so I insist that no one ever writes using LinearAlgebraTools.
CtrlVQE.LinearAlgebraTools.MatrixList — TypeMatrixList{T}Semantic alias for a 3d array representing a distinct matrix for each final index.
In other words, think of a MatrixList Ā semantically as a list A where each A[i] = Ā[:,:,i] is a matrix.
CtrlVQE.LinearAlgebraTools.VectorList — TypeVectorList{T}Semantic alias for a 2d array representing a distinct vector in each column.
This is philosophically (but not operationally) distinct from a Matrix, which may imply some additional structure relating columns.
CtrlVQE.LinearAlgebraTools.basisvector — Methodbasisvector(N::Int, i::Int; result=nothing)Construct a length-N basis vector for index i.
The result is written to result if provided. Otherwise returns a vector of type Bool.
basisvector(::Type{T}, N::Int, i::Int)Construct a length-N basis vector of type T for index i.
julia> LAT.basisvector(4, 2)
4-element Vector{Bool}:
0
1
0
0
julia> LAT.basisvector(ComplexF64, 4, 2)
4-element Vector{ComplexF64}:
0.0 + 0.0im
1.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0imCtrlVQE.LinearAlgebraTools.basisvectors — Methodbasisvectors(N::Int)Construct a matrix of length-N basis vectors, aka an identity matrix.
The result is written to result if provided. Otherwise returns a matrix of type Bool.
basisvectors(::Type{T}, N::Int)Construct a size-N identity matrix of type T.
julia> LAT.basisvectors(4)
4×4 Matrix{Bool}:
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
julia> LAT.basisvectors(ComplexF64, 4)
4×4 Matrix{ComplexF64}:
1.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im
0.0+0.0im 1.0+0.0im 0.0+0.0im 0.0+0.0im
0.0+0.0im 0.0+0.0im 1.0+0.0im 0.0+0.0im
0.0+0.0im 0.0+0.0im 0.0+0.0im 1.0+0.0imCtrlVQE.LinearAlgebraTools.braket — Methodbraket(x1, A, x2)Compute the braket $⟨x1|A|x2⟩$.
Parameters
- A: the operator to measure. Usually an (abstract) matrix. When
Ais aMatrixList, the operator is a Kronecker product of each matrix. - x1, x2: the states, both (abstract) vectors, to measure with respect to. Note that
x1should be passed as a vector, NOT as a dual vector.
julia> LAT.braket([1; 0], [0 1; 1 0], [0; 1]) # ⟨0|X|1⟩
1CtrlVQE.LinearAlgebraTools.cis! — Functioncis!(A::AbstractMatrix, x=1)Calculates $\exp(ixA)$ for a Hermitian matrix A.
The name comes from the identity exp(ix) = Cos(x) + I Sin(x).
Note that this method mutates A itself to the calculated exponential. Therefore, A must have a complex float type, and it must not be an immutable view. For example, even though A must be Hermitian for this method to work correctly, it can't actually be a LinearAlgebra.Hermitian view.
julia> A = ComplexF64[0 1; 1 0];
julia> LAT.cis!(A, π/4) * √2
2×2 Matrix{ComplexF64}:
1.0+0.0im 0.0+1.0im
0.0+1.0im 1.0+0.0im
CtrlVQE.LinearAlgebraTools.cis_type — Methodcis_type(x)Promote the number type of x to a complex float (compatible with cis operations).
The argument x may be a number, an array of numbers, or a number type itself.
CtrlVQE.LinearAlgebraTools.eigen! — Methodeigen!(Λ::Vector, U::Matrix, A::Matrix)Diagonalize a matrix with minimal allocations.
Parameters
- Λ: Vector where eigenvalues are written.
- U: Matrix where eigenvectors are written.
U[:,i]corresponds toΛ[i]. - A: An (abstract) matrix to diagonalize - assumed to be Hermitian.
Returns
This function explicitly returns nothing.
julia> Λ = zeros(2);
julia> U = zeros(2,2);
julia> LAT.eigen!(Λ, U, Float64[0 1; 1 0]);
julia> Λ
2-element Vector{Float64}:
-1.0
1.0
julia> U * √2
2×2 Matrix{Float64}:
1.0 1.0
-1.0 1.0
CtrlVQE.LinearAlgebraTools.expectation — Methodexpectation(A, x)Compute the braket $⟨x|A|x⟩$.
Parameters
- A: the operator to measure. Usually a matrix. When
Ais aMatrixList, the operator is a Kronecker product of each matrix. - x: the state (a vector) to measure with respect to.
julia> LAT.expectation([1 0; 0 -1], [0; 1]) # ⟨1|Z|1⟩
-1CtrlVQE.LinearAlgebraTools.globalize — Methodglobalize(op::AbstractMatrix, n::Int, q::Int; result=nothing)Extend a local operator op acting on qubit q, into the global Hilbert space of n qubits.
The array is stored in result if provided.
julia> LAT.globalize([0 1; 1 0], 2, 1) # X⊗I
4×4 Matrix{Int64}:
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
julia> LAT.globalize([0 1; 1 0], 2, 2) # I⊗X
4×4 Matrix{Int64}:
0 1 0 0
1 0 0 0
0 0 0 1
0 0 1 0
CtrlVQE.LinearAlgebraTools.kron — Functionfunction kron(Ā; result=nothing)Construct the Kronecker product of each element of Ā.
Parameters
- Ā: either a
MatrixList(to construct a large matrix) or aVectorList(to construct a large vector)
Ordering: [x1; x2] ⊗ [y1; y2] = [x1⋅y1l x1⋅y2; x2⋅y1; x2⋅y2]
Optionally, pass a pre-allocated array of compatible type and shape as result.
julia> LAT.kron([1 0; 0 1]) # |0⟩⊗|1⟩
4-element Vector{Int64}:
0
1
0
0
julia> LAT.kron([0 1; 1 0;;; 0 1; 1 0]) # X⊗X
4×4 Matrix{Int64}:
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
CtrlVQE.LinearAlgebraTools.rotate! — Functionrotate!(R, x)Apply the rotation R to the object x, mutating x.
Generally, R is a unitary (or orthogonal) matrix. If x is a vector, rotate! computes $x ← Rx$. If x is a matrix, rotate! computes $x ← RxR'$.
You may also pass R as a MatrixList, which is interpreted as a rotation with a factorized tensor structure. In other words, if r̄ is a MatrixList, rotate!(r̄, x) is equivalent to rotate!(kron(r̄), x), except that the former has a more efficient implementation.
Since this method mutates x, the number type of x must be sufficiently expressive. For example, if R is a unitary matrix, x had better be a vector of complex floats.
julia> LAT.rotate!([0 1; 1 0], [1; 0]) # X|0⟩
2-element Vector{Int64}:
0
1
julia> LAT.rotate!([0 1; 1 0], [1 0; 0 -1]) # XZX'
2×2 Matrix{Int64}:
-1 0
0 1
QubitOperations
CtrlVQE.QubitProjections — ModuleQubitProjectionsImplement some handy tools for working with specifically two-level systems.
CtrlVQE.QubitProjections.isometrize — Methodisometrize(A, n, m; result)Lift or reduce a statevector or matrix for n qubits onto a physical Hilbert space with just m levels per qubit.
If result is provided, results are written to result without further allocation.
CtrlVQE.QubitProjections.isometry — Methodisometry(n, m; m0=2, result)An isometry lifting or reducing a system over m0 levels to m levels.
The result is an (m^n⨯m0^n) matrix, acting on a vector with n qubits of m0 levels each, and producing a vector with n qubits of m levels each.
If result is provided, results are written to result without further allocation.
CtrlVQE.QubitProjections.localisometries — Methodlocalisometries(n, m; m0=2, result)A matrix list (aka a 3d array) of n local qubit isometries.
Each isometry is an (m⨯m0) matrix, acting on a vector with m0 levels and producing a vector with m levels.
If result is provided, results are written to result without further allocation.
CtrlVQE.QubitProjections.localprojectors — Methodlocalprojectors(n, m; m0=2, result)A matrix list (aka a 3d array) of n local qubit projectors.
Each projector is an (m⨯m) matrix, acting on a vector with m levels and producing a vector with the same size, but support on only m0 levels.
If result is provided, results are written to result without further allocation.
CtrlVQE.QubitProjections.mapindex — Functionmapindex(i0, n, m, m0=2)Given an index i0 defined for vectors of n qubits with m0 levels each, compute the corresponding index in a space with m levels each.
This function assumes m > m0. Otherwise, there may not be a corresponding index!
CtrlVQE.QubitProjections.nlevels — Methodnlevels(N, n)Infer the number of levels per qubit from the number of states and qubits.
CtrlVQE.QubitProjections.nqubits — Functionnqubits(N, m=2)Infer the number of qubits from the number of states and levels per qubit.
CtrlVQE.QubitProjections.nstates — Functionnstates(n, m=2)Infer the number of states from the number of qubits and levels per qubit.
CtrlVQE.QubitProjections.projector — Methodprojector(n, m; m0=2, result)A projector from a system with m levels per qubit onto one with m0 levels.
The result is an (m^n⨯m^n) matrix, acting on a vector with n qubits of m levels each, producing a vector of the same size but where each qubit has support on only the first m0 levels.
If result is provided, results are written to result without further allocation.