Skip to content

Implement a Batching Logic for Commuting Terms in a Hamiltonian #32

@Bmete7

Description

@Bmete7

In the current logic (v1.2.1), the tool support expectation values of Hamiltonians, as follows:

import pennylane as qml
from pennylane import numpy as np
from mqss.pennylane_adapter.device import MQSSPennylaneDevice
dev_hamiltonian = MQSSPennylaneDevice(wires=2, token='<MQSS_TOKEN>', backends='<MQSS_BACKENDS>')

@qml.qnode(dev_hamiltonian, shots = 1024)
def quantum_function_hamiltonian_expval(
    x: float, y: float, H: qml.Hamiltonian
) -> float:
    qml.RZ(x, wires=0)
    qml.CNOT(wires=[0, 1])
    qml.RY(y, wires=1)

    return qml.expval(H)

J = 0.5  # Interaction strength
h = 0.2  # Transverse field strength
coeffs = [-J, -h, -h]  # TFIM with 2 sites
obs = [
    qml.PauliZ(0) @ qml.PauliZ(1),
    qml.PauliX(0),
    qml.PauliX(1),
]

hamiltonian = qml.Hamiltonian(coeffs, obs)
result = quantum_function_hamiltonian_expval(*params, hamiltonian)

However, job submission logic creates and submits M circuits, where M is the number of terms inside the Hamiltonian (in the above case, three: qml.PauliZ(0) @ qml.PauliZ(1), qml.PauliX(0) and qml.PauliX(1)), see here:

if is_hamiltonian:
if observable is None:
measured_qubits = list(measurement.wires.labels)
else:
base_observable = getattr(observable, "base", observable)
if hasattr(base_observable, "operands"):
obs_terms = base_observable.operands
else:
obs_terms = [base_observable]
measured_qubits = [op.wires.labels for op in obs_terms]
else:
if observable is None:
measured_qubits = list(measurement.wires.labels)
else:
if isinstance(observable, (qml.PauliX, qml.PauliY, qml.PauliZ)):
measured_qubits = [tuple([observable.wires.labels[0]])]
elif hasattr(observable, "operands"):
measured_qubits = [observable.wires.labels]
else:
measured_qubits = [observable.wires.labels[0]]
if self.batch_circuits:
num_qubits = len(circuits[0].wires)
else:
num_qubits = len(circuits.wires)
expectation = self.get_expectation_value(
count, measured_qubits[cdx], num_qubits, shots
)
if is_hamiltonian:
final_expectation += expectation * observable.coeffs[cdx]
else:
final_expectation += expectation
return [final_expectation]

This is not ideal, as the commuting terms should be able to grouped together and submitted once, and the expectation values can be calculated in the post-processing.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requesthelp wantedExtra attention is neededusabilityIncreasing the utility
No fields configured for Feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions