Skip to content

Commit

Permalink
Be stricter about allowed num_ctrl_qubits
Browse files Browse the repository at this point in the history
  • Loading branch information
jakelishman committed Oct 28, 2022
1 parent 361cac0 commit af1abf0
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 5 deletions.
14 changes: 10 additions & 4 deletions qiskit/circuit/controlledgate.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,16 @@ def num_ctrl_qubits(self, num_ctrl_qubits):
Raises:
CircuitError: ``num_ctrl_qubits`` is not an integer in ``[1, num_qubits]``.
"""
if num_ctrl_qubits == int(num_ctrl_qubits) and 1 <= num_ctrl_qubits <= self.num_qubits:
self._num_ctrl_qubits = num_ctrl_qubits
else:
raise CircuitError("The number of control qubits must be in [1, num_qubits]")
if num_ctrl_qubits != int(num_ctrl_qubits):
raise CircuitError("The number of control qubits must be an integer.")
num_ctrl_qubits = int(num_ctrl_qubits)
# This is a range rather than an equality limit because some controlled gates represent a
# controlled version of the base gate whose definition also uses auxiliary qubits.
upper_limit = self.num_qubits - getattr(self.base_gate, "num_qubits", 0)
if num_ctrl_qubits < 1 or num_ctrl_qubits > upper_limit:
limit = "num_qubits" if self.base_gate is None else "num_qubits - base_gate.num_qubits"
raise CircuitError(f"The number of control qubits must be in `[1, {limit}]`.")
self._num_ctrl_qubits = num_ctrl_qubits

@property
def ctrl_state(self) -> int:
Expand Down
25 changes: 24 additions & 1 deletion test/python/circuit/test_controlled_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

from qiskit import QuantumRegister, QuantumCircuit, execute, BasicAer, QiskitError
from qiskit.test import QiskitTestCase
from qiskit.circuit import ControlledGate, Parameter
from qiskit.circuit import ControlledGate, Parameter, Gate
from qiskit.circuit.exceptions import CircuitError
from qiskit.quantum_info.operators.predicates import matrix_equal, is_unitary_matrix
from qiskit.quantum_info.random import random_unitary
Expand Down Expand Up @@ -1135,6 +1135,29 @@ def test_improper_num_ctrl_qubits(self, num_ctrl_qubits):
name="cgate", num_qubits=num_qubits, params=[], num_ctrl_qubits=num_ctrl_qubits
)

def test_improper_num_ctrl_qubits_base_gate(self):
"""Test that the allowed number of control qubits takes the base gate into account."""
with self.assertRaises(CircuitError):
ControlledGate(
name="cx?", num_qubits=2, params=[], num_ctrl_qubits=2, base_gate=XGate()
)
self.assertIsInstance(
ControlledGate(
name="cx?", num_qubits=2, params=[], num_ctrl_qubits=1, base_gate=XGate()
),
ControlledGate,
)
self.assertIsInstance(
ControlledGate(
name="p",
num_qubits=1,
params=[np.pi],
num_ctrl_qubits=1,
base_gate=Gate("gphase", 0, [np.pi]),
),
ControlledGate,
)

def test_open_controlled_equality(self):
"""
Test open controlled gates are equal if their base gates and control states are equal.
Expand Down

0 comments on commit af1abf0

Please sign in to comment.