Skip to content

CNOT with interacting qubits

Digital-analog quantum computing focuses on using single qubit digital gates combined with more complex and device-dependent analog interactions to represent quantum programs. This paradigm has been shown to be universal for quantum computation1. However, while this approach may have advantages when adapting quantum programs to real devices, known quantum algorithms are very often expressed in a fully digital paradigm. As such, it is also important to have concrete ways to transform from one paradigm to another.

This tutorial will exemplify the DAQC transformation starting with the representation of a simple digital CNOT using the universality of the Ising Hamiltonian2.

CNOT with CPHASE

Let's look at a single example of how the digital-analog transformation can be used to perform a CNOT on two qubits inside a register of globally interacting qubits.

First, note that the CNOT can be decomposed with two Hadamard and a CPHASE gate with \(\phi=\pi\):

import torch
from qadence import chain, sample, product_state

from qadence.draw import display
from qadence import X, I, Z, H, N, CPHASE, CNOT, HamEvo, PI

n_qubits = 2

# CNOT gate
cnot_gate = CNOT(0, 1)

# CNOT decomposed
phi = PI
cnot_decomp = chain(H(1), CPHASE(0, 1, phi), H(1))

init_state = product_state("10")
sample from CNOT gate and 100 shots = [Counter({'11': 100})]
sample from decomposed CNOT gate and 100 shots = [Counter({'11': 100})]

The CPHASE matrix is diagonal, and can be implemented by exponentiating an Ising-like Hamiltonian, or generator,

\[\text{CPHASE}(i,j,\phi)=\text{exp}\left(-i\phi \mathcal{H}_\text{CP}(i, j)\right)\]
\[\begin{aligned} \mathcal{H}_\text{CP}&=-\frac{1}{4}(I_i-Z_i)(I_j-Z_j)\\ &=-N_iN_j \end{aligned}\]

where the number operator \(N_i = \frac{1}{2}(I_i-Z_i)=\hat{n}_i\) is used, leading to an Ising-like interaction \(\hat{n}_i\hat{n}_j\) realisable in neutral-atom systems. Let's rebuild the CNOT using this evolution.

from qadence import kron, block_to_tensor

# Hamiltonian for the CPHASE gate
h_cphase = (-1.0) * kron(N(0), N(1))

# Exponentiating and time-evolving the Hamiltonian until t=phi.
cphase_evo = HamEvo(h_cphase, phi)

# Check that we have the CPHASE gate:
cphase_matrix = block_to_tensor(CPHASE(0, 1, phi))
cphase_evo_matrix = block_to_tensor(cphase_evo)
cphase_matrix == cphase_evo_matrix: True

Now that the CPHASE generator is checked, it can be applied to the CNOT:

# CNOT with Hamiltonian Evolution
cnot_evo = chain(
    H(1),
    cphase_evo,
    H(1)
)

# Initialize state to check CNOTs sample outcomes.
init_state = product_state("10")
sample cnot_gate = [Counter({'11': 100})]
sample cnot_evo = [Counter({'11': 100})]

Thus, a CNOT gate can be created by combining a few single-qubit gates together with a two-qubit Ising interaction between the control and the target qubit which is the essence of the Ising transform proposed in the seminal DAQC paper2 for \(ZZ\) interactions. In Qadence, both \(ZZ\) and \(NN\) interactions are supported.

CNOT in an interacting system of three qubits

Consider a simple experimental setup with \(n=3\) interacting qubits laid out in a triangular grid. For the sake of simplicity, all qubits interact with each other with an \(NN\)-Ising interaction of constant strength \(g_\text{int}\). The Hamiltonian for the system can be written by summing interaction terms over all pairs:

\[\mathcal{H}_\text{sys}=\sum_{i=0}^{n}\sum_{j=0}^{i-1}g_\text{int}N_iN_j,\]

which in this case leads to only three interaction terms,

\[\mathcal{H}_\text{sys}=g_\text{int}(N_0N_1+N_1N_2+N_0N_2)\]

This generator can be easily built in Qadence:

from qadence import add, kron
n_qubits = 3

# Interaction strength.
g_int = 1.0

# Build a list of interactions.
interaction_list = []
for i in range(n_qubits):
    for j in range(i):
        interaction_list.append(g_int * kron(N(i), N(j)))

