{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Gate and gate_typical"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "np.set_printoptions(linewidth=200)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Gate\n",
    "Mathematically a quantum gate is a linear trace-preserving and completely positive (L-TPCP) map on the space of quantum states, and there are several different matrix representations for quantum gate. In Quara, a class Gate is based on the Hilbert-Schmidt matrix representation of a gate with respect to the matrix basis in the CompositeSystem.  \n",
    "This matrix representation is denote `hs` in Quara. `hs` is a 2-dimensional numpy array.  \n",
    "\n",
    "Example.  \n",
    "$X$ maps each element of basis as follows\n",
    "$X = \\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\\\ \\end{bmatrix}$ maps each element of basis $B = \\{ I/\\sqrt{2},  X/\\sqrt{2},  Y/\\sqrt{2},  Z/\\sqrt{2} \\}$ as follows:\n",
    "\n",
    "- $I/\\sqrt{2} \\mapsto X \\cdot I/\\sqrt{2} \\cdot X^\\dagger = I/\\sqrt{2} = [1, 0, 0, 0]^T$ on basis $B$.\n",
    "- $X/\\sqrt{2} \\mapsto X \\cdot X/\\sqrt{2} \\cdot X^\\dagger = X/\\sqrt{2} = [0, 1, 0, 0]^T$ on basis $B$.\n",
    "- $Y/\\sqrt{2} \\mapsto X \\cdot Y/\\sqrt{2} \\cdot X^\\dagger = -Y/\\sqrt{2} = [0, 0, -1, 0]^T$ on basis $B$.\n",
    "- $Z/\\sqrt{2} \\mapsto X \\cdot Z/\\sqrt{2} \\cdot X^\\dagger = -Z/\\sqrt{2} = [0, 0, 0, -1]^T$ on basis $B$.\n",
    "\n",
    "Therefore, the Hilbert-Schmidt matrix representation `hs` of $X$ is $\\begin{bmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & -1 & 0 \\\\ 0 & 0 & 0 & -1 \\end{bmatrix}$."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The methods for generating a Gate includes the following:\n",
    "\n",
    "- Generate from `gate_typical` module\n",
    "- Generate Gate object directly\n",
    "\n",
    "Generate from `gate_typical` module by specifying CompositeSystem and gate name (ex. \"x\")."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type:\n",
      "Gate\n",
      "\n",
      "Dim:\n",
      "2\n",
      "\n",
      "HS:\n",
      "[[ 1.  0.  0.  0.]\n",
      " [ 0.  1.  0.  0.]\n",
      " [ 0.  0. -1.  0.]\n",
      " [ 0.  0.  0. -1.]]\n"
     ]
    }
   ],
   "source": [
    "from quara.objects.composite_system_typical import generate_composite_system\n",
    "from quara.objects.gate_typical import generate_gate_from_gate_name\n",
    "\n",
    "c_sys = generate_composite_system(\"qubit\", 1)\n",
    "gate = generate_gate_from_gate_name(\"x\", c_sys)\n",
    "print(gate)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Generate Gate object directly using CompositeSystem and a numpy array."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type:\n",
      "Gate\n",
      "\n",
      "Dim:\n",
      "2\n",
      "\n",
      "HS:\n",
      "[[ 1.  0.  0.  0.]\n",
      " [ 0.  1.  0.  0.]\n",
      " [ 0.  0. -1.  0.]\n",
      " [ 0.  0.  0. -1.]]\n"
     ]
    }
   ],
   "source": [
    "from quara.objects.composite_system import CompositeSystem\n",
    "from quara.objects.elemental_system import ElementalSystem\n",
    "from quara.objects.matrix_basis import get_normalized_pauli_basis\n",
    "from quara.objects.gate import Gate\n",
    "\n",
    "basis = get_normalized_pauli_basis(1)\n",
    "e_sys = ElementalSystem(0, basis)\n",
    "c_sys = CompositeSystem([e_sys])\n",
    "hs = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 0], [0, 0, 0, -1]], dtype=np.float64)\n",
    "gate = Gate(c_sys, hs)\n",
    "print(gate)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### specific properties\n",
    "The property `hs` of Gate is a 2-dimensional numpy array specified by the constructor argument `hs`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hs: \n",
      "[[ 1.  0.  0.  0.]\n",
      " [ 0.  1.  0.  0.]\n",
      " [ 0.  0. -1.  0.]\n",
      " [ 0.  0.  0. -1.]]\n"
     ]
    }
   ],
   "source": [
    "gate = Gate(c_sys, hs)\n",
    "print(f\"hs: \\n{gate.hs}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The property `dim` of Gate is the size of square matrix `hs`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dim: 2\n",
      "size of square matrix hs: 2\n"
     ]
    }
   ],
   "source": [
    "print(f\"dim: {gate.dim}\")\n",
    "print(f\"size of square matrix hs: {int(np.sqrt(hs.shape[0]))}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### functions to check constraints\n",
    "The `is_eq_constraint_satisfied()` function returns True, if and only if `hs` is TP(trace-preserving map), i.e. if and only if the first row of `hs` is equal to $[ 1, 0, \\dots, 0 ]$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "is_eq_constraint_satisfied(): True\n",
      "is_tp(): True\n",
      "hs[0]: [1. 0. 0. 0.]\n"
     ]
    }
   ],
   "source": [
    "print(f\"is_eq_constraint_satisfied(): {gate.is_eq_constraint_satisfied()}\")\n",
    "print(f\"is_tp(): {gate.is_tp()}\")\n",
    "print(f\"hs[0]: {gate.hs[0]}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `is_ineq_constraint_satisfied()` function returns True, if and only if `hs` is CP(Complete-Positivity-Preserving), i.e. if and only if Choi matrix of `hs` is positive semidifinite matrix."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "is_ineq_constraint_satisfied(): True\n",
      "is_cp(): True\n"
     ]
    }
   ],
   "source": [
    "print(f\"is_ineq_constraint_satisfied(): {gate.is_ineq_constraint_satisfied()}\")\n",
    "print(f\"is_cp(): {gate.is_cp()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### projection functions\n",
    "`calc_proj_eq_constraint()` function calculates the projection of Gate on equal constraint.  \n",
    "This function replaces the first row of `hs` with $[ 1, 0, \\dots, 0 ]$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hs: \n",
      "[[ 1.  0.  0.  0.]\n",
      " [ 0.  1.  0.  0.]\n",
      " [ 0.  0. -1.  0.]\n",
      " [ 0.  0.  0. -1.]]\n"
     ]
    }
   ],
   "source": [
    "hs = np.array(range(16), dtype=np.float64).reshape((4, 4))\n",
    "print(f\"hs: \\n{gate.hs}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hs: \n",
      "[[ 1.  0.  0.  0.]\n",
      " [ 4.  5.  6.  7.]\n",
      " [ 8.  9. 10. 11.]\n",
      " [12. 13. 14. 15.]]\n"
     ]
    }
   ],
   "source": [
    "gate = Gate(c_sys, hs, is_physicality_required=False)\n",
    "proj_gate = gate.calc_proj_eq_constraint()\n",
    "print(f\"hs: \\n{proj_gate.hs}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`calc_proj_ineq_constraint()` function calculates the projection of Gate with `hs` on inequal constraint as follows:\n",
    "\n",
    "- Let $\\text{Choi}$ be Choi matrix of `hs`\n",
    "- Executes singular value decomposition on $\\text{Choi}$, $\\text{Choi} = U \\Lambda U^{\\dagger}$, where $\\Lambda = \\text{diag}[\\lambda_0, \\dots , \\lambda_{d-1}]$, and $\\lambda_{i} \\in \\mathbb{R}$.\n",
    "- $\\lambda^{\\prime}_{i} := \\begin{cases} \\lambda_{i} & (\\lambda_{i} \\geq 0) \\\\ 0 & (\\lambda_{i} < 0) \\end{cases}$\n",
    "- $\\Lambda^{\\prime} = \\text{diag}[\\lambda^{\\prime}_0, \\dots , \\lambda^{\\prime}_{d-1}]$\n",
    "- $\\text{Choi}^{\\prime} = U \\Lambda^{\\prime} U^{\\dagger}$\n",
    "- Let $\\text{HS}^{\\prime}$ be Hilbert-Schmidt matrix representation of $\\text{Choi}^{\\prime}$\n",
    "- The projection of Gate is Gate with `hs` = $\\text{HS}^{\\prime}$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hs: \n",
      "[[15.84558996  4.43570942  5.29265833  6.14960724]\n",
      " [ 2.63097854  2.34702553  3.08437192  3.44443746]\n",
      " [ 4.98440409  4.50900796  4.73510284  5.71575945]\n",
      " [ 7.33782964  6.29370952  7.14039548  7.60980059]]\n"
     ]
    }
   ],
   "source": [
    "gate = Gate(c_sys, hs, is_physicality_required=False)\n",
    "proj_gate = gate.calc_proj_ineq_constraint()\n",
    "print(f\"hs: \\n{proj_gate.hs}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### functions to transform parameters\n",
    "`to_stacked_vector()` function returns a one-dimensional numpy array of all variables. This is equal to flattened `hs`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "to_stacked_vector(): [ 0.  1.  2.  3.  4.  5.  6.  7.  8.  9. 10. 11. 12. 13. 14. 15.]\n",
      "lattened hs: [ 0.  1.  2.  3.  4.  5.  6.  7.  8.  9. 10. 11. 12. 13. 14. 15.]\n"
     ]
    }
   ],
   "source": [
    "print(f\"to_stacked_vector(): {gate.to_stacked_vector()}\")\n",
    "print(f\"lattened hs: {gate.hs.flatten()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If `on_para_eq_constraint` is True, then the first row of `hs` is equal to $[1, 0, \\dots, 0]$. Thus, Gate is characterized by the second and subsequent rows of `hs`.  \n",
    "Therefore, `to_var()` function returns the flattened second and subsequent rows of `hs`, where `on_para_eq_constraint` is True."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "to_var(): [ 4.  5.  6.  7.  8.  9. 10. 11. 12. 13. 14. 15.]\n"
     ]
    }
   ],
   "source": [
    "# on_para_eq_constraint=True\n",
    "gate = Gate(c_sys, hs, is_physicality_required=False, on_para_eq_constraint=True)\n",
    "print(f\"to_var(): {gate.to_var()}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "to_var(): [ 0.  1.  2.  3.  4.  5.  6.  7.  8.  9. 10. 11. 12. 13. 14. 15.]\n"
     ]
    }
   ],
   "source": [
    "# on_para_eq_constraint=False\n",
    "gate = Gate(c_sys, hs, is_physicality_required=False, on_para_eq_constraint=False)\n",
    "print(f\"to_var(): {gate.to_var()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### functions to generate special objects"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "zero: \n",
      "[[0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]]\n",
      "origin: \n",
      "[[1. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "zero_gate = gate.generate_zero_obj()\n",
    "print(f\"zero: \\n{zero_gate.hs}\")\n",
    "origin_gate = gate.generate_origin_obj()\n",
    "print(f\"origin: \\n{origin_gate.hs}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### supports arithmetic operations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0.  1.  2.  3.]\n",
      " [ 4.  5.  6.  7.]\n",
      " [ 8.  9. 10. 11.]\n",
      " [12. 13. 14. 15.]]\n",
      "[[16. 17. 18. 19.]\n",
      " [20. 21. 22. 23.]\n",
      " [24. 25. 26. 27.]\n",
      " [28. 29. 30. 31.]]\n"
     ]
    }
   ],
   "source": [
    "hs1 = np.array(range(16), dtype=np.float64).reshape((4, 4))\n",
    "gate1 = Gate(c_sys, hs1, is_physicality_required=False)\n",
    "hs2 = np.array(range(16, 32), dtype=np.float64).reshape((4, 4))\n",
    "gate2 = Gate(c_sys, hs2, is_physicality_required=False)\n",
    "\n",
    "print(gate1.hs)\n",
    "print(gate2.hs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sum: \n",
      "[[16. 18. 20. 22.]\n",
      " [24. 26. 28. 30.]\n",
      " [32. 34. 36. 38.]\n",
      " [40. 42. 44. 46.]]\n",
      "subtraction: \n",
      "[[-16. -16. -16. -16.]\n",
      " [-16. -16. -16. -16.]\n",
      " [-16. -16. -16. -16.]\n",
      " [-16. -16. -16. -16.]]\n",
      "right multiplication: \n",
      "[[ 0.  2.  4.  6.]\n",
      " [ 8. 10. 12. 14.]\n",
      " [16. 18. 20. 22.]\n",
      " [24. 26. 28. 30.]]\n",
      "left multiplication: \n",
      "[[ 0.  2.  4.  6.]\n",
      " [ 8. 10. 12. 14.]\n",
      " [16. 18. 20. 22.]\n",
      " [24. 26. 28. 30.]]\n",
      "division: \n",
      "[[0.  0.5 1.  1.5]\n",
      " [2.  2.5 3.  3.5]\n",
      " [4.  4.5 5.  5.5]\n",
      " [6.  6.5 7.  7.5]]\n"
     ]
    }
   ],
   "source": [
    "print(f\"sum: \\n{(gate1 + gate2).hs}\")\n",
    "print(f\"subtraction: \\n{(gate1 - gate2).hs}\")\n",
    "print(f\"right multiplication: \\n{(2 * gate1).hs}\")\n",
    "print(f\"left multiplication: \\n{(gate1 * 2).hs}\")\n",
    "print(f\"division: \\n{(gate1 / 2).hs}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### calc_gradient functions\n",
    "Calculates gradient of Gate with variable index."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hs: \n",
      "[[1. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "grad_gate = gate.calc_gradient(0)\n",
    "print(f\"hs: \\n{grad_gate.hs}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### convert_basis function\n",
    "Returns `hs` converted to the specified basis."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hs: \n",
      "[[-2.23711432e-17+0.j  0.00000000e+00+0.j  0.00000000e+00+0.j  1.00000000e+00+0.j]\n",
      " [ 0.00000000e+00+0.j  0.00000000e+00+0.j  1.00000000e+00+0.j  0.00000000e+00+0.j]\n",
      " [ 0.00000000e+00+0.j  1.00000000e+00+0.j  0.00000000e+00+0.j  0.00000000e+00+0.j]\n",
      " [ 1.00000000e+00+0.j  0.00000000e+00+0.j  0.00000000e+00+0.j -2.23711432e-17+0.j]]\n"
     ]
    }
   ],
   "source": [
    "from quara.objects.matrix_basis import get_comp_basis\n",
    "\n",
    "gate = generate_gate_from_gate_name(\"x\", c_sys)\n",
    "converted_hs = gate.convert_basis(get_comp_basis())\n",
    "print(f\"hs: \\n{converted_hs}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### to_choi_matrix\n",
    "Returns Choi matrix of Gate."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "to_choi_matrix(): \n",
      "[[0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n",
      " [0.+0.j 1.+0.j 1.+0.j 0.+0.j]\n",
      " [0.+0.j 1.+0.j 1.+0.j 0.+0.j]\n",
      " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]\n",
      "to_choi_matrix_with_dict(): \n",
      "[[0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n",
      " [0.+0.j 1.+0.j 1.+0.j 0.+0.j]\n",
      " [0.+0.j 1.+0.j 1.+0.j 0.+0.j]\n",
      " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]\n",
      "to_choi_matrix_with_sparsity(): \n",
      "[[0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n",
      " [0.+0.j 1.+0.j 1.+0.j 0.+0.j]\n",
      " [0.+0.j 1.+0.j 1.+0.j 0.+0.j]\n",
      " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]\n"
     ]
    }
   ],
   "source": [
    "gate = generate_gate_from_gate_name(\"x\", c_sys)\n",
    "print(f\"to_choi_matrix(): \\n{gate.to_choi_matrix()}\")\n",
    "print(f\"to_choi_matrix_with_dict(): \\n{gate.to_choi_matrix_with_dict()}\")\n",
    "print(f\"to_choi_matrix_with_sparsity(): \\n{gate.to_choi_matrix_with_sparsity()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### to_kraus_matrices\n",
    "Returns Kraus matrices of Gate."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "to_kraus_matrices(): \n",
      "[array([[0.+0.j, 1.+0.j],\n",
      "       [1.+0.j, 0.+0.j]])]\n"
     ]
    }
   ],
   "source": [
    "gate = generate_gate_from_gate_name(\"x\", c_sys)\n",
    "print(f\"to_kraus_matrices(): \\n{gate.to_kraus_matrices()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### to_process_matrix\n",
    "Returns process matrix of Gate."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "to_process_matrix(): \n",
      "[[-2.23711432e-17+0.j  0.00000000e+00+0.j  0.00000000e+00+0.j  0.00000000e+00+0.j]\n",
      " [ 0.00000000e+00+0.j  1.00000000e+00+0.j  1.00000000e+00+0.j  0.00000000e+00+0.j]\n",
      " [ 0.00000000e+00+0.j  1.00000000e+00+0.j  1.00000000e+00+0.j  0.00000000e+00+0.j]\n",
      " [ 0.00000000e+00+0.j  0.00000000e+00+0.j  0.00000000e+00+0.j -2.23711432e-17+0.j]]\n"
     ]
    }
   ],
   "source": [
    "gate = generate_gate_from_gate_name(\"x\", c_sys)\n",
    "print(f\"to_process_matrix(): \\n{gate.to_process_matrix()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### some utility functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "is_tp(): True\n",
      "is_cp(): True\n"
     ]
    }
   ],
   "source": [
    "print(f\"is_tp(): {gate.is_tp()}\")\n",
    "print(f\"is_cp(): {gate.is_cp()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## gate_typical\n",
    "`generate_gate_object_from_gate_name_object_name()` function in `gate_typical` module can easily generate objects related to Gate.  \n",
    "The `generate_gate_object_from_gate_name_object_name()` function has the following arguments:\n",
    "\n",
    "- The string that can be specified for `gate_name` can be checked by executing the `get_gate_names()` function. The tensor product of state_name \"a\", \"b\" is written \"a_b\".\n",
    "- `object_name` can be the following string:\n",
    "  - \"unitary_mat\" - unitary matrix of the gate.\n",
    "  - \"gate_mat\" - The Hilbert-Schmidt matrix representation of the gate.\n",
    "  - \"gate\" - Gate object.\n",
    "- `c_sys` - CompositeSystem of objects related to Gate. Specify when `object_name` is \"gate\".\n",
    "- `is_physicality_required` - Whether the generated object is physicality required, by default True."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "from quara.objects.gate_typical import (\n",
    "    get_gate_names,\n",
    "    generate_gate_object_from_gate_name_object_name,\n",
    ")\n",
    "\n",
    "#get_gate_names()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### object_name = \"unitary_mat\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.+0.j 1.+0.j]\n",
      " [1.+0.j 0.+0.j]]\n"
     ]
    }
   ],
   "source": [
    "mat = generate_gate_object_from_gate_name_object_name(\"x\", \"unitary_mat\")\n",
    "print(mat)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### object_name = \"gate_mat\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1.  0.  0.  0.]\n",
      " [ 0.  1.  0.  0.]\n",
      " [ 0.  0. -1.  0.]\n",
      " [ 0.  0.  0. -1.]]\n"
     ]
    }
   ],
   "source": [
    "mat = generate_gate_object_from_gate_name_object_name(\"x\", \"gate_mat\")\n",
    "print(mat)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### object_name = \"gate\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type:\n",
      "Gate\n",
      "\n",
      "Dim:\n",
      "2\n",
      "\n",
      "HS:\n",
      "[[ 1.  0.  0.  0.]\n",
      " [ 0.  1.  0.  0.]\n",
      " [ 0.  0. -1.  0.]\n",
      " [ 0.  0.  0. -1.]]\n"
     ]
    }
   ],
   "source": [
    "c_sys = generate_composite_system(\"qubit\", 1)\n",
    "gate = generate_gate_object_from_gate_name_object_name(\"x\", \"gate\", c_sys=c_sys)\n",
    "print(gate)"
   ]
  }
 ],
 "metadata": {
  "hide_input": false,
  "kernelspec": {
   "display_name": "Python 3",
   "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.10"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
