SpinChainAngledDrive¶
- class qugradlab.systems.semiconducting.esr.SpinChainAngledDrive(spins: int, zeeman_splittings: ndarray[float], drive_vectors: ndarray[float], max_drive_strength: float, J_max: float, J_min: float = 0, feromagnetic: bool = True, use_graph: bool = True)[source]¶
Bases:
Controls,QubitSystemA
qugrad.QuantumSystemfor a spin chain with electron spin resonance (ESR) controls. The Hamiltonian is given bywhere \(\vec\sigma_i\equiv\begin{pmatrix}X_i & Y_i & Z_i\end{pmatrix}^\intercal\) is the vector of the Pauli-x, -y, and -z operators acting on the \(i\)th spin, \(B_i\) are the Zeeman splittings, \(J_i(t)\) is the exchange coupling, \(\vec v_i\) are the drive vectors, and\[ H(t) = \sum_{i=0}^{\texttt{spins}-1} \frac{1}{2} B_i Z_i + g(t) \sum_{i=0}^{\texttt{spins}-1} \frac{1}{2} \vec v_i \cdot \vec\sigma_i + \frac{1}{4} \sum_{i=0}^{\texttt{spins}-2} J_i(t) \vec\sigma_i \cdot \vec\sigma_{i+1}, \]is the Rabi drive with frequency components \(\omega_j\) and amplitudes \(a_j(t)\).\[ g(t) = \sum_{j=0}^{\texttt{spins}-1}\real\left(a_j(t)e^{i\omega_j t}\right), \]See also
Attributes
An array of the system's control Hamiltonians with shape (
n_ctrl,dim,dim).The maximum value of the exchange coupling \(J\)
The minimum value of the exchange coupling \(J\)
The dimension of states in the quantum system.
The drive vectors for each of the spins
The integrator used for time evolutions of the system.
Whether the exchange coupling is ferromagnetic or antiferromagnetic
The Hilbert space of the system
The maximum drive strength that can be applied to the system
The number of control Hamiltonians.
The shape of the states in the system.
Whether to use TensorFlow graphs during computation.
The Zeeman splittings of the spins
Methods
Computes the system Hamiltonian for the specified control amplitudes.
Initialises a spin chain with ESR controls.
When calling any evolution method (listed in the See also section section)
_pre_processing()is executed on the arguements before the control amplitudes are modulated by the frequencies during_envolope_processing()and then finally the modulated control amplitudes are used by the evolution method.When calling any evolution method (listed in the See also section)
_pre_processing()is executed on the arguments before the control amplitudes are modulated by the frequencies (during_envolope_processing()) and then finally the modulated control amplitudes are used by the evolution method.Evolves a state vector under the time-dependent Hamiltonian defined by the control amplitudes and computes the expectation value of a specified observable with respect to the final state using
evolved_expectation_value()from PySTE.Evolves a state vector under the time-dependent Hamiltonian defined by the control amplitudes and computes the expectation value of a specified observable with respect to the state at each time-step using
evolved_expectation_value_all()from PySTE.When calling any evolution method (listed in the See also section`) get_driving_pulses() is executed on the arguements before the evolution method.
Evolves a state vector under the time-dependent Hamiltonian defined by the control amplitudes and computes the expectation value of a specified observable with respect to the final state and then computes the gradient of the final state with respect to the first argument (
args[0]) usingswitching_function()from PySTE.Evolves a state vector under the time-dependent Hamiltonian defined by the control amplitudes using
propagate()from PySTE.Evolves a state vector under the time-dependent Hamiltonian defined by the control amplitudes using
propagate_all()from PySTE and returns the state at each time-step.Evolves a collection of state vectors under the time-dependent Hamiltonian defined by the control amplitudes using
propagate_collection()from PySTE.Initialises a new
QuantumSystemin which_pre_processing()corresponds to executingpulse_function()and piping the output into the previous definition of_pre_processing().
- H(ctrl_amp: ndarray[float] | ndarray[Callable[[float], ndarray[float]]]) ndarray[complex] | Callable[[float], ndarray[complex]]¶
Computes the system Hamiltonian for the specified control amplitudes.
- Parameters:
ctrl_amp (NDArray[Shape[s := Any_Shape,
n_ctrl], float | Callable[[float], np.ndarray[float]]]) – The control amplitudes (stored in the last axis). The prior axes allow for multiple sets of control amplitudes to be passed and the Hamiltonian for each computed. The control amplitudes can be passed asnp.ndarray[float]to compute the system Hamiltonian for a specific value of the control ampltiudes. Alternatively, the control amplitudes can be passed asnp.ndarray[Callable[[float], np.ndarray[float]]]where each element is a function of time. This will generate a time-dependent Hamiltonian: a function that takes a single parameter (time) and returns the Hamiltonian at this time.- Returns:
Either the systems Hamiltonian stored in the last two axes (if specific control amplitudes were passed) or a collection of time-dependent Hamiltonians (if time-dependent controls were passed).
- Return type:
NDArray[Shape[s,
dim,dim], complex] | NDArray[Shape[s], Callable[[float], np.ndarray[complex]]]]
- __init__(spins: int, zeeman_splittings: ndarray[float], drive_vectors: ndarray[float], max_drive_strength: float, J_max: float, J_min: float = 0, feromagnetic: bool = True, use_graph: bool = True)[source]¶
Initialises a spin chain with ESR controls. The Hamiltonian is given by:
where \(\vec\sigma_i\equiv\begin{pmatrix}X_i&Y_i&Z_i\end{pmatrix}^\intercal\) is the vector of the Pauli-x, -y, and -z operators acting on the \(i\)th spin, \(B_i\) corresponds to zeeman_splittings, \(J_i(t)\) is the exchange coupling, \(\vec v_i\) corresponds to drive_vectors, and\[ H(t) = \sum_{i=0}^{\texttt{spins}-1} \frac{1}{2} B_i Z_i + g(t) \sum_{i=0}^{\texttt{spins}-1} \frac{1}{2} \vec v_i \cdot \vec\sigma_i + \frac{1}{4} \sum_{i=0}^{\texttt{spins}-2} J_i(t) \vec\sigma_i \cdot \vec\sigma_{i+1}, \]is the Rabi drive with frequency components \(\omega_j\) and amplitudes \(a_j(t)\).\[ g(t) = \sum_{j=0}^{\texttt{spins}-1}\real\left(a_j(t)e^{i\omega_j t}\right), \]- Parameters:
spins (int) – The number of spins in the chain
zeeman_splittings (NDArray[Shape[spins], float]) – The Zeeman splitting of each of the spins
drive_vectors (NDArray[Shape[spins, 3], float]) – The drive vectors for each of the spins
max_drive_strength (float) –
The maximum drive strength that can be applied at a specific frequency and quadrature. That is if their are
n_drive_ctrlfrequencies and both quadratures are used then the maximum amplitude of the drive that can be applied to the device is:np.sqrt(2) * n_drive_ctrl * max_drive_strength
J_max (float) – The minimum value of the exchange coupling \(J\)
J_min (float) – The maximum value of the exchange coupling \(J\), by default 0
feromagnetic (bool) – If
True, the exchange coupling is ferromagnetic. IfFalse, the exchange coupling is antiferromagnetic. By default,True.use_graph (bool) – Whether to use TensorFlow graphs during computation, by default
True
- _envolope_processing(ctrl_amp, dt: float, frequencies, number_channels: list[int]) tuple¶
When calling any evolution method (listed in the See also section section)
_pre_processing()is executed on the arguements before the control amplitudes are modulated by the frequencies during_envolope_processing()and then finally the modulated control amplitudes are used by the evolution method.- Parameters:
ctrl_amp (tf.Tensor[Shape[n_time_steps, total_n_channels], tf.complex128]) – The envolope control amplitudes
dt (float) – The itegration time step
frequencies (tf.Tensor[Shape[n_time_steps, total_n_channels], tf.complex128]) – The frequencies to modulate the control amplitudes with
The number of channels associated with each control Hamiltonian
Warning
This must be a
listand not anNDArrayor a TensorFlow tensor.
- Returns:
The modulated control amplitudes
- Return type:
tf.Tensor[Shape[n_time_steps,
n_ctrl], tf.complex128]
- _pre_processing(drive_ctrl_amp: ndarray[complex], drive_frequencies: ndarray[complex], J_ctrl_amp: ndarray[complex], initial_state: ndarray[complex], dt: float) tuple¶
When calling any evolution method (listed in the See also section)
_pre_processing()is executed on the arguments before the control amplitudes are modulated by the frequencies (during_envolope_processing()) and then finally the modulated control amplitudes are used by the evolution method._pre_processing()can be overridden to produce desired pulse shapes. You can either override_pre_processing()directly by creating a child class, or you can usepulse_form().For
gradient()to function correctly_pre_processing()should be written in TensorFlow.- Parameters:
drive_ctrl_amp (NDArray[Shape[n_time_steps, n_drive_ctrl], complex]) – The control amplitudes for the global Rabi-drive Hamiltonian. These values should be in the range [
-1,1] and will be linearly rescaled to the range [−max_drive_strength,max_drive_strength] where-1corresponds to the −max_drive_strengthand1to themax_drive_strength.drive_frequencies (NDArray[Shape[n_drive_ctrl], complex]) – The frequencies to modulate the control amplitude of the global Rabi-drive Hamiltonian with
J_ctrl_amp (NDArray[Shape[n_time_steps, n_J_ctrl], complex]) – The control amplitudes for the exchange Hamiltonians. These values should be in the range [
-1,1] and will be linearly rescaled to the range [J_min,J_max] where-1corresponds to theJ_minand1to theJ_max.initial_state (NDArray[Shape[
dim], complex]) – The initial state for the integratordt (float) – The itegration time step
- Returns:
tuple[tf.Tensor[Shape[n_time_steps, total_n_channels], tf.complex128], tf.Tensor[Shape[ – A tuple of 1. The control amplitude envolopes 2. The initial state 3. The integrator time step 4. The frequencies to modulate the control amplitude envolopes with 5. A list of the number of channels for each control Hamiltonian
Warning
The number of channels for each control Hamiltonian must be stored as a
listand not anNDArrayor a TensorFlow tensor.- Return type:
attr:
state_shape], tf.complex128], float, tf.Tensor[Shape[n_time_steps, total_n_channels], tf.complex128], list[int]]
- evolved_expectation_value(drive_ctrl_amp: ndarray[complex], drive_frequencies: ndarray[complex], J_ctrl_amp: ndarray[complex], initial_state: ndarray[complex], dt: float, observable: ndarray[complex]) complex¶
Evolves a state vector under the time-dependent Hamiltonian defined by the control amplitudes and computes the expectation value of a specified observable with respect to the final state using
evolved_expectation_value()from PySTE.- Parameters:
drive_ctrl_amp (NDArray[Shape[n_time_steps, n_drive_ctrl], complex]) – The control amplitudes for the global Rabi-drive Hamiltonian. These values should be in the range [
-1,1] and will be linearly rescaled to the range [−max_drive_strength,max_drive_strength] where-1corresponds to the −max_drive_strengthand1to themax_drive_strength.drive_frequencies (NDArray[Shape[n_drive_ctrl], complex]) – The frequencies to modulate the control amplitude of the global Rabi-drive Hamiltonian with
J_ctrl_amp (NDArray[Shape[n_time_steps, n_J_ctrl], complex]) – The control amplitudes for the exchange Hamiltonians. These values should be in the range [
-1,1] and will be linearly rescaled to the range [J_min,J_max] where-1corresponds to theJ_minand1to theJ_max.initial_state (NDArray[Shape[
dim], complex]) – The initial state for the integratordt (float) – The itegration time step
observable (NDArray[Shape[
dim,dim], complex]) – The observable to take the expectation value of.
Warning
Keyword arguments are not supported.
- Returns:
The expectation value.
- Return type:
- evolved_expectation_value_all(drive_ctrl_amp: ndarray[complex], drive_frequencies: ndarray[complex], J_ctrl_amp: ndarray[complex], initial_state: ndarray[complex], dt: float, observable: ndarray[complex]) ndarray[complex]¶
Evolves a state vector under the time-dependent Hamiltonian defined by the control amplitudes and computes the expectation value of a specified observable with respect to the state at each time-step using
evolved_expectation_value_all()from PySTE.- Parameters:
drive_ctrl_amp (NDArray[Shape[n_time_steps, n_drive_ctrl], complex]) – The control amplitudes for the global Rabi-drive Hamiltonian. These values should be in the range [
-1,1] and will be linearly rescaled to the range [−max_drive_strength,max_drive_strength] where-1corresponds to the −max_drive_strengthand1to themax_drive_strength.drive_frequencies (NDArray[Shape[n_drive_ctrl], complex]) – The frequencies to modulate the control amplitude of the global Rabi-drive Hamiltonian with
J_ctrl_amp (NDArray[Shape[n_time_steps, n_J_ctrl], complex]) – The control amplitudes for the exchange Hamiltonians. These values should be in the range [
-1,1] and will be linearly rescaled to the range [J_min,J_max] where-1corresponds to theJ_minand1to theJ_max.initial_state (NDArray[Shape[
dim], complex]) – The initial state for the integratordt (float) – The itegration time step
observable (NDArray[Shape[
dim,dim], complex]) – The observable to take the expectation value of.
Warning
Keyword arguments are not supported.
- Returns:
The state at each integrator time step (including the initial state).
- Return type:
NDArray[Shape[n_time_steps+1], complex]
See also
- get_driving_pulses(drive_ctrl_amp: ndarray[complex], drive_frequencies: ndarray[complex], J_ctrl_amp: ndarray[complex], initial_state: ndarray[complex], dt: float) tuple[ndarray[complex], ndarray[complex], float]¶
When calling any evolution method (listed in the See also section`) get_driving_pulses() is executed on the arguements before the evolution method.
- Parameters:
drive_ctrl_amp (NDArray[Shape[n_time_steps, n_drive_ctrl], complex]) – The control amplitudes for the global Rabi-drive Hamiltonian. These values should be in the range [
-1,1] and will be linearly rescaled to the range [−max_drive_strength,max_drive_strength] where-1corresponds to the −max_drive_strengthand1to themax_drive_strength.drive_frequencies (NDArray[Shape[n_drive_ctrl], complex]) – The frequencies to modulate the control amplitude of the global Rabi-drive Hamiltonian with
J_ctrl_amp (NDArray[Shape[n_time_steps, n_J_ctrl], complex]) – The control amplitudes for the exchange Hamiltonians. These values should be in the range [
-1,1] and will be linearly rescaled to the range [J_min,J_max] where-1corresponds to theJ_minand1to theJ_max.initial_state (NDArray[Shape[
dim], complex]) – The initial state for the integratordt (float) – The itegration time step
Warning
Keyword arguments are not supported.
- Returns:
A tuple of: 1. Control amplitudes 2. Initial state 3. Integrator time step
- Return type:
tuple[NDArray[Shape[n_time_steps, n_ctrl], complex], NDArray[Shape[
state_shape], complex], float]
- gradient(drive_ctrl_amp: ndarray[complex], drive_frequencies: ndarray[complex], J_ctrl_amp: ndarray[complex], initial_state: ndarray[complex], dt: float, observable: ndarray[complex]) tuple[float, ndarray[float]]¶
Evolves a state vector under the time-dependent Hamiltonian defined by the control amplitudes and computes the expectation value of a specified observable with respect to the final state and then computes the gradient of the final state with respect to the first argument (
args[0]) usingswitching_function()from PySTE.- Parameters:
drive_ctrl_amp (NDArray[Shape[n_time_steps, n_drive_ctrl], complex]) – The control amplitudes for the global Rabi-drive Hamiltonian. These values should be in the range [
-1,1] and will be linearly rescaled to the range [−max_drive_strength,max_drive_strength] where-1corresponds to the −max_drive_strengthand1to themax_drive_strength.drive_frequencies (NDArray[Shape[n_drive_ctrl], complex]) – The frequencies to modulate the control amplitude of the global Rabi-drive Hamiltonian with
J_ctrl_amp (NDArray[Shape[n_time_steps, n_J_ctrl], complex]) – The control amplitudes for the exchange Hamiltonians. These values should be in the range [
-1,1] and will be linearly rescaled to the range [J_min,J_max] where-1corresponds to theJ_minand1to theJ_max.initial_state (NDArray[Shape[
dim], complex]) – The initial state for the integratordt (float) – The itegration time step
observable (NDArray[Shape[
dim,dim], complex]) – The observable to take the expectation value of.
Warning
Keyword arguments are not supported.
- initialise_evolver(sparse: bool = False, force_dynamic: bool = False)¶
Initialises
evolverwith an evolver from PySTE. PySTE is Python wrapper around the C++ header-only library Suzuki-Trotter-Evolver: a fast Schrödinger solver utilising the first-order Suzuki-Trotter expansion.Warning
This can take a very long time to execute, especially for large Hilbert space dimensions. If you plan to evolve the same quantum system many times we recommended pickling the
evolver.- Parameters:
sparse (bool) – Whether to use sparse or dense matrices during integration. To make a decision on whether sparse or dense matrices are likely to lead to faster integration you can consult the benchmarks at https://PySTE.readthedocs.io/en/latest/benchmarks.
force_dynamic (bool) –
Whether to force PySTE to use a dynamic evolver.
- propagate(drive_ctrl_amp: ndarray[complex], drive_frequencies: ndarray[complex], J_ctrl_amp: ndarray[complex], initial_state: ndarray[complex], dt: float) ndarray[complex]¶
Evolves a state vector under the time-dependent Hamiltonian defined by the control amplitudes using
propagate()from PySTE.- Parameters:
drive_ctrl_amp (NDArray[Shape[n_time_steps, n_drive_ctrl], complex]) – The control amplitudes for the global Rabi-drive Hamiltonian. These values should be in the range [
-1,1] and will be linearly rescaled to the range [−max_drive_strength,max_drive_strength] where-1corresponds to the −max_drive_strengthand1to themax_drive_strength.drive_frequencies (NDArray[Shape[n_drive_ctrl], complex]) – The frequencies to modulate the control amplitude of the global Rabi-drive Hamiltonian with
J_ctrl_amp (NDArray[Shape[n_time_steps, n_J_ctrl], complex]) – The control amplitudes for the exchange Hamiltonians. These values should be in the range [
-1,1] and will be linearly rescaled to the range [J_min,J_max] where-1corresponds to theJ_minand1to theJ_max.initial_state (NDArray[Shape[
dim], complex]) – The initial state for the integratordt (float) – The itegration time step
Warning
Keyword arguments are not supported.
- Returns:
The final state
- Return type:
NDArray[Shape[
state_shape], complex]
See also
- propagate_all(drive_ctrl_amp: ndarray[complex], drive_frequencies: ndarray[complex], J_ctrl_amp: ndarray[complex], initial_state: ndarray[complex], dt: float) ndarray[complex]¶
Evolves a state vector under the time-dependent Hamiltonian defined by the control amplitudes using
propagate_all()from PySTE and returns the state at each time-step.- Parameters:
drive_ctrl_amp (NDArray[Shape[n_time_steps, n_drive_ctrl], complex]) – The control amplitudes for the global Rabi-drive Hamiltonian. These values should be in the range [
-1,1] and will be linearly rescaled to the range [−max_drive_strength,max_drive_strength] where-1corresponds to the −max_drive_strengthand1to themax_drive_strength.drive_frequencies (NDArray[Shape[n_drive_ctrl], complex]) – The frequencies to modulate the control amplitude of the global Rabi-drive Hamiltonian with
J_ctrl_amp (NDArray[Shape[n_time_steps, n_J_ctrl], complex]) – The control amplitudes for the exchange Hamiltonians. These values should be in the range [
-1,1] and will be linearly rescaled to the range [J_min,J_max] where-1corresponds to theJ_minand1to theJ_max.initial_state (NDArray[Shape[
dim], complex]) – The initial state for the integratordt (float) – The itegration time step
Warning
Keyword arguments are not supported.
- Returns:
The state at each integrator time step (including the initial state).
- Return type:
NDArray[Shape[n_time_steps+1,
state_shape], complex]
See also
- propagate_collection(drive_ctrl_amp: ndarray[complex], drive_frequencies: ndarray[complex], J_ctrl_amp: ndarray[complex], initial_state: ndarray[complex], dt: float) ndarray[complex]¶
Evolves a collection of state vectors under the time-dependent Hamiltonian defined by the control amplitudes using
propagate_collection()from PySTE.- Parameters:
drive_ctrl_amp (NDArray[Shape[n_time_steps, n_drive_ctrl], complex]) – The control amplitudes for the global Rabi-drive Hamiltonian. These values should be in the range [
-1,1] and will be linearly rescaled to the range [−max_drive_strength,max_drive_strength] where-1corresponds to the −max_drive_strengthand1to themax_drive_strength.drive_frequencies (NDArray[Shape[n_drive_ctrl], complex]) – The frequencies to modulate the control amplitude of the global Rabi-drive Hamiltonian with
J_ctrl_amp (NDArray[Shape[n_time_steps, n_J_ctrl], complex]) – The control amplitudes for the exchange Hamiltonians. These values should be in the range [
-1,1] and will be linearly rescaled to the range [J_min,J_max] where-1corresponds to theJ_minand1to theJ_max.initial_state (NDArray[Shape[
dim], complex]) – The initial state for the integratordt (float) –
The itegration time step
Warning
This must be a
listand not anNDArrayor a TensorFlow tensor.
Warning
Keyword arguments are not supported.
- Returns:
The final state
- Return type:
NDArray[Shape[n_states,
state_shape], complex]
See also
- pulse_form(pulse_function: Callable, path: str | None = None) PulseForm¶
Initialises a new
QuantumSystemin which_pre_processing()corresponds to executingpulse_function()and piping the output into the previous definition of_pre_processing().- Parameters:
pulse_function (Callable) – The function to compose with
_pre_processing().- Returns:
The new
QuantumSystem- Return type:
PulseForm
- property Hs: ndarray[complex]¶
An array of the system’s control Hamiltonians with shape (
n_ctrl,dim,dim).See also
- property evolver: UnitaryEvolver¶
The integrator used for time evolutions of the system.
Note
The evolver can take a while to initialise and so is not initialised until evolver is is first used or when
initialise_evolver()is called. Using evolver before callinginitialise_evolver()initialises the evolver with the default parameters ofinitialise_evolver().
- property hilbert_space: HilbertSpace¶
The Hilbert space of the system
- property using_graph: bool¶
Whether to use TensorFlow graphs during computation. Using a TensorFlow graph will increase the speed of computation. However, you have to be careful that function parameters have not been baked into the graph leading to unexpected behaviour.