# Core SDK：发现设备与配置任务

用 Core SDK 列出设备、查询门集和连接关系，并为自己的 OpenQASM 程序设置设备选项。本章从查找设备开始，最后准备一条 Bell 线路的报价。

Core SDK 通过 Python 管理任务，上传的线路使用 OpenQASM。你可以沿章节逐步查询，也可以直接使用后面的完整示例。prepare_submission 完成上传和报价，确认执行的流程见 Core 主教程。

| 你想完成的操作 | 使用的入口 | 得到的内容 |
| --- | --- | --- |
| 找到设备标识 | list_backends(scheduler=scheduler) | 可用于后续选择的 short_code 列表 |
| 查看某台设备及可选配置 | scheduler.get_backend_class(backend_code) | BackendClassRead：目录字段与 configuration_schema |
| 读取门、拓扑、timing、noise、features | capabilities_from_backend(resource) | BackendCapabilities：便于 Python 使用的能力对象 |
| 把设备选项用于自己的程序 | JobSubmissionConfig(configuration_data={...}) | 本次任务的配置；再交给 prepare_submission 取得报价 |

## 开始前：创建客户端

先按连接与认证章节配置平台地址和 SDK Key。下面从 QUANTUM_SOURCE_API_URL 读取地址，SchedulerClient 自动读取已配置的凭据。使用 QUANTUM_SOURCE_SDK_KEY 指定密钥文件时，优先读取文件中的凭据。

```python
import os
from quantum_source_sdk import (
    SchedulerClient,
    JobSubmissionConfig,
    list_backends,
    get_capabilities,
    capabilities_from_backend,
)

scheduler = SchedulerClient(
    base_url=os.environ["QUANTUM_SOURCE_API_URL"],
)
```

SchedulerClient 是查询设备和准备任务的入口，base_url 填写平台 API 根地址。本章共用一个 scheduler，完成后调用 close() 关闭连接。

创建客户端时用 currency 选择钱包，默认 OPEN；需要 FULL 时加入 currency="FULL"。通过 scheduler.currency 查看当前选择，后续新准备的报价使用该币种。

## 列出设备

用 list_backends(scheduler=...) 获取设备标识列表。它自动读取目录中的全部分页，返回去重、排序后的 short_code 字符串。

```python
backend_codes = list_backends(scheduler=scheduler)
for code in backend_codes:
    print(code)

backend_code = input("复制要查询的设备 short_code：").strip()
resource = scheduler.get_backend_class(backend_code)
```

backend_codes 是 list[str]，每一项都是可用于选择设备的 short_code。将其中一项传给 get_backend_class 后，resource 就代表这台设备。input() 只是本教程让你选择设备的交互方式；在自己的程序里可以把 backend_code 直接设为目录中实际返回的标识。

### 按页读取设备属性

需要比较设备名称、类型和在线状态时，使用 scheduler.management 的分页目录接口。下面的代码依次读取全部页面。

cursor 标记下一页的位置，None 表示从第一页开始。每次读取后，将 page.pagination.next_cursor 传给下一次查询；其值为空时结束。只查看第一页时，调用 list_backend_classes(limit=100) 并读取 page.backend_classes。

```python
cursor = None
while True:
    page = scheduler.management.list_backend_classes(limit=100, cursor=cursor)
    for item in page.backend_classes:
        print(item.short_code, item.type, item.status, item.num_qubits,
              item.platform_active_tasks)
    cursor = page.pagination.next_cursor
    if not cursor:
        break
```

platform_active_tasks 是该设备在本平台已经接受、尚未确认完成、失败或取消的任务总数，用于了解平台任务负载。返回 None 时表示暂无统计。准备和确认任务时，平台会检查账号权限、余额及额度。

## 设备详情：BackendClassRead

将上一步取得的 short_code 传给 scheduler.get_backend_class(identifier)，得到 BackendClassRead。这个对象包含设备身份、目录状态和公开的配置选项。

