{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Introduction to Linear Algebra and Quantum Information modules of Paddle Quantum\n", "*Copyright (c) 2023 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n", "\n", "`linalg` and `qinfo` module are Paddle Quantum modules that support operations of matrices and functions of quantum information respectively. `linalg` module provides many matrix operations includeing transpose, conjuagte, tensor product and trace. And `qinfo` module mainly includes partial trace, different quantum entropy, fidelity of quantum states and trace distance, which are functions that related to quantum information theory." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Common operations of matrix\n", "\n", "We know that quantum mechanics has a close connection with linear algebra. Here, we will introduce the common operations of matrix in `linalg` module with simple examples." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "c:\\Users\\liugeng02\\Anaconda3\\envs\\2023q2\\lib\\site-packages\\openfermion\\hamiltonians\\hartree_fock.py:11: DeprecationWarning: Please use `OptimizeResult` from the `scipy.optimize` namespace, the `scipy.optimize.optimize` namespace is deprecated.\n", " from scipy.optimize.optimize import OptimizeResult\n", "c:\\Users\\liugeng02\\Anaconda3\\envs\\2023q2\\lib\\site-packages\\paddle\\tensor\\creation.py:125: DeprecationWarning: `np.object` is a deprecated alias for the builtin `object`. To silence this warning, use `object` by itself. Doing this will not modify any behavior and is safe. \n", "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n", " if data.dtype == np.object:\n", "c:\\Users\\liugeng02\\Anaconda3\\envs\\2023q2\\lib\\site-packages\\paddle\\tensor\\creation.py:125: DeprecationWarning: `np.object` is a deprecated alias for the builtin `object`. To silence this warning, use `object` by itself. Doing this will not modify any behavior and is safe. \n", "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n", " if data.dtype == np.object:\n" ] } ], "source": [ "import paddle\n", "import paddle_quantum\n", "from paddle_quantum.state import State\n", "from paddle.linalg import eigvals, eig\n", "from paddle_quantum.linalg import dagger, NKron, density_matrix_random, unitary_random\n", "from paddle_quantum.qinfo import (\n", " partial_trace,\n", " state_fidelity,\n", " trace_distance,\n", " von_neumann_entropy,\n", " relative_entropy,\n", ")\n", "\n", "paddle_quantum.set_backend(\"density_matrix\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We first initialize two random unitary matrices through built-in function of Paddle Quantum. The matrix A and B here are both in `paddle.Tensor` format." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Matrix A is:\n", "Tensor(shape=[2, 2], dtype=complex64, place=Place(cpu), stop_gradient=True,\n", " [[(-0.008479282259941101-0.3407862186431885j),\n", " (0.6076244115829468-0.7173460721969604j) ],\n", " [(-0.3203158378601074-0.8838498592376709j) ,\n", " (-0.12643268704414368+0.3165784478187561j) ]])\n", "\n", "Matrix B is:\n", "Tensor(shape=[2, 2], dtype=complex64, place=Place(cpu), stop_gradient=True,\n", " [[(-0.6520524621009827-0.2549170255661011j) ,\n", " (-0.5733906030654907-0.42552101612091064j)],\n", " [ (0.5613574981689453+0.44127389788627625j),\n", " (-0.4174516499042511-0.5620402097702026j) ]])\n" ] } ], "source": [ "A = unitary_random(num_qubits=1)\n", "B = unitary_random(num_qubits=1)\n", "print(f\"Matrix A is:\\n{A}\\n\")\n", "print(f\"Matrix B is:\\n{B}\")\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "**matrix multiplication**:There are two ways to calculate matrix multiplication, the first way is using `matmul` method of Paddle, and the second way is directly using `@`.\n", "\n", "**transpose**:The transpose of matrix A can be calculated using `A.t()`.\n", "\n", "**conjugate**:The conjugate of matrix A can be calculated using `A.conjugate()`.\n", "\n", "**conjugate transpose**:There are two ways to calculate conjugate transpose of a matrix. The first way is calculating the conjugate of the matrix followed by calculating the transpose, using `A.conj().t()`; the second way is directly using `dagger` method of Paddle Quantum.\n", "\n", "**tensor product of two matrices**:The tensor product of two matrices can be calculated using `paddle.kron()`.\n", "\n", "**tensor product of multiple matrices**:The tensor product of multiple matrices can be calculated using `NKron()` of Paddle Quantum.\n", "\n", "**trace of matrix**:The trace of a matrix can be calculated using `paddle.trace()`.\n", "\n", "**partial trace of matrix**:The partial trace of a matrix can be calculated using `partial_trace()` of Paddle Quantum.\n", "\n", "**eigenvalue and eigenvector of matrix**:The eigenvalues and eigenvectors of a matrix can be calculated using `eig`, and the eigenvalues can be directly calculated using `eigvals`." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "multiplyAB_1 = paddle.matmul(A, B) # matrix multiplication\n", "multiplyAB_2 = A @ B # matrix multiplication\n", "A_transpose = A.t() # transpose\n", "A_conjugate = A.conj() # conjugate\n", "A_dagger = dagger(A) # conjugate transpose\n", "tensor_product_AB = paddle.kron(A, B) # tensor product of two matrices\n", "tensor_product_ABA = NKron(A, B, A) # tensor product of multiple matrices\n", "A_trace = paddle.trace(A) # trace of the matrix\n", "partial_trace_matrix = partial_trace(tensor_product_AB, dim1=2, dim2=2, A_or_B=2) # partial trace of matrix\n", "eigenvalue, eigenvector = eig(A) # eigenvalue and eigenvector of the matrix" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Common functions in quantum information" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We first initialize two random single qubit quantum states with `density_matrix_random`." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The first quantum state is:\n", " Tensor(shape=[2, 2], dtype=complex64, place=Place(cpu), stop_gradient=True,\n", " [[(0.5706692337989807+0j) ,\n", " (0.4849703907966614+0.09904339164495468j)],\n", " [(0.4849703907966614-0.09904339164495468j),\n", " (0.4293307662010193+0j) ]])\n", "\n", "The second quantum state is:\n", " Tensor(shape=[2, 2], dtype=complex64, place=Place(cpu), stop_gradient=True,\n", " [[ (0.8634329438209534+0j) ,\n", " (-0.04915342852473259+0.33985358476638794j)],\n", " [(-0.04915342852473259-0.33985358476638794j),\n", " (0.13656707108020782+0j) ]])\n" ] } ], "source": [ "state1 = density_matrix_random(1)\n", "print(f\"The first quantum state is:\\n {state1}\\n\")\n", "state2 = density_matrix_random(1)\n", "print(f\"The second quantum state is:\\n {state2}\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We can use `state_fidelity()` to calculate the fidelity of two quantum states." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The fidelity is:\n", "Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,\n", " [0.75565338])\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "c:\\Users\\liugeng02\\Anaconda3\\envs\\2023q2\\lib\\site-packages\\paddle\\fluid\\framework.py:1104: DeprecationWarning: `np.bool` is a deprecated alias for the builtin `bool`. To silence this warning, use `bool` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.bool_` here.\n", "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n", " elif dtype == np.bool:\n" ] } ], "source": [ "fidelity = state_fidelity(state1, state2)\n", "print(f\"The fidelity is:\\n{fidelity}\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "It is worth noting that the functions of Paddle Quantum that related to quantum states supports different format of input, including `paddle.Tensor`, `numpy.ndarray`, and `State`. At the same time, the output format is consistent with the input format. For example, the output will be `numpy.ndarray` format if the input is also `numpy.ndarray` format." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.7556533814816342\n" ] } ], "source": [ "# Input with numpy.ndarray format\n", "state1 = state1.numpy()\n", "state2 = state2.numpy()\n", "print(state_fidelity(state1, state2))" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,\n", " [0.75565338])\n" ] } ], "source": [ "# Input with State format\n", "state1 = State(state1)\n", "state2 = State(state2)\n", "print(state_fidelity(state1, state2))" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We can use `trace_distance` to calculate the trace distance between two quantum states." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The trace distance is:\n", "Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,\n", " [0.65497208])\n" ] } ], "source": [ "TraceDistance = trace_distance(state1, state2)\n", "print(f\"The trace distance is:\\n{TraceDistance}\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We can use `von_neumann_entropy()` to calculate the von neumann entropy of a quantum state." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The von veumann entropy of the quantum state is:\n", "Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,\n", " [0.00000026])\n" ] } ], "source": [ "v_entropy = von_neumann_entropy(state2)\n", "print(f\"The von veumann entropy of the quantum state is:\\n{v_entropy}\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We can use `relative_entropy()` to calculate the relative entropy of two quantum states." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "logm result may be inaccurate, approximate err = 3.3328131580525864e-07\n", "logm result may be inaccurate, approximate err = 2.3121323283812061e-07\n", "The relative entropy is:\n", "Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,\n", " [11.14819717])\n" ] } ], "source": [ "r_entropy = relative_entropy(state1, state2)\n", "print(f\"The relative entropy is:\\n{r_entropy}\")" ] } ], "metadata": { "kernelspec": { "display_name": "2023q2", "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.8.16" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }