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.KetType

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} \\ a_{10} \\ a_{01} \\ a_{11} \\ \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

source
Snowflurry.BraType

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

source
Snowflurry.DiagonalOperatorType
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
source
Snowflurry.AntiDiagonalOperatorType
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    .
source
Snowflurry.DenseOperatorType
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

source
Snowflurry.SwapLikeOperatorType
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
source
Snowflurry.IdentityOperatorType
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
source
Snowflurry.SparseOperatorType
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
source
Snowflurry.ReadoutType
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 
source
Snowflurry.readoutFunction
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.

source
Base.adjointFunction
Base.adjoint(x)

Compute the adjoint (a.k.a. conjugate transpose) of a Ket, a Bra, or an Operator.

source
Snowflurry.is_hermitianFunction
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
source
Base.expMethod
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

source
Base.getindexMethod

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
source
Snowflurry.expected_valueMethod
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
source
SparseArrays.sparseFunction
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
source
LinearAlgebra.eigenFunction
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
source
LinearAlgebra.trFunction
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
source
Base.kronFunction
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

source
Snowflurry.MultiBodySystemType

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.
source
Snowflurry.commuteFunction
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
source
Snowflurry.anticommuteFunction
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
source
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
source
Snowflurry.get_measurement_probabilitiesMethod
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
source
Snowflurry.fock_dmFunction
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

source
Snowflurry.wignerFunction
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
source
Snowflurry.moyalFunction
moyal(m, n)

Returns the Moyal function w_mn(eta) for Fock states m and n.

Note

Fock basis states numbering starts at 0.

source
Snowflurry.get_embed_operatorFunction
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

source
Snowflurry.get_num_qubitsMethod
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
source
Snowflurry.get_num_qubitsMethod
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
source
Snowflurry.get_num_bodiesFunction
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
source
Snowflurry.get_num_bodiesFunction
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
source
Snowflurry.fockFunction
fock(i, hspace_size,T::Type{<:Complex}=ComplexF64)

Returns the ith Fock basis of a Hilbert space with size hspace_size as a Ket.

Note

Fock basis states numbering starts at 0.

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
source
Snowflurry.spin_upFunction
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

source
Snowflurry.spin_downFunction
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

source
Snowflurry.createFunction
create(hspace_size,T::Type{<:Complex}=ComplexF64)

Returns the bosonic creation operator for a Fock space of size hspace_size, of default type ComplexF64.

source
Snowflurry.destroyFunction
destroy(hspace_size,T::Type{<:Complex}=ComplexF64)

Returns the bosonic annhilation operator for a Fock space of size hspace_size, of default type ComplexF64.

source
Snowflurry.number_opFunction
number_op(hspace_size,T::Type{<:Complex}=ComplexF64)

Returns the number operator for a Fock space of size hspace_size, of default type ComplexF64.

source
Snowflurry.coherentFunction
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
source
Snowflurry.compare_ketsFunction
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
source
Snowflurry.compare_operatorsFunction
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
source