mirror of https://github.com/Qiskit/qiskit-aer.git
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:
parent
f601733d43
commit
2150983ebd
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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, "
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:]]
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
# ---------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue