Skip to content

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:

BackendTypeTested availabilityTested notes
PQPUMESH8Real QPUAvailable3 qubits, topology [[0, 1], [0, 2], [1, 2]], native gates CZ and RPhi, single-gate timing 30, double-gate timing 40
WK_C180_2Real QPUAvailable180 qubits, native gates RPhi and CZ, single-gate timing 25, double-gate timing 40, topology prefix includes [0, 9], [0, 10], [1, 10]
WK_C180Real QPUUnavailable180 qubits; chip metadata was still readable, with single-gate timing 40 and double-gate timing 40
HanYuan_01Real QPUUnavailable100 qubits, native gates RPhi and CZ, current topology was empty
full_amplitudeCloud simulatorAvailableThe Bell example ran successfully; it returned probabilities, while counts were empty in the test
partial_amplitudeCloud simulatorAvailablechip_info() raises because this is not a real QPU backend
single_amplitudeCloud simulatorAvailablechip_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 ​

UserGoalStart here
Quantum beginnerUnderstand cloud execution versus local simulationWhat quantum cloud does, then Submit your first cloud job
pyqpanda3 userSubmit an existing QProg to a remote backendSetup and Submit circuits
Algorithm developerRun batches and read probabilities or countsBatch experiments and Read results
Hardware workflow userUse topology, fidelity, timing, and instruction streamsReal hardware workflows
Operator or debuggerTrack jobs, inspect errors, and keep raw service fieldsJob 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.

CapabilityPurposeMain API
Backend discoverySee which devices or simulators your account can useQCloudService.backends()
Backend selectionOpen one execution targetQCloudService.backend(name)
Circuit submissionSubmit one or more QProg objectsQCloudBackend.run(...)
Instruction submissionSubmit transpiled and scheduled instruction JSONQCloudBackend.run_instruction(...)
Job trackingRead job id, status, query data, and final resultQCloudJob
Result handlingRead probabilities, counts, amplitudes, tomography data, timing fields, and raw JSONQCloudResult
Noise simulationAttach a noise model to a cloud simulator runQCloudNoiseModel
Chip metadataRead topology, gates, timing, fidelity, and compensate anglesChipInfo / ChipBackend

Setup ​

Install pyqpanda3:

bash
pip install pyqpanda3

Store your API key outside source code:

bash
export QPANDA_QCLOUD_API_KEY="your_api_key_here"

Windows PowerShell:

powershell
$env:QPANDA_QCLOUD_API_KEY="your_api_key_here"

Create the service:

python
import os

from pyqpanda3.qcloud import QCloudService

service = QCloudService(os.environ["QPANDA_QCLOUD_API_KEY"])

Discover available backends:

python
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.

python
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 ​

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

Use this for tutorials, single algorithm checks, and small experiments.

Batch experiments ​

python
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:

OptionDefaultGetterSetter
MappingTrueis_mapping()set_mapping(bool)
OptimizationTrueis_optimization()set_optimization(bool)
AmendmentTrueis_amend()set_amend(bool)
Probability countsTrueis_prob_counts()set_is_prob_counts(bool)
Point label1point_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.

python
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.

python
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.

mermaid
flowchart LR
    A["submit"] --> B["QUEUING"]
    B --> C["WAITING"]
    C --> D["COMPUTING"]
    D --> E["FINISHED"]
    B --> F["FAILED"]
    C --> F
    D --> F

Poll with a delay:

python
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 ​

python
from pyqpanda3.qcloud import DataBase

result = job.result()
probs = result.get_probs(base=DataBase.Binary)
counts = result.get_counts(base=DataBase.Binary)

For batches:

python
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:

python
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:

python
raw_mapping = result["mappingQprog"] if "mappingQprog" in result else ""

For complete debugging, read the raw service JSON with origin_data():

python
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:

python
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:

python
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.

python
backend = service.backend("WK_C180_2")
chip_info = backend.chip_info()
chip_backend = backend.chip_backend([0, 10])

Typical hardware-aware flow:

python
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:

python
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]:

python
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.

python
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 ​

CheckWhy it matters
API key comes from an environment variablePrevents secret leaks
Local simulation passesRemoves circuit construction mistakes first
Backend is currently availableAvoids maintenance windows or closed queues
Qubit count fits the backendOversized jobs are rejected
Two-qubit gates match topology or mapping is enabledKeeps circuits executable
shots is intentionalControls queue time and quota usage
job_id is savedEnables recovery and debugging
origin_data() and important raw fields are saved when debuggingkeys= returns selected fields; origin_data() is the complete response

Troubleshooting ​

SymptomLikely causeFix
KeyError: QPANDA_QCLOUD_API_KEYEnvironment variable is missingSet the API key before running Python
Backend is unavailableMaintenance, missing account access, or closed queueCall service.backends() and pick an available backend
Job stays queuedBusy QPU queueLower shots, use a cloud simulator, or resume later with the same job_id
Failed job has little detailOnly probabilities or counts were readUse job.query(), result.error_message(), and result.origin_data()
job.result(keys=[...]) raises TypeErrorRuntime is not the 0.4.0 source binding, or the installed package is olderCheck pyqpanda3.__version__ and binding source; the 0.4.0 source supports keys / key
get_counts() returns {}Some cloud simulator jobs return probabilities rather than countsRead get_probs() first; check backend behavior and QCloudOptions.is_prob_counts()
chip_info() says it is only for real QPU backendIt was called on a cloud simulatorCall chip_info() only on real QPU backends
Noise model raises TypeErrorKeyword arguments were usedUse positional arguments: QCloudNoiseModel(NOISE_MODEL.X, [...], [...])
Real QPU differs from local simulationHardware noise, readout error, and topology constraintsInspect chip fidelity, increase shots, or use amendment options

Next Steps ​

Released under the MIT License.