Skip to content

Commit

Permalink
Merge pull request #1626 from hhorii/release_0.11.1
Browse files Browse the repository at this point in the history
Release 0.11.1
  • Loading branch information
mtreinish authored Oct 25, 2022
2 parents b7c4a32 + 8c4b6c1 commit 9c4e69d
Show file tree
Hide file tree
Showing 23 changed files with 671 additions and 84 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ jobs:
- name: Build wheels
env:
CIBW_BEFORE_ALL: "yum install -y yum-utils wget && wget -q https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel6-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm && rpm -i cuda-repo-rhel6-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm && yum clean all && yum -y install cuda-10-1 openblas-devel"
CIBW_MANYLINUX_X86_64_IMAGE: quay.io/pypa/manylinux2010_x86_64:latest
CIBW_SKIP: "*-manylinux_i686 cp310* pp* cp36* *musllinux*"
CIBW_TEST_SKIP: "cp*"
CIBW_ENVIRONMENT: QISKIT_AER_PACKAGE_NAME=qiskit-aer-gpu AER_THRUST_BACKEND=CUDA CUDACXX=/usr/local/cuda/bin/nvcc
run: |
python -m cibuildwheel --output-dir wheelhouse
Expand Down
8 changes: 7 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ if(AER_THRUST_BACKEND STREQUAL "CUDA")
set(CUDA_FOUND TRUE)
#include(FindCUDA) # for cuda_select_nvcc_arch_flags, CUDA_FOUND
include(FindCUDA/select_compute_arch)
enable_language(CUDA)
else()
# idiosyncrasy of CMake that it still creates a reference to this
set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION "")
Expand Down Expand Up @@ -252,6 +251,12 @@ if(AER_THRUST_SUPPORTED)
cuda_select_nvcc_arch_flags(AER_CUDA_ARCH_FLAGS ${AER_CUDA_ARCH})

string(REPLACE ";" " " AER_CUDA_ARCH_FLAGS_EXPAND "${AER_CUDA_ARCH_FLAGS}")

string(REGEX MATCHALL "sm_[0-9][0-9]" CUDA_SM "${AER_CUDA_ARCH_FLAGS}")
string(REPLACE "sm_" "" AER_CUDA_ARCHITECTURES "${CUDA_SM}")
set(CMAKE_CUDA_ARCHITECTURES "${AER_CUDA_ARCHITECTURES}")
message(STATUS "CMAKE_CUDA_ARCHITECTURES = ${CMAKE_CUDA_ARCHITECTURES}")

set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} ${AER_CUDA_ARCH_FLAGS_EXPAND} -DAER_THRUST_CUDA -I${AER_SIMULATOR_CPP_SRC_DIR} -isystem ${AER_SIMULATOR_CPP_SRC_DIR}/third-party/headers -use_fast_math --expt-extended-lambda")

set(AER_COMPILER_DEFINITIONS ${AER_COMPILER_DEFINITIONS} THRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_CUDA)
Expand Down Expand Up @@ -362,6 +367,7 @@ else() # Standalone build
LINK_FLAGS ${AER_LINKER_FLAGS}
RUNTIME_OUTPUT_DIRECTORY_DEBUG Debug
RUNTIME_OUTPUT_DIRECTORY_RELEASE Release)
enable_language(CUDA)
endfunction()

function(build_cpu target src_file is_exec)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Qiskit is made up of elements that each work together to enable quantum computin
We encourage installing Qiskit via the pip tool (a python package manager). The following command installs the core Qiskit components, including Aer.

```bash
pip install qiskit
pip install qiskit qiskit-aer
```

Pip will handle all dependencies automatically for us and you will always install the latest (and well-tested) version.
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
# The short X.Y version
version = ''
# The full version, including alpha/beta/rc tags
release = '0.11.0'
release = '0.11.1'

