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

n_qubits = 2

# CNOT gate
cnot_gate = CNOT(0, 1)

# CNOT decomposed
phi = torch.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=torch.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_729eb6832bdd40d18c4f3b5b7eca9caa cluster_45efc602aa1340ee8cffc0f6bdc92714 cluster_a7214c38c1fc4e2ebcf57bbdfcaed4a7 cluster_06547320a48c49379b970ef1d44f0f38 cluster_e6f38ecf58af4e6a958a9eb9dc5e1e42 cluster_1ce85f12fa6e4cb09c59e4fe90e68ec7 cluster_80089d996b0f461d881f6d728105d63f 83e2d621c42e435e93fb5f815aa8a530 0 dec9807f282c4dff8119bdd291d52b4e HamEvo 83e2d621c42e435e93fb5f815aa8a530--dec9807f282c4dff8119bdd291d52b4e 61fc0cdfc0794cbda0f49d128d380a69 1 45f78f9bfe534d529a213ae743db9ca0 HamEvo dec9807f282c4dff8119bdd291d52b4e--45f78f9bfe534d529a213ae743db9ca0 39fd2eceb54b48b3ba54fb7edf095204 HamEvo 45f78f9bfe534d529a213ae743db9ca0--39fd2eceb54b48b3ba54fb7edf095204 a46e7ee5ad3a4b72a37f602b7a1d1667 X 39fd2eceb54b48b3ba54fb7edf095204--a46e7ee5ad3a4b72a37f602b7a1d1667 8feda2a115d94a7491de0f955afae62d HamEvo a46e7ee5ad3a4b72a37f602b7a1d1667--8feda2a115d94a7491de0f955afae62d efdafba34bb74aefad06c316a60b8750 HamEvo 8feda2a115d94a7491de0f955afae62d--efdafba34bb74aefad06c316a60b8750 280398766e19420494d06d27c1b1aa29 X efdafba34bb74aefad06c316a60b8750--280398766e19420494d06d27c1b1aa29 48d43a10f4c14bd2a92eba9ba3e7b134 280398766e19420494d06d27c1b1aa29--48d43a10f4c14bd2a92eba9ba3e7b134 02071391f73a4771bd945c8312191052 HamEvo 48d43a10f4c14bd2a92eba9ba3e7b134--02071391f73a4771bd945c8312191052 8af4d2e163f94a91b53fbc1b2152963c HamEvo 02071391f73a4771bd945c8312191052--8af4d2e163f94a91b53fbc1b2152963c 2004e39985734f62a72e0602c7839a91 8af4d2e163f94a91b53fbc1b2152963c--2004e39985734f62a72e0602c7839a91 0e1e4cbd6615478d9efd61f4dfe496c9 2004e39985734f62a72e0602c7839a91--0e1e4cbd6615478d9efd61f4dfe496c9 3d0b7a696b85477296ba9500f7607cc3 775a3dae42194f7bb803b75c007ee697 t = -3.142 61fc0cdfc0794cbda0f49d128d380a69--775a3dae42194f7bb803b75c007ee697 8ebf38d21b8441a69361f0f7f35f39a6 2 c6c5ba4cdb3d43bab20cdf0c56c53eac t = 3.142 775a3dae42194f7bb803b75c007ee697--c6c5ba4cdb3d43bab20cdf0c56c53eac 751942b87eca490982de777ef7d0ed38 t = -3.142 c6c5ba4cdb3d43bab20cdf0c56c53eac--751942b87eca490982de777ef7d0ed38 de4ef68c90174333a6095abacf0322d6 751942b87eca490982de777ef7d0ed38--de4ef68c90174333a6095abacf0322d6 2951346b15ad4518a42a094f410c0c0e t = 1.571 de4ef68c90174333a6095abacf0322d6--2951346b15ad4518a42a094f410c0c0e 187969bf57c044b8b634b5cdfd8f39ba t = 1.571 2951346b15ad4518a42a094f410c0c0e--187969bf57c044b8b634b5cdfd8f39ba 03f146d028664fdbb1796d43572bfa60 187969bf57c044b8b634b5cdfd8f39ba--03f146d028664fdbb1796d43572bfa60 cd094d9caf13443f965238e15bda70fd X 03f146d028664fdbb1796d43572bfa60--cd094d9caf13443f965238e15bda70fd d5f869d5eb4f4179ae7a11cf5303d82b t = 1.571 cd094d9caf13443f965238e15bda70fd--d5f869d5eb4f4179ae7a11cf5303d82b 7023a485552b4f2b808152876afdbcc0 t = 1.571 d5f869d5eb4f4179ae7a11cf5303d82b--7023a485552b4f2b808152876afdbcc0 d0b3a32ac035423d8bad5286564f5a27 X 7023a485552b4f2b808152876afdbcc0--d0b3a32ac035423d8bad5286564f5a27 d0b3a32ac035423d8bad5286564f5a27--3d0b7a696b85477296ba9500f7607cc3 172a7ea0513f4477a8dfcb3f64835b98 ff5674b5330749f28d69003633a8b7b7 8ebf38d21b8441a69361f0f7f35f39a6--ff5674b5330749f28d69003633a8b7b7 8927fc3913a54e1babab327ec6dc32d0 ff5674b5330749f28d69003633a8b7b7--8927fc3913a54e1babab327ec6dc32d0 ef3d6fb2fb2345379b62dc1a08ea02c9 8927fc3913a54e1babab327ec6dc32d0--ef3d6fb2fb2345379b62dc1a08ea02c9 5da971e3e7e94a5fb713411be367d0e0 X ef3d6fb2fb2345379b62dc1a08ea02c9--5da971e3e7e94a5fb713411be367d0e0 8c51cb5ec63947afbe55dcd9cbbdb6ea 5da971e3e7e94a5fb713411be367d0e0--8c51cb5ec63947afbe55dcd9cbbdb6ea 5b646b44f0694fb3b9c4f8b08ee97a63 8c51cb5ec63947afbe55dcd9cbbdb6ea--5b646b44f0694fb3b9c4f8b08ee97a63 89f7781665914c9ab2d7c7f0119dd8d7 X 5b646b44f0694fb3b9c4f8b08ee97a63--89f7781665914c9ab2d7c7f0119dd8d7 02a762705860445999901cd67a83a778 X 89f7781665914c9ab2d7c7f0119dd8d7--02a762705860445999901cd67a83a778 5083a44f98b94417ba2a751ca7b2c8c9 02a762705860445999901cd67a83a778--5083a44f98b94417ba2a751ca7b2c8c9 1553b8c4f7ba4f6cbb1325aabacb2bc7 5083a44f98b94417ba2a751ca7b2c8c9--1553b8c4f7ba4f6cbb1325aabacb2bc7 96472e81cb1645f6af8f85d35d85c7c6 X 1553b8c4f7ba4f6cbb1325aabacb2bc7--96472e81cb1645f6af8f85d35d85c7c6 96472e81cb1645f6af8f85d35d85c7c6--172a7ea0513f4477a8dfcb3f64835b98

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_4dda9e352446456fa22f94c6a5d5844e cluster_d47ca694cfb04ad4b8e41c99266e38aa ec6cd3aad24743898fd1db0af8ca875a 0 a004b43a3e914c3d84c9d06560892110 X ec6cd3aad24743898fd1db0af8ca875a--a004b43a3e914c3d84c9d06560892110 685db354a03548b88d7ac3f63ce5797c 1 d289caa4b8d6418f81576a09c20ffda3 HamEvo a004b43a3e914c3d84c9d06560892110--d289caa4b8d6418f81576a09c20ffda3 47a8140a0d204d769707ee0582d2e62c X d289caa4b8d6418f81576a09c20ffda3--47a8140a0d204d769707ee0582d2e62c 72cf998cf98c4b50b4f4363cfbc74294 47a8140a0d204d769707ee0582d2e62c--72cf998cf98c4b50b4f4363cfbc74294 0ab7143e27eb492283494f3d54c11ff3 HamEvo 72cf998cf98c4b50b4f4363cfbc74294--0ab7143e27eb492283494f3d54c11ff3 ce1e116423934839aaf68fbe8d51712b 0ab7143e27eb492283494f3d54c11ff3--ce1e116423934839aaf68fbe8d51712b e0be72533b6d454a8b4d4a358e7800da ce1e116423934839aaf68fbe8d51712b--e0be72533b6d454a8b4d4a358e7800da d3fe679419bc4b70937e9b76e61c08c0 98009114064b4f00891a58f989d93ff6 685db354a03548b88d7ac3f63ce5797c--98009114064b4f00891a58f989d93ff6 d9a479ba4d6e43b9bc1190a77b2a62e0 2 60af7dd07f4e417592c7ea3d2594ba88 t = -0.500 98009114064b4f00891a58f989d93ff6--60af7dd07f4e417592c7ea3d2594ba88 d15ceb24da0842a59e7cd5e43805b390 60af7dd07f4e417592c7ea3d2594ba88--d15ceb24da0842a59e7cd5e43805b390 c3a23c669c0d4ff497f93ef3b50091b5 X d15ceb24da0842a59e7cd5e43805b390--c3a23c669c0d4ff497f93ef3b50091b5 6091fd45465e448d834ff55addcce5d2 t = -0.500 c3a23c669c0d4ff497f93ef3b50091b5--6091fd45465e448d834ff55addcce5d2 7e165a0410ff47b6a03746371b75b05f X 6091fd45465e448d834ff55addcce5d2--7e165a0410ff47b6a03746371b75b05f 7e165a0410ff47b6a03746371b75b05f--d3fe679419bc4b70937e9b76e61c08c0 59ac8ba6ebb44cc292bf28e7894126be 05029f4b4dde4567abcaa6f64056453f X d9a479ba4d6e43b9bc1190a77b2a62e0--05029f4b4dde4567abcaa6f64056453f 0e6a7a5bf9e7411b97a12cfc30d05ecd 05029f4b4dde4567abcaa6f64056453f--0e6a7a5bf9e7411b97a12cfc30d05ecd 446820c8b308400ba0695180c0fd41ec X 0e6a7a5bf9e7411b97a12cfc30d05ecd--446820c8b308400ba0695180c0fd41ec d872eea3e4334eacaf308f198302d13f X 446820c8b308400ba0695180c0fd41ec--d872eea3e4334eacaf308f198302d13f d57e41ae86354eceab1d51f36d818c0a d872eea3e4334eacaf308f198302d13f--d57e41ae86354eceab1d51f36d818c0a 5a37fa83628340a585a4c4d28a89b0eb X d57e41ae86354eceab1d51f36d818c0a--5a37fa83628340a585a4c4d28a89b0eb 5a37fa83628340a585a4c4d28a89b0eb--59ac8ba6ebb44cc292bf28e7894126be

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_c460bbd9e1ff4053a584bd2892a86cb6 cluster_2942730b4c224ec4aa7f1855d4e0cbc4 f4acee8591b64f25b6562201df8bd838 0 0742c60bfab14fbaaeda6ff71e3fda6c X f4acee8591b64f25b6562201df8bd838--0742c60bfab14fbaaeda6ff71e3fda6c 3e2701b870294107a586c878546461f7 1 db8d54760d154a07abf935f17812668d HamEvo 0742c60bfab14fbaaeda6ff71e3fda6c--db8d54760d154a07abf935f17812668d 3c80c586c8094d5383ddf1388791221c X db8d54760d154a07abf935f17812668d--3c80c586c8094d5383ddf1388791221c dcbb255f863848d9b3689466daaa689d 3c80c586c8094d5383ddf1388791221c--dcbb255f863848d9b3689466daaa689d 54af439a25534349b68506f23046578d HamEvo dcbb255f863848d9b3689466daaa689d--54af439a25534349b68506f23046578d c1a9955f9dc94759896548e3503faa44 54af439a25534349b68506f23046578d--c1a9955f9dc94759896548e3503faa44 a193b97c39c840da9c755149b10ef984 c1a9955f9dc94759896548e3503faa44--a193b97c39c840da9c755149b10ef984 ca06166f1d304c6a803e56a045603696 c88d017fdbe54a528bb55ee661aee058 3e2701b870294107a586c878546461f7--c88d017fdbe54a528bb55ee661aee058 7ae572e5aec8446a8e5edaba0a811fc3 2 13e88d7f973d49b29f1187ad869acc0b t = -500.000000000000 c88d017fdbe54a528bb55ee661aee058--13e88d7f973d49b29f1187ad869acc0b d433da021bfc46b6ac27e5cf9bfdaca0 13e88d7f973d49b29f1187ad869acc0b--d433da021bfc46b6ac27e5cf9bfdaca0 c6ee2174ea734366b13d9fd436ba71aa X d433da021bfc46b6ac27e5cf9bfdaca0--c6ee2174ea734366b13d9fd436ba71aa 2e1d250fb38b40b8b07f01e94a4cdc5c t = -500.000000000000 c6ee2174ea734366b13d9fd436ba71aa--2e1d250fb38b40b8b07f01e94a4cdc5c 7b6177ff4e214921bce2c04be577f8c0 X 2e1d250fb38b40b8b07f01e94a4cdc5c--7b6177ff4e214921bce2c04be577f8c0 7b6177ff4e214921bce2c04be577f8c0--ca06166f1d304c6a803e56a045603696 45ffce73c0dc47a886ddec5ac53904d4 79be4163bace48d1bdc9c27c3f7c9df6 X 7ae572e5aec8446a8e5edaba0a811fc3--79be4163bace48d1bdc9c27c3f7c9df6 b29716b3348c4759abde12dae33b2b5c 79be4163bace48d1bdc9c27c3f7c9df6--b29716b3348c4759abde12dae33b2b5c 2020b61207a24a10b0677fcd182692b4 X b29716b3348c4759abde12dae33b2b5c--2020b61207a24a10b0677fcd182692b4 a34282e596764faf83714d9fdaab493a X 2020b61207a24a10b0677fcd182692b4--a34282e596764faf83714d9fdaab493a 75ede891858242dca44de73cece9984d a34282e596764faf83714d9fdaab493a--75ede891858242dca44de73cece9984d 1a65accbaf0c4c71b1fd2910d52411b1 X 75ede891858242dca44de73cece9984d--1a65accbaf0c4c71b1fd2910d52411b1 1a65accbaf0c4c71b1fd2910d52411b1--45ffce73c0dc47a886ddec5ac53904d4

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