Library reference
Quantum Toolkit
Basic Quantum Objects
There are three basic quantum objects in Snowflurry to simulate a quantum system. These objects are Ket, Bra, and AbstractOperator.
Snowflurry.Ket — Type.
A Ket represents a quantum wavefunction and is mathematically equivalent to a column vector of complex values. The norm of a Ket should always be unity. A Ket representing a system with a qubit count of $n=2$ has $2^n$ states. By convention, qubit 1 is the leftmost digit, followed by every subsequent qubit. Hence, a 2-qubit Ket has 4 complex-valued coefficients $a_{ij}$, each corresponding to state $\left|ij\right\rangle$, in the following order:
$$ \psi = \begin{bmatrix} a_{00} \newline a_{10} \newline a_{01} \newline a_{11} \newline \end{bmatrix}. $$
Examples
A Ket can be initialized by using a pre-built basis such as the fock basis. See fock for further information on this function.
julia> ψ = fock(2, 4)
4-element Ket{ComplexF64}:
0.0 + 0.0im
0.0 + 0.0im
1.0 + 0.0im
0.0 + 0.0im
Although NOT the preferred way, one can also directly build a Ket object by passing a column vector as the initializer.
julia> using Snowflurry
julia> ψ = Ket([1.0; 0.0; 0.0; 0.0])
4-element Ket{ComplexF64}:
1.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
Snowflurry.Bra — Type.
A structure representing a Bra (i.e., a row vector of complex values). A Bra is created as the complex conjugate of a Ket.
Examples
julia> ψ = fock(1, 3)
3-element Ket{ComplexF64}:
0.0 + 0.0im
1.0 + 0.0im
0.0 + 0.0im
julia> _ψ = Bra(ψ)
3-element Bra{ComplexF64}:
0.0 - 0.0im
1.0 - 0.0im
0.0 - 0.0im
julia> _ψ * ψ # A Bra times a Ket is a scalar
1.0 + 0.0im
julia> ψ*_ψ # A Ket times a Bra is an operator
(3, 3)-element Snowflurry.DenseOperator:
Underlying data ComplexF64:
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
Snowflurry.DiagonalOperator — Type.
DiagonalOperator{N,T<:Complex}<:AbstractOperator
A structure representing a diagonal quantum Operator (i.e., a complex matrix of element type T, with non-zero elements all lying on the diagonal). The equivalent dense matrix would have size NxN.
Examples
julia> z = DiagonalOperator([1.0,-1.0])
(2,2)-element Snowflurry.DiagonalOperator:
Underlying data type: ComplexF64:
1.0 + 0.0im .
. -1.0 + 0.0im
julia> z = DiagonalOperator([1.0+im,1.0,1.0,0.0-im])
(4,4)-element Snowflurry.DiagonalOperator:
Underlying data type: ComplexF64:
1.0 + 1.0im . . .
. 1.0 + 0.0im . .
. . 1.0 + 0.0im .
. . . 0.0 - 1.0im
Snowflurry.AntiDiagonalOperator — Type.
AntiDiagonalOperator{N,T<:Complex}<:AbstractOperator
A structure representing a anti-diagonal quantum Operator (i.e., a complex matrix of element type T, with non-zero elements all lying on the cross-diagonal). The equivalent dense matrix would have size NxN.
Examples
julia> AntiDiagonalOperator([1, 2])
(2,2)-element Snowflurry.AntiDiagonalOperator:
Underlying data type: ComplexF64:
. 1.0 + 0.0im
2.0 + 0.0im .
Snowflurry.DenseOperator — Type.
DenseOperator{N,T<:Complex}<:AbstractOperator
A structure representing a quantum operator with a full (dense) matrix representation of size NxN and containing elements of type T.
Examples
julia> z = DenseOperator([1.0 0.0;0.0 -1.0])
(2, 2)-element Snowflurry.DenseOperator:
Underlying data ComplexF64:
1.0 + 0.0im 0.0 + 0.0im
0.0 + 0.0im -1.0 + 0.0im
Alternatively:
julia> z = rotation(π/2, -π/4)
(2, 2)-element Snowflurry.DenseOperator:
Underlying data ComplexF64:
0.7071067811865476 + 0.0im 0.4999999999999999 - 0.5im
-0.4999999999999999 - 0.5im 0.7071067811865476 + 0.0im
Snowflurry.SwapLikeOperator — Type.
SwapLikeOperator{N,T<:Complex}<:AbstractOperator
A structure representing a quantum operator performing a "swap" operation, with element type T. A phase value is applied to the swapped qubit coefficients. This operator is always of size 4x4.
For example, the iswap Operator can be built using a phase=0.0 + 1.0im by calling:
julia> SwapLikeOperator(0.0 + 1.0im)
(4, 4)-element Snowflurry.SwapLikeOperator:
Underlying data ComplexF64:
Equivalent DenseOperator:
1.0 + 0.0im 0.0 + 0.0im 0.0 + 0.0im 0.0 + 0.0im
0.0 + 0.0im 0.0 + 0.0im 0.0 + 1.0im 0.0 + 0.0im
0.0 + 0.0im 0.0 + 1.0im 0.0 + 0.0im 0.0 + 0.0im
0.0 + 0.0im 0.0 + 0.0im 0.0 + 0.0im 1.0 + 0.0im
Snowflurry.IdentityOperator — Type.
IdentityOperator{N,T<:Complex}<:AbstractOperator
A structure representing the identity quantum operator, with element type T. This operator is always of size 2x2.
Example
julia> IdentityOperator()
(2, 2)-element Snowflurry.IdentityOperator:
Underlying data ComplexF64:
Equivalent DenseOperator:
1.0 + 0.0im 0.0 + 0.0im
0.0 + 0.0im 1.0 + 0.0im
Snowflurry.SparseOperator — Type.
SparseOperator{N,T<:Complex}<:AbstractOperator
A structure representing a quantum operator with a sparse (CSR) matrix representation, with element type T. The equivalent dense matrix would have size NxN.
Warning
The apply_operator() method is not implemented for this operator type. Try using DenseOperator instead.
Examples
julia> z = SparseOperator([-1.0 1.0;0.0 -1.0])
(2, 2)-element Snowflurry.SparseOperator:
Underlying data ComplexF64:
-1.0 + 0.0im 1.0 + 0.0im
⋅ -1.0 + 0.0im
Snowflurry.Readout — Type.
Readout <: AbstractInstruction
Readout is an implementation of an AbstractInstruction that specifies an explicit measurement on a particular qubit, and the destination bit in the classical result registry (classical bit). It is built using the readout(qubit::Int, bit::Int) helper function, where the first argument is the target qubit, and the second is the destination classical bit. Measurements are always performed in the $Z$ basis (also known as the computational basis).
Examples
julia> r = readout(1, 2)
Explicit Readout object:
connected_qubit: 1
destination_bit: 2
Snowflurry.readout — Function.
readout(qubit::Int, bit::Int)
Return a Readout AbstractInstruction, which performs a readout on the target qubit, and places the result in the destination bit.
Base.adjoint — Function.
Base.adjoint(x)
Compute the adjoint (a.k.a. conjugate transpose) of a Ket, a Bra, or an Operator.
Snowflurry.is_hermitian — Function.
is_hermitian(A::AbstractOperator)
Determine if Operator A is Hermitian (i.e., self-adjoint).
Examples
julia> Y = sigma_y()
(2,2)-element Snowflurry.AntiDiagonalOperator:
Underlying data type: ComplexF64:
. 0.0 - 1.0im
0.0 + 1.0im .
julia> is_hermitian(Y)
true
julia> P = sigma_p()
(2,2)-element Snowflurry.AntiDiagonalOperator:
Underlying data type: ComplexF64:
. 1.0 + 0.0im
0.0 + 0.0im .
julia> is_hermitian(P)
false
Base.exp — Method.
exp(A::AbstractOperator)
Compute the matrix exponential of Operator A.
Examples
julia> X = sigma_x()
(2,2)-element Snowflurry.AntiDiagonalOperator:
Underlying data type: ComplexF64:
. 1.0 + 0.0im
1.0 + 0.0im .
julia> x_rotation_90_deg = exp(-im*π/4*X)
(2, 2)-element Snowflurry.DenseOperator:
Underlying data ComplexF64:
0.7071067811865475 + 0.0im 0.0 - 0.7071067811865475im
0.0 - 0.7071067811865475im 0.7071067811865475 + 0.0im
Base.getindex — Method.
getindex(A::AbstractOperator, i::Integer, j::Integer)
Access the element at row i and column j in the matrix corresponding to Operator A.
Examples
julia> Y = sigma_y()
(2,2)-element Snowflurry.AntiDiagonalOperator:
Underlying data type: ComplexF64:
. 0.0 - 1.0im
0.0 + 1.0im .
julia> Y[1,1]
0.0 + 0.0im
julia> Y[1,2]
0.0 - 1.0im
julia> Y[2,1]
0.0 + 1.0im
julia> Y[2,2]
0.0 + 0.0im
Snowflurry.expected_value — Method.
expected_value(A::AbstractOperator, psi::Ket)
Compute the expectation value ⟨ψ|A|ψ⟩ given Operator A and Ket |ψ⟩.
Examples
julia> ψ = Ket([0.0; 1.0])
2-element Ket{ComplexF64}:
0.0 + 0.0im
1.0 + 0.0im
julia> A = sigma_z()
(2,2)-element Snowflurry.DiagonalOperator:
Underlying data type: ComplexF64:
1.0 + 0.0im .
. -1.0 + 0.0im
julia> expected_value(A, ψ)
-1.0 + 0.0im
SparseArrays.sparse — Function.
sparse(x::AbstractOperator)
Returns a SparseOperator representation of x.
Examples
julia> z = sparse(sigma_z())
(2, 2)-element Snowflurry.SparseOperator:
Underlying data ComplexF64:
1.0 + 0.0im ⋅
⋅ -1.0 + 0.0im
LinearAlgebra.eigen — Function.
eigen(A::AbstractOperator)
Compute the eigenvalue decomposition of Operator A and return an Eigen factorization object F. Eigenvalues are found in F.values while eigenvectors are found in the matrix F.vectors. Each column of this matrix corresponds to an eigenvector. The ith eigenvector is extracted by calling F.vectors[:, i].
Examples
julia> X = sigma_x()
(2,2)-element Snowflurry.AntiDiagonalOperator:
Underlying data type: ComplexF64:
. 1.0 + 0.0im
1.0 + 0.0im .
julia> F = eigen(X);
julia> eigenvalues = F.values
2-element Vector{Float64}:
-1.0
1.0
julia> eigenvector_1 = F.vectors[:, 1]
2-element Vector{ComplexF64}:
-0.7071067811865475 + 0.0im
0.7071067811865475 + 0.0im
LinearAlgebra.tr — Function.
tr(A::AbstractOperator)
Compute the trace of Operator A.
Examples
julia> I = eye()
(2, 2)-element Snowflurry.DenseOperator:
Underlying data ComplexF64:
1.0 + 0.0im 0.0 + 0.0im
0.0 + 0.0im 1.0 + 0.0im
julia> trace = tr(I)
2.0 + 0.0im
Base.kron — Function.
kron(x, y)
Compute the Kronecker product of two Kets or two DenseOperator , DiagonalOperator, AntiDiagonalOperator. More details about the Kronecker product can be found here.
Examples
julia> ψ_0 = Ket([0.0; 1.0])
2-element Ket{ComplexF64}:
0.0 + 0.0im
1.0 + 0.0im
julia> ψ_1 = Ket([1.0; 0.0])
2-element Ket{ComplexF64}:
1.0 + 0.0im
0.0 + 0.0im
julia> ψ_0_1 = kron(ψ_0, ψ_1)
4-element Ket{ComplexF64}:
0.0 + 0.0im
0.0 + 0.0im
1.0 + 0.0im
0.0 + 0.0im
julia> kron(sigma_x(), sigma_y())
(4, 4)-element Snowflurry.DenseOperator:
Underlying data ComplexF64:
0.0 + 0.0im 0.0 + 0.0im 0.0 + 0.0im 0.0 - 1.0im
0.0 + 0.0im 0.0 + 0.0im 0.0 + 1.0im 0.0 + 0.0im
0.0 + 0.0im 0.0 - 1.0im 0.0 + 0.0im 0.0 + 0.0im
0.0 + 1.0im 0.0 + 0.0im 0.0 + 0.0im 0.0 + 0.0im
Snowflurry.MultiBodySystem — Type.
A structure representing a quantum multi-body system.
Fields
hilbert_space_structure– a vector of integers specifying the local Hilbert space size for each "body" within the multi-body system.
Snowflurry.commute — Function.
commute(A::AbstractOperator, B::AbstractOperator)
Returns the commutation of A and B.
julia> σ_x = sigma_x()
(2,2)-element Snowflurry.AntiDiagonalOperator:
Underlying data type: ComplexF64:
. 1.0 + 0.0im
1.0 + 0.0im .
julia> σ_y = sigma_y()
(2,2)-element Snowflurry.AntiDiagonalOperator:
Underlying data type: ComplexF64:
. 0.0 - 1.0im
0.0 + 1.0im .
julia> commute(σ_x, σ_y)
(2,2)-element Snowflurry.DiagonalOperator:
Underlying data type: ComplexF64:
0.0 + 2.0im .
. 0.0 - 2.0im
Snowflurry.anticommute — Function.
anticommute(A::AbstractOperator, B::AbstractOperator)
Returns the anticommutation of A and B.
julia> σ_x = sigma_x()
(2,2)-element Snowflurry.AntiDiagonalOperator:
Underlying data type: ComplexF64:
. 1.0 + 0.0im
1.0 + 0.0im .
julia> anticommute(σ_x, σ_x)
(2,2)-element Snowflurry.DiagonalOperator:
Underlying data type: ComplexF64:
2.0 + 0.0im .
. 2.0 + 0.0im
LinearAlgebra.normalize! — Function.
normalize!(x::Ket)
Normalizes Ket x such that its magnitude becomes unity.
julia> ψ = Ket([1., 2., 4.])
3-element Ket{ComplexF64}:
1.0 + 0.0im
2.0 + 0.0im
4.0 + 0.0im
julia> normalize!(ψ)
3-element Ket{ComplexF64}:
0.2182178902359924 + 0.0im
0.4364357804719848 + 0.0im
0.8728715609439696 + 0.0im
Snowflurry.get_measurement_probabilities — Method.
get_measurement_probabilities(x::Ket{Complex{T}},
[target_bodies::Vector{U},
hspace_size_per_body::Union{U,Vector{U}}=2])::AbstractVector{T}
where {T<:Real, U<:Integer}
Returns a vector listing the measurement probabilities of the target_bodies of Ket x.
The Hilbert space size per body can be specified by providing a Vector of Integer for the hspace_size_per_body argument. The Vector must specify the Hilbert space size for each body. If the space size is uniform, a single Integer can be given instead. If only x is provided, the probabilities are provided for all the bodies.
The measurement probabilities are listed from the smallest to the largest computational basis state. For instance, for a 2-qubit Ket, the probabilities are listed for $\left|00\right\rangle$, $\left|10\right\rangle$, $\left|01\right\rangle$, and $\left|11\right\rangle$.
Note
By convention, qubit 1 is the leftmost digit, followed by every subsequent qubit. $\left|10\right\rangle$ has qubit 1 in state $\left|1\right\rangle$ and qubit 2 in state $\left|0\right\rangle$
Examples
The following example constructs a Ket, where the probability of measuring $\left|00\right\rangle$ is 50% and the probability of measuring $\left|01\right\rangle$ is also 50%.
julia> ψ = 1/sqrt(2) * Ket([1, 0, 1, 0])
4-element Ket{ComplexF64}:
0.7071067811865475 + 0.0im
0.0 + 0.0im
0.7071067811865475 + 0.0im
0.0 + 0.0im
julia> get_measurement_probabilities(ψ)
4-element Vector{Float64}:
0.4999999999999999
0.0
0.4999999999999999
0.0
For the same Ket, the probability of measuring qubit 2 and finding 0 is 100%.
julia> target_qubit = [2];
julia> get_measurement_probabilities(ψ, target_qubit)
2-element Vector{Float64}:
0.9999999999999998
0.0
Snowflurry.ket2dm — Function.
ket2dm(ψ::Ket)
Returns the density matrix corresponding to the pure state ψ.
Snowflurry.fock_dm — Function.
fock_dm(i::Int64, hspace_size::Int64)
Returns the density matrix corresponding to the Fock base i defined in a Hilbert space of size hspace_size.
julia> dm = fock_dm(0, 2)
(2, 2)-element Snowflurry.DenseOperator:
Underlying data ComplexF64:
1.0 + 0.0im 0.0 + 0.0im
0.0 + 0.0im 0.0 + 0.0im
Snowflurry.wigner — Function.
wigner(ρ::AbstractOperator, p::Real, q::Real)
Computes the Wigner function of the density matrix ρ at the point (p,q).
julia> alpha = 0.25;
julia> hspace_size = 8;
julia> Ψ = coherent(alpha, hspace_size);
julia> prob = wigner(ket2dm(Ψ), 0, 0);
julia> @printf "prob: %.6f" prob
prob: -0.561815
Snowflurry.moyal — Function.
moyal(m, n)
Returns the Moyal function w_mn(eta) for Fock states m and n.
Snowflurry.genlaguerre — Function.
genlaguerre(x, alpha, n)
Returns the generalized Laguerre polynomial of degree n for x using a recursive method. See https://en.wikipedia.org/wiki/Laguerre_polynomials.
Snowflurry.get_embed_operator — Function.
get_embed_operator(op::DenseOperator, target_body_index::Int, system::MultiBodySystem)
Uses a local operator (op), which is defined for a particular body (e.g. qubit) with index target_body_index, to build the corresponding operator for the Hilbert space of the multi-body system given by system.
Examples
julia> system = MultiBodySystem(3, 2)
Snowflurry.Multibody system with 3 bodies
Hilbert space structure:
[2, 2, 2]
julia> x = sigma_x()
(2,2)-element Snowflurry.AntiDiagonalOperator:
Underlying data type: ComplexF64:
. 1.0 + 0.0im
1.0 + 0.0im .
julia> X_1 = get_embed_operator(x, 1, system)
(8, 8)-element Snowflurry.DenseOperator:
Underlying data ComplexF64:
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 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 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 0.0 + 0.0im 0.0 + 0.0im 0.0 + 0.0im 0.0 + 0.0im 1.0 + 0.0im
1.0 + 0.0im 0.0 + 0.0im 0.0 + 0.0im 0.0 + 0.0im 0.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 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 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
Snowflurry.get_num_qubits — Method.
get_num_qubits(x::AbstractOperator)
Returns the number of qubits associated with an Operator.
Examples
julia> ρ = DenseOperator([1. 0.
0. 0.])
(2, 2)-element Snowflurry.DenseOperator:
Underlying data ComplexF64:
1.0 + 0.0im 0.0 + 0.0im
0.0 + 0.0im 0.0 + 0.0im
julia> get_num_qubits(ρ)
1
Snowflurry.get_num_qubits — Method.
get_num_qubits(x::Union{Ket, Bra})
Returns the number of qubits associated with a Ket or a Bra.
Examples
julia> ψ = Ket([1., 0., 0., 0.])
4-element Ket{ComplexF64}:
1.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
julia> get_num_qubits(ψ)
2
Snowflurry.get_num_bodies — Function.
get_num_bodies(x::AbstractOperator, hilbert_space_size_per_body=2)
Returns the number of bodies associated with an Operator given the hilbert_space_size_per_body.
Examples
julia> ρ = DenseOperator([1. 0. 0.
0. 0. 0.
0. 0. 0.])
(3, 3)-element Snowflurry.DenseOperator:
Underlying data ComplexF64:
1.0 + 0.0im 0.0 + 0.0im 0.0 + 0.0im
0.0 + 0.0im 0.0 + 0.0im 0.0 + 0.0im
0.0 + 0.0im 0.0 + 0.0im 0.0 + 0.0im
julia> get_num_bodies(ρ, 3)
1
Snowflurry.get_num_bodies — Function.
get_num_bodies(x::Union{Ket, Bra}, hilbert_space_size_per_body=2)
Returns the number of bodies associated with a Ket or a Bra given the hilbert_space_size_per_body.
Examples
julia> ψ = Ket([1., 0., 0., 0., 0., 0., 0., 0., 0.])
9-element Ket{ComplexF64}:
1.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
julia> get_num_bodies(ψ, 3)
2
Snowflurry.fock — Function.
fock(i, hspace_size,T::Type{<:Complex}=ComplexF64)
Returns the ith Fock basis of a Hilbert space with size hspace_size as a Ket.
The Ket contains values of type T, which by default is ComplexF64.
Examples
julia> ψ = fock(0, 3)
3-element Ket{ComplexF64}:
1.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
julia> ψ = fock(1, 3)
3-element Ket{ComplexF64}:
0.0 + 0.0im
1.0 + 0.0im
0.0 + 0.0im
julia> ψ = fock(1, 3, ComplexF32) # specifying a type other than ComplexF64
3-element Ket{ComplexF32}:
0.0f0 + 0.0f0im
1.0f0 + 0.0f0im
0.0f0 + 0.0f0im
Snowflurry.spin_up — Function.
spin_up(T::Type{<:Complex}=ComplexF64)
Returns the Ket representation of the spin-up state.
The Ket stores values of type T, which is ComplexF64 by default.
Examples
julia> ψ = spin_up()
2-element Ket{ComplexF64}:
1.0 + 0.0im
0.0 + 0.0im
Snowflurry.spin_down — Function.
spin_down(T::Type{<:Complex}=ComplexF64)
Returns the Ket representation of the spin-down state.
The Ket stores values of type T, which is ComplexF64 by default.
Examples
julia> ψ = spin_down()
2-element Ket{ComplexF64}:
0.0 + 0.0im
1.0 + 0.0im
Snowflurry.create — Function.
create(hspace_size,T::Type{<:Complex}=ComplexF64)
Returns the bosonic creation operator for a Fock space of size hspace_size, of default type ComplexF64.
Snowflurry.destroy — Function.
destroy(hspace_size,T::Type{<:Complex}=ComplexF64)
Returns the bosonic annhilation operator for a Fock space of size hspace_size, of default type ComplexF64.
Snowflurry.number_op — Function.
number_op(hspace_size,T::Type{<:Complex}=ComplexF64)
Returns the number operator for a Fock space of size hspace_size, of default type ComplexF64.
Snowflurry.coherent — Function.
coherent(alpha, hspace_size)
Returns a coherent state for the parameter alpha in a Fock space of size hspace_size. Note that |alpha|^2 is equal to the photon number of the coherent state.
# Examples
julia> ψ = coherent(2.0, 20)
20-element Ket{ComplexF64}:
0.1353352832366127 + 0.0im
0.2706705664732254 + 0.0im
0.3827859860416437 + 0.0im
0.44200318416631873 + 0.0im
0.44200318416631873 + 0.0im
0.3953396664268989 + 0.0im
0.3227934859426707 + 0.0im
0.24400893961026582 + 0.0im
0.17254037586855772 + 0.0im
0.11502691724570517 + 0.0im
0.07274941014482605 + 0.0im
0.043869544940011405 + 0.0im
0.025328093580341972 + 0.0im
0.014049498479026656 + 0.0im
0.007509772823502764 + 0.0im
0.003878030010563634 + 0.0im
0.001939015005281817 + 0.0im
0.000940560432521708 + 0.0im
0.0004433844399679012 + 0.0im
0.00020343873336404819 + 0.0im
julia> expected_value(number_op(20), ψ)
3.99999979364864 + 0.0im
Snowflurry.compare_kets — Function.
compare_kets(ψ_0::Ket,ψ_1::Ket)
Checks for equivalence allowing for a global phase difference between two input kets.
Examples
julia> ψ_0 = Ket([1., 2., 3., 4.])
4-element Ket{ComplexF64}:
1.0 + 0.0im
2.0 + 0.0im
3.0 + 0.0im
4.0 + 0.0im
julia> δ = π/3 # phase offset
1.0471975511965976
julia> ψ_1 = exp(im * δ) * ψ_0
4-element Ket{ComplexF64}:
0.5000000000000001 + 0.8660254037844386im
1.0000000000000002 + 1.7320508075688772im
1.5000000000000004 + 2.598076211353316im
2.0000000000000004 + 3.4641016151377544im
julia> compare_kets(ψ_0, ψ_1)
true
julia> apply_instruction!(ψ_1, sigma_x(1))
4-element Ket{ComplexF64}:
1.5000000000000004 + 2.598076211353316im
2.0000000000000004 + 3.4641016151377544im
0.5000000000000001 + 0.8660254037844386im
1.0000000000000002 + 1.7320508075688772im
julia> compare_kets(ψ_0, ψ_1) # no longer equivalent after SigmaX gate
false
Snowflurry.compare_operators — Function.
compare_operators(H_0::AbstractOperator, H_1::AbstractOperator)::Bool
Checks for equivalence allowing for a global phase difference between two input operators.
Examples
julia> H_0 = z_90()
(2,2)-element Snowflurry.DiagonalOperator:
Underlying data type: ComplexF64:
0.7071067811865476 - 0.7071067811865475im .
. 0.7071067811865476 + 0.7071067811865475im
julia> H_1 = phase_shift(pi / 2)
(2,2)-element Snowflurry.DiagonalOperator:
Underlying data type: ComplexF64:
1.0 + 0.0im .
. 6.123233995736766e-17 + 1.0im
julia> compare_operators(H_0, H_1)
true
julia> H_1 *= sigma_x()
(2, 2)-element Snowflurry.DenseOperator:
Underlying data ComplexF64:
0.0 + 0.0im 1.0 + 0.0im
6.123233995736766e-17 + 1.0im 0.0 + 0.0im
julia> compare_operators(H_0, H_1) # no longer equivalent after applying sigma x
false