{ "cells": [ { "cell_type": "markdown", "id": "165d0391", "metadata": {}, "source": [ "# More features" ] }, { "cell_type": "markdown", "id": "593edd58", "metadata": {}, "source": [ "Zixy collections are suitable for Pauli tableau operations." ] }, { "cell_type": "code", "execution_count": 1, "id": "0ea07aff", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[1, 0, 1, 0],\n", " [0, 1, 1, 1],\n", " [1, 1, 1, 1],\n", " [0, 1, 1, 1]], dtype=uint8)" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from zixy.qubit import Qubits\n", "from zixy.qubit.pauli import Strings, I, X, Y, Z\n", "strings = Strings.from_iterable((\n", " (X, Y, I, I, X, X, Z, Y),\n", " (Y, I, I, X, X, Z, X, Y),\n", " (Y, I, I, X, X, Z, I, Y),\n", " (X, Z, I, Y, Y, I, I, X),\n", "), Qubits.from_count(8))\n", "strings.compatibility_matrix()" ] }, { "cell_type": "markdown", "id": "f2deccdf", "metadata": {}, "source": [ "The `compatibility_matrix` function has efficiently computed the commutivity (`1`) or anti-commutivity (`0`) between each Pauli string in the tableau.\n", "\n", "Notice that the string with index `2` commutes with all other strings. This is the sole member of the list's *centralizer* set.\n", "\n", "We have a function to extract this:" ] }, { "cell_type": "code", "execution_count": 2, "id": "c74e2c8c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Y0 X3 X4 Z5 Y7" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "centralizer, remainder = strings.centralizer_and_remainder()\n", "assert len(centralizer) == 1\n", "assert centralizer[0] == strings[2]\n", "centralizer" ] }, { "cell_type": "markdown", "id": "f7e5197e", "metadata": {}, "source": [ "Now as expected the compatibility matrix of the remainder shows no rows that are all `1`s" ] }, { "cell_type": "code", "execution_count": 3, "id": "38fadc8f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[1, 0, 0],\n", " [0, 1, 1],\n", " [0, 1, 1]], dtype=uint8)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "remainder.compatibility_matrix()" ] }, { "cell_type": "markdown", "id": "1fb3e817", "metadata": {}, "source": [ "Change of basis (conjugation) by a sequence of Clifford gates is supported." ] }, { "cell_type": "code", "execution_count": 4, "id": "468788c5-e94f-4302-ae3d-39ab2ffd6e8c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "+i" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "strings[0].phase_of_mul(strings[1])" ] }, { "cell_type": "code", "execution_count": 5, "id": "7b49a0aa-f4c8-4a53-a6ef-4b9bae958d18", "metadata": {}, "outputs": [ { "ename": "ValueError", "evalue": "Cannot multiply-assign left-hand operand X0 Y1 X4 X5 Z6 Y7 with type by value Y0 X3 X4 Z5 X6 Y7. Result with factor +i is not representable by the left-hand operand type.", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mValueError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[5]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[43mstrings\u001b[49m\u001b[43m[\u001b[49m\u001b[32;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m=\u001b[49m\u001b[43m \u001b[49m\u001b[43mstrings\u001b[49m\u001b[43m[\u001b[49m\u001b[32;43m1\u001b[39;49m\u001b[43m]\u001b[49m\n", "\u001b[36mFile \u001b[39m\u001b[32m~/Desktop/zixy/zixy-py/docs/.venv/lib/python3.14/site-packages/zixy/qubit/pauli/_strings.py:185\u001b[39m, in \u001b[36mString.__imul__\u001b[39m\u001b[34m(self, rhs)\u001b[39m\n\u001b[32m 183\u001b[39m phase = \u001b[38;5;28mself\u001b[39m.phase_of_mul(rhs)\n\u001b[32m 184\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m phase != ComplexSign():\n\u001b[32m--> \u001b[39m\u001b[32m185\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m _imul_factor_error(\u001b[38;5;28mself\u001b[39m, rhs, phase)\n\u001b[32m 186\u001b[39m \u001b[38;5;28mself\u001b[39m.imul_ignore_phase(rhs)\n\u001b[32m 187\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\n", "\u001b[31mValueError\u001b[39m: Cannot multiply-assign left-hand operand X0 Y1 X4 X5 Z6 Y7 with type by value Y0 X3 X4 Z5 X6 Y7. Result with factor +i is not representable by the left-hand operand type." ] } ], "source": [ "strings[0] *= strings[1]" ] }, { "cell_type": "code", "execution_count": 6, "id": "cb2775e2-53c5-4d2f-9422-5a5adee436c6", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "X0 Y1 X4 X5 Z6 Y7, Y0 X3 X4 Z5 X6 Y7, Y0 X3 X4 Z5 Y7, X0 Z1 Y3 Y4 X7" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "strings" ] }, { "cell_type": "code", "execution_count": 7, "id": "45bf96a3", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "S(1), H(2), CX(0, 2), S(3)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from zixy.qubit.clifford import GateList\n", "GateList().s(1).h(2).cx(0, 2).s(3)" ] }, { "cell_type": "markdown", "id": "1cc08e38", "metadata": {}, "source": [ "An exception is raised if any input is invalid" ] }, { "cell_type": "code", "execution_count": 8, "id": "957b37d4-69f0-4a19-9a9a-25023d9e9dbf", "metadata": {}, "outputs": [ { "ename": "ValueError", "evalue": "Value 2 is both elements of what is supposed to be a distinct pair.", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mValueError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[8]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[43mGateList\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m.\u001b[49m\u001b[43ms\u001b[49m\u001b[43m(\u001b[49m\u001b[32;43m1\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m.\u001b[49m\u001b[43mh\u001b[49m\u001b[43m(\u001b[49m\u001b[32;43m2\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m.\u001b[49m\u001b[43mcx\u001b[49m\u001b[43m(\u001b[49m\u001b[32;43m2\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[32;43m2\u001b[39;49m\u001b[43m)\u001b[49m.s(\u001b[32m3\u001b[39m)\n", "\u001b[36mFile \u001b[39m\u001b[32m~/Desktop/zixy/zixy-py/docs/.venv/lib/python3.14/site-packages/zixy/qubit/clifford/gate_list.py:74\u001b[39m, in \u001b[36mGateList.cx\u001b[39m\u001b[34m(self, i_control, i_target)\u001b[39m\n\u001b[32m 61\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mcx\u001b[39m(\u001b[38;5;28mself\u001b[39m, i_control: \u001b[38;5;28mint\u001b[39m, i_target: \u001b[38;5;28mint\u001b[39m) -> GateList:\n\u001b[32m 62\u001b[39m \u001b[38;5;250m \u001b[39m\u001b[33;03m\"\"\"Push a CNOT gate into the list.\u001b[39;00m\n\u001b[32m 63\u001b[39m \n\u001b[32m 64\u001b[39m \u001b[33;03m Args:\u001b[39;00m\n\u001b[32m (...)\u001b[39m\u001b[32m 72\u001b[39m \u001b[33;03m This method operates in-place.\u001b[39;00m\n\u001b[32m 73\u001b[39m \u001b[33;03m \"\"\"\u001b[39;00m\n\u001b[32m---> \u001b[39m\u001b[32m74\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_impl\u001b[49m\u001b[43m.\u001b[49m\u001b[43mpush_cx\u001b[49m\u001b[43m(\u001b[49m\u001b[43mi_control\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mi_target\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 75\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\n", "\u001b[31mValueError\u001b[39m: Value 2 is both elements of what is supposed to be a distinct pair." ] } ], "source": [ "GateList().s(1).h(2).cx(2, 2).s(3)" ] }, { "cell_type": "code", "execution_count": 9, "id": "3c87e371", "metadata": {}, "outputs": [], "source": [ "from zixy.qubit.pauli import SignTerms\n", "terms = SignTerms.from_iterable((\n", " (X, Y, I, I, X, X, Z, Y),\n", " (Y, I, Z, Z, X, Z, X, Y),\n", " (I, X, I, X, Y, Y, X, Y),\n", " (Y, Z, Z, Z, X, Z, I, Y),\n", " (Y, I, I, X, X, X, I, Y),\n", " (X, Z, I, Y, Y, I, I, X),\n", "), Qubits.from_count(8))\n", "cliffords = GateList().s(1).h(2).cx(0, 2).h(3).cx(6, 3)" ] }, { "cell_type": "code", "execution_count": 10, "id": "b81931e2", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ComponentCoefficient
0X0 X1 X2 X4 X5 Z6 Y7-1
1Y0 X4 Z5 X6 Y7+1
2Y1 Y3 Y4 Y5 Y6 Y7-1
3Y0 Z1 X3 X4 Z5 Y7+1
4Y0 X2 Z3 X4 X5 Z6 Y7+1
5X0 Z1 X2 Y3 Y4 Z6 X7-1
\n", "
" ], "text/plain": [ " Component Coefficient\n", "0 X0 X1 X2 X4 X5 Z6 Y7 -1\n", "1 Y0 X4 Z5 X6 Y7 +1\n", "2 Y1 Y3 Y4 Y5 Y6 Y7 -1\n", "3 Y0 Z1 X3 X4 Z5 Y7 +1\n", "4 Y0 X2 Z3 X4 X5 Z6 Y7 +1\n", "5 X0 Z1 X2 Y3 Y4 Z6 X7 -1" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "terms.conj_clifford_list(cliffords)\n", "terms.to_dataframe()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.14.0" } }, "nbformat": 4, "nbformat_minor": 5 }