qml.transforms.cond

cond(condition, true_fn, false_fn=None)[source]

Condition a quantum operation on the results of mid-circuit qubit measurements.

Support for using cond() is device-dependent. If a device doesn’t support mid-circuit measurements natively, then the QNode will apply the defer_measurements() transform.

Parameters
  • condition (MeasurementValue[bool]) – a conditional expression involving a mid-circuit measurement value (see pennylane.measure())

  • true_fn (callable) – The quantum function of PennyLane operation to apply if condition is True

  • false_fn (callable) – The quantum function of PennyLane operation to apply if condition is False

Returns

A new function that applies the conditional equivalent of true_fn. The returned function takes the same input arguments as true_fn.

Return type

function

Example

dev = qml.device("default.qubit", wires=3)

@qml.qnode(dev)
def qnode(x, y):
    qml.Hadamard(0)
    m_0 = qml.measure(0)
    qml.cond(m_0, qml.RY)(x, wires=1)

    qml.Hadamard(2)
    qml.RY(-np.pi/2, wires=[2])
    m_1 = qml.measure(2)
    qml.cond(m_1 == 0, qml.RX)(y, wires=1)
    return qml.expval(qml.PauliZ(1))
>>> first_par = np.array(0.3, requires_grad=True)
>>> sec_par = np.array(1.23, requires_grad=True)
>>> qnode(first_par, sec_par)
tensor(0.32677361, requires_grad=True)

Note

If the first argument of cond is a measurement value (e.g., m_0 in qml.cond(m_0, qml.RY)), then m_0 == 1 is considered internally.

Conditional quantum functions

The cond transform allows conditioning quantum functions too:

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

def qfunc(par, wires):
    qml.Hadamard(wires[0])
    qml.RY(par, wires[0])

@qml.qnode(dev)
def qnode(x):
    qml.Hadamard(0)
    m_0 = qml.measure(0)
    qml.cond(m_0, qfunc)(x, wires=[1])
    return qml.expval(qml.PauliZ(1))
>>> par = np.array(0.3, requires_grad=True)
>>> qnode(par)
tensor(0.3522399, requires_grad=True)

Passing two quantum functions

In the qubit model, single-qubit measurements may result in one of two outcomes. Such measurement outcomes may then be used to create conditional expressions.

According to the truth value of the conditional expression passed to cond, the transform can apply a quantum function in both the True and False case:

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

def qfunc1(x, wires):
    qml.Hadamard(wires[0])
    qml.RY(x, wires[0])

def qfunc2(x, wires):
    qml.Hadamard(wires[0])
    qml.RZ(x, wires[0])

@qml.qnode(dev)
def qnode1(x):
    qml.Hadamard(0)
    m_0 = qml.measure(0)
    qml.cond(m_0, qfunc1, qfunc2)(x, wires=[1])
    return qml.expval(qml.PauliZ(1))
>>> par = np.array(0.3, requires_grad=True)
>>> qnode1(par)
tensor(-0.1477601, requires_grad=True)

The previous QNode is equivalent to using cond twice, inverting the conditional expression in the second case using the ~ unary operator:

@qml.qnode(dev)
def qnode2(x):
    qml.Hadamard(0)
    m_0 = qml.measure(0)
    qml.cond(m_0, qfunc1)(x, wires=[1])
    qml.cond(~m_0, qfunc2)(x, wires=[1])
    return qml.expval(qml.PauliZ(1))
>>> qnode2(par)
tensor(-0.1477601, requires_grad=True)

Quantum functions with different signatures

It may be that the two quantum functions passed to qml.cond have different signatures. In such a case, lambda functions taking no arguments can be used with Python closure:

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

def qfunc1(x, wire):
    qml.Hadamard(wire)
    qml.RY(x, wire)

def qfunc2(x, y, z, wire):
    qml.Hadamard(wire)
    qml.Rot(x, y, z, wire)

@qml.qnode(dev)
def qnode(a, x, y, z):
    qml.Hadamard(0)
    m_0 = qml.measure(0)
    qml.cond(m_0, lambda: qfunc1(a, wire=1), lambda: qfunc2(x, y, z, wire=1))()
    return qml.expval(qml.PauliZ(1))
>>> par = np.array(0.3, requires_grad=True)
>>> x = np.array(1.2, requires_grad=True)
>>> y = np.array(1.1, requires_grad=True)
>>> z = np.array(0.3, requires_grad=True)
>>> qnode(par, x, y, z)
tensor(-0.30922805, requires_grad=True)