Quantum Systems
Piccolo.jl models quantum control using drive-based Hamiltonians:
\[H(\boldsymbol{u}, t) = H_{\text{drift}} + \sum_{d} c_d(\boldsymbol{u})\, H_d\]
where $H_{\text{drift}}$ is the always-on Hamiltonian, $\{H_d\}$ are the drive operators, and $c_d(\boldsymbol{u})$ is a scalar coefficient for each drive. For standard bilinear control, $c_d = u_i$ (LinearDrive); Piccolo.jl also supports NonlinearDrive terms (e.g., $c_d = u_1^2 + u_2^2$) for displaced-frame and cross-Kerr physics.
For optimization, the Hamiltonian is converted to a generator:
\[G(\boldsymbol{u}) = -i\!\left( H_{\text{drift}} + \sum_{d} c_d(\boldsymbol{u})\, H_d \right)\]
so that $\dot{\psi} = G\,\psi$ (ket) or $\dot{U} = G\,U$ (unitary propagator). For open systems, the Lindbladian superoperator $\mathcal{G}(\boldsymbol{u})$ has the same bilinear structure (see Isomorphisms).
System Types
| Type | Dynamics | Use Case |
|---|---|---|
QuantumSystem | $\dot{U} = G\,U$ | Closed systems, gate synthesis |
OpenQuantumSystem | $\dot{\vec\rho} = \mathcal{G}\,\vec\rho$ | Dissipative systems (Lindblad) |
CompositeQuantumSystem | $\mathcal{H} = \mathcal{H}_1 \otimes \mathcal{H}_2$ | Multi-subsystem setups |
Platform Templates
Each page below documents the physical Hamiltonian, constructor API, and a worked optimization example.
| Platform | Template(s) | System Type | Key Physics |
|---|---|---|---|
| Transmon Qubits | TransmonSystem, MultiTransmonSystem, TransmonCavitySystem | QuantumSystem / CompositeQuantumSystem | Anharmonicity, dipole coupling, dispersive readout |
| Trapped Ions | IonChainSystem, RadialMSGateSystem | QuantumSystem | Motional modes, Lamb-Dicke coupling, Mølmer-Sørensen gates |
| Rydberg Atoms | RydbergChainSystem | QuantumSystem | Van der Waals blockade, global/local drives |
| Cat Qubits | CatSystem | OpenQuantumSystem | Two-photon drive, Kerr nonlinearity, photon loss |
| Silicon Spins | (coming soon) | QuantumSystem | Exchange-only qubits, detuning control |
Construction
All templates produce a QuantumSystem (or subtype) that plugs directly into Trajectories and Problem Templates:
using Piccolo
sys = TransmonSystem(levels=3, δ=0.2, drive_bounds=[0.2, 0.2])
pulse = ZeroOrderPulse(0.05 * randn(2, 100), collect(range(0, 10, 100)))
qtraj = UnitaryTrajectory(sys, pulse, GATES[:X])
qcp = SmoothPulseProblem(qtraj, 100; Q=100.0)
solve!(qcp)Custom Systems
For platforms not covered by a template, build directly from matrices:
using Piccolo
using SparseArrays
# Standard linear drives: H(u) = H_drift + u₁ H₁ + u₂ H₂
H_drift = PAULIS[:Z]
H_drives = [PAULIS[:X], PAULIS[:Y]]
drive_bounds = [1.0, 1.0]
sys = QuantumSystem(H_drift, H_drives, drive_bounds)QuantumSystem: levels = 2, n_drives = 2For systems with nonlinear drive coefficients, use typed drive terms. The Jacobian is auto-generated via ForwardDiff:
# H(u) = u₁ σx + u₂ σy + (u₁² + u₂²) σz
drives = AbstractDrive[
LinearDrive(sparse(ComplexF64.(PAULIS[:X])), 1),
LinearDrive(sparse(ComplexF64.(PAULIS[:Y])), 2),
NonlinearDrive(PAULIS[:Z], u -> u[1]^2 + u[2]^2), # auto-Jacobian
]
sys = QuantumSystem(H_drift, drives, [1.0, 1.0])QuantumSystem: levels = 2, n_drives = 2You can also provide a hand-written Jacobian (validated against ForwardDiff at construction):
NonlinearDrive(PAULIS[:Z],
u -> u[1]^2 + u[2]^2, # coefficient c(u)
(u, j) -> j == 1 ? 2u[1] : j == 2 ? 2u[2] : 0.0; # Jacobian ∂c/∂uⱼ
active_controls = [1, 2] # structural sparsity hint
)NonlinearDrive{Main.var"#6#7", Main.var"#8#9"}(sparse([1, 2], [1, 2], ComplexF64[1.0 + 0.0im, -1.0 + 0.0im], 2, 2), Main.var"#6#7"(), Main.var"#8#9"(), [1, 2])All Hamiltonians must be Hermitian ($H = H^\dagger$); Piccolo.jl validates this at construction.
See Also
- Trajectories — Combining systems with pulses and goals
- Pulses — Control parameterizations
- Problem Templates — Setting up optimization
- Isomorphisms — How complex matrices become real generators