{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Approximate multi-controlled X gate\n", "\n", "**Download Notebook** - {nb-download}`cnx_approx.ipynb`\n", "\n", "## Empirical Validation\n", "\n", "The $C^nX$ gate applies an X gate to a target qubit only when all n control qubits are in the $|1\\rangle$ state.\n", "\n", "Exact implementations require $O(n)$ $T$ gates, whereas the approximate $C^nX$ gate requires only $O(log(1/\\epsilon))$ $T$ gates for an implementation within an error $\\epsilon$ .\n", "\n", "This algorithm for the approximate multi-controlled X gate originates from the paper [arXiv:2510.07223](https://arxiv.org/abs/2510.07223) \"Multi-qubit Toffoli with exponentially fewer T gates\"." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from math import ceil, log2\n", "from guppylang import guppy\n", "from guppylang.std.builtins import array, comptime, output\n", "from guppylang.std.quantum import qubit, x, measure, discard_array\n", "from guppylang.std.qsystem.random import RNG\n", "from guppylang.std.qsystem.utils import get_current_shot\n", "from guppyalgos.primitives.gate_decompositions.cnx.cnx_approx import cnx_approx\n", "from guppyalgos.utils import qarray" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We define the following parameters:\n", "\n", "- **N_CTRL**: Number of control qubits\n", "- **EPSILON**: Error bound\n", "- **SEED**: Seed for random number generation\n", "- **N_SHOTS**: Number of simulation runs to estimate error rate" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of controls: 10\n", "Target epsilon: 0.1\n", "Number of shots: 1000\n" ] } ], "source": [ "N_CTRL = 10\n", "EPSILON = 0.1\n", "SEED = 1\n", "N_SHOTS = 1000\n", "\n", "# Generate the approximate CnX gate with and error EPSILON and N_CTRL control qubits\n", "cnx_approx_fn = cnx_approx(N_CTRL, EPSILON)\n", "\n", "# Number of controls for the exact CnX gate\n", "k = min(ceil(log2(1 / EPSILON)) + 2, N_CTRL)\n", "\n", "print(f\"Number of controls: {N_CTRL}\")\n", "print(f\"Target epsilon: {EPSILON}\")\n", "print(f\"Number of shots: {N_SHOTS}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To verify the approximate $C^nX$ gate implementation, we set up a test where some control qubits are initialized in $\\lvert 0 \\rangle$.\n", "Since not all controls are $|1\\rangle$, the target should remain $|0\\rangle$ after applying $C^nX$. We expect the error rate to be at most $\\epsilon$." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@guppy\n", "def test_cnx_approx() -> None:\n", " # Initialize controls\n", " controls = qarray(N_CTRL)\n", " for i in range(comptime(N_CTRL - 1)):\n", " x(controls[i])\n", "\n", " # Initialize target to |0⟩\n", " target = qubit()\n", "\n", " # Create RNG with shot-dependent seed\n", " rng = RNG(SEED + get_current_shot())\n", "\n", " # Apply approximate cnx gate\n", " cnx_approx_fn(controls, target, rng)\n", "\n", " # Measure target\n", " target_result = measure(target).read()\n", " output(\"target_result\", target_result)\n", "\n", " # Cleanup\n", " rng.discard()\n", " discard_array(controls)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We run the circuit N_SHOTS times to statistically estimate the error rate of the approximation.\n", "A shot is successful if the target is measured as $|0\\rangle$." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "=== Results ===\n", "Epsilon: 0.1\n", "Successes: 994/1000\n", "Success rate: 0.9940\n", "Error rate: 0.0060\n" ] } ], "source": [ "n_ancillas = (k - 2) // 2 + (k - 2) % 2 if k > 2 else 0\n", "n_qubits = N_CTRL + 1 + n_ancillas\n", "\n", "results = test_cnx_approx.emulator(n_qubits=n_qubits).with_shots(N_SHOTS).run()\n", "\n", "shots_data = results.collated_shots()\n", "successes = sum(1 for shot in shots_data if not shot[\"target_result\"][0])\n", "success_rate = successes / N_SHOTS\n", "error_rate = 1 - success_rate\n", "\n", "print(f\"\\n=== Results ===\")\n", "print(f\"Epsilon: {EPSILON}\")\n", "print(f\"Successes: {successes}/{N_SHOTS}\")\n", "print(f\"Success rate: {success_rate:.4f}\")\n", "print(f\"Error rate: {error_rate:.4f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Resource Estimation\n", "\n", "The algorithm guarantees that the approximate $C^nX$ is implemented to within error $\\varepsilon$ in the diamond distance.\n", "To do this approximation, the algorithm requires an exact $C^kX$ gate where $k$ is given by:\n", "$$k = \\lceil \\log_2(1/\\varepsilon) \\rceil + 2.$$\n", "\n", "The key advantage is that $k$ grows logarithmically with $1/\\varepsilon$ and is independent of $n$, the number of controls in the $C^nX$ gate. This means the $T$-count is $O(\\log(1/\\varepsilon))$ instead of $O(n)$.\n", "\n", "The graph below shows the $k$ value with respect to $\\varepsilon$.\n", "For example, for $\\varepsilon = 0.01$, we get $k = 9$. This means that a $C^nX$ gate ($n$ controls) can be approximated with the same number of $T$ gates as implementing an exact $C^{9}X$ gate (9 controls).\n" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA90AAAJOCAYAAACqS2TfAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjUsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvWftoOwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAUX5JREFUeJzt3Xt4VOW5/vF7ksnMADlggo1GAgbk0CJHBayKBI1FBAQ821YD1BOwpRYQdKuEoJGiwqZVi6cKurenWjaRtm6rttggaAEJ7m6qAjF4QoIKJBCYCUnW7w9/TI1JyMxkvTOzku/nurwka973XU+G9czinjUHl2VZlgAAAAAAgO0SYl0AAAAAAABtFaEbAAAAAABDCN0AAAAAABhC6AYAAAAAwBBCNwAAAAAAhhC6AQAAAAAwhNANAAAAAIAhhG4AAAAAAAwhdAMAAAAAYAihGwAAAAAAQwjdAAAAAAAYQugGgDj25ptvyuVyacGCBbEuxRZHjx7VggUL1KtXL3m9XrlcLhUXF8e6rLi0a9cuuVwuTZ48OdalxFQ83A/h1sBxDgD4NkI3gHbj2D+cXS6XRo8e3eSYd955J+b/wG/LlixZosLCQmVlZWnOnDkqKChQ3759Y11WSNraEyAwx8nHOQDAfu5YFwAAsfDaa6/pr3/9q84///xYl9Ku/PGPf1RycrJef/11eTyeWJcDBzjllFP0/vvvKy0tLdalhIzjHADwbVzpBtDunHrqqUpISNC8efNkWVasy2lXdu/erYyMDIIIQpaUlKS+ffvq5JNPjnUpIeM4BwB8G6EbQLvTp08fXXvttdq8ebN+97vftTh+5cqVcrlcWrlyZaPbmnrJ8be3bdiwQaNGjVJKSopOPPFETZ8+XUeOHJEk/elPf9IPf/hDderUSZmZmZo7d65qa2ubreOtt95Sbm6uUlJS1LlzZ1122WXauXNns+NLSko0fvx4denSRV6vV7169dJdd92lw4cPN/s7bNiwQT/60Y/UuXNnuVyuFu8bSVqxYoWGDx+u5ORkJScna/jw4Y3uqwULFsjlcqm8vFwff/xx8GX+p556akj7KCkp0cSJE5WZmSmv16vs7GxdeumleuuttyKq57u/9+bNm3XhhRcqJSVFaWlpmjRpknbt2tWg/lGjRkmSCgsLg/W7XK7guFDvx1Dra86qVas0cuRIfe9735PP51NWVpby8vK0atWqFueGWmOox44k1dXVafHixTrttNPk8/l02mmnadGiRfroo4+afKtGuP3U3Pupo/m71NfXH/+O/f9CPc4jOUbD6c2amho99NBDGj16tLKzs+X1evW9731Pl156qUpLS4+7n5Z6IVR2Pf7Y3VetfbwrLS1Vfn6+cnJy5PP5lJ6eriFDhmj+/Plh30cA2g9CN4B2aeHChfJ6vbrrrrt09OhRI/v4+9//rgsuuEBpaWm66aab1K1bNy1fvlw33HCDXnzxRV1++eXq3r27brrpJnXu3FkPPPCA7rvvvibXeuedd4Jr3XLLLRo5cqRWr16ts88+Wx999FGj8cuXL1dubq7Wr1+vsWPHaubMmeratauKiop04YUXqqamptGcDRs2KDc3Vy6XSzfeeKOuuuqqFn/HmTNnaurUqfr888/1s5/9TD/72c/0+eefa8qUKfr5z38eHJebm6uCggKlpaUpLS1NBQUFKigo0K233triPn71q18pNzdXr7/+ui688ELNnj1b559/vt577z39/ve/j6ieb9u0aZPOO+88eTwe3XTTTTrzzDNVXFysvLw8+f3+YP35+fmSpJEjRwbrLygoUOfOnUO+HyOp79uWL1+uyy+/XDt27NCkSZM0a9YsXXTRRdqzZ49Wr17d4vxQagz32Lnxxht1++23q76+XjNmzNDo0aO1dOnSkH4fO8TT7xLKcR7JMRBub+7bt0+33nqrAoGALr74Yv3iF79Qbm6uXnnlFZ199tnatGlTk/NC6YVQmHj8sbuvInm8Ky4u1rBhw7Rq1SqdffbZmjVrlq6++mp16NBBn3zyScj3D4B2yAKAdqK8vNySZI0ePdqyLMuaM2eOJcl66KGHgmPefvttS5KVn58f3LZixQpLkrVixYpGa65du9aSZBUUFDTaJskqLi4Obq+pqbEGDBhguVwuq0uXLtbGjRuDt1VVVVnf+973rPT0dKumpqbJtR599NEG+3700UctSda4ceMabN+2bZvldrutgQMHWl999VWD2xYtWmRJsh588MEm9/HUU08d5x5s6G9/+5slyfr+979vHThwILh93759Vu/evS1JVklJSYM53bt3t7p37x7yPrZu3WolJCRYWVlZVnl5eYPb6uvrrc8//zzier79e7/wwgsN1r722mstSdbzzz/faPy3/66/raX7Mdz6jh2v3z4WhwwZYnk8HquioqLR+t/9u46kxkiPnYEDB1qHDh0Kbv/ss8+sLl26NKrfssLvp6buh3j5XZrT3HHemmM0nN70+/3WZ5991mj7//3f/1nJyclWXl5eg+3h9sLx2P34Y3dfRXqfWpZlff/737dSUlKs7du3hzUPALjSDaDd+vd//3d17txZ99xzjw4dOmT7+qNGjdKECROCPyclJenyyy+XZVkaP368hg4dGrwtJSVF48aN0759+/TZZ581Wqt379664YYbGmy74YYb1KtXL/3pT3/Sl19+Gdz+2GOPqba2Vg899JAyMjIazJk7d65OPPFEPf/88432MWTIEE2ZMiXk3+/pp5+W9M1Lar/9IVcnnHCCCgoKJCmsl0035bHHHlN9fb3uvffeRi/RdblcysrKanU95513XqOrXFOnTpWkZq8IHk9z96Nd91dSUpKSkpIabf/u33UkNYZ77DzzzDOSpPnz56tTp07B7aecckrUrnQ76XeJ9BgItze9Xq9OOeWURtv79eunUaNGqaSkpMlX+NjRC6Yef+zuq3DvU0n6+uuvdfLJJ6tnz55hzQMAPr0cQLt1wgkn6Pbbb9ftt9+uBx980Pavgho0aFCjbcc+DOp4t+3evVs5OTkNbjvnnHOUkNDwedKEhASdc8452rFjh9577z3l5eVJ+ual6JL05z//WX/5y18a7ScpKUkffPBBo+3ffhIgFMfeG5qbm9votmPvf966dWtYa37Xxo0bJUk/+tGPjNVzxhlnNNrWtWtXSdKBAwdCrPRfmrsf7bi/rr76as2dO1enn366fvzjH2vUqFE699xzlZqaakuN4R477733niRpxIgRjcY2tc0EJ/0ukR4D4fbmsXXuv/9+vfXWW9qzZ0+jkP3VV181+nA6O3rB1OOP3X0VyX36q1/9StOmTdNZZ52l3NxcdezYUT/+8Y/Vu3fvsNcC0L4QugG0azNnztTDDz+sJUuWaPr06bau3VQQcrvdLd7W1BWozMzMJvdxbHtlZWVw2759+yRJRUVFYdXb3D6aU1VVpYSEBJ144olNruVyuVRVVRXWmt9VWVkpl8sV0idXR1rP8f4u6urqwq65ufvRjvtrzpw5ysjI0PLly7VkyRI9+OCDcrvdGjt2rP7jP/6j0ZM14dYY7rFTWVmphIQEdenSJeR92M1Jv0ukx0C4+9+wYUPw6xB/9KMfqVevXkpOTpbL5VJxcbHee+89BQKBRvPs6AVTjz9291W492ldXZ2+/vprde3aVZs2bQpe+b/66qvDWgdA+8TLywG0ax06dFBhYaEOHTqkwsLCJsccu8Lc1CeLfzvsmlRRUXHc7d9+WeWxfzhXVVXJsqxm//uuUD+999v7qa+vb/DS9mP27t0ry7LCvgL7XZ07d5ZlWfriiy/iop5QNHc/2lGfy+XS1KlTtWnTJn355ZdavXq1Lr30Ur388ssaN25cyMHoeDVKoR87aWlpqq+v11dffdVoreaOWbv7KZa/S7giPQbC7c2ioiIFAgG98cYbWrNmjZYsWaLCwkItWLBAJ510UsT1h8LU44/dfRXufXrzzTfrlltu0ZgxY7R9+3bV1NTIsiz17ds3rHUAtE+EbgDtXn5+vvr166cnnniiya/gOuGEEyRJn3/+eaPbmvr6HRPWr1/f6GuL6uvrtWHDBrlcLg0cODC4ffjw4ZL+9TJPUwYPHizpm6/g+a5j25p6GX04hg0bJkl67bXXYl5PYmKipMiufkv215eRkaGJEyfqxRdf1Pnnn69//vOfx/0KuVCEe+wcO+7WrVvX6LamtknR66do/C7hikbPSFJZWZnS09N17rnnNth++PBhbdmypdXrH0+0Hn+OicZ9unv3bj355JO66qqrdP/996tXr15Nfq4CADSH0A2g3UtMTNR9992no0ePNvm+7jPOOEMul0svvPBCg6/N2bFjh371q19Fpcbt27friSeeaLDtiSee0Pbt2zV27NgGL62cPn263G63brnllia/xubAgQO2hJtjX6FVWFjY4OWblZWVwVcNHBsTqZtvvlmJiYm666679PHHHze4zbIs7d69O2r1pKenS5I+/fTTiObbUd+bb77Z6Crh0aNHgy/p9fl8EdV2TLjHzrXXXivpm6/gq66uDm7//PPPm+2NaPVTNH6XcEWjZySpe/fu2r9/v7Zt2xbcVldXpzlz5jR5RdhO0Xr8OSYa9+nevXslNf++9iNHjrRqfQBtH+/pBgBJl1xyic4991y99dZbjW7LysrSNddco+eee05nnHGGLrroIu3du1erV6/WRRddpFWrVhmvb/To0Zo5c6ZeeeUV9evXT9u2bdMf/vAHdenSpVEgOP300/Wb3/xG06ZNU58+fXTxxRerZ8+eOnjwoD766CP97W9/0+TJ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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "epsilon_values = np.array(sorted([2**(-k) for k in range(1, 15)]))\n", "k_values = np.array([ceil(log2(1 / eps)) + 2 for eps in epsilon_values])\n", "\n", "plt.figure(figsize=(10, 6))\n", "plt.step(epsilon_values, k_values, where='post', linewidth=3)\n", "plt.xscale('log')\n", "plt.xlabel('Error $\\\\varepsilon$', fontsize=13)\n", "plt.ylabel('$k$ controls', fontsize=13)\n", "plt.title('Number of controls required for an error $\\\\varepsilon$\\n', fontsize=14)\n", "plt.grid(True, which='major', alpha=0.6, linewidth=0.8, color=\"black\")\n", "plt.grid(True, which='minor', alpha=0.2, linewidth=0.5, color=\"black\")\n", "plt.tight_layout()\n", "plt.show()" ] } ], "metadata": { "kernelspec": { "display_name": "guppyalgos", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 4 }