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

Singleton parameterless controlled gates #10898

Merged
merged 13 commits into from
Oct 16, 2023
Merged
1 change: 1 addition & 0 deletions qiskit/circuit/add_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def control(
else:
basis = ["p", "u", "x", "z", "rx", "ry", "rz", "cx"]
if isinstance(operation, controlledgate.ControlledGate):
operation = operation.to_mutable()
operation.ctrl_state = None
unrolled_gate = _unroll_gate(operation, basis_gates=basis)
if unrolled_gate.definition.global_phase:
Expand Down
16 changes: 10 additions & 6 deletions qiskit/circuit/controlledgate.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ def __init__(
definition: Optional["QuantumCircuit"] = None,
ctrl_state: Optional[Union[int, str]] = None,
base_gate: Optional[Gate] = None,
duration=None,
unit=None,
):
"""Create a new ControlledGate. In the new gate the first ``num_ctrl_qubits``
of the gate are the controls.
Expand Down Expand Up @@ -95,12 +97,14 @@ def __init__(
qc2.draw('mpl')
"""
self.base_gate = None if base_gate is None else base_gate.copy()
super().__init__(name, num_qubits, params, label=label)
self._num_ctrl_qubits = 1
self.num_ctrl_qubits = num_ctrl_qubits
super().__init__(name, num_qubits, params, label=label, duration=duration, unit=unit)
if not hasattr(self, "_num_ctrl_qubits"):
self._num_ctrl_qubits = 1
self.num_ctrl_qubits = num_ctrl_qubits
if not hasattr(self, "_ctrl_state"):
self._ctrl_state = None
self.ctrl_state = ctrl_state
self.definition = copy.deepcopy(definition)
self._ctrl_state = None
self.ctrl_state = ctrl_state
self._name = name

@property
Expand All @@ -111,7 +115,7 @@ def definition(self) -> QuantumCircuit:
`_definition`.
"""
if self._open_ctrl:
closed_gate = self.copy()
closed_gate = self.to_mutable()
closed_gate.ctrl_state = None
bit_ctrl_state = bin(self.ctrl_state)[2:].zfill(self.num_ctrl_qubits)
qreg = QuantumRegister(self.num_qubits, "q")
Expand Down
20 changes: 16 additions & 4 deletions qiskit/circuit/library/standard_gates/h.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
from math import sqrt, pi
from typing import Optional, Union
import numpy
from qiskit.circuit.controlledgate import ControlledGate
from qiskit.circuit.singleton_gate import SingletonGate
from qiskit.circuit.singleton_gate import SingletonGate, SingletonControlledGate
from qiskit.circuit.quantumregister import QuantumRegister
from qiskit.circuit._utils import with_gate_array, with_controlled_gate_array
from .t import TGate, TdgGate
Expand Down Expand Up @@ -108,7 +107,7 @@ def inverse(self):


@with_controlled_gate_array(_H_ARRAY, num_ctrl_qubits=1)
class CHGate(ControlledGate):
class CHGate(SingletonControlledGate):
r"""Controlled-Hadamard gate.

Applies a Hadamard on the target qubit if the control is
Expand Down Expand Up @@ -170,16 +169,29 @@ def __init__(
label: Optional[str] = None,
ctrl_state: Optional[Union[int, str]] = None,
_base_label=None,
_condition=None,
duration=None,
unit=None,
):
"""Create new CH gate."""
if unit is None:
unit = "dt"
if _base_label:
base_gate = HGate(label=_base_label)
else:
base_gate = HGate()
super().__init__(
"ch",
2,
[],
num_ctrl_qubits=1,
label=label,
ctrl_state=ctrl_state,
base_gate=HGate(label=_base_label),
base_gate=base_gate,
duration=duration,
_condition=_condition,
unit=unit,
_base_label=_base_label,
)

def _define(self):
Expand Down
41 changes: 34 additions & 7 deletions qiskit/circuit/library/standard_gates/s.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@

import numpy

from qiskit.circuit.controlledgate import ControlledGate
from qiskit.circuit.singleton_gate import SingletonGate
from qiskit.circuit.singleton_gate import SingletonGate, SingletonControlledGate
from qiskit.circuit.library.standard_gates.p import CPhaseGate, PhaseGate
from qiskit.circuit.quantumregister import QuantumRegister
from qiskit.circuit._utils import with_gate_array, with_controlled_gate_array
Expand Down Expand Up @@ -159,7 +158,7 @@ def power(self, exponent: float):


@with_controlled_gate_array(_S_ARRAY, num_ctrl_qubits=1)
class CSGate(ControlledGate):
class CSGate(SingletonControlledGate):
r"""Controlled-S gate.

Can be applied to a :class:`~qiskit.circuit.QuantumCircuit`
Expand Down Expand Up @@ -188,10 +187,28 @@ class CSGate(ControlledGate):
\end{pmatrix}
"""

def __init__(self, label: Optional[str] = None, ctrl_state: Optional[Union[str, int]] = None):
def __init__(
self,
label: Optional[str] = None,
ctrl_state: Optional[Union[str, int]] = None,
_condition=None,
duration=None,
unit=None,
):
"""Create new CS gate."""
if unit is None:
unit = "dt"
super().__init__(
"cs", 2, [], label=label, num_ctrl_qubits=1, ctrl_state=ctrl_state, base_gate=SGate()
"cs",
2,
[],
label=label,
num_ctrl_qubits=1,
ctrl_state=ctrl_state,
base_gate=SGate(),
duration=duration,
_condition=_condition,
unit=unit,
)

def _define(self):
Expand All @@ -210,7 +227,7 @@ def power(self, exponent: float):


@with_controlled_gate_array(_SDG_ARRAY, num_ctrl_qubits=1)
class CSdgGate(ControlledGate):
class CSdgGate(SingletonControlledGate):
r"""Controlled-S^\dagger gate.

Can be applied to a :class:`~qiskit.circuit.QuantumCircuit`
Expand Down Expand Up @@ -239,7 +256,14 @@ class CSdgGate(ControlledGate):
\end{pmatrix}
"""

def __init__(self, label: Optional[str] = None, ctrl_state: Optional[Union[str, int]] = None):
def __init__(
self,
label: Optional[str] = None,
ctrl_state: Optional[Union[str, int]] = None,
_condition=None,
duration=None,
unit=None,
):
"""Create new CSdg gate."""
super().__init__(
"csdg",
Expand All @@ -249,6 +273,9 @@ def __init__(self, label: Optional[str] = None, ctrl_state: Optional[Union[str,
num_ctrl_qubits=1,
ctrl_state=ctrl_state,
base_gate=SdgGate(),
duration=duration,
_condition=_condition,
unit=unit,
)

def _define(self):
Expand Down
13 changes: 10 additions & 3 deletions qiskit/circuit/library/standard_gates/swap.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@

from typing import Optional, Union
import numpy
from qiskit.circuit.controlledgate import ControlledGate
from qiskit.circuit.singleton_gate import SingletonGate
from qiskit.circuit.singleton_gate import SingletonGate, SingletonControlledGate
from qiskit.circuit.quantumregister import QuantumRegister
from qiskit.circuit._utils import with_gate_array, with_controlled_gate_array

Expand Down Expand Up @@ -117,7 +116,7 @@ def inverse(self):


@with_controlled_gate_array(_SWAP_ARRAY, num_ctrl_qubits=1)
class CSwapGate(ControlledGate):
class CSwapGate(SingletonControlledGate):
r"""Controlled-SWAP gate, also known as the Fredkin gate.

Can be applied to a :class:`~qiskit.circuit.QuantumCircuit`
Expand Down Expand Up @@ -199,8 +198,13 @@ def __init__(
label: Optional[str] = None,
ctrl_state: Optional[Union[str, int]] = None,
_base_label=None,
_condition=None,
duration=None,
unit=None,
):
"""Create new CSWAP gate."""
if unit is None:
unit = "dt"
super().__init__(
"cswap",
3,
Expand All @@ -209,6 +213,9 @@ def __init__(
label=label,
ctrl_state=ctrl_state,
base_gate=SwapGate(label=_base_label),
duration=duration,
_condition=_condition,
unit=unit,
)

def _define(self):
Expand Down
15 changes: 11 additions & 4 deletions qiskit/circuit/library/standard_gates/sx.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@

from math import pi
from typing import Optional, Union
from qiskit.circuit.controlledgate import ControlledGate
from qiskit.circuit.singleton_gate import SingletonGate
from qiskit.circuit.singleton_gate import SingletonGate, SingletonControlledGate
from qiskit.circuit.quantumregister import QuantumRegister
from qiskit.circuit._utils import with_gate_array, with_controlled_gate_array

Expand Down Expand Up @@ -108,7 +107,7 @@ def control(
string (e.g. '110'), or None. If None, use all 1s.

Returns:
ControlledGate: controlled version of this gate.
SingletonControlledGate: controlled version of this gate.
"""
if num_ctrl_qubits == 1:
gate = CSXGate(label=label, ctrl_state=ctrl_state, _base_label=self.label)
Expand Down Expand Up @@ -176,7 +175,7 @@ def inverse(self):


@with_controlled_gate_array(_SX_ARRAY, num_ctrl_qubits=1)
class CSXGate(ControlledGate):
class CSXGate(SingletonControlledGate):
r"""Controlled-√X gate.

Can be applied to a :class:`~qiskit.circuit.QuantumCircuit`
Expand Down Expand Up @@ -237,8 +236,13 @@ def __init__(
label: Optional[str] = None,
ctrl_state: Optional[Union[str, int]] = None,
_base_label=None,
_condition=None,
duration=None,
unit=None,
):
"""Create new CSX gate."""
if unit is None:
unit = "dt"
super().__init__(
"csx",
2,
Expand All @@ -247,6 +251,9 @@ def __init__(
label=label,
ctrl_state=ctrl_state,
base_gate=SXGate(label=_base_label),
duration=duration,
_condition=_condition,
unit=unit,
)

def _define(self):
Expand Down
Loading