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

Handle gates with ctrl_stete=0 #2148

Merged
merged 13 commits into from
May 30, 2024
36 changes: 29 additions & 7 deletions qiskit_aer/backends/aer_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -812,18 +812,43 @@ def _assemble_op(

aer_cond_expr = conditional_expr.accept(_AssembleExprImpl(circ)) if conditional_expr else None

# check if there is ctrl_state option
ctrl_state_pos = name.find("_o")
if ctrl_state_pos > 0:
gate_name = name[0:ctrl_state_pos]
else:
gate_name = name

num_of_aer_ops = 1
# fmt: off
if basis_gates is None and name in {
if (gate_name in {
"ccx", "ccz", "cp", "cswap", "csx", "cx", "cy", "cz", "delay", "ecr", "h",
"id", "mcp", "mcphase", "mcr", "mcrx", "mcry", "mcrz", "mcswap", "mcsx",
"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)
}) and (basis_gates is None or gate_name in basis_gates):
if ctrl_state_pos > 0:
# Add x gates for ctrl qubits which state=0
ctrl_state = int(name[ctrl_state_pos+2:len(name)])
for i in range(len(qubits)):
if (ctrl_state >> i) & 1 == 0:
qubits_i = [qubits[len(qubits) - 1 - i]]
aer_circ.gate("x", qubits_i, params, [], conditional_reg, aer_cond_expr,
label if label else "x")
num_of_aer_ops += 1
aer_circ.gate(gate_name, qubits, params, [], conditional_reg, aer_cond_expr,
label if label else gate_name)
for i in range(len(qubits)):
if (ctrl_state >> i) & 1 == 0:
qubits_i = [qubits[len(qubits) - 1 - i]]
aer_circ.gate("x", qubits_i, params, [], conditional_reg, aer_cond_expr,
label if label else "x")
num_of_aer_ops += 1
else:
aer_circ.gate(name, qubits, params, [], conditional_reg, aer_cond_expr,
label if label else name)
elif name == "measure":
if is_conditional:
aer_circ.measure(qubits, clbits, clbits)
Expand Down Expand Up @@ -915,9 +940,6 @@ def _assemble_op(
aer_circ.mark(qubits, params)
elif name == "qerror_loc":
aer_circ.set_qerror_loc(qubits, label if label else name, conditional_reg, aer_cond_expr)
elif basis_gates is not None and name in basis_gates:
aer_circ.gate(name, qubits, params, [], conditional_reg, aer_cond_expr,
label if label else name)
elif name in ("for_loop", "while_loop", "if_else"):
raise AerError(
"control-flow instructions must be converted " f"to jump and mark instructions: {name}"
Expand Down
1 change: 1 addition & 0 deletions test/terra/backends/aer_simulator/test_cliffords.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from test.terra.reference import ref_1q_clifford
from test.terra.reference import ref_2q_clifford
from qiskit import transpile
from qiskit import QuantumCircuit
from test.terra.backends.simulator_test_case import SimulatorTestCase, supported_methods

SUPPORTED_METHODS = [
Expand Down
26 changes: 26 additions & 0 deletions test/terra/reference/ref_2q_clifford.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ def cx_gate_circuits_deterministic(final_measure=True):
circuit.measure(qr, cr)
circuits.append(circuit)

# test ctrl_states=0
circuit = QuantumCircuit(*regs)
circuit.cx(qr[0], qr[1], ctrl_state=0)
if final_measure:
circuit.barrier(qr)
circuit.measure(qr, cr)
circuits.append(circuit)

return circuits


Expand All @@ -132,6 +140,8 @@ def cx_gate_counts_deterministic(shots, hex_counts=True):
targets.append({"0x1": shots}) # {"00": shots}
# CX10.(X^X), |10> state
targets.append({"0x2": shots}) # {"00": shots}
# test ctrl_states=0
targets.append({"0x2": shots}) # {"00": shots}
else:
# CX01, |00> state
targets.append({"00": shots}) # {"00": shots}
Expand All @@ -149,6 +159,8 @@ def cx_gate_counts_deterministic(shots, hex_counts=True):
targets.append({"01": shots}) # {"00": shots}
# CX10.(X^X), |10> state
targets.append({"10": shots}) # {"00": shots}
# test ctrl_states=0
targets.append({"10": shots}) # {"00": shots}
return targets


Expand Down Expand Up @@ -225,6 +237,16 @@ def cx_gate_circuits_nondeterministic(final_measure=True):
circuit.barrier(qr)
circuit.measure(qr, cr)
circuits.append(circuit)

# test ctrl_states=0
circuit = QuantumCircuit(*regs)
circuit.h(qr[0])
circuit.cx(qr[0], qr[1], ctrl_state=0)
if final_measure:
circuit.barrier(qr)
circuit.measure(qr, cr)
circuits.append(circuit)

return circuits


Expand All @@ -236,11 +258,15 @@ def cx_gate_counts_nondeterministic(shots, hex_counts=True):
targets.append({"0x0": shots / 2, "0x3": shots / 2})
# CX10.(I^H), Bell state
targets.append({"0x0": shots / 2, "0x3": shots / 2})
# test ctrl_states=0
targets.append({"0x1": shots / 2, "0x2": shots / 2})
else:
# CX01.(I^H), Bell state
targets.append({"00": shots / 2, "11": shots / 2})
# CX10.(I^H), Bell state
targets.append({"00": shots / 2, "11": shots / 2})
# test ctrl_states=0
targets.append({"01": shots / 2, "10": shots / 2})
return targets


Expand Down
Loading