Skip to content

量子云计算 ​

本教程介绍如何连接到本源量子的量子云平台,使用 pyqpanda3.qcloud 模块将量子程序提交到真实量子处理器和云模拟器,跟踪任务状态,以及获取结果。

前置知识: 模拟 -- 在进行云端执行之前,你应该已经熟悉构建量子程序并在本地模拟器上运行。


目录 ​


1. 量子云计算简介 ​

1.1 为什么要使用量子云计算 ​

本地模拟器非常适合学习、调试和开发算法。然而,它们面临着根本性的限制:

  • 模拟 n 个量子比特所需的内存以 O(2n) 的速度增长,在典型工作站上模拟超过大约 30 个量子比特是不切实际的。
  • 模拟器模拟的是理想的量子行为,这与受噪声、退相干和门错误影响的真实量子处理器存在显著差异。

量子云计算解决了这两个问题:

方面本地模拟器量子云计算
量子比特数量受 RAM 限制(通常约 25-30 个量子比特)在真实硬件上可达 72+ 个量子比特
噪声模型人为设定的,用户指定的真实的,物理设备固有的
速度小型线路速度快,指数级扩展在真实 QPU 上任何线路深度均为常数
成本免费消耗云端积分或订阅
可用性始终可用受排队时间和维护影响
保真度默认完美(无噪声)受硬件质量限制

云平台还提供云托管模拟器,能够处理比本地机器更大的线路,以及用于全振幅模拟、部分振幅计算和期望值估计的专用后端。

1.2 本源量子云平台概览 ​

本源量子云平台提供对以下几类量子后端的访问:

  • 真实量子处理器(QPU) -- 具有 6 到 72+ 个量子比特的超导量子芯片。这些是在实际量子硬件上执行你的线路的物理设备。
  • 全振幅模拟器 -- 云托管的态矢量模拟器,计算所有 2n 个振幅。适用于验证和算法开发。
  • 部分振幅模拟器 -- 仅计算态矢量的特定振幅,能够模拟更大的线路。
  • 专用后端 -- 用于态层析、期望值计算和其他分析任务的后端。

通过 pyqpanda3.qcloud 模块访问云平台,该模块提供了用于身份验证、后端发现、任务提交和结果获取的 Python 接口。

mermaid
graph TD
    USER["Your Python Code<br/>pyqpanda3.qcloud"] --> SERVICE["QCloudService<br/>API Authentication"]
    SERVICE --> BACKENDS["Available Backends"]
    BACKENDS --> QPU["Real QPUs<br/>WK_C180_2, PQPUMESH8, ..."]
    BACKENDS --> SIM["Cloud Simulators<br/>full_amplitude, partial_amplitude"]
    BACKENDS --> SPEC["Specialized<br/>state_tomography, expectation"]
    QPU --> JOB["QCloudJob<br/>Submitted to Queue"]
    SIM --> JOB
    SPEC --> JOB
    JOB --> RESULT["QCloudResult<br/>Probabilities, Counts"]

    style USER fill:#4a90d9,color:#fff
    style SERVICE fill:#7b68ee,color:#fff
    style BACKENDS fill:#50c878,color:#fff
    style JOB fill:#e8913a,color:#fff
    style RESULT fill:#c0392b,color:#fff

2. QCloudService — 连接云平台 ​

QCloudService 类是与本源量子云平台交互的主要入口。它处理身份验证、后端发现和日志配置。

2.1 创建服务实例 ​

要创建 QCloudService,你需要一个 API 密钥。单参构造 QCloudService(api_key) 会从新格式 API key 解析服务域名;旧格式 key 回退历史默认端点。需要测试或私有部署时,用 QCloudService(api_key, url=...) 显式覆盖。

python
from pyqpanda3.qcloud import QCloudService

# 新格式 key:从 key 中解析服务域名
service = QCloudService("your_api_key_here")

# 或指定自定义 URL(例如私有云部署)
# service = QCloudService("your_api_key_here", url="https://custom-cloud.example.com")

API 密钥是一个用于验证你账户的字符串。你可以在本源量子云平台上注册来获取。请像对待密码一样保护你的 API 密钥 -- 不要分享它或将它提交到版本控制中。

推荐的做法是将 API 密钥存储在环境变量中:

python
import os
from pyqpanda3.qcloud import QCloudService

# Read the API key from an environment variable
api_key = os.environ["QPANDA_QCLOUD_API_KEY"]
service = QCloudService(api_key)

然后在运行脚本之前设置环境变量:

bash
export QPANDA_QCLOUD_API_KEY="your_api_key_here"
python your_script.py

2.2 配置日志 ​

云服务支持可配置的日志功能,用于调试和监控。使用 setup_logging 来启用它:

python
from pyqpanda3.qcloud import QCloudService, LogOutput

service = QCloudService("your_api_key_here")

# Log to the console (default)
service.setup_logging(output=LogOutput.CONSOLE)

# Log to a file instead
service.setup_logging(output=LogOutput.FILE, file_path="cloud_debug.log")

setup_logging 方法接受两个参数:

参数类型默认值描述
outputLogOutputLogOutput.CONSOLE日志输出目标
file_pathstr""当 output=LogOutput.FILE 时的文件路径

日志功能是可选的。如果你不调用 setup_logging,服务将静默运行。

2.3 列出可用后端 ​

backends() 方法返回一个字典,键为后端名称,值为可用性标志:

python
from pyqpanda3.qcloud import QCloudService

service = QCloudService("your_api_key_here")
backends = service.backends()

print("Available backends:")
for name, available in backends.items():
    status = "available" if available else "unavailable"
    print(f"  - {name}: {status}")

运行结果:

Available backends:
  - WK_C180_2: available
  - PQPUMESH8: available
  - full_amplitude: available
  - partial_amplitude: available

可用后端取决于你的账户权限和云平台的当前状态。真实量子处理器在校准或维护期间可能暂时不可用。

2.4 获取特定后端 ​

一旦你知道了后端的名称,可以使用 backend() 来获取它:

python
from pyqpanda3.qcloud import QCloudService

service = QCloudService("your_api_key_here")

# Get a real quantum processor backend
qpu_backend = service.backend("WK_C180_2")

# Get a cloud simulator backend
sim_backend = service.backend("full_amplitude")

返回的 QCloudBackend 对象提供了提交任务、查询芯片信息和计算期望值的方法。我们将在下一节详细探讨。


3. QCloudBackend — 执行目标 ​

QCloudBackend 代表一个特定的量子计算资源 -- 可以是真实量子处理器或云托管的模拟器。你通过 QCloudService.backend() 获取它。

3.1 后端概览 ​

python
from pyqpanda3.qcloud import QCloudService

service = QCloudService("your_api_key_here")
backend = service.backend("WK_C180_2")

# Get the backend name
print(f"Backend name: {backend.name()}")

3.2 运行量子程序 ​

