Utilities
Quples
CtrlVQE.Quples
— ModuleQuples
Qubit 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
— ModuleLinearAlgebraTools
Implement 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.0im
CtrlVQE.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.0im
CtrlVQE.LinearAlgebraTools.braket
— Methodbraket(x1, A, x2)
Compute the braket $⟨x1|A|x2⟩$.
Parameters
- A: the operator to measure. Usually an (abstract) matrix. When
A
is aMatrixList
, the operator is a Kronecker product of each matrix. - x1, x2: the states, both (abstract) vectors, to measure with respect to. Note that
x1
should be passed as a vector, NOT as a dual vector.
julia> LAT.braket([1; 0], [0 1; 1 0], [0; 1]) # ⟨0|X|1⟩
1
CtrlVQE.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
A
is 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⟩
-1
CtrlVQE.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
— ModuleQubitProjections
Implement 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.