

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用 Amazon Braket 构建您的量子任务
<a name="braket-build"></a>

Braket 提供完全托管的 Jupyter Notebook 环境，可以让您轻松入门。Braket Notebook 预装了示例算法、资源和开发人员工具，包括 Amazon Braket SDK。借助 Amazon Braket SDK，您可以构建量子算法，然后通过更改一行代码在不同的量子计算机和模拟器上对其进行测试和运行。

**Topics**
+ [构建您的第一个电路](braket-get-started-run-circuit.md)
+ [获取专家建议](braket-expert-advice.md)
+ [使用 OpenQASM 3.0 运行您的电路](braket-openqasm.md)
+ [探索实验能力](braket-experimental-capabilities.md)
+ [Amazon Braket 上的脉冲控制](braket-pulse-control.md)
+ [模拟哈密顿模拟](braket-analog-hamiltonian-simulation.md)
+ [使用 AWS Boto3](braket-using-boto3.md)

# 构建您的第一个电路
<a name="braket-get-started-run-circuit"></a>

启动 Notebook 实例后，选择您刚刚创建的 Notebook，使用标准 Jupyter 界面打开该实例。

![\[Notebooks 界面显示了名为状态 InService 和其 URL amazon-braket-test 的现有笔记本实例。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/console-page.png)


Amazon Braket Notebook 实例预装了 Amazon Braket SDK 及其所有依赖项。首先创建一个带有 `conda_braket` 内核的新 Notebook。

![\[Notebook、控制台和其他工具（如终端、文本文件、Markdown 文件、Python 文件）的启动器界面，突出显示了 conda_braket Python 环境。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/jupyter-open.png)


您可以从一个简单的“您好，世界！” 示例开始。首先，构造一个准备贝尔态的电路，然后在不同设备上运行该电路以获得结果。

首先导入 Begin，导入 Amazon Braket SDK 模块并定义一个简单BRAKETlong的 SDK 模块并定义基本的 Bell State 电路。

```
import boto3
from braket.aws import AwsDevice
from braket.devices import LocalSimulator
from braket.circuits import Circuit

# Create the circuit
bell = Circuit().h(0).cnot(0, 1)
```

您可以使用以下命令对电路进行可视化：

```
print(bell)
```

```
T  : │  0  │  1  │
      ┌───┐       
q0 : ─┤ H ├───●───
      └───┘   │   
            ┌─┴─┐ 
q1 : ───────┤ X ├─
            └───┘ 
T  : │  0  │  1  │
```

 **在本地模拟器上运行您的电路** 

接下来，选择运行电路的量子设备。Amazon Braket SDK 附带本地模拟器，用于快速制作原型和测试。对于较小的电路，我们建议使用本地模拟器，最大可达 25 个 qubits（取决于您的本地硬件）。

要实例化本地模拟器，请执行以下操作：

```
# Instantiate the local simulator
local_sim = LocalSimulator()
```

然后运行电路：

```
# Run the circuit
result = local_sim.run(bell, shots=1000).result()
counts = result.measurement_counts
print(counts)
```

您应该会看到这样的结果：

```
Counter({'11': 503, '00': 497})
```

正如预期的那样，您准备的具体贝尔态是 \$100⟩ 和 \$111⟩ 的相等叠加，以及与测量结果大致相等（最多为 shot 噪声）的 00 和 11 分布。

 **在按需模拟器上运行您的电路** 

Amazon Braket 还允许访问高性能按需模拟器 SV1，用于运行更大的电路。SV1 是一款按需状态向量模拟器，允许模拟多达 34 个 qubits 的量子电路。您可以SV1在 “[支持的设备](braket-devices.md)” 部分和 AWS 控制台中找到更多信息。在 SV1（和 TN1 及任何 QPU 上）上运行量子任务时，量子任务的结果将存储在您账户的 S3 存储桶中。如果您未指定存储桶，Braket SDK 会为您创建一个默认存储桶 `amazon-braket-{region}-{accountID}`。要了解更多信息，请参阅[管理 Amazon Braket 的访问权限](braket-manage-access.md)。

**注意**  
填写您的实际现有存储桶名称，以下示例显示 `amazon-braket-s3-demo-bucket` 为您的存储桶名称。Amazon Braket 的存储桶名称始终以 `amazon-braket-` 开头，其后跟的是您添加的其他识别字符。如果您需要有关如何设置 S3 存储桶的信息，请参阅 [Amazon S3 入门](https://docs.aws.amazon.com/AmazonS3/latest/userguide/GetStartedWithS3.html)。

```
# Get the account ID
aws_account_id = boto3.client("sts").get_caller_identity()["Account"]

# The name of the bucket
my_bucket = "amazon-braket-s3-demo-bucket"

# The name of the folder in the bucket
my_prefix = "simulation-output"
s3_folder = (my_bucket, my_prefix)
```

要运行电路 SV1，您必须提供先前在 `.run()` 调用中作为位置参数选择的 S3 存储桶的位置。

```
# Choose the cloud-based on-demand simulator to run your circuit
device = AwsDevice("arn:aws:braket:::device/quantum-simulator/amazon/sv1")

# Run the circuit
task = device.run(bell, s3_folder, shots=100)

# Display the results
print(task.result().measurement_counts)
```

Amazon Braket 控制台提供了有关您的量子任务的更多信息。导航到控制台中的“**量子任务**”选项卡，您的量子任务应该位于列表顶部。或者，您可以使用唯一的量子任务 ID 或其他条件搜索您的量子任务。

**注意**  
90 天后，Amazon Braket 会自动删除与您的量子任务 IDs 相关的所有量子任务和其他元数据。有关更多信息，请参阅[数据留存](https://docs.aws.amazon.com/braket/latest/developerguide/security.html#braket-data-retention)。

 **在 QPU 上运行** 

使用 Amazon Braket，您只需更改一行代码即可在物理量子计算机上运行前面的量子电路示例。Amazon Braket 允许访问各种量子处理单元 (QPU) 设备。您可以在 “[支持的设备” 部分和 AWS 控制台的 “设备](braket-devices.md)” 选项卡下找到有关不同**设备**和可用性窗口的信息。以下示例说明了如何实例化 IQM 设备。

```
# Choose the IQM hardware to run your circuit
device = AwsDevice("arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet")
```

或者选择带有以下代码的 IonQ 设备：

```
# Choose the Ionq device to run your circuit
device = AwsDevice("arn:aws:braket:us-east-1::device/qpu/ionq/Aria-1")
```

选择设备后，在运行工作负载之前，您可以使用以下代码查询设备队列深度，以确定量子任务或混合作业的数量。此外，客户可在 Amazon Braket Management Console 的“设备”页面上查看设备特定的队列深度。

```
# Print your queue depth
print(device.queue_depth().quantum_tasks)
# Returns the number of quantum tasks queued on the device
# {<QueueType.NORMAL: 'Normal'>: '0', <QueueType.PRIORITY: 'Priority'>: '0'}

print(device.queue_depth().jobs)
# Returns the number of hybrid jobs queued on the device
# '2'
```

当您运行任务时，Amazon Braket SDK 会轮询结果（默认超时时间为 5 天）。您可以通过修改 `.run()` 命令中的 `poll_timeout_seconds` 参数来更改此默认值，如以下示例所示。请记住，如果您的轮询超时时间太短，则可能无法在轮询时间内返回结果，例如当 QPU 不可用且返回本地超时错误时。您可以通过调用 `task.result()` 函数来重新开始轮询。

```
# Define quantum task with 1 day polling timeout
task = device.run(bell, s3_folder, poll_timeout_seconds=24*60*60)
print(task.result().measurement_counts)
```

此外，提交量子任务或混合作业后，您可以调用 `queue_position()` 函数来检查队列位置。

```
print(task.queue_position().queue_position)
# Return the number of quantum tasks queued ahead of you
# '2'
```

# 构建您的第一个量子算法
<a name="braket-explore-algorithm-library"></a>

Amazon Braket 算法库是用 Python 编写的预先构建的量子算法的目录。按原样运行这些算法，或者将它们作为构建更复杂算法的起点使用。您可以从 Braket 控制台访问算法库。有关更多信息，请参阅 [Braket Github 算法库](https://github.com/aws-samples/amazon-braket-algorithm-library)。

![\[Amazon Braket 的算法库页面显示了预先构建的量子算法列表，如 Berstein Vazirani、Deutsch-Jozsa、Grover 的算法和量子近似优化算法，并附有简要说明。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/AlgorithmLibrary.png)


Braket 控制台提供了算法库中每种可用算法的描述。选择一个 GitHub 链接以查看每种算法的详细信息，或者选择 “**打开笔记本**” 以打开或创建包含所有可用算法的笔记本。如果您选择 Notebook 选项，则可以在 Notebook 的根文件夹中找到 Braket 算法库。

# 在 SDK 中构造电路
<a name="braket-constructing-circuit"></a>

本节提供了定义电路、查看可用门、扩展电路以及查看每个设备支持的门的示例。它还包含有关如何进行手动 qubits 分配、指示编译器完全按照定义运行电路以及如何使用噪声模拟器构造噪声电路的说明。

当然，你也可以在 Braket 中为各种门设置脉冲电平。 QPUs有关更多信息，请参阅 [Amazon Braket 上的脉冲控制](braket-pulse-control.md)。

**Topics**
+ [门和电路](#braket-gates)
+ [程序集](#braket-program-set)
+ [部分测量](#braket-partial-measurement)
+ [手动 qubit 分配](#manual-qubit-allocation)
+ [逐字记录编译](#verbatim-compilation)
+ [噪声模拟](#noise-simulation)

## 门和电路
<a name="braket-gates"></a>

量子门和电路是在 Amazon Braket Python SDK 的 [https://github.com/aws/amazon-braket-sdk-python/blob/main/src/braket/circuits/circuit.py](https://github.com/aws/amazon-braket-sdk-python/blob/main/src/braket/circuits/circuit.py) 类别中定义的。在 SDK 中，您可以通过调用 `Circuit()` 来实例化一个新的电路对象。

 **示例：定义电路** 

该示例首先定义了一个由四个 qubits（标记为 `q0`、`q1`、`q2` 和 `q3`）组成的样本电路，包括标准的单量子比特的 Hadamard 门和两个量子比特的 CNOT 门。您可以通过调用 `print` 函数来实现此电路的可视化，如下例所示。

```
# Import the circuit module
from braket.circuits import Circuit

# Define circuit with 4 qubits
my_circuit = Circuit().h(range(4)).cnot(control=0, target=2).cnot(control=1, target=3)
print(my_circuit)
```

```
T  : │  0  │     1     │
      ┌───┐             
q0 : ─┤ H ├───●─────────
      └───┘   │         
      ┌───┐   │         
q1 : ─┤ H ├───┼─────●───
      └───┘   │     │   
      ┌───┐ ┌─┴─┐   │   
q2 : ─┤ H ├─┤ X ├───┼───
      └───┘ └───┘   │   
      ┌───┐       ┌─┴─┐ 
q3 : ─┤ H ├───────┤ X ├─
      └───┘       └───┘ 
T  : │  0  │     1     │
```

 **示例：定义参数化电路** 

在此示例中，我们定义了一个电路，该电路的门依赖于自由参数。我们可以通过指定这些参数的值来构建新电路，或者在提交电路时，在某些设备上将其作为量子任务运行。

```
from braket.circuits import Circuit, FreeParameter

# Define a FreeParameter to represent the angle of a gate
alpha = FreeParameter("alpha")

# Define a circuit with three qubits
my_circuit = Circuit().h(range(3)).cnot(control=0, target=2).rx(0, alpha).rx(1, alpha)
print(my_circuit)
```

您可以通过向电路提供单个参数 `float`（这是所有自由参数将采用的值）或关键字参数来指定每个参数的值，从而从参数化电路中构造一个新的非参数化电路，如下所示。

```
my_fixed_circuit = my_circuit(1.2)
my_fixed_circuit = my_circuit(alpha=1.2)
print(my_fixed_circuit)
```

请注意，`my_circuit` 是未修改的，因此您可以使用它来实例化许多具有固定参数值的新电路。

 **示例：修改电路中的门** 

以下示例定义了一个电路，该电路的门使用了控制和功率修改器。您可以使用这些修改来创建新的门，如受控的 `Ry` 门。

```
from braket.circuits import Circuit

# Create a bell circuit with a controlled x gate
my_circuit = Circuit().h(0).x(control=0, target=1)

# Add a multi-controlled Ry gate of angle .13
my_circuit.ry(angle=.13, target=2, control=(0, 1))

# Add a 1/5 root of X gate
my_circuit.x(0, power=1/5)

print(my_circuit)
```

只有本地模拟器支持门修改器。

 **示例：查看所有可用的门** 

以下示例说明了如何查看 Amazon Braket 中的所有可用门。

```
from braket.circuits import Gate
# Print all available gates in Amazon Braket
gate_set = [attr for attr in dir(Gate) if attr[0].isupper()]
print(gate_set)
```

这段代码的输出列出了所有的门。

```
['CCNot', 'CNot', 'CPhaseShift', 'CPhaseShift00', 'CPhaseShift01', 'CPhaseShift10', 'CSwap', 'CV', 'CY', 'CZ', 'ECR', 'GPhase', 'GPi', 'GPi2', 'H', 'I', 'ISwap', 'MS', 'PRx', 'PSwap', 'PhaseShift', 'PulseGate', 'Rx', 'Ry', 'Rz', 'S', 'Si', 'Swap', 'T', 'Ti', 'U', 'Unitary', 'V', 'Vi', 'X', 'XX', 'XY', 'Y', 'YY', 'Z', 'ZZ']
```

通过调用该类电路的方法，可以将这些门中的任何一个附加到电路中。例如，调用 `circ.h(0)`，在第一个 qubit 门上添加 Hadamard 门。

**注意**  
门已追加到位，以下示例将上一个示例中列出的所有门添加到同一个电路中。

```
circ = Circuit()
# toffoli gate with q0, q1 the control qubits and q2 the target.
circ.ccnot(0, 1, 2)
# cnot gate
circ.cnot(0, 1)
# controlled-phase gate that phases the |11> state, cphaseshift(phi) = diag((1,1,1,exp(1j*phi))), where phi=0.15 in the examples below
circ.cphaseshift(0, 1, 0.15)
# controlled-phase gate that phases the |00> state, cphaseshift00(phi) = diag([exp(1j*phi),1,1,1])
circ.cphaseshift00(0, 1, 0.15)
# controlled-phase gate that phases the |01> state, cphaseshift01(phi) = diag([1,exp(1j*phi),1,1])
circ.cphaseshift01(0, 1, 0.15)
# controlled-phase gate that phases the |10> state, cphaseshift10(phi) = diag([1,1,exp(1j*phi),1])
circ.cphaseshift10(0, 1, 0.15)
# controlled swap gate
circ.cswap(0, 1, 2)
# swap gate
circ.swap(0,1)
# phaseshift(phi)= diag([1,exp(1j*phi)])
circ.phaseshift(0,0.15)
# controlled Y gate
circ.cy(0, 1)
# controlled phase gate
circ.cz(0, 1)
# Echoed cross-resonance gate applied to q0, q1
circ = Circuit().ecr(0,1)
# X rotation with angle 0.15
circ.rx(0, 0.15)
# Y rotation with angle 0.15
circ.ry(0, 0.15)
# Z rotation with angle 0.15
circ.rz(0, 0.15)
# Hadamard gates applied to q0, q1, q2
circ.h(range(3))
# identity gates applied to q0, q1, q2
circ.i([0, 1, 2])
# iswap gate, iswap = [[1,0,0,0],[0,0,1j,0],[0,1j,0,0],[0,0,0,1]]
circ.iswap(0, 1)
# pswap gate, PSWAP(phi) = [[1,0,0,0],[0,0,exp(1j*phi),0],[0,exp(1j*phi),0,0],[0,0,0,1]]
circ.pswap(0, 1, 0.15)
# X gate applied to q1, q2
circ.x([1, 2])
# Y gate applied to q1, q2
circ.y([1, 2])
# Z gate applied to q1, q2
circ.z([1, 2])
# S gate applied to q0, q1, q2
circ.s([0, 1, 2])
# conjugate transpose of S gate applied to q0, q1
circ.si([0, 1])
# T gate applied to q0, q1
circ.t([0, 1])
# conjugate transpose of T gate applied to q0, q1
circ.ti([0, 1])
# square root of not gate applied to q0, q1, q2
circ.v([0, 1, 2])
# conjugate transpose of square root of not gate applied to q0, q1, q2
circ.vi([0, 1, 2])
# exp(-iXX theta/2)
circ.xx(0, 1, 0.15)
# exp(i(XX+YY) theta/4), where theta=0.15 in the examples below
circ.xy(0, 1, 0.15)
# exp(-iYY theta/2)
circ.yy(0, 1, 0.15)
# exp(-iZZ theta/2)
circ.zz(0, 1, 0.15)
# IonQ native gate GPi with angle 0.15 applied to q0
circ.gpi(0, 0.15)
# IonQ native gate GPi2 with angle 0.15 applied to q0
circ.gpi2(0, 0.15)
# IonQ native gate MS with angles 0.15, 0.15, 0.15 applied to q0, q1
circ.ms(0, 1, 0.15, 0.15, 0.15)
```

除了预定义的门设置之外，您还可以将自定义的单一门应用于电路。它们可以是单量子比特门（如以下源代码所示），也可以是应用于参数 `targets` 定义的 qubits 的多量子比特门。

```
import numpy as np

# Apply a general unitary
my_unitary = np.array([[0, 1],[1, 0]])
circ.unitary(matrix=my_unitary, targets=[0])
```

 **示例：扩展现有电路** 

您可以通过添加指令来扩展现有电路。`Instruction` 是一种量子指令，该指令描述了要在量子设备上执行的量子任务。`Instruction` 运算符仅包括 `Gate` 类型的对象。

```
# Import the Gate and Instruction modules
from braket.circuits import Gate, Instruction

# Add instructions directly.
circ = Circuit([Instruction(Gate.H(), 4), Instruction(Gate.CNot(), [4, 5])])

# Or with add_instruction/add functions
instr = Instruction(Gate.CNot(), [0, 1])
circ.add_instruction(instr)
circ.add(instr)

# Specify where the circuit is appended
circ.add_instruction(instr, target=[3, 4])
circ.add_instruction(instr, target_mapping={0: 3, 1: 4})

# Print the instructions
print(circ.instructions)
# If there are multiple instructions, you can print them in a for loop
for instr in circ.instructions:
     print(instr)

# Instructions can be copied
new_instr = instr.copy()
# Appoint the instruction to target
new_instr = instr.copy(target=[5, 6])
new_instr = instr.copy(target_mapping={0: 5, 1: 6})
```

 **示例：查看每台设备支持的门** 

模拟器支持 Braket SDK 中的所有门，但是 QPU 设备支持的子集较小。您可以在设备属性中找到设备支持的门。下面给出了 IonQ 设备的一个示例：

```
# Import the device module
from braket.aws import AwsDevice

device = AwsDevice("arn:aws:braket:us-east-1::device/qpu/ionq/Aria-1")

# Get device name
device_name = device.name
# Show supportedQuantumOperations (supported gates for a device)
device_operations = device.properties.dict()['action']['braket.ir.openqasm.program']['supportedOperations']
print('Quantum Gates supported by {}:\n {}'.format(device_name, device_operations))
```

```
Quantum Gates supported by Aria 1:
 ['x', 'y', 'z', 'h', 's', 'si', 't', 'ti', 'v', 'vi', 'rx', 'ry', 'rz', 'cnot', 'swap', 'xx', 'yy', 'zz']
```

受支持的门可能需要编译成原生门，然后才能在量子硬件上运行。当您提交电路时，Amazon Braket 会自动执行此编译。

 **示例：以编程方式检索设备支持的原生门的保真度** 

您可以在 Braket 控制台的“**设备**”页面上查看保真度信息。有时，以编程方式访问相同的信息会很有帮助。以下代码显示如何提取 QPU 的两门之间的两个 qubit 门保真度。

```
# Import the device module
from braket.aws import AwsDevice
 
device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3") 

# Specify the qubits 
a=10 
b=11
edge_properties_entry = device.properties.standardized.twoQubitProperties['10-11'].twoQubitGateFidelity
gate_name = edge_properties_entry[0].gateName
fidelity = edge_properties_entry[0].fidelity
print(f"Fidelity of the {gate_name} gate between qubits {a} and {b}: {fidelity}")
```

## 程序集
<a name="braket-program-set"></a>

程序集在单个量子任务中高效运行多个量子电路。在这一项任务中，您可以提交多达 100 个量子电路或一个包含多达 100 个不同参数集的单个参数电路。此操作可最大限度地缩短后续电路执行的时间间隔，并降低量子任务处理开销。目前，Amazon Braket Local Simulator 等设备和设备都支持程序集IQM。AQT Rigetti

**定义一个 ProgramSet**

以下第一个代码示例演示了如何同时使用参数化电路和不带参数的电路来构建 `ProgramSet`。

```
from braket.aws import AwsDevice
from braket.circuits import Circuit, FreeParameter
from braket.program_sets.circuit_binding import CircuitBinding
from braket.program_sets import ProgramSet

# Initialize the quantum device
device = AwsDevice("arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet")

# Define circuits
circ1 = Circuit().h(0).cnot(0, 1)
circ2 = Circuit().rx(0, 0.785).ry(1, 0.393).cnot(1, 0)
circ3 = Circuit().t(0).t(1).cz(0, 1).s(0).cz(1, 2).s(1).s(2)
parameterize_circuit = Circuit().rx(0, FreeParameter("alpha")).cnot(0, 1).ry(1, FreeParameter("beta"))

# Create circuit bindings with different parameters
circuit_binding = CircuitBinding(
    circuit=parameterize_circuit,
    input_sets={
            'alpha': (0.10, 0.11, 0.22, 0.34, 0.45),
            'beta': (1.01, 1.01, 1.03, 1.04, 1.04),
    })

# Creating the program set
program_set_1 = ProgramSet([
    circ1,
    circ2,
    circ3,
    circuit_binding,
])
```

该程序集包含四个独特的程序：`circ1`、`circ2`、`circ3` 和 `circuit_binding`。`circuit_binding` 程序使用五个不同的参数绑定运行，创建了五个可执行文件。其他三个无参数程序分别创建一个可执行文件。这会生成八个可执行文件，如下图所示。

![\[ProgramSet 包含四个电路的结构，其中 c4 CircuitBinding 用于处理五个输入集。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/program_set1.png)


以下第二个代码示例演示了如何使用 `product()` 方法将同一组可观测值附加到程序集的每个可执行文件中。

```
from braket.circuits.observables import I, X, Y, Z

observables = [Z(0) @ Z(1), X(0) @ X(1), Z(0) @ X(1), X(0) @ Z(1)]

program_set_2 = ProgramSet.product(
    circuits=[circ1, circ2, circuit_binding],
    observables=observables
)
```

对于无参数程序，针对每个电路测量各个可观测值。对于参数化程序，针对每个输入集测量每个可观测值，如下图所示。

![\[ProgramSet.product 显示了三个电路的并行执行，其中 c3 CircuitBinding 用于处理五个输入集，每个输入集有五个可观察值。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/program_set2.png)


下列第三个代码示例演示了如何使用 `zip()` 方法将单个可观测值与 `ProgramSet` 中的特定参数集配对。

```
program_set_3 = ProgramSet.zip(
    circuits=circuit_binding,
    observables=observables + [Y(0) @ Y(1)]
)
```

![\[ProgramSet.zip，其中 CircuitBinding 演示了使用共享电路的五个并行执行，每个输入集都有单独的可观察对象。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/program_set3.png)


不选择 `CircuitBinding()`，您可以直接压缩带有电路和输入集列表的可观察值列表。

```
program_set_4 = ProgramSet.zip(
    circuits=[circ1, circ2, circ3],
    input_sets=[{}, {}, {}],
    observables=observables[:3]
)
```

![\[ProgramSet.zip 显示了七个电路的并行执行及其相应的单个输入集和单个可观察对象。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/program_set4.png)


有关程序集的更多信息和示例，请参阅 amazon-braket-examples Github 中的[程序集文件夹](https://github.com/amazon-braket/amazon-braket-examples/tree/main/examples/braket_features/program_sets)。

**检查并运行设备上设置的程序**

程序集的可执行文件数量等于其唯一参数绑定的电路的数量。使用以下代码示例计算电路可执行文件总数和总拍摄次数。

```
# Number of shots per executable
shots = 10
num_executables = program_set_1.total_executables

# Calculate total number of shots across all executables
total_num_shots = shots*num_executables
```

**注意**  
使用程序集，您需要根据程序集中所有电路的总拍摄次数来支付每项任务的单次费用和每次拍摄的费用。

要运行程序集，请使用以下代码示例。

```
# Run the program set
task = device.run(
   program_set_1, shots=total_num_shots,
)
```

使用 Rigetti 设备时，当任务部分完成及部分排队时，您的程序集可能会保持 `RUNNING` 状态。为了更快地获得结果，请考虑将您的程序集作为[混合作业](braket-jobs-first.md)提交。

**分析结果**

运行以下代码，分析、测量 `ProgramSet` 中可执行文件的结果。

```
# Get the results from a program set 
result = task.result()

# Get the first executbable
first_program = result[0] 
first_executable = first_program[0]

# Inspect the results of the first executable
measurements_from_first_executable = first_executable.measurements
print(measurements_from_first_executable)
```

## 部分测量
<a name="braket-partial-measurement"></a>

不测量量子电路中的所有量子比特，而是使用部分测量来测量单个量子比特或量子比特子集。

**注意**  
其他功能，如中间电路测量和前馈操作，可作为实验功能提供，请参阅[访问 IQM 设备上的动态电路](braket-experimental-capabilities.md#braket-access-dynamic-circuits)。

**示例：测量量子比特的子集**

以下代码示例演示了通过在贝尔态电路中仅测量量子比特 0 来进行部分测量。

```
from braket.devices import LocalSimulator
from braket.circuits import Circuit

# Use the local state vector simulator
device = LocalSimulator()

# Define an example bell circuit and measure qubit 0
circuit = Circuit().h(0).cnot(0, 1).measure(0)

# Run the circuit
task = device.run(circuit, shots=10)

# Get the results
result = task.result()

# Print the circuit and measured qubits
print(circuit)
print()
print("Measured qubits: ", result.measured_qubits)
```

## 手动 qubit 分配
<a name="manual-qubit-allocation"></a>

当您在量子计算机上从 Rigetti 运行量子电路时，您可以选择使用手动 qubit 分配来控制将哪些 qubits 用于您的算法。[Amazon Braket 控制台](https://console.aws.amazon.com/braket/home)和 [Amazon Braket SDK](https://github.com/aws/amazon-braket-sdk-python) 可帮助您检查所选量子处理单元（QPU）设备的最新校准数据，以便您可以为实验选择最佳 qubits。

通过手动 qubit 分配，能够更准确地运行电路及调查各个 qubit 特性。研究人员和高级用户可以根据最新的设备校准数据优化其电路设计，从而获得更准确的结果。

以下示例演示了如何进行 qubits 显式分配。

```
# Import the device module
from braket.aws import AwsDevice

device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")
circ = Circuit().h(0).cnot(0, 7)  # Indices of actual qubits in the QPU

# Set up S3 bucket (where results are stored)
my_bucket = "amazon-braket-s3-demo-bucket" # The name of the bucket
my_prefix = "your-folder-name" # The name of the folder in the bucket
s3_location = (my_bucket, my_prefix)

my_task = device.run(circ, s3_location, shots=100, disable_qubit_rewiring=True)
```

有关更多信息，请参阅本笔记本[上 GitHub的 Amazon Braket 示例](https://github.com/aws/amazon-braket-examples)：在 [QPU 设备上分配量子比特](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Allocating_Qubits_on_QPU_Devices.ipynb)。

## 逐字记录编译
<a name="verbatim-compilation"></a>

当您在基于门的量子计算机上运行量子电路时，您可以指示编译器完全按照定义运行您的电路，而无需做出任何修改。使用逐字记录编译，您可以指定要么完全按照指定方式保留整个电路，要么仅保留其中的特定部分（仅受 Rigetti 支持）。在为硬件基准测试或错误缓解协议开发算法时，您需要能够选择精确指定硬件上运行的门和电路布局。通过逐字记录编译，您可以关闭某些优化步骤来直接控制编译过程，从而确保您的电路完全按照设计运行。

、、和Rigetti设备支持逐字编译 AQT IonQIQM，并且需要使用原生门。使用逐字记录编译时，建议检查设备的拓扑结构，以确保在连接的 qubits 上调用门且电路使用硬件支持的原生门。以下示例说明如何以编程方式访问设备支持的原生门列表。

```
device.properties.paradigm.nativeGateSet
```

对于 Rigetti，必须通过设置 `disableQubitRewiring=True` 与逐字记录编译一起使用，进而关闭 qubit 重新布线。如果在编译中使用逐字记录框时设置 `disableQubitRewiring=False`，则量子电路验证失败且电路无法运行。

如果为电路启用了逐字记录编译且在不支持逐字记录编译的 QPU 上运行，则会生成一个错误，指明不支持的操作导致任务失败。随着越来越多的量子硬件原生支持编译器功能，该功能将扩展到包括这些设备。使用以下代码查询时，支持逐字记录编译的设备将其列为支持的操作。

```
from braket.aws import AwsDevice
from braket.device_schema.device_action_properties import DeviceActionType
device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")
device.properties.action[DeviceActionType.OPENQASM].supportedPragmas
```

使用逐字记录编译不会产生额外成本。对于在 Braket QPU 设备、Notebook 实例和按需模拟器上执行的量子任务，您需要继续按照“[Amazon Braket 定价](https://aws.amazon.com/braket/pricing/)”页面上指定的当前费率付费。有关更多信息，请参阅[逐字记录编译](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Verbatim_Compilation.ipynb)示例 Notebook。

**注意**  
如果您使用 OpenQasm 为AQT和IonQ设备编写电路，并且希望将电路直接映射到物理量子比特，则需要使用，因`#pragma braket verbatim`为 OpenQasm 会忽略`disableQubitRewiring`标志。

## 噪声模拟
<a name="noise-simulation"></a>

要实例化本地噪声模拟器，您可以按如下方式更改后端。

```
# Import the device module
from braket.aws import AwsDevice

device = LocalSimulator(backend="braket_dm")
```

您可以通过两种方式构造噪声电路：

1. 自下而上地构造嘈杂电路。

1. 采用现有的无噪声电路，并在整个过程中注入噪声。

以下示例显示了使用具有去极化噪声和自定义 Kraus 通道的基本电路的方法。

```
import scipy.stats
import numpy as np

# Bottom up approach
# Apply depolarizing noise to qubit 0 with probability of 0.1
circ = Circuit().x(0).x(1).depolarizing(0, probability=0.1)

# Create an arbitrary 2-qubit Kraus channel
E0 = scipy.stats.unitary_group.rvs(4) * np.sqrt(0.8)
E1 = scipy.stats.unitary_group.rvs(4) * np.sqrt(0.2)
K = [E0, E1]

# Apply a two-qubit Kraus channel to qubits 0 and 2
circ = circ.kraus([0, 2], K)
```

```
from braket.circuits import Noise

# Inject noise approach
# Define phase damping noise
noise = Noise.PhaseDamping(gamma=0.1)
# The noise channel is applied to all the X gates in the circuit
circ = Circuit().x(0).y(1).cnot(0, 2).x(1).z(2)
circ_noise = circ.copy()
circ_noise.apply_gate_noise(noise, target_gates=Gate.X)
```

运行电路的用户体验与之前相同，如以下两个示例所示。

 **示例 1** 

```
task = device.run(circ, shots=100)
```

Or

 **示例 2** 

```
task = device.run(circ_noise, shots=100)
```

有关更多示例，请参阅 [Braket 入门噪声模拟器示例](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Simulating_Noise_On_Amazon_Braket.ipynb) 

# 检查电路
<a name="braket-inspecting-circut"></a>

Amazon Braket 中的量子电路有一个名为 `Moments` 的“伪时间”概念。每个 qubit 每 `Moment` 只能体验一个门。`Moments` 的目的是使电路及其门更易于寻址，并提供时间结构。

**注意**  
时刻通常不对应于 QPU 上执行门的实时。

电路深度由该电路中的总时刻数给出。您可以查看调用 `circuit.depth` 方法的电路深度，如以下示例所示。

```
from braket.circuits import Circuit

# Define a circuit with parametrized gates
circ = Circuit().rx(0, 0.15).ry(1, 0.2).cnot(0, 2).zz(1, 3, 0.15).x(0)
print(circ)
print('Total circuit depth:', circ.depth)
```

```
T  : │     0      │        1         │  2  │
      ┌──────────┐                    ┌───┐ 
q0 : ─┤ Rx(0.15) ├───●────────────────┤ X ├─
      └──────────┘   │                └───┘ 
      ┌──────────┐   │   ┌──────────┐       
q1 : ─┤ Ry(0.20) ├───┼───┤ ZZ(0.15) ├───────
      └──────────┘   │   └────┬─────┘       
                   ┌─┴─┐      │             
q2 : ──────────────┤ X ├──────┼─────────────
                   └───┘      │             
                         ┌────┴─────┐       
q3 : ────────────────────┤ ZZ(0.15) ├───────
                         └──────────┘       
T  : │     0      │        1         │  2  │
Total circuit depth: 3
```

以上电路的总电路深度为 3（显示为时刻 `0`、`1` 和 `2`）。您可以查看每个时刻的门操作情况。

 `Moments` 函数作为*键值*对的字典。
+ 键是 `MomentsKey()`，它包含伪时间和 qubit 信息。
+ 该值的分配类型为 `Instructions()`。

```
moments = circ.moments
for key, value in moments.items():
    print(key)
    print(value, "\n")
```

```
MomentsKey(time=0, qubits=QubitSet([Qubit(0)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': Rx('angle': 0.15, 'qubit_count': 1), 'target': QubitSet([Qubit(0)]), 'control': QubitSet([]), 'control_state': (), 'power': 1) 

MomentsKey(time=0, qubits=QubitSet([Qubit(1)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': Ry('angle': 0.2, 'qubit_count': 1), 'target': QubitSet([Qubit(1)]), 'control': QubitSet([]), 'control_state': (), 'power': 1) 

MomentsKey(time=1, qubits=QubitSet([Qubit(0), Qubit(2)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': CNot('qubit_count': 2), 'target': QubitSet([Qubit(0), Qubit(2)]), 'control': QubitSet([]), 'control_state': (), 'power': 1) 

MomentsKey(time=1, qubits=QubitSet([Qubit(1), Qubit(3)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': ZZ('angle': 0.15, 'qubit_count': 2), 'target': QubitSet([Qubit(1), Qubit(3)]), 'control': QubitSet([]), 'control_state': (), 'power': 1) 

MomentsKey(time=2, qubits=QubitSet([Qubit(0)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': X('qubit_count': 1), 'target': QubitSet([Qubit(0)]), 'control': QubitSet([]), 'control_state': (), 'power': 1)
```

您也可以通过 `Moments` 为电路添加门。

```
from braket.circuits import Instruction, Gate

new_circ = Circuit()
instructions = [Instruction(Gate.S(), 0),
                Instruction(Gate.CZ(), [1, 0]),
                Instruction(Gate.H(), 1)
                ]

new_circ.moments.add(instructions)
print(new_circ)
```

```
T  : │  0  │  1  │  2  │
      ┌───┐ ┌───┐       
q0 : ─┤ S ├─┤ Z ├───────
      └───┘ └─┬─┘       
              │   ┌───┐ 
q1 : ─────────●───┤ H ├─
                  └───┘ 
T  : │  0  │  1  │  2  │
```

# 结果类型列表
<a name="braket-result-types"></a>

使用测量电路时，Amazon Braket 可以使用 `ResultType` 返回不同类型的结果。电路可以返回以下类型的结果。
+  `AdjointGradient` 返回所提供的可观测值的期望值的梯度（向量导数）。该可观测值使用伴随微分法根据指定参数作用于所提供的目标。只有当 shots=0 时才能使用此方法。
+  `Amplitude` 返回输出波函数中指定量子态的振幅。它仅在 SV1 和本地模拟器上可用。
+  `Expectation` 返回给定可观测值的期望值，该值可以通过本章后面介绍的 `Observable` 类来指定。必须指定 qubits 用于测量可观测值的目标，并且指定目标的数量必须等于可观测值所针对的 qubits 数量。如果未指定目标，则可观测值必须仅在 1 个 qubit 上运行，且并行应用于所有 qubits。
+  `Probability` 返回测量计算基态的概率。如果未指定目标，则 `Probability` 返回测量所有基态的概率。如果指定了目标，则仅返回指定 qubits 上的基向量的边际概率。托管模拟器， QPUs 最大量子比特限制为 15 个，本地模拟器仅限于系统的内存大小。
+  `Reduced density matrix` 返回 qubits 系统中指定目标 qubits 子系统的密度矩阵。为了限制此结果类型的大小，Braket 将 qubits 目标的最大数量限制为 8。
+  `StateVector` 返回完整的状态向量。它可在本地模拟器上使用。
+  `Sample` 返回指定目标 qubit 集和可观测值的测量计数。如果未指定目标，则可观测值必须仅在 1 个 qubit 上运行，且并行应用于所有 qubits。如果指定了目标，则仅返回指定 qubits 上的基向量的边际概率。
+  `Variance` 返回指定目标 qubit 集的方差 (`mean([x-mean(x)]2)`)，并作为请求的结果类型进行观察。如果未指定目标，则可观测值必须仅在 1 个 qubit 上运行，且并行应用于所有 qubits。否则，指定的目标数量必须等于可以应用可观测值的 qubits 的数量。

 **不同提供程序支持的结果类型：**


|  |  |  |  |  |  |  |  |  | 
| --- |--- |--- |--- |--- |--- |--- |--- |--- |
|  |  本地 SIM  |   SV1   |   DM1   |   TN1   |   AQT   |   IonQ   |   IQM   |   Rigetti   | 
|  伴随梯度  |  N  |  Y  |  N  |  N  |  N  |  N  |  N  |  N  | 
|  振幅  |  Y  |  Y  |  N  |  N  |  N  |  N  |  N  |  N  | 
|  期望  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  | 
|  概率  |  Y  |  Y  |  Y  |  N  |  Y  |  Y  |  Y  |  Y  | 
|  低密度矩阵  |  Y  |  N  |  Y  |  N  |  N  |  N  |  N  |  N  | 
|  状态向量  |  Y  |  N  |  N  |  N  |  N  |  N  |  N  |  N  | 
|  样本  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  | 
|  方差  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  | 

您可以通过检查设备属性来查看受支持的结果类型，如以下示例所示。

```
from braket.aws import AwsDevice

device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")

# Print the result types supported by this device
for iter in device.properties.action['braket.ir.openqasm.program'].supportedResultTypes:
    print(iter)
```

```
name='Sample' observables=['x', 'y', 'z', 'h', 'i'] minShots=10 maxShots=50000
name='Expectation' observables=['x', 'y', 'z', 'h', 'i'] minShots=10 maxShots=50000
name='Variance' observables=['x', 'y', 'z', 'h', 'i'] minShots=10 maxShots=50000
name='Probability' observables=None minShots=10 maxShots=50000
```

要调用 `ResultType`，请将其追加到电路中，如以下示例所示。

```
from braket.circuits import Circuit, Observable

circ = Circuit().h(0).cnot(0, 1).amplitude(state=["01", "10"])
circ.probability(target=[0, 1])
circ.probability(target=0)
circ.expectation(observable=Observable.Z(), target=0)
circ.sample(observable=Observable.X(), target=0)
circ.state_vector()
circ.variance(observable=Observable.Z(), target=0)

# Print one of the result types assigned to the circuit
print(circ.result_types[0])
```

**注意**  
不同的量子设备提供不同格式的结果。例如，Rigetti 设备返回测量值，而 IonQ 设备则提供概率。Amazon Braket SDK 为所有结果提供了一个测量属性。但是，对于返回概率的设备，这些测量值是事后计算的，且基于概率，无法进行逐次测量。要确定结果是否要进行后期计算，请检查结果对象上的 `measurements_copied_from_device`。此操作在 Amazon Braket 软件开发工具包 GitHub 存储库[中的 gate\$1model\$1quantum\$1task\$1result.py](https://github.com/aws/amazon-braket-sdk-python/blob/ca5b08dada4839ca31c012ff50aa20b656fd1879/src/braket/tasks/gate_model_quantum_task_result.py#L70-L72) 文件中有详细介绍。

## 可观测值
<a name="braket-result-types-observables"></a>

Amazon Braket 的 `Observable` 类可测量特定的可观测值。

您只能将一个唯一非身份可观测值应用于每个 qubit。如果您将两个或多个不同的非身份可观测值指定为相同的 qubit，则会发生错误。为此，张量乘积的每个因子都算作一个单独的可观测值。这意味着您可以将多个张量乘积放在同一个 qubit 上，前提是作用于 qubit 的因子保持不变。

可以扩展可观测值并添加其他可观测值（无论是否扩展）。这将创建可在 `AdjointGradient` 结果类型中使用的 `Sum`。

`Observable` 类包括以下可观测值。

```
import numpy as np

Observable.I()
Observable.H()
Observable.X()
Observable.Y()
Observable.Z()

# Get the eigenvalues of the observable
print("Eigenvalue:", Observable.H().eigenvalues)
# Or rotate the basis to be computational basis
print("Basis rotation gates:", Observable.H().basis_rotation_gates)

# Get the tensor product of the observable for the multi-qubit case
tensor_product = Observable.Y() @ Observable.Z()
# View the matrix form of an observable by using
print("The matrix form of the observable:\n", Observable.Z().to_matrix())
print("The matrix form of the tensor product:\n", tensor_product.to_matrix())

# Factorize an observable in the tensor form
print("Factorize an observable:", tensor_product.factors)

# Self-define observables, given it is a Hermitian
print("Self-defined Hermitian:", Observable.Hermitian(matrix=np.array([[0, 1], [1, 0]])))

print("Sum of other (scaled) observables:", 2.0 * Observable.X() @ Observable.X() + 4.0 * Observable.Z() @ Observable.Z())
```

```
Eigenvalue: [ 1. -1.]
Basis rotation gates: (Ry('angle': -0.7853981633974483, 'qubit_count': 1),)
The matrix form of the observable:
 [[ 1.+0.j  0.+0.j]
 [ 0.+0.j -1.+0.j]]
The matrix form of the tensor product:
 [[ 0.+0.j  0.+0.j  0.-1.j  0.+0.j]
 [ 0.+0.j -0.+0.j  0.+0.j  0.+1.j]
 [ 0.+1.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.-1.j  0.+0.j -0.+0.j]]
Factorize an observable: (Y('qubit_count': 1), Z('qubit_count': 1))
Self-defined Hermitian: Hermitian('qubit_count': 1, 'matrix': [[0.+0.j 1.+0.j], [1.+0.j 0.+0.j]])
Sum of other (scaled) observables: Sum(TensorProduct(X('qubit_count': 1), X('qubit_count': 1)), TensorProduct(Z('qubit_count': 1), Z('qubit_count': 1)))
```

## 参数
<a name="braket-result-types-parameters"></a>

电路可以包含自由参数。这些自由参数只需要构造一次即可运行多次，并且可用于计算梯度。

每个自由参数都使用字符串编码的名称，该名称用于：
+ 设置参数值
+ 确定要使用的参数

```
from braket.circuits import Circuit, FreeParameter, observables
from braket.parametric import FreeParameter

theta = FreeParameter("theta")
phi = FreeParameter("phi")
circ = Circuit().h(0).rx(0, phi).ry(0, phi).cnot(0, 1).xx(0, 1, theta)
```

## 伴随梯度
<a name="braket-result-types-adjoint-gradient"></a>

SV1 设备计算可观测期望值（包括多项哈密顿量）的伴随梯度。要区分参数，请指定其名称（字符串格式）或通过直接引用来指定。

```
from braket.aws import AwsDevice
from braket.devices import Devices

device = AwsDevice(Devices.Amazon.SV1)

circ.adjoint_gradient(observable=3 * Observable.Z(0) @ Observable.Z(1) - 0.5 * observables.X(0), parameters = ["phi", theta])
```

如果将固定参数值作为参数传递给参数化电路，自由参数将会被移除。由于自由参数已不存在，用 `AdjointGradient` 运行此电路会产生错误。以下代码示例演示了正确及错误的用法：

```
# Will error, as no free parameters will be present
#device.run(circ(0.2), shots=0)

# Will succeed
device.run(circ, shots=0, inputs={'phi': 0.2, 'theta': 0.2})
```

# 获取专家建议
<a name="braket-expert-advice"></a>

直接在 Braket 管理控制台中与量子计算专家联系，获取有关工作负载的更多指导。

要通过 Braket Direct 浏览专家建议选项，请打开 Braket 控制台，在左侧窗格中选择 **Braket Direct**，然后导航到“**专家建议**”部分。以下专家建议选项也可用：
+ **Braket 办公时间：**Braket 办公时间为 1:1 会议，先到先得，每月举行一次。每个可用的办公时间段均为 30 分钟，且免费。与Braket专家交谈可以探索 use-case-to-device拟合度，确定最适合使用Braket进行算法的选项，并获得有关如何使用某些Braket功能的建议，例如Amazon Braket混合任务、Braket Pulse或模拟哈密尔顿模拟，从而帮助您更快地从构思到执行。
  + 要注册 Braket 办公时间，请选择“**注册**”并填写联系信息、工作负载详情和所需讨论的主题。
  + 您将通过电子邮件收到下一个可用时段的日历邀请。
**注意**  
对于紧急问题或快速故障排除问题，我们建议您联系 [AWS 支持](https://console.aws.amazon.com/support/home#/case/create?issueType=technical)。对于非紧急问题，您也可以使用 [AWS re:Post 论坛](https://repost.aws/tags/questions/TAhMWeHkpfSMSCxIFNqcqYog?view=all)或 [Quantum Computing Stack Exchange](https://quantumcomputing.stackexchange.com/questions/ask)，在那里您可以浏览之前回答过的问题并提出新问题。
+ **量子硬件提供商提供的产品：**IonQ、QuEra 和 Rigetti 分别通过 AWS Marketplace提供专业服务产品。
  + 要浏览他们的产品，请选择 **Connect** 并浏览他们的列表。
  + 要详细了解上提供的专业服务 AWS Marketplace，请参阅[专业服务产品](https://docs.aws.amazon.com/marketplace/latest/buyerguide/buyer-proserv-products.html)。
+ **Amazon Quantum Solutions Lab（QSL）：**QSL 是一个合作研究和专业服务团队，由量子计算专家组成，可以帮助您有效地探索量子计算并评测该技术的当前性能。
  + 要联系 QSL，请选择 **Connect**，然后填写联系信息和使用案例详细信息。
  + QSL 团队将通过电子邮件与您联系，告知后续步骤。

# 使用 OpenQASM 3.0 运行您的电路
<a name="braket-openqasm"></a>

 Amazon Braket 现在支持适用于基于门的量子设备和模拟器的 [OpenQASM 3.0](https://openqasm.com/)。本用户指南提供了有关 Braket 支持的 OpenQASM 3.0 子集的信息。Braket 客户现在可以选择使用 [SDK](braket-constructing-circuit.md) 提交 Braket 电路，也可以使用 [Amazon Braket API](https://docs.aws.amazon.com/braket/latest/APIReference/Welcome.html) 和 [Amazon Braket Python SDK](https://github.com/aws/amazon-braket-sdk-python) 直接向所有基于门的设备提供 OpenQASM 3.0 字符型。

本指南中的主题将引导您了解如何完成以下量子任务的各种示例。
+  [在不同的 Braket 设备上创建和提交 OpenQASM 量子任务](braket-openqasm-create-submit-task.md) 
+  [访问受支持的操作和结果类型](braket-openqasm-device-support.md#braket-openqasm-supported-operations-results-result-types) 
+  [使用 OpenQASM 模拟噪声](braket-openqasm-noise-simulation.md) 
+  [在 OpenQASM 中使用逐字记录编译](braket-openqasm-verbatim-compilation.md) 
+  [排查 OpenQASM 问题](https://docs.aws.amazon.com/braket/latest/developerguide/braket-troubleshooting-openqasm.html) 

本指南还介绍了某些硬件特有的功能，这些功能可以通过 Braket 上的 OpenQASM 3.0 实现，并提供了更多资源的链接。

**Topics**
+ [什么是 OpenQASM 3.0？](#braket-openqasm-what-is)
+ [何时使用 OpenQASM 3.0](#braket-openqasm-when-to-use)
+ [OpenQASM 3.0 的工作方式](#braket-openqasm-how-it-works)
+ [先决条件](#braket-openqasm-prerequisites)
+ [Braket 支持哪些 OpenQASM 功能？](braket-openqasm-supported-features.md)
+ [创建并提交示例 OpenQASM 3.0 量子任务](braket-openqasm-create-submit-task.md)
+ [在不同的 Braket 设备上支持 OpenQASM](braket-openqasm-device-support.md)
+ [使用 OpenQASM 3.0 模拟噪声](braket-openqasm-noise-simulation.md)
+ [Qubit 使用 OpenQASM 3.0 重新布线](braket-openqasm-rewire-qubits.md)
+ [使用 OpenQASM 3.0 进行逐字记录编译](braket-openqasm-verbatim-compilation.md)
+ [Braket 控制台](#braket-openqasm-braket-console)
+ [其他资源](#braket-openqasm-more-resources)
+ [使用 OpenQASM 3.0 计算梯度](braket-openqasm-computing-gradients.md)
+ [使用 OpenQASM 3.0 测量特定的量子比特](braket-openqasm-measure-qubits.md)

## 什么是 OpenQASM 3.0？
<a name="braket-openqasm-what-is"></a>

开放量子汇编语言（OpenQASM）是量子指令的[中间表示形式](https://en.wikipedia.org/wiki/Intermediate_representation)。OpenQASM 是一个开源框架，广泛用于规范基于门的设备的量子程序。使用 OpenQASM，用户可以对构成量子计算基块的量子门和测量操作进行编程。许多量子编程库都使用先前版本的 OpenQASM (2.0) 来描述基本程序。

新版本的 OpenQASM (3.0) 扩展了之前的版本，增加了更多功能，如脉冲电平控制、门定时和经典控制流，以弥合最终用户界面和硬件描述语言之间的差距。当前版本 3.0 的详细信息和规格可在 GitHub [OpenQasm 3.x](https://github.com/openqasm/openqasm) 实时规格中找到。OpenQasm 的未来发展由 OpenQasm 3.0 [技术指导委员会管理，该委员会](https://aws.amazon.com/blogs/quantum-computing/aws-joins-the-openqasm-3-0-technical-steering-committee/)与 IBM、微软和因斯布鲁克大学一起 AWS 是该委员会的成员。

## 何时使用 OpenQASM 3.0
<a name="braket-openqasm-when-to-use"></a>

OpenQASM 提供了一个富有表现力的框架，可通过非特定架构的低级控件来指定量子程序，因而非常适合作为多个基于门的设备的表示形式。Braket 对 OpenQASM 的支持进一步推动了其作为开发基于门的量子算法的一致方法的采用，从而减少了用户在多个框架中学习和维护库的需求。

如果您在 OpenQASM 3.0 中已有程序库，则可以对其进行调整，使其与 Braket 配合使用，而不必完全重写这些电路。研究人员和开发人员还应受益于越来越多的支持 OpenQASM 算法开发的可用第三方库。

## OpenQASM 3.0 的工作方式
<a name="braket-openqasm-how-it-works"></a>

Braket 对 OpenQASM 3.0 的支持提供了与当前中间表示法相同的功能。这意味着，您今天在硬件设备和使用 Braket 的按需模拟器上能做的任何事情，都可以使用 Braket API 在 OpenQASM 上处理。您可以通过直接向所有基于门的设备提供 OpenQASM 字符串来运行 OpenQASM 3.0 程序，其方式类似于当前向 Braket 上的设备提供电路。Braket 用户还可以集成支持 OpenQASM 3.0 的第三方库。本指南的其他部分详细介绍了如何开发用于 Braket 的 OpenQASM 表示形式。

## 先决条件
<a name="braket-openqasm-prerequisites"></a>

要在 Amazon Braket 上使用 OpenQASM 3.0，您必须拥有 [Amazon Braket Python 架构](https://github.com/aws/amazon-braket-schemas-python)的 1.8.0 版本和 [Amazon Braket Python SDK](https://github.com/aws/amazon-braket-sdk-python) 的 1.17.0 版本或更高版本。

如果您是首次接触 Amazon Braket 的用户，则需要启用 Amazon Braket。有关说明，请参阅[启用 Amazon Braket](https://docs.aws.amazon.com/braket/latest/developerguide/braket-enable-overview.html)。

# Braket 支持哪些 OpenQASM 功能？
<a name="braket-openqasm-supported-features"></a>

下节列出了 Braket 支持的 OpenQASM 3.0 数据类型、语句和编译指令。

**Topics**
+ [受支持的 OpenQASM 数据类型](#braket-openqasm-supported-features-datatypes)
+ [受支持的 OpenQASM 语句](#braket-openqasm-supported-features-statements)
+ [Braket OpenQASM 编译指示](#braket-openqasm-supported-features-pragmas)
+ [本地模拟器上对 OpenQASM 的高级功能支持](#braket-openqasm-supported-features-advanced-feature-local-simulator)
+ [支持的操作和语法 OpenPulse](#braket-openpulse-supported-operations-grammar)

## 受支持的 OpenQASM 数据类型
<a name="braket-openqasm-supported-features-datatypes"></a>

Amazon Braket 支持以下 OpenQASM 数据类型：
+ 非负整数用于（虚拟和物理）量子比特索引：
  +  `cnot q[0], q[1];` 
  +  `h $0;` 
+ 浮点数或常数可用于门旋转角度：
  +  `rx(-0.314) $0;` 
  +  `rx(pi/4) $0;` 

**注意**  
pi 是 OpenQASM 中的内置常量，不能用作参数名称。
+ 在用于定义一般哈密特量可观测值的结果类型编译指示和单一编译指示中，允许使用复数数组（虚数部分使用 OpenQASM `im` 表示法）：
  +  `#pragma braket unitary [[0, -1im], [1im, 0]] q[0]` 
  +  `#pragma braket result expectation hermitian([[0, -1im], [1im, 0]]) q[0]` 

## 受支持的 OpenQASM 语句
<a name="braket-openqasm-supported-features-statements"></a>

Amazon Braket 支持以下 OpenQASM 语句。
+  `Header: OPENQASM 3;` 
+ 经典位声明：
  +  `bit b1;` (equivalently, `creg b1;`)
  +  `bit[10] b2;` (equivalently, `creg b2[10];`)
+ 量子比特声明：
  +  `qubit b1;` (equivalently, `qreg b1;`)
  +  `qubit[10] b2;` (equivalently, `qreg b2[10];`)
+ 在数组内建立索引：`q[0]`
+ 输入：`input float alpha;`
+ 物理 qubits 的规格：`$0`
+ 设备上受支持的门和操作：
  +  `h $0;` 
  +  `iswap q[0], q[1];` 

**注意**  
设备支持的门可以在 OpenQASM 操作的设备属性中找到；使用这些门不需要任何门定义。
+ 逐字记录表声明。目前，我们不支持方框持续时间表示法。原生门和物理 qubits 必须放在逐字记录框中。

```
#pragma braket verbatim
box{
    rx(0.314) $0;
}
```
+ 在 qubits 或整个 qubit 寄存器上进行测量和测量分配。
  +  `measure $0;` 
  +  `measure q;` 
  +  `measure q[0];` 
  +  `b = measure q;` 
  +  `measure q → b;` 
+ Barrier 语句通过防止跨屏障边界的门重新排序和优化，提供对电路编译和执行的明确控制。它们还在执行期间强制执行严格的时间顺序，确保屏障之前的所有操作在后续操作开始之前完成。
  +  `barrier;` 
  +  `barrier q[0], q[1];` 
  +  `barrier $3, $6;` 

## Braket OpenQASM 编译指示
<a name="braket-openqasm-supported-features-pragmas"></a>

Amazon Braket 支持下列 OpenQASM 编译指示说明。
+ 噪声编译指示
  +  `#pragma braket noise bit_flip(0.2) q[0]` 
  +  `#pragma braket noise phase_flip(0.1) q[0]` 
  +  `#pragma braket noise pauli_channel` 
+ 逐字编译指示
  +  `#pragma braket verbatim` 
+ 结果类型编译指示
  + 基数不变结果类型：
    + 状态向量：`#pragma braket result state_vector`
    + 密度矩阵：`#pragma braket result density_matrix`
  + 梯度计算编译指示：
    + 伴随渐变：`#pragma braket result adjoint_gradient expectation(2.2 * x[0] @ x[1]) all`
  + Z 基准结果类型：
    + 振幅：`#pragma braket result amplitude "01"`
    + 概率：`#pragma braket result probability q[0], q[1]`
  + 基础轮换结果类型
    + 期望：`#pragma braket result expectation x(q[0]) @ y([q1])`
    + 方差：`#pragma braket result variance hermitian([[0, -1im], [1im, 0]]) $0`
    + 示例：`#pragma braket result sample h($1)`

**注意**  
由于 OpenQASM 3.0 向后兼容 OpenQASM 2.0，因而使用 2.0 编写的程序可以在 Braket 上运行。但是，Braket 支持的 OpenQASM 3.0 功能确实存在一些细微的语法差异，如 `qreg` vs `creg` 和 `qubit` vs `bit`。测量句法也有差异，需要用正确的语法来支持这些语法。

## 本地模拟器上对 OpenQASM 的高级功能支持
<a name="braket-openqasm-supported-features-advanced-feature-local-simulator"></a>

`LocalSimulator` 支持高级 OpenQASM 功能，这些功能不是作为 Braket 的 QPU 模拟器或按需模拟器的一部分提供的。在 `LocalSimulator` 中，仅支持下列功能：
+ 门修改器
+ OpenQASM 内置门
+ 经典变量
+ 经典运算
+ 定制门
+ 经典控制
+ QASM 文件
+ 子程序

有关每项高级功能的示例，请参阅此[样本 Notebook。](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Simulating_Advanced_OpenQASM_Programs_with_the_Local_Simulator.ipynb)有关完整的 OpenQASM 规范，请访问 [OpenQASM 网站](https://openqasm.com/language/index.html)。

## 支持的操作和语法 OpenPulse
<a name="braket-openpulse-supported-operations-grammar"></a>

 **支持 OpenPulse 的数据类型** 

Cal 块：

```
cal {
    ...
}
```

Defcal 块：

```
// 1 qubit
defcal x $0 {
...
}

// 1 qubit w. input parameters as constants
defcal my_rx(pi) $0 {
...
}

// 1 qubit w. input parameters as free parameters
defcal my_rz(angle theta) $0 {
...
}

// 2 qubit (above gate args are also valid)
defcal cz $1, $0 {
...
}
```

帧:

```
frame my_frame = newframe(port_0, 4.5e9, 0.0);
```

波形：

```
// prebuilt
waveform my_waveform_1 = constant(1e-6, 1.0);

//arbitrary
waveform my_waveform_2 = {0.1 + 0.1im, 0.1 + 0.1im, 0.1, 0.1};
```

 **自定义门校准示例：**

```
cal {
    waveform wf1 = constant(1e-6, 0.25);
}

defcal my_x $0 {
   play(wf1, q0_rf_frame);
}

defcal my_cz $1, $0 {
    barrier q0_q1_cz_frame, q0_rf_frame;
    play(q0_q1_cz_frame, wf1);
    delay[300ns] q0_rf_frame
    shift_phase(q0_rf_frame, 4.366186381749424);
    delay[300ns] q0_rf_frame;
    shift_phase(q0_rf_frame.phase, 5.916747563126659);
    barrier q0_q1_cz_frame, q0_rf_frame;
    shift_phase(q0_q1_cz_frame, 2.183093190874712);
}

bit[2] ro;
my_x $0;
my_cz $1,$0;
c[0] = measure $0;
```

 **任意脉冲示例：**

```
bit[2] ro;
cal {
    waveform wf1 = {0.1 + 0.1im, 0.1 + 0.1im, 0.1, 0.1};
    barrier q0_drive, q0_q1_cross_resonance;
    play(q0_q1_cross_resonance, wf1);
    delay[300ns] q0_drive;
    shift_phase(q0_drive, 4.366186381749424);
    delay[300dt] q0_drive;
   barrier q0_drive, q0_q1_cross_resonance;
   play(q0_q1_cross_resonance, wf1);
    ro[0] = capture_v0(r0_measure);
    ro[1] = capture_v0(r1_measure);
}
```

# 创建并提交示例 OpenQASM 3.0 量子任务
<a name="braket-openqasm-create-submit-task"></a>

你可以使用 Amazon Braket Python SDK、Boto3 或，向亚马逊 Braket AWS CLI 设备提交 OpenQasm 3.0 量子任务。

**Topics**
+ [一个 OpenQASM 3.0 程序示例](#braket-openqasm-example-program)
+ [使用 Python SDK 创建 OpenQASM 3.0 量子任务](#braket-openqasm-create-tasks-with-python-sdk)
+ [使用 Boto3 创建 OpenQASM 3.0 量子任务](#braket-openqasm-create-tasks-with-boto3)
+ [使用创建 OpenQasm 3.0 任务 AWS CLI](#braket-openqasm-create-tasks-with-aws-cli)

## 一个 OpenQASM 3.0 程序示例
<a name="braket-openqasm-example-program"></a>

要创建 OpenQASM 3.0 任务，您可以从一个基本的 OpenQASM 3.0 程序 (ghz.qasm) 开始，该程序准备 [GHZ](https://en.wikipedia.org/wiki/Greenberger%E2%80%93Horne%E2%80%93Zeilinger_state) 状态，如以下示例所示。

```
// ghz.qasm
// Prepare a GHZ state
OPENQASM 3;

qubit[3] q;
bit[3] c;

h q[0];
cnot q[0], q[1];
cnot q[1], q[2];

c = measure q;
```

## 使用 Python SDK 创建 OpenQASM 3.0 量子任务
<a name="braket-openqasm-create-tasks-with-python-sdk"></a>

您可以使用以下代码及 [Amazon Braket Python SDK](https://github.com/aws/amazon-braket-sdk-python) 将此程序提交到 Amazon Braket 设备。请务必将 Amazon S3 存储桶位置“amzn-s3-demo-bucket”替换为您自己的 Amazon S3 存储桶名称。

```
with open("ghz.qasm", "r") as ghz:
    ghz_qasm_string = ghz.read()

# Import the device module
from braket.aws import AwsDevice
# Choose the Rigetti device
device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")
from braket.ir.openqasm import Program

program = Program(source=ghz_qasm_string)
my_task = device.run(program)

# Specify an optional s3 bucket location and number of shots
s3_location = ("amzn-s3-demo-bucket", "openqasm-tasks")
my_task = device.run(
    program,
    s3_location,
    shots=100,
)
```

## 使用 Boto3 创建 OpenQASM 3.0 量子任务
<a name="braket-openqasm-create-tasks-with-boto3"></a>

您还可以使用 [AWS 适用于 Braket 的 Python SDK（Boto3）](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/braket.html)，利用 OpenQASM 3.0 字符串创建量子任务，如以下示例所示。以下代码片段引用了 ghz.qasm，它准备了 [GHZ](https://en.wikipedia.org/wiki/Greenberger%E2%80%93Horne%E2%80%93Zeilinger_state) 状态，如上所示。

```
import boto3
import json

my_bucket = "amzn-s3-demo-bucket"
s3_prefix = "openqasm-tasks"

with open("ghz.qasm") as f:
    source = f.read()

action = {
    "braketSchemaHeader": {
        "name": "braket.ir.openqasm.program",
        "version": "1"
    },
    "source": source
}
device_parameters = {}
device_arn = "arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3"
shots = 100

braket_client = boto3.client('braket', region_name='us-west-1')
rsp = braket_client.create_quantum_task(
    action=json.dumps(
        action
    ),
    deviceParameters=json.dumps(
        device_parameters
    ),
    deviceArn=device_arn,
    shots=shots,
    outputS3Bucket=my_bucket,
    outputS3KeyPrefix=s3_prefix,
)
```

## 使用创建 OpenQasm 3.0 任务 AWS CLI
<a name="braket-openqasm-create-tasks-with-aws-cli"></a>

[AWS Command Line Interface （CLI）](https://aws.amazon.com/cli/)也可用于提交 OpenQASM 3.0 程序，如以下示例所示。

```
aws braket create-quantum-task \
    --region "us-west-1" \
    --device-arn "arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3" \
    --shots 100 \
    --output-s3-bucket "amzn-s3-demo-bucket" \
    --output-s3-key-prefix "openqasm-tasks" \
    --action '{
        "braketSchemaHeader": {
            "name": "braket.ir.openqasm.program",
            "version": "1"
        },
        "source": $(cat ghz.qasm)
    }'
```

# 在不同的 Braket 设备上支持 OpenQASM
<a name="braket-openqasm-device-support"></a>

对于支持 OpenQASM 3.0 的设备，`action` 字段支持通过 `GetDevice` 响应执行新操作，如下列 Rigetti 和 IonQ 设备示例所示。

```
//OpenQASM as available with the Rigetti device capabilities
{
    "braketSchemaHeader": {
        "name": "braket.device_schema.rigetti.rigetti_device_capabilities",
        "version": "1"
    },
    "service": {...},
    "action": {
        "braket.ir.jaqcd.program": {...},
        "braket.ir.openqasm.program": {
            "actionType": "braket.ir.openqasm.program",
            "version": [
                "1"
            ],
            ….
        }
    }
}

//OpenQASM as available with the IonQ device capabilities
{
    "braketSchemaHeader": {
        "name": "braket.device_schema.ionq.ionq_device_capabilities",
        "version": "1"
    },
    "service": {...},
    "action": {
        "braket.ir.jaqcd.program": {...},
        "braket.ir.openqasm.program": {
            "actionType": "braket.ir.openqasm.program",
            "version": [
                "1"
            ],
            ….
        }
    }
}
```

对于支持脉冲控制的设备，`pulse` 字段显示在 `GetDevice` 响应中。以下示例显示了 Rigetti 设备的 `pulse` 字段。

```
// Rigetti
{
  "pulse": {
    "braketSchemaHeader": {
      "name": "braket.device_schema.pulse.pulse_device_action_properties",
      "version": "1"
    },
    "supportedQhpTemplateWaveforms": {
      "constant": {
        "functionName": "constant",
        "arguments": [
          {
            "name": "length",
            "type": "float",
            "optional": false
          },
          {
            "name": "iq",
            "type": "complex",
            "optional": false
          }
        ]
      },
      ...
    },
    "ports": {
      "q0_ff": {
        "portId": "q0_ff",
        "direction": "tx",
        "portType": "ff",
        "dt": 1e-9,
        "centerFrequencies": [
          375000000
        ]
      },
      ...
    },
    "supportedFunctions": {
      "shift_phase": {
        "functionName": "shift_phase",
        "arguments": [
          {
            "name": "frame",
            "type": "frame",
            "optional": false
          },
          {
            "name": "phase",
            "type": "float",
            "optional": false
          }
        ]
      },
     ...
    },
    "frames": {
      "q0_q1_cphase_frame": {
        "frameId": "q0_q1_cphase_frame",
        "portId": "q0_ff",
        "frequency": 462475694.24460185,
        "centerFrequency": 375000000,
        "phase": 0,
        "associatedGate": "cphase",
        "qubitMappings": [
          0,
          1
        ]
      },
      ...
    },
    "supportsLocalPulseElements": false,
    "supportsDynamicFrames": false,
    "supportsNonNativeGatesWithPulses": false,
    "validationParameters": {
      "MAX_SCALE": 4,
      "MAX_AMPLITUDE": 1,
      "PERMITTED_FREQUENCY_DIFFERENCE": 400000000
    }
  }
}
```

前面的字段详细说明了以下内容：

 **端口：**

描述了在 QPU 上声明的预制外部 (`extern`) 设备端口以及给定端口的相关属性。此结构中列出的所有端口都预先声明为用户提交的 `OpenQASM 3.0` 程序中的有效标识符。端口的其他属性包括：
+ 端口 ID (portId)
  + 在 OpenQASM 3.0 中声明为标识符的端口名称。
+ 方向 (direction)
  + 端口的方向。驱动端口传输脉冲（“tx”方向），而测量端口接收脉冲（“rx”方向）。
+ 端口类型 (portType)
  + 此端口负责的操作类型（例如，驱动、捕获或 ff - fast-flux）。
+ Dt (dt)
  + 表示给定端口上的单个采样时间步长，以秒为单位。
+ 量子比特映射 (qubitMappings)
  + 与给定端口关联的量子比特。
+ 中心频率 (centerFrequencies)
  + 端口上所有预先声明或用户定义的帧的相关中心频率列表。有关更多信息，请参阅“帧”。
+ QHP 特定属性 () qhpSpecificProperties
  + 一张可选地图，详细介绍有关 QHP 特定端口的现有属性。

 **帧：**

描述了在 QPU 上声明的预制外部帧以及与这些帧相关的属性。此结构中列出的所有帧都预先声明为用户提交的 `OpenQASM 3.0` 程序中的有效标识符。帧的其他属性包括：
+ 帧编号 (frameId)
  + 在 OpenQASM 3.0 中声明为标识符的帧名称。
+ 端口 ID (portId)
  + 帧的关联硬件端口。
+ 频率 (frequency)
  + 帧的默认初始频率。
+ 中心频率 (centerFrequency)
  + 帧频率带宽的中心。通常，只能将帧调整到中心频率周围的特定带宽。因此，频率调整应保持在中心频率的给定增量之内。您可以在验证参数中找到带宽值。
+ 阶段 (phase)
  + 帧的默认初始阶段。
+ 关联门 (associatedGate)
  + 与给定帧关联的门。
+ 量子比特映射 (qubitMappings)
  + 与给定帧关联的量子比特。
+ QHP 特定属性 () qhpSpecificProperties
  + 一张可选地图，详细说明有关 QHP 特定帧的现有属性。

 **SupportsDynamicFrames:** 

描述了帧是否可以通过 OpenPulse `newframe` 函数在 `cal` 或 `defcal` 块中声明。如果该值为 false，则只能在程序中使用帧结构中列出的帧。

 **SupportedFunctions:** 

除了给定函数的关联参数、参数类型和返回类型之外，还描述了设备支持的 OpenPulse 函数。要查看使用这些OpenPulse函数的示例，请参阅[OpenPulse规范](https://openqasm.com/language/openpulse.html)。目前，Braket 支持：
+ shift\$1phase
  + 按指定值移动帧的相位
+ set\$1phase
  + 将帧的相位设置为指定值
+ swap\$1phases
  + 在两帧之间交换相位。
+ shift\$1frequency
  + 按指定值移动帧的频率
+ set\$1frequency
  + 将帧频设置为指定值
+ play
  + 安排波形
+ capture\$1v0
  + 将捕获帧上的值返回到位寄存器

 **SupportedQhpTemplateWaveforms:** 

描述了设备上可用的预先构造的波形函数以及相关的参数和类型。默认情况下，Braket Pulse 在所有设备上提供预先构造的波形例程，它们是：

 ***Constant*** 

![\[显示参数为 t、tau 和 iq 的常数函数的数学表达式，其中：输出始终等于 iq。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/ConstantFunction.png)


 `τ` 是波形长度，`iq` 是一个复数。

```
def constant(length, iq)
```

 ***Gaussian*** 

![\[显示参数为 t、tau、sigma、A=1 和 zae=0 的高斯函数的数学方程。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/GaussianFunction.png)


 `τ` 是波形长度，`σ` 是高斯宽度，`A` 是振幅。如果将 `ZaE` 设置为 `True`，则对 Gaussian 进行偏移和重新缩放，使其在波形的开头和结尾处都等于零，且最大达到 `A`。

```
def gaussian(length, sigma, amplitude=1, zero_at_edges=False)
```

 ***DRAG Gaussian*** 

![\[参数为 t、tau、sigma、beta、A=1 和 zae=0 的阻力高斯分布的数学方程。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/DRAGGaussianFunction.png)


 `τ` 是波形长度，`σ` 是高斯宽度，`β` 是自由参数，`A` 是振幅。如果将 `ZaE` 设置为 `True`，则对绝热门导数去除（DRAG）Gaussian 进行偏移和重新缩放，使其在波形的开头和结尾处都等于零，实数部分最大达到 `A`。有关阻力波形的更多信息，请参阅论文 [Simple Pulses for Elimination of Leakage in Weakly Nonlinear Qubits](https://doi.org/10.1103/PhysRevLett.103.110501)。

```
def drag_gaussian(length, sigma, beta, amplitude=1, zero_at_edges=False)
```

 ***Erf Square*** 

![\[Erf Square 分布的数学方程，含参数 t、长度、宽度、sigma、A=1 和 zae=0。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/ErfSquareFunction.PNG)


其中：`L` 是长度，`W` 是波形宽度，`σ` 定义了边缘上升和下降的速度，`t1​=(L−W)/2` 和 `t22=(L+W)/2`，`A` 是振幅。如果将 `ZaE` 设置为 `True`，则对 Gaussian 进行偏移和重新缩放，使其在波形的开头和结尾处都等于零，且最大达到 `A`。以下方程是波形的重新缩放版本。

![\[参数为 zae=1 的重新缩放的 Erf Square 分布数学方程。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/RescaledErfSquareFunction.PNG)


其中：`a=erf(W/2σ)` 且 `b=erf(-t1​/σ)/2+erf(t2​/σ)/2`。

```
def erf_square(length, width, sigma, amplitude=1, zero_at_edges=False)
```

 **SupportsLocalPulseElements:** 

描述了脉冲元素（如端口、帧和波形）是否可以在 `defcal` 块中进行本地定义。如果值为 `false`，则必须以 `cal` 块形式定义元素。

 **SupportsNonNativeGatesWithPulses:** 

描述了我们是否可以将非原生门与脉冲程序结合使用。例如，如果不先通过 `defcal` 为所使用的量子比特定义门，就不能像程序中的 `H` 门一样使用非原生门。您可以在“设备功能”下方找到原生门 `nativeGateSet` 键列表。

 **ValidationParameters:** 

描述了脉冲元件验证边界，包括：
+ （任意及预先构造的）波形的最大扩展/最大振幅值
+ 所提供中心频率的最大频率带宽（单位为赫兹）
+  length/duration 以秒为单位的最小脉冲
+ 以秒为单位的最 length/duration 大脉冲

## OpenQASM 支持的操作、结果和结果类型
<a name="braket-openqasm-supported-operations-results-result-types"></a>

要了解每台设备支持哪些 OpenQASM 3.0 功能，可以参考设备功能输出 `action` 字段中的 `braket.ir.openqasm.program` 键。例如，以下是 Braket 状态向量模拟器 SV1 支持的操作和结果类型。

```
...
  "action": {
    "braket.ir.jaqcd.program": {
      ...
    },
 "braket.ir.openqasm.program": {
      "version": [
        "1.0"
      ],
      "actionType": "braket.ir.openqasm.program",
      "supportedOperations": [
        "ccnot",
        "cnot",
        "cphaseshift",
        "cphaseshift00",
        "cphaseshift01",
        "cphaseshift10",
        "cswap",
        "cy",
        "cz",
        "h",
        "i",
        "iswap",
        "pswap",
        "phaseshift",
        "rx",
        "ry",
        "rz",
        "s",
        "si",
        "swap",
        "t",
        "ti",
        "v",
        "vi",
        "x",
        "xx",
        "xy",
        "y",
        "yy",
        "z",
        "zz"
      ],
      "supportedPragmas": [
        "braket_unitary_matrix"
      ],
      "forbiddenPragmas": [],
      "maximumQubitArrays": 1,
      "maximumClassicalArrays": 1,
      "forbiddenArrayOperations": [
        "concatenation",
        "negativeIndex",
        "range",
        "rangeWithStep",
        "slicing",
        "selection"
      ],
      "requiresAllQubitsMeasurement": true,
      "supportsPhysicalQubits": false,
      "requiresContiguousQubitIndices": true,
      "disabledQubitRewiringSupported": false,
      "supportedResultTypes": [
        {
          "name": "Sample",
          "observables": [
            "x",
            "y",
            "z",
            "h",
            "i",
            "hermitian"
          ],
          "minShots": 1,
          "maxShots": 100000
        },
        {
          "name": "Expectation",
          "observables": [
            "x",
            "y",
            "z",
            "h",
            "i",
            "hermitian"
          ],
          "minShots": 0,
          "maxShots": 100000
        },
        {
          "name": "Variance",
          "observables": [
            "x",
            "y",
            "z",
            "h",
            "i",
            "hermitian"
          ],
          "minShots": 0,
          "maxShots": 100000
        },
        {
          "name": "Probability",
          "minShots": 1,
          "maxShots": 100000
        },
        {
          "name": "Amplitude",
          "minShots": 0,
          "maxShots": 0
        }
        {
          "name": "AdjointGradient",
          "minShots": 0,
          "maxShots": 0
        }
      ]
    }
  },
...
```

# 使用 OpenQASM 3.0 模拟噪声
<a name="braket-openqasm-noise-simulation"></a>

要使用 Open 模拟噪声QASM3，可以使用 *pragma* 指令添加噪音运算符。例如，要模拟之前提供的 [GHZ 程序](braket-openqasm-create-submit-task.md#braket-openqasm-example-program)的噪声版本，您可以提交以下 OpenQASM 程序。

```
// ghz.qasm
// Prepare a GHZ state
OPENQASM 3;

qubit[3] q;
bit[3] c;

h q[0];
#pragma braket noise depolarizing(0.75) q[0] cnot q[0], q[1];
#pragma braket noise depolarizing(0.75) q[0]
#pragma braket noise depolarizing(0.75) q[1] cnot q[1], q[2];
#pragma braket noise depolarizing(0.75) q[0]
#pragma braket noise depolarizing(0.75) q[1]

c = measure q;
```

以下列表给出了所有受支持的编译指示噪声运算符的规格。

```
#pragma braket noise bit_flip(<float in [0,1/2]>) <qubit>
#pragma braket noise phase_flip(<float in [0,1/2]>) <qubit>
#pragma braket noise pauli_channel(<float>, <float>, <float>)  <qubit>
#pragma braket noise depolarizing(<float in [0,3/4]>) <qubit>
#pragma braket noise two_qubit_depolarizing(<float in [0,15/16]>) <qubit>, <qubit>
#pragma braket noise two_qubit_dephasing(<float in [0,3/4]>) <qubit>, <qubit>
#pragma braket noise amplitude_damping(<float in [0,1]>) <qubit>
#pragma braket noise generalized_amplitude_damping(<float in [0,1]> <float in [0,1]>)  <qubit>
#pragma braket noise phase_damping(<float in [0,1]>) <qubit>
#pragma braket noise kraus([[<complex m0_00>, ], ...], [[<complex m1_00>, ], ...], ...) <qubit>[, <qubit>]     // maximum of 2 qubits and maximum of 4 matrices for 1 qubit, 16 for 2
```

## Kraus 运算符
<a name="braket-openqasm-kraus-operator"></a>

要生成 Kraus 运算符，可以遍历矩阵列表，将矩阵的每个元素打印为复杂表达式。

使用克劳斯运算符时，请记住以下几点：
+ qubits 的数量不得超过 2。[架构中的当前定义](https://github.com/aws/amazon-braket-sdk-python/blob/0d28a8fa89263daf5d88bc706e79200d8dc091a8/src/braket/circuits/noises.py#L811-L814))设定了此限制。
+ 参数列表的长度必须是 8 的倍数。这意味着它必须仅由 2x2 矩阵组成。
+ 总长度不超过 22\$1num\$1qubits 矩阵。这意味着，1 个 qubit 有 4 个矩阵，2 个 qubits 有 16 个矩阵。
+ 所有提供的矩阵均为[完全正迹线保持(CPTP）](https://github.com/aws/amazon-braket-sdk-python/blob/0d28a8fa89263daf5d88bc706e79200d8dc091a8/src/braket/circuits/quantum_operator_helpers.py#L94-L108)。
+ Kraus 运算符及其转置共轭的乘积需要相加得出一个单位矩阵。

# Qubit 使用 OpenQASM 3.0 重新布线
<a name="braket-openqasm-rewire-qubits"></a>

[Amazon Braket Rigetti 支持设备上的 OpenQASM 中的物理 qubit 符号（要了解更多信息，请参阅本](https://github.com/openqasm/openqasm/blob/main/source/language/types.rst)页面）。在将物理 qubits 与[原生重新布线策略](https://pyquil-docs.rigetti.com/en/v2.28.1/compiler.html#naive)配合使用时，请确保 qubits 已连接到所选设备上。或者，如果改用 qubit 寄存器，则默认情况下，Rigetti 设备上会启用部分重新布线策略。

```
// ghz.qasm
// Prepare a GHZ state
OPENQASM 3;

h $0;
cnot $0, $1;
cnot $1, $2;

measure $0;
measure $1;
measure $2;
```

# 使用 OpenQASM 3.0 进行逐字记录编译
<a name="braket-openqasm-verbatim-compilation"></a>

当您在 Rigetti 和 IonQ 等供应商提供的量子计算机上运行量子电路时，您可以指示编译器完全按照定义运行您的电路，而无需做出任何修改。此功能称为*逐字记录编译*。使用Rigetti设备，您可以精确地指定要保留的内容——要么是整个电路，要么仅保留其中的特定部分。如果仅保留电路的特定部分，需要在保留区域内使用原生门。目前，IonQ 仅支持整个电路的逐字记录编译，因此电路中的每条指令都需要放在逐字记录框中。

使用 OpenQASM，您可以围绕代码框明确指定逐字记录编译指示，然后该代码保持不变，不会被硬件的低级编译例程优化。以下代码示例演示了如何使用 `#pragma braket verbatim` 指令实现这一点。

```
OPENQASM 3;

bit[2] c;

#pragma braket verbatim
box{
    rx(0.314159) $0;
    rz(0.628318) $0, $1;
    cz $0, $1;
}

c[0] = measure $0;
c[1] = measure $1;
```

有关逐字编译过程的更多详细信息，包括示例和最佳实践，请参阅 github 存储库中提供的 [Verbatim 编译](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Verbatim_Compilation.ipynb)示例笔记本。 amazon-braket-examples

## Braket 控制台
<a name="braket-openqasm-braket-console"></a>

OpenQASM 3.0 任务可用，可在 Amazon Braket 控制台中进行管理。在控制台上，您在 OpenQASM 3.0 中提交量子任务的体验与提交现有量子任务的体验相同。

## 其他资源
<a name="braket-openqasm-more-resources"></a>

OpenQASM 在所有 Amazon Braket 区域中都可用。

[有关在 Amazon Braket 上开始使用 OpenQasm 的笔记本示例，请参阅 Braket 教程。 GitHub](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Getting_Started_with_OpenQASM_on_Braket.ipynb)

# 使用 OpenQASM 3.0 计算梯度
<a name="braket-openqasm-computing-gradients"></a>

在 `shots=0`（精确）模式下运行时，Amazon Braket 支持在按需模拟器和本地模拟器上计算梯度。通过使用伴随微分法，可以实现这一点。要指定所计算的梯度，可以提供相应的编译指示，如以下示例中的代码所示。

```
OPENQASM 3.0;
input float alpha;

bit[2] b;
qubit[2] q;

h q[0];
h q[1];
rx(alpha) q[0];
rx(alpha) q[1];
b[0] = measure q[0];
b[1] = measure q[1];

#pragma braket result adjoint_gradient h(q[0]) @ i(q[1]) alpha
```

您不必明确列出所有单独的参数，可以在编译指示中指定 `all` 关键字。这样可以计算出所列的所有参数的梯度，当 `input` 参数数量非常大时，这可能是一个方便的选择。在这种情况下，编译指示与以下示例中的代码类似。

```
#pragma braket result adjoint_gradient h(q[0]) @ i(q[1]) all
```

Amazon Braket 的 OpenQASM 3.0 实现支持所有可观察类型，包括单个运算符、张量乘积、哈密特量可观测值和 `Sum` 可观测值。计算梯度时要使用的特定运算符必须封装在 `expectation()` 函数中，而且必须明确指定可观测值的每一项所作用的量子比特。

# 使用 OpenQASM 3.0 测量特定的量子比特
<a name="braket-openqasm-measure-qubits"></a>

Amazon Braket 提供的局部状态向量模拟器和局部密度矩阵模拟器支持提交可以选择性测量电路量子比特子集的 OpenQASM 程序。这种能力通常被称为部分测量，可以更有针对性、更高效地进行量子计算。例如，在以下代码片段中，您可以创建一个双量子比特电路，并选择仅测量第一个量子比特，而不测量第二个量子比特。

```
partial_measure_qasm = """
OPENQASM 3.0;
bit[1] b;
qubit[2] q;
h q[0];
cnot q[0], q[1];
b[0] = measure q[0];
"""
```

在该例中，我们有一个包含两个量子比特的量子电路，`q[0]` 和 `q[1]`，但是我们只对测量第一个量子比特的状态感兴趣。这是通过直线 `b[0] = measure q[0]` 来实现的，它测量的是 quit[0] 的状态并将结果存储在经典位 b[0] 中。要运行此部分测量场景，我们可以在 Amazon Braket 提供的本地状态向量模拟器上运行以下代码。

```
from braket.devices import LocalSimulator

local_sim = LocalSimulator()
partial_measure_local_sim_task = local_sim.run(OpenQASMProgram(source=partial_measure_qasm), shots = 10)
partial_measure_local_sim_result = partial_measure_local_sim_task.result()
print(partial_measure_local_sim_result.measurement_counts)
print("Measured qubits: ", partial_measure_local_sim_result.measured_qubits)
```

您可以通过检查设备动作属性中的 `requiresAllQubitsMeasurement` 字段来检查设备是否支持部分测量；如果是 `False`，则支持部分测量。

```
from braket.devices import Devices
            
AwsDevice(Devices.Rigetti.Ankaa3).properties.action['braket.ir.openqasm.program'].requiresAllQubitsMeasurement
```

这里，`requiresAllQubitsMeasurement` 是 `False`，这表明并非所有量子比特都必须进行测量。

# 探索实验能力
<a name="braket-experimental-capabilities"></a>

实验功能允许访问可用性有限的硬件和新出现的新软件功能。这些功能可能会影响超出标准规格的设备性能。您可以通过 Amazon Braket SDK 按任务自动启用实验性软件功能。

要使用实验能力，请在创建量子任务时指定`experimental_capabilities`参数。将此参数设置为`"ALL"`，以启用该任务的所有可用实验功能。以下示例说明如何在设备上运行电路时启用实验功能：

```
from braket.aws import AwsDevice

device = AwsDevice("arn:aws:braket:us-east-1::device/qpu/quera/Aquila")

task = device.run(
   circuit,
   shots=1000,
   experimental_capabilities="ALL"
)
```

**注意**  
这些功能是实验性的，可能会更改，恕不另行通知。设备性能可能与公布的规格不同，结果可能与标准操作有所不同。您必须为每项任务明确启用实验能力。没有此参数的任务将仅使用标准设备功能。

**Topics**
+ [在 Aquila 上 QuEra 访问本地停机功能](#braket-access-local-detuning)
+ [在 Aquila 上 QuEra 访问高大的几何形状](#braket-access-tall-geometries)
+ [在 Aquila 上 QuEra 可以看到紧凑的几何形状](#braket-access-tight-geometries)
+ [IQM 设备上的动态电路](#braket-access-dynamic-circuits)

## 在 Aquila 上 QuEra 访问本地停机功能
<a name="braket-access-local-detuning"></a>

局部失谐是一个新的时变控制字段，具有可自定义的空间规律。LD 场根据可自定义的空间规律影响量子比特，从而针对不同的量子比特实现不同的哈密顿量子比特，而不仅仅是均匀驱动场和 Rydberg-Rydberg 相互作用所能创造的范围。

**约束**：

局部失谐字段的空间规律可以针对每个 AHS 程序进行自定义，但在整个程序过程中是恒定的。局部失谐字段的时间序列必须从零开始和结束，并且所有值都小于等于零。此外，局部失谐字段的参数受数值约束的限制，可通过 Braket SDK 的特定设备属性部分 `aquila_device.properties.paradigm.rydberg.rydbergLocal` 查看。

**限制:**

在运行使用局部失谐场（即使其振幅在哈密顿量中设置为恒定零）的量子程序时，设备的去相干速度比 Aquila 属性的性能部分中列出的 T2 时间更快。如不必要，最佳做法是省略 AHS 程序的哈密顿量中的局部失谐字段。

![\[自旋术语中的模拟哈密顿模拟，其中含有量子比特、时变局部驱动场和时变局部失谐。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/AHS_spin_terminology.png)


**示例：**

1. **模拟自旋系统中非均匀纵向磁场的影响**

   虽然驱动场的振幅和相位对量子比特的影响与横向磁场对自旋的影响相同，但驱动场失谐和局部失谐之和对量子比特产生的影响与纵向磁场对自旋造成的影响相同。通过对局部失谐场的空间控制，可以模拟更复杂的自旋系统。

1. **准备非平衡初始状态**

   示例 Notebook [用 Rydberg 原子模拟晶格计理论](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/analog_hamiltonian_simulation/07_Simulating_Lattice_Gauge_Theory_with_Rydberg_Atoms.ipynb)，展示了当系统向 Z2 有序相退火时，如何抑制 9 原子线性排列的中心原子受到激发。准备步骤完成后，局部失谐场会缩小，AHS 程序继续模拟系统从这种特定的非平衡状态开始的时间演变。

1. **求解加权优化问题**

   示例 Notebook [最大重量独立套装](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/analog_hamiltonian_simulation/08_Maximum_Weight_Independent_Set.ipynb)（MWIS）展示了如何解决 Aquila 上的 MWIS 问题。局部失谐字段用于定义单位磁盘图节点上的权重，这些节点的边缘由 Rydberg 阻塞效应实现。从均匀基态开始，逐渐增大局部失谐场，使系统过渡到 MWIS 哈密顿量的基态，以找到问题的解决方案。

## 在 Aquila 上 QuEra 访问高大的几何形状
<a name="braket-access-tall-geometries"></a>

高几何图形功能可指定高度增加的几何图形。有了这种能力，您的 AHS 程序的原子排列可以在 y 方向上跨越额外的长度，超出 Aquila 的常规能力。

**约束**：

高几何形状的最大高度为 0.000128 米（128 微米）。

**限制:**

为您的账户启用此实验功能后，设备属性页面和 `GetDevice` 调用中显示的功能将继续反映常规的高度下限。当 AHS 程序使用超出常规能力的原子排列时，预计填充误差会增加。在任务结果的 `pre_sequence` 部分，您会发现 0 数量的意外增加现象，这反过来又减少了获得完美初始化排列的机会。在有许多原子的行中，这种效果最明显。

![\[这三张点图以一维线、梯形和多路复用形式描绘了高几何形状。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/tall-geometry-graphs.PNG)


**示例：**

1. **更大的一维和准一维排列**

   原子链和梯子状排列可以扩展到更大的原子数。通过将长方向定向平行于 y，可以对这些模型的更长实例进行编程。

1. **为多路复用小几何图形执行任务提供更大空间**

   示例 Notebook [Aquila 上的并行量子任务](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/analog_hamiltonian_simulation/03_Parallel_tasks_on_Aquila.ipynb)展示了如何充分利用可用区域：将相关几何体的多路复用副本放在一个原子排列中。可用区域越多，可以放置的副本就越多。

## 在 Aquila 上 QuEra 可以看到紧凑的几何形状
<a name="braket-access-tight-geometries"></a>

紧凑的几何结构特征可指定相邻行间距较短的几何图形。在 AHS 程序中，原子成行排列，由最小的垂直间距隔开。任意两个原子位点的 y 坐标必须为零（同一行），或者差值大于最小行间距（不同的行）。凭借紧凑的几何形状能力，可以缩小最小行距，从而创建更紧密的原子排列。虽然这种扩展不会改变原子之间的最小欧几里得距离要求，但它创建晶格，其中遥远的原子占据彼此更近的相邻行，一个值得注意的例子是三角形晶格。

**约束**：

紧凑几何形状的最小行间距为 0.000002 米（2 微米）。

**限制:**

为您的账户启用此实验功能后，设备属性页面和 `GetDevice` 调用中显示的功能将继续反映常规的高度下限。当 AHS 程序使用超出常规能力的原子排列时，预计填充误差会增加。客户会在任务结果的 `pre_sequence` 部分发现更多意外的 0，这反过来又减少了获得完美初始化安排的机会。在有许多原子的行中，这种效果最明显。

![\[这些图显示了左边的三角形点阵的紧凑几何形状，右边的图形是六角形的点状晶格。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/tight-geometry-graphs.PNG)


**示例：**

1. **具有小晶格常数的非矩形晶格**

   行间距更紧凑，可创建晶格，其中与某些原子最近的邻居在对角线方向上。值得注意的例子是三角形、六角形和 Kagome 晶格以及一些准晶体。

1. **可调晶格系列**

   在 AHS 程序中，通过调整原子对之间的距离可以调整相互作用。更紧的行间距可保证以更大的自由度调整不同原子对彼此之间的相互作用，因为定义原子结构的角度和距离受最小行间距的约束较少。一个值得注意的例子是具有不同键长的 Shastry-Sutherland 晶格家族。

## IQM 设备上的动态电路
<a name="braket-access-dynamic-circuits"></a>

IQM 设备上的动态电路支持中间电路测量（MCM）和前馈操作。有了这些功能，量子研究人员和开发人员能够实现具有条件逻辑和量子比特重用功能的高级量子算法。该实验功能有助于探索具有更高资源效率的量子算法，并研究量子误差缓解和纠错方案。

**主要说明：**
+ `measure_ff`：实现前馈控制的测量，测量量子比特并使用反馈键存储结果。
+ `cc_prx`: 实现经典控制的轮换，该轮换仅在与给定反馈键关联的结果测量 \$11⟩ 状态时适用。

Amazon Braket 通过 OpenQASM、Amazon Braket SDK 和 Amazon Braket Qiskit Provider 支持动态电路。

**约束**：

1. `measure_ff` 说明中的反馈键必须是唯一的。

1. `cc_prx` 必须在 `measure_ff` 之后，使用相同的反馈键。

1. 在单个电路中，量子比特的前馈只能由一个量子比特控制，可以由其自身控制，也可由另一个量子比特控制。在不同的电路中，您可以有不同的控制对。<a name="lower"></a>

   1. 例如，如果量子比特 1 由量子比特 2 控制，则无法在相同电路中由量子比特 3 控制。在量子比特 1 和量子比特 2 之间，应用控制的次数没有限制。量子比特 2 可由量子比特 3（或量子比特 1）控制，除非对量子比特 2 进行了主动重置。

1. 控制只能应用于同一组中的量子比特。IQM Garnet 和 Emerald 设备的量子比特组如下图所示。

1. 具有这些功能的程序必须作为逐字记录程序提交。要了解有关逐字记录程序的更多信息，请参阅[使用 OpenQASM 3.0 进行逐字记录编译](https://docs.aws.amazon.com/braket/latest/developerguide/braket-openqasm-verbatim-compilation.html)。

**限制:**

MCM 只能用于程序中的前馈控制。MCM 结果（0 或 1）不会作为任务结果的一部分返回。

![\[左图是 IQM Garnet 20 量子比特设备，在方形晶格中有 2 个量子比特组，右图是 IQM Emerald 54 量子比特设备，在方形晶格中有 4 个量子比特组。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/IQM-Garnet-Emerald-qubit-grouping.png)


这些图像显示了两个 IQM 设备的量子比特分组。Garnet 20 量子比特设备包含 2 组量子比特，而 Emerald 54 量子比特设备包含 4 组量子比特。

**示例：**

1. **通过主动重置来重复使用量子比特**

   带有条件复位操作的 MCM 允许在单个电路执行中重复使用量子比特。这就降低了电路深度要求，提高了量子设备的资源利用率。

1. **主动位翻转保护**

   动态电路可检测位翻转错误，并根据测量结果进行校正操作。该实现用作量子误差检测实验。

1. **传送实验**

   状态隐形传态使用局部量子运算和来自的经典信息传输量子比特态。 MCMs门传送无需直接进行量子运算即可实现量子比特之间的门。这些实验演示了三个关键领域的基础子程序：量子误差校正、基于测量的量子计算和量子通信。

1. **开放量子系统模拟**

   动态电路通过数据量子比特和环境纠缠以及环境测量对量子系统中的噪声进行建模。这种方法使用特定的量子比特来表示数据和环境元素。噪声通道可通过对环境施加的门和测量值进行设计。

有关使用动态电路的更多信息，请参阅 [Amazon Braket Notebook 存储库](https://github.com/amazon-braket/amazon-braket-examples/tree/main/examples/experimental_capabilities/dynamic_circuits)中的其他示例。

# Amazon Braket 上的脉冲控制
<a name="braket-pulse-control"></a>

脉冲是控制量子计算机中量子比特的模拟信号。使用 Amazon Braket 上的某些设备，您可以访问脉冲控制功能，使用脉冲提交电路。你可以通过 Braket SDK、OpenQasm 3.0 或直接通过 Braket 访问脉冲控制。 APIs首先介绍 Braket 中脉冲控制的一些关键概念。

**Topics**
+ [帧](#braket-frame)
+ [端口](#braket-port)
+ [波形](#braket-waveform)
+ [使用 Hello Pulse](braket-hello-pulse.md)
+ [使用脉冲访问原生门](braket-native-gate-pulse.md)

## 帧
<a name="braket-frame"></a>

帧是一种软件抽象，既充当量子程序中的时钟，又充当相位。每次使用时，时钟时间都会递增，并且有状态的载波信号由频率定义。向量子比特传输信号时，帧决定量子比特的载波频率、相位偏移以及波形包络的发射时间。在 Braket Pulse 中，构造帧取决于设备、频率和相位。根据设备的不同，您可以选择预定义的帧，也可以通过提供端口来实例化新帧。

```
from braket.aws import AwsDevice
from braket.pulse import Frame, Port

# Predefined frame from a device
device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")
drive_frame = device.frames["Transmon_5_charge_tx"]

# Create a custom frame
readout_frame = Frame(frame_id="r0_measure", port=Port("channel_0", dt=1e-9), frequency=5e9, phase=0)
```

## 端口
<a name="braket-port"></a>

端口是一种软件抽象，代表任何控制量子比特的 input/output 硬件组件。它可以帮助硬件供应商提供一个接口，用户可以通过该界面进行交互以操作和观测量子比特。端口有一个表示连接器名称的单个字符串。该字符串还显示了最小时间增量，该增量指定了我们可以定义波形的精细程度。

```
from braket.pulse import Port

Port0 = Port("channel_0", dt=1e-9)
```

## 波形
<a name="braket-waveform"></a>

波形是一种时变包络，我们可以用它在输出端口上发射信号或通过输入端口捕获信号。您可以通过复数列表直接指定波形，也可以使用波形模板生成硬件提供商提供的列表。

```
from braket.pulse import ArbitraryWaveform, ConstantWaveform
import numpy as np

cst_wfm = ConstantWaveform(length=1e-7, iq=0.1)
arb_wf = ArbitraryWaveform(amplitudes=np.linspace(0, 100))
```

 Braket Pulse 提供了一个标准波形库，包括恒定波形、高斯波形和绝热门导数去除（DRAG）波形。您可以通过 `sample` 函数检索波形数据，以绘制波形，如以下示例所示。

```
from braket.pulse import GaussianWaveform
import numpy as np
import matplotlib.pyplot as plt

zero_at_edge1 = GaussianWaveform(1e-7, 25e-9, 0.1, True)
# or zero_at_edge1 = GaussianWaveform(1e-7, 25e-9, 0.1)
zero_at_edge2 = GaussianWaveform(1e-7, 25e-9, 0.1, False)

times_1 = np.arange(0, zero_at_edge1.length, drive_frame.port.dt)
times_2 = np.arange(0, zero_at_edge2.length, drive_frame.port.dt)

plt.plot(times_1, zero_at_edge1.sample(drive_frame.port.dt))
plt.plot(times_2, zero_at_edge2.sample(drive_frame.port.dt))
```

![\[该图显示了两种情况下随时间变化的振幅：ZaE = True（下部曲线）和 ZaE = False（顶部曲线）。曲线呈钟形，峰值约为 0.5 秒，振幅为 0.10 a. u.。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/gaussianwaveform.png)


上图描绘了从 `GaussianWaveform` 中创建的高斯波形。我们选择的脉冲长度为 100 纳米，宽度为 25 纳米，振幅为 0.1（任意单位）。波形在脉冲窗口中居中。`GaussianWaveform` 接受布尔参数 `zero_at_edges`（图例中的 ZaE）。设置为 `True` 时，此参数会偏移高斯波形，使 t=0 和 t= `length` 处的点为零，并重新缩放其振幅，使最大值与 `amplitude` 参数相对应。

# 使用 Hello Pulse
<a name="braket-hello-pulse"></a>

在本节中，您将了解如何使用 Rigetti 设备上的 Pulse 直接表征和构造单个量子比特门。对量子比特施加电磁场会导致 Rabi 振荡，在量子比特的 0 状态和 1 状态之间切换。通过校准脉冲的长度和相位，Rabi 振荡可以计算出单个量子比特门。在这里，我们将确定测量 pi/2 脉冲的最佳脉冲长度，该脉冲是用于构建更复杂的脉冲序列的基本模块。

首先，要构建脉冲序列，请导入 `PulseSequence` 类。

```
from braket.aws import AwsDevice
from braket.circuits import FreeParameter
from braket.devices import Devices
from braket.pulse import PulseSequence, GaussianWaveform

import numpy as np
```

接下来，使用 QPU 的 Amazon Resource Name（ARN）实例化一台新的 Braket 设备。以下命令块使用 Rigetti Ankaa-3：

```
device = AwsDevice(Devices.Rigetti.Ankaa3)
```

以下脉冲序列包括两个部分：播放波形和测量量子比特。脉冲序列通常可以应用于帧。有一些例外，如屏障和延迟，可以应用于量子比特。在构造脉冲序列之前，必须检索可用的帧。驱动框架用于施加脉冲以实现 Rabi 振荡，读出帧用于测量量子比特状态。此示例使用量子比特 25 的帧。

```
drive_frame = device.frames["Transmon_25_charge_tx"]
readout_frame = device.frames["Transmon_25_readout_rx"]
```

现在，创建要在驱动器帧中播放的波形。这样做的目的是描述量子比特在不同脉冲长度下的行为。每次您将播放一个长度不同的波形。不是每次都实例化一个新波形，而是在脉冲序列中使用 Braket 支持的 `FreeParameter`。您可以使用自由参数创建一次波形和脉冲序列，然后使用不同的输入值运行相同的脉冲序列。

```
waveform = GaussianWaveform(FreeParameter("length"), FreeParameter("length") * 0.25, 0.2, False)
```

最后，将它们组合成脉冲序列。在脉冲序列中，`play` 播放驱动器帧上的指定波形，`capture_v0` 测量读出帧的状态。

```
pulse_sequence = (
    PulseSequence()
    .play(drive_frame, waveform)
    .capture_v0(readout_frame)
)
```

扫描一定范围的脉冲长度，然后将其提交给 QPU。在 QPU 上执行脉冲序列之前，请绑定自由参数的值。

```
start_length = 12e-9
end_length = 2e-7
lengths = np.arange(start_length, end_length, 12e-9)
N_shots = 100

tasks = [
    device.run(pulse_sequence(length=length), shots=N_shots)
    for length in lengths
]

probability_of_zero = [
    task.result().measurement_counts['0']/N_shots
    for task in tasks
]
```

量子比特测量的统计数据显示了在 0 状态和 1 状态之间振荡的量子比特的振荡动力学。从测量数据中，您可以提取 Rabi 频率并微调脉冲长度以实现特定的 1 量子比特门。例如，根据下图中的数据，周期约为 154 纳米。因此，pi/2 旋转门对应于长度为 38.5 纳米的脉冲序列。

![\[以秒为单位显示脉冲持续时间的折线图。图中有两个峰值和一个低谷。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/Rabi-frequency.png)


## 你好 Pulse 使用 OpenPulse
<a name="braket-hello-pulse-openpulse"></a>

 [OpenPulse](https://openqasm.com/language/openpulse.html)是一种用于指定通用量子器件脉冲电平控制的语言，是 OpenQasm 3.0 规范的一部分。Amazon Braket 支持 OpenPulse 使用 OpenQASM 3.0 表示形式直接对脉冲进行编程。

 Braket 使用 OpenPulse 在原生指令中表达脉冲的底层中间表示形式。OpenPulse 支持以 `defcal`（“定义校准”的缩写）声明形式添加指令校准。通过这些声明，您可以在较低级别的控制语法中指定门指令的实现。

您可以使用以下命令查看 Brake `PulseSequence` t 的 OpenPulse 程序。

```
print(pulse_sequence.to_ir())
```

您也可以直接构造 OpenPulse 程序。

```
from braket.ir.openqasm import Program
 
openpulse_script = """
OPENQASM 3.0;
cal {
    bit[1] psb;
    waveform my_waveform = gaussian(12.0ns, 3.0ns, 0.2, false);
    play(Transmon_25_charge_tx, my_waveform);
    psb[0] = capture_v0(Transmon_25_readout_rx);
}
"""
```

使用脚本创建 `Program` 对象。然后，将该程序提交给 QPU。

```
from braket.aws import AwsDevice
from braket.devices import Devices
from braket.ir.openqasm import Program

program = Program(source=openpulse_script)

device = AwsDevice(Devices.Rigetti.Ankaa3)
task = device.run(program, shots=100)
```

# 使用脉冲访问原生门
<a name="braket-native-gate-pulse"></a>

研究人员通常需要确切了解特定 QPU 支持的*原生*门是如何实现为脉冲的。脉冲序列由硬件提供商仔细校准，但是访问脉冲序列为研究人员提供了设计更好的门或探索错误缓解协议的机会，如通过拉伸特定门的脉冲来进行零噪声外推。

Amazon Braket 支持以编程方式从 Rigetti 访问原生门。

```
import math
from braket.aws import AwsDevice
from braket.circuits import Circuit, GateCalibrations, QubitSet
from braket.circuits.gates import Rx

device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")

calibrations = device.gate_calibrations
print(f"Downloaded {len(calibrations)} calibrations.")
```

**注意**  
硬件提供商定期校准 QPU，通常每天不止一次。通过 Braket SDK，您能够获得最新的门校准。

```
device.refresh_gate_calibrations()
```

要检索给定的原生门，如 RX 或 XY 门，您需要传递相关 `Gate` 对象和量子比特。例如，您可以检查应用于 qubit 0 的 RX(π/2) 的脉冲实现。

```
rx_pi_2_q0 = (Rx(math.pi/2), QubitSet(0))

pulse_sequence_rx_pi_2_q0 = calibrations.pulse_sequences[rx_pi_2_q0]
```

您可以使用 `filter` 函数创建一组经过筛选的校准。您传递了一个门列表或一个 `QubitSet` 列表。以下代码创建了两个集合，其中包含 RX(π/2) 和 qubit 0 的所有校准。

```
rx_calibrations = calibrations.filter(gates=[Rx(math.pi/2)])
q0_calibrations = calibrations.filter(qubits=QubitSet([0]))
```

现在，您可以通过附加自定义校准集来提供或修改原生门的操作。例如，考虑以下电路：

```
bell_circuit = (
    Circuit()
    .rx(0, math.pi/2)
    .rx(1, math.pi/2)
    .iswap(0, 1)
    .rx(1, -math.pi/2)
)
```

您可以通过将 `PulseSequence` 对象字典传递给 `gate_definitions` 关键字参数 `qubit 0` 来运行它，为 `rx` 门开启自定义门校准。您可以根据 `GateCalibrations` 对象的属性 `pulse_sequences` 构造字典。所有未指定的门都被量子硬件提供商的脉冲校准所取代。

```
nb_shots = 50
custom_calibration = GateCalibrations({rx_pi_2_q0: pulse_sequence_rx_pi_2_q0})
task = device.run(bell_circuit, gate_definitions=custom_calibration.pulse_sequences, shots=nb_shots)
```

# 模拟哈密顿模拟
<a name="braket-analog-hamiltonian-simulation"></a>

[模拟哈密顿模拟](https://en.wikipedia.org/wiki/Hamiltonian_simulation)（AHS）是量子计算的新兴范式，与传统的量子电路模型有很大的不同。它不是一系列门，即每个电路一次只能作用于几个量子比特。AHS 程序由相关哈密顿量的时变和空间相关参数定义。[系统的哈密顿量](https://en.wikipedia.org/wiki/Hamiltonian_(quantum_mechanics))对其能级和外力的影响进行编码，它们共同控制着其状态的时间演变。对于 N 量子比特系统，哈密顿量可以用 2NX2N 个复数方阵表示。

能够执行 AHS 的量子设备旨在通过仔细调整其内部控制参数，近似定制哈密顿量下的量子系统的时间演变。例如，调整相干驱动场的振幅和失谐参数。AHS 范式非常适合模拟具有许多相互作用粒子的量子系统的静态和动态特性，比如在凝聚态物理学或量子化学中。专门设计的量子处理单元 (QPUs)，例如的 [Aquila设备](https://aws.amazon.com/braket/quantum-computers/quera/)QuEra，是为了利用AHS的力量，以创新的方式解决传统数字量子计算方法无法解决的问题。

**Topics**
+ [Hello AHS：运行您的第一个模拟哈密顿模拟](braket-get-started-hello-ahs.md)
+ [使用 A QuEra quila 提交模拟节目](braket-quera-submitting-analog-program-aquila.md)

# Hello AHS：运行您的第一个模拟哈密顿模拟
<a name="braket-get-started-hello-ahs"></a>

本节提供了有关运行第一个模拟哈密顿模拟的信息。

**Topics**
+ [交互式旋转链](#braket-get-started-interacting-spin-chain)
+ [排列](#braket-get-started-arrangement)
+ [相互作用](#braket-get-started-interaction)
+ [驱动场](#braket-get-started-driving-field)
+ [AHS 程序](#braket-get-started-ahs-program)
+ [在本地模拟器上运行](#braket-get-started-running-local-simulator)
+ [分析模拟器结果](#braket-get-started-analyzing-simulator-results)
+ [Run QuEra ning on 的 Aquila QPU](#braket-get-started-running-aquila-qpu)
+ [分析结果](#braket-get-started-analyzing-qpu-results)
+ [后续步骤](#braket-get-started-ahs-next)

## 交互式旋转链
<a name="braket-get-started-interacting-spin-chain"></a>

举一个由许多相互作用粒子组成的系统的典型示例，让我们考虑一个由八个旋转组成的环（每个旋转都可以处于“向上”∣↑⟩ 和“向下”∣↓⟩ 的状态）。尽管规模很小，但该模型系统已经表现出自然存在的磁性材料的一些有趣现象。在此例中，我们将展示如何准备一个所谓的反铁磁阶数，即连续的自旋指向相反的方向。

![\[连接 8 个包含向上和向下反向箭头的圆形节点的示意图。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/AntiFerromagnetic.png)


## 排列
<a name="braket-get-started-arrangement"></a>

我们将使用一个中性原子来代表每次自旋，“向上”和“向下”自旋态将分别以激发的里德伯格态和原子的基态编码。首先，创建二维排列。我们可以用以下代码对上面的旋转圈进行编程。

 **先决条件**：您需要 pip 安装 [Braket SDK](https://github.com/aws/amazon-braket-sdk-python#installing-the-amazon-braket-python-sdk)。（如果您使用的是 Braket 托管的 Notebook 实例，则此 SDK 已预先安装在 Notebook 中。） 要重现绘图，您还需要使用 shell 命令 `pip install matplotlib` 单独安装 matplotlib。

```
from braket.ahs.atom_arrangement import AtomArrangement
import numpy as np
import matplotlib.pyplot as plt  # Required for plotting

a = 5.7e-6  # Nearest-neighbor separation (in meters)

register = AtomArrangement()
register.add(np.array([0.5, 0.5 + 1/np.sqrt(2)]) * a)
register.add(np.array([0.5 + 1/np.sqrt(2), 0.5]) * a)
register.add(np.array([0.5 + 1/np.sqrt(2), - 0.5]) * a)
register.add(np.array([0.5, - 0.5 - 1/np.sqrt(2)]) * a)
register.add(np.array([-0.5, - 0.5 - 1/np.sqrt(2)]) * a)
register.add(np.array([-0.5 - 1/np.sqrt(2), - 0.5]) * a)
register.add(np.array([-0.5 - 1/np.sqrt(2), 0.5]) * a)
register.add(np.array([-0.5, 0.5 + 1/np.sqrt(2)]) * a)
```

我们还可以绘制散点图，

```
fig, ax = plt.subplots(1, 1, figsize=(7, 7))
xs, ys = [register.coordinate_list(dim) for dim in (0, 1)]
ax.plot(xs, ys, 'r.', ms=15)

for idx, (x, y) in enumerate(zip(xs, ys)):
    ax.text(x, y, f" {idx}", fontsize=12)

plt.show()  # This will show the plot below in an ipython or jupyter session
```

![\[显示在两个轴上的正值和负值分布的点。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/PlotNeutralAtoms.png)


## 相互作用
<a name="braket-get-started-interaction"></a>

为准备反铁磁相，我们需要诱导相邻自旋之间的相互作用。为此，我们使用了 [van der Waals 相互作用](https://en.wikipedia.org/wiki/Van_der_Waals_force)，该相互作用是由中性原子设备（如来自 QuEra 的 Aquila 设备）原生实现的。这种相互作用的哈密顿项使用自旋表示，可以表示为所有自旋对 (j,k) 的总和。

![\[这种相互作用的哈密顿项使用自旋表示，可以表示为所有自旋对 (j,k) 的总和。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/HInteraction.png)


其中：nj=∣↑j​⟩⟨↑j​∣ 是一个运算符，仅当自旋 j 处于“向上”状态时才取值 1，否则取值 0。强度为 Vj,k​=C6​/(dj,k​)6，其中：C6 是固定系数，dj,k 是自旋 j 和 k 之间的欧几里得距离。这个相互作用项的直接影响是，任何自旋 j 和自旋 k 都是“向上”状态的能量都会升高（按量 Vj,k）。通过精心设计 AHS 程序的其余部分，这种相互作用可防止相邻的旋转都处于“向上”状态，这种效果通常被称为“Rydberg 阻塞”。

## 驱动场
<a name="braket-get-started-driving-field"></a>

AHS 程序开始时，所有旋转（默认情况下）都以“向下”状态开始，它们处于所谓的铁磁阶段。着眼于准备反铁磁相位的目标，我们指定了一个时变相干驱动场，该驱动场可以平稳地将自旋从这种状态过渡到多体状态，首选为“向上”状态。相应的哈密顿量可以写成

![\[描述哈密顿驱动函数计算的数学方程。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/HDrive.png)


其中 Ω(t)、(t)、Δ(t) 是时变全局振幅（又名 [Rabi 频率](https://en.wikipedia.org/wiki/Rabi_frequency)）、相位和失谐均匀地影响所有自旋的驱动场。其中：S−,k​ =∣↓k​⟩⟨↑k​∣and S\$1,k​​=(S−,k​)†=∣↑k​⟩⟨↓k​∣分别是 spin k 的降低和升高运算符，nk​=∣↑k​⟩⟨↑k​∣和以前的运算符相同。驱动场的 Ω 部分同时连贯地耦合所有旋转的“向下”和“向上”状态，而 Δ 部分控制“向上”状态的能量奖励。

为了对从铁磁相向到反铁磁相的平滑过渡进行编程，我们使用以下代码指定驱动场。

```
from braket.timings.time_series import TimeSeries
from braket.ahs.driving_field import DrivingField

# Smooth transition from "down" to "up" state
time_max = 4e-6  # seconds
time_ramp = 1e-7  # seconds
omega_max = 6300000.0  # rad / sec
delta_start = -5 * omega_max
delta_end = 5 * omega_max

omega = TimeSeries()
omega.put(0.0, 0.0)
omega.put(time_ramp, omega_max)
omega.put(time_max - time_ramp, omega_max)
omega.put(time_max, 0.0)

delta = TimeSeries()
delta.put(0.0, delta_start)
delta.put(time_ramp, delta_start)
delta.put(time_max - time_ramp, delta_end)
delta.put(time_max, delta_end)

phi = TimeSeries().put(0.0, 0.0).put(time_max, 0.0)

drive = DrivingField(
   amplitude=omega,
   phase=phi,
   detuning=delta
)
```

我们可以使用以下脚本可视化驱动场的时间序列。

```
fig, axes = plt.subplots(3, 1, figsize=(12, 7), sharex=True)

ax = axes[0]
time_series = drive.amplitude.time_series
ax.plot(time_series.times(), time_series.values(), '.-')
ax.grid()
ax.set_ylabel('Omega [rad/s]')

ax = axes[1]
time_series = drive.detuning.time_series
ax.plot(time_series.times(), time_series.values(), '.-')
ax.grid()
ax.set_ylabel('Delta [rad/s]')

ax = axes[2]
time_series = drive.phase.time_series
# Note: time series of phase is understood as a piecewise constant function
ax.step(time_series.times(), time_series.values(), '.-', where='post')
ax.set_ylabel('phi [rad]')
ax.grid()
ax.set_xlabel('time [s]')

plt.show()  # This will show the plot below in an ipython or jupyter session
```

![\[三张图显示了一段时间内的 phi、delta 和 omega。顶部的子图显示增长到略高于 6， rads/s 在此处它保持 4 秒钟，直到回落到 0。中间的图描绘了导数的相关线性增长，底图描绘了一条接近零的平线。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/DrivingTimeSeries.png)


## AHS 程序
<a name="braket-get-started-ahs-program"></a>

寄存器、驱动场（以及隐式的范德华相互作用）构成了模拟哈密顿模拟程序 `ahs_program`。

```
from braket.ahs.analog_hamiltonian_simulation import AnalogHamiltonianSimulation

ahs_program = AnalogHamiltonianSimulation(
   register=register,
   hamiltonian=drive
)
```

## 在本地模拟器上运行
<a name="braket-get-started-running-local-simulator"></a>

由于此示例很小（少于 15 次旋转），因此在兼容 AHS 的 QPU 上运行之前，我们可以在 Braket SDK 附带的本地 AHS 模拟器上运行它。由于本地模拟器可免费使用 Braket SDK，因而这是确保我们的代码能够正确执行的最佳实践。

在这里，我们可以将拍摄次数设置为较大的值（比如 100 万），因为本地模拟器会跟踪量子态的时间演变并从最终状态中抽取样本；因此，可以增加拍摄次数，而总运行时仅略有增加。

```
from braket.devices import LocalSimulator

device = LocalSimulator("braket_ahs")

result_simulator = device.run(
   ahs_program,
   shots=1_000_000
).result()  # Takes about 5 seconds
```

## 分析模拟器结果
<a name="braket-get-started-analyzing-simulator-results"></a>

我们可以使用以下函数汇总拍摄结果，该函数可以推断每次旋转的状态（可以是“d”代表“向下”，“u”表示“向上”，“e“代表空场地），并计算每种配置在拍摄中发生的次数。

```
from collections import Counter


def get_counts(result):
    """Aggregate state counts from AHS shot results

    A count of strings (of length = # of spins) are returned, where
    each character denotes the state of a spin (site):
      e: empty site
      u: up state spin
      d: down state spin

    Args:
      result (braket.tasks.analog_hamiltonian_simulation_quantum_task_result.AnalogHamiltonianSimulationQuantumTaskResult)

    Returns
       dict: number of times each state configuration is measured

    """
    state_counts = Counter()
    states = ['e', 'u', 'd']
    for shot in result.measurements:
        pre = shot.pre_sequence
        post = shot.post_sequence
        state_idx = np.array(pre) * (1 + np.array(post))
        state = "".join(map(lambda s_idx: states[s_idx], state_idx))
        state_counts.update((state,))
    return dict(state_counts)


counts_simulator = get_counts(result_simulator)  # Takes about 5 seconds
print(counts_simulator)
```

```
*[Output]*
{'dddddddd': 5, 'dddddddu': 12, 'ddddddud': 15, ...}
```

在这里，`counts` 是一本字典，它计算了拍摄中观察到的每种状态配置的次数。我们还可以使用以下代码实现它们的可视化。

```
from collections import Counter


def has_neighboring_up_states(state):
    if 'uu' in state:
        return True
    if state[0] == 'u' and state[-1] == 'u':
        return True
    return False


def number_of_up_states(state):
    return Counter(state)['u']


def plot_counts(counts):
    non_blockaded = []
    blockaded = []
    for state, count in counts.items():
        if not has_neighboring_up_states(state):
            collection = non_blockaded
        else:
            collection = blockaded
        collection.append((state, count, number_of_up_states(state)))

    blockaded.sort(key=lambda _: _[1], reverse=True)
    non_blockaded.sort(key=lambda _: _[1], reverse=True)

    for configurations, name in zip((non_blockaded,
                                     blockaded),
                                    ('no neighboring "up" states',
                                     'some neighboring "up" states')):
        plt.figure(figsize=(14, 3))
        plt.bar(range(len(configurations)), [item[1] for item in configurations])
        plt.xticks(range(len(configurations)))
        plt.gca().set_xticklabels([item[0] for item in configurations], rotation=90)
        plt.ylabel('shots')
        plt.grid(axis='y')
        plt.title(f'{name} configurations')
        plt.show()


plot_counts(counts_simulator)
```

![\[条形图显示了大量没有相邻的“向上”状态配置的拍摄。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/AHSCounts1.png)


![\[条形图显示了一些相邻的“向上”状态配置的拍摄，其中 1.0 次拍摄有 4 个状态。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/AHSCounts2.png)


从图中，我们可以读出以下观测结果，以验证我们成功制备了反铁磁相。

1. 通常，非阻塞状态（没有两个相邻的旋转处于“向上”状态）比至少有一对相邻旋转都处于“向上”状态的状态更为常见。

1. 通常，除非配置被阻止，否则会优先选择激励更多“向上”状态。

1. 最常见的状态确实是完美的反铁磁态 `"dudududu"` 和 `"udududud"`。

1. 第二种常见的状态是只有 3 个“向上”激励，连续间隔为 1、2、2 的状态。这表明范德华的相互作用也会对最近的邻居产生影响（尽管该影响要小得多）。

## Run QuEra ning on 的 Aquila QPU
<a name="braket-get-started-running-aquila-qpu"></a>

 **先决条件**：除了 pip 安装 [Braket SDK](https://github.com/aws/amazon-braket-sdk-python#installing-the-amazon-braket-python-sdk) 之外，如果您不熟悉 Amazon Braket，请确保您已完成必要的[入门步骤](https://docs.aws.amazon.com/braket/latest/developerguide/braket-get-started.html)。

**注意**  
如果您使用的是 Braket 托管的 Notebook 实例，则该实例预装了 Braket SDK。

安装所有依赖项后，我们就可以连接到 Aquila QPU 了。

```
from braket.aws import AwsDevice

aquila_qpu = AwsDevice("arn:aws:braket:us-east-1::device/qpu/quera/Aquila")
```

为了使我们的 AHS 程序适合 QuEra 机器，我们需要对所有值进行四舍五入，以符合 Aquila QPU 规定的精度水平。（这些要求受名称中带有“分辨率”的设备参数的约束。我们可以通过在 Notebook 中执行 `aquila_qpu.properties.dict()` 来看到它们。有关 Aquila 功能和要求的更多详细信息，请参阅 [Aquila Notebook 简介](https://github.com/aws/amazon-braket-examples/blob/main/examples/analog_hamiltonian_simulation/01_Introduction_to_Aquila.ipynb)。） 我们可以通过调用 `discretize` 方法来做到这一点。

```
discretized_ahs_program = ahs_program.discretize(aquila_qpu)
```

现在，我们可以在 Aquila QPU 上运行该程序（目前只运行 100 次拍摄）。

**注意**  
在 Aquila 处理器上运行此程序将产生一定的成本。Amazon Braket SDK 包含一个[成本追踪器](https://aws.amazon.com/blogs/quantum-computing/managing-the-cost-of-your-experiments-in-amazon-braket/)，这样，客户能够设置成本限额并近乎实时地跟踪成本。

```
task = aquila_qpu.run(discretized_ahs_program, shots=100)

metadata = task.metadata()
task_arn = metadata['quantumTaskArn']
task_status = metadata['status']

print(f"ARN: {task_arn}")
print(f"status: {task_status}")
```

```
*[Output]*
ARN: arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef
status: CREATED
```

由于量子任务的运行时差异很大（取决于可用窗口和 QPU 利用率），因此记下量子任务 ARN 是个好主意，这样我们就可以在后续时间使用以下代码片段检查其状态了。

```
# Optionally, in a new python session
from braket.aws import AwsQuantumTask

SAVED_TASK_ARN = "arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef"

task = AwsQuantumTask(arn=SAVED_TASK_ARN)
metadata = task.metadata()
task_arn = metadata['quantumTaskArn']
task_status = metadata['status']

print(f"ARN: {task_arn}")
print(f"status: {task_status}")
```

```
*[Output]*
ARN: arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef
status: COMPLETED
```

状态为“已完成”（也可以从 Amazon Braket [控制台](https://us-east-1.console.aws.amazon.com/braket/home?region=us-east-1#/tasks)的量子任务页面进行检查）后，我们可以通过以下方式查询结果：

```
result_aquila = task.result()
```

## 分析结果
<a name="braket-get-started-analyzing-qpu-results"></a>

我们可以使用与以前相同的 `get_counts` 函数计算计数。

```
counts_aquila = get_counts(result_aquila)
   print(counts_aquila)
```

```
*[Output]*
{'dddududd': 2, 'dudududu': 18, 'ddududud': 4, ...}
```

然后，用 `plot_counts` 绘制函数：

```
plot_counts(counts_aquila)
```

![\[条形图显示了大量没有相邻的“向上”状态配置的拍摄。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/QPUPlotCounts1.png)


![\[条形图显示了一些相邻的“向上”状态配置的拍摄，其中 1.0 次拍摄有 4 个状态。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/QPUPlotCounts2.png)


请注意，一小部分拍摄的场地为空（标为“e”）。这是由于 Aquila QPU 的每个原子制备存在 1%-2% 的缺陷。除此之外，由于拍摄次数少，结果在预期的统计波动范围内与模拟相符。

## 后续步骤
<a name="braket-get-started-ahs-next"></a>

恭喜！您现在已经使用本地 AHS 模拟器和 Aquila QPU 在 Amazon Braket 上运行了第一个 AHS 工作负载。

要了解有关 Rydberg 物理学、模拟哈密顿模拟和 Aquila 设备的更多信息，请参阅我们的[示例 Notebook。](https://github.com/aws/amazon-braket-examples/tree/main/examples/analog_hamiltonian_simulation)

# 使用 A QuEra quila 提交模拟节目
<a name="braket-quera-submitting-analog-program-aquila"></a>

本页提供了有关来自 QuEra 的 Aquila 机器能力的整个文档。此处涵盖的详细信息如下：

1. 通过以下方法模拟的参数化哈密顿量模型 Aquila

1. AHS 程序参数

1. AHS 结果内容

1. Aquila 能力参数

**Topics**
+ [哈密顿量](#braket-quera-aquila-device-hamiltonian)
+ [Braket AHS 程序架构](#braket-quera-ahs-program-schema)
+ [Braket AHS 任务结果架构](#braket-quera-ahs-task-result-schema)
+ [QuEra 设备属性架构](#braket-quera-device-properties-schema)

## 哈密顿量
<a name="braket-quera-aquila-device-hamiltonian"></a>

来自 QuEra 的 Aquila 机器以原生方式对以下（时变）哈密顿量程进行模拟。

![\[数学方程，其中：求和表示系统的哈密顿量，包括驱动、局部失谐和点间耦合项。\]](http://docs.aws.amazon.com/zh_cn/braket/latest/developerguide/images/TimeDependentDrivingHamiltonian.png)


**注意**  
访问局部失谐是一项[实验能力](https://docs.aws.amazon.com/braket/latest/developerguide/braket-experimental-capabilities.html)，可通过 Braket Direct 申请获得。

where
+ Hdrive,k​(t)=( 1/2 ​Ω(t)eiϕ(t)S−,k​ \$1 1/2 ​Ω(t)e−iϕ(t) S\$1,k​) \$1 (−Δglobal​(t)nk​)，
  + Ω(t) 是时变全局驱动振幅（又名 Rabi 频率），单位为（弧度/秒）
  + ϕ(t) 是时变全局相位，单位为弧度
  + S−,k​ 和 S\$1,k 是原子 k 的自旋降低和升高运算符（在基数中，\$1↓⟩=\$1g⟩,\$1↑⟩=\$1r），它们是 S−​=\$1g⟩⟨r\$1,S\$1​=(S−​)†=\$1r⟩⟨g\$1)
  + Δglobal​(t) 是时变全局失谐
  + nk 是原子 k 的里德伯格状态的投影运算符（也就是说，n=\$1r⟩⟨r\$1）
+ Hlocal detuning,k(t)=-Δlocal(t)hknk
  + Δlocal(t) 是局部频移的时变因子，单位为（弧度/秒）
  + hk 是与位置相关的因子，介于 0.0 到 1.0 之间的无量纲数字
+ Vvdw,k,l​=C6​/(dk,l​)6nk​nl​，
  + C6 是范德华系数，单位为 (rad / s) \$1 (m)^6
  + dk,l 是原子 k 和 l 之间的欧几里得距离，单位为米。

用户可以通过 Braket AHS 程序架构控制以下参数。
+ 二维原子排列（每个原子 k 的 xk 和 yk 坐标，单位为 um），它控制成对原子距离 dk,l​，其中：k,l=1,2,…N
+ Ω(t)，时变全局 Rabi 频率，单位为（弧度/秒）
+ ϕ(t)，时变全局相位，单位为（弧度）
+ Δglobal​(t)，时变全局失谐，单位为（弧度/秒）
+ Δlocal(t)，局部失谐振幅的时变（全局）因子，单位为（弧度/秒）
+ hk，与地点相关的局部失谐振幅的（静态）因子，属于介于 0.0 和 1.0 之间的无量纲数字

**注意**  
用户无法控制涉及哪些级别（即 S−、S\$1​、n 运算符是固定的），也无法控制里德伯-里德伯交互系数 (C6) 的强度。

## Braket AHS 程序架构
<a name="braket-quera-ahs-program-schema"></a>

 **braket.ir.ahs.program\$1v1.Program 对象**（示例）

**注意**  
如果您的账户未启用[局部失谐](https://docs.aws.amazon.com/braket/latest/developerguide/braket-experimental-capabilities.html#braket-access-local-detuning)功能，请在以下示例中使用 `localDetuning=[]`。

```
Program(
    braketSchemaHeader=BraketSchemaHeader(
        name='braket.ir.ahs.program',
        version='1'
    ),
    setup=Setup(
        ahs_register=AtomArrangement(
            sites=[
                [Decimal('0'), Decimal('0')],
                [Decimal('0'), Decimal('4e-6')],
                [Decimal('4e-6'), Decimal('0')]
            ],
            filling=[1, 1, 1]
        )
    ),
    hamiltonian=Hamiltonian(
        drivingFields=[
            DrivingField(
                amplitude=PhysicalField(
                    time_series=TimeSeries(
                        values=[Decimal('0'), Decimal('15700000.0'), Decimal('15700000.0'), Decimal('0')],
                        times=[Decimal('0'), Decimal('0.000001'), Decimal('0.000002'), Decimal('0.000003')]
                    ),
                    pattern='uniform'
                ),
                phase=PhysicalField(
                    time_series=TimeSeries(
                        values=[Decimal('0'), Decimal('0')],
                        times=[Decimal('0'), Decimal('0.000003')]
                    ),
                    pattern='uniform'
                ),
                detuning=PhysicalField(
                    time_series=TimeSeries(
                        values=[Decimal('-54000000.0'), Decimal('54000000.0')],
                        times=[Decimal('0'), Decimal('0.000003')]
                    ),
                    pattern='uniform'
                )
            )
        ],
        localDetuning=[
            LocalDetuning(
                magnitude=PhysicalField(
                    times_series=TimeSeries(
                        values=[Decimal('0'), Decimal('25000000.0'), Decimal('25000000.0'), Decimal('0')],
                        times=[Decimal('0'), Decimal('0.000001'), Decimal('0.000002'), Decimal('0.000003')]
                    ),
                    pattern=Pattern([Decimal('0.8'), Decimal('1.0'), Decimal('0.9')])
                )
            )
        ]
    )
)
```

**JSON**（示例）

**注意**  
如果您的账户未启用[局部失谐](https://docs.aws.amazon.com/braket/latest/developerguide/braket-experimental-capabilities.html#braket-access-local-detuning)功能，请在以下示例中使用 `"localDetuning": []`。

```
{
    "braketSchemaHeader": {
        "name": "braket.ir.ahs.program",
        "version": "1"
    },
    "setup": {
        "ahs_register": {
            "sites": [
                [0E-7, 0E-7], 
                [0E-7, 4E-6],
                [4E-6, 0E-7]
            ],
            "filling": [1, 1, 1]
        }
    },
    "hamiltonian": {
        "drivingFields": [
            {
                "amplitude": {
                    "time_series": {
                        "values": [0.0, 15700000.0, 15700000.0, 0.0],
                        "times": [0E-9, 0.000001000, 0.000002000, 0.000003000]
                    },
                    "pattern": "uniform"
                },
                "phase": {
                    "time_series": {
                        "values": [0E-7, 0E-7],
                        "times": [0E-9, 0.000003000]
                    },
                    "pattern": "uniform"
                },
                "detuning": {
                    "time_series": {
                        "values": [-54000000.0, 54000000.0],
                        "times": [0E-9, 0.000003000]
                    },
                    "pattern": "uniform"
                }
            }
        ],
        "localDetuning": [
            {
                "magnitude": {
                    "time_series": {
                        "values": [0.0, 25000000.0, 25000000.0, 0.0],
                        "times": [0E-9, 0.000001000, 0.000002000, 0.000003000]
                    },
                    "pattern": [0.8, 1.0, 0.9]
                }
            }
        ]
    }
}
```


**主要字段**  

| 程序字段 | 类型 | 描述 | 
| --- | --- | --- | 
|  setup.ahs\$1register.sites  |  List[List[Decimal]]  |  镊子捕获原子的二维坐标清单  | 
|  setup.ahs\$1register.filling  |  List[int]  |  用 1 标记占据陷阱位点的原子，用 0 标记占据空位点的原子  | 
|  hamiltonian.drivingFields[].amplitude.time\$1series.times  |  List[Decimal]  |  驱动振幅的时间点，Omega(t)  | 
|  hamiltonian.drivingFields[].amplitude.time\$1series.values  |  List[Decimal]  |  驱动振幅值，Omega(t)  | 
|  hamiltonian.drivingFields[].amplitude.pattern  |  str  |  驱动振幅的空间规律，Omega(t)；必须是“均匀的”  | 
|  hamiltonian.drivingFields[].phase.time\$1series.times  |  List[Decimal]  |  驾驶相位的时间点，phi(t)  | 
|  hamiltonian.drivingFields[].phase.time\$1series.values  |  List[Decimal]  |  驱动相位的值，phi(t)  | 
|  hamiltonian.drivingFields[].phase.pattern  |  str  |  驱动相位的空间规律，phi(t)；必须是“均匀的”  | 
|  hamiltonian.drivingFields[].detuning.time\$1series.times  |  List[Decimal]  |  驱动的时间点，delta\$1Global(t)  | 
|  hamiltonian.drivingFields[].detuning.time\$1series.values  |  List[Decimal]  |  驱动失谐值，delta\$1Global(t)  | 
|  hamiltonian.drivingFields[].detuning.pattern  |  str  |  驾驶失谐的空间规律，delta\$1Global(t)；必须是“均匀的”  | 
|  hamiltonian.localDetuning[].magnitude.time\$1series.times  |  List[Decimal]  |  局部失谐振幅的时变因子的时间点，delta\$1Local(t)  | 
|  hamiltonian.localDetuning[].magnitude.time\$1series.values  |  List[Decimal]  |  局部失谐振幅的时变因子值，delta\$1Local(t)  | 
|  hamiltonian.localDetuning[].magnitude.pattern  |  List[Decimal]  |  局部失谐振幅的站点相关因子 h\$1k（数值对应于 setup.ahs\$1register.sites 中的站点）  | 


**元数据字段**  

| 程序字段 | 类型 | 描述 | 
| --- | --- | --- | 
|  braketSchemaHeader.name  |  str  |  架构的名称；必须是“braket.ir.ahs.program”  | 
|  braketSchemaHeader. 版本  |  str  |  架构版本  | 

## Braket AHS 任务结果架构
<a name="braket-quera-ahs-task-result-schema"></a>

 **braket.tasks.analog\$1hamiltonian\$1simulation\$1quantum\$1task\$1result AnalogHamiltonianSimulationQuantumTaskResult**（示例）

```
AnalogHamiltonianSimulationQuantumTaskResult(
    task_metadata=TaskMetadata(
        braketSchemaHeader=BraketSchemaHeader(
            name='braket.task_result.task_metadata',
            version='1'
        ),
        id='arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef',
        shots=2,
        deviceId='arn:aws:braket:us-east-1::device/qpu/quera/Aquila',
        deviceParameters=None,
        createdAt='2022-10-25T20:59:10.788Z',
        endedAt='2022-10-25T21:00:58.218Z',
        status='COMPLETED',
        failureReason=None
    ),
    measurements=[
        ShotResult(
            status=<AnalogHamiltonianSimulationShotStatus.SUCCESS: 'Success'>,

            pre_sequence=array([1, 1, 1, 1]),
            post_sequence=array([0, 1, 1, 1])
        ),

        ShotResult(
            status=<AnalogHamiltonianSimulationShotStatus.SUCCESS: 'Success'>,

            pre_sequence=array([1, 1, 0, 1]),
            post_sequence=array([1, 0, 0, 0])
        )
    ]
)
```

 **JSON**（示例）

```
{
    "braketSchemaHeader": {
        "name": "braket.task_result.analog_hamiltonian_simulation_task_result",
        "version": "1"
    },
    "taskMetadata": {
        "braketSchemaHeader": {
            "name": "braket.task_result.task_metadata",
            "version": "1"
        },
        "id": "arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef",
        "shots": 2,
        "deviceId": "arn:aws:braket:us-east-1::device/qpu/quera/Aquila",

        "createdAt": "2022-10-25T20:59:10.788Z",
        "endedAt": "2022-10-25T21:00:58.218Z",
        "status": "COMPLETED"

    },
    "measurements": [
        {
            "shotMetadata": {"shotStatus": "Success"},
            "shotResult": {
                "preSequence": [1, 1, 1, 1],
                "postSequence": [0, 1, 1, 1]
            }
        },
        {
            "shotMetadata": {"shotStatus": "Success"},
            "shotResult": {
                "preSequence": [1, 1, 0, 1],
                "postSequence": [1, 0, 0, 0]
            }
        }
    ],
    "additionalMetadata": {
        "action": {...}
        "queraMetadata": {
            "braketSchemaHeader": {
                "name": "braket.task_result.quera_metadata",
                "version": "1"
            },
            "numSuccessfulShots": 100
        }
    }
}
```


**主要字段**  

| 任务结果字段 | 类型 | 描述 | 
| --- | --- | --- | 
|  measurements[].shotResult.preSequence  |  List[int]  |  每次拍摄的预序测量位（每个原子位点一个）：如果位点为空，则为 0，如果位点已填满，则为 1，在运行量子进化的脉冲序列之前测量  | 
|  measurements[].shotResult.postSequence  |  List[int]  |  每次拍摄的序列后测量位：如果原子处于里德伯格状态或位点为空，则为 0；如果原子处于基态，则为 1，在运行量子进化的脉冲序列末尾测量  | 


**元数据字段**  

| 任务结果字段 | 类型 | 描述 | 
| --- | --- | --- | 
|  braketSchemaHeader.name  |  str  |  架构名称；必须是“braket.task\$1result.analog\$1hamiltonian\$1simulation\$1task\$1result.result”  | 
|  braketSchemaHeader. 版本  |  str  |  架构版本  | 
|  任务元数据。 braketSchemaHeader.name  |  str  |  架构名称；必须是“braket.task\$1result.task\$1metadata”  | 
|  任务元数据。 braketSchemaHeader. 版本  |  str  |  架构版本  | 
|  taskmetadata.id  |  str  |  量子任务 ID。对于 AWS 量子任务，这是量子任务 ARN。  | 
|  taskMetadata.shots  |  int  |  量子任务的拍摄次数  | 
|  taskmetadata.shots.deviceId  |  str  |  运行量子任务的设备的 ID。对于 AWS 设备，这是设备 ARN。  | 
|  taskMetadata.shots.createdAt  |  str  |  创建的时间戳；格式必须采用 ISO-8 RFC3339 601/ 字符串格式：mm: ss.sssz。 YYYY-MM-DDTHH默认值：无。  | 
|  taskMetadata.shots.endedAt  |  str  |  量子任务结束的时间戳；格式必须采用 ISO-8 RFC3339 601/ 字符串格式：mm: ss.sssz。 YYYY-MM-DDTHH默认值：无。  | 
|  taskMetadata.shots.status  |  str  |  量子任务的状态（已创建、已排队、正在运行、已完成、失败）。默认值：无。  | 
|  taskMetadata.shots.failureReason  |  str  |  量子任务失败的原因。默认值：无。  | 
|  additionalMetadata.action  |  braket.ir.ahs.program\$1v1.Program  |  （请参阅 [Braket AHS 程序架构](#braket-quera-ahs-program-schema)部分）  | 
|  其他元数据.action。 braketSchemaHeader.querametadata.name  |  str  |  架构名称；必须是“braket.task\$1result.quera\$1metadata”  | 
|  其他元数据.action。 braketSchemaHeader.querametaData.version  |  str  |  架构版本  | 
|  其他元数据.action。 numSuccessfulShots  |  int  |  完全成功拍摄的次数；必须等于请求的拍摄次数  | 
|  measurements[].shotMetadata.shotStatus  |  int  |  拍摄状态（成功、部分成功、失败）；必须为“成功”  | 

## QuEra 设备属性架构
<a name="braket-quera-device-properties-schema"></a>

 **braket.device\$1schema.quera.quera\$1device\$1capabilities\$1v1。 QueraDeviceCapabilities**（示例）

```
QueraDeviceCapabilities(
    service=DeviceServiceProperties(
        braketSchemaHeader=BraketSchemaHeader(
            name='braket.device_schema.device_service_properties', 
            version='1'
            ), 
            executionWindows=[
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.MONDAY: 'Monday'>, 
                    windowStartHour=datetime.time(1, 0), 
                    windowEndHour=datetime.time(23, 59, 59)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.TUESDAY: 'Tuesday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(12, 0)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.WEDNESDAY: 'Wednesday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(12, 0)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.FRIDAY: 'Friday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(23, 59, 59)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.SATURDAY: 'Saturday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(23, 59, 59)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.SUNDAY: 'Sunday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(12, 0)
                )
            ], 
            shotsRange=(1, 1000), 
            deviceCost=DeviceCost(
                price=0.01, 
                unit='shot'
            ), 
            deviceDocumentation=
                DeviceDocumentation(
                    imageUrl='https://a.b.cdn.console.awsstatic.com/59534b58c709fc239521ef866db9ea3f1aba73ad3ebcf60c23914ad8c5c5c878/a6cfc6fca26cf1c2e1c6.png', 
                    summary='Analog quantum processor based on neutral atom arrays', 
                    externalDocumentationUrl='https://www.quera.com/aquila'
                ), 
                deviceLocation='Boston, USA', 
                updatedAt=datetime.datetime(2024, 1, 22, 12, 0, tzinfo=datetime.timezone.utc), 
                getTaskPollIntervalMillis=None
    ), 
    action={
        <DeviceActionType.AHS: 'braket.ir.ahs.program'>: DeviceActionProperties(
                version=['1'], 
                actionType=<DeviceActionType.AHS: 'braket.ir.ahs.program'>
            )
    }, 
    deviceParameters={}, 
    braketSchemaHeader=BraketSchemaHeader(
        name='braket.device_schema.quera.quera_device_capabilities', 
        version='1'
    ), 
    paradigm=QueraAhsParadigmProperties(
        ...
        # See https://github.com/amazon-braket/amazon-braket-schemas-python/blob/main/src/braket/device_schema/quera/quera_ahs_paradigm_properties_v1.py
        ...
    )  
)
```

 **JSON**（示例）

```
{
    "service": {
        "braketSchemaHeader": {
            "name": "braket.device_schema.device_service_properties",
            "version": "1"
        },
        "executionWindows": [
            {
                "executionDay": "Monday",
                "windowStartHour": "01:00:00",
                "windowEndHour": "23:59:59"
            },
            {
                "executionDay": "Tuesday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "12:00:00"
            },
            {
                "executionDay": "Wednesday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "12:00:00"
            },
            {
                "executionDay": "Friday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "23:59:59"
            },
            {
                "executionDay": "Saturday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "23:59:59"
            },
            {
                "executionDay": "Sunday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "12:00:00"
            }
        ],
        "shotsRange": [
            1,
            1000
        ],
        "deviceCost": {
            "price": 0.01,
            "unit": "shot"
        },
        "deviceDocumentation": {
            "imageUrl": "https://a.b.cdn.console.awsstatic.com/59534b58c709fc239521ef866db9ea3f1aba73ad3ebcf60c23914ad8c5c5c878/a6cfc6fca26cf1c2e1c6.png",
            "summary": "Analog quantum processor based on neutral atom arrays",
            "externalDocumentationUrl": "https://www.quera.com/aquila"
        },
        "deviceLocation": "Boston, USA",
        "updatedAt": "2024-01-22T12:00:00+00:00"
    },
    "action": {
        "braket.ir.ahs.program": {
            "version": [
                "1"
            ],
            "actionType": "braket.ir.ahs.program"
        }
    },
    "deviceParameters": {},
    "braketSchemaHeader": {
        "name": "braket.device_schema.quera.quera_device_capabilities",
        "version": "1"
    },
    "paradigm": {
        ...
        # See Aquila device page > "Calibration" tab > "JSON" page
        ...
    }
}
```


**服务属性字段**  

| 服务属性字段 | 类型 | 描述 | 
| --- | --- | --- | 
|  service.executionWindows[].executionDay  |  ExecutionDay  |  执行窗口的天数；必须是 “每天”、“工作日”、“周末”、“星期一”、“星期二”、“星期三”、“星期四”、“星期五”、“星期六”或“星期日”  | 
|  Service.executionWindows []。 windowStartHour  |  datetime.time  |  执行窗口开始时间的 UTC 24 小时格式  | 
|  Service.executionWindows []。 windowEndHour  |  datetime.time  |  执行窗口结束时间的 UTC 24 小时格式  | 
|  service.qpu\$1Capabilities.service.shotsRange  |  Tuple[int, int]  |  设备的最小和最大拍摄次数  | 
|  service.qpu\$1capabilities.service.deviceCost.price  |  浮点数  |  设备价格（以美元计）  | 
|  service.qpu\$1capabilities.service.deviceCost.unit  |  str  |  计费单位，例如：“分钟”、“小时”、“拍摄”、“任务”  | 


**元数据字段**  

| 元数据字段 | 类型 | 描述 | 
| --- | --- | --- | 
|  action[].version  |  str  |  AHS 程序架构的版本  | 
|  action[].actionType  |  ActionType  |  AHS 程序架构名称；必须是“braket.ir.ahs.program”  | 
|  服务。 braketSchemaHeader.name  |  str  |  架构的名称；必须是“braket.device\$1schema.device\$1service\$1properties”  | 
|  服务。 braketSchemaHeader. 版本  |  str  |  架构版本  | 
|  service.deviceDocumentation.imageUrl  |  str  |  设备图片的 URL  | 
|  service.deviceDocumentation.summary  |  str  |  设备的简要描述  | 
|  服务设备文档。 externalDocumentationUrl  |  str  |  外部文档 URL  | 
|  service.deviceLocation  |  str  |  设备的地理位置  | 
|  service.updatedAt  |  datetime  |  上次更新设备属性的时间  | 

# 使用 AWS Boto3
<a name="braket-using-boto3"></a>

Boto3 是 Python 的 AWS 软件开发工具包。使用 Boto3，Python 开发者可以创建、配置和管理 AWS 服务，比如 Amazon Braket。Boto3 提供了面向对象的 API，以及对 Amazon Braket 的低级别访问。

按照 [Boto3 快速入门指南](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html)中的说明进行操作，了解如何安装和配置 Boto3。

Boto3 提供了与 Amazon Braket Python SDK 配合使用的核心功能，可帮助您配置和运行量子任务。Python 客户总是需要安装 Boto3，因为这是核心实现。如果您想使用其他辅助方法，则还需要安装 Amazon Braket 软件开发工具包。

例如，当您调用 `CreateQuantumTask` 时，Amazon Braket SDK 会将请求提交给 Boto3，然后由 Boto3 调用 AWS API。

**Topics**
+ [打开 Amazon Braket Boto3 客户端](braket-using-boto3-client.md)
+ [为 Boto3 和 Braket SDK AWS CLI 配置配置文件](braket-using-boto3-profiles.md)

# 打开 Amazon Braket Boto3 客户端
<a name="braket-using-boto3-client"></a>

要实现 Boto3 与 Amazon Braket 的配合使用，您必须导入 Boto3，然后定义用于连接 Amazon Braket API 的客户端。在以下示例中，Boto3客户端名为 `braket`。

```
import boto3
import botocore

braket = boto3.client("braket")
```

**注意**  
支@@ [架支撑 IPv6](https://docs.aws.amazon.com/vpc/latest/userguide/aws-ipv6-support.html)。如果您使用的是 IPv6仅限网络或希望确保您的工作负载使用 IPv6 流量，请使用双栈[和 FIPS 端点指南中概述的双栈](https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoints.html)端点。

既然您已经建立了 `braket` 客户端，就可以通过 Amazon Braket 服务提出请求和处理回复了。您可以在 [API 参考](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/braket.html)中获取有关请求和响应数据的更多详细信息。

**Topics**
+ [搜索设备](#braket-using-boto3-example-search-devices)
+ [检索设备](#braket-using-boto3-example-retrieve-devices)
+ [创建量子任务](#braket-using-boto3-example-create-task)
+ [检索量子任务](#braket-using-boto3-example-retrieve-task)
+ [搜索量子任务](#braket-using-boto3-example-search-tasks)
+ [取消量子任务](#braket-using-boto3-example-cancel-task)

## 搜索设备
<a name="braket-using-boto3-example-search-devices"></a>
+  `search_devices(**kwargs)` 

使用指定的过滤器搜索设备。

```
# Pass search filters and optional parameters when sending the
# request and capture the response
response = braket.search_devices(filters=[{
    'name': 'deviceArn',
    'values': ['arn:aws:braket:::device/quantum-simulator/amazon/sv1']
}], maxResults=10)

print(f"Found {len(response['devices'])} devices")

for i in range(len(response['devices'])):
    device = response['devices'][i]
    print(device['deviceArn'])
```

## 检索设备
<a name="braket-using-boto3-example-retrieve-devices"></a>
+  `get_device(deviceArn)` 

检索在 Amazon Braket 中可用的设备。

```
# Pass the device ARN when sending the request and capture the repsonse
response = braket.get_device(deviceArn='arn:aws:braket:::device/quantum-simulator/amazon/sv1')

print(f"Device {response['deviceName']} is {response['deviceStatus']}")
```

## 创建量子任务
<a name="braket-using-boto3-example-create-task"></a>
+  `create_quantum_task(**kwargs)` 

创建量子任务。

```
# Create parameters to pass into create_quantum_task()
kwargs = {
    # Create a Bell pair
    'action': '{"braketSchemaHeader": {"name": "braket.ir.jaqcd.program", "version": "1"}, "results": [], "basis_rotation_instructions": [], "instructions": [{"type": "h", "target": 0}, {"type": "cnot", "control": 0, "target": 1}]}',
    # Specify the SV1 Device ARN
    'deviceArn': 'arn:aws:braket:::device/quantum-simulator/amazon/sv1',
    # Specify 2 qubits for the Bell pair
    'deviceParameters': '{"braketSchemaHeader": {"name": "braket.device_schema.simulators.gate_model_simulator_device_parameters", "version": "1"}, "paradigmParameters": {"braketSchemaHeader": {"name": "braket.device_schema.gate_model_parameters", "version": "1"}, "qubitCount": 2}}',
    # Specify where results should be placed when the quantum task completes.
    # You must ensure the S3 Bucket exists before calling create_quantum_task()
    'outputS3Bucket': 'amazon-braket-examples',
    'outputS3KeyPrefix': 'boto-examples',
    # Specify number of shots for the quantum task
    'shots': 100
}

# Send the request and capture the response
response = braket.create_quantum_task(**kwargs)

print(f"Quantum task {response['quantumTaskArn']} created")
```

## 检索量子任务
<a name="braket-using-boto3-example-retrieve-task"></a>
+  `get_quantum_task(quantumTaskArn)` 

检索指定的量子任务。

```
# Pass the quantum task ARN when sending the request and capture the response
response = braket.get_quantum_task(quantumTaskArn='arn:aws:braket:us-west-1:123456789012:quantum-task/ce78c429-cef5-45f2-88da-123456789012')

print(response['status'])
```

## 搜索量子任务
<a name="braket-using-boto3-example-search-tasks"></a>
+  `search_quantum_tasks(**kwargs)` 

搜索与指定过滤值匹配的量子任务。

```
# Pass search filters and optional parameters when sending the
# request and capture the response
response = braket.search_quantum_tasks(filters=[{
    'name': 'deviceArn',
    'operator': 'EQUAL',
    'values': ['arn:aws:braket:::device/quantum-simulator/amazon/sv1']
}], maxResults=25)

print(f"Found {len(response['quantumTasks'])} quantum tasks")

for n in range(len(response['quantumTasks'])):
    task = response['quantumTasks'][n]
    print(f"Quantum task {task['quantumTaskArn']} for {task['deviceArn']} is {task['status']}")
```

## 取消量子任务
<a name="braket-using-boto3-example-cancel-task"></a>
+  `cancel_quantum_task(quantumTaskArn)` 

取消指定的量子任务。

```
# Pass the quantum task ARN when sending the request and capture the response
response = braket.cancel_quantum_task(quantumTaskArn='arn:aws:braket:us-west-1:123456789012:quantum-task/ce78c429-cef5-45f2-88da-123456789012')

print(f"Quantum task {response['quantumTaskArn']} is {response['cancellationStatus']}")
```

# 为 Boto3 和 Braket SDK AWS CLI 配置配置文件
<a name="braket-using-boto3-profiles"></a>

除非您另有明确说明，否则 Amazon Braket SDK 依赖于默认 AWS CLI 证书。我们建议您在托管 Amazon Braket Notebook 上运行时保留默认设置，因为您必须提供有权启动 Notebook 实例的 IAM 角色。

或者，如果您在本地运行代码（例如在 Amazon EC2 实例上），则可以建立命名 AWS CLI 配置文件。您可以为每个配置文件指定不同的权限集，而不必定期覆盖默认配置文件。

本节简要说明了如何配置这样的 CLI `profile` 以及如何将该配置文件合并到 Amazon Braket 中，以便使用该配置文件的权限进行 API 调用。

**Topics**
+ [步骤 1：配置本地 C AWS LI `profile`](#braket-using-boto3-profiles-step-1)
+ [步骤 2：建立 Boto3 会话对象](#braket-using-boto3-profiles-step-2)
+ [第 3 步：将 Boto3 会话合并到 Braket 中 AwsSession](#braket-using-boto3-profiles-step-3)

## 步骤 1：配置本地 C AWS LI `profile`
<a name="braket-using-boto3-profiles-step-1"></a>

解释如何创建用户以及如何配置非默认配置文件已超出本文档的讨论范围。有关这些主题的更多信息，请参阅：
+  [入门](https://docs.aws.amazon.com/singlesignon/latest/userguide/getting-started.html) 
+  [配置 AWS CLI 要使用 AWS IAM Identity Center](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html) 

要使用 Amazon Braket，您必须向该用户以及相关的 CLI `profile` 提供必要的 Braket 权限。例如，您可以附加**AmazonBraketFullAccess**策略。

## 步骤 2：建立 Boto3 会话对象
<a name="braket-using-boto3-profiles-step-2"></a>

要建立 Boto3 会话对象，请使用以下代码示例。

```
from boto3 import Session

# Insert CLI profile name here
boto_sess = Session(profile_name=`profile`)
```

**注意**  
如果预期的 API 调用具有基于区域的限制，而这些限制与您的 `profile` 默认区域不一致，则可以为 Boto3 会话指定一个区域，如以下示例所示。

```
# Insert CLI profile name _and_ region
boto_sess = Session(profile_name=`profile`, region_name=`region`)
```

对于指定为的参数`region`，请替换一个与 Amazon Braket 可用的值相对应的值`us-east-1`，例如`us-west-1`、等。 AWS 区域 

## 第 3 步：将 Boto3 会话合并到 Braket 中 AwsSession
<a name="braket-using-boto3-profiles-step-3"></a>

以下示例说明如何初始化 Boto3 Braket 会话并在该会话中实例化设备。

```
from braket.aws import AwsSession, AwsDevice

# Initialize Braket session with Boto3 Session credentials
aws_session = AwsSession(boto_session=boto_sess)

# Instantiate any Braket QPU device with the previously initiated AwsSession
sim_arn = 'arn:aws:braket:::device/quantum-simulator/amazon/sv1'
device = AwsDevice(sim_arn, aws_session=aws_session)
```

设置完成后，您可以向该实例化的 `AwsDevice` 对象提交量子任务（例如，通过调用 `device.run(…​)` 命令）。该设备进行的所有 API 调用都可以使用与您之前指定为 `profile` 的 CLI 配置文件关联的 IAM 凭证。