最简单的运行方式是使用 run() 方法,它接受一个 QProg 和一个 shot 数:

python
from pyqpanda3 import core
from pyqpanda3.qcloud import QCloudService

# Build a Bell state circuit
prog = core.QProg()
prog << core.H(0)
prog << core.CNOT(0, 1)
prog << core.measure([0, 1], [0, 1])

# Connect and submit
service = QCloudService("your_api_key_here")
backend = service.backend("full_amplitude")

# Submit the job with 3000 shots
job = backend.run(prog, shots=3000)
print(f"Submitted job: {job.job_id()}")

run() 方法立即返回一个 QCloudJob 对象。实际执行在云服务器上异步进行。

3.3 带选项运行 ​

为了更好地控制编译和执行,可以使用 QCloudOptions:

python
from pyqpanda3 import core
from pyqpanda3.qcloud import QCloudService, QCloudOptions

prog = core.QProg()
prog << core.H(0)
prog << core.CNOT(0, 1)
prog << core.measure([0, 1], [0, 1])

service = QCloudService("your_api_key_here")
backend = service.backend("WK_C180_2")

# Configure execution options
options = QCloudOptions()
options.set_amend(True)        # Enable amendment (error mitigation)
options.set_mapping(True)      # Enable qubit mapping to physical qubits
options.set_optimization(True) # Enable circuit optimization

# Submit with options
job = backend.run(prog, shots=3000, options=options)

QCloudOptions 类(在第 6 节详细介绍)让你能够控制服务器端的编译行为。

3.4 带噪声模型运行 ​

当提交到云模拟器(而非真实 QPU)时,你可以指定噪声模型来模拟真实的硬件行为:

python
from pyqpanda3 import core
from pyqpanda3.qcloud import (
    QCloudService, QCloudNoiseModel, NOISE_MODEL
)

prog = core.QProg()
prog << core.H(0)
prog << core.CNOT(0, 1)
prog << core.measure([0, 1], [0, 1])

service = QCloudService("your_api_key_here")
backend = service.backend("full_amplitude")

# Create a depolarizing noise model
noise = QCloudNoiseModel(
    NOISE_MODEL.DEPOLARIZING_KRAUS_OPERATOR,
    [0.001],   # single-qubit gate noise parameter
    [0.01]     # two-qubit gate noise parameter
)

# Submit with noise model
job = backend.run(prog, shots=3000, model=noise)

请注意,噪声模型仅对云模拟器有意义。真实量子处理器本身就有固有噪声 -- 你无法在之上再添加软件噪声模型。

3.5 芯片信息 ​

对于真实 QPU 后端,你可以查询芯片物理特性的详细信息:

python
from pyqpanda3.qcloud import QCloudService

service = QCloudService("your_api_key_here")
backend = service.backend("WK_C180_2")

# Get chip information
chip_info = backend.chip_info()

# Number of qubits on the chip
print(f"Qubits: {chip_info.qubits_num()}")

# Chip identifier
print(f"Chip ID: {chip_info.chip_id()}")

# Available qubits (not all physical qubits may be usable)
available = chip_info.available_qubits()
print(f"Available qubits: {available}")

# High-frequency qubits
hf_qubits = chip_info.high_frequency_qubits()
print(f"High-frequency qubits: {hf_qubits}")

# Basic gate set supported by this chip
gates = chip_info.get_basic_gates()
print(f"Basic gates: {gates}")

# Chip topology (connectivity between qubits)
topology = chip_info.get_chip_topology()
print(f"Topology edges ({len(topology)} connections):")
for edge in topology[:5]:  # Show first 5 edges
    print(f"  {edge[0]} <-> {edge[1]}")

芯片上的每个量子比特都有各自的特性:

python
# Get per-qubit information
single_info_list = chip_info.single_qubit_info()
for info in single_info_list[:3]:  # Show first 3 qubits
    print(f"Qubit {info.get_qubit_id()}:")
    print(f"  T1 (relaxation): {info.get_t1():.2f} us")
    print(f"  T2 (coherence):  {info.get_t2():.2f} us")
    print(f"  Gate fidelity:   {info.get_single_gate_fidelity():.4f}")
    print(f"  Readout fidelity: {info.get_readout_fidelity():.4f}")
    print(f"  Frequency:       {info.get_frequency():.2f} GHz")

双量子比特门信息同样可以获取:

python
# Get two-qubit gate information
double_info_list = chip_info.double_qubits_info()
for info in double_info_list[:3]:
    qubits = info.get_qubits()
    print(f"Qubits ({qubits[0]}, {qubits[1]}): "
          f"fidelity = {info.get_fidelity():.4f}")

这些信息对于以下方面很有价值:

  • 选择线路中使用哪些量子比特
  • 了解连通性约束(哪些量子比特对支持双量子比特门)
  • 估算线路在真实硬件上的预期保真度

3.6 期望值 ​

云后端可以直接计算哈密顿量或泡利算符的期望值,无需手动解析测量结果:

python
from pyqpanda3 import core
from pyqpanda3.qcloud import QCloudService, QCloudOptions
from pyqpanda3.hamiltonian import Hamiltonian, PauliOperator

# Build a circuit
prog = core.QProg()
prog << core.X(0)
prog << core.CNOT(0, 1)
prog << core.SWAP(1, 2)

# Define a Hamiltonian
hamiltonian = Hamiltonian({"X0 Y1": 1.1, "X0 Z1 I2": 2.1, "I1 Z2": 3.1})

# Or equivalently, a Pauli operator
pauli_op = PauliOperator({"X0 Y1": 1.1, "X0 Z1 I2": 2.1, "I1 Z2": 3.1})

service = QCloudService("your_api_key_here")

# Compute expectation on a real QPU
backend = service.backend("WK_C180_2")
expval = backend.expval_hamiltonian(prog, hamiltonian, QCloudOptions())
print(f"Hamiltonian expectation (QPU): {expval}")

# Compute on cloud simulator
sim_backend = service.backend("full_amplitude")
expval_sim = sim_backend.expval_hamiltonian(prog, hamiltonian)
print(f"Hamiltonian expectation (sim): {expval_sim}")

# Pauli operator expectation
expval_pauli = backend.expval_pauli_operator(prog, pauli_op, QCloudOptions())
print(f"Pauli operator expectation: {expval_pauli}")

expval_hamiltonian 和 expval_pauli_operator 方法也接受 shots 参数和可选的噪声模型:

python
# With explicit shots and noise model on simulator
from pyqpanda3.qcloud import QCloudNoiseModel, NOISE_MODEL

noise = QCloudNoiseModel(NOISE_MODEL.DEPOLARIZING_KRAUS_OPERATOR, [0.001], [0.01])
expval = sim_backend.expval_hamiltonian(prog, hamiltonian, shots=5000, noise_model=noise)

4. QCloudJob — 跟踪执行 ​

