Skip to content

Commit

Permalink
Add support for ECR gate to MPS (#2137)
Browse files Browse the repository at this point in the history
* Add support for ECR gate

* replace is not to !=

* fix release note

* Fix ecr implementation for stabilizer/extended-stabilizer
  • Loading branch information
doichanj authored May 29, 2024
1 parent 0320a14 commit 0e7d658
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 19 deletions.
21 changes: 18 additions & 3 deletions qiskit_aer/backends/aer_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,9 @@ def __init__(
backend_options=backend_options,
)

if "basis_gates" in backend_options.items():
self._check_basis_gates(backend_options["basis_gates"])

@classmethod
def _default_options(cls):
return Options(
Expand Down Expand Up @@ -898,11 +901,12 @@ def configuration(self):
config = copy.copy(self._configuration)
for key, val in self._options_configuration.items():
setattr(config, key, val)

method = getattr(self.options, "method", "automatic")

# Update basis gates based on custom options, config, method,
# and noise model
config.custom_instructions = self._CUSTOM_INSTR[
getattr(self.options, "method", "automatic")
]
config.custom_instructions = self._CUSTOM_INSTR[method]
config.basis_gates = self._cached_basis_gates + config.custom_instructions
return config

Expand Down Expand Up @@ -933,6 +937,9 @@ def set_option(self, key, value):
f" are: {self.available_methods()}"
)
self._set_method_config(value)
if key == "basis_gates":
self._check_basis_gates(value)

super().set_option(key, value)
if key in ["method", "noise_model", "basis_gates"]:
self._cached_basis_gates = self._basis_gates()
Expand Down Expand Up @@ -1047,3 +1054,11 @@ def _set_method_config(self, method=None):

self._set_configuration_option("description", description)
self._set_configuration_option("n_qubits", n_qubits)

def _check_basis_gates(self, basis_gates):
method = getattr(self.options, "method", "automatic")
# check if basis_gates contains non-supported gates
if method != "automatic":
for gate in basis_gates:
if gate not in self._BASIS_GATES[method]:
raise AerError(f"Invalid gate {gate} for simulation method {method}.")
3 changes: 3 additions & 0 deletions qiskit_aer/backends/backend_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@
"cswap",
"diagonal",
"initialize",
"ecr",
]
),
"stabilizer": sorted(
Expand Down Expand Up @@ -246,6 +247,7 @@
"ccz",
"delay",
"pauli",
"ecr",
"rz",
]
),
Expand Down Expand Up @@ -417,6 +419,7 @@
"delay",
"pauli",
"mcx_gray",
"ecr",
]
),
}
Expand Down
7 changes: 7 additions & 0 deletions releasenotes/notes/add_ecr_to_mps-0eec56596fc486c7.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
features:
- |
`matrix_product_state`, `extended_stabilizer` and `tensor_network` methods
now support ecr gate.
Add check if `basis_gates` backend option has unsupported gate for
the `method`
11 changes: 10 additions & 1 deletion src/simulators/extended_stabilizer/extended_stabilizer_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const Operations::OpSet StateOpSet(
// Gates
{"CX", "u0", "u1", "p", "cx", "cz", "swap", "id",
"x", "y", "z", "h", "s", "sdg", "sx", "sxdg",
"t", "tdg", "ccx", "ccz", "delay", "pauli", "rz"});
"t", "tdg", "ccx", "ccz", "delay", "pauli", "ecr", "rz"});

