# Qiskit：设备发现、Target 与设备专属选项

想知道“这台机器支持哪些门”“能不能固定物理比特”“mapping 应该怎么设置”，先取得一个 backend。本页从选择设备开始，分别演示读取能力、检查 Qiskit Target、查询可选参数，以及把这些参数用于一次线路准备。

在 Qiskit 中，你提供 QuantumCircuit，插件负责转换成所选设备支持的 OpenQASM。capabilities 描述设备能力，configuration_schema 描述可设置的选项，options 保存后续任务的默认值，target 供本地编译使用。

钱包在 QuantumSourceService(..., currency="FULL") 中选择，省略时默认 OPEN。service.currency 可只读查看选择，新准备的实验使用该钱包。

| 你的问题 | 直接阅读 |
| --- | --- |
| 有哪些可选设备？如何得到 backend？ | 第 1 节：发现并选择设备 |
| 门、物理连接、timing / noise / features 在哪里？ | 第 3、4、6 节：设备能力和 Target |
| 所选机器有哪些额外参数？ | 第 5 节：读取 configuration_schema |
| 如何设置默认值或只覆盖一次？ | 第 7、8 节：Options、配置字典、动态关键字 |
| 如何坚持使用指定物理位置？ | 第 9 节：physical_qubits 与 initial_layout |

先完成连接章节的 API 地址和平台 SDK 凭据配置。以下代码在同一会话中运行：第 1–6 节查询设备，第 7 节设置默认值，第 8 节准备报价，第 9 节进行本地编译。

选定设备后，使用它当前公布的门、物理连接和参数说明配置实验。下面按用途分别读取所需字段。

- [配置平台连接和认证](connection.html)
- [只想先跑一个线路：Qiskit 入门](qiskit.html)

## 1. 发现并选择设备

用 service.backends() 查看当前平台目录。online=True 将列表缩小到在线、且未明确停止接收任务的设备；下面只做目录查询。

```python
import os
from pprint import pprint
from quantum_source_qiskit import QuantumSourceService

service = QuantumSourceService(
    base_url=os.environ["QUANTUM_SOURCE_API_URL"],
)
devices = service.backends(online=True)
print(devices)
```

devices 是兼容 list 的字典列表，print 和 Notebook 显示五列摘要。选择其中的 short_code，传给 return_backend 创建设备对象。

| 列表字段 | 用途 |
| --- | --- |
| short_code | 选择 backend 时使用的设备标识 |
| type / num_qubits | 设备类型和目录公布的量子比特数 |
| status | 当前平台目录中的设备状态 |
| platform_active_tasks | 全平台在该设备尚未确认终态的任务总数 |

可用 name、device_type、vendor_id、min_num_qubits 缩小结果。name 对名称或 short_code 做包含筛选，忽略大小写；limit 设置每页条数，方法会自动读取全部页。

```python
# 查询平台目录中的在线真机。
online_qpus = service.backends(online=True, device_type="QPU", min_num_qubits=2)
print(online_qpus)
```

```python
backend_code = input("填写列表中的设备 short_code：").strip()
backend = service.return_backend(backend_code)
print(type(backend).__name__)
print("设备：", backend.name)
print("线路导出格式：", backend.export_format)
```

return_backend 返回遵循 Qiskit BackendV2 接口的 QuantumSourceBackend。创建时从平台目录构建能力、schema、Options 与 Target，随后通过这些属性读取该对象保存的数据。export_format 显示插件选择的线路导出格式。

## 2. 选择合适的查询对象

同一台机器的信息按用途放在不同对象中。普通提交先看能力和可选参数；准备做客户端物理编译时，再看 Target。

| 我要知道什么 | 查询入口 | 实际返回形式 |
| --- | --- | --- |
| 平台设备记录、输入格式、公开配置 schema | service.scheduler.get_backend_class(backend_code) | BackendClassRead；通过属性访问 |
| 门、可用物理编号、连接、限制、可选 timing / noise / features | backend.capabilities | BackendCapabilities；可使用 to_dict()，但通常按需读取字段 |
| 当前设备允许用户设置哪些专属任务选项 | backend.configuration_schema | dict；properties 按名称描述 type、enum、default 等 |
| 当前对象后续任务的默认选项 | backend.options | qiskit.providers.Options |
| Qiskit 本地编译采用的门及其放置规则 | backend.target | qiskit.transpiler.Target |

