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 = [OrderedCounter({'11': 100})]
sample from decomposed CNOT gate and 100 shots = [OrderedCounter({'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 = [OrderedCounter({'11': 100})]
sample cnot_evo = [OrderedCounter({'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.000] 
   └── KronBlock(0,1)
       ├── N(1)
       └── N(0)
├── [mul: 1.000] 
   └── KronBlock(0,2)
       ├── N(2)
       └── N(0)
└── [mul: 1.000] 
    └── 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_a3af8085f9764a9a9d571c21974369c1 cluster_7267aa45bc604209a5a45d8517bf2f7d cluster_d61aa52174a345c4bfe049be99bdbf7a cluster_3a31ded1fa4c4a7eb403dc899cc5f721 cluster_d7cbcf38770545fda454776a7ce33ada cluster_dca2649d0a1049c28028c8461131fdfd cluster_dffcfcd6ef524d45bcc170bc41b6117a bab84c63d69647f294d1fb2f55c43ca0 0 2261490fddc746d9a95c7b9362411171 HamEvo bab84c63d69647f294d1fb2f55c43ca0--2261490fddc746d9a95c7b9362411171 f90ce7da8e13416a97c44c099bcb89ad 1 b0aadea744a647169bcdc662744ffcb2 HamEvo 2261490fddc746d9a95c7b9362411171--b0aadea744a647169bcdc662744ffcb2 cd026f7075d940c48ac6bc4ff0b77a03 HamEvo b0aadea744a647169bcdc662744ffcb2--cd026f7075d940c48ac6bc4ff0b77a03 5cc417619d4a4c4c9dd83da744c8de27 X cd026f7075d940c48ac6bc4ff0b77a03--5cc417619d4a4c4c9dd83da744c8de27 1064ea9aa72c40e7ad859df0bcd428d1 HamEvo 5cc417619d4a4c4c9dd83da744c8de27--1064ea9aa72c40e7ad859df0bcd428d1 cfa8d5967b86412cb2d86bddc78f2682 HamEvo 1064ea9aa72c40e7ad859df0bcd428d1--cfa8d5967b86412cb2d86bddc78f2682 9442417a2cab4a3ab9f88f29b1717e01 X cfa8d5967b86412cb2d86bddc78f2682--9442417a2cab4a3ab9f88f29b1717e01 abe52d9d96b04dea8307601041c9351c 9442417a2cab4a3ab9f88f29b1717e01--abe52d9d96b04dea8307601041c9351c 57beab9496c54a0e817697cbb523d8a5 HamEvo abe52d9d96b04dea8307601041c9351c--57beab9496c54a0e817697cbb523d8a5 7e0ddc91ec7f4235a3a29d7c4976a111 HamEvo 57beab9496c54a0e817697cbb523d8a5--7e0ddc91ec7f4235a3a29d7c4976a111 8b7b510c0c5d42129b268df17debddb9 7e0ddc91ec7f4235a3a29d7c4976a111--8b7b510c0c5d42129b268df17debddb9 316df89f37df4715943dbb7ba0d3a6e5 8b7b510c0c5d42129b268df17debddb9--316df89f37df4715943dbb7ba0d3a6e5 4a617905b652433a85e965f7378db0d2 8b6c4c59b4d1412080dc7a6287dd6a81 t = -3.14 f90ce7da8e13416a97c44c099bcb89ad--8b6c4c59b4d1412080dc7a6287dd6a81 657a57a7a6fa43788df5f2a4d1b08f97 2 44fda9e1272443dea3910b14b2871174 t = 3.142 8b6c4c59b4d1412080dc7a6287dd6a81--44fda9e1272443dea3910b14b2871174 364d547db49442c3bd82877a9248f085 t = -3.14 44fda9e1272443dea3910b14b2871174--364d547db49442c3bd82877a9248f085 c6957539d8254aadab2f621fe1649417 364d547db49442c3bd82877a9248f085--c6957539d8254aadab2f621fe1649417 d9643115e51b4e7995d42e543ec0acf3 t = 1.571 c6957539d8254aadab2f621fe1649417--d9643115e51b4e7995d42e543ec0acf3 cd4347f22bbf4a15a84882b04fbdda23 t = 1.571 d9643115e51b4e7995d42e543ec0acf3--cd4347f22bbf4a15a84882b04fbdda23 2136b876a3c7404abfb3500c25b76c2c cd4347f22bbf4a15a84882b04fbdda23--2136b876a3c7404abfb3500c25b76c2c 36d2ef2c61fd4ae98112b9d254eab0ec X 2136b876a3c7404abfb3500c25b76c2c--36d2ef2c61fd4ae98112b9d254eab0ec dc21dbbb897d437094deb2652db623fe t = 1.571 36d2ef2c61fd4ae98112b9d254eab0ec--dc21dbbb897d437094deb2652db623fe 692ad6e08cba4cc0bb37c0682f98391f t = 1.571 dc21dbbb897d437094deb2652db623fe--692ad6e08cba4cc0bb37c0682f98391f e4a8da85498043e48ef8401fd253a94e X 692ad6e08cba4cc0bb37c0682f98391f--e4a8da85498043e48ef8401fd253a94e e4a8da85498043e48ef8401fd253a94e--4a617905b652433a85e965f7378db0d2 cb7b7b1d2dce4acfa56e964d97614c9a b1579b5c8e05421b80e65a9dece71a90 657a57a7a6fa43788df5f2a4d1b08f97--b1579b5c8e05421b80e65a9dece71a90 399e1e13c7674db0b8e727100b549fa6 b1579b5c8e05421b80e65a9dece71a90--399e1e13c7674db0b8e727100b549fa6 34c305f45970442382880fdf8e9e2102 399e1e13c7674db0b8e727100b549fa6--34c305f45970442382880fdf8e9e2102 624acb5bb2a94780961e032e56a46b07 X 34c305f45970442382880fdf8e9e2102--624acb5bb2a94780961e032e56a46b07 2df6539611fd479181ea4981426cc8eb 624acb5bb2a94780961e032e56a46b07--2df6539611fd479181ea4981426cc8eb bb03dd2a7ca24d0bb67a97899bacfabe 2df6539611fd479181ea4981426cc8eb--bb03dd2a7ca24d0bb67a97899bacfabe 508122fa7aad41cba0482508c99e072f X bb03dd2a7ca24d0bb67a97899bacfabe--508122fa7aad41cba0482508c99e072f 6b81f7b9511c4c5ba79af38ec3fdc51c X 508122fa7aad41cba0482508c99e072f--6b81f7b9511c4c5ba79af38ec3fdc51c 6b8c803571c34780b7f3d3bddf8f326c 6b81f7b9511c4c5ba79af38ec3fdc51c--6b8c803571c34780b7f3d3bddf8f326c d42c15a7cbfd4137be634a26614e6975 6b8c803571c34780b7f3d3bddf8f326c--d42c15a7cbfd4137be634a26614e6975 1dec9b7801654eafb9d47d035cea569d X d42c15a7cbfd4137be634a26614e6975--1dec9b7801654eafb9d47d035cea569d 1dec9b7801654eafb9d47d035cea569d--cb7b7b1d2dce4acfa56e964d97614c9a

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 = [OrderedCounter({'111': 100})]
sample cnot_dacq = [OrderedCounter({'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_7b178e162bd04973b1cdd85fd65be1dc cluster_980b62b824c3459a943645943c520068 3b4e2fbb9d0547238d5ef81725a568cf 0 62794c9d3de74c948f3832771d1437a9 X 3b4e2fbb9d0547238d5ef81725a568cf--62794c9d3de74c948f3832771d1437a9 6a0ec9377ce74dba871b192093862307 1 e14e3a6a7a81473191d575cb238ec1c0 HamEvo 62794c9d3de74c948f3832771d1437a9--e14e3a6a7a81473191d575cb238ec1c0 d9ff99fb622d4c14ae2fb0cfa53d88ea X e14e3a6a7a81473191d575cb238ec1c0--d9ff99fb622d4c14ae2fb0cfa53d88ea 3a1762490e7247ea8bb730fa1f4aae62 d9ff99fb622d4c14ae2fb0cfa53d88ea--3a1762490e7247ea8bb730fa1f4aae62 1eb7c95940bc4d48b0782e2b5e37cc92 HamEvo 3a1762490e7247ea8bb730fa1f4aae62--1eb7c95940bc4d48b0782e2b5e37cc92 27f747b6e65c4c2fa46a763fd852d682 1eb7c95940bc4d48b0782e2b5e37cc92--27f747b6e65c4c2fa46a763fd852d682 5ae7e1bdd4784facae005a313c8d68ea 27f747b6e65c4c2fa46a763fd852d682--5ae7e1bdd4784facae005a313c8d68ea f481bebe23a44aff97ed844d92aef72f 557f0da88f434a2182f5f8d98f9f380f 6a0ec9377ce74dba871b192093862307--557f0da88f434a2182f5f8d98f9f380f 48cea49ff2bd401e93367dc554059fa5 2 75dda38c31d8472285d74603fc26e23c t = -0.50 557f0da88f434a2182f5f8d98f9f380f--75dda38c31d8472285d74603fc26e23c b4a043dcfde44589a9a89bdd3b1d7b86 75dda38c31d8472285d74603fc26e23c--b4a043dcfde44589a9a89bdd3b1d7b86 d16aa39d89a047f08199faa6579da807 X b4a043dcfde44589a9a89bdd3b1d7b86--d16aa39d89a047f08199faa6579da807 c6b73a8f101840fc96bb4c4dc953b29c t = -0.50 d16aa39d89a047f08199faa6579da807--c6b73a8f101840fc96bb4c4dc953b29c 761f535cc9e64765b47769fe0ea43551 X c6b73a8f101840fc96bb4c4dc953b29c--761f535cc9e64765b47769fe0ea43551 761f535cc9e64765b47769fe0ea43551--f481bebe23a44aff97ed844d92aef72f 1dd0e397e3a6408cb5521f3e475317b0 2864ff598f63482b9da32744659753f9 X 48cea49ff2bd401e93367dc554059fa5--2864ff598f63482b9da32744659753f9 d0a2aba949d846f88d32353fa3e4418d 2864ff598f63482b9da32744659753f9--d0a2aba949d846f88d32353fa3e4418d 9caf45f95d0f40a4afece8580aa7695b X d0a2aba949d846f88d32353fa3e4418d--9caf45f95d0f40a4afece8580aa7695b 63724a4a929e42de940af218bd1b3542 X 9caf45f95d0f40a4afece8580aa7695b--63724a4a929e42de940af218bd1b3542 6abb368c234845cc8f6a88d0a6121cfd 63724a4a929e42de940af218bd1b3542--6abb368c234845cc8f6a88d0a6121cfd 83c82fb976ec4d6f90244ab73b6ff41f X 6abb368c234845cc8f6a88d0a6121cfd--83c82fb976ec4d6f90244ab73b6ff41f 83c82fb976ec4d6f90244ab73b6ff41f--1dd0e397e3a6408cb5521f3e475317b0

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_1201076366a04c52834007eafc49600c cluster_6a4b454f087b41f4a0843b8efe4d843f a430556fe7f84a18938e2397a77170bc 0 b4b9855cbd004b868d31c781801e0f2d X a430556fe7f84a18938e2397a77170bc--b4b9855cbd004b868d31c781801e0f2d 06a120c9cd76400e952ea597834169c1 1 23398e620dda41919152c8729aaeb158 HamEvo b4b9855cbd004b868d31c781801e0f2d--23398e620dda41919152c8729aaeb158 ac854dc6133649f4a8859ae9a5cb8d34 X 23398e620dda41919152c8729aaeb158--ac854dc6133649f4a8859ae9a5cb8d34 86bd02825ca84799bf59b755d0dc5dc0 ac854dc6133649f4a8859ae9a5cb8d34--86bd02825ca84799bf59b755d0dc5dc0 0c6d160e4ef348458ad079865e3d5edb HamEvo 86bd02825ca84799bf59b755d0dc5dc0--0c6d160e4ef348458ad079865e3d5edb 7b56aa9ae1f04cb0aae18dab82f18fb2 0c6d160e4ef348458ad079865e3d5edb--7b56aa9ae1f04cb0aae18dab82f18fb2 8995c95a453c4acbae9b1f3a053371a4 7b56aa9ae1f04cb0aae18dab82f18fb2--8995c95a453c4acbae9b1f3a053371a4 cbe3fe13829a4ab48bebc071586a208c dbe8395108c9402d8009e383d05d4ef9 06a120c9cd76400e952ea597834169c1--dbe8395108c9402d8009e383d05d4ef9 efd625ea153b48e9b84e99487b47cfe9 2 d9200d6788d14e7faf6fb157848aa0b5 t = -500. dbe8395108c9402d8009e383d05d4ef9--d9200d6788d14e7faf6fb157848aa0b5 f1ff5ca01128446db196148057045090 d9200d6788d14e7faf6fb157848aa0b5--f1ff5ca01128446db196148057045090 afde874167424f98a335733f8180268f X f1ff5ca01128446db196148057045090--afde874167424f98a335733f8180268f e879f91182164fc48aa28570605b9468 t = -500. afde874167424f98a335733f8180268f--e879f91182164fc48aa28570605b9468 81076a377a0a499e9aa91e9b69fd5ef5 X e879f91182164fc48aa28570605b9468--81076a377a0a499e9aa91e9b69fd5ef5 81076a377a0a499e9aa91e9b69fd5ef5--cbe3fe13829a4ab48bebc071586a208c a66db4ce41604ed98feb3d84477c456a aa7816a64f4d4490bde9c34706d06862 X efd625ea153b48e9b84e99487b47cfe9--aa7816a64f4d4490bde9c34706d06862 dc3e88ca907c46649501d641dab69d6c aa7816a64f4d4490bde9c34706d06862--dc3e88ca907c46649501d641dab69d6c de9cb31193b141f88886e8a4437520f6 X dc3e88ca907c46649501d641dab69d6c--de9cb31193b141f88886e8a4437520f6 1976b3032405435ea8baf5cdcae93753 X de9cb31193b141f88886e8a4437520f6--1976b3032405435ea8baf5cdcae93753 dc8bcdb33618428a93b3b448a1c4c516 1976b3032405435ea8baf5cdcae93753--dc8bcdb33618428a93b3b448a1c4c516 0685c61f4d024f35bd3aa9a4d9409041 X dc8bcdb33618428a93b3b448a1c4c516--0685c61f4d024f35bd3aa9a4d9409041 0685c61f4d024f35bd3aa9a4d9409041--a66db4ce41604ed98feb3d84477c456a

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