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

Noise transformation with new channel interface #145

Closed
wants to merge 90 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
3c7a102
Previous stable version of the noise transformation module
gadial Apr 15, 2019
2fc76a0
Previous stable version of the noise transformation unit tests
gadial Apr 15, 2019
1c2809e
Adding noise transformation to the noise package
gadial Apr 15, 2019
b0f8ef0
Beginning noise transformation overhaul (tests are failing)
gadial Apr 15, 2019
289d3ee
Unified interface for dict/list/string approximating operator input
gadial Apr 15, 2019
686bf6c
Bugfixes in quantum_error_to_kraus_operators
gadial Apr 15, 2019
c075079
More bugfixes
gadial Apr 15, 2019
b7ec9e0
update install from source instructions in contributing.md
derivation Apr 2, 2019
5b9c129
fix scikit-build instructions, etc. in CONTRIBUTING.md
derivation Apr 8, 2019
8cc3eec
fix quantum channel import path (#139)
chriseclectic Apr 15, 2019
b3969b4
Add initialise simulator instruction to statevector_state (#117)
ShellyGarion Apr 15, 2019
861a6ca
Add two-qubit lambda in qubitvector (#133)
hhorii Apr 15, 2019
d5c4762
Improve windows build (#138)
atilag Apr 15, 2019
5c0e8a3
add to_channel method to QuantumError
chriseclectic Apr 15, 2019
80264ec
remove inplace from QuantumError, ReadoutError
chriseclectic Apr 15, 2019
5f0e8a0
Using the new to_channel method for errors
gadial Apr 16, 2019
165069b
small adjustments
gadial Apr 16, 2019
ea684ff
Beginning testing overhaul; 3 working tests with the new interface
gadial Apr 16, 2019
fb7928e
Target channel matrix now computed via SuperOp
gadial Apr 16, 2019
20be137
Tests are now fully working
gadial Apr 16, 2019
c5c2fb8
Implementation of approximate_noise_model
gadial Apr 16, 2019
0e9e4b5
Now testing noise model transformation
gadial Apr 16, 2019
f9758a5
Noise transformer tests will be skipped unless cvxopt is installed; a…
gadial Apr 16, 2019
444110a
Initialize gate (#137)
yaelbh Apr 16, 2019
bfdd678
Add to_channel method to QuantumError (#143)
chriseclectic Apr 16, 2019
103afbf
add omp to probabilities in qubitvector (#141)
hhorii Apr 16, 2019
04b9338
fix failing quantum volume benchmarks
chriseclectic Apr 17, 2019
f13ac32
disable omp in qubitvector probabilities
chriseclectic Apr 17, 2019
e2df381
Merge pull request #149 from chriseclectic/fix-quantum-volume
chriseclectic Apr 17, 2019
22a0aec
Added Clifford support
gadial Apr 17, 2019
42f5029
Added support for approximate_noise_model
gadial Apr 17, 2019
9df0b53
Documentation
gadial Apr 17, 2019
3f87962
Add controlled-swap and update static indexing in qubitvector (#142)
chriseclectic Apr 17, 2019
499a7ae
Now generates noise approximation using unitaries if possible
gadial Apr 18, 2019
580075a
Restructure - add noise utils directory
gadial Apr 18, 2019
4b6d796
Allow uppercase letters in named noises
gadial Apr 18, 2019
43804b2
Update if case to use sample measure when shot is 1 (#151)
hitomitak Apr 18, 2019
8cbcff1
add reset to standard_gate_instruction (#154)
chriseclectic Apr 18, 2019
572da09
reorganize tests (#156)
chriseclectic Apr 18, 2019
29c8ca5
Fix symbol resolution misbehaior for GCC and Clang on MacOS (#158)
atilag Apr 18, 2019
03b1d43
* Add __kmpc_critical and __kmpc_end_critical symbols for CLang/MacOS…
atilag Apr 18, 2019
8353fc6
Fix linker for linux build (#159)
chriseclectic Apr 19, 2019
576906c
optimize composition and tensor of QuantumError (#153)
chriseclectic Apr 19, 2019
43e2c20
Error reporting and version to 0.2.0 (#160)
chriseclectic Apr 19, 2019
c87c88e
add fusion optimization for qasm simulator (#136)
hhorii Apr 20, 2019
34f363d
change format of unitary qobj params (#161)
chriseclectic Apr 21, 2019
4117dca
Adding -flat_namespace link flag to MacOS to avoid misbehavior in dyn…
atilag Apr 15, 2019
25454c7
Initialize gate (#137)
yaelbh Apr 16, 2019
fb5f164
add omp to probabilities in qubitvector (#141)
hhorii Apr 16, 2019
c0d79c1
fix failing quantum volume benchmarks
chriseclectic Apr 17, 2019
89cc9e9
disable omp in qubitvector probabilities
chriseclectic Apr 17, 2019
6260427
Add controlled-swap and update static indexing in qubitvector (#142)
chriseclectic Apr 17, 2019
2451bff
Update if case to use sample measure when shot is 1 (#151)
hitomitak Apr 18, 2019
9453879
add reset to standard_gate_instruction (#154)
chriseclectic Apr 18, 2019
6b66399
reorganize tests (#156)
chriseclectic Apr 18, 2019
4985229
Fix symbol resolution misbehaior for GCC and Clang on MacOS (#158)
atilag Apr 18, 2019
dfaf731
* Add __kmpc_critical and __kmpc_end_critical symbols for CLang/MacOS…
atilag Apr 18, 2019
4980d53
Fix linker for linux build (#159)
chriseclectic Apr 19, 2019
6dc5fb5
optimize composition and tensor of QuantumError (#153)
chriseclectic Apr 19, 2019
1d67909
Error reporting and version to 0.2.0 (#160)
chriseclectic Apr 19, 2019
4609d1b
add fusion optimization for qasm simulator (#136)
hhorii Apr 20, 2019
11ba4e5
change format of unitary qobj params (#161)
chriseclectic Apr 21, 2019
aff5dcf
Now when possible outputs error circuits instead of Kraus/Unitary
gadial Apr 22, 2019
cf34bee
Now represent all named operators using circuits
gadial Apr 22, 2019
54bd21b
Previous stable version of the noise transformation module
gadial Apr 15, 2019
cb9581d
Previous stable version of the noise transformation unit tests
gadial Apr 15, 2019
d78be7d
Adding noise transformation to the noise package
gadial Apr 15, 2019
1f58bfd
Beginning noise transformation overhaul (tests are failing)
gadial Apr 15, 2019
b83b328
Unified interface for dict/list/string approximating operator input
gadial Apr 15, 2019
b4e4642
Bugfixes in quantum_error_to_kraus_operators
gadial Apr 15, 2019
e35a958
More bugfixes
gadial Apr 15, 2019
f39350f
add to_channel method to QuantumError
chriseclectic Apr 15, 2019
97aa883
remove inplace from QuantumError, ReadoutError
chriseclectic Apr 15, 2019
00f73ae
Using the new to_channel method for errors
gadial Apr 16, 2019
90b7872
small adjustments
gadial Apr 16, 2019
e3d1073
Beginning testing overhaul; 3 working tests with the new interface
gadial Apr 16, 2019
0e03ee6
Target channel matrix now computed via SuperOp
gadial Apr 16, 2019
593c5ac
Tests are now fully working
gadial Apr 16, 2019
1b9d4e1
Implementation of approximate_noise_model
gadial Apr 16, 2019
e8e554d
Now testing noise model transformation
gadial Apr 16, 2019
45efe0d
Noise transformer tests will be skipped unless cvxopt is installed; a…
gadial Apr 16, 2019
79e37e7
Added Clifford support
gadial Apr 17, 2019
210aa4c
Added support for approximate_noise_model
gadial Apr 17, 2019
3c88bb2
Documentation
gadial Apr 17, 2019
3e23dcc
Now generates noise approximation using unitaries if possible
gadial Apr 18, 2019
a843049
Restructure - add noise utils directory
gadial Apr 18, 2019
bf30c5c
Allow uppercase letters in named noises
gadial Apr 18, 2019
96850a0
Now when possible outputs error circuits instead of Kraus/Unitary
gadial Apr 22, 2019
efdd10d
Now represent all named operators using circuits
gadial Apr 22, 2019
05f4174
Merge branch 'noise_transformation' of github.com:gadial/qiskit-aer i…
gadial Apr 22, 2019
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ out/*
*.so
*.pyc
*_skbuild*
*_cmake_test_compile*
*.whl
*.egg*
build/*
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Added
-----
- Improve efficiency of parallelization with max_memory_mb a new parameter of backend_opts (#61)
- Add optimized mcx, mcy, mcz, mcu1, mcu2, mcu3, gates to QubitVector (#124)
- Add optimized controlled-swap gate to QubitVector
- Add gate-fusion optimization for QasmContoroller, which is enabled by setting fusion_enable=true (#136)

Changed
-------
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.1.1
0.2.0
7 changes: 6 additions & 1 deletion qiskit/providers/aer/backends/aerbackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,17 @@ def _format_results(self, job_id, output, time_taken):

def _validate_controller_output(self, output):
"""Validate output from the controller wrapper."""
if not isinstance(output, dict):
logger.error("%s: simulation failed.", self.name())
if output:
logger.error('Output: %s', output)
raise AerError("simulation terminated without returning valid output.")
# Check results
# TODO: Once https://github.com/Qiskit/qiskit-terra/issues/1023
# is merged this should be updated to deal with errors using
# the Result object methods
if not output.get("success", False):
logger.error("AerBackend: simulation failed")
logger.error("%s: simulation failed", self.name())
# Check for error message in the failed circuit
for res in output.get('results'):
if not res.get('success', False):
Expand Down
59 changes: 30 additions & 29 deletions qiskit/providers/aer/backends/wrappers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,41 @@ find_package(PythonLibs REQUIRED)
# shared library.
string(REPLACE " -static " "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")

# Set some general flags
if(APPLE)
message(STATUS "On Mac, we force linking with undefined symbols for Python library, they will be
solved at runtime by the loader")
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(AER_LINKER_FLAGS "-undefined dynamic_lookup")
else()
# -flat_namespace linker flag is needed otherwise dynamic symbol resolution doesn't work as expected with GCC.
# Symbols with the same name exist in different .so, so the loader just takes the first one it finds,
# which is usually the one from the first .so loaded.
# See: Two-Leve namespace symbol resolution
set(AER_LINKER_FLAGS "-undefined dynamic_lookup -flat_namespace")
endif()
unset(PYTHON_LIBRARIES)
endif()


# QASM Controller

add_cython_target(qasm_controller_wrapper qasm_controller_wrapper.pyx CXX)
add_library(qasm_controller_wrapper MODULE ${qasm_controller_wrapper})
set_target_properties(qasm_controller_wrapper PROPERTIES
LINKER_LANGUAGE CXX
LINKER_LANGUAGE CXX
CXX_STANDARD 14)
if(APPLE)
set_target_properties(qasm_controller_wrapper PROPERTIES
LINK_FLAGS ${AER_LINKER_FLAGS})
endif()
# We only need to pass the linter once, as the codebase is the same for
# all controllers
add_linter(qasm_controller_wrapper)
target_include_directories(qasm_controller_wrapper
PRIVATE ${AER_SIMULATOR_CPP_SRC_DIR}
PRIVATE ${AER_SIMULATOR_CPP_EXTERNAL_LIBS}
PRIVATE ${PYTHON_INCLUDE_DIRS})

if(APPLE)
message(STATUS "On Mac, we force linking with undefined symbols for Python library, they will be
solved at runtime by the loader")
set_target_properties(qasm_controller_wrapper PROPERTIES LINK_FLAGS "-undefined dynamic_lookup -flat_namespace")
unset(PYTHON_LIBRARIES)
endif()

target_link_libraries(qasm_controller_wrapper
${AER_LIBRARIES}
${PYTHON_LIBRARIES})
Expand All @@ -51,22 +64,14 @@ add_library(statevector_controller_wrapper MODULE ${statevector_controller_wrapp
set_target_properties(statevector_controller_wrapper PROPERTIES
LINKER_LANGUAGE CXX
CXX_STANDARD 14)
if(APPLE)
set_target_properties(statevector_controller_wrapper PROPERTIES
LINK_FLAGS ${AER_LINKER_FLAGS})
endif()
target_include_directories(statevector_controller_wrapper
PRIVATE ${AER_SIMULATOR_CPP_SRC_DIR}
PRIVATE ${AER_SIMULATOR_CPP_EXTERNAL_LIBS}
PRIVATE ${PYTHON_INCLUDE_DIRS})

if(APPLE)
message(STATUS "On Mac, we force linking with undefined symbols for Python library, they will be
solved at runtime by the loader")
# -flat_namespace linker flag is needed otherwise dynamic symbol resolution doesn't work as expected.
# Symbols with the same name exist in different .so, so the loader just takes the first one it finds,
# which is usually the one from the first .so loaded.
# See: Two-Leve namespace symbol resolution
set_target_properties(statevector_controller_wrapper PROPERTIES LINK_FLAGS "-undefined dynamic_lookup -flat_namespace")
unset(PYTHON_LIBRARIES)
endif()

target_link_libraries(statevector_controller_wrapper
${AER_LIBRARIES}
${PYTHON_LIBRARIES})
Expand All @@ -86,18 +91,14 @@ add_library(unitary_controller_wrapper MODULE ${unitary_controller_wrapper})
set_target_properties(unitary_controller_wrapper PROPERTIES
LINKER_LANGUAGE CXX
CXX_STANDARD 14)
if(APPLE)
set_target_properties(unitary_controller_wrapper PROPERTIES
LINK_FLAGS ${AER_LINKER_FLAGS})
endif()
target_include_directories(unitary_controller_wrapper
PRIVATE ${AER_SIMULATOR_CPP_SRC_DIR}
PRIVATE ${AER_SIMULATOR_CPP_EXTERNAL_LIBS}
PRIVATE ${PYTHON_INCLUDE_DIRS})

if(APPLE)
message(STATUS "On Mac, we force linking with undefined symbols for Python library, they will be
solved at runtime by the loader")
set_target_properties(unitary_controller_wrapper PROPERTIES LINK_FLAGS "-undefined dynamic_lookup -flat_namespace")
unset(PYTHON_LIBRARIES)
endif()

target_link_libraries(unitary_controller_wrapper
${AER_LIBRARIES}
${PYTHON_LIBRARIES})
Expand Down
9 changes: 9 additions & 0 deletions qiskit/providers/aer/noise/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,17 @@
Amplitude damping error
Phase damping error
Combined phase and amplitude damping error

Noise Utilities
--------------
The `noise.utils` module contains utilities for noise models and errors including:
'approximate_quantum_error' for approximating a general quantum error via
a provided set of errors (e.g. approximating amplitude damping via reset errors)
'approximate_noise_model' for approximating all the errors in a nose model using
the same provided set of errors
"""

from .noise_model import NoiseModel
from . import errors
from . import device
from . import utils
138 changes: 133 additions & 5 deletions qiskit/providers/aer/noise/errors/errorutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

import numpy as np

from qiskit.quantum_info.operators.operator import Operator
from qiskit.quantum_info.operators.channel.kraus import Kraus
from qiskit.quantum_info.operators.channel.superop import SuperOp
from qiskit.quantum_info.operators.predicates import is_identity_matrix
from qiskit.quantum_info.operators.predicates import is_unitary_matrix
from qiskit.quantum_info.operators.predicates import matrix_equal
Expand Down Expand Up @@ -45,13 +47,30 @@ def standard_gate_instruction(instruction, ignore_phase=True):
Returns:
list: a list of qobj instructions equivalent to in input instruction.
"""
if instruction.get("name", None) not in ["mat", "unitary"]:
return [instruction]

name = instruction.get("name", None)
if name not in ["mat", "unitary", "kraus"]:
return [instruction]
qubits = instruction["qubits"]
mat_dagger = np.conj(instruction["params"])
params = instruction["params"]

# Check for single-qubit reset Kraus
if name == "kraus":
if len(qubits) == 1:
superop = SuperOp(Kraus(params))
# Check if reset to |0>
reset0 = reset_superop(1)
if superop == reset0:
return [{"name": "reset", "qubits": qubits}]
# Check if reset to |1>
reset1 = reset0.compose(Operator(standard_gate_unitary('x')))
if superop == reset1:
return [{"name": "reset", "qubits": qubits}, {"name": "x", "qubits": qubits}]
# otherwise just return the kraus instruction
return [instruction]

# Check single qubit gates
mat_dagger = np.conj(params[0])
if len(qubits) == 1:
# Check clifford gates
for j in range(24):
Expand Down Expand Up @@ -87,7 +106,8 @@ def standard_gate_instruction(instruction, ignore_phase=True):
for pauli0 in paulis:
for pauli1 in paulis:
pmat = np.kron(
standard_gate_unitary(pauli1), standard_gate_unitary(pauli0))
standard_gate_unitary(pauli1),
standard_gate_unitary(pauli0))
if matrix_equal(mat_dagger, pmat, ignore_phase=ignore_phase):
if pauli0 is "id":
return [{"name": pauli1, "qubits": [qubits[1]]}]
Expand Down Expand Up @@ -304,6 +324,114 @@ def standard_gate_unitary(name):
return None


def reset_superop(num_qubits):
"""Return a N-qubit reset SuperOp."""
reset = SuperOp(
np.array([[1, 0, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]))
if num_qubits == 1:
return reset
reset_n = reset
for _ in range(num_qubits - 1):
reset_n.tensor(reset)
return reset_n


def standard_instruction_operator(instr):
"""Return the Operator for a standard gate instruction."""
# Convert to dict (for QobjInstruction types)
if hasattr(instr, 'as_dict'):
instr = instr.as_dict()
# Get name and parameters
name = instr.get('name', "")
params = instr.get('params', [])
# Check if standard unitary gate name
mat = standard_gate_unitary(name)
if isinstance(mat, np.ndarray):
return Operator(mat)

# Check if standard parameterized waltz gates
if name == 'u1':
lam = params[0]
mat = np.diag([1, np.exp(1j * lam)])
return Operator(mat)
if name == 'u2':
phi = params[0]
lam = params[1]
mat = np.array([[1, -np.exp(1j * lam)],
[np.exp(1j * phi),
np.exp(1j * (phi + lam))]]) / np.sqrt(2)
return Operator(mat)
if name == 'u3':
theta = params[0]
phi = params[1]
lam = params[2]
mat = np.array(
[[np.cos(theta / 2), -np.exp(1j * lam) * np.sin(theta / 2)],
[np.exp(1j * phi) * np.sin(theta / 2), np.exp(1j * (phi + lam)) * np.cos(theta / 2)]])
return Operator(mat)

# Check if unitary instruction
if name == 'unitary':
return Operator(params[0])

# Otherwise return None if we cannot convert instruction
return None


def standard_instruction_channel(instr):
"""Return the SuperOp channel for a standard instruction."""
# Check if standard operator
oper = standard_instruction_operator(instr)
if oper is not None:
return SuperOp(oper)

# Convert to dict (for QobjInstruction types)
if hasattr(instr, 'as_dict'):
instr = instr.as_dict()
# Get name and parameters
name = instr.get('name', "")

# Check if reset instruction
if name == 'reset':
# params should be the number of qubits being reset
num_qubits = len(instr['qubits'])
return reset_superop(num_qubits)
# Check if Kraus instruction
if name == 'kraus':
params = instr['params']
return SuperOp(Kraus(params))
return None


def circuit2superop(circuit, min_qubits=1):
"""Return the SuperOp for a standard instruction."""
# Get number of qubits
max_qubits = 1
for instr in circuit:
qubits = []
if hasattr(instr, 'qubits'):
qubits = instr.qubits
elif isinstance(instr, dict):
qubits = instr.get('qubits', [])
max_qubits = max(max_qubits, 1 + max(qubits))

num_qubits = max(max_qubits, min_qubits)

# Initialize N-qubit identity superoperator
superop = SuperOp(np.eye(4**num_qubits))
# compose each circuit element with the superoperator
for instr in circuit:
instr_op = standard_instruction_channel(instr)
if instr_op is None:
raise NoiseError('Cannot convert instruction {} to SuperOp'.format(instr))
if hasattr(instr, 'qubits'):
qubits = instr.qubits
else:
qubits = instr['qubits']
superop = superop.compose(instr_op, qubits=qubits)
return superop


def make_unitary_instruction(mat, qubits, standard_gates=True):
"""Return a qobj instruction for a unitary matrix gate.

Expand All @@ -323,7 +451,7 @@ def make_unitary_instruction(mat, qubits, standard_gates=True):
raise NoiseError("Input matrix is not unitary.")
elif isinstance(qubits, int):
qubits = [qubits]
instruction = {"name": "unitary", "qubits": qubits, "params": mat}
instruction = {"name": "unitary", "qubits": qubits, "params": [mat]}
if standard_gates:
return standard_gate_instruction(instruction)
else:
Expand Down
Loading