需要读取设备记录中的状态、格式和 schema 时，使用 scheduler.get_backend_class，返回值为 BackendClassRead。

```python
details = service.scheduler.get_backend_class(backend_code)
pprint({
    "short_code": details.short_code,
    "type": details.type,
    "status": details.status,
    "supported_formats": list(details.supported_formats),
    "configuration_schema": dict(details.configuration_schema),
})
```

这段代码显示设备支持的输入格式和任务配置 schema。配置可通过 backend.configuration_schema 或 details.configuration_schema 读取。

需要最新设备对象时，重新调用 service.return_backend。已有 backend 保留创建时的数据，prepared 保留准备实验时的配置和报价。

| 对象或调用 | 是否重新读取平台目录 | 后续使用方式 |
| --- | --- | --- |
| backend.capabilities / target / configuration_schema / options | 读取当前 Python 对象持有的数据 | 在一个实验中查看所选设备的能力和设置 |
| service.scheduler.get_backend_class(backend_code) | 发起一次设备详情查询 | 取得最新的平台详情记录 |
| service.return_backend(backend_code) | 重新构造设备对象时获取目录 | 新实验可使用新的 backend；已有 prepared 仍保留原报价和准备内容 |

## 3. 按需查询门、物理连接和执行限制

backend.capabilities 提供线路宽度、可用编号、输入格式、编译方式和执行限制。下面读取摘要，再分别查看输入门、原生门和物理连接。

```python
caps = backend.capabilities
pprint({
    "num_qubits": caps.num_qubits,
    "available_qubits": list(caps.available_qubits),
    "supported_formats": list(caps.supported_formats),
    "compilation_mode": caps.compilation_mode.value,
    "accepts_logical_circuit": caps.supports_execution_path("logical"),
    "accepts_compiled_physical_circuit": caps.supports_execution_path("physical"),
    "limits": caps.limits,
})

print("支持的输入门：")
pprint([gate.to_dict() for gate in caps.supported_ops])
print("原生门声明：")
pprint([gate.to_dict() for gate in caps.native_ops])
print("平台公布的拓扑边：", list(caps.topology.coupling_map))
print("边是否有方向：", caps.topology.is_directed)
print("Qiskit 实际编译连接：",
      None if backend.coupling_map is None else list(backend.coupling_map.get_edges()))
```

supports_execution_path 是只读查询，回答“平台是否明确声明接收这种线路”，返回 True 或 False。字典中的两个键是显示标签，用于打印查询结果；它们不参与任务配置。logical 对应逻辑线路，physical 对应已经确定物理位置并完成编译的线路。

| 查询结果 | 代表什么 | 怎样用于自己的线路 |
| --- | --- | --- |
| supports_execution_path("logical") 为 True | 平台明确声明支持逻辑线路提交 | 对未指定物理布局的 QuantumCircuit 调用 backend.prepare(qc, shots=...)；本源真机开启云端拓扑映射。 |
| supports_execution_path("physical") 为 True | 平台明确声明支持已编译物理线路提交 | 查看 Target 和可用物理位置，再用 physical_qubits 或 initial_layout 指定布局，详见第 9 节。 |

两个查询可以同时返回 True，分别提供两种工作方式。False 表示当前目录未明确声明支持，也可能是该项声明尚未提供；需要时重新获取 backend 或选择已声明支持的设备。调用这两个查询会保持 backend.options 和线路布局不变。

| 读到的内容 | 如何用于自己的线路 |
| --- | --- |
| supported_ops | 判断插件能够接收的输入门；输入门可能随后被分解 |
| native_ops | 查看平台收到的设备原生门声明 |
| available_qubits | 固定物理位置时可选的编号集合 |
| topology.coupling_map / is_directed | 查看平台公布的连接边及方向性 |
| limits | 查看设备已公布的 shots、批次等限制 |
| compilation_mode | 查看设备的编译分工，例如由客户端或厂商执行编译 |
| supports_execution_path(...) | 读取平台对逻辑线路或已编译物理线路的接收声明 |

