diff --git a/.travis.yml b/.travis.yml index 9538df9860..17f9a31386 100644 --- a/.travis.yml +++ b/.travis.yml @@ -67,7 +67,7 @@ stage_linux: &stage_linux stage_osx: &stage_osx <<: *stage_generic os: osx - osx_image: xcode9.2 + osx_image: xcode9.4 language: generic python: 3.7 env: @@ -90,14 +90,11 @@ stage_osx: &stage_osx cd ../../.. python-build $PYTHON_VERSION ~/python-interpreters/$PYTHON_VERSION fi + sudo pip2 install -U virtualenv pip setuptools virtualenv --python ~/python-interpreters/$PYTHON_VERSION/bin/python venv source venv/bin/activate fi before_script: - - | - if [ ! "$(ls -A .stestr)" ]; then - rm -rf .stestr - fi # Build with Thrust OpenMP CPU backend - python setup.py bdist_wheel -- -DAER_THRUST_BACKEND=OMP -- -j4 - pip install dist/qiskit_aer*whl diff --git a/cmake/compiler_utils.cmake b/cmake/compiler_utils.cmake index 6598ff1f50..038222d43b 100644 --- a/cmake/compiler_utils.cmake +++ b/cmake/compiler_utils.cmake @@ -132,6 +132,10 @@ function(uncompress_muparsersx_lib) if(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le") set(MUPARSER_ARCH_POSTFIX ".ppc64le") endif() + # Raspberry Pi (4) + if(CMAKE_SYSTEM_PROCESSOR MATCHES "armv7l") + set(MUPARSER_ARCH_POSTFIX ".armv7l") + endif() set(PLATFORM "linux") endif() diff --git a/pyproject.toml b/pyproject.toml index cba5b8630b..6279d0b02b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,2 +1,2 @@ [build-system] -requires = ["setuptools", "wheel", "scikit-build", "cmake", "ninja", "pybind11>2.4"] +requires = ["setuptools", "wheel", "scikit-build", "cmake!=3.17.1,!=3.17.0", "ninja", "pybind11>2.4"] diff --git a/qiskit/providers/aer/VERSION.txt b/qiskit/providers/aer/VERSION.txt index 267577d47e..2b7c5ae018 100644 --- a/qiskit/providers/aer/VERSION.txt +++ b/qiskit/providers/aer/VERSION.txt @@ -1 +1 @@ -0.4.1 +0.4.2 diff --git a/qiskit/providers/aer/backends/qasm_simulator.py b/qiskit/providers/aer/backends/qasm_simulator.py index c6cfaa8ad9..64493b0731 100644 --- a/qiskit/providers/aer/backends/qasm_simulator.py +++ b/qiskit/providers/aer/backends/qasm_simulator.py @@ -234,9 +234,9 @@ class QasmSimulator(AerBackend): 'coupling_map': None, 'basis_gates': [ 'u1', 'u2', 'u3', 'cx', 'cz', 'id', 'x', 'y', 'z', 'h', 's', 'sdg', - 't', 'tdg', 'swap', 'ccx', 'unitary', 'initialize', 'cu1', 'cu2', - 'cu3', 'cswap', 'mcx', 'mcy', 'mcz', 'mcu1', 'mcu2', 'mcu3', - 'mcswap', 'multiplexer', 'kraus', 'roerror' + 't', 'tdg', 'swap', 'ccx', 'unitary', 'diagonal', 'initialize', + 'cu1', 'cu2', 'cu3', 'cswap', 'mcx', 'mcy', 'mcz', + 'mcu1', 'mcu2', 'mcu3', 'mcswap', 'multiplexer', 'kraus', 'roerror' ], 'gates': [{ 'name': 'u1', @@ -349,9 +349,16 @@ class QasmSimulator(AerBackend): 'name': 'unitary', 'parameters': ['matrix'], 'conditional': True, - 'description': 'N-qubit arbitrary unitary gate. ' + 'description': 'N-qubit unitary gate. ' 'The parameter is the N-qubit matrix to apply.', 'qasm_def': 'unitary(matrix) q1, q2,...' + }, { + 'name': 'diagonal', + 'parameters': ['diag_elements'], + 'conditional': True, + 'description': 'N-qubit diagonal unitary gate. The parameters are the' + ' diagonal entries of the N-qubit matrix to apply.', + 'qasm_def': 'TODO' }, { 'name': 'initialize', 'parameters': ['vector'], diff --git a/qiskit/providers/aer/backends/statevector_simulator.py b/qiskit/providers/aer/backends/statevector_simulator.py index cd3680eee1..56c0f469bc 100644 --- a/qiskit/providers/aer/backends/statevector_simulator.py +++ b/qiskit/providers/aer/backends/statevector_simulator.py @@ -89,9 +89,9 @@ class StatevectorSimulator(AerBackend): 'coupling_map': None, 'basis_gates': [ 'u1', 'u2', 'u3', 'cx', 'cz', 'id', 'x', 'y', 'z', 'h', 's', 'sdg', - 't', 'tdg', 'swap', 'ccx', 'unitary', 'initialize', 'cu1', 'cu2', - 'cu3', 'cswap', 'mcx', 'mcy', 'mcz', 'mcu1', 'mcu2', 'mcu3', - 'mcswap', 'multiplexer', + 't', 'tdg', 'swap', 'ccx', 'unitary', 'diagonal', 'initialize', + 'cu1', 'cu2', 'cu3', 'cswap', 'mcx', 'mcy', 'mcz', + 'mcu1', 'mcu2', 'mcu3', 'mcswap', 'multiplexer', ], 'gates': [{ 'name': 'u1', @@ -207,6 +207,13 @@ class StatevectorSimulator(AerBackend): 'description': 'N-qubit arbitrary unitary gate. ' 'The parameter is the N-qubit matrix to apply.', 'qasm_def': 'unitary(matrix) q1, q2,...' + }, { + 'name': 'diagonal', + 'parameters': ['diag_elements'], + 'conditional': True, + 'description': 'N-qubit diagonal unitary gate. The parameters are the' + ' diagonal entries of the N-qubit matrix to apply.', + 'qasm_def': 'TODO' }, { 'name': 'initialize', 'parameters': ['vector'], diff --git a/qiskit/providers/aer/backends/unitary_simulator.py b/qiskit/providers/aer/backends/unitary_simulator.py index c65d1b779d..137135aa3a 100644 --- a/qiskit/providers/aer/backends/unitary_simulator.py +++ b/qiskit/providers/aer/backends/unitary_simulator.py @@ -96,7 +96,7 @@ class UnitarySimulator(AerBackend): 'coupling_map': None, 'basis_gates': [ 'u1', 'u2', 'u3', 'cx', 'cz', 'id', 'x', 'y', 'z', 'h', 's', 'sdg', - 't', 'tdg', 'swap', 'ccx', 'unitary', 'cu1', 'cu2', + 't', 'tdg', 'swap', 'ccx', 'unitary', 'diagonal', 'cu1', 'cu2', 'cu3', 'cswap', 'mcx', 'mcy', 'mcz', 'mcu1', 'mcu2', 'mcu3', 'mcswap', 'multiplexer', ], @@ -214,6 +214,13 @@ class UnitarySimulator(AerBackend): 'description': 'N-qubit arbitrary unitary gate. ' 'The parameter is the N-qubit matrix to apply.', 'qasm_def': 'unitary(matrix) q1, q2,...' + }, { + 'name': 'diagonal', + 'parameters': ['diag_elements'], + 'conditional': True, + 'description': 'N-qubit diagonal unitary gate. The parameters are the' + ' diagonal entries of the N-qubit matrix to apply.', + 'qasm_def': 'TODO' }, { 'name': 'cu1', 'parameters': ['lam'], diff --git a/qiskit/providers/aer/noise/errors/quantum_error.py b/qiskit/providers/aer/noise/errors/quantum_error.py index 87a239232d..0aeaaf67e1 100644 --- a/qiskit/providers/aer/noise/errors/quantum_error.py +++ b/qiskit/providers/aer/noise/errors/quantum_error.py @@ -41,9 +41,9 @@ class QuantumError: """ # pylint: disable=invalid-name - ATOL = ATOL_DEFAULT - RTOL = RTOL_DEFAULT - MAX_TOL = 1e-4 + _ATOL_DEFAULT = ATOL_DEFAULT + _RTOL_DEFAULT = RTOL_DEFAULT + _MAX_TOL = 1e-4 def __init__(self, noise_ops, @@ -187,35 +187,37 @@ def copy(self): @property def atol(self): - """The absolute tolerance parameter for float comparisons.""" - return self.ATOL - - @atol.setter - def atol(self, atol): - """Set the absolute tolerance parameter for float comparisons.""" - max_tol = self.MAX_TOL - if atol < 0: - raise NoiseError("Invalid atol: must be non-negative.") - if atol > max_tol: - raise NoiseError( - "Invalid atol: must be less than {}.".format(max_tol)) - self.ATOL = atol + """The default absolute tolerance parameter for float comparisons.""" + return QuantumError._ATOL_DEFAULT @property def rtol(self): """The relative tolerance parameter for float comparisons.""" - return self.RTOL - - @rtol.setter - def rtol(self, rtol): - """Set the relative tolerance parameter for float comparisons.""" - max_tol = self.MAX_TOL - if rtol < 0: - raise NoiseError("Invalid rtol: must be non-negative.") - if rtol > max_tol: + return QuantumError._RTOL_DEFAULT + + @classmethod + def set_atol(cls, value): + """Set the class default absolute tolerance parameter for float comparisons.""" + if value < 0: + raise NoiseError( + "Invalid atol ({}) must be non-negative.".format(value)) + if value > cls._MAX_TOL: + raise NoiseError( + "Invalid atol ({}) must be less than {}.".format( + value, cls._MAX_TOL)) + cls._ATOL_DEFAULT = value + + @classmethod + def set_rtol(cls, value): + """Set the class default relative tolerance parameter for float comparisons.""" + if value < 0: + raise NoiseError( + "Invalid rtol ({}) must be non-negative.".format(value)) + if value > cls._MAX_TOL: raise NoiseError( - "Invalid rtol: must be less than {}.".format(max_tol)) - self.RTOL = rtol + "Invalid rtol ({}) must be less than {}.".format( + value, cls._MAX_TOL)) + cls._RTOL_DEFAULT = value @property def size(self): diff --git a/qiskit/providers/aer/noise/errors/readout_error.py b/qiskit/providers/aer/noise/errors/readout_error.py index 5921826b9d..f492e2c26c 100644 --- a/qiskit/providers/aer/noise/errors/readout_error.py +++ b/qiskit/providers/aer/noise/errors/readout_error.py @@ -30,9 +30,9 @@ class ReadoutError: Readout error class for Qiskit Aer noise model. """ # pylint: disable=invalid-name - ATOL = ATOL_DEFAULT - RTOL = RTOL_DEFAULT - MAX_TOL = 1e-4 + _ATOL_DEFAULT = ATOL_DEFAULT + _RTOL_DEFAULT = RTOL_DEFAULT + _MAX_TOL = 1e-4 def __init__(self, probabilities, atol=ATOL_DEFAULT): """ @@ -112,35 +112,37 @@ def probabilities(self): @property def atol(self): - """The absolute tolerance parameter for float comparisons.""" - return self.ATOL - - @atol.setter - def atol(self, atol): - """Set the absolute tolerance parameter for float comparisons.""" - max_tol = self.MAX_TOL - if atol < 0: - raise NoiseError("Invalid atol: must be non-negative.") - if atol > max_tol: - raise NoiseError( - "Invalid atol: must be less than {}.".format(max_tol)) - self.ATOL = atol + """The default absolute tolerance parameter for float comparisons.""" + return ReadoutError._ATOL_DEFAULT @property def rtol(self): """The relative tolerance parameter for float comparisons.""" - return self.RTOL - - @rtol.setter - def rtol(self, rtol): - """Set the relative tolerance parameter for float comparisons.""" - max_tol = self.MAX_TOL - if rtol < 0: - raise NoiseError("Invalid rtol: must be non-negative.") - if rtol > max_tol: + return ReadoutError._RTOL_DEFAULT + + @classmethod + def set_atol(cls, value): + """Set the class default absolute tolerance parameter for float comparisons.""" + if value < 0: + raise NoiseError( + "Invalid atol ({}) must be non-negative.".format(value)) + if value > cls._MAX_TOL: + raise NoiseError( + "Invalid atol ({}) must be less than {}.".format( + value, cls._MAX_TOL)) + cls._ATOL_DEFAULT = value + + @classmethod + def set_rtol(cls, value): + """Set the class default relative tolerance parameter for float comparisons.""" + if value < 0: + raise NoiseError( + "Invalid rtol ({}) must be non-negative.".format(value)) + if value > cls._MAX_TOL: raise NoiseError( - "Invalid rtol: must be less than {}.".format(max_tol)) - self.RTOL = rtol + "Invalid rtol ({}) must be less than {}.".format( + value, cls._MAX_TOL)) + cls._RTOL_DEFAULT = value def ideal(self): """Return True if current error object is an identity""" diff --git a/requirements-dev.txt b/requirements-dev.txt index 4915ecb39a..c0f861ccec 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,4 +1,4 @@ -cmake +cmake!=3.17.1,!=3.17.0 scikit-build cython asv diff --git a/setup.py b/setup.py index 204983bb47..92e5ec7b39 100644 --- a/setup.py +++ b/setup.py @@ -34,7 +34,7 @@ setup_requirements = requirements + [ 'scikit-build', - 'cmake' + 'cmake!=3.17,!=3.17.0' ] if not hasattr(setuptools, diff --git a/src/framework/operations.hpp b/src/framework/operations.hpp index 7af3e7ae0d..85da5c97bc 100755 --- a/src/framework/operations.hpp +++ b/src/framework/operations.hpp @@ -24,6 +24,7 @@ #include "framework/types.hpp" #include "framework/json.hpp" #include "framework/utils.hpp" +#include "framework/linalg/almost_equal.hpp" namespace AER { namespace Operations { @@ -36,7 +37,7 @@ enum class RegComparison {Equal, NotEqual, Less, LessEqual, Greater, GreaterEqua // Enum class for operation types enum class OpType { gate, measure, reset, bfunc, barrier, snapshot, - matrix, multiplexer, kraus, superop, roerror, noise_switch, initialize + matrix, diagonal_matrix, multiplexer, kraus, superop, roerror, noise_switch, initialize }; inline std::ostream& operator<<(std::ostream& stream, const OpType& type) { @@ -60,7 +61,10 @@ inline std::ostream& operator<<(std::ostream& stream, const OpType& type) { stream << "snapshot"; break; case OpType::matrix: - stream << "matrix"; + stream << "unitary"; + break; + case OpType::diagonal_matrix: + stream << "diagonal"; break; case OpType::multiplexer: stream << "multiplexer"; @@ -561,6 +565,7 @@ Op json_to_op_snapshot_pauli(const json_t &js); // Matrices Op json_to_op_unitary(const json_t &js); +Op json_to_op_diagonal(const json_t &js); Op json_to_op_superop(const json_t &js); Op json_to_op_multiplexer(const json_t &js); Op json_to_op_kraus(const json_t &js); @@ -596,6 +601,8 @@ Op json_to_op(const json_t &js) { // Arbitrary matrix gates if (name == "unitary") return json_to_op_unitary(js); + if (name == "diagonal" || name == "diag") + return json_to_op_diagonal(js); if (name == "superop") return json_to_op_superop(js); // Snapshot @@ -866,6 +873,35 @@ Op json_to_op_unitary(const json_t &js) { return op; } +Op json_to_op_diagonal(const json_t &js) { + Op op; + op.type = OpType::diagonal_matrix; + op.name = "diagonal"; + JSON::get_value(op.qubits, "qubits", js); + JSON::get_value(op.params, "params", js); + + // Validation + check_empty_qubits(op); + check_duplicate_qubits(op); + if (op.params.size() != 1ULL << op.qubits.size()) { + throw std::invalid_argument("\"diagonal\" matrix is wrong size."); + } + for (const auto val : op.params) { + if (!Linalg::almost_equal(std::abs(val), 1.0)) { + throw std::invalid_argument("\"diagonal\" matrix is not unitary."); + } + } + + // Check for a label + std::string label; + JSON::get_value(label, "label", js); + op.string_params.push_back(label); + + // Conditional + add_condtional(Allowed::Yes, op, js); + return op; +} + Op json_to_op_superop(const json_t &js) { // Warning: we don't check superoperator is valid! Op op; diff --git a/src/framework/qobj.hpp b/src/framework/qobj.hpp index 2a48ee8fae..b35981039d 100755 --- a/src/framework/qobj.hpp +++ b/src/framework/qobj.hpp @@ -29,7 +29,7 @@ namespace AER { //============================================================================ class Qobj { -public: + public: //---------------------------------------------------------------- // Constructors //---------------------------------------------------------------- @@ -51,13 +51,12 @@ class Qobj { json_t config; // (optional) qobj level config data }; - //============================================================================ // JSON initialization and deserialization //============================================================================ // JSON deserialization -inline void from_json(const json_t &js, Qobj &qobj) {qobj = Qobj(js);} +inline void from_json(const json_t &js, Qobj &qobj) { qobj = Qobj(js); } Qobj::Qobj(const json_t &js) { // Check required fields @@ -83,23 +82,76 @@ Qobj::Qobj(const json_t &js) { int_t seed = -1; uint_t seed_shift = 0; JSON::get_value(seed, "seed_simulator", config); - - // Parse experiments const json_t &circs = js["experiments"]; - for (const auto &circ : circs) { - Circuit circuit(circ, config); - // Override random seed with fixed seed if set - // We shift the seed for each successive experiment - // So that results aren't correlated between experiments - if (seed >= 0) { + const size_t num_circs = circs.size(); + + // Check if parameterized qobj + // It should be of the form + // [exp0_params, exp1_params, ...] + // where: + // expk_params = [((i, j), pars), ....] + // i is the instruction index in the experiment + // j is the param index in the instruction + // pars = [par0, par1, ...] is a list of different parameterizations + using pos_t = std::pair; + using exp_params_t = std::vector>>; + std::vector param_table; + JSON::get_value(param_table, "parameterizations", config); + + // Validate parameterizations for number of circuis + if (!param_table.empty() && param_table.size() != num_circs) { + throw std::invalid_argument( + R"(Invalid parameterized qobj: "parameterizations" length does not match number of circuits.)"); + } + + // Load circuits + for (size_t i=0; i= num_instr) { + throw std::invalid_argument(R"(Invalid parameterized qobj: instruction position out of range)"); + } + auto &op = param_circuit.ops[instr_pos]; + if (param_pos >= op.params.size()) { + throw std::invalid_argument(R"(Invalid parameterized qobj: instruction param position out of range)"); + } + if (j >= params.second.size()) { + throw std::invalid_argument(R"(Invalid parameterized qobj: parameterization value out of range)"); + } + // Update the param + op.params[param_pos] = params.second[j]; + } + circuits.push_back(param_circuit); + } + } + } + // Override random seed with fixed seed if set + // We shift the seed for each successive experiment + // So that results aren't correlated between experiments + if (seed >= 0) { + for (auto& circuit : circuits) { circuit.set_seed(seed + seed_shift); - seed_shift += 2113; // Shift the seed + seed_shift += 2113; // Shift the seed } - circuits.push_back(circuit); } } //------------------------------------------------------------------------------ -} // end namespace QISKIT +} // namespace AER //------------------------------------------------------------------------------ #endif \ No newline at end of file diff --git a/src/simulators/density_matrix/densitymatrix_state.hpp b/src/simulators/density_matrix/densitymatrix_state.hpp index ca846496bd..6672512cea 100644 --- a/src/simulators/density_matrix/densitymatrix_state.hpp +++ b/src/simulators/density_matrix/densitymatrix_state.hpp @@ -77,6 +77,7 @@ class State : public Base::State { Operations::OpType::bfunc, Operations::OpType::roerror, Operations::OpType::matrix, + Operations::OpType::diagonal_matrix, Operations::OpType::kraus, Operations::OpType::superop }); @@ -417,6 +418,9 @@ void State::apply_ops(const std::vector &ops, case Operations::OpType::matrix: apply_matrix(op.qubits, op.mats[0]); break; + case Operations::OpType::diagonal_matrix: + BaseState::qreg_.apply_diagonal_matrix(op.qubits, op.params); + break; case Operations::OpType::superop: BaseState::qreg_.apply_superop_matrix(op.qubits, Utils::vectorize_matrix(op.mats[0])); break; diff --git a/src/simulators/statevector/statevector_state.hpp b/src/simulators/statevector/statevector_state.hpp index cfb873eaaf..af9d0a201e 100755 --- a/src/simulators/statevector/statevector_state.hpp +++ b/src/simulators/statevector/statevector_state.hpp @@ -80,6 +80,7 @@ class State : public Base::State { Operations::OpType::bfunc, Operations::OpType::roerror, Operations::OpType::matrix, + Operations::OpType::diagonal_matrix, Operations::OpType::multiplexer, Operations::OpType::kraus }); @@ -469,6 +470,9 @@ void State::apply_ops(const std::vector &ops, case Operations::OpType::matrix: apply_matrix(op); break; + case Operations::OpType::diagonal_matrix: + BaseState::qreg_.apply_diagonal_matrix(op.qubits, op.params); + break; case Operations::OpType::multiplexer: apply_multiplexer(op.regs[0], op.regs[1], op.mats); // control qubits ([0]) & target qubits([1]) break; diff --git a/src/simulators/superoperator/superoperator_state.hpp b/src/simulators/superoperator/superoperator_state.hpp index 080ea5257f..bd02c48e0f 100755 --- a/src/simulators/superoperator/superoperator_state.hpp +++ b/src/simulators/superoperator/superoperator_state.hpp @@ -65,6 +65,7 @@ class State : public Base::State { Operations::OpType::snapshot, Operations::OpType::barrier, Operations::OpType::matrix, + Operations::OpType::diagonal_matrix, Operations::OpType::kraus, Operations::OpType::superop }); @@ -234,6 +235,9 @@ void State::apply_ops(const std::vector &ops, case Operations::OpType::matrix: apply_matrix(op.qubits, op.mats[0]); break; + case Operations::OpType::diagonal_matrix: + BaseState::qreg_.apply_diagonal_matrix(op.qubits, op.params); + break; case Operations::OpType::kraus: apply_kraus(op.qubits, op.mats); break; diff --git a/src/simulators/unitary/unitary_state.hpp b/src/simulators/unitary/unitary_state.hpp index f2d12e866a..0dc52d27be 100755 --- a/src/simulators/unitary/unitary_state.hpp +++ b/src/simulators/unitary/unitary_state.hpp @@ -69,9 +69,13 @@ class State : public Base::State { // Return the set of qobj instruction types supported by the State virtual Operations::OpSet::optypeset_t allowed_ops() const override { - return Operations::OpSet::optypeset_t( - {Operations::OpType::gate, Operations::OpType::barrier, - Operations::OpType::matrix, Operations::OpType::snapshot}); + return Operations::OpSet::optypeset_t({ + Operations::OpType::gate, + Operations::OpType::barrier, + Operations::OpType::matrix, + Operations::OpType::diagonal_matrix, + Operations::OpType::snapshot + }); } // Return the set of qobj gate instruction names supported by the State @@ -233,6 +237,9 @@ void State::apply_ops( case Operations::OpType::matrix: apply_matrix(op.qubits, op.mats[0]); break; + case Operations::OpType::diagonal_matrix: + BaseState::qreg_.apply_diagonal_matrix(op.qubits, op.params); + break; default: throw std::invalid_argument( "QubitUnitary::State::invalid instruction \'" + op.name + "\'."); diff --git a/src/third-party/linux/lib/muparserx.armv7l.7z b/src/third-party/linux/lib/muparserx.armv7l.7z new file mode 100644 index 0000000000..4472c81a18 Binary files /dev/null and b/src/third-party/linux/lib/muparserx.armv7l.7z differ diff --git a/test/terra/backends/qasm_simulator/qasm_unitary_gate.py b/test/terra/backends/qasm_simulator/qasm_unitary_gate.py index bfea1aff91..63545b2aa1 100644 --- a/test/terra/backends/qasm_simulator/qasm_unitary_gate.py +++ b/test/terra/backends/qasm_simulator/qasm_unitary_gate.py @@ -13,11 +13,12 @@ QasmSimulator Integration Tests """ + +from test.terra.reference import ref_unitary_gate, ref_diagonal_gate + from qiskit import execute from qiskit.providers.aer import QasmSimulator -from test.terra.reference import ref_unitary_gate - class QasmUnitaryGateTests: """QasmSimulator additional tests.""" @@ -48,3 +49,25 @@ def test_random_unitary_gate(self): result = execute(circuits, self.SIMULATOR, shots=shots).result() self.assertTrue(getattr(result, 'success', False)) self.compare_counts(result, circuits, targets, delta=0.05 * shots) + + +class QasmDiagonalGateTests: + """QasmSimulator additional tests.""" + + SIMULATOR = QasmSimulator() + BACKEND_OPTS = {} + + # --------------------------------------------------------------------- + # Test unitary gate qobj instruction + # --------------------------------------------------------------------- + + def test_diagonal_gate(self): + """Test simulation with unitary gate circuit instructions.""" + shots = 100 + circuits = ref_diagonal_gate.diagonal_gate_circuits_deterministic( + final_measure=True) + targets = ref_diagonal_gate.diagonal_gate_counts_deterministic( + shots) + result = execute(circuits, self.SIMULATOR, shots=shots).result() + self.assertTrue(getattr(result, 'success', False)) + self.compare_counts(result, circuits, targets, delta=0) diff --git a/test/terra/backends/statevector_simulator/statevector_basics.py b/test/terra/backends/statevector_simulator/statevector_basics.py index e4c54781b1..18083e111c 100644 --- a/test/terra/backends/statevector_simulator/statevector_basics.py +++ b/test/terra/backends/statevector_simulator/statevector_basics.py @@ -21,6 +21,7 @@ from test.terra.reference import ref_2q_clifford from test.terra.reference import ref_non_clifford from test.terra.reference import ref_unitary_gate +from test.terra.reference import ref_diagonal_gate from qiskit import execute from qiskit.compiler import assemble @@ -1072,6 +1073,19 @@ def test_unitary_gate(self): self.assertTrue(getattr(result, 'success', False)) self.compare_statevector(result, circuits, targets) + def test_diagonal_gate(self): + """Test simulation with diagonal gate circuit instructions.""" + circuits = ref_diagonal_gate.diagonal_gate_circuits_deterministic( + final_measure=False) + targets = ref_diagonal_gate.diagonal_gate_statevector_deterministic() + job = execute(circuits, + self.SIMULATOR, + shots=1, + backend_options=self.BACKEND_OPTS) + result = job.result() + self.assertTrue(getattr(result, 'success', False)) + self.compare_statevector(result, circuits, targets) + # --------------------------------------------------------------------- # Test cu1 gate # --------------------------------------------------------------------- diff --git a/test/terra/backends/test_parameterized_qobj.py b/test/terra/backends/test_parameterized_qobj.py new file mode 100644 index 0000000000..f56d9ebc0f --- /dev/null +++ b/test/terra/backends/test_parameterized_qobj.py @@ -0,0 +1,127 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2018, 2019. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +""" +Integration Tests for Parameterized Qobj execution, testing qasm_simulator, +statevector_simulator, and expectation value snapshots. +""" + +import unittest +import numpy as np + +from test.terra import common + +from qiskit import assemble +from test.terra.reference.ref_snapshot_expval import ( + snapshot_expval_circuits, snapshot_expval_counts, snapshot_expval_labels, + snapshot_expval_pre_meas_values, snapshot_expval_circuit_parameterized, + snapshot_expval_final_statevecs) +from qiskit.providers.aer import QasmSimulator, StatevectorSimulator + + +class TestParameterizedQobj(common.QiskitAerTestCase): + """Parameterized Qobj extension tests""" + + BACKEND_OPTS = { + "seed_simulator": 2113 + } + + @staticmethod + def expval_snapshots(data, labels): + """Format snapshots as nested dicts""" + # Check snapshot entry exists in data + output = {} + for label in labels: + snaps = data.get("snapshots", {}).get("expectation_value", + {}).get(label, []) + # Convert list into dict + inner = {} + for snap_dict in snaps: + inner[snap_dict['memory']] = snap_dict['value'] + output[label] = inner + return output + + @staticmethod + def parameterized_qobj(backend, shots=1000, measure=True, snapshot=False): + """Return ParameterizedQobj for settings.""" + single_shot = shots == 1 + pcirc1, param1 = snapshot_expval_circuit_parameterized(single_shot=single_shot, + measure=measure, + snapshot=snapshot) + circuits2to4 = snapshot_expval_circuits(pauli=True, + skip_measure=(not measure), + single_shot=single_shot) + pcirc2, param2 = snapshot_expval_circuit_parameterized(single_shot=single_shot, + measure=measure, + snapshot=snapshot) + circuits = [pcirc1] + circuits2to4 + [pcirc2] + params = [param1, [], [], [], param2] + qobj = assemble(circuits, + backend=backend, + shots=shots, + parameterizations=params) + return qobj + + def test_parameterized_qobj_qasm_snapshot_expval(self): + """Test parameterized qobj with Expectation Value snapshot and qasm simulator.""" + shots = 1000 + labels = snapshot_expval_labels() * 3 + counts_targets = snapshot_expval_counts(shots) * 3 + value_targets = snapshot_expval_pre_meas_values() * 3 + + backend = QasmSimulator() + qobj = self.parameterized_qobj(backend=backend, + shots=1000, + measure=True, + snapshot=True) + self.assertIn('parameterizations', qobj.to_dict()['config']) + job = backend.run(qobj, self.BACKEND_OPTS) + result = job.result() + success = getattr(result, 'success', False) + num_circs = len(result.to_dict()['results']) + self.assertTrue(success) + self.compare_counts(result, + range(num_circs), + counts_targets, + delta=0.1 * shots) + # Check snapshots + for j in range(num_circs): + data = result.data(j) + all_snapshots = self.expval_snapshots(data, labels) + for label in labels: + snaps = all_snapshots.get(label, {}) + self.assertTrue(len(snaps), 1) + for memory, value in snaps.items(): + target = value_targets[j].get(label, + {}).get(memory, {}) + self.assertAlmostEqual(value, target, delta=1e-7) + + def test_parameterized_qobj_statevector(self): + """Test parameterized qobj with Expectation Value snapshot and qasm simulator.""" + statevec_targets = snapshot_expval_final_statevecs() * 3 + + backend = StatevectorSimulator() + qobj = self.parameterized_qobj(backend=backend, + measure=False, + snapshot=False) + self.assertIn('parameterizations', qobj.to_dict()['config']) + job = backend.run(qobj, self.BACKEND_OPTS) + result = job.result() + success = getattr(result, 'success', False) + num_circs = len(result.to_dict()['results']) + self.assertTrue(success) + + for j in range(num_circs): + statevector = result.get_statevector(j) + np.testing.assert_array_almost_equal(statevector, statevec_targets[j].data, decimal=7) + +if __name__ == '__main__': + unittest.main() diff --git a/test/terra/backends/test_qasm_simulator.py b/test/terra/backends/test_qasm_simulator.py index bd944ec761..c6c9deddf7 100644 --- a/test/terra/backends/test_qasm_simulator.py +++ b/test/terra/backends/test_qasm_simulator.py @@ -28,6 +28,7 @@ from test.terra.backends.qasm_simulator.qasm_noncliffords import QasmNonCliffordTestsWaltzBasis from test.terra.backends.qasm_simulator.qasm_noncliffords import QasmNonCliffordTestsMinimalBasis from test.terra.backends.qasm_simulator.qasm_unitary_gate import QasmUnitaryGateTests +from test.terra.backends.qasm_simulator.qasm_unitary_gate import QasmDiagonalGateTests from test.terra.backends.qasm_simulator.qasm_initialize import QasmInitializeTests # Conditional instruction tests from test.terra.backends.qasm_simulator.qasm_conditional import QasmConditionalGateTests @@ -77,6 +78,7 @@ class TestQasmSimulator(common.QiskitAerTestCase, QasmAlgorithmTestsWaltzBasis, QasmAlgorithmTestsMinimalBasis, QasmUnitaryGateTests, + QasmDiagonalGateTests, QasmReadoutNoiseTests, QasmPauliNoiseTests, QasmThreadManagementTests, diff --git a/test/terra/backends/test_qasm_simulator_density_matrix.py b/test/terra/backends/test_qasm_simulator_density_matrix.py index b32c6db9fb..c1183e3623 100644 --- a/test/terra/backends/test_qasm_simulator_density_matrix.py +++ b/test/terra/backends/test_qasm_simulator_density_matrix.py @@ -28,6 +28,7 @@ from test.terra.backends.qasm_simulator.qasm_noncliffords import QasmNonCliffordTestsWaltzBasis from test.terra.backends.qasm_simulator.qasm_noncliffords import QasmNonCliffordTestsMinimalBasis from test.terra.backends.qasm_simulator.qasm_unitary_gate import QasmUnitaryGateTests +from test.terra.backends.qasm_simulator.qasm_unitary_gate import QasmDiagonalGateTests # Conditional instruction tests from test.terra.backends.qasm_simulator.qasm_conditional import QasmConditionalGateTests from test.terra.backends.qasm_simulator.qasm_conditional import QasmConditionalUnitaryTests @@ -61,7 +62,7 @@ class DensityMatrixTests( QasmCliffordTestsMinimalBasis, QasmNonCliffordTests, QasmNonCliffordTestsWaltzBasis, QasmNonCliffordTestsMinimalBasis, QasmAlgorithmTests, QasmAlgorithmTestsWaltzBasis, - QasmAlgorithmTestsMinimalBasis, QasmUnitaryGateTests, + QasmAlgorithmTestsMinimalBasis, QasmUnitaryGateTests, QasmDiagonalGateTests, QasmReadoutNoiseTests, QasmPauliNoiseTests, QasmResetNoiseTests, QasmKrausNoiseTests, QasmSnapshotStatevectorTests, QasmSnapshotDensityMatrixTests, QasmSnapshotProbabilitiesTests, diff --git a/test/terra/backends/test_qasm_simulator_statevector.py b/test/terra/backends/test_qasm_simulator_statevector.py index 1c203d0abe..fca386d100 100644 --- a/test/terra/backends/test_qasm_simulator_statevector.py +++ b/test/terra/backends/test_qasm_simulator_statevector.py @@ -28,6 +28,7 @@ from test.terra.backends.qasm_simulator.qasm_noncliffords import QasmNonCliffordTestsWaltzBasis from test.terra.backends.qasm_simulator.qasm_noncliffords import QasmNonCliffordTestsMinimalBasis from test.terra.backends.qasm_simulator.qasm_unitary_gate import QasmUnitaryGateTests +from test.terra.backends.qasm_simulator.qasm_unitary_gate import QasmDiagonalGateTests from test.terra.backends.qasm_simulator.qasm_initialize import QasmInitializeTests # Conditional instruction tests from test.terra.backends.qasm_simulator.qasm_conditional import QasmConditionalGateTests @@ -66,7 +67,7 @@ class StatevectorTests( QasmCliffordTestsMinimalBasis, QasmNonCliffordTests, QasmNonCliffordTestsWaltzBasis, QasmNonCliffordTestsMinimalBasis, QasmAlgorithmTests, QasmAlgorithmTestsWaltzBasis, - QasmAlgorithmTestsMinimalBasis, QasmUnitaryGateTests, + QasmAlgorithmTestsMinimalBasis, QasmUnitaryGateTests, QasmDiagonalGateTests, QasmReadoutNoiseTests, QasmPauliNoiseTests, QasmThreadManagementTests, QasmFusionTests, QasmDelayMeasureTests, QasmQubitsTruncateTests, QasmResetNoiseTests, QasmKrausNoiseTests, QasmBasicsTests, diff --git a/test/terra/backends/unitary_simulator/unitary_basics.py b/test/terra/backends/unitary_simulator/unitary_basics.py index dcb448b38c..86edda3fe8 100644 --- a/test/terra/backends/unitary_simulator/unitary_basics.py +++ b/test/terra/backends/unitary_simulator/unitary_basics.py @@ -19,6 +19,7 @@ from test.terra.reference import ref_2q_clifford from test.terra.reference import ref_non_clifford from test.terra.reference import ref_unitary_gate +from test.terra.reference import ref_diagonal_gate from qiskit import execute from qiskit.providers.aer import UnitarySimulator @@ -1050,6 +1051,19 @@ def test_unitary_gate(self): self.assertTrue(getattr(result, 'success', False)) self.compare_unitary(result, circuits, targets) + def test_diagonal_gate(self): + """Test simulation with diagonal gate circuit instructions.""" + circuits = ref_diagonal_gate.diagonal_gate_circuits_deterministic( + final_measure=False) + targets = ref_diagonal_gate.diagonal_gate_unitary_deterministic() + job = execute(circuits, + self.SIMULATOR, + shots=1, + backend_options=self.BACKEND_OPTS) + result = job.result() + self.assertTrue(getattr(result, 'success', False)) + self.compare_unitary(result, circuits, targets) + # --------------------------------------------------------------------- # Test cswap-gate (Fredkin) # --------------------------------------------------------------------- diff --git a/test/terra/common.py b/test/terra/common.py index 8ca5774e87..229a29867f 100644 --- a/test/terra/common.py +++ b/test/terra/common.py @@ -118,16 +118,19 @@ def compare_statevector(self, result, circuits, targets, for pos, test_case in enumerate(zip(circuits, targets)): circuit, target = test_case output = result.get_statevector(circuit) - msg = ("Circuit ({}/{}):".format(pos + 1, len(circuits)) + - " {} != {}".format(output, target)) - if (global_phase): - # Test equal including global phase - self.assertAlmostEqual(norm(output - target), 0, places=places, - msg=msg) - else: - # Test equal ignorning global phase - self.assertAlmostEqual(state_fidelity(output, target) - 1, 0, places=places, - msg=msg + " up to global phase") + test_msg = "Circuit ({}/{}):".format(pos + 1, len(circuits)) + with self.subTest(msg=test_msg): + msg = " {} != {}".format(output, target) + if global_phase: + # Test equal including global phase + self.assertAlmostEqual( + norm(output - target), 0, places=places, + msg=msg) + else: + # Test equal ignorning global phase + self.assertAlmostEqual( + state_fidelity(output, target) - 1, 0, places=places, + msg=msg + " up to global phase") def compare_unitary(self, result, circuits, targets, global_phase=True, places=None): @@ -135,17 +138,19 @@ def compare_unitary(self, result, circuits, targets, for pos, test_case in enumerate(zip(circuits, targets)): circuit, target = test_case output = result.get_unitary(circuit) - msg = ("Circuit ({}/{}):".format(pos + 1, len(circuits)) + - " {} != {}".format(output, target)) - if (global_phase): - # Test equal including global phase - self.assertAlmostEqual(norm(output - target), 0, - places=places, msg=msg) - else: - # Test equal ignorning global phase - delta = np.trace(np.dot(np.conj(np.transpose(output)), target)) - len(output) - self.assertAlmostEqual(delta, 0, places=places, - msg=msg + " up to global phase") + test_msg = "Circuit ({}/{}):".format(pos + 1, len(circuits)) + with self.subTest(msg=test_msg): + msg = "\n{}\n {} != {}".format(circuit, output, target) + if global_phase: + # Test equal including global phase + self.assertAlmostEqual( + norm(output - target), 0, places=places, msg=msg) + else: + # Test equal ignorning global phase + delta = np.trace(np.dot( + np.conj(np.transpose(output)), target)) - len(output) + self.assertAlmostEqual( + delta, 0, places=places, msg=msg + " up to global phase") def compare_counts(self, result, circuits, targets, hex_counts=True, delta=0): """Compare counts dictionary to targets.""" @@ -157,9 +162,11 @@ def compare_counts(self, result, circuits, targets, hex_counts=True, delta=0): else: # Use get counts method which converts hex output = result.get_counts(circuit) - msg = ("Circuit ({}/{}):".format(pos + 1, len(circuits)) + - " {} != {}".format(output, target)) - self.assertDictAlmostEqual(output, target, delta=delta, msg=msg) + test_msg = "Circuit ({}/{}):".format(pos + 1, len(circuits)) + with self.subTest(msg=test_msg): + msg = " {} != {}".format(output, target) + self.assertDictAlmostEqual( + output, target, delta=delta, msg=msg) def compare_memory(self, result, circuits, targets, hex_counts=True): """Compare memory list to target.""" @@ -172,9 +179,10 @@ def compare_memory(self, result, circuits, targets, hex_counts=True): else: # Use get counts method which converts hex output = result.get_memory(circuit) - msg = ("Circuit ({}/{}):".format(pos + 1, len(circuits)) + - " {} != {}".format(output, target)) - self.assertEqual(output, target, msg=msg) + test_msg = "Circuit ({}/{}):".format(pos + 1, len(circuits)) + with self.subTest(msg=test_msg): + msg = " {} != {}".format(output, target) + self.assertEqual(output, target, msg=msg) def compare_result_metadata(self, result, circuits, key, targets): """Compare result metadata key value.""" @@ -186,9 +194,10 @@ def compare_result_metadata(self, result, circuits, key, targets): metadata = getattr(result.results[0], 'metadata') if metadata: value = metadata.get(key) - msg = ("Circuit ({}/{}):".format(pos + 1, len(circuits)) + - " metadata {} value {} != {}".format(key, value, target)) - self.assertEqual(value, target, msg=msg) + test_msg = "Circuit ({}/{}):".format(pos + 1, len(circuits)) + with self.subTest(msg=test_msg): + msg = " metadata {} value {} != {}".format(key, value, target) + self.assertEqual(value, target, msg=msg) def assertDictAlmostEqual(self, dict1, dict2, delta=None, msg=None, places=None, default_value=0): diff --git a/test/terra/decorators.py b/test/terra/decorators.py index 8c82fb9e2a..1ed2d3426e 100644 --- a/test/terra/decorators.py +++ b/test/terra/decorators.py @@ -21,6 +21,10 @@ from qiskit.providers.aer import AerProvider, QasmSimulator from qiskit.providers.aer import AerError +# Backwards compatibility for Terra <= 0.13 +if not hasattr(QuantumCircuit, 'i'): + QuantumCircuit.i = QuantumCircuit.iden + def is_method_available(backend, method): """Check if input method is available for the qasm simulator.""" @@ -28,7 +32,7 @@ def is_method_available(backend, method): if isinstance(backend, str): backend = AerProvider().get_backend(backend) dummy_circ = QuantumCircuit(1) - dummy_circ.iden(0) + dummy_circ.i(0) qobj = assemble(dummy_circ, optimization_level=0) backend_options = {"method": method} try: diff --git a/test/terra/noise/test_noise_model.py b/test/terra/noise/test_noise_model.py index c76a0851c5..8e66417d2e 100644 --- a/test/terra/noise/test_noise_model.py +++ b/test/terra/noise/test_noise_model.py @@ -16,7 +16,7 @@ import unittest from test.terra import common -from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute +from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit from qiskit.compiler import assemble, transpile from qiskit.providers.aer.backends import QasmSimulator from qiskit.providers.aer.noise import NoiseModel @@ -25,6 +25,10 @@ from qiskit.providers.aer.noise.errors.standard_errors import amplitude_damping_error from qiskit.test import mock +# Backwards compatibility for Terra <= 0.13 +if not hasattr(QuantumCircuit, 'i'): + QuantumCircuit.i = QuantumCircuit.iden + class TestNoise(common.QiskitAerTestCase): """Testing noise model""" @@ -38,7 +42,7 @@ def test_amplitude_damping_error(self): for _ in range(30): # Add noisy identities circuit.barrier(qr) - circuit.iden(qr) + circuit.i(qr) circuit.barrier(qr) circuit.measure(qr, cr) shots = 2000 diff --git a/test/terra/reference/ref_algorithms.py b/test/terra/reference/ref_algorithms.py index a04275b7bb..39bcb6661c 100644 --- a/test/terra/reference/ref_algorithms.py +++ b/test/terra/reference/ref_algorithms.py @@ -17,6 +17,10 @@ from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit +# Backwards compatibility for Terra <= 0.13 +if not hasattr(QuantumCircuit, 'i'): + QuantumCircuit.i = QuantumCircuit.iden + def grovers_circuit(final_measure=True, allow_sampling=True): """Testing a circuit originated in the Grover algorithm""" @@ -62,7 +66,7 @@ def grovers_circuit(final_measure=True, allow_sampling=True): circuit.measure(qr[1], cr[1]) if not allow_sampling: circuit.barrier(qr) - circuit.iden(qr) + circuit.i(qr) circuits.append(circuit) return circuits diff --git a/test/terra/reference/ref_diagonal_gate.py b/test/terra/reference/ref_diagonal_gate.py new file mode 100644 index 0000000000..eb88cd04fe --- /dev/null +++ b/test/terra/reference/ref_diagonal_gate.py @@ -0,0 +1,141 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2018, 2019. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +""" +Test circuits and reference outputs for diagonal instruction. +""" + + +import numpy as np +from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister + +# Backwards compatibility for Terra <= 0.13 +if not hasattr(QuantumCircuit, 'diagonal'): + QuantumCircuit.diagonal = QuantumCircuit.diag_gate + + +def diagonal_gate_circuits_deterministic(final_measure=True): + """Diagonal gate test circuits with deterministic count output.""" + + circuits = [] + qr = QuantumRegister(2, 'qr') + if final_measure: + cr = ClassicalRegister(2, 'cr') + regs = (qr, cr) + else: + regs = (qr, ) + + # Swap |00> <--> |01> states + circuit = QuantumCircuit(*regs) + circuit.h(0) + circuit.diagonal([1, -1], [0]) + circuit.h(0) + if final_measure: + circuit.barrier(qr) + circuit.measure(qr, cr) + circuits.append(circuit) + + # Swap |00> <--> |10> states + circuit = QuantumCircuit(*regs) + circuit.h(1) + circuit.diagonal([1, -1], [1]) + circuit.h(1) + if final_measure: + circuit.barrier(qr) + circuit.measure(qr, cr) + circuits.append(circuit) + + # Swap |00> <--> |11> states + circuit = QuantumCircuit(*regs) + circuit.h(qr) + circuit.diagonal([1, -1, -1, 1], qr) + circuit.h(qr) + if final_measure: + circuit.barrier(qr) + circuit.measure(qr, cr) + circuits.append(circuit) + + # CS01.XX, 1j|11> state + circuit = QuantumCircuit(*regs) + circuit.x(qr) + circuit.diagonal([1, 1, 1, 1j], qr) + if final_measure: + circuit.barrier(qr) + circuit.measure(qr, cr) + circuits.append(circuit) + + return circuits + + +def diagonal_gate_counts_deterministic(shots, hex_counts=True): + """Diagonal gate circuits reference counts.""" + targets = [] + if hex_counts: + # Swap |00> <--> |01> states + targets.append({'0x1': shots}) + # Swap |00> <--> |10> states + targets.append({'0x2': shots}) + # Swap |00> <--> |11> states + targets.append({'0x3': shots}) + # CS01.XX, 1j|11> state + targets.append({'0x3': shots}) + else: + # Swap |00> <--> |01> states + targets.append({'01': shots}) + # Swap |00> <--> |10> states + targets.append({'10': shots}) + # Swap |00> <--> |11> states + targets.append({'11': shots}) + # CS01.XX, 1j|11> state + targets.append({'11': shots}) + return targets + + +def diagonal_gate_statevector_deterministic(): + """Diagonal gate test circuits with deterministic counts.""" + targets = [] + # Swap |00> <--> |01> states + targets.append(np.array([0, 1, 0, 0])) + # Swap |00> <--> |10> states + targets.append(np.array([0, 0, 1, 0])) + # Swap |00> <--> |11> states + targets.append(np.array([0, 0, 0, 1])) + # CS01.XX, 1j|11> state + targets.append(np.array([0, 0, 0, 1j])) + return targets + + +def diagonal_gate_unitary_deterministic(): + """Diagonal gate circuits reference unitaries.""" + targets = [] + + # Swap |00> <--> |01> states + targets.append(np.array([[0, 1, 0, 0], + [1, 0, 0, 0], + [0, 0, 0, 1], + [0, 0, 1, 0]])) + # Swap |00> <--> |10> states + targets.append(np.array([[0, 0, 1, 0], + [0, 0, 0, 1], + [1, 0, 0, 0], + [0, 1, 0, 0]])) + # Swap |00> <--> |11> states + targets.append(np.array([[0, 0, 0, 1], + [0, 0, 1, 0], + [0, 1, 0, 0], + [1, 0, 0, 0]])) + # CS01.XX, 1j|11> state + targets.append(np.array([[0, 0, 0, 1], + [0, 0, 1, 0], + [0, 1, 0, 0], + [1j, 0, 0, 0]])) + return targets diff --git a/test/terra/reference/ref_kraus_noise.py b/test/terra/reference/ref_kraus_noise.py index 1c9cc087ea..6c00da1f25 100644 --- a/test/terra/reference/ref_kraus_noise.py +++ b/test/terra/reference/ref_kraus_noise.py @@ -20,6 +20,10 @@ from qiskit.providers.aer.noise import NoiseModel from qiskit.providers.aer.noise.errors.standard_errors import amplitude_damping_error +# Backwards compatibility for Terra <= 0.13 +if not hasattr(QuantumCircuit, 'i'): + QuantumCircuit.i = QuantumCircuit.iden + # ========================================================================== # Amplitude damping error @@ -37,7 +41,7 @@ def kraus_gate_error_circuits(): for _ in range(30): # Add noisy identities circuit.barrier(qr) - circuit.iden(qr) + circuit.i(qr) circuit.barrier(qr) circuit.measure(qr, cr) circuits.append(circuit) diff --git a/test/terra/reference/ref_measure.py b/test/terra/reference/ref_measure.py index d7e3bd17a9..23e1348027 100644 --- a/test/terra/reference/ref_measure.py +++ b/test/terra/reference/ref_measure.py @@ -18,6 +18,10 @@ from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit from qiskit.circuit import Instruction +# Backwards compatibility for Terra <= 0.13 +if not hasattr(QuantumCircuit, 'i'): + QuantumCircuit.i = QuantumCircuit.iden + # ========================================================================== # Single-qubit measurements with deterministic output @@ -36,7 +40,7 @@ def measure_circuits_deterministic(allow_sampling=True): circuit.measure(qr, cr) if not allow_sampling: circuit.barrier(qr) - circuit.iden(qr) + circuit.i(qr) circuits.append(circuit) # Measure |01> state @@ -46,7 +50,7 @@ def measure_circuits_deterministic(allow_sampling=True): circuit.measure(qr, cr) if not allow_sampling: circuit.barrier(qr) - circuit.iden(qr) + circuit.i(qr) circuits.append(circuit) # Measure |10> state @@ -56,7 +60,7 @@ def measure_circuits_deterministic(allow_sampling=True): circuit.measure(qr, cr) if not allow_sampling: circuit.barrier(qr) - circuit.iden(qr) + circuit.i(qr) circuits.append(circuit) # Measure |11> state @@ -66,7 +70,7 @@ def measure_circuits_deterministic(allow_sampling=True): circuit.measure(qr, cr) if not allow_sampling: circuit.barrier(qr) - circuit.iden(qr) + circuit.i(qr) circuits.append(circuit) return circuits @@ -153,7 +157,7 @@ def measure_circuits_nondeterministic(allow_sampling=True): circuit.measure(qr, cr) if not allow_sampling: circuit.barrier(qr) - circuit.iden(qr) + circuit.i(qr) circuits.append(circuit) return circuits @@ -195,7 +199,7 @@ def measure_n(num_qubits): circuit.append(measure_n(2), [0, 1], [0, 1]) if not allow_sampling: circuit.barrier(qr) - circuit.iden(qr) + circuit.i(qr) circuits.append(circuit) # 3-qubit measure |101> @@ -208,7 +212,7 @@ def measure_n(num_qubits): circuit.append(measure_n(3), [0, 1, 2], [0, 1, 2]) if not allow_sampling: circuit.barrier(qr) - circuit.iden(qr) + circuit.i(qr) circuits.append(circuit) # 4-qubit measure |1010> @@ -221,7 +225,7 @@ def measure_n(num_qubits): circuit.append(measure_n(4), [0, 1, 2, 3], [0, 1, 2, 3]) if not allow_sampling: circuit.barrier(qr) - circuit.iden(qr) + circuit.i(qr) circuits.append(circuit) return circuits @@ -304,7 +308,7 @@ def measure_n(num_qubits): circuit.append(measure_n(2), [0, 1], [0, 1]) if not allow_sampling: circuit.barrier(qr) - circuit.iden(qr) + circuit.i(qr) circuits.append(circuit) # 3-qubit measure |++0> @@ -317,7 +321,7 @@ def measure_n(num_qubits): circuit.append(measure_n(3), [0, 1, 2], [0, 1, 2]) if not allow_sampling: circuit.barrier(qr) - circuit.iden(qr) + circuit.i(qr) circuits.append(circuit) return circuits diff --git a/test/terra/reference/ref_pauli_noise.py b/test/terra/reference/ref_pauli_noise.py index 1527ca152d..e431c6fa63 100644 --- a/test/terra/reference/ref_pauli_noise.py +++ b/test/terra/reference/ref_pauli_noise.py @@ -20,6 +20,10 @@ from qiskit.providers.aer.noise import NoiseModel from qiskit.providers.aer.noise.errors.standard_errors import pauli_error +# Backwards compatibility for Terra <= 0.13 +if not hasattr(QuantumCircuit, 'i'): + QuantumCircuit.i = QuantumCircuit.iden + # ========================================================================== # Pauli Gate Errors @@ -34,28 +38,28 @@ def pauli_gate_error_circuits(): # 100% all-qubit Pauli error on "id" gate circuit = QuantumCircuit(qr, cr) - circuit.iden(qr) + circuit.i(qr) circuit.barrier(qr) circuit.measure(qr, cr) circuits.append(circuit) # 25% all-qubit Pauli error on "id" gates circuit = QuantumCircuit(qr, cr) - circuit.iden(qr) + circuit.i(qr) circuit.barrier(qr) circuit.measure(qr, cr) circuits.append(circuit) # 100% Pauli error on "id" gates on qubit-1 circuit = QuantumCircuit(qr, cr) - circuit.iden(qr) + circuit.i(qr) circuit.barrier(qr) circuit.measure(qr, cr) circuits.append(circuit) # 25% all-qubit Pauli error on "id" gates on qubit-0 circuit = QuantumCircuit(qr, cr) - circuit.iden(qr) + circuit.i(qr) circuit.barrier(qr) circuit.measure(qr, cr) circuits.append(circuit) diff --git a/test/terra/reference/ref_reset_noise.py b/test/terra/reference/ref_reset_noise.py index b83936e154..f167520570 100644 --- a/test/terra/reference/ref_reset_noise.py +++ b/test/terra/reference/ref_reset_noise.py @@ -20,6 +20,10 @@ from qiskit.providers.aer.noise import NoiseModel from qiskit.providers.aer.noise.errors.standard_errors import reset_error +# Backwards compatibility for Terra <= 0.13 +if not hasattr(QuantumCircuit, 'i'): + QuantumCircuit.i = QuantumCircuit.iden + # ========================================================================== # Reset Gate Errors @@ -60,7 +64,7 @@ def reset_gate_error_circuits(): qr = QuantumRegister(1, 'qr') cr = ClassicalRegister(1, 'cr') circuit = QuantumCircuit(qr, cr) - circuit.iden(qr) + circuit.i(qr) circuit.barrier(qr) circuit.measure(qr, cr) circuits.append(circuit) @@ -69,7 +73,7 @@ def reset_gate_error_circuits(): qr = QuantumRegister(2, 'qr') cr = ClassicalRegister(2, 'cr') circuit = QuantumCircuit(qr, cr) - circuit.iden(qr[0]) + circuit.i(qr[0]) circuit.x(qr[1]) circuit.barrier(qr) circuit.measure(qr, cr) diff --git a/test/terra/reference/ref_snapshot_expval.py b/test/terra/reference/ref_snapshot_expval.py index abe4ddb1c1..1eeb144676 100644 --- a/test/terra/reference/ref_snapshot_expval.py +++ b/test/terra/reference/ref_snapshot_expval.py @@ -18,6 +18,10 @@ from qiskit.quantum_info.states import Statevector from qiskit.providers.aer.extensions.snapshot_expectation_value import * +# Backwards compatibility for Terra <= 0.13 +if not hasattr(QuantumCircuit, 'i'): + QuantumCircuit.i = QuantumCircuit.iden + def snapshot_expval_labels(): """List of labels for exp val snapshots.""" @@ -69,7 +73,8 @@ def snapshot_expval_params(pauli=False): def snapshot_expval_circuits(pauli=False, single_shot=False, variance=False, - post_measure=False): + post_measure=False, + skip_measure=False): """SnapshotExpectationValue test circuits with deterministic counts""" circuits = [] @@ -91,7 +96,8 @@ def snapshot_expval_circuits(pauli=False, single_shot=single_shot, variance=variance) circuit.barrier(qr) - circuit.measure(qr, cr) + if not skip_measure: + circuit.measure(qr, cr) circuit.barrier(qr) if post_measure: for label, (params, @@ -116,7 +122,8 @@ def snapshot_expval_circuits(pauli=False, single_shot=single_shot, variance=variance) circuit.barrier(qr) - circuit.measure(qr, cr) + if not skip_measure: + circuit.measure(qr, cr) circuit.barrier(qr) if post_measure: for label, (params, @@ -131,7 +138,7 @@ def snapshot_expval_circuits(pauli=False, # State |10> -i|01> circuit = QuantumCircuit(*regs) circuit.h(0) - circuit.s(0) + circuit.sdg(0) circuit.cx(0, 1) circuit.x(1) if not post_measure: @@ -143,7 +150,8 @@ def snapshot_expval_circuits(pauli=False, single_shot=single_shot, variance=variance) circuit.barrier(qr) - circuit.measure(qr, cr) + if not skip_measure: + circuit.measure(qr, cr) circuit.barrier(qr) if post_measure: for label, (params, @@ -218,3 +226,103 @@ def snapshot_expval_post_meas_values(): values[label] = inner_dict targets.append(values) return targets + + +def snapshot_expval_circuit_parameterized(single_shot=False, + measure=True, + snapshot=False): + """SnapshotExpectationValue test circuits, rewritten as a single parameterized circuit and + parameterizations array. """ + + num_qubits = 2 + qr = QuantumRegister(num_qubits) + cr = ClassicalRegister(num_qubits) + regs = (qr, cr) + + circuit = QuantumCircuit(*regs) + circuit.u3(0, 0, 0, 0) + circuit.u1(0, 0) + circuit.u3(0, 0, 0, 1) + circuit.cu3(0, 0, 0, 0, 1) + circuit.u3(0, 0, 0, 1) + circuit.i(0) + if snapshot: + for label, (params, qubits) in snapshot_expval_params(pauli=True).items(): + circuit.snapshot_expectation_value(label, + params, + qubits, + single_shot=single_shot) + if measure: + circuit.barrier(qr) + circuit.measure(qr, cr) + circuit.barrier(qr) + + # Parameterizations + + # State |+1> + plus_one_params = { + # X on 0 + (0, 0): np.pi, + (0, 1): 0, + (0, 2): np.pi, + # No rZ + (1, 0): 0, + # H on 1 + (2, 0): np.pi / 2, + (2, 2): np.pi, + # No CrX + (3, 0): 0, + (3, 1): 0, + (3, 2): 0, + # No X + (4, 0): 0, + (4, 1): 0, + (4, 2): 0, + } + # State |00> + |11> + bell_params = { + # H 0 + (0, 0): np.pi / 2, + (0, 1): 0, + (0, 2): np.pi, + # No rZ + (1, 0): 0, + # No H + (2, 0): 0, + (2, 2): 0, + # CX from 0 on 1 + (3, 0): np.pi, + (3, 1): 0, + (3, 2): np.pi, + # No X + (4, 0): 0, + (4, 1): 0, + (4, 2): 0, + } + # State |10> -i|01> + iminus_bell_params = { + # H 0 + (0, 0): np.pi / 2, + (0, 1): 0, + (0, 2): np.pi, + # S 0 + (1, 0): - np.pi / 2, + # No H + (2, 0): 0, + (2, 2): 0, + # CX from 0 on 1 + (3, 0): np.pi, + (3, 1): 0, + (3, 2): np.pi, + # X 1 + (4, 0): np.pi, + (4, 1): 0, + (4, 2): np.pi, + } + param_mat = np.transpose([list(plus_one_params.values()), + list(bell_params.values()), + list(iminus_bell_params.values())]).tolist() + parameterizations = [[list(index), params] + for (index, params) in zip(plus_one_params.keys(), param_mat)] + + return circuit, parameterizations diff --git a/tools/verify_wheels.py b/tools/verify_wheels.py index 6b94c1479f..9f85c964b2 100644 --- a/tools/verify_wheels.py +++ b/tools/verify_wheels.py @@ -24,6 +24,10 @@ from qiskit.providers.aer import UnitarySimulator from qiskit.providers.aer import PulseSimulator +# Backwards compatibility for Terra <= 0.13 +if not hasattr(QuantumCircuit, 'i'): + QuantumCircuit.i = QuantumCircuit.iden + def assertAlmostEqual(first, second, places=None, msg=None, delta=None): @@ -114,7 +118,7 @@ def grovers_circuit(final_measure=True, allow_sampling=True): circuit.measure(qr[1], cr[1]) if not allow_sampling: circuit.barrier(qr) - circuit.iden(qr) + circuit.i(qr) circuits.append(circuit) return circuits