将量子程序提交到云端后,你会收到一个 QCloudJob 对象,它代表异步计算。任务在完成之前会经历多个状态。

4.1 任务生命周期 ​

当你提交一个任务时,它会经历以下状态:

状态描述
QUEUING任务已被接收,正在执行队列中等待
WAITING任务正在等待被分配到计算资源
COMPUTING任务正在量子处理器或模拟器上执行
FINISHED任务已成功完成,结果可用
FAILED任务遇到错误,未能完成
mermaid
stateDiagram-v2
    [*] --> QUEUING: Submit job
    QUEUING --> WAITING: Dequeue
    WAITING --> COMPUTING: Resource assigned
    COMPUTING --> FINISHED: Execution complete
    COMPUTING --> FAILED: Execution error
    WAITING --> FAILED: Resource error
    QUEUING --> FAILED: Submission error
    FINISHED --> [*]: Retrieve results
    FAILED --> [*]: Check error message

4.2 创建任务引用 ​

QCloudJob 可以通过两种方式创建:

从提交中创建 -- backend.run() 方法返回一个 QCloudJob:

python
job = backend.run(prog, shots=3000)

从任务 ID 创建 -- 如果你保存了之前会话中的任务 ID,可以重建任务引用:

python
from pyqpanda3.qcloud import QCloudJob

# Reconstruct a job reference from a known job ID
job = QCloudJob("ABC123DEF456")

当你提交了一个长时间运行的任务,并想在新的 Python 会话中检查其状态时,这很有用。

4.3 检查任务状态 ​

使用 status() 方法来检查任务的当前状态:

python
from pyqpanda3.qcloud import JobStatus

status = job.status()
print(f"Current status: {status}")

# Compare against known states
if status == JobStatus.FINISHED:
    print("Job completed successfully!")
elif status == JobStatus.FAILED:
    print("Job failed. Check error messages.")
elif status == JobStatus.QUEUING:
    print("Job is in the queue. Please wait.")
elif status == JobStatus.COMPUTING:
    print("Job is currently executing.")
elif status == JobStatus.WAITING:
    print("Job is waiting to be processed.")

4.4 查询任务信息 ​

query() 方法在不获取完整结果的情况下检索任务的详细信息。它返回一个包含元数据的 QCloudResult:

python
result_info = job.query()
print(f"Job ID: {result_info.job_id()}")
print(f"Job status: {result_info.job_status()}")

如果任务失败了,你可以获取错误信息:

python
if result_info.job_status() == JobStatus.FAILED:
    print(f"Error: {result_info.error_message()}")

4.5 获取任务结果 ​

result() 方法会阻塞,直到任务完成(或服务器报告最终状态),然后返回一个 QCloudResult:

python
# Wait for completion and get results
result = job.result()

# Access the data
probs = result.get_probs()
counts = result.get_counts()

print(f"Probabilities: {probs}")
print(f"Counts: {counts}")

如果任务尚未完成,result() 可能返回一个状态非 FINISHED 的结果。务必检查状态:

python
result = job.result()
if result.job_status() == JobStatus.FINISHED:
    counts = result.get_counts()
    print(f"Measurement counts: {counts}")
else:
    print(f"Job not finished. Status: {result.job_status()}")

5. QCloudResult — 处理输出 ​

QCloudResult 类提供了多种方式来访问已完成的云端任务的输出。

5.1 获取概率 ​

get_probs() 方法返回测量结果的概率分布估计:

python
from pyqpanda3.qcloud import DataBase

result = job.result()

# Get probabilities as binary strings (default)
probs_binary = result.get_probs(base=DataBase.Binary)
print("Probabilities (binary):", probs_binary)
# Example: {'00': 0.4987, '11': 0.5013}

# Get probabilities as hexadecimal strings
probs_hex = result.get_probs(base=DataBase.Hex)
print("Probabilities (hex):", probs_hex)
# Example: {'0x0': 0.4987, '0x3': 0.5013}

注意:在真实 QPU 后端上,base 参数会按上例控制键的格式(DataBase.Binary → '00',DataBase.Hex → '0x0')。而在 full_amplitude 云模拟器上,结果为概率型,统一返回十六进制键(与 base 无关),且 get_counts() 返回 {}(请改用 get_probs() 读取结果)。

对于批量提交(多个线路),使用 get_probs_list(),它返回概率字典的列表:

python
# When running multiple programs in a batch
probs_list = result.get_probs_list()
for i, probs in enumerate(probs_list):
    print(f"Circuit {i} probabilities: {probs}")

5.2 获取测量计数 ​

get_counts() 方法返回每次 shot 的原始测量计数:

重要:概率型结果(默认 is_prob_counts=True)下 get_counts() 实际返回空字典 {}。下面示例中的计数注释仅表示原始计数型结果的形态——要在真实 QPU 上拿到原始计数,需通过 QCloudOptions.set_is_prob_counts(False) 显式请求(云模拟器不接受 QCloudOptions,会抛 RuntimeError: Run with QCloudOptions is only for QPU)。读取概率型结果请使用上节的 get_probs()。

python
from pyqpanda3.qcloud import DataBase

result = job.result()

# Counts as binary strings (default)
counts = result.get_counts(base=DataBase.Binary)
print("Counts (binary):", counts)
# Example (raw-counts result): {'00': 1496, '11': 1504}
# Note: with default is_prob_counts=True this prints {}

# Counts as hexadecimal strings
counts_hex = result.get_counts(base=DataBase.Hex)
print("Counts (hex):", counts_hex)
# Example (raw-counts result): {'0x0': 1496, '0x3': 1504}

类似地,get_counts_list() 返回批量提交的结果(仅当使用批量 run() 提交多个线路时可用):

python
counts_list = result.get_counts_list(base=DataBase.Binary)
for i, counts in enumerate(counts_list):
    total = sum(counts.values())
    print(f"Circuit {i}: {total} total shots, counts = {counts}")

5.3 访问原始数据 ​

origin_data() 方法返回来自云服务器的原始 JSON 响应。这对于调试或访问 Python API 未公开的字段很有用:

python
raw_json = result.origin_data()
print("Raw server response:")
print(raw_json)

5.4 其他结果方法 ​

QCloudResult 类还提供了几个用于专用输出类型的方法:

python
result = job.result()

# Job ID from the result
job_id = result.job_id()
print(f"Job ID: {job_id}")

# Job status from the result
status = result.job_status()
print(f"Status: {status}")

# Error message (if job failed)
error = result.error_message()
if error:
    print(f"Error: {error}")

# Amplitudes (for partial amplitude backend)
amplitudes = result.get_amplitudes()
print(f"Amplitudes: {amplitudes}")

# State fidelity (for state tomography backend)
fidelity = result.get_state_fidelity()
print(f"State fidelity: {fidelity}")

# State tomography density matrix (returns list[list[complex]])
density = result.get_state_tomography_density()
print(f"Density matrix rows: {len(density)}, cols: {len(density[0])}")

