qml.tape.QuantumTape

class QuantumTape(name=None)[source]

Bases: pennylane.tape.queuing.AnnotatedQueue

A quantum tape recorder, that records, validates and executes variational quantum programs.

Note

As the quantum tape is a beta feature. See pennylane.tape for more details.

Parameters

name (str) – a name given to the quantum tape

Example

import pennylane.tape

with qml.tape.QuantumTape() as tape:
    qml.RX(0.432, wires=0)
    qml.RY(0.543, wires=0)
    qml.CNOT(wires=[0, 'a'])
    qml.RX(0.133, wires='a')
    expval(qml.PauliZ(wires=[0]))

Once constructed, information about the quantum circuit can be queried:

>>> tape.operations
[RX(0.432, wires=[0]), RY(0.543, wires=[0]), CNOT(wires=[0, 'a']), RX(0.133, wires=['a'])]
>>> tape.observables
[expval(PauliZ(wires=[0]))]
>>> tape.get_parameters()
[0.432, 0.543, 0.133]
>>> tape.wires
<Wires = [0, 'a']>
>>> tape.num_params
3

The TapeCircuitGraph can also be accessed:

>>> tape.graph
<pennylane.tape.circuit_graph.TapeCircuitGraph object at 0x7fcc0433a690>

Once constructed, the quantum tape can be executed directly on a supported device:

>>> dev = qml.device("default.qubit", wires=[0, 'a'])

Execution can take place either using the in-place constructed parameters,

>>> tape.execute(dev)
[0.77750694]

or by providing parameters at run time:

>>> tape.execute(dev, params=[0.1, 0.1, 0.1])
[0.99003329]

The trainable parameters of the tape can be explicitly set, and the values of the parameters modified in-place:

>>> tape.trainable_params = {0} # set only the first parameter as free
>>> tape.set_parameters(0.56)
>>> tape.get_parameters()
[0.56]
>>> tape.get_parameters(trainable_only=False)
[0.56, 0.543, 0.133]

data

Alias to get_parameters() and set_parameters() for backwards compatibilities with operations.

diagonalizing_gates

Returns the gates that diagonalize the measured wires such that they are in the eigenbasis of the circuit observables.

graph

Returns a directed acyclic graph representation of the recorded quantum circuit:

interface

automatic differentiation interface used by the quantum tape (if any)

measurements

Returns the measurements on the quantum tape.

num_params

Returns the number of trainable parameters on the quantum tape.

observables

Returns the observables on the quantum tape.

operations

Returns the operations on the quantum tape.

output_dim

The (inferred) output dimension of the quantum tape.

queue

Returns a list of objects in the annotated queue

trainable_params

Store or return a set containing the indices of parameters that support differentiability.

data

Alias to get_parameters() and set_parameters() for backwards compatibilities with operations.

diagonalizing_gates

Returns the gates that diagonalize the measured wires such that they are in the eigenbasis of the circuit observables.

Returns

the operations that diagonalize the observables

Return type

List[Operation]

graph

Returns a directed acyclic graph representation of the recorded quantum circuit:

>>> tape.graph
<pennylane.tape.circuit_graph.TapeCircuitGraph object at 0x7fcc0433a690>

Note that the circuit graph is only constructed once, on first call to this property, and cached for future use.

Returns

the circuit graph object

Return type

TapeCircuitGraph

interface

automatic differentiation interface used by the quantum tape (if any)

Type

str, None

measurements

Returns the measurements on the quantum tape.

Returns

list of recorded measurement processess

Return type

list[MeasurementProcess]

Example

with JacobianTape() as tape:
    qml.RX(0.432, wires=0)
    qml.RY(0.543, wires=0)
    qml.CNOT(wires=[0, 'a'])
    qml.RX(0.133, wires='a')
    expval(qml.PauliZ(wires=[0]))
>>> tape.measurements
[<pennylane.tape.measure.MeasurementProcess object at 0x7f10b2150c10>]
num_params

Returns the number of trainable parameters on the quantum tape.

observables

Returns the observables on the quantum tape.

Returns

list of recorded quantum operations

Return type

list[Observable]

Example

with JacobianTape() as tape:
    qml.RX(0.432, wires=0)
    qml.RY(0.543, wires=0)
    qml.CNOT(wires=[0, 'a'])
    qml.RX(0.133, wires='a')
    expval(qml.PauliZ(wires=[0]))
>>> tape.observables
[expval(PauliZ(wires=[0]))]
operations

