qml.tape.OperationRecorder

class OperationRecorder[source]

Bases: pennylane.tape.tape.QuantumTape

A template and quantum function inspector, allowing easy introspection of operators that have been applied without requiring a QNode.

Example:

The OperationRecorder is a context manager. Executing templates or quantum functions stores applied operators in the recorder, which can then be printed.

>>> shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=1, n_wires=2)
>>> weights = np.random.random(shape)
>>>
>>> with OperationRecorder() as rec:
>>>    qml.templates.StronglyEntanglingLayers(weights, wires=[0, 1])

Alternatively, the queue attribute can be used to directly access the applied Operation and Observable objects.

batch_size

The batch size of the quantum tape inferred from the batch sizes of the used operations for parameter broadcasting.

circuit

Returns the quantum circuit recorded by the tape.

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:

hash

returns an integer hash uniquely representing the quantum tape

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.

numeric_type

Returns the expected numeric type of the tape result by inspecting its measurements.

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

specs

Resource information about a quantum circuit.

trainable_params

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

batch_size

The batch size of the quantum tape inferred from the batch sizes of the used operations for parameter broadcasting.

See also

batch_size for details.

Returns

The batch size of the quantum tape if present, else None.

Return type

int or None

circuit

Returns the quantum circuit recorded by the tape.

The circuit is created with the assumptions that:

  • The operations attribute contains quantum operations and mid-circuit measurements and

  • The measurements attribute contains terminal measurements.

Note that the resulting list could contain MeasurementProcess objects that some devices may not support.

Returns

the quantum circuit containing quantum operations and measurements as recorded by the tape.

Return type

list[Operator, MeasurementProcess]

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.circuit_graph.CircuitGraph 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

CircuitGraph

hash

returns an integer hash uniquely representing the quantum tape

Type

int

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 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')
    qml.expval(qml.PauliZ(wires=[0]))
>>> tape.measurements
[expval(PauliZ(wires=[0]))]
num_params

Returns the number of trainable parameters on the quantum tape.

numeric_type

Returns the expected numeric type of the tape result by inspecting its measurements.

Raises

TapeError – raised for unsupported cases for example when the tape contains heterogeneous measurements

Returns

the numeric type corresponding to the result type of the tape

Return type

type

Example:

dev = qml.device("default.qubit", wires=2)
a = np.array([0.1, 0.2, 0.3])

def func(a):
    qml.RY(a[0], wires=0)
    qml.RX(a[1], wires=0)
    qml.RY(a[2], wires=0)

with qml.tape.QuantumTape() as tape:
    func(a)
    qml.state()
>>> tape.numeric_type
complex
observables

Returns the observables on the quantum tape.

Returns

list of recorded quantum operations

Return type

list[Observable]

Example

with 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')
    qml.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 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')
    qml.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
specs

Resource information about a quantum circuit.

Returns

dictionaries that contain tape specifications

Return type

