# 编译与物理比特

提交逻辑线路时，保留逻辑比特编号，由设备端完成后续物理编译；实验需要固定物理比特时，先给线路指定布局。本页用两个独立例子说明这两种用法，并区分 Qiskit 的本地优化级别与本源的云端拓扑映射、线路优化开关。

| 你的目标 | 代码入口 | 得到什么 |
| --- | --- | --- |
| 提交逻辑线路，由设备端完成物理编译 | backend.prepare(circuit, shots=128) | 逻辑线路的准备对象和报价 |
| 先在本地转换逻辑门 | backend.transpile(circuit, optimization_level=2) | 没有物理布局的 QuantumCircuit |
| 固定所选物理编号 | backend.transpile(circuit, initial_layout=physical_qubits, optimization_level=0) | 带固定布局的新 QuantumCircuit |
| 使用自己的布局参数名称 | 将 initial_layout 换为 physical_qubits | 相同的固定位置入口；二者只传一个 |

物理线路示例先查询所选设备的可用编号、连接和门位置，再输入你选定的两个物理编号。transpile 完成本地编译，prepare 获取报价，confirm 确认执行。

## 1. 连接并读取当前设备

开始前完成安装与认证：安装 SDK 的 Qiskit 扩展，设置 QUANTUM_SOURCE_API_URL，并配置平台 SDK Key 文件或 Client ID / Client Secret。QUANTUM_SOURCE_BACKEND 填写设备列表返回的 short_code。下面各步骤在同一个 Python 会话中运行，共用 service、backend 和线路变量。

```python
import os
from qiskit import QuantumCircuit
from quantum_source_qiskit import QuantumSourceService

service = QuantumSourceService(
    base_url=os.environ["QUANTUM_SOURCE_API_URL"],
    currency="OPEN",  # 使用 FULL 时在首次准备前改为 "FULL"
)
devices = service.backends(online=True)
devices
```

```python
backend = service.return_backend(os.environ["QUANTUM_SOURCE_BACKEND"])
backend.available_qubits, backend.max_shots
```

```python
backend.configuration_schema, backend.options
```

本页后续例子共用这个 backend。configuration_schema 列出设备选项，options 保存后续提交的默认设置。物理位置通过 physical_qubits 或 initial_layout 指定。

configuration_schema 的 properties 描述当前设备可设置的参数、类型、允许值和默认值。按这些声明为所选设备配置任务。

## 2. 区分客户端编译与设备开关

| 参数 | 入口 | 含义与限制 |
| --- | --- | --- |
| optimization_level | backend.transpile(...) | 客户端 Qiskit 编译级别；逻辑线路允许整数 0、1、2、3，固定物理位置只允许 0。 |
| mapping | 声明支持时用于 prepare/run 或 configuration_data | 本源云端拓扑映射开关：将逻辑比特及门操作适配芯片连接关系；逻辑路径开启，已固定布局的物理路径关闭。 |
| optimization | 声明支持时用于 prepare/run 或 configuration_data | 设备布尔优化开关；与 optimization_level 独立，固定位置要求 False。 |
| amend | 声明支持时用于 prepare/run 或 configuration_data | 按设备公布的语义、允许值与默认值使用。 |
| shots | prepare/run 或 backend.set_options(...) | 每条线路的正整数采样次数，须符合当前设备限制。 |

设备布尔选项使用 Python True 或 False。optimization_level 在 backend.transpile 中设置；逻辑编译转换输入门，后续拓扑映射由设备端完成。mapping 控制这一映射过程，具体物理布局通过 physical_qubits 或 initial_layout 指定。

## 3. 默认值与单次覆盖

同一设备要反复使用相同 shots 时，先设一次默认即可。单次 prepare(circuit, shots=...) 仍可以覆盖它。

```python
backend.set_options(shots=128)
backend.options
```

带默认值的设备声明进入 Options。用 backend.set_options(...) 设置已有字段的后续默认；将设备选项设为 None 可清除显式覆盖，恢复相应路径的默认设置。已准备的实验保留原报价和选项。

设备选项优先级从高到低为：本次直接关键字、本次 configuration_data、创建 backend 时的 config.configuration_data、Options、逻辑或物理路径默认值。固定位置使用 mapping=False 和 optimization=False；从逻辑实验切换时，可先将 Options 中的显式覆盖设为 None。

例如，当前设备明确支持 optimization=False 时，可使用 backend.set_options(optimization=False) 设置后续默认；或只在一次准备中传 optimization=False；或用 configuration_data={"optimization": False}。三者是不同作用范围的写法。

## 4. 逻辑线路：先本地编译，再准备报价

先构造与入门页相同的 Bell 线路，再调用本项目 backend.transpile。它将输入门转换为当前路径能够接收的形式；这里没有指定物理位置。

```python
circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure([0, 1], [0, 1])
circuit.draw("text")
```

```python
logical = backend.transpile(circuit, optimization_level=2)
logical.layout
```