Returns the operations on the quantum tape.

Returns

recorded quantum operations

Return type

list[Operation]

Example

with JacobianTape() as tape:
    qml.RX(0.432, wires=0)
    qml.RY(0.543, wires=0)
    qml.CNOT(wires=[0, 'a'])
    qml.RX(0.133, wires='a')
    expval(qml.PauliZ(wires=[0]))
>>> tape.operations
[RX(0.432, wires=[0]), RY(0.543, wires=[0]), CNOT(wires=[0, 'a']), RX(0.133, wires=['a'])]
output_dim

The (inferred) output dimension of the quantum tape.

queue

Returns a list of objects in the annotated queue

trainable_params

Store or return a set containing the indices of parameters that support differentiability. The indices provided match the order of appearence in the quantum circuit.

Setting this property can help reduce the number of quantum evaluations needed to compute the Jacobian; parameters not marked as trainable will be automatically excluded from the Jacobian computation.

The number of trainable parameters determines the number of parameters passed to set_parameters(), execute(), and jacobian(), and changes the default output size of methods jacobian() and get_parameters().

Note

Since the jacobian() method is not called for devices that support native backpropagation (such as default.qubit.tf and default.qubit.autograd), this property contains no relevant information when using backpropagation to compute gradients.

Example

with JacobianTape() as tape:
    qml.RX(0.432, wires=0)
    qml.RY(0.543, wires=0)
    qml.CNOT(wires=[0, 'a'])
    qml.RX(0.133, wires='a')
    expval(qml.PauliZ(wires=[0]))
>>> tape.trainable_params
{0, 1, 2}
>>> tape.trainable_params = {0} # set only the first parameter as free
>>> tape.get_parameters()
[0.432]
Parameters

param_indices (set[int]) – parameter indices

active_context()

Returns the currently active queuing context.

append(obj, **kwargs)

Append an object to the queue(s).

copy([copy_operations, tape_cls])

Returns a shallow copy of the quantum tape.

draw([charset])

Draw the quantum tape as a circuit diagram.

execute(device[, params])

Execute the tape on a quantum device.

execute_device(params, device)

Execute the tape on a quantum device.

expand([depth, stop_at, expand_measurements])

Expand all operations in the processed queue to a specific depth.

get_depth()

Depth of the quantum circuit.

get_info(obj)

Retrieves information of an object in the active queue.

get_parameters([trainable_only])

Return the parameters incident on the tape operations.

get_resources()

Resource requirements of a quantum circuit.

inv()

Inverts the processed operations.

recording()

Whether a queuing context is active and recording operations

remove(obj)

Remove an object from the queue(s) if it is in the queue(s).

set_parameters(params[, trainable_only])

Set the parameters incident on the tape operations.

update_info(obj, **kwargs)

Updates information of an object in the active queue.

classmethod active_context()

Returns the currently active queuing context.

classmethod append(obj, **kwargs)

Append an object to the queue(s).

Parameters

obj – the object to be appended

copy(copy_operations=False, tape_cls=None)[source]

Returns a shallow copy of the quantum tape.

Parameters
  • copy_operations (bool) – If True, the tape operations are also shallow copied. Otherwise, if False, the copied tape operations will simply be references to the original tape operations; changing the parameters of one tape will likewise change the parameters of all copies.

  • tape_cls (QuantumTape) – Cast the copied tape to a specific quantum tape subclass. If not provided, the same subclass is used as the original tape.

Returns

a shallow copy of the tape

Return type

QuantumTape

draw(charset='unicode')[source]

Draw the quantum tape as a circuit diagram.

Consider the following circuit as an example:

with QuantumTape() as tape:
    qml.Hadamard(0)
    qml.CRX(2.3, wires=[0, 1])
    qml.Rot(1.2, 3.2, 0.7, wires=[1])
    qml.CRX(-2.3, wires=[0, 1])
    qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))

We can draw the tape after construction:

>>> print(tape.draw())
0: ──H──╭C────────────────────────────╭C─────────╭┤ ⟨Z ⊗ Z⟩
1: ─────╰RX(2.3)──Rot(1.2, 3.2, 0.7)──╰RX(-2.3)──╰┤ ⟨Z ⊗ Z⟩
>>> print(tape.draw(charset="ascii"))
0: --H--+C----------------------------+C---------+| <Z @ Z>
1: -----+RX(2.3)--Rot(1.2, 3.2, 0.7)--+RX(-2.3)--+| <Z @ Z>
Parameters

