

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

# 构建您的第一个电路
<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})
```