{ "cells": [ { "cell_type": "markdown", "id": "equivalence-0", "metadata": {}, "source": [ "# Are two circuits the same?\n", "\n", "`equivalent` says whether two programs apply the same gates up to a global phase, and how it decided: by their stabilizer tableaus (Clifford circuits, at any width), on every basis state (up to 8 qubits), by a chain of checked rewrites, or on random product states (evidence, not proof)." ] }, { "cell_type": "code", "execution_count": 1, "id": "equivalence-1", "metadata": { "execution": { "iopub.execute_input": "2026-11-11T12:23:54.515997Z", "iopub.status.busy": "2026-11-11T12:23:54.515923Z", "iopub.status.idle": "2026-11-11T12:23:54.520848Z", "shell.execute_reply": "2026-11-11T12:23:54.520519Z" } }, "outputs": [], "source": [ "import wai_quantum as wq" ] }, { "cell_type": "code", "execution_count": 2, "id": "equivalence-2", "metadata": { "execution": { "iopub.execute_input": "2026-11-11T12:23:54.521714Z", "iopub.status.busy": "2026-11-11T12:23:54.521646Z", "iopub.status.idle": "2026-11-11T12:23:54.524167Z", "shell.execute_reply": "2026-11-11T12:23:54.523909Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "two Hadamards and nothing equivalent by tableau both are Clifford circuits with the same tableau: the same unitary up to a global phase, at any number of qubits\n", "T twice and S equivalent by exact every one of the 2 basis states gives the same output up to one global phase\n", "X and Z different by tableau both are Clifford circuits, and their tableaus differ\n", "a CX, and H CZ H equivalent by tableau both are Clifford circuits with the same tableau: the same unitary up to a global phase, at any number of qubits\n", "different widths different by shape one has 1 qubits and the other 2\n" ] } ], "source": [ "pairs = {\n", " \"two Hadamards and nothing\": (\"qubit[1] q; h q[0]; h q[0];\", \"qubit[1] q;\"),\n", " \"T twice and S\": (\"qubit[1] q; t q[0]; t q[0];\", \"qubit[1] q; s q[0];\"),\n", " \"X and Z\": (\"qubit[1] q; x q[0];\", \"qubit[1] q; z q[0];\"),\n", " \"a CX, and H CZ H\": (\n", " \"qubit[2] q; cx q[0], q[1];\",\n", " \"qubit[2] q; h q[1]; cz q[0], q[1]; h q[1];\",\n", " ),\n", " \"different widths\": (\"qubit[1] q; x q[0];\", \"qubit[2] q; x q[0];\"),\n", "}\n", "for name, (a, b) in pairs.items():\n", " v = wq.equivalent(\"OPENQASM 3.0; \" + a, \"OPENQASM 3.0; \" + b)\n", " print(f\"{name:<26} {v['verdict']:<11} by {v['how']:<8} {v['why']}\")" ] }, { "cell_type": "markdown", "id": "equivalence-3", "metadata": {}, "source": [ "## Improve a design, proved equal\n", "\n", "`improve` makes the critique's fixes and offers each variant only after the engine has checked it equivalent to the program." ] }, { "cell_type": "code", "execution_count": 3, "id": "equivalence-4", "metadata": { "execution": { "iopub.execute_input": "2026-11-11T12:23:54.524950Z", "iopub.status.busy": "2026-11-11T12:23:54.524890Z", "iopub.status.idle": "2026-11-11T12:23:54.530006Z", "shell.execute_reply": "2026-11-11T12:23:54.529545Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "changes: ['h on qubit 0 twice in a row (lines 3 and 4): together they do nothing', 'rz on qubit 1 twice in a row (lines 5 and 6): one rz with the angles added']\n", "gates 5 -> 2 | every one of the 4 basis states gives the same output up to one global phase\n", "OPENQASM 3.0;\n", "qubit[2] q;\n", "rz(0.25 + 0.5) q[1];\n", "cx q[0], q[1];\n", "\n" ] } ], "source": [ "src = '''OPENQASM 3.0;\n", "qubit[2] q;\n", "h q[0];\n", "h q[0];\n", "rz(0.25) q[1];\n", "rz(0.5) q[1];\n", "cx q[0], q[1];\n", "'''\n", "v = wq.improve(src)\n", "best = v[\"candidates\"][0]\n", "print(\"changes:\", best[\"changes\"])\n", "print(\"gates\", v[\"base\"][\"gates\"], \"->\", best[\"measures\"][\"gates\"], \"|\", best[\"equivalence\"][\"why\"])\n", "print(best[\"qasm\"])" ] }, { "cell_type": "code", "execution_count": 4, "id": "equivalence-5", "metadata": { "execution": { "iopub.execute_input": "2026-11-11T12:23:54.530871Z", "iopub.status.busy": "2026-11-11T12:23:54.530783Z", "iopub.status.idle": "2026-11-11T12:23:54.583284Z", "shell.execute_reply": "2026-11-11T12:23:54.582841Z" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "a593a276d8444db48c18b8c8cf80e6ef", "version_major": 2, "version_minor": 1 }, "image/svg+xml": [ "q0q1H on q0HRz(0.25) on q1Rz(0.25)H on q0HRz(0.5) on q1Rz(0.5)● on q0, ⊕ on q1M0 on q00M1 on q11" ], "text/html": [ "
q0q1H on q0HRz(0.25) on q1Rz(0.25)H on q0HRz(0.5) on q1Rz(0.5)● on q0, ⊕ on q1M0 on q00M1 on q11
" ], "text/plain": [ "Circuit(2 qubits, 7 operations in 4 columns)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "wq.Circuit(src)" ] }, { "cell_type": "code", "execution_count": 5, "id": "equivalence-6", "metadata": { "execution": { "iopub.execute_input": "2026-11-11T12:23:54.584337Z", "iopub.status.busy": "2026-11-11T12:23:54.584255Z", "iopub.status.idle": "2026-11-11T12:23:54.587174Z", "shell.execute_reply": "2026-11-11T12:23:54.586867Z" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "d7a9bc9b298d4f4fb27ac436a7a21d00", "version_major": 2, "version_minor": 1 }, "image/svg+xml": [ "q0q1Rz(0.75) on q1Rz(0.75)● on q0, ⊕ on q1M0 on q00M1 on q11" ], "text/html": [ "
q0q1Rz(0.75) on q1Rz(0.75)● on q0, ⊕ on q1M0 on q00M1 on q11
" ], "text/plain": [ "Circuit(2 qubits, 4 operations in 3 columns)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "wq.Circuit(best[\"qasm\"])" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.15" } }, "nbformat": 4, "nbformat_minor": 5 }