Skip to content

DAQC Transform

Digital-analog quantum computing focuses on using simple digital gates combined with more complex and device-dependent analog interactions to represent quantum programs. Such techniques have been shown to be universal for quantum computation 1. 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.

In this tutorial we will exemplify this transformation starting with the representation of a simple digital CNOT using the universality of the Ising Hamiltonian 2.

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
import qadence as qd

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 = qd.chain(H(1), CPHASE(0, 1, phi), H(1))

init_state = qd.product_state("10")

print(qd.sample(n_qubits, block = cnot_gate, state = init_state, n_shots = 100))
print(qd.sample(n_qubits, block = cnot_decomp, state = init_state, n_shots = 100))
[Counter({'11': 100})]
[Counter({'11': 100})]

The CPHASE gate is fully 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 we used the number operator \(N_i = \frac{1}{2}(I_i-Z_i)\), leading to an Ising-like interaction \(N_iN_j\) that is common in neutral-atom systems. Let's rebuild the CNOT using this evolution.

# Hamiltonian for the CPHASE gate
h_cphase = (-1.0) * qd.kron(N(0), N(1))

# Exponentiating the Hamiltonian
cphase_evo = HamEvo(h_cphase, phi)

# Check that we have the CPHASE gate:
cphase_matrix = qd.block_to_tensor(CPHASE(0, 1, phi))
cphase_evo_matrix = qd.block_to_tensor(cphase_evo)

assert torch.allclose(cphase_matrix, cphase_evo_matrix)

Now that we have checked the generator of the CPHASE gate, we can use it to apply the CNOT:

# CNOT with Hamiltonian Evolution
cnot_evo = qd.chain(
    H(1),
    cphase_evo,
    H(1)
)

init_state = qd.product_state("10")

print(qd.sample(n_qubits, block = cnot_gate, state = init_state, n_shots = 100))
print(qd.sample(n_qubits, block = cnot_evo, state = init_state, n_shots = 100))
[Counter({'11': 100})]
[Counter({'11': 100})]

Thus, a CNOT gate can be applied by combining a few single-qubit gates together with a 2-qubit Ising interaction between the control and the target qubit. This is important because it now allows us to exemplify the usage of the Ising transform proposed in the DAQC paper 2. In the paper, the transform is described for \(ZZ\) interactions. In qadence it works both with \(ZZ\) and \(NN\) interactions.

CNOT in an interacting system of 3 qubits

Consider a simple experimental setup with \(n=3\) interacting qubits in a triangular grid. For simplicity let's consider that all qubits interact with each other with an Ising (\(NN\)) interaction of constant strength \(g_\text{int}\). The Hamiltonian for the system can be written by summing this interaction 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:

n_qubits = 3

g_int = 1.0

interaction_list = []
for i in range(n_qubits):
    for j in range(i):
        interaction_list.append(g_int * qd.kron(N(i), N(j)))

h_sys = qd.add(*interaction_list)

print(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 we cannot isolate the qubits from each other. All we can do is the following:

  • Turn on or off the global system Hamiltonian.
  • Perform single-qubit rotations on individual qubits.

How can we perform a CNOT on two specific qubits of our choice?

To perform a fully digital CNOT we would need to isolate the control and target qubit from the third one and have those interact to implement the gate directly. While this may be relatively simple for a 3-qubit system, the experimental burden becomes much greater when we start going into the dozens of qubits.

However, with the digital-analog paradigm that is not the case! In fact, we can represent the two qubit Ising interaction required for the CNOT by combining the global system Hamiltonian with a specific set of single-qubit rotations. The full details of this transformation are described in the DAQC paper 2, and it is available in qadence by calling the daqc_transform function.

The daqc_transform function will essentially return a program that represents the evolution of an Hamiltonian \(H_\text{target}\) (target Hamiltonian) for a specified time \(t_f\) by using only the evolution of an Hamiltonian \(H_\text{build}\) (build Hamiltonian) for specific intervals of time together with specific single-qubit \(X\) rotations. Currently, in qadence it is available for resource and target Hamiltonians composed only of \(ZZ\) or \(NN\) interactions. The generators are parsed by the daqc_transform function, the appropriate type is automatically determined, and the appropriate single-qubit detunings and global phases are applied.

Let's exemplify it for our CNOT problem:

# The target operation
i = 0  # Control
j = 1  # Target
k = 2  # The extra qubit

# CNOT on control and target, Identity on the extra qubit
cnot_target = qd.kron(CNOT(i, j), I(k))

# The two-qubit Ising (NN) interaction for the CPHASE
h_int = (-1.0) * qd.kron(N(i), N(j))

# Transforming the two-qubit Ising interaction using only our system Hamiltonian
transformed_ising = qd.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 = "sDAQC",   # Currently only sDAQC is implemented
    ignore_global_phases = False  # Global phases from mapping between Z and N
)