| 读取位置 | 含义 | 使用注意 |
| --- | --- | --- |
| resource.id / resource.short_code / resource.name | 资源 ID、设备标识和显示名称 | 任务的 backend_class_id 使用 id 或 short_code。 |
| resource.type / resource.is_hardware | 设备类别与真机声明 | is_hardware 为 None 时表示类型尚未明确。 |
| resource.status / resource.num_qubits | 目录状态与设备宽度 | 可用物理位置通过能力模型的 available_qubits 查看。 |
| resource.supported_formats | 目录声明的输入格式 | 按自己使用的 Core、Qiskit 或 PennyLane 入口编写程序。 |
| resource.configuration_schema | 该设备公开任务配置的 schema | 读取 properties 查看设备选项。 |
| resource.metadata / resource.extra | 扩展能力信息 | 需要详细分析设备数据时按字段读取。 |

```python
print("设备：", resource.short_code, resource.name)
print("类别：", resource.type)
print("在线状态：", resource.status)
print("目录格式：", resource.supported_formats)
print("编译方式：", resource.compilation_mode)
```

## 查询门集与连接关系

已有 resource 时，用 capabilities_from_backend(resource) 在本地解析设备能力。需要重新从平台读取时，使用 get_capabilities(backend_code, scheduler=scheduler)。两种方式都返回 BackendCapabilities。

```python
caps = capabilities_from_backend(resource)

print("设备宽度：", caps.num_qubits)
print("支持操作：", sorted(caps.supported_gate_names))
print("原生操作：", sorted(caps.native_gate_names))
print("当前可用位置：", caps.available_qubits)
print("连接边：", caps.topology.coupling_map)
print("连接有方向：", caps.topology.is_directed)
print("任务限制：", caps.limits)
print("功能声明：", sorted(caps.features))
print("平台是否声明可接收逻辑线路：", caps.supports_execution_path("logical"))
print("平台是否声明可接收已编译的物理线路：", caps.supports_execution_path("physical"))
```

supported_gate_names 展示可表达的操作，native_gate_names 展示设备公开的原生门。coupling_map 中的每一对物理比特编号表示一条连接边；is_directed 表示是否区分连接方向。固定布局时，结合 client_instructions 查看各个门允许使用的位置。

supports_execution_path 是只读能力查询，返回 True 或 False。上面两个 print 用于了解平台接受哪一种线路：logical 表示提交逻辑线路，由平台对应的编译流程适配设备；physical 表示提交已经确定物理比特位置并完成编译的线路。两项可以同时为 True，你按本次线路的准备方式选择。

| 查询 | True 的含义 | 接下来怎样使用 |
| --- | --- | --- |
| caps.supports_execution_path("logical") | 当前目录明确声明接收逻辑线路 | 编写使用逻辑比特的 OpenQASM，configuration_data 使用 circuit_representation="logical"；本源真机由云端完成拓扑映射。 |
| caps.supports_execution_path("physical") | 当前目录明确声明接收已编译的物理线路 | 按设备门集与连接关系完成物理编译，configuration_data 使用 circuit_representation="physical"。 |

False 表示当前目录没有明确声明支持该提交方式，包括声明缺失的情况。可以重新查询设备详情，或选择已声明支持所需方式的设备。真正选择提交方式的是任务配置中的 circuit_representation；调用查询方法会保持现有配置不变。

| 字段或方法 | 内容 | 如何使用 |
| --- | --- | --- |
| supported_gate_names / supported_ops | 支持的操作名称、门元数及参数名 | 了解线路可用的操作；缺少 supported_ops 时解析器可回退到 native_ops。 |
| native_gate_names / native_ops | 设备公开的原生门集 | 结合具体操作的 qargs 查看物理放置位置。 |
| topology.coupling_map / is_directed | 连接关系与方向标记 | 查看量子比特连接图。 |
| available_qubits | 解析后的可用物理位置 | 精确分析时核对原始声明；兼容旧目录时可能按设备宽度补齐。 |
| limits / max_shots | 设备执行范围 | 设置符合设备范围的线路宽度与采样次数。 |
| features / supports_feature(name) | 平台明确声明的功能 | True 表示已声明支持，False 表示当前目录未声明。 |
| client_instructions | 各个操作及允许的 qargs | 为固定物理布局提供逐门位置数据。 |