h_sys = add(*interaction_list)
h_sys = AddBlock(0,1,2)
├── [mul: 1.00000000000000] 
   └── KronBlock(0,1)
       ├── N(1)
       └── N(0)
├── [mul: 1.00000000000000] 
   └── KronBlock(0,2)
       ├── N(2)
       └── N(0)
└── [mul: 1.00000000000000] 
    └── KronBlock(1,2)
        ├── N(2)
        └── N(1)

Now let's consider that the experimental system is fixed, and qubits can not be isolated one from another. The options are:

  • Turn on or off the global system Hamiltonian.
  • Perform local single-qubit rotations.

To perform a fully digital CNOT(0,1), the interacting control on qubit 0 and target on qubit 1 must be isolated from the third one to implement the gate directly. While this can be achieved for a three-qubit system, it becomes experimentally untractable when scaling the qubit count.

However, this is not the case within the digital-analog paradigm. In fact, the two qubit Ising interaction required for the CNOT can be represented with a combination of the global system Hamiltonian and a specific set of single-qubit rotations. Full details about this transformation are to be found in the DAQC paper2 but a more succint yet in-depth description takes place in the next section. It is conveniently available in Qadence by calling the daqc_transform function.

In the most general sense, the daqc_transform function will return a circuit that represents the evolution of a target Hamiltonian \(\mathcal{H}_\text{target}\) (here the unitary of the gate) until a specified time \(t_f\) by using only the evolution of a build Hamiltonian \(\mathcal{H}_\text{build}\) (here \(\mathcal{H}_\text{sys}\)) together with local \(X\)-gates. In Qadence, daqc_transform is applicable for \(\mathcal{H}_\text{target}\) and \(\mathcal{H}_\text{build}\) composed only of \(ZZ\)- or \(NN\)-interactions. These generators are parsed by the daqc_transform function and the appropriate type is automatically determined together with the appropriate single-qubit detunings and global phases.

Let's apply it for the CNOT implementation:

from qadence import daqc_transform, Strategy

# Settings for the target CNOT operation
i = 0  # Control qubit
j = 1  # Target qubit
k = 2  # The extra qubit

# Define the target CNOT operation
# by composing with identity on the extra qubit.
cnot_target = kron(CNOT(i, j), I(k))

# The two-qubit NN-Ising interaction term for the CPHASE
h_int = (-1.0) * kron(N(i), N(j))

# Transforming the two-qubit Ising interaction using only our system Hamiltonian
transformed_ising = daqc_transform(
    n_qubits=3,        # Total number of qubits in the transformation
    gen_target=h_int,  # The target Ising generator
    t_f=PI,            # The target evolution time
    gen_build=h_sys,   # The building block Ising generator to be used
    strategy=Strategy.SDAQC,   # Currently only sDAQC is implemented
    ignore_global_phases=False  # Global phases from mapping between Z and N
)

