pyqpanda3 v0.3.5 is a comprehensive release that delivers the built-in visualization module — one of the most requested features from our community — along with better observability into cloud job execution and fixes for several correctness bugs.
Visualization Module
We're introducing the pyqpanda3.visualization module — a comprehensive toolkit for rendering quantum circuits, plotting Bloch spheres, and visualizing state vectors and probability distributions. The module is built on matplotlib and provides both quick one-liner functions and detailed plotting APIs:
from pyqpanda3 import visualization
from pyqpanda3.core import H, X, CNOT, measure, QProg
# Circuit drawing (ASCII art)
prog = QProg()
prog << H(0) << X(1) << CNOT(0, 1) << measure(0, 0) << measure(1, 1)
print(prog.draw())For state visualization, you can generate city plots, density matrices, and Bloch sphere representations:
from pyqpanda3.core import H, CNOT, QProg, CPUQVM
qvm = CPUQVM()
prog = QProg()
prog << H(0) << CNOT(0, 1)
qvm.run(prog)
state = qvm.get_qstate()
# City plot, density matrix, or Bloch sphere
visualization.plot_state(state, kind='city', title='State City Plot')The module also includes circuit statistics — gate counts, depth, and width — accessible through circuit_info() functions. See the visualization API docs for the full reference.
Improved Cloud Error Handling
Previously, when a cloud job failed, the SDK would throw an unhandled exception, making it difficult to diagnose issues in production pipelines. Now, errors are stored in the QCloudResult object and can be retrieved gracefully:
result = job.result()
if result.error_message():
print(f"Job {result.job_id()} failed: {result.error_message()}")We've also added the job_id() method to QCloudResult so you can always trace which task produced a given result — especially useful when running many jobs in parallel.
ECHO Gate with Duration Parameter
The ECHO gate now accepts an optional param parameter (default 0.0), making it more flexible for pulse-level circuit design:
from pyqpanda3.core import ECHO
gate = ECHO(0, param=1.5)Transpiler Fixes
This release fixes several issues in the transpiler pipeline:
- QProg.remap() now flattens nested programs before remapping, fixing incorrect qubit/cbit mappings for programs with sub-circuits or conditional blocks.
- VF2 subgraph matching no longer fails on circuits with non-contiguous qubit indices or disconnected topology nodes.
- Routing pass now correctly handles BARRIER gates and unmapped ancilla qubits.
- Empty topology — the transpiler now skips routing automatically when the chip has no connectivity edges, instead of erroring out.
Job Execution Timing
When you submit a quantum job to the cloud, understanding where time is spent is critical for optimization. v0.3.5 adds the timing_info() method to QCloudResult, which returns a dictionary containing timing information for the job:
result = job.result()
timing = result.timing_info()
print(f"QPU runtime: {timing['qpuRunTime']} ms")The dictionary contains the qpuRunTime (float) field, which records the actual time the task spends executing and completing measurements on the quantum chip, in milliseconds (ms). The value defaults to 0 if the timing data is not available for a particular job.
Bug Fixes
This release fixes several bugs that could affect correctness of quantum computations:
QCloud error reporting. Error messages now include task IDs for easier debugging, and result count mismatches for large bit systems (32+ qubits) have been resolved. Previously, for example, when QCloud returned 4000 results, only 2600 were available in the result object.
Measure interface fix. The measure() function was incorrectly passing qubit indices as both the qubit and cbit arguments. If you were measuring qubits onto different cbits, the results could be silently wrong. This is now corrected.
Expectation computation with noise models. Computing expectation values (expval_hamiltonian and expval_pauli_operator) with a noise model on machines without a GPU would previously fail. This combination is now supported on CPU-only systems.
Matrix decomposition. The decompose function would incorrectly sort qubit indices for 1–2 qubit matrices. Sorting is now skipped for these small cases, which fixes decomposition results for single-qubit gates and two-qubit operations.
IDLE gate serialization. We fixed two issues with IDLE gate parameters: a decoding bug that incorrectly applied an angle-based formula, and a range limitation that capped parameters at 16-bit values. Parameters now support the full 32-bit range (0–4,294,967,295) using dual uint64 encoding for values above 65535.
Profiling on empty circuits. The QCircuitFeatures profiling module could crash with division-by-zero when computing metrics on empty circuits. These edge cases are now handled correctly.
Breaking Changes
The QCloudResult constructor now requires two arguments: QCloudResult(result_string, job_id_str). In practice, most users obtain QCloudResult objects through QCloudJob.result() or QCloudJob.query(), so this should not affect typical workflows.
API Changes
The first parameter of expval_hamiltonian and expval_pauli_operator has been renamed from node to prog for clarity:
# Updated keyword usage:
expval_hamiltonian(prog=prog, hamiltonian=ham, shots=1000)This is a keyword argument change only — positional usage continues to work as before.
What's Next
We're focused on expanding the visualization module with new plot types and improving simulation performance for larger circuits. We also have several cloud service improvements in the pipeline.