diff --git a/pyzx/generate.py b/pyzx/generate.py index 0fbdbbbd..a0b49a34 100644 --- a/pyzx/generate.py +++ b/pyzx/generate.py @@ -24,6 +24,7 @@ "phase_poly", "phase_poly_approximate", "phase_poly_from_gadgets", + "qft", ] import random @@ -706,3 +707,17 @@ def build_random_parity_map(qubits: int, n_cnots: int, circuit=None) -> MatLike: for c in circuit: c.row_add(gate.control, gate.target) return matrix.data + + +def qft(qubits: int) -> Circuit: + """Returns a quantum Fourier transform circuit + + This returns the unoptimised Fourier transform circuit. This is the version with O(n^2) gates + which reverses the order of logical qubits.""" + c = Circuit(qubits) + + for i in range(qubits): + c.add_gate('H', i) + for j in range(i+1, qubits): + c.add_gate('CPhase', j, i, Fraction(1, 2**(j-i+1))) + return c diff --git a/scratchpads/ak2.ipynb b/scratchpads/ak2.ipynb index b69fe4e3..dcb5c0e3 100644 --- a/scratchpads/ak2.ipynb +++ b/scratchpads/ak2.ipynb @@ -7,7 +7,7 @@ "metadata": {}, "outputs": [], "source": [ - "import sys, os; sys.path.append('..')\n", + "import sys, os; sys.path.insert(0, '..')\n", "import random, logging, math\n", "import pyzx as zx\n", "from fractions import Fraction\n", @@ -22,7 +22,7 @@ { "cell_type": "code", "execution_count": 2, - "id": "c5ff702b", + "id": "4f030a0a", "metadata": {}, "outputs": [ { @@ -49,7 +49,7 @@ { "cell_type": "code", "execution_count": 3, - "id": "b1ff2788", + "id": "b19c5271", "metadata": {}, "outputs": [], "source": [ @@ -62,21 +62,21 @@ }, { "cell_type": "code", - "execution_count": 4, - "id": "31afc22d", + "execution_count": 13, + "id": "ccf76e80", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "575\n", + "496\n", "True\n" ] } ], "source": [ - "c = zx.Circuit.load('../circuits/QFT_and_Adders/QFTAdd16_before')\n", + "c = zx.generate.qft(32) #zx.Circuit.load('../circuits/QFT_and_Adders/QFT32_before')\n", "g = c.to_graph()\n", "zx.full_reduce(g)\n", "print(g.num_edges() - g.num_vertices() + g.num_outputs())\n", @@ -85,14 +85,14 @@ }, { "cell_type": "code", - "execution_count": 5, - "id": "7d200432", + "execution_count": 14, + "id": "90d49c61", "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "\n", "" ], @@ -440,45 +442,49 @@ }, { "cell_type": "code", - "execution_count": 6, - "id": "764485e8", + "execution_count": 15, + "id": "cb5cf517", "metadata": {}, "outputs": [], "source": [ - "def squash_reduce(g, err_budget):\n", + "def squash_reduce(g, err_budget, quiet=True):\n", " total_err = 0\n", - " for i in range(50, 1, -1):\n", + " for i in range(50, -1, -1):\n", " zx.full_reduce(g)\n", " th = Fraction(1, 2**i)\n", - " print('T=2^-' + str(i), end=' ')\n", + " if not quiet: print(f'threshold Δθ <= 2^-{i} π')\n", " for v in list(g.vertices()):\n", " p = g.phase(v)\n", - " new_p = Fraction(round(2*p), 2)\n", - " err = abs(float(p)-round(new_p))\n", - " if p.denominator != 1 and err <= th:\n", - " if total_err + err > err_budget:\n", - " zx.full_reduce(g)\n", - " print('exceeded budget, done.')\n", - " return\n", - " else:\n", - " g.set_phase(v, new_p)\n", - " total_err += abs(math.sin(err/2))" + " if p.denominator > 2:\n", + " new_p = Fraction(round(2*p), 2)\n", + " err = abs(float(p)-round(new_p))\n", + " if err <= th:\n", + " if total_err + err > err_budget:\n", + " zx.full_reduce(g)\n", + " if not quiet: print('exceeded error budget, done.')\n", + " return\n", + " else:\n", + " norm_err = 2*(math.sin(err/2)**2)\n", + " if not quiet: print(f' * {p} ~ {new_p} (ε = {norm_err})')\n", + " g.set_phase(v, new_p)\n", + " total_err += norm_err\n", + " zx.full_reduce(g)" ] }, { "cell_type": "code", - "execution_count": 7, - "id": "3284cbfa", + "execution_count": 16, + "id": "783574b6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Circuit QFTAdd16_before on 32 qubits with 1822 gates.\n", - " 1026 is the T-count\n", - " 796 Cliffords among which\n", - " 716 2-qubit gates (716 CNOT, 0 other) and\n", + "Circuit on 32 qubits with 2512 gates.\n", + " 1488 is the T-count\n", + " 1024 Cliffords among which\n", + " 992 2-qubit gates (992 CNOT, 0 other) and\n", " 32 Hadamard gates.\n" ] } @@ -489,7 +495,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 17, "id": "44aad5a9", "metadata": {}, "outputs": [ @@ -497,13 +503,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "T=2^-50 T=2^-49 T=2^-48 T=2^-47 T=2^-46 T=2^-45 T=2^-44 T=2^-43 T=2^-42 T=2^-41 T=2^-40 T=2^-39 T=2^-38 T=2^-37 T=2^-36 T=2^-35 T=2^-34 T=2^-33 T=2^-32 T=2^-31 T=2^-30 T=2^-29 T=2^-28 T=2^-27 T=2^-26 T=2^-25 T=2^-24 T=2^-23 T=2^-22 T=2^-21 T=2^-20 T=2^-19 T=2^-18 T=2^-17 T=2^-16 T=2^-15 T=2^-14 T=2^-13 exceeded budget, done.\n", "extracting circuit...\n", - "Circuit on 32 qubits with 2145 gates.\n", - " 402 is the T-count\n", - " 1743 Cliffords among which\n", - " 967 2-qubit gates (631 CNOT, 336 other) and\n", - " 776 Hadamard gates.\n" + "Circuit on 32 qubits with 2818 gates.\n", + " 558 is the T-count\n", + " 2260 Cliffords among which\n", + " 1174 2-qubit gates (909 CNOT, 265 other) and\n", + " 1086 Hadamard gates.\n" ] } ], @@ -519,749 +524,63 @@ }, { "cell_type": "code", - "execution_count": 9, - "id": "9539aa74", - "metadata": {}, + "execution_count": 19, + "id": "976f071e", + "metadata": { + "scrolled": false + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "T=2^-50 T=2^-49 T=2^-48 T=2^-47 T=2^-46 T=2^-45 T=2^-44 T=2^-43 T=2^-42 T=2^-41 T=2^-40 T=2^-39 T=2^-38 T=2^-37 T=2^-36 T=2^-35 T=2^-34 T=2^-33 T=2^-32 T=2^-31 T=2^-30 T=2^-29 T=2^-28 T=2^-27 T=2^-26 T=2^-25 T=2^-24 T=2^-23 T=2^-22 T=2^-21 T=2^-20 T=2^-19 T=2^-18 T=2^-17 T=2^-16 T=2^-15 T=2^-14 T=2^-13 T=2^-12 T=2^-11 T=2^-10 T=2^-9 T=2^-8 exceeded budget, done.\n", "extracting circuit...\n", - "Circuit on 32 qubits with 1516 gates.\n", - " 270 is the T-count\n", - " 1246 Cliffords among which\n", - " 710 2-qubit gates (424 CNOT, 286 other) and\n", - " 532 Hadamard gates.\n" + "Circuit on 32 qubits with 928 gates.\n", + " 180 is the T-count\n", + " 748 Cliffords among which\n", + " 418 2-qubit gates (110 CNOT, 308 other) and\n", + " 330 Hadamard gates.\n" ] } ], "source": [ "g1 = c.to_graph()\n", - "squash_reduce(g1, err_budget=0.1)\n", + "squash_reduce(g1, err_budget=0.01, quiet=True)\n", "print(\"extracting circuit...\")\n", "c1 = zx.extract_circuit(g1, up_to_perm=True)\n", + "zx.basic_optimization(c1)\n", "#zx.draw(c1)\n", "print(c1.stats())" ] }, { "cell_type": "code", - "execution_count": 24, - "id": "e2482a26", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "290\n", - "388\n", - "114\n" - ] - } - ], - "source": [ - "print(g.num_vertices())\n", - "print(g.num_edges())\n", - "print(g.num_edges() - g.num_vertices() + g.num_outputs())" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "f7edea32", - "metadata": {}, + "execution_count": 20, + "id": "29239690", + "metadata": { + "scrolled": false + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "spider_simp: 30. 19. 12. 3. 3. 1. 6 iterations\n" + "extracting circuit...\n", + "Circuit on 32 qubits with 311 gates.\n", + " 93 is the T-count\n", + " 218 Cliffords among which\n", + " 62 2-qubit gates (0 CNOT, 62 other) and\n", + " 156 Hadamard gates.\n" ] - }, - { - "data": { - "text/plain": [ - "6" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ - "g = c.to_graph()\n", - "zx.to_gh(g)\n", - "zx.spider_simp(g)\n", - "c1 = zx.extract.extract_simple(g)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "a3440181", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - "" - ], - "text/plain": [ - "