Skip to content

Commit 6b93668

Browse files
authored
Add new features in QCircuit and fix circuit extraction (#63)
* fix phase_ids changes in rule pab * update checks for phase gadgets * fix check * add max iter in simplify! * parallel matching for p2 and p3 * avoid matching spiders in phase gadgets * rm redundant * avoid infinite simplify! for rule p2 and p3 * avoid infinite simplify! for rule p2 and p3 * add adjoint and vcat * add tests * resolve conflict * fix wrong conversion and add new features * fix circuit extraction * rm test for debugging * add more test
1 parent b1e3702 commit 6b93668

3 files changed

Lines changed: 57 additions & 14 deletions

File tree

src/circuit_extraction.jl

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,11 @@ function circuit_extraction(zxg::ZXGraph{T, P}) where {T, P}
6565
M = biadjancency(nzxg, frontier, Ins)
6666
M, steps = gaussian_elimination(M)
6767
for step in steps
68-
if step.op == :swap
68+
if step.op == :addto
69+
ctrl = step.r2
70+
loc = step.r1
71+
pushfirst_gate!(cir, Val{:CNOT}(), loc, ctrl)
72+
elseif step.op == :swap
6973
q1 = step.r1
7074
q2 = step.r2
7175
pushfirst_gate!(cir, Val{:CNOT}(), q2, q1)
@@ -147,7 +151,7 @@ function update_frontier!(zxg::ZXGraph{T, P}, frontier::Vector{T}, cir::ZXDiagra
147151
end
148152
rem_edge!(zxg, v, w)
149153
if spider_type(zxg, w) == SpiderType.In
150-
add_edge!(zxg, w, v, 1)
154+
add_edge!(zxg, w, v, EdgeType.SIM)
151155
end
152156
deleteat!(frontier, frontier .== v)
153157
push!(frontier, w)
@@ -211,13 +215,11 @@ function gaussian_elimination(M::Matrix{T}, steps::Vector{GEStep} = Vector{GESte
211215
end
212216
while current_col <= nc
213217
r0 = findfirst(!iszero, M[i:nr, current_col])
214-
if r0 != nothing
218+
if r0 !== nothing
215219
r0 += i - 1
216220
r0 == i && break
217-
r_temp = M[i,:]
218-
M[i,:] = M[r0,:]
219-
M[r0,:] = r_temp
220-
step = GEStep(:swap, i, r0)
221+
M[i,:] = M[i,:] .⊻ M[r0,:]
222+
step = GEStep(:addto, r0, i)
221223
push!(steps, step)
222224
break
223225
else

src/qcircuit.jl

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Base: show
1+
import Base: show, vcat, hcat, adjoint, getindex
22
export QCircuit, QGate, random_circuit, gates, gate_count
33

44
struct QGate
@@ -21,6 +21,15 @@ QGate(::Val{:Rx}, loc, theta) = QGate(:Rx, loc; param = theta)
2121
QGate(::Val{:CNOT}, loc, ctrl) = QGate(:CNOT, loc; ctrl = ctrl)
2222
QGate(::Val{:CZ}, loc, ctrl) = QGate(:CZ, loc; ctrl = ctrl)
2323

24+
function adjoint(g::QGate)
25+
g.name in (:X, :Z, :H, :CNOT, :CZ) && return g
26+
g.name === :S && return QGate(Val(:Sdag), g.loc)
27+
g.name === :Sdag && return QGate(Val(:S), g.loc)
28+
g.name === :T && return QGate(Val(:Tdag), g.loc)
29+
g.name === :Tdag && return QGate(Val(:T), g.loc)
30+
g.name in (:shift, :Rz, :Rx) && return QGate(g.name, g.loc; param = -g.param)
31+
end
32+
2433
function show(io::IO, g::QGate)
2534
if g.ctrl == 0
2635
if g.param === nothing
@@ -51,6 +60,30 @@ function show(io::IO, qc::QCircuit)
5160
end
5261
end
5362

63+
function vcat(qcs::QCircuit...)
64+
n = nqubits(qcs[1])
65+
nqc = QCircuit(n)
66+
for qc in qcs
67+
n == nqubits(qc) || error("Can not catenate quantum circuits with different qubit numbers")
68+
nqc.gates = [gates(nqc); gates(qc)]
69+
end
70+
return nqc
71+
end
72+
hcat(qcs::QCircuit...) = vcat(qcs...)
73+
74+
function adjoint(qc::QCircuit)
75+
adj_qc = QCircuit(nqubits(qc))
76+
for i = gate_count(qc):-1:1
77+
push_gate!(adj_qc, qc.gates[i]')
78+
end
79+
return adj_qc
80+
end
81+
82+
function getindex(qc::QCircuit, i...)
83+
n = nqubits(qc)
84+
return QCircuit(n, gates(qc)[i...])
85+
end
86+
5487
nqubits(qc::QCircuit) = qc.nbits
5588
gates(qc::QCircuit) = qc.gates
5689
gate_count(qc::QCircuit) = length(qc.gates)
@@ -171,13 +204,13 @@ function QCircuit(circ::ZXDiagram{T, P}) where {T, P}
171204
push_gate!(qc, Val(:T), q)
172205
elseif phase(circ, v) == 7//4
173206
push_gate!(qc, Val(:Tdag), q)
174-
else
207+
elseif phase(circ, v) != 0
175208
push_gate!(qc, Val(:shift), q, θ)
176209
end
177210
elseif spider_type(circ, v) == ZXCalculus.SpiderType.X
178211
if phase(circ, v) == 1
179212
push_gate!(qc, Val(:X), q)
180-
else
213+
else phase(circ, v) != 0
181214
push_gate!(qc, Val(:Rx), q, θ)
182215
end
183216
elseif spider_type(circ, v) == ZXCalculus.SpiderType.H
@@ -220,11 +253,11 @@ function QCircuit(circ::ZXDiagram{T, P}) where {T, P}
220253
push_gate!(qc, Val(:Z), qubit_loc(circ, v1))
221254
elseif phase(circ, v1) == 1//2
222255
push_gate!(qc, Val(:S), qubit_loc(circ, v1))
223-
elseif phase(circ, v) == 3//2
256+
elseif phase(circ, v1) == 3//2
224257
push_gate!(qc, Val(:Sdag), qubit_loc(circ, v1))
225258
elseif phase(circ, v1) == 1//4
226259
push_gate!(qc, Val(:T), qubit_loc(circ, v1))
227-
elseif phase(circ, v) == 7//4
260+
elseif phase(circ, v1) == 7//4
228261
push_gate!(qc, Val(:Tdag), qubit_loc(circ, v1))
229262
else
230263
push_gate!(qc, Val(:shift), qubit_loc(circ, v1), phase(circ, v1)*π)

test/qcircuit.jl

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using ZXCalculus
1+
using ZXCalculus, Test
22

33
qc = random_circuit(4, 100)
44
@test gate_count(qc) == 100
@@ -40,4 +40,12 @@ pt_qc = QCircuit(pt_circ)
4040

4141
ex_circ = clifford_simplification(circ)
4242
ex_qc = QCircuit(ex_circ)
43-
@test tcount(ex_circ) == tcount(ex_qc)
43+
@test tcount(ex_circ) == tcount(ex_qc)
44+
45+
qc_id = [qc qc']
46+
zxd_id = ZXDiagram(qc_id)
47+
zxd_id = phase_teleportation(zxd_id)
48+
for _ = 1:5
49+
global zxd_id = clifford_simplification(zxd_id)
50+
end
51+
@test ZXCalculus.nv(zxd_id) == 8

0 commit comments

Comments
 (0)