Skip to content

Commit

Permalink
Merge branch 'master' into Remove-str-input-control-values-of-MultiCo…
Browse files Browse the repository at this point in the history
…ntrolledX
  • Loading branch information
JerryChen97 authored Jan 17, 2025
2 parents 41d8a0d + d7490d4 commit 7fc2793
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 110 deletions.
5 changes: 5 additions & 0 deletions doc/development/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ Completed deprecation cycles
- Deprecated in v0.36
- Removed in v0.41

* The input argument ``control_wires`` of ``MultiControlledX`` has been removed.

- Deprecated in v0.22
- Removed in v0.41

* The ``decomp_depth`` argument in :func:`~pennylane.transforms.set_decomposition` has been removed.

- Deprecated in v0.40
Expand Down
3 changes: 3 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
* `MultiControlledX` no longer accepts strings as control values.
[(#6835)](https://github.com/PennyLaneAI/pennylane/pull/6835)

* The input argument `control_wires` of `MultiControlledX` has been removed.
[(#6832)](https://github.com/PennyLaneAI/pennylane/pull/6832)

* `qml.execute` now has a collection of keyword-only arguments.
[(#6598)](https://github.com/PennyLaneAI/pennylane/pull/6598)

Expand Down
27 changes: 7 additions & 20 deletions pennylane/ops/op_math/controlled_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -1172,38 +1172,25 @@ def _validate_control_values(control_values):
# pylint: disable=too-many-arguments
def __init__(
self,
control_wires: WiresLike = (),
wires: WiresLike = (),
control_values: Union[bool, List[bool], int, List[int]] = None,
work_wires: WiresLike = (),
):
control_wires = Wires(() if control_wires is None else control_wires)
wires = Wires(() if wires is None else wires)
work_wires = Wires(() if work_wires is None else work_wires)

if len(control_wires) > 0:
warnings.warn(
"The control_wires keyword for MultiControlledX is deprecated, and will "
"be removed soon. Use wires = (*control_wires, target_wire) instead.",
UserWarning,
)

self._validate_control_values(control_values)

if len(wires) == 0:
raise ValueError("Must specify the wires where the operation acts on")

if len(control_wires) > 0:
if len(wires) != 1:
raise ValueError("MultiControlledX accepts a single target wire.")
else:
if len(wires) < 2:
raise ValueError(
f"MultiControlledX: wrong number of wires. {len(wires)} wire(s) given. "
f"Need at least 2."
)
control_wires = wires[:-1]
wires = wires[-1:]
if len(wires) < 2:
raise ValueError(
f"MultiControlledX: wrong number of wires. {len(wires)} wire(s) given. "
f"Need at least 2."
)
control_wires = wires[:-1]
wires = wires[-1:]

control_values = _check_and_convert_control_values(control_values, control_wires)

Expand Down
90 changes: 0 additions & 90 deletions tests/ops/qubit/test_non_parametric_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,96 +631,6 @@ def test_invalid_arguments_to_init(self, wires, control_values, error_message):
with pytest.raises(ValueError, match=error_message):
_ = qml.MultiControlledX(wires=wires, control_values=control_values)

@pytest.mark.parametrize(
"control_wires, wires, control_values, error_message",
[
(
[0, 1],
[2],
[0, 1, 0],
"Length of control values must equal number of control wires.",
),
([0], None, [1], "Must specify the wires where the operation acts on"),
([0, 1], 2, [0, 1, 1], "Length of control values must equal number of control wires."),
([0, 1], [2, 3], [1, 0], "MultiControlledX accepts a single target wire."),
],
)
def test_invalid_arguments_to_init_old(
self, control_wires, wires, control_values, error_message
):
"""Tests initializing a MultiControlledX with invalid arguments with the old interface"""
with pytest.warns(
UserWarning,
match="The control_wires keyword for MultiControlledX is deprecated",
):
with pytest.raises(ValueError, match=error_message):
_ = qml.MultiControlledX(
control_wires=control_wires, wires=wires, control_values=control_values
)

@pytest.mark.parametrize(
"control_wires,wires,control_values",
[
([0], 1, [0]),
([0, 1], 2, [0, 0]),
([0, 1], 2, [1, 0]),
([1, 0], 2, [1, 0]),
([0, 1], 2, [1, 1]),
([0, 2], 1, [1, 0]),
([1, 2, 0], 3, [1, 0, 0]),
([1, 0, 2, 4], 3, [1, 0, 0, 1]),
([0, 1, 2, 5, 3, 6], 4, [1, 0, 0, 0, 0, 1]),
],
)
def test_mixed_polarity_controls_old(self, control_wires, wires, control_values):
"""Test if MultiControlledX properly applies mixed-polarity
control values with old version of the arguments."""

target_wires = Wires(wires)
dev = qml.device("default.qubit", wires=len(control_wires + target_wires))

# Pick random starting state for the control and target qubits
control_state_weights = np.random.normal(size=2 ** (len(control_wires) + 1) - 2)
target_state_weights = np.random.normal(size=2 ** (len(target_wires) + 1) - 2)

@qml.qnode(dev)
def circuit_mpmct():
qml.templates.ArbitraryStatePreparation(control_state_weights, wires=control_wires)
qml.templates.ArbitraryStatePreparation(target_state_weights, wires=target_wires)

qml.MultiControlledX(
control_wires=control_wires, wires=target_wires, control_values=control_values
)
return qml.state()

# The result of applying the mixed-polarity gate should be the same as
# if we conjugated the specified control wires with Pauli X and applied the
# "regular" ControlledQubitUnitary in between.

x_locations = [x for x in range(len(control_values)) if control_values[x] == 0]

@qml.qnode(dev)
def circuit_pauli_x():
qml.templates.ArbitraryStatePreparation(control_state_weights, wires=control_wires)
qml.templates.ArbitraryStatePreparation(target_state_weights, wires=target_wires)

for wire in x_locations:
qml.PauliX(wires=control_wires[wire])

qml.ControlledQubitUnitary(X, control_wires=control_wires, wires=target_wires)

for wire in x_locations:
qml.PauliX(wires=control_wires[wire])

return qml.state()

with pytest.warns(UserWarning, match="deprecated"):
mpmct_state = circuit_mpmct()

pauli_x_state = circuit_pauli_x()

assert qml.math.allclose(mpmct_state, pauli_x_state)

def test_decomposition_not_enough_wires(self):
"""Test that the decomposition raises an error if the number of wires is lower than two"""
with pytest.raises(ValueError, match="Wrong number of wires"):
Expand Down

0 comments on commit 7fc2793

Please sign in to comment.