qml.pattern_matching_optimization

pattern_matching_optimization(tape: pennylane.tape.tape.QuantumTape, pattern_tapes, custom_quantum_cost=None)[source]

Quantum function transform to optimize a circuit given a list of patterns (templates).

Parameters
  • qfunc (function) – A quantum function to be optimized.

  • pattern_tapes (list(QuantumTape)) – List of quantum tapes that implements the identity.

  • custom_quantum_cost (dict) – Optional, quantum cost that overrides the default cost dictionnary.

Returns

the transformed quantum function

Return type

function

Raises

QuantumFunctionError – The pattern provided is not a valid QuantumTape or the pattern contains measurements or the pattern does not implement identity or the circuit has less qubits than the pattern.

Example

First let’s consider the following circuit where we want to replace sequence of two pennylane.S gates with a pennylane.PauliZ gate.

def circuit():
    qml.S(wires=0)
    qml.PauliZ(wires=0)
    qml.S(wires=1)
    qml.CZ(wires=[0, 1])
    qml.S(wires=1)
    qml.S(wires=2)
    qml.CZ(wires=[1, 2])
    qml.S(wires=2)
    return qml.expval(qml.PauliX(wires=0))

Therefore we use the following pattern that implements the identity:

with qml.tape.QuantumTape() as pattern:
    qml.S(wires=0)
    qml.S(wires=0)
    qml.PauliZ(wires=0)

For optimizing the circuit given the given following template of CNOTs we apply the pattern_matching transform.

>>> dev = qml.device('default.qubit', wires=5)
>>> qnode = qml.QNode(circuit, dev)
>>> optimized_qfunc = pattern_matching_optimization(pattern_tapes=[pattern])(circuit)
>>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
>>> print(qml.draw(qnode)())
0: ──S──Z─╭●──────────┤  <X>
1: ──S────╰Z──S─╭●────┤
2: ──S──────────╰Z──S─┤
>>> print(qml.draw(optimized_qnode)())
0: ──S†─╭●────┤  <X>
1: ──Z──╰Z─╭●─┤
2: ──Z─────╰Z─┤

Note that with this pattern we also replace a pennylane.S, pennylane.PauliZ sequence by pennylane.S. If one would like avoiding this, it possible to give a custom quantum cost dictionary with a negative cost for pennylane.PauliZ.

>>> my_cost = {"PauliZ": -1 , "S": 1, "Adjoint(S)": 1}
>>> optimized_qfunc = pattern_matching_optimization(pattern_tapes=[pattern], custom_quantum_cost=my_cost)(circuit)
>>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
>>> print(qml.draw(optimized_qnode)())
0: ──S──Z─╭●────┤  <X>
1: ──Z────╰Z─╭●─┤
2: ──Z───────╰Z─┤

Now we can consider a more complicated example with the following quantum circuit to be optimized

def circuit():
    qml.Toffoli(wires=[3, 4, 0])
    qml.CNOT(wires=[1, 4])
    qml.CNOT(wires=[2, 1])
    qml.Hadamard(wires=3)
    qml.PauliZ(wires=1)
    qml.CNOT(wires=[2, 3])
    qml.Toffoli(wires=[2, 3, 0])
    qml.CNOT(wires=[1, 4])
    return qml.expval(qml.PauliX(wires=0))

We define a pattern that implement the identity:

with qml.tape.QuantumTape() as pattern:
    qml.CNOT(wires=[1, 2])
    qml.CNOT(wires=[0, 1])
    qml.CNOT(wires=[1, 2])
    qml.CNOT(wires=[0, 1])
    qml.CNOT(wires=[0, 2])

For optimizing the circuit given the given following pattern of CNOTs we apply the pattern_matching transform.

>>> dev = qml.device('default.qubit', wires=5)
>>> qnode = qml.QNode(circuit, dev)
>>> optimized_qfunc = pattern_matching_optimization(pattern_tapes=[pattern])(circuit)
>>> optimized_qnode = qml.QNode(optimized_qfunc, dev)

In our case, it is possible to find three CNOTs and replace this pattern with only two CNOTs and therefore optimizing the circuit. The number of CNOTs in the circuit is reduced by one.

>>> qml.specs(qnode)()["gate_types"]["CNOT"]
3
>>> qml.specs(optimized_qnode)()["gate_types"]["CNOT"]
2
>>> print(qml.draw(qnode)())
0: ─╭X──────────╭X────┤  <X>
1: ─│──╭●─╭X──Z─│──╭●─┤
2: ─│──│──╰●─╭●─├●─│──┤
3: ─├●─│───H─╰X─╰●─│──┤
4: ─╰●─╰X──────────╰X─┤
>>> print(qml.draw(optimized_qnode)())
0: ─╭X──────────╭X─┤  <X>
1: ─│─────╭X──Z─│──┤
2: ─│──╭●─╰●─╭●─├●─┤
3: ─├●─│───H─╰X─╰●─┤
4: ─╰●─╰X──────────┤

Reference:

[1] Iten, R., Moyard, R., Metger, T., Sutter, D. and Woerner, S., 2022. Exact and practical pattern matching for quantum circuit optimization. doi.org/10.1145/3498325

Contents

Using PennyLane

Development

API

Internals