0.3.5
New Features and Important Updates
1. Added the visualization module for quantum state, circuit, and probability visualization.
The new pyqpanda3.visualization module provides Bloch sphere plotting, quantum state visualization (city plots, density matrices), probability distribution charts, circuit drawing (text/pic/latex), and circuit statistics.
from pyqpanda3 import visualization
# Circuit drawing
from pyqpanda3.core import H, X, CNOT, measure, QProg
prog = QProg()
prog << H(0) << X(1) << CNOT(0, 1) << measure(0, 0) << measure(1, 1)
print(prog.draw())
# State visualization
from pyqpanda3.core import H, CNOT, measure, QProg, CPUQVM
import numpy as np
qvm = CPUQVM()
prog = QProg()
prog << H(0) << CNOT(0, 1)
qvm.run(prog)
state = qvm.get_qstate()
from pyqpanda3 import visualization
visualization.plot_state(state, kind='city', title='State City Plot')2. Improved QCloudResult error handling — errors are now stored in the result instead of throwing exceptions.
Previously, cloud task failures would throw unhandled exceptions. Now, errors are stored in QCloudResult and can be retrieved via error_message() and job_id() methods.
result = job.result()
if result.error_message():
print(f"Job {result.job_id()} failed: {result.error_message()}")3. ECHO gate now supports an optional duration parameter.
The ECHO gate accepts an optional param parameter (default 0.0) for specifying duration.
from pyqpanda3.core import ECHO
gate = ECHO(0, param=1.5)4. Added timing_info() method to QCloudResult.
The new method returns a dictionary containing timing information for quantum job execution:
qpuRunTime(float): QPU runtime, the actual time the task spends executing and completing measurements on the quantum chip, in milliseconds (ms)
result = job.result()
timing = result.timing_info()
print(f"QPU runtime: {timing['qpuRunTime']} ms")5.Linux compilation now requires GCC 8.5 or above.
6.Python version support is now 3.10–3.14; Python 3.9 is no longer supported.
Bug Fixes
5. Fixed QProg.remap() to flatten nested programs before remapping.
Previously, calling remap() on programs with sub-circuits or conditional blocks could produce incorrect qubit/cbit mappings. Now the program is flattened first.
6. Fixed VF2 subgraph matching for sparse graph topologies.
The transpiler's initial qubit layout could fail on circuits with non-contiguous qubit indices or disconnected nodes. This is now corrected.
7. Fixed routing pass handling of unmapped qubits and BARRIER gates.
Circuits with BARRIER gates or ancilla qubits not part of the VF2 mapping now compile correctly.
8. Transpiler now automatically skips routing when chip topology has no connectivity edges.
Compilation for unconstrained targets (empty edge list) now succeeds without errors.
9. Fixed hex/binary conversion for measurement results with more than 8 qubits.
Measurement results from cloud backends with larger qubit counts now produce correct probability distributions.
10. Enhanced QCloud error reporting with task ID information.
When QCloud task result requests fail, the error message now includes the task ID for easier debugging and issue tracking. Improved error handling mechanisms provide more detailed error information.
11. Fixed QCloud result count mismatch for large bit systems (32+ qubits).
Fixed a bug where the number of results returned by QCloud for large bit systems (32 qubits or more) did not match the number of results after base conversion. Previously, for example, when QCloud returned 4000 results, only 2600 were available in the result object. This issue has been resolved.
from pyqpanda3.core import H, measure, QProg
from pyqpanda3.qcloud import QCloudService, QCloudOptions, QCloudJob
prog = QProg()
prog << H(0) << measure(0, 0) << measure(1, 1)
# Get your real API token from https://account.originqc.com.cn/
api_key = "your_api_key"
service = QCloudService(api_key=api_key)
job = QCloudJob("task_id")
result = job.result()
for result_list in result.get_probs_list():
print(result_list)12. Fixed measure() interface passing wrong cbits parameter.
The measure() function was incorrectly passing qubits as both the qubit and cbit arguments. This has been corrected so that the specified cbits are used properly.
13. Fixed IDLE gate parameter encoding/decoding.
- Fixed the decoding bug where IDLE gate parameters were incorrectly converted using an angle-based formula.
- Extended IDLE gate parameter range from 16-bit to 32-bit (0–4294967295) using dual uint64 encoding.
- IDLE gate parameters ≤ 65535 use single uint64; parameters > 65535 use dual uint64 with a resume mechanism.
14. Fixed expval_hamiltonian and expval_pauli_operator error when using noise model without GPU.
Fixed a bug where expectation value computation would fail on machines without a GPU when both a noise model and a backend type were specified.
15. Fixed decompose error for 1–2 qubit matrices.
The decompose function would incorrectly sort qubit indices for matrices with 1–2 qubits. Sorting is now skipped for these cases.
16. Fixed profiling module division-by-zero errors on empty circuits.
The profiling module (QCircuitFeatures) could crash with division-by-zero when computing connectivity, liveness, parallelism, entanglement, or depth metrics on empty circuits. These edge cases are now handled correctly.
17. Fixed BARRIER gate mapping errors in transpiler.
Fixed multiple barrier-related bugs in the transpiler: VF2 subgraph matching for sparse graph topologies, routing pass handling of unmapped qubits and BARRIER gates, and BARRIER gate errors in the DAG construction. Circuits with BARRIER gates or ancilla qubits not part of the VF2 mapping now compile correctly.
18. Fixed visualization measurement support and LaTeX output.
Improved the visualization module to correctly handle measurement gates in circuit diagrams. Fixed LaTeX output to produce correct circuit representations and support saving to files. The circuit layering algorithm now uses sequential layering to preserve correct timing for measurements.
19. Fixed GPU code compilation for CUDA 13.2.
Resolved compilation errors when building the GPU quantum virtual machine module against CUDA Toolkit 13.2.
20. Fixed transpile Python interface for ChipBackend parameter type mismatch.
The transpile function's Python binding was incorrectly passing ChipBackend values, causing type errors. This is now corrected.
21. Fixed pybinder return value policy for all .def() bindings.
Added explicit py::return_value_policy::automatic to all Pybinder .def() calls, preventing potential memory management issues when Python code accesses C++ objects through bindings.
Breaking Changes
QCloudResult constructor now requires two arguments.
The QCloudResult constructor changed from QCloudResult(result_string) to QCloudResult(result_string, job_id_str). In most cases, QCloudResult objects are obtained through QCloudJob.result() or QCloudJob.query() rather than constructed directly, so this should not affect most users.
API Changes
expval_hamiltonian and expval_pauli_operator parameter renamed: node → prog.
The first parameter of expval_hamiltonian and expval_pauli_operator has been renamed from node to prog for clarity. This is a keyword argument change only; positional usage is unaffected.
# Before (still works positionally):
expval_hamiltonian(prog, ham, shots=1000)
# Updated keyword usage:
expval_hamiltonian(prog=prog, hamiltonian=ham, shots=1000)QGate.dagger() and QCircuit.dagger() now return a new copy instead of modifying in place.
Previously, dagger() mutated the gate/circuit and returned a reference. Now it returns a new copy, leaving the original unchanged. Code that relied on in-place mutation should assign the result:
# Before (in-place mutation):
gate.dagger() # gate is now daggered
# After (returns new copy):
gate = gate.dagger() # must reassignQGate.control() and QCircuit.control() now return a new instance instead of modifying in place.
Previously, control() mutated the gate/circuit in place and returned a reference. Now it returns a new instance, leaving the original unchanged. Code that relied on in-place mutation should assign the result:
# Before (in-place mutation):
gate.control(0) # gate is now controlled
# After (returns new instance):
gate = gate.control(0) # must reassignChipBackend moved from qcloud to transpilation module.
ChipBackend is now exported from pyqpanda3.transpilation instead of pyqpanda3.qcloud. Update your imports accordingly:
# Before:
from pyqpanda3.qcloud import ChipBackend
# After:
from pyqpanda3.transpilation import ChipBackend