qml.排队

概述

警告

除非您是PennyLane开发者,否则您可能不需要直接使用这些类。

该模块包含用于将对象放入队列的类。

描述

用户提供 量子函数,PennyLane 需要将其转换为能够被设备执行的电路表示。量子函数是任何可调用的内容:

例如:

def qfunc(x, scale_value=1):
    qml.RX(x * scale_value, wires=0)
    if (1 != 2):
        qml.S(0)
    return qml.expval(qml.Z(0)), qml.expval(qml.X(1))

要将量子函数转换为电路的表示,我们使用排队。

一个 可排队对象 是任何可以放入队列中的东西。这些将是 OperatorMeasurementProcessQuantumTape 对象。 OperatorMeasurementProcess 对象通过构造时调用的 queue() 方法实现排队。 请注意,尽管 QuantumTape 是一个可排队对象,但它没有 queue 方法。

当一个对象被排队时,它将自身发送到 QueuingManagerQueuingManager 是一个全局单例类,用于方便地将对象放入队列。所有 QueuingManager 的方法和属性都是类方法和属性,因此所有实例将访问相同的信息。

active_context() 是放置任何新对象的队列。QueuingManager 如果存在活动上下文,则被称为记录中

活动上下文是 AnnotatedQueue 实例。它们是 上下文管理器,录制发生在 with 块内。

让我们看一个例子。如果我们在AnnotatedQueue的上下文之外查询QueuingManager,我们会发现没有任何记录,且不存在活动上下文。

>>> print("Are we recording? ", qml.QueuingManager.recording())
Are we recording?  False
>>> print("What's the active context? ", qml.QueuingManager.active_context())
What's the active context?  None

在一个上下文中,我们可以看到活动的记录上下文:

>>> with qml.queuing.AnnotatedQueue() as q:
...     print("Are we recording? ", qml.QueuingManager.recording())
...     print("Is q the active queue? ", q is qml.QueuingManager.active_context())
Are we recording?  True
Is q the active queue?  True

如果我们有嵌套的 AnnotatedQueue 上下文,只有最内层的一个会进行记录。 一旦当前活动的队列退出,任何外层队列将恢复记录。

>>> with qml.queuing.AnnotatedQueue() as q1:
...     print("Is q1 recording? ", q1 is qml.QueuingManager.active_context())
...     with qml.queuing.AnnotatedQueue() as q2:
...         print("Is q1 recording? ", q1 is qml.QueuingManager.active_context())
...     print("Is q1 recording? ", q1 is qml.QueuingManager.active_context())
Is q1 recording?  True
Is q1 recording?  False
Is q1 recording?  True

如果我们在录制上下文中构造一个算子,我们可以看到它被添加到队列中:

>>> with qml.queuing.AnnotatedQueue() as q:
...     op = qml.X(0)
>>> q.queue
[X(0)]

如果一个运算符是在上下文之外构造的,我们可以通过调用queue()方法手动将其添加到队列中。queue()方法在初始化时会自动调用,但也可以在稍后的时间手动调用。

>>> op = qml.X(0)
>>> with qml.queuing.AnnotatedQueue() as q:
...     op.queue()
>>> q.queue
[X(0)]

一个对象在队列中只能存在一次,因此多次调用队列将不会产生任何效果。

>>> op = qml.X(0)
>>> with qml.queuing.AnnotatedQueue() as q:
...     op.queue()
...     op.queue()
>>> q.queue
[X(0)]

这个 apply() 方法允许将单个对象多次排队到电路中。 如果该对象已经在队列中,函数会排队一个原始对象的副本。

>>> op = qml.X(0)
>>> with qml.queuing.AnnotatedQueue() as q:
...     qml.apply(op)
...     qml.apply(op)
>>> q.queue
[X(0), X(0)]
>>> q.queue[0] is q.queue[1]
False

在由其他运算符组成的运算符的情况下,比如SymbolicOpCompositeOp,新的嵌套操作会从队列中移除其组成部分。只会保留最终将进入电路的运算符。

>>> with qml.queuing.AnnotatedQueue() as q:
...     base = qml.X(0)
...     print(q.queue)
...     pow_op = base ** 1.5
...     print(q.queue)
[X(0)]
[X(0)**1.5]

一旦队列构建完成,process_queue() 函数将其转换为最终电路中的操作和测量。这个步骤消除了任何有所有者的对象。

>>> with qml.queuing.AnnotatedQueue() as q:
...     qml.StatePrep(np.array([1.0, 0]), wires=0)
...     base = qml.X(0)
...     pow_op = base ** 1.5
...     qml.expval(qml.Z(0) @ qml.X(1))
>>> ops, measurements = qml.queuing.process_queue(q)
>>> ops
[StatePrep(tensor([1., 0.], requires_grad=True), wires=[0]), X(0)**1.5]
>>> measurements
[expval(Z(0) @ X(1))]

这些列表可以用来构建一个 QuantumScript

>>> qml.tape.QuantumScript(ops, measurements)
<QuantumScript: wires=[0, 1], params=1>

为了在录制中构造新的操作符,但不将其排队,请在构造时使用stop_recording()上下文:

>>> with qml.queuing.AnnotatedQueue() as q:
...     with qml.QueuingManager.stop_recording():
...         qml.Y(1)
>>> q.queue
[]

函数

apply(op[, context])

将已实例化的算子或测量应用于排队上下文。

process_queue(队列)

处理标注的队列,创建量子操作和测量过程的列表。

AnnotatedQueue

轻量级类,除了元数据注释之外,还维护基本的操作队列。

QueuingError

当出现排队错误时引发的异常

QueuingManager()

管理活动录音上下文的单例全局入口点。

WrappedObj(对象)

包装一个对象,使其哈希值依赖于其身份