# display(transformed_ising)
cluster_9dd396f591fb470d8c389e503c861dbc cluster_55325d4e20034061922406a1db7031c0 cluster_485f809742e34ed6a13e5b5ce75bfffd cluster_85be90fceefb49c586dbf0aa1305b57c cluster_0b0ac83bf6a14842959467980d698fb2 cluster_2b8adba516d043e6bf019eed27e71485 cluster_bbcdc80b690d45ffb7216d54a88622d0 f2c2d23d1ea24e5e9259bebee70a00b6 0 8b5bcf27f2e347b4b0c559ec1830b9e3 HamEvo f2c2d23d1ea24e5e9259bebee70a00b6--8b5bcf27f2e347b4b0c559ec1830b9e3 967f9f6b0d2045f5bb707e3c3c5ccbe4 1 b7907fd323f24a8aa1fdfdf8f6ff0ccf HamEvo 8b5bcf27f2e347b4b0c559ec1830b9e3--b7907fd323f24a8aa1fdfdf8f6ff0ccf aadc75e0b9f148aa8b5250ac9e66f2bf HamEvo b7907fd323f24a8aa1fdfdf8f6ff0ccf--aadc75e0b9f148aa8b5250ac9e66f2bf aa84b335b96743a8bb3c854aa665db87 X aadc75e0b9f148aa8b5250ac9e66f2bf--aa84b335b96743a8bb3c854aa665db87 9c369f364b984afb9d38851da214c40e HamEvo aa84b335b96743a8bb3c854aa665db87--9c369f364b984afb9d38851da214c40e 6f00fa24e498473792fe0eab27103241 HamEvo 9c369f364b984afb9d38851da214c40e--6f00fa24e498473792fe0eab27103241 1918ac4b6195411cb187bb2adbd20d84 X 6f00fa24e498473792fe0eab27103241--1918ac4b6195411cb187bb2adbd20d84 2839c2cc236d4371a4841f7d8168ed0c 1918ac4b6195411cb187bb2adbd20d84--2839c2cc236d4371a4841f7d8168ed0c aba154e0d45f4a3aa147232493f09f14 HamEvo 2839c2cc236d4371a4841f7d8168ed0c--aba154e0d45f4a3aa147232493f09f14 b16455b15d004f0e9221d7707913d3bc HamEvo aba154e0d45f4a3aa147232493f09f14--b16455b15d004f0e9221d7707913d3bc 90e668992ca1465896044ca52cb0ce57 b16455b15d004f0e9221d7707913d3bc--90e668992ca1465896044ca52cb0ce57 ef3d1846a36a4312b079a017195e1ad8 90e668992ca1465896044ca52cb0ce57--ef3d1846a36a4312b079a017195e1ad8 58f4be8e267b4128910d0c6fdc6d7b61 e254a25ecf6443b6b6445ada86046494 t = -3.142 967f9f6b0d2045f5bb707e3c3c5ccbe4--e254a25ecf6443b6b6445ada86046494 01888605a0bd402f8f510b633d2c21bf 2 0dc6873b3b1e46d38d0b5c92599a77d7 t = 3.142 e254a25ecf6443b6b6445ada86046494--0dc6873b3b1e46d38d0b5c92599a77d7 73b1159bbdf649d28248e4dadd70be6d t = -3.142 0dc6873b3b1e46d38d0b5c92599a77d7--73b1159bbdf649d28248e4dadd70be6d 4bb631e43ceb4148bca064e5ea7d8370 73b1159bbdf649d28248e4dadd70be6d--4bb631e43ceb4148bca064e5ea7d8370 d29da1d8f75b4c389c2778a18a8807cb t = 1.571 4bb631e43ceb4148bca064e5ea7d8370--d29da1d8f75b4c389c2778a18a8807cb e256015a4e9c479fb30640d54ce6404b t = 1.571 d29da1d8f75b4c389c2778a18a8807cb--e256015a4e9c479fb30640d54ce6404b e99aef689b394f60b83976332c82a976 e256015a4e9c479fb30640d54ce6404b--e99aef689b394f60b83976332c82a976 1c1e6e3bde384f078b8a1ab191adb1da X e99aef689b394f60b83976332c82a976--1c1e6e3bde384f078b8a1ab191adb1da 4f0febca54c740ab97a700a4d942b466 t = 1.571 1c1e6e3bde384f078b8a1ab191adb1da--4f0febca54c740ab97a700a4d942b466 77ae55cb17b940d48c4412d2d098fc24 t = 1.571 4f0febca54c740ab97a700a4d942b466--77ae55cb17b940d48c4412d2d098fc24 d4230d62c33a4512b4cd675167e661b0 X 77ae55cb17b940d48c4412d2d098fc24--d4230d62c33a4512b4cd675167e661b0 d4230d62c33a4512b4cd675167e661b0--58f4be8e267b4128910d0c6fdc6d7b61 1a0516603f894d71a89b5ae6f7171385 76f86d3f7d204b8c9916ad524bc7ceec 01888605a0bd402f8f510b633d2c21bf--76f86d3f7d204b8c9916ad524bc7ceec ed16f511a0924ef68b70ea816223c2a2 76f86d3f7d204b8c9916ad524bc7ceec--ed16f511a0924ef68b70ea816223c2a2 0d6a77dfe04548bb8cb7b189fae1091e ed16f511a0924ef68b70ea816223c2a2--0d6a77dfe04548bb8cb7b189fae1091e 684ab2ab47584e25b9fa984ab9a73d3a X 0d6a77dfe04548bb8cb7b189fae1091e--684ab2ab47584e25b9fa984ab9a73d3a fcc61f5b641f45caa592f6b02348d7b3 684ab2ab47584e25b9fa984ab9a73d3a--fcc61f5b641f45caa592f6b02348d7b3 d51040e9c204421492d382ca5cdcb5e4 fcc61f5b641f45caa592f6b02348d7b3--d51040e9c204421492d382ca5cdcb5e4 b75258e5317f457c9609a1ac6657b597 X d51040e9c204421492d382ca5cdcb5e4--b75258e5317f457c9609a1ac6657b597 2b753d22e717476fab5d9a7162e7834e X b75258e5317f457c9609a1ac6657b597--2b753d22e717476fab5d9a7162e7834e 8d46b68052674c959fd6830055f08555 2b753d22e717476fab5d9a7162e7834e--8d46b68052674c959fd6830055f08555 ba087a0c16c541a49d2a2080c264281b 8d46b68052674c959fd6830055f08555--ba087a0c16c541a49d2a2080c264281b ab3032c086b54547b455af5448735b67 X ba087a0c16c541a49d2a2080c264281b--ab3032c086b54547b455af5448735b67 ab3032c086b54547b455af5448735b67--1a0516603f894d71a89b5ae6f7171385

