Adiabatic Pulse
Adiabatic Pulse Shaper
AdiabaticPulseShaper
is a class for implementing a standard adiabatic pulse shaping method. It creates an InterpolatedWaveform
pulse for solving a QUBOInstance
using adiabatic quantum evolution, There are no parameters to be customized.
How it works:
- Creates a normalized weights list for the later application of DMM.
- Computes the maximum amplitude value.
- Computes the global detuning values (initial and final).
- Creates a pulse with the values of amplitude, detuning and duration (4000 ns).
Fields
Field | Type | Description |
---|---|---|
pulse |
Pulse |
A Pulser-compatible pulse object generated by generate() . |
Methods
generate(register: Register, instance: QUBOInstance) -> tuple[Pulse, QUBOSolution]
Generates a shaped adiabatic pulse for the given QUBO problem and register layout.
Argument | Type | Description |
---|---|---|
register |
Register |
The spatial layout of qubits/atoms in the physical system. |
instance |
QUBOInstance |
The QUBO matrix of the problem. |
Returns
Type | Description |
---|---|
tuple[Pulse, QUBOSolution] |
Returns the generated Pulse object and a placeholder QUBOSolution (with all fields set to None ) |
Notes
The method sets:
-
pulse.norm_weights
: A normalized weight per node, used for DMM. -
pulse.duration
: Total evolution time (fixed atT = 4000
ns by default).
Definition of Amplitude and Detuning:
For the Adiabatic Pulse, the values of the amplitude \(\Omega\) (Rabi frequency) and global detuning \(\delta\) are defined in terms of the QUBOInstance
, as follows:
- Amplitude: has a sine-like shape, starting from \(0\) and ending in \(0\), with a maximum value being the maximum value among the off-diagonal terms of the QUBO matrix:
If \(\Omega_{max}\) reaches a value above the maximum amplitude allowed by the device, it uses this max_amp
as \(\Omega_{max}\).
- Detuning: starts from a negative value \(\delta_0\) that is the minimum value among the diagonal terms of the QUBO matrix (since diagonal terms are either negative or \(0\)), reaches \(0\) and ends in a positive final value \(\delta_f\), following a linear behavior:
Application of DMM
Along with the pulse created with the amplitude and detuning values, the detuning of individual qubits (defined as list of values between 0 and 1) is applied using a channel called Detuning Map Modulator or DMM
. Proportionally to the weights of each qubit, a pulse of zero amplitude and negative detuning is applied. Here, the values of the detuning are normalized in terms of the maximum absolute value of the diagonal terms and subtracted from 1. For each qubit \(i\) the value is:
This way, the qubits with lower weights receive higher detuning values, whilst the ones with higher weights receive lower values.
Example
import torch
from qubosolver import QUBOInstance
from qubosolver.config import SolverConfig, PulseShapingConfig
from qoolqit._solvers.types import BackendType, DeviceType
from qubosolver.solver import QuboSolver
from qubosolver.qubo_types import PulseType
Q = torch.tensor([
[-63.9423, 0.0000, 73.6471, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 55.2853],
[ 0.0000, -44.1916, 0.0000, 0.0000, 0.0000, 0.0000, 58.9307, 0.0000, 0.0000, 0.0000],
[ 73.6471, 0.0000, -89.8861, 51.0382, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
[ 0.0000, 0.0000, 51.0382, -63.7618, 0.0000, 0.0000, 33.9093, 0.0000, 0.0000, 0.0000],
[ 0.0000, 0.0000, 0.0000, 0.0000, -94.4426, 18.7963, 0.0000, 0.0000, 14.3994, 0.0000],
[ 0.0000, 0.0000, 0.0000, 0.0000, 18.7963, -60.7545, 0.0000, 0.0000, 0.0000, 96.9903],
[ 0.0000, 58.9307, 0.0000, 33.9093, 0.0000, 0.0000, -71.3241, 0.0000, 0.0000, 0.0000],
[ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, -38.2094, 59.3175, 0.0000],
[ 0.0000, 0.0000, 0.0000, 0.0000, 14.3994, 0.0000, 0.0000, 59.3175, -94.5790, 18.0653],
[ 55.2853, 0.0000, 0.0000, 0.0000, 0.0000, 96.9903, 0.0000, 0.0000, 18.0653, -97.3174]
])
instance = QUBOInstance(Q)
default_config = SolverConfig(
use_quantum = True, pulse_shaping=PulseShapingConfig(pulse_shaping_method=PulseType.ADIABATIC)
)
solver = QuboSolver(instance, default_config)
solution = solver.solve()
print(solution)
QUBOSolution
instance, which comprehends the solution bitstrings, the counts of each bitstring, their probabilities and costs.
Obs.: The ADIABATIC
method is the default one, it's explicit in pulse_shaping_method
for ilustration purposes.