Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export QuantumStateSmoothPulseProblem


"""
QuantumStateSmoothPulseProblem(system, ψ_inits, ψ_goals, T, Δt; kwargs...)
QuantumStateSmoothPulseProblem(system, ψ_init, ψ_goal, T, Δt; kwargs...)
Expand Down
2 changes: 1 addition & 1 deletion src/problem_templates/unitary_minimum_time_problem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ end
@test unitary_rollout_fidelity(min_prob.trajectory, sys) ≥ constraint_tol * final_fidelity
duration_after = sum(get_timesteps(min_prob.trajectory))
duration_before = sum(get_timesteps(prob.trajectory))
@test duration_after < duration_before
@test duration_after <= duration_before
end

@testitem "Test relaxed final_fidelity constraint" begin
Expand Down
2 changes: 1 addition & 1 deletion src/problem_templates/unitary_sampling_problem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ end
# *************************************************************************** #

@testitem "Sample robustness test" begin
using PiccoloQuantumObjects
using PiccoloQuantumObjects

T = 50
Δt = 0.2
Expand Down
134 changes: 123 additions & 11 deletions src/quantum_system_templates/transmons.jl
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,36 @@ where `a_i` is the annihilation operator for the `i`th transmon.
"""
function TransmonDipoleCoupling end

# TODO: this function is already difined in PiccoloQuantumObjects.jl so should be used from there, but it is not in a module
function lift_operator(operator::AbstractMatrix{T}, i::Int, subsystem_levels::AbstractVector{Int}) where T <: Number
@assert size(operator, 1) == subsystem_levels[i] "Operator must match subsystem level."
Is = [Matrix{T}(I(l)) for l ∈ subsystem_levels]
Is[i] = operator
return reduce(kron, Is)
end

struct QuantumSystemCoupling
op
g_ij
pair
subsystem_levels
coupling_type
params
end

export QuantumSystemCoupling

function TransmonDipoleCoupling(
g_ij::Float64,
pair::Tuple{Int, Int},
subsystem_levels::Vector{Int};
lab_frame::Bool=false,
mulitply_by_2π::Bool=true,
)

i, j = pair
a_i = lift(annihilate(subsystem_levels[i]), i, subsystem_levels)
a_j = lift(annihilate(subsystem_levels[j]), j, subsystem_levels)
a_i = lift_operator(annihilate(subsystem_levels[i]), i, subsystem_levels)
a_j = lift_operator(annihilate(subsystem_levels[j]), j, subsystem_levels)

