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_808eed1c2b894f8b8f756ec52187b9fd cluster_a80bcf0840cf444e8dbe08067ae9e41a cluster_2d690cb879934636a9f81e4eabc32c5a cluster_d203e70d9bfe4f95a4765c649fdc403d cluster_d8c5b7faabed4ff4929ff9ecc5fbff37 cluster_458f316fd1a34ebf92d9bf31dbab4462 cluster_3e4673631a5f45ae8f9415f0a8c53ee0 677d9ed163b640138ba072667b5013cb 0 7053c5b8e50244b69357473322fcf062 HamEvo 677d9ed163b640138ba072667b5013cb--7053c5b8e50244b69357473322fcf062 ac95cabe45d9436ab500e27d39c2527f 1 71217c720af3486c9bd563f619d76ec9 HamEvo 7053c5b8e50244b69357473322fcf062--71217c720af3486c9bd563f619d76ec9 ed46f9c0d90c441cbba1086fc605aed6 HamEvo 71217c720af3486c9bd563f619d76ec9--ed46f9c0d90c441cbba1086fc605aed6 66b7c30b559c49f49607de7ac0f96992 X ed46f9c0d90c441cbba1086fc605aed6--66b7c30b559c49f49607de7ac0f96992 ed8c7324e15c4374876244689f6204ad HamEvo 66b7c30b559c49f49607de7ac0f96992--ed8c7324e15c4374876244689f6204ad 28eba1fe0e504cc48f6e8386ee3c90b8 HamEvo ed8c7324e15c4374876244689f6204ad--28eba1fe0e504cc48f6e8386ee3c90b8 3ea4b4b6703240f6a5a5b5f70da58eca X 28eba1fe0e504cc48f6e8386ee3c90b8--3ea4b4b6703240f6a5a5b5f70da58eca aec7116c3afa41ba9cd04c9896c8b255 3ea4b4b6703240f6a5a5b5f70da58eca--aec7116c3afa41ba9cd04c9896c8b255 5fe4be286d124c9293fcd758f5c295d7 HamEvo aec7116c3afa41ba9cd04c9896c8b255--5fe4be286d124c9293fcd758f5c295d7 8a4ed4fc919b4e91b0c9e537cad80b52 HamEvo 5fe4be286d124c9293fcd758f5c295d7--8a4ed4fc919b4e91b0c9e537cad80b52 1fbad323f3b040dea030ed89aefaa981 8a4ed4fc919b4e91b0c9e537cad80b52--1fbad323f3b040dea030ed89aefaa981 29419344d65547ccbc78d033773ea62f 1fbad323f3b040dea030ed89aefaa981--29419344d65547ccbc78d033773ea62f d37211b5273b4283838cabbe42a8e397 033f2e171f3240ceb99f6440371f995a t = -3.14 ac95cabe45d9436ab500e27d39c2527f--033f2e171f3240ceb99f6440371f995a 9a92a5057cb14e2584b8198409ac5927 2 fa1502ba2480491cafd88817584b2d20 t = 3.142 033f2e171f3240ceb99f6440371f995a--fa1502ba2480491cafd88817584b2d20 9c2b83d7858149d48aa7fe3ab8860eec t = -3.14 fa1502ba2480491cafd88817584b2d20--9c2b83d7858149d48aa7fe3ab8860eec 5ff7e9f64b44421b9f456af2692aa217 9c2b83d7858149d48aa7fe3ab8860eec--5ff7e9f64b44421b9f456af2692aa217 b0c31a9ff79c42549da99ae0f594e9fc t = 1.571 5ff7e9f64b44421b9f456af2692aa217--b0c31a9ff79c42549da99ae0f594e9fc 904d5edb07e94c57b155028c2276a6ab t = 1.571 b0c31a9ff79c42549da99ae0f594e9fc--904d5edb07e94c57b155028c2276a6ab a548e8c8ba60415b8c364aae8a88afca 904d5edb07e94c57b155028c2276a6ab--a548e8c8ba60415b8c364aae8a88afca d77e5230573641829df28f6c010abf5d X a548e8c8ba60415b8c364aae8a88afca--d77e5230573641829df28f6c010abf5d 0543ffbb45a64625bb4a399fbb77ca81 t = 1.571 d77e5230573641829df28f6c010abf5d--0543ffbb45a64625bb4a399fbb77ca81 3cbf740e4f5242d98e4c244b64d960ec t = 1.571 0543ffbb45a64625bb4a399fbb77ca81--3cbf740e4f5242d98e4c244b64d960ec 8ecb24fba40544c4afbe566dc806b862 X 3cbf740e4f5242d98e4c244b64d960ec--8ecb24fba40544c4afbe566dc806b862 8ecb24fba40544c4afbe566dc806b862--d37211b5273b4283838cabbe42a8e397 0121887fa9634b6fa59762d19f4db7aa 79442a4cb9f04e948a117243e3a433ec 9a92a5057cb14e2584b8198409ac5927--79442a4cb9f04e948a117243e3a433ec 0a75cb25f51047a6bdde2aaedd8da18e 79442a4cb9f04e948a117243e3a433ec--0a75cb25f51047a6bdde2aaedd8da18e 8fd7540afbea4fa384f94d13250732b3 0a75cb25f51047a6bdde2aaedd8da18e--8fd7540afbea4fa384f94d13250732b3 6f7f9a954b3e4911a56fd052165176c4 X 8fd7540afbea4fa384f94d13250732b3--6f7f9a954b3e4911a56fd052165176c4 d9717d8f7c984850b2535d44fa0d0d8c 6f7f9a954b3e4911a56fd052165176c4--d9717d8f7c984850b2535d44fa0d0d8c bf9bf0bbb004436eaaf64fda03f4d3c9 d9717d8f7c984850b2535d44fa0d0d8c--bf9bf0bbb004436eaaf64fda03f4d3c9 44551296e56847a4b858827ae1e2128e X bf9bf0bbb004436eaaf64fda03f4d3c9--44551296e56847a4b858827ae1e2128e bc611f36357944549544563bbe77ed98 X 44551296e56847a4b858827ae1e2128e--bc611f36357944549544563bbe77ed98 e3d25c4aaad24a9aa777961d2fff0398 bc611f36357944549544563bbe77ed98--e3d25c4aaad24a9aa777961d2fff0398 98d82bdaa68a4dfa8f62c7ceda252ffb e3d25c4aaad24a9aa777961d2fff0398--98d82bdaa68a4dfa8f62c7ceda252ffb 2c95c303c3bf4c01974ba4bae99dd791 X 98d82bdaa68a4dfa8f62c7ceda252ffb--2c95c303c3bf4c01974ba4bae99dd791 2c95c303c3bf4c01974ba4bae99dd791--0121887fa9634b6fa59762d19f4db7aa

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_87d35e7ab96f4adaaaf9ccd2a1786c84 cluster_327c27738e7f422f9f3f898b5d416060 6fe0a51b8de7498bb0ca8054e606bb67 0 7dc1b9b73b03418e8201f7f54e85259e X 6fe0a51b8de7498bb0ca8054e606bb67--7dc1b9b73b03418e8201f7f54e85259e 7aa0cc33ca224301977dd9cd3fbe0efd 1 35619c142fe143e7aebd8bc4a9c23192 HamEvo 7dc1b9b73b03418e8201f7f54e85259e--35619c142fe143e7aebd8bc4a9c23192 30147d6cb1794f50afb8c17d23ba51b9 X 35619c142fe143e7aebd8bc4a9c23192--30147d6cb1794f50afb8c17d23ba51b9 25ff0c24a2a4479488a4a444362e5f16 30147d6cb1794f50afb8c17d23ba51b9--25ff0c24a2a4479488a4a444362e5f16 8652ffea585645f291efb6e7295d07c1 HamEvo 25ff0c24a2a4479488a4a444362e5f16--8652ffea585645f291efb6e7295d07c1 74bff35f90a942fb9b19d8131b98ee7e 8652ffea585645f291efb6e7295d07c1--74bff35f90a942fb9b19d8131b98ee7e c41e7b563d72447db4f413a690a18d9e 74bff35f90a942fb9b19d8131b98ee7e--c41e7b563d72447db4f413a690a18d9e 226be12978b5457c9da9fe195a94ed09 aa376017490b4584879538af3a441199 7aa0cc33ca224301977dd9cd3fbe0efd--aa376017490b4584879538af3a441199 8c4fa1d40ab14551ae565bd15a0e6f8d 2 f1863029d78e4d43aaedbe94036b7074 t = -0.50 aa376017490b4584879538af3a441199--f1863029d78e4d43aaedbe94036b7074 ca29173a69dc423c87808eccd20ae1e4 f1863029d78e4d43aaedbe94036b7074--ca29173a69dc423c87808eccd20ae1e4 e9cc5bb46acf400c96e728235723829c X ca29173a69dc423c87808eccd20ae1e4--e9cc5bb46acf400c96e728235723829c 5de46be2e5814e7bbfba6a270c0960e7 t = -0.50 e9cc5bb46acf400c96e728235723829c--5de46be2e5814e7bbfba6a270c0960e7 b77de6de45834017be7ccd82c7b6885d X 5de46be2e5814e7bbfba6a270c0960e7--b77de6de45834017be7ccd82c7b6885d b77de6de45834017be7ccd82c7b6885d--226be12978b5457c9da9fe195a94ed09 0e8d473831a144e1be30eac7836c32c8 60fa063e519f405ba608bf2f3a31b171 X 8c4fa1d40ab14551ae565bd15a0e6f8d--60fa063e519f405ba608bf2f3a31b171 e485d0bf4dfe4bc99b06b39544d2668b 60fa063e519f405ba608bf2f3a31b171--e485d0bf4dfe4bc99b06b39544d2668b 17385340c908469f8346f39a8db6451a X e485d0bf4dfe4bc99b06b39544d2668b--17385340c908469f8346f39a8db6451a 387b2a5e17e24d03bbb66efb7d895f22 X 17385340c908469f8346f39a8db6451a--387b2a5e17e24d03bbb66efb7d895f22 b994392cb17f4e0692e5066b00a3a902 387b2a5e17e24d03bbb66efb7d895f22--b994392cb17f4e0692e5066b00a3a902 5e5c2c34838e46ad86be22554473efe8 X b994392cb17f4e0692e5066b00a3a902--5e5c2c34838e46ad86be22554473efe8 5e5c2c34838e46ad86be22554473efe8--0e8d473831a144e1be30eac7836c32c8

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_df582ae577b7456697f1d8eb8aaa815c cluster_d61e0dd87ba04d6a9fac7de7550e6c54 bd114474045844cf83741a1b5ae93560 0 a73c71f67217404889b6ea9414b0df5b X bd114474045844cf83741a1b5ae93560--a73c71f67217404889b6ea9414b0df5b 354f6ec376e74415940bf66de35233bc 1 5d608e1a58ab47f5b7bb69a4c652a63a HamEvo a73c71f67217404889b6ea9414b0df5b--5d608e1a58ab47f5b7bb69a4c652a63a faceb4bc7b4a4426b0a9fa3679dee750 X 5d608e1a58ab47f5b7bb69a4c652a63a--faceb4bc7b4a4426b0a9fa3679dee750 d5dec5e0b4524a92b8dc3c91eb9b09cb faceb4bc7b4a4426b0a9fa3679dee750--d5dec5e0b4524a92b8dc3c91eb9b09cb 7f95a7222e3d433b989b2ba4972c6f8c HamEvo d5dec5e0b4524a92b8dc3c91eb9b09cb--7f95a7222e3d433b989b2ba4972c6f8c 3e7006161569422dbc13839d23b48c78 7f95a7222e3d433b989b2ba4972c6f8c--3e7006161569422dbc13839d23b48c78 e8a7a0678b704ffbbda564738f38cc7f 3e7006161569422dbc13839d23b48c78--e8a7a0678b704ffbbda564738f38cc7f 61ec99fbff874c2795f3ceefbfd1ccc0 7b58785b3f6546bc808f704149473058 354f6ec376e74415940bf66de35233bc--7b58785b3f6546bc808f704149473058 a4d826b3a05c4dbf9ff627a7e3b832a2 2 bc37ffc9594e4f8daa959c1259e1309a t = -500. 7b58785b3f6546bc808f704149473058--bc37ffc9594e4f8daa959c1259e1309a cb7f4179e1104a509d61b8594faf033a bc37ffc9594e4f8daa959c1259e1309a--cb7f4179e1104a509d61b8594faf033a 400c1ecbce5f42768dc022342b954d61 X cb7f4179e1104a509d61b8594faf033a--400c1ecbce5f42768dc022342b954d61 5e468a1e8ff2451792ef1e571d87f025 t = -500. 400c1ecbce5f42768dc022342b954d61--5e468a1e8ff2451792ef1e571d87f025 743c1ba5383a498fbc3f10f572b95cd8 X 5e468a1e8ff2451792ef1e571d87f025--743c1ba5383a498fbc3f10f572b95cd8 743c1ba5383a498fbc3f10f572b95cd8--61ec99fbff874c2795f3ceefbfd1ccc0 c44290583c404646988d0eaa6a4331b3 61bfca5ce5c64865ad2e2cd3bdeace69 X a4d826b3a05c4dbf9ff627a7e3b832a2--61bfca5ce5c64865ad2e2cd3bdeace69 5c368ba32a544ddfba27ffebe8cd4c04 61bfca5ce5c64865ad2e2cd3bdeace69--5c368ba32a544ddfba27ffebe8cd4c04 90cb60a72ce640648728ee85452530f7 X 5c368ba32a544ddfba27ffebe8cd4c04--90cb60a72ce640648728ee85452530f7 d2ec6d2471c041a5b7d05c4a4a0258c9 X 90cb60a72ce640648728ee85452530f7--d2ec6d2471c041a5b7d05c4a4a0258c9 05ecefff15d24d42a48dc1a3f5612405 d2ec6d2471c041a5b7d05c4a4a0258c9--05ecefff15d24d42a48dc1a3f5612405 26001d68a56e41b2bcedca5602776d76 X 05ecefff15d24d42a48dc1a3f5612405--26001d68a56e41b2bcedca5602776d76 26001d68a56e41b2bcedca5602776d76--c44290583c404646988d0eaa6a4331b3

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