Fixes for dependency issues caused by 0.14 release (#2094)

* Fixes for dependency issues

* lint

* lint

* lint

* fix release note

* fix sampler

* fix sampler

* fix sampler

* fix sampler

* remove skip cp38

* hide primitives V2 for qiskit < 1.0

* lint

* add test case for sampling measure for large stabilizer circuit

* reduce warning

* replace test case for large stabilizer with GHZ circuit

* format

* format

* convert basis_gates from list to set

* fix assemble_circuits
This commit is contained in:
Jun Doi 2024-04-23 14:36:24 +09:00 committed by GitHub
parent f601733d43
commit 2150983ebd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 80 additions and 21 deletions

View File

@ -12,7 +12,7 @@ build-backend = "setuptools.build_meta"
[tool.cibuildwheel]
manylinux-x86_64-image = "manylinux2014"
manylinux-i686-image = "manylinux2014"
skip = "pp* cp36* cp37* cp38* *musllinux*"
skip = "pp* cp36* cp37* *musllinux*"
test-skip = "cp3*-win32 cp3*-manylinux_i686"
test-command = "python {project}/tools/verify_wheels.py"
# We need to use pre-built versions of Numpy and Scipy in the tests; they have a

View File

@ -605,7 +605,7 @@ def generate_aer_config(
return config
def assemble_circuit(circuit: QuantumCircuit):
def assemble_circuit(circuit: QuantumCircuit, basis_gates=None):
"""assemble circuit object mapped to AER::Circuit"""
num_qubits = circuit.num_qubits
@ -687,6 +687,7 @@ def assemble_circuit(circuit: QuantumCircuit):
is_conditional,
conditional_reg,
conditional_expr,
basis_gates,
)
index_map.append(num_of_aer_ops - 1)
@ -792,6 +793,7 @@ def _assemble_op(
is_conditional,
conditional_reg,
conditional_expr,
basis_gates,
):
operation = inst.operation
qubits = [qubit_indices[qubit] for qubit in inst.qubits]
@ -812,7 +814,7 @@ def _assemble_op(
num_of_aer_ops = 1
# fmt: off
if name in {
if basis_gates is None and name in {
"ccx", "ccz", "cp", "cswap", "csx", "cx", "cy", "cz", "delay", "ecr", "h",
"id", "mcp", "mcphase", "mcr", "mcrx", "mcry", "mcrz", "mcswap", "mcsx",
"mcu", "mcu1", "mcu2", "mcu3", "mcx", "mcx_gray", "mcy", "mcz", "p", "r",
@ -912,6 +914,9 @@ def _assemble_op(
aer_circ.mark(qubits, params)
elif name == "qerror_loc":
aer_circ.set_qerror_loc(qubits, label if label else name, conditional_reg, aer_cond_expr)
elif basis_gates is not None and name in basis_gates:
aer_circ.gate(name, qubits, params, [], conditional_reg, aer_cond_expr,
label if label else name)
elif name in ("for_loop", "while_loop", "if_else"):
raise AerError(
"control-flow instructions must be converted " f"to jump and mark instructions: {name}"
@ -923,11 +928,12 @@ def _assemble_op(
return num_of_aer_ops
def assemble_circuits(circuits: List[QuantumCircuit]) -> List[AerCircuit]:
def assemble_circuits(circuits: List[QuantumCircuit], basis_gates: list = None) -> List[AerCircuit]:
"""converts a list of Qiskit circuits into circuits mapped AER::Circuit
Args:
circuits: circuit(s) to be converted
basis_gates (list): supported gates to be converted
Returns:
a list of circuits to be run on the Aer backends and
@ -947,5 +953,11 @@ def assemble_circuits(circuits: List[QuantumCircuit]) -> List[AerCircuit]:
# Generate AerCircuit from the input circuit
aer_qc_list, idx_maps = assemble_circuits(circuits=[qc])
"""
aer_circuits, idx_maps = zip(*[assemble_circuit(circuit) for circuit in circuits])
if basis_gates is not None:
basis_gates_set = set(basis_gates)
aer_circuits, idx_maps = zip(
*[assemble_circuit(circuit, basis_gates_set) for circuit in circuits]
)
else:
aer_circuits, idx_maps = zip(*[assemble_circuit(circuit) for circuit in circuits])
return list(aer_circuits), list(idx_maps)

View File

@ -15,6 +15,7 @@ Aer qasm simulator backend.
import copy
import logging
from qiskit.providers import convert_to_target
from qiskit.providers.options import Options
from qiskit.providers.models import QasmBackendConfiguration
from qiskit.providers.backend import BackendV2, BackendV1
@ -33,6 +34,7 @@ from .backend_utils import (
# pylint: disable=import-error, no-name-in-module, abstract-method
from .controller_wrappers import aer_controller_execute
from .name_mapping import NAME_MAPPING
logger = logging.getLogger(__name__)
@ -856,7 +858,7 @@ class AerSimulator(AerBackend):
name = configuration.backend_name
configuration.backend_name = f"aer_simulator_from({name})"
target = None
target = convert_to_target(configuration, properties, None, NAME_MAPPING)
else:
raise TypeError(
"The backend argument requires a BackendV2 or BackendV1 object, "

View File

@ -350,6 +350,11 @@ class AerBackend(Backend, ABC):
tgt._coupling_graph = self._coupling_map.graph.copy()
return tgt
def set_max_qubits(self, max_qubits):
"""Set maximun number of qubits to be used for this backend."""
if self._target is not None:
self._configuration.n_qubits = max_qubits
def clear_options(self):
"""Reset the simulator options to default values."""
self._options = self._default_options()
@ -445,7 +450,10 @@ class AerBackend(Backend, ABC):
# Compile circuits
circuits, noise_model = self._compile(circuits, **run_options)
aer_circuits, idx_maps = assemble_circuits(circuits)
if self._target is not None:
aer_circuits, idx_maps = assemble_circuits(circuits, self.configuration().basis_gates)
else:
aer_circuits, idx_maps = assemble_circuits(circuits)
if parameter_binds:
run_options["parameterizations"] = self._convert_binds(
circuits, parameter_binds, idx_maps

View File

@ -31,7 +31,11 @@ Classes
Estimator
"""
import qiskit
from .estimator import Estimator
from .estimator_v2 import EstimatorV2
from .sampler import Sampler
from .sampler_v2 import SamplerV2
if not qiskit.__version__.startswith("0."):
from .estimator_v2 import EstimatorV2
from .sampler_v2 import SamplerV2

View File

@ -532,6 +532,7 @@ class Estimator(BaseEstimator):
circuit = self._circuits[i].copy()
circuit.measure_all()
num_qubits = circuit.num_qubits
self._backend.set_max_qubits(num_qubits)
circuit = self._transpile(circuit)
bit_map = {bit: index for index, bit in enumerate(circuit.qubits)}
layout = [bit_map[qr[0]] for _, qr, _ in circuit[-num_qubits:]]

View File

@ -182,6 +182,15 @@ class Sampler(BaseSampler):
circuit.save_probabilities_dict(qargs)
return circuit
def _transpile_circuit(self, circuit):
self._backend.set_max_qubits(circuit.num_qubits)
transpiled = transpile(
circuit,
self._backend,
**self._transpile_options,
)
return transpiled
def _transpile(self, circuit_indices: Sequence[int], is_shots_none: bool):
to_handle = [
i for i in set(circuit_indices) if (i, is_shots_none) not in self._transpiled_circuits
@ -191,11 +200,7 @@ class Sampler(BaseSampler):
if is_shots_none:
circuits = (self._preprocess_circuit(circ) for circ in circuits)
if not self._skip_transpilation:
circuits = transpile(
list(circuits),
self._backend,
**self._transpile_options,
)
circuits = (self._transpile_circuit(circ) for circ in circuits)
for i, circuit in zip(to_handle, circuits):
self._transpiled_circuits[(i, is_shots_none)] = circuit

View File

@ -0,0 +1,11 @@
---
fixes:
- |
Fixes for dependency issues caused by release 0.14.
Fix for issue in samplingVector.allocate() when > 63 qubits
Use basis_gates in AerCompiler when AerBackend is made by from_backend
Setting number of qubits before transpile for Primitives V1 (issue #2084)

View File

@ -797,7 +797,7 @@ State::sample_measure_using_apply_measure(const reg_t &qubits, uint_t shots,
for (int_t i = 0; i < static_cast<int_t>(shots); i++) {
temp.initialize(qreg_);
auto single_result = temp.apply_measure_internal(qubits, rnds_list[i]);
all_samples[i] = single_result;
all_samples[i].from_vector(single_result);
}
}
return all_samples;
@ -811,7 +811,7 @@ std::vector<SampleVector> State::sample_measure_all(uint_t shots,
#pragma omp parallel for if (getenv("PRL_PROB_MEAS"))
for (int_t i = 0; i < static_cast<int_t>(shots); i++) {
auto single_result = qreg_.sample_measure(shots, rng);
all_samples[i] = single_result;
all_samples[i].from_vector(single_result);
}
return all_samples;
}

View File

@ -123,9 +123,7 @@ void SampleVector::allocate(uint_t n, uint_t base) {
elem_mask_ = (1ull << (elem_shift_bits_ + 1)) - 1;
vec_mask_ = (1ull << vec_shift_bits_) - 1;
uint_t size = n >> vec_shift_bits_;
if (size == 0)
size = 1;
uint_t size = (n + (REG_SIZE >> elem_shift_bits_) - 1) >> vec_shift_bits_;
bits_.resize(size, 0ull);
size_ = n;
}
@ -185,7 +183,6 @@ void SampleVector::from_vector_with_map(const reg_t &src, const reg_t &map,
uint_t pos = 0;
uint_t n = REG_SIZE >> elem_shift_bits_;
for (uint_t i = 0; i < bits_.size(); i++) {
uint_t n = REG_SIZE;
uint_t val = 0;
if (n > size_ - pos)
n = size_ - pos;

View File

@ -519,7 +519,7 @@ std::vector<SampleVector> State::sample_measure(const reg_t &qubits,
auto qreg_cache = BaseState::qreg_;
std::vector<SampleVector> samples(shots);
for (int_t ishot = 0; ishot < shots; ishot++) {
samples[ishot] = apply_measure_and_update(qubits, rng);
samples[ishot].from_vector(apply_measure_and_update(qubits, rng));
BaseState::qreg_ = qreg_cache; // restore pre-measurement data from cache
}
return samples;

View File

@ -17,6 +17,7 @@ from ddt import ddt
from test.terra.reference import ref_measure
from qiskit import QuantumCircuit
from qiskit import transpile
import qiskit.quantum_info as qi
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel
from qiskit_aer.noise.errors import ReadoutError, depolarizing_error
@ -265,6 +266,24 @@ class TestMeasure(SimulatorTestCase):
self.assertDictAlmostEqual(output, targets, delta=delta * shots)
@supported_methods(["stabilizer"], [65, 127, 433])
def test_measure_sampling_large_ghz_stabilizer(self, method, device, num_qubits):
"""Test sampling measure for large stabilizer circuit"""
shots = 1000
delta = 0.05
qc = QuantumCircuit(num_qubits)
qc.h(0)
for q in range(1, num_qubits):
qc.cx(q - 1, q)
qc.measure_all()
backend = self.backend(method=method)
result = backend.run(qc, shots=shots).result()
counts = result.get_counts()
targets = {}
targets["0" * num_qubits] = shots / 2
targets["1" * num_qubits] = shots / 2
self.assertDictAlmostEqual(counts, targets, delta=delta * shots)
# ---------------------------------------------------------------------
# Test MPS algorithms for measure
# ---------------------------------------------------------------------