Snowflurry™ v0.5.0 is released!


Snowflurry™ v0.5.0
Snowflurry™ ❄️ v0.5.0 is our fifth release of SnowflurrySDK in 2024, which includes several improvements.
Automatically increase qubit_count during transpilation
When a circuit is transpiled for a particular QPU, and the original circuit's qubit_count cannot accommodate the transpiled circuit, the qubit_count is increased automatically. For instance, consider the following circuit:
julia> circuit = QuantumCircuit(qubit_count=2, instructions=[control_x(1,2), readout(2,1)])
Quantum Circuit Object:
qubit_count: 2
bit_count: 2
q[1]:──*───────
|
q[2]:──X────✲──
In order to perform it on an AnyonYamaskaQPU, with the following connectivity:
julia> Snowflurry.AnyonYamaskaConnectivity
LatticeConnectivity{6,4}
1
|
9 ── 5 ── 2
| | |
17 ── 13 ── 10 ── 6 ── 3
| | | | |
21 ── 18 ── 14 ── 11 ── 7 ── 4
| | | | |
22 ── 19 ── 15 ── 12 ── 8
| | |
23 ── 20 ── 16
|
24
the gate must be padded with Swaps so that qubits number 1 and 2 can interact. However, that would mean interacting with qubits beyond the original qubit_count.
The transpiler for the AnyonYamaskaQPU solves this automatically:
julia> transpiler = Snowflurry.get_anyon_transpiler(connectivity=Snowflurry.AnyonYamaskaConnectivity);
julia> transpiled_circuit = transpile(transpiler, circuit)
Quantum Circuit Object:
qubit_count: 5
bit_count: 2
Part 1 of 3
q[1]:───────────────────────────────────────────────────────────────────────────────────────────────────
q[2]:──Z────Z────Z_m90────────────X_90────Z_90─────────────────────Z────Z_90─────────────X_90────Z_m90──
| |
q[3]:───────|──────────────────────────────────────────────────────|────────────────────────────────────
| |
q[4]:───────|──────────────────────────────────────────────────────|────────────────────────────────────
| |
q[5]:───────*─────────────Z_90────────────────────X_90────Z_m90────*────────────Z_m90───────────────────
Part 2 of 3
q[1]:───────────────────────*──────────────────────────────────────────────────────────────────────
|
q[2]:──────────────────Z────|────Z────Z_m90────────────X_90────Z_90─────────────────────Z────Z_90──
| | | |
q[3]:──────────────────|────|────|──────────────────────────────────────────────────────|──────────
| | | |
q[4]:──────────────────|────|────|──────────────────────────────────────────────────────|──────────
| | | |
q[5]:──X_90────Z_90────*────Z────*─────────────Z_90────────────────────X_90────Z_m90────*──────────
Part 3 of 3
q[1]:─────────────────────────────────────────────────────────
q[2]:───────────X_90────Z_m90────────────────────Z────Z────✲──
|
q[3]:────────────────────────────────────────────|────────────
|
q[4]:────────────────────────────────────────────|────────────
|
q[5]:──Z_m90─────────────────────X_90────Z_90────*────────────
Note that the transpiled_circuit's qubit_count is now 5.
Transpiler rejects gates targetting excluded positions or excluded connections.
When a QPU reports that some qubit or couplers are out of commission (for maintenance or due to technical issues), the transpiler now automatically knows to avoid those, i.e, not use excluded_positions (qubit numbers) nor excluded connections (links between qubits, i.e., couplers) during tranpilation.
The current excluded_positions and excluded_connections can be queried from Thunderhead using the get_connectivity() function:
julia> user = ENV["THUNDERHEAD_USER"];
julia> token = ENV["THUNDERHEAD_API_TOKEN"];
julia> host = ENV["THUNDERHEAD_HOST"];
julia> project_id = ENV["THUNDERHEAD_PROJECT_ID"];
julia> realm = ENV["THUNDERHEAD_REALM"];
julia> qpu = AnyonYamaskaQPU(
host = host,
user = user,
access_token = token,
project_id = project_id,
realm = realm,
);
julia> connectivity = get_connectivity(qpu)
LatticeConnectivity{6,4}
1
|
9 ── 5 ── 2
| | |
17 ── 13 ── 10 ── 6 ── 3
| | | | |
21 ── 18 ── 14 ── 11 ── 7 ── 4
| | | | |
22 ── 19 ── 15 ── 12 ── 8
| | |
23 ── 20 ── 16
|
24
excluded positions: [11, 15, 16, 20]
excluded connections: [(7, 12)]
A 2-qubit gate that targets qubits 7 and 12, must be padded with Swaps to circumvent the disconnected coupler between qubits 7 and 12. It must do so given the excluded positions at 11, 15, 16 and 20. Internally, the transpiler relies on the path_search() function to find the shortest path given such constraints, which can then be visualized with the Snowflurry.print_connectivity(), which yields the path highlighted with (#).
julia> path = Snowflurry.path_search(7, 12, connectivity)
4-element Vector{Int64}:
12
8
4
7
julia> Snowflurry.print_connectivity(connectivity, path)
1
|
9 ── 5 ── 2
| | |
17 ── 13 ── 10 ── 6 ── 3
| | | | |
21 ── 18 ── 14 ── 11 ── (7)── (4)
| | | | |
22 ── 19 ── 15 ──(12)── (8)
| | |
23 ── 20 ── 16
|
24