Skip to content

Commit

Permalink
Handle gates with ctrl_stete=0 (#2148)
Browse files Browse the repository at this point in the history
* handle cx gate with ctrl_stete=0

* add handling *_o0, add test for cx_o0

* format

* fix test

* fix test

* fix test cx

* fix to handle multiple control states

* fix ctrl_state

* format

* resolve conflict again

* fix aer_compiler
  • Loading branch information
doichanj authored May 30, 2024
1 parent 0e7d658 commit 0062f64
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 7 deletions.
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

0 comments on commit 0062f64

Please sign in to comment.