并非所有方法都适用于所有任务类型。例如,get_state_fidelity() 和 get_state_tomography_density() 仅在使用 run_quantum_state_tomography() 提交任务时可用。同样,get_amplitudes() 仅对部分振幅任务可用。


6. QCloudOptions — 配置执行 ​

QCloudOptions 类提供了对云服务器如何编译和执行你的线路的细粒度控制。

6.1 创建选项 ​

python
from pyqpanda3.qcloud import QCloudOptions

# Create with all defaults
options = QCloudOptions()

# Print current settings
options.print()

示例输出(默认值):

is_prob_counts: true
amend_flag: 1
use_cz_pattern: false
mapping: true
optimization: true
point_label: 1

6.2 编译选项 ​

当提交到真实 QPU 时,云服务器会执行多个编译步骤。你可以通过 QCloudOptions 分别配置每个步骤。所有选项都有适用于大多数情况的合理默认值:

选项默认值描述
amendTrue遗留布尔开关,等价于 amend_flag 的 0/1(基于校准数据的错误缓解)
amend_flag1纠错模式:0 关闭,1 全局采样纠错,3 局部实时纠错
use_cz_patternFalse串扰噪声抑制
mappingTrue基于芯片拓扑的逻辑到物理量子比特映射
optimizationTrue线路简化(门抵消、分解)
point_label1校准点级别标识符
specified_block[]限制执行到特定块(空 = 无限制)
is_prob_countsTrue输出格式:概率与原始计数

仅当需要更改默认值时才调用 setter:

python
from pyqpanda3.qcloud import QCloudOptions

options = QCloudOptions()

# Disable amendment (enabled by default)
options.set_amend(False)

# Specify calibration point (default is 1)
options.set_point_label(0)

# Restrict execution to a specific block on the chip
options.set_specified_block([1])

# Output raw counts instead of probabilities (default is True for probabilities)
options.set_is_prob_counts(False)

查询当前设置:

python
print(f"Amendment: {options.is_amend()}")
print(f"Mapping: {options.is_mapping()}")
print(f"Optimization: {options.is_optimization()}")
print(f"Point label: {options.point_label()}")
print(f"Is prob counts: {options.is_prob_counts()}")
print(f"Specified block: {options.specified_block()}")

6.3 自定义选项 ​

对于高级用例,你可以设置任意键值对选项:

python
from pyqpanda3.qcloud import QCloudOptions

options = QCloudOptions()

# Set custom options of various types
options.set_custom_option("repetitions", 10)         # int
options.set_custom_option("threshold", 0.95)          # double
options.set_custom_option("label", "experiment_1")    # string
options.set_custom_option("verbose", True)            # bool

# Check if a custom option exists
if options.has_custom_option("threshold"):
    print("threshold exists")

# Get all custom options as a dictionary
all_options = options.get_custom_options()
print(f"All custom options: {all_options}")
print(f"Threshold: {all_options['threshold']}")
print(f"Repetitions: {all_options['repetitions']}")
print(f"Label: {all_options['label']}")
print(f"Verbose: {all_options['verbose']}")

7. QCloudNoiseModel — 云端噪声模拟 ​

在云模拟器上运行时,你可以附加噪声模型来模拟真实量子处理器的行为。QCloudNoiseModel 类定义了噪声模型,分别为单量子比特门和双量子比特门设置独立的参数。

7.1 创建噪声模型 ​

python
from pyqpanda3.qcloud import QCloudNoiseModel, NOISE_MODEL

# Default constructor -- no noise (disabled)
clean_model = QCloudNoiseModel()
print(f"Clean model enabled: {clean_model.is_enabled()}")
# Output: Clean model enabled: False

# Construct with a specific noise model and parameters
noisy_model = QCloudNoiseModel(
    NOISE_MODEL.DEPOLARIZING_KRAUS_OPERATOR,
    [0.001],   # single-qubit gate error rate
    [0.01]     # two-qubit gate error rate
)
print(f"Noisy model enabled: {noisy_model.is_enabled()}")
# Output: Noisy model enabled: True

构造函数接受三个参数(均为位置参数):

参数类型描述
modelNOISE_MODEL噪声信道类型
single_plist[float]单量子比特门的噪声参数
double_plist[float]双量子比特门的噪声参数

7.2 检查和修改参数 ​

python
from pyqpanda3.qcloud import QCloudNoiseModel, NOISE_MODEL

noise = QCloudNoiseModel(
    NOISE_MODEL.DEPOLARIZING_KRAUS_OPERATOR,
    [0.001],
    [0.01]
)

# Get the noise model type
model_type = noise.get_noise_model()
print(f"Noise model: {model_type}")

# Get current parameters
single_params = noise.get_single_params()
double_params = noise.get_double_params()
print(f"Single-qubit params: {single_params}")
print(f"Two-qubit params: {double_params}")

# Update parameters
noise.set_single_params([0.002])
noise.set_double_params([0.02])
print(f"Updated single params: {noise.get_single_params()}")

# Print a human-readable summary
noise.print()

7.3 比较噪声模型 ​

两个噪声模型可以进行相等和不相等比较:

python
from pyqpanda3.qcloud import QCloudNoiseModel, NOISE_MODEL

model_a = QCloudNoiseModel(
    NOISE_MODEL.DEPOLARIZING_KRAUS_OPERATOR,
    [0.001], [0.01]
)

model_b = QCloudNoiseModel(
    NOISE_MODEL.DEPOLARIZING_KRAUS_OPERATOR,
    [0.001], [0.01]
)

model_c = QCloudNoiseModel(
    NOISE_MODEL.BITFLIP_KRAUS_OPERATOR,
    [0.005], [0.05]
)

print(f"model_a == model_b: {model_a == model_b}")   # True
print(f"model_a != model_c: {model_a != model_c}")   # True

8. 枚举参考 ​

qcloud 模块定义了几个控制任务行为和数据格式的枚举。

8.1 JobStatus ​

表示云任务的生命周期状态。

值描述
JobStatus.WAITING任务正在等待被处理
JobStatus.COMPUTING任务正在执行中
JobStatus.FINISHED任务已成功完成
JobStatus.FAILED任务失败,出现错误
JobStatus.QUEUING任务在提交队列中
python
from pyqpanda3.qcloud import JobStatus

# Status values can be compared directly
status = job.status()
if status == JobStatus.FINISHED:
    result = job.result()

8.2 DataBase ​

控制测量结果在结果中的表示方式。

值描述
DataBase.Binary二进制表示(例如 "00"、"11")
DataBase.Hex十六进制表示(例如 "0x0"、"0x3")
python
from pyqpanda3.qcloud import DataBase

result = job.result()

# Binary representation (human-readable)
probs_bin = result.get_probs(base=DataBase.Binary)
# {'00': 0.4987, '11': 0.5013}