# display(transformed_ising)
%3 cluster_b497e439d944476893ea8db6f701566a cluster_e470c497eca14c359921cc1c54c521dd cluster_da15075112b84d9c95d34b5f60f18a62 cluster_3eb7af709f294c65af518d773073a6cd cluster_21343d5f0f4c4697a75b843b08679d50 cluster_6b099851d3f243bda16b332988be8deb cluster_7375e4292c60422391857c72ae161e0c 2762e40572e24ca197eaf866e07c526b 0 827386fc8f3f4f3591761ff218de2c25 HamEvo 2762e40572e24ca197eaf866e07c526b--827386fc8f3f4f3591761ff218de2c25 2c6ffd89a70e4406af0f9410e38af653 1 33863a4ec2a4420995036ef07c7ea8b5 HamEvo 827386fc8f3f4f3591761ff218de2c25--33863a4ec2a4420995036ef07c7ea8b5 288fd3e250af4a2a84f03044419bc7df HamEvo 33863a4ec2a4420995036ef07c7ea8b5--288fd3e250af4a2a84f03044419bc7df 7fbcbdb7eaba46db8c4034d09d82ffcf X 288fd3e250af4a2a84f03044419bc7df--7fbcbdb7eaba46db8c4034d09d82ffcf 23f9cd54180840bf854475bd3fe8356c HamEvo 7fbcbdb7eaba46db8c4034d09d82ffcf--23f9cd54180840bf854475bd3fe8356c a6a55093080944b3a32582f2487bdcb1 HamEvo 23f9cd54180840bf854475bd3fe8356c--a6a55093080944b3a32582f2487bdcb1 8b4650a4e0ee4d52b49a0d468c8e0d2a X a6a55093080944b3a32582f2487bdcb1--8b4650a4e0ee4d52b49a0d468c8e0d2a cb6503b18c7449278d8253f67270aba8 8b4650a4e0ee4d52b49a0d468c8e0d2a--cb6503b18c7449278d8253f67270aba8 a465b1c10ec648678b17af16c9af5a10 HamEvo cb6503b18c7449278d8253f67270aba8--a465b1c10ec648678b17af16c9af5a10 1fce0ae82f904164bf612365bcff87fd HamEvo a465b1c10ec648678b17af16c9af5a10--1fce0ae82f904164bf612365bcff87fd 9e3a7ea5d702458991170df8a413f4ac 1fce0ae82f904164bf612365bcff87fd--9e3a7ea5d702458991170df8a413f4ac 2c027b38da7249a7a712cb5a313ce6eb 9e3a7ea5d702458991170df8a413f4ac--2c027b38da7249a7a712cb5a313ce6eb 0d65f0a8dae347c3843949516ce0aa91 87528705aff5400f9b6829c3e54640bd t = -3.142 2c6ffd89a70e4406af0f9410e38af653--87528705aff5400f9b6829c3e54640bd a861fc6acfc148a58289acaf99dcb7c5 2 55d23a09fb434081a5e9d9df82c53e50 t = 3.142 87528705aff5400f9b6829c3e54640bd--55d23a09fb434081a5e9d9df82c53e50 12c9006a487c4a17bd0e2125a2d18737 t = -3.142 55d23a09fb434081a5e9d9df82c53e50--12c9006a487c4a17bd0e2125a2d18737 a20395709f1e406ebd3f07854859ee59 12c9006a487c4a17bd0e2125a2d18737--a20395709f1e406ebd3f07854859ee59 6069469624fc49dc8dbda05569ff7826 t = 1.571 a20395709f1e406ebd3f07854859ee59--6069469624fc49dc8dbda05569ff7826 b1e70e7077bf449581c82b87d4266065 t = 1.571 6069469624fc49dc8dbda05569ff7826--b1e70e7077bf449581c82b87d4266065 1a976ed317e34ae296f26a5c1e345ce3 b1e70e7077bf449581c82b87d4266065--1a976ed317e34ae296f26a5c1e345ce3 61f28e202abe42caaf66df234989b47f X 1a976ed317e34ae296f26a5c1e345ce3--61f28e202abe42caaf66df234989b47f bdab0546cd174fa1acf0206e2ed9e857 t = 1.571 61f28e202abe42caaf66df234989b47f--bdab0546cd174fa1acf0206e2ed9e857 d2a50960321f4d2ebf069de0d3bc262f t = 1.571 bdab0546cd174fa1acf0206e2ed9e857--d2a50960321f4d2ebf069de0d3bc262f ccd55af9c9a24507a629077d9f7a2c4e X d2a50960321f4d2ebf069de0d3bc262f--ccd55af9c9a24507a629077d9f7a2c4e ccd55af9c9a24507a629077d9f7a2c4e--0d65f0a8dae347c3843949516ce0aa91 c831ad03a1af47c0ac7f0203471ce50c f416f906d3bd419e8fa436c64a218be3 a861fc6acfc148a58289acaf99dcb7c5--f416f906d3bd419e8fa436c64a218be3 ece4e743d8aa4bdbbf014198248033fa f416f906d3bd419e8fa436c64a218be3--ece4e743d8aa4bdbbf014198248033fa b1f7505c81984811bed938fa4ca778a1 ece4e743d8aa4bdbbf014198248033fa--b1f7505c81984811bed938fa4ca778a1 54726d17efc94787bed059604c7fbd8e X b1f7505c81984811bed938fa4ca778a1--54726d17efc94787bed059604c7fbd8e 90c56d65d56d4f41a2de3af171235cbb 54726d17efc94787bed059604c7fbd8e--90c56d65d56d4f41a2de3af171235cbb a567e44282894e19a98f530b0538877a 90c56d65d56d4f41a2de3af171235cbb--a567e44282894e19a98f530b0538877a d76689bbc11849f38bcb62e8a5d8a2e3 X a567e44282894e19a98f530b0538877a--d76689bbc11849f38bcb62e8a5d8a2e3 cf949ecb965e4b32b6edc01b4b0adcd0 X d76689bbc11849f38bcb62e8a5d8a2e3--cf949ecb965e4b32b6edc01b4b0adcd0 5b62d56a673d4b589a8b0186bb838519 cf949ecb965e4b32b6edc01b4b0adcd0--5b62d56a673d4b589a8b0186bb838519 e36fc335e25b4118ba2106bbf222e9c7 5b62d56a673d4b589a8b0186bb838519--e36fc335e25b4118ba2106bbf222e9c7 125fe1f83e7141669b6e1338e664408c X e36fc335e25b4118ba2106bbf222e9c7--125fe1f83e7141669b6e1338e664408c 125fe1f83e7141669b6e1338e664408c--c831ad03a1af47c0ac7f0203471ce50c

