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.