# Hexadecimal representation (compact for many qubits)
probs_hex = result.get_probs(base=DataBase.Hex)
# {'0x0': 0.4987, '0x3': 0.5013}

对于具有多个量子比特的线路,十六进制表示更加紧凑。一个 10 量子比特的结果在二进制下需要 10 个字符("0010110101"),而在十六进制下只需要 4 个字符("0xB5")。在真实 QPU 上,base 会按预期选择二进制/十六进制格式;而在 full_amplitude 模拟器上,键始终为十六进制(与 base 无关)。

8.3 NOISE_MODEL ​

定义云端噪声模拟的噪声信道类型。

值描述
NOISE_MODEL.BITFLIP_KRAUS_OPERATOR随机 X(比特翻转)错误
NOISE_MODEL.BIT_PHASE_FLIP_OPERATOR比特和相位翻转的组合错误
NOISE_MODEL.DAMPING_KRAUS_OPERATOR振幅阻尼(T1 衰减)
NOISE_MODEL.DECOHERENCE_KRAUS_OPERATORT1 和 T2 退相干的组合
NOISE_MODEL.DEPHASING_KRAUS_OPERATOR相位阻尼(T2 衰减)
NOISE_MODEL.DEPOLARIZING_KRAUS_OPERATOR均匀去极化噪声
NOISE_MODEL.PHASE_DAMPING_OPERATOR纯退相位错误
python
from pyqpanda3.qcloud import NOISE_MODEL, QCloudNoiseModel

# Common choice: depolarizing noise (uniform error model)
noise = QCloudNoiseModel(
    NOISE_MODEL.DEPOLARIZING_KRAUS_OPERATOR,
    [0.001],  # 0.1% error on single-qubit gates
    [0.01]    # 1% error on two-qubit gates
)

# Decoherence model (T1 + T2) — requires 3 parameters per gate type
# (T1 relaxation time, T2 dephasing time, gate time)
decoherence_noise = QCloudNoiseModel(
    NOISE_MODEL.DECOHERENCE_KRAUS_OPERATOR,
    [0.0005, 0.0, 0.0],  # single-qubit: T1, T2, gate time
    [0.005, 0.0, 0.0]    # two-qubit: T1, T2, gate time
)

8.4 LogOutput ​

控制云服务日志的输出目标。

值描述
LogOutput.CONSOLE将日志打印到标准输出
LogOutput.FILE将日志写入文件
python
from pyqpanda3.qcloud import QCloudService, LogOutput

service = QCloudService("your_api_key_here")

# Console logging for development
service.setup_logging(output=LogOutput.CONSOLE)

# File logging for production
service.setup_logging(output=LogOutput.FILE, file_path="/var/log/qcloud.log")

9. 实践工作流 ​

本节通过完整的端到端示例演示如何使用云服务。

9.1 在云端运行 Bell 态的完整步骤 ​

以下是在云模拟器上运行 Bell 态的完整工作流程,从初始化到结果分析。

python
import os
from pyqpanda3 import core
from pyqpanda3.qcloud import (
    QCloudService,
    LogOutput, JobStatus, DataBase
)

# ------------------------------------------------
# Step 1: Authenticate with the cloud platform
# ------------------------------------------------
api_key = os.environ["QPANDA_QCLOUD_API_KEY"]
service = QCloudService(api_key)
service.setup_logging(output=LogOutput.CONSOLE)

# ------------------------------------------------
# Step 2: Discover available backends
# ------------------------------------------------
backends = service.backends()
print(f"Available backends: {backends}")

# ------------------------------------------------
# Step 3: Select a backend
# ------------------------------------------------
# Use the full-amplitude simulator for this example
backend = service.backend("full_amplitude")

# ------------------------------------------------
# Step 4: Build the quantum circuit
# ------------------------------------------------
prog = core.QProg()
prog << core.H(0)                    # Superposition on qubit 0
prog << core.CNOT(0, 1)              # Entangle qubits 0 and 1
prog << core.measure([0, 1], [0, 1]) # Measure both qubits

print("Circuit:")
print(prog)

# ------------------------------------------------
# Step 5: Submit the job
# ------------------------------------------------
# Note: full_amplitude simulator uses run(prog, shots) or run(prog, shots, model)
# QCloudOptions is only for real QPU backends
job = backend.run(prog, shots=3000)
job_id = job.job_id()
print(f"Job submitted. ID: {job_id}")

# ------------------------------------------------
# Step 6: Monitor job status
# ------------------------------------------------
import time

while True:
    status = job.status()
    print(f"  Status: {status}")
    if status == JobStatus.FINISHED:
        break
    elif status == JobStatus.FAILED:
        print("Job failed!")
        result = job.result()
        print(f"Error: {result.error_message()}")
        exit(1)
    time.sleep(2)  # Wait before polling again

# ------------------------------------------------
# Step 7: Retrieve and analyze results
# ------------------------------------------------
result = job.result()

# Get probabilities (the full_amplitude simulator returns hexadecimal keys like 0x0 / 0x3)
probs = result.get_probs(base=DataBase.Binary)
print("\nProbabilities:")
for state, prob in sorted(probs.items()):
    print(f"  |{state}>: {prob:.4f}")

# Get raw counts (note: on the full_amplitude simulator get_counts() returns {}
# because results are probability-type by default; read probs above instead)
counts = result.get_counts(base=DataBase.Binary)
print("\nMeasurement counts:")
for state, count in sorted(counts.items()):
    print(f"  |{state}>: {count}")

# Expected output for Bell state (keys are hexadecimal on current cloud backends):
#   |0x0>: ~0.50
#   |0x3>: ~0.50
#   (other states should be absent or near zero)

说明:上面的 full_amplitude 模拟器返回概率型结果,get_counts() 会得到空字典 {};真实 QPU 上可通过 QCloudOptions.set_is_prob_counts(False) 请求原始计数。

9.2 监控长时间运行的任务 ​

当提交到真实 QPU 时,任务可能在队列中花费大量时间。以下是一个健壮的监控模式:

python
import time
from pyqpanda3.qcloud import QCloudJob, JobStatus

# Reconstruct job reference from a saved ID
saved_job_id = "ABC123DEF456"
job = QCloudJob(saved_job_id)

# Poll with exponential backoff
wait_times = [2, 4, 8, 15, 30, 60]  # seconds
attempt = 0

while True:
    status = job.status()
    print(f"[{time.strftime('%H:%M:%S')}] Job {saved_job_id}: {status}")

    if status == JobStatus.FINISHED:
        result = job.result()
        counts = result.get_counts()
        print(f"Final counts: {counts}")
        break

    if status == JobStatus.FAILED:
        result = job.result()
        print(f"Job failed: {result.error_message()}")
        break

    # Wait with increasing delay
    wait = wait_times[min(attempt, len(wait_times) - 1)]
    attempt += 1
    time.sleep(wait)

9.3 云计算工作流图 ​

