qml.specs¶
- specs(qnode, level='gradient', compute_depth=True)[source]¶
Provides the specifications of a quantum circuit.
This transform converts a QNode into a callable that provides resource information about the circuit after applying the specified amount of transforms/expansions first.
- Parameters:
qnode (.QNode | .QJIT) – the QNode to calculate the specifications for.
- Keyword Arguments:
level (str | int | slice | iter[int]) – An indication of which transforms to apply before computing the resource information.
compute_depth (bool) – Whether to compute the depth of the circuit. If
False, the depth will not be included in the returned information. Default: True
- Returns:
A function that has the same argument signature as
qnode. This function returns aCircuitSpecsobject containing theqnodespecifications.
Example
from pennylane import numpy as pnp dev = qml.device("default.qubit", wires=2) x = pnp.array([0.1, 0.2]) Hamiltonian = qml.dot([1.0, 0.5], [qml.X(0), qml.Y(0)]) gradient_kwargs = {"shifts": pnp.pi / 4} @qml.qnode(dev, diff_method="parameter-shift", gradient_kwargs=gradient_kwargs) def circuit(x, add_ry=True): qml.RX(x[0], wires=0) qml.CNOT(wires=(0,1)) qml.TrotterProduct(Hamiltonian, time=1.0, n=4, order=2) if add_ry: qml.RY(x[1], wires=1) qml.TrotterProduct(Hamiltonian, time=1.0, n=4, order=4) return qml.probs(wires=(0,1))
>>> print(qml.specs(circuit)(x, add_ry=False)) Device: default.qubit Device wires: 2 Shots: Shots(total=None) Level: gradient Resource specifications: Total qubit allocations: 2 Total gates: 98 Circuit depth: 98 Gate types: RX: 1 CNOT: 1 Evolution: 96 Measurements: probs(all wires): 1
Usage Details
Here you can see how the number of gates and their types change as we apply different amounts of transforms through the
levelargument:dev = qml.device("default.qubit") gradient_kwargs = {"shifts": pnp.pi / 4} @qml.transforms.merge_rotations @qml.transforms.undo_swaps @qml.transforms.cancel_inverses @qml.qnode(dev, diff_method="parameter-shift", gradient_kwargs=gradient_kwargs) def circuit(x): qml.RandomLayers(pnp.array([[1.0, 2.0]]), wires=(0, 1)) qml.RX(x, wires=0) qml.RX(-x, wires=0) qml.SWAP((0, 1)) qml.X(0) qml.X(0) return qml.expval(qml.X(0) + qml.Y(1))
First, we can check the resource information of the QNode without any modifications. Note that
level=topwould return the same results:>>> print(qml.specs(circuit, level=0)(0.1).resources) Total qubit allocations: 2 Total gates: 6 Circuit depth: 6 Gate types: RandomLayers: 1 RX: 2 SWAP: 1 PauliX: 2 Measurements: expval(Sum(num_wires=2, num_terms=2)): 1
We then check the resources after applying all transforms:
>>> print(qml.specs(circuit, level="device")(0.1).resources) Total qubit allocations: 2 Total gates: 2 Circuit depth: 1 Gate types: RY: 1 RX: 1 Measurements: expval(Sum(num_wires=2, num_terms=2)): 1
We can also notice that
SWAPandPauliXare not present in the circuit if we setlevel=2:>>> print(qml.specs(circuit, level=2)(0.1).resources) Total qubit allocations: 2 Total gates: 3 Circuit depth: 3 Gate types: RandomLayers: 1 RX: 2 Measurements: expval(Sum(num_wires=2, num_terms=2)): 1
If a QNode with a tape-splitting transform is supplied to the function, with the transform included in the desired transforms, the specs output’s resources field is instead returned as a list with a
CircuitSpecsfor each resulting tape:dev = qml.device("default.qubit") H = qml.Hamiltonian([0.2, -0.543], [qml.X(0) @ qml.Z(1), qml.Z(0) @ qml.Y(2)]) gradient_kwargs = {"shifts": pnp.pi / 4} @qml.transforms.split_non_commuting @qml.qnode(dev, diff_method="parameter-shift", gradient_kwargs=gradient_kwargs) def circuit(): qml.RandomLayers(qml.numpy.array([[1.0, 2.0]]), wires=(0, 1)) return qml.expval(H)
>>> from pprint import pprint >>> pprint(qml.specs(circuit, level="user")()) CircuitSpecs(device_name='default.qubit', num_device_wires=None, shots=Shots(total_shots=None, shot_vector=()), level='user', resources=[SpecsResources(gate_types={'RandomLayers': 1}, gate_sizes={2: 1}, measurements={'expval(Prod(num_wires=2, num_terms=2))': 1}, num_allocs=2, depth=1), SpecsResources(gate_types={'RandomLayers': 1}, gate_sizes={2: 1}, measurements={'expval(Prod(num_wires=2, num_terms=2))': 1}, num_allocs=3, depth=1)])