charset (str, optional) – The charset that should be used. Currently, “unicode” and “ascii” are supported.

Raises

ValueError – if the given charset is not supported

Returns

the circuit representation of the tape

Return type

str

execute(device, params=None)[source]

Execute the tape on a quantum device.

Parameters
  • device (Device) – a PennyLane device that can execute quantum operations and return measurement statistics

  • params (list[Any]) – The quantum tape operation parameters. If not provided, the current tape parameters are used (via get_parameters()).

Example

with JacobianTape() as tape:
    qml.RX(0.432, wires=0)
    qml.RY(0.543, wires=0)
    qml.CNOT(wires=[0, 'a'])
    qml.RX(0.133, wires='a')
    probs(wires=[0, 'a'])

If parameters are not provided, the existing tape parameters are used:

>>> dev = qml.device("default.qubit", wires=[0, 'a'])
>>> tape.execute(dev)
array([[8.84828969e-01, 3.92449987e-03, 4.91235209e-04, 1.10755296e-01]])

Parameters can be optionally passed during execution:

>>> tape.execute(dev, params=[1.0, 0.0, 1.0])
array([[0.5931328 , 0.17701835, 0.05283049, 0.17701835]])

Parameters provided for execution are temporary, and do not affect the tapes’ parameters in-place:

>>> tape.get_parameters()
[0.432, 0.543, 0.133]
execute_device(params, device)[source]

Execute the tape on a quantum device.

This is a low-level method, intended to be called by an interface, and does not support autodifferentiation.

For more details on differentiable tape execution, see execute().

Parameters
  • device (Device) – a PennyLane device that can execute quantum operations and return measurement statistics

  • params (list[Any]) – The quantum tape operation parameters. If not provided, the current tape parameter values are used (via get_parameters()).

expand(depth=1, stop_at=None, expand_measurements=False)[source]

Expand all operations in the processed queue to a specific depth.

Parameters
  • depth (int) – the depth the tape should be expanded

  • stop_at (Callable) – A function which accepts a queue object, and returns True if this object should not be expanded. If not provided, all objects that support expansion will be expanded.

  • expand_measurements (bool) – If True, measurements will be expanded to basis rotations and computational basis measurements.

Example

Consider the following nested tape:

with JacobianTape() as tape:
    qml.BasisState(np.array([1, 1]), wires=[0, 'a'])

    with JacobianTape() as tape2:
        qml.Rot(0.543, 0.1, 0.4, wires=0)

    qml.CNOT(wires=[0, 'a'])
    qml.RY(0.2, wires='a')
    probs(wires=0), probs(wires='a')

The nested structure is preserved:

>>> tape.operations
[BasisState(array([1, 1]), wires=[0, 'a']),
 <JacobianTape: wires=[0], params=3>,
 CNOT(wires=[0, 'a']),
 RY(0.2, wires=['a'])]

Calling .expand will return a tape with all nested tapes expanded, resulting in a single tape of quantum operations:

>>> new_tape = tape.expand()
>>> new_tape.operations
[PauliX(wires=[0]),
 PauliX(wires=['a']),
 Rot(0.543, 0.1, 0.4, wires=[0]),
 CNOT(wires=[0, 'a']),
 RY(0.2, wires=['a'])]
get_depth()[source]

Depth of the quantum circuit.

Returns

Circuit depth, computed as the longest path in the circuit’s directed acyclic graph representation.

Return type

int

Example

with QuantumTape() as tape:
    qml.Hadamard(wires=0)
    qml.PauliX(wires=1)
    qml.CRX(2.3, wires=[0, 1])
    qml.Rot(1.2, 3.2, 0.7, wires=[1])
    qml.CRX(-2.3, wires=[0, 1])
    qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))

The depth can be obtained like so:

>>> tape.get_depth()
4
classmethod get_info(obj)

Retrieves information of an object in the active queue.

Parameters

obj – the object with metadata to be retrieved

Returns

object metadata

get_parameters(trainable_only=True)[source]

Return the parameters incident on the tape operations.

The returned parameters are provided in order of appearance on the tape.

Parameters

trainable_only (bool) – if True, returns only trainable parameters

Example

with JacobianTape() as tape:
    qml.RX(0.432, wires=0)
    qml.RY(0.543, wires=0)
    qml.CNOT(wires=[0, 'a'])
    qml.RX(0.133, wires='a')
    expval(qml.PauliZ(wires=[0]))

