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_b21bdf1a0cf34fe293dacbffb80648cd cluster_271e503fe1164e579f3639035307c654 cluster_4e727f23ee174763a3770f6bc40a6750 cluster_01a81a1e49ec4331b6a4fb3da6a487a9 cluster_9cfb167e928a4a4499da03a9a0178989 cluster_581b660c7f804e72b3f69b1ae01c603c cluster_835d9a21860147a392770125f0e461c2 6e201bf834f24af8839c31a96628bcc8 0 de2c98dabb234195b93af1782736c2d7 HamEvo 6e201bf834f24af8839c31a96628bcc8--de2c98dabb234195b93af1782736c2d7 1c5ee9f5f47d406ca4cb479d7e6d666a 1 be42de66fdf04ad28b4ae5c4c2b69278 HamEvo de2c98dabb234195b93af1782736c2d7--be42de66fdf04ad28b4ae5c4c2b69278 95573447f9664fd5a1358ee27d9e12f5 HamEvo be42de66fdf04ad28b4ae5c4c2b69278--95573447f9664fd5a1358ee27d9e12f5 2b4238d98ca14772b181992ef2946c8e X 95573447f9664fd5a1358ee27d9e12f5--2b4238d98ca14772b181992ef2946c8e 6c4964b6e19b413bb2bccfa5bb95935f HamEvo 2b4238d98ca14772b181992ef2946c8e--6c4964b6e19b413bb2bccfa5bb95935f 7dbaaefcabb240a8b9e002702deb1c2a HamEvo 6c4964b6e19b413bb2bccfa5bb95935f--7dbaaefcabb240a8b9e002702deb1c2a e3ce00f6514e4836a648f1921dcfcfa5 X 7dbaaefcabb240a8b9e002702deb1c2a--e3ce00f6514e4836a648f1921dcfcfa5 27721574d2eb436c994e8189bfc3b9d7 e3ce00f6514e4836a648f1921dcfcfa5--27721574d2eb436c994e8189bfc3b9d7 da950133593f4a4bbfa9315ed0ad7d51 HamEvo 27721574d2eb436c994e8189bfc3b9d7--da950133593f4a4bbfa9315ed0ad7d51 170b986275e94adc987bd6c77392766a HamEvo da950133593f4a4bbfa9315ed0ad7d51--170b986275e94adc987bd6c77392766a 46009db478af4de1a4389fdc60b078db 170b986275e94adc987bd6c77392766a--46009db478af4de1a4389fdc60b078db 38fc8b4d565c4fd79e2bc631f94fe2ee 46009db478af4de1a4389fdc60b078db--38fc8b4d565c4fd79e2bc631f94fe2ee f2d710adde954e0087e4393b15b6e796 a88d004ecaa0402fb94077f42c0ca562 t = -3.14 1c5ee9f5f47d406ca4cb479d7e6d666a--a88d004ecaa0402fb94077f42c0ca562 18907d61a9d84d88928deb3d13d888a7 2 0320718be57b471f8be50160025633ae t = 3.142 a88d004ecaa0402fb94077f42c0ca562--0320718be57b471f8be50160025633ae c21e816ec6cc41f1be67b26ce383e021 t = -3.14 0320718be57b471f8be50160025633ae--c21e816ec6cc41f1be67b26ce383e021 c849e6ec000e48f0abc61867e631bf28 c21e816ec6cc41f1be67b26ce383e021--c849e6ec000e48f0abc61867e631bf28 ab1bd7d972604f85b931d86d781d1c9b t = 1.571 c849e6ec000e48f0abc61867e631bf28--ab1bd7d972604f85b931d86d781d1c9b 50c67f65fab34b798c9ee22b7453cba1 t = 1.571 ab1bd7d972604f85b931d86d781d1c9b--50c67f65fab34b798c9ee22b7453cba1 148e489853e44c1c8b79906720e5e93f 50c67f65fab34b798c9ee22b7453cba1--148e489853e44c1c8b79906720e5e93f d7033f3659084f69b0dcb1690dcd79f4 X 148e489853e44c1c8b79906720e5e93f--d7033f3659084f69b0dcb1690dcd79f4 13835c8f826d46f6922a2372ca7dff1f t = 1.571 d7033f3659084f69b0dcb1690dcd79f4--13835c8f826d46f6922a2372ca7dff1f 266110e8a0bc4f0895b5e1cd8fb0c2bc t = 1.571 13835c8f826d46f6922a2372ca7dff1f--266110e8a0bc4f0895b5e1cd8fb0c2bc 825dbdc58d974ef3aaa5ed163de95fb2 X 266110e8a0bc4f0895b5e1cd8fb0c2bc--825dbdc58d974ef3aaa5ed163de95fb2 825dbdc58d974ef3aaa5ed163de95fb2--f2d710adde954e0087e4393b15b6e796 b2f74b67e8714d98b4a2913b85731113 236b9dd74f49486bb89588a6088645ba 18907d61a9d84d88928deb3d13d888a7--236b9dd74f49486bb89588a6088645ba 80a58aa52623442a8294bcd81460e180 236b9dd74f49486bb89588a6088645ba--80a58aa52623442a8294bcd81460e180 9bb75269c1ac48f18a26cd483d92a57b 80a58aa52623442a8294bcd81460e180--9bb75269c1ac48f18a26cd483d92a57b 004a32af333e4ee692cce6031f9ddabe X 9bb75269c1ac48f18a26cd483d92a57b--004a32af333e4ee692cce6031f9ddabe 1db801b39e96414ea05ca2b2e2b30eac 004a32af333e4ee692cce6031f9ddabe--1db801b39e96414ea05ca2b2e2b30eac 6d953a4c74654bcdad1716598baf5963 1db801b39e96414ea05ca2b2e2b30eac--6d953a4c74654bcdad1716598baf5963 d6791704654e4047a59240b780a50966 X 6d953a4c74654bcdad1716598baf5963--d6791704654e4047a59240b780a50966 e45c9f324ea843d18494c3b12ff76ce1 X d6791704654e4047a59240b780a50966--e45c9f324ea843d18494c3b12ff76ce1 d1660d3bedbd413eb73da6b53b373e15 e45c9f324ea843d18494c3b12ff76ce1--d1660d3bedbd413eb73da6b53b373e15 c4709358097b49919ab84e8cfa2cbd9c d1660d3bedbd413eb73da6b53b373e15--c4709358097b49919ab84e8cfa2cbd9c 8720b7582e3f43af8e96d112d5d191ff X c4709358097b49919ab84e8cfa2cbd9c--8720b7582e3f43af8e96d112d5d191ff 8720b7582e3f43af8e96d112d5d191ff--b2f74b67e8714d98b4a2913b85731113

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_ebba297b4ba44889a5c206c6e57ce2ed cluster_83f5ca378589460ba8e40c04d1bacf58 da0cf14940744215a1e959751cbb71b8 0 94e4dffc58514886bc4b2212356c510b X da0cf14940744215a1e959751cbb71b8--94e4dffc58514886bc4b2212356c510b 232ac84ffa7c434bb3ed0228f822318e 1 5879c52e95a64103b275306e22ffbcf4 HamEvo 94e4dffc58514886bc4b2212356c510b--5879c52e95a64103b275306e22ffbcf4 2bef753b9ca2413fbb506c9f0a97e37b X 5879c52e95a64103b275306e22ffbcf4--2bef753b9ca2413fbb506c9f0a97e37b 63261984c31c4a7a96493d4f8ebb2dcf 2bef753b9ca2413fbb506c9f0a97e37b--63261984c31c4a7a96493d4f8ebb2dcf 58b84efbcd964288bc84499f06dd8ac9 HamEvo 63261984c31c4a7a96493d4f8ebb2dcf--58b84efbcd964288bc84499f06dd8ac9 c50abd8c10cf4e7099cbf8569ba80b41 58b84efbcd964288bc84499f06dd8ac9--c50abd8c10cf4e7099cbf8569ba80b41 20b4ddd0dbf44695972bd286ef954be3 c50abd8c10cf4e7099cbf8569ba80b41--20b4ddd0dbf44695972bd286ef954be3 28676daf717f44f3a79fc86b691c13f2 2cc3687b58ac4468b5d619913d48a72e 232ac84ffa7c434bb3ed0228f822318e--2cc3687b58ac4468b5d619913d48a72e 9ef4a086e9e94269871cb5018db00c0c 2 f768bc7f60fc4954b4d241d69bb0ac6b t = -0.50 2cc3687b58ac4468b5d619913d48a72e--f768bc7f60fc4954b4d241d69bb0ac6b 594e3859496141e1ad937521c1d79c52 f768bc7f60fc4954b4d241d69bb0ac6b--594e3859496141e1ad937521c1d79c52 3d3608916ffa44ebaa5efc2a6d8d81a0 X 594e3859496141e1ad937521c1d79c52--3d3608916ffa44ebaa5efc2a6d8d81a0 2dd025797af54b8b8d7d18a23367fdd3 t = -0.50 3d3608916ffa44ebaa5efc2a6d8d81a0--2dd025797af54b8b8d7d18a23367fdd3 6bf47f509b054eb2b3502977d3ab00da X 2dd025797af54b8b8d7d18a23367fdd3--6bf47f509b054eb2b3502977d3ab00da 6bf47f509b054eb2b3502977d3ab00da--28676daf717f44f3a79fc86b691c13f2 03676ae9ccf74c25b86331df9946edcf cc846ecce3c74433b2f06f11fcac9dd8 X 9ef4a086e9e94269871cb5018db00c0c--cc846ecce3c74433b2f06f11fcac9dd8 0ffafce90c014fc6b59b1e9341a72aa7 cc846ecce3c74433b2f06f11fcac9dd8--0ffafce90c014fc6b59b1e9341a72aa7 cbcce3a5f1f44a02925e18c4aa135475 X 0ffafce90c014fc6b59b1e9341a72aa7--cbcce3a5f1f44a02925e18c4aa135475 07e2b4771037438997b6767a6405641e X cbcce3a5f1f44a02925e18c4aa135475--07e2b4771037438997b6767a6405641e 49b7a7b7092a4bf3a85a2456affe6fce 07e2b4771037438997b6767a6405641e--49b7a7b7092a4bf3a85a2456affe6fce ff76c3b3d30a455b9d6350743e030343 X 49b7a7b7092a4bf3a85a2456affe6fce--ff76c3b3d30a455b9d6350743e030343 ff76c3b3d30a455b9d6350743e030343--03676ae9ccf74c25b86331df9946edcf

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_3e2368c361284abda7bf9046258b6086 cluster_54057209f8424f949f440b7eefc3d211 ba472206443a44a2a65ff3bdd649df12 0 a8142e6a65f2416aa6315c65449863ca X ba472206443a44a2a65ff3bdd649df12--a8142e6a65f2416aa6315c65449863ca 7f8fd8160ff64ff183af7da14f1428b3 1 27376d0fb0f24be2a5fd4a72a89bd9a2 HamEvo a8142e6a65f2416aa6315c65449863ca--27376d0fb0f24be2a5fd4a72a89bd9a2 fccf8f4cd48d47eda9e23774429617ab X 27376d0fb0f24be2a5fd4a72a89bd9a2--fccf8f4cd48d47eda9e23774429617ab e99a097f35e74eab9eb6cab92dde9673 fccf8f4cd48d47eda9e23774429617ab--e99a097f35e74eab9eb6cab92dde9673 5155a5d003d943ea8583d8f983d79104 HamEvo e99a097f35e74eab9eb6cab92dde9673--5155a5d003d943ea8583d8f983d79104 8dd70d4843954d84bf31145407d3afe6 5155a5d003d943ea8583d8f983d79104--8dd70d4843954d84bf31145407d3afe6 6534358cef3047508ef2c4a2c77f246e 8dd70d4843954d84bf31145407d3afe6--6534358cef3047508ef2c4a2c77f246e f386fe61abbd4cea96f5918a87103661 a7c60334c23e4c22b76bafaf8c24370f 7f8fd8160ff64ff183af7da14f1428b3--a7c60334c23e4c22b76bafaf8c24370f 2d6cf1b86fcc46b2a0e0c8d48106c331 2 1e3b41dd5423463b9e350c9fd4c66199 t = -500. a7c60334c23e4c22b76bafaf8c24370f--1e3b41dd5423463b9e350c9fd4c66199 c6e8dfbd6d2748b3888baee97fcd4a36 1e3b41dd5423463b9e350c9fd4c66199--c6e8dfbd6d2748b3888baee97fcd4a36 72d29c48f41c4bdebbb939e819b8ac98 X c6e8dfbd6d2748b3888baee97fcd4a36--72d29c48f41c4bdebbb939e819b8ac98 000998a6d5f64069a64502ecce4437d0 t = -500. 72d29c48f41c4bdebbb939e819b8ac98--000998a6d5f64069a64502ecce4437d0 bbe5f47404d747168548a9b605311312 X 000998a6d5f64069a64502ecce4437d0--bbe5f47404d747168548a9b605311312 bbe5f47404d747168548a9b605311312--f386fe61abbd4cea96f5918a87103661 501916d5365c4c9c90fc26d4ac8ad61d d4b8fa58bc674cfbae58020ffa35f026 X 2d6cf1b86fcc46b2a0e0c8d48106c331--d4b8fa58bc674cfbae58020ffa35f026 d453ac8702d14a6192c0a393a6daf7e2 d4b8fa58bc674cfbae58020ffa35f026--d453ac8702d14a6192c0a393a6daf7e2 a549dc1d72714b1da28d77a24334cdb6 X d453ac8702d14a6192c0a393a6daf7e2--a549dc1d72714b1da28d77a24334cdb6 58d602c2ddc34c7a934ca6f11573ed17 X a549dc1d72714b1da28d77a24334cdb6--58d602c2ddc34c7a934ca6f11573ed17 302e8cb302f24e2d9ad6e03f8224b5d6 58d602c2ddc34c7a934ca6f11573ed17--302e8cb302f24e2d9ad6e03f8224b5d6 96b0784620e64f629173ac471435032f X 302e8cb302f24e2d9ad6e03f8224b5d6--96b0784620e64f629173ac471435032f 96b0784620e64f629173ac471435032f--501916d5365c4c9c90fc26d4ac8ad61d

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