|
1 | 1 | from typing import Optional
|
2 | 2 |
|
3 |
| -from qibo import Circuit |
| 3 | +from qibo import Circuit, gates |
4 | 4 | from qibo.backends import Backend
|
5 | 5 | from qibo.transpiler.pipeline import Passes
|
6 | 6 | from qibo.transpiler.unroller import NativeGates, Unroller
|
| 7 | +from qibolab.compilers.compiler import Compiler |
| 8 | +from qibolab.pulses import PulseSequence |
7 | 9 | from qibolab.qubits import QubitId
|
8 | 10 |
|
| 11 | +REPLACEMENTS = { |
| 12 | + "RX": "GPI2", |
| 13 | + "MZ": "M", |
| 14 | +} |
| 15 | + |
9 | 16 |
|
10 | 17 | def transpile_circuits(
|
11 | 18 | circuits: list[Circuit],
|
@@ -97,19 +104,70 @@ def execute_transpiled_circuit(
|
97 | 104 | backend,
|
98 | 105 | transpiler,
|
99 | 106 | )[0]
|
100 |
| - |
101 | 107 | return transpiled_circ, backend.execute_circuit(
|
102 | 108 | transpiled_circ, initial_state=initial_state, nshots=nshots
|
103 | 109 | )
|
104 | 110 |
|
105 | 111 |
|
| 112 | +def natives(platform): |
| 113 | + """ |
| 114 | + Return the list of native gates defined in the `platform`. |
| 115 | + This function assumes the native gates to be the same for each |
| 116 | + qubit and pair. |
| 117 | + """ |
| 118 | + pair = next(iter(platform.pairs.values())) |
| 119 | + qubit = next(iter(platform.qubits.values())) |
| 120 | + two_qubit_natives = list(pair.native_gates.raw) |
| 121 | + single_qubit_natives = list(qubit.native_gates.raw) |
| 122 | + # Solve Qibo-Qibolab mismatch |
| 123 | + single_qubit_natives.append("RZ") |
| 124 | + single_qubit_natives.append("Z") |
| 125 | + single_qubit_natives.remove("RX12") |
| 126 | + new_single_natives = [REPLACEMENTS.get(i, i) for i in single_qubit_natives] |
| 127 | + return new_single_natives + two_qubit_natives |
| 128 | + |
| 129 | + |
| 130 | +def create_rule(native): |
| 131 | + def rule(qubits_ids, platform, parameters=None): |
| 132 | + if len(qubits_ids[1]) == 1: |
| 133 | + native_gate = platform.qubits[tuple(qubits_ids[1])].native_gates |
| 134 | + else: |
| 135 | + native_gate = platform.pairs[tuple(qubits_ids[1])].native_gates |
| 136 | + pulses = getattr(native_gate, native).pulses |
| 137 | + return PulseSequence(pulses), {} |
| 138 | + |
| 139 | + return rule |
| 140 | + |
| 141 | + |
| 142 | +def set_compiler(backend, natives_): |
| 143 | + """ |
| 144 | + Set the compiler to execute the native gates defined by the platform. |
| 145 | + """ |
| 146 | + compiler = backend.compiler |
| 147 | + rules = {} |
| 148 | + for native in natives_: |
| 149 | + gate = getattr(gates, native) |
| 150 | + if gate not in compiler.rules: |
| 151 | + rules[gate] = create_rule(native) |
| 152 | + else: |
| 153 | + rules[gate] = compiler.rules[gate] |
| 154 | + rules[gates.I] = compiler.rules[gates.I] |
| 155 | + backend.compiler = Compiler(rules=rules) |
| 156 | + |
| 157 | + |
106 | 158 | def dummy_transpiler(backend: Backend) -> Passes:
|
107 | 159 | """
|
108 | 160 | If the backend is `qibolab`, a transpiler with just an unroller is returned,
|
109 |
| - otherwise None. |
| 161 | + otherwise `None`. This function overwrites the compiler defined in the |
| 162 | + backend, taking into account the native gates defined in the`platform` (see |
| 163 | + :func:`set_compiler`). |
110 | 164 | """
|
111 |
| - unroller = Unroller(NativeGates.default()) |
112 |
| - return Passes(connectivity=backend.platform.topology, passes=[unroller]) |
| 165 | + platform = backend.platform |
| 166 | + native_gates = natives(platform) |
| 167 | + set_compiler(backend, native_gates) |
| 168 | + native_gates = [getattr(gates, x) for x in native_gates] |
| 169 | + unroller = Unroller(NativeGates.from_gatelist(native_gates)) |
| 170 | + return Passes(connectivity=platform.topology, passes=[unroller]) |
113 | 171 |
|
114 | 172 |
|
115 | 173 | def pad_circuit(nqubits, circuit: Circuit, qubit_map: list[int]) -> Circuit:
|
|
0 commit comments