diff --git a/.gitignore b/.gitignore
index 49220a0..590d502 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@
/docs/src/assets/indigo.css
/docs/Manifest.toml
.vscode
+.JuliaFormatter.toml
diff --git a/Project.toml b/Project.toml
index 48d664e..82d97d6 100644
--- a/Project.toml
+++ b/Project.toml
@@ -14,6 +14,13 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
YaoHIR = "6769671a-fce8-4286-b3f7-6099e1b1298a"
YaoLocations = "66df03fb-d475-48f7-b449-3d9064bf085b"
+[weakdeps]
+DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
+Vega = "239c3e63-733f-47ad-beb7-a12fde22c578"
+
+[extensions]
+ZXCalculusExt = ["Vega", "DataFrames"]
+
[compat]
Expronicon = "0.10.3"
Graphs = "1"
@@ -22,11 +29,12 @@ Multigraphs = "0.3"
OMEinsum = "0.7, 0.8"
YaoHIR = "0.2"
YaoLocations = "0.1"
-julia = "1.9"
+julia = ">= 1.9"
[extras]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
+Vega = "239c3e63-733f-47ad-beb7-a12fde22c578"
[targets]
-test = ["Test", "Documenter"]
+test = ["Test", "Documenter", "Vega", "DataFrames"]
diff --git a/ext/ZXCalculusExt.jl b/ext/ZXCalculusExt.jl
new file mode 100644
index 0000000..16601ee
--- /dev/null
+++ b/ext/ZXCalculusExt.jl
@@ -0,0 +1,266 @@
+module ZXCalculusExt
+
+using Graphs
+import Graphs: AbstractEdge, src, dst
+using Vega, DataFrames
+using ZXCalculus, ZXCalculus.ZX
+using ZXCalculus: ZX
+
+function spider_type_string(st1)
+ st1 == SpiderType.X && return "X"
+ st1 == SpiderType.Z && return "Z"
+ st1 == SpiderType.H && return "H"
+ st1 == SpiderType.Out && return "Out"
+ st1 == SpiderType.In && return "In"
+end
+
+function generate_d_spiders(vs, st, ps, x_locs_normal, y_locs_normal)
+ return DataFrame(
+ id = [v for v in vs],
+ x = [get(x_locs_normal, v, nothing) for v in vs],
+ y = [get(y_locs_normal, v, nothing) for v in vs],
+ spider_type = [spider_type_string(st[v]) for v in vs],
+ phase = [iszero(ps[v]) ? "" : "$(ps[v])" for v in vs],
+ )
+end
+
+function generate_d_edges(zxd::ZXDiagram)
+ s = Int[]
+ d = Int[]
+ isH = Bool[]
+ for e in ZXCalculus.ZX.edges(zxd.mg)
+ push!(s, src(e))
+ push!(d, dst(e))
+ push!(isH, false)
+ end
+ return DataFrame(src = s, dst = d, isHadamard = isH)
+end
+function generate_d_edges(zxd::ZXGraph)
+ s = Int[]
+ d = Int[]
+ isH = Bool[]
+ for e in ZXCalculus.ZX.edges(zxd.mg)
+ push!(s, src(e))
+ push!(d, dst(e))
+ push!(isH, ZXCalculus.ZX.is_hadamard(zxd, src(e), dst(e)))
+ end
+ return DataFrame(src = s, dst = d, isHadamard = isH)
+end
+
+function ZXCalculus.ZX.plot(zxd::Union{ZXDiagram,ZXGraph}; kwargs...)
+ scale = 2
+ lattice_unit = 50 * scale
+ zxd = copy(zxd)
+ ZXCalculus.ZX.generate_layout!(zxd)
+ vs = spiders(zxd)
+ x_locs = zxd.layout.spider_col
+ x_min = minimum(values(x_locs), init = 0)
+ x_max = maximum(values(x_locs), init = 1)
+ x_range = (x_max - x_min) * lattice_unit
+ y_locs = zxd.layout.spider_q
+ y_min = minimum(values(y_locs), init = 0)
+ y_max = maximum(values(y_locs), init = 1)
+ y_range = (y_max - y_min) * lattice_unit
+ x_locs_normal = copy(x_locs)
+ for (k, v) in x_locs_normal
+ x_locs_normal[k] = v * lattice_unit
+ end
+ y_locs_normal = copy(y_locs)
+ for (k, v) in y_locs_normal
+ y_locs_normal[k] = v * lattice_unit
+ end
+
+ st = zxd.st
+ ps = zxd.ps
+
+ d_spiders = generate_d_spiders(vs, st, ps, x_locs_normal, y_locs_normal)
+ d_edges = generate_d_edges(zxd)
+
+ spec = @vgplot(
+ $schema = "https://vega.github.io/schema/vega/v5.json",
+ height = y_range,
+ width = x_range,
+ padding = 0.5 * lattice_unit,
+ marks = [
+ {
+ encode = {
+ update = {strokeWidth = {signal = "edgeWidth"}, path = {field = "path"}},
+ enter = {stroke = {field = "color"}},
+ },
+ from = {data = "edges"},
+ type = "path",
+ },
+ {
+ encode = {
+ update = {
+ stroke = {value = "black"},
+ x = {field = "x"},
+ strokeWidth = {signal = "strokeWidth"},
+ size = {signal = "spiderSize"},
+ y = {field = "y"},
+ },
+ enter = {shape = {field = "shape"}, fill = {field = "color"}},
+ },
+ from = {data = "spiders"},
+ type = "symbol",
+ },
+ {
+ encode = {
+ update = {
+ align = {value = "center"},
+ x = {field = "x"},
+ ne = {value = "top"},
+ opacity = {signal = "showIds"},
+ y = {field = "y"},
+ fontSize = {value = 6 * lattice_unit / 50},
+ dy = {value = 18 * lattice_unit / 50},
+ },
+ enter = {fill = {value = "lightgray"}, text = {field = "id"}},
+ },
+ from = {data = "spiders"},
+ type = "text",
+ },
+ {
+ encode = {
+ update = {
+ align = {value = "center"},
+ x = {field = "x"},
+ dy = {value = lattice_unit / 50},
+ baseline = {value = "middle"},
+ opacity = {signal = "showPhases"},
+ fontSize = {value = 6 * lattice_unit / 50},
+ y = {field = "y"},
+ },
+ enter = {fill = {value = "black"}, text = {field = "phase"}},
+ },
+ from = {data = "spiders"},
+ type = "text",
+ },
+ ],
+ data = [
+ {
+ name = "spiders",
+ values = d_spiders,
+ on = [{
+ modify = "whichSymbol",
+ values = "newLoc && {x: newLoc.x, y: newLoc.y}",
+ trigger = "newLoc",
+ }],
+ transform = [
+ {
+ as = "shape",
+ expr = "datum.spider_type === 'Z' ? 'circle' : (datum.spider_type === 'X' ? 'circle' : (datum.spider_type === 'H' ? 'square' : 'circle'))",
+ type = "formula",
+ },
+ {
+ as = "color",
+ expr = "datum.spider_type === 'Z' ? '#D8F8D8' : (datum.spider_type === 'X' ? '#E8A5A5' : (datum.spider_type === 'H' ? 'yellow' : '#9558B2'))",
+ type = "formula",
+ },
+ ],
+ },
+ {
+ name = "edges",
+ values = d_edges,
+ transform = [
+ {
+ key = "id",
+ fields = ["src", "dst"],
+ as = ["source", "target"],
+ from = "spiders",
+ type = "lookup",
+ },
+ {
+ targetX = "target.x",
+ shape = {signal = "shape"},
+ sourceX = "source.x",
+ targetY = "target.y",
+ type = "linkpath",
+ sourceY = "source.y",
+ orient = {signal = "orient"},
+ },
+ {
+ as = "color",
+ expr = "datum.isHadamard ? '#4063D8' : 'black'",
+ type = "formula",
+ },
+ ],
+ },
+ ],
+ signals = [
+ {name = "showIds", bind = {input = "checkbox"}, value = true},
+ {name = "showPhases", bind = {input = "checkbox"}, value = true},
+ {
+ name = "spiderSize",
+ bind = {
+ step = lattice_unit / 5,
+ max = 40 * lattice_unit,
+ min = 2 * lattice_unit,
+ input = "range",
+ },
+ value = 20 * lattice_unit,
+ },
+ {
+ name = "strokeWidth",
+ bind = {
+ step = 0.001 * lattice_unit,
+ max = 3 * lattice_unit / 50,
+ min = 0,
+ input = "range",
+ },
+ value = 1.5 * lattice_unit / 50,
+ },
+ {
+ name = "edgeWidth",
+ bind = {
+ step = 0.001 * lattice_unit,
+ max = 3 * lattice_unit / 50,
+ min = 0.002 * lattice_unit,
+ input = "range",
+ },
+ value = 1.5 * lattice_unit / 50,
+ },
+ {
+ name = "orient",
+ bind = {options = ["horizontal", "vertical"], input = "select"},
+ value = "horizontal",
+ },
+ {
+ name = "shape",
+ bind = {
+ options = ["line", "arc", "curve", "diagonal", "orthogonal"],
+ input = "select",
+ },
+ value = "diagonal",
+ },
+ {
+ name = "whichSymbol",
+ on = [
+ {events = "symbol:mousedown", update = "datum"},
+ {events = "*:mouseup", update = "{}"},
+ ],
+ value = {},
+ },
+ {
+ name = "newLoc",
+ on = [
+ {events = "symbol:mouseout[!event.buttons], window:mouseup", update = "false"},
+ {events = "symbol:mouseover", update = "{x: x(), y: y()}"},
+ {
+ events = "[symbol:mousedown, window:mouseup] > window:mousemove!",
+ update = "{x: x(), y: y()}",
+ },
+ ],
+ value = false,
+ },
+ ]
+ )
+ return spec
+end
+
+
+
+
+
+
+end
diff --git a/notebooks/demonstration.jl b/notebooks/demonstration.jl
new file mode 100644
index 0000000..4738fa8
--- /dev/null
+++ b/notebooks/demonstration.jl
@@ -0,0 +1,1360 @@
+### A Pluto.jl notebook ###
+# v0.19.38
+
+using Markdown
+using InteractiveUtils
+
+# ╔═╡ aa11ea12-6a9c-11ee-11b6-77a1fbfdf4b5
+begin
+ # Extensions
+ using OpenQASM
+ using Vega
+ using DataFrames
+
+ # ZX Calculus Tools
+ using ZXCalculus, ZXCalculus.ZX
+ using YaoHIR: BlockIR
+
+
+ using PlutoUI
+
+end
+
+# ╔═╡ c467fe63-487b-4087-b166-01ed41a47eec
+using MLStyle
+
+# ╔═╡ 6ebebc14-6b0f-48b7-a8e4-fb6f7f9f7f0e
+begin
+ function Base.show(io::IO, mime::MIME"text/html", zx::Union{ZXDiagram,ZXGraph})
+ g = ZXCalculus.plot(zx)
+ Base.show(io, mime, g)
+ end
+end
+
+
+# ╔═╡ 639aaf18-e63b-4b07-8557-8e21a874d91a
+begin
+ b1 = BlockIR("""
+ // Benchmark was created by MQT Bench on 2023-06-29
+ // For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/
+ // MQT Bench version: v1.0.0
+ // TKET version: 1.16.0
+
+ OPENQASM 2.0;
+ include "qelib1.inc";
+
+ qreg q[107];
+ creg c[106];
+ h q[0];
+ h q[1];
+ h q[2];
+ h q[3];
+ h q[4];
+ h q[5];
+ h q[6];
+ h q[7];
+ h q[8];
+ h q[9];
+ h q[10];
+ h q[11];
+ h q[12];
+ h q[13];
+ h q[14];
+ h q[15];
+ h q[16];
+ h q[17];
+ h q[18];
+ h q[19];
+ h q[20];
+ h q[21];
+ h q[22];
+ h q[23];
+ h q[24];
+ h q[25];
+ h q[26];
+ h q[27];
+ h q[28];
+ h q[29];
+ h q[30];
+ h q[31];
+ h q[32];
+ h q[33];
+ h q[34];
+ h q[35];
+ h q[36];
+ h q[37];
+ h q[38];
+ h q[39];
+ h q[40];
+ h q[41];
+ h q[42];
+ h q[43];
+ h q[44];
+ h q[45];
+ h q[46];
+ h q[47];
+ h q[48];
+ h q[49];
+ h q[50];
+ h q[51];
+ h q[52];
+ h q[53];
+ h q[54];
+ h q[55];
+ h q[56];
+ h q[57];
+ h q[58];
+ h q[59];
+ h q[60];
+ h q[61];
+ h q[62];
+ h q[63];
+ h q[64];
+ h q[65];
+ h q[66];
+ h q[67];
+ h q[68];
+ h q[69];
+ h q[70];
+ h q[71];
+ h q[72];
+ h q[73];
+ h q[74];
+ h q[75];
+ h q[76];
+
+ h q[105];
+ """)
+ c1 = ZXDiagram(b1)
+
+end
+
+# ╔═╡ 69587b8e-26cf-4862-abe6-f81cc6967db3
+b1
+
+# ╔═╡ 97eae154-ce25-4f22-b89a-af653f79dcd7
+g1_reduced = full_reduction(c1)
+
+# ╔═╡ 15e4062a-37b3-40dc-add3-9d8ad7520b4d
+c2 = ZXDiagram(BlockIR("""
+// Benchmark was created by MQT Bench on 2023-06-29
+// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/
+// MQT Bench version: v1.0.0
+// TKET version: 1.16.0
+
+OPENQASM 2.0;
+include "qelib1.inc";
+
+qreg q[107];
+creg c[106];
+h q[0];
+h q[1];
+h q[2];
+h q[3];
+h q[4];
+h q[5];
+h q[6];
+h q[7];
+h q[8];
+h q[9];
+h q[10];
+h q[11];
+h q[12];
+h q[13];
+h q[14];
+h q[15];
+h q[16];
+h q[17];
+h q[18];
+h q[19];
+h q[20];
+h q[21];
+h q[22];
+h q[23];
+h q[24];
+h q[25];
+h q[26];
+h q[27];
+h q[28];
+h q[29];
+h q[30];
+h q[31];
+h q[32];
+h q[33];
+h q[34];
+h q[35];
+h q[36];
+h q[37];
+h q[38];
+h q[39];
+h q[40];
+h q[41];
+h q[42];
+h q[43];
+h q[44];
+h q[45];
+h q[46];
+h q[47];
+h q[48];
+h q[49];
+h q[50];
+h q[51];
+h q[52];
+h q[53];
+h q[54];
+h q[55];
+h q[56];
+h q[57];
+h q[58];
+h q[59];
+h q[60];
+h q[61];
+h q[62];
+h q[63];
+h q[64];
+h q[65];
+h q[66];
+h q[67];
+h q[68];
+h q[69];
+h q[70];
+h q[71];
+h q[72];
+h q[73];
+h q[74];
+h q[75];
+h q[76];
+h q[77];
+h q[78];
+h q[79];
+h q[80];
+h q[81];
+h q[82];
+h q[83];
+h q[84];
+h q[85];
+h q[86];
+h q[87];
+h q[88];
+h q[89];
+h q[90];
+h q[91];
+h q[92];
+h q[93];
+h q[94];
+h q[95];
+h q[96];
+h q[97];
+h q[98];
+h q[99];
+h q[100];
+h q[101];
+h q[102];
+h q[103];
+h q[104];
+h q[105];
+x q[106];
+x q[0];
+x q[1];
+x q[3];
+x q[5];
+x q[6];
+x q[8];
+x q[9];
+x q[11];
+x q[12];
+x q[15];
+x q[21];
+x q[24];
+x q[25];
+x q[28];
+x q[31];
+x q[35];
+x q[36];
+x q[38];
+x q[39];
+x q[40];
+x q[41];
+x q[42];
+x q[44];
+x q[49];
+x q[51];
+x q[52];
+x q[53];
+x q[55];
+x q[57];
+x q[58];
+x q[60];
+x q[63];
+x q[67];
+x q[68];
+x q[72];
+x q[74];
+x q[75];
+x q[77];
+x q[78];
+x q[80];
+x q[86];
+x q[88];
+x q[96];
+x q[97];
+x q[99];
+x q[100];
+x q[103];
+h q[106];
+cx q[0],q[106];
+x q[0];
+cx q[1],q[106];
+h q[0];
+x q[1];
+cx q[2],q[106];
+h q[1];
+h q[2];
+cx q[3],q[106];
+x q[3];
+cx q[4],q[106];
+h q[3];
+h q[4];
+cx q[5],q[106];
+x q[5];
+cx q[6],q[106];
+h q[5];
+x q[6];
+cx q[7],q[106];
+h q[6];
+h q[7];
+cx q[8],q[106];
+x q[8];
+cx q[9],q[106];
+h q[8];
+x q[9];
+cx q[10],q[106];
+h q[9];
+h q[10];
+cx q[11],q[106];
+x q[11];
+cx q[12],q[106];
+h q[11];
+x q[12];
+cx q[13],q[106];
+h q[12];
+h q[13];
+cx q[14],q[106];
+h q[14];
+cx q[15],q[106];
+x q[15];
+cx q[16],q[106];
+h q[15];
+h q[16];
+cx q[17],q[106];
+h q[17];
+cx q[18],q[106];
+h q[18];
+cx q[19],q[106];
+h q[19];
+cx q[20],q[106];
+h q[20];
+cx q[21],q[106];
+x q[21];
+cx q[22],q[106];
+h q[21];
+h q[22];
+cx q[23],q[106];
+h q[23];
+cx q[24],q[106];
+x q[24];
+cx q[25],q[106];
+h q[24];
+x q[25];
+cx q[26],q[106];
+h q[25];
+h q[26];
+cx q[27],q[106];
+h q[27];
+cx q[28],q[106];
+x q[28];
+cx q[29],q[106];
+h q[28];
+h q[29];
+cx q[30],q[106];
+h q[30];
+cx q[31],q[106];
+x q[31];
+cx q[32],q[106];
+h q[31];
+h q[32];
+cx q[33],q[106];
+h q[33];
+cx q[34],q[106];
+h q[34];
+cx q[35],q[106];
+x q[35];
+cx q[36],q[106];
+h q[35];
+x q[36];
+cx q[37],q[106];
+h q[36];
+h q[37];
+cx q[38],q[106];
+x q[38];
+cx q[39],q[106];
+h q[38];
+x q[39];
+cx q[40],q[106];
+h q[39];
+x q[40];
+cx q[41],q[106];
+h q[40];
+x q[41];
+cx q[42],q[106];
+h q[41];
+x q[42];
+cx q[43],q[106];
+h q[42];
+h q[43];
+cx q[44],q[106];
+x q[44];
+cx q[45],q[106];
+h q[44];
+h q[45];
+cx q[46],q[106];
+h q[46];
+cx q[47],q[106];
+h q[47];
+cx q[48],q[106];
+h q[48];
+cx q[49],q[106];
+x q[49];
+cx q[50],q[106];
+h q[49];
+h q[50];
+cx q[51],q[106];
+x q[51];
+cx q[52],q[106];
+h q[51];
+x q[52];
+cx q[53],q[106];
+h q[52];
+x q[53];
+cx q[54],q[106];
+h q[53];
+h q[54];
+cx q[55],q[106];
+x q[55];
+cx q[56],q[106];
+h q[55];
+h q[56];
+cx q[57],q[106];
+x q[57];
+cx q[58],q[106];
+h q[57];
+x q[58];
+cx q[59],q[106];
+h q[58];
+h q[59];
+cx q[60],q[106];
+x q[60];
+cx q[61],q[106];
+h q[60];
+h q[61];
+cx q[62],q[106];
+h q[62];
+cx q[63],q[106];
+x q[63];
+cx q[64],q[106];
+h q[63];
+h q[64];
+cx q[65],q[106];
+h q[65];
+cx q[66],q[106];
+h q[66];
+cx q[67],q[106];
+x q[67];
+cx q[68],q[106];
+h q[67];
+x q[68];
+cx q[69],q[106];
+h q[68];
+h q[69];
+cx q[70],q[106];
+h q[70];
+cx q[71],q[106];
+h q[71];
+cx q[72],q[106];
+x q[72];
+cx q[73],q[106];
+h q[72];
+h q[73];
+cx q[74],q[106];
+x q[74];
+cx q[75],q[106];
+h q[74];
+x q[75];
+cx q[76],q[106];
+h q[75];
+h q[76];
+cx q[77],q[106];
+x q[77];
+cx q[78],q[106];
+h q[77];
+x q[78];
+cx q[79],q[106];
+h q[78];
+h q[79];
+cx q[80],q[106];
+x q[80];
+cx q[81],q[106];
+h q[80];
+h q[81];
+cx q[82],q[106];
+h q[82];
+cx q[83],q[106];
+h q[83];
+cx q[84],q[106];
+h q[84];
+cx q[85],q[106];
+h q[85];
+cx q[86],q[106];
+x q[86];
+cx q[87],q[106];
+h q[86];
+h q[87];
+cx q[88],q[106];
+x q[88];
+cx q[89],q[106];
+h q[88];
+h q[89];
+cx q[90],q[106];
+h q[90];
+cx q[91],q[106];
+h q[91];
+cx q[92],q[106];
+h q[92];
+cx q[93],q[106];
+h q[93];
+cx q[94],q[106];
+h q[94];
+cx q[95],q[106];
+h q[95];
+cx q[96],q[106];
+x q[96];
+cx q[97],q[106];
+h q[96];
+x q[97];
+cx q[98],q[106];
+h q[97];
+h q[98];
+cx q[99],q[106];
+x q[99];
+cx q[100],q[106];
+h q[99];
+x q[100];
+cx q[101],q[106];
+h q[100];
+h q[101];
+cx q[102],q[106];
+h q[102];
+cx q[103],q[106];
+x q[103];
+cx q[104],q[106];
+h q[103];
+h q[104];
+cx q[105],q[106];
+h q[105];
+ """))
+
+
+# ╔═╡ e22922f8-5a54-475b-b325-dda82547c556
+
+
+# ╔═╡ 37954f01-da8c-4018-a7e1-811d4a86fb26
+c2_inv = dagger(c2)
+
+# ╔═╡ c984b469-89d0-4d02-9264-e967697e50b3
+g2_reduced = full_reduction(c2)
+
+# ╔═╡ 996a236f-90b5-42bb-8627-19d5a7facef6
+m_2 = concat!(c1, dagger(c2))
+
+# ╔═╡ df136e09-4958-433d-a3ce-60f73a10968a
+verify_equality(c1, c2)
+
+# ╔═╡ 69d97139-73d2-4b3f-8d1f-aa8437880754
+m = concat!(c1, c2_inv)
+
+# ╔═╡ 57c4c6eb-54e1-4412-b3ca-3bd7588e4e34
+full_reduction(m)
+
+# ╔═╡ a092392c-eff5-4c5a-be9b-c9e67881cf46
+verify_equality(c1, c2)
+
+# ╔═╡ a6819a4e-3029-4fec-9baa-8ec842755e49
+contains_only_bare_wires(m)
+
+# ╔═╡ d9da3492-048d-4458-aa37-801e84b61ec7
+typeof(c2.st[3])
+
+# ╔═╡ d65ab9bd-6dcc-4502-a8fb-301abf404856
+vs = spider_sequence(c2)
+
+# ╔═╡ 27b7b121-0c13-49ed-97e6-c73386e844a0
+st = SpiderType.Z
+
+# ╔═╡ ed656d2d-c4af-45a3-a5d8-5fd8c1cccac8
+st
+
+# ╔═╡ 1b36a6ba-5498-4aa5-ab67-67dff42c8422
+st == SpiderType.Z || st == SpiderType.Z || st == SpiderType.H
+
+# ╔═╡ ab841776-6b79-4662-9998-04f513370fee
+Int(SpiderType.X)
+
+# ╔═╡ 4ff2d0e2-9dda-405d-aa77-9abb70eace77
+SpiderType.H == SpiderType.Out
+
+# ╔═╡ 7bec3f25-507a-42e8-8547-cae8bfc317d8
+dj3 = ZXDiagram(BlockIR("""
+OPENQASM 2.0;
+include "qelib1.inc";
+
+qreg q[3];
+creg c[2];
+h q[0];
+h q[1];
+x q[2];
+x q[0];
+x q[1];
+h q[2];
+cx q[0],q[2];
+x q[0];
+cx q[1],q[2];
+h q[0];
+x q[1];
+h q[1];
+"""))
+
+# ╔═╡ f3235791-4582-44a3-ba68-6c39a0d0b26b
+verify_equality(dj3, dj3)
+
+# ╔═╡ 7220947a-f153-4bb7-a0ba-972af51d3fe7
+dj_m = concat!(copy(dj3), dagger(dj3))
+
+# ╔═╡ 3f98b870-a534-4f69-b460-64c59cd8ef96
+dj3_reduced = full_reduction(dj_m)
+
+# ╔═╡ dd5c40da-0530-4975-8245-78538ad6d244
+replace!(Rule{:id}(), dj3_reduced)
+
+
+# ╔═╡ a48d68b5-559a-4937-a2b7-c13e5f5181b0
+show(dj3_reduced)
+
+# ╔═╡ 00000000-0000-0000-0000-000000000001
+PLUTO_PROJECT_TOML_CONTENTS = """
+[deps]
+DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
+MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078"
+OpenQASM = "a8821629-a4c0-4df7-9e00-12969ff383a7"
+PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
+Vega = "239c3e63-733f-47ad-beb7-a12fde22c578"
+YaoHIR = "6769671a-fce8-4286-b3f7-6099e1b1298a"
+ZXCalculus = "3525faa3-032d-4235-a8d4-8c2939a218dd"
+
+[compat]
+DataFrames = "~1.6.1"
+MLStyle = "~0.4.17"
+OpenQASM = "~2.1.4"
+PlutoUI = "~0.7.55"
+Vega = "~2.6.2"
+YaoHIR = "~0.2.2"
+ZXCalculus = "~0.6.0"
+"""
+
+# ╔═╡ 00000000-0000-0000-0000-000000000002
+PLUTO_MANIFEST_TOML_CONTENTS = """
+# This file is machine-generated - editing it directly is not advised
+
+julia_version = "1.10.0"
+manifest_format = "2.0"
+project_hash = "dc2131f03a0dd356c9b167032d6d5c79ba566e98"
+
+[[deps.AbstractPlutoDingetjes]]
+deps = ["Pkg"]
+git-tree-sha1 = "c278dfab760520b8bb7e9511b968bf4ba38b7acc"
+uuid = "6e696c72-6542-2067-7265-42206c756150"
+version = "1.2.3"
+
+[[deps.AbstractTrees]]
+git-tree-sha1 = "faa260e4cb5aba097a73fab382dd4b5819d8ec8c"
+uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
+version = "0.4.4"
+
+[[deps.ArgTools]]
+uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
+version = "1.1.1"
+
+[[deps.ArnoldiMethod]]
+deps = ["LinearAlgebra", "Random", "StaticArrays"]
+git-tree-sha1 = "62e51b39331de8911e4a7ff6f5aaf38a5f4cc0ae"
+uuid = "ec485272-7323-5ecc-a04f-4719b315124d"
+version = "0.2.0"
+
+[[deps.Artifacts]]
+uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
+
+[[deps.Base64]]
+uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
+
+[[deps.BatchedRoutines]]
+deps = ["LinearAlgebra"]
+git-tree-sha1 = "441db9f0399bcfb4eeb8b891a6b03f7acc5dc731"
+uuid = "a9ab73d0-e05c-5df1-8fde-d6a4645b8d8e"
+version = "0.2.2"
+
+[[deps.BetterExp]]
+git-tree-sha1 = "dd3448f3d5b2664db7eceeec5f744535ce6e759b"
+uuid = "7cffe744-45fd-4178-b173-cf893948b8b7"
+version = "0.1.0"
+
+[[deps.BufferedStreams]]
+git-tree-sha1 = "4ae47f9a4b1dc19897d3743ff13685925c5202ec"
+uuid = "e1450e63-4bb3-523b-b2a4-4ffa8c0fd77d"
+version = "1.2.1"
+
+[[deps.ChainRulesCore]]
+deps = ["Compat", "LinearAlgebra"]
+git-tree-sha1 = "ad25e7d21ce10e01de973cdc68ad0f850a953c52"
+uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
+version = "1.21.1"
+weakdeps = ["SparseArrays"]
+
+ [deps.ChainRulesCore.extensions]
+ ChainRulesCoreSparseArraysExt = "SparseArrays"
+
+[[deps.ColorTypes]]
+deps = ["FixedPointNumbers", "Random"]
+git-tree-sha1 = "eb7f0f8307f71fac7c606984ea5fb2817275d6e4"
+uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
+version = "0.11.4"
+
+[[deps.Combinatorics]]
+git-tree-sha1 = "08c8b6831dc00bfea825826be0bc8336fc369860"
+uuid = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
+version = "1.0.2"
+
+[[deps.Compat]]
+deps = ["TOML", "UUIDs"]
+git-tree-sha1 = "75bd5b6fc5089df449b5d35fa501c846c9b6549b"
+uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
+version = "4.12.0"
+weakdeps = ["Dates", "LinearAlgebra"]
+
+ [deps.Compat.extensions]
+ CompatLinearAlgebraExt = "LinearAlgebra"
+
+[[deps.CompilerSupportLibraries_jll]]
+deps = ["Artifacts", "Libdl"]
+uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"
+version = "1.0.5+1"
+
+[[deps.ConstructionBase]]
+deps = ["LinearAlgebra"]
+git-tree-sha1 = "c53fc348ca4d40d7b371e71fd52251839080cbc9"
+uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
+version = "1.5.4"
+
+ [deps.ConstructionBase.extensions]
+ ConstructionBaseIntervalSetsExt = "IntervalSets"
+ ConstructionBaseStaticArraysExt = "StaticArrays"
+
+ [deps.ConstructionBase.weakdeps]
+ IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
+ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
+
+[[deps.Crayons]]
+git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15"
+uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
+version = "4.1.1"
+
+[[deps.DataAPI]]
+git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe"
+uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
+version = "1.16.0"
+
+[[deps.DataFrames]]
+deps = ["Compat", "DataAPI", "DataStructures", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrecompileTools", "PrettyTables", "Printf", "REPL", "Random", "Reexport", "SentinelArrays", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"]
+git-tree-sha1 = "04c738083f29f86e62c8afc341f0967d8717bdb8"
+uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
+version = "1.6.1"
+
+[[deps.DataStructures]]
+deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
+git-tree-sha1 = "ac67408d9ddf207de5cfa9a97e114352430f01ed"
+uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
+version = "0.18.16"
+
+[[deps.DataValueInterfaces]]
+git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
+uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
+version = "1.0.0"
+
+[[deps.DataValues]]
+deps = ["DataValueInterfaces", "Dates"]
+git-tree-sha1 = "d88a19299eba280a6d062e135a43f00323ae70bf"
+uuid = "e7dc6d0d-1eca-5fa6-8ad6-5aecde8b7ea5"
+version = "0.4.13"
+
+[[deps.Dates]]
+deps = ["Printf"]
+uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
+
+[[deps.Distributed]]
+deps = ["Random", "Serialization", "Sockets"]
+uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
+
+[[deps.Downloads]]
+deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
+uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
+version = "1.6.0"
+
+[[deps.Expronicon]]
+deps = ["MLStyle"]
+git-tree-sha1 = "d64373d3c6ca8605baf3f8569e92c0564c17479b"
+uuid = "6b7a57c9-7cc1-4fdf-b7f5-e857abae3636"
+version = "0.10.5"
+
+[[deps.FileIO]]
+deps = ["Pkg", "Requires", "UUIDs"]
+git-tree-sha1 = "c5c28c245101bd59154f649e19b038d15901b5dc"
+uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
+version = "1.16.2"
+
+[[deps.FilePaths]]
+deps = ["FilePathsBase", "MacroTools", "Reexport", "Requires"]
+git-tree-sha1 = "919d9412dbf53a2e6fe74af62a73ceed0bce0629"
+uuid = "8fc22ac5-c921-52a6-82fd-178b2807b824"
+version = "0.8.3"
+
+[[deps.FilePathsBase]]
+deps = ["Compat", "Dates", "Mmap", "Printf", "Test", "UUIDs"]
+git-tree-sha1 = "9f00e42f8d99fdde64d40c8ea5d14269a2e2c1aa"
+uuid = "48062228-2e41-5def-b9a4-89aafe57970f"
+version = "0.9.21"
+
+[[deps.FileWatching]]
+uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"
+
+[[deps.FixedPointNumbers]]
+deps = ["Statistics"]
+git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc"
+uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
+version = "0.8.4"
+
+[[deps.Future]]
+deps = ["Random"]
+uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
+
+[[deps.Graphs]]
+deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"]
+git-tree-sha1 = "899050ace26649433ef1af25bc17a815b3db52b7"
+uuid = "86223c79-3864-5bf0-83f7-82e725a168b6"
+version = "1.9.0"
+
+[[deps.Hyperscript]]
+deps = ["Test"]
+git-tree-sha1 = "179267cfa5e712760cd43dcae385d7ea90cc25a4"
+uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91"
+version = "0.0.5"
+
+[[deps.HypertextLiteral]]
+deps = ["Tricks"]
+git-tree-sha1 = "7134810b1afce04bbc1045ca1985fbe81ce17653"
+uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
+version = "0.9.5"
+
+[[deps.IOCapture]]
+deps = ["Logging", "Random"]
+git-tree-sha1 = "8b72179abc660bfab5e28472e019392b97d0985c"
+uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89"
+version = "0.2.4"
+
+[[deps.Inflate]]
+git-tree-sha1 = "ea8031dea4aff6bd41f1df8f2fdfb25b33626381"
+uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9"
+version = "0.1.4"
+
+[[deps.InlineStrings]]
+deps = ["Parsers"]
+git-tree-sha1 = "9cc2baf75c6d09f9da536ddf58eb2f29dedaf461"
+uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48"
+version = "1.4.0"
+
+[[deps.InteractiveUtils]]
+deps = ["Markdown"]
+uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
+
+[[deps.InvertedIndices]]
+git-tree-sha1 = "0dc7b50b8d436461be01300fd8cd45aa0274b038"
+uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
+version = "1.3.0"
+
+[[deps.IteratorInterfaceExtensions]]
+git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
+uuid = "82899510-4779-5014-852e-03e436cf321d"
+version = "1.0.0"
+
+[[deps.JSON]]
+deps = ["Dates", "Mmap", "Parsers", "Unicode"]
+git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a"
+uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
+version = "0.21.4"
+
+[[deps.JSON3]]
+deps = ["Dates", "Mmap", "Parsers", "PrecompileTools", "StructTypes", "UUIDs"]
+git-tree-sha1 = "eb3edce0ed4fa32f75a0a11217433c31d56bd48b"
+uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
+version = "1.14.0"
+
+ [deps.JSON3.extensions]
+ JSON3ArrowExt = ["ArrowTypes"]
+
+ [deps.JSON3.weakdeps]
+ ArrowTypes = "31f734f8-188a-4ce0-8406-c8a06bd891cd"
+
+[[deps.JSONSchema]]
+deps = ["Downloads", "JSON", "JSON3", "URIs"]
+git-tree-sha1 = "5f0bd0cd69df978fa64ccdcb5c152fbc705455a1"
+uuid = "7d188eb4-7ad8-530c-ae41-71a32a6d4692"
+version = "1.3.0"
+
+[[deps.LaTeXStrings]]
+git-tree-sha1 = "50901ebc375ed41dbf8058da26f9de442febbbec"
+uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
+version = "1.3.1"
+
+[[deps.LibCURL]]
+deps = ["LibCURL_jll", "MozillaCACerts_jll"]
+uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"
+version = "0.6.4"
+
+[[deps.LibCURL_jll]]
+deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
+uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"
+version = "8.4.0+0"
+
+[[deps.LibGit2]]
+deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"]
+uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
+
+[[deps.LibGit2_jll]]
+deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"]
+uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5"
+version = "1.6.4+0"
+
+[[deps.LibSSH2_jll]]
+deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
+uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"
+version = "1.11.0+1"
+
+[[deps.Libdl]]
+uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
+
+[[deps.LinearAlgebra]]
+deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"]
+uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
+
+[[deps.Logging]]
+uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
+
+[[deps.MIMEs]]
+git-tree-sha1 = "65f28ad4b594aebe22157d6fac869786a255b7eb"
+uuid = "6c6e2e6c-3030-632d-7369-2d6c69616d65"
+version = "0.1.4"
+
+[[deps.MLStyle]]
+git-tree-sha1 = "bc38dff0548128765760c79eb7388a4b37fae2c8"
+uuid = "d8e11817-5142-5d16-987a-aa16d5891078"
+version = "0.4.17"
+
+[[deps.MacroTools]]
+deps = ["Markdown", "Random"]
+git-tree-sha1 = "2fa9ee3e63fd3a4f7a9a4f4744a52f4856de82df"
+uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
+version = "0.5.13"
+
+[[deps.Markdown]]
+deps = ["Base64"]
+uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
+
+[[deps.MbedTLS_jll]]
+deps = ["Artifacts", "Libdl"]
+uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
+version = "2.28.2+1"
+
+[[deps.Missings]]
+deps = ["DataAPI"]
+git-tree-sha1 = "f66bdc5de519e8f8ae43bdc598782d35a25b1272"
+uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
+version = "1.1.0"
+
+[[deps.Mmap]]
+uuid = "a63ad114-7e13-5084-954f-fe012c677804"
+
+[[deps.MozillaCACerts_jll]]
+uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
+version = "2023.1.10"
+
+[[deps.Multigraphs]]
+deps = ["Graphs", "LinearAlgebra", "SparseArrays"]
+git-tree-sha1 = "055a7c49a626e17a8c99bcaaf472d0de60848929"
+uuid = "7ebac608-6c66-46e6-9856-b5f43e107bac"
+version = "0.3.0"
+
+[[deps.NetworkOptions]]
+uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"
+version = "1.2.0"
+
+[[deps.NodeJS]]
+deps = ["Pkg"]
+git-tree-sha1 = "bf1f49fd62754064bc42490a8ddc2aa3694a8e7a"
+uuid = "2bd173c7-0d6d-553b-b6af-13a54713934c"
+version = "2.0.0"
+
+[[deps.OMEinsum]]
+deps = ["AbstractTrees", "BatchedRoutines", "ChainRulesCore", "Combinatorics", "LinearAlgebra", "MacroTools", "OMEinsumContractionOrders", "Test", "TupleTools"]
+git-tree-sha1 = "3b7f8f3ffb63e3c7fd0d9b364862a2e35f70478e"
+uuid = "ebe7aa44-baf0-506c-a96f-8464559b3922"
+version = "0.7.6"
+
+ [deps.OMEinsum.extensions]
+ CUDAExt = "CUDA"
+
+ [deps.OMEinsum.weakdeps]
+ CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
+
+[[deps.OMEinsumContractionOrders]]
+deps = ["AbstractTrees", "BetterExp", "JSON", "SparseArrays", "Suppressor"]
+git-tree-sha1 = "b0cba9f4a6f021a63b066f0bb29a6fd63c93be44"
+uuid = "6f22d1fd-8eed-4bb7-9776-e7d684900715"
+version = "0.8.3"
+
+ [deps.OMEinsumContractionOrders.extensions]
+ KaHyParExt = ["KaHyPar"]
+
+ [deps.OMEinsumContractionOrders.weakdeps]
+ KaHyPar = "2a6221f6-aa48-11e9-3542-2d9e0ef01880"
+
+[[deps.OpenBLAS_jll]]
+deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
+uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"
+version = "0.3.23+2"
+
+[[deps.OpenQASM]]
+deps = ["MLStyle", "RBNF"]
+git-tree-sha1 = "aa6c47be6512e3299d9e56224d13d6a2303e3d6e"
+uuid = "a8821629-a4c0-4df7-9e00-12969ff383a7"
+version = "2.1.4"
+
+[[deps.OrderedCollections]]
+git-tree-sha1 = "dfdf5519f235516220579f949664f1bf44e741c5"
+uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
+version = "1.6.3"
+
+[[deps.Parsers]]
+deps = ["Dates", "PrecompileTools", "UUIDs"]
+git-tree-sha1 = "8489905bcdbcfac64d1daa51ca07c0d8f0283821"
+uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
+version = "2.8.1"
+
+[[deps.Pkg]]
+deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
+uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
+version = "1.10.0"
+
+[[deps.PlutoUI]]
+deps = ["AbstractPlutoDingetjes", "Base64", "ColorTypes", "Dates", "FixedPointNumbers", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "MIMEs", "Markdown", "Random", "Reexport", "URIs", "UUIDs"]
+git-tree-sha1 = "68723afdb616445c6caaef6255067a8339f91325"
+uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
+version = "0.7.55"
+
+[[deps.PooledArrays]]
+deps = ["DataAPI", "Future"]
+git-tree-sha1 = "36d8b4b899628fb92c2749eb488d884a926614d3"
+uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720"
+version = "1.4.3"
+
+[[deps.PrecompileTools]]
+deps = ["Preferences"]
+git-tree-sha1 = "03b4c25b43cb84cee5c90aa9b5ea0a78fd848d2f"
+uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
+version = "1.2.0"
+
+[[deps.Preferences]]
+deps = ["TOML"]
+git-tree-sha1 = "00805cd429dcb4870060ff49ef443486c262e38e"
+uuid = "21216c6a-2e73-6563-6e65-726566657250"
+version = "1.4.1"
+
+[[deps.PrettyPrint]]
+git-tree-sha1 = "632eb4abab3449ab30c5e1afaa874f0b98b586e4"
+uuid = "8162dcfd-2161-5ef2-ae6c-7681170c5f98"
+version = "0.2.0"
+
+[[deps.PrettyTables]]
+deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "Reexport", "StringManipulation", "Tables"]
+git-tree-sha1 = "88b895d13d53b5577fd53379d913b9ab9ac82660"
+uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
+version = "2.3.1"
+
+[[deps.Printf]]
+deps = ["Unicode"]
+uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
+
+[[deps.RBNF]]
+deps = ["DataStructures", "MLStyle", "PrettyPrint"]
+git-tree-sha1 = "c7da51b46fb5d206ffe19f7c2e86d1cae7bd7fd5"
+uuid = "83ef0002-5b9e-11e9-219b-65bac3c6d69c"
+version = "0.2.3"
+
+[[deps.REPL]]
+deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
+uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
+
+[[deps.Random]]
+deps = ["SHA"]
+uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
+
+[[deps.Reexport]]
+git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
+uuid = "189a3867-3050-52da-a836-e630ba90ab69"
+version = "1.2.2"
+
+[[deps.Requires]]
+deps = ["UUIDs"]
+git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
+uuid = "ae029012-a4dd-5104-9daa-d747884805df"
+version = "1.3.0"
+
+[[deps.SHA]]
+uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
+version = "0.7.0"
+
+[[deps.SentinelArrays]]
+deps = ["Dates", "Random"]
+git-tree-sha1 = "0e7508ff27ba32f26cd459474ca2ede1bc10991f"
+uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
+version = "1.4.1"
+
+[[deps.Serialization]]
+uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
+
+[[deps.Setfield]]
+deps = ["ConstructionBase", "Future", "MacroTools", "StaticArraysCore"]
+git-tree-sha1 = "e2cc6d8c88613c05e1defb55170bf5ff211fbeac"
+uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46"
+version = "1.1.1"
+
+[[deps.SharedArrays]]
+deps = ["Distributed", "Mmap", "Random", "Serialization"]
+uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383"
+
+[[deps.SimpleTraits]]
+deps = ["InteractiveUtils", "MacroTools"]
+git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231"
+uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
+version = "0.9.4"
+
+[[deps.Sockets]]
+uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
+
+[[deps.SortingAlgorithms]]
+deps = ["DataStructures"]
+git-tree-sha1 = "66e0a8e672a0bdfca2c3f5937efb8538b9ddc085"
+uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
+version = "1.2.1"
+
+[[deps.SparseArrays]]
+deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"]
+uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
+version = "1.10.0"
+
+[[deps.StaticArrays]]
+deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"]
+git-tree-sha1 = "7b0e9c14c624e435076d19aea1e5cbdec2b9ca37"
+uuid = "90137ffa-7385-5640-81b9-e52037218182"
+version = "1.9.2"
+weakdeps = ["ChainRulesCore", "Statistics"]
+
+ [deps.StaticArrays.extensions]
+ StaticArraysChainRulesCoreExt = "ChainRulesCore"
+ StaticArraysStatisticsExt = "Statistics"
+
+[[deps.StaticArraysCore]]
+git-tree-sha1 = "36b3d696ce6366023a0ea192b4cd442268995a0d"
+uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
+version = "1.4.2"
+
+[[deps.Statistics]]
+deps = ["LinearAlgebra", "SparseArrays"]
+uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
+version = "1.10.0"
+
+[[deps.StringManipulation]]
+deps = ["PrecompileTools"]
+git-tree-sha1 = "a04cabe79c5f01f4d723cc6704070ada0b9d46d5"
+uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e"
+version = "0.3.4"
+
+[[deps.StructTypes]]
+deps = ["Dates", "UUIDs"]
+git-tree-sha1 = "ca4bccb03acf9faaf4137a9abc1881ed1841aa70"
+uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
+version = "1.10.0"
+
+[[deps.SuiteSparse_jll]]
+deps = ["Artifacts", "Libdl", "libblastrampoline_jll"]
+uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c"
+version = "7.2.1+1"
+
+[[deps.Suppressor]]
+deps = ["Logging"]
+git-tree-sha1 = "6cd9e4a207964c07bf6395beff7a1e8f21d0f3b2"
+uuid = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
+version = "0.2.6"
+
+[[deps.TOML]]
+deps = ["Dates"]
+uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
+version = "1.0.3"
+
+[[deps.TableTraits]]
+deps = ["IteratorInterfaceExtensions"]
+git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
+uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
+version = "1.0.1"
+
+[[deps.TableTraitsUtils]]
+deps = ["DataValues", "IteratorInterfaceExtensions", "Missings", "TableTraits"]
+git-tree-sha1 = "78fecfe140d7abb480b53a44f3f85b6aa373c293"
+uuid = "382cd787-c1b6-5bf2-a167-d5b971a19bda"
+version = "1.0.2"
+
+[[deps.Tables]]
+deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits"]
+git-tree-sha1 = "cb76cf677714c095e535e3501ac7954732aeea2d"
+uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
+version = "1.11.1"
+
+[[deps.Tar]]
+deps = ["ArgTools", "SHA"]
+uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
+version = "1.10.0"
+
+[[deps.Test]]
+deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
+uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
+
+[[deps.Tricks]]
+git-tree-sha1 = "eae1bb484cd63b36999ee58be2de6c178105112f"
+uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775"
+version = "0.1.8"
+
+[[deps.TupleTools]]
+git-tree-sha1 = "155515ed4c4236db30049ac1495e2969cc06be9d"
+uuid = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6"
+version = "1.4.3"
+
+[[deps.URIParser]]
+deps = ["Unicode"]
+git-tree-sha1 = "53a9f49546b8d2dd2e688d216421d050c9a31d0d"
+uuid = "30578b45-9adc-5946-b283-645ec420af67"
+version = "0.4.1"
+
+[[deps.URIs]]
+git-tree-sha1 = "67db6cc7b3821e19ebe75791a9dd19c9b1188f2b"
+uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
+version = "1.5.1"
+
+[[deps.UUIDs]]
+deps = ["Random", "SHA"]
+uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
+
+[[deps.Unicode]]
+uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
+
+[[deps.Vega]]
+deps = ["BufferedStreams", "DataStructures", "DataValues", "Dates", "FileIO", "FilePaths", "IteratorInterfaceExtensions", "JSON", "JSONSchema", "MacroTools", "NodeJS", "Pkg", "REPL", "Random", "Setfield", "TableTraits", "TableTraitsUtils", "URIParser"]
+git-tree-sha1 = "9d5c73642d291cb5aa34eb47b9d71428c4132398"
+uuid = "239c3e63-733f-47ad-beb7-a12fde22c578"
+version = "2.6.2"
+
+[[deps.YaoHIR]]
+deps = ["Expronicon", "MLStyle", "YaoLocations"]
+git-tree-sha1 = "7fa66adcb137e2b3025642b758ce612d2d8ff1fa"
+uuid = "6769671a-fce8-4286-b3f7-6099e1b1298a"
+version = "0.2.2"
+
+[[deps.YaoLocations]]
+git-tree-sha1 = "c90c42c8668c9096deb0c861822f0f8f80cbdc68"
+uuid = "66df03fb-d475-48f7-b449-3d9064bf085b"
+version = "0.1.6"
+
+[[deps.ZXCalculus]]
+deps = ["Expronicon", "Graphs", "LinearAlgebra", "MLStyle", "Multigraphs", "OMEinsum", "SparseArrays", "YaoHIR", "YaoLocations"]
+git-tree-sha1 = "9110975b06644a0844c98e13944c00af26087bf4"
+uuid = "3525faa3-032d-4235-a8d4-8c2939a218dd"
+version = "0.6.0"
+
+[[deps.Zlib_jll]]
+deps = ["Libdl"]
+uuid = "83775a58-1f1d-513f-b197-d71354ab007a"
+version = "1.2.13+1"
+
+[[deps.libblastrampoline_jll]]
+deps = ["Artifacts", "Libdl"]
+uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"
+version = "5.8.0+1"
+
+[[deps.nghttp2_jll]]
+deps = ["Artifacts", "Libdl"]
+uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
+version = "1.52.0+1"
+
+[[deps.p7zip_jll]]
+deps = ["Artifacts", "Libdl"]
+uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
+version = "17.4.0+2"
+"""
+
+# ╔═╡ Cell order:
+# ╠═aa11ea12-6a9c-11ee-11b6-77a1fbfdf4b5
+# ╟─6ebebc14-6b0f-48b7-a8e4-fb6f7f9f7f0e
+# ╠═639aaf18-e63b-4b07-8557-8e21a874d91a
+# ╠═69587b8e-26cf-4862-abe6-f81cc6967db3
+# ╠═97eae154-ce25-4f22-b89a-af653f79dcd7
+# ╠═15e4062a-37b3-40dc-add3-9d8ad7520b4d
+# ╠═e22922f8-5a54-475b-b325-dda82547c556
+# ╟─37954f01-da8c-4018-a7e1-811d4a86fb26
+# ╠═c984b469-89d0-4d02-9264-e967697e50b3
+# ╠═996a236f-90b5-42bb-8627-19d5a7facef6
+# ╠═df136e09-4958-433d-a3ce-60f73a10968a
+# ╠═69d97139-73d2-4b3f-8d1f-aa8437880754
+# ╠═57c4c6eb-54e1-4412-b3ca-3bd7588e4e34
+# ╠═a092392c-eff5-4c5a-be9b-c9e67881cf46
+# ╠═a6819a4e-3029-4fec-9baa-8ec842755e49
+# ╠═d9da3492-048d-4458-aa37-801e84b61ec7
+# ╠═d65ab9bd-6dcc-4502-a8fb-301abf404856
+# ╠═c467fe63-487b-4087-b166-01ed41a47eec
+# ╠═27b7b121-0c13-49ed-97e6-c73386e844a0
+# ╠═ed656d2d-c4af-45a3-a5d8-5fd8c1cccac8
+# ╠═1b36a6ba-5498-4aa5-ab67-67dff42c8422
+# ╠═ab841776-6b79-4662-9998-04f513370fee
+# ╠═4ff2d0e2-9dda-405d-aa77-9abb70eace77
+# ╠═7bec3f25-507a-42e8-8547-cae8bfc317d8
+# ╠═f3235791-4582-44a3-ba68-6c39a0d0b26b
+# ╠═7220947a-f153-4bb7-a0ba-972af51d3fe7
+# ╠═3f98b870-a534-4f69-b460-64c59cd8ef96
+# ╠═dd5c40da-0530-4975-8245-78538ad6d244
+# ╠═a48d68b5-559a-4937-a2b7-c13e5f5181b0
+# ╟─00000000-0000-0000-0000-000000000001
+# ╟─00000000-0000-0000-0000-000000000002
diff --git a/notebooks/research.jl b/notebooks/research.jl
new file mode 100644
index 0000000..708bc7b
--- /dev/null
+++ b/notebooks/research.jl
@@ -0,0 +1,1135 @@
+### A Pluto.jl notebook ###
+# v0.19.43
+
+using Markdown
+using InteractiveUtils
+
+# ╔═╡ dd08aa73-0d86-4f8b-970b-59f9ad9fac2d
+begin
+ # Used for creating the IRCode for a BlockIR
+ using Core.Compiler: IRCode
+
+ # Pluto
+ using PlutoUI
+
+ # Weak Dependencies
+ using Vega
+ using OpenQASM
+ using DataFrames
+ using YaoHIR
+ using YaoLocations
+ using YaoHIR: BlockIR
+ using YaoHIR.IntrinsicOperation
+ using ZXCalculus, ZXCalculus.ZX, ZXCalculus.ZXW
+ using DynamicQuantumCircuits
+
+end
+
+# ╔═╡ 506db9e1-4260-408d-ba72-51581b548e53
+function Base.show(io::IO, mime::MIME"text/html", zx::Union{ZXDiagram,ZXGraph})
+ g = plot(zx)
+ Base.show(io, mime, g)
+end
+
+
+# ╔═╡ db7e9cf8-9abf-448b-be68-43231853faff
+md"""
+
+
+## Equivalence Checking of Quantum Circuits
+### Principle of Quantum Circuit Equality
+#### Reversiblity
+Equivalence checking the equality of two quantum circuits relies on the reversibility
+of quantum operations. Every quantum operation is *unitary* and thus reversible. The product of any quantum operation and its inverse (adjoint)
+will always yield the identity.
+
+
+#### Unitary
+For a matrix to be unitary, this property needs to hold:
+`` U \cdot U^\dagger = U^\dagger \cdot U = I_n | U \in \mathbb{R}^{n \times n} ``
+
+If ``U_1`` and ``U_2`` are unitary matrices, so is their matrix product ``U_1 \cdot U_2``.
+Unitary matrices preserve inner products. Thus, if ``U`` is unitary, then for all ``V , V′ \in \mathbb{C}^n`` we have:
+``⟨U V |U V ′ ⟩ = ⟨U |V ′ ⟩``
+
+### Equality
+In order to verify the equality of two quantum circuits we exploit their reversibility.
+
+Given two quantum circuits ``G_1`` and ``G_2`` as well the systems matrices ``U_1`` and ``U_1`` that describe the operations of these quantum circuits we ask ourself, the problem of equivalence checking is to verify if there is no difference ``D = U_1 \cdot U_2^\dagger`` between the first and second quantum circuit.
+
+To verify if the two quantum circuits are equal we check if ``tr(D) = 0``, as this implies that the difference is the idenity matrix.
+ ``U_1 \cdot U_2^\dagger = D````U_1 \cdot U_2^\dagger = D = I``.
+
+If the two quantum circuits are not equal, ``U_1 \cdot U_2^\dagger = D != I``, the
+problem is to
+- approximate how close the quantum circuits are
+- debug the quantum circuits, in order to reduce the difference `D` between them.
+
+
+
+## ZX Calculus Diagram
+### Introduction
+ZX-Calculus is a unified formalism for describing quantum computation, mainly over
+qubits. It is a rigorous graphical language, that utilizes the powerful set of rewrite
+rules for reasoning about linear maps between qubits, which are represented as string diagrams called ZX-Diagrams.
+
+#### Example
+Of three CNOT Gats that are equal to a SWAP Gate
+
+"""
+
+
+
+
+# ╔═╡ c06c5b9f-e5c1-4d0c-8ed5-937ad3871d3d
+begin
+ zx1 = ZXDiagram(2)
+ push_gate!(zx1, Val(:CNOT), 1, 2)
+ push_gate!(zx1, Val(:CNOT), 2, 1)
+ push_gate!(zx1, Val(:CNOT), 1, 2)
+
+end
+
+# ╔═╡ 5e0fb39e-68b3-45f6-8cb2-2dd0b79b35d4
+md"""
+### Applications
+ZX-Calculus has been successfully applied to
+- quantum circuit compilationoptimization and equivalence checking.
+
+ZX-Calculus is a generaliation of Quantum Computing. It is complete, meaning that all equations concerning quantum processes can be derived using linear algebra, can also be obtained using a handful of graphical rules.
+
+
+### Example Bernstein-Vazirani ZX-Diagram
+"""
+
+# ╔═╡ 587be022-6005-44d5-bb72-53cc9e3ba3bb
+bv_101_static = ZXDiagram(BlockIR("""
+OPENQASM 2.0;
+include "qelib1.inc";
+qreg q[4];
+creg c[3];
+x q[3];
+h q[0];
+h q[1];
+h q[2];
+h q[3];
+CX q[0],q[3];
+CX q[2],q[3];
+h q[0];
+h q[1];
+h q[2];
+measure q[0] -> c[0];
+measure q[1] -> c[1];
+measure q[2] -> c[2];
+"""))
+
+# ╔═╡ 482fdb57-2b0b-44b9-a5a0-f4dc26e15a7d
+bv_101_dynamic = ZXDiagram(BlockIR(unitary_reconstruction(OpenQASM.parse("""
+OPENQASM 2.0;
+include "qelib1.inc";
+qreg q[2];
+creg c[3];
+x q[1];
+h q[0];
+h q[1];
+CX q[0],q[1];
+h q[0];
+measure q[0] -> c[0];
+reset q[0];
+h q[0];
+h q[0];
+measure q[0] -> c[1];
+reset q[0];
+h q[0];
+CX q[0],q[1];
+h q[0];
+measure q[0] -> c[2];
+"""))))
+
+# ╔═╡ 57301b22-969f-481e-ae0b-0336e1ee5055
+md"""
+## Logic Verification of Quantum Circuits
+### Informal Definition of Quantum Circuit Equality
+> Two circuits are equivalent if they produce the same output for every possible input
+`` U_1 \cdot U_2 = I ``
+
+"""
+
+# ╔═╡ a8470d1a-8dc1-4a86-85b9-efd1836cf42c
+verify_equality(bv_101_dynamic, bv_101_static)
+
+# ╔═╡ 6e823d50-9107-4488-897e-d647334573f9
+md"""
+What happens if we add an extra Z gate to the first qubit?
+"""
+
+# ╔═╡ e3aa4e99-cb1f-478b-9e80-82b0ab02f606
+begin
+ push_gate!(bv_101_static, Val(:X), 1, 1 // 1)
+ verify_equality(bv_101_dynamic, bv_101_static)
+end
+
+# ╔═╡ a44ef98a-61fb-4271-9d36-c4d096f7e600
+md"""
+## Differenciation of ZX-Calculus
+"""
+
+# ╔═╡ fb2448ef-aebe-419f-ad1d-a161edacd5a0
+md"""
+### Difference of two quantum circuits
+Approximation equality of ZX-Diagrams using algebraic ZX-Calculus
+
+"""
+
+# ╔═╡ 38da72a7-7e81-426f-ba08-b4158dc6a011
+bv_101_difference = full_reduction(concat!(ZXDiagram(BlockIR(unitary_reconstruction(OpenQASM.parse("""
+ OPENQASM 2.0;
+ include "qelib1.inc";
+ qreg q[2];
+ creg c[3];
+ x q[1];
+ h q[0];
+ h q[1];
+ CX q[0],q[1];
+ h q[0];
+ measure q[0] -> c[0];
+ reset q[0];
+ h q[0];
+ h q[0];
+ measure q[0] -> c[1];
+ reset q[0];
+ h q[0];
+ CX q[0],q[1];
+ h q[0];
+ measure q[0] -> c[2];
+ """)))), dagger(ZXDiagram(BlockIR(unitary_reconstruction(OpenQASM.parse("""
+ OPENQASM 2.0;
+ include "qelib1.inc";
+ qreg q[2];
+ creg c[3];
+ x q[1];
+ h q[0];
+ h q[1];
+ CX q[0],q[1];
+ h q[0];
+ measure q[0] -> c[0];
+ reset q[0];
+ h q[0];
+ h q[0];
+ measure q[0] -> c[1];
+ reset q[0];
+ h q[0];
+ CX q[0],q[1];
+ h q[0];
+ x q[0];
+ measure q[0] -> c[2];
+ """)))))))
+
+# ╔═╡ 742750be-1262-4cbe-b476-f62e5e5c1fcf
+bir = circuit_extraction(bv_101_difference)
+
+# ╔═╡ 686cfe18-598b-4184-8a6d-85711109b055
+ZXW.convert_to_zxwd(BlockIR(IRCode(), 4, bir))
+
+# ╔═╡ 9af85660-a4e3-4f27-b6cb-cf36d9b50d91
+z1 = ZXDiagram(1)
+
+
+# ╔═╡ 785ec008-63af-4f56-9792-f66b27a27388
+md"""
+Add a green spider
+"""
+
+# ╔═╡ 44cbd3d8-6d36-4a0b-8613-552bbba48f3d
+begin
+ zx_z = ZXDiagram(1)
+ push_gate!(zx_z, Val(:Z), 1)
+end
+
+# ╔═╡ 0c2b4e33-5dcc-476d-8a9c-1e4244231e05
+begin
+ zx_x = ZXDiagram(1)
+ push_gate!(zx_x, Val(:X), 1, 1 // 1)
+end
+
+
+# ╔═╡ eebd1e46-0c0f-487d-8bee-07b1c17552c4
+begin
+ zx_s = ZXDiagram(1)
+ push_gate!(zx_s, Val(:Z), 1, 1 // 2)
+end
+
+
+
+
+# ╔═╡ 9200a1b1-11f7-4428-8840-c52dd4403c45
+begin
+ zx_t = ZXDiagram(1)
+ push_gate!(zx_t, Val(:Z), 1, 1 // 4)
+end
+
+
+
+
+# ╔═╡ 924efc08-681b-4804-93c6-38acc125315a
+begin
+ zx_h = ZXDiagram(1)
+ push_gate!(zx_h, Val(:H), 1)
+end
+
+
+
+
+# ╔═╡ 5fdc6a08-c284-414e-9e96-8734289a98de
+begin
+ zx_cnot = ZXDiagram(2)
+ push_gate!(zx_cnot, Val(:CNOT), 1, 2)
+
+end
+
+# ╔═╡ 0523c034-06ac-4383-b50f-6b68e6b1739f
+begin
+ zx = ZXDiagram(3)
+ push_gate!(zx, Val(:X), 1, 1 // 1)
+ push_gate!(zx, Val(:CNOT), 1, 2)
+ push_gate!(zx, Val(:H), 1)
+ push_gate!(zx, Val(:CNOT), 2, 3)
+ push_gate!(zx, Val(:H), 2)
+end
+
+
+# ╔═╡ 4d7d8a96-5aba-4b63-a5da-959716f2d2bf
+md"## Converting ZXDiagrams into ZXGraphs"
+
+# ╔═╡ 7da637f0-e359-41d9-b395-27168459c20c
+zx_graph = ZXGraph(zx)
+
+# ╔═╡ bed7a0c5-da16-40b5-9d84-4dad2dfb8739
+begin
+ zx_id = ZXDiagram(2)
+ push_gate!(zx_id, Val(:X), 1)
+ push_gate!(zx_id, Val(:X), 1)
+end
+
+
+# ╔═╡ 8cde99fd-ee0a-4d94-a94e-23ebc9ac8608
+zx_id_graph = ZXGraph(zx_id)
+
+# ╔═╡ 17389edf-33d2-4dd8-bf86-df0467e65059
+full_reduction(zx_id)
+
+# ╔═╡ 99bb5eff-79e7-4c0e-95ae-a6d2130f46cb
+md"Equality"
+
+# ╔═╡ f240382f-b682-4947-938f-c98d9c901c90
+zx_dagger = dagger(zx)
+
+# ╔═╡ 89f14c32-895d-4101-b4a8-bc410a2adaa5
+concat!(zx, zx_dagger)
+
+# ╔═╡ 0b838710-91e4-4572-9fe0-5c97e579ddd1
+m_simple = full_reduction(zx)
+
+
+# ╔═╡ fdb7ca6a-bf5c-4216-8a18-a7c3603240ea
+contains_only_bare_wires(m_simple)
+
+# ╔═╡ 6da61df3-b6e7-4991-ab9f-5994b55841e0
+full_reduction(zx)
+
+# ╔═╡ 6b431ff3-f644-4123-82fd-704c054eb5bb
+md"DQC Example"
+
+# ╔═╡ cee877f2-8fd8-4a4e-9b8c-199411d449c5
+begin
+ traditional = """
+ OPENQASM 2.0;
+ include "qelib1.inc";
+ qreg q0[3];
+ creg c0[2];
+ h q0[0];
+ h q0[1];
+ x q0[2];
+ h q0[2];
+ CX q0[0],q0[2];
+ h q0[0];
+ CX q0[1],q0[2];
+ h q0[1];
+ measure q0[0] -> c0[0];
+ measure q0[1] -> c0[1];
+ """
+ c1 = ZXDiagram(BlockIR(traditional))
+end
+
+# ╔═╡ 20886e57-0c2c-4bf3-8c3d-8ed7d4f33fec
+begin
+ dynamic = OpenQASM.parse("""
+ OPENQASM 2.0;
+ include "qelib1.inc";
+ qreg q0[2];
+ creg mcm[1];
+ creg end[1];
+ h q0[0];
+ x q0[1];
+ h q0[1];
+ CX q0[0],q0[1];
+ h q0[0];
+ measure q0[0] -> mcm[0];
+ reset q0[0];
+ h q0[0];
+ CX q0[0],q0[1];
+ h q0[0];
+ measure q0[0] -> end[0];
+ """)
+ unitary = unitary_reconstruction(dynamic)
+ c2 = ZXDiagram(BlockIR(unitary))
+
+
+end
+
+# ╔═╡ 9b838e52-79f6-49bd-9574-62d94f941558
+c2_dagger = dagger(c2)
+
+
+# ╔═╡ 91ea0d20-8f8b-4bec-a98d-6aebbc4228e1
+dqc_merged = concat!(c1, c2_dagger)
+
+# ╔═╡ fbbe52e6-40d0-48ab-aa92-58a5125a33b2
+reduced = full_reduction(concat!(ZXDiagram(BlockIR(traditional)), dagger(ZXDiagram(BlockIR(unitary)))))
+
+# ╔═╡ f7982574-ddff-4e7b-a4fc-52462a59d21c
+contains_only_bare_wires(reduced)
+
+# ╔═╡ 00000000-0000-0000-0000-000000000001
+PLUTO_PROJECT_TOML_CONTENTS = """
+[deps]
+DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
+OpenQASM = "a8821629-a4c0-4df7-9e00-12969ff383a7"
+PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
+Vega = "239c3e63-733f-47ad-beb7-a12fde22c578"
+YaoHIR = "6769671a-fce8-4286-b3f7-6099e1b1298a"
+YaoLocations = "66df03fb-d475-48f7-b449-3d9064bf085b"
+ZXCalculus = "3525faa3-032d-4235-a8d4-8c2939a218dd"
+
+[compat]
+DataFrames = "~1.6.1"
+OpenQASM = "~2.1.4"
+PlutoUI = "~0.7.59"
+Vega = "~2.7.0"
+YaoHIR = "~0.2.3"
+YaoLocations = "~0.1.6"
+ZXCalculus = "~0.6.0"
+"""
+
+# ╔═╡ 00000000-0000-0000-0000-000000000002
+PLUTO_MANIFEST_TOML_CONTENTS = """
+# This file is machine-generated - editing it directly is not advised
+
+julia_version = "1.10.4"
+manifest_format = "2.0"
+project_hash = "e6f4606be1811753c50082763b6d71d5d123551f"
+
+[[deps.AbstractPlutoDingetjes]]
+deps = ["Pkg"]
+git-tree-sha1 = "6e1d2a35f2f90a4bc7c2ed98079b2ba09c35b83a"
+uuid = "6e696c72-6542-2067-7265-42206c756150"
+version = "1.3.2"
+
+[[deps.AbstractTrees]]
+git-tree-sha1 = "2d9c9a55f9c93e8887ad391fbae72f8ef55e1177"
+uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
+version = "0.4.5"
+
+[[deps.ArgTools]]
+uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
+version = "1.1.1"
+
+[[deps.ArnoldiMethod]]
+deps = ["LinearAlgebra", "Random", "StaticArrays"]
+git-tree-sha1 = "d57bd3762d308bded22c3b82d033bff85f6195c6"
+uuid = "ec485272-7323-5ecc-a04f-4719b315124d"
+version = "0.4.0"
+
+[[deps.Artifacts]]
+uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
+
+[[deps.Base64]]
+uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
+
+[[deps.BatchedRoutines]]
+deps = ["LinearAlgebra"]
+git-tree-sha1 = "441db9f0399bcfb4eeb8b891a6b03f7acc5dc731"
+uuid = "a9ab73d0-e05c-5df1-8fde-d6a4645b8d8e"
+version = "0.2.2"
+
+[[deps.BetterExp]]
+git-tree-sha1 = "dd3448f3d5b2664db7eceeec5f744535ce6e759b"
+uuid = "7cffe744-45fd-4178-b173-cf893948b8b7"
+version = "0.1.0"
+
+[[deps.BufferedStreams]]
+git-tree-sha1 = "4ae47f9a4b1dc19897d3743ff13685925c5202ec"
+uuid = "e1450e63-4bb3-523b-b2a4-4ffa8c0fd77d"
+version = "1.2.1"
+
+[[deps.ChainRulesCore]]
+deps = ["Compat", "LinearAlgebra"]
+git-tree-sha1 = "71acdbf594aab5bbb2cec89b208c41b4c411e49f"
+uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
+version = "1.24.0"
+weakdeps = ["SparseArrays"]
+
+ [deps.ChainRulesCore.extensions]
+ ChainRulesCoreSparseArraysExt = "SparseArrays"
+
+[[deps.ColorTypes]]
+deps = ["FixedPointNumbers", "Random"]
+git-tree-sha1 = "b10d0b65641d57b8b4d5e234446582de5047050d"
+uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
+version = "0.11.5"
+
+[[deps.Combinatorics]]
+git-tree-sha1 = "08c8b6831dc00bfea825826be0bc8336fc369860"
+uuid = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
+version = "1.0.2"
+
+[[deps.Compat]]
+deps = ["TOML", "UUIDs"]
+git-tree-sha1 = "b1c55339b7c6c350ee89f2c1604299660525b248"
+uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
+version = "4.15.0"
+weakdeps = ["Dates", "LinearAlgebra"]
+
+ [deps.Compat.extensions]
+ CompatLinearAlgebraExt = "LinearAlgebra"
+
+[[deps.CompilerSupportLibraries_jll]]
+deps = ["Artifacts", "Libdl"]
+uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"
+version = "1.1.1+0"
+
+[[deps.ConstructionBase]]
+deps = ["LinearAlgebra"]
+git-tree-sha1 = "260fd2400ed2dab602a7c15cf10c1933c59930a2"
+uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
+version = "1.5.5"
+
+ [deps.ConstructionBase.extensions]
+ ConstructionBaseIntervalSetsExt = "IntervalSets"
+ ConstructionBaseStaticArraysExt = "StaticArrays"
+
+ [deps.ConstructionBase.weakdeps]
+ IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
+ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
+
+[[deps.Crayons]]
+git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15"
+uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
+version = "4.1.1"
+
+[[deps.DataAPI]]
+git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe"
+uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
+version = "1.16.0"
+
+[[deps.DataFrames]]
+deps = ["Compat", "DataAPI", "DataStructures", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrecompileTools", "PrettyTables", "Printf", "REPL", "Random", "Reexport", "SentinelArrays", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"]
+git-tree-sha1 = "04c738083f29f86e62c8afc341f0967d8717bdb8"
+uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
+version = "1.6.1"
+
+[[deps.DataStructures]]
+deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
+git-tree-sha1 = "1d0a14036acb104d9e89698bd408f63ab58cdc82"
+uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
+version = "0.18.20"
+
+[[deps.DataValueInterfaces]]
+git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
+uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
+version = "1.0.0"
+
+[[deps.DataValues]]
+deps = ["DataValueInterfaces", "Dates"]
+git-tree-sha1 = "d88a19299eba280a6d062e135a43f00323ae70bf"
+uuid = "e7dc6d0d-1eca-5fa6-8ad6-5aecde8b7ea5"
+version = "0.4.13"
+
+[[deps.Dates]]
+deps = ["Printf"]
+uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
+
+[[deps.Distributed]]
+deps = ["Random", "Serialization", "Sockets"]
+uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
+
+[[deps.Downloads]]
+deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
+uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
+version = "1.6.0"
+
+[[deps.Expronicon]]
+deps = ["MLStyle"]
+git-tree-sha1 = "35141514242193e3e820d90007f973bf35bf5da0"
+uuid = "6b7a57c9-7cc1-4fdf-b7f5-e857abae3636"
+version = "0.10.10"
+
+[[deps.FileIO]]
+deps = ["Pkg", "Requires", "UUIDs"]
+git-tree-sha1 = "82d8afa92ecf4b52d78d869f038ebfb881267322"
+uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
+version = "1.16.3"
+
+[[deps.FilePaths]]
+deps = ["FilePathsBase", "MacroTools", "Reexport", "Requires"]
+git-tree-sha1 = "919d9412dbf53a2e6fe74af62a73ceed0bce0629"
+uuid = "8fc22ac5-c921-52a6-82fd-178b2807b824"
+version = "0.8.3"
+
+[[deps.FilePathsBase]]
+deps = ["Compat", "Dates", "Mmap", "Printf", "Test", "UUIDs"]
+git-tree-sha1 = "9f00e42f8d99fdde64d40c8ea5d14269a2e2c1aa"
+uuid = "48062228-2e41-5def-b9a4-89aafe57970f"
+version = "0.9.21"
+
+[[deps.FileWatching]]
+uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"
+
+[[deps.FixedPointNumbers]]
+deps = ["Statistics"]
+git-tree-sha1 = "05882d6995ae5c12bb5f36dd2ed3f61c98cbb172"
+uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
+version = "0.8.5"
+
+[[deps.Future]]
+deps = ["Random"]
+uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
+
+[[deps.Graphs]]
+deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"]
+git-tree-sha1 = "ebd18c326fa6cee1efb7da9a3b45cf69da2ed4d9"
+uuid = "86223c79-3864-5bf0-83f7-82e725a168b6"
+version = "1.11.2"
+
+[[deps.Hyperscript]]
+deps = ["Test"]
+git-tree-sha1 = "179267cfa5e712760cd43dcae385d7ea90cc25a4"
+uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91"
+version = "0.0.5"
+
+[[deps.HypertextLiteral]]
+deps = ["Tricks"]
+git-tree-sha1 = "7134810b1afce04bbc1045ca1985fbe81ce17653"
+uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
+version = "0.9.5"
+
+[[deps.IOCapture]]
+deps = ["Logging", "Random"]
+git-tree-sha1 = "b6d6bfdd7ce25b0f9b2f6b3dd56b2673a66c8770"
+uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89"
+version = "0.2.5"
+
+[[deps.Inflate]]
+git-tree-sha1 = "d1b1b796e47d94588b3757fe84fbf65a5ec4a80d"
+uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9"
+version = "0.1.5"
+
+[[deps.InlineStrings]]
+deps = ["Parsers"]
+git-tree-sha1 = "86356004f30f8e737eff143d57d41bd580e437aa"
+uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48"
+version = "1.4.1"
+
+ [deps.InlineStrings.extensions]
+ ArrowTypesExt = "ArrowTypes"
+
+ [deps.InlineStrings.weakdeps]
+ ArrowTypes = "31f734f8-188a-4ce0-8406-c8a06bd891cd"
+
+[[deps.InteractiveUtils]]
+deps = ["Markdown"]
+uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
+
+[[deps.InvertedIndices]]
+git-tree-sha1 = "0dc7b50b8d436461be01300fd8cd45aa0274b038"
+uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
+version = "1.3.0"
+
+[[deps.IteratorInterfaceExtensions]]
+git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
+uuid = "82899510-4779-5014-852e-03e436cf321d"
+version = "1.0.0"
+
+[[deps.JSON]]
+deps = ["Dates", "Mmap", "Parsers", "Unicode"]
+git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a"
+uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
+version = "0.21.4"
+
+[[deps.JSON3]]
+deps = ["Dates", "Mmap", "Parsers", "PrecompileTools", "StructTypes", "UUIDs"]
+git-tree-sha1 = "eb3edce0ed4fa32f75a0a11217433c31d56bd48b"
+uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
+version = "1.14.0"
+
+ [deps.JSON3.extensions]
+ JSON3ArrowExt = ["ArrowTypes"]
+
+ [deps.JSON3.weakdeps]
+ ArrowTypes = "31f734f8-188a-4ce0-8406-c8a06bd891cd"
+
+[[deps.JSONSchema]]
+deps = ["Downloads", "JSON", "JSON3", "URIs"]
+git-tree-sha1 = "5f0bd0cd69df978fa64ccdcb5c152fbc705455a1"
+uuid = "7d188eb4-7ad8-530c-ae41-71a32a6d4692"
+version = "1.3.0"
+
+[[deps.LaTeXStrings]]
+git-tree-sha1 = "50901ebc375ed41dbf8058da26f9de442febbbec"
+uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
+version = "1.3.1"
+
+[[deps.LibCURL]]
+deps = ["LibCURL_jll", "MozillaCACerts_jll"]
+uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"
+version = "0.6.4"
+
+[[deps.LibCURL_jll]]
+deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
+uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"
+version = "8.4.0+0"
+
+[[deps.LibGit2]]
+deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"]
+uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
+
+[[deps.LibGit2_jll]]
+deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"]
+uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5"
+version = "1.6.4+0"
+
+[[deps.LibSSH2_jll]]
+deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
+uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"
+version = "1.11.0+1"
+
+[[deps.Libdl]]
+uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
+
+[[deps.LinearAlgebra]]
+deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"]
+uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
+
+[[deps.Logging]]
+uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
+
+[[deps.MIMEs]]
+git-tree-sha1 = "65f28ad4b594aebe22157d6fac869786a255b7eb"
+uuid = "6c6e2e6c-3030-632d-7369-2d6c69616d65"
+version = "0.1.4"
+
+[[deps.MLStyle]]
+git-tree-sha1 = "bc38dff0548128765760c79eb7388a4b37fae2c8"
+uuid = "d8e11817-5142-5d16-987a-aa16d5891078"
+version = "0.4.17"
+
+[[deps.MacroTools]]
+deps = ["Markdown", "Random"]
+git-tree-sha1 = "2fa9ee3e63fd3a4f7a9a4f4744a52f4856de82df"
+uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
+version = "0.5.13"
+
+[[deps.Markdown]]
+deps = ["Base64"]
+uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
+
+[[deps.MbedTLS_jll]]
+deps = ["Artifacts", "Libdl"]
+uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
+version = "2.28.2+1"
+
+[[deps.Missings]]
+deps = ["DataAPI"]
+git-tree-sha1 = "ec4f7fbeab05d7747bdf98eb74d130a2a2ed298d"
+uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
+version = "1.2.0"
+
+[[deps.Mmap]]
+uuid = "a63ad114-7e13-5084-954f-fe012c677804"
+
+[[deps.MozillaCACerts_jll]]
+uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
+version = "2023.1.10"
+
+[[deps.Multigraphs]]
+deps = ["Graphs", "LinearAlgebra", "SparseArrays"]
+git-tree-sha1 = "055a7c49a626e17a8c99bcaaf472d0de60848929"
+uuid = "7ebac608-6c66-46e6-9856-b5f43e107bac"
+version = "0.3.0"
+
+[[deps.NetworkOptions]]
+uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"
+version = "1.2.0"
+
+[[deps.NodeJS]]
+deps = ["Pkg"]
+git-tree-sha1 = "bf1f49fd62754064bc42490a8ddc2aa3694a8e7a"
+uuid = "2bd173c7-0d6d-553b-b6af-13a54713934c"
+version = "2.0.0"
+
+[[deps.OMEinsum]]
+deps = ["AbstractTrees", "BatchedRoutines", "ChainRulesCore", "Combinatorics", "LinearAlgebra", "MacroTools", "OMEinsumContractionOrders", "Test", "TupleTools"]
+git-tree-sha1 = "3b7f8f3ffb63e3c7fd0d9b364862a2e35f70478e"
+uuid = "ebe7aa44-baf0-506c-a96f-8464559b3922"
+version = "0.7.6"
+
+ [deps.OMEinsum.extensions]
+ CUDAExt = "CUDA"
+
+ [deps.OMEinsum.weakdeps]
+ CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
+
+[[deps.OMEinsumContractionOrders]]
+deps = ["AbstractTrees", "BetterExp", "JSON", "SparseArrays", "Suppressor"]
+git-tree-sha1 = "b0cba9f4a6f021a63b066f0bb29a6fd63c93be44"
+uuid = "6f22d1fd-8eed-4bb7-9776-e7d684900715"
+version = "0.8.3"
+
+ [deps.OMEinsumContractionOrders.extensions]
+ KaHyParExt = ["KaHyPar"]
+
+ [deps.OMEinsumContractionOrders.weakdeps]
+ KaHyPar = "2a6221f6-aa48-11e9-3542-2d9e0ef01880"
+
+[[deps.OpenBLAS_jll]]
+deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
+uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"
+version = "0.3.23+4"
+
+[[deps.OpenQASM]]
+deps = ["MLStyle", "RBNF"]
+git-tree-sha1 = "aa6c47be6512e3299d9e56224d13d6a2303e3d6e"
+uuid = "a8821629-a4c0-4df7-9e00-12969ff383a7"
+version = "2.1.4"
+
+[[deps.OrderedCollections]]
+git-tree-sha1 = "dfdf5519f235516220579f949664f1bf44e741c5"
+uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
+version = "1.6.3"
+
+[[deps.Parsers]]
+deps = ["Dates", "PrecompileTools", "UUIDs"]
+git-tree-sha1 = "8489905bcdbcfac64d1daa51ca07c0d8f0283821"
+uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
+version = "2.8.1"
+
+[[deps.Pkg]]
+deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
+uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
+version = "1.10.0"
+
+[[deps.PlutoUI]]
+deps = ["AbstractPlutoDingetjes", "Base64", "ColorTypes", "Dates", "FixedPointNumbers", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "MIMEs", "Markdown", "Random", "Reexport", "URIs", "UUIDs"]
+git-tree-sha1 = "ab55ee1510ad2af0ff674dbcced5e94921f867a9"
+uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
+version = "0.7.59"
+
+[[deps.PooledArrays]]
+deps = ["DataAPI", "Future"]
+git-tree-sha1 = "36d8b4b899628fb92c2749eb488d884a926614d3"
+uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720"
+version = "1.4.3"
+
+[[deps.PrecompileTools]]
+deps = ["Preferences"]
+git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f"
+uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
+version = "1.2.1"
+
+[[deps.Preferences]]
+deps = ["TOML"]
+git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6"
+uuid = "21216c6a-2e73-6563-6e65-726566657250"
+version = "1.4.3"
+
+[[deps.PrettyPrint]]
+git-tree-sha1 = "632eb4abab3449ab30c5e1afaa874f0b98b586e4"
+uuid = "8162dcfd-2161-5ef2-ae6c-7681170c5f98"
+version = "0.2.0"
+
+[[deps.PrettyTables]]
+deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "Reexport", "StringManipulation", "Tables"]
+git-tree-sha1 = "66b20dd35966a748321d3b2537c4584cf40387c7"
+uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
+version = "2.3.2"
+
+[[deps.Printf]]
+deps = ["Unicode"]
+uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
+
+[[deps.RBNF]]
+deps = ["DataStructures", "MLStyle", "PrettyPrint"]
+git-tree-sha1 = "12c19821099177fad12336af5e3d0ca8f41eb3d3"
+uuid = "83ef0002-5b9e-11e9-219b-65bac3c6d69c"
+version = "0.2.4"
+
+[[deps.REPL]]
+deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
+uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
+
+[[deps.Random]]
+deps = ["SHA"]
+uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
+
+[[deps.Reexport]]
+git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
+uuid = "189a3867-3050-52da-a836-e630ba90ab69"
+version = "1.2.2"
+
+[[deps.Requires]]
+deps = ["UUIDs"]
+git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
+uuid = "ae029012-a4dd-5104-9daa-d747884805df"
+version = "1.3.0"
+
+[[deps.SHA]]
+uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
+version = "0.7.0"
+
+[[deps.SentinelArrays]]
+deps = ["Dates", "Random"]
+git-tree-sha1 = "ff11acffdb082493657550959d4feb4b6149e73a"
+uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
+version = "1.4.5"
+
+[[deps.Serialization]]
+uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
+
+[[deps.Setfield]]
+deps = ["ConstructionBase", "Future", "MacroTools", "StaticArraysCore"]
+git-tree-sha1 = "e2cc6d8c88613c05e1defb55170bf5ff211fbeac"
+uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46"
+version = "1.1.1"
+
+[[deps.SharedArrays]]
+deps = ["Distributed", "Mmap", "Random", "Serialization"]
+uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383"
+
+[[deps.SimpleTraits]]
+deps = ["InteractiveUtils", "MacroTools"]
+git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231"
+uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
+version = "0.9.4"
+
+[[deps.Sockets]]
+uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
+
+[[deps.SortingAlgorithms]]
+deps = ["DataStructures"]
+git-tree-sha1 = "66e0a8e672a0bdfca2c3f5937efb8538b9ddc085"
+uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
+version = "1.2.1"
+
+[[deps.SparseArrays]]
+deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"]
+uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
+version = "1.10.0"
+
+[[deps.StaticArrays]]
+deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"]
+git-tree-sha1 = "eeafab08ae20c62c44c8399ccb9354a04b80db50"
+uuid = "90137ffa-7385-5640-81b9-e52037218182"
+version = "1.9.7"
+weakdeps = ["ChainRulesCore", "Statistics"]
+
+ [deps.StaticArrays.extensions]
+ StaticArraysChainRulesCoreExt = "ChainRulesCore"
+ StaticArraysStatisticsExt = "Statistics"
+
+[[deps.StaticArraysCore]]
+git-tree-sha1 = "192954ef1208c7019899fbf8049e717f92959682"
+uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
+version = "1.4.3"
+
+[[deps.Statistics]]
+deps = ["LinearAlgebra", "SparseArrays"]
+uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
+version = "1.10.0"
+
+[[deps.StringManipulation]]
+deps = ["PrecompileTools"]
+git-tree-sha1 = "a04cabe79c5f01f4d723cc6704070ada0b9d46d5"
+uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e"
+version = "0.3.4"
+
+[[deps.StructTypes]]
+deps = ["Dates", "UUIDs"]
+git-tree-sha1 = "ca4bccb03acf9faaf4137a9abc1881ed1841aa70"
+uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
+version = "1.10.0"
+
+[[deps.SuiteSparse_jll]]
+deps = ["Artifacts", "Libdl", "libblastrampoline_jll"]
+uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c"
+version = "7.2.1+1"
+
+[[deps.Suppressor]]
+deps = ["Logging"]
+git-tree-sha1 = "9143c41bd539a8885c79728b9dedb0ce47dc9819"
+uuid = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
+version = "0.2.7"
+
+[[deps.TOML]]
+deps = ["Dates"]
+uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
+version = "1.0.3"
+
+[[deps.TableTraits]]
+deps = ["IteratorInterfaceExtensions"]
+git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
+uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
+version = "1.0.1"
+
+[[deps.TableTraitsUtils]]
+deps = ["DataValues", "IteratorInterfaceExtensions", "Missings", "TableTraits"]
+git-tree-sha1 = "78fecfe140d7abb480b53a44f3f85b6aa373c293"
+uuid = "382cd787-c1b6-5bf2-a167-d5b971a19bda"
+version = "1.0.2"
+
+[[deps.Tables]]
+deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits"]
+git-tree-sha1 = "cb76cf677714c095e535e3501ac7954732aeea2d"
+uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
+version = "1.11.1"
+
+[[deps.Tar]]
+deps = ["ArgTools", "SHA"]
+uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
+version = "1.10.0"
+
+[[deps.Test]]
+deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
+uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
+
+[[deps.Tricks]]
+git-tree-sha1 = "eae1bb484cd63b36999ee58be2de6c178105112f"
+uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775"
+version = "0.1.8"
+
+[[deps.TupleTools]]
+git-tree-sha1 = "41d61b1c545b06279871ef1a4b5fcb2cac2191cd"
+uuid = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6"
+version = "1.5.0"
+
+[[deps.URIParser]]
+deps = ["Unicode"]
+git-tree-sha1 = "53a9f49546b8d2dd2e688d216421d050c9a31d0d"
+uuid = "30578b45-9adc-5946-b283-645ec420af67"
+version = "0.4.1"
+
+[[deps.URIs]]
+git-tree-sha1 = "67db6cc7b3821e19ebe75791a9dd19c9b1188f2b"
+uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
+version = "1.5.1"
+
+[[deps.UUIDs]]
+deps = ["Random", "SHA"]
+uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
+
+[[deps.Unicode]]
+uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
+
+[[deps.Vega]]
+deps = ["BufferedStreams", "DataStructures", "DataValues", "Dates", "FileIO", "FilePaths", "IteratorInterfaceExtensions", "JSON", "JSONSchema", "MacroTools", "NodeJS", "Pkg", "REPL", "Random", "Setfield", "TableTraits", "TableTraitsUtils", "URIParser"]
+git-tree-sha1 = "0efd71a3df864e86d24236c99aaae3970e6f0ed0"
+uuid = "239c3e63-733f-47ad-beb7-a12fde22c578"
+version = "2.7.0"
+
+[[deps.YaoHIR]]
+deps = ["Expronicon", "MLStyle", "YaoLocations"]
+git-tree-sha1 = "b1e17fb84f1b322bef9910c942c1c9beb3e919ef"
+uuid = "6769671a-fce8-4286-b3f7-6099e1b1298a"
+version = "0.2.3"
+weakdeps = ["OpenQASM"]
+
+ [deps.YaoHIR.extensions]
+ YaoHIRExt = ["OpenQASM"]
+
+[[deps.YaoLocations]]
+git-tree-sha1 = "c90c42c8668c9096deb0c861822f0f8f80cbdc68"
+uuid = "66df03fb-d475-48f7-b449-3d9064bf085b"
+version = "0.1.6"
+
+[[deps.ZXCalculus]]
+deps = ["Expronicon", "Graphs", "LinearAlgebra", "MLStyle", "Multigraphs", "OMEinsum", "SparseArrays", "YaoHIR", "YaoLocations"]
+git-tree-sha1 = "9110975b06644a0844c98e13944c00af26087bf4"
+uuid = "3525faa3-032d-4235-a8d4-8c2939a218dd"
+version = "0.6.0"
+
+[[deps.Zlib_jll]]
+deps = ["Libdl"]
+uuid = "83775a58-1f1d-513f-b197-d71354ab007a"
+version = "1.2.13+1"
+
+[[deps.libblastrampoline_jll]]
+deps = ["Artifacts", "Libdl"]
+uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"
+version = "5.8.0+1"
+
+[[deps.nghttp2_jll]]
+deps = ["Artifacts", "Libdl"]
+uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
+version = "1.52.0+1"
+
+[[deps.p7zip_jll]]
+deps = ["Artifacts", "Libdl"]
+uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
+version = "17.4.0+2"
+"""
+
+# ╔═╡ Cell order:
+# ╠═dd08aa73-0d86-4f8b-970b-59f9ad9fac2d
+# ╠═506db9e1-4260-408d-ba72-51581b548e53
+# ╟─db7e9cf8-9abf-448b-be68-43231853faff
+# ╟─c06c5b9f-e5c1-4d0c-8ed5-937ad3871d3d
+# ╟─5e0fb39e-68b3-45f6-8cb2-2dd0b79b35d4
+# ╠═587be022-6005-44d5-bb72-53cc9e3ba3bb
+# ╠═482fdb57-2b0b-44b9-a5a0-f4dc26e15a7d
+# ╠═57301b22-969f-481e-ae0b-0336e1ee5055
+# ╠═a8470d1a-8dc1-4a86-85b9-efd1836cf42c
+# ╠═6e823d50-9107-4488-897e-d647334573f9
+# ╠═e3aa4e99-cb1f-478b-9e80-82b0ab02f606
+# ╠═a44ef98a-61fb-4271-9d36-c4d096f7e600
+# ╠═fb2448ef-aebe-419f-ad1d-a161edacd5a0
+# ╠═38da72a7-7e81-426f-ba08-b4158dc6a011
+# ╠═742750be-1262-4cbe-b476-f62e5e5c1fcf
+# ╠═686cfe18-598b-4184-8a6d-85711109b055
+# ╠═9af85660-a4e3-4f27-b6cb-cf36d9b50d91
+# ╟─785ec008-63af-4f56-9792-f66b27a27388
+# ╠═44cbd3d8-6d36-4a0b-8613-552bbba48f3d
+# ╠═0c2b4e33-5dcc-476d-8a9c-1e4244231e05
+# ╠═eebd1e46-0c0f-487d-8bee-07b1c17552c4
+# ╠═9200a1b1-11f7-4428-8840-c52dd4403c45
+# ╠═924efc08-681b-4804-93c6-38acc125315a
+# ╠═5fdc6a08-c284-414e-9e96-8734289a98de
+# ╠═0523c034-06ac-4383-b50f-6b68e6b1739f
+# ╠═4d7d8a96-5aba-4b63-a5da-959716f2d2bf
+# ╠═7da637f0-e359-41d9-b395-27168459c20c
+# ╠═bed7a0c5-da16-40b5-9d84-4dad2dfb8739
+# ╠═8cde99fd-ee0a-4d94-a94e-23ebc9ac8608
+# ╠═17389edf-33d2-4dd8-bf86-df0467e65059
+# ╠═99bb5eff-79e7-4c0e-95ae-a6d2130f46cb
+# ╠═f240382f-b682-4947-938f-c98d9c901c90
+# ╠═89f14c32-895d-4101-b4a8-bc410a2adaa5
+# ╠═0b838710-91e4-4572-9fe0-5c97e579ddd1
+# ╠═fdb7ca6a-bf5c-4216-8a18-a7c3603240ea
+# ╠═6da61df3-b6e7-4991-ab9f-5994b55841e0
+# ╠═6b431ff3-f644-4123-82fd-704c054eb5bb
+# ╠═cee877f2-8fd8-4a4e-9b8c-199411d449c5
+# ╠═20886e57-0c2c-4bf3-8c3d-8ed7d4f33fec
+# ╠═9b838e52-79f6-49bd-9574-62d94f941558
+# ╠═91ea0d20-8f8b-4bec-a98d-6aebbc4228e1
+# ╠═fbbe52e6-40d0-48ab-aa92-58a5125a33b2
+# ╠═f7982574-ddff-4e7b-a4fc-52462a59d21c
+# ╟─00000000-0000-0000-0000-000000000001
+# ╟─00000000-0000-0000-0000-000000000002
diff --git a/notebooks/tutorial.jl b/notebooks/tutorial.jl
index 1baf7a0..282256a 100644
--- a/notebooks/tutorial.jl
+++ b/notebooks/tutorial.jl
@@ -1,22 +1,40 @@
### A Pluto.jl notebook ###
-# v0.11.9
+# v0.19.43
using Markdown
using InteractiveUtils
# ╔═╡ 8ab9b70a-e98d-11ea-239c-73dc659722c2
-using YaoLang, YaoPlots, ZXCalculus, Compose, Revise
+begin
+ using OpenQASM
+ using Vega
+ using DataFrames
+ using YaoHIR: BlockIR
+ using ZXCalculus, ZXCalculus.ZX
+ using YaoHIR, YaoLocations
+ using YaoHIR.IntrinsicOperation
+
+ # Used for creating the IRCode for a BlockIR
+ using Core.Compiler: IRCode
+ using PlutoUI
+
+end
-# ╔═╡ 282bd90e-e9fd-11ea-0b79-174cade05905
-using Yao, YaoExtensions
+# ╔═╡ a9bf8e31-686a-4057-acec-bd04e8b5a3dc
+using Multigraphs
-# ╔═╡ e0a83244-e98e-11ea-3213-fdf02f4df920
-function Base.show(io::IO, mime::MIME"text/html", zx::Union{ZXDiagram, ZXGraph})
- g = plot(zx; size_x=13, size_y = 3, NODELABELSIZE=8pt)
- Compose.set_default_graphic_size(18cm, 5cm)
- Base.show(io, mime, compose(context(0.0, 0.0, 1.0, 1.0), g))
+# ╔═╡ 1e11009f-7b70-49fd-a6f3-ef8b5a79636e
+using ZXCalculus.ZXW
+
+# ╔═╡ fdfa8ed2-f19c-4b80-b64e-f4bb22d09327
+function Base.show(io::IO, mime::MIME"text/html", zx::Union{ZXDiagram,ZXGraph})
+ g = plot(zx)
+ Base.show(io, mime, g)
end
+# ╔═╡ 03405af4-0984-43c6-9312-f18fc3b23792
+TableOfContents(title="📚 Table of Contents", indent=true, depth=4, aside=true)
+
# ╔═╡ 227f7884-e99a-11ea-3a90-0beb697a2da6
md"# Construct a ZX diagram"
@@ -24,47 +42,61 @@ md"# Construct a ZX diagram"
z1 = ZXDiagram(4)
# ╔═╡ 51e72d20-e994-11ea-1a50-854039f728aa
-push_gate!(z1, Val(:Z), 1, 3//2)
+push_gate!(z1, Val(:Z), 1, 3 // 2)
# ╔═╡ e1dbb828-e995-11ea-385d-fb20b58d1b49
let
- push_gate!(z1, Val(:H), 1)
- push_gate!(z1, Val(:H), 1)
- push_gate!(z1, Val(:Z), 1, 1//2)
- push_gate!(z1, Val(:H), 4)
- push_gate!(z1, Val(:CZ), 4, 1)
- push_gate!(z1, Val(:CNOT), 1, 4)
+ push_gate!(z1, Val(:H), 1)
+ push_gate!(z1, Val(:H), 1)
+ push_gate!(z1, Val(:Z), 1, 1 // 2)
+ push_gate!(z1, Val(:H), 4)
+ push_gate!(z1, Val(:CZ), 4, 1)
+ push_gate!(z1, Val(:CNOT), 1, 4)
end
# ╔═╡ 60c59c0a-e994-11ea-02da-7360cbcf81f7
function load_graph()
- zxd = ZXDiagram(4)
- push_gate!(zxd, Val(:Z), 1, 3//2)
- push_gate!(zxd, Val(:H), 1)
- push_gate!(zxd, Val(:Z), 1, 1//2)
+ zxd = ZXDiagram(4)
+ push_gate!(zxd, Val(:Z), 1, 3 // 2)
+ push_gate!(zxd, Val(:H), 1)
+ push_gate!(zxd, Val(:Z), 1, 1 // 2)
push_gate!(zxd, Val(:H), 4)
push_gate!(zxd, Val(:CZ), 4, 1)
push_gate!(zxd, Val(:CNOT), 1, 4)
push_gate!(zxd, Val(:H), 1)
push_gate!(zxd, Val(:H), 4)
- push_gate!(zxd, Val(:Z), 1, 1//4)
- push_gate!(zxd, Val(:Z), 4, 3//2)
- push_gate!(zxd, Val(:X), 4, 1//1)
+ push_gate!(zxd, Val(:Z), 1, 1 // 4)
+ push_gate!(zxd, Val(:Z), 4, 3 // 2)
+ push_gate!(zxd, Val(:X), 4, 1 // 1)
push_gate!(zxd, Val(:H), 1)
- push_gate!(zxd, Val(:Z), 4, 1//2)
- push_gate!(zxd, Val(:X), 4, 1//1)
- push_gate!(zxd, Val(:Z), 2, 1//2)
+ push_gate!(zxd, Val(:Z), 4, 1 // 2)
+ push_gate!(zxd, Val(:X), 4, 1 // 1)
+ push_gate!(zxd, Val(:Z), 2, 1 // 2)
push_gate!(zxd, Val(:CNOT), 3, 2)
push_gate!(zxd, Val(:H), 2)
push_gate!(zxd, Val(:CNOT), 3, 2)
- push_gate!(zxd, Val(:Z), 2, 1//4)
- push_gate!(zxd, Val(:Z), 3, 1//2)
+ push_gate!(zxd, Val(:Z), 2, 1 // 4)
+ push_gate!(zxd, Val(:Z), 3, 1 // 2)
push_gate!(zxd, Val(:H), 2)
push_gate!(zxd, Val(:H), 3)
- push_gate!(zxd, Val(:Z), 3, 1//2)
+ push_gate!(zxd, Val(:Z), 3, 1 // 2)
push_gate!(zxd, Val(:CNOT), 3, 2)
end
+# ╔═╡ ba769665-063b-4a17-8aa8-afa1fffc574c
+md"""
+# Multigraph ZXDigram
+"""
+
+
+# ╔═╡ b9d32b41-8bff-4faa-b198-db096582fb2e
+begin
+ g = Multigraph([0 1 0; 1 0 1; 0 1 0])
+ ps = [Rational(0) for i = 1:3]
+ v_t = [SpiderType.X, SpiderType.Z, SpiderType.X]
+ zxd_m = ZXDiagram(g, v_t, ps)
+end
+
# ╔═╡ 90b83d5e-e99a-11ea-1fb2-95c907668262
md"# Simplify the ZX diagram"
@@ -132,81 +164,161 @@ ex_zxd = clifford_simplification(zxd2)
# ╔═╡ c0f046ea-e9b5-11ea-302c-c5fd4399d400
pt_zxd = phase_teleportation(zxd2)
+# ╔═╡ 52c1ae46-a440-4d72-8dc1-fa9903feac80
+pt_zxg = ZXGraph(pt_zxd)
+
# ╔═╡ c3e8b5b4-e99a-11ea-0e56-6b18757f94df
md"# Extract circuit"
# ╔═╡ c1b9828c-e99a-11ea-006a-013a2eab8cf3
-zxd_simplified = circuit_extraction(zxg)
+chain_simplified = circuit_extraction(pt_zxg)
# ╔═╡ 6ddffea2-e9a4-11ea-1c32-0975a45aba7c
-tcount(zxd_simplified)
+tcount(pt_zxg)
+
+# ╔═╡ 4f07895a-58aa-4555-aa14-b0526bc1de2d
+md"""
+## ZXWDiagram as a Matrix
+Convert a ZXWDiagram into a matrix using Einsum.jl
+"""
+
+# ╔═╡ 80c79503-b85e-4938-9253-58dd45cf42b0
+begin
+ zxw1 = ZXWDiagram(2)
+ push_gate!(zxw1, Val(:Z), 1, 1 // 2)
+ push_gate!(zxw1, Val(:H), 2)
+ push_gate!(zxw1, Val(:CZ), 2, 1)
+end
+
+# ╔═╡ a5b21163-7e60-409f-ad59-66ca72375094
+Matrix(zxw1)
# ╔═╡ 2082486e-e9fd-11ea-1a46-6395b4b34657
-md"# Porting Yao"
+md"""
+# Porting Yao
+
+We can define a Yao Chain and push gates into the chain
-# ╔═╡ 3a2c5d22-e9fd-11ea-1e48-a9be2e8b213b
-zxd3 = ZXDiagram(4)
+"""
-# ╔═╡ d341cde4-e9fd-11ea-1c3b-63f35fc648d5
+# ╔═╡ d1789ff9-3628-4fd3-aa39-823191e78ee0
begin
-function ZXCalculus.push_gate!(zxd::ZXDiagram, c::AbstractBlock)
- error("Block type `$c` is not supported.")
-end
-# rotation blocks
-function ZXCalculus.push_gate!(zxd::ZXDiagram, c::PutBlock{N,1,RotationGate{1,T,XGate}}) where {N,T}
- push_gate!(zxd, Val(:X), c.locs[1], c.content.theta)
-end
-function ZXCalculus.push_gate!(zxd::ZXDiagram, c::PutBlock{N,1,RotationGate{1,T,ZGate}}) where {N,T}
- push_gate!(zxd, Val(:Z), c.locs[1], c.content.theta)
-end
-function ZXCalculus.push_gate!(zxd::ZXDiagram, c::PutBlock{N,1,ShiftGate{T}}) where {N,T}
- push_gate!(zxd, Val(:Z), c.locs[1], c.content.theta)
-end
-function ZXCalculus.push_gate!(zxd::ZXDiagram, c::PutBlock{N,1,HGate}) where {N}
- push_gate!(zxd, Val(:H), c.locs[1])
-end
-function ZXCalculus.push_gate!(zxd::ZXDiagram, c::ChainBlock{N}) where {N}
- push_gate!.(Ref(zxd), subblocks(c))
- zxd
+ chain_t = Chain()
+ push_gate!(chain_t, Val(:H), 1)
+ push_gate!(chain_t, Val(:H), 2)
+ push_gate!(chain_t, Val(:X), 3)
+ push_gate!(chain_t, Val(:H), 3)
+ push_gate!(chain_t, Val(:CNOT), 1, 3)
+ push_gate!(chain_t, Val(:X), 1)
+ push_gate!(chain_t, Val(:CNOT), 2, 3)
+ push_gate!(chain_t, Val(:H), 2)
end
-# constant block
-function ZXCalculus.push_gate!(zxd::ZXDiagram, c::PutBlock{N,1,RotationGate{1,T,XGate}}) where {N,T}
- push_gate!(zxd, Val(:X), c.locs[1], c.content.theta)
-end
-function ZXCalculus.push_gate!(zxd::ZXDiagram, c::PutBlock{N,1,RotationGate{1,T,ZGate}}) where {N,T}
- push_gate!(zxd, Val(:Z), c.locs[1], c.content.theta)
-end
+# ╔═╡ 9ba5aa18-9e6b-4f75-a35c-e7a3e548d557
+md"""
+## Convert BlockIR to ZXDiagram
+Create a BlockIR and convert it into a ZXDiagram
+"""
-# control blocks
-function ZXCalculus.push_gate!(zxd::ZXDiagram, c::ControlBlock{N,1,RotationGate{1,T,XGate}}) where {N,T}
- push_gate!(zxd, Val(:X), c.locs[1], c.content.theta)
-end
-function ZXCalculus.push_gate!(zxd::ZXDiagram, c::ControBlock{N,1,RotationGate{1,T,ZGate}}) where {N,T}
- push_gate!(zxd, Val(:Z), c.locs[1], c.content.theta)
-end
-function ZXCalculus.push_gate!(zxd::ZXDiagram, c::ControlBlock{N,1,ShiftGate{T}}) where {N,T}
- push_gate!(zxd, Val(:Z), c.locs[1], c.content.theta)
-end
+# ╔═╡ 71fc6836-3c30-43de-aa2b-2d3d48bdb3da
+begin
+
+ ir_t = IRCode()
+ bir_t = BlockIR(ir_t, 4, chain_t)
+ zxd_t = convert_to_zxd(bir_t)
end
-# ╔═╡ 581e847c-e9fd-11ea-3fd0-6bbc0f6efd56
-c = qft_circuit(4)
+# ╔═╡ 31753c83-847a-4c2a-a6b3-8be6aaa8f792
+zxg_t = ZXGraph(zxd_t)
-# ╔═╡ 2e84a5ce-e9fd-11ea-12d0-b3a3dd75a76f
-push_gate!(zxd3, c)
+# ╔═╡ 4a189a46-9ae6-458c-94c4-7cc8d5dab788
+md"""
+# Equivalence Checking
+
+## Equivalence Checking of Quantum Circuits
+### Principle of Quantum Circuit Equality
+#### Reversiblity
+Equivalence checking the equality of two quantum circuits relies on the reversibility
+of quantum operations. Every quantum operation is *unitary* and thus reversible. The product of any quantum operation and its inverse (adjoint)
+will always yield the identity.
+
+
+#### Unitary
+For a matrix to be unitary, this property needs to hold:
+`` U \cdot U^\dagger = U^\dagger \cdot U = I_n | U \in \mathbb{R}^{n \times n} ``
+
+If ``U_1`` and ``U_2`` are unitary matrices, so is their matrix product ``U_1 \cdot U_2``.
+Unitary matrices preserve inner products. Thus, if ``U`` is unitary, then for all ``V , V′ \in \mathbb{C}^n`` we have:
+``⟨U V |U V ′ ⟩ = ⟨U |V ′ ⟩``
+
+### Equality
+In order to verify the equality of two quantum circuits we exploit their reversibility.
+
+Given two quantum circuits ``G_1`` and ``G_2`` as well the systems matrices ``U_1`` and ``U_1`` that describe the operations of these quantum circuits we ask ourself, the problem of equivalence checking is to verify if there is no difference ``D = U_1 \cdot U_2^\dagger`` between the first and second quantum circuit.
+
+To verify if the two quantum circuits are equal we check if ``tr(D) = 0``, as this implies that the difference is the idenity matrix.
+ ``U_1 \cdot U_2^\dagger = D````U_1 \cdot U_2^\dagger = D = I``.
+
+If the two quantum circuits are not equal, ``U_1 \cdot U_2^\dagger = D != I``, the
+problem is to
+- approximate how close the quantum circuits are
+- debug the quantum circuits, in order to reduce the difference `D` between them.
+
+
+"""
-# ╔═╡ 7b850816-ea02-11ea-183c-5db2d670be24
-ZXDiagram(4) |> typeof
+# ╔═╡ daa4e9e7-aefa-490d-b8ba-876643b4c7f3
+bv_010 = full_reduction(concat!(ZXDiagram(BlockIR("""
+OPENQASM 2.0;
+include "qelib1.inc";
+qreg q[4];
+creg c[3];
+x q[3];
+h q[2];
+h q[3];
+h q[2];
+h q[1];
+CX q[1], q[3];
+h q[1];
+h q[0];
+h q[0];
+measure q[0] -> c[2];
+measure q[2] -> c[0];
+measure q[1] -> c[1];
+ """)), dagger(ZXDiagram(BlockIR("""
+OPENQASM 2.0;
+include "qelib1.inc";
+qreg q[4];
+creg c[3];
+x q[3];
+h q[0];
+h q[1];
+h q[2];
+h q[3];
+CX q[1],q[3];
+h q[0];
+h q[1];
+h q[2];
+measure q[0] -> c[0];
+measure q[1] -> c[1];
+measure q[2] -> c[2];
+ """)))))
+
+# ╔═╡ 7bcc5502-a6d3-44fc-85a1-5ee33d855fa9
+contains_only_bare_wires(bv_010)
# ╔═╡ Cell order:
# ╠═8ab9b70a-e98d-11ea-239c-73dc659722c2
-# ╟─e0a83244-e98e-11ea-3213-fdf02f4df920
+# ╠═fdfa8ed2-f19c-4b80-b64e-f4bb22d09327
+# ╠═03405af4-0984-43c6-9312-f18fc3b23792
# ╟─227f7884-e99a-11ea-3a90-0beb697a2da6
# ╠═49d6e6ac-e994-11ea-2ac5-27ab8242e297
# ╠═51e72d20-e994-11ea-1a50-854039f728aa
# ╠═e1dbb828-e995-11ea-385d-fb20b58d1b49
# ╠═60c59c0a-e994-11ea-02da-7360cbcf81f7
+# ╟─ba769665-063b-4a17-8aa8-afa1fffc574c
+# ╠═a9bf8e31-686a-4057-acec-bd04e8b5a3dc
+# ╠═b9d32b41-8bff-4faa-b198-db096582fb2e
# ╟─90b83d5e-e99a-11ea-1fb2-95c907668262
# ╠═64bff9ec-e9b5-11ea-3b23-c51d2149697a
# ╠═5dbf9f96-e9a4-11ea-19d7-e15e7f2327c9
@@ -227,13 +339,19 @@ ZXDiagram(4) |> typeof
# ╠═b6eaa762-e9b5-11ea-145e-7b5fa6b01872
# ╠═5464bc40-e9b5-11ea-2a2e-dfb0d31a33d3
# ╠═c0f046ea-e9b5-11ea-302c-c5fd4399d400
+# ╠═52c1ae46-a440-4d72-8dc1-fa9903feac80
# ╟─c3e8b5b4-e99a-11ea-0e56-6b18757f94df
# ╠═c1b9828c-e99a-11ea-006a-013a2eab8cf3
# ╠═6ddffea2-e9a4-11ea-1c32-0975a45aba7c
-# ╠═2082486e-e9fd-11ea-1a46-6395b4b34657
-# ╠═282bd90e-e9fd-11ea-0b79-174cade05905
-# ╠═3a2c5d22-e9fd-11ea-1e48-a9be2e8b213b
-# ╠═d341cde4-e9fd-11ea-1c3b-63f35fc648d5
-# ╠═581e847c-e9fd-11ea-3fd0-6bbc0f6efd56
-# ╠═2e84a5ce-e9fd-11ea-12d0-b3a3dd75a76f
-# ╠═7b850816-ea02-11ea-183c-5db2d670be24
+# ╟─4f07895a-58aa-4555-aa14-b0526bc1de2d
+# ╠═1e11009f-7b70-49fd-a6f3-ef8b5a79636e
+# ╠═80c79503-b85e-4938-9253-58dd45cf42b0
+# ╠═a5b21163-7e60-409f-ad59-66ca72375094
+# ╟─2082486e-e9fd-11ea-1a46-6395b4b34657
+# ╠═d1789ff9-3628-4fd3-aa39-823191e78ee0
+# ╟─9ba5aa18-9e6b-4f75-a35c-e7a3e548d557
+# ╠═71fc6836-3c30-43de-aa2b-2d3d48bdb3da
+# ╠═31753c83-847a-4c2a-a6b3-8be6aaa8f792
+# ╟─4a189a46-9ae6-458c-94c4-7cc8d5dab788
+# ╠═daa4e9e7-aefa-490d-b8ba-876643b4c7f3
+# ╠═7bcc5502-a6d3-44fc-85a1-5ee33d855fa9
diff --git a/notebooks/zx_intro.jl b/notebooks/zx_intro.jl
new file mode 100644
index 0000000..c9ba72f
--- /dev/null
+++ b/notebooks/zx_intro.jl
@@ -0,0 +1,451 @@
+### A Pluto.jl notebook ###
+# v0.19.38
+
+using Markdown
+using InteractiveUtils
+
+# ╔═╡ dd08aa73-0d86-4f8b-970b-59f9ad9fac2d
+begin
+ using OpenQASM
+ using Vega
+ using DataFrames
+ using YaoHIR: BlockIR
+ using ZXCalculus, ZXCalculus.ZX
+ using PlutoUI
+end
+
+# ╔═╡ 741c3ca4-2dd5-406c-9ae5-7d19a3192e7d
+TableOfContents(title = "📚 Table of Contents", indent = true, depth = 2, aside = true)
+
+# ╔═╡ 24749683-0566-4f46-989d-22336d296517
+html"""
+
+"""
+
+
+# ╔═╡ 506db9e1-4260-408d-ba72-51581b548e53
+function Base.show(io::IO, mime::MIME"text/html", zx::Union{ZXDiagram,ZXGraph})
+ g = plot(zx)
+ Base.show(io, mime, g)
+end
+
+# ╔═╡ 92dccd1c-6582-40bf-9b57-f326b2aff67a
+html""
+
+# ╔═╡ a93915fc-01ef-4411-bc98-ea1fe8674fa9
+md"""
+# Introduction
+ZX-Calculus is a unified formalism for describing quantum computation, mainly over
+qubits. It is a rigorous graphical language, that utilizes the powerful set of rewrite
+rules [1] for reasoning about linear maps between qubits, which are represented as string diagrams called ZX-Diagrams [2-3].
+
+ZX-Calculus was invented in 2008 by Bob Coecke and Russ Duncan as an extension
+of categorical quantum mechanics. They introduced the fundamental concepts of
+spiders, strong complementarity and most the rewrite rules
+
+All equations
+concerning quantum processes can be derived using a handful of graphical rules [4].
+
+The ZX-Calculus is universal, because any linear map between qubits can be rep-
+resented as a ZX-Diagram. It is complete, meaning that all equations concerning
+quantum processes can be derived using linear algebra, can also be obtained using a
+handful of graphical rules [5, 6]. This makes the ZX-Calculus an alternative to the
+Hilbert Space Formalism and a tool for generalization of quantum circuit notations
+[1].
+
+This section notebook demonstrates the universality of the ZX-Calculus by exhibiting how the Clifford group (CN OT , H, S) + T , one of the universal gate sets [7], is implemented.
+The ZX-Calculus, which has been proven complete in [8], provides a powerful repre-
+sentation of static quantum circuits.
+
+
+## ZXDiagrams
+ZXDiagrams can be created by specifying the number of qubits.
+Bare wires are equivalent to an identiy gate. The identity gate is the identity matrix and does not modify the quantum state.
+
+The ZX-Calculus is built around the concept of wires, which serve as a visual representation of a system. The first diagram below shows a single wire, which corresponds to a quantum system with one qubit, emphasizing their equivalence.
+It represents the identity I, since the state of the system does not change.
+"""
+
+# ╔═╡ 9af85660-a4e3-4f27-b6cb-cf36d9b50d91
+z1 = ZXDiagram(1)
+
+# ╔═╡ 3f82bd5a-7528-4b1c-9b67-252ed076ed97
+md"The second diagram shows a quantum system with 3 qubits."
+
+# ╔═╡ df00b5c6-9217-11ee-0b09-632420c4e265
+z3 = ZXDiagram(3)
+
+# ╔═╡ 785ec008-63af-4f56-9792-f66b27a27388
+md"""
+## Gates
+Spiders, which represent gates can be pushed onto a Diagram.
+The following example shows, how the clifford+T universal gate set, is constructed using ZXCalculus.
+
+### Pauli-X Gate
+The Pauli-X Gate rotates around the x axis of the Bloch Sphere with a phase of ``\pi``. The quantum equivalent of the classical NOT gate is the Pauli-X gate with respect to the standard basis ``|0\rangle, |1\rangle``
+It flips the ``|0\rangle`` into the ``|1\rangle`` state and vice-versa.
+
+Its matrix is represented as:
+`` X = \sigma_x =\operatorname{NOT} = \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}``
+
+"""
+
+# ╔═╡ 0c2b4e33-5dcc-476d-8a9c-1e4244231e05
+begin
+ zx_x = ZXDiagram(1)
+ push_gate!(zx_x, Val(:X), 1, 1 // 1)
+end
+
+
+# ╔═╡ 3cf7e1a1-7f99-4191-8e38-1533da8ebba1
+md"""
+### Z-Gate
+The effect of the Pauli-Z Gate is a phase flip. It leaves the basis state ``|0\rangle`` and maps
+``|0\rangle`` to ``−|0\rangle``.
+
+`` Z = \begin{bmatrix} 1 & 0 \\ 0 & e^{i \pi} \end{bmatrix} = \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix} = P\left(\pi\right)``
+"""
+
+# ╔═╡ eeb5001c-2599-4d01-8e45-d417bda4d83c
+begin
+ zx_z = ZXDiagram(1)
+ push_gate!(zx_z, Val(:Z), 1, 1 // 1)
+end
+
+# ╔═╡ 24609bab-a13b-49d9-be85-b8770a9153b1
+md"""
+### S-Gate
+The T-Gate has a phase of ``P(\frac{\pi}{2})``
+
+
+``S = \begin{bmatrix} 1 & 0 \\ 0 & e^{i \frac{\pi}{2}} \end{bmatrix} = \begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix} = P\left(\frac{\pi}{2}\right)=\sqrt{Z}``
+"""
+
+# ╔═╡ eebd1e46-0c0f-487d-8bee-07b1c17552c4
+begin
+ zx_s = ZXDiagram(1)
+ push_gate!(zx_s, Val(:Z), 1, 1 // 2)
+end
+
+# ╔═╡ 3e0f5adc-c47c-4363-890f-f2c6a9843115
+md"""
+### T-Gate
+The T-Gate has a phase of ``P(\frac{\pi}{4})``
+
+
+``T = \begin{bmatrix} 1 & 0 \\ 0 & e^{i \frac{\pi}{4}} \end{bmatrix} =P\left(\frac{\pi}{4}\right) = \sqrt{S} = \sqrt[4]{Z}``
+
+"""
+
+# ╔═╡ 9200a1b1-11f7-4428-8840-c52dd4403c45
+begin
+ zx_t = ZXDiagram(1)
+ push_gate!(zx_t, Val(:Z), 1, 1 // 4)
+end
+
+# ╔═╡ 518c82ab-ee25-4929-b9c7-976c27482d51
+md"""
+### H-Gate
+The Hadamard gate is a fundamental gate used to create superposition states in quantum computing.
+When applied to a qubit, the Hadamard gate creates a superposition of the basis
+states ``|0\rangle`` and ``|1\rangle``. It transforms the basis states as follows:
+
+``H = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix}``
+"""
+
+# ╔═╡ 924efc08-681b-4804-93c6-38acc125315a
+begin
+ zx_h = ZXDiagram(1)
+ push_gate!(zx_h, Val(:H), 1)
+end
+
+# ╔═╡ 08199250-2746-4779-b2d7-347c321ceb55
+md"""
+### H-Gate
+Contary to quantum logic gates, CNOT is not a gate primitive but composed out of a red and a green spider.
+
+"""
+
+# ╔═╡ 5fdc6a08-c284-414e-9e96-8734289a98de
+begin
+ zx_cnot = ZXDiagram(2)
+ push_gate!(zx_cnot, Val(:CNOT), 1, 2)
+
+end
+
+# ╔═╡ e2d695a4-7962-4d77-b348-74eb05c72b9c
+md"""
+
+## Quantum Circuit
+
+"""
+
+# ╔═╡ 0523c034-06ac-4383-b50f-6b68e6b1739f
+begin
+ zx = ZXDiagram(3)
+ push_gate!(zx, Val(:X), 1, 1 // 1)
+ push_gate!(zx, Val(:CNOT), 1, 2)
+ push_gate!(zx, Val(:H), 1)
+ push_gate!(zx, Val(:CNOT), 2, 3)
+ push_gate!(zx, Val(:H), 2)
+end
+
+
+# ╔═╡ 92fd5c2b-95a1-4820-99cb-45923429117c
+md"""
+# Rewrite Rules
+The ZX-Calculus provides a set of rewrite rules that allow us to transform one diagram
+into another equivalent diagram. These rules include the ability to move wires and
+effects, cancel pairs of H and Z gates, and commute certain gates. Rewrite rules are
+powerful, they allow us to change the structure of the ZX-Diagrams without changing
+the quantum circuit, since the linear maps remain the same.
+
+## Spider Fusion Rule
+Spiders of the same color can be fused together. Their phases are then added up.
+In this example we have the equivalent of two Pauli-X Gates on a wire.
+
+> Spider Fusion (f): Two spiders of the same color can fuse together if touching, adding their phases. This is because spiders of the same color represent an orthonormal basis.
+"""
+
+# ╔═╡ 5dabc4ae-ecd7-4339-837a-e1272b925acf
+begin
+ push_gate!(zx_x, Val(:X), 1, 1 // 1)
+end
+
+
+# ╔═╡ 973ad229-2b87-48f8-9926-c833766d45cb
+md"""
+After fusion them together, we get a phaseless spider.
+"""
+
+# ╔═╡ 852455dd-b95d-45a4-a771-053c1e95b82f
+simplify!(Rule{:f}(), zx_x)
+
+# ╔═╡ b4702fb4-e21a-43b0-8be4-fbfca81b4a8b
+md"""
+## Identiy Rule
+The identiy rules states, that phase less spiders are the idenity, as they do not change the phase of the Z or the X base.
+
+> Identity Rule (id): A phaseless arity 2 Z-or X-spider equals the identity. The Bell State (Definiton TODO) is the same if expressed in the computational basis or Hadamard basis.
+
+After applying the second idenity rule, we are left with a bare wire.
+
+"""
+
+# ╔═╡ 64be3d04-4983-467e-9b06-45b64132ee30
+simplify!(Rule{:i1}(), zx_x)
+
+# ╔═╡ c604a76d-9b95-4f0d-8133-df2a3e9dabe9
+md"""
+We can verify, that these rules are correct by checking constructing the same qunatum circuit using matrices in the hilbert space.
+
+`` \fbox{x} \cdot \fbox{x} = \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} \cdot \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} = \mathbb{I}``
+
+"""
+
+# ╔═╡ 4d7d8a96-5aba-4b63-a5da-959716f2d2bf
+md"""#
+## ZXDiagrams and ZXGraphs"""
+
+# ╔═╡ 7da637f0-e359-41d9-b395-27168459c20c
+zx_graph = ZXGraph(zx)
+
+# ╔═╡ bed7a0c5-da16-40b5-9d84-4dad2dfb8739
+begin
+ zx_id = ZXDiagram(2)
+ push_gate!(zx_id, Val(:X), 1)
+ push_gate!(zx_id, Val(:X), 1)
+end
+
+
+# ╔═╡ 8cde99fd-ee0a-4d94-a94e-23ebc9ac8608
+zx_id_graph = ZXGraph(zx_id)
+
+# ╔═╡ 99bb5eff-79e7-4c0e-95ae-a6d2130f46cb
+md"## Equality"
+
+# ╔═╡ f240382f-b682-4947-938f-c98d9c901c90
+zx_dagger = dagger(zx)
+
+# ╔═╡ 89f14c32-895d-4101-b4a8-bc410a2adaa5
+merged_diagram = concat!(zx, zx_dagger)
+
+# ╔═╡ 0b838710-91e4-4572-9fe0-5c97e579ddd1
+m_simple = full_reduction(merged_diagram)
+
+
+# ╔═╡ fdb7ca6a-bf5c-4216-8a18-a7c3603240ea
+contains_only_bare_wires(m_simple)
+
+# ╔═╡ 6b431ff3-f644-4123-82fd-704c054eb5bb
+md"""# Circuit Verification
+## Informal Definition
+Equivalence checking the equality of two quantum circuits relies on the reversibility
+of quantum operations. Every quantum operation is *unitary* and thus reversible. The product of any quantum operation and its inverse (adjoint)
+will always yield the identity.
+
+## Formal Definition
+### Unitary
+For a matrix to be unitary, this property needs to hold:
+`` U \cdot U^\dagger = U^\dagger \cdot U = I_n | U \in \mathbb{R}^{n \times n} ``
+
+If ``U_1`` and ``U_2`` are unitary matrices, so is their matrix product ``U_1 \cdot U_2``.
+Unitary matrices preserve inner products. Thus, if ``U`` is unitary, then for all ``V , V′ \in \mathbb{C}^n`` we have:
+``⟨U V |U V ′ ⟩ = ⟨U |V ′ ⟩``
+
+### Equality
+In order to verify the equality of two quantum circuits we exploit their reversibility.
+
+Given two quantum circuits ``G_1`` and ``G_2`` as well the systems matrices ``U_1`` and ``U_1`` that describe the operations of these quantum circuits we ask ourself, the problem of equivalence checking is to verify if there is no difference ``D = U_1 \cdot U_2^\dagger`` between the first and second quantum circuit.
+
+To verify if the two quantum circuits are equal we check if ``tr(D) = 0``, as this implies that the difference is the idenity matrix.
+ ``U_1 \cdot U_2^\dagger = D````U_1 \cdot U_2^\dagger = D = I``.
+
+If the two quantum circuits are not equal, ``U_1 \cdot U_2^\dagger = D != I``, the
+problem is to
+- approximate how close the quantum circuits are
+- debug the quantum circuits, in order to reduce the difference `D` between them.
+
+### Example
+Given circuits `b1` and `b2`. Can we proof that they are equal?
+"""
+
+# ╔═╡ cee877f2-8fd8-4a4e-9b8c-199411d449c5
+begin
+ b1 = BlockIR("""
+ OPENQASM 2.0;
+ include "qelib1.inc";
+ qreg q0[3];
+ creg c0[2];
+ h q0[0];
+ h q0[1];
+ x q0[2];
+ h q0[2];
+ CX q0[0],q0[2];
+ h q0[0];
+ CX q0[1],q0[2];
+ h q0[1];
+ x q0[2];
+ x q0[2];
+ measure q0[0] -> c0[0];
+ measure q0[1] -> c0[1];
+ """)
+ c1 = ZXDiagram(b1)
+end
+
+# ╔═╡ 20886e57-0c2c-4bf3-8c3d-8ed7d4f33fec
+begin
+ b2 = BlockIR("""
+ OPENQASM 2.0;
+ include "qelib1.inc";
+ qreg q0[3];
+ creg mcm[1];
+ creg end[1];
+ h q0[1];
+ x q0[2];
+ h q0[2];
+ CX q0[1], q0[2];
+ h q0[1];
+ h q0[0];
+ CX q0[0], q0[2];
+ h q0[0];
+ measure q0[0] -> end[0];
+ measure q0[1] -> mcm[0];
+ """)
+ c2 = ZXDiagram(b2)
+
+
+end
+
+# ╔═╡ 02be99e0-1b97-4fe0-b316-5151febe92d8
+concat!(c1, dagger(c2))
+
+# ╔═╡ e529aa93-4f3e-4038-97dd-1ce570df8076
+c_reduced = full_reduction(c1)
+
+# ╔═╡ 94ac0dd1-390e-42d6-8300-f67a5a633043
+contains_only_bare_wires(c_reduced)
+
+# ╔═╡ 796e6c34-0664-488d-a186-c7810df06d77
+verify_equality(ZXDiagram(b1), ZXDiagram(b1))
+
+# ╔═╡ f7982574-ddff-4e7b-a4fc-52462a59d21c
+md"""
+# Sources
+1. [B. Coecke, D. Horsman, A. Kissinger, and Q. Wang. “Kindergarden quantum mechanics graduates ...or how I learned to stop gluing LEGO together and love the ZX-calculus”. In: Theoretical Computer Science 897 (2022), pp. 1–22. issn: 0304-3975](https://doi.org/10.1016/j.tcs.2021.07.024)
+
+2. [R. Duncan, A. Kissinger, S. Perdrix, and J. van de Wetering. “Graph-theoretic Simplification of Quantum Circuits with the ZX -calculus”. In: Quantum 4 (June 2020), p. 279. issn: 2521-327X](https://doi.org/10.22331/q-2020-06-04-279)
+
+3. [J. van de Wetering. ZX-calculus for the working quantum computer scientist. 2020. arXiv: 2012.13966 [quant-ph]](https://arxiv.org/abs/2012.13966)
+
+4. [A. Kissinger and J. van de Wetering. “PyZX: Large Scale Automated Diagrammatic Reasoning”. In: Electronic Proceedings in Theoretical Computer Science 318 (May 2020), pp. 229–241](https://doi.org/10.4204/eptcs.318.14)
+
+5. [A. Hadzihasanovic, K. F. Ng, and Q. Wang. “Two complete axiomatisations of pure-state qubit quantum computing”. In: Proceedings of the 33rd Annual ACM/IEEE Symposium on Logic in Computer Science (2018)](https://api.semanticscholar.org/CorpusID:195347007)
+
+6. [R. Vilmart. “A Near-Minimal Axiomatisation of ZX-Calculus for Pure Qubit Quantum Mechanics”. In: 2019 34th Annual ACM/IEEE Symposium on Logic in Computer Science (LICS). 2019, pp. 1–10](https://doi.org/10.1109/LICS.2019.8785765)
+
+7. [M. A. Nielsen and I. L. Chuang. Quantum computation and quantum information. 10th anniversary ed. Cambridge ; New York: Cambridge University Press, 2010. isbn: 9781107002173](#)
+
+8. [Q. Wang. Completeness of the ZX-calculus. 2023. arXiv: 2209 . 14894 [quant-ph]](https://arxiv.org/abs/2209.14894)
+
+
+"""
+
+# ╔═╡ Cell order:
+# ╠═dd08aa73-0d86-4f8b-970b-59f9ad9fac2d
+# ╠═741c3ca4-2dd5-406c-9ae5-7d19a3192e7d
+# ╠═24749683-0566-4f46-989d-22336d296517
+# ╠═506db9e1-4260-408d-ba72-51581b548e53
+# ╠═92dccd1c-6582-40bf-9b57-f326b2aff67a
+# ╟─a93915fc-01ef-4411-bc98-ea1fe8674fa9
+# ╠═9af85660-a4e3-4f27-b6cb-cf36d9b50d91
+# ╟─3f82bd5a-7528-4b1c-9b67-252ed076ed97
+# ╠═df00b5c6-9217-11ee-0b09-632420c4e265
+# ╟─785ec008-63af-4f56-9792-f66b27a27388
+# ╠═0c2b4e33-5dcc-476d-8a9c-1e4244231e05
+# ╟─3cf7e1a1-7f99-4191-8e38-1533da8ebba1
+# ╠═eeb5001c-2599-4d01-8e45-d417bda4d83c
+# ╟─24609bab-a13b-49d9-be85-b8770a9153b1
+# ╠═eebd1e46-0c0f-487d-8bee-07b1c17552c4
+# ╟─3e0f5adc-c47c-4363-890f-f2c6a9843115
+# ╠═9200a1b1-11f7-4428-8840-c52dd4403c45
+# ╟─518c82ab-ee25-4929-b9c7-976c27482d51
+# ╠═924efc08-681b-4804-93c6-38acc125315a
+# ╟─08199250-2746-4779-b2d7-347c321ceb55
+# ╠═5fdc6a08-c284-414e-9e96-8734289a98de
+# ╟─e2d695a4-7962-4d77-b348-74eb05c72b9c
+# ╠═0523c034-06ac-4383-b50f-6b68e6b1739f
+# ╟─92fd5c2b-95a1-4820-99cb-45923429117c
+# ╠═5dabc4ae-ecd7-4339-837a-e1272b925acf
+# ╟─973ad229-2b87-48f8-9926-c833766d45cb
+# ╠═852455dd-b95d-45a4-a771-053c1e95b82f
+# ╟─b4702fb4-e21a-43b0-8be4-fbfca81b4a8b
+# ╠═64be3d04-4983-467e-9b06-45b64132ee30
+# ╟─c604a76d-9b95-4f0d-8133-df2a3e9dabe9
+# ╟─4d7d8a96-5aba-4b63-a5da-959716f2d2bf
+# ╠═7da637f0-e359-41d9-b395-27168459c20c
+# ╠═bed7a0c5-da16-40b5-9d84-4dad2dfb8739
+# ╠═8cde99fd-ee0a-4d94-a94e-23ebc9ac8608
+# ╟─99bb5eff-79e7-4c0e-95ae-a6d2130f46cb
+# ╠═f240382f-b682-4947-938f-c98d9c901c90
+# ╠═89f14c32-895d-4101-b4a8-bc410a2adaa5
+# ╠═0b838710-91e4-4572-9fe0-5c97e579ddd1
+# ╠═fdb7ca6a-bf5c-4216-8a18-a7c3603240ea
+# ╠═6b431ff3-f644-4123-82fd-704c054eb5bb
+# ╠═cee877f2-8fd8-4a4e-9b8c-199411d449c5
+# ╠═20886e57-0c2c-4bf3-8c3d-8ed7d4f33fec
+# ╠═02be99e0-1b97-4fe0-b316-5151febe92d8
+# ╠═e529aa93-4f3e-4038-97dd-1ce570df8076
+# ╠═94ac0dd1-390e-42d6-8300-f67a5a633043
+# ╠═796e6c34-0664-488d-a186-c7810df06d77
+# ╟─f7982574-ddff-4e7b-a4fc-52462a59d21c
diff --git a/src/ZX/ZX.jl b/src/ZX/ZX.jl
index f05e9dd..0f5688f 100644
--- a/src/ZX/ZX.jl
+++ b/src/ZX/ZX.jl
@@ -20,8 +20,10 @@ export Rule, Match
export rewrite!, simplify!
-export convert_to_chain, convert_to_zxd
+export convert_to_chain, convert_to_zxd, convert_to_zxwd
export clifford_simplification, full_reduction, circuit_extraction, phase_teleportation
+export plot
+export concat!, dagger, contains_only_bare_wires, verify_equality
include("abstract_zx_diagram.jl")
include("zx_layout.jl")
@@ -35,4 +37,6 @@ include("circuit_extraction.jl")
include("phase_teleportation.jl")
include("ir.jl")
+
+include("equality.jl")
end
diff --git a/src/ZX/circuit_extraction.jl b/src/ZX/circuit_extraction.jl
index 466fe75..2e592da 100644
--- a/src/ZX/circuit_extraction.jl
+++ b/src/ZX/circuit_extraction.jl
@@ -285,7 +285,7 @@ function update_frontier!(zxg::ZXGraph{T, P}, gads::Set{T}, frontier::Vector{T},
v = frontier[i]
nb_v = neighbors(zxg, v)
u = findfirst([u in gads for u in nb_v])
- if u !== nothing
+ if !isnothing(u)
u = nb_v[u]
gad_u = zero(T)
for w in neighbors(zxg, u)
@@ -474,7 +474,7 @@ function normalize_perm(M::Matrix{T}, steps::Vector{GEStep} = Vector{GEStep}())
tar_c = findfirst(isone, M[cur_r, :])
M[cur_r, cur_c] = 1
M[tar_r, cur_c] = 0
- if tar_c !== nothing
+ if !isnothing(tar_c)
M[tar_r, tar_c] = 1
M[cur_r, tar_c] = 0
end
@@ -488,7 +488,7 @@ end
# """
# reverse_gaussian_elimination(M, steps)
-
+#
# Apply back the operations in `steps` to `M`.
# """
# function reverse_gaussian_elimination(M, steps)
diff --git a/src/ZX/equality.jl b/src/ZX/equality.jl
new file mode 100644
index 0000000..42132ea
--- /dev/null
+++ b/src/ZX/equality.jl
@@ -0,0 +1,19 @@
+"""
+ verify_equality(zxd_1::ZXDiagram, zxd_2::ZXDiagram)
+
+checks the equivalence of two different ZXDiagrams
+
+"""
+function verify_equality(zxd_1::ZXDiagram, zxd_2::ZXDiagram)
+ merged_diagram = concat!(zxd_1, dagger(zxd_2))
+ m_simple = full_reduction(merged_diagram)
+ contains_only_bare_wires(m_simple)
+end
+
+function contains_only_bare_wires(zxd::Union{ZXDiagram,ZXGraph})
+ all(is_in_or_out_spider(st[2]) for st in zxd.st)
+end
+
+function is_in_or_out_spider(st::SpiderType.SType)
+ st == SpiderType.In || st == SpiderType.Out
+end
diff --git a/src/ZX/ir.jl b/src/ZX/ir.jl
index 5e91aba..16a956a 100644
--- a/src/ZX/ir.jl
+++ b/src/ZX/ir.jl
@@ -6,7 +6,7 @@ convert_to_gate(::Val{:Z}, loc) = Gate(Z, Locations(loc))
convert_to_gate(::Val{:H}, loc) = Gate(H, Locations(loc))
convert_to_gate(::Val{:S}, loc) = Gate(S, Locations(loc))
convert_to_gate(::Val{:Sdag}, loc) = Gate(AdjointOperation(S), Locations(loc))
-convert_to_gate(::Val{:T}, loc) = Gate(T, Locations(loc))
+convert_to_gate(::Val{:T}, loc) = Gate(T, Locations(loc))
convert_to_gate(::Val{:Tdag}, loc) = Gate(AdjointOperation(S), Locations(loc))
convert_to_gate(::Val{:SWAP}, loc1, loc2) = Gate(SWAP, Locations((loc1, loc2)))
convert_to_gate(::Val{:CNOT}, loc, ctrl) = Ctrl(Gate(X, Locations(loc)), CtrlLocations(ctrl))
@@ -25,6 +25,14 @@ function convert_to_gate(::Val{:Rx}, loc, theta)
end
return Gate(Rx(theta), Locations(loc))
end
+
+function convert_to_gate(::Val{:Ry}, loc, theta)
+ if theta isa Phase
+ theta = theta * π
+ theta = theta.ex
+ end
+ return Gate(Ry(theta), Locations(loc))
+end
function convert_to_gate(::Val{:shift}, loc, theta)
if theta isa Phase
theta = theta * π
@@ -33,11 +41,11 @@ function convert_to_gate(::Val{:shift}, loc, theta)
return Gate(shift(theta), Locations(loc))
end
-function push_gate!(circ::Chain, gargs...)
+function push_gate!(circ::Chain, gargs...)
push!(circ.args, convert_to_gate(gargs...))
return circ
end
-function pushfirst_gate!(circ::Chain, gargs...)
+function pushfirst_gate!(circ::Chain, gargs...)
pushfirst!(circ.args, convert_to_gate(gargs...))
return circ
end
@@ -74,10 +82,7 @@ function canonicalize_single_location(node::YaoHIR.Gate)
return YaoHIR.Gate(node.operation, node.locations[1])
end
-function convert_to_zxd(root::YaoHIR.BlockIR)
- circ = ZXDiagram(root.nqubits)
-
- circuit = canonicalize_single_location(root.circuit)
+function gates_to_circ(circ, circuit, root)
for gate in YaoHIR.leaves(circuit)
@switch gate begin
@case Gate(&Z, loc::Locations{Int})
@@ -92,18 +97,18 @@ function convert_to_zxd(root::YaoHIR.BlockIR)
push_gate!(circ, Val(:Z), plain(loc), 1//4)
@case Gate(shift(theta), loc::Locations{Int})
theta = unwrap_ssa_phase(theta, root.parent)
- push_gate!(circ, Val(:Z), plain(loc), (1/π)*theta)
+ push_gate!(circ, Val(:Z), plain(loc), (1/π) * theta)
@case Gate(Rx(theta), loc::Locations{Int})
theta = unwrap_ssa_phase(theta, root.parent)
- push_gate!(circ, Val(:X), plain(loc), (1/π)*theta)
+ push_gate!(circ, Val(:X), plain(loc), (1/π) * theta)
@case Gate(Ry(theta), loc::Locations{Int})
theta = unwrap_ssa_phase(theta, root.parent)
- push_gate!(circ, Val(:X), plain(loc), 1//2)
- push_gate!(circ, Val(:Z), plain(loc), (1/π) * theta)
+ push_gate!(circ, Val(:X), plain(loc), 1//2)
+ push_gate!(circ, Val(:Z), plain(loc), (1/π) * theta)
push_gate!(circ, Val(:X), plain(loc), -1//2)
@case Gate(Rz(theta), loc::Locations{Int})
theta = unwrap_ssa_phase(theta, root.parent)
- push_gate!(circ, Val(:Z), plain(loc), (1/π)*theta)
+ push_gate!(circ, Val(:Z), plain(loc), (1/π) * theta)
@case Gate(AdjointOperation(&S), loc::Locations{Int})
push_gate!(circ, Val(:Z), plain(loc), 3//2)
@case Gate(AdjointOperation(&T), loc::Locations{Int})
@@ -127,7 +132,51 @@ function convert_to_zxd(root::YaoHIR.BlockIR)
return circ
end
-function convert_to_chain(circ::ZXDiagram{TT, P}) where {TT, P}
+function convert_to_zxd(root::YaoHIR.BlockIR)
+ diagram = ZXDiagram(root.nqubits)
+ circuit = canonicalize_single_location(root.circuit)
+ gates_to_circ(diagram, circuit, root)
+end
+
+
+function push_spider_to_chain!(qc, q, ps, st)
+ if ps != 0
+ if st == SpiderType.Z
+ if ps == 1
+ push!(qc, Gate(Z, Locations(q)))
+ elseif ps == 1 // 2
+ push!(qc, Gate(S, Locations(q)))
+ elseif ps == 3 // 2
+ push!(qc, Gate(AdjointOperation(S), Locations(q)))
+ elseif ps == 1 // 4
+ push!(qc, Gate(T, Locations(q)))
+ elseif ps == 7 // 4
+ push!(qc, Gate(AdjointOperation(T), Locations(q)))
+ elseif ps != 0
+ θ = ps * π
+ if θ isa Phase
+ θ = θ.ex
+ end
+ push!(qc, Gate(shift(θ), Locations(q)))
+ end
+ elseif st == SpiderType.X
+ if ps == 1
+ push!(qc, Gate(X, Locations(q)))
+ else
+ ps != 0
+ θ = ps * π
+ if θ isa Phase
+ θ = θ.ex
+ end
+ push!(qc, Gate(Rx(θ), Locations(q)))
+ end
+ elseif st == SpiderType.H
+ push!(qc, Gate(H, Locations(q)))
+ end
+ end
+end
+
+function convert_to_chain(circ::ZXDiagram{TT,P}) where {TT,P}
spider_seq = spider_sequence(circ)
qc = []
for vs in spider_seq
@@ -167,38 +216,3 @@ function convert_to_chain(circ::ZXDiagram{TT, P}) where {TT, P}
return Chain(qc...)
end
-function push_spider_to_chain!(qc, q, ps, st)
- if ps != 0
- if st == SpiderType.Z
- if ps == 1
- push!(qc, Gate(Z, Locations(q)))
- elseif ps == 1//2
- push!(qc, Gate(S, Locations(q)))
- elseif ps == 3//2
- push!(qc, Gate(AdjointOperation(S), Locations(q)))
- elseif ps == 1//4
- push!(qc, Gate(T, Locations(q)))
- elseif ps == 7//4
- push!(qc, Gate(AdjointOperation(T), Locations(q)))
- elseif ps != 0
- θ = ps * π
- if θ isa Phase
- θ = θ.ex
- end
- push!(qc, Gate(shift(θ), Locations(q)))
- end
- elseif st == SpiderType.X
- if ps == 1
- push!(qc, Gate(X, Locations(q)))
- else ps != 0
- θ = ps * π
- if θ isa Phase
- θ = θ.ex
- end
- push!(qc, Gate(Rx(θ), Locations(q)))
- end
- elseif st == SpiderType.H
- push!(qc, Gate(H, Locations(q)))
- end
- end
-end
\ No newline at end of file
diff --git a/src/ZX/rules.jl b/src/ZX/rules.jl
index fb709a2..9ac6897 100644
--- a/src/ZX/rules.jl
+++ b/src/ZX/rules.jl
@@ -273,17 +273,30 @@ function Base.match(::Rule{:p3}, zxg::ZXGraph{T, P}) where {T, P}
return matches
end
-function Base.match(::Rule{:id}, zxg::ZXGraph{T, P}) where {T, P}
+function Base.match(::Rule{:id}, zxg::ZXGraph{T,P}) where {T,P}
matches = Match{T}[]
for v2 in spiders(zxg)
nb2 = neighbors(zxg, v2)
- if spider_type(zxg, v2) == SpiderType.Z && length(nb2) == 2
+ if spider_type(zxg, v2) == SpiderType.Z && length(nb2) == 2
v1, v3 = nb2
if phase(zxg, v2) == 0
if spider_type(zxg, v1) == SpiderType.Z && spider_type(zxg, v3) == SpiderType.Z
push!(matches, Match{T}([v1, v2, v3]))
end
- else phase(zxg, v2) == 1
+
+ if (
+ (
+ spider_type(zxg, v1) == SpiderType.In ||
+ spider_type(zxg, v1) == SpiderType.Out
+ ) && (
+ spider_type(zxg, v3) == SpiderType.In ||
+ spider_type(zxg, v3) == SpiderType.Out
+ )
+ )
+ push!(matches, Match{T}([v1, v2, v3]))
+ end
+ else
+ phase(zxg, v2) == 1
if spider_type(zxg, v1) == SpiderType.Z && spider_type(zxg, v3) == SpiderType.Z
if degree(zxg, v1) == 1
push!(matches, Match{T}([v1, v2, v3]))
@@ -896,6 +909,11 @@ function check_rule(::Rule{:id}, zxg::ZXGraph{T, P}, vs::Vector{T}) where {T, P}
if spider_type(zxg, v1) == SpiderType.Z && spider_type(zxg, v3) == SpiderType.Z
return true
end
+ if ((spider_type(zxg, v1) == SpiderType.In || spider_type(zxg, v1) == SpiderType.Out) &&
+ (spider_type(zxg, v3) == SpiderType.In || spider_type(zxg, v3) == SpiderType.Out))
+ return true
+ end
+
else phase(zxg, v2) == 1
if spider_type(zxg, v1) == SpiderType.Z && spider_type(zxg, v3) == SpiderType.Z
return degree(zxg, v1) == 1 || degree(zxg, v3) == 1
@@ -913,16 +931,23 @@ function rewrite!(::Rule{:id}, zxg::ZXGraph{T, P}, vs::Vector{T}) where {T, P}
set_phase!(zxg, v1, -phase(zxg, v1))
zxg.phase_ids[v1] = (zxg.phase_ids[v1][1], -zxg.phase_ids[v1][2])
end
- set_phase!(zxg, v3, phase(zxg, v3)+phase(zxg, v1))
- id1, mul1 = zxg.phase_ids[v1]
- id3, mul3 = zxg.phase_ids[v3]
- set_phase!(zxg.master, id3, (mul3 * phase(zxg.master, id3) + mul1 * phase(zxg.master, id1)) * mul3)
- set_phase!(zxg.master, id1, zero(P))
- for v in neighbors(zxg, v1)
- v == v2 && continue
- add_edge!(zxg, v, v3, is_hadamard(zxg, v, v1) ? EdgeType.HAD : EdgeType.SIM)
+ if ((spider_type(zxg, v1) == SpiderType.In || spider_type(zxg, v1) == SpiderType.Out ||
+ spider_type(zxg, v3) == SpiderType.In || spider_type(zxg, v3) == SpiderType.Out))
+ rem_spider!(zxg, v2)
+ add_edge!(zxg, v1, v3, EdgeType.SIM)
+
+ else
+ set_phase!(zxg, v3, phase(zxg, v3)+phase(zxg, v1))
+ id1, mul1 = zxg.phase_ids[v1]
+ id3, mul3 = zxg.phase_ids[v3]
+ set_phase!(zxg.master, id3, (mul3 * phase(zxg.master, id3) + mul1 * phase(zxg.master, id1)) * mul3)
+ set_phase!(zxg.master, id1, zero(P))
+ for v in neighbors(zxg, v1)
+ v == v2 && continue
+ add_edge!(zxg, v, v3, is_hadamard(zxg, v, v1) ? EdgeType.HAD : EdgeType.SIM)
+ end
+ rem_spiders!(zxg, [v1, v2])
end
- rem_spiders!(zxg, [v1, v2])
return zxg
end
@@ -986,4 +1011,5 @@ function rewrite!(::Rule{:scalar}, zxg::Union{ZXGraph{T, P}, ZXDiagram{T, P}}, v
@inbounds v = vs[1]
rem_spider!(zxg, v)
return zxg
-end
\ No newline at end of file
+end
+
diff --git a/src/ZX/zx_diagram.jl b/src/ZX/zx_diagram.jl
index c07eb27..abfac4b 100644
--- a/src/ZX/zx_diagram.jl
+++ b/src/ZX/zx_diagram.jl
@@ -19,10 +19,17 @@ struct ZXDiagram{T<:Integer, P} <: AbstractZXDiagram{T, P}
inputs::Vector{T}
outputs::Vector{T}
- function ZXDiagram{T, P}(mg::Multigraph{T}, st::Dict{T, SpiderType.SType}, ps::Dict{T, P},
- layout::ZXLayout{T}, phase_ids::Dict{T, Tuple{T, Int}} = Dict{T, Tuple{T, Int}}(),
- s::Scalar{P} = Scalar{P}(),
- inputs::Vector{T} = Vector{T}(), outputs::Vector{T} = Vector{T}()) where {T<:Integer, P}
+ function ZXDiagram{T,P}(
+ mg::Multigraph{T},
+ st::Dict{T,SpiderType.SType},
+ ps::Dict{T,P},
+ layout::ZXLayout{T},
+ phase_ids::Dict{T,Tuple{T,Int}} = Dict{T,Tuple{T,Int}}(),
+ s::Scalar{P} = Scalar{P}(),
+ inputs::Vector{T} = Vector{T}(),
+ outputs::Vector{T} = Vector{T}(),
+ round_phases::Bool = true,
+ ) where {T<:Integer,P}
if nv(mg) == length(ps) && nv(mg) == length(st)
if length(phase_ids) == 0
for v in vertices(mg)
@@ -52,7 +59,9 @@ struct ZXDiagram{T<:Integer, P} <: AbstractZXDiagram{T, P}
end
end
zxd = new{T, P}(mg, st, ps, layout, phase_ids, s, inputs, outputs)
- round_phases!(zxd)
+ if round_phases
+ round_phases!(zxd)
+ end
return zxd
else
error("There should be a phase and a type for each spider!")
@@ -549,7 +558,7 @@ function generate_layout!(zxd::ZXDiagram{T, P}, seq::Vector{Any} = []) where {T,
for v1 in nb
if !(v1 in vs_generated)
q1 = findfirst(isequal(v1), vs_frontier)
- if q1 !== nothing
+ if !isnothing(q1)
col = maximum(frontier_col[min(q, q1):max(q, q1)])
set_loc!(layout, v, q, col)
set_loc!(layout, v1, q1, col)
@@ -571,7 +580,7 @@ function generate_layout!(zxd::ZXDiagram{T, P}, seq::Vector{Any} = []) where {T,
nb_v1 = neighbors(zxd, v1)
v2 = nb_v1[findfirst(!isequal(v), nb_v1)]
q2 = findfirst(isequal(v2), vs_frontier)
- if q2 !== nothing
+ if !isnothing(q2)
col = maximum(frontier_col[min(q, q2):max(q, q2)])
set_loc!(layout, v, q, col)
set_loc!(layout, v2, q2, col)
@@ -629,3 +638,180 @@ function safe_convert(::Type{T}, x::Real) where T<:Rational
@warn "converting phase to rational, but with rounding error $(abs(fr-x))."
return fr
end
+
+"""
+ plot(zxd::ZXDiagram{T, P}; kwargs...) where {T, P}
+
+Plots a ZXDiagram using Vega.
+
+If called from the REPL it will open in the Browser.
+Please remeber to run "using Vega, DataFrames" before, as this uses an extension
+"""
+plot(zxd::ZXDiagram{T, P}; kwargs...) where {T, P} =
+ error("missing extension, please use Vega with 'using Vega, DataFrames'")
+
+
+"""
+ get_output_idx(zxd::ZXDiagram{T,P}, q::T) where {T,P}
+
+Get spider index of output qubit q. Returns -1 is non-existant
+"""
+function get_output_idx(zxd::ZXDiagram{T,P}, q::T) where {T,P}
+ for v in get_outputs(zxd)
+ if spider_type(zxd, v) == SpiderType.Out && Int(qubit_loc(zxd, v)) == q
+ res = v
+ else
+ res = nothing
+ end
+
+ !isnothing(res) && return res
+ end
+ return -1
+end
+
+"""
+ import_non_in_out!(d1::ZXDiagram{T,P}, d2::ZXDiagram{T,P}, v2tov1::Dict{T,T}) where {T,P}
+
+Add non input and output spiders of d2 to d1, modify d1. Record the mapping of vertex indices.
+"""
+function import_non_in_out!(
+ d1::ZXDiagram{T,P},
+ d2::ZXDiagram{T,P},
+ v2tov1::Dict{T,T},
+) where {T,P}
+ for v2 in vertices(d2.mg)
+ st = spider_type(d2, v2)
+ if st == SpiderType.In || st == SpiderType.Out
+ new_v = nothing
+ # FIXME why is Out = H ?
+ elseif st == SpiderType.Z || st == SpiderType.X || st == SpiderType.H
+ new_v = add_vertex!(d1.mg)[1]
+ else
+ throw(ArgumentError("Unknown spider type $(d2.st[v2])"))
+ end
+ if !isnothing(new_v)
+ v2tov1[v2] = new_v
+ d1.st[new_v] = spider_type(d2, v2)
+ d1.ps[new_v] = d2.ps[v2]
+ d1.phase_ids[new_v] = (v2, 1)
+ end
+ end
+end
+
+nout(zxd::ZXDiagram) = length(zxd.outputs)
+nin(zxd::ZXDiagram) = length(zxd.inputs)
+
+"""
+ get_input_idx(zwd::ZXDiagram{T,P}, q::T) where {T,P}
+
+Get spider index of input qubit q. Returns -1 if non-existant
+"""
+function get_input_idx(zxd::ZXDiagram{T,P}, q::T) where {T,P}
+ for v in get_inputs(zxd)
+ if spider_type(zxd, v) == SpiderType.In && Int(qubit_loc(zxd, v)) == q
+ res = v
+ else
+ res = nothing
+ end
+
+ !isnothing(res) && return res
+ end
+ return -1
+end
+
+
+"""
+ import_edges!(d1::ZXDiagram{T,P}, d2::ZXDiagram{T,P}, v2tov1::Dict{T,T}) where {T,P}
+
+Import edges of d2 to d1, modify d1
+"""
+function import_edges!(d1::ZXDiagram{T,P}, d2::ZXDiagram{T,P}, v2tov1::Dict{T,T}) where {T,P}
+ for edge in edges(d2.mg)
+ src, dst, emul = edge.src, edge.dst, edge.mul
+ add_edge!(d1.mg, v2tov1[src], v2tov1[dst], emul)
+ end
+end
+
+"""
+ concat!(zxd_1::ZXDiagram{T,P}, zxd_2::ZXDiagram{T,P})::ZXDiagram{T,P} where {T,P}
+
+Appends two diagrams, where the second diagram is inverted
+"""
+function concat!(zxd_1::ZXDiagram{T,P}, zxd_2::ZXDiagram{T,P})::ZXDiagram{T,P} where {T,P}
+ nqubits(zxd_1) == nqubits(zxd_2) || throw(
+ ArgumentError(
+ "number of qubits need to be equal, go $(nqubits(zxd_1)) and $(nqubits(zxd_2))",
+ ),
+ )
+
+ v2tov1 = Dict{T,T}()
+ import_non_in_out!(zxd_1, zxd_2, v2tov1)
+
+ for i = 1:nout(zxd_1)
+ out_idx = get_output_idx(zxd_1, i)
+ # output spiders cannot be connected to multiple vertices or with multiedge
+ prior_vtx = neighbors(zxd_1, out_idx)[1]
+ rem_edge!(zxd_1, out_idx, prior_vtx)
+ # zxd_2 input vtx idx is mapped to the vtx prior to zxd_1 output
+ v2tov1[get_input_idx(zxd_2, i)] = prior_vtx
+ end
+
+ for i = 1:nout(zxd_2)
+ v2tov1[get_output_idx(zxd_2, i)] = get_output_idx(zxd_1, i)
+ end
+
+ import_edges!(zxd_1, zxd_2, v2tov1)
+ add_global_phase!(zxd_1, zxd_2.scalar.phase)
+ add_power!(zxd_1, zxd_2.scalar.power_of_sqrt_2)
+
+ return zxd_1
+end
+
+"""
+ stype_to_val(st)::Union{SpiderType,nothing}
+
+Converts SpiderType into Val
+"""
+function stype_to_val(st)::Val
+ if st == SpiderType.Z
+ Val{:Z}()
+ elseif st == SpiderType.X
+ Val{:X}()
+ elseif st == SpiderType.H
+ Val{:H}()
+ else
+ throw(ArgumentError("$st has no corresponding SpiderType"))
+ end
+end
+
+
+
+"""
+ dagger(zxd::ZXDiagram{T,P})::ZXDiagram{T,P} where {T,P}
+
+Dagger of a ZXDiagram by swapping input and outputs and negating the values of the phases
+"""
+
+function dagger(zxd::ZXDiagram{T,P})::ZXDiagram{T,P} where {T,P}
+ ps_i = Dict([k => -v for (k, v) in zxd.ps])
+ zxd_dg = ZXDiagram{T,P}(
+ copy(zxd.mg),
+ copy(zxd.st),
+ ps_i,
+ copy(zxd.layout),
+ deepcopy(zxd.phase_ids),
+ copy(zxd.scalar),
+ copy(zxd.outputs),
+ copy(zxd.inputs),
+ false,
+ )
+ for v in vertices(zxd_dg.mg)
+ value = zxd_dg.st[v]
+ if value == SpiderType.In
+ zxd_dg.st[v] = SpiderType.Out
+ elseif (value == SpiderType.Out)
+ zxd_dg.st[v] = SpiderType.In
+ end
+ end
+ return zxd_dg
+end
diff --git a/src/ZX/zx_graph.jl b/src/ZX/zx_graph.jl
index f70f95d..6d11b00 100644
--- a/src/ZX/zx_graph.jl
+++ b/src/ZX/zx_graph.jl
@@ -9,11 +9,14 @@ This is the type for representing the graph-like ZX-diagrams.
"""
struct ZXGraph{T<:Integer, P} <: AbstractZXDiagram{T, P}
mg::Multigraph{T}
+
ps::Dict{T, P}
st::Dict{T, SpiderType.SType}
et::Dict{Tuple{T, T}, EdgeType.EType}
+
layout::ZXLayout{T}
phase_ids::Dict{T,Tuple{T, Int}}
+
scalar::Scalar{P}
master::ZXDiagram{T, P}
inputs::Vector{T}
@@ -160,7 +163,7 @@ nqubits(zxg::ZXGraph) = zxg.layout.nbits
qubit_loc(zxg::ZXGraph{T, P}, v::T) where {T, P} = qubit_loc(zxg.layout, v)
function column_loc(zxg::ZXGraph{T, P}, v::T) where {T, P}
c_loc = column_loc(zxg.layout, v)
- if c_loc !== nothing
+ if !isnothing(c_loc)
if spider_type(zxg, v) == SpiderType.Out
nb = neighbors(zxg, v)
if length(nb) == 1
@@ -177,7 +180,7 @@ function column_loc(zxg::ZXGraph{T, P}, v::T) where {T, P}
c_loc = ceil(column_loc(zxg, nb) - 2)
end
end
- c_loc !== nothing && return c_loc
+ !isnothing(c_loc) && return c_loc
return 0
end
@@ -299,7 +302,7 @@ function spider_sequence(zxg::ZXGraph{T, P}) where {T, P}
spider_seq[q] = Vector{T}()
end
for v in vs
- if qubit_loc(zxg, v) !== nothing
+ if !isnothing(qubit_loc(zxg, v))
q_loc = Int(qubit_loc(zxg, v))
q_loc > 0 && push!(spider_seq[q_loc], v)
end
@@ -376,3 +379,7 @@ function add_power!(zxg::ZXGraph, n)
add_power!(zxg.scalar, n)
return zxg
end
+
+
+plot(zxd::ZXGraph{T, P}; kwargs...) where {T, P} =
+ error("missing extension, please use Vega with 'using Vega, DataFrames'")
diff --git a/src/ZXW/ZXW.jl b/src/ZXW/ZXW.jl
index fd0e220..bde7443 100644
--- a/src/ZXW/ZXW.jl
+++ b/src/ZXW/ZXW.jl
@@ -4,10 +4,12 @@ using Expronicon.ADT: @const_use, @adt
using MLStyle, Multigraphs, Graphs
using ..Utils: Scalar, Phase, Parameter, PiUnit, Factor, add_phase!
using ..ZX: safe_convert, AbstractRule, Rule, Match
+using YaoHIR
+using YaoHIR: BlockIR
import ..Utils: add_power!
import ..ZX:
- rewrite!, simplify!, push_gate!, pushfirst_gate!, spiders, rem_spider!, rem_spiders!
+ rewrite!, simplify!, push_gate!, pushfirst_gate!, spiders, rem_spider!, rem_spiders!, canonicalize_single_location, gates_to_circ
export ZXWDiagram, substitute_variables!
diff --git a/src/ZXW/utils.jl b/src/ZXW/utils.jl
index 8b7c056..19179c9 100644
--- a/src/ZXW/utils.jl
+++ b/src/ZXW/utils.jl
@@ -667,3 +667,14 @@ function substitute_variables!(
end
return zxwd
end
+
+
+function convert_to_zxwd(root::YaoHIR.BlockIR)
+ # FIXME add test
+ diagram = ZXWDiagram(root.nqubits)
+ circuit = canonicalize_single_location(root.circuit)
+ gates_to_circ(diagram, circuit, root)
+end
+
+
+
diff --git a/src/ZXW/zxw_diagram.jl b/src/ZXW/zxw_diagram.jl
index dd4909b..adfd9f9 100644
--- a/src/ZXW/zxw_diagram.jl
+++ b/src/ZXW/zxw_diagram.jl
@@ -81,6 +81,10 @@ function ZXWDiagram(nbits::T) where {T<:Integer}
end
+
+ZXWDiagram(bir::BlockIR) = convert_to_zxwd(bir)
+
+
Base.copy(zxwd::ZXWDiagram{T,P}) where {T,P} = ZXWDiagram{T,P}(
copy(zxwd.mg),
copy(zxwd.st),
diff --git a/test/ancilla_extraction.jl b/test/ancilla_extraction.jl
index 1a5e787..1cc9531 100644
--- a/test/ancilla_extraction.jl
+++ b/test/ancilla_extraction.jl
@@ -17,14 +17,14 @@ zxd = gen_phase_gadget()
zxg = full_reduction(zxd)
anc_circ = ancilla_extraction(zxg)
-# plot(anc_circ)
+@test !isnothing(plot(anc_circ))
zxd_swap = ZXDiagram(2)
pushfirst_gate!(zxd_swap, Val(:SWAP), [1, 2])
-# plot(zxd_swap)
+plot(zxd_swap)
convert_to_chain(zxd_swap)
zxg_swap = ZXGraph(zxd_swap)
zxd_anc = ancilla_extraction(zxg_swap)
-# plot(zxd_anc)
+@test !isnothing(plot(zxd_anc))
@test length(ZX.convert_to_chain(zxd_anc)) == 3
diff --git a/test/challenge.jl b/test/challenge.jl
index b9eacf4..d63e69d 100644
--- a/test/challenge.jl
+++ b/test/challenge.jl
@@ -208,4 +208,5 @@ for i = 1:5
push!(zxg.outputs, i+23)
end
+@test !isnothing(plot(zxg))
ZX.ancilla_extraction(zxg)
diff --git a/test/circuit_extraction.jl b/test/circuit_extraction.jl
index 0c83041..561bb35 100644
--- a/test/circuit_extraction.jl
+++ b/test/circuit_extraction.jl
@@ -38,3 +38,9 @@ zxg2 = clifford_simplification(zxd)
zxg3 = full_reduction(zxd)
cir = circuit_extraction(zxg3)
+
+# Plotting
+@test !isnothing(plot(zxd))
+@test !isnothing(plot(zxg))
+@test !isnothing(plot(zxg2))
+@test !isnothing(plot(zxg3))
diff --git a/test/equality.jl b/test/equality.jl
new file mode 100644
index 0000000..03df647
--- /dev/null
+++ b/test/equality.jl
@@ -0,0 +1,25 @@
+using YaoHIR: BlockIR
+using YaoHIR, YaoLocations
+using Core.Compiler: IRCode
+
+chain = Chain()
+push_gate!(chain, Val(:H), 1)
+push_gate!(chain, Val(:H), 2)
+push_gate!(chain, Val(:H), 3)
+push_gate!(chain, Val(:H), 4)
+push_gate!(chain, Val(:CNOT), 4, 1)
+push_gate!(chain, Val(:CNOT), 4, 3)
+push_gate!(chain, Val(:X), 1)
+push_gate!(chain, Val(:X), 2)
+push_gate!(chain, Val(:X), 3)
+
+bir = BlockIR(IRCode(), 4, chain)
+d1 = ZXDiagram(bir)
+
+# create second version
+d2 = copy(d1)
+# Push H spider with Val spidertype
+push_gate!(d2, Val(:H), 1)
+
+@test verify_equality(copy(d1), copy(d1)) == true
+@test verify_equality(copy(d1), copy(d2)) == false
diff --git a/test/ir.jl b/test/ir.jl
index 3c7f3fa..f84bbdc 100644
--- a/test/ir.jl
+++ b/test/ir.jl
@@ -1,8 +1,8 @@
using Test
-using ZXCalculus
+using ZXCalculus.ZXW
+using ZXCalculus, ZXCalculus.ZX, ZXCalculus.Utils
using YaoHIR, YaoLocations
-using YaoHIR.IntrinsicOperation
-using CompilerPluginTools
+using Core.Compiler: IRCode
chain = Chain()
push_gate!(chain, Val(:Sdag), 1)
@@ -33,113 +33,293 @@ push_gate!(chain, Val(:S), 3)
push_gate!(chain, Val(:X), 4)
push_gate!(chain, Val(:CNOT), 3, 2)
push_gate!(chain, Val(:H), 1)
-push_gate!(chain, Val(:shift), 4, ZXCalculus.Phase(1//2))
-push_gate!(chain, Val(:Rx), 4, ZXCalculus.Phase(1//1))
-push_gate!(chain, Val(:Rx), 3, ZXCalculus.Phase(1//4))
-push_gate!(chain, Val(:Rx), 2, ZXCalculus.Phase(1//4))
+push_gate!(chain, Val(:shift), 4, Phase(1 // 2))
+push_gate!(chain, Val(:Rx), 4, Phase(1 // 1))
+push_gate!(chain, Val(:Rx), 3, Phase(1 // 4))
+push_gate!(chain, Val(:Rx), 2, Phase(1 // 4))
push_gate!(chain, Val(:S), 3)
-ir = @make_ircode begin
-end
-bir = BlockIR(ir, 4, chain)
-zxd = convert_to_zxd(bir)
-convert_to_chain(zxd)
-pt_zxd = phase_teleportation(zxd)
-@test tcount(pt_zxd) <= tcount(zxd)
-pt_chain = convert_to_chain(pt_zxd)
-@test length(pt_chain) <= length(chain)
-
-zxg = clifford_simplification(zxd)
-cl_chain = circuit_extraction(zxg)
-
-zxg = full_reduction(zxd)
-fl_chain = circuit_extraction(zxg)
-ZXCalculus.generate_layout!(zxg)
-@test ZXCalculus.qubit_loc(zxg, 40) == 0//1
-ZXCalculus.spider_sequence(zxg)
-
-pt_bir = phase_teleportation(bir)
-cl_bir = clifford_simplification(bir)
-fl_bir = full_reduction(bir)
-
-@test length(pt_chain) == length(pt_bir.circuit)
-@test length(cl_chain) == length(cl_bir.circuit)
-@test length(fl_chain) == length(fl_bir.circuit)
-
-@testset "issue#80" begin
- ir = @make_ircode begin
- end
- circuit = Chain(Gate(X, Locations(1)), Gate(X, Locations(1)))
- bir = BlockIR(ir, 1, circuit)
- bir = clifford_simplification(bir)
- bir = clifford_simplification(bir)
- @test bir.circuit == Chain(Gate(H, Locations((1, ))), Gate(H, Locations((1, ))))
-end
+@testset "ir.jl" begin
+ # Shadow operation in ir.jl testset, so that they do not overrride SpiderTypes
+ X = YaoHIR.IntrinsicOperation.X
+ Z = YaoHIR.IntrinsicOperation.Z
+ H = YaoHIR.IntrinsicOperation.H
+ T = YaoHIR.IntrinsicOperation.T
+ S = YaoHIR.IntrinsicOperation.S
+ SGate = YaoHIR.IntrinsicOperation.SGate
-@testset "generate_layout!" begin
- circ = Chain(Gate(H, Locations(2)), Gate(T, Locations(4)), Gate(H, Locations(1)), Gate(AdjointOperation{SGate}(S), Locations(2)), Gate(H, Locations(2)), Gate(X, Locations(3)), Gate(AdjointOperation{SGate}(S), Locations(1)), Gate(Z, Locations(1)), Gate(H, Locations(2)), Gate(X, Locations(1)), Gate(Z, Locations(1)), Gate(T, Locations(5)), Ctrl(Gate(X, Locations(5)), CtrlLocations(1)), Gate(H, Locations(1)), Gate(T, Locations(1)), Ctrl(Gate(X, Locations(3)), CtrlLocations(5)), Gate(H, Locations(1)), Gate(X, Locations(4)), Ctrl(Gate(X, Locations(5)), CtrlLocations(4)), Gate(S, Locations(2)), Ctrl(Gate(X, Locations(1)), CtrlLocations(3)), Gate(X, Locations(2)), Ctrl(Gate(X, Locations(3)), CtrlLocations(1)), Gate(X, Locations(2)), Gate(S, Locations(3)), Gate(Z, Locations(2)), Gate(Z, Locations(5)), Gate(X, Locations(2)), Gate(X, Locations(1)), Ctrl(Gate(X, Locations(3)), CtrlLocations(5)), Gate(S, Locations(4)), Gate(X, Locations(3)), Ctrl(Gate(X, Locations(1)), CtrlLocations(2)), Gate(AdjointOperation{SGate}(S), Locations(4)), Gate(Z, Locations(2)), Gate(AdjointOperation{SGate}(S), Locations(5)), Ctrl(Gate(X, Locations(1)), CtrlLocations(2)), Gate(Z, Locations(5)), Ctrl(Gate(X, Locations(1)), CtrlLocations(4)), Ctrl(Gate(X, Locations(3)), CtrlLocations(4)), Gate(H, Locations(4)), Gate(Z, Locations(1)), Gate(X, Locations(4)), Gate(Z, Locations(3)), Gate(H, Locations(4)), Ctrl(Gate(X, Locations(1)), CtrlLocations(4)), Ctrl(Gate(X, Locations(4)), CtrlLocations(1)), Gate(X, Locations(4)), Gate(S, Locations(3)), Gate(AdjointOperation{SGate}(S), Locations(2)), Gate(Z, Locations(3)), Gate(S, Locations(5)), Ctrl(Gate(X, Locations(3)), CtrlLocations(5)), Gate(H, Locations(2)), Gate(Z, Locations(4)), Gate(H, Locations(1)), Gate(X, Locations(1)), Gate(X, Locations(2)), Ctrl(Gate(X, Locations(5)), CtrlLocations(3)), Ctrl(Gate(X, Locations(1)), CtrlLocations(3)), Gate(Z, Locations(4)), Gate(S, Locations(5)), Gate(S, Locations(5)), Ctrl(Gate(X, Locations(5)), CtrlLocations(1)), Gate(T, Locations(4)), Gate(Z, Locations(2)), Gate(X, Locations(4)), Gate(H, Locations(2)), Gate(AdjointOperation{SGate}(S), Locations(3)), Gate(H, Locations(5)), Gate(T, Locations(2)), Gate(AdjointOperation{SGate}(S), Locations(5)), Gate(AdjointOperation{SGate}(S), Locations(4)), Gate(H, Locations(2)), Gate(S, Locations(2)), Gate(AdjointOperation{SGate}(S), Locations(3)), Ctrl(Gate(X, Locations(5)), CtrlLocations(1)), Gate(H, Locations(5)), Ctrl(Gate(X, Locations(4)), CtrlLocations(3)), Gate(H, Locations(4)), Gate(Z, Locations(2)), Gate(H, Locations(2)), Gate(S, Locations(2)), Gate(H, Locations(4)), Ctrl(Gate(X, Locations(1)), CtrlLocations(2)), Gate(X, Locations(4)), Gate(H, Locations(1)), Gate(AdjointOperation{SGate}(S), Locations(5)), Gate(X, Locations(1)), Gate(X, Locations(3)), Gate(Z, Locations(1)), Ctrl(Gate(X, Locations(1)), CtrlLocations(2)), Gate(T, Locations(3)), Gate(X, Locations(4)), Gate(X, Locations(3)), Gate(AdjointOperation{SGate}(S), Locations(1)), Gate(AdjointOperation{SGate}(S), Locations(3)), Gate(H, Locations(5)), Gate(S, Locations(4)), Gate(Z, Locations(4)))
- ir = @make_ircode begin end
- bir = BlockIR(ir, 5, circ)
+
+
+ ir = IRCode()
+ bir = BlockIR(ir, 4, chain)
zxd = ZXDiagram(bir)
- zxg = ZXGraph(zxd)
- full_reduction(zxg)
- ZXCalculus.generate_layout!(zxg)
- @test ZXCalculus.generate_layout!(zxg) !== nothing
-end
+ zxwd = ZXWDiagram(bir)
-function random_circuit(nbits, ngates; T = 0.1, CZ = 0.0, CNOT = 0.1)
- ir = @make_ircode begin
+
+ @testset "convert SpiderType to Val" begin
+ @test ZX.stype_to_val(SpiderType.Z) == Val{:Z}()
+ @test ZX.stype_to_val(SpiderType.X) == Val{:X}()
+ @test ZX.stype_to_val(SpiderType.H) == Val{:H}()
+ @test_throws ArgumentError ZX.stype_to_val("anything else") end
+
+ @testset "convert BlockIR into ZXWDiagram" begin
+ @test !isnothing(zxwd)
end
- CLIFF = 1 - T - CZ - CNOT
- circ = Chain()
- for _ = 1:ngates
- x = rand()
- nbits == 1 && (x = x*(CLIFF+T))
- if x <= CLIFF
- g = rand([:X, :X, :Z, :Z, :S, :Sdag, :H, :H])
- push_gate!(circ, Val(g), rand(1:nbits))
- elseif x - CLIFF <= T
- g = rand([:T, :Tdag])
- push_gate!(circ, Val(g), rand(1:nbits))
- elseif x - CLIFF - T <= CZ
- loc = rand(1:nbits)
- ctrl = loc
- while ctrl == loc
- ctrl = rand(1:nbits)
- end
- push_gate!(circ, Val(:CZ), loc, ctrl)
- else
- loc = rand(1:nbits)
- ctrl = loc
- while ctrl == loc
- ctrl = rand(1:nbits)
+
+
+ @testset "create Matrix from ZXDiagram" begin
+ matrix_from_zxd =
+ Matrix(ZXWDiagram(BlockIR(IRCode(), 4, circuit_extraction(full_reduction(zxd)))))
+ @test !isnothing(matrix_from_zxd)
+ end
+
+
+
+ @testset "BlockIR to Matrix" begin
+ @test !isnothing(Matrix(zxwd))
+ end
+
+ @test !isnothing(plot(zxd))
+ convert_to_chain(zxd)
+ pt_zxd = phase_teleportation(zxd)
+ @test tcount(pt_zxd) <= tcount(zxd)
+ pt_chain = convert_to_chain(pt_zxd)
+ @test length(pt_chain) <= length(chain)
+
+ zxg = clifford_simplification(zxd)
+ @test !isnothing(plot(zxg))
+ cl_chain = circuit_extraction(zxg)
+
+ zxg = full_reduction(zxd)
+ @test !isnothing(plot(zxg))
+ fl_chain = circuit_extraction(zxg)
+ ZX.generate_layout!(zxg)
+ @test ZX.qubit_loc(zxg, 40) == 0 // 1
+ ZX.spider_sequence(zxg)
+
+ pt_bir = phase_teleportation(bir)
+ cl_bir = clifford_simplification(bir)
+ fl_bir = full_reduction(bir)
+
+ @test length(pt_chain) == length(pt_bir.circuit)
+ @test length(cl_chain) == length(cl_bir.circuit)
+ @test length(fl_chain) == length(fl_bir.circuit)
+
+ @testset "issue#80" begin
+ ir = IRCode()
+ circuit = Chain(Gate(X, Locations(1)), Gate(X, Locations(1)))
+ bir = BlockIR(ir, 1, circuit)
+ bir = clifford_simplification(bir)
+ bir = clifford_simplification(bir)
+ @test bir.circuit == Chain(Gate(H, Locations((1,))), Gate(H, Locations((1,))))
+ end
+
+ @testset "generate_layout!" begin
+
+ circ = Chain(
+ Gate(H, Locations(2)),
+ Gate(T, Locations(4)),
+ Gate(H, Locations(1)),
+ Gate(AdjointOperation{SGate}(S), Locations(2)),
+ Gate(H, Locations(2)),
+ Gate(X, Locations(3)),
+ Gate(AdjointOperation{SGate}(S), Locations(1)),
+ Gate(Z, Locations(1)),
+ Gate(H, Locations(2)),
+ Gate(X, Locations(1)),
+ Gate(Z, Locations(1)),
+ Gate(T, Locations(5)),
+ Ctrl(Gate(X, Locations(5)), CtrlLocations(1)),
+ Gate(H, Locations(1)),
+ Gate(T, Locations(1)),
+ Ctrl(Gate(X, Locations(3)), CtrlLocations(5)),
+ Gate(H, Locations(1)),
+ Gate(X, Locations(4)),
+ Ctrl(Gate(X, Locations(5)), CtrlLocations(4)),
+ Gate(S, Locations(2)),
+ Ctrl(Gate(X, Locations(1)), CtrlLocations(3)),
+ Gate(X, Locations(2)),
+ Ctrl(Gate(X, Locations(3)), CtrlLocations(1)),
+ Gate(X, Locations(2)),
+ Gate(S, Locations(3)),
+ Gate(Z, Locations(2)),
+ Gate(Z, Locations(5)),
+ Gate(X, Locations(2)),
+ Gate(X, Locations(1)),
+ Ctrl(Gate(X, Locations(3)), CtrlLocations(5)),
+ Gate(S, Locations(4)),
+ Gate(X, Locations(3)),
+ Ctrl(Gate(X, Locations(1)), CtrlLocations(2)),
+ Gate(AdjointOperation{SGate}(S), Locations(4)),
+ Gate(Z, Locations(2)),
+ Gate(AdjointOperation{SGate}(S), Locations(5)),
+ Ctrl(Gate(X, Locations(1)), CtrlLocations(2)),
+ Gate(Z, Locations(5)),
+ Ctrl(Gate(X, Locations(1)), CtrlLocations(4)),
+ Ctrl(Gate(X, Locations(3)), CtrlLocations(4)),
+ Gate(H, Locations(4)),
+ Gate(Z, Locations(1)),
+ Gate(X, Locations(4)),
+ Gate(Z, Locations(3)),
+ Gate(H, Locations(4)),
+ Ctrl(Gate(X, Locations(1)), CtrlLocations(4)),
+ Ctrl(Gate(X, Locations(4)), CtrlLocations(1)),
+ Gate(X, Locations(4)),
+ Gate(S, Locations(3)),
+ Gate(AdjointOperation{SGate}(S), Locations(2)),
+ Gate(Z, Locations(3)),
+ Gate(S, Locations(5)),
+ Ctrl(Gate(X, Locations(3)), CtrlLocations(5)),
+ Gate(H, Locations(2)),
+ Gate(Z, Locations(4)),
+ Gate(H, Locations(1)),
+ Gate(X, Locations(1)),
+ Gate(X, Locations(2)),
+ Ctrl(Gate(X, Locations(5)), CtrlLocations(3)),
+ Ctrl(Gate(X, Locations(1)), CtrlLocations(3)),
+ Gate(Z, Locations(4)),
+ Gate(S, Locations(5)),
+ Gate(S, Locations(5)),
+ Ctrl(Gate(X, Locations(5)), CtrlLocations(1)),
+ Gate(T, Locations(4)),
+ Gate(Z, Locations(2)),
+ Gate(X, Locations(4)),
+ Gate(H, Locations(2)),
+ Gate(AdjointOperation{SGate}(S), Locations(3)),
+ Gate(H, Locations(5)),
+ Gate(T, Locations(2)),
+ Gate(AdjointOperation{SGate}(S), Locations(5)),
+ Gate(AdjointOperation{SGate}(S), Locations(4)),
+ Gate(H, Locations(2)),
+ Gate(S, Locations(2)),
+ Gate(AdjointOperation{SGate}(S), Locations(3)),
+ Ctrl(Gate(X, Locations(5)), CtrlLocations(1)),
+ Gate(H, Locations(5)),
+ Ctrl(Gate(X, Locations(4)), CtrlLocations(3)),
+ Gate(H, Locations(4)),
+ Gate(Z, Locations(2)),
+ Gate(H, Locations(2)),
+ Gate(S, Locations(2)),
+ Gate(H, Locations(4)),
+ Ctrl(Gate(X, Locations(1)), CtrlLocations(2)),
+ Gate(X, Locations(4)),
+ Gate(H, Locations(1)),
+ Gate(AdjointOperation{SGate}(S), Locations(5)),
+ Gate(X, Locations(1)),
+ Gate(X, Locations(3)),
+ Gate(Z, Locations(1)),
+ Ctrl(Gate(X, Locations(1)), CtrlLocations(2)),
+ Gate(T, Locations(3)),
+ Gate(X, Locations(4)),
+ Gate(X, Locations(3)),
+ Gate(AdjointOperation{SGate}(S), Locations(1)),
+ Gate(AdjointOperation{SGate}(S), Locations(3)),
+ Gate(H, Locations(5)),
+ Gate(S, Locations(4)),
+ Gate(Z, Locations(4)),
+ )
+ ir = IRCode()
+ bir = BlockIR(ir, 5, circ)
+ zxd = ZXDiagram(bir)
+ zxg = ZXGraph(zxd)
+ full_reduction(zxg)
+ ZX.generate_layout!(zxg)
+ @test !isnothing(plot(zxg))
+ @test !isnothing(ZX.generate_layout!(zxg))
+ end
+
+
+ @testset "generate_layout with chain" begin
+ bir = BlockIR(ir, 5, chain)
+ zxd = ZXDiagram(bir)
+ zxg = ZXGraph(zxd)
+ full_reduction(zxg)
+ ZX.generate_layout!(zxg)
+ @test !isnothing(plot(zxg))
+ @test !isnothing(ZX.generate_layout!(zxg))
+
+ end
+
+ function random_circuit(nbits, ngates; T = 0.1, CZ = 0.0, CNOT = 0.1)
+ ir = IRCode()
+ CLIFF = 1 - T - CZ - CNOT
+ circ = Chain()
+ for _ = 1:ngates
+ x = rand()
+ nbits == 1 && (x = x * (CLIFF + T))
+ if x <= CLIFF
+ g = rand([:X, :X, :Z, :Z, :S, :Sdag, :H, :H])
+ push_gate!(circ, Val(g), rand(1:nbits))
+ elseif x - CLIFF <= T
+ g = rand([:T, :Tdag])
+ push_gate!(circ, Val(g), rand(1:nbits))
+ elseif x - CLIFF - T <= CZ
+ loc = rand(1:nbits)
+ ctrl = loc
+ while ctrl == loc
+ ctrl = rand(1:nbits)
+ end
+ push_gate!(circ, Val(:CZ), loc, ctrl)
+ else
+ loc = rand(1:nbits)
+ ctrl = loc
+ while ctrl == loc
+ ctrl = rand(1:nbits)
+ end
+ push_gate!(circ, Val(:CNOT), loc, ctrl)
end
- push_gate!(circ, Val(:CNOT), loc, ctrl)
end
+ return BlockIR(ir, nbits, circ)
end
- return BlockIR(ir, nbits, circ)
-end
-function random_identity(nbits, ngates; T = 0.1, CZ = 0.0, CNOT = 0.1)
- bir = random_circuit(nbits, ngates; T = T, CZ = CZ, CNOT = CNOT)
- c = bir.circuit.args
- for i = length(c):-1:1
- if c[i] isa Gate
- g = c[i].operation
- if (g in (S, YaoHIR.IntrinsicOperation.T)) || (g isa AdjointOperation)
- push!(c, Gate(g', c[i].locations))
+ function random_identity(nbits, ngates; T = 0.1, CZ = 0.0, CNOT = 0.1)
+ bir = random_circuit(nbits, ngates; T = T, CZ = CZ, CNOT = CNOT)
+ c = bir.circuit.args
+ for i = length(c):-1:1
+ if c[i] isa Gate
+ g = c[i].operation
+ if (g in (YaoHIR.IntrinsicOperation.S, YaoHIR.IntrinsicOperation.T)) ||
+ (g isa AdjointOperation)
+ push!(c, Gate(g', c[i].locations))
+ else
+ push!(c, c[i])
+ end
else
push!(c, c[i])
end
- else
- push!(c, c[i])
end
+ return bir
end
- return bir
-end
-circ = random_identity(5, 50);
-zxd = convert_to_zxd(circ)
-zxg = ZXGraph(zxd)
-zxg |> clifford_simplification |> full_reduction
+ @testset "plot random_identity" begin
+ circ = random_identity(5, 50)
+ zxd = convert_to_zxd(circ)
+ @test !isnothing(plot(zxd))
+ zxg = ZXGraph(zxd)
+ @test !isnothing(plot(zxg))
+ @test !isnothing(plot(zxg |> clifford_simplification |> full_reduction))
+ end
+
+ @testset "gates_to_circ with addition Ry" begin
+ n_qubits = 4
+ # TODO add tests for Ry gate
+ chain_a = Chain()
+ push_gate!(chain_a, Val(:Ry), n_qubits, Phase(1 // 1))
+ push_gate!(chain_a, Val(:Rz), 4, Phase(1 // 1))
+ bir = BlockIR(ir, n_qubits, chain_a)
+
+ diagram = ZXDiagram(n_qubits)
+ ZX.gates_to_circ(diagram, chain_a, bir)
+ end
+
+ # TODO add test that checks if error is thrown for unkown gate
+
+ @testset "Chain of ZXDiagram" begin
+ # FIXME add better equal for Chain
+ # @test chain.args == Chain(ZXDiagram(bir)).args
+ # @test chain.args == Chain(ZXDiagram(bir)).args
+ @test !isnothing(Chain(zxd))
+ end
+
+end
diff --git a/test/phase.jl b/test/phase.jl
index b5865a0..dba45de 100644
--- a/test/phase.jl
+++ b/test/phase.jl
@@ -1,25 +1,19 @@
using Test
using ZXCalculus.Utils: Phase
-# ir = @make_ircode begin
-# Expr(:call, :+, 1, 1)::Int
-# Expr(:call, :+, 3, 3)::Int
-# end
+chain = Chain()
+push_gate!(chain, Val(:shift), 1, Phase(1 // 1))
+push_gate!(chain, Val(:Rz), 1, Phase(2 // 1))
-# circ = Chain(
-# Gate(shift(1.0), Locations(1)),
-# Gate(Rz(Core.SSAValue(2)), Locations(1)),
-# )
+bir = BlockIR(IRCode(), 4, chain)
-# bir = BlockIR(ir, 4, circ)
+zxd = convert_to_zxd(bir)
+c = clifford_simplification(zxd)
+ZX.generate_layout!(zxd)
+qc_tl = convert_to_chain(phase_teleportation(zxd))
+@test length(qc_tl) == 1
-# zxd = convert_to_zxd(bir)
-# c = clifford_simplification(zxd)
-# ZXCalculus.generate_layout!(zxd)
-# qc_tl = convert_to_chain(phase_teleportation(zxd))
-# @test length(qc_tl) == 1
-
-p = Phase(1//1)
+p = Phase(1 // 1)
@test p + 1 == 1 + p == p + p
@test p - 1 == 1 - p == p - p
diff --git a/test/phase_teleportation.jl b/test/phase_teleportation.jl
index bf350e6..3269521 100644
--- a/test/phase_teleportation.jl
+++ b/test/phase_teleportation.jl
@@ -75,6 +75,8 @@ function gen_cir()
end
cir = gen_cir()
+@test !isnothing(cir)
@test tcount(cir) == 28
cir2 = phase_teleportation(cir)
+@test !isnothing(plot(cir2))
@test tcount(cir2) == 8
diff --git a/test/plots.jl b/test/plots.jl
new file mode 100644
index 0000000..069cd23
--- /dev/null
+++ b/test/plots.jl
@@ -0,0 +1,13 @@
+using Test, ZXCalculus, ZXCalculus.ZX
+using ZXCalculus: ZX
+
+
+# Othertests for ZXGraphs and ZXDigram are embededd into the zx_graph and zx_diagram testsets
+zxd = ZXDiagram(3)
+ZX.insert_spider!(zxd, 1, 2, SpiderType.H)
+ZX.insert_spider!(zxd, 1, 2, SpiderType.X)
+ZX.insert_spider!(zxd, 1, 2, SpiderType.Z)
+zxg = ZXGraph(zxd)
+
+@test !isnothing(plot(zxd))
+@test !isnothing(plot(zxg))
diff --git a/test/rules.jl b/test/rules.jl
index bcc6d1e..b951ec9 100644
--- a/test/rules.jl
+++ b/test/rules.jl
@@ -10,6 +10,7 @@ matches = match(Rule{:f}(), zxd)
rewrite!(Rule{:f}(), zxd, matches)
@test sort!(spiders(zxd)) == [1, 3]
@test phase(zxd, 1) == phase(zxd, 3) == 3 // 4
+@test !isnothing(zxd)
g = Multigraph(path_graph(5))
add_edge!(g, 1, 2)
@@ -19,6 +20,7 @@ zxd = ZXDiagram(g, v_t, ps)
matches = match(Rule{:i1}(), zxd)
rewrite!(Rule{:i1}(), zxd, matches)
@test nv(zxd) == 3 && ne(zxd, count_mul = true) == 3 && ne(zxd) == 2
+@test !isnothing(zxd)
g = Multigraph([0 2 0; 2 0 1; 0 1 0])
ps = [i // 4 for i = 1:3]
@@ -27,6 +29,7 @@ zxd = ZXDiagram(g, v_t, ps)
matches = match(Rule{:h}(), zxd)
rewrite!(Rule{:h}(), zxd, matches)
@test nv(zxd) == 8 && ne(zxd) == 8
+@test !isnothing(zxd)
matches = match(Rule{:i2}(), zxd)
rewrite!(Rule{:i2}(), zxd, matches)
@@ -52,6 +55,8 @@ matches = match(Rule{:pi}(), zxd)
rewrite!(Rule{:pi}(), zxd, matches)
@test nv(zxd) == 8 && ne(zxd) == 7
@test zxd.scalar == Scalar(0, 1 // 2)
+# FIXME generate layout does not terminat
+# @test !isnothing(zxd)
g = Multigraph([0 2 0; 2 0 1; 0 1 0])
ps = [1, 1 // 2, 0]
@@ -61,6 +66,7 @@ matches = match(Rule{:pi}(), zxd)
rewrite!(Rule{:pi}(), zxd, matches)
@test nv(zxd) == 4 && ne(zxd) == 3 && ne(zxd, count_mul = true) == 4
@test zxd.scalar == Scalar(0, 1 // 2)
+@test !isnothing(zxd)
g = Multigraph(5)
add_edge!(g, 1, 2)
@@ -74,6 +80,8 @@ matches = match(Rule{:c}(), zxd)
rewrite!(Rule{:c}(), zxd, matches)
@test nv(zxd) == 7 && ne(zxd) == 4
@test zxd.scalar == Scalar(-3, 0 // 1)
+# FIXME generate layout does not terminate
+# @test !isnothing(zxd)
g = Multigraph(6)
add_edge!(g, 1, 3)
@@ -100,6 +108,7 @@ matches = match(Rule{:b}(), zxd)
rewrite!(Rule{:b}(), zxd, matches)
@test nv(zxd) == 8 && ne(zxd) == 8
@test zxd.scalar == Scalar(1, 0 // 1)
+@test !isnothing(zxd)
g = Multigraph(9)
for e in [[2, 6], [3, 7], [4, 8], [5, 9]]
@@ -127,6 +136,7 @@ replace!(Rule{:lc}(), zxg)
phase(zxg, 3) == 7 // 4 &&
phase(zxg, 4) == 0 // 1 &&
phase(zxg, 5) == 1 // 4
+@test !isnothing(zxd)
g = Multigraph(14)
for e in [[3, 9], [4, 10], [5, 11], [6, 12], [7, 13], [8, 14]]
@@ -178,6 +188,7 @@ end
@test length(match(Rule{:p1}(), zxg)) == 1
replace!(Rule{:pab}(), zxg)
@test nv(zxg) == 7 && ne(zxg) == 6
+@test !isnothing(zxg)
g = Multigraph(14)
for e in [[3, 9], [4, 10], [5, 11], [6, 12], [7, 13], [8, 14]]
@@ -207,6 +218,7 @@ end
match(Rule{:p2}(), zxg)
replace!(Rule{:p2}(), zxg)
@test zxg.phase_ids[15] == (2, -1)
+@test !isnothing(zxg)
g = Multigraph(15)
for e in [[3, 9], [4, 10], [5, 11], [6, 12], [7, 13], [8, 14], [2, 15]]
@@ -238,3 +250,4 @@ replace!(Rule{:p3}(), zxg)
@test nv(zxg) == 16 && ne(zxg) == 28
@test ZXCalculus.ZX.is_hadamard(zxg, 2, 15) && ZXCalculus.ZX.is_hadamard(zxg, 1, 16)
+@test !isnothing(zxg)
diff --git a/test/runtests.jl b/test/runtests.jl
index 13f992f..899ccaf 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -1,4 +1,15 @@
using ZXCalculus, Documenter, Test
+using Vega
+using DataFrames
+
+
+@testset "plots.jl" begin
+ include("plots.jl")
+end
+
+@testset "equality.jl" begin
+ include("equality.jl")
+end
@testset "abstract_zx_diagram.jl" begin
include("abstract_zx_diagram.jl")
@@ -24,9 +35,9 @@ end
include("phase_teleportation.jl")
end
-# @testset "ir.jl" begin
-# include("ir.jl")
-# end
+@testset "ir.jl" begin
+ include("ir.jl")
+end
@testset "scalar.jl" begin
include("scalar.jl")
diff --git a/test/zx_diagram.jl b/test/zx_diagram.jl
index 370442f..4f84884 100644
--- a/test/zx_diagram.jl
+++ b/test/zx_diagram.jl
@@ -7,11 +7,13 @@ v_t = [SpiderType.X, SpiderType.Z, SpiderType.X]
zxd = ZXDiagram(g, v_t, ps)
zxd2 = ZXDiagram(g, Dict(zip(1:3, v_t)), Dict(zip(1:3, ps)))
@test zxd.mg == zxd2.mg && zxd.st == zxd2.st && zxd.ps == zxd2.ps
+@test !isnothing(zxd)
zxd2 = copy(zxd)
@test zxd.st == zxd2.st && zxd.ps == zxd2.ps
@test ZX.spider_type(zxd, 1) == SpiderType.X
@test nv(zxd) == 3 && ne(zxd) == 2
+@test !isnothing(zxd2)
@test rem_edge!(zxd, 2, 3)
@test outneighbors(zxd, 2) == inneighbors(zxd, 2)
@@ -24,7 +26,11 @@ zxd3 = ZXDiagram(3)
ZX.insert_spider!(zxd3, 1, 2, SpiderType.H)
pushfirst_gate!(zxd3, Val{:SWAP}(), [1, 2])
push_gate!(zxd3, Val{:SWAP}(), [2, 3])
+
+@test ZX.nout(zxd3) == 3
+@test ZX.nout(zxd3) == 3
@test ZX.qubit_loc(zxd3, 1) == ZX.qubit_loc(zxd3, 2)
+@test !isnothing(zxd3)
@testset "float to rational" begin
@test ZX.continued_fraction(2.41, 10) === 241 // 100
@@ -42,6 +48,7 @@ push_gate!(zxd3, Val{:SWAP}(), [2, 3])
@test_throws MethodError push_gate!(zxd, Val(:Z), 3, sqrt(2); autoconvert = false)
@test ZX.safe_convert(Rational{Int64}, 1.2) == 6 // 5 &&
ZX.safe_convert(Rational{Int64}, 1 // 2) == 1 // 2
+ @test !isnothing(zxd)
end
zxd4 = ZXDiagram(2)
@@ -52,4 +59,5 @@ pushfirst_gate!(zxd4, Val(:X), 1)
pushfirst_gate!(zxd4, Val(:H), 1)
pushfirst_gate!(zxd4, Val(:CNOT), 2, 1)
pushfirst_gate!(zxd4, Val(:CZ), 1, 2)
+@test !isnothing(zxd4)
@test indegree(zxd4, 5) == outdegree(zxd4, 5) == degree(zxd4, 5)
diff --git a/test/zx_graph.jl b/test/zx_graph.jl
index a27f8eb..e909b30 100644
--- a/test/zx_graph.jl
+++ b/test/zx_graph.jl
@@ -7,10 +7,11 @@ add_edge!(g, 2, 4)
add_edge!(g, 3, 4)
add_edge!(g, 3, 5)
add_edge!(g, 4, 6)
-ps = [0//1 for i = 1:6]
+ps = [0 // 1 for i = 1:6]
v_t = [SpiderType.In, SpiderType.In, SpiderType.X, SpiderType.Z, SpiderType.Out, SpiderType.Out]
zxd = ZXDiagram(g, v_t, ps)
zxg1 = ZXGraph(zxd)
+@test !isnothing(zxg1)
@test outneighbors(zxg1, 1) == inneighbors(zxg1, 1)
@test !ZX.is_hadamard(zxg1, 2, 4) && !ZX.is_hadamard(zxg1, 4, 6)
@test add_edge!(zxg1, 1, 1)
@@ -21,16 +22,20 @@ replace!(Rule{:b}(), zxd)
zxg2 = ZXGraph(zxd)
@test !ZX.is_hadamard(zxg2, 5, 8) && !ZX.is_hadamard(zxg2, 1, 7)
-zxd = ZXDiagram(2)
-push_gate!(zxd, Val(:H), 1)
-push_gate!(zxd, Val(:CNOT), 2, 1)
-zxg = ZXGraph(zxd)
-zxg3 = ZXGraph(ZXDiagram(3))
-ZX.add_global_phase!(zxg3, ZXCalculus.Utils.Phase(1//4))
-ZX.add_power!(zxg3, 3)
-@test ZX.scalar(zxg3) == Scalar(3, 1//4)
-@test degree(zxg3, 1) == indegree(zxg3, 1) == outdegree(zxg3, 1)
-@test ZX.qubit_loc(zxg3, 1) == ZX.qubit_loc(zxg3, 2)
-@test ZX.column_loc(zxg3, 1) == 1//1
-@test ZX.column_loc(zxg3, 2) == 3//1
+@testset "push gates into Diagram then plot ZXGraph" begin
+ zxd = ZXDiagram(2)
+ push_gate!(zxd, Val(:H), 1)
+ push_gate!(zxd, Val(:CNOT), 2, 1)
+ zxg = ZXGraph(zxd)
+ @test !isnothing(zxg)
+
+ zxg3 = ZXGraph(ZXDiagram(3))
+ ZX.add_global_phase!(zxg3, ZXCalculus.Utils.Phase(1 // 4))
+ ZX.add_power!(zxg3, 3)
+ @test ZX.scalar(zxg3) == Scalar(3, 1 // 4)
+ @test degree(zxg3, 1) == indegree(zxg3, 1) == outdegree(zxg3, 1)
+ @test ZX.qubit_loc(zxg3, 1) == ZX.qubit_loc(zxg3, 2)
+ @test ZX.column_loc(zxg3, 1) == 1 // 1
+ @test ZX.column_loc(zxg3, 2) == 3 // 1
+end
diff --git a/test/zxw_diagram.jl b/test/zxw_diagram.jl
index 03807ef..c960a78 100644
--- a/test/zxw_diagram.jl
+++ b/test/zxw_diagram.jl
@@ -6,9 +6,9 @@ using ZXCalculus: ZXW
@testset "ZXWSpiderType" begin
spider_vec =
- [Z(Parameter(Val(:PiUnit), 3)) Z(Parameter(Val(:Factor), exp(im * 1.5 * π))) X(
+ [Z(Parameter(Val(:PiUnit), 3)) Z(Parameter(Val(:Factor), exp(im * 1.5 * π))) ZXW.X(
Parameter(Val(:PiUnit), 3),
- ) X(Parameter(Val(:Factor), exp(im * 0.5 * π))) W H D Input(10) Output(2)]
+ ) ZXW.X(Parameter(Val(:Factor), exp(im * 0.5 * π))) W ZXW.H D Input(10) Output(2)]
@test spider_vec[1].p == Parameter(Val(:PiUnit), 3)
@test spider_vec[2].p == Parameter(Val(:Factor), exp(im * 1.5 * π))