通过 caps.supports_feature("reset") 或 caps.allows_reset() 查询线路功能；通过 configuration_schema 查询 mapping 等提交选项。

```python
print("reset 已声明：", caps.allows_reset())
print("中途测量已声明：", caps.allows_mid_circuit_measure())
print("动态线路已声明：", caps.allows_dynamic_circuits())

for instruction in caps.client_instructions:
    print(instruction.name, instruction.arity,
          instruction.parameters, instruction.qargs)
```

## 读取 timing、noise 与 features

资源中的 constraint_data 保存平台发布的能力数据；capabilities_from_backend 合并这些数据与目录字段，生成 caps。需要详细查看设备声明时，读取下面的原始字段。

```python
raw_capabilities = (
    resource.extra.get("constraint_data")
    or resource.metadata.get("constraint_data")
    or resource.extra.get("capabilities")
    or resource.metadata.get("capabilities")
    or {}
)
raw_topology = raw_capabilities.get("topology", {})
print("原始可用位置声明：",
      raw_topology.get("available_qubits",
                       raw_capabilities.get("available_qubits")))
print("原始 timing：", raw_capabilities.get("timing"))
print("原始 noise：", raw_capabilities.get("noise"))
print("原始 features：", raw_capabilities.get("features"))

print("解析后的 timing：", dict(caps.timing))
print("解析后的 noise：", dict(caps.noise))
```

timing 包含设备公布的时间信息，noise 包含可用的噪声或错误率信息，features 列出已识别的线路功能。空值表示当前平台尚未提供该项数据；例如 dt=None 表示采样周期未知。

## 使用自己的 OpenQASM 程序

Core SDK 读取 OpenQASM 文件或 UTF-8 字节内容。按程序头部的版本选择 input_format，平台负责转换为设备执行格式。使用 Qiskit 或 PennyLane 编写线路时，可直接使用对应插件完成提交。

| Core input_format | 文件内容 |
| --- | --- |
| openqasm2 | 以 OPENQASM 2.0; 开头的程序 |
| openqasm3 | 以 OPENQASM 3 开头的程序 |

设备的 configuration_schema 用于查询 mapping 等执行选项，OpenQASM 2 和 3 使用同一份设备配置说明。高级查询中的 caps.supports_format() 按语言家族归类；具体程序由准备接口检查。

## 发现设备专属选项

读取 resource.configuration_schema 后，逐项查看名称、类型、范围、默认值和说明。下面把常用字段整理成简短的字典；None 表示该项未提供。

```python
schema = resource.configuration_schema
properties = schema.get("properties", {})
required = set(schema.get("required", []))

for name, definition in properties.items():
    print({
        "name": name,
        "type": definition.get("type"),
        "enum": definition.get("enum"),
        "const": definition.get("const"),
        "default": definition.get("default"),
        "minimum": definition.get("minimum"),
        "maximum": definition.get("maximum"),
        "required": name in required,
        "description": definition.get("description"),
    })
```

例如，name=mapping、type=boolean、default=True 表示该设备的映射选项默认开启。希望显式选择这个值时，在任务中填写 configuration_data={"mapping": True}。其他选项同样根据查询到的类型和取值范围填写。

