diff --git a/qiskit/providers/aer/backends/qasm_simulator.py b/qiskit/providers/aer/backends/qasm_simulator.py index e956252c1d..73eaedaf34 100644 --- a/qiskit/providers/aer/backends/qasm_simulator.py +++ b/qiskit/providers/aer/backends/qasm_simulator.py @@ -250,7 +250,8 @@ class QasmSimulator(AerBackend): 't', 'tdg', 'swap', 'ccx', 'r', 'rx', 'ry', 'rz', 'rxx', 'ryy', 'rzz', 'rzx', 'unitary', 'diagonal', 'initialize', 'cu1', 'cu2', 'cu3', 'cswap', 'mcx', 'mcy', 'mcz', 'mcrx', 'mcry', 'mcrz', 'mcr', - 'mcu1', 'mcu2', 'mcu3', 'mcswap', 'multiplexer', 'kraus', 'roerror' + 'mcu1', 'mcu2', 'mcu3', 'mcswap', 'p', 'cp', 'mcp', 'sx', 'csx', 'mcsx', + 'multiplexer', 'kraus', 'roerror' ], 'gates': [] } diff --git a/qiskit/providers/aer/backends/statevector_simulator.py b/qiskit/providers/aer/backends/statevector_simulator.py index 961e8a441b..c06beccdfa 100644 --- a/qiskit/providers/aer/backends/statevector_simulator.py +++ b/qiskit/providers/aer/backends/statevector_simulator.py @@ -92,7 +92,8 @@ class StatevectorSimulator(AerBackend): 't', 'tdg', 'swap', 'ccx', 'r', 'rx', 'ry', 'rz', 'rxx', 'ryy', 'rzz', 'rzx', 'unitary', 'diagonal', 'initialize', 'cu1', 'cu2', 'cu3', 'cswap', 'mcx', 'mcy', 'mcz', 'mcrx', 'mcry', 'mcrz', 'mcr', - 'mcu1', 'mcu2', 'mcu3', 'mcswap', 'multiplexer', + 'mcu1', 'mcu2', 'mcu3', 'mcswap', 'p', 'cp', 'mcp', 'sx', 'csx', 'mcsx', + 'multiplexer', ], 'gates': [] } diff --git a/qiskit/providers/aer/backends/unitary_simulator.py b/qiskit/providers/aer/backends/unitary_simulator.py index f4b91e6d0a..e441b3c124 100644 --- a/qiskit/providers/aer/backends/unitary_simulator.py +++ b/qiskit/providers/aer/backends/unitary_simulator.py @@ -100,7 +100,8 @@ class UnitarySimulator(AerBackend): 't', 'tdg', 'swap', 'ccx', 'r', 'rx', 'ry', 'rz', 'rxx', 'ryy', 'rzz', 'rzx', 'unitary', 'diagonal', 'cu1', 'cu2', 'cu3', 'cswap', 'mcx', 'mcy', 'mcz', 'mcrx', 'mcry', 'mcrz', 'mcr', - 'mcu1', 'mcu2', 'mcu3', 'mcswap', 'multiplexer', 'kraus', 'roerror' + 'mcu1', 'mcu2', 'mcu3', 'mcswap', 'p', 'cp', 'mcp', 'sx', 'csx', 'mcsx', + 'multiplexer' ], 'gates': [] } diff --git a/qiskit/providers/aer/noise/noise_model.py b/qiskit/providers/aer/noise/noise_model.py index 43838ab371..419f771a93 100644 --- a/qiskit/providers/aer/noise/noise_model.py +++ b/qiskit/providers/aer/noise/noise_model.py @@ -15,6 +15,7 @@ import json import logging +from warnings import warn from qiskit.circuit import Instruction from qiskit.providers import BaseBackend @@ -94,10 +95,10 @@ class NoiseModel: # Checks for standard 1-3 qubit instructions _1qubit_instructions = set([ "x90", "u1", "u2", "u3", "U", "id", "x", "y", "z", "h", "s", "sdg", - "t", "tdg", "r", "rx", "ry", "rz" + "t", "tdg", "r", "rx", "ry", "rz", "p" ]) _2qubit_instructions = set(["cx", "cz", "swap", "rxx", "ryy", "rzz", - "rzx", "cu1", "cu2", "cu3"]) + "rzx", "cu1", "cu2", "cu3", "cp"]) _3qubit_instructions = set(["ccx", "cswap"]) def __init__(self, basis_gates=None): @@ -415,6 +416,11 @@ def set_x90_single_qubit_gates(self, instructions): Raises: NoiseError: if the input instructions are not valid. """ + warn('This function is deprecated and will be removed in a future release. ' + 'To use an X90 based noise model use the Sqrt(X) "sx" gate and one of ' + ' the single-qubit phase gates "u1", "rx", "p" in the noise model and ' + ' basis gates to decompose into this gateset for noise simulations.', + DeprecationWarning) for name, label in self._instruction_names_labels(instructions): # Add X-90 based gate to noisy gates self._noise_instructions.add(label) diff --git a/releasenotes/notes/basis-gates-acbc8a1a52a49413.yaml b/releasenotes/notes/basis-gates-acbc8a1a52a49413.yaml new file mode 100644 index 0000000000..fb0b1883d0 --- /dev/null +++ b/releasenotes/notes/basis-gates-acbc8a1a52a49413.yaml @@ -0,0 +1,33 @@ +--- +features: + - | + Adds support for parameterized delay gate ``"delay"`` to the + :class:`~qiskit.providers.aer.StatevectorSimulator`, + :class:`~qiskit.providers.aer.UnitarySimulator`, and + :class:`~qiskit.providers.aer.QasmSimulator`. + By default this gate is treated as an identity gate during simulation. + - | + Adds support for parameterized phase gate ``"p"`` and controlled-phase + gate ``"cp"`` to the :class:`~qiskit.providers.aer.StatevectorSimulator`, + :class:`~qiskit.providers.aer.UnitarySimulator`, and the + ``"statevector"`` and ``"density_matrix"`` methods of the + :class:`~qiskit.providers.aer.QasmSimulator`. + - | + Adds support for the multi-controlled phase gate ``"mcphase"`` to the + :class:`~qiskit.providers.aer.StatevectorSimulator`, + :class:`~qiskit.providers.aer.UnitarySimulator`, and the + ``"statevector"`` method of the + :class:`~qiskit.providers.aer.QasmSimulator`. + - | + Adds support for the :math:`\sqrt(X)` gate ``"sx"`` to the + class:`~qiskit.providers.aer.StatevectorSimulator`, + :class:`~qiskit.providers.aer.UnitarySimulator`, and the + ``"statevector"`` and ``"density_matrix"`` methods of the + :class:`~qiskit.providers.aer.QasmSimulator`. +deprecations: + - | + :meth:`qiskit.providers.aer.noise.NoiseModel.set_x90_single_qubit_gates` has + been deprecated as unrolling to custom basis gates has been added to the + qiskit transpiler. The correct way to use an X90 based noise model is to + define noise on the Sqrt(X) "sx" or "rx" gate and one of the single-qubit + phase gates "u1", "rx", "p" in the noise model. diff --git a/src/framework/linalg/matrix_utils/matrix_defs.hpp b/src/framework/linalg/matrix_utils/matrix_defs.hpp index 56ae1bdbbe..6c663321b5 100755 --- a/src/framework/linalg/matrix_utils/matrix_defs.hpp +++ b/src/framework/linalg/matrix_utils/matrix_defs.hpp @@ -42,6 +42,7 @@ class Matrix { const static cmatrix_t SDG; // name: "sdg" const static cmatrix_t T; // name: "t" const static cmatrix_t TDG; // name: "tdg" + const static cmatrix_t SX; // name: "sx" const static cmatrix_t X90; // name: "x90" // Two-qubit gates @@ -70,9 +71,15 @@ class Matrix { static cmatrix_t rzz(double theta); static cmatrix_t rzx(double theta); // rotation around Tensor(X, Z) + // Phase Gates + static cmatrix_t phase(double theta); + static cmatrix_t phase_diag(double theta); + static cmatrix_t cphase(double theta); + static cmatrix_t cphase_diag(double theta); + // Complex arguments are implemented by taking std::real // of the input - static cmatrix_t u1(complex_t lam) { return u1(std::real(lam)); } + static cmatrix_t u1(complex_t lam) { return phase(std::real(lam)); } static cmatrix_t u2(complex_t phi, complex_t lam) { return u2(std::real(phi), std::real(lam)); } @@ -89,6 +96,10 @@ class Matrix { static cmatrix_t ryy(complex_t theta) { return ryy(std::real(theta)); } static cmatrix_t rzz(complex_t theta) { return rzz(std::real(theta)); } static cmatrix_t rzx(complex_t theta) { return rzx(std::real(theta)); } + static cmatrix_t phase(complex_t theta) { return phase(std::real(theta)); } + static cmatrix_t phase_diag(complex_t theta) { return phase_diag(std::real(theta)); } + static cmatrix_t cphase(complex_t theta) { return cphase(std::real(theta)); } + static cmatrix_t cphase_diag(complex_t theta) { return cphase_diag(std::real(theta)); } // Return the matrix for a named matrix string // Allowed names correspond to all the const static single-qubit @@ -138,6 +149,9 @@ const cmatrix_t Matrix::H = Utils::make_matrix( {{{1 / std::sqrt(2.), 0}, {1 / std::sqrt(2.), 0}}, {{1 / std::sqrt(2.), 0}, {-1 / std::sqrt(2.), 0}}}); +const cmatrix_t Matrix::SX = Utils::make_matrix( + {{{0.5, 0.5}, {0.5, -0.5}}, {{0.5, -0.5}, {0.5, 0.5}}}); + const cmatrix_t Matrix::X90 = Utils::make_matrix( {{{1. / std::sqrt(2.), 0}, {0, -1. / std::sqrt(2.)}}, {{0, -1. / std::sqrt(2.)}, {1. / std::sqrt(2.), 0}}}); @@ -172,7 +186,8 @@ const stringmap_t Matrix::label_map_ = { {"z", &Matrix::Z}, {"h", &Matrix::H}, {"s", &Matrix::S}, {"sdg", &Matrix::SDG}, {"t", &Matrix::T}, {"tdg", &Matrix::TDG}, {"x90", &Matrix::X90}, {"cx", &Matrix::CX}, {"cy", &Matrix::CY}, - {"cz", &Matrix::CZ}, {"swap", &Matrix::SWAP}}; + {"cz", &Matrix::CZ}, {"swap", &Matrix::SWAP}, {"sx", &Matrix::SX}, + {"delay", &Matrix::I}}; cmatrix_t Matrix::identity(size_t dim) { cmatrix_t mat(dim, dim); @@ -182,10 +197,7 @@ cmatrix_t Matrix::identity(size_t dim) { } cmatrix_t Matrix::u1(double lambda) { - cmatrix_t mat(2, 2); - mat(0, 0) = {1., 0.}; - mat(1, 1) = std::exp(complex_t(0., lambda)); - return mat; + return phase(lambda); } cmatrix_t Matrix::u2(double phi, double lambda) { @@ -306,6 +318,38 @@ cmatrix_t Matrix::rzx(double theta) { return mat; } +cmatrix_t Matrix::phase(double theta) { + cmatrix_t mat(2, 2); + mat(0, 0) = 1; + mat(1, 1) = std::exp(complex_t(0.0, theta)); + return mat; +} + +cmatrix_t Matrix::phase_diag(double theta) { + cmatrix_t mat(1, 2); + mat(0, 0) = 1; + mat(0, 1) = std::exp(complex_t(0.0, theta)); + return mat; +} + +cmatrix_t Matrix::cphase(double theta) { + cmatrix_t mat(4, 4); + mat(0, 0) = 1; + mat(1, 1) = 1; + mat(2, 2) = 1; + mat(3, 3) = std::exp(complex_t(0.0, theta)); + return mat; +} + +cmatrix_t Matrix::cphase_diag(double theta) { + cmatrix_t mat(1, 4); + mat(0, 0) = 1; + mat(0, 1) = 1; + mat(0, 2) = 1; + mat(0, 3) = std::exp(complex_t(0.0, theta)); + return mat; +} + //------------------------------------------------------------------------------ } // end namespace Linalg //------------------------------------------------------------------------------ diff --git a/src/framework/linalg/matrix_utils/smatrix_defs.hpp b/src/framework/linalg/matrix_utils/smatrix_defs.hpp index 9b61110e80..7f731de912 100755 --- a/src/framework/linalg/matrix_utils/smatrix_defs.hpp +++ b/src/framework/linalg/matrix_utils/smatrix_defs.hpp @@ -43,6 +43,7 @@ class SMatrix { const static cmatrix_t SDG; // name: "sdg" const static cmatrix_t T; // name: "t" const static cmatrix_t TDG; // name: "tdg" + const static cmatrix_t SX; // name: "sx" const static cmatrix_t X90; // name: "x90" // Two-qubit gates @@ -71,9 +72,15 @@ class SMatrix { static cmatrix_t rzz(double theta); static cmatrix_t rzx(double theta); // rotation around Tensor(X, Z) + // Phase Gates + static cmatrix_t phase(double theta); + static cmatrix_t phase_diag(double theta); + static cmatrix_t cphase_diag(double theta); + static cmatrix_t cphase(double theta); + // Complex arguments are implemented by taking std::real // of the input - static cmatrix_t u1(complex_t lam) { return u1(std::real(lam)); } + static cmatrix_t u1(complex_t lam) { return phase(std::real(lam)); } static cmatrix_t u2(complex_t phi, complex_t lam) { return u2(std::real(phi), std::real(lam)); } @@ -90,6 +97,10 @@ class SMatrix { static cmatrix_t ryy(complex_t theta) { return ryy(std::real(theta)); } static cmatrix_t rzz(complex_t theta) { return rzz(std::real(theta)); } static cmatrix_t rzx(complex_t theta) { return rzx(std::real(theta)); } + static cmatrix_t phase(complex_t theta) { return phase(std::real(theta)); } + static cmatrix_t phase_diag(complex_t theta) { return phase_diag(std::real(theta)); } + static cmatrix_t cphase(complex_t theta) { return cphase(std::real(theta)); } + static cmatrix_t cphase_diag(complex_t theta) { return cphase_diag(std::real(theta)); } // Return superoperator matrix for reset instruction // on specified dim statespace. @@ -135,6 +146,8 @@ const cmatrix_t SMatrix::TDG = Utils::unitary_superop(Matrix::TDG); const cmatrix_t SMatrix::H = Utils::unitary_superop(Matrix::H); +const cmatrix_t SMatrix::SX = Utils::unitary_superop(Matrix::SX); + const cmatrix_t SMatrix::X90 = Utils::unitary_superop(Matrix::X90); const cmatrix_t SMatrix::CX = Utils::unitary_superop(Matrix::CX); @@ -151,17 +164,13 @@ const stringmap_t SMatrix::label_map_ = { {"z", &SMatrix::Z}, {"h", &SMatrix::H}, {"s", &SMatrix::S}, {"sdg", &SMatrix::SDG}, {"t", &SMatrix::T}, {"tdg", &SMatrix::TDG}, {"x90", &SMatrix::X90}, {"cx", &SMatrix::CX}, {"cy", &SMatrix::CY}, - {"cz", &SMatrix::CZ}, {"swap", &SMatrix::SWAP}}; + {"cz", &SMatrix::CZ}, {"swap", &SMatrix::SWAP}, {"sx", &SMatrix::SX}, + {"delay", &SMatrix::I}}; cmatrix_t SMatrix::identity(size_t dim) { return Matrix::identity(dim * dim); } cmatrix_t SMatrix::u1(double lambda) { - cmatrix_t mat(4, 4); - mat(0, 0) = {1., 0.}; - mat(1, 1) = std::exp(complex_t(0., lambda)); - mat(2, 2) = std::exp(complex_t(0., -lambda)); - mat(3, 3) = {1., 0.}; - return mat; + return phase(lambda); } cmatrix_t SMatrix::u2(double phi, double lambda) { @@ -206,6 +215,70 @@ cmatrix_t SMatrix::rzx(double theta) { return Utils::tensor_product(Matrix::rzx(-theta), Matrix::rzx(theta)); } +cmatrix_t SMatrix::phase(double theta) { + cmatrix_t mat(4, 4); + mat(0, 0) = {1., 0.}; + mat(1, 1) = std::exp(complex_t(0., theta)); + mat(2, 2) = std::exp(complex_t(0., -theta)); + mat(3, 3) = {1., 0.}; + return mat; +} + +cmatrix_t SMatrix::phase_diag(double theta) { + cmatrix_t mat(1, 4); + mat(0, 0) = {1., 0.}; + mat(0, 1) = std::exp(complex_t(0., theta)); + mat(0, 2) = std::exp(complex_t(0., -theta)); + mat(0, 3) = {1., 0.}; + return mat; +} + +cmatrix_t SMatrix::cphase(double theta) { + const auto exp_p = std::exp(complex_t(0., theta)); + const auto exp_m = std::exp(complex_t(0., -theta)); + cmatrix_t mat(16, 16); + mat(0, 0) = {1., 0.}; + mat(1, 1) = {1., 0.}; + mat(2, 2) = {1., 0.}; + mat(3, 3) = exp_p; + mat(4, 4) = {1., 0.}; + mat(5, 5) = {1., 0.}; + mat(6, 6) = {1., 0.}; + mat(7, 7) = exp_p; + mat(8, 8) = {1., 0.}; + mat(9, 9) = {1., 0.}; + mat(10, 10) = {1., 0.}; + mat(11, 11) = exp_p; + mat(12, 12) = exp_m; + mat(13, 13) = exp_m; + mat(14, 14) = exp_m; + mat(15, 15) = {1., 0.}; + return mat; +} + +cmatrix_t SMatrix::cphase_diag(double theta) { + const auto exp_p = std::exp(complex_t(0., theta)); + const auto exp_m = std::exp(complex_t(0., -theta)); + cmatrix_t mat(1, 16); + mat(0, 0) = {1., 0.}; + mat(0, 1) = {1., 0.}; + mat(0, 2) = {1., 0.}; + mat(0, 3) = exp_p; + mat(0, 4) = {1., 0.}; + mat(0, 5) = {1., 0.}; + mat(0, 6) = {1., 0.}; + mat(0, 7) = exp_p; + mat(0, 8) = {1., 0.}; + mat(0, 9) = {1., 0.}; + mat(0, 10) = {1., 0.}; + mat(0, 11) = exp_p; + mat(0, 12) = exp_m; + mat(0, 13) = exp_m; + mat(0, 14) = exp_m; + mat(0, 15) = {1., 0.}; + return mat; +} + cmatrix_t SMatrix::reset(size_t dim) { cmatrix_t mat(dim * dim, dim * dim); for (size_t j = 0; j < dim; j++) { diff --git a/src/framework/linalg/matrix_utils/vmatrix_defs.hpp b/src/framework/linalg/matrix_utils/vmatrix_defs.hpp index fbc740d2ad..2c4e7adcd0 100755 --- a/src/framework/linalg/matrix_utils/vmatrix_defs.hpp +++ b/src/framework/linalg/matrix_utils/vmatrix_defs.hpp @@ -43,6 +43,7 @@ class VMatrix { const static cvector_t SDG; // name: "sdg" const static cvector_t T; // name: "t" const static cvector_t TDG; // name: "tdg" + const static cvector_t SX; // name: "sx" const static cvector_t X90; // name: "x90" // Two-qubit gates @@ -73,9 +74,15 @@ class VMatrix { static cvector_t rzx(double theta); // rotation around Tensor(X, Z) static cvector_t rzz_diag(double theta); // return the matrix diagonal + // Phase Gates + static cvector_t phase(double theta); + static cvector_t phase_diag(double theta); + static cvector_t cphase(double theta); + static cvector_t cphase_diag(double theta); + // Complex arguments are implemented by taking std::real // of the input - static cvector_t u1(complex_t lam) { return u1(std::real(lam)); } + static cvector_t u1(complex_t lam) { return phase(std::real(lam)); } static cvector_t u2(complex_t phi, complex_t lam) { return u2(std::real(phi), std::real(lam)); } @@ -94,6 +101,10 @@ class VMatrix { static cvector_t rzz(complex_t theta) { return rzz(std::real(theta)); } static cvector_t rzz_diag(complex_t theta) { return rzz_diag(std::real(theta)); } static cvector_t rzx(complex_t theta) { return rzx(std::real(theta)); } + static cvector_t phase(complex_t theta) { return phase(std::real(theta)); } + static cvector_t phase_diag(complex_t theta) { return phase_diag(std::real(theta)); } + static cvector_t cphase(complex_t theta) { return cphase(std::real(theta)); } + static cvector_t cphase_diag(complex_t theta) { return cphase_diag(std::real(theta)); } // Return the matrix for a named matrix string // Allowed names correspond to all the const static single-qubit @@ -134,6 +145,8 @@ const cvector_t VMatrix::TDG = Utils::vectorize_matrix(Matrix::TDG); const cvector_t VMatrix::H = Utils::vectorize_matrix(Matrix::H); +const cvector_t VMatrix::SX = Utils::vectorize_matrix(Matrix::SX); + const cvector_t VMatrix::X90 = Utils::vectorize_matrix(Matrix::X90); const cvector_t VMatrix::CX = Utils::vectorize_matrix(Matrix::CX); @@ -150,7 +163,8 @@ const stringmap_t VMatrix::label_map_ = { {"z", &VMatrix::Z}, {"h", &VMatrix::H}, {"s", &VMatrix::S}, {"sdg", &VMatrix::SDG}, {"t", &VMatrix::T}, {"tdg", &VMatrix::TDG}, {"x90", &VMatrix::X90}, {"cx", &VMatrix::CX}, {"cy", &VMatrix::CY}, - {"cz", &VMatrix::CZ}, {"swap", &VMatrix::SWAP}}; + {"cz", &VMatrix::CZ}, {"swap", &VMatrix::SWAP}, {"sx", &VMatrix::SX}, + {"delay", &VMatrix::I}}; cvector_t VMatrix::identity(size_t dim) { cvector_t mat(dim * dim); @@ -160,10 +174,7 @@ cvector_t VMatrix::identity(size_t dim) { } cvector_t VMatrix::u1(double lambda) { - cvector_t mat(2 * 2); - mat[0 + 0 * 2] = {1., 0.}; - mat[1 + 1 * 2] = std::exp(complex_t(0., lambda)); - return mat; + return phase(lambda); } cvector_t VMatrix::u2(double phi, double lambda) { @@ -297,6 +308,30 @@ cvector_t VMatrix::rzx(double theta) { return mat; } +cvector_t VMatrix::phase(double theta) { + cvector_t mat(2 * 2); + mat[0] = 1; + mat[3] = std::exp(complex_t(0.0, theta)); + return mat; +} + +cvector_t VMatrix::phase_diag(double theta) { + return {{1, std::exp(complex_t(0.0, theta))}}; +} + +cvector_t VMatrix::cphase(double theta) { + cvector_t mat(4 * 4); + mat[0] = 1; + mat[5] = 1; + mat[10] = 1; + mat[15] = std::exp(complex_t(0.0, theta)); + return mat; +} + +cvector_t VMatrix::cphase_diag(double theta) { + return {{1, 1, 1, std::exp(complex_t(0.0, theta))}}; +} + //------------------------------------------------------------------------------ } // end namespace Linalg //------------------------------------------------------------------------------ diff --git a/src/noise/noise_model.hpp b/src/noise/noise_model.hpp index 43960dc458..0b9b86030c 100644 --- a/src/noise/noise_model.hpp +++ b/src/noise/noise_model.hpp @@ -241,7 +241,7 @@ class NoiseModel { const static stringmap_t waltz_gate_table_; // Parameterized Gates - enum class ParamGate {u1, u2, u3, r, rx, ry, rz, rxx, ryy, rzz, rzx}; + enum class ParamGate {u1, u2, u3, r, rx, ry, rz, rxx, ryy, rzz, rzx, cp}; const static stringmap_t param_gate_table_; // waltz threshold for applying u1 rotations if |theta - 2n*pi | > threshold @@ -270,7 +270,10 @@ NoiseModel::param_gate_table_ = { {"rxx", ParamGate::rxx}, {"ryy", ParamGate::ryy}, {"rzz", ParamGate::rzz}, - {"rzx", ParamGate::rzx} + {"rzx", ParamGate::rzx}, + {"p", ParamGate::u1}, + {"cp", ParamGate::cp}, + {"cu1", ParamGate::cp} }; @@ -888,6 +891,8 @@ cmatrix_t NoiseModel::op2superop(const Operations::Op &op) const { return Linalg::SMatrix::rzz(op.params[0]); case ParamGate::rzx: return Linalg::SMatrix::rzx(op.params[0]); + case ParamGate::cp: + return Linalg::SMatrix::cphase(op.params[0]); } } else { // Check if we can convert this gate to a standard superoperator matrix @@ -932,6 +937,8 @@ cmatrix_t NoiseModel::op2unitary(const Operations::Op &op) const { return Linalg::Matrix::rzz(op.params[0]); case ParamGate::rzx: return Linalg::Matrix::rzx(op.params[0]); + case ParamGate::cp: + return Linalg::Matrix::cphase(op.params[0]); } } else { // Check if we can convert this gate to a standard superoperator matrix diff --git a/src/simulators/density_matrix/densitymatrix.hpp b/src/simulators/density_matrix/densitymatrix.hpp index 10fca33f75..9db6081360 100755 --- a/src/simulators/density_matrix/densitymatrix.hpp +++ b/src/simulators/density_matrix/densitymatrix.hpp @@ -99,8 +99,8 @@ class DensityMatrix : public UnitaryMatrix { // Apply a 2-qubit Controlled-NOT gate to the state vector void apply_cnot(const uint_t qctrl, const uint_t qtrgt); - // Apply a 2-qubit Controlled-Z gate to the state vector - void apply_cz(const uint_t q0, const uint_t q1); + // Apply 2-qubit controlled-phase gate + void apply_cphase(const uint_t q0, const uint_t q1, const complex_t &phase); // Apply a 2-qubit SWAP gate to the state vector void apply_swap(const uint_t q0, const uint_t q1); @@ -111,8 +111,8 @@ class DensityMatrix : public UnitaryMatrix { // Apply a single-qubit Pauli-Y gate to the state vector void apply_y(const uint_t qubit); - // Apply a single-qubit Pauli-Z gate to the state vector - void apply_z(const uint_t qubit); + // Apply 1-qubit phase gate + void apply_phase(const uint_t q, const complex_t &phase); // Apply a 3-qubit toffoli gate void apply_toffoli(const uint_t qctrl0, const uint_t qctrl1, const uint_t qtrgt); @@ -275,17 +275,32 @@ void DensityMatrix::apply_cnot(const uint_t qctrl, const uint_t qtrgt) { } template -void DensityMatrix::apply_cz(const uint_t q0, const uint_t q1) { +void DensityMatrix::apply_phase(const uint_t q, const complex_t &phase) { + const complex_t iphase = std::conj(phase); + // Lambda function for CZ gate + auto lambda = [&](const areg_t<1ULL << 2> &inds)->void { + BaseVector::data_[inds[1]] *= phase; + BaseVector::data_[inds[2]] *= iphase; + }; + const auto nq = num_qubits(); + const areg_t<2> qubits = {{q, q + nq}}; + BaseVector::apply_lambda(lambda, qubits); +} + +template +void DensityMatrix::apply_cphase(const uint_t q0, const uint_t q1, + const complex_t &phase) { + const complex_t iphase = std::conj(phase); // Lambda function for CZ gate auto lambda = [&](const areg_t<1ULL << 4> &inds)->void { - BaseVector::data_[inds[3]] *= -1.; - BaseVector::data_[inds[7]] *= -1.; - BaseVector::data_[inds[11]] *= -1.; - BaseVector::data_[inds[12]] *= -1.; - BaseVector::data_[inds[13]] *= -1.; - BaseVector::data_[inds[14]] *= -1.; + BaseVector::data_[inds[3]] *= phase; + BaseVector::data_[inds[7]] *= phase; + BaseVector::data_[inds[11]] *= phase; + BaseVector::data_[inds[12]] *= iphase; + BaseVector::data_[inds[13]] *= iphase; + BaseVector::data_[inds[14]] *= iphase; }; - const auto nq = num_qubits(); + const auto nq = num_qubits(); const areg_t<4> qubits = {{q0, q1, q0 + nq, q1 + nq}}; BaseVector::apply_lambda(lambda, qubits); } @@ -327,18 +342,6 @@ void DensityMatrix::apply_y(const uint_t qubit) { BaseVector::apply_lambda(lambda, qubits); } -template -void DensityMatrix::apply_z(const uint_t qubit) { - // Lambda function for Z gate superoperator - auto lambda = [&](const areg_t<1ULL << 2> &inds)->void { - BaseVector::data_[inds[1]] *= -1; - BaseVector::data_[inds[2]] *= -1; - }; - // Use the lambda function - const areg_t<2> qubits = {{qubit, qubit + num_qubits()}}; - BaseVector::apply_lambda(lambda, qubits); -} - template void DensityMatrix::apply_toffoli(const uint_t qctrl0, const uint_t qctrl1, diff --git a/src/simulators/density_matrix/densitymatrix_state.hpp b/src/simulators/density_matrix/densitymatrix_state.hpp index 2bc30b731c..8cc77e3f04 100644 --- a/src/simulators/density_matrix/densitymatrix_state.hpp +++ b/src/simulators/density_matrix/densitymatrix_state.hpp @@ -43,7 +43,8 @@ const Operations::OpSet StateOpSet( // Gates {"U", "CX", "u1", "u2", "u3", "cx", "cz", "swap", "id", "x", "y", "z", "h", "s", "sdg", "t", "tdg", "ccx", - "r", "rx", "ry", "rz", "rxx", "ryy", "rzz", "rzx"}, + "r", "rx", "ry", "rz", "rxx", "ryy", "rzz", "rzx", "p", + "cp","cu1", "sx", "x90", "delay"}, // Snapshots {"density_matrix", "memory", "register", "probabilities", "probabilities_with_variance", "expectation_value_pauli", @@ -51,8 +52,8 @@ const Operations::OpSet StateOpSet( // Allowed gates enum class enum class Gates { - u1, u2, u3, r, rx,ry, rz, id, x, y, z, h, s,sdg, t, tdg, - cx, cz, swap, rxx, ryy, rzz, rzx, ccx + u1, u2, u3, r, rx,ry, rz, id, x, y, z, h, s, sdg, sx, t, tdg, + cx, cz, swap, rxx, ryy, rzz, rzx, ccx, cp }; // Allowed snapshots enum class @@ -223,9 +224,6 @@ class State : public Base::State { void apply_gate_u3(const uint_t qubit, const double theta, const double phi, const double lambda); - // Optimize phase gate with diagonal [1, phase] - void apply_gate_phase(const uint_t qubit, const complex_t phase); - //----------------------------------------------------------------------- // Config Settings //----------------------------------------------------------------------- @@ -252,6 +250,7 @@ class State : public Base::State { template const stringmap_t State::gateset_({ // Single qubit gates + {"delay", Gates::id},// Delay gate {"id", Gates::id}, // Pauli-Identity gate {"x", Gates::x}, // Pauli-X gate {"y", Gates::y}, // Pauli-Y gate @@ -261,11 +260,14 @@ const stringmap_t State::gateset_({ {"h", Gates::h}, // Hadamard gate (X + Z / sqrt(2)) {"t", Gates::t}, // T-gate (sqrt(S)) {"tdg", Gates::tdg}, // Conjguate-transpose of T gate + {"x90", Gates::sx}, // Pi/2 X (equiv to Sqrt(X) gate) + {"sx", Gates::sx}, // Sqrt(X) gate {"r", Gates::r}, // R rotation gate {"rx", Gates::rx}, // Pauli-X rotation gate {"ry", Gates::ry}, // Pauli-Y rotation gate {"rz", Gates::rz}, // Pauli-Z rotation gate // Waltz Gates + {"p", Gates::u1}, // Phase gate {"u1", Gates::u1}, // zero-X90 pulse waltz gate {"u2", Gates::u2}, // single-X90 pulse waltz gate {"u3", Gates::u3}, // two X90 pulse waltz gate @@ -274,6 +276,8 @@ const stringmap_t State::gateset_({ {"CX", Gates::cx}, // Controlled-X gate (CNOT) {"cx", Gates::cx}, // Controlled-X gate (CNOT) {"cz", Gates::cz}, // Controlled-Z gate + {"cp", Gates::cp}, // Controlled-Phase gate + {"cu1", Gates::cp}, // Controlled-Phase gate {"swap", Gates::swap}, // SWAP gate {"rxx", Gates::rxx}, // Pauli-XX rotation gate {"ryy", Gates::ryy}, // Pauli-YY rotation gate @@ -663,13 +667,17 @@ void State::apply_gate(const Operations::Op &op) { std::real(op.params[1])); break; case Gates::u1: - apply_gate_phase(op.qubits[0], std::exp(complex_t(0., 1.) * op.params[0])); + BaseState::qreg_.apply_phase(op.qubits[0], std::exp(complex_t(0., 1.) * op.params[0])); break; case Gates::cx: BaseState::qreg_.apply_cnot(op.qubits[0], op.qubits[1]); break; case Gates::cz: - BaseState::qreg_.apply_cz(op.qubits[0], op.qubits[1]); + BaseState::qreg_.apply_cphase(op.qubits[0], op.qubits[1], -1); + break; + case Gates::cp: + BaseState::qreg_.apply_cphase(op.qubits[0], op.qubits[1], + std::exp(complex_t(0., 1.) * op.params[0])); break; case Gates::id: break; @@ -680,24 +688,27 @@ void State::apply_gate(const Operations::Op &op) { BaseState::qreg_.apply_y(op.qubits[0]); break; case Gates::z: - BaseState::qreg_.apply_z(op.qubits[0]); + BaseState::qreg_.apply_phase(op.qubits[0], -1); break; case Gates::h: apply_gate_u3(op.qubits[0], M_PI / 2., 0., M_PI); break; case Gates::s: - apply_gate_phase(op.qubits[0], complex_t(0., 1.)); + BaseState::qreg_.apply_phase(op.qubits[0], complex_t(0., 1.)); break; case Gates::sdg: - apply_gate_phase(op.qubits[0], complex_t(0., -1.)); + BaseState::qreg_.apply_phase(op.qubits[0], complex_t(0., -1.)); + break; + case Gates::sx: + BaseState::qreg_.apply_unitary_matrix(op.qubits, Linalg::VMatrix::SX); break; case Gates::t: { const double isqrt2{1. / std::sqrt(2)}; - apply_gate_phase(op.qubits[0], complex_t(isqrt2, isqrt2)); + BaseState::qreg_.apply_phase(op.qubits[0], complex_t(isqrt2, isqrt2)); } break; case Gates::tdg: { const double isqrt2{1. / std::sqrt(2)}; - apply_gate_phase(op.qubits[0], complex_t(isqrt2, -isqrt2)); + BaseState::qreg_.apply_phase(op.qubits[0], complex_t(isqrt2, -isqrt2)); } break; case Gates::swap: { BaseState::qreg_.apply_swap(op.qubits[0], op.qubits[1]); @@ -753,12 +764,6 @@ void State::apply_gate_u3(uint_t qubit, double theta, double phi, reg_t({qubit}), Linalg::VMatrix::u3(theta, phi, lambda)); } -template -void State::apply_gate_phase(uint_t qubit, complex_t phase) { - cvector_t diag = {{1., phase}}; - BaseState::qreg_.apply_diagonal_unitary_matrix(reg_t({qubit}), diag); -} - //========================================================================= // Implementation: Reset and Measurement Sampling //========================================================================= diff --git a/src/simulators/density_matrix/densitymatrix_thrust.hpp b/src/simulators/density_matrix/densitymatrix_thrust.hpp index 22a485f94d..ff76c3d762 100755 --- a/src/simulators/density_matrix/densitymatrix_thrust.hpp +++ b/src/simulators/density_matrix/densitymatrix_thrust.hpp @@ -103,8 +103,8 @@ class DensityMatrixThrust : public UnitaryMatrixThrust { // Apply a 2-qubit Controlled-NOT gate to the state vector void apply_cnot(const uint_t qctrl, const uint_t qtrgt); - // Apply a 2-qubit Controlled-Z gate to the state vector - void apply_cz(const uint_t q0, const uint_t q1); + // Apply 2-qubit controlled-phase gate + void apply_cphase(const uint_t q0, const uint_t q1, const complex_t &phase); // Apply a 2-qubit SWAP gate to the state vector void apply_swap(const uint_t q0, const uint_t q1); @@ -115,8 +115,8 @@ class DensityMatrixThrust : public UnitaryMatrixThrust { // Apply a single-qubit Pauli-Y gate to the state vector void apply_y(const uint_t qubit); - // Apply a single-qubit Pauli-Z gate to the state vector - void apply_z(const uint_t qubit); + // Apply 1-qubit phase gate + void apply_phase(const uint_t q, const complex_t &phase); // Apply a 3-qubit toffoli gate void apply_toffoli(const uint_t qctrl0, const uint_t qctrl1, const uint_t qtrgt); @@ -302,17 +302,19 @@ void DensityMatrixThrust::apply_cnot(const uint_t qctrl, const uint_t qt } template -void DensityMatrixThrust::apply_cz(const uint_t q0, const uint_t q1) { - cvector_t diag({1, 1, 1, -1, - 1, 1, 1, -1, - 1, 1, 1, -1, - -1, -1, -1, 1}); +void DensityMatrixThrust::apply_cphase(const uint_t q0, const uint_t q1, + const complex_t &phase) { + const complex_t iphase = std::conj(phase); + cvector_t diag({1, 1, 1, phase, + 1, 1, 1, phase, + 1, 1, 1, phase, + iphase, iphase, iphase, 1}); const auto nq = num_qubits(); const reg_t qubits = {{q0, q1, q0 + nq, q1 + nq}}; BaseVector::apply_diagonal_matrix(qubits, diag); #ifdef AER_DEBUG - BaseVector::DebugMsg(" density::apply_cz",qubits); + BaseVector::DebugMsg(" density::apply_cphase",qubits); #endif } @@ -465,14 +467,14 @@ void DensityMatrixThrust::apply_y(const uint_t qubit) { } template -void DensityMatrixThrust::apply_z(const uint_t qubit) { - cvector_t diag({1, -1, -1, 1}); +void DensityMatrixThrust::apply_phase(const uint_t qubit, const complex_t &phase) { + cvector_t diag({1, phase, std::conj(phase), 1}); // Use the lambda function const reg_t qubits = {{qubit, qubit + num_qubits()}}; BaseVector::apply_diagonal_matrix(qubits, diag); #ifdef AER_DEBUG - BaseVector::DebugMsg(" density::apply_z",qubits); + BaseVector::DebugMsg(" density::apply_phase",qubits); #endif } diff --git a/src/simulators/extended_stabilizer/extended_stabilizer_state.hpp b/src/simulators/extended_stabilizer/extended_stabilizer_state.hpp index d22158913d..0099e5b7a1 100644 --- a/src/simulators/extended_stabilizer/extended_stabilizer_state.hpp +++ b/src/simulators/extended_stabilizer/extended_stabilizer_state.hpp @@ -39,7 +39,7 @@ const Operations::OpSet StateOpSet( Operations::OpType::snapshot}, // Gates {"CX", "u0", "u1", "cx", "cz", "swap", "id", "x", "y", "z", "h", - "s", "sdg", "t", "tdg", "ccx", "ccz"}, + "s", "sdg", "t", "tdg", "ccx", "ccz", "delay"}, // Snapshots {"statevector", "probabilities", "memory", "register"} ); @@ -179,6 +179,7 @@ class State: public Base::State const stringmap_t State::gateset_({ // Single qubit gates + {"delay", Gates::id}, // Delay gate {"id", Gates::id}, // Pauli-Identity gate {"x", Gates::x}, // Pauli-X gate {"y", Gates::y}, // Pauli-Y gate diff --git a/src/simulators/stabilizer/stabilizer_state.hpp b/src/simulators/stabilizer/stabilizer_state.hpp index 80fa536719..1b5db45f0d 100644 --- a/src/simulators/stabilizer/stabilizer_state.hpp +++ b/src/simulators/stabilizer/stabilizer_state.hpp @@ -35,7 +35,7 @@ const Operations::OpSet StateOpSet( Operations::OpType::barrier, Operations::OpType::bfunc, Operations::OpType::roerror}, // Gates - {"CX", "cx", "cy", "cz", "swap", "id", "x", "y", "z", "h", "s", "sdg"}, + {"CX", "cx", "cy", "cz", "swap", "id", "x", "y", "z", "h", "s", "sdg", "delay"}, // Snapshots {"stabilizer", "memory", "register", "probabilities", "probabilities_with_variance", "expectation_value_pauli", @@ -191,6 +191,7 @@ class State : public Base::State { const stringmap_t State::gateset_({ // Single qubit gates + {"delay", Gates::id},// Delay gate {"id", Gates::id}, // Pauli-Identity gate {"x", Gates::x}, // Pauli-X gate {"y", Gates::y}, // Pauli-Y gate diff --git a/src/simulators/statevector/statevector_state.hpp b/src/simulators/statevector/statevector_state.hpp index 81f879f6a5..87a3c9d36f 100755 --- a/src/simulators/statevector/statevector_state.hpp +++ b/src/simulators/statevector/statevector_state.hpp @@ -45,7 +45,7 @@ const Operations::OpSet StateOpSet( "h", "s", "sdg", "t", "tdg", "r", "rx", "ry", "rz", "rxx", "ryy", "rzz", "rzx", "ccx", "cswap", "mcx", "mcy", "mcz", "mcu1", "mcu2", "mcu3", "mcswap", "mcphase", "mcr", - "mcrx", "mcry", "mcry"}, + "mcrx", "mcry", "mcry", "sx", "csx", "mcsx", "delay"}, // Snapshots {"statevector", "memory", "register", "probabilities", "probabilities_with_variance", "expectation_value_pauli", "density_matrix", @@ -58,8 +58,8 @@ const Operations::OpSet StateOpSet( enum class Gates { id, h, s, sdg, t, tdg, rxx, ryy, rzz, rzx, - mcx, mcy, mcz, mcr, mcrx, mcry, mcp, - mcrz, mcu1, mcu2, mcu3, mcswap + mcx, mcy, mcz, mcr, mcrx, mcry, + mcrz, mcp, mcu2, mcu3, mcswap, mcsx }; // Allowed snapshots enum class @@ -299,6 +299,7 @@ class State : public Base::State { template const stringmap_t State::gateset_({ // 1-qubit gates + {"delay", Gates::id},// Delay gate {"id", Gates::id}, // Pauli-Identity gate {"x", Gates::mcx}, // Pauli-X gate {"y", Gates::mcy}, // Pauli-Y gate @@ -309,20 +310,23 @@ const stringmap_t State::gateset_({ {"t", Gates::t}, // T-gate (sqrt(S)) {"tdg", Gates::tdg}, // Conjguate-transpose of T gate {"p", Gates::mcp}, // Parameterized phase gate + {"sx", Gates::mcsx}, // Sqrt(X) gate // 1-qubit rotation Gates {"r", Gates::mcr}, // R rotation gate {"rx", Gates::mcrx}, // Pauli-X rotation gate {"ry", Gates::mcry}, // Pauli-Y rotation gate {"rz", Gates::mcrz}, // Pauli-Z rotation gate // Waltz Gates - {"u1", Gates::mcu1}, // zero-X90 pulse waltz gate + {"p", Gates::mcp}, // Parameterized phase gate + {"u1", Gates::mcp}, // zero-X90 pulse waltz gate {"u2", Gates::mcu2}, // single-X90 pulse waltz gate {"u3", Gates::mcu3}, // two X90 pulse waltz gate // 2-qubit gates {"cx", Gates::mcx}, // Controlled-X gate (CNOT) {"cy", Gates::mcy}, // Controlled-Y gate {"cz", Gates::mcz}, // Controlled-Z gate - {"cu1", Gates::mcu1}, // Controlled-u1 gate + {"cp", Gates::mcp}, // Controlled-Phase gate + {"cu1", Gates::mcp}, // Controlled-u1 gate {"cu2", Gates::mcu2}, // Controlled-u2 gate {"cu3", Gates::mcu3}, // Controlled-u3 gate {"cp", Gates::mcp}, // Controlled-Phase gate @@ -331,6 +335,7 @@ const stringmap_t State::gateset_({ {"ryy", Gates::ryy}, // Pauli-YY rotation gate {"rzz", Gates::rzz}, // Pauli-ZZ rotation gate {"rzx", Gates::rzx}, // Pauli-ZX rotation gate + {"csx", Gates::mcsx}, // Controlled-Sqrt(X) gate // 3-qubit gates {"ccx", Gates::mcx}, // Controlled-CX gate (Toffoli) {"cswap", Gates::mcswap}, // Controlled SWAP gate (Fredkin) @@ -342,12 +347,13 @@ const stringmap_t State::gateset_({ {"mcrx", Gates::mcrx}, // Multi-controlled X-rotation gate {"mcry", Gates::mcry}, // Multi-controlled Y-rotation gate {"mcrz", Gates::mcrz}, // Multi-controlled Z-rotation gate - {"mcu1", Gates::mcu1}, // Multi-controlled-u1 + {"mcphase", Gates::mcp}, // Multi-controlled-Phase gate + {"mcu1", Gates::mcp}, // Multi-controlled-u1 {"mcu2", Gates::mcu2}, // Multi-controlled-u2 {"mcu3", Gates::mcu3}, // Multi-controlled-u3 {"mcphase", Gates::mcp}, // Multi-controlled-Phase gate - {"mcswap", Gates::mcswap} // Multi-controlled SWAP gate - + {"mcswap", Gates::mcswap},// Multi-controlled SWAP gate + {"mcsx", Gates::mcsx} // Multi-controlled-Sqrt(X) gate }); template @@ -805,10 +811,6 @@ void State::apply_gate(const Operations::Op &op) { // Includes Z, CZ, CCZ, etc BaseState::qreg_.apply_mcphase(op.qubits, -1); break; - case Gates::mcp: - // Includes Phase, CPhase, MCPhase, etc - BaseState::qreg_.apply_mcphase(op.qubits, op.params[0]); - break; case Gates::mcr: BaseState::qreg_.apply_mcu(op.qubits, Linalg::VMatrix::r(op.params[0], op.params[1])); break; @@ -866,10 +868,14 @@ void State::apply_gate(const Operations::Op &op) { apply_gate_mcu3(op.qubits, M_PI / 2., std::real(op.params[0]), std::real(op.params[1])); break; - case Gates::mcu1: - // Includes u1, cu1, etc + case Gates::mcp: + // Includes u1, cu1, p, cp, mcp etc BaseState::qreg_.apply_mcphase(op.qubits, - std::exp(complex_t(0, 1) * op.params[0])); + std::exp(complex_t(0, 1) * op.params[0])); + break; + case Gates::mcsx: + // Includes sx, csx, mcsx etc + BaseState::qreg_.apply_mcu(op.qubits, Linalg::VMatrix::SX); break; default: // We shouldn't reach here unless there is a bug in gateset diff --git a/src/simulators/superoperator/superoperator_state.hpp b/src/simulators/superoperator/superoperator_state.hpp index 8c6b6ec77d..f6246476f7 100755 --- a/src/simulators/superoperator/superoperator_state.hpp +++ b/src/simulators/superoperator/superoperator_state.hpp @@ -37,14 +37,15 @@ const Operations::OpSet StateOpSet( // Gates {"U", "CX", "u1", "u2", "u3", "cx", "cz", "swap", "id", "x", "y", "z", "h", "s", "sdg", "t", "tdg", "ccx", - "r", "rx", "ry", "rz", "rxx", "ryy", "rzz", "rzx"}, + "r", "rx", "ry", "rz", "rxx", "ryy", "rzz", "rzx", "p", + "cp", "cu1", "sx", "x90", "delay"}, // Snapshots {"superoperator"}); // Allowed gates enum class enum class Gates { - u2, u1, u3, id, x, y, z, h, s, sdg, t, tdg, r, rx, ry, rz, - cx, cz, swap, rxx, ryy, rzz, rzx, ccx + u2, u1, u3, id, x, y, z, h, s, sdg, sx, t, tdg, r, rx, ry, rz, + cx, cz, cp, swap, rxx, ryy, rzz, rzx, ccx }; // Allowed snapshots enum class @@ -131,13 +132,6 @@ class State : public Base::State { // Apply a Kraus error operation void apply_kraus(const reg_t &qubits, const std::vector &krausops); - //----------------------------------------------------------------------- - // 1-Qubit Gates - //----------------------------------------------------------------------- - - // Optimize phase gate with diagonal [1, phase] - void apply_gate_phase(const uint_t qubit, const complex_t phase); - //----------------------------------------------------------------------- // Multi-controlled u3 //----------------------------------------------------------------------- @@ -169,6 +163,7 @@ class State : public Base::State { template const stringmap_t State::gateset_({ // Single qubit gates + {"delay", Gates::id},// Delay gate {"id", Gates::id}, // Pauli-Identity gate {"x", Gates::x}, // Pauli-X gate {"y", Gates::y}, // Pauli-Y gate @@ -178,11 +173,14 @@ const stringmap_t State::gateset_({ {"h", Gates::h}, // Hadamard gate (X + Z / sqrt(2)) {"t", Gates::t}, // T-gate (sqrt(S)) {"tdg", Gates::tdg}, // Conjguate-transpose of T gate + {"x90", Gates::sx}, // Pi/2 X (equiv to Sqrt(X) gate) + {"sx", Gates::sx}, // Sqrt(X) gate {"r", Gates::r}, // R rotation gate {"rx", Gates::rx}, // Pauli-X rotation gate {"ry", Gates::ry}, // Pauli-Y rotation gate {"rz", Gates::rz}, // Pauli-Z rotation gate // Waltz Gates + {"p", Gates::u1}, // Phase gate {"u1", Gates::u1}, // zero-X90 pulse waltz gate {"u2", Gates::u2}, // single-X90 pulse waltz gate {"u3", Gates::u3}, // two X90 pulse waltz gate @@ -191,6 +189,8 @@ const stringmap_t State::gateset_({ {"CX", Gates::cx}, // Controlled-X gate (CNOT) {"cx", Gates::cx}, // Controlled-X gate (CNOT) {"cz", Gates::cz}, // Controlled-Z gate + {"cp", Gates::cp}, // Controlled-Phase gate + {"cu1", Gates::cp}, // Controlled-Phase gate {"swap", Gates::swap}, // SWAP gate {"rxx", Gates::rxx}, // Pauli-XX rotation gate {"ryy", Gates::ryy}, // Pauli-YY rotation gate @@ -351,7 +351,7 @@ void State::apply_gate(const Operations::Op &op) { std::real(op.params[1])); break; case Gates::u1: - apply_gate_phase(op.qubits[0], std::exp(complex_t(0., 1.) * op.params[0])); + BaseState::qreg_.apply_phase(op.qubits[0], std::exp(complex_t(0., 1.) * op.params[0])); break; case Gates::r: apply_matrix(op.qubits, Linalg::VMatrix::r(op.params[0], op.params[1])); @@ -381,7 +381,11 @@ void State::apply_gate(const Operations::Op &op) { BaseState::qreg_.apply_cnot(op.qubits[0], op.qubits[1]); break; case Gates::cz: - BaseState::qreg_.apply_cz(op.qubits[0], op.qubits[1]); + BaseState::qreg_.apply_cphase(op.qubits[0], op.qubits[1], -1); + break; + case Gates::cp: + BaseState::qreg_.apply_cphase(op.qubits[0], op.qubits[1], + std::exp(complex_t(0., 1.) * op.params[0])); break; case Gates::id: break; @@ -392,24 +396,27 @@ void State::apply_gate(const Operations::Op &op) { BaseState::qreg_.apply_y(op.qubits[0]); break; case Gates::z: - BaseState::qreg_.apply_z(op.qubits[0]); + BaseState::qreg_.apply_phase(op.qubits[0], -1); break; case Gates::h: apply_gate_u3(op.qubits[0], M_PI / 2., 0., M_PI); break; case Gates::s: - apply_gate_phase(op.qubits[0], complex_t(0., 1.)); + BaseState::qreg_.apply_phase(op.qubits[0], complex_t(0., 1.)); break; case Gates::sdg: - apply_gate_phase(op.qubits[0], complex_t(0., -1.)); + BaseState::qreg_.apply_phase(op.qubits[0], complex_t(0., -1.)); + break; + case Gates::sx: + BaseState::qreg_.apply_unitary_matrix(op.qubits, Linalg::VMatrix::SX); break; case Gates::t: { const double isqrt2{1. / std::sqrt(2)}; - apply_gate_phase(op.qubits[0], complex_t(isqrt2, isqrt2)); + BaseState::qreg_.apply_phase(op.qubits[0], complex_t(isqrt2, isqrt2)); } break; case Gates::tdg: { const double isqrt2{1. / std::sqrt(2)}; - apply_gate_phase(op.qubits[0], complex_t(isqrt2, -isqrt2)); + BaseState::qreg_.apply_phase(op.qubits[0], complex_t(isqrt2, -isqrt2)); } break; case Gates::swap: { BaseState::qreg_.apply_swap(op.qubits[0], op.qubits[1]); @@ -441,14 +448,6 @@ void State::apply_matrix(const reg_t &qubits, const cvector_t &vmat) { } } -template -void State::apply_gate_phase(uint_t qubit, complex_t phase) { - cvector_t diag(2); - diag[0] = 1.0; - diag[1] = phase; - BaseState::qreg_.apply_diagonal_unitary_matrix(reg_t({qubit}), diag); -} - template void State::apply_gate_u3(const uint_t qubit, double theta, double phi, double lambda) { diff --git a/src/simulators/unitary/unitary_state.hpp b/src/simulators/unitary/unitary_state.hpp index 6bfb4b6ad5..ebb4898095 100755 --- a/src/simulators/unitary/unitary_state.hpp +++ b/src/simulators/unitary/unitary_state.hpp @@ -42,14 +42,14 @@ const Operations::OpSet StateOpSet( "h", "s", "sdg", "t", "tdg", "r", "rx", "ry", "rz", "rxx", "ryy", "rzz", "rzx", "ccx", "cswap", "mcx", "mcy", "mcz", "mcu1", "mcu2", "mcu3", "mcswap", "mcphase", "mcr", - "mcrx", "mcry", "mcry"}, + "mcrx", "mcry", "mcry", "sx", "csx", "mcsx", "delay"}, // Snapshots {"unitary"}); // Allowed gates enum class enum class Gates { id, h, s, sdg, t, tdg, rxx, ryy, rzz, rzx, - mcx, mcy, mcz, mcr, mcrx, mcry, mcrz, mcu1, mcu2, mcu3, mcp, mcswap + mcx, mcy, mcz, mcr, mcrx, mcry, mcrz, mcp, mcu2, mcu3, mcswap, mcsx }; //========================================================================= @@ -166,6 +166,7 @@ class State : public Base::State { template const stringmap_t State::gateset_({ // Single qubit gates + {"delay", Gates::id},// Delay gate {"id", Gates::id}, // Pauli-Identity gate {"x", Gates::mcx}, // Pauli-X gate {"y", Gates::mcy}, // Pauli-Y gate @@ -175,21 +176,24 @@ const stringmap_t State::gateset_({ {"h", Gates::h}, // Hadamard gate (X + Z / sqrt(2)) {"t", Gates::t}, // T-gate (sqrt(S)) {"tdg", Gates::tdg}, // Conjguate-transpose of T gate - {"p", Gates::mcp}, // Parameterized phase gate + {"p", Gates::mcp}, // Parameterized phase gate + {"sx", Gates::mcsx}, // Sqrt(X) gate // 1-qubit rotation Gates {"r", Gates::mcr}, // R rotation gate {"rx", Gates::mcrx}, // Pauli-X rotation gate {"ry", Gates::mcry}, // Pauli-Y rotation gate {"rz", Gates::mcrz}, // Pauli-Z rotation gate // Waltz Gates - {"u1", Gates::mcu1}, // zero-X90 pulse waltz gate + {"p", Gates::mcp}, // Parameterized phase gate + {"u1", Gates::mcp}, // zero-X90 pulse waltz gate {"u2", Gates::mcu2}, // single-X90 pulse waltz gate {"u3", Gates::mcu3}, // two X90 pulse waltz gate // Two-qubit gates {"cx", Gates::mcx}, // Controlled-X gate (CNOT) {"cy", Gates::mcy}, // Controlled-Z gate {"cz", Gates::mcz}, // Controlled-Z gate - {"cu1", Gates::mcu1}, // Controlled-u1 gate + {"cp", Gates::mcp}, // Controlled-Phase gate + {"cu1", Gates::mcp}, // Controlled-u1 gate {"cu2", Gates::mcu2}, // Controlled-u2 {"cu3", Gates::mcu3}, // Controlled-u3 gate {"cp", Gates::mcp}, // Controlled-Phase gate @@ -198,6 +202,7 @@ const stringmap_t State::gateset_({ {"ryy", Gates::ryy}, // Pauli-YY rotation gate {"rzz", Gates::rzz}, // Pauli-ZZ rotation gate {"rzx", Gates::rzx}, // Pauli-ZX rotation gate + {"csx", Gates::mcsx}, // Controlled-Sqrt(X) gate // Three-qubit gates {"ccx", Gates::mcx}, // Controlled-CX gate (Toffoli) {"cswap", Gates::mcswap}, // Controlled-SWAP gate (Fredkin) @@ -209,11 +214,13 @@ const stringmap_t State::gateset_({ {"mcrx", Gates::mcrx}, // Multi-controlled X-rotation gate {"mcry", Gates::mcry}, // Multi-controlled Y-rotation gate {"mcrz", Gates::mcrz}, // Multi-controlled Z-rotation gate - {"mcu1", Gates::mcu1}, // Multi-controlled-u1 + {"mcphase", Gates::mcp}, // Multi-controlled-Phase gate + {"mcu1", Gates::mcp}, // Multi-controlled-u1 {"mcu2", Gates::mcu2}, // Multi-controlled-u2 {"mcu3", Gates::mcu3}, // Multi-controlled-u3 {"mcphase", Gates::mcp}, // Multi-controlled-Phase gate - {"mcswap", Gates::mcswap} // Multi-controlled-SWAP gate + {"mcswap", Gates::mcswap},// Multi-controlled SWAP gate + {"mcsx", Gates::mcsx} // Multi-controlled-Sqrt(X) gate }); //============================================================================ @@ -344,10 +351,6 @@ void State::apply_gate(const Operations::Op &op) { // Includes Z, CZ, CCZ, etc BaseState::qreg_.apply_mcphase(op.qubits, -1); break; - case Gates::mcp: - // Includes Phase, CPhase, MCPhase, etc - BaseState::qreg_.apply_mcphase(op.qubits, op.params[0]); - break; case Gates::mcr: BaseState::qreg_.apply_mcu(op.qubits, Linalg::VMatrix::r(op.params[0], op.params[1])); break; @@ -405,10 +408,14 @@ void State::apply_gate(const Operations::Op &op) { apply_gate_mcu3(op.qubits, M_PI / 2., std::real(op.params[0]), std::real(op.params[1])); break; - case Gates::mcu1: - // Includes u1, cu1, etc + case Gates::mcp: + // Includes u1, cu1, p, cp, mcp, etc BaseState::qreg_.apply_mcphase(op.qubits, - std::exp(complex_t(0, 1) * op.params[0])); + std::exp(complex_t(0, 1) * op.params[0])); + break; + case Gates::mcsx: + // Includes sx, csx, mcsx etc + BaseState::qreg_.apply_mcu(op.qubits, Linalg::VMatrix::SX); break; default: // We shouldn't reach here unless there is a bug in gateset diff --git a/test/terra/backends/qasm_simulator/qasm_standard_gates.py b/test/terra/backends/qasm_simulator/qasm_standard_gates.py index ddc8a1ed2d..706d31f712 100644 --- a/test/terra/backends/qasm_simulator/qasm_standard_gates.py +++ b/test/terra/backends/qasm_simulator/qasm_standard_gates.py @@ -84,11 +84,11 @@ DENSITY_MATRIX_BG = [ "u1", "u2", "u3", "cx", "cz", "swap", "id", "x", "y", "z", "h", "s", "sdg", "t", "tdg", "ccx", "r", "rx", "ry", "rz", "rxx", "ryy", "rzz", - "rzx" + "rzx", "p", "cp", "cu1", "sx", "delay", ] MATRIX_PRODUCT_STATE_BG = [ "id", "x", "y", "z", "s", "sdg", "h", "t", "tdg", "u1", "u2", "u3", - "cx", "cz", "cu1", "swap", "ccx" + "cx", "cz", "cu1", "swap", "ccx", "delay", ] BASIS_GATES = { 'statevector': STATEVECTOR_BG, diff --git a/test/terra/backends/statevector_simulator/statevector_gates.py b/test/terra/backends/statevector_simulator/statevector_gates.py index 0493122c81..85a1bca3c3 100644 --- a/test/terra/backends/statevector_simulator/statevector_gates.py +++ b/test/terra/backends/statevector_simulator/statevector_gates.py @@ -89,9 +89,8 @@ class StatevectorGateTests: (U3Gate, 3), (UGate, 3) ] - BASIS_GATES = [ - None, ['id', 'u3', 'cx'], ['id', 'r', 'cz'], ['id', 'rz', 'rx', 'cx'] - ] + BASIS_GATES = [None, ['id', 'u3', 'cx'], ['id', 'r', 'cz'], + ['id', 'rz', 'rx', 'cz'], ['id', 'p', 'sx', 'cx']] @data(*[(gate_params[0], gate_params[1], basis_gates) for gate_params, basis_gates in product(GATES, BASIS_GATES)]) diff --git a/test/terra/backends/unitary_simulator/unitary_gates.py b/test/terra/backends/unitary_simulator/unitary_gates.py index 3f18db33ec..28eeb0f037 100644 --- a/test/terra/backends/unitary_simulator/unitary_gates.py +++ b/test/terra/backends/unitary_simulator/unitary_gates.py @@ -89,9 +89,8 @@ class UnitaryGateTests: (U3Gate, 3), (UGate, 3) ] - BASIS_GATES = [ - None, ['id', 'u3', 'cx'], ['id', 'r', 'cz'], ['id', 'rz', 'rx', 'cx'] - ] + BASIS_GATES = [None, ['id', 'u3', 'cx'], ['id', 'r', 'cz'], + ['id', 'rz', 'rx', 'cz'], ['id', 'p', 'sx', 'cx']] @data(*[(gate_params[0], gate_params[1], basis_gates) for gate_params, basis_gates in product(GATES, BASIS_GATES)])