if lab_frame
op = g_ij * (a_i + a_i') * (a_j + a_j')
Expand Down Expand Up @@ -227,16 +247,108 @@ function MultiTransmonSystem(

couplings = QuantumSystemCoupling[]

for i = 1:n_subsystems-1
for j = i+1:n_subsystems
if i ∈ subsystems && j ∈ subsystems
push!(
couplings,
TransmonDipoleCoupling(gs[i, j], (i, j), systems; lab_frame=lab_frame)
)
end
for local_i = 1:length(systems)-1
for local_j = local_i+1:length(systems)
global_i = subsystems[local_i]
global_j = subsystems[local_j]
push!(
couplings,
TransmonDipoleCoupling(gs[global_i, global_j], (local_i, local_j), [sys.levels for sys in systems]; lab_frame=lab_frame)
)
end
end

return CompositeQuantumSystem(systems, couplings)
levels = prod([sys.levels for sys in systems])
H_drift = sum(c -> c.op, couplings; init=zeros(ComplexF64, levels, levels))
return CompositeQuantumSystem(H_drift, systems)
end


@testitem "TransmonSystem: default and custom parameters" begin
using PiccoloQuantumObjects
sys = TransmonSystem()
@test typeof(sys) == QuantumSystem
@test haskey(sys.params, :ω)
@test haskey(sys.params, :δ)
@test sys.params[:levels] == 3

sys2 = TransmonSystem(ω=5.0, δ=0.3, levels=4, lab_frame=true, frame_ω=0.0, lab_frame_type=:duffing, drives=false)
@test sys2.params[:ω] == 5.0
@test sys2.params[:δ] == 0.3
@test sys2.params[:levels] == 4
@test sys2.params[:lab_frame] == true
@test sys2.params[:drives] == false
end

@testitem "TransmonSystem: lab_frame_type variations" begin
using PiccoloQuantumObjects
sys_duffing = TransmonSystem(lab_frame=true, lab_frame_type=:duffing)
sys_quartic = TransmonSystem(lab_frame=true, lab_frame_type=:quartic)
sys_cosine = TransmonSystem(lab_frame=true, lab_frame_type=:cosine)
@test typeof(sys_duffing) == QuantumSystem
@test typeof(sys_quartic) == QuantumSystem
@test typeof(sys_cosine) == QuantumSystem
end

@testitem "TransmonSystem: error on invalid lab_frame_type" begin
@test_throws AssertionError TransmonSystem(lab_frame=true, lab_frame_type=:invalid)
end

@testitem "TransmonDipoleCoupling: both constructors and frames" begin
using PiccoloQuantumObjects
levels = [3, 3]
g = 0.01

c1 = TransmonDipoleCoupling(g, (1,2), levels, lab_frame=false)
c2 = TransmonDipoleCoupling(g, (1,2), levels, lab_frame=true)
@test typeof(c1) == QuantumSystemCoupling
@test typeof(c2) == QuantumSystemCoupling

sys1 = TransmonSystem(levels=3)
sys2 = TransmonSystem(levels=3)
c3 = TransmonDipoleCoupling(g, (1,2), [sys1, sys2], lab_frame=false)
@test typeof(c3) == QuantumSystemCoupling
end

@testitem "MultiTransmonSystem: minimal and custom" begin
using LinearAlgebra: norm
using PiccoloQuantumObjects

ωs = [4.0, 4.1]
δs = [0.2, 0.21]
gs = [0.0 0.01; 0.01 0.0]

comp = MultiTransmonSystem(ωs, δs, gs)
@test typeof(comp) == CompositeQuantumSystem
@test length(comp.subsystems) == 2
@test !iszero(comp.H(zeros(comp.n_drives)))

comp2 = MultiTransmonSystem(
ωs, δs, gs;
levels_per_transmon=4,
subsystem_levels=[4,4],
subsystems=[1],
subsystem_drive_indices=[1]
)
@test typeof(comp2) == CompositeQuantumSystem
@test length(comp2.subsystems) == 1
@test !isapprox(norm(comp2.H(zeros(comp2.n_drives))), 0.0; atol=1e-12)
end

@testitem "MultiTransmonSystem: edge cases" begin
using PiccoloQuantumObjects
ωs = [4.0, 4.1, 4.2]
δs = [0.2, 0.21, 0.22]
gs = [0.0 0.01 0.02; 0.01 0.0 0.03; 0.02 0.03 0.0]
# Only a subset of subsystems
comp = MultiTransmonSystem(
ωs, δs, gs;
subsystems=[1,3],
subsystem_drive_indices=[3]
)
@test typeof(comp) == CompositeQuantumSystem
@test length(comp.subsystems) == 2
# Only one drive
@test comp.subsystems[1].params[:drives] == false
@test comp.subsystems[2].params[:drives] == true
end
109 changes: 109 additions & 0 deletions src/trajectory_initialization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ end
linear_interpolation(x::AbstractVector, y::AbstractVector, n::Int) =
hcat(range(x, y, n)...)

linear_interpolation(X::AbstractMatrix, Y::AbstractMatrix, n::Int) =
hcat([X + (Y - X) * t for t in range(0, 1, length=n)]...)

# ============================================================================= #

const VectorBound = Union{AbstractVector{R}, Tuple{AbstractVector{R}, AbstractVector{R}}} where R <: Real
Expand Down Expand Up @@ -675,5 +678,111 @@ end
@test traj isa NamedTrajectory
end

@testitem "unitary_linear_interpolation direct" begin
using PiccoloQuantumObjects
U_init = GATES[:I]
U_goal = GATES[:X]
samples = 5
# Direct matrix
Ũ⃗ = TrajectoryInitialization.unitary_linear_interpolation(U_init, U_goal, samples)
@test size(Ũ⃗, 2) == samples
# EmbeddedOperator
U_init_emb = EmbeddedOperator(U_init, [1,2], [2,2])
U_goal_emb = EmbeddedOperator(U_goal, [1,2], [2,2])
Ũ⃗2 = TrajectoryInitialization.unitary_linear_interpolation(U_init_emb.operator, U_goal_emb, samples)
@test size(Ũ⃗2, 2) == samples
end

@testitem "initialize_unitary_trajectory geodesic=false" begin
using PiccoloQuantumObjects
U_init = GATES[:I]
U_goal = GATES[:X]
T = 4
Ũ⃗ = TrajectoryInitialization.initialize_unitary_trajectory(U_init, U_goal, T; geodesic=false)
@test size(Ũ⃗, 2) == T
end

@testitem "initialize_control_trajectory with a, Δt, n_derivatives" begin
n_drives = 2
T = 5
n_derivatives = 2
a = randn(n_drives, T)
Δt = fill(0.1, T)
controls = TrajectoryInitialization.initialize_control_trajectory(a, Δt, n_derivatives)
@test length(controls) == n_derivatives + 1
@test size(controls[1]) == (n_drives, T)
# Real Δt version
controls2 = TrajectoryInitialization.initialize_control_trajectory(a, 0.1, n_derivatives)
@test length(controls2) == n_derivatives + 1
end

@testitem "initialize_trajectory with bound_state and zero_initial_and_final_derivative" begin
using NamedTrajectories: NamedTrajectory
state_data = [rand(2, 4)]
state_inits = [rand(2)]
state_goals = [rand(2)]
state_names = [:x]
T = 4
Δt = 0.1
n_drives = 1
control_bounds = ([1.0], [1.0])
traj = TrajectoryInitialization.initialize_trajectory(
state_data, state_inits, state_goals, state_names, T, Δt, n_drives, control_bounds;
bound_state=true, zero_initial_and_final_derivative=true
)
@test traj isa NamedTrajectory
end

@testitem "initialize_trajectory with free_time=false" begin
using NamedTrajectories: NamedTrajectory
state_data = [rand(2, 4)]
state_inits = [rand(2)]
state_goals = [rand(2)]
state_names = [:x]
T = 4
Δt = 0.1
n_drives = 1
control_bounds = ([1.0], [1.0])
traj = TrajectoryInitialization.initialize_trajectory(
state_data, state_inits, state_goals, state_names, T, Δt, n_drives, control_bounds;
free_time=false
)
@test traj isa NamedTrajectory
end

@testitem "initialize_trajectory error branches" begin
state_data = [rand(2, 4)]
state_inits = [rand(2)]
state_goals = [rand(2)]
state_names = [:x]
T = 4
Δt = 0.1
n_drives = 1
control_bounds = ([1.0], [1.0])
# state_names not unique
@test_throws AssertionError TrajectoryInitialization.initialize_trajectory(
state_data, state_inits, state_goals, [:x, :x], T, Δt, n_drives, control_bounds
)
# control_bounds wrong length
@test_throws AssertionError TrajectoryInitialization.initialize_trajectory(
state_data, state_inits, state_goals, state_names, T, Δt, n_drives, ([1.0],); n_control_derivatives=1
)
# bounds wrong type
@test_throws MethodError TrajectoryInitialization.initialize_control_trajectory(
n_drives, 2, T, "notabounds", 0.1
)
end

@testitem "linear_interpolation for matrices" begin
X = [1.0 2.0; 3.0 4.0]
Y = [5.0 6.0; 7.0 8.0]
n = 3
result = linear_interpolation(X, Y, n)
@test size(result) == (2, 2 * n)
@test result[:, 1:2] ≈ X
@test result[:, 5:6] ≈ Y
@test result[:, 3:4] ≈ (X + Y) / 2
end


end
Loading