Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare 0.7.6 release #1170

Merged
merged 8 commits into from
Mar 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
notifications:
email: false

cache:
pip: true

os: linux
dist: bionic
language: python
python: 3.7
jobs:
include:
- name: Build aarch64 wheels
arch: arm64
services:
- docker
install:
- echo ""
env:
- CIBW_BEFORE_ALL_LINUX="yum install -y https://dl.fedoraproject.org/pub/epel/7/aarch64/Packages/e/epel-release-7-12.noarch.rpm && yum install -y openblas-devel"
- CIBW_SKIP="cp27-* cp34-* cp35-* pp*"
- TWINE_USERNAME=qiskit
- CIBW_TEST_COMMAND="python {project}/tools/verify_wheels.py"
if: tag IS present
script:
- pip install -U twine importlib-metadata keyring cibuildwheel==1.9.0
- cibuildwheel --output-dir wheelhouse
- twine upload wheelhouse/*
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.7.5'
release = '0.7.6'

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

Expand Down
2 changes: 1 addition & 1 deletion qiskit/providers/aer/VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.7.5
0.7.6
2 changes: 1 addition & 1 deletion qiskit/providers/aer/backends/qasm_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ class QasmSimulator(AerBackend):
to store a state vector. If a state vector needs more, an error
is thrown. In general, a state vector of n-qubits uses 2^n complex
values (16 Bytes). If set to 0, the maximum will be automatically
set to half the system memory size (Default: 0).
set to the system memory size (Default: 0).

* ``optimize_ideal_threshold`` (int): Sets the qubit threshold for
applying circuit optimization passes on ideal circuits.
Expand Down
2 changes: 1 addition & 1 deletion qiskit/providers/aer/backends/statevector_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class StatevectorSimulator(AerBackend):
to store a state vector. If a state vector needs more, an error
is thrown. In general, a state vector of n-qubits uses 2^n complex
values (16 Bytes). If set to 0, the maximum will be automatically
set to half the system memory size (Default: 0).
set to the system memory size (Default: 0).

* ``statevector_parallel_threshold`` (int): Sets the threshold that
"n_qubits" must be greater than to enable OpenMP
Expand Down
2 changes: 1 addition & 1 deletion qiskit/providers/aer/backends/unitary_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class UnitarySimulator(AerBackend):
to store a state vector. If a state vector needs more, an error
is thrown. In general, a state vector of n-qubits uses 2^n complex
values (16 Bytes). If set to 0, the maximum will be automatically
set to half the system memory size (Default: 0).
set to the system memory size (Default: 0).

* ``"statevector_parallel_threshold"`` (int): Sets the threshold that
2 * "n_qubits" must be greater than to enable OpenMP
Expand Down
7 changes: 6 additions & 1 deletion qiskit/providers/aer/noise/noise_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@

from qiskit.circuit import Instruction
from qiskit.providers import BaseBackend
try:
from qiskit.providers import Backend as _Backend
BACKEND = (BaseBackend, _Backend)
except ImportError:
BACKEND = BaseBackend
from qiskit.providers.models import BackendProperties

from ..backends.aerbackend import AerJSONEncoder
Expand Down Expand Up @@ -269,7 +274,7 @@ def from_backend(cls, backend,
Raises:
NoiseError: If the input backend is not valid.
"""
if isinstance(backend, BaseBackend):
if isinstance(backend, BACKEND):
properties = backend.properties()
basis_gates = backend.configuration().basis_gates
if not properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
from warnings import warn
from collections import OrderedDict
from qiskit.providers import BaseBackend
try:
from qiskit.providers import Backend as _Backend
Backend = (BaseBackend, _Backend)
except ImportError:
Backend = BaseBackend
from ...aererror import AerError
from .hamiltonian_model import HamiltonianModel

Expand Down Expand Up @@ -94,7 +99,7 @@ def from_backend(cls, backend, subsystem_list=None):
AerError: If channel or u_channel_lo are invalid.
"""

if not isinstance(backend, BaseBackend):
if not isinstance(backend, Backend):
raise AerError("{} is not a Qiskit backend".format(backend))

# get relevant information from backend
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
fixes:
- |
Fixes a bug ([#1153](https://github.com/Qiskit/qiskit-aer/issues/1153))
where noise on conditional gates was always being applied regardless of
whether the conditional gate was actually applied based on the classical
register value. Now noise on a conditional gate will only be applied in
the case where the conditional gate is applied.
7 changes: 7 additions & 0 deletions releasenotes/notes/issue1126-e2d51f660b0078db.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---

fixes:
- |
Fixed issue #1126: bug in reporting measurement of a single qubit. The bug
occured when copying the measured value to the output data structure.

2 changes: 1 addition & 1 deletion src/controllers/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ void Controller::clear_parallelization() {
parallel_nested_ = false;

explicit_parallelization_ = false;
max_memory_mb_ = get_system_memory_mb() / 2;
max_memory_mb_ = get_system_memory_mb();
}

void Controller::set_parallelization_experiments(
Expand Down
2 changes: 2 additions & 0 deletions src/framework/linalg/vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ template <class T>
Vector<T>::Vector(Vector<T> &&other) noexcept
: size_(other.size_), data_(other.data_) {
other.data_ = nullptr;
other.size_ = 0;
}

//-----------------------------------------------------------------------
Expand All @@ -214,6 +215,7 @@ template <class T> Vector<T> &Vector<T>::operator=(Vector<T> &&other) noexcept {
size_ = other.size_;
data_ = other.data_;
other.data_ = nullptr;
other.size_ = 0;
return *this;
}

Expand Down
69 changes: 44 additions & 25 deletions src/noise/noise_model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,38 +284,57 @@ NoiseModel::param_gate_table_ = {

NoiseModel::NoiseOps NoiseModel::sample_noise(const Operations::Op &op,
RngEngine &rng) const {
// Noise operations
NoiseOps noise_ops;
// Look to see if gate is a waltz gate for this error model
// NOTE this is deprecated and waltz gate noise sampling should be removed
auto it = x90_gates_.find(op.name);
if (it == x90_gates_.end()) {
// Non-X90 based gate, run according to base model
return sample_noise_helper(op, rng);
noise_ops = sample_noise_helper(op, rng);
} else {
// Decompose ops in terms of their waltz implementation
auto gate = waltz_gate_table_.find(op.name);
if (gate != waltz_gate_table_.end()) {
switch (gate->second) {
case WaltzGate::u3:
noise_ops = sample_noise_x90_u3(op.qubits[0],
op.params[0], op.params[1], op.params[2],
rng);
break;
case WaltzGate::u2:
noise_ops = sample_noise_x90_u2(op.qubits[0],
op.params[0], op.params[1],
rng);
break;
case WaltzGate::x:
noise_ops = sample_noise_x90_u3(op.qubits[0], M_PI, 0., M_PI, rng);
break;
case WaltzGate::y:
noise_ops = sample_noise_x90_u3(op.qubits[0], M_PI, 0.5 * M_PI, 0.5 * M_PI, rng);
break;
case WaltzGate::h:
noise_ops = sample_noise_x90_u2(op.qubits[0], 0., M_PI, rng);
break;
default:
// The rest of the Waltz operations are noise free (u1 only)
noise_ops = {op};
break;
}
} else {
// something went wrong if we end up here
throw std::invalid_argument("Invalid waltz gate.");
}
}
// Decompose ops in terms of their waltz implementation
auto gate = waltz_gate_table_.find(op.name);
if (gate != waltz_gate_table_.end()) {
switch (gate->second) {
case WaltzGate::u3:
return sample_noise_x90_u3(op.qubits[0],
op.params[0], op.params[1], op.params[2],
rng);
case WaltzGate::u2:
return sample_noise_x90_u2(op.qubits[0],
op.params[0], op.params[1],
rng);
case WaltzGate::x:
return sample_noise_x90_u3(op.qubits[0], M_PI, 0., M_PI, rng);
case WaltzGate::y:
return sample_noise_x90_u3(op.qubits[0], M_PI, 0.5 * M_PI, 0.5 * M_PI, rng);
case WaltzGate::h:
return sample_noise_x90_u2(op.qubits[0], 0., M_PI, rng);
default:
// The rest of the Waltz operations are noise free (u1 only)
return {op};
// If original op is conditional, make all the noise operations also conditional
if (op.conditional) {
for (auto& noise_op : noise_ops) {
noise_op.conditional = op.conditional;
noise_op.conditional_reg = op.conditional_reg;
noise_op.bfunc = op.bfunc;
}
} else {
// something went wrong if we end up here
throw std::invalid_argument("Invalid waltz gate.");
}
return noise_ops;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,6 @@ rvector_t State::measure_probs(const reg_t &qubits) const {
std::vector<reg_t> State::sample_measure(const reg_t &qubits,
uint_t shots,
RngEngine &rng) {

// There are two alternative algorithms for sample measure
// We choose the one that is optimal relative to the total number
// of qubits,and the number of shots.
Expand Down Expand Up @@ -820,11 +819,11 @@ sample_measure_using_probabilities(const reg_t &qubits,
std::vector<reg_t> all_samples;
all_samples.reserve(shots);
for (int_t val : allbit_samples) {
reg_t allbit_sample = Utils::int2reg(val, 2, qreg_.num_qubits());
reg_t allbit_sample = Utils::int2reg(val, 2, qubits.size());
reg_t sample;
sample.reserve(qubits.size());
for (uint_t qubit : qubits) {
sample.push_back(allbit_sample[qubit]);
for (uint_t j=0; j<qubits.size(); j++){
sample.push_back(allbit_sample[j]);
}
all_samples.push_back(sample);
}
Expand Down
19 changes: 19 additions & 0 deletions test/terra/reference/ref_measure.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,20 @@ def measure_circuits_deterministic(allow_sampling=True):
circuit.i(qr)
circuits.append(circuit)

# Measure a single qubit (qubit 1) in |1> state
qr = QuantumRegister(3)
cr = ClassicalRegister(1)
circuit = QuantumCircuit(qr, cr)
circuit.h(0)
circuit.x(1)
circuit.cx(0, 2)
circuit.barrier(qr)
circuit.measure(1, 0)
if not allow_sampling:
circuit.barrier(qr)
circuit.i(qr)
circuits.append(circuit)

return circuits


Expand All @@ -89,6 +103,8 @@ def measure_counts_deterministic(shots, hex_counts=True):
targets.append({'0x2': shots})
# Measure |11> state
targets.append({'0x3': shots})
# Measure a single qubit (qubit 1) in |1> state
targets.append({'0x1': shots})
else:
# Measure |00> state
targets.append({'00': shots})
Expand All @@ -98,6 +114,9 @@ def measure_counts_deterministic(shots, hex_counts=True):
targets.append({'10': shots})
# Measure |11> state
targets.append({'11': shots})
# Measure a single qubit (qubit 1) in |1> state
targets.append({'0x1': shots})

return targets


Expand Down
35 changes: 34 additions & 1 deletion test/terra/reference/ref_pauli_noise.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ def pauli_gate_error_circuits():
circuit.measure(qr, cr)
circuits.append(circuit)

# 50% Pauli error on conditional gate that doesn't get applied
circuit = QuantumCircuit(qr, cr)
circuit.x(qr).c_if(cr, 1)
circuit.barrier(qr)
circuit.measure(qr, cr)
circuits.append(circuit)

# 50% Pauli error on conditional gate that does get applied
circuit = QuantumCircuit(qr, cr)
circuit.x(qr).c_if(cr, 0)
circuit.barrier(qr)
circuit.measure(qr, cr)
circuits.append(circuit)

# 25% Pauli-X error on spectator for CX gate on [0, 1]
qr = QuantumRegister(3, 'qr')
cr = ClassicalRegister(3, 'cr')
Expand Down Expand Up @@ -106,6 +120,18 @@ def pauli_gate_error_noise_models():
noise_model.add_quantum_error(error, 'id', [0])
noise_models.append(noise_model)

# 50% Pauli error on conditional gate that doesn't get applied
error = pauli_error([('X', 0.5), ('I', 0.5)])
noise_model = NoiseModel()
noise_model.add_all_qubit_quantum_error(error, 'x')
noise_models.append(noise_model)

# 50% Pauli error on conditional gate that does get applied
error = pauli_error([('X', 0.5), ('I', 0.5)])
noise_model = NoiseModel()
noise_model.add_all_qubit_quantum_error(error, 'x')
noise_models.append(noise_model)

# 25% Pauli-X error on spectator for CX gate on [0, 1]
error = pauli_error([('XII', 0.25), ('III', 0.75)])
noise_model = NoiseModel()
Expand Down Expand Up @@ -135,11 +161,18 @@ def pauli_gate_error_counts(shots, hex_counts=True):
counts = [3 * shots / 4, shots / 4, 0, 0]
counts_lists.append(counts)

# 50% Pauli error on conditional gate that doesn't get applied
counts = [shots, 0, 0, 0]
counts_lists.append(counts)

# 50% Pauli error on conditional gate that does get applied
counts = 4 * [shots / 4]
counts_lists.append(counts)

# 25% Pauli-X error on spectator for CX gate on [0, 1]
counts = [3 * shots / 4, 0, 0, 0, shots / 4, 0, 0, 0]
counts_lists.append(counts)

# Convert to counts dict
return [list2dict(i, hex_counts) for i in counts_lists]


Expand Down