using chpauli_t = CHSimulator::pauli_t;
using chstate_t = CHSimulator::Runner;
Expand Down Expand Up @@ -224,6 +224,7 @@ const stringmap_t<Gates> State::gateset_({
{"cx", Gates::cx}, // Controlled-X gate (CNOT)
{"cz", Gates::cz}, // Controlled-Z gate
{"swap", Gates::swap}, // SWAP gate
{"ecr", Gates::ecr}, // ECR Gate
// Three-qubit gates
{"ccx", Gates::ccx}, // Controlled-CX gate (Toffoli)
{"ccz", Gates::ccz}, // Constrolled-CZ gate (H3 Toff H3)
Expand Down Expand Up @@ -716,6 +717,14 @@ 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::ecr:
BaseState::qreg_.apply_s(op.qubits[0], rank);
BaseState::qreg_.apply_sdag(op.qubits[1], rank);
BaseState::qreg_.apply_h(op.qubits[1], rank);
BaseState::qreg_.apply_sdag(op.qubits[1], rank);
BaseState::qreg_.apply_cx(op.qubits[0], op.qubits[1], rank);
BaseState::qreg_.apply_x(op.qubits[0], rank);
break;
case Gates::rz:
pi2 = (int_t)std::round(std::real(op.params[0]) * 2.0 / M_PI) & 3;
if (pi2 == 1) {
Expand Down
2 changes: 2 additions & 0 deletions src/simulators/extended_stabilizer/gates.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ enum class Gates {
ccx,
ccz,
pauli,
ecr,
rz,
};

Expand Down Expand Up @@ -87,6 +88,7 @@ const AER::stringmap_t<Gatetypes> gate_types_ = {
{"cx", Gatetypes::clifford}, // Controlled-X gate (CNOT)
{"cz", Gatetypes::clifford}, // Controlled-Z gate
{"swap", Gatetypes::clifford}, // SWAP gate
{"ecr", Gatetypes::clifford}, // ECR Gate
// Three-qubit gates
{"ccx", Gatetypes::non_clifford}, // Controlled-CX gate (Toffoli)
{"ccz", Gatetypes::non_clifford}, // Controlled-CZ gate (H3 Toff H3)
Expand Down
12 changes: 8 additions & 4 deletions src/simulators/matrix_product_state/matrix_product_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ const Operations::OpSet StateOpSet(
OpType::jump,
OpType::mark},
// Gates
{"id", "x", "y", "z", "s", "sdg", "h", "t", "tdg", "p",
"u1", "u2", "u3", "u", "U", "CX", "cx", "cy", "cz", "cp",
"cu1", "swap", "ccx", "sx", "sxdg", "r", "rx", "ry", "rz", "rxx",
"ryy", "rzz", "rzx", "csx", "delay", "cswap", "pauli"});
{"id", "x", "y", "z", "s", "sdg", "h", "t", "tdg", "p",
"u1", "u2", "u3", "u", "U", "CX", "cx", "cy", "cz", "cp",
"cu1", "swap", "ccx", "sx", "sxdg", "r", "rx", "ry", "rz", "rxx",
"ryy", "rzz", "rzx", "csx", "delay", "cswap", "pauli", "ecr"});

//=========================================================================
// Matrix Product State subclass
Expand Down Expand Up @@ -296,6 +296,7 @@ const stringmap_t<Gates>
{"ryy", Gates::ryy}, // Pauli-YY rotation gate
{"rzz", Gates::rzz}, // Pauli-ZZ rotation gate
{"rzx", Gates::rzx}, // Pauli-ZX rotation gate
{"ecr", Gates::ecr}, // ECR Gate
/* Three-qubit gates */
{"ccx", Gates::ccx}, // Controlled-CX gate (Toffoli)
{"cswap", Gates::cswap},
Expand Down Expand Up @@ -673,6 +674,9 @@ void State::apply_gate(const Operations::Op &op) {
case Gates::pauli:
apply_pauli(op.qubits, op.string_params[0]);
break;
case Gates::ecr:
qreg_.apply_matrix(op.qubits, Linalg::Matrix::ECR);
break;
default:
// We shouldn't reach here unless there is a bug in gateset
throw std::invalid_argument(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ enum Gates {
csx, // two qubit
ccx,
cswap, // three qubit
pauli
pauli,
ecr,
};

// enum class Direction {RIGHT, LEFT};
Expand Down
8 changes: 4 additions & 4 deletions src/simulators/stabilizer/stabilizer_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,14 +383,14 @@ void State::apply_gate(const Operations::Op &op) {
apply_pauli(op.qubits, op.string_params[0]);
break;
case Gates::ecr:
BaseState::qreg_.append_h(op.qubits[1]);
BaseState::qreg_.append_s(op.qubits[0]);
BaseState::qreg_.append_z(op.qubits[1]); // sdg(1)
BaseState::qreg_.append_s(op.qubits[1]); // sdg(1)
BaseState::qreg_.append_z(op.qubits[1]);
BaseState::qreg_.append_s(op.qubits[1]);
BaseState::qreg_.append_h(op.qubits[1]);
BaseState::qreg_.append_z(op.qubits[1]);
BaseState::qreg_.append_s(op.qubits[1]);
BaseState::qreg_.append_cx(op.qubits[0], op.qubits[1]);
BaseState::qreg_.append_x(op.qubits[0]);
BaseState::qreg_.append_x(op.qubits[1]);
break;
case Gates::rz:
pi2 = (int_t)std::round(std::real(op.params[0]) * 2.0 / M_PI) & 3;
Expand Down
8 changes: 2 additions & 6 deletions test/terra/backends/aer_simulator/test_cliffords.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@
"tensor_network",
]

SUPPORTED_ECR_METHODS = [
"stabilizer",
]


@ddt
class TestCliffords(SimulatorTestCase):
Expand Down Expand Up @@ -249,11 +245,11 @@ def test_pauli_gate_deterministic(self, method, device):
# ---------------------------------------------------------------------
# Test ecr gate
# ---------------------------------------------------------------------
@supported_methods(SUPPORTED_ECR_METHODS)
@supported_methods(SUPPORTED_METHODS)
def test_ecr_gate_nondeterministic(self, method, device):
"""Test ecr gate circuits"""
backend = self.backend(method=method, device=device, seed_simulator=self.SEED)
shots = 100
shots = 1000
circuits = ref_2q_clifford.ecr_gate_circuits_nondeterministic(final_measure=True)
targets = ref_2q_clifford.ecr_gate_counts_nondeterministic(shots)
result = backend.run(circuits, shots=shots).result()
Expand Down

0 comments on commit 0e7d658

Please sign in to comment.