Skip to content

Commit

Permalink
Add support for rotation gates (#2147)
Browse files Browse the repository at this point in the history
* add rotation gates

* add cr* gates to operations.hpp

* fix test for stabilkize/extended-stabilizer

* fix test again
  • Loading branch information
doichanj authored May 28, 2024
1 parent 83d679e commit 5e9be0b
Show file tree
Hide file tree
Showing 13 changed files with 135 additions and 91 deletions.
1 change: 1 addition & 0 deletions qiskit_aer/backends/aer_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,7 @@ def _assemble_op(
"mcu", "mcu1", "mcu2", "mcu3", "mcx", "mcx_gray", "mcy", "mcz", "p", "r",
"rx", "rxx", "ry", "ryy", "rz", "rzx", "rzz", "s", "sdg", "swap", "sx", "sxdg",
"t", "tdg", "u", "x", "y", "z", "u1", "u2", "u3", "cu", "cu1", "cu2", "cu3",
"crx", "cry", "crz",
}:
aer_circ.gate(name, qubits, params, [], conditional_reg, aer_cond_expr,
label if label else name)
Expand Down
12 changes: 10 additions & 2 deletions qiskit_aer/backends/backend_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@
"rzx",
"ccx",
"ccz",
"crx",
"cry",
"crz",
"cswap",
"mcx",
"mcy",
Expand Down Expand Up @@ -217,8 +220,6 @@
"delay",
"pauli",
"ecr",
"rx",
"ry",
"rz",
]
),
Expand All @@ -245,6 +246,7 @@
"ccz",
"delay",
"pauli",
"rz",
]
),
"unitary": sorted(
Expand Down Expand Up @@ -286,6 +288,9 @@
"ccx",
"ccz",
"cswap",
"crx",
"cry",
"crz",
"mcx",
"mcy",
"mcz",
Expand Down Expand Up @@ -387,6 +392,9 @@
"ccx",
"ccz",
"cswap",
"crx",
"cry",
"crz",
"mcx",
"mcy",
"mcz",
Expand Down
8 changes: 8 additions & 0 deletions releasenotes/notes/add_rotation_support-c0ef8155a761e560.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
features:
- |
Add `rz` gate with n*pi/2 cases to `extended_stabilizer` method
as well as `stabilizer` method.
Add `crx`, `cry` and `crz` gates to `statevector` and `tensor_netowork`
methods.
44 changes: 23 additions & 21 deletions src/framework/operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -724,27 +724,29 @@ inline void check_duplicate_qubits(const Op &op) {
}

inline void check_gate_params(const Op &op) {
const stringmap_t<std::tuple<int_t, int_t>> param_tables(
{{"u1", {1, 1}}, {"u2", {1, 2}}, {"u3", {1, 3}},
{"u", {1, 3}}, {"U", {1, 3}}, {"CX", {2, 0}},
{"cx", {2, 0}}, {"cz", {2, 0}}, {"cy", {2, 0}},
{"cp", {2, 1}}, {"cu1", {2, 1}}, {"cu2", {2, 2}},
{"cu3", {2, 3}}, {"swap", {2, 0}}, {"id", {0, 0}},
{"p", {1, 1}}, {"x", {1, 0}}, {"y", {1, 0}},
{"z", {1, 0}}, {"h", {1, 0}}, {"s", {1, 0}},
{"sdg", {1, 0}}, {"t", {1, 0}}, {"tdg", {1, 0}},
{"r", {1, 2}}, {"rx", {1, 1}}, {"ry", {1, 1}},
{"rz", {1, 1}}, {"rxx", {2, 1}}, {"ryy", {2, 1}},
{"rzz", {2, 1}}, {"rzx", {2, 1}}, {"ccx", {3, 0}},
{"ccz", {3, 0}}, {"cswap", {3, 0}}, {"mcx", {1, 0}},
{"mcy", {1, 0}}, {"mcz", {1, 0}}, {"mcu1", {1, 1}},
{"mcu2", {1, 2}}, {"mcu3", {1, 3}}, {"mcswap", {2, 0}},
{"mcphase", {1, 1}}, {"mcr", {1, 1}}, {"mcrx", {1, 1}},
{"mcry", {1, 1}}, {"mcrz", {1, 1}}, {"sx", {1, 0}},
{"sxdg", {1, 0}}, {"csx", {2, 0}}, {"mcsx", {1, 0}},
{"csxdg", {2, 0}}, {"mcsxdg", {1, 0}}, {"delay", {1, 0}},
{"pauli", {1, 0}}, {"mcx_gray", {1, 0}}, {"cu", {2, 4}},
{"mcu", {1, 4}}, {"mcp", {1, 1}}, {"ecr", {2, 0}}});
const stringmap_t<std::tuple<int_t, int_t>> param_tables({
{"u1", {1, 1}}, {"u2", {1, 2}}, {"u3", {1, 3}},
{"u", {1, 3}}, {"U", {1, 3}}, {"CX", {2, 0}},
{"cx", {2, 0}}, {"cz", {2, 0}}, {"cy", {2, 0}},
{"cp", {2, 1}}, {"cu1", {2, 1}}, {"cu2", {2, 2}},
{"cu3", {2, 3}}, {"swap", {2, 0}}, {"id", {0, 0}},
{"p", {1, 1}}, {"x", {1, 0}}, {"y", {1, 0}},
{"z", {1, 0}}, {"h", {1, 0}}, {"s", {1, 0}},
{"sdg", {1, 0}}, {"t", {1, 0}}, {"tdg", {1, 0}},
{"r", {1, 2}}, {"rx", {1, 1}}, {"ry", {1, 1}},
{"rz", {1, 1}}, {"rxx", {2, 1}}, {"ryy", {2, 1}},
{"rzz", {2, 1}}, {"rzx", {2, 1}}, {"ccx", {3, 0}},
{"ccz", {3, 0}}, {"cswap", {3, 0}}, {"mcx", {1, 0}},
{"mcy", {1, 0}}, {"mcz", {1, 0}}, {"mcu1", {1, 1}},
{"mcu2", {1, 2}}, {"mcu3", {1, 3}}, {"mcswap", {2, 0}},
{"mcphase", {1, 1}}, {"mcr", {1, 1}}, {"mcrx", {1, 1}},
{"mcry", {1, 1}}, {"mcrz", {1, 1}}, {"sx", {1, 0}},
{"sxdg", {1, 0}}, {"csx", {2, 0}}, {"mcsx", {1, 0}},
{"csxdg", {2, 0}}, {"mcsxdg", {1, 0}}, {"delay", {1, 0}},
{"pauli", {1, 0}}, {"mcx_gray", {1, 0}}, {"cu", {2, 4}},
{"mcu", {1, 4}}, {"mcp", {1, 1}}, {"ecr", {2, 0}},
{"crx", {1, 1}}, {"cry", {1, 1}}, {"crz", {1, 1}},
});

auto it = param_tables.find(op.name);
if (it == param_tables.end()) {
Expand Down
41 changes: 38 additions & 3 deletions src/simulators/extended_stabilizer/extended_stabilizer_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ const Operations::OpSet StateOpSet(
Operations::OpType::save_statevec,
}, // Operations::OpType::save_expval, Operations::OpType::save_expval_var},
// Gates
{"CX", "u0", "u1", "p", "cx", "cz", "swap", "id",
"x", "y", "z", "h", "s", "sdg", "sx", "sxdg",
"t", "tdg", "ccx", "ccz", "delay", "pauli"});
{"CX", "u0", "u1", "p", "cx", "cz", "swap", "id",
"x", "y", "z", "h", "s", "sdg", "sx", "sxdg",
"t", "tdg", "ccx", "ccz", "delay", "pauli", "rz"});

using chpauli_t = CHSimulator::pauli_t;
using chstate_t = CHSimulator::Runner;
Expand Down Expand Up @@ -89,6 +89,9 @@ class State : public QuantumState::State<chstate_t> {
std::vector<SampleVector> sample_measure(const reg_t &qubits, uint_t shots,
RngEngine &rng) override;

bool
validate_parameters(const std::vector<Operations::Op> &ops) const override;

protected:
// Alongside the sample measure optimisaiton, we can parallelise
// circuit applicaiton over the states. This reduces the threading overhead
Expand Down Expand Up @@ -211,6 +214,7 @@ const stringmap_t<Gates> State::gateset_({
{"sxdg", Gates::sxdg}, // Inverse sqrt(X) gate
{"t", Gates::t}, // T-gate (sqrt(S))
{"tdg", Gates::tdg}, // Conjguate-transpose of T gate
{"rz", Gates::rz}, // RZ gate (only support k * pi/2 cases)
// Waltz Gates
{"u0", Gates::u0}, // idle gate in multiples of X90
{"u1", Gates::u1}, // zero-X90 pulse waltz gate
Expand Down Expand Up @@ -336,6 +340,23 @@ bool State::check_measurement_opt(InputIterator first,
return true;
}

bool State::validate_parameters(const std::vector<Operations::Op> &ops) const {
for (uint_t i = 0; i < ops.size(); i++) {
if (ops[i].type == OpType::gate) {
// check parameter of RZ gates
if (ops[i].name == "rz") {
double pi2 = std::real(ops[i].params[0]) * 2.0 / M_PI;
double pi2_int = (double)std::round(pi2);

if (!AER::Linalg::almost_equal(pi2, pi2_int)) {
return false;
}
}
}
}
return true;
}

//-------------------------------------------------------------------------
// Implementation: Operations
//-------------------------------------------------------------------------
Expand Down Expand Up @@ -633,6 +654,7 @@ void State::apply_gate(const Operations::Op &op, RngEngine &rng) {
}

void State::apply_gate(const Operations::Op &op, RngEngine &rng, uint_t rank) {
int_t pi2;
auto it = gateset_.find(op.name);
if (it == gateset_.end()) {
throw std::invalid_argument("CH::State: Invalid gate operation \'" +
Expand Down Expand Up @@ -694,6 +716,19 @@ void State::apply_gate(const Operations::Op &op, RngEngine &rng, uint_t rank) {
case Gates::pauli:
apply_pauli(op.qubits, op.string_params[0], rank);
break;
case Gates::rz:
pi2 = (int_t)std::round(std::real(op.params[0]) * 2.0 / M_PI) & 3;
if (pi2 == 1) {
// S
BaseState::qreg_.apply_s(op.qubits[0], rank);
} else if (pi2 == 2) {
// Z
BaseState::qreg_.apply_z(op.qubits[0], rank);
} else if (pi2 == 3) {
// Sdg
BaseState::qreg_.apply_sdag(op.qubits[0], rank);
}
break;
default: // u0 or Identity
break;
}
Expand Down
4 changes: 3 additions & 1 deletion src/simulators/extended_stabilizer/gates.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ enum class Gates {
swap,
ccx,
ccz,
pauli
pauli,
rz,
};

enum class Gatetypes { pauli, clifford, non_clifford };
Expand All @@ -80,6 +81,7 @@ const AER::stringmap_t<Gatetypes> gate_types_ = {
{"tdg", Gatetypes::non_clifford}, // Conjguate-transpose of T gate
{"u1", Gatetypes::non_clifford}, // zero-X90 pulse waltz gate
{"p", Gatetypes::non_clifford}, // zero-X90 pulse waltz gate
{"rz", Gatetypes::clifford}, // RZ gate (only support k * pi/2 cases)
// Two-qubit gates
{"CX", Gatetypes::clifford}, // Controlled-X gate (CNOT)
{"cx", Gatetypes::clifford}, // Controlled-X gate (CNOT)
Expand Down
45 changes: 5 additions & 40 deletions src/simulators/stabilizer/stabilizer_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ const Operations::OpSet StateOpSet(
OpType::save_amps_sq, OpType::save_stabilizer, OpType::save_clifford,
OpType::save_state, OpType::set_stabilizer, OpType::jump, OpType::mark},
// Gates
{"CX", "cx", "cy", "cz", "swap", "id", "x", "y", "z", "h",
"s", "sdg", "sx", "sxdg", "delay", "pauli", "ecr", "rx", "ry", "rz"});
{"CX", "cx", "cy", "cz", "swap", "id", "x", "y", "z", "h", "s", "sdg", "sx",
"sxdg", "delay", "pauli", "ecr", "rz"});

enum class Gates {
id,
Expand All @@ -57,8 +57,6 @@ enum class Gates {
swap,
pauli,
ecr,
rx,
ry,
rz
};

Expand Down Expand Up @@ -202,6 +200,7 @@ const stringmap_t<Gates> State::gateset_({
{"h", Gates::h}, // Hadamard gate (X + Z / sqrt(2))
{"sx", Gates::sx}, // Sqrt X gate.
{"sxdg", Gates::sxdg}, // Inverse Sqrt X gate.
{"rz", Gates::rz}, // RZ gate (only support k * pi/2 cases)
// Two-qubit gates
{"CX", Gates::cx}, // Controlled-X gate (CNOT)
{"cx", Gates::cx}, // Controlled-X gate (CNOT),
Expand All @@ -210,9 +209,6 @@ const stringmap_t<Gates> State::gateset_({
{"swap", Gates::swap}, // SWAP gate
{"pauli", Gates::pauli}, // Pauli gate
{"ecr", Gates::ecr}, // ECR gate
{"rx", Gates::rx}, // RX gate (only support k * pi/2 cases)
{"ry", Gates::ry}, // RY gate (only support k * pi/2 cases)
{"rz", Gates::rz} // RZ gate (only support k * pi/2 cases)
});

//============================================================================
Expand Down Expand Up @@ -257,8 +253,8 @@ void State::set_config(const Config &config) {
bool State::validate_parameters(const std::vector<Operations::Op> &ops) const {
for (uint_t i = 0; i < ops.size(); i++) {
if (ops[i].type == OpType::gate) {
// check parameter of R gates
if (ops[i].name == "rx" || ops[i].name == "ry" || ops[i].name == "rz") {
// check parameter of RZ gates
if (ops[i].name == "rz") {
double pi2 = std::real(ops[i].params[0]) * 2.0 / M_PI;
double pi2_int = (double)std::round(pi2);

Expand Down Expand Up @@ -396,37 +392,6 @@ void State::apply_gate(const Operations::Op &op) {
BaseState::qreg_.append_x(op.qubits[0]);
BaseState::qreg_.append_x(op.qubits[1]);
break;
case Gates::rx:
pi2 = (int_t)std::round(std::real(op.params[0]) * 2.0 / M_PI) & 3;
if (pi2 == 1) {
// HSH
BaseState::qreg_.append_h(op.qubits[0]);
BaseState::qreg_.append_s(op.qubits[0]);
BaseState::qreg_.append_h(op.qubits[0]);
} else if (pi2 == 2) {
// X
BaseState::qreg_.append_x(op.qubits[0]);
} else if (pi2 == 3) {
// HSdgH
BaseState::qreg_.append_h(op.qubits[0]);
BaseState::qreg_.append_z(op.qubits[0]);
BaseState::qreg_.append_s(op.qubits[0]);
BaseState::qreg_.append_h(op.qubits[0]);
}
break;
case Gates::ry:
pi2 = (int_t)std::round(std::real(op.params[0]) * 2.0 / M_PI) & 3;
if (pi2 == 1) {
BaseState::qreg_.append_h(op.qubits[0]);
BaseState::qreg_.append_x(op.qubits[0]);
} else if (pi2 == 2) {
// Y
BaseState::qreg_.append_y(op.qubits[0]);
} else if (pi2 == 3) {
BaseState::qreg_.append_x(op.qubits[0]);
BaseState::qreg_.append_h(op.qubits[0]);
}
break;
case Gates::rz:
pi2 = (int_t)std::round(std::real(op.params[0]) * 2.0 / M_PI) & 3;
if (pi2 == 1) {
Expand Down
22 changes: 14 additions & 8 deletions src/simulators/statevector/statevector_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,17 @@ const Operations::OpSet StateOpSet(
OpType::jump,
OpType::mark},
// Gates
{"u1", "u2", "u3", "u", "U", "CX", "cx", "cz",
"cy", "cp", "cu1", "cu2", "cu3", "swap", "id", "p",
"x", "y", "z", "h", "s", "sdg", "t", "tdg",
"r", "rx", "ry", "rz", "rxx", "ryy", "rzz", "rzx",
"ccx", "ccz", "cswap", "mcx", "mcy", "mcz", "mcu1", "mcu2",
"mcu3", "mcswap", "mcr", "mcrx", "mcry", "mcrz", "sx", "sxdg",
"csx", "mcsx", "csxdg", "mcsxdg", "delay", "pauli", "mcx_gray", "cu",
"mcu", "mcp", "ecr", "mcphase"});
{
"u1", "u2", "u3", "u", "U", "CX", "cx",
"cz", "cy", "cp", "cu1", "cu2", "cu3", "swap",
"id", "p", "x", "y", "z", "h", "s",
"sdg", "t", "tdg", "r", "rx", "ry", "rz",
"rxx", "ryy", "rzz", "rzx", "ccx", "ccz", "cswap",
"mcx", "mcy", "mcz", "mcu1", "mcu2", "mcu3", "mcswap",
"mcr", "mcrx", "mcry", "mcrz", "sx", "sxdg", "csx",
"mcsx", "csxdg", "mcsxdg", "delay", "pauli", "mcx_gray", "cu",
"mcu", "mcp", "ecr", "mcphase", "crx", "cry", "crz",
});

// Allowed gates enum class
enum class Gates {
Expand Down Expand Up @@ -368,6 +371,9 @@ const stringmap_t<Gates> State<statevec_t>::gateset_(
{"csx", Gates::mcsx}, // Controlled-Sqrt(X) gate
{"csxdg", Gates::mcsxdg}, // Controlled-Sqrt(X)dg gate
{"ecr", Gates::ecr}, // ECR Gate
{"crx", Gates::mcrx}, // Controlled X-rotation gate
{"cry", Gates::mcry}, // Controlled Y-rotation gate
{"crz", Gates::mcrz}, // Controlled Z-rotation gate
/* 3-qubit gates */
{"ccx", Gates::mcx}, // Controlled-CX gate (Toffoli)
{"ccz", Gates::mcz}, // Controlled-CZ gate
Expand Down
7 changes: 5 additions & 2 deletions src/simulators/tensor_network/tensor_net_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ const Operations::OpSet StateOpSet(
"sdg", "t", "tdg", "r", "rx", "ry", "rz",
"rxx", "ryy", "rzz", "rzx", "ccx", "ccz", "mcx",
"mcy", "mcz", "mcu1", "mcu2", "mcu3", "mcswap", "mcphase",
"mcr", "mcrx", "mcry", "mcry", "sx", "sxdg", "csx",
"mcr", "mcrx", "mcry", "mcrz", "sx", "sxdg", "csx",
"mcsx", "csxdg", "mcsxdg", "delay", "pauli", "mcx_gray", "cu",
"mcu", "mcp", "ecr", "cswap"});
"mcu", "mcp", "ecr", "cswap", "crx", "cry", "crz"});

// Allowed gates enum class
enum class Gates {
Expand Down Expand Up @@ -361,6 +361,9 @@ const stringmap_t<Gates> State<tensor_net_t>::gateset_(
{"csx", Gates::mcsx}, // Controlled-Sqrt(X) gate
{"csxdg", Gates::mcsxdg}, // Controlled-Sqrt(X)dg gate
{"ecr", Gates::ecr}, // ECR Gate
{"crx", Gates::mcrx}, // Controlled X-rotation gate
{"cry", Gates::mcry}, // Controlled Y-rotation gate
{"crz", Gates::mcrz}, // Controlled Z-rotation gate
/* 3-qubit gates */
{"ccx", Gates::mcx}, // Controlled-CX gate (Toffoli)
{"ccz", Gates::mcz}, // Controlled-CZ gate
Expand Down
21 changes: 13 additions & 8 deletions src/simulators/unitary/unitary_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,16 @@ const Operations::OpSet StateOpSet(
Operations::OpType::save_state, Operations::OpType::set_unitary,
Operations::OpType::jump, Operations::OpType::mark},
// Gates
{"u1", "u2", "u3", "u", "U", "CX", "cx", "cz",
"cy", "cp", "cu1", "cu2", "cu3", "swap", "id", "p",
"x", "y", "z", "h", "s", "sdg", "t", "tdg",
"r", "rx", "ry", "rz", "rxx", "ryy", "rzz", "rzx",
"ccx", "ccz", "cswap", "mcx", "mcy", "mcz", "mcu1", "mcu2",
"mcu3", "mcswap", "mcr", "mcrx", "mcry", "mcry", "sx", "sxdg",
"csx", "mcsx", "csxdg", "mcsxdg", "delay", "pauli", "cu", "mcu",
"mcp", "ecr", "mcphase"});
{
"u1", "u2", "u3", "u", "U", "CX", "cx", "cz",
"cy", "cp", "cu1", "cu2", "cu3", "swap", "id", "p",
"x", "y", "z", "h", "s", "sdg", "t", "tdg",
"r", "rx", "ry", "rz", "rxx", "ryy", "rzz", "rzx",
"ccx", "ccz", "cswap", "mcx", "mcy", "mcz", "mcu1", "mcu2",
"mcu3", "mcswap", "mcr", "mcrx", "mcry", "mcrz", "sx", "sxdg",
"csx", "mcsx", "csxdg", "mcsxdg", "delay", "pauli", "cu", "mcu",
"mcp", "ecr", "mcphase", "crx", "cry", "crz",
});

// Allowed gates enum class
enum class Gates {
Expand Down Expand Up @@ -253,6 +255,9 @@ const stringmap_t<Gates> State<unitary_matrix_t>::gateset_({
{"csx", Gates::mcsx}, // Controlled-Sqrt(X) gate
{"csxdg", Gates::mcsxdg}, // Controlled-Sqrt(X)dg gate
{"ecr", Gates::ecr}, // ECR Gate
{"crx", Gates::mcrx}, // Controlled X-rotation gate
{"cry", Gates::mcry}, // Controlled Y-rotation gate
{"crz", Gates::mcrz}, // Controlled Z-rotation gate
// Three-qubit gates
{"ccx", Gates::mcx}, // Controlled-CX gate (Toffoli)
{"ccz", Gates::mcz}, // Controlled-CZ gate
Expand Down
Loading

0 comments on commit 5e9be0b

Please sign in to comment.