# -- General configuration ---------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion qiskit_aer/VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.11.0
0.11.1
1 change: 1 addition & 0 deletions qiskit_aer/backends/wrappers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ if(AER_THRUST_BACKEND STREQUAL "CUDA")
string(STRIP ${AER_COMPILER_FLAGS} AER_COMPILER_FLAGS_STRIPPED)
nvcc_add_compiler_options(${AER_COMPILER_FLAGS_STRIPPED} AER_COMPILER_FLAGS_OUT)
set_target_properties(controller_wrappers PROPERTIES COMPILE_FLAGS "${AER_COMPILER_FLAGS_OUT}")
enable_language(CUDA)
else()
if(DEFINED SIMD_SOURCE_FILE)
string(REPLACE ";" " " SIMD_FLAGS "${SIMD_FLAGS_LIST}")
Expand Down
11 changes: 7 additions & 4 deletions qiskit_aer/noise/passes/local_noise_pass.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def func(

def __init__(
self,
func: Callable[[Instruction, Sequence[int]], InstructionLike],
func: Callable[[Instruction, Sequence[int]], Optional[InstructionLike]],
op_types: Optional[Union[type, Iterable[type]]] = None,
method: str = 'append'
):
Expand Down Expand Up @@ -118,7 +118,7 @@ def run(self, dag: DAGCircuit) -> DAGCircuit:

# If appending re-apply original op node first
if self._method == "append":
new_dag.apply_operation_back(node.op, qargs=node.qargs)
new_dag.apply_operation_back(node.op, qargs=node.qargs, cargs=node.cargs)

# If the new op is not a QuantumCircuit or Instruction, attempt
# to conver to an Instruction
Expand All @@ -130,6 +130,9 @@ def run(self, dag: DAGCircuit) -> DAGCircuit:
"Function must return an object implementing 'to_instruction' method."
) from att_err

if new_op.num_clbits > 0:
raise TranspilerError("Noise must be an instruction without clbits.")

