Skip to content

Commit

Permalink
Fix for save_expval truncation
Browse files Browse the repository at this point in the history
  • Loading branch information
gadial committed Nov 24, 2024
1 parent 5994b77 commit d2b5de1
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
fixes:
- |
Fixes a small bug preventing the expval truncation mechanism from activating correctly.
8 changes: 5 additions & 3 deletions src/framework/circuit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,13 +420,14 @@ void Circuit::reset_metadata() {
void Circuit::add_op_metadata(const Op &op) {
has_conditional |= op.conditional;
opset_.insert(op);
if (!qubitset_.empty() &&
(op.type == OpType::save_expval || op.type == OpType::save_expval_var)) {
if (op.type == OpType::save_expval || op.type == OpType::save_expval_var) {
for (int_t j = 0; j < op.expval_params.size(); j++) {
const std::string &pauli = std::get<0>(op.expval_params[j]);
for (int_t i = 0; i < op.qubits.size(); i++) {
// add qubit with non-I operator
if (pauli[pauli.size() - 1 - i] != 'I') {
// we also add one qubit if the qubitset is empty to prevent edge cases
// with empty circuits
if (qubitset_.empty() || pauli[pauli.size() - 1 - i] != 'I') {
qubitset_.insert(op.qubits[i]);
}
}
Expand Down Expand Up @@ -693,6 +694,7 @@ void Circuit::remap_qubits(Op &op) const {
}
pauli = new_pauli;
}
op.qubits.resize(qubitmap_.size());
for (int_t i = 0; i < qubitmap_.size(); i++) {
op.qubits[i] = i;
}
Expand Down
27 changes: 27 additions & 0 deletions test/terra/primitives/test_estimator_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,33 @@ def test_truncate(self):
result_5[0].data["evs"][0], result_2[0].data["evs"][0], delta=self._rtol
)

def test_truncate_large_backends(self):
"""Test truncation allows us to run few-qubit circuits on many-qubit backends"""
N = 12
qc = QuantumCircuit(N)

qc.x(range(N))
qc.h(range(N))

for kk in range(N // 2, 0, -1):
qc.ch(kk, kk - 1)
for kk in range(N // 2, N - 1):
qc.ch(kk, kk + 1)

op = SparsePauliOp("Z" * N)
backend_127 = GenericBackendV2(num_qubits=127)
pm = generate_preset_pass_manager(backend=backend_127, optimization_level=1)
isa_circuit = pm.run(qc)
mapped_observable = op.apply_layout(isa_circuit.layout)

ref_est = StatevectorEstimator()
ref_result = ref_est.run(pubs=[(qc, op)]).result()

est = EstimatorV2()
res = est.run(pubs=[(isa_circuit, mapped_observable)]).result()

self.assertAlmostEqual(ref_result[0].data.evs, res[0].data.evs)


if __name__ == "__main__":
unittest.main()

0 comments on commit d2b5de1

Please sign in to comment.