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.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_0e2354391a2e4fbc85cf4708b1f8eaab cluster_bb99db1c9a2c422da41818362e2cee51 cluster_c2cb542b98994cefa0d792e0286f990d cluster_2c0c7effe64f4af8b36783a89c4124a9 cluster_f2711fcaaff1439f837fa8f748221ff0 cluster_fc84362102cf4d6595f3f8cd4c7109e3 cluster_af5b97aa65814c63b6f465cb98303caa efc196a210174bd1b0d65cad6b6131e8 0 264ca403bb9c4244b30650c994d3017f HamEvo efc196a210174bd1b0d65cad6b6131e8--264ca403bb9c4244b30650c994d3017f d85ac453d93947209ef703fae56760b9 1 7e1ce8edfbc04475a2d7ee6c24cc5ef7 HamEvo 264ca403bb9c4244b30650c994d3017f--7e1ce8edfbc04475a2d7ee6c24cc5ef7 dd457da38eba4c19a033f1af2a29667e HamEvo 7e1ce8edfbc04475a2d7ee6c24cc5ef7--dd457da38eba4c19a033f1af2a29667e 5d3f9daa87dd4968a136d127daee7991 X dd457da38eba4c19a033f1af2a29667e--5d3f9daa87dd4968a136d127daee7991 1c162f6459374ae4afb2a30385d9dadc HamEvo 5d3f9daa87dd4968a136d127daee7991--1c162f6459374ae4afb2a30385d9dadc 9bb1debee1bd4979a3809adb140c05e7 HamEvo 1c162f6459374ae4afb2a30385d9dadc--9bb1debee1bd4979a3809adb140c05e7 eecc735866c14ae9811f601316514bac X 9bb1debee1bd4979a3809adb140c05e7--eecc735866c14ae9811f601316514bac c7d6d7c5f30540fcb0c434b5df3c9169 eecc735866c14ae9811f601316514bac--c7d6d7c5f30540fcb0c434b5df3c9169 2da5d9b426ed4e44b86c2bfa07b32727 HamEvo c7d6d7c5f30540fcb0c434b5df3c9169--2da5d9b426ed4e44b86c2bfa07b32727 50a2120c79d2469c8921775cc403fb74 HamEvo 2da5d9b426ed4e44b86c2bfa07b32727--50a2120c79d2469c8921775cc403fb74 6f240afb7a44408c86a526d8977658a8 50a2120c79d2469c8921775cc403fb74--6f240afb7a44408c86a526d8977658a8 10353fa7c9054a7388ee6c5b58026fc2 6f240afb7a44408c86a526d8977658a8--10353fa7c9054a7388ee6c5b58026fc2 d0f543d11d7a4e518cdf2b21a42f9b16 a2900adb6ee540ab9ebf00f7da9e49aa t = -3.14 d85ac453d93947209ef703fae56760b9--a2900adb6ee540ab9ebf00f7da9e49aa c5c90b10ceff40808d6332bda8b4ce78 2 e386d12ddf04499fbfd74c530fa9a38f t = 3.142 a2900adb6ee540ab9ebf00f7da9e49aa--e386d12ddf04499fbfd74c530fa9a38f 2fc3d41186714279b7acaf53944cfadc t = -3.14 e386d12ddf04499fbfd74c530fa9a38f--2fc3d41186714279b7acaf53944cfadc 9f39ecb7fa154e248b1e43853307f060 2fc3d41186714279b7acaf53944cfadc--9f39ecb7fa154e248b1e43853307f060 12261c51760e4ac1bf893c0580aac6ba t = 1.571 9f39ecb7fa154e248b1e43853307f060--12261c51760e4ac1bf893c0580aac6ba ce43df6a70aa4c21b7b1bad6285ca202 t = 1.571 12261c51760e4ac1bf893c0580aac6ba--ce43df6a70aa4c21b7b1bad6285ca202 b26ac996a4014116854a912ef72feb5f ce43df6a70aa4c21b7b1bad6285ca202--b26ac996a4014116854a912ef72feb5f 30165611c74c47e996393a9a097d081e X b26ac996a4014116854a912ef72feb5f--30165611c74c47e996393a9a097d081e 511dd5fb371c439dbfd8944c1dd734fd t = 1.571 30165611c74c47e996393a9a097d081e--511dd5fb371c439dbfd8944c1dd734fd b32cae33346840e584b61e3f13aad8f7 t = 1.571 511dd5fb371c439dbfd8944c1dd734fd--b32cae33346840e584b61e3f13aad8f7 c49b41a436d849edb6084c9fb0eb6d72 X b32cae33346840e584b61e3f13aad8f7--c49b41a436d849edb6084c9fb0eb6d72 c49b41a436d849edb6084c9fb0eb6d72--d0f543d11d7a4e518cdf2b21a42f9b16 7ca631eb7c26497db21a476e3ea3c4d2 0521392a7f3b40daabc7d70f2949badb c5c90b10ceff40808d6332bda8b4ce78--0521392a7f3b40daabc7d70f2949badb a278c67216784f2687fd67b08e5b610f 0521392a7f3b40daabc7d70f2949badb--a278c67216784f2687fd67b08e5b610f bd96cecaf82f4089b296fb661bf2ce4b a278c67216784f2687fd67b08e5b610f--bd96cecaf82f4089b296fb661bf2ce4b bf4ab84e28324fc7a2e325e8ef1c410f X bd96cecaf82f4089b296fb661bf2ce4b--bf4ab84e28324fc7a2e325e8ef1c410f 6c0ed96d901d44a5b1450908b76b0465 bf4ab84e28324fc7a2e325e8ef1c410f--6c0ed96d901d44a5b1450908b76b0465 eea463ebe7854a198290ac5ef85d2fd6 6c0ed96d901d44a5b1450908b76b0465--eea463ebe7854a198290ac5ef85d2fd6 57191420e4d143a58a07fc2d2c88e579 X eea463ebe7854a198290ac5ef85d2fd6--57191420e4d143a58a07fc2d2c88e579 f6e9f97866a84c29ac151d564ff74b77 X 57191420e4d143a58a07fc2d2c88e579--f6e9f97866a84c29ac151d564ff74b77 fde331bdb7ef45eaa9dbb7c94b65575c f6e9f97866a84c29ac151d564ff74b77--fde331bdb7ef45eaa9dbb7c94b65575c 2f94bf948b8149acafc35a54f340b829 fde331bdb7ef45eaa9dbb7c94b65575c--2f94bf948b8149acafc35a54f340b829 c671f39a00574139b2c6fa2931d5f6df X 2f94bf948b8149acafc35a54f340b829--c671f39a00574139b2c6fa2931d5f6df c671f39a00574139b2c6fa2931d5f6df--7ca631eb7c26497db21a476e3ea3c4d2

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_20cb71605bdb49cb81bdc48a1a9a9404 cluster_c990c7227142438b85bce264b75dd615 d27c7fd104ec4cbca730be825dcea394 0 95e84590782f4534ae32d103c52d7d03 X d27c7fd104ec4cbca730be825dcea394--95e84590782f4534ae32d103c52d7d03 5ff0afa0f6684b25a92afd41a843a22d 1 67e40fb83435418a878116fb876e2228 HamEvo 95e84590782f4534ae32d103c52d7d03--67e40fb83435418a878116fb876e2228 8ad01241332546dba0d546b5e35fe994 X 67e40fb83435418a878116fb876e2228--8ad01241332546dba0d546b5e35fe994 8b2f9703ee7a4c17b1882cf2d5da5ce4 8ad01241332546dba0d546b5e35fe994--8b2f9703ee7a4c17b1882cf2d5da5ce4 efee0bf020714f7d90e1ee3f891b7933 HamEvo 8b2f9703ee7a4c17b1882cf2d5da5ce4--efee0bf020714f7d90e1ee3f891b7933 ac39cb6c05cf4f7ba0e916dcdf7772e8 efee0bf020714f7d90e1ee3f891b7933--ac39cb6c05cf4f7ba0e916dcdf7772e8 6b2723cc0f7e4b62ac98da9b447bf43d ac39cb6c05cf4f7ba0e916dcdf7772e8--6b2723cc0f7e4b62ac98da9b447bf43d 27b598f135a74dd5894e937ac190b474 c990ad6dc78a41d686fb8a9eff607c6c 5ff0afa0f6684b25a92afd41a843a22d--c990ad6dc78a41d686fb8a9eff607c6c 177152fe4e6a464caf05ae67133e059d 2 20a8acdd3e72485f8721290ead7f560f t = -0.50 c990ad6dc78a41d686fb8a9eff607c6c--20a8acdd3e72485f8721290ead7f560f fdb972aaa3d149cfa1625927d0eb5fa7 20a8acdd3e72485f8721290ead7f560f--fdb972aaa3d149cfa1625927d0eb5fa7 231b3c091ec74131ad1f53febf1ec664 X fdb972aaa3d149cfa1625927d0eb5fa7--231b3c091ec74131ad1f53febf1ec664 b6fb252a5f974584a4b8ba3284564e24 t = -0.50 231b3c091ec74131ad1f53febf1ec664--b6fb252a5f974584a4b8ba3284564e24 f249849905734491b608ef5b41c11d00 X b6fb252a5f974584a4b8ba3284564e24--f249849905734491b608ef5b41c11d00 f249849905734491b608ef5b41c11d00--27b598f135a74dd5894e937ac190b474 ebab77fbfde54d46941f3030ab59afed 44130581b34f4d66850d5a982a8971e3 X 177152fe4e6a464caf05ae67133e059d--44130581b34f4d66850d5a982a8971e3 d1d775d407994ff6a41045e6f6ef78b6 44130581b34f4d66850d5a982a8971e3--d1d775d407994ff6a41045e6f6ef78b6 3dce86d24b4c44afb216aa8068adbf0b X d1d775d407994ff6a41045e6f6ef78b6--3dce86d24b4c44afb216aa8068adbf0b 063ce7db2ca14446aa26f1b97c95a374 X 3dce86d24b4c44afb216aa8068adbf0b--063ce7db2ca14446aa26f1b97c95a374 12bbfec9742547318867fa9accec9304 063ce7db2ca14446aa26f1b97c95a374--12bbfec9742547318867fa9accec9304 118568f8bab14b48bab498d4a42e77e7 X 12bbfec9742547318867fa9accec9304--118568f8bab14b48bab498d4a42e77e7 118568f8bab14b48bab498d4a42e77e7--ebab77fbfde54d46941f3030ab59afed

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_ebb595a48422409eb67ef50df3940d5e cluster_c60ab69764404d1ebd435cd2efc0d69d d56d00b913ac4cdda048b5c9f566c72f 0 7d194d76cf2940ad96af624ddd14bc30 X d56d00b913ac4cdda048b5c9f566c72f--7d194d76cf2940ad96af624ddd14bc30 a269d75d9ef843e4b09612d2eb26c7bd 1 8888cab19e4345be82e87ba42baf804c HamEvo 7d194d76cf2940ad96af624ddd14bc30--8888cab19e4345be82e87ba42baf804c e3e370f568154d988f8769dbdf1be23f X 8888cab19e4345be82e87ba42baf804c--e3e370f568154d988f8769dbdf1be23f 49a4e9d16a3e4a87adb8833097c23329 e3e370f568154d988f8769dbdf1be23f--49a4e9d16a3e4a87adb8833097c23329 9e6b9f13f63e45e68e69202f90a10e18 HamEvo 49a4e9d16a3e4a87adb8833097c23329--9e6b9f13f63e45e68e69202f90a10e18 12b39bd5ccf74982b465e9ebf8f108f4 9e6b9f13f63e45e68e69202f90a10e18--12b39bd5ccf74982b465e9ebf8f108f4 a2a703aebe004c32a94905e71bae64e8 12b39bd5ccf74982b465e9ebf8f108f4--a2a703aebe004c32a94905e71bae64e8 a45f85a2eeff4879b0d440c05a2c138a e3499665e6f24ab59b228ea41edb968d a269d75d9ef843e4b09612d2eb26c7bd--e3499665e6f24ab59b228ea41edb968d 5c0b386fa0f44ba5a677ec3de17addce 2 a5ece62ff5c84eaba87733a1c24cd88a t = -500. e3499665e6f24ab59b228ea41edb968d--a5ece62ff5c84eaba87733a1c24cd88a 927540619b7f4eb0a3a11c42765a3816 a5ece62ff5c84eaba87733a1c24cd88a--927540619b7f4eb0a3a11c42765a3816 8415655a5811461493fb9e18f8da38a8 X 927540619b7f4eb0a3a11c42765a3816--8415655a5811461493fb9e18f8da38a8 03268fd756804cee942e2f10df5993f6 t = -500. 8415655a5811461493fb9e18f8da38a8--03268fd756804cee942e2f10df5993f6 cbdca3399b8441d09c928e741a1a2ae0 X 03268fd756804cee942e2f10df5993f6--cbdca3399b8441d09c928e741a1a2ae0 cbdca3399b8441d09c928e741a1a2ae0--a45f85a2eeff4879b0d440c05a2c138a 551428429c294fd1ae5fc1c70c872fb9 f29a4072fab94f08b237ebc6bcf68f0e X 5c0b386fa0f44ba5a677ec3de17addce--f29a4072fab94f08b237ebc6bcf68f0e bf71155b11494f478edb162f6549e182 f29a4072fab94f08b237ebc6bcf68f0e--bf71155b11494f478edb162f6549e182 3ee06e79f6be46c1885c3f8fe1a666a3 X bf71155b11494f478edb162f6549e182--3ee06e79f6be46c1885c3f8fe1a666a3 822485aa17064c3186ec625cdfd7bed7 X 3ee06e79f6be46c1885c3f8fe1a666a3--822485aa17064c3186ec625cdfd7bed7 56ad6eea49244774b28da863a8bb5db8 822485aa17064c3186ec625cdfd7bed7--56ad6eea49244774b28da863a8bb5db8 93b428043b3246859ce68afaeb23fdc7 X 56ad6eea49244774b28da863a8bb5db8--93b428043b3246859ce68afaeb23fdc7 93b428043b3246859ce68afaeb23fdc7--551428429c294fd1ae5fc1c70c872fb9

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