The output circuit displays three groups of system Hamiltonian evolutions which account for global-phases and single-qubit detunings related to the mapping between the \(Z\) and \(N\) operators. Optionally, global phases can be ignored.

In general, the mapping of a \(n\)-qubit Ising Hamiltonian to another will require at most \(n(n-1)\) evolutions. The transformed circuit performs these evolutions for specific times that are computed from the solution of a linear system of equations involving the set of interactions in the target and build Hamiltonians.

In this case, the mapping is exact when using the step-wise DAQC strategy (Strategy.SDAQC) available in Qadence. In banged DAQC (Strategy.BDAQC) the mapping is approximate, but easier to implement on a physical device with always-on interactions such as neutral-atom systems.

Just as before, the transformed Ising circuit can be checked to exactly recover the CPHASE gate:

# CPHASE on (i, j), Identity on third qubit:
cphase_matrix = block_to_tensor(kron(CPHASE(i, j, phi), I(k)))

# CPHASE using the transformed circuit:
cphase_evo_matrix = block_to_tensor(transformed_ising)

# Check that it implements the CPHASE.
# Will fail if global phases are ignored.
cphase_matrix == cphase_evo_matrix : True

The CNOT gate can now finally be built:

from qadence import equivalent_state, run, sample

cnot_daqc = chain(
    H(j),
    transformed_ising,
    H(j)
)

# And finally apply the CNOT on a specific 3-qubit initial state:
init_state = product_state("101")

# Check we get an equivalent wavefunction
wf_cnot = run(n_qubits, block=cnot_target, state=init_state)
wf_daqc = run(n_qubits, block=cnot_daqc, state=init_state)

# Visualize the CNOT bit-flip in samples.
wf_cnot == wf_dacq : True
sample cnot_target = [Counter({'111': 100})]
sample cnot_dacq = [Counter({'111': 100})]

As one can see, a CNOT operation has been succesfully implemented on the desired target qubits by using only the global system as the building block Hamiltonian and single-qubit rotations. Decomposing a single digital gate into an Ising Hamiltonian serves as a proof of principle for the potential of this technique to represent universal quantum computation.

Technical details on the DAQC transformation

  • The mapping between target generator and final circuit is performed by solving a linear system of size \(n(n-1)\) where \(n\) is the number of qubits, so it can be computed efficiently (i.e., with a polynomial cost in the number of qubits).
  • The linear system to be solved is actually not invertible for \(n=4\) qubits. This is very specific edge case requiring a workaround, that is currently not yet implemented.
  • As mentioned, the final circuit has at most \(n(n-1)\) slices, so there is at most a quadratic overhead in circuit depth.

Finally, and most important to its usage:

  • The target Hamiltonian should be sufficiently represented in the building block Hamiltonian.

To illustrate this point, consider the following target and build Hamiltonians:

# Interaction between qubits 0 and 1
gen_target = 1.0 * (Z(0) @ Z(1))

# Fixed interaction between qubits 1 and 2, and customizable between 0 and 1
def gen_build(g_int):
    return g_int * (Z(0) @ Z(1)) + 1.0 * (Z(1) @ Z(2))

And now we perform the DAQC transform by setting g_int=1.0, exactly matching the target Hamiltonian:

transformed_ising = daqc_transform(
    n_qubits=3,
    gen_target=gen_target,
    t_f=1.0,
    gen_build=gen_build(g_int=1.0),
)