The circuit above actually only uses two evolutions of the global Hamiltonian. In the displayed circuit also see other instances of HamEvo which account for global-phases and single-qubit detunings related to the mapping between the \(Z\) and \(N\) operator. Optionally, the application of the global phases can also be ignored, as shown in the input of daqc_transform. This will not create exactly the same state or operator matrix in tensor form, but in practice they will be equivalent.

In general, the mapping of a \(n\)-qubit Ising Hamiltonian 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, since we used the step-wise DAQC technique (sDAQC). In banged DAQC (bDAQC) the mapping is not exact, but is easier to implement on a physical device with always-on interactions such as neutral-atom systems. Currently, only the sDAQC technique is available in qadence.

Just as before, we can check that using the transformed Ising circuit we exactly recover the CPHASE gate:

# CPHASE on (i, j), Identity on third qubit:
cphase_matrix = qd.block_to_tensor(qd.kron(CPHASE(i, j, phi), I(k)))

# CPHASE using the transformed circuit:
cphase_evo_matrix = qd.block_to_tensor(transformed_ising)

# Will fail if global phases are ignored:
assert torch.allclose(cphase_matrix, cphase_evo_matrix)

And we can now build the CNOT gate:

cnot_daqc = qd.chain(
    H(j),
    transformed_ising,
    H(j)
)

# And finally run the CNOT on a specific 3-qubit initial state:
init_state = qd.product_state("101")

# Check we get an equivalent wavefunction (will still pass if global phases are ignored)
wf_cnot = qd.run(n_qubits, block = cnot_target, state = init_state)
wf_daqc = qd.run(n_qubits, block = cnot_daqc, state = init_state)
assert qd.equivalent_state(wf_cnot, wf_daqc)