# Validate the instruction matches the number of qubits and clbits of the node
if new_op.num_qubits != len(node.qargs):
raise TranspilerError(
Expand All @@ -141,10 +144,10 @@ def run(self, dag: DAGCircuit) -> DAGCircuit:
if isinstance(new_op, QuantumCircuit):
# If the new op is a quantum circuit, compose its DAG with the new dag
# so that it is unrolled rather than added as an opaque instruction
new_dag.compose(circuit_to_dag(new_op), qubits=node.qargs, clbits=node.cargs)
new_dag.compose(circuit_to_dag(new_op), qubits=node.qargs) # never touch clbits
else:
# Otherwise append the instruction returned by the function
new_dag.apply_operation_back(new_op, qargs=node.qargs, cargs=node.cargs)
new_dag.apply_operation_back(new_op, qargs=node.qargs) # never touch cargs

# If prepending reapply original op node last
if self._method == "prepend":
Expand Down
60 changes: 51 additions & 9 deletions qiskit_aer/primitives/estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@
from qiskit.opflow import PauliSumOp
from qiskit.primitives import BaseEstimator, EstimatorResult
from qiskit.primitives.utils import init_circuit, init_observable
from qiskit.providers import Options
from qiskit.quantum_info import Pauli
from qiskit.quantum_info.operators.base_operator import BaseOperator

from qiskit.providers import Options

from .. import AerSimulator


Expand Down Expand Up @@ -60,11 +59,12 @@ class Estimator(BaseEstimator):

def __init__(
self,
circuits: QuantumCircuit | Iterable[QuantumCircuit],
observables: BaseOperator | PauliSumOp | Iterable[BaseOperator | PauliSumOp],
circuits: QuantumCircuit | Iterable[QuantumCircuit] | None = None,
observables: BaseOperator | PauliSumOp | Iterable[BaseOperator | PauliSumOp] | None = None,
parameters: Iterable[Iterable[Parameter]] | None = None,
backend_options: dict | None = None,
transpile_options: dict | None = None,
run_options: dict | None = None,
approximation: bool = False,
skip_transpilation: bool = False,
):
Expand All @@ -78,24 +78,28 @@ def __init__(
``circuits[i]``.
backend_options: Options passed to AerSimulator.
transpile_options: Options passed to transpile.
run_options: Options passed to run.
approximation: If True, it calculates expectation values with normal distribution
approximation.
skip_transpilation: If True, transpilation is skipped.
"""
if isinstance(circuits, QuantumCircuit):
circuits = (circuits,)
circuits = tuple(init_circuit(circuit) for circuit in circuits)
if circuits is not None:
circuits = tuple(init_circuit(circuit) for circuit in circuits)

if isinstance(observables, (PauliSumOp, BaseOperator)):
observables = (observables,)
observables = tuple(
init_observable(observable).simplify(atol=0) for observable in observables
)
if observables is not None:
observables = tuple(
init_observable(observable).simplify(atol=0) for observable in observables
)

super().__init__(
circuits=circuits,
observables=observables,
parameters=parameters,
options=run_options,
)
self._is_closed = False
backend_options = {} if backend_options is None else backend_options
Expand Down Expand Up @@ -134,6 +138,44 @@ def _call(
else:
return self._compute(circuits, observables, parameter_values, run_options)

# This method will be used after Terra 0.22.
def _run(
self,
circuits: Sequence[QuantumCircuit],
observables: Sequence[BaseOperator | PauliSumOp],
parameter_values: Sequence[Sequence[float]],
**run_options,
) -> PrimitiveJob:
# pylint: disable=no-name-in-module, import-error, import-outside-toplevel, no-member
from qiskit.primitives.primitive_job import PrimitiveJob
from qiskit.primitives.utils import _circuit_key, _observable_key

circuit_indices: list = []
for circuit in circuits:
index = self._circuit_ids.get(_circuit_key(circuit))
if index is not None:
circuit_indices.append(index)
else:
circuit_indices.append(len(self._circuits))
self._circuit_ids[_circuit_key(circuit)] = len(self._circuits)
self._circuits.append(circuit)
self._parameters.append(circuit.parameters)
observable_indices: list = []
for observable in observables:
observable = init_observable(observable)
index = self._observable_ids.get(_observable_key(observable))
if index is not None:
observable_indices.append(index)
else:
observable_indices.append(len(self._observables))
self._observable_ids[_observable_key(observable)] = len(self._observables)
self._observables.append(observable)
job = PrimitiveJob(
self._call, circuit_indices, observable_indices, parameter_values, **run_options
)
job.submit()
return job

def close(self):
self._is_closed = True

Expand Down Expand Up @@ -294,7 +336,7 @@ def _compute_with_approximation(

def _validate_parameter_length(self, parameter, circuit_index):
if len(parameter) != len(self._parameters[circuit_index]):
raise QiskitError(
raise ValueError(
f"The number of values ({len(parameter)}) does not match "
f"the number of parameters ({len(self._parameters[circuit_index])})."
)
Expand Down
79 changes: 64 additions & 15 deletions qiskit_aer/primitives/sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ class Sampler(BaseSampler):

def __init__(
self,
circuits: QuantumCircuit | Iterable[QuantumCircuit],
circuits: QuantumCircuit | Iterable[QuantumCircuit] | None = None,
parameters: Iterable[Iterable[Parameter]] | None = None,
backend_options: dict | None = None,
transpile_options: dict | None = None,
run_options: dict | None = None,
skip_transpilation: bool = False,
):
"""
Expand All @@ -65,15 +66,18 @@ def __init__(
Defaults to ``[circ.parameters for circ in circuits]``.
backend_options: Options passed to AerSimulator.
transpile_options: Options passed to transpile.
run_options: Options passed to run.
skip_transpilation: if True, transpilation is skipped.
"""
if isinstance(circuits, QuantumCircuit):
circuits = (circuits,)
circuits = tuple(init_circuit(circuit) for circuit in circuits)
if circuits is not None:
circuits = tuple(init_circuit(circuit) for circuit in circuits)

super().__init__(
circuits=circuits,
parameters=parameters,
options=run_options,
)
self._is_closed = False
self._backend = AerSimulator()
Expand All @@ -82,6 +86,8 @@ def __init__(
self._transpile_options = {} if transpile_options is None else transpile_options
self._skip_transpilation = skip_transpilation

self._transpiled_circuits = {}

def _call(
self,
circuits: Sequence[int],
Expand All @@ -95,7 +101,9 @@ def _call(
if seed is not None:
run_options.setdefault("seed_simulator", seed)

# Prepare circuits and parameter_binds
is_shots_none = "shots" in run_options and run_options["shots"] is None
self._transpile(circuits, is_shots_none)

experiments = []
parameter_binds = []
for i, value in zip(circuits, parameter_values):
Expand All @@ -104,17 +112,9 @@ def _call(
f"The number of values ({len(value)}) does not match "
f"the number of parameters ({len(self._parameters[i])})."
)
parameter_binds.append({k: [v] for k, v in zip(self._parameters[i], value)})
experiments.append(self._transpiled_circuits[(i, is_shots_none)])

circuit = self._circuits[i]
if "shots" in run_options and run_options["shots"] is None:
circuit = self._preprocess_circuit(circuit)
experiments.append(circuit)
parameter = {k: [v] for k, v in zip(self._parameters[i], value)}
parameter_binds.append(parameter)

# Transpile and Run
if not self._skip_transpilation:
experiments = transpile(experiments, self._backend, **self._transpile_options)
result = self._backend.run(
experiments, parameter_binds=parameter_binds, **run_options
).result()
Expand All @@ -123,18 +123,50 @@ def _call(
metadata = []
quasis = []
for i in range(len(experiments)):
if "shots" in run_options and run_options["shots"] is None:
if is_shots_none:
probabilities = result.data(i)["probabilities"]
quasis.append(QuasiDistribution(probabilities))
metadata.append({"shots": None, "simulator_metadata": result.results[i].metadata})
else:
counts = result.data(i)["counts"]
shots = sum(counts.values())
quasis.append(QuasiDistribution({k: v / shots for k, v in counts.items()}))
quasis.append(
QuasiDistribution(
{k: v / shots for k, v in counts.items()},
shots=shots,
)
)
metadata.append({"shots": shots, "simulator_metadata": result.results[i].metadata})

return SamplerResult(quasis, metadata)

# This method will be used after Terra 0.22.
def _run(
self,
circuits: Sequence[QuantumCircuit],
parameter_values: Sequence[Sequence[float]],
**run_options,
):
# pylint: disable=no-name-in-module, import-error, import-outside-toplevel, no-member
from typing import List

from qiskit.primitives.primitive_job import PrimitiveJob
from qiskit.primitives.utils import _circuit_key

circuit_indices: List[int] = []
for circuit in circuits:
index = self._circuit_ids.get(_circuit_key(circuit))
if index is not None:
circuit_indices.append(index)
else:
circuit_indices.append(len(self._circuits))
self._circuit_ids[_circuit_key(circuit)] = len(self._circuits)
self._circuits.append(circuit)
self._parameters.append(circuit.parameters)
job = PrimitiveJob(self._call, circuit_indices, parameter_values, **run_options)
job.submit()
return job

def close(self):
self._is_closed = True

Expand All @@ -153,3 +185,20 @@ def _preprocess_circuit(circuit: QuantumCircuit):
circuit = circuit.remove_final_measurements(inplace=False)
circuit.save_probabilities_dict(qargs)
return circuit

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
]
if to_handle:
circuits = (self._circuits[i] for i in to_handle)
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,
)
for i, circuit in zip(to_handle, circuits):
self._transpiled_circuits[(i, is_shots_none)] = circuit
3 changes: 2 additions & 1 deletion qiskit_aer/quantum_info/states/aer_statevector.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ class AerStatevector(Statevector):
def __init__(self, data, dims=None, **configs):
"""
Args:
data (np.array or list or Statevector or QuantumCircuit or qiskit.circuit.Instruction):
data (np.array or list or AerStatevector or QuantumCircuit or
qiskit.circuit.Instruction):
Data from which the statevector can be constructed. This can be either a complex
vector, another statevector or a ``QuantumCircuit`` or ``Instruction``
(``Operator`` is not supportted in the current implementation). If the data is
Expand Down
3 changes: 3 additions & 0 deletions releasenotes/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
encoding: utf8
default_branch: main
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fixes:
.. code-block:: python
import qiskit
from qiskit.providers.aer import AerSimulator
from qiskit_aer import AerSimulator
qc = qiskit.QuantumCircuit(2)
with qc.for_loop(range(4)) as i:
Expand Down
Loading

0 comments on commit 9c4e69d

Please sign in to comment.