dict[str, Union[defaultdict,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 specs produces a dictionary as shown below:

>>> tape.specs['gate_sizes']
defaultdict(int, {1: 4, 2: 2})
>>> tape.specs['gate_types']
defaultdict(int, {'Hadamard': 2, 'RZ': 1, 'CNOT': 2, 'Rot': 1})

As defaultdict objects, any key not present in the dictionary returns 0.

>>> tape.specs['gate_types']['RX']
0
trainable_params

Store or return a list 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(), and changes the default output size of method get_parameters().

Note

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 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')
    qml.expval(qml.PauliZ(wires=[0]))
>>> tape.trainable_params
[0, 1, 2]
>>> tape.trainable_params = [0] # set only the first parameter as trainable
>>> tape.get_parameters()
[0.432]

active_context()

Returns the currently active queuing context.

adjoint()

Create a tape that is the adjoint of this one.

append(obj, **kwargs)

Append an object to this QueuingContext instance.

copy([copy_operations])

Returns a shallow copy of the quantum tape.

draw([wire_order, show_all_wires, decimals, …])

Draw the quantum tape as a circuit diagram.

expand([depth, stop_at, expand_measurements])

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

get_info(obj)

Retrieves information of an object in the queue instance.

get_operation(idx)

Returns the trainable operation, and the corresponding operation argument index, for a specified trainable parameter index.

get_parameters([trainable_only, operations_only])

Return the parameters incident on the tape operations.

inv()

Inverts the processed operations.

recording()

Whether a queuing context is active and recording operations

remove(obj)

Remove an object from this QueuingContext instance.

safe_update_info(obj, **kwargs)

Updates information of an object in the queue instance only if the object is in the queue.

set_parameters(params[, trainable_only])

Set the parameters incident on the tape operations.

shape(device)

Produces the output shape of the tape by inspecting its measurements and the device used for execution.

stop_recording()

Context manager to temporarily stop recording operations onto the tape.

to_openqasm([wires, rotations, measure_all, …])

Serialize the circuit as an OpenQASM 2.0 program.

unwrap()

A context manager that unwraps a tape with tensor-like parameters to NumPy arrays.

update_info(obj, **kwargs)

Updates information of an object in the queue instance.

classmethod active_context()

Returns the currently active queuing context.

adjoint()

Create a tape that is the adjoint of this one.

Adjointed tapes are the conjugated and transposed version of the original tapes. Adjointed ops are equivalent to the inverted operation for unitary gates.

Returns

the adjointed tape

Return type

QuantumTape

append(obj, **kwargs)

Append an object to this QueuingContext instance.

Parameters

obj – The object to be appended

copy(copy_operations=False)

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.

Returns

a shallow copy of the tape

Return type

QuantumTape

draw(wire_order=None, show_all_wires=False, decimals=None, max_length=100, show_matrices=False)

Draw the quantum tape as a circuit diagram. See tape_text() for more information.

Parameters
  • wire_order (Sequence[Any]) – the order (from top to bottom) to print the wires of the circuit

  • show_all_wires (bool) – If True, all wires, including empty wires, are printed.

  • decimals (int) – How many decimal points to include when formatting operation parameters. Default None will omit parameters from operation labels.

  • max_length (Int) – Maximum length of a individual line. After this length, the diagram will begin anew beneath the previous lines.

  • show_matrices=False (bool) – show matrix valued parameters below all circuit diagrams

Returns

the circuit representation of the tape

Return type

str

expand(depth=1, stop_at=None, expand_measurements=False)

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 QuantumTape() as tape:
    qml.BasisState(np.array([1, 1]), wires=[0, 'a'])

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

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

The nested structure is preserved:

>>> tape.operations
[BasisState(array([1, 1]), wires=[0, 'a']),
 <QuantumTape: 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(depth=2)
>>> new_tape.operations
[PauliX(wires=[0]),
PauliX(wires=['a']),
RZ(0.543, wires=[0]),
RY(0.1, wires=[0]),
RZ(0.4, wires=[0]),
CNOT(wires=[0, 'a']),
RY(0.2, wires=['a'])]
get_info(obj)

Retrieves information of an object in the queue instance.

get_operation(idx)

Returns the trainable operation, and the corresponding operation argument index, for a specified trainable parameter index.

Parameters

idx (int) – the trainable parameter index

Returns

tuple containing the corresponding operation, and an integer representing the argument index, for the provided trainable parameter.

Return type

tuple[Operation, int]

get_parameters(trainable_only=True, operations_only=False, **kwargs)

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

  • operations_only (bool) – if True, returns only the parameters of the operations excluding parameters to observables of measurements

Example

with 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')
    qml.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 trainable
>>> 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]
inv()

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 QuantumTape() 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'])
    qml.probs(wires=0), qml.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

remove(obj)

Remove an object from this QueuingContext instance.

Parameters

obj – the object to be removed

safe_update_info(obj, **kwargs)

Updates information of an object in the queue instance only if the object is in the queue. If the object is not in the queue, nothing is done and no errors are raised.

set_parameters(params, trainable_only=True)

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 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')
    qml.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 trainable
>>> 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]
shape(device)

Produces the output shape of the tape by inspecting its measurements and the device used for execution.

Note

The computed shape is not stored because the output shape may be dependent on the device used for execution.

Parameters

device (Device) – the device that will be used for the tape execution

Raises

TapeError – raised for unsupported cases for example when the tape contains heterogeneous measurements

Returns

the output shape(s) of the tape result

Return type

Union[tuple[int], list[tuple[int]]]

Example:

dev = qml.device("default.qubit", wires=2)
a = np.array([0.1, 0.2, 0.3])

def func(a):
    qml.RY(a[0], wires=0)
    qml.RX(a[1], wires=0)
    qml.RY(a[2], wires=0)

with qml.tape.QuantumTape() as tape:
    func(a)
    qml.state()
>>> tape.shape(dev)
(1, 4)
stop_recording()

Context manager to temporarily stop recording operations onto the tape. This is useful is scratch space is needed.

Example

>>> with qml.tape.QuantumTape() as tape:
...     qml.RX(0, wires=0)
...     with tape.stop_recording():
...         qml.RY(1.0, wires=1)
...     qml.RZ(2, wires=1)
>>> tape.operations
[RX(0, wires=[0]), RZ(2, wires=[1])]
to_openqasm(wires=None, rotations=True, measure_all=True, precision=None)

Serialize the circuit as an OpenQASM 2.0 program.

Measurements are assumed to be performed on all qubits in the computational basis. An optional rotations argument can be provided so that output of the OpenQASM circuit is diagonal in the eigenbasis of the tape’s observables. The measurement outputs can be restricted to only those specified in the tape by setting measure_all=False.

Note

The serialized OpenQASM program assumes that gate definitions in qelib1.inc are available.

Parameters
  • wires (Wires or None) – the wires to use when serializing the circuit

  • rotations (bool) – in addition to serializing user-specified operations, also include the gates that diagonalize the measured wires such that they are in the eigenbasis of the circuit observables.

  • measure_all (bool) – whether to perform a computational basis measurement on all qubits or just those specified in the tape

  • precision (int) – decimal digits to display for parameters

Returns

OpenQASM serialization of the circuit

Return type

str

unwrap()

A context manager that unwraps a tape with tensor-like parameters to NumPy arrays.

Parameters

tape (QuantumTape) – the quantum tape to unwrap

Returns

the unwrapped quantum tape

Return type

QuantumTape

Example

>>> with tf.GradientTape():
...     with qml.tape.QuantumTape() as tape:
...         qml.RX(tf.Variable(0.1), wires=0)
...         qml.RY(tf.constant(0.2), wires=0)
...         qml.RZ(tf.Variable(0.3), wires=0)
...     with tape.unwrap():
...         print("Trainable params:", tape.trainable_params)
...         print("Unwrapped params:", tape.get_parameters())
Trainable params: [0, 2]
Unwrapped params: [0.1, 0.3]
>>> print("Original parameters:", tape.get_parameters())
Original parameters: [<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=0.1>,
  <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=0.3>]
update_info(obj, **kwargs)

Updates information of an object in the queue instance. Raises a QueuingError if the object is not in the queue.