# Visualize the CNOT bit-flip:
print(qd.sample(n_qubits, block = cnot_target, state = init_state, n_shots = 100))
print(qd.sample(n_qubits, block = cnot_daqc, state = init_state, n_shots = 100))
[Counter({'111': 100})]
[Counter({'111': 100})]

And we are done! We have effectively performed a CNOT operation on our desired target qubits by using only the global interaction of the system as the building block Hamiltonian, together with single-qubit rotations. Going through the trouble of decomposing a single digital gate into its Ising Hamiltonian is certainly not very practical, but it serves as a proof of principle for the potential of this technique to represent universal quantum computation. In the next example, we will see it applied to the digital-analog Quantum Fourier Transform.

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 polynomial 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, matching the target Hamiltonian:

transformed_ising = qd.daqc_transform(
    n_qubits = 3,
    gen_target = gen_target,
    t_f = 1.0,
    gen_build = gen_build(g_int = 1.0),
)

# display(transformed_ising)
cluster_88143b6603184752908b0c92bb3fe003 cluster_6092345626a445e693b2603dabb20653 1d570a92d5d842d8b774e2c2bd78905a 0 1ff1a40da4ee4a6f9f0f33f6f93c4379 X 1d570a92d5d842d8b774e2c2bd78905a--1ff1a40da4ee4a6f9f0f33f6f93c4379 4c64eca9039f4071a400923046a81227 1 fdaf937e7d934a73af0784b06c3fec56 HamEvo 1ff1a40da4ee4a6f9f0f33f6f93c4379--fdaf937e7d934a73af0784b06c3fec56 6230b5e5f9694da399f24968fa254878 X fdaf937e7d934a73af0784b06c3fec56--6230b5e5f9694da399f24968fa254878 a4d217f5d32a48648b39f4ffde10407e 6230b5e5f9694da399f24968fa254878--a4d217f5d32a48648b39f4ffde10407e a30a46b1b9904ad799306d81cad0cf00 HamEvo a4d217f5d32a48648b39f4ffde10407e--a30a46b1b9904ad799306d81cad0cf00 56dd8cad62034f958cce496c068b2f7b a30a46b1b9904ad799306d81cad0cf00--56dd8cad62034f958cce496c068b2f7b 66b85cec5e454b578afc2192c78dca5e 56dd8cad62034f958cce496c068b2f7b--66b85cec5e454b578afc2192c78dca5e e982683990254a19953e0b1ddf9e8a6b af258005fb7448a38dec8d3969cdb6be 4c64eca9039f4071a400923046a81227--af258005fb7448a38dec8d3969cdb6be d607adefe8be4183b7b0db2ad548c047 2 6eede3b3301d4d7eaced18e94a7b446f t = -0.500 af258005fb7448a38dec8d3969cdb6be--6eede3b3301d4d7eaced18e94a7b446f dfb6b62eecd14b719c1ef031388e5a87 6eede3b3301d4d7eaced18e94a7b446f--dfb6b62eecd14b719c1ef031388e5a87 f15c5973e83045939e91ac20e358ddd1 X dfb6b62eecd14b719c1ef031388e5a87--f15c5973e83045939e91ac20e358ddd1 9d5ded858d35403faba40b594bc1fbfb t = -0.500 f15c5973e83045939e91ac20e358ddd1--9d5ded858d35403faba40b594bc1fbfb e1cb3fec68754a6bb1bdcc6d0d79f53e X 9d5ded858d35403faba40b594bc1fbfb--e1cb3fec68754a6bb1bdcc6d0d79f53e e1cb3fec68754a6bb1bdcc6d0d79f53e--e982683990254a19953e0b1ddf9e8a6b 62da9341389e4d3e964145141057c01a e22e26190a4c4c0da8bb8a41e254eb7c X d607adefe8be4183b7b0db2ad548c047--e22e26190a4c4c0da8bb8a41e254eb7c c13ac686f2d2407c8aab9a91eba529ad e22e26190a4c4c0da8bb8a41e254eb7c--c13ac686f2d2407c8aab9a91eba529ad e950ef59dc734ebdb08741fb47764266 X c13ac686f2d2407c8aab9a91eba529ad--e950ef59dc734ebdb08741fb47764266 0ec2001660e040cab058399cec44b476 X e950ef59dc734ebdb08741fb47764266--0ec2001660e040cab058399cec44b476 5e9923509dfe4e6a9dc621dba5e9b022 0ec2001660e040cab058399cec44b476--5e9923509dfe4e6a9dc621dba5e9b022 81781c743b3447228fa50c12eaaa186c X 5e9923509dfe4e6a9dc621dba5e9b022--81781c743b3447228fa50c12eaaa186c 81781c743b3447228fa50c12eaaa186c--62da9341389e4d3e964145141057c01a

