Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleaning/aaron 18 11 24 #172

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "QuantumCollocation"
uuid = "0dc23a59-5ffb-49af-b6bd-932a8ae77adf"
authors = ["Aaron Trowbridge <[email protected]> and contributors"]
version = "0.3.3"
version = "0.3.2"

[deps]
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
Expand Down Expand Up @@ -37,7 +37,7 @@ Interpolations = "0.15"
Ipopt = "1.6"
JLD2 = "0.5"
MathOptInterface = "1.31"
NamedTrajectories = "0.2.3"
NamedTrajectories = "0.2.4"
ProgressMeter = "1.10"
Reexport = "1.2"
Symbolics = "6.14"
Expand Down
2 changes: 1 addition & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ QuantumCollocation = "0dc23a59-5ffb-49af-b6bd-932a8ae77adf"
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"

[compat]
NamedTrajectories = "0.2.3"
NamedTrajectories = "0.2.4"
10 changes: 7 additions & 3 deletions src/callbacks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@ using TestItemRunner

using ..Losses
using ..Problems: QuantumControlProblem, get_datavec
using ..QuantumSystems
using ..Rollouts


function best_rollout_callback(prob::QuantumControlProblem, rollout::Function)
function best_rollout_callback(
prob::QuantumControlProblem, rollout_fidelity::Function;
system::Union{AbstractQuantumSystem, AbstractVector{<:AbstractQuantumSystem}}=prob.system
)
best_value = 0.0
best_trajectories = []

function callback(args...)
traj = NamedTrajectory(get_datavec(prob), prob.trajectory)
value = rollout(traj, prob.system)
value = rollout_fidelity(traj, system)
if value > best_value
best_value = value
push!(best_trajectories, traj)
Expand Down Expand Up @@ -47,7 +51,7 @@ function trajectory_history_callback(prob::QuantumControlProblem)
return callback, trajectory_history
end

# ========================================================================== #
# *************************************************************************** #

@testitem "Callback returns false early stops" begin
using MathOptInterface
Expand Down
212 changes: 21 additions & 191 deletions src/direct_sums.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ export add_suffix
export get_suffix
export get_suffix_label
export direct_sum
export merge_outer

using ..Integrators
using ..Problems
Expand Down Expand Up @@ -61,81 +60,12 @@ function direct_sum(sys1::QuantumSystem, sys2::QuantumSystem)
return QuantumSystem(
H_drift,
H_drives,
params=merge_outer(sys1.params, sys2.params)
params=merge(sys1.params, sys2.params)
)
end

direct_sum(systems::AbstractVector{<:QuantumSystem}) = reduce(direct_sum, systems)

"""
direct_sum(traj1::NamedTrajectory, traj2::NamedTrajectory)

Returns the direct sum of two `NamedTrajectory` objects.

The `NamedTrajectory` objects must have the same timestep. However, a direct sum
can return a free time problem by passing the keyword argument `free_time=true`.
In this case, the timestep symbol must be provided. If a free time problem with more
than two trajectories is desired, the `reduce` function has been written to handle calls
to direct sums of `NamedTrajectory` objects; simply pass the keyword argument `free_time=true`
to the `reduce` function.

# Arguments
- `traj1::NamedTrajectory`: The first `NamedTrajectory` object.
- `traj2::NamedTrajectory`: The second `NamedTrajectory` object.
- `free_time::Bool=false`: Whether to construct a free time problem.
- `timestep_name::Symbol=:Δt`: The timestep symbol to use for free time problems.
"""
function direct_sum(
traj1::NamedTrajectory,
traj2::NamedTrajectory;
free_time::Bool=false,
timestep_name::Symbol=:Δt,
)
return direct_sum([traj1, traj2]; free_time=free_time, timestep_name=timestep_name)
end

function direct_sum(
trajs::AbstractVector{<:NamedTrajectory};
free_time::Bool=false,
timestep_name::Symbol=:Δt,
)
if length(trajs) < 2
throw(ArgumentError("At least two trajectories must be provided"))
end

for traj in trajs
if traj.timestep isa Symbol
throw(ArgumentError("Provided trajectories must have fixed timesteps"))
end
end

timestep = trajs[1].timestep
for traj in trajs[2:end]
if timestep != traj.timestep
throw(ArgumentError("Fixed timesteps must be equal"))
end
end

