using NamedTrajectories
using PiccoloQuantumObjects
using QuantumCollocation
Unitary Smooth Pulse Problem
QuantumCollocation.ProblemTemplates.UnitarySmoothPulseProblem
— FunctionUnitarySmoothPulseProblem(system::AbstractQuantumSystem, operator::AbstractPiccoloOperator, T::Int, Δt::Float64; kwargs...)
UnitarySmoothPulseProblem(H_drift, H_drives, operator, T, Δt; kwargs...)
Construct a DirectTrajOptProblem
for a free-time unitary gate problem with smooth control pulses enforced by constraining the second derivative of the pulse trajectory, i.e.,
\[\begin{aligned} \underset{\vec{\tilde{U}}, a, \dot{a}, \ddot{a}, \Delta t}{\text{minimize}} & \quad Q \cdot \ell\qty(\vec{\tilde{U}}_T, \vec{\tilde{U}}_{\text{goal}}) + \frac{1}{2} \sum_t \qty(R_a a_t^2 + R_{\dot{a}} \dot{a}_t^2 + R_{\ddot{a}} \ddot{a}_t^2) \\ \text{ subject to } & \quad \vb{P}^{(n)}\qty(\vec{\tilde{U}}_{t+1}, \vec{\tilde{U}}_t, a_t, \Delta t_t) = 0 \\ & \quad a_{t+1} - a_t - \dot{a}_t \Delta t_t = 0 \\ & \quad \dot{a}_{t+1} - \dot{a}_t - \ddot{a}_t \Delta t_t = 0 \\ & \quad |a_t| \leq a_{\text{bound}} \\ & \quad |\ddot{a}_t| \leq \ddot{a}_{\text{bound}} \\ & \quad \Delta t_{\text{min}} \leq \Delta t_t \leq \Delta t_{\text{max}} \\ \end{aligned}\]
where, for $U \in SU(N)$,
\[\ell\qty(\vec{\tilde{U}}_T, \vec{\tilde{U}}_{\text{goal}}) = \abs{1 - \frac{1}{N} \abs{ \tr \qty(U_{\text{goal}}, U_T)} }\]
is the infidelity objective function, $Q$ is a weight, $R_a$, $R_{\dot{a}}$, and $R_{\ddot{a}}$ are weights on the regularization terms, and $\vb{P}^{(n)}$ is the $n$th-order Pade integrator.
Arguments
system::AbstractQuantumSystem
: the system to be controlled
or
H_drift::AbstractMatrix{<:Number}
: the drift hamiltonianH_drives::Vector{<:AbstractMatrix{<:Number}}
: the control hamiltonians
with
goal::AbstractPiccoloOperator
: the target unitary, either in the form of anEmbeddedOperator
or a `Matrix{ComplexF64}T::Int
: the number of timestepsΔt::Float64
: the (initial) time step size
Keyword Arguments
piccolo_options::PiccoloOptions=PiccoloOptions()
: the options for the Piccolo solverstate_name::Symbol = :Ũ⃗
: the name of the statecontrol_name::Symbol = :a
: the name of the controltimestep_name::Symbol = :Δt
: the name of the timestepinit_trajectory::Union{NamedTrajectory, Nothing}=nothing
: an initial trajectory to usea_guess::Union{Matrix{Float64}, Nothing}=nothing
: an initial guess for the control pulsesa_bound::Float64=1.0
: the bound on the control pulsea_bounds=fill(a_bound, length(system.G_drives))
: the bounds on the control pulses, one for each driveda_bound::Float64=Inf
: the bound on the control pulse derivativeda_bounds=fill(da_bound, length(system.G_drives))
: the bounds on the control pulse derivatives, one for each drivedda_bound::Float64=1.0
: the bound on the control pulse second derivativedda_bounds=fill(dda_bound, length(system.G_drives))
: the bounds on the control pulse second derivatives, one for each driveΔt_min::Float64=Δt isa Float64 ? 0.5 * Δt : 0.5 * mean(Δt)
: the minimum time step sizeΔt_max::Float64=Δt isa Float64 ? 1.5 * Δt : 1.5 * mean(Δt)
: the maximum time step sizeQ::Float64=100.0
: the weight on the infidelity objectiveR=1e-2
: the weight on the regularization termsR_a::Union{Float64, Vector{Float64}}=R
: the weight on the regularization term for the control pulsesR_da::Union{Float64, Vector{Float64}}=R
: the weight on the regularization term for the control pulse derivativesR_dda::Union{Float64, Vector{Float64}}=R
: the weight on the regularization term for the control pulse second derivativesconstraints::Vector{<:AbstractConstraint}=AbstractConstraint[]
: the constraints to enforce
The UnitarySmoothPulseProblem
is similar to the QuantumStateSmoothPulseProblem
, but instead of driving the system to a target state, the goal is to drive the system to a target unitary operator, U_goal
.
system = QuantumSystem(0.1 * PAULIS.Z, [PAULIS.X, PAULIS.Y])
U_goal = GATES.H
T = 51
Δt = 0.2
prob = UnitarySmoothPulseProblem(system, U_goal, T, Δt);
constructing UnitarySmoothPulseProblem...
using integrator: typeof(UnitaryIntegrator)
control derivative names: [:da, :dda]
applying timesteps_all_equal constraint: Δt
check the fidelity before solving
println("Before: ", unitary_rollout_fidelity(prob.trajectory, system))
Before: 0.052704898220366614
finding an optimal control is as simple as calling solve!
solve!(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: ", unitary_rollout_fidelity(prob.trajectory, system))
After: 0.999999997330097
The NamedTrajectory
object stores the control pulse, state variables, and the time grid.
extract the control pulses
prob.trajectory.a |> size
(2, 51)
Unitary Minimum Time Problem
QuantumCollocation.ProblemTemplates.UnitaryMinimumTimeProblem
— FunctionUnitaryMinimumTimeProblem(
goal::AbstractPiccoloOperator,
trajectory::NamedTrajectory,
objective::Objective,
dynamics::TrajectoryDynamics,
constraints::AbstractVector{<:AbstractConstraint};
kwargs...
)
UnitaryMinimumTimeProblem(
goal::AbstractPiccoloOperator,
prob::DirectTrajOptProblem;
kwargs...
)
Create a minimum-time problem for unitary control.
\[\begin{aligned} \underset{\vec{\tilde{U}}, a, \dot{a}, \ddot{a}, \Delta t}{\text{minimize}} & \quad J(\vec{\tilde{U}}, a, \dot{a}, \ddot{a}) + D \sum_t \Delta t_t \\ \text{ subject to } & \quad \vb{P}^{(n)}\qty(\vec{\tilde{U}}_{t+1}, \vec{\tilde{U}}_t, a_t, \Delta t_t) = 0 \\ & c(\vec{\tilde{U}}, a, \dot{a}, \ddot{a}) = 0 \\ & \quad \Delta t_{\text{min}} \leq \Delta t_t \leq \Delta t_{\text{max}} \\ \end{aligned}\]
Keyword Arguments
piccolo_options::PiccoloOptions=PiccoloOptions()
: The Piccolo options.unitary_name::Symbol=:Ũ⃗
: The name of the unitary for the goal.final_fidelity::Float64=1.0
: The final fidelity constraint.D::Float64=1.0
: The scaling factor for the minimum-time objective.
The goal of this problem is to find the shortest time it takes to drive the system to a target unitary operator, U_goal
. The problem is solved by minimizing the sum of all of the time steps. It is constructed from prob
in the previous example.
min_prob = UnitaryMinimumTimeProblem(prob, U_goal);
constructing UnitaryMinimumTimeProblem...
final fidelity: 1.0
check the previous duration
println("Duration before: ", get_duration(prob.trajectory))
Duration before: 13.737976970100554
solve the minimum time problem
solve!(min_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_prob.trajectory))
Duration after: 5.0000403003566065
the fidelity is preserved by a constraint
println("Fidelity after: ", unitary_rollout_fidelity(min_prob.trajectory, system))
Fidelity after: 0.9999999999999671
Unitary Sampling Problem
QuantumCollocation.ProblemTemplates.UnitarySamplingProblem
— FunctionUnitarySamplingProblem(systemns, operator, T, Δt; kwargs...)
A UnitarySamplingProblem
is a quantum control problem where the goal is to find a control pulse that generates a target unitary operator for a set of quantum systems. The controls are shared among all systems, and the optimization seeks to find the control pulse that achieves the operator for each system. The idea is to enforce a robust solution by including multiple systems reflecting the problem uncertainty.
Arguments
systems::AbstractVector{<:AbstractQuantumSystem}
: A vector of quantum systems.operators::AbstractVector{<:AbstractPiccoloOperator}
: A vector of target operators.T::Int
: The number of time steps.Δt::Union{Float64, Vector{Float64}}
: The time step value or vector of time steps.
Keyword Arguments
system_labels::Vector{String} = string.(1:length(systems))
: The labels for each system.system_weights::Vector{Float64} = fill(1.0, length(systems))
: The weights for each system.init_trajectory::Union{NamedTrajectory, Nothing} = nothing
: The initial trajectory.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.constraints::Vector{<:AbstractConstraint} = AbstractConstraint[]
: The constraints.a_bound::Float64 = 1.0
: The bound for the control amplitudes.a_bounds = fill(a_bound, length(systems[1].G_drives))
: The bounds for the control amplitudes.a_guess::Union{Matrix{Float64}, Nothing} = nothing
: The initial guess for the control amplitudes.da_bound::Float64 = Inf
: The bound for the control first derivatives.da_bounds = fill(da_bound, length(systems[1].G_drives))
: The bounds for the control first derivatives.dda_bound::Float64 = 1.0
: The bound for the control second derivatives.dda_bounds = fill(dda_bound, length(systems[1].G_drives))
: The bounds for the control second derivatives.Δt_min::Float64 = 0.5 * Δt
: The minimum time step size.Δt_max::Float64 = 1.5 * Δt
: The maximum time step size.Q::Float64 = 100.0
: The fidelity weight.R::Float64 = 1e-2
: The regularization weight.R_a::Union{Float64, Vector{Float64}} = R
: The regularization weight for the control amplitudes.R_da::Union{Float64, Vector{Float64}} = R
: The regularization weight for the control first derivatives.R_dda::Union{Float64, Vector{Float64}} = R
: The regularization weight for the control second derivatives.piccolo_options::PiccoloOptions = PiccoloOptions()
: The Piccolo options.
A sampling problem is used to solve over multiple quantum systems with the same control. This can be useful for exploring robustness, for example.
create a sampling problem
driftless_system = QuantumSystem([PAULIS.X, PAULIS.Y])
sampling_prob = UnitarySamplingProblem([system, driftless_system], U_goal, T, Δt);
constructing UnitarySamplingProblem...
using integrator: typeof(UnitaryIntegrator)
using 2 systems
applying timesteps_all_equal constraint: Δt
new keys are addded to the trajectory for the new states
println(sampling_prob.trajectory.state_names)
(:Ũ⃗_system_1, :a, :da, :Ũ⃗_system_2)
the solve!
proceeds as in the Quantum State Sampling Problem]
Unitary Variational Problem
QuantumCollocation.ProblemTemplates.UnitaryVariationalProblem
— FunctionUnitaryVariationalProblem(
system::VariationalQuantumSystem,
goal::AbstractPiccoloOperator,
T::Int,
Δt::Union{Float64, <:AbstractVector{Float64}};
robust_times::AbstractVector{<:Union{AbstractVector{Int}, Nothing}}=[nothing for s ∈ system.G_vars],
sensitive_times::AbstractVector{<:Union{AbstractVector{Int}, Nothing}}=[nothing for s ∈ system.G_vars],
kwargs...
)
Constructs a unitary variational problem for optimizing quantum control trajectories.
Arguments
system::VariationalQuantumSystem
: The quantum system to be controlled, containing variational parameters.goal::AbstractPiccoloOperator
: The target operator or state to achieve at the end of the trajectory.T::Int
: The total number of timesteps in the trajectory.Δt::Union{Float64, <:AbstractVector{Float64}}
: The timestep duration or a vector of timestep durations.
Keyword Arguments
robust_times::AbstractVector
: Times at which robustness to variations in the trajectory is enforced.sensitive_times::AbstractVector
: Times at which sensitivity to variations in the trajectory is enhanced.unitary_integrator
: The integrator used for unitary evolution (default:VariationalUnitaryIntegrator
).state_name::Symbol
: The name of the state variable in the trajectory (default::Ũ⃗
).variational_state_name::Symbol
: The name of the variational state variable (default::Ũ⃗ₐ
).variational_scales::AbstractVector
: Scaling factors for the variational state variables (default:1.0
).control_name::Symbol
: The name of the control variable (default::a
).timestep_name::Symbol
: The name of the timestep variable (default::Δt
).init_trajectory::Union{NamedTrajectory, Nothing}
: An optional initial trajectory to start optimization.a_bound::Float64
: The bound for the control variablea
(default:1.0
).a_bounds
: Bounds for each control variable (default: filled witha_bound
).da_bound::Float64
: The bound for the derivative of the control variable (default:Inf
).da_bounds
: Bounds for each derivative of the control variable.dda_bound::Float64
: The bound for the second derivative of the control variable (default:1.0
).dda_bounds
: Bounds for each second derivative of the control variable.Δt_min::Float64
: Minimum allowed timestep duration.Δt_max::Float64
: Maximum allowed timestep duration.Q::Float64
: Weight for the unitary infidelity objective (default:100.0
).Q_v::Float64
: Weight for sensitivity objectives (default:1.0
).R
: Regularization weight for control variables (default:1e-2
).R_a
,R_da
,R_dda
: Regularization weights for control, its derivative, and second derivative.constraints::Vector
: Additional constraints for the optimization problem.piccolo_options::PiccoloOptions
: Options for configuring the Piccolo optimization framework.
Returns
A DirectTrajOptProblem
object representing the optimization problem, including the trajectory, objective, integrators, and constraints.
Notes
This function constructs a trajectory optimization problem for quantum control using variational principles. It supports robust and sensitive trajectory design, regularization, and optional constraints. The problem is solved using the Piccolo optimization framework.
The UnitaryVariationalProblem
uses a VariationalQuantumSystem
to find a control that is sensitive or robust to terms in the Hamiltonian. See the documentation for the VariationalQuantumSystem
in PiccoloQuantumObjects.jl
for more details.
create a variational system, with a variational Hamiltonian, PAULIS.X
H_var = PAULIS.X
varsys = VariationalQuantumSystem([PAULIS.X, PAULIS.Y], [H_var]);
create a variational problem that is robust to PAULIS.X
at the end
robprob = UnitaryVariationalProblem(varsys, U_goal, T, Δt, robust_times=[[T]]);
constructing UnitaryVariationalProblem...
using integrator: typeof(VariationalUnitaryIntegrator)
total variational parameters: 1
robust knot points: [[51]]
sensitive knot points: [Int64[]]
control derivative names: [:da, :dda]
applying timesteps_all_equal constraint: Δt
This page was generated using Literate.jl.