qml.estimator.estimate.estimate

estimate(workflow, gate_set=None, zeroed_wires=0, any_state_wires=0, tight_wires_budget=False, config=None)[source]

Estimate the quantum resources required to implement a circuit or operator in terms of a given gateset.

Parameters:
  • workflow (Callable | ResourceOperator | Resources | QNode) – The quantum circuit or operator for which to estimate resources.

  • gate_set (set[str] | None) – A set of names (strings) of the fundamental operators to count throughout the quantum workflow. If not provided, the default gate set will be used, i.e., {'Toffoli', 'T', 'CNOT', 'X', 'Y', 'Z', 'S', 'Hadamard'}.

  • zeroed_wires (int) – Number of work wires pre-allocated in the zeroed state. Default is 0.

  • any_state_wires (int) – Number of work wires pre-allocated in an unknown state. Default is 0.

  • tight_wires_budget (bool) – If True, extra work wires may not be allocated in addition to the pre-allocated ones. The default is False.

  • config (ResourceConfig | None) – Configurations for the resource estimation pipeline.

Returns:

The estimated quantum resources required to execute the circuit.

Return type:

Resources | Callable[…, Resources]

Raises:

TypeError – If the workflow is of an invalid type.

Example

The resources of a quantum workflow can be estimated by supplying a quantum function describing the workflow. The function can be written in terms of resource operators:

import pennylane.estimator as qre

def circuit():
    qre.Hadamard()
    qre.CNOT()
    qre.QFT(num_wires=4)
>>> res = qre.estimate(circuit)()
>>> print(res)
--- Resources: ---
 Total wires: 4
   algorithmic wires: 4
   allocated wires: 0
     zero state: 0
     any state: 0
 Total gates : 816
   'T': 792,
   'CNOT': 19,
   'Hadamard': 5

The resource estimation can be performed with respect to an alternative gate set:

>>> res = qre.estimate(circuit, gate_set={"RX", "RZ", "Hadamard", "CNOT"})()
>>> print(res)
--- Resources: ---
 Total wires: 4
   algorithmic wires: 4
   allocated wires: 0
     zero state: 0
     any state: 0
 Total gates : 42
   'RZ': 18,
   'CNOT': 19,
   'Hadamard': 5

Most PennyLane operators have a corresponding resource operator defined in the pennylane.estimator module. The resource operator is a lightweight representation of an operator that contains the minimum information required to perform resource estimation. For most basic operators, it is simply the type of the operator. For more complex operators and templates, you may be required to provide more information as specified in the operator’s resource_params, such as the number of wires.

import pennylane.estimator as qre

def circuit():
    qre.CNOT()
    qre.MultiRZ(num_wires=3)
    qre.CNOT()
    qre.MultiRZ(num_wires=3)
>>> res = qre.estimate(circuit)()
>>> print(res)
--- Resources: ---
 Total wires: 3
   algorithmic wires: 3
   allocated wires: 0
     zero state: 0
     any state: 0
 Total gates : 98
   'T': 88,
   'CNOT': 10

The estimate function returns a Resources object, which contains an estimate of the total number of gates (after decomposing to the fundamental gate set) and the total number of wires that the gates in this circuit act on (i.e., the “algorithmic wires”). When explicit wire labels are not provided, the operators are assumed to be overlapping, which may lead to an underestimate. For a more accurate estimate of the number of wires used by a circuit, you may optionally provide explicit wire labels via the wires argument:

import pennylane.estimator as qre

def circuit():
    qre.CNOT()
    qre.MultiRZ(wires=[0, 1, 2])
    qre.CNOT()
    qre.MultiRZ(wires=[2, 3, 4])
>>> res = qre.estimate(circuit)()
>>> print(res)
--- Resources: ---
 Total wires: 7
   algorithmic wires: 7
   allocated wires: 0
     zero state: 0
     any state: 0
 Total gates : 98
   'T': 88,
   'CNOT': 10

For a detailed explanation of the “allocated wires”, see the “Dynamic work wire allocation in decompositions” section below.

Some operators require additional auxiliary wires (work wires) to decompose. These wires are not part of the operator’s definition, so they will be dynamically allocated when performing the operator’s decomposition. The estimate function also tracks the usage of these dynamically allocated wires.

import pennylane.estimator as qre

def circuit():
    qre.Hadamard()
    qre.CNOT()
    qre.AliasSampling(num_coeffs=3)
>>> res = qre.estimate(circuit)()
>>> print(res)
--- Resources: ---
 Total wires: 123
   algorithmic wires: 2
   allocated wires: 121
     zero state: 58
     any state: 63
 Total gates : 1.271E+3
   'Toffoli': 65,
   'T': 88,
   'CNOT': 639,
   'X': 195,
   'Hadamard': 284

In the above example, a total of 121 work wires were allocated (in the zeroed state) to perform the decomposition of the AliasSampling, 58 of which were restored to the original zeroed state before deallocation, and the rest were deallocated in an unknown state. You may also pre-allocate work wires:

>>> res = qre.estimate(circuit, zeroed_wires=150)()
>>> print(res)
--- Resources: ---
 Total wires: 152
   algorithmic wires: 2
   allocated wires: 150
     zero state: 87
     any state: 63
 Total gates : 1.271E+3
   'Toffoli': 65,
   'T': 88,
   'CNOT': 639,
   'X': 195,
   'Hadamard': 284

In this case, you have the option to treat this pre-allocated pool of work wires as the only work wires available, by setting tight_wires_budget=True, then an error is raised if the required number of wires exceeds the number of pre-allocated wires.

The estimate function can also be used to estimate the resources of a standard PennyLane circuit.

import pennylane as qml
import pennylane.estimator as qre

@qml.qnode(qml.device("default.qubit"))
def circuit():
    qml.Hadamard(0)
    qml.CNOT(wires=[0, 1])
    qml.QFT(wires=[0, 1, 2, 3])
>>> res = qre.estimate(circuit)()
>>> print(res)
--- Resources: ---
 Total wires: 4
   algorithmic wires: 4
   allocated wires: 0
     zero state: 0
     any state: 0
 Total gates : 816
   'T': 792,
   'CNOT': 19,
   'Hadamard': 5