Skip to content

Commit

Permalink
Fixes for dependency issues caused by 0.14 release (Qiskit#2094)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
doichanj committed Apr 25, 2024
1 parent 879e388 commit 0abacdf
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 21 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 16 additions & 4 deletions qiskit_aer/backends/aer_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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]
Expand All @@ -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",
Expand Down Expand Up @@ -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}"
Expand All @@ -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
Expand All @@ -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)
4 changes: 3 additions & 1 deletion qiskit_aer/backends/aer_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

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
Expand All @@ -33,6 +34,7 @@

# 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__)

Expand Down Expand Up @@ -856,7 +858,7 @@ def from_backend(cls, backend, **options):
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, "
Expand Down
10 changes: 9 additions & 1 deletion qiskit_aer/backends/aerbackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,11 @@ def target(self):
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()
Expand Down Expand Up @@ -445,7 +450,10 @@ def _execute_circuits_job(
# 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
Expand Down
8 changes: 6 additions & 2 deletions qiskit_aer/primitives/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@
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
1 change: 1 addition & 0 deletions qiskit_aer/primitives/estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ def _transpile_circuits(self, circuits):
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:]]
Expand Down
15 changes: 10 additions & 5 deletions qiskit_aer/primitives/sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ def _preprocess_circuit(circuit: QuantumCircuit):
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
Expand All @@ -191,11 +200,7 @@ def _transpile(self, circuit_indices: Sequence[int], is_shots_none: bool):
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

Expand Down
Original file line number Diff line number Diff line change
@@ -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)
4 changes: 2 additions & 2 deletions src/simulators/matrix_product_state/matrix_product_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down
5 changes: 1 addition & 4 deletions src/simulators/sample_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/simulators/stabilizer/stabilizer_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
19 changes: 19 additions & 0 deletions test/terra/backends/aer_simulator/test_measure.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
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
Expand Down Expand Up @@ -265,6 +266,24 @@ def test_measure_stablizer_64bit(self, method, device):

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
# ---------------------------------------------------------------------
Expand Down

0 comments on commit 0abacdf

Please sign in to comment.