By default, all parameters are trainable and will be returned:

>>> tape.get_parameters()
[0.432, 0.543, 0.133]

Setting the trainable parameter indices will result in only the specified parameters being returned:

>>> tape.trainable_params = {1} # set the second parameter as free
>>> tape.get_parameters()
[0.543]

The trainable_only argument can be set to False to instead return all parameters:

>>> tape.get_parameters(trainable_only=False)
[0.432, 0.543, 0.133]
get_resources()[source]

Resource requirements of a quantum circuit.

Returns

how many times constituent operations are applied

Return type

dict[str, int]

Example

with qml.tape.QuantumTape() as tape:
    qml.Hadamard(wires=0)
    qml.RZ(0.26, wires=1)
    qml.CNOT(wires=[1, 0])
    qml.Rot(1.8, -2.7, 0.2, wires=0)
    qml.Hadamard(wires=1)
    qml.CNOT(wires=[0, 1])
    qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))

Asking for the resources produces a dictionary as shown below:

>>> tape.get_resources()
{'Hadamard': 2, 'RZ': 1, 'CNOT': 2, 'Rot': 1}
inv()[source]

Inverts the processed operations.

Inversion is performed in-place.

Note

This method only inverts the quantum operations/unitary recorded by the quantum tape; state preparations and measurements are left unchanged.

Example

with JacobianTape() as tape:
    qml.BasisState(np.array([1, 1]), wires=[0, 'a'])
    qml.RX(0.432, wires=0)
    qml.Rot(0.543, 0.1, 0.4, wires=0).inv()
    qml.CNOT(wires=[0, 'a'])
    probs(wires=0), probs(wires='a')

This tape has the following properties:

>>> tape.operations
[BasisState(array([1, 1]), wires=[0, 'a']),
 RX(0.432, wires=[0]),
 Rot.inv(0.543, 0.1, 0.4, wires=[0]),
 CNOT(wires=[0, 'a'])]
>>> tape.get_parameters()
[array([1, 1]), 0.432, 0.543, 0.1, 0.4]

Here, let’s set some trainable parameters:

>>> tape.trainable_params = {1, 2}
>>> tape.get_parameters()
[0.432, 0.543]

Inverting the tape:

>>> tape.inv()
>>> tape.operations
[BasisState(array([1, 1]), wires=[0, 'a']),
 CNOT.inv(wires=[0, 'a']),
 Rot(0.543, 0.1, 0.4, wires=[0]),
 RX.inv(0.432, wires=[0])]

Tape inversion also modifies the order of tape parameters:

>>> tape.get_parameters(trainable_only=False)
[array([1, 1]), 0.543, 0.1, 0.4, 0.432]
>>> tape.get_parameters(trainable_only=True)
[0.543, 0.432]
>>> tape.trainable_params
{1, 4}
classmethod recording()

Whether a queuing context is active and recording operations

classmethod remove(obj)

Remove an object from the queue(s) if it is in the queue(s).

Parameters

obj – the object to be removed

set_parameters(params, trainable_only=True)[source]

Set the parameters incident on the tape operations.

Parameters
  • params (list[float]) – A list of real numbers representing the parameters of the quantum operations. The parameters should be provided in order of appearance in the quantum tape.

  • trainable_only (bool) – if True, set only trainable parameters

Example

with JacobianTape() as tape:
    qml.RX(0.432, wires=0)
    qml.RY(0.543, wires=0)
    qml.CNOT(wires=[0, 'a'])
    qml.RX(0.133, wires='a')
    expval(qml.PauliZ(wires=[0]))

By default, all parameters are trainable and can be modified:

>>> tape.set_parameters([0.1, 0.2, 0.3])
>>> tape.get_parameters()
[0.1, 0.2, 0.3]

Setting the trainable parameter indices will result in only the specified parameters being modifiable. Note that this only modifies the number of parameters that must be passed.

>>> tape.trainable_params = {0, 2} # set the first and third parameter as free
>>> tape.set_parameters([-0.1, 0.5])
>>> tape.get_parameters(trainable_only=False)
[-0.1, 0.2, 0.5]

The trainable_only argument can be set to False to instead set all parameters:

>>> tape.set_parameters([4, 1, 6], trainable_only=False)
>>> tape.get_parameters(trainable_only=False)
[4, 1, 6]
classmethod update_info(obj, **kwargs)

Updates information of an object in the active queue.

Parameters

obj – the object with metadata to be updated