using NamedTrajectories
using PiccoloQuantumObjects
using QuantumCollocation

Unitary Smooth Pulse Problem

QuantumCollocation.ProblemTemplates.UnitarySmoothPulseProblemFunction
UnitarySmoothPulseProblem(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 hamiltonian
  • H_drives::Vector{<:AbstractMatrix{<:Number}}: the control hamiltonians

with

  • goal::AbstractPiccoloOperator: the target unitary, either in the form of an EmbeddedOperator 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 solver
  • state_name::Symbol = :Ũ⃗: the name of the state
  • control_name::Symbol = :a: the name of the control
  • timestep_name::Symbol = :Δt: the name of the timestep
  • init_trajectory::Union{NamedTrajectory, Nothing}=nothing: an initial trajectory to use
  • a_guess::Union{Matrix{Float64}, Nothing}=nothing: an initial guess for the control pulses
  • 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 pulses, one for each drive
  • da_bound::Float64=Inf: the bound on the control pulse derivative
  • da_bounds=fill(da_bound, length(system.G_drives)): the bounds on the control pulse derivatives, one for each drive
  • dda_bound::Float64=1.0: the bound on the control pulse second derivative
  • dda_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 size
  • Q::Float64=100.0: the weight on the infidelity objective
  • R=1e-2: the weight on the regularization terms
  • R_a::Union{Float64, Vector{Float64}}=R: the weight on the regularization term for the control pulses
  • R_da::Union{Float64, Vector{Float64}}=R: the weight on the regularization term for the control pulse derivatives
  • R_dda::Union{Float64, Vector{Float64}}=R: the weight on the regularization term for the control pulse second derivatives
  • constraints::Vector{<:AbstractConstraint}=AbstractConstraint[]: the constraints to enforce
source

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.UnitaryMinimumTimeProblemFunction
UnitaryMinimumTimeProblem(
    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.
source

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.UnitarySamplingProblemFunction
UnitarySamplingProblem(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.
source

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.UnitaryVariationalProblemFunction
UnitaryVariationalProblem(
    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 variable a (default: 1.0).
  • a_bounds: Bounds for each control variable (default: filled with a_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.

source

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.