Your first chip¶
Build a coupled transmon–resonator model, read its dressed frequencies, and find bare parameters that meet a design target. Frequencies are in GHz.
Declare the model¶
from quchip import Capacitive, Chip, DuffingTransmon, Resonator, fit_a_dress
q = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=4, label="q")
r = Resonator(freq=7.0, levels=5, label="r")
qr = Capacitive(q, r, g=0.05, label="qr")
chip = Chip([q, r], [qr])
Labels name the model’s parameters: q.freq, q.anharmonicity, and qr.g.
Inspect the declaration with describe():
print(chip.describe())
Output:
Chip
════
Frame : lab
Approx. : RWA
Dressed : not computed
Hilbert : 4 x 5 = 20 levels
Sectors : N conserved; dressed queries with N <= 2 diagonalize at most 3 states
Devices (2)
───────────
q — DuffingTransmon
T1 = None T2 = None thermal_occupation = None freq = 5 GHz anharmonicity = -0.25 GHz levels = 4
r — Resonator
T1 = None T2 = None thermal_occupation = None freq = 7 GHz internal_quality_factor = None levels = 5
Couplings (1)
─────────────
qr : q ↔ r
g = 0.05 GHz
The Sectors line shows that this RWA model conserves the total excitation
number \(N\), the sum of the device levels. Dressed queries therefore diagonalize
one small block for each \(N\) instead of all 20 levels.
chip.excitation_structure() lists the terms that decide this.
Read dressed observables¶
Device constructors specify bare parameters, and chip returns the
coupled system’s frequencies and interactions.
print(f"Qubit f01: {chip.freq(q):.6f} GHz")
print(f"Resonator frequency: {chip.freq(r):.6f} GHz")
print(f"Conditional resonator pull: {1000 * chip.dispersive_shift(q, r):.3f} MHz")
Output:
Qubit f01: 4.998751 GHz
Resonator frequency: 7.001249 GHz
Conditional resonator pull: -0.277 MHz
The full conditional pull is \(E_{11}-E_{10}-E_{01}+E_{00}\).
For quchip’s \(Z=|0\rangle\langle0|-|1\rangle\langle1|\), the coefficient
of \(Z n_r\) is negative half this pull: \(\chi_Z=-\mathrm{dispersive\_shift}/2\).
chip.kerr_matrix() collects full pulls off-diagonal and dressed
anharmonicities on the diagonal.
Change a parameter¶
with_params() returns a new chip, and the source declaration stays available.
shifted = chip.with_params({"q.freq": 5.1})
print(f"Original bare / dressed: {q.freq:.3f} / {chip.freq(q):.6f} GHz")
print(f"Changed bare / dressed: {shifted.parameters['q.freq']:.3f} / {shifted.freq('q'):.6f} GHz")
Output:
Original bare / dressed: 5.000 / 4.998751 GHz
Changed bare / dressed: 5.100 / 5.098685 GHz
Inspect the Hamiltonian¶
unresolved_hamiltonian() shows the Hamiltonian you declared. hamiltonian() is the
expression selected for simulation, after basis, frame, and RWA choices. Both show as
equations in a notebook.
declared = chip.unresolved_hamiltonian()
resolved = chip.resolve(frame="rotating")
print(resolved.dropped_terms_summary())
Output:
2 term(s) dropped:
[qr] coupling band (-1, -1) on q·r (discarded by RWA band selection; amp 0.173205 GHz, detuning 11.5 GHz)
[qr] coupling band (+1, +1) on q·r (discarded by RWA band selection; amp 0.173205 GHz, detuning 11.5 GHz)
The dropped terms create or annihilate two excitations. Each record shows
the matrix element with the largest |V|²/ΔE and its bare-energy detuning.
Here the detunings are much larger than the matrix elements. Band weights
use column - row, so lowering has positive weight.
See the physics reference for frame and approximation
conventions.
Fit a dressed target¶
For fit_a_dress(), device values specify desired dressed frequencies
and anharmonicities. Coupling values specify desired full cross-Kerr pulls.
The fit returns the bare parameters that produce those targets.
target_q = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=4, label="q")
target_r = Resonator(freq=7.0, levels=5, label="r")
target_pull = Capacitive(target_q, target_r, g=-0.0003, label="qr")
target = Chip([target_q, target_r], [target_pull])
fit = fit_a_dress(target)
print(f"Converged: {fit.converged}; normalized loss: {fit.loss:.2e}")
Output:
Converged: True; normalized loss: 5.43e-24
Inspect fitted parameters and residuals
print(fit.summary())
Output:
fit_a_dress: converged | loss 5.43e-24 | targets: 4 | parameters: 4
identifiability: rank 4/4 | condition 35.8
`xtol` termination condition is satisfied.
targets (GHz):
q.freq [component default]: 5 -> 5 (error +1.8e-15)
q.anharmonicity [component default]: -0.25 -> -0.25 (error +3.6e-15)
r.freq [component default]: 7 -> 7 (error +0)
qr.cross_kerr [component default]: -0.0003 -> -0.0003 (error +7e-16)
bare parameters (GHz):
q.freq: 5 -> 5.00135 [component declaration]
q.anharmonicity: -0.25 -> -0.2503 [component declaration]
r.freq: 7 -> 6.99865 [component declaration]
qr.g: 0.0520244 -> 0.0519304 [isolated-pair root solve; positive convention]
Continue with spectra and parameter sweeps to sweep the coupled spectrum. For imported or custom models, see scqubits interoperability and extensions.