Multilevel Transmon
In this example we will look at a multilevel transmon qubit with a Hamiltonian given by
\[\hat{H}(t) = -\frac{\delta}{2} \hat{n}(\hat{n} - 1) + u_1(t) (\hat{a} + \hat{a}^\dagger) + u_2(t) i (\hat{a} - \hat{a}^\dagger)\]
where $\hat{n} = \hat{a}^\dagger \hat{a}$ is the number operator, $\hat{a}$ is the annihilation operator, $\delta$ is the anharmonicity, and $u_1(t)$ and $u_2(t)$ are control fields.
We will use the following parameter values:
\[\begin{aligned} \delta &= 0.2 \text{ GHz}\\ \abs{u_i(t)} &\leq 0.2 \text{ GHz}\\ T_0 &= 10 \text{ ns}\\ \end{aligned}\]
For convenience, we have defined the TransmonSystem
function in the QuantumSystemTemplates
module, which returns a QuantumSystem
object for a transmon qubit. We will use this function to define the system.
Setting up the problem
To begin, let's load the necessary packages, define the system parameters, and create a a QuantumSystem
object using the TransmonSystem
function.
using Piccolo
using SparseArrays
using Random;
Random.seed!(123);
# define the time parameters
T₀ = 10 # total time in ns
T = 50 # number of time steps
Δt = T₀ / T # time step
# define the system parameters
levels = 5
δ = 0.2
# add a bound to the controls
a_bound = 0.2
dda_bound = 1.0
# create the system
sys = TransmonSystem(levels = levels, δ = δ)
# let's look at the parameters of the system
sys.params
Dict{Symbol, Any} with 8 entries:
:lab_frame_type => :duffing
:ω => 4.0
:lab_frame => false
:δ => 0.2
:mutiply_by_2π => true
:drives => true
:levels => 5
:frame_ω => 4.0
Since this is a multilevel transmon and we want to implement an, let's say, $X$ gate on the qubit subspace, i.e., the first two levels we can utilize the EmbeddedOperator
type to define the target operator.
# define the target operator
op = EmbeddedOperator(:X, sys)
# show the full operator
op.operator |> sparse
5×5 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 2 stored entries:
⋅ 1.0+0.0im ⋅ ⋅ ⋅
1.0+0.0im ⋅ ⋅ ⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅
We can then pass this embedded operator to the UnitarySmoothPulseProblem
template to create
# create the problem
prob = UnitarySmoothPulseProblem(sys, op, T, Δt; a_bound = a_bound, dda_bound = dda_bound)
# solve the problem
solve!(prob; max_iter = 50)
constructing UnitarySmoothPulseProblem...
using integrator: typeof(UnitaryIntegrator)
control derivative names: [:da, :dda]
applying timesteps_all_equal constraint: Δt
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
******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
Ipopt is released as open source code under the Eclipse Public License (EPL).
For more information visit https://github.com/coin-or/Ipopt
******************************************************************************
This is Ipopt version 3.14.17, running with linear solver MUMPS 5.7.3.
Number of nonzeros in equality constraint Jacobian...: 130578
Number of nonzeros in inequality constraint Jacobian.: 0
Number of nonzeros in Lagrangian Hessian.............: 11223
Total number of variables............................: 2796
variables with only lower bounds: 0
variables with lower and upper bounds: 246
variables with only upper bounds: 0
Total number of equality constraints.................: 2695
Total number of inequality constraints...............: 0
inequality constraints with only lower bounds: 0
inequality constraints with lower and upper bounds: 0
inequality constraints with only upper bounds: 0
iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
0 6.3299435e-04 9.98e-01 1.21e+01 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0
1 1.7611808e+01 4.88e-01 3.64e+03 -1.0 1.02e+00 2.0 3.63e-02 5.00e-01h 2
2 1.1626885e+01 1.95e-01 6.06e+03 -1.0 9.74e-01 2.4 5.67e-01 5.97e-01f 1
3 9.0738552e+00 1.82e-01 5.64e+03 -1.0 6.41e-01 2.9 8.73e-01 6.62e-02f 1
4 5.4476271e-01 1.32e-01 3.99e+03 -1.0 6.22e-01 2.4 1.00e+00 2.77e-01f 1
5 4.9608010e+00 1.10e-01 3.22e+03 -1.0 4.71e-01 2.8 1.00e+00 1.65e-01h 1
6 1.2131745e+01 7.23e-02 2.63e+03 -1.0 6.25e-01 2.3 1.00e+00 3.43e-01h 1
7 1.5295386e+01 5.61e-02 2.08e+03 -1.0 1.96e-01 2.7 1.00e+00 2.23e-01h 1
8 2.1787507e+01 1.81e-02 2.35e+03 -1.0 2.18e-01 2.3 1.00e+00 6.78e-01h 1
9 2.2472806e+01 1.81e-03 1.00e+03 -1.0 8.15e-02 1.8 1.00e+00 1.00e+00h 1
iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
10 1.8243233e+01 7.47e-04 8.33e+00 -1.0 7.76e-02 1.3 1.00e+00 1.00e+00f 1
11 1.2330470e+01 2.07e-03 2.00e+00 -1.0 1.28e-01 0.8 1.00e+00 1.00e+00f 1
12 7.8850401e+00 3.55e-03 3.18e+00 -1.0 1.19e-01 0.4 1.00e+00 1.00e+00f 1
13 2.3590321e+00 2.43e-02 2.06e+02 -1.0 3.46e-01 -0.1 1.00e+00 1.00e+00f 1
14 5.6339492e+00 6.29e-03 1.93e+02 -1.0 1.24e-01 0.3 1.00e+00 1.00e+00h 1
15 4.7907666e+00 6.30e-05 8.54e+00 -1.0 1.89e-02 1.6 1.00e+00 1.00e+00h 1
16 4.5971259e+00 2.41e-05 2.85e-01 -1.0 9.63e-03 1.2 1.00e+00 1.00e+00f 1
17 4.0697675e+00 1.22e-04 4.87e-01 -1.7 2.33e-02 0.7 1.00e+00 1.00e+00f 1
18 2.7231869e+00 7.64e-04 1.31e+00 -1.7 5.62e-02 0.2 1.00e+00 1.00e+00f 1
19 9.0863884e-01 3.66e-03 5.29e+00 -1.7 3.75e+01 -0.3 1.91e-02 3.24e-03f 3
iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
20 1.7938112e+00 5.45e-04 1.27e+00 -1.7 5.16e-02 0.2 1.00e+00 1.00e+00h 1
21 1.7905022e+00 6.17e-05 7.12e-02 -1.7 1.85e-02 0.6 1.00e+00 1.00e+00h 1
22 1.2784826e+00 3.84e-04 8.71e-01 -2.5 4.42e-02 0.1 1.00e+00 1.00e+00f 1
23 1.2678687e+00 4.20e-05 1.15e-01 -2.5 1.62e-02 0.5 1.00e+00 1.00e+00h 1
24 9.0086071e-01 3.64e-04 9.75e-01 -2.5 3.87e-02 0.1 1.00e+00 1.00e+00f 1
25 9.3918137e-01 3.20e-05 6.83e-02 -2.5 1.37e-02 0.5 1.00e+00 1.00e+00h 1
26 5.5616301e-01 4.62e-04 1.42e+00 -2.5 4.40e-02 0.0 1.00e+00 1.00e+00f 1
27 7.2172706e-01 2.80e-05 1.10e-01 -2.5 1.21e-02 0.4 1.00e+00 1.00e+00h 1
28 7.0830396e-01 3.50e-06 3.26e-02 -2.5 4.52e-03 0.9 1.00e+00 1.00e+00h 1
29 6.6044209e-01 2.81e-05 3.14e-02 -2.5 1.31e-02 0.4 1.00e+00 1.00e+00f 1
iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
30 6.4560785e-01 3.89e-06 3.14e-02 -2.5 4.91e-03 0.8 1.00e+00 1.00e+00h 1
31 6.0067414e-01 3.20e-05 3.01e-02 -2.5 1.41e-02 0.3 1.00e+00 1.00e+00f 1
32 5.8655363e-01 4.42e-06 3.00e-02 -2.5 5.27e-03 0.8 1.00e+00 1.00e+00h 1
33 5.4406614e-01 3.63e-05 2.87e-02 -2.5 1.51e-02 0.3 1.00e+00 1.00e+00f 1
34 5.3068545e-01 5.00e-06 2.85e-02 -2.5 5.64e-03 0.7 1.00e+00 1.00e+00h 1
35 4.9045153e-01 4.09e-05 2.72e-02 -2.5 1.61e-02 0.2 1.00e+00 1.00e+00h 1
36 4.7766299e-01 5.77e-06 2.78e-02 -3.8 6.19e-03 0.7 1.00e+00 1.00e+00h 1
37 4.3911494e-01 4.72e-05 4.45e-02 -3.8 1.77e-02 0.2 1.00e+00 1.00e+00h 1
38 4.2717857e-01 6.40e-06 2.62e-02 -3.8 6.55e-03 0.6 1.00e+00 1.00e+00h 1
39 3.9075439e-01 5.19e-05 3.43e-02 -3.8 1.87e-02 0.1 1.00e+00 1.00e+00h 1
iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
40 3.7941168e-01 6.96e-06 2.45e-02 -3.8 6.89e-03 0.6 1.00e+00 1.00e+00h 1
41 3.4507703e-01 5.61e-05 2.32e-02 -3.8 1.96e-02 0.1 1.00e+00 1.00e+00h 1
42 3.3434834e-01 7.43e-06 2.28e-02 -3.8 7.21e-03 0.5 1.00e+00 1.00e+00h 1
43 3.0181424e-01 5.87e-05 5.40e-02 -3.8 2.06e-02 0.0 1.00e+00 1.00e+00h 1
44 2.9201755e-01 7.74e-06 2.11e-02 -3.8 7.52e-03 0.4 1.00e+00 1.00e+00h 1
45 2.8812840e-01 1.08e-06 2.10e-02 -3.8 2.80e-03 0.9 1.00e+00 1.00e+00h 1
46 2.7649970e-01 9.24e-06 2.05e-02 -3.8 8.20e-03 0.4 1.00e+00 1.00e+00h 1
47 2.7244872e-01 1.26e-06 2.03e-02 -3.8 3.04e-03 0.8 1.00e+00 1.00e+00h 1
48 2.6034221e-01 1.07e-05 1.97e-02 -3.8 8.89e-03 0.3 1.00e+00 1.00e+00h 1
49 2.5615390e-01 1.46e-06 1.95e-02 -3.8 3.29e-03 0.8 1.00e+00 1.00e+00h 1
iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
50 2.4363899e-01 1.23e-05 1.89e-02 -3.8 9.60e-03 0.3 1.00e+00 1.00e+00h 1
Number of Iterations....: 50
(scaled) (unscaled)
Objective...............: 2.4363898861347127e-01 2.4363898861347127e-01
Dual infeasibility......: 1.8947104563602525e-02 1.8947104563602525e-02
Constraint violation....: 1.2333246874995929e-05 1.2333246874995929e-05
Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00
Complementarity.........: 1.5042412372085081e-04 1.5042412372085081e-04
Overall NLP error.......: 1.8947104563602525e-02 1.8947104563602525e-02
Number of objective function evaluations = 58
Number of objective gradient evaluations = 51
Number of equality constraint evaluations = 58
Number of inequality constraint evaluations = 0
Number of equality constraint Jacobian evaluations = 51
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations = 50
Total seconds in IPOPT = 439.215
EXIT: Maximum Number of Iterations Exceeded.
Let's look at the fidelity in the subspace
println(
"Fidelity: ",
unitary_rollout_fidelity(prob.trajectory, sys; subspace = op.subspace),
)
Fidelity: 0.9975846386321956
and plot the result using the plot_unitary_populations
function.
plot_unitary_populations(prob.trajectory)
Leakage suppresion
As can be seen from the above plot, there is a substantial amount of leakage into the higher levels during the evolution. To mitigate this, we have implemented the ability to add a cost to populating the leakage levels, in particular this is an $L_1$ norm cost, which is implemented via slack variables and should ideally drive those leakage populations down to zero. To implement this, pass leakage_suppresion=true
and R_leakage={value}
to the UnitarySmoothPulseProblem
template.
# create the a leakage suppression problem, initializing with the previous solution
prob_leakage = UnitarySmoothPulseProblem(
sys,
op,
T,
Δt;
a_bound = a_bound,
dda_bound = dda_bound,
leakage_suppression = true,
R_leakage = 1e-1,
a_guess = prob.trajectory.a,
)
# solve the problem
solve!(prob_leakage; max_iter = 50)
Let's look at the fidelity in the subspace
println(
"Fidelity: ",
unitary_rollout_fidelity(prob_leakage.trajectory, sys; subspace = op.subspace),
)
and plot the result using the plot_unitary_populations
function from PiccoloPlots.jl
plot_unitary_populations(prob_leakage.trajectory)
Here we can see that the leakage populations have been driven substantially down.
This page was generated using Literate.jl.