| schema 字段 | 读法 | 示例含义 |
| --- | --- | --- |
| properties | 可选择的设备参数及定义 | 查找 mapping 等字段，读取它的类型与默认值。 |
| type | JSON 值类型 | boolean 在 Python 中填写 True 或 False。 |
| enum / const | 候选值列表 / 固定值 | enum=[False, True] 可选择布尔值；const=False 表示该上下文只允许 False。 |
| default | 设备声明的默认值 | 采用默认行为时可省略对应选项。 |
| minimum / maximum | 数值范围 | 选择此区间内的数值。 |
| required | 必填的设备选项名称 | 在任务的 configuration_data 中填写这些选项。 |

选择本源真机后，可以从 schema 查看 amend、mapping、optimization 等设备选项。设置本次实验需要调整的选项即可，其余沿用默认行为。

| 本源设备选项 | 用途 | 使用方式 |
| --- | --- | --- |
| mapping | 启用本源云端拓扑映射，完成逻辑比特到物理比特的映射，并适配芯片连接关系 | 逻辑线路设为 True；已经完成物理编译的线路设为 False。 |
| optimization | 开启或关闭本源云端线路优化 | True 开启，False 关闭；当前固定物理线路使用 False 保留已编译的线路。 |
| amend | 开启或关闭本源云端修正功能 | True 启用，False 关闭。 |

mapping 是云端编译中的拓扑映射开关。开启后，本源将逻辑线路的比特和门操作安排到芯片可执行的连接关系上。需要指定物理比特时，先完成下面介绍的固定布局流程，再关闭云端映射。

