|
1 | | -using DocStringExtensions |
2 | | - |
3 | | -""" |
4 | | - $(TYPEDSIGNATURES) |
5 | | -
|
6 | | -Convert a BlockIR to a ZXCircuit. |
7 | | -
|
8 | | -This function converts YaoHIR's BlockIR representation to a ZXCircuit by translating |
9 | | -each gate operation to the corresponding ZX-diagram representation. |
10 | | -
|
11 | | -Returns a `ZXCircuit` containing the circuit representation. |
12 | | -
|
13 | | -See also: [`convert_to_zxd`](@ref) |
14 | | -""" |
15 | | -function convert_to_circuit(root::YaoHIR.BlockIR) |
16 | | - circ = ZXCircuit(root.nqubits) |
17 | | - circuit = canonicalize_single_location(root.circuit) |
18 | | - return gates_to_circ(circ, circuit, root) |
| 1 | +YaoHIR.Chain(zxd::AbstractZXCircuit) = convert_to_chain(zxd) |
| 2 | +convert_to_chain(circ::ZXCircuit) = convert_to_chain(ZXDiagram(circ)) |
| 3 | +function convert_to_chain(circ::ZXDiagram{TT, P}) where {TT, P} |
| 4 | + spider_seq = spider_sequence(circ) |
| 5 | + gates = [] |
| 6 | + for vs in spider_seq |
| 7 | + if length(vs) == 1 |
| 8 | + v = vs |
| 9 | + q = Int(qubit_loc(circ, v)) |
| 10 | + push_spider_to_chain!(gates, q, phase(circ, v), spider_type(circ, v)) |
| 11 | + elseif length(vs) == 2 |
| 12 | + v1, v2 = vs |
| 13 | + q1 = Int(qubit_loc(circ, v1)) |
| 14 | + q2 = Int(qubit_loc(circ, v2)) |
| 15 | + push_spider_to_chain!(gates, q1, phase(circ, v1), spider_type(circ, v1)) |
| 16 | + push_spider_to_chain!(gates, q2, phase(circ, v2), spider_type(circ, v2)) |
| 17 | + if spider_type(circ, v1) == SpiderType.Z && spider_type(circ, v2) == SpiderType.X |
| 18 | + push!(gates, Ctrl(Gate(X, Locations(q2)), CtrlLocations(q1))) |
| 19 | + elseif spider_type(circ, v1) == SpiderType.X && spider_type(circ, v2) == SpiderType.Z |
| 20 | + push!(gates, Ctrl(Gate(X, Locations(q1)), CtrlLocations(q2))) |
| 21 | + else |
| 22 | + error("Spiders ($v1, $v2) should represent a CNOT") |
| 23 | + end |
| 24 | + elseif length(vs) == 3 |
| 25 | + v1, h, v2 = vs |
| 26 | + spider_type(circ, h) == SpiderType.H || error("The spider $h should be a H-box") |
| 27 | + q1 = Int(qubit_loc(circ, v1)) |
| 28 | + q2 = Int(qubit_loc(circ, v2)) |
| 29 | + push_spider_to_chain!(gates, q1, phase(circ, v1), spider_type(circ, v1)) |
| 30 | + push_spider_to_chain!(gates, q2, phase(circ, v2), spider_type(circ, v2)) |
| 31 | + if spider_type(circ, v1) == SpiderType.Z && spider_type(circ, v2) == SpiderType.Z |
| 32 | + push!(gates, Ctrl(Gate(Z, Locations(q2)), CtrlLocations(q1))) |
| 33 | + else |
| 34 | + error("Spiders ($v1, $h, $v2) should represent a CZ") |
| 35 | + end |
| 36 | + else |
| 37 | + error("ZXDiagram's without circuit structure are not supported") |
| 38 | + end |
| 39 | + end |
| 40 | + return Chain(gates...) |
19 | 41 | end |
20 | 42 |
|
21 | | -""" |
22 | | - $(TYPEDSIGNATURES) |
23 | | -
|
24 | | -Convert a BlockIR to a ZXDiagram. |
25 | | -
|
26 | | -!!! warning "Deprecated" |
27 | | - `convert_to_zxd` is deprecated. Use [`convert_to_circuit`](@ref) instead. |
28 | | - This function internally converts to ZXCircuit and then wraps it in ZXDiagram. |
29 | | -
|
30 | | -Returns a `ZXDiagram` for backward compatibility. |
31 | | -""" |
32 | | -function convert_to_zxd(root::YaoHIR.BlockIR) |
33 | | - Base.depwarn("convert_to_zxd is deprecated, use convert_to_circuit instead", :convert_to_zxd) |
34 | | - circ = convert_to_circuit(root) |
35 | | - return ZXDiagram(circ) |
| 43 | +function push_spider_to_chain!(gates, q::Integer, ps::AbstractPhase, st::SpiderType.SType) |
| 44 | + if ps != 0 |
| 45 | + if st == SpiderType.Z |
| 46 | + if ps == 1 |
| 47 | + push!(gates, Gate(Z, Locations(q))) |
| 48 | + elseif ps == 1 // 2 |
| 49 | + push!(gates, Gate(S, Locations(q))) |
| 50 | + elseif ps == 3 // 2 |
| 51 | + push!(gates, Gate(AdjointOperation(S), Locations(q))) |
| 52 | + elseif ps == 1 // 4 |
| 53 | + push!(gates, Gate(T, Locations(q))) |
| 54 | + elseif ps == 7 // 4 |
| 55 | + push!(gates, Gate(AdjointOperation(T), Locations(q))) |
| 56 | + elseif ps != 0 |
| 57 | + θ = ps * π |
| 58 | + if θ isa Phase |
| 59 | + θ = θ.ex |
| 60 | + end |
| 61 | + push!(gates, Gate(shift(θ), Locations(q))) |
| 62 | + end |
| 63 | + elseif st == SpiderType.X |
| 64 | + if ps == 1 |
| 65 | + push!(gates, Gate(X, Locations(q))) |
| 66 | + else |
| 67 | + ps != 0 |
| 68 | + θ = ps * π |
| 69 | + if θ isa Phase |
| 70 | + θ = θ.ex |
| 71 | + end |
| 72 | + push!(gates, Gate(Rx(θ), Locations(q))) |
| 73 | + end |
| 74 | + elseif st == SpiderType.H |
| 75 | + push!(gates, Gate(H, Locations(q))) |
| 76 | + end |
| 77 | + end |
36 | 78 | end |
37 | 79 |
|
38 | | -ZXDiagram(bir::BlockIR) = ZXDiagram(convert_to_circuit(bir)) |
39 | | -ZXCircuit(bir::BlockIR) = convert_to_circuit(bir) |
40 | | -YaoHIR.Chain(zxd::ZXDiagram) = convert_to_chain(zxd) |
41 | | - |
42 | 80 | convert_to_gate(::Val{:X}, loc) = Gate(X, Locations(loc)) |
43 | 81 | convert_to_gate(::Val{:Z}, loc) = Gate(Z, Locations(loc)) |
44 | 82 | convert_to_gate(::Val{:H}, loc) = Gate(H, Locations(loc)) |
@@ -120,7 +158,46 @@ function canonicalize_single_location(node::YaoHIR.Gate) |
120 | 158 | return YaoHIR.Gate(node.operation, node.locations[1]) |
121 | 159 | end |
122 | 160 |
|
123 | | -function gates_to_circ(circ, circuit, root) |
| 161 | +""" |
| 162 | + $(TYPEDSIGNATURES) |
| 163 | +
|
| 164 | +Convert a BlockIR to a ZXCircuit. |
| 165 | +
|
| 166 | +This function converts YaoHIR's BlockIR representation to a ZXCircuit by translating |
| 167 | +each gate operation to the corresponding ZX-diagram representation. |
| 168 | +
|
| 169 | +Returns a `ZXCircuit` containing the circuit representation. |
| 170 | +
|
| 171 | +See also: [`convert_to_zxd`](@ref) |
| 172 | +""" |
| 173 | +function convert_to_circuit(root::YaoHIR.BlockIR) |
| 174 | + circ = ZXCircuit(root.nqubits) |
| 175 | + circuit = canonicalize_single_location(root.circuit) |
| 176 | + return _append_chain_to_zx_circ!(circ, circuit, root) |
| 177 | +end |
| 178 | + |
| 179 | +""" |
| 180 | + $(TYPEDSIGNATURES) |
| 181 | +
|
| 182 | +Convert a BlockIR to a ZXDiagram. |
| 183 | +
|
| 184 | +!!! warning "Deprecated" |
| 185 | +
|
| 186 | + `convert_to_zxd` is deprecated. Use [`convert_to_circuit`](@ref) instead. |
| 187 | + This function internally converts to ZXCircuit and then wraps it in ZXDiagram. |
| 188 | +
|
| 189 | +Returns a `ZXDiagram` for backward compatibility. |
| 190 | +""" |
| 191 | +function convert_to_zxd(root::YaoHIR.BlockIR) |
| 192 | + Base.depwarn("Use convert_to_circuit instead", :convert_to_zxd) |
| 193 | + circ = convert_to_circuit(root) |
| 194 | + return ZXDiagram(circ) |
| 195 | +end |
| 196 | + |
| 197 | +ZXDiagram(bir::BlockIR) = ZXDiagram(convert_to_circuit(bir)) |
| 198 | +ZXCircuit(bir::BlockIR) = convert_to_circuit(bir) |
| 199 | + |
| 200 | +function _append_chain_to_zx_circ!(circ::AbstractZXCircuit, circuit, root) |
124 | 201 | for gate in YaoHIR.leaves(circuit) |
125 | 202 | @switch gate begin |
126 | 203 | @case Gate(&Z, loc::Locations{Int}) |
@@ -169,81 +246,3 @@ function gates_to_circ(circ, circuit, root) |
169 | 246 | end |
170 | 247 | return circ |
171 | 248 | end |
172 | | - |
173 | | -function push_spider_to_chain!(qc, q, ps, st) |
174 | | - if ps != 0 |
175 | | - if st == SpiderType.Z |
176 | | - if ps == 1 |
177 | | - push!(qc, Gate(Z, Locations(q))) |
178 | | - elseif ps == 1 // 2 |
179 | | - push!(qc, Gate(S, Locations(q))) |
180 | | - elseif ps == 3 // 2 |
181 | | - push!(qc, Gate(AdjointOperation(S), Locations(q))) |
182 | | - elseif ps == 1 // 4 |
183 | | - push!(qc, Gate(T, Locations(q))) |
184 | | - elseif ps == 7 // 4 |
185 | | - push!(qc, Gate(AdjointOperation(T), Locations(q))) |
186 | | - elseif ps != 0 |
187 | | - θ = ps * π |
188 | | - if θ isa Phase |
189 | | - θ = θ.ex |
190 | | - end |
191 | | - push!(qc, Gate(shift(θ), Locations(q))) |
192 | | - end |
193 | | - elseif st == SpiderType.X |
194 | | - if ps == 1 |
195 | | - push!(qc, Gate(X, Locations(q))) |
196 | | - else |
197 | | - ps != 0 |
198 | | - θ = ps * π |
199 | | - if θ isa Phase |
200 | | - θ = θ.ex |
201 | | - end |
202 | | - push!(qc, Gate(Rx(θ), Locations(q))) |
203 | | - end |
204 | | - elseif st == SpiderType.H |
205 | | - push!(qc, Gate(H, Locations(q))) |
206 | | - end |
207 | | - end |
208 | | -end |
209 | | - |
210 | | -function convert_to_chain(circ::ZXDiagram{TT, P}) where {TT, P} |
211 | | - spider_seq = spider_sequence(circ) |
212 | | - qc = [] |
213 | | - for vs in spider_seq |
214 | | - if length(vs) == 1 |
215 | | - v = vs |
216 | | - q = Int(qubit_loc(circ, v)) |
217 | | - push_spider_to_chain!(qc, q, phase(circ, v), spider_type(circ, v)) |
218 | | - elseif length(vs) == 2 |
219 | | - v1, v2 = vs |
220 | | - q1 = Int(qubit_loc(circ, v1)) |
221 | | - q2 = Int(qubit_loc(circ, v2)) |
222 | | - push_spider_to_chain!(qc, q1, phase(circ, v1), spider_type(circ, v1)) |
223 | | - push_spider_to_chain!(qc, q2, phase(circ, v2), spider_type(circ, v2)) |
224 | | - if spider_type(circ, v1) == SpiderType.Z && spider_type(circ, v2) == SpiderType.X |
225 | | - push!(qc, Ctrl(Gate(X, Locations(q2)), CtrlLocations(q1))) |
226 | | - elseif spider_type(circ, v1) == SpiderType.X && spider_type(circ, v2) == SpiderType.Z |
227 | | - push!(qc, Ctrl(Gate(X, Locations(q1)), CtrlLocations(q2))) |
228 | | - else |
229 | | - error("Spiders ($v1, $v2) should represent a CNOT") |
230 | | - end |
231 | | - elseif length(vs) == 3 |
232 | | - v1, h, v2 = vs |
233 | | - spider_type(circ, h) == SpiderType.H || error("The spider $h should be a H-box") |
234 | | - q1 = Int(qubit_loc(circ, v1)) |
235 | | - q2 = Int(qubit_loc(circ, v2)) |
236 | | - push_spider_to_chain!(qc, q1, phase(circ, v1), spider_type(circ, v1)) |
237 | | - push_spider_to_chain!(qc, q2, phase(circ, v2), spider_type(circ, v2)) |
238 | | - if spider_type(circ, v1) == SpiderType.Z && spider_type(circ, v2) == SpiderType.Z |
239 | | - push!(qc, Ctrl(Gate(Z, Locations(q2)), CtrlLocations(q1))) |
240 | | - else |
241 | | - error("Spiders ($v1, $h, $v2) should represent a CZ") |
242 | | - end |
243 | | - else |
244 | | - error("ZXDiagram's without circuit structure are not supported") |
245 | | - end |
246 | | - end |
247 | | - return Chain(qc...) |
248 | | -end |
249 | | - |
0 commit comments