Quantum Cloud User Guide
This guide is the map for every pyqpanda3 quantum cloud workflow: first-time cloud submission, batch algorithm experiments, hardware-aware transpilation, result inspection, and production troubleshooting. It sits above the detailed Cloud Computing tutorial and the QCloud API reference, linking each user goal to the right API.
If you only need the shortest working path, start with Submit your first cloud job. If you are running real experiments, jump to Production checklist and Troubleshooting.
Verified Environment And Current Backends
This page was checked against the pyqpanda3 0.4.0 source bindings and the live QCloud service on 2026-06-25. The tested account saw these backends:
| Backend | Type | Tested availability | Tested notes |
|---|---|---|---|
PQPUMESH8 | Real QPU | Available | 3 qubits, topology [[0, 1], [0, 2], [1, 2]], native gates CZ and RPhi, single-gate timing 30, double-gate timing 40 |
WK_C180_2 | Real QPU | Available | 180 qubits, native gates RPhi and CZ, single-gate timing 25, double-gate timing 40, topology prefix includes [0, 9], [0, 10], [1, 10] |
WK_C180 | Real QPU | Unavailable | 180 qubits; chip metadata was still readable, with single-gate timing 40 and double-gate timing 40 |
HanYuan_01 | Real QPU | Unavailable | 100 qubits, native gates RPhi and CZ, current topology was empty |
full_amplitude | Cloud simulator | Available | The Bell example ran successfully; it returned probabilities, while counts were empty in the test |
partial_amplitude | Cloud simulator | Available | chip_info() raises because this is not a real QPU backend |
single_amplitude | Cloud simulator | Available | chip_info() raises because this is not a real QPU backend |
One practical binding detail: use the instance returned by backend = service.backend(name) for workflows such as chip_backend(), run_instruction(), and best_qubit_blocks(). Chip metadata is valid only for real QPU backends; cloud simulators raise an error for chip_info().
Choose Your Path
| User | Goal | Start here |
|---|---|---|
| Quantum beginner | Understand cloud execution versus local simulation | What quantum cloud does, then Submit your first cloud job |
| pyqpanda3 user | Submit an existing QProg to a remote backend | Setup and Submit circuits |
| Algorithm developer | Run batches and read probabilities or counts | Batch experiments and Read results |
| Hardware workflow user | Use topology, fidelity, timing, and instruction streams | Real hardware workflows |
| Operator or debugger | Track jobs, inspect errors, and keep raw service fields | Job lifecycle and Troubleshooting |
What Quantum Cloud Does
Local simulators are best for development and debugging. Quantum cloud execution sends work to remote resources: real QPUs or cloud-hosted simulators.
| Capability | Purpose | Main API |
|---|---|---|
| Backend discovery | See which devices or simulators your account can use | QCloudService.backends() |
| Backend selection | Open one execution target | QCloudService.backend(name) |
| Circuit submission | Submit one or more QProg objects | QCloudBackend.run(...) |
| Instruction submission | Submit transpiled and scheduled instruction JSON | QCloudBackend.run_instruction(...) |
| Job tracking | Read job id, status, query data, and final result | QCloudJob |
| Result handling | Read probabilities, counts, amplitudes, tomography data, timing fields, and raw JSON | QCloudResult |
| Noise simulation | Attach a noise model to a cloud simulator run | QCloudNoiseModel |
| Chip metadata | Read topology, gates, timing, fidelity, and compensate angles | ChipInfo / ChipBackend |
Setup
Install pyqpanda3:
pip install pyqpanda3Store your API key outside source code:
export QPANDA_QCLOUD_API_KEY="your_api_key_here"Windows PowerShell:
$env:QPANDA_QCLOUD_API_KEY="your_api_key_here"Create the service:
import os
from pyqpanda3.qcloud import QCloudService
service = QCloudService(os.environ["QPANDA_QCLOUD_API_KEY"])Discover available backends:
for name, available in service.backends().items():
print(name, "available" if available else "unavailable")Use cloud simulators while developing. Switch to a real QPU only after local simulation and cloud simulator checks pass.
Submit Your First Cloud Job
This example builds a Bell state, submits it to the full_amplitude cloud simulator, and reads probabilities. Change QPANDA_QCLOUD_BACKEND to a backend available to your account.
import os
from pyqpanda3.core import CNOT, H, QProg, measure
from pyqpanda3.qcloud import DataBase, JobStatus, QCloudService
service = QCloudService(os.environ["QPANDA_QCLOUD_API_KEY"])
backend = service.backend(os.environ.get("QPANDA_QCLOUD_BACKEND", "full_amplitude"))
prog = QProg()
prog << H(0)
prog << CNOT(0, 1)
prog << measure([0, 1], [0, 1])
job = backend.run(prog, shots=1000)
print("job id:", job.job_id())
print("status:", job.status())
result = job.result()
print("final status:", result.job_status())
print(result.get_probs(base=DataBase.Binary))
print(result.timing_info())
if result.job_status() == JobStatus.FAILED:
print(result.error_message())In the live full_amplitude test, the returned probability distribution was close to {'0x0': 0.51, '0x3': 0.49} (hexadecimal keys). get_counts() returned {} for that tested simulator job, so this quick path reads get_probs() first. On real hardware, small 01 and 10 outcomes can appear because of device noise and readout error.
Submit Circuits
Single circuit
job = backend.run(prog, shots=3000)Use this for tutorials, single algorithm checks, and small experiments.
Batch experiments
programs = []
for index in range(4):
circuit = QProg()
circuit << H(0)
circuit << CNOT(0, 1)
circuit << measure([0, 1], [0, 1])
programs.append(circuit)
job = backend.run(programs, shots=2000)
result = job.result()
print(result.get_counts_list(base=DataBase.Binary))Read batch output with get_probs_list() or get_counts_list().
Execution options
QCloudOptions controls cloud-side mapping, optimization, amendment, and probability-count behavior. The pyqpanda3 0.4.0 source defaults are:
| Option | Default | Getter | Setter |
|---|---|---|---|
| Mapping | True | is_mapping() | set_mapping(bool) |
| Optimization | True | is_optimization() | set_optimization(bool) |
| Amendment | True | is_amend() | set_amend(bool) |
| Probability counts | True | is_prob_counts() | set_is_prob_counts(bool) |
| Point label | 1 | point_label() | set_point_label(int) |
| Specified physical block | [] | specified_block() | set_specified_block(list[int]) |
Real QPU submissions usually keep mapping and optimization enabled. Instruction submissions that were already transpiled locally usually turn cloud mapping and optimization off.
from pyqpanda3.qcloud import QCloudOptions
options = QCloudOptions()
options.set_mapping(True)
options.set_optimization(True)
options.set_amend(True)
job = backend.run(prog, shots=3000, options=options)set_custom_option() can store booleans, integers, floats, and strings. The source exposes multiple same-name get_custom_option() overloads through pybind; prefer has_custom_option() and get_custom_options() when you need stable inspection.
Noise models
Noise models apply to cloud simulator runs. Real QPUs already have physical noise.
from pyqpanda3.qcloud import NOISE_MODEL, QCloudNoiseModel
noise = QCloudNoiseModel(
NOISE_MODEL.DEPOLARIZING_KRAUS_OPERATOR,
[0.001],
[0.01],
)
job = backend.run(prog, shots=3000, model=noise)The three-argument QCloudNoiseModel constructor accepts positional arguments only.
Job Lifecycle
Cloud jobs are asynchronous. backend.run(...) returns a job handle before execution finishes.
flowchart LR
A["submit"] --> B["QUEUING"]
B --> C["WAITING"]
C --> D["COMPUTING"]
D --> E["FINISHED"]
B --> F["FAILED"]
C --> F
D --> FPoll with a delay:
import time
from pyqpanda3.qcloud import JobStatus
while True:
status = job.status()
print(status)
if status == JobStatus.FINISHED:
result = job.result()
break
if status == JobStatus.FAILED:
result = job.query()
print(result.error_message())
break
time.sleep(5)Save job.job_id() if another script needs to resume tracking with QCloudJob(job_id).
Read Results
Probabilities and counts
from pyqpanda3.qcloud import DataBase
result = job.result()
probs = result.get_probs(base=DataBase.Binary)
counts = result.get_counts(base=DataBase.Binary)For batches:
probs_list = result.get_probs_list(base=DataBase.Binary)
counts_list = result.get_counts_list(base=DataBase.Binary)Raw Fields, Raw JSON, and Timing Fields
In the pyqpanda3 0.4.0 source bindings, QCloudJob.query() and QCloudJob.result() accept keys= or key= for extra raw fields. Common fields include mappingQprog, mappingQubit, probCount, convertQProg, srcQubits, targetCbits, and measureQubits:
result = job.result(keys=["mappingQprog", "mappingQubit", "probCount"])
if "mappingQubit" in result:
print(result.mapping_qubit())
if "probCount" in result:
print(result.prob_count_raw())You can also access returned fields generically:
raw_mapping = result["mappingQprog"] if "mappingQprog" in result else ""For complete debugging, read the raw service JSON with origin_data():
import json
raw = json.loads(result.origin_data())
print(raw["success"], raw["code"], raw["message"])
print(raw["obj"]["taskId"])
print(raw["obj"].get("taskResult"))
print(result.timing_info())timing_info() returns the timing fields provided by the service. The tested full_amplitude Bell job returned fields such as startTime, totalTime, pulseTime, cirExecuteTime, compileTime, and queueTime. The field set varies by backend and task type.
Amplitudes, tomography, and fidelity
Specialized backends or task types can expose extra data:
amplitudes = result.get_amplitudes()
density = result.get_state_tomography_density()
fidelity = result.get_state_fidelity()Call these only for task types that return the matching data.
Real Hardware Workflows
Real QPUs have topology, native gates, timing, fidelity, and availability constraints. Inspect chip metadata before submission:
chip_info = backend.chip_info()
print(chip_info.qubits_num())
print(chip_info.available_qubits())
print(chip_info.get_basic_gates())
print(chip_info.get_chip_topology())Build a local ChipBackend from cloud calibration
ChipInfo.get_chip_backend() builds a local ChipBackend with topology, native gates, timing, fidelity maps, and compensate angles.
backend = service.backend("WK_C180_2")
chip_info = backend.chip_info()
chip_backend = backend.chip_backend([0, 10])Typical hardware-aware flow:
from pyqpanda3.core import CZ, H, QProg, measure
from pyqpanda3.qcloud import QCloudOptions
from pyqpanda3.transpilation import Transpiler, decompose
from pyqpanda3.visualization import draw_time_scheduling
prog = QProg()
prog << H(0)
prog << CZ(0, 1)
prog << measure(0, 0)
prog << 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,
)
figure = 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)Mapping and optimization are disabled here because the program was already transpiled and scheduled locally against the same chip metadata.
Choose physical qubit blocks
pyqpanda3 0.4.0 source exposes both entry points:
blocks_from_service = service.best_qubit_blocks("WK_C180_2", qubit_num=2, label=1, qubit_block_num=1)
blocks_from_backend = backend.best_qubit_blocks(qubit_num=2, label=1, qubit_block_num=1)If you have manually selected physical qubits from the live topology, use QCloudOptions.set_specified_block(). For example, WK_C180_2 currently includes the edge [0, 10]:
options = QCloudOptions()
options.set_specified_block([0, 10])
job = backend.run(prog, shots=1000, options=options)Before submitting, check chip_info.available_qubits() and chip_info.get_chip_topology() so the chosen physical qubits are available and connected for the two-qubit gates you need.
Expectation Value Jobs
Variational algorithms often need Hamiltonian or Pauli expectation values.
from pyqpanda3.hamiltonian import Hamiltonian, PauliOperator
from pyqpanda3.qcloud import QCloudOptions
hamiltonian = Hamiltonian({"X0 Y1": 1.1, "Z0 Z1": 0.5})
pauli_op = PauliOperator({"X0 Y1": 1.1, "Z0 Z1": 0.5})
value_h = backend.expval_hamiltonian(prog, hamiltonian, QCloudOptions())
value_p = backend.expval_pauli_operator(prog, pauli_op, QCloudOptions())Simulator paths can also use shots and noise_model.
Production Checklist
| Check | Why it matters |
|---|---|
| API key comes from an environment variable | Prevents secret leaks |
| Local simulation passes | Removes circuit construction mistakes first |
| Backend is currently available | Avoids maintenance windows or closed queues |
| Qubit count fits the backend | Oversized jobs are rejected |
| Two-qubit gates match topology or mapping is enabled | Keeps circuits executable |
shots is intentional | Controls queue time and quota usage |
job_id is saved | Enables recovery and debugging |
origin_data() and important raw fields are saved when debugging | keys= returns selected fields; origin_data() is the complete response |
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
KeyError: QPANDA_QCLOUD_API_KEY | Environment variable is missing | Set the API key before running Python |
| Backend is unavailable | Maintenance, missing account access, or closed queue | Call service.backends() and pick an available backend |
| Job stays queued | Busy QPU queue | Lower shots, use a cloud simulator, or resume later with the same job_id |
| Failed job has little detail | Only probabilities or counts were read | Use job.query(), result.error_message(), and result.origin_data() |
job.result(keys=[...]) raises TypeError | Runtime is not the 0.4.0 source binding, or the installed package is older | Check pyqpanda3.__version__ and binding source; the 0.4.0 source supports keys / key |
get_counts() returns {} | Some cloud simulator jobs return probabilities rather than counts | Read get_probs() first; check backend behavior and QCloudOptions.is_prob_counts() |
chip_info() says it is only for real QPU backend | It was called on a cloud simulator | Call chip_info() only on real QPU backends |
Noise model raises TypeError | Keyword arguments were used | Use positional arguments: QCloudNoiseModel(NOISE_MODEL.X, [...], [...]) |
| Real QPU differs from local simulation | Hardware noise, readout error, and topology constraints | Inspect chip fidelity, increase shots, or use amendment options |
Next Steps
- Cloud Computing tutorial: longer end-to-end teaching guide.
- QCloud API reference: all classes, methods, overloads, and enums.
- Transpilation tutorial: prepare circuits for hardware constraints.
- Fidelity layout QCloud tutorial: connect cloud calibration, fidelity-aware layout, and timing visualization.
- Time Scheduling API: inspect scheduled instructions before submission.