# display(transformed_ising)
%3 cluster_1da82d7aaa9245ea8c6d73d248e3f79c cluster_fb58e4b3d98c44d8ba5e2f3a55bc36be eebd7af74d0f4c97bfc494f6460efda2 0 8437f0e9cbb44f51bc8c5bf67c06d83b X eebd7af74d0f4c97bfc494f6460efda2--8437f0e9cbb44f51bc8c5bf67c06d83b d6c400a324cd4fb7964f9d0318cf7512 1 17f334aa28dd41858fdbed8bceec00de HamEvo 8437f0e9cbb44f51bc8c5bf67c06d83b--17f334aa28dd41858fdbed8bceec00de 1b914631721646a8a9813a8bbdcf45d9 X 17f334aa28dd41858fdbed8bceec00de--1b914631721646a8a9813a8bbdcf45d9 358cb72909c84c959055442acf8d3ef7 1b914631721646a8a9813a8bbdcf45d9--358cb72909c84c959055442acf8d3ef7 d1d2271177a94fe690184efe2cc3c173 HamEvo 358cb72909c84c959055442acf8d3ef7--d1d2271177a94fe690184efe2cc3c173 e8708e0c8ae145daae861b51ee622e83 d1d2271177a94fe690184efe2cc3c173--e8708e0c8ae145daae861b51ee622e83 39343544672845d1a97f839782d8c749 e8708e0c8ae145daae861b51ee622e83--39343544672845d1a97f839782d8c749 e386423e60884ba4bac5cd997c9c34bd 6e86de60fd7b48cb8056ba0ab3911953 d6c400a324cd4fb7964f9d0318cf7512--6e86de60fd7b48cb8056ba0ab3911953 0435a89c25f547f49e0de8c14eb86470 2 66bb46d2a8694915831c9a24c5fd40b2 t = -0.500 6e86de60fd7b48cb8056ba0ab3911953--66bb46d2a8694915831c9a24c5fd40b2 94dbaf7d7c0040b8972cfcb15f87e60d 66bb46d2a8694915831c9a24c5fd40b2--94dbaf7d7c0040b8972cfcb15f87e60d 9d41b295d212462d8c2517b7a5024a3f X 94dbaf7d7c0040b8972cfcb15f87e60d--9d41b295d212462d8c2517b7a5024a3f 7d611f240eae4ca382dd8d6c4ddc36b4 t = -0.500 9d41b295d212462d8c2517b7a5024a3f--7d611f240eae4ca382dd8d6c4ddc36b4 357400158b6e4b99900d769ff784fabc X 7d611f240eae4ca382dd8d6c4ddc36b4--357400158b6e4b99900d769ff784fabc 357400158b6e4b99900d769ff784fabc--e386423e60884ba4bac5cd997c9c34bd 3e7de165536d4aa89691054d35059a82 3db2ef9595234995af59d737e9533740 X 0435a89c25f547f49e0de8c14eb86470--3db2ef9595234995af59d737e9533740 b7f1a94c6621476c9ae4d17d5ceeaa70 3db2ef9595234995af59d737e9533740--b7f1a94c6621476c9ae4d17d5ceeaa70 f05a53959a084ccf8742e92abb5c1037 X b7f1a94c6621476c9ae4d17d5ceeaa70--f05a53959a084ccf8742e92abb5c1037 c56ad4270cc04699b7486453b613b60c X f05a53959a084ccf8742e92abb5c1037--c56ad4270cc04699b7486453b613b60c a99d1773ccf04572b8e67e415318f1f9 c56ad4270cc04699b7486453b613b60c--a99d1773ccf04572b8e67e415318f1f9 ff905dfcf9524803a79c3a0642c3e13b X a99d1773ccf04572b8e67e415318f1f9--ff905dfcf9524803a79c3a0642c3e13b ff905dfcf9524803a79c3a0642c3e13b--3e7de165536d4aa89691054d35059a82

Now, if the interaction between qubits 0 and 1 is weakened in the build Hamiltonian:

transformed_ising = daqc_transform(
    n_qubits=3,
    gen_target=gen_target,
    t_f=1.0,
    gen_build=gen_build(g_int=0.001),
)

