Composite Quantum Systems
using PiccoloQuantumObjects
using SparseArrays # for visualization
⊗ = kron;Composite quantum systems
A CompositeQuantumSystem is constructed from a list of subsystems and their interactions. The interaction, in the form of drift or drive Hamiltonian, acts on the full Hilbert space. The subsystems, with their own drift and drive Hamiltonians, are internally lifted to the full Hilbert space.
system_1 = QuantumSystem([PAULIS[:X]], 1.0, [(-1.0, 1.0)])
system_2 = QuantumSystem([PAULIS[:Y]], 1.0, [(-1.0, 1.0)])
H_drift = PAULIS[:Z] ⊗ PAULIS[:Z]
system = CompositeQuantumSystem(H_drift, Matrix{ComplexF64}[], [system_1, system_2], 1.0, Float64[]);The drift Hamiltonian is the ZZ coupling.
get_drift(system) |> sparse4×4 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 4 stored entries:
1.0+0.0im ⋅ ⋅ ⋅
⋅ -1.0+0.0im ⋅ ⋅
⋅ ⋅ -1.0+0.0im ⋅
⋅ ⋅ ⋅ 1.0+0.0imThe drives are the X and Y operators on the first and second subsystems.
drives = get_drives(system)
drives[1] |> sparse4×4 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 4 stored entries:
⋅ ⋅ 1.0+0.0im ⋅
⋅ ⋅ ⋅ 1.0+0.0im
1.0+0.0im ⋅ ⋅ ⋅
⋅ 1.0+0.0im ⋅ ⋅ drives[2] |> sparse4×4 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 4 stored entries:
⋅ 0.0-1.0im ⋅ ⋅
0.0+1.0im ⋅ ⋅ ⋅
⋅ ⋅ ⋅ 0.0-1.0im
⋅ ⋅ 0.0+1.0im ⋅ The lift_operator function
To lift operators acting on a subsystem into the full Hilbert space, use lift_operator.
PiccoloQuantumObjects.QuantumSystems.lift_operator — Function
lift_operator(operator::AbstractMatrix{<:Number}, i::Int, subsystem_levels::Vector{Int})
lift_operator(operator::AbstractMatrix{<:Number}, i::Int, n_qubits::Int; kwargs...)
lift_operator(operators::AbstractVector{<:AbstractMatrix{T}}, indices::AbstractVector{Int}, subsystem_levels::Vector{Int})
lift_operator(operators::AbstractVector{<:AbstractMatrix{T}}, indices::AbstractVector{Int}, n_qubits::Int; kwargs...)
lift_operator(operator::AbstractMatrix{T}, indices::AbstractVector{Int}, subsystem_levels::AbstractVector{Int})
lift_operator(operator::AbstractMatrix{T}, indices::AbstractVector{Int}, n_qubits::Int; kwargs...)Lift an operator acting on the i-th subsystem within subsystem_levels to an operator acting on the entire system spanning subsystem_levels.
Create an a + a' operator acting on the 1st subsystem of a qutrit and qubit system.
subspace_levels = [3, 2]
lift_operator(create(3) + annihilate(3), 1, subspace_levels) .|> real |> sparse6×6 SparseArrays.SparseMatrixCSC{Float64, Int64} with 8 stored entries:
⋅ ⋅ 1.0 ⋅ ⋅ ⋅
⋅ ⋅ ⋅ 1.0 ⋅ ⋅
1.0 ⋅ ⋅ ⋅ 1.41421 ⋅
⋅ 1.0 ⋅ ⋅ ⋅ 1.41421
⋅ ⋅ 1.41421 ⋅ ⋅ ⋅
⋅ ⋅ ⋅ 1.41421 ⋅ ⋅ Create IXI operator on the 2nd qubit in a 3-qubit system.
lift_operator(PAULIS[:X], 2, 3) .|> real |> sparse8×8 SparseArrays.SparseMatrixCSC{Float64, Int64} with 8 stored entries:
⋅ ⋅ 1.0 ⋅ ⋅ ⋅ ⋅ ⋅
⋅ ⋅ ⋅ 1.0 ⋅ ⋅ ⋅ ⋅
1.0 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅
⋅ 1.0 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0 ⋅
⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0
⋅ ⋅ ⋅ ⋅ 1.0 ⋅ ⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅ 1.0 ⋅ ⋅ Create an XX operator acting on qubits 3 and 4 in a 4-qubit system.
lift_operator([PAULIS[:X], PAULIS[:X]], [3, 4], 4) .|> real |> sparse16×16 SparseArrays.SparseMatrixCSC{Float64, Int64} with 16 stored entries:
⎡⡠⠊⠀⠀⠀⠀⠀⠀⎤
⎢⠀⠀⡠⠊⠀⠀⠀⠀⎥
⎢⠀⠀⠀⠀⡠⠊⠀⠀⎥
⎣⠀⠀⠀⠀⠀⠀⡠⠊⎦We can also lift an operator that entangles different subspaces by passing the indices of the entangled subsystems.
#_Here's another way to create an XX operator acting on qubits 3 and 4 in a 4-qubit system._
lift_operator(kron(PAULIS[:X], PAULIS[:X]), [3, 4], 4) .|> real |> sparse16×16 SparseArrays.SparseMatrixCSC{Float64, Int64} with 16 stored entries:
⎡⡠⠊⠀⠀⠀⠀⠀⠀⎤
⎢⠀⠀⡠⠊⠀⠀⠀⠀⎥
⎢⠀⠀⠀⠀⡠⠊⠀⠀⎥
⎣⠀⠀⠀⠀⠀⠀⡠⠊⎦Lift a CX gate acting on the 1st and 3rd qubits in a 3-qubit system.The result is independent of the state of the second qubit.
lift_operator(GATES[:CX], [1, 3], 3) .|> real |> sparse8×8 SparseArrays.SparseMatrixCSC{Float64, Int64} with 8 stored entries:
1.0 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅
⋅ 1.0 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅
⋅ ⋅ 1.0 ⋅ ⋅ ⋅ ⋅ ⋅
⋅ ⋅ ⋅ 1.0 ⋅ ⋅ ⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅ 1.0 ⋅ ⋅
⋅ ⋅ ⋅ ⋅ 1.0 ⋅ ⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0
⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0 ⋅ This page was generated using Literate.jl.