Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for ECR gate to MPS #2137

Merged
merged 8 commits into from
May 29, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions qiskit_aer/backends/aer_simulator.py
Original file line number Diff line number Diff line change
@@ -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(
@@ -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

@@ -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()
@@ -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
@@ -200,6 +200,7 @@
"cswap",
"diagonal",
"initialize",
"ecr",
]
),
"stabilizer": sorted(
@@ -246,6 +247,7 @@
"ccz",
"delay",
"pauli",
"ecr",
"rz",
]
),
@@ -417,6 +419,7 @@
"delay",
"pauli",
"mcx_gray",
"ecr",
]
),
}
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
@@ -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;
@@ -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)
@@ -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) {
2 changes: 2 additions & 0 deletions src/simulators/extended_stabilizer/gates.hpp
Original file line number Diff line number Diff line change
@@ -59,6 +59,7 @@ enum class Gates {
ccx,
ccz,
pauli,
ecr,
rz,
};

@@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, I am a junior in the realm of Quantum, Just out of curiosity, Is ECR gate a clifford gate ?

// Three-qubit gates
{"ccx", Gatetypes::non_clifford}, // Controlled-CX gate (Toffoli)
{"ccz", Gatetypes::non_clifford}, // Controlled-CZ gate (H3 Toff H3)
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
@@ -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
@@ -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},
@@ -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(
Original file line number Diff line number Diff line change
@@ -58,7 +58,8 @@ enum Gates {
csx, // two qubit
ccx,
cswap, // three qubit
pauli
pauli,
ecr,
};

// enum class Direction {RIGHT, LEFT};
8 changes: 4 additions & 4 deletions src/simulators/stabilizer/stabilizer_state.hpp
Original file line number Diff line number Diff line change
@@ -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;
8 changes: 2 additions & 6 deletions test/terra/backends/aer_simulator/test_cliffords.py
Original file line number Diff line number Diff line change
@@ -28,10 +28,6 @@
"tensor_network",
]

SUPPORTED_ECR_METHODS = [
"stabilizer",
]


@ddt
class TestCliffords(SimulatorTestCase):
@@ -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()