Skip to content

0.4.0 ​

pyqpanda3 0.4.0 is a hardware-workflow release. The individual commits are connected by one theme: move between cloud chip metadata, fidelity-aware transpilation, native instruction JSON, instruction recovery, and schedule visualization without losing context.

1. QCloud Chip Metadata -> Scheduled Instructions -> Result Recovery ​

The most important QCloud change in 0.4.0 is not just that more fields can be returned. It is that the full hardware path now stays connected: chip metadata creates a ChipBackend, the ChipBackend drives fidelity layout and instruction timing, the scheduled instruction stream can be visualized before submission, and QCloud result fields can be converted back into local objects.

Credential-dependent example:

python
import os

from pyqpanda3.core import CZ, H, QProg, instruction_to_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"))

chip_info = backend.chip_info()
chip_backend = chip_info.get_chip_backend()

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)

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

print(chip_backend.single_gate_timing, chip_backend.double_gate_timing)
print(type(figures).__name__)
print("convertQProg" in result)
print("mappingQprog" in result)
print("mappingQubit" in result)

if "convertQProg" in result:
    recovered = instruction_to_qprog(result.instructions(), qubit_offset=1)
    print(type(recovered).__name__)

Example output shape:

text
40 80
Figure
True
True
True
QProg

Local instruction-round-trip example:

python
import json

from pyqpanda3.core import instruction_to_qprog
from pyqpanda3.visualization import draw_time_scheduling, parse_instruction_schedule

single_stream = [
    {"RPhi": [1, 90.0, 0.0, 0]},
    {"CZ": [1, 2, 40]},
    {"Measure": [[2, 1], 120]},
]

prog = instruction_to_qprog(json.dumps(single_stream), qubit_offset=1)
programs = instruction_to_qprog(
    json.dumps([single_stream, single_stream]),
    qubit_offset=1,
    insert_barrier=False,
)
items = parse_instruction_schedule(single_stream, durations={"RPhi": 40, "CZ": 40})
fig = draw_time_scheduling(single_stream, durations={"RPhi": 40, "CZ": 40})
fig.savefig("schedule-v040.png", dpi=160)

print(type(prog).__name__)
print(type(programs).__name__, len(programs))
print(items[0].name, items[0].end_time)
print("schedule-v040.png")

Output:

text
QProg
list 2
RPhi 40.0
schedule-v040.png

2. Fidelity Layout -> Transpile -> Native Instruction Export ​

The fidelity-layout commits and transpile(backend, ..., layout_method="fidelity") fixes are intended to be used together. fidelity_layout() computes an initial mapping from topology and fidelity maps; Transpiler().transpile(..., "fidelity") can apply that idea internally; QProg.to_instruction() then exports backend-native instructions with optional CZ compensation.

python
from pyqpanda3.core import CZ, H, QProg, measure
from pyqpanda3.transpilation import ChipBackend, Transpiler, fidelity_layout

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

backend = ChipBackend()
backend.chip_topology_edges = [[0, 1], [1, 2]]
backend.basic_gates = ["RPhi", "CZ"]
backend.single_gate_fidelity = {0: 0.99, 1: 0.99, 2: 0.99}
backend.readout_fidelity = {0: 0.90, 1: 0.90, 2: 0.99}
backend.double_gate_fidelity = {(0, 1): 0.90, (1, 2): 0.99}

mapping = fidelity_layout(
    prog,
    backend.chip_topology_edges,
    backend.single_gate_fidelity,
    backend.readout_fidelity,
    backend.double_gate_fidelity,
)
transpiled = Transpiler().transpile(prog, backend, {}, 1, "fidelity")

print(mapping)
print(len(transpiled.operations()) > 0)

Output from the documented backend:

text
{0: 2, 1: 1}
True

For instruction export, first decompose into the gate family accepted by virtual_z(), then export:

python
import json

from pyqpanda3.core import CZ, H, QProg, measure
from pyqpanda3.transpilation import ChipBackend, decompose, virtual_z

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

backend = ChipBackend()
backend.chip_topology_edges = [[0, 1], [1, 2]]
backend.basic_gates = ["RPhi", "CZ"]
backend.single_gate_timing = 40
backend.double_gate_timing = 80

ready = virtual_z(decompose(prog, ["X1", "RZ", "CZ"]))
instruction_json = ready.to_instruction(
    backend,
    offset=1,
    is_scheduling=True,
    compensate_pulse=False,
)
instructions = json.loads(instruction_json)

print(type(instruction_json).__name__, len(instructions))
print(instructions[0])

Output:

text
str 3
{'RPhi': [1, 270.0, 90.0, 0]}

3. OriginIR -> Protocol Encoding ​

The OriginIR communication-protocol update lets workflows that already produce OriginIR enter the binary protocol layer directly.

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

config = CommProtocolConfig()
config.shots = 2048

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

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

Example output:

text
bytes
True

4. Topology-Aware State Preparation ​

Encode.topology_aware_mps_encode() prepares an approximate amplitude-encoding circuit while respecting a connected topology.

python
from pyqpanda3.core import Encode

data = [0.25] * 16
topology = [[0, 1], [1, 2], [2, 3]]

encoder = Encode()
encoder.topology_aware_mps_encode([0, 1, 2, 3], data, topology, depth=3)

print(type(encoder.get_circuit()).__name__)
print(round(encoder.get_fidelity(data), 6))

Output:

text
QCircuit
1.0

API Changes ​

Released under the MIT License.