下图展示了从身份验证到结果获取的完整工作流程:

mermaid
flowchart TD
    START["Start"] --> AUTH["1. Create QCloudService<br/>with API key"]
    AUTH --> LOG["2. Optional: setup_logging()"]
    LOG --> LIST["3. List backends<br/>service.backends()"]
    LIST --> SELECT["4. Select backend<br/>service.backend(name)"]
    SELECT --> BUILD["5. Build QProg<br/>with gates and measurement"]
    BUILD --> OPTIONS["6. Configure QCloudOptions<br/>(optional)"]
    OPTIONS --> SUBMIT["7. Submit job<br/>backend.run(prog, shots)"]
    SUBMIT --> POLL{"8. Check status<br/>job.status()"}
    POLL -->|QUEUING/WAITING| WAIT["Wait 2-60 seconds"]
    WAIT --> POLL
    POLL -->|COMPUTING| WAIT2["Wait 2-30 seconds"]
    WAIT2 --> POLL
    POLL -->|FINISHED| RETRIEVE["9. Get results<br/>job.result()"]
    POLL -->|FAILED| ERROR["Check error<br/>result.error_message()"]
    RETRIEVE --> ANALYZE["10. Analyze<br/>get_probs() / get_counts()"]
    ERROR --> FIX["Fix circuit or options"]
    FIX --> BUILD
    ANALYZE --> DONE["Done"]

    style START fill:#4a90d9,color:#fff
    style SUBMIT fill:#e8913a,color:#fff
    style RETRIEVE fill:#50c878,color:#fff
    style DONE fill:#50c878,color:#fff
    style ERROR fill:#c0392b,color:#fff

9.4 任务生命周期图 ​

下图展示了任务从提交到完成所经历的状态转换:

mermaid
flowchart LR
    SUBMIT["Submit Job"] --> QUEUING["QUEUING<br/>Job enters queue"]
    QUEUING --> WAITING["WAITING<br/>Awaiting resource"]
    WAITING --> COMPUTING["COMPUTING<br/>Executing on QPU/Sim"]
    COMPUTING --> FINISHED["FINISHED<br/>Results available"]

    QUEUING -.->|error| FAILED["FAILED"]
    WAITING -.->|error| FAILED
    COMPUTING -.->|error| FAILED

    FINISHED --> PROBS["get_probs()"]
    FINISHED --> COUNTS["get_counts()"]
    FINISHED --> RAW["origin_data()"]
    FAILED --> ERRMSG["error_message()"]

    style SUBMIT fill:#4a90d9,color:#fff
    style QUEUING fill:#f39c12,color:#fff
    style WAITING fill:#f39c12,color:#fff
    style COMPUTING fill:#3498db,color:#fff
    style FINISHED fill:#27ae60,color:#fff
    style FAILED fill:#c0392b,color:#fff

10. 高级模式 ​

10.1 批量任务提交 ​

你可以在一个批次中提交多个量子程序,这比逐个提交更高效:

python
from pyqpanda3 import core
from pyqpanda3.qcloud import QCloudService, QCloudOptions

service = QCloudService("your_api_key_here")
backend = service.backend("WK_C180_2")

# Build multiple circuits
progs = []
for angle_idx in range(4):
    prog = core.QProg()
    prog << core.H(0)
    prog << core.RZ(1, angle_idx * 3.14159 / 4)
    prog << core.CNOT(0, 1)
    prog << core.measure([0, 1], [0, 1])
    progs.append(prog)

# Submit all at once
options = QCloudOptions()
options.set_amend(True)
job = backend.run(progs, shots=2000, options=options)

# Get results for all circuits
result = job.result()
probs_list = result.get_probs_list()
for i, probs in enumerate(probs_list):
    print(f"Circuit {i}: {probs}")

10.2 云端提交前的转译 ​

当目标是真实 QPU 时,线路必须与芯片的原生门集和量子比特连通性兼容。云服务器通过 QCloudOptions 中的编译选项自动处理这一点。你可以查询芯片信息来了解硬件约束,并通过 QCloudOptions 控制服务器端的编译行为:

python
from pyqpanda3 import core
from pyqpanda3.qcloud import QCloudService, QCloudOptions

service = QCloudService("your_api_key_here")
backend = service.backend("WK_C180_2")

# Query chip information to understand hardware constraints
chip_info = backend.chip_info()
print(f"Number of qubits: {chip_info.qubits_num()}")
print(f"Available qubits: {chip_info.available_qubits()}")
print(f"Basic gates: {chip_info.get_basic_gates()}")
print(f"Topology: {chip_info.get_chip_topology()}")

# Build a circuit
prog = core.QProg()
prog << core.H(0)
prog << core.CNOT(0, 1)
prog << core.CNOT(1, 2)
prog << core.measure([0, 1, 2], [0, 1, 2])

# Configure server-side compilation via QCloudOptions
options = QCloudOptions()
options.set_mapping(True)        # Enable automatic qubit mapping to chip topology
options.set_optimization(True)   # Enable circuit optimization
options.set_amend(True)          # Enable error mitigation

# Submit with compilation options -- the server handles transpilation
job = backend.run(prog, shots=3000, options=options)
result = job.result()
print(result.get_probs())

10.3 部分振幅和态层析 ​

云平台支持标准线路模拟之外的专用执行模式。

部分振幅计算 -- 仅计算态矢量的特定振幅:

python
from pyqpanda3 import core
from pyqpanda3.qcloud import QCloudService

service = QCloudService("your_api_key_here")
backend = service.backend("partial_amplitude")

prog = core.QProg()
prog << core.H(0)
prog << core.H(1)
prog << core.H(2)
prog << core.CNOT(0, 1)
prog << core.CNOT(1, 2)

# Request specific amplitudes
job = backend.run(prog, ["000", "111"])
result = job.result()
amplitudes = result.get_amplitudes()
print(f"Amplitudes: {amplitudes}")

态层析 -- 通过测量重建完整的密度矩阵(get_state_tomography_density() 返回 list[list[complex]]):

python
from pyqpanda3 import core
from pyqpanda3.qcloud import QCloudService, QCloudOptions

service = QCloudService("your_api_key_here")
backend = service.backend("WK_C180_2")

prog = core.QProg()
prog << core.H(0)
prog << core.CNOT(0, 1)

# Run state tomography
options = QCloudOptions()
job = backend.run_quantum_state_tomography(prog, 5000, options)
result = job.result()

fidelity = result.get_state_fidelity()
density = result.get_state_tomography_density()
print(f"State fidelity: {fidelity}")
print(f"Density matrix ({len(density)}x{len(density[0])}):")
for row in density:
    print(row)

10.4 0.4.0 源码与实测:原始字段、ChipBackend 与指令提交 ​

本节结合 pyqpanda3 0.4.0 源码绑定和真实 QCloud 服务校准。当前源码与云端有三点需要特别注意:

