{ "cells": [ { "cell_type": "markdown", "id": "fb9014d4", "metadata": {}, "source": [ "# Qudit Circuit Basics\n", "\n", "*A gentle intro to `tensorcircuit.quditcircuit.QuditCircuit`*" ] }, { "cell_type": "markdown", "id": "78755298", "metadata": {}, "source": [ "\n", "## Overview\n", "\n", "This tutorial shows how to build and simulate **qudit** circuits (d‑level systems, where `d ≥ 3`) using `tensorcircuit`'s `QuditCircuit` API.\n", "**Highlights**\n", "- Create a `QuditCircuit(nqudits, dim)` with dimension `dim ∈ [3, 36]`.\n", "- Single-qudit gates: `X`, `Z`, `H`, rotations `RX/RY/RZ` on selected levels `(j, k)`.\n", "- Two‑qudit gates: `RXX`, `RZZ`, and the generalized controlled‑sum `CSUM` and controlled-phase `CPHASE`.\n", "- Obtain wavefunctions, probabilities, samples, expectations, and sub‑system projections.\n", "- Samples and bitstrings use base‑36 digits (`0–9A–Z`) where `A = 10, ..., Z = 35`.\n" ] }, { "cell_type": "markdown", "id": "639c47d1", "metadata": {}, "source": [ "\n", "## Setup" ] }, { "cell_type": "code", "execution_count": 1, "id": "8f2d9565", "metadata": { "ExecuteTime": { "end_time": "2025-09-10T10:32:59.941117Z", "start_time": "2025-09-10T10:32:58.690552Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensorcircuit version: 1.3.0\n" ] } ], "source": [ "import tensorcircuit as tc\n", "from tensorcircuit.quditcircuit import QuditCircuit\n", "\n", "tc.set_backend(\"numpy\") # or \"jax\", \"tensorflow\", \"pytorch\"\n", "print(\"tensorcircuit version:\", tc.__version__)" ] }, { "cell_type": "markdown", "id": "e19b9c5d", "metadata": {}, "source": [ "\n", "## Hello, Qutrit! (dim = 13)\n", "\n", "We'll prepare a **single qudit** (`nqudits=1`, `dim=13`), apply a generalized Hadamard `H` to put it into an equal superposition, and inspect the resulting state and probabilities.\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "3fa13efe", "metadata": { "ExecuteTime": { "end_time": "2025-09-10T10:33:00.001551Z", "start_time": "2025-09-10T10:32:59.998454Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\\psi: [0.2773501+0.j 0.2773501+0.j 0.2773501+0.j 0.2773501+0.j 0.2773501+0.j\n", " 0.2773501+0.j 0.2773501+0.j 0.2773501+0.j 0.2773501+0.j 0.2773501+0.j\n", " 0.2773501+0.j 0.2773501+0.j 0.2773501+0.j]\n", "P: [0.07692308 0.07692308 0.07692308 0.07692308 0.07692308 0.07692308\n", " 0.07692308 0.07692308 0.07692308 0.07692308 0.07692308 0.07692308\n", " 0.07692308]\n" ] } ], "source": [ "c = QuditCircuit(nqudits=1, dim=13)\n", "c.h(0) # generalized Hadamard on the only qudit\n", "psi = c.wavefunction() # state vector of length 13^1 = 13\n", "probs = c.probability() # probability vector (length 3)\n", "print(r\"\\psi:\", psi)\n", "print(\"P:\", probs)" ] }, { "cell_type": "markdown", "id": "3d4bd27e", "metadata": {}, "source": [ "\n", "## Multi‑Qudit Basics\n", "\n", "Let's move to **two qutrits** and create a maximally entangled state using `H` and the qudit controlled‑sum `CSUM`.\n", "\n", "The operator `CSUM(control, target, cv=None)` adds the control's value to the target modulo `dim`. It's a natural generalization of CNOT. If you pass `cv`, the gate activates only when the control equals that value (default is `None`).\n" ] }, { "cell_type": "code", "execution_count": 3, "id": "c53a755e", "metadata": { "ExecuteTime": { "end_time": "2025-09-10T10:33:00.018234Z", "start_time": "2025-09-10T10:33:00.014110Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "|\\psi|^2 (length 3^2=9): [0.3333333 0. 0. 0. 0.3333333 0. 0.\n", " 0. 0.3333333]\n" ] } ], "source": [ "cq = QuditCircuit(nqudits=2, dim=3) # two qutrits\n", "cq.h(0) # superpose control\n", "cq.csum(0, 1) # qudit CNOT analog (control=0, target=1)\n", "psi = cq.wavefunction()\n", "probs = cq.probability()\n", "print(r\"|\\psi|^2 (length 3^2=9):\", probs)" ] }, { "cell_type": "markdown", "id": "10f5f60a", "metadata": {}, "source": [ "\n", "### Sampling and Base‑36 Readout\n", "\n", "Sampling returns strings in base‑`dim` using **`0-9A-Z`**. For `dim=3`, the alphabet is `0,1,2`:\n" ] }, { "cell_type": "code", "execution_count": 4, "id": "6542deab", "metadata": { "ExecuteTime": { "end_time": "2025-09-10T10:33:00.335589Z", "start_time": "2025-09-10T10:33:00.031885Z" } }, "outputs": [ { "data": { "text/plain": [ "{'00': 160, '11': 171, '22': 181}" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "samples = cq.sample(batch=512, format=\"count_dict_bin\") # e.g., '00', '11', '22'\n", "samples" ] }, { "cell_type": "markdown", "id": "d2bd578c", "metadata": {}, "source": [ "\n", "## Single‑Qudit Rotations on Selected Levels\n", "\n", "For a qudit, rotations target a **two‑level subspace** inside the `d` levels.\n", "\n", "- `rx(index, theta, j=0, k=1)` rotates between levels `j` and `k` about the X‑axis of that embedded SU(2).\n", "- `ry(index, theta, j=0, k=1)` similarly for Y.\n", "- `rz(index, theta, j=0)` applies a Z‑phase to a single level `j`.\n", "\n", "> Tip: `(j, k)` must be distinct integers in `[0, dim-1]`.\n" ] }, { "cell_type": "code", "execution_count": 5, "id": "e4e2b769", "metadata": { "ExecuteTime": { "end_time": "2025-09-10T10:33:00.350793Z", "start_time": "2025-09-10T10:33:00.346566Z" } }, "outputs": [ { "data": { "text/plain": [ "(array([0.4472136 +0.j , 0.38729832-0.2236068j ,\n", " 0.4472136 +0.j , 0.38729832-0.2236068j ,\n", " 0.3618034 +0.26286554j], dtype=complex64),\n", " array([0.19999999, 0.19999997, 0.19999999, 0.19999997, 0.20000002],\n", " dtype=float32))" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "\n", "c = QuditCircuit(nqudits=1, dim=5) # a ququint\n", "c.h(0) # start in equal superposition\n", "c.rx(0, theta=np.pi / 3, j=1, k=3) # rotate levels 1 and 3\n", "c.rz(0, theta=np.pi / 5, j=4) # add a phase to level 4\n", "psi = c.wavefunction()\n", "probs = c.probability()\n", "psi, probs" ] }, { "cell_type": "markdown", "id": "9d98e918", "metadata": {}, "source": [ "\n", "## Two‑Qudit Interactions: `RXX`, `RZZ`\n", "\n", "You can couple two qudits by acting on chosen **subspaces** of each:\n", "\n", "- `rxx(q1, q2, theta, j1=0, k1=1, j2=0, k2=1)`\n", "- `rzz(q1, q2, theta, j1=0, k1=1, j2=0, k2=1)`\n", "\n", "Both gates are the natural generalizations of qubit XX/ZZ rotations but restricted to the `(j, k)` subspaces.\n" ] }, { "cell_type": "code", "execution_count": 6, "id": "a56be75e", "metadata": { "ExecuteTime": { "end_time": "2025-09-10T10:33:00.361091Z", "start_time": "2025-09-10T10:33:00.357370Z" } }, "outputs": [ { "data": { "text/plain": [ "array([0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625,\n", " 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625],\n", " dtype=float32)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c2 = QuditCircuit(nqudits=2, dim=4) # two ququarts\n", "c2.h(0)\n", "c2.h(1)\n", "c2.rxx(0, 1, theta=np.pi / 4, j1=0, k1=2, j2=1, k2=3)\n", "c2.rzz(0, 1, theta=np.pi / 7, j1=0, k1=1, j2=0, k2=1)\n", "c2.probability()" ] }, { "cell_type": "markdown", "id": "c5a56af8", "metadata": {}, "source": [ "\n", "## Expectation Values of Local Operators\n", "\n", "`expectation(*ops)` computes the expectation for one or more local observables. Each observable is a pair `(op, [site_indices])` where `op` is a tensor (matrix) with appropriate dimension.\n" ] }, { "cell_type": "code", "execution_count": 7, "id": "fe4ed499", "metadata": { "ExecuteTime": { "end_time": "2025-09-10T10:33:00.372256Z", "start_time": "2025-09-10T10:33:00.367671Z" } }, "outputs": [ { "data": { "text/plain": [ "array(0.49999997+0.j, dtype=complex64)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Example: build a diagonal operator on a single qutrit (dim=3)\n", "import numpy as np\n", "\n", "c = QuditCircuit(1, dim=3)\n", "c.h(0)\n", "op = np.diag([0.0, 0.5, 1.0]) # acts on subspace levels 0,1,2\n", "expval = c.expectation((op, [0]))\n", "expval" ] }, { "cell_type": "markdown", "id": "648ee02776427b3c", "metadata": {}, "source": [ "### Apply Arbitrary Gate\n", "\n", "Just directly using ``any`` API by feeding the corresponding unitary" ] }, { "cell_type": "code", "execution_count": 8, "id": "4d73e00b952f2ac4", "metadata": { "ExecuteTime": { "end_time": "2025-09-10T10:33:14.972605Z", "start_time": "2025-09-10T10:33:00.385060Z" } }, "outputs": [ { "data": { "text/plain": [ "{'00': 29,\n", " '11': 35,\n", " '22': 29,\n", " '33': 41,\n", " '44': 25,\n", " '55': 28,\n", " '66': 28,\n", " '77': 35,\n", " '88': 32,\n", " '99': 27,\n", " 'AA': 38,\n", " 'BB': 35,\n", " 'CC': 29,\n", " 'DD': 31,\n", " 'EE': 30,\n", " 'FF': 22,\n", " 'GG': 26,\n", " 'HH': 19,\n", " 'II': 26,\n", " 'JJ': 24,\n", " 'KK': 37,\n", " 'LL': 27,\n", " 'MM': 34,\n", " 'NN': 27,\n", " 'OO': 31,\n", " 'PP': 31,\n", " 'QQ': 28,\n", " 'RR': 26,\n", " 'SS': 23,\n", " 'TT': 27,\n", " 'UU': 32,\n", " 'VV': 27,\n", " 'WW': 19,\n", " 'XX': 27,\n", " 'YY': 22,\n", " 'ZZ': 17}" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d = 36\n", "c = tc.QuditCircuit(2, dim=d)\n", "h_matrix = tc.quditgates.h_matrix_func(d)\n", "c.any(0, unitary=h_matrix)\n", "csum_matrix = tc.quditgates.csum_matrix_func(d)\n", "c.any(0, 1, unitary=csum_matrix)\n", "c.sample(1024, format=\"count_dict_bin\")" ] }, { "cell_type": "markdown", "id": "7aa6de25", "metadata": {}, "source": [ "\n", "## Notes & Tips\n", "\n", "- **Dimensions**: `QuditCircuit` validates `dim` and keeps it consistent across the circuit.\n", "- **Wavefunction & Probability**: `wavefunction()` returns the state; `probability()` returns a length‑`dim^n` vector.\n", "- **Sampling**: `sample(batch, format=\"str\")` returns base‑36 strings for readability; use `format=None` for raw integers.\n", "- **Controlled Operations**: `csum(control, target, cv=None)` generalizes CNOT; `cv` picks the active control value.\n", "- **Backend**: Switch via `tc.set_backend(\"numpy\" | \"jax\" | \"tensorflow\" | \"pytorch\")` as needed.\n", "- **Interoperability**: You can still obtain `matrix()` for the full unitary or `quoperator()` MPO‑like forms for advanced workflows.\n", "\n", "All the functions are similar to the `tc.Circuit`\n" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 }