返回的 logical 是新的 QuantumCircuit。layout 为 None 表示线路保持逻辑编号，物理位置由后续设备映射确定。

optimization_level=2 设置本地门转换的优化级别；设备端的 optimization 则使用当前设备默认值或本次提交的设置。

```python
prepared = backend.prepare(logical, shots=128)
prepared.quote
```

若当前设备声明支持关闭设备优化，可将上一个准备单元替换为下面这一单元；一个实验只选择一种准备方式。configuration_data 使用扁平字典。

```python
prepared = backend.prepare(
    logical,
    shots=128,
    configuration_data={"optimization": False},
)
prepared.quote
```

接受报价后再单独确认；真机执行可能产生费用。

```python
job = prepared.confirm()
```

```python
result = job.result(timeout=300)
result.get_counts()
```

## 5. 固定物理位置：核对比特和直接连接

以下物理位置实验继续使用本页的 backend。通过 available_qubits、coupling_map 和 target 选择两个可用、直接连接且支持示例所需门的物理位置，然后在输入提示中填写这两个编号。

本节适用于 backend.capabilities.has_client_target 为 True 且支持 physical 路径的设备。provider_compile 模式由厂商完成物理编译，使用前面的逻辑线路流程。

- [查询完整能力与 Target 区别的具体代码](capabilities-qiskit.html#target)

```python
backend.available_qubits, backend.coupling_map
```

```python
backend.target
```

```python
physical_qubits = [
    int(value.strip())
    for value in input("输入两个已核对的物理比特编号（用逗号分隔）：").split(",")
]
if len(physical_qubits) != 2 or len(set(physical_qubits)) != 2:
    raise ValueError("请填写两个不同的物理比特编号。")
physical_circuit = QuantumCircuit(2, 2)
physical_circuit.h(0)
physical_circuit.h(1)
physical_circuit.cz(0, 1)
physical_circuit.h(1)
physical_circuit.measure([0, 1], [0, 1])
physical_circuit.draw("text")
```

physical_qubits 按顺序将逻辑线分配到物理位置。下面在本地编译并检查固定布局：保留选定编号，双比特门使用直接连接的端点。

```python
physical = backend.transpile(
    physical_circuit,
    physical_qubits=physical_qubits,
    optimization_level=0,
)
physical.layout
```

physical_qubits 中的第一个编号分配给逻辑线 0，第二个编号分配给逻辑线 1。通过 physical.layout 查看分配结果。

initial_layout 是等价的布局入口。选择这一写法时，使用原始的 physical_circuit 进行编译。

```python
physical = backend.transpile(
    physical_circuit,
    initial_layout=physical_qubits,
    optimization_level=0,
)
physical.layout
```

固定位置编译保持布局，并关闭设备映射和优化。先清除 Options 中这两个选项的显式覆盖，然后直接准备已经带布局的 physical。

```python
for option in ("mapping", "optimization"):
    if hasattr(backend.options, option):
        backend.set_options(**{option: None})

prepared_physical = backend.prepare(physical, shots=128)
prepared_physical.quote
```

核对物理实验报价后，单独确认并读取结果。

```python
physical_job = prepared_physical.confirm()
```

```python
physical_result = physical_job.result(timeout=300)
physical_result.get_counts()
```

也可将物理布局直接传给 backend.prepare 或 backend.run；Sampler / Estimator 的 prepare/run 也接受这两个入口。一次只选 physical_qubits 或 initial_layout，且线路的每个逻辑比特都需要明确分配。run 会默认自动确认报价并执行，因此可能产生费用。

## 支持范围与报错

本源逻辑线路开启映射，并按设备默认值或用户设置选择优化。固定物理线路关闭映射和设备优化，使用当前 Target 公布的门、物理位置与直接连接。

提交或查询报错时，阅读异常消息并保留 prepared 或 job，随后查询同一个实验。已经取得 job 时调用它的 status() 或 result(timeout=...)；提交结果待核实时调用 prepared.recover()。recover() 使用原提交信息，返回可等待任务句柄后即可继续调用 result(timeout=...)。仍返回回执时，稍后再次 recover()。等待超时后，任务继续保留，重新调用原 job.result(...) 即可继续等待。

## 配置入口速查

设备选项统一写入扁平的 configuration_data，或使用当前设备声明的单次关键字。钱包在 QuantumSourceService / SchedulerClient 构造时通过 currency="OPEN" 或 "FULL" 选择。prepared.quote.currency 可查看已准备实验的币种；换用新客户端后，已有 prepared 保留原报价。

## 下一步

- [分阶段的 Qiskit 入门](qiskit.html)
- [下载固定物理位置 Notebook（未执行）](../../notebooks/sdk_qiskit_physical_current.ipynb)
- [常用 API](api.html)

## 下载本页 Jupyter Notebook

收录本页 Python 示例与说明，便于在 Jupyter Notebook 中学习和运行；安装命令保留为说明。

[下载《编译与物理布局》Notebook（.ipynb）](../../notebooks/sdk_user_guide_compilation.ipynb)