# display(transformed_ising)
%3 cluster_4e6a7ddab1584328ac815c64cd296c88 cluster_1c35f51ac43d4806acdff54023505b05 c767eb64ee4b4446b84a76d609bbb89a 0 760fcff4aeac444db472984723411629 X c767eb64ee4b4446b84a76d609bbb89a--760fcff4aeac444db472984723411629 29487c8b73a040a69790026cb86d88af 1 cabcd0a53b2d481081ee0baa3758cc2a HamEvo 760fcff4aeac444db472984723411629--cabcd0a53b2d481081ee0baa3758cc2a 887794410cc24ea6a246671bb820b9df X cabcd0a53b2d481081ee0baa3758cc2a--887794410cc24ea6a246671bb820b9df b2b6a2e991664001868b9250342bf3af 887794410cc24ea6a246671bb820b9df--b2b6a2e991664001868b9250342bf3af 3e3ee55c0fe54758a1c74b3740244b26 HamEvo b2b6a2e991664001868b9250342bf3af--3e3ee55c0fe54758a1c74b3740244b26 3b15ddb508394bdab891319acd2d3a0b 3e3ee55c0fe54758a1c74b3740244b26--3b15ddb508394bdab891319acd2d3a0b 644d46fabcf440668f1b78f0dbf73ba7 3b15ddb508394bdab891319acd2d3a0b--644d46fabcf440668f1b78f0dbf73ba7 7080167959414eeb9bf740b9c2ad8e5e 9c127fec29b14d539842471e1eedd24d 29487c8b73a040a69790026cb86d88af--9c127fec29b14d539842471e1eedd24d 06e1e9274f7f4e0f824f3553b1840c57 2 041bbb87457b4c2794a41e96250ab6c0 t = -500.000000000000 9c127fec29b14d539842471e1eedd24d--041bbb87457b4c2794a41e96250ab6c0 d22b28e3645742b38d2bd1814ab7d916 041bbb87457b4c2794a41e96250ab6c0--d22b28e3645742b38d2bd1814ab7d916 e91e69f3cdd848359b73834503f6c33d X d22b28e3645742b38d2bd1814ab7d916--e91e69f3cdd848359b73834503f6c33d 6b85a1e9f3cc4d529afab3eedb8216d6 t = -500.000000000000 e91e69f3cdd848359b73834503f6c33d--6b85a1e9f3cc4d529afab3eedb8216d6 69bfdcfa76074ba48064784d84708162 X 6b85a1e9f3cc4d529afab3eedb8216d6--69bfdcfa76074ba48064784d84708162 69bfdcfa76074ba48064784d84708162--7080167959414eeb9bf740b9c2ad8e5e 0e3e71ad2f8e40c98079d1195a031922 4e1c54023d444c179b55ff1b45d07858 X 06e1e9274f7f4e0f824f3553b1840c57--4e1c54023d444c179b55ff1b45d07858 bb47256a2ed94fab9b405b42b475e4fe 4e1c54023d444c179b55ff1b45d07858--bb47256a2ed94fab9b405b42b475e4fe 729e47f17559498990a0719acc32e1c4 X bb47256a2ed94fab9b405b42b475e4fe--729e47f17559498990a0719acc32e1c4 b401135e99f649809c4a6fc1b6ccea6e X 729e47f17559498990a0719acc32e1c4--b401135e99f649809c4a6fc1b6ccea6e c2bf1c5d9bf14cc7bc00b8886dbcc2d4 b401135e99f649809c4a6fc1b6ccea6e--c2bf1c5d9bf14cc7bc00b8886dbcc2d4 b50d3f42d0f04f32846b8f255efe6865 X c2bf1c5d9bf14cc7bc00b8886dbcc2d4--b50d3f42d0f04f32846b8f255efe6865 b50d3f42d0f04f32846b8f255efe6865--0e3e71ad2f8e40c98079d1195a031922

The times slices using the build Hamiltonian need now to evolve for much longer to represent the same interaction since it is not sufficiently represented in the building block Hamiltonian.

In the limit where that interaction is not present, the transform will not work:

try:
    transformed_ising = daqc_transform(
        n_qubits=3,
        gen_target=gen_target,
        t_f=1.0,
        gen_build=gen_build(g_int = 0.0),
    )
except ValueError as error:
    print("Error:", error)
Error: Incompatible interactions between target and build Hamiltonians.

References