From 72529706b10d720d3b25418794cc4a17c4037a11 Mon Sep 17 00:00:00 2001 From: Weiguo Ma Date: Wed, 10 Sep 2025 18:02:30 +0800 Subject: [PATCH 1/3] add tutorial for quditcircuit in English. --- .../tutorials/circuit_qudit_basics.ipynb | 445 ++++++++++++++++++ 1 file changed, 445 insertions(+) create mode 100644 docs/source/tutorials/circuit_qudit_basics.ipynb diff --git a/docs/source/tutorials/circuit_qudit_basics.ipynb b/docs/source/tutorials/circuit_qudit_basics.ipynb new file mode 100644 index 00000000..0f6333a5 --- /dev/null +++ b/docs/source/tutorials/circuit_qudit_basics.ipynb @@ -0,0 +1,445 @@ +{ + "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. It mirrors the structure of the classic *Circuit Basics* notebook but focuses on **qutrits and higher**.\n", + "\n", + "**Highlights**\n", + "- Create a `QuditCircuit(nqudits, dim)` with dimension `dim ∈ [3, 36]`.\n", + "- Use generalized gates: `X`, `Z`, `H`, rotations `RX/RY/RZ` on selected levels `(j, k)`.\n", + "- Two‑qudit interactions: `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", + "id": "8f2d9565", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T09:52:45.586900Z", + "start_time": "2025-09-10T09:52:45.584017Z" + } + }, + "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__)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "tensorcircuit version: 1.3.0\n" + ] + } + ], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "id": "e19b9c5d", + "metadata": {}, + "source": [ + "\n", + "## Hello, Qutrit! (dim = 13)\n", + "\n", + "We'll prepare a **single qutrit** (`nqudits=1`, `dim=3`), apply a generalized Hadamard `H` to put it into an equal superposition, and inspect the resulting state and probabilities.\n" + ] + }, + { + "cell_type": "code", + "id": "3fa13efe", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T09:52:46.860189Z", + "start_time": "2025-09-10T09:52:46.856020Z" + } + }, + "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)" + ], + "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" + ] + } + ], + "execution_count": 31 + }, + { + "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 `1`).\n" + ] + }, + { + "cell_type": "code", + "id": "c53a755e", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T09:52:49.285065Z", + "start_time": "2025-09-10T09:52:49.281466Z" + } + }, + "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)" + ], + "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" + ] + } + ], + "execution_count": 32 + }, + { + "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", + "id": "6542deab", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T09:53:30.797350Z", + "start_time": "2025-09-10T09:53:30.502390Z" + } + }, + "source": [ + "\n", + "samples = cq.sample(batch=512, format=\"count_dict_bin\") # e.g., '00', '11', '22'\n", + "samples\n" + ], + "outputs": [ + { + "data": { + "text/plain": [ + "{'00': 180, '11': 167, '22': 165}" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 37 + }, + { + "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", + "id": "e4e2b769", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T09:54:39.562209Z", + "start_time": "2025-09-10T09:54:39.556487Z" + } + }, + "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" + ], + "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": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 38 + }, + { + "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", + "id": "a56be75e", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T09:54:46.472203Z", + "start_time": "2025-09-10T09:54:46.468063Z" + } + }, + "source": [ + "c2 = QuditCircuit(nqudits=2, dim=4) # two ququarts\n", + "c2.h(0); 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()" + ], + "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": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 39 + }, + { + "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", + "id": "fe4ed499", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T09:55:01.754737Z", + "start_time": "2025-09-10T09:55:01.750563Z" + } + }, + "source": [ + "# Example: build a diagonal operator on a single qutrit (dim=3)\n", + "import numpy as np\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" + ], + "outputs": [ + { + "data": { + "text/plain": [ + "array(0.49999997+0.j, dtype=complex64)" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 41 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### Apply Arbitrary Gate\n", + "\n", + "Just directly using ``any`` API by feeding the corresponding unitary" + ], + "id": "648ee02776427b3c" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T09:59:59.378191Z", + "start_time": "2025-09-10T09:59:46.147228Z" + } + }, + "cell_type": "code", + "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\")" + ], + "id": "4d73e00b952f2ac4", + "outputs": [ + { + "data": { + "text/plain": [ + "{'00': 33,\n", + " '11': 26,\n", + " '22': 30,\n", + " '33': 35,\n", + " '44': 25,\n", + " '55': 31,\n", + " '66': 27,\n", + " '77': 36,\n", + " '88': 31,\n", + " '99': 39,\n", + " 'AA': 32,\n", + " 'BB': 32,\n", + " 'CC': 36,\n", + " 'DD': 29,\n", + " 'EE': 22,\n", + " 'FF': 26,\n", + " 'GG': 28,\n", + " 'HH': 24,\n", + " 'II': 20,\n", + " 'JJ': 27,\n", + " 'KK': 24,\n", + " 'LL': 39,\n", + " 'MM': 23,\n", + " 'NN': 40,\n", + " 'OO': 22,\n", + " 'PP': 18,\n", + " 'QQ': 25,\n", + " 'RR': 27,\n", + " 'SS': 28,\n", + " 'TT': 24,\n", + " 'UU': 28,\n", + " 'VV': 29,\n", + " 'WW': 21,\n", + " 'XX': 29,\n", + " 'YY': 30,\n", + " 'ZZ': 28}" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 52 + }, + { + "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": {}, + "cell_type": "code", + "outputs": [], + "execution_count": null, + "source": "", + "id": "9a33f318814fa510" + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 5 +} From 1d3b2c2ce7b76990606846fcc2871932ff836b53 Mon Sep 17 00:00:00 2001 From: Weiguo Ma Date: Wed, 10 Sep 2025 18:33:58 +0800 Subject: [PATCH 2/3] add tutorials in both chinese and english for quditcircuit. --- .../tutorials/circuit_qudit_basics.ipynb | 185 ++++---- .../tutorials/circuit_qudit_basics_cn.ipynb | 444 ++++++++++++++++++ 2 files changed, 539 insertions(+), 90 deletions(-) create mode 100644 docs/source/tutorials/circuit_qudit_basics_cn.ipynb diff --git a/docs/source/tutorials/circuit_qudit_basics.ipynb b/docs/source/tutorials/circuit_qudit_basics.ipynb index 0f6333a5..44f22e75 100644 --- a/docs/source/tutorials/circuit_qudit_basics.ipynb +++ b/docs/source/tutorials/circuit_qudit_basics.ipynb @@ -18,12 +18,11 @@ "\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. It mirrors the structure of the classic *Circuit Basics* notebook but focuses on **qutrits and higher**.\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", - "- Use generalized gates: `X`, `Z`, `H`, rotations `RX/RY/RZ` on selected levels `(j, k)`.\n", - "- Two‑qudit interactions: `RXX`, `RZZ`, and the generalized controlled‑sum `CSUM` and controlled-phase `CPHASE`.\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" ] @@ -42,8 +41,8 @@ "id": "8f2d9565", "metadata": { "ExecuteTime": { - "end_time": "2025-09-10T09:52:45.586900Z", - "start_time": "2025-09-10T09:52:45.584017Z" + "end_time": "2025-09-10T10:32:59.941117Z", + "start_time": "2025-09-10T10:32:58.690552Z" } }, "source": [ @@ -62,7 +61,7 @@ ] } ], - "execution_count": 30 + "execution_count": 1 }, { "cell_type": "markdown", @@ -72,7 +71,7 @@ "\n", "## Hello, Qutrit! (dim = 13)\n", "\n", - "We'll prepare a **single qutrit** (`nqudits=1`, `dim=3`), apply a generalized Hadamard `H` to put it into an equal superposition, and inspect the resulting state and probabilities.\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" ] }, { @@ -80,15 +79,15 @@ "id": "3fa13efe", "metadata": { "ExecuteTime": { - "end_time": "2025-09-10T09:52:46.860189Z", - "start_time": "2025-09-10T09:52:46.856020Z" + "end_time": "2025-09-10T10:33:00.001551Z", + "start_time": "2025-09-10T10:32:59.998454Z" } }, "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", + "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)" ], @@ -106,7 +105,7 @@ ] } ], - "execution_count": 31 + "execution_count": 2 }, { "cell_type": "markdown", @@ -118,7 +117,7 @@ "\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 `1`).\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" ] }, { @@ -126,14 +125,14 @@ "id": "c53a755e", "metadata": { "ExecuteTime": { - "end_time": "2025-09-10T09:52:49.285065Z", - "start_time": "2025-09-10T09:52:49.281466Z" + "end_time": "2025-09-10T10:33:00.018234Z", + "start_time": "2025-09-10T10:33:00.014110Z" } }, "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", + "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)" @@ -148,7 +147,7 @@ ] } ], - "execution_count": 32 + "execution_count": 3 }, { "cell_type": "markdown", @@ -166,28 +165,27 @@ "id": "6542deab", "metadata": { "ExecuteTime": { - "end_time": "2025-09-10T09:53:30.797350Z", - "start_time": "2025-09-10T09:53:30.502390Z" + "end_time": "2025-09-10T10:33:00.335589Z", + "start_time": "2025-09-10T10:33:00.031885Z" } }, "source": [ - "\n", "samples = cq.sample(batch=512, format=\"count_dict_bin\") # e.g., '00', '11', '22'\n", - "samples\n" + "samples" ], "outputs": [ { "data": { "text/plain": [ - "{'00': 180, '11': 167, '22': 165}" + "{'00': 160, '11': 171, '22': 181}" ] }, - "execution_count": 37, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 37 + "execution_count": 4 }, { "cell_type": "markdown", @@ -211,17 +209,17 @@ "id": "e4e2b769", "metadata": { "ExecuteTime": { - "end_time": "2025-09-10T09:54:39.562209Z", - "start_time": "2025-09-10T09:54:39.556487Z" + "end_time": "2025-09-10T10:33:00.350793Z", + "start_time": "2025-09-10T10:33:00.346566Z" } }, "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", + "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" @@ -237,12 +235,12 @@ " dtype=float32))" ] }, - "execution_count": 38, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 38 + "execution_count": 5 }, { "cell_type": "markdown", @@ -265,15 +263,16 @@ "id": "a56be75e", "metadata": { "ExecuteTime": { - "end_time": "2025-09-10T09:54:46.472203Z", - "start_time": "2025-09-10T09:54:46.468063Z" + "end_time": "2025-09-10T10:33:00.361091Z", + "start_time": "2025-09-10T10:33:00.357370Z" } }, "source": [ - "c2 = QuditCircuit(nqudits=2, dim=4) # two ququarts\n", - "c2.h(0); 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 = 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()" ], "outputs": [ @@ -285,12 +284,12 @@ " dtype=float32)" ] }, - "execution_count": 39, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 39 + "execution_count": 6 }, { "cell_type": "markdown", @@ -308,13 +307,14 @@ "id": "fe4ed499", "metadata": { "ExecuteTime": { - "end_time": "2025-09-10T09:55:01.754737Z", - "start_time": "2025-09-10T09:55:01.750563Z" + "end_time": "2025-09-10T10:33:00.372256Z", + "start_time": "2025-09-10T10:33:00.367671Z" } }, "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", @@ -328,12 +328,12 @@ "array(0.49999997+0.j, dtype=complex64)" ] }, - "execution_count": 41, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 41 + "execution_count": 7 }, { "metadata": {}, @@ -348,8 +348,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2025-09-10T09:59:59.378191Z", - "start_time": "2025-09-10T09:59:46.147228Z" + "end_time": "2025-09-10T10:33:14.972605Z", + "start_time": "2025-09-10T10:33:00.385060Z" } }, "cell_type": "code", @@ -367,50 +367,50 @@ { "data": { "text/plain": [ - "{'00': 33,\n", - " '11': 26,\n", - " '22': 30,\n", - " '33': 35,\n", + "{'00': 29,\n", + " '11': 35,\n", + " '22': 29,\n", + " '33': 41,\n", " '44': 25,\n", - " '55': 31,\n", - " '66': 27,\n", - " '77': 36,\n", - " '88': 31,\n", - " '99': 39,\n", - " 'AA': 32,\n", - " 'BB': 32,\n", - " 'CC': 36,\n", - " 'DD': 29,\n", - " 'EE': 22,\n", - " 'FF': 26,\n", - " 'GG': 28,\n", - " 'HH': 24,\n", - " 'II': 20,\n", - " 'JJ': 27,\n", - " 'KK': 24,\n", - " 'LL': 39,\n", - " 'MM': 23,\n", - " 'NN': 40,\n", - " 'OO': 22,\n", - " 'PP': 18,\n", - " 'QQ': 25,\n", - " 'RR': 27,\n", - " 'SS': 28,\n", - " 'TT': 24,\n", - " 'UU': 28,\n", - " 'VV': 29,\n", - " 'WW': 21,\n", - " 'XX': 29,\n", - " 'YY': 30,\n", - " 'ZZ': 28}" + " '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": 52, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 52 + "execution_count": 8 }, { "cell_type": "markdown", @@ -431,12 +431,17 @@ ] }, { - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T10:33:14.985131Z", + "start_time": "2025-09-10T10:33:14.983579Z" + } + }, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": "", - "id": "9a33f318814fa510" + "id": "9a33f318814fa510", + "outputs": [], + "execution_count": null } ], "metadata": {}, diff --git a/docs/source/tutorials/circuit_qudit_basics_cn.ipynb b/docs/source/tutorials/circuit_qudit_basics_cn.ipynb new file mode 100644 index 00000000..c2d986bc --- /dev/null +++ b/docs/source/tutorials/circuit_qudit_basics_cn.ipynb @@ -0,0 +1,444 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fb9014d4", + "metadata": {}, + "source": [ + "# Qudit(多能级量子比特) 电路基础\n", + "\n", + "*`tensorcircuit.quditcircuit.QuditCircuit` 的轻量入门*" + ] + }, + { + "cell_type": "markdown", + "id": "78755298", + "metadata": {}, + "source": [ + "\n", + "## 概述\n", + "\n", + "这个教程展示了如何使用 `tensorcircuit` 的 `QuditCircuit` API 来构建和模拟 **qudit(多能级量子比特)** 电路(d 级系统,其中 `d ≥ 3`)。\n", + "\n", + "**要点**\n", + "- 创建一个 `QuditCircuit(nqudits, dim)` with dimension `dim ∈ [3, 36]`;\n", + "- 单比特门: `X`, `Z`, `H`, rotations `RX/RY/RZ` on selected levels `(j, k)`;\n", + "- 两比特门: `RXX`, `RZZ`, and the 广义受控求和 `CSUM` and 受控相位 `CPHASE`;\n", + "- 可得到波函数、概率、采样、期望值以及子系统投影;\n", + "- 样本和比特串使用36进制数字(`0–9A–Z`),其中`A = 10, ..., Z = 35`。\n" + ] + }, + { + "cell_type": "markdown", + "id": "639c47d1", + "metadata": {}, + "source": [ + "\n", + "## 配置" + ] + }, + { + "cell_type": "code", + "id": "8f2d9565", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T10:32:55.146319Z", + "start_time": "2025-09-10T10:32:54.084837Z" + } + }, + "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__)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "tensorcircuit version: 1.3.0\n" + ] + } + ], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "id": "e19b9c5d", + "metadata": {}, + "source": [ + "## 嗨,Qutrit!(维度为 13)\n", + "\n", + "我们来准备一个**单独的 qudit* (`nqudits=1`, `dim=13`), 对它应用一个广义的 Hadamard 门 `H`,让它进入一个等概率叠加态,然后观察最终的状态和概率。" + ] + }, + { + "cell_type": "code", + "id": "3fa13efe", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T10:32:55.208690Z", + "start_time": "2025-09-10T10:32:55.205644Z" + } + }, + "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)" + ], + "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" + ] + } + ], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "id": "3d4bd27e", + "metadata": {}, + "source": [ + "## 多量子比特基础\n", + "\n", + "让我们来研究一下**两个三态量子比特**,使用 `H` 门和量子比特受控和门 `CSUM` 来创建一个最大纠缠态。\n", + "\n", + "算符 `CSUM(control, target, cv=None)` 将控制位的数值加到目标位上,结果对 `dim` 取模。这是 CNOT 门的自然推广。如果传入 `cv`,则该门仅在控制位等于该值时激活(默认为 `None`)。" + ] + }, + { + "cell_type": "code", + "id": "c53a755e", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T10:32:55.224139Z", + "start_time": "2025-09-10T10:32:55.221295Z" + } + }, + "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)" + ], + "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" + ] + } + ], + "execution_count": 3 + }, + { + "cell_type": "markdown", + "id": "10f5f60a", + "metadata": {}, + "source": [ + "### 采样和 36 进制读数\n", + "\n", + "采样会返回用 `0-9A-Z` 表示的、基于 `dim` 进制的字符串。例如,当 `dim=3` 时,字母表是 `0,1,2`:" + ] + }, + { + "cell_type": "code", + "id": "6542deab", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T10:32:55.513434Z", + "start_time": "2025-09-10T10:32:55.230298Z" + } + }, + "source": [ + "samples = cq.sample(batch=512, format=\"count_dict_bin\") # e.g., '00', '11', '22'\n", + "samples" + ], + "outputs": [ + { + "data": { + "text/plain": [ + "{'00': 175, '11': 165, '22': 172}" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "id": "d2bd578c", + "metadata": {}, + "source": [ + "## 在选定能级上的单量子比特旋转\n", + "\n", + "对于一个 qudit(多态量子位),旋转的目标是 `d` 个能级中的一个**双能级子空间**。\n", + "\n", + "- `rx(index, theta, j=0, k=1)` 在能级 `j` 和 `k` 之间绕该嵌入的 SU(2) 的 X 轴旋转。\n", + "- `ry(index, theta, j=0, k=1)` 类似地,绕 Y 轴旋转。\n", + "- `rz(index, theta, j=0)` 对单个能级 `j` 应用 Z 相位。\n", + "\n", + "> 提示:`(j, k)` 必须是 `[0, dim-1]` 中的不同整数。" + ] + }, + { + "cell_type": "code", + "id": "e4e2b769", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T10:32:55.529822Z", + "start_time": "2025-09-10T10:32:55.526134Z" + } + }, + "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" + ], + "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" + } + ], + "execution_count": 5 + }, + { + "cell_type": "markdown", + "id": "9d98e918", + "metadata": {}, + "source": [ + "## 两个多能级量子比特的相互作用:`RXX`,`RZZ`\n", + "\n", + "你可以对每个多能级量子比特的选定**子空间**进行操作来进行耦合:\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", + "这两个门都是量子比特 XX/ZZ 旋转的自然推广,但仅限于 `(j, k)` 子空间。" + ] + }, + { + "cell_type": "code", + "id": "a56be75e", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T10:32:55.542966Z", + "start_time": "2025-09-10T10:32:55.539802Z" + } + }, + "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()" + ], + "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" + } + ], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "id": "c5a56af8", + "metadata": {}, + "source": [ + "## 局部算符的期望值\n", + "\n", + "`expectation(*ops)` 计算一个或多个局部可观测量(算符)的期望值。每个可观测量是一个对 `(op, [site_indices])`,其中 `op` 是一个具有适当维度的张量(矩阵)。" + ] + }, + { + "cell_type": "code", + "id": "fe4ed499", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T10:32:55.554767Z", + "start_time": "2025-09-10T10:32:55.551801Z" + } + }, + "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" + ], + "outputs": [ + { + "data": { + "text/plain": [ + "array(0.49999997+0.j, dtype=complex64)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "id": "648ee02776427b3c", + "metadata": {}, + "source": [ + "### 应用任意门\n", + "\n", + "直接使用 ``any`` API,输入对应的幺正矩阵即可。" + ] + }, + { + "cell_type": "code", + "id": "4d73e00b952f2ac4", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T10:33:10.278158Z", + "start_time": "2025-09-10T10:32:55.563904Z" + } + }, + "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\")" + ], + "outputs": [ + { + "data": { + "text/plain": [ + "{'00': 35,\n", + " '11': 28,\n", + " '22': 28,\n", + " '33': 25,\n", + " '44': 33,\n", + " '55': 30,\n", + " '66': 34,\n", + " '77': 25,\n", + " '88': 22,\n", + " '99': 22,\n", + " 'AA': 40,\n", + " 'BB': 38,\n", + " 'CC': 35,\n", + " 'DD': 17,\n", + " 'EE': 21,\n", + " 'FF': 27,\n", + " 'GG': 24,\n", + " 'HH': 26,\n", + " 'II': 27,\n", + " 'JJ': 24,\n", + " 'KK': 18,\n", + " 'LL': 27,\n", + " 'MM': 23,\n", + " 'NN': 38,\n", + " 'OO': 26,\n", + " 'PP': 31,\n", + " 'QQ': 27,\n", + " 'RR': 37,\n", + " 'SS': 28,\n", + " 'TT': 20,\n", + " 'UU': 34,\n", + " 'VV': 34,\n", + " 'WW': 32,\n", + " 'XX': 25,\n", + " 'YY': 29,\n", + " 'ZZ': 34}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "id": "7aa6de25", + "metadata": {}, + "source": [ + "## 注意事项和提示\n", + "\n", + "- **维度**: `QuditCircuit` 会验证 `dim` 并且保持它在整个电路中的一致性。\n", + "- **波函数和概率**: `wavefunction()` 返回状态;`probability()` 返回一个长度为 `dim^n` 的向量。\n", + "- **采样**: `sample(batch, format=\"str\")` 返回易于阅读的 36 进制字符串;使用 `format=None` 获取原始整数。\n", + "- **受控操作**: `csum(control, target, cv=None)` 泛化了 CNOT 门;`cv` 选择激活的控制值。\n", + "- **后端**: 根据需要通过 `tc.set_backend(\"numpy\" | \"jax\" | \"tensorflow\" | \"pytorch\")` 切换后端。\n", + "- **互操作性**: 你仍然可以获取完整幺正矩阵的 `matrix()` 或类似 MPO 的 `quoperator()` 形式,用于高级工作流程。\n", + "\n", + "所有这些函数都类似于 `tc.Circuit`。" + ] + }, + { + "cell_type": "code", + "id": "9a33f318814fa510", + "metadata": { + "ExecuteTime": { + "end_time": "2025-09-10T10:33:10.287714Z", + "start_time": "2025-09-10T10:33:10.286396Z" + } + }, + "source": [], + "outputs": [], + "execution_count": null + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 5 +} From 59463478efff9816536b16dc68a0c8c5d2ff9559 Mon Sep 17 00:00:00 2001 From: Weiguo Ma Date: Wed, 10 Sep 2025 18:52:19 +0800 Subject: [PATCH 3/3] add qudit tutorials to .rst --- docs/source/tutorial.rst | 1 + docs/source/tutorial_cn.rst | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/source/tutorial.rst b/docs/source/tutorial.rst index 2de28001..ed616f2d 100644 --- a/docs/source/tutorial.rst +++ b/docs/source/tutorial.rst @@ -5,6 +5,7 @@ Jupyter Tutorials .. toctree:: tutorials/circuit_basics.ipynb + tutorials/circuit_qudit_basics.ipynb tutorials/qaoa.ipynb tutorials/qaoa_bo.ipynb tutorials/qaoa_nae3sat.ipynb diff --git a/docs/source/tutorial_cn.rst b/docs/source/tutorial_cn.rst index 956d03b6..7a373045 100644 --- a/docs/source/tutorial_cn.rst +++ b/docs/source/tutorial_cn.rst @@ -5,6 +5,7 @@ .. toctree:: tutorials/circuit_basics_cn.ipynb + tutorials/circuit_qudit_basics_cn.ipynb tutorials/qaoa_cn.ipynb tutorials/tfim_vqe_cn.ipynb tutorials/mnist_qml_cn.ipynb