And we get the transformed circuit. What if our build Hamiltonian has a very weak interaction between qubits 0 and 1?

transformed_ising = qd.daqc_transform(
    n_qubits = 3,
    gen_target = gen_target,
    t_f = 1.0,
    gen_build = gen_build(g_int = 0.001),
)

# display(transformed_ising)
cluster_9dd75b1bef154a97acd3681dbf477152 cluster_2da0f5b15101467193257d5d0e514123 37a5771c8559490caac7e514f00702d7 0 79a91e788054426bb324c21ea78bf825 X 37a5771c8559490caac7e514f00702d7--79a91e788054426bb324c21ea78bf825 3ae7022d660043f0bb0530bd09e40dd5 1 caa1e47b66044581b53926b6eeffdf56 HamEvo 79a91e788054426bb324c21ea78bf825--caa1e47b66044581b53926b6eeffdf56 00290ff745d74cb2867f8f203feb50d9 X caa1e47b66044581b53926b6eeffdf56--00290ff745d74cb2867f8f203feb50d9 e6f9e00c1679481abba79b4e4576daab 00290ff745d74cb2867f8f203feb50d9--e6f9e00c1679481abba79b4e4576daab 122016016adc4c629981460be82b36c9 HamEvo e6f9e00c1679481abba79b4e4576daab--122016016adc4c629981460be82b36c9 b2738c0b98fe42c7872459e36149dd5d 122016016adc4c629981460be82b36c9--b2738c0b98fe42c7872459e36149dd5d 9e94e1bc0bf44475902b03392b883c86 b2738c0b98fe42c7872459e36149dd5d--9e94e1bc0bf44475902b03392b883c86 e15fd60a25c64acd8f259369c4b6d07a b3b18a892c5b4cb8909542a1b334338f 3ae7022d660043f0bb0530bd09e40dd5--b3b18a892c5b4cb8909542a1b334338f d69a703fbd21402a90be3128561e8384 2 421c3002a7ee42408ee4fcfd22d8d3e1 t = -500.000000000000 b3b18a892c5b4cb8909542a1b334338f--421c3002a7ee42408ee4fcfd22d8d3e1 0b6a65189a9a453e811c7fee189a790a 421c3002a7ee42408ee4fcfd22d8d3e1--0b6a65189a9a453e811c7fee189a790a 69bd75d5dab24660ab0a344bede3fd67 X 0b6a65189a9a453e811c7fee189a790a--69bd75d5dab24660ab0a344bede3fd67 f3991da3296d47ad97dde6ff04aa92e9 t = -500.000000000000 69bd75d5dab24660ab0a344bede3fd67--f3991da3296d47ad97dde6ff04aa92e9 358390d4a5744e52b51fd9fcd6472625 X f3991da3296d47ad97dde6ff04aa92e9--358390d4a5744e52b51fd9fcd6472625 358390d4a5744e52b51fd9fcd6472625--e15fd60a25c64acd8f259369c4b6d07a df75b10b6bfd4502baebd375ebccc229 3892c7012ccb48d6980b66553549b796 X d69a703fbd21402a90be3128561e8384--3892c7012ccb48d6980b66553549b796 85d51f5e1adb419ab14c6b5bb0e31880 3892c7012ccb48d6980b66553549b796--85d51f5e1adb419ab14c6b5bb0e31880 f7f658ac61fe405cbe476e1697c7c512 X 85d51f5e1adb419ab14c6b5bb0e31880--f7f658ac61fe405cbe476e1697c7c512 fb48e9b642fb48a1a5f3e6ab5ee45e95 X f7f658ac61fe405cbe476e1697c7c512--fb48e9b642fb48a1a5f3e6ab5ee45e95 34c1776ab4254111bda205c88db68f12 fb48e9b642fb48a1a5f3e6ab5ee45e95--34c1776ab4254111bda205c88db68f12 04cd64f1b9214fce84bbc33757d7928a X 34c1776ab4254111bda205c88db68f12--04cd64f1b9214fce84bbc33757d7928a 04cd64f1b9214fce84bbc33757d7928a--df75b10b6bfd4502baebd375ebccc229

As we can see, to represent the same interaction between 0 and 1, the slices using the build Hamiltonian need to evolve for much longer, since the target interaction is not sufficiently represented in the building block Hamiltonian.

In the limit where that interaction is not present at all, the transform will not work:

try:
    transformed_ising = qd.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