Skip to content

Commit e26970a

Browse files
gadialdoichanj
andauthored
Fix for save_expval truncation (#2265)
* Fix for save_expval truncation * Fixed a bug in pauli truncation and add relevant test * limit cuQuantum version * fix setup.py * add release note --------- Co-authored-by: U-AzureAD\JUNDOI <[email protected]>
1 parent 269c26f commit e26970a

File tree

8 files changed

+72
-10
lines changed

8 files changed

+72
-10
lines changed

.github/workflows/build.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ jobs:
7777
- name: Build wheels
7878
env:
7979
CIBW_BEFORE_ALL: "sed -i -e 's/^mirrorlist/#mirrorlist/' -e 's/^#baseurl/baseurl/' -e 's/mirror.centos.org/vault.centos.org/' /etc/yum.repos.d/*.repo && yum install -y yum-utils wget && wget -q https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda-repo-rhel7-11-8-local-11.8.0_520.61.05-1.x86_64.rpm && rpm -i cuda-repo-rhel7-11-8-local-11.8.0_520.61.05-1.x86_64.rpm && yum clean all && yum -y install cuda && yum -y install openblas-devel && yum-config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel7/x86_64/cuda-rhel7.repo && yum clean all"
80-
CIBW_BEFORE_BUILD : "pip cache purge && pip install nvidia-cuda-runtime-cu11 nvidia-cublas-cu11 nvidia-cusolver-cu11 nvidia-cusparse-cu11 cuquantum-cu11"
80+
CIBW_BEFORE_BUILD : "pip cache purge && pip install nvidia-cuda-runtime-cu11 nvidia-cublas-cu11 nvidia-cusolver-cu11 nvidia-cusparse-cu11 'cuquantum-cu11<24.11.0'"
8181
CIBW_SKIP: "*-manylinux_i686 pp* cp36* cp37* cp38* cp39* cp310* cp311* *musllinux*"
8282
CIBW_ENVIRONMENT: QISKIT_AER_PACKAGE_NAME=qiskit-aer-gpu-cu11 QISKIT_AER_CUDA_MAJOR=11 CMAKE_VERBOSE_MAKEFILE=true AER_THRUST_BACKEND=CUDA CUDACXX=/usr/local/cuda/bin/nvcc AER_CUDA_ARCH="7.0 7.2 7.5 8.0 8.6 8.7" AER_PYTHON_CUDA_ROOT=/opt/_internal AER_CIBUILD=true
8383
CIBW_REPAIR_WHEEL_COMMAND: 'auditwheel repair --exclude libcudart.so.11.0 --exclude libcustatevec.so.1 --exclude libcutensornet.so.2 --exclude libcutensor.so.1 --exclude libcutensorMg.so.1 --exclude libcusolver.so.11 --exclude libcusolverMg.so.11 --exclude libcusparse.so.11 --exclude libcublas.so.11 --exclude libcublasLt.so.11 -w {dest_dir} {wheel}'
@@ -110,7 +110,7 @@ jobs:
110110
- name: Build wheels
111111
env:
112112
CIBW_BEFORE_ALL: "sed -i -e 's/^mirrorlist/#mirrorlist/' -e 's/^#baseurl/baseurl/' -e 's/mirror.centos.org/vault.centos.org/' /etc/yum.repos.d/*.repo && yum install -y yum-utils wget && wget -q https://developer.download.nvidia.com/compute/cuda/12.5.1/local_installers/cuda-repo-rhel8-12-5-local-12.5.1_555.42.06-1.x86_64.rpm && rpm -i cuda-repo-rhel8-12-5-local-12.5.1_555.42.06-1.x86_64.rpm && yum clean all && yum -y install cuda-toolkit-12-5 && yum -y install openblas-devel && yum clean all"
113-
CIBW_BEFORE_BUILD : "pip cache purge && pip install nvidia-cuda-runtime-cu12 nvidia-nvjitlink-cu12 nvidia-cublas-cu12 nvidia-cusolver-cu12 nvidia-cusparse-cu12 cuquantum-cu12"
113+
CIBW_BEFORE_BUILD : "pip cache purge && pip install nvidia-cuda-runtime-cu12 nvidia-nvjitlink-cu12 nvidia-cublas-cu12 nvidia-cusolver-cu12 nvidia-cusparse-cu12 'cuquantum-cu12<24.11.0'"
114114
CIBW_SKIP: "*-manylinux_i686 pp* cp36* cp37* cp38* cp39* cp310* cp311* *musllinux*"
115115
CIBW_ENVIRONMENT: QISKIT_AER_PACKAGE_NAME=qiskit-aer-gpu QISKIT_AER_CUDA_MAJOR=12 CMAKE_VERBOSE_MAKEFILE=true AER_THRUST_BACKEND=CUDA CUDACXX=/usr/local/cuda/bin/nvcc AER_CUDA_ARCH="7.0 7.2 7.5 8.0 8.6 8.7 8.9 9.0" AER_PYTHON_CUDA_ROOT=/opt/_internal AER_CIBUILD=true
116116
CIBW_REPAIR_WHEEL_COMMAND: 'auditwheel repair --exclude libcudart.so.12 --exclude libcustatevec.so.1 --exclude libcutensornet.so.2 --exclude libcutensor.so.1 --exclude libcutensorMg.so.1 --exclude libcusolver.so.11 --exclude libcusolverMg.so.11 --exclude libcusolver.so.12 --exclude libcusolverMg.so.12 --exclude libcusparse.so.12 --exclude libcublas.so.12 --exclude libcublasLt.so.12 --exclude libnvJitLink.so.12 -w {dest_dir} {wheel}'

.github/workflows/deploy.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ jobs:
144144
- name: Build wheels
145145
env:
146146
CIBW_BEFORE_ALL: "sed -i -e 's/^mirrorlist/#mirrorlist/' -e 's/^#baseurl/baseurl/' -e 's/mirror.centos.org/vault.centos.org/' /etc/yum.repos.d/*.repo && yum install -y yum-utils wget && wget -q https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda-repo-rhel7-11-8-local-11.8.0_520.61.05-1.x86_64.rpm && rpm -i cuda-repo-rhel7-11-8-local-11.8.0_520.61.05-1.x86_64.rpm && yum clean all && yum -y install cuda && yum -y install openblas-devel && yum-config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel7/x86_64/cuda-rhel7.repo && yum clean all"
147-
CIBW_BEFORE_BUILD : "pip install nvidia-cuda-runtime-cu11 nvidia-cublas-cu11 nvidia-cusolver-cu11 nvidia-cusparse-cu11 cuquantum-cu11"
147+
CIBW_BEFORE_BUILD : "pip install nvidia-cuda-runtime-cu11 nvidia-cublas-cu11 nvidia-cusolver-cu11 nvidia-cusparse-cu11 'cuquantum-cu11<24.11.0'"
148148
CIBW_SKIP: "*-manylinux_i686 pp* cp36* cp37* *musllinux*"
149149
CIBW_TEST_SKIP: "*"
150150
CIBW_ENVIRONMENT: QISKIT_AER_PACKAGE_NAME=qiskit-aer-gpu-cu11 QISKIT_AER_CUDA_MAJOR=11 CMAKE_VERBOSE_MAKEFILE=true AER_THRUST_BACKEND=CUDA CUDACXX=/usr/local/cuda/bin/nvcc AER_CUDA_ARCH="7.0 7.2 7.5 8.0 8.6 8.7" AER_PYTHON_CUDA_ROOT=/opt/_internal AER_CIBUILD=true
@@ -188,7 +188,7 @@ jobs:
188188
- name: Build wheels
189189
env:
190190
CIBW_BEFORE_ALL: "sed -i -e 's/^mirrorlist/#mirrorlist/' -e 's/^#baseurl/baseurl/' -e 's/mirror.centos.org/vault.centos.org/' /etc/yum.repos.d/*.repo && yum install -y yum-utils wget && wget -q https://developer.download.nvidia.com/compute/cuda/12.5.1/local_installers/cuda-repo-rhel8-12-5-local-12.5.1_555.42.06-1.x86_64.rpm && rpm -i cuda-repo-rhel8-12-5-local-12.5.1_555.42.06-1.x86_64.rpm && yum clean all && yum -y install cuda-toolkit-12-5 && yum -y install openblas-devel && yum clean all"
191-
CIBW_BEFORE_BUILD : "pip install nvidia-cuda-runtime-cu12 nvidia-nvjitlink-cu12 nvidia-cublas-cu12 nvidia-cusolver-cu12 nvidia-cusparse-cu12 cuquantum-cu12"
191+
CIBW_BEFORE_BUILD : "pip install nvidia-cuda-runtime-cu12 nvidia-nvjitlink-cu12 nvidia-cublas-cu12 nvidia-cusolver-cu12 nvidia-cusparse-cu12 'cuquantum-cu12<24.11.0"
192192
CIBW_SKIP: "*-manylinux_i686 pp* cp36* cp37* *musllinux*"
193193
CIBW_TEST_SKIP: "*"
194194
CIBW_ENVIRONMENT: QISKIT_AER_PACKAGE_NAME=qiskit-aer-gpu QISKIT_AER_CUDA_MAJOR=12 CMAKE_VERBOSE_MAKEFILE=true AER_THRUST_BACKEND=CUDA CUDACXX=/usr/local/cuda/bin/nvcc AER_CUDA_ARCH="7.0 7.2 7.5 8.0 8.6 8.7 9.0" AER_PYTHON_CUDA_ROOT=/opt/_internal AER_CIBUILD=true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
fixes:
3+
- |
4+
This fix limit the version of cuQuantum temporary to solve link issue
5+
of GLIBC version containing in the latest cuQuantum.
6+
Make sure to unlimit the version when cuQuantum will be fixed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
fixes:
3+
- |
4+
Fixes a small bug preventing the expval truncation mechanism from activating correctly.

setup.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"nvidia-cublas-cu11>=11.11.3.6",
5757
"nvidia-cusolver-cu11>=11.4.1.48",
5858
"nvidia-cusparse-cu11>=11.7.5.86",
59-
"cuquantum-cu11>=23.3.0",
59+
"cuquantum-cu11>=23.3.0,<24.11.0",
6060
]
6161
classifiers_cuda = [
6262
"Environment :: GPU :: NVIDIA CUDA :: 11",
@@ -68,7 +68,7 @@
6868
"nvidia-cublas-cu12>=12.1.3.1",
6969
"nvidia-cusolver-cu12>=11.4.5.107",
7070
"nvidia-cusparse-cu12>=12.1.0.106",
71-
"cuquantum-cu12>=23.3.0",
71+
"cuquantum-cu12>=23.3.0,<24.11.0",
7272
]
7373
classifiers_cuda = [
7474
"Environment :: GPU :: NVIDIA CUDA :: 12",

src/framework/circuit.hpp

+11-4
Original file line numberDiff line numberDiff line change
@@ -420,13 +420,14 @@ void Circuit::reset_metadata() {
420420
void Circuit::add_op_metadata(const Op &op) {
421421
has_conditional |= op.conditional;
422422
opset_.insert(op);
423-
if (!qubitset_.empty() &&
424-
(op.type == OpType::save_expval || op.type == OpType::save_expval_var)) {
423+
if (op.type == OpType::save_expval || op.type == OpType::save_expval_var) {
425424
for (int_t j = 0; j < op.expval_params.size(); j++) {
426425
const std::string &pauli = std::get<0>(op.expval_params[j]);
427426
for (int_t i = 0; i < op.qubits.size(); i++) {
428427
// add qubit with non-I operator
429-
if (pauli[pauli.size() - 1 - i] != 'I') {
428+
// we also add one qubit if the qubitset is empty to prevent edge cases
429+
// with empty circuits
430+
if (qubitset_.empty() || pauli[pauli.size() - 1 - i] != 'I') {
430431
qubitset_.insert(op.qubits[i]);
431432
}
432433
}
@@ -682,17 +683,23 @@ void Circuit::set_params(bool truncation) {
682683
void Circuit::remap_qubits(Op &op) const {
683684
// truncate save_expval
684685
if (op.type == OpType::save_expval || op.type == OpType::save_expval_var) {
686+
// map each qubit to its location in the pauli strings
687+
std::unordered_map<uint_t, uint_t> ops_pauli_qubit_map;
688+
for (size_t i = 0; i < op.qubits.size(); ++i) {
689+
ops_pauli_qubit_map[op.qubits[i]] = op.qubits.size() - 1 - i;
690+
}
685691
int_t nparams = op.expval_params.size();
686692
for (int_t i = 0; i < nparams; i++) {
687693
std::string &pauli = std::get<0>(op.expval_params[i]);
688694
std::string new_pauli;
689695
new_pauli.resize(qubitmap_.size());
690696
for (auto q = qubitmap_.cbegin(); q != qubitmap_.cend(); q++) {
691697
new_pauli[qubitmap_.size() - 1 - q->second] =
692-
pauli[pauli.size() - 1 - q->first];
698+
pauli[ops_pauli_qubit_map[q->first]];
693699
}
694700
pauli = new_pauli;
695701
}
702+
op.qubits.resize(qubitmap_.size());
696703
for (int_t i = 0; i < qubitmap_.size(); i++) {
697704
op.qubits[i] = i;
698705
}

test/terra/backends/aer_simulator/test_save_expval.py

+18
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,21 @@ def test_save_expval_var_stabilizer_pauli_cache_blocking(self, method, device, p
271271
blocking_qubits=2,
272272
max_parallel_threads=1,
273273
)
274+
275+
@supported_methods(
276+
[
277+
"automatic",
278+
"stabilizer",
279+
"statevector",
280+
"density_matrix",
281+
"matrix_product_state",
282+
"tensor_network",
283+
],
284+
)
285+
def test_save_expval_truncation(self, method, device):
286+
"""Test save expval when qubits are not in use and are truncated"""
287+
circ = QuantumCircuit(3)
288+
circ.x(1)
289+
oper = qi.Pauli("ZZ")
290+
qubits = [1, 2] # qubit 0 will be truncated
291+
self._test_save_expval(circ, oper, qubits, False, method=method, device=device)

test/terra/primitives/test_estimator_v2.py

+27
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,33 @@ def test_truncate(self):
445445
result_5[0].data["evs"][0], result_2[0].data["evs"][0], delta=self._rtol
446446
)
447447

448+
def test_truncate_large_backends(self):
449+
"""Test truncation allows us to run few-qubit circuits on many-qubit backends"""
450+
N = 12
451+
qc = QuantumCircuit(N)
452+
453+
qc.x(range(N))
454+
qc.h(range(N))
455+
456+
for kk in range(N // 2, 0, -1):
457+
qc.ch(kk, kk - 1)
458+
for kk in range(N // 2, N - 1):
459+
qc.ch(kk, kk + 1)
460+
461+
op = SparsePauliOp("Z" * N)
462+
backend_127 = GenericBackendV2(num_qubits=127)
463+
pm = generate_preset_pass_manager(backend=backend_127, optimization_level=1)
464+
isa_circuit = pm.run(qc)
465+
mapped_observable = op.apply_layout(isa_circuit.layout)
466+
467+
ref_est = StatevectorEstimator()
468+
ref_result = ref_est.run(pubs=[(qc, op)]).result()
469+
470+
est = EstimatorV2()
471+
res = est.run(pubs=[(isa_circuit, mapped_observable)]).result()
472+
473+
self.assertAlmostEqual(ref_result[0].data.evs, res[0].data.evs)
474+
448475

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

0 commit comments

Comments
 (0)