using NamedTrajectories
using PiccoloQuantumObjects
using QuantumCollocation
Quantum State Smooth Pulse Problem
QuantumCollocation.ProblemTemplates.QuantumStateSmoothPulseProblem
— FunctionQuantumStateSmoothPulseProblem(system, ψ_inits, ψ_goals, T, Δt; kwargs...)
QuantumStateSmoothPulseProblem(system, ψ_init, ψ_goal, T, Δt; kwargs...)
QuantumStateSmoothPulseProblem(H_drift, H_drives, args...; kwargs...)
Create a quantum state smooth pulse problem. The goal is to find a control pulse a(t)
that drives all of the initial states ψ_inits
to the corresponding target states ψ_goals
using T
timesteps of size Δt
. This problem also controls the first and second derivatives of the control pulse, da(t)
and dda(t)
, to ensure smoothness.
Arguments
system::AbstractQuantumSystem
: The quantum system.
or
H_drift::AbstractMatrix{<:Number}
: The drift Hamiltonian.H_drives::Vector{<:AbstractMatrix{<:Number}}
: The control Hamiltonians.
with
ψ_inits::Vector{<:AbstractVector{<:ComplexF64}}
: The initial states.ψ_goals::Vector{<:AbstractVector{<:ComplexF64}}
: The target states.
or
ψ_init::AbstractVector{<:ComplexF64}
: The initial state.ψ_goal::AbstractVector{<:ComplexF64}
: The target state.
with
T::Int
: The number of timesteps.Δt::Float64
: The timestep size.
Keyword Arguments
state_name::Symbol=:ψ̃
: The name of the state variable.control_name::Symbol=:a
: The name of the control variable.timestep_name::Symbol=:Δt
: The name of the timestep variable.init_trajectory::Union{NamedTrajectory, Nothing}=nothing
: The initial trajectory.a_bound::Float64=1.0
: The bound on the control pulse.a_bounds=fill(a_bound, length(system.G_drives))
: The bounds on the control pulse.a_guess::Union{Matrix{Float64}, Nothing}=nothing
: The initial guess for the control pulse.da_bound::Float64=Inf
: The bound on the first derivative of the control pulse.da_bounds=fill(da_bound, length(system.G_drives))
: The bounds on the first derivative of the control pulse.dda_bound::Float64=1.0
: The bound on the second derivative of the control pulse.dda_bounds=fill(dda_bound, length(system.G_drives))
: The bounds on the second derivative of the control pulse.Δt_min::Float64=0.5 * Δt
: The minimum timestep size.Δt_max::Float64=1.5 * Δt
: The maximum timestep size.drive_derivative_σ::Float64=0.01
: The standard deviation of the drive derivative random initialization.Q::Float64=100.0
: The weight on the state objective.R=1e-2
: The weight on the control pulse and its derivatives.R_a::Union{Float64, Vector{Float64}}=R
: The weight on the control pulse.R_da::Union{Float64, Vector{Float64}}=R
: The weight on the first derivative of the control pulse.R_dda::Union{Float64, Vector{Float64}}=R
: The weight on the second derivative of the control pulse.constraints::Vector{<:AbstractConstraint}=AbstractConstraint[]
: The constraints.piccolo_options::PiccoloOptions=PiccoloOptions()
: The Piccolo options.
Each problem starts with a QuantumSystem
object, which is used to define the system's Hamiltonian and control operators. The goal is to find a control pulse that drives the intial state, ψ_init
, to a target state, ψ_goal
.
define the quantum system
system = QuantumSystem(0.1 * PAULIS.Z, [PAULIS.X, PAULIS.Y])
ψ_init = Vector{ComplexF64}([1.0, 0.0])
ψ_goal = Vector{ComplexF64}([0.0, 1.0])
T = 51
Δt = 0.2
0.2
create the smooth pulse problem
state_prob = QuantumStateSmoothPulseProblem(system, ψ_init, ψ_goal, T, Δt);
constructing QuantumStateSmoothPulseProblem...
using integrator: typeof(KetIntegrator)
using 1 initial state(s)
applying timesteps_all_equal constraint: Δt
check the fidelity before solving
println("Before: ", rollout_fidelity(state_prob.trajectory, system))
Before: 0.1221221797409181
solve the problem
solve!(state_prob, max_iter=100, verbose=true, print_level=1);
initializing optimizer...
applying constraint: timesteps all equal constraint
applying constraint: initial value of ψ̃
applying constraint: initial value of a
applying constraint: final value of a
applying constraint: bounds on a
applying constraint: bounds on da
applying constraint: bounds on dda
applying constraint: bounds on Δt
check the fidelity after solving
println("After: ", rollout_fidelity(state_prob.trajectory, system))
After: 0.9999999998848629
extract the control pulses
state_prob.trajectory.a |> size
(2, 51)
Quantum State Minimum Time Problem
QuantumCollocation.ProblemTemplates.QuantumStateMinimumTimeProblem
— FunctionQuantumStateMinimumTimeProblem(traj, sys, obj, integrators, constraints; kwargs...)
QuantumStateMinimumTimeProblem(prob; kwargs...)
Construct a DirectTrajOptProblem
for the minimum time problem of reaching a target state.
Keyword Arguments
state_name::Symbol=:ψ̃
: The symbol for the state variables.final_fidelity::Union{Real, Nothing}=nothing
: The final fidelity.D=1.0
: The cost weight on the time.piccolo_options::PiccoloOptions=PiccoloOptions()
: The Piccolo options.
create the minimum time problem
min_state_prob = QuantumStateMinimumTimeProblem(state_prob, ψ_goal);
constructing QuantumStateMinimumTimeProblem...
final fidelity: 1.0
check the previous duration
println("Duration before: ", get_duration(state_prob.trajectory))
Duration before: 7.961222307948598
solve the minimum time problem
solve!(min_state_prob, max_iter=100, verbose=true, print_level=1);
initializing optimizer...
applying constraint: timesteps all equal constraint
applying constraint: initial value of ψ̃
applying constraint: initial value of a
applying constraint: final value of a
applying constraint: bounds on a
applying constraint: bounds on da
applying constraint: bounds on dda
applying constraint: bounds on Δt
check the new duration
println("Duration after: ", get_duration(min_state_prob.trajectory))
Duration after: 5.000001174755045
the fidelity is preserved by a constraint
println("Fidelity after: ", rollout_fidelity(min_state_prob.trajectory, system))
Fidelity after: 0.9999999083629822
Quantum State Sampling Problem
QuantumCollocation.ProblemTemplates.QuantumStateSamplingProblem
— Functioncreate a sampling problem
driftless_system = QuantumSystem([PAULIS.X, PAULIS.Y])
sampling_state_prob = QuantumStateSamplingProblem([system, driftless_system], ψ_init, ψ_goal, T, Δt);
constructing QuantumStateSamplingProblem...
using integrator: typeof(KetIntegrator)
using 2 initial state(s)
applying timesteps_all_equal constraint: Δt
new keys are added to the trajectory for the new states
println(sampling_state_prob.trajectory.state_names)
(:ψ̃1_system_1, :a, :da, :ψ̃1_system_2)
solve the sampling problem for a few iterations
solve!(sampling_state_prob, max_iter=25, verbose=true, print_level=1);
initializing optimizer...
applying constraint: timesteps all equal constraint
applying constraint: initial value of ψ̃1_system_1
applying constraint: initial value of a
applying constraint: initial value of ψ̃1_system_2
applying constraint: final value of a
applying constraint: bounds on a
applying constraint: bounds on da
applying constraint: bounds on dda
applying constraint: bounds on Δt
check the fidelity of the sampling problem (use the updated key to get the initial and goal)
println("After (original system): ", rollout_fidelity(sampling_state_prob.trajectory, system, state_name=:ψ̃1_system_1))
println("After (new system): ", rollout_fidelity(sampling_state_prob.trajectory, driftless_system, state_name=:ψ̃1_system_1))
After (original system): 0.9888117137579057
After (new system): 0.9895884605263655
compare this to using the original problem on the new system
println("After (new system, original `prob`): ", rollout_fidelity(state_prob.trajectory, driftless_system))
After (new system, original `prob`): 0.9422436462465993
This page was generated using Literate.jl.