# collect component data
component_names = [vcat(traj.state_names..., traj.control_names...) for traj ∈ trajs]
components = merge_outer([get_components(names, traj) for (names, traj) ∈ zip(component_names, trajs)])

# add timestep to components
if free_time
components = merge_outer(components, NamedTuple{(timestep_name,)}([get_timesteps(trajs[1])]))
end

return NamedTrajectory(
components,
controls=merge_outer([traj.control_names for traj in trajs]),
timestep=free_time ? timestep_name : timestep,
bounds=merge_outer([traj.bounds for traj in trajs]),
initial=merge_outer([traj.initial for traj in trajs]),
final=merge_outer([traj.final for traj in trajs]),
goal=merge_outer([traj.goal for traj in trajs])
)
end

# Add suffix utilities
# -----------------------
Base.startswith(symb::Symbol, prefix::AbstractString) = startswith(String(symb), prefix)
Expand Down Expand Up @@ -322,47 +252,6 @@ function remove_suffix(
end


# Merge utilities
# ---------------

function merge_outer(objs::AbstractVector{<:Any})
return reduce(merge_outer, objs)
end

function merge_outer(objs::AbstractVector{<:Tuple})
# only construct final tuple
return Tuple(mᵢ for mᵢ in reduce(merge_outer, [[tᵢ for tᵢ in tup] for tup in objs]))
end

function merge_outer(nt1::NamedTuple, nt2::NamedTuple)
common_keys = intersect(keys(nt1), keys(nt2))
if !isempty(common_keys)
error("Key collision detected: ", common_keys)
end
return merge(nt1, nt2)
end

function merge_outer(d1::Dict{Symbol, <:Any}, d2::Dict{Symbol, <:Any})
common_keys = intersect(keys(d1), keys(d2))
if !isempty(common_keys)
error("Key collision detected: ", common_keys)
end
return merge(d1, d2)
end

function merge_outer(s1::AbstractVector, s2::AbstractVector)
common_keys = intersect(s1, s2)
if !isempty(common_keys)
error("Key collision detected: ", common_keys)
end
return vcat(s1, s2)
end

function merge_outer(t1::Tuple, t2::Tuple)
m = merge_outer([tᵢ for tᵢ in t1], [tⱼ for tⱼ in t2])
return Tuple(mᵢ for mᵢ in m)
end

# Get suffix utilities
# --------------------

Expand Down Expand Up @@ -502,7 +391,6 @@ end
# =========================================================================== #

@testitem "Apply suffix to trajectories" begin
using NamedTrajectories
include("../test/test_utils.jl")

traj = named_trajectory_type_1(free_time=false)
Expand All @@ -516,66 +404,7 @@ end
@test traj == same_traj
end

@testitem "Merge trajectories" begin
using NamedTrajectories
include("../test/test_utils.jl")

traj = named_trajectory_type_1(free_time=false)

# apply suffix
pf_traj1 = add_suffix(traj, "_1")
pf_traj2 = add_suffix(traj, "_2")

# merge
new_traj = direct_sum(pf_traj1, pf_traj2)

@test issetequal(new_traj.state_names, vcat(pf_traj1.state_names..., pf_traj2.state_names...))
@test issetequal(new_traj.control_names, vcat(pf_traj1.control_names..., pf_traj2.control_names...))

# merge2
new_traj2 = direct_sum([pf_traj1, pf_traj2])

@test new_traj == new_traj2
end

@testitem "Merge free time trajectories" begin
using NamedTrajectories
include("../test/test_utils.jl")

traj = named_trajectory_type_1(free_time=false)

# apply suffix
pf_traj1 = add_suffix(traj, "_1")
pf_traj2 = add_suffix(traj, "_2")
pf_traj3 = add_suffix(traj, "_3")
state_names = vcat(pf_traj1.state_names..., pf_traj2.state_names..., pf_traj3.state_names...)
control_names = vcat(pf_traj1.control_names..., pf_traj2.control_names..., pf_traj3.control_names...)

# merge (without reduce)
new_traj_1 = direct_sum(direct_sum(pf_traj1, pf_traj2), pf_traj3, free_time=true)
@test new_traj_1.timestep isa Symbol
@test issetequal(new_traj_1.state_names, state_names)
@test issetequal(setdiff(new_traj_1.control_names, control_names), [new_traj_1.timestep])

# merge (with reduce)
new_traj_2 = direct_sum([pf_traj1, pf_traj2, pf_traj3], free_time=true)
@test new_traj_2.timestep isa Symbol
@test issetequal(new_traj_2.state_names, state_names)
@test issetequal(setdiff(new_traj_2.control_names, control_names), [new_traj_2.timestep])

# check equality
for c in new_traj_1.control_names
@test new_traj_1[c] == new_traj_2[c]
end
for s in new_traj_1.state_names
@test new_traj_1[s] == new_traj_2[s]
end
end

@testitem "Merge systems" begin
using NamedTrajectories
include("../test/test_utils.jl")

H_drift = 0.01 * GATES[:Z]
H_drives = [GATES[:X], GATES[:Y]]
T = 50
Expand Down Expand Up @@ -660,31 +489,32 @@ end
# @test prob2_new[2].variable == add_suffix(prob2.integrators[2].variable, suffix)
end

# TODO: fix broken test
@testitem "Free time get suffix" begin
using NamedTrajectories
# using NamedTrajectories

sys = QuantumSystem(0.01 * GATES[:Z], [GATES[:Y]])
T = 50
Δt = 0.2
ops = IpoptOptions(print_level=1)
pi_false_ops = PiccoloOptions(verbose=false, free_time=false)
pi_true_ops = PiccoloOptions(verbose=false, free_time=true)
suffix = "_new"
timestep_name = :Δt
# sys = QuantumSystem(0.01 * GATES[:Z], [GATES[:Y]])
# T = 50
# Δt = 0.2
# ops = IpoptOptions(print_level=1)
# pi_false_ops = PiccoloOptions(verbose=false, free_time=false)
# pi_true_ops = PiccoloOptions(verbose=false, free_time=true)
# suffix = "_new"
# timestep_name = :Δt

prob1 = UnitarySmoothPulseProblem(sys, GATES[:Y], T, Δt, piccolo_options=pi_false_ops, ipopt_options=ops)
traj1 = direct_sum(prob1.trajectory, add_suffix(prob1.trajectory, suffix), free_time=true)
# prob1 = UnitarySmoothPulseProblem(sys, GATES[:Y], T, Δt, piccolo_options=pi_false_ops, ipopt_options=ops)
# traj1 = direct_sum(prob1.trajectory, add_suffix(prob1.trajectory, suffix), free_time=true)

# Direct sum (shared timestep name)
@test get_suffix(traj1, suffix).timestep == timestep_name
@test get_suffix(traj1, suffix, remove=true).timestep == timestep_name
# # Direct sum (shared timestep name)
# @test get_suffix(traj1, suffix).timestep == timestep_name
# @test get_suffix(traj1, suffix, remove=true).timestep == timestep_name

prob2 = UnitarySmoothPulseProblem(sys, GATES[:Y], T, Δt, ipopt_options=ops, piccolo_options=pi_true_ops)
traj2 = add_suffix(prob2.trajectory, suffix)
# prob2 = UnitarySmoothPulseProblem(sys, GATES[:Y], T, Δt, ipopt_options=ops, piccolo_options=pi_true_ops)
# traj2 = add_suffix(prob2.trajectory, suffix)

# Trajectory (unique timestep name)
@test get_suffix(traj2, suffix).timestep == add_suffix(timestep_name, suffix)
@test get_suffix(traj2, suffix, remove=true).timestep == timestep_name
# # Trajectory (unique timestep name)
# @test get_suffix(traj2, suffix).timestep == add_suffix(timestep_name, suffix)
# @test get_suffix(traj2, suffix, remove=true).timestep == timestep_name
end

end # module
2 changes: 1 addition & 1 deletion src/embedded_operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ function get_subspace_leakage_indices(
subsystem_levels::AbstractVector{Int};
)
subspace_indices = get_subspace_indices(subspaces, subsystem_levels)
return get_subspace_leakage_indices(subspace_indices)
return get_subspace_leakage_indices(subspace_indices, prod(subsystem_levels))
end

get_subspace_leakage_indices(subspace_indices::AbstractVector{Int}, levels::Int) =
Expand Down
2 changes: 1 addition & 1 deletion src/isomorphisms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ iso_dm(ρ::AbstractMatrix) = ket_to_iso(vec(ρ))



# =========================================================================== #
# *************************************************************************** #

@testitem "Test isomorphism utilities" begin
using LinearAlgebra
Expand Down
Loading
Loading