python
import os

from pyqpanda3.core import CZ, H, QProg, measure
from pyqpanda3.qcloud import QCloudOptions, QCloudService
from pyqpanda3.transpilation import Transpiler, decompose
from pyqpanda3.visualization import draw_time_scheduling

service = QCloudService(os.environ["QPANDA_QCLOUD_API_KEY"])
backend = service.backend(os.environ.get("QPANDA_QCLOUD_BACKEND", "WK_C180_2"))

chip_info = backend.chip_info()
chip_backend = backend.chip_backend([0, 10])

prog = QProg()
prog << H(0) << CZ(0, 1) << measure(0, 0) << measure(1, 1)

decomposed = decompose(prog, ["U3", "CZ"])
transpiled = Transpiler().transpile(decomposed, chip_backend, {}, 2, "fidelity")
instruction = transpiled.to_instruction(
    chip_backend,
    offset=1,
    is_scheduling=True,
    compensate_pulse=False,
)
figures = draw_time_scheduling(instruction, backend=chip_backend, output="plotly")

options = QCloudOptions()
options.set_mapping(False)
options.set_optimization(False)
options.set_amend(False)
options.set_specified_block([0, 10])

job = backend.run_instruction([instruction], shots=1000, options=options)
result = job.result(keys=["mappingQprog", "mappingQubit", "probCount"])

print(chip_backend.basic_gates)
print(chip_backend.single_gate_timing, chip_backend.double_gate_timing)
print(type(figures).__name__)
print(result.mapping_qubit() if "mappingQubit" in result else "")
print(result.timing_info())
print(result.origin_data()[:200])

示例输出形态:

text
['RPhi', 'CZ']
25 40
Figure
{"0": 10, ...}
{'totalTime': ..., 'pulseTime': ..., ...}
{"success":true,"code":10000,...

这条链路把 WK_C180_2 的 QCloud 元数据、本地转译、to_instruction(is_scheduling=True) 和时序可视化连起来。实时后端信息显示 WK_C180_2 当前可用,180 个量子比特,基础门为 RPhi / CZ,单门时序 25、双门时序 40,拓扑前缀包含 [0, 9]、[0, 10]、[1, 10] 等边。结果侧以 get_probs() / get_counts() 读取标准输出,以 mapping_qubit() 等 helper 读取已请求的原始字段,以 origin_data() 读取服务端原始 JSON,以 timing_info() 查看时间字段。

10.5 BestQubitBlocks — 最优比特选择 ​

在目标为真实 QPU 时,你通常希望为线路选择芯片上性能最佳的物理量子比特。best_qubit_blocks API 可查询云服务,获取按标定质量排序的最优量子比特块推荐。

python
from pyqpanda3.qcloud import QCloudService

service = QCloudService("your_api_key")
backend = service.backend("WK_C180_2")

# Query via QCloudService (needs chip_id)
blocks = service.best_qubit_blocks(
    chip_id="WK_C180_2",
    qubit_num=3,         # qubits per block
    label=1,             # optimization label
    qubit_block_num=2,   # number of blocks to return
)
print(blocks.chip_id)        # "WK_C180_2"
print(blocks.qubit_blocks)   # [[73, 82, 83], [90, 99, 108]]
print(blocks[0])             # [73, 82, 83]

# Query via QCloudBackend (chip_id inferred)
blocks2 = backend.best_qubit_blocks(qubit_num=2, label=1, qubit_block_num=3)
print(blocks2.qubit_blocks)  # [[59, 69], [99, 108], ...]

返回的比特块可以直接传递给 QCloudOptions.set_specified_block(),用于固定到最优比特块,从而锁定任务的物理量子比特:

python
from pyqpanda3.qcloud import QCloudOptions

options = QCloudOptions()
options.set_mapping(False)        # let the transpiler handle mapping
options.set_optimization(False)   # skip server-side optimization
options.set_specified_block(blocks[0])  # pin to the best block

job = backend.run(prog, shots=1000, options=options)

结合 BestQubitBlocks 与保真度布局 ​

推荐的工作流程是将最优比特块选择与保真度感知转译串联起来:

python
from pyqpanda3.core import H, CZ, QProg, measure
from pyqpanda3.qcloud import QCloudService, QCloudOptions
from pyqpanda3.transpilation import Transpiler, decompose
from pyqpanda3.visualization import draw_time_scheduling

service = QCloudService("your_api_key")
backend = service.backend("WK_C180_2")

# 1. Get the best qubit block
blocks = backend.best_qubit_blocks(qubit_num=3, qubit_block_num=1)
best_block = blocks[0]

# 2. Build ChipBackend for the selected qubits
chip_backend = backend.chip_backend(best_block)

# 3. Build and transpile
prog = QProg()
prog << H(0) << CZ(0, 1) << CZ(1, 2) << measure(0, 0) << measure(1, 1) << measure(2, 2)

decomposed = decompose(prog, ["U3", "CZ"])
transpiled = Transpiler().transpile(decomposed, chip_backend, {}, 2, "fidelity")

# 4. Export and visualize
instruction = transpiled.to_instruction(
    chip_backend, offset=1, is_scheduling=True, compensate_pulse=False
)
fig = draw_time_scheduling(instruction, backend=chip_backend, title="Best-Block Schedule")
fig.savefig("best_block_schedule.png", dpi=150)

# 5. Submit to QPU
options = QCloudOptions()
options.set_mapping(False)
options.set_optimization(False)
options.set_amend(False)
options.set_specified_block(best_block)

job = backend.run_instruction([instruction], shots=2000, options=options)
result = job.result()
print(result.get_probs())

此端到端模式确保比特选择、转译、时序和提交都引用相同的最优物理量子比特。


10.6 OriginIR → 通信协议编码 与 指令还原 ​

前面几节用 to_instruction(is_scheduling=True) 把转译后的程序导出成指令 JSON,再用 run_instruction() 提交。但实际硬件链路里还有两条常用的"序列化"路径,它们在 0.4.0 引入后经常配合云端批量提交使用。

OriginIR 字符串 / 文件 → 二进制通信协议 ​

comm_protocol_encode_originir_string() 和 comm_protocol_encode_originir_file() 可以跳过构造 QProg,直接把一段 OriginIR 文本(或文件)编码成量子云的二进制通信协议字节流。配置由 CommProtocolConfig 控制:

python
from pyqpanda3.utils import CommProtocolConfig, comm_protocol_encode_originir_string

config = CommProtocolConfig()
config.shots = 2048
config.open_mapping = True
config.optimization_level = 4

originir = "QINIT 1\nCREG 1\nH q[0]\nMEASURE q[0],c[0]\n"
payload = comm_protocol_encode_originir_string(originir, config)

print(type(payload).__name__)
print(len(payload) > 0)

运行结果:

bytes
True
字段默认值含义
shots1000采样次数。
circuits_num100批量线路数量。
open_mappingTrue是否启用映射。
open_error_mitigationTrue是否启用误差缓解。
optimization_level4云端编译优化等级。

如果你手里已经是 QProg 对象,等价的做法是先用 comm_protocol_encode([prog], config) 编码——它与上面 OriginIR 直编码产出的字节流一致:

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog
from pyqpanda3.utils import CommProtocolConfig, comm_protocol_encode

originir = "QINIT 1\nCREG 1\nH q[0]\nMEASURE q[0],c[0]\n"
config = CommProtocolConfig()
config.shots = 2048

prog = convert_originir_string_to_qprog(originir)
payload_from_qprog = comm_protocol_encode([prog], config)

print(type(payload_from_qprog).__name__)
print(len(payload_from_qprog) > 0)

运行结果:

bytes
True

指令 JSON → QProg 还原 ​

to_instruction() 的逆操作是 instruction_to_qprog():把指令 JSON 还原成本地 QProg。云端返回的 convertQProg 字段(用 result(keys=["convertQProg"]) 请求并通过 QCloudResult.instructions() 读取)正是这种指令 JSON:

python
from pyqpanda3.core import instruction_to_qprog

# 假设 result 是一次 run_instruction + result(keys=["convertQProg"]) 的结果
# recovered = instruction_to_qprog(result.instructions(), qubit_offset=1)
# print(type(recovered).__name__)  # QProg

多流指令 JSON(一个 JSON 数组里有多条指令流)也由 instruction_to_qprog() 处理——传入多流时它返回 list[QProg],每条流一个程序(单流则返回单个 QProg)。详见 线路 API 参考。


11. 总结 ​

本教程介绍了 pyqpanda3 中完整的云计算工作流程:

组件用途关键方法
QCloudService身份验证和发现后端.backends() / .backend() / .best_qubit_blocks() / .setup_logging()
QCloudBackend执行线路和查询芯片信息.run() / .chip_info() / .best_qubit_blocks() / .expval_hamiltonian()
QCloudJob跟踪和获取任务状态.status() / .result() / .query() / .job_id()
QCloudResult访问测量数据.get_probs() / .get_counts() / .origin_data()
QCloudOptions配置编译和执行.set_amend() / .set_mapping() / .set_optimization()
QCloudNoiseModel为云模拟器定义噪声使用 NOISE_MODEL 和参数的构造函数

关键要点:

  1. 先进行身份验证 -- 在做任何其他事情之前,使用你的 API 密钥创建 QCloudService。
  2. 选择正确的后端 -- 使用云模拟器进行开发和验证;在需要真实量子硬件时使用真实 QPU。
  3. 任务是异步的 -- 提交后,轮询 job.status() 直到 FINISHED 或 FAILED。
  4. 结果有多种格式 -- 使用 DataBase.Binary 获取人类可读的输出,使用 DataBase.Hex 获取紧凑表示。
  5. 噪声模型仅适用于模拟器 -- 真实硬件具有固有噪声;软件噪声模型仅适用于云模拟器。
  6. 使用 QCloudOptions 控制编译 -- 通过 set_mapping()、set_optimization() 和 set_amend() 配置服务器端的线路编译和错误缓解。
  7. 使用 BestQubitBlocks 选择最优量子比特 -- 通过 best_qubit_blocks() 查询按标定质量排序的物理量子比特块,然后使用 QCloudOptions.set_specified_block() 固定到最优比特块。

后续学习:


快速参考 ​

python
from pyqpanda3 import core
from pyqpanda3.qcloud import (
    QCloudService, QCloudJob, QCloudOptions,
    QCloudNoiseModel, BestQubitBlocks,
    DataBase, NOISE_MODEL,
    LogOutput,
)
import os

# ===========================
# Authentication
# ===========================
service = QCloudService(os.environ["QPANDA_QCLOUD_API_KEY"])
service.setup_logging(output=LogOutput.CONSOLE)

# ===========================
# Backend Discovery
# ===========================
backends = service.backends()           # dict[str, bool] mapping names to availability
qpu_backend = service.backend("WK_C180_2")  # Real QPU
sim_backend = service.backend("full_amplitude") # Cloud simulator

# ===========================
# Chip Information (QPU only)
# ===========================
chip_info = qpu_backend.chip_info()
print(f"Qubits: {chip_info.qubits_num()}")
print(f"Available: {chip_info.available_qubits()}")
print(f"Topology: {chip_info.get_chip_topology()}")

# ===========================
# Optimal Qubit Selection
# ===========================
# Via QCloudService
blocks = service.best_qubit_blocks("WK_C180_2", qubit_num=3, qubit_block_num=1)
best_block = blocks[0]  # e.g., [73, 82, 83]

# Via QCloudBackend (chip_id inferred)
blocks = qpu_backend.best_qubit_blocks(qubit_num=2, qubit_block_num=2)
print(blocks.qubit_blocks)

# ===========================
# Submit a Job
# ===========================
prog = core.QProg()
prog << core.H(0) << core.CNOT(0, 1)
prog << core.measure([0, 1], [0, 1])

# Simulator: run(prog, shots) or run(prog, shots, model)
job = sim_backend.run(prog, shots=3000)

# QPU: run(prog, shots, options)
options = QCloudOptions()
options.set_amend(True)
options.set_mapping(True)
job = qpu_backend.run(prog, shots=3000, options=options)

# Simulator with noise model
noise = QCloudNoiseModel(
    NOISE_MODEL.DEPOLARIZING_KRAUS_OPERATOR,
    [0.001], [0.01]
)
job = sim_backend.run(prog, shots=3000, model=noise)

# ===========================
# Monitor Job
# ===========================
job_id = job.job_id()
status = job.status()

# Reconstruct from saved job ID
job = QCloudJob(job_id)

# ===========================
# Get Results
# ===========================
result = job.result()
probs = result.get_probs(base=DataBase.Binary)
# Note: probability-type results (default is_prob_counts=True) have empty get_counts();
# to read raw counts, set is_prob_counts=False via QCloudOptions on a real QPU
counts = result.get_counts(base=DataBase.Binary)
raw = result.origin_data()

# ===========================
# Expectation Values
# ===========================
from pyqpanda3.hamiltonian import Hamiltonian
h = Hamiltonian({"X0 Y1": 1.0, "Z0 Z1": 0.5})
expval = qpu_backend.expval_hamiltonian(prog, h, QCloudOptions())

# ===========================
# Noise Model
# ===========================
noise = QCloudNoiseModel(
    NOISE_MODEL.DEPOLARIZING_KRAUS_OPERATOR,
    [0.001], [0.01]
)
noise.is_enabled()            # True
noise.get_noise_model()       # DEPOLARIZING_KRAUS_OPERATOR
noise.get_single_params()     # [0.001]
noise.get_double_params()     # [0.01]
noise.set_single_params([0.002])
noise.print()

Released under the MIT License.