qml.ctrl

ctrl(op, control, control_values=None, work_wires=None)[source]

Create a method that applies a controlled version of the provided op. qjit() compatible.

Note

When used with qjit(), this function only supports the Catalyst compiler. See catalyst.ctrl() for more details.

Please see the Catalyst quickstart guide, as well as the sharp bits and debugging tips page for an overview of the differences between Catalyst and PennyLane.

Parameters
  • op (function or Operator) – A single operator or a function that applies pennylane operators.

  • control (Wires) – The control wire(s).

  • control_values (bool or list[bool]) – The value(s) the control wire(s) should take. Integers other than 0 or 1 will be treated as int(bool(x)).

  • work_wires (Any) – Any auxiliary wires that can be used in the decomposition

Returns

If an Operator is provided, returns a Controlled version of the Operator. If a function is provided, returns a function with the same call signature that creates a controlled version of the provided function.

Return type

function or Operator

See also

Controlled.

Example

@qml.qnode(qml.device('default.qubit', wires=range(4)))
def circuit(x):
    qml.X(2)
    qml.ctrl(qml.RX, (1,2,3), control_values=(0,1,0))(x, wires=0)
    return qml.expval(qml.Z(0))
>>> print(qml.draw(circuit)("x"))
0: ────╭RX(x)─┤  <Z>
1: ────├○─────┤
2: ──X─├●─────┤
3: ────╰○─────┤
>>> x = np.array(1.2)
>>> circuit(x)
tensor(0.36235775, requires_grad=True)
>>> qml.grad(circuit)(x)
tensor(-0.93203909, requires_grad=True)

ctrl() works on both callables like qml.RX or a quantum function and individual Operator’s.

>>> qml.ctrl(qml.Hadamard(0), (1,2))
Controlled(Hadamard(wires=[0]), control_wires=[1, 2])

Controlled operations work with all other forms of operator math and simplification:

>>> op = qml.ctrl(qml.RX(1.2, wires=0) ** 2 @ qml.RY(0.1, wires=0), control=1)
>>> qml.simplify(qml.adjoint(op))
Controlled(RY(12.466370614359173, wires=[0]) @ RX(10.166370614359172, wires=[0]), control_wires=[1])

Example with compiler

dev = qml.device("lightning.qubit", wires=2)

@qml.qjit
@qml.qnode(dev)
def workflow(theta, w, cw):
    qml.Hadamard(wires=[0])
    qml.Hadamard(wires=[1])

    def func(arg):
        qml.RX(theta, wires=arg)

    def cond_fn():
        qml.RY(theta, wires=w)

    qml.ctrl(func, control=[cw])(w)
    qml.ctrl(qml.cond(theta > 0.0, cond_fn), control=[cw])()
    qml.ctrl(qml.RZ, control=[cw])(theta, wires=w)
    qml.ctrl(qml.RY(theta, wires=w), control=[cw])
    return qml.probs()
>>> workflow(jnp.pi/4, 1, 0)
array([0.25, 0.25, 0.03661165, 0.46338835])