Skip to content

Commit 22863a1

Browse files
[Bug Fix] Higher order Trotter product for CDF Hamiltonian (#1354)
Fixes the higher order Trotter product for CDF Hamiltonian demo. [sc-88945]
1 parent 3707e93 commit 22863a1

2 files changed

Lines changed: 20 additions & 20 deletions

demonstrations/tutorial_how_to_build_compressed_double_factorized_hamiltonians.metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
}
77
],
88
"dateOfPublication": "2025-03-05T09:00:00+00:00",
9-
"dateOfLastModification": "2025-03-05T09:00:00+00:00",
9+
"dateOfLastModification": "2025-04-28T09:00:00+00:00",
1010
"categories": [
1111
"Quantum Chemistry",
1212
"Algorithms",

demonstrations/tutorial_how_to_build_compressed_double_factorized_hamiltonians.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
# the following double-factorized form in terms of orthonormal core tensors :math:`Z^{(t)}`
7676
# and symmetric leaf tensors :math:`U^{(t)}` [#cdf2]_:
7777
#
78-
# .. math:: V_{pqrs} \approx \sum_t^T \sum_{ij} U_{pi}^{(t)} U_{pj}^{(t)} Z_{ij}^{(t)} U_{qk}^{(t)} U_{ql}^{(t)},
78+
# .. math:: V_{pqrs} \approx \sum_t^T \sum_{ij} U_{pi}^{(t)} U_{qi}^{(t)} Z_{ij}^{(t)} U_{rj}^{(t)} U_{sj}^{(t)},
7979
#
8080
# where :math:`Z_{ij}^{(t)} = W_i^{(t)} W_j^{(t)}`. This decomposition is referred
8181
# to as the *explicit* double factorization (XDF) and decreases the number of terms
@@ -234,7 +234,7 @@
234234
def leaf_unitary_rotation(leaf, wires):
235235
"""Applies the basis rotation transformation corresponding to the leaf tensor."""
236236
basis_mat = qml.math.kron(leaf, qml.math.eye(2)) # account for spin
237-
qml.BasisRotation(unitary_matrix=basis_mat, wires=wires)
237+
return qml.BasisRotation(unitary_matrix=basis_mat, wires=wires)
238238

239239
######################################################################
240240
# Similarly, the unitary transformation for the core tensors can be applied efficiently
@@ -248,20 +248,22 @@ def leaf_unitary_rotation(leaf, wires):
248248

249249
def core_unitary_rotation(core, body_type, wires):
250250
"""Applies the unitary transformation corresponding to the core tensor."""
251+
ops = []
251252
if body_type == "one_body": # implements one-body term
252253
for wire, cval in enumerate(qml.math.diag(core)):
253254
for sigma in [0, 1]:
254-
qml.RZ(-cval, wires=2 * wire + sigma)
255-
qml.GlobalPhase(qml.math.sum(core), wires=wires)
255+
ops.append(qml.RZ(-cval, wires=2 * wire + sigma))
256+
ops.append(qml.GlobalPhase(qml.math.sum(core), wires=wires))
256257

257258
if body_type == "two_body": # implements two-body term
258259
for odx1, odx2 in it.product(range(len(wires) // 2), repeat=2):
259-
cval = core[odx1, odx2]
260+
cval = core[odx1, odx2] / 4.0
260261
for sigma, tau in it.product(range(2), repeat=2):
261262
if odx1 != odx2 or sigma != tau:
262-
qml.IsingZZ(cval / 4.0, wires=[2*odx1+sigma, 2*odx2+tau])
263-
gphase = 0.5 * qml.math.sum(core) + 0.25 * qml.math.trace(core)
264-
qml.GlobalPhase(-gphase, wires=wires)
263+
ops.append(qml.IsingZZ(cval, wires=[2*odx1+sigma, 2*odx2+tau]))
264+
gphase = 0.5 * qml.math.sum(core) - 0.25 * qml.math.trace(core)
265+
ops.append(qml.GlobalPhase(-gphase, wires=wires))
266+
return ops
265267

266268
######################################################################
267269
# We can now use these functions to approximate the evolution operator :math:`e^{-iHt}` for
@@ -292,19 +294,16 @@ def CDFTrotterStep(time, cdf_ham, wires):
292294
"""
293295
cores, leaves = cdf_ham["core_tensors"], cdf_ham["leaf_tensors"]
294296
for bidx, (core, leaf) in enumerate(zip(cores, leaves)):
295-
# apply the basis rotation for leaf tensor
296-
leaf_unitary_rotation(leaf, wires)
297-
298-
# apply the rotation for core tensor scaled by the time-step
299297
# Note: only the first term is one-body, others are two-body
300298
body_type = "two_body" if bidx else "one_body"
301-
core_unitary_rotation(time * core, body_type, wires)
302-
303-
# revert the change-of-basis for leaf tensor
304-
leaf_unitary_rotation(leaf.conjugate().T, wires)
305-
306-
# apply the global phase gate based on the nuclear core energy
307-
qml.GlobalPhase(cdf_ham["nuc_constant"] * time, wires=wires)
299+
qml.prod(
300+
# revert the change-of-basis for leaf tensor
301+
leaf_unitary_rotation(leaf.conjugate().T, wires),
302+
# apply the rotation for core tensor scaled by the time-step
303+
*core_unitary_rotation(time * core, body_type, wires),
304+
# apply the basis rotation for leaf tensor
305+
leaf_unitary_rotation(leaf, wires),
306+
) # Note: prod applies operations in the reverse order (right-to-left).
308307

309308
######################################################################
310309
# We now use this function to simulate the evolution of the :math:`H_4` Hamiltonian
@@ -320,6 +319,7 @@ def CDFTrotterStep(time, cdf_ham, wires):
320319
def cdf_circuit(n_steps, order):
321320
qml.BasisState(hf_state, wires=circ_wires)
322321
qml.trotterize(CDFTrotterStep, n_steps, order)(time, cdf_hamiltonian, circ_wires)
322+
qml.GlobalPhase(cdf_hamiltonian["nuc_constant"], wires=circ_wires)
323323
return qml.state()
324324

325325
circuit_state = cdf_circuit(n_steps=10, order=2)

0 commit comments

Comments
 (0)