{ "cells": [ { "cell_type": "markdown", "id": "578a4cb9", "metadata": {}, "source": [ "# Circuits and Gates" ] }, { "cell_type": "markdown", "id": "2f201125", "metadata": {}, "source": [ "## Overview\n", "\n", "In TensorCircuit, a quantum circuit on $n$ qubits -- which supports both noiseless and noisy simulations via Monte Carlo trajectory methods -- is created by the ``tc.Circuit(n)`` API. Here we show how to create basic circuits, apply gates to them, and compute various outputs. " ] }, { "cell_type": "markdown", "id": "c4eb555a", "metadata": {}, "source": [ "## Setup" ] }, { "cell_type": "code", "execution_count": 1, "id": "761f6a48", "metadata": {}, "outputs": [], "source": [ "import inspect\n", "import numpy as np\n", "import tensorcircuit as tc\n", "\n", "K = tc.set_backend(\"tensorflow\")" ] }, { "cell_type": "markdown", "id": "b1be293e", "metadata": {}, "source": [ "In TensorCircuit the default runtime datatype is complex64, but if higher precision is required this can be set as follows" ] }, { "cell_type": "code", "execution_count": 2, "id": "e51ef263", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('complex128', 'float64')" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tc.set_dtype(\"complex128\")" ] }, { "cell_type": "markdown", "id": "50ff32b6", "metadata": {}, "source": [ "## Basic Circuits and Outputs\n", "\n", "Quantum circuits can be constructed as follows." ] }, { "cell_type": "code", "execution_count": 3, "id": "0f787d90", "metadata": {}, "outputs": [], "source": [ "c = tc.Circuit(2)\n", "c.h(0)\n", "c.cnot(0, 1)\n", "c.rx(1, theta=0.2)" ] }, { "cell_type": "markdown", "id": "ef28386a", "metadata": {}, "source": [ "**Output: state**\n", "\n", "From this, various outputs can be computed.\n", "\n", "The full wavefunction can be obtained via\n" ] }, { "cell_type": "code", "execution_count": 4, "id": "d6d889ef", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.state()" ] }, { "cell_type": "markdown", "id": "0ffea92d", "metadata": {}, "source": [ "The full wavefunction can also be used to generate the reduced density matrix of a subset of the qubits\n" ] }, { "cell_type": "code", "execution_count": 5, "id": "e83bf578", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# reduced density matrix for qubit 1\n", "s = c.state()\n", "tc.quantum.reduced_density_matrix(s, cut=[0]) # cut: list of qubit indices to trace out" ] }, { "cell_type": "markdown", "id": "bb8ea75d", "metadata": {}, "source": [ "Amplitudes of individual basis vectors are computed by passing the corresponding bit-string value to the ``amplitude`` function. For example, the amplitude of the $\\vert{10}\\rangle$ basis vector is computed by\n" ] }, { "cell_type": "code", "execution_count": 6, "id": "ed144734", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.amplitude(\"10\")" ] }, { "cell_type": "markdown", "id": "de0ca800", "metadata": {}, "source": [ "The unitary matrix corresponding to the entire quantum circuit can also be output." ] }, { "cell_type": "code", "execution_count": 7, "id": "aafe76f3", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.matrix()" ] }, { "cell_type": "markdown", "id": "e0534fdc", "metadata": {}, "source": [ "**Output: measurement**\n", "\n", "Random samples corresponding to $Z$-measurements on all qubits can be generated using the following API, which will output a $(\\text{bitstring}, \\text{probability})$ tuple, comprising a binary string corresponding to the measurement outcomes of a Z measurement on all the qubits and the associated probability of obtaining that outcome. Z measurements on a subset of qubits can be performed with the ``measure`` command" ] }, { "cell_type": "code", "execution_count": 8, "id": "cd64d8b8", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(,\n", " )" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.sample()" ] }, { "cell_type": "code", "execution_count": 9, "id": "224d9bdf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(,\n", " )" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.measure(0, with_prob=True)" ] }, { "cell_type": "code", "execution_count": 10, "id": "3870a23a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(,\n", " )" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.measure(0, 1, with_prob=True)" ] }, { "cell_type": "markdown", "id": "b349ce80", "metadata": {}, "source": [ "**Output: expectation**\n", " \n", "Expectation values such as $\\langle X_0 \\rangle$, $\\langle X_1 + Z_1\\rangle$ or $\\langle Z_0 Z_1\\rangle$ can be computed via the ${\\sf expectation}$ method of a circuit object" ] }, { "cell_type": "code", "execution_count": 11, "id": "e928bd7c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(0j, shape=(), dtype=complex128)\n", "tf.Tensor(0j, shape=(), dtype=complex128)\n", "tf.Tensor((0.9800665437029109+0j), shape=(), dtype=complex128)\n" ] } ], "source": [ "print(c.expectation([tc.gates.x(), [0]])) # \n", "print(c.expectation([tc.gates.x() + tc.gates.z(), [1]])) # \n", "print(c.expectation([tc.gates.z(), [0]], [tc.gates.z(), [1]])) # " ] }, { "cell_type": "code", "execution_count": 12, "id": "ed8dfb67", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# user-defined operator\n", "\n", "c.expectation([np.array([[3, 2], [2, -3]]), [0]])" ] }, { "cell_type": "markdown", "id": "99a3ade6", "metadata": {}, "source": [ "While expectations of products of Pauli operators, e.g. $\\langle Z_0 X_1\\rangle$ can be computed using ``c.expectation`` as above, TensorCircuit provides another way of computing such expressions which may be more convenient for longer Pauli strings, and longer Pauli strings can similarly be computed by providing lists of indices corresponding to the qubits that the $X,Y,Z$ operators act on." ] }, { "cell_type": "code", "execution_count": 13, "id": "85971e20", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.expectation_ps(x=[1], z=[0])" ] }, { "cell_type": "markdown", "id": "898b50b7", "metadata": {}, "source": [ "## Built-in Gates" ] }, { "cell_type": "markdown", "id": "3ad34c35", "metadata": {}, "source": [ "TensorCircuit provides support for a wide variety of commonly encountered quantum gates. The full list is as below." ] }, { "cell_type": "code", "execution_count": 14, "id": "2d36bfff", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "i\n", "[[1.+0.j 0.+0.j]\n", " [0.+0.j 1.+0.j]]\n", "x\n", "[[0.+0.j 1.+0.j]\n", " [1.+0.j 0.+0.j]]\n", "y\n", "[[0.+0.j 0.-1.j]\n", " [0.+1.j 0.+0.j]]\n", "z\n", "[[ 1.+0.j 0.+0.j]\n", " [ 0.+0.j -1.+0.j]]\n", "h\n", "[[ 0.70710678+0.j 0.70710678+0.j]\n", " [ 0.70710678+0.j -0.70710678+0.j]]\n", "t\n", "[[1. +0.j 0. +0.j ]\n", " [0. +0.j 0.70710678+0.70710678j]]\n", "s\n", "[[1.+0.j 0.+0.j]\n", " [0.+0.j 0.+1.j]]\n", "td\n", "[[1. +0.j 0. +0.j ]\n", " [0. +0.j 0.70710677-0.70710677j]]\n", "sd\n", "[[1.+0.j 0.+0.j]\n", " [0.+0.j 0.-1.j]]\n", "wroot\n", "[[ 0.70710678+0.j -0.5 -0.5j]\n", " [ 0.5 -0.5j 0.70710678+0.j ]]\n", "cnot\n", "[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 1.+0.j]\n", " [0.+0.j 0.+0.j 1.+0.j 0.+0.j]]\n", "cz\n", "[[ 1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [ 0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", " [ 0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", " [ 0.+0.j 0.+0.j 0.+0.j -1.+0.j]]\n", "swap\n", "[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", " [0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 1.+0.j]]\n", "cy\n", "[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.-1.j]\n", " [0.+0.j 0.+0.j 0.+1.j 0.+0.j]]\n", "iswap\n", "[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+1.j 0.+0.j]\n", " [0.+0.j 0.+1.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 1.+0.j]]\n", "ox\n", "[[0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", " [1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 1.+0.j]]\n", "oy\n", "[[0.+0.j 0.-1.j 0.+0.j 0.+0.j]\n", " [0.+1.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 1.+0.j]]\n", "oz\n", "[[ 1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [ 0.+0.j -1.+0.j 0.+0.j 0.+0.j]\n", " [ 0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", " [ 0.+0.j 0.+0.j 0.+0.j 1.+0.j]]\n", "toffoli\n", "[[1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j]]\n", "fredkin\n", "[[1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j]]\n" ] } ], "source": [ "for g in tc.Circuit.sgates:\n", " gf = getattr(tc.gates, g)\n", " print(g)\n", " print(tc.gates.matrix_for_gate(gf()))" ] }, { "cell_type": "code", "execution_count": 15, "id": "5cbabd45", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "r (theta: float = 0, alpha: float = 0, phi: float = 0) -> tensorcircuit.gates.Gate\n", "cr (theta: float = 0, alpha: float = 0, phi: float = 0) -> tensorcircuit.gates.Gate\n", "rx (theta: float = 0) -> tensorcircuit.gates.Gate\n", "ry (theta: float = 0) -> tensorcircuit.gates.Gate\n", "rz (theta: float = 0) -> tensorcircuit.gates.Gate\n", "crx (*args: Any, **kws: Any) -> Any\n", "cry (*args: Any, **kws: Any) -> Any\n", "crz (*args: Any, **kws: Any) -> Any\n", "orx (*args: Any, **kws: Any) -> Any\n", "ory (*args: Any, **kws: Any) -> Any\n", "orz (*args: Any, **kws: Any) -> Any\n", "any (unitary: Any, name: str = 'any') -> tensorcircuit.gates.Gate\n", "exp (unitary: Any, theta: float, name: str = 'none') -> tensorcircuit.gates.Gate\n", "exp1 (unitary: Any, theta: float, name: str = 'none') -> tensorcircuit.gates.Gate\n" ] } ], "source": [ "for g in tc.Circuit.vgates:\n", " print(g, inspect.signature(getattr(tc.gates, g).f))" ] }, { "cell_type": "markdown", "id": "41cc322f", "metadata": {}, "source": [ "Also, we have built-in matrices as" ] }, { "cell_type": "code", "execution_count": 16, "id": "9b968be1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "_cnot_matrix :\n", " [[1. 0. 0. 0.]\n", " [0. 1. 0. 0.]\n", " [0. 0. 0. 1.]\n", " [0. 0. 1. 0.]]\n", "_cy_matrix :\n", " [[ 1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [ 0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", " [ 0.+0.j 0.+0.j 0.+0.j -0.-1.j]\n", " [ 0.+0.j 0.+0.j 0.+1.j 0.+0.j]]\n", "_cz_matrix :\n", " [[ 1. 0. 0. 0.]\n", " [ 0. 1. 0. 0.]\n", " [ 0. 0. 1. 0.]\n", " [ 0. 0. 0. -1.]]\n", "_fredkin_matrix :\n", " [[1. 0. 0. 0. 0. 0. 0. 0.]\n", " [0. 1. 0. 0. 0. 0. 0. 0.]\n", " [0. 0. 1. 0. 0. 0. 0. 0.]\n", " [0. 0. 0. 1. 0. 0. 0. 0.]\n", " [0. 0. 0. 0. 1. 0. 0. 0.]\n", " [0. 0. 0. 0. 0. 0. 1. 0.]\n", " [0. 0. 0. 0. 0. 1. 0. 0.]\n", " [0. 0. 0. 0. 0. 0. 0. 1.]]\n", "_h_matrix :\n", " [[ 0.70710678 0.70710678]\n", " [ 0.70710678 -0.70710678]]\n", "_i_matrix :\n", " [[1. 0.]\n", " [0. 1.]]\n", "_ii_matrix :\n", " [[1. 0. 0. 0.]\n", " [0. 1. 0. 0.]\n", " [0. 0. 1. 0.]\n", " [0. 0. 0. 1.]]\n", "_s_matrix :\n", " [[1.+0.j 0.+0.j]\n", " [0.+0.j 0.+1.j]]\n", "_swap_matrix :\n", " [[1. 0. 0. 0.]\n", " [0. 0. 1. 0.]\n", " [0. 1. 0. 0.]\n", " [0. 0. 0. 1.]]\n", "_t_matrix :\n", " [[1. +0.j 0. +0.j ]\n", " [0. +0.j 0.70710678+0.70710678j]]\n", "_toffoli_matrix :\n", " [[1. 0. 0. 0. 0. 0. 0. 0.]\n", " [0. 1. 0. 0. 0. 0. 0. 0.]\n", " [0. 0. 1. 0. 0. 0. 0. 0.]\n", " [0. 0. 0. 1. 0. 0. 0. 0.]\n", " [0. 0. 0. 0. 1. 0. 0. 0.]\n", " [0. 0. 0. 0. 0. 1. 0. 0.]\n", " [0. 0. 0. 0. 0. 0. 0. 1.]\n", " [0. 0. 0. 0. 0. 0. 1. 0.]]\n", "_wroot_matrix :\n", " [[ 0.70710678+0.j -0.5 -0.5j]\n", " [ 0.5 -0.5j 0.70710678+0.j ]]\n", "_x_matrix :\n", " [[0. 1.]\n", " [1. 0.]]\n", "_xx_matrix :\n", " [[0. 0. 0. 1.]\n", " [0. 0. 1. 0.]\n", " [0. 1. 0. 0.]\n", " [1. 0. 0. 0.]]\n", "_y_matrix :\n", " [[ 0.+0.j -0.-1.j]\n", " [ 0.+1.j 0.+0.j]]\n", "_yy_matrix :\n", " [[ 0.+0.j 0.-0.j 0.-0.j -1.+0.j]\n", " [ 0.+0.j 0.+0.j 1.-0.j 0.-0.j]\n", " [ 0.+0.j 1.-0.j 0.+0.j 0.-0.j]\n", " [-1.+0.j 0.+0.j 0.+0.j 0.+0.j]]\n", "_z_matrix :\n", " [[ 1. 0.]\n", " [ 0. -1.]]\n", "_zz_matrix :\n", " [[ 1. 0. 0. 0.]\n", " [ 0. -1. 0. -0.]\n", " [ 0. 0. -1. -0.]\n", " [ 0. -0. -0. 1.]]\n" ] } ], "source": [ "for name in dir(tc.gates):\n", " if name.endswith(\"_matrix\"):\n", " print(name, \":\\n\", getattr(tc.gates, name))" ] }, { "cell_type": "markdown", "id": "76a975be", "metadata": {}, "source": [ "**Arbitrary unitaries.** User-defined unitary gates may be implemented by specifying their matrix elements as an array. As an example, the unitary $S = \\begin{pmatrix} 1 & 0 \\\\ 0 & i\\end{pmatrix}$ -- which can also directly be added by calling ``c.s()``\n", "can be implemented as" ] }, { "cell_type": "code", "execution_count": 17, "id": "3e432d95", "metadata": {}, "outputs": [], "source": [ "c.unitary(0, unitary=np.array([[1, 0], [0, 1j]]), name=\"S\")\n", "\n", "# the optional name argument specifies how this gate is displayed when the circuit is output to \\LaTeX" ] }, { "cell_type": "markdown", "id": "3ab55dce", "metadata": {}, "source": [ "**Exponential gates.** Gates of the form $e^{i\\theta G}$ where matrix $G$ satisfies $G^2 = I$ admit a fast implementation via the ``exp1`` command, e.g., the two-qubit gate $e^{i\\theta Z\\otimes Z}$ acting on qubits $0$ and $1$" ] }, { "cell_type": "code", "execution_count": 18, "id": "2e536a58", "metadata": {}, "outputs": [], "source": [ "c.exp1(0, 1, theta=0.2, unitary=tc.gates._zz_matrix)" ] }, { "cell_type": "markdown", "id": "1b4f5918", "metadata": {}, "source": [ "General exponential gates, where $G^2\\neq 1$ can be implemented via the ``exp`` command:" ] }, { "cell_type": "code", "execution_count": 19, "id": "8b91ca7b", "metadata": {}, "outputs": [], "source": [ "c.exp(0, theta=0.2, unitary=np.array([[2, 0], [0, 1]]))" ] }, { "cell_type": "markdown", "id": "d041f1f1", "metadata": {}, "source": [ "**Non-unitary gates.**\n", "TensorCircuit also supports the application of non-unitary gates, either by providing a non-unitary matrix as the argument to ``c.unitary`` or by supplying a complex angle $\\theta$ to an exponential gate." ] }, { "cell_type": "code", "execution_count": 20, "id": "50d509e4", "metadata": {}, "outputs": [], "source": [ "c.unitary(0, unitary=np.array([[1, 2], [2, 3]]), name=\"non_unitary\")\n", "c.exp1(0, theta=0.2 + 1j, unitary=tc.gates._x_matrix)" ] }, { "cell_type": "markdown", "id": "a8feb800", "metadata": {}, "source": [ "Note that the non-unitary gates will lead to an output state that is no longer normalized since normalization is often unnecessary and takes extra time which can be avoided." ] }, { "cell_type": "markdown", "id": "4ce19540", "metadata": {}, "source": [ "## Specifying the Input State and Composing Circuits" ] }, { "cell_type": "markdown", "id": "e89da50d", "metadata": {}, "source": [ "By default, quantum circuits are applied to the initial all zero product state. Arbitrary initial states can be set by passing an array containing the input state amplitudes to the optional ``inputs`` argument of ``tc.Circuit``. For example, the maximally entangled state $\\frac{\\vert{00}\\rangle+\\vert{11}\\rangle}{\\sqrt{2}}$ can be input as follows." ] }, { "cell_type": "code", "execution_count": 21, "id": "5dce4e2b", "metadata": {}, "outputs": [], "source": [ "c1 = tc.Circuit(2, inputs=np.array([1, 0, 0, 1] / np.sqrt(2)))" ] }, { "cell_type": "markdown", "id": "c7874007", "metadata": {}, "source": [ "Circuits that act on the same number of qubits can be composed together via the ``c.append()`` or ``c.prepend()`` commands. With ``c1`` defined as above, we can create a new circuit ``c2`` and then compose them together:" ] }, { "cell_type": "code", "execution_count": 22, "id": "dcb563f1", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c2 = tc.Circuit(2)\n", "c2.cnot(1, 0)\n", "\n", "c3 = c1.append(c2)\n", "c3.state()" ] }, { "cell_type": "markdown", "id": "6b1ba8a8", "metadata": {}, "source": [ "## Circuit Transformation and Visualization" ] }, { "cell_type": "markdown", "id": "4c5e26a9", "metadata": {}, "source": [ "``tc.Circuit`` objects can be converted to and from Qiskit ``QuantumCircuit`` objects." ] }, { "cell_type": "code", "execution_count": 23, "id": "45f87a5e", "metadata": {}, "outputs": [], "source": [ "c = tc.Circuit(2)\n", "c.H(0)\n", "c.cnot(1, 0)\n", "cq = c.to_qiskit()" ] }, { "cell_type": "code", "execution_count": 24, "id": "c1484dcd", "metadata": {}, "outputs": [], "source": [ "c1 = tc.Circuit.from_qiskit(cq)" ] }, { "cell_type": "code", "execution_count": 25, "id": "398c1861", "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "[{'gatef': h,\n", " 'gate': Gate(\n", " name: 'h',\n", " tensor:\n", " ,\n", " edges: [\n", " Edge('cnot'[3] -> 'h'[0] ),\n", " Edge('h'[1] -> 'qb-1'[0] )\n", " ]),\n", " 'index': (0,),\n", " 'name': 'h',\n", " 'split': None,\n", " 'mpo': False},\n", " {'gatef': cnot,\n", " 'gate': Gate(\n", " name: 'cnot',\n", " tensor:\n", " ,\n", " edges: [\n", " Edge(Dangling Edge)[0],\n", " Edge(Dangling Edge)[1],\n", " Edge('cnot'[2] -> 'qb-2'[0] ),\n", " Edge('cnot'[3] -> 'h'[0] )\n", " ]),\n", " 'index': (1, 0),\n", " 'name': 'cnot',\n", " 'split': None,\n", " 'mpo': False}]" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# print the quantum circuit intermediate representation\n", "\n", "c1.to_qir()" ] }, { "cell_type": "markdown", "id": "6ef7a8bd", "metadata": {}, "source": [ "There are two ways to visualize quantum circuits generated in TensorCircuit. The first is to use ``c.tex()`` to get \\Latex quantikz commands.\n" ] }, { "cell_type": "code", "execution_count": 26, "id": "9a3394f3", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'\\\\begin{quantikz}\\n\\\\lstick{$\\\\ket{0}$}&\\\\gate{h} &\\\\targ{} &\\\\qw \\\\\\\\\\n\\\\lstick{$\\\\ket{0}$}&\\\\qw &\\\\ctrl{-1} &\\\\qw \\n\\\\end{quantikz}'" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.tex()" ] }, { "cell_type": "markdown", "id": "70dfb85d", "metadata": {}, "source": [ "The second method uses the draw function from [qiskit](https://qiskit.org/documentation/stubs/qiskit.circuit.QuantumCircuit.draw.html)." ] }, { "cell_type": "code", "execution_count": 27, "id": "f63d7baf", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.draw(output=\"mpl\")" ] } ], "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.8.0" } }, "nbformat": 4, "nbformat_minor": 5 }