- [本源 QPanda3 官方说明：QCloudOptions](https://github.com/OriginQ/pyqpanda3-skill/blob/main/resources/api/qcloud/index.md)
- [本源官方说明：云端选项与固定布局](https://github.com/OriginQ/pyqpanda3-skill/blob/main/resources/api/qcloud/service.md)

## 设置 configuration_data

把设备选项放进 JobSubmissionConfig 的 configuration_data。这个字典使用平铺结构，mapping、optimization 等名称直接作为键。

```python
# 为本源真机的逻辑线路设置映射与优化选项。
configuration = {
    "circuit_representation": "logical",
    "mapping": True,
    "optimization": False,
}

config = JobSubmissionConfig(
    backend_class_id=resource.short_code,
    organization_id="替换为平台返回的组织 ID",
    name="bell-core-logical",
    shots=128,
    input_format="openqasm2",
    configuration_data=configuration,
)
```

| 示例参数 | 填写内容 | 作用 |
| --- | --- | --- |
| backend_class_id | 刚查询到的 resource.short_code | 将任务发送到你已检查能力的同一台设备 |
| organization_id | 平台返回的组织 ID | 确定任务归属、访问权限与共享名额；费用由当前用户的钱包支付 |
| shots | 128 | 本次线路请求的测量次数 |
| input_format | openqasm2 | 按 OpenQASM 2 解释随后上传的文本 |
| configuration_data | 本次选择的设备选项字典 | 携带厂商编译选项和平台线路表示信息 |

circuit_representation 标记线路采用逻辑比特还是已经编译好的物理位置，默认 logical。固定布局的程序使用 physical，详见后面的物理线路章节。

| 情况 | 使用方法 |
| --- | --- |
| 显式选择设备选项 | 把取值写入 configuration_data，平台按设备 schema 检查。 |
| 采用默认选项 | 省略对应字段，平台在准备时应用设备及执行路径的默认值。 |
| 调整实验配置 | 创建新的 config，再准备新的报价。 |
| 设置采样次数 | 使用 shots=128；若同时在 configuration_data 中填写 shots，两处保持一致。 |

## 完整示例：为 Bell 线路准备报价

下面是可单独复制的 Core 示例。运行前配置平台地址和 SDK 凭据；运行时选择设备并输入组织 ID。示例根据设备公开的选项启用 mapping，完成线路上传并展示报价。

```python
import os
from quantum_source_sdk import SchedulerClient, JobSubmissionConfig, list_backends

qasm = b'''OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
h q[0];
cx q[0],q[1];
measure q -> c;
'''

with SchedulerClient(base_url=os.environ["QUANTUM_SOURCE_API_URL"]) as client:
    print("设备：", list_backends(scheduler=client))
    selected_code = input("设备 short_code：").strip()
    selected = client.get_backend_class(selected_code)
    print("格式：", selected.supported_formats)
    print("设备参数：", selected.configuration_schema.get("properties", {}))

    organization = input("平台组织 ID：").strip()
    configuration = {"circuit_representation": "logical"}
    if "mapping" in selected.configuration_schema.get("properties", {}):
        configuration["mapping"] = True

    config = JobSubmissionConfig(
        backend_class_id=selected.short_code,
        organization_id=organization,
        name="bell-core-logical",
        shots=128,
        input_format="openqasm2",
        configuration_data=configuration,
    )
    prepared = client.prepare_submission(config, file_content=qasm)
    print("准备记录：", prepared.preparation.id)
    print("报价：", prepared.quote)
    # 本例完成报价准备，执行流程见 Core 主教程。
```

### 理解示例与返回值

线路先对逻辑 q[0] 应用 H 门，再用 CX 关联 q[0] 与 q[1]，最后测量两个逻辑比特。mapping=True 启用本源云端拓扑映射，把这条逻辑线路适配到芯片的物理比特和连接关系。

| 调用或返回值 | 本例中的含义 |
| --- | --- |
| qasm | bytes 类型的 OpenQASM 文件内容；若原始程序是 str，使用 .encode("utf-8") 转换 |
| client.prepare_submission(config, file_content=qasm) | 上传程序、进行准备并获取报价，返回 PreparedSubmission |
| prepared.preparation.id | 本次准备记录的标识，用于后续确认和查询 |
| prepared.quote | 这次程序、设备、shots 与配置对应的报价对象 |

继续执行时，参考 Core 主教程中的报价确认步骤，并保持创建 prepared 的客户端连接有效。本独立示例使用 with，在代码块结束时自动关闭连接。

## 使用已编译的物理线路

需要在指定物理比特上运行时，先根据设备连接图和逐门位置完成布局编译，再通过 Core 提交物理 OpenQASM 程序。使用 Qiskit 的 physical_qubits 或 initial_layout 可以完成这一流程，详见编译与物理布局章节。

设备提供物理执行路径时，已编译的物理程序使用 circuit_representation="physical"、mapping=False、optimization=False，保留编译好的物理位置和线路。

## 重新查询与关闭连接

```python
# 重新读取平台设备目录并解析能力。
resource = scheduler.get_backend_class(backend_code)
caps = capabilities_from_backend(resource)
schema = resource.configuration_schema

# 或直接重新取得能力模型：
caps = get_capabilities(backend_code, scheduler=scheduler)
```

重新查询会得到平台当前发布的目录数据，再生成新的 caps 对象。平台可能缓存设备信息；需要校准时间时，读取设备实际提供的时间字段。schema.properties、timing 或 noise 为空表示该项信息暂未发布。

```python
# 完成本章后释放本地 HTTP 连接。
scheduler.close()
```

## API 参考

查询函数、能力字段、任务配置的完整签名与返回值统一收录在 API 参考中，可按接口名称查阅。

- [API 参考：设备能力](api.html#capabilities)
- [API 参考：Core 客户端与任务](api.html#core)

- [Core 完整提交教程](core.html)
- [提交后查询、恢复与历史分页](job-query.html)
- [OpenQuantum：Backend Discovery（组织方式参考）](https://docs.openquantum.com/core-sdk/backend-discovery/)
- [Qiskit 设备能力](capabilities-qiskit.html)
- [PennyLane 设备能力](capabilities-pennylane.html)
- [编译与物理比特](compilation.html)

## 下载本页 Jupyter Notebook

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

[下载《Core 设备配置》Notebook（.ipynb）](../../notebooks/sdk_user_guide_capabilities_core.ipynb)
