diff --git a/pyzx/gflow.py b/pyzx/gflow.py index 98d51910..a81b0dc5 100644 --- a/pyzx/gflow.py +++ b/pyzx/gflow.py @@ -16,11 +16,9 @@ from typing import Dict, Set, Tuple, Optional -from networkx import neighbors - from .extract import bi_adj from .linalg import Mat2 -from .graph.base import BaseGraph, VertexType, VT, ET +from .graph.base import BaseGraph, VT, ET from .utils import vertex_is_zx @@ -99,7 +97,7 @@ def gflow( k: int = 1 while True: - correct = set() + correct: Set[VT] = set() processed_prime = [ v for v in (processed | paulis).difference(pattern_inputs) @@ -121,7 +119,7 @@ def gflow( m = bi_adj(g, processed_prime, clean) for index, u in enumerate(clean): - if not focus or (u not in processed and any(w in processed_prime for w in g.neighbors(v))): + if not focus or (u not in processed and any(w in processed_prime for w in g.neighbors(u))): vu = zerovec.copy() vu.data[index][0] = 1 x = m.solve(vu) diff --git a/pyzx/pauliwebs.py b/pyzx/pauliwebs.py index 0a63bd2c..af8cde9b 100644 --- a/pyzx/pauliwebs.py +++ b/pyzx/pauliwebs.py @@ -17,39 +17,58 @@ from .circuit import Circuit from .utils import EdgeType, VertexType from .simplify import gadgetize, to_rg -from .graph.base import BaseGraph +from .graph.base import BaseGraph, VT, ET -def preprocess(g: BaseGraph): +def preprocess(g: BaseGraph[VT,ET]): gadgetize(g) - to_rg(g) # TODO: i/o should stay Z - in_circ = Circuit() - out_circ = Circuit() + to_rg(g) + + in_circ = Circuit(len(g.inputs())) for j,i in enumerate(g.inputs()): e = g.incident_edges(i)[0] - v = g.neighbors(i)[0] + v = next(iter(g.neighbors(i))) p = g.phase(v) + ty = g.type(v) + + # remove local cliffords from the inputs if g.edge_type(e) == EdgeType.HADAMARD: in_circ.add_gate('H', j) g.set_edge_type(e, EdgeType.SIMPLE) if p != 0: g.set_phase(v, 0) - in_circ.add_gate("ZPhase", j, phase=p) + in_circ.add_gate("ZPhase" if ty == VertexType.Z else "XPhase", j, phase=p) + out_circ = Circuit(len(g.outputs())) for j,o in enumerate(g.outputs()): - r = g.get_row(o) - g.set_row(o, r + 1) + r = g.row(o) + g.set_row(o, r + 2) e = g.incident_edges(o)[0] - v = g.neighbors(o)[0] + v = next(iter(g.neighbors(o))) p = g.phase(v) + ty = g.type(v) + + # remove local cliffords from the outputs if p != 0: g.set_phase(v, 0) - out_circ.add_gate("ZPhase", j, phase=p) + out_circ.add_gate("ZPhase" if ty == VertexType.Z else "XPhase", j, phase=p) if g.edge_type(e) == EdgeType.HADAMARD: out_circ.add_gate('H', j) g.remove_edge(e) + + # introduce ID spiders at the outputs for computing pauli webs + if ty == VertexType.X: + v1 = g.add_vertex(VertexType.Z, qubit=g.qubit(o), row=r) + g.add_edge((v,v1), EdgeType.SIMPLE) + else: + v1 = v + g.set_row(v1, r) + + v2 = g.add_vertex(VertexType.X, qubit=g.qubit(o), row=r+1) + - v1 = g.add_vertex(VertexType.Z, qubit=g.qubit(o), row=r) - g.add_edge((v,v1), EdgeType.HADAMARD) - g.add_edge((v1,o), EdgeType.HADAMARD) \ No newline at end of file + g.add_edge((v1,v2), EdgeType.SIMPLE) + g.add_edge((v2,o), EdgeType.SIMPLE) + + return (in_circ, out_circ) \ No newline at end of file diff --git a/pyzx/simplify.py b/pyzx/simplify.py index 77f3c5ba..aa60db94 100644 --- a/pyzx/simplify.py +++ b/pyzx/simplify.py @@ -85,8 +85,8 @@ def simp( Returns: Number of iterations of ``rewrite`` that had to be applied before no more matches were found.""" + auto_simp_value = g.get_auto_simplify() if auto_simplify_parallel_edges: - auto_simp_value = g.get_auto_simplify() g.set_auto_simplify(True) i = 0 new_matches = True @@ -361,7 +361,7 @@ def to_rg(g: BaseGraph[VT,ET], select:Optional[Callable[[VT],bool]]=None, change for e in g.incident_edges(v): g.set_edge_type(e, toggle_edge(g.edge_type(e))) -def gadgetize(g: BaseGraph): +def gadgetize(g: BaseGraph[VT,ET]): """Convert every non-Clifford phase to a phase gadget""" for v in list(g.vertices()): p = g.phase(v) diff --git a/scratchpads/ak.ipynb b/scratchpads/ak.ipynb index 259ff3dd..2339d0e5 100644 --- a/scratchpads/ak.ipynb +++ b/scratchpads/ak.ipynb @@ -17,6 +17,7 @@ "from fractions import Fraction\n", "import random\n", "from pyzx.gflow import gflow\n", + "from pyzx.pauliwebs import preprocess\n", "from pyzx.utils import vertex_is_zx\n", "from pyzx.graph.base import BaseGraph\n", "from pyzx import VertexType, EdgeType\n", @@ -83,7 +84,7 @@ { "data": { "text/html": [ - "
\n", + "\n", "" @@ -452,7 +453,7 @@ { "data": { "text/html": [ - "\n", + "\n", "" ], @@ -802,7 +803,8 @@ "gadgetize(g1)\n", "g1.normalize()\n", "g1 = g1.copy()\n", - "zx.to_rg(g1)\n", + "preprocess(g1)\n", + "#zx.to_rg(g1)\n", "# g2 = g1.copy()\n", "# for e in list(g2.edges()): zx.hrules.had_edge_to_hbox(g2, e)\n", "zx.draw(g1, labels=True)" @@ -810,76 +812,53 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "17 <- {16} + {17, 3}\n", - "19 <- {18} + {19, 4}\n", - "15 <- {3, 4, 6, 7, 17, 19} + {5, 8, 9, 10, 15, 16, 18}\n", - "21 <- {19, 4, 20, 6} + {3, 5, 9, 18, 21}\n", - "25 <- {24, 19, 4} + {9, 18, 25}\n", - "23 <- {4, 5, 19, 21, 22} + {3, 6, 8, 9, 18, 20, 23}\n", - "27 <- {3, 5, 6, 17, 21, 26} + {8, 9, 10, 16, 20, 27}\n" + "15 <- {11, 28, 7} + {8, 10, 15, 29, 30}\n", + "23 <- {11, 22} + {8, 30, 23}\n", + "25 <- {24, 31} + {32, 9, 25}\n", + "27 <- {26, 28} + {10, 27, 29}\n", + "17 <- {10, 11, 15, 16, 27, 29, 31} + {32, 3, 7, 8, 9, 17, 26, 28, 30}\n", + "21 <- {8, 10, 11, 20, 23, 27, 28, 29, 30, 31} + {32, 3, 5, 7, 9, 21, 22, 26}\n", + "19 <- {32, 5, 8, 9, 11, 15, 18, 21, 23, 25, 30, 31} + {3, 4, 6, 7, 10, 19, 20, 22, 24}\n" ] } ], "source": [ - "o, p = gflow(g1, focus=True, reverse=True, pauli=True)\n", - "vs = [v for v in g1.vertices() if not is_clifford(g1.phase(v))]\n", - "list.sort(vs, key=lambda v: o[v], reverse=True)\n", - "for v in vs: print(f\"{v} <- {p[v]} + {extend(g1, p[v]).difference(p[v])}\")" + "gf = gflow(g1, focus=True, pauli=True)\n", + "if gf:\n", + " o,p = gf\n", + " vs = [v for v in g1.vertices() if not is_clifford(g1.phase(v))]\n", + " list.sort(vs, key=lambda v: o[v], reverse=True)\n", + " for v in vs: print(f\"{v} <- {p[v]} + {extend(g1, p[v]).difference(p[v])}\")" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "{9: 4, 10: 4, 11: 4, 8: 3, 15: 3, 23: 3, 25: 3, 27: 3, 3: 2, 5: 2, 7: 2, 17: 2, 21: 2, 22: 2, 24: 2, 26: 2, 4: 1, 6: 1, 16: 1, 19: 1, 20: 1, 18: 0}\n" + "{32: 4, 29: 4, 30: 4, 8: 3, 9: 3, 10: 3, 11: 3, 15: 3, 23: 3, 25: 3, 27: 3, 28: 3, 31: 3, 3: 2, 5: 2, 7: 2, 17: 2, 21: 2, 22: 2, 24: 2, 26: 2, 4: 1, 6: 1, 16: 1, 19: 1, 20: 1, 18: 0}\n", + "{11: {3, 4, 5, 8, 15, 17, 19, 21, 23}, 31: {3, 4, 5, 9, 17, 19, 21, 25}, 28: {5, 10, 15, 21, 27}, 30: {4, 5, 11, 19, 21}, 7: {15}, 22: {23}, 24: {25}, 26: {27}, 29: {3, 5, 6, 17, 21, 28}, 32: {19, 4, 31}, 10: {3, 5, 6, 17, 21}, 15: {3, 4, 6, 7, 17, 19}, 27: {3, 5, 6, 17, 21, 26}, 8: {21, 19, 4, 5}, 23: {4, 5, 19, 21, 22}, 16: {17}, 20: {21}, 25: {24, 19, 4}, 5: {19, 4, 6}, 9: {19, 4}, 21: {19, 4, 20, 6}, 17: {16}, 18: {19}, 19: {18}}\n" ] - }, - { - "data": { - "text/plain": [ - "{11: {3, 4, 5, 8, 15, 17, 19, 21, 23},\n", - " 7: {15},\n", - " 22: {23},\n", - " 24: {25},\n", - " 26: {27},\n", - " 27: {3, 5, 6, 17, 21, 26},\n", - " 10: {3, 5, 6, 17, 21},\n", - " 15: {3, 4, 6, 7, 17, 19},\n", - " 8: {4, 5, 19, 21},\n", - " 23: {4, 5, 19, 21, 22},\n", - " 16: {17},\n", - " 20: {21},\n", - " 25: {4, 19, 24},\n", - " 5: {4, 6, 19},\n", - " 9: {4, 19},\n", - " 21: {4, 6, 19, 20},\n", - " 17: {16},\n", - " 18: {19},\n", - " 19: {18}}" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ - "o,p = gflow(g1, focus=True, reverse=False, pauli=True)\n", - "pt = transpose(p)\n", - "print(o)\n", - "pt" + "gf = gflow(g1, focus=True, reverse=False, pauli=True)\n", + "if gf:\n", + " o,p = gf\n", + " pt = transpose(p)\n", + " print(o)\n", + " print(pt)" ] }, { @@ -892,7 +871,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "venv", "language": "python", "name": "python3" }, @@ -906,7 +885,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.1" + "version": "3.12.3" } }, "nbformat": 4,