GateSpec.name 是门名，arity 是作用比特数，parameters 是参数名，qargs 给出可选的物理位置组合。输入门可经过分解，原生门描述设备直接执行的指令，client_instructions 用于构建客户端物理 Target。

num_qubits 表示线路宽度，available_qubits 给出可用物理编号。物理编号可能不连续，线路宽度也可能大于可用编号的数量。固定布局时结合可用编号、门位置和直接连接选择物理比特。

caps.topology.coupling_map 是平台公布的连接图；backend.coupling_map 是 Qiskit 编译使用的连接图，会结合 Target 的指令位置、方向及可用编号构建。模拟器缺少连接图时可使用全连接模型，真机使用设备公布的连接信息。

## 4. timing、noise、features 怎样查询，空值怎样解释

时序、噪声和 reset 等功能可通过能力对象的可选字段与 backend 查询方法了解，用于选择设备或编译线路。

```python
pprint({
    "timing": dict(caps.timing),
    "noise": dict(caps.noise),
    "features": sorted(caps.features),
    "reset": backend.allows_reset(),
    "mid_circuit_measure": backend.allows_mid_circuit_measure(),
    "dynamic_circuits": backend.allows_dynamic_circuits(),
    "physical_qubits": backend.allows_physical_qubits(),
    "custom_gates": backend.allows_custom_gates(),
})
```

| 字段或现象 | 含义 | 使用方式 |
| --- | --- | --- |
| timing 为 {} 或某个 duration 为 None | 当前数据尚未提供对应时序 | 提供 duration 时按秒读取门耗时 |
| noise 为 {} 或某个 error 为 None | 当前数据尚未提供对应错误率 | 有值时用于了解设备噪声 |
| features 为 []，allows_reset() 为 False | 当前客户端支持范围中未声明 reset | 按当前设备已声明的功能编写线路 |
| allows_physical_qubits() 为 True | 有客户端 Target 或 physical_qubits 功能声明 | 继续查看可用编号和门位置 |
| supports_execution_path("physical") 为 True | 平台开放物理线路路径 | 结合 Target 与直接连接设置布局 |

timing、noise、features 展示当前设备已提供的信息。设置任务选项时，使用 configuration_schema 中列出的参数及其允许值。

## 5. 查询设备专属选项

要让用户选择本源 mapping 或其他设备参数，先读取所选 backend 的 configuration_schema。properties 是选项菜单；循环打印每个字段的类型、候选值、默认值和说明，就能据此构造 Notebook 选择项或网页表单。

```python
schema = backend.configuration_schema
properties = schema.get("properties", {})
print("可设置的设备选项：", list(properties))
for option_name, definition in properties.items():
    print(option_name)
    pprint({key: definition[key]
            for key in ("title", "description", "type", "enum", "const", "default", "minimum", "maximum")
            if key in definition})

print("当前 Options：", backend.options)
```

| schema 中的字段 | 你应该怎样使用 |
| --- | --- |
| title / description | 查看选项名称和设备功能说明 |
| type | 决定输入类型，例如 boolean 对应 Python True / False |
| enum / const | enum 给出允许候选值；const 表示只能使用该固定值 |
| default | 设备声明的默认值；带默认的设备选项会加入 backend.options |
| minimum / maximum | 数值型选项的上下界 |

schema 列出可选择的参数，Options 保存当前 backend 的默认值。选择 backend 后，按 schema 通过 set_options、configuration_data 或单次关键字配置设备选项。

本源设备的 schema 可提供 mapping、optimization、amend 等选项。mapping 控制云端拓扑映射，将逻辑比特及门操作适配到芯片的物理连接关系；optimization 控制云端线路优化。每项的功能说明、允许值和默认值可在 description、enum、default 中查看。本地编译级别则在 backend.transpile 中通过 optimization_level 设置。

schema 中带 default 的设备字段会加入 Options。使用 set_options 设置这些字段的后续默认；schema 中没有 default 的字段可通过单次关键字或 configuration_data 设置。完整选项列表以 schema.properties 为准。

```python
# 从当前设备的 schema 中读取 mapping 说明。
if "mapping" in properties:
    pprint(properties["mapping"])
    print("是否进入 Options：", hasattr(backend.options, "mapping"))
else:
    print("当前设备没有声明 mapping 选项。")
```

这段代码专门查询 mapping。设备提供该选项时，读取它的类型和允许值，然后选择下一节中的设置方式。

## 6. 查询 Qiskit Target：指令、位置与可选时序属性

Target 是给 Qiskit 编译器用的结构。operation_names 告诉你它表示哪些指令；target[门名] 将允许的物理位置映射到 InstructionProperties。下例先打印摘要，再查看每个门的前五个放置位置。

```python
target = backend.target
print("Target 类型：", type(target).__name__)
print("Target 宽度：", target.num_qubits)
print("Target dt（秒）：", target.dt)
print("Target 指令：", sorted(target.operation_names))
print("是否具备明确的客户端物理 Target：", caps.has_client_target)

# 查看设备已公布的指令位置。
if caps.has_client_target:
    for operation_name in sorted(target.operation_names):
        placements = target[operation_name]
        sample = list(placements.items())[:5]
        print(operation_name, "位置示例：", [qargs for qargs, _ in sample])
        for qargs, instruction_properties in sample:
            print("  ", qargs,
                  "duration(s)=", getattr(instruction_properties, "duration", None),
                  "error=", getattr(instruction_properties, "error", None))
```

InstructionProperties 提供某个门在指定位置上的 duration 和 error，缺少数据时为 None。duration 的单位是秒，dt 是独立的时间步长。这些属性来自能力数据中的 timing.durations 和 noise.gate_error。

compilation_mode 为 provider_compile 时，Target 用作逻辑入口，目前包含 measure；设备输入门和原生门分别通过 caps.supported_ops、caps.native_ops 查看，由厂商完成物理编译。平台提供客户端物理 Target 时，可采用固定物理布局流程。

用 Target.operation_names 查看指令名，用 target["cz"] 查看 CZ 门的位置和属性，用 instruction_supported(...) 检查指定放置。时序与噪声数据也可通过 caps.timing、caps.noise 读取。

客户端 Target 的指令位置来自 client_compilation.instructions 中的 qargs。其他编译方式结合原生门、输入门、可用编号和拓扑构建可用信息。只需要 Target 时，可调用 service.return_target(backend_code)。

## 7. 设置选项的三种方式与实际优先级

设备选项有三种设置方式：set_options 设置后续默认，configuration_data 为当前任务传入配置字典，直接关键字设置当前任务的单个选项。下面用 mapping 演示，并根据 schema 读取其允许值。

```python
mapping_definition = properties.get("mapping")
mapping_true_allowed = (
    isinstance(mapping_definition, dict)
    and mapping_definition.get("type") == "boolean"
    and ("enum" not in mapping_definition or True in mapping_definition["enum"])
    and ("const" not in mapping_definition or mapping_definition["const"] is True)
)

# A. 设置当前 backend 对象的后续默认值；只改本机对象。
if mapping_true_allowed and hasattr(backend.options, "mapping"):
    backend.set_options(mapping=True)
    print("mapping 默认已设为：", backend.options.mapping)
else:
    print("请使用当前设备 schema 中列出的选项。")

# B、C 的单次写法见下一节；此处只准备一个扁平字典。
task_configuration = {"mapping": True} if mapping_true_allowed else {}
```

set_options(mapping=True) 返回 None，设置后的值可通过 backend.options.mapping 查看。task_configuration 保存本次任务的配置字典，下一节演示字典和直接关键字两种写法。

| 优先级：从高到低 | 入口 | 作用范围 |
| --- | --- | --- |
| 1 | backend.prepare(qc, mapping=True) 或 run 中相应动态关键字 | 仅本次调用；字段必须被当前设备 schema 声明 |
| 2 | 本次 configuration_data={"mapping": True} | 仅本次调用；字典保持扁平 |
| 3 | return_backend(..., config={"configuration_data": {...}}) | 构造时的默认任务配置 |
| 4 | backend.set_options(mapping=True) | 当前 backend 后续调用默认；字段必须已有 |
| 5 | 设备声明的路径默认值 | 前面均未指定时采用；逻辑和物理规则不同 |

构造配置中的 config.configuration_data 优先于 Options。同名字段按上表顺序选择；单次设置只作用于当前准备，后续实验继续使用 backend 默认值。已经准备的实验保留当时的配置。

设备布尔选项使用 Python True / False。参数名称、类型和候选值按照当前设备的 configuration_schema 填写。

## 8. 逻辑线路：启用本源云端拓扑映射

以 Bell 线路为例，qc 中的 0、1 是逻辑线。对提供 mapping 选项的本源真机，mapping=True 启用云端拓扑映射，使逻辑比特上的门操作适配芯片的连接关系。下面 B 使用通用字典，C 使用动态关键字，两者表达同一次任务的相同意图，选一个即可。prepare 返回准备对象及报价，不执行计算。

```python
from qiskit import QuantumCircuit

qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])

# B. 以扁平配置字典指定本次选项。
if mapping_true_allowed and caps.supports_execution_path("logical"):
    prepared = backend.prepare(
        qc,
        shots=128,
        configuration_data={"mapping": True},
    )
    pprint(prepared.quote.to_dict())
else:
    print("此设备不满足本节 mapping=True 的逻辑线路示例条件。")
```

configuration_data 填写本次需要设置的选项，其余项采用默认值。prepared.quote.to_dict() 展示这条线路的报价。

```python
# C. 替代 B：用匹配当前 schema 的动态关键字。
# 与 B 选择一种写法，准备并查看报价。
if mapping_true_allowed and caps.supports_execution_path("logical"):
    prepared = backend.prepare(qc, shots=128, mapping=True)
    pprint(prepared.quote.to_dict())
```

这里的 mapping 是云端编译中的拓扑映射开关：本源按芯片连接关系处理逻辑线路。指定本次实验使用哪些物理比特，则通过下一节的 physical_qubits 或 initial_layout 完成；物理编译完成后使用 mapping=False，保留已经确定的布局。

- [本源官方说明：QCloudOptions 与固定布局](https://github.com/OriginQ/pyqpanda3-skill/blob/main/resources/api/qcloud/service.md)
- [本源官方说明：编译与拓扑映射](https://github.com/OriginQ/QPanda3-doc/blob/main/tutorials/tutorial_06_quantum_circuit_transpiler/tutorial_root_quantum_circuit_transpiler.markdown)

## 9. 固定物理位置：设置布局并关闭设备映射

本节适用于 caps.supports_execution_path("physical") 和 caps.has_client_target 同时为 True 的设备：前者声明平台接收物理线路，后者提供本地物理编译所需的逐门位置数据。

使用 physical_qubits 或 initial_layout 将逻辑线分配到物理位置，选择其中一个入口即可。本例为两比特线路：从设备公布的可用编号和连接关系中选取两个位置，核对它们支持线路所需的门，再输入这两个物理编号。

```python
print("可用物理比特：", backend.available_qubits)
print("设备连接关系：", caps.topology.coupling_map)
physical_qubits = [
    int(value.strip())
    for value in input("输入两个已核对的物理比特编号（用逗号分隔）：").split(",")
]
if len(physical_qubits) != 2 or len(set(physical_qubits)) != 2:
    raise ValueError("请填写两个不同的物理比特编号。")
print("选中编号当前是否在可用集合：",
      set(physical_qubits).issubset(set(backend.available_qubits)))
print("是否声明物理路径：", caps.supports_execution_path("physical"))
print("是否有客户端物理 Target：", caps.has_client_target)
if caps.has_client_target:
    print("所选位置是否支持 CZ：",
          target.instruction_supported("cz", tuple(physical_qubits)))
```

选好可用位置后，固定物理 Bell 用 H、CZ、H 表达受控翻转。本地编译保留所选编号，双比特门使用直接连接的两个端点。

```python
physical_qc = QuantumCircuit(2, 2)
physical_qc.h(0)
physical_qc.h(1)
physical_qc.cz(0, 1)
physical_qc.h(1)
physical_qc.measure([0, 1], [0, 1])

# 清除本页前面为逻辑示例显式设置的选项默认。
# None 表示清除覆盖，恢复对应执行方式的默认值。
for option_name in ("mapping", "optimization"):
    if hasattr(backend.options, option_name):
        backend.set_options(**{option_name: None})

# 本地编译并检查布局。
physical = backend.transpile(
    physical_qc,
    initial_layout=physical_qubits,
    optimization_level=0,
)
print(physical.layout)
```

physical_qubits 的第一个编号对应逻辑线 0，第二个编号对应逻辑线 1。transpile 返回带布局的 QuantumCircuit，通过 physical.layout 查看分配。随后准备 physical 时，插件保持布局并关闭云端拓扑映射。

initial_layout 可替换为 physical_qubits。对原始线路直接指定布局，可用 backend.prepare(physical_qc, shots=128, physical_qubits=physical_qubits)；对已经带布局的 physical，使用 backend.prepare(physical, shots=128)。

固定物理方式使用 mapping=False、optimization=False。由设备默认值建立的 Options 会按物理方式自动选择对应值；如果之前显式设置过逻辑映射选项，先将 Options 中的覆盖设为 None，并使用适合固定布局的 configuration_data。

固定物理编译使用 optimization_level=0。本地逻辑编译可选择级别 0、1、2、3；厂商侧的 optimization 则是任务配置中的布尔选项。

## 可选：查看线路的 OpenQASM 导出内容

插件自动选择设备支持的 OpenQASM 版本，优先使用 qasm3，其次为 qasm2。通常直接调用 backend.prepare 即可；学习或调试时，可在本地查看导出的文本。

```python
from quantum_source_qiskit import export_circuit_to_qasm

print("本对象选定格式：", backend.export_format)
print("目录支持格式：", caps.supported_formats)
# 使用上面已经定义、没有未绑定参数的逻辑 qc。
qasm_payload = export_circuit_to_qasm(qc, backend.export_format)
print(type(qasm_payload).__name__)
print(qasm_payload.decode("utf-8"))
```

export_circuit_to_qasm 返回 UTF-8 bytes。传入 backend=backend 可同时检查该设备的输入约束；本地编译使用 backend.transpile。参数化线路可以先绑定参数，也可以通过 Sampler/Estimator 的 PUB 输入完成绑定。

- [参数绑定与原生结果：Sampler / Estimator](qiskit-primitives.html)

## 10. 查询结果速查

| 查询结果 | 如何继续使用 |
| --- | --- |
| schema 为空 | 通过 capabilities 查看门和拓扑，使用设备默认配置提交实验。 |
| schema 字段没有 default | 按该字段声明，通过单次关键字或 configuration_data 设置。 |
| 设备显示在线 | 选中设备，准备线路并查看报价。 |
| 查看可输入的逻辑门 | 使用 caps.supported_ops；编译时插件按支持能力转换。 |
| 读取时序与噪声 | 查看 caps.timing、caps.noise 中的实际值；None 表示尚未提供。 |
| 获取最新设备对象 | 重新调用 service.return_backend(backend_code)。 |
| 完成结果读取 | 调用 service.close() 释放客户端连接。 |

## 11. API 参考

Service、Backend、能力模型和编译接口的完整签名、参数及返回值统一收录在 API 参考中。

- [API 参考：Qiskit 插件](api.html#qiskit)
- [API 参考：设备能力](api.html#capabilities)

```python
# 完成所有查看与准备工作后关闭客户端。
service.close()
```

- [三种入口的能力查询总览](capabilities.html)
- [Qiskit 提交、Sampler 与 Estimator](qiskit.html)
- [Sampler 与 Estimator 深入用法](qiskit-primitives.html)
- [PennyLane 的设备专属能力](capabilities-pennylane.html)
- [Core 的设备专属能力](capabilities-core.html)

## 下载本页 Jupyter Notebook

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

[下载《设备、Options 与 Target》Notebook（.ipynb）](../../notebooks/sdk_user_guide_capabilities_qiskit.ipynb)
