{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# EffectiveLindbladian and effective_lindbladian_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": [
    "## EffectiveLindbladian\n",
    "\n",
    "Assume the following situation:\n",
    "\n",
    "- $B = \\{ B_\\alpha \\}$ is a orthonormalized Hermitian matrix basis with $B_0 = I/\\sqrt{d}$, where $d$ is dimension of CompositeSystem.\n",
    "- $\\rho$ is a density matrix.\n",
    "- $H = \\sum_{\\alpha=1}^{d^2-1} H_\\alpha B_\\alpha$ ($H_\\alpha \\in \\mathbb{R}$, $H \\in \\mathbb{C}^{d \\times d}$) : Hermitian matrix.\n",
    "- $J = \\sum_{\\alpha=0}^{d^2-1} J_\\alpha B_\\alpha$ ($J_\\alpha \\in \\mathbb{R}$, $J \\in \\mathbb{C}^{d \\times d}$) : Hermitian matrix.\n",
    "- $K$ is a Hermitian and positive semidifinite matrix, with $(\\alpha, \\beta)$ entries are $K_{\\alpha, \\beta}$. ($K_{\\alpha, \\beta} \\in \\mathbb{R}$,  $K \\in \\mathbb{C}^{(d^2-1) \\times (d^2-1)}$))\n",
    "\n",
    "Then Lindbladian operator $\\mathcal{L}$ is defined by $\\mathcal{L}(\\rho) = -i[H, \\rho] + \\{J, \\rho\\} + \\sum_{\\alpha, \\beta=1}^{d^2-1} K_{\\alpha, \\beta} B_\\alpha \\rho B^{\\dagger}_\\beta$.  \n",
    "Let $L^{cb}$ (resp. $L^{gb}$) be a Hilbert-Schmidt representation matrix of $\\mathcal{L}$ on computational basis (resp. on basis $B$).  \n",
    "We can write $L^{cb} = -i(H \\otimes I - I \\otimes \\bar{H}) + (J \\otimes I + I \\otimes \\bar{J}) + \\sum_{\\alpha, \\beta=1}^{d^2-1} K_{\\alpha, \\beta} B_\\alpha \\otimes \\overline{B_\\beta}$. And $L^{gb} \\in \\mathbb{R}^{d^2 \\times d^2}$.  \n",
    "The property `hs` of EffectiveLindbladian is a two-dimensional numpy array $L^{gb}$ in Quara.  \n",
    "Also, there is a relationship $G = e^L$, where $G$ is a `hs` of Gate and $e^L$ is a exponential of `hs` of EffectiveLindbladian.  \n",
    "The following terms are used in Quara:\n",
    "\n",
    "- $-i(H \\otimes I - I \\otimes \\bar{H})$ is called H-part.\n",
    "- $J \\otimes I + I \\otimes \\bar{J}$ is called J-part.\n",
    "- $\\sum_{\\alpha, \\beta=1}^{d^2-1} K_{\\alpha, \\beta} B_\\alpha \\otimes \\overline{B_\\beta}$ is called K-part.\n",
    "- The sum of J-part and K-part is called D-part.\n",
    "\n",
    "EffectiveLindbladian class inherits Gate class in Quara."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Generate from `effective_lindbladian_typical` module by specifying CompositeSystem and state mprocess (ex. “z-type1”)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type:\n",
      "EffectiveLindbladian\n",
      "\n",
      "Dim:\n",
      "2\n",
      "\n",
      "HS:\n",
      "[[ 0.          0.          0.          0.        ]\n",
      " [ 0.          0.          0.          0.        ]\n",
      " [ 0.          0.          0.         -3.14159265]\n",
      " [ 0.          0.          3.14159265  0.        ]]\n"
     ]
    }
   ],
   "source": [
    "from quara.objects.composite_system_typical import generate_composite_system\n",
    "from quara.objects.effective_lindbladian_typical import generate_effective_lindbladian_from_gate_name\n",
    "\n",
    "c_sys = generate_composite_system(\"qubit\", 1)\n",
    "el = generate_effective_lindbladian_from_gate_name(\"x\", c_sys)\n",
    "print(el)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Generate EffectiveLindbladian object directly using CompositeSystem and a numpy array."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type:\n",
      "EffectiveLindbladian\n",
      "\n",
      "Dim:\n",
      "2\n",
      "\n",
      "HS:\n",
      "[[ 0.          0.          0.          0.        ]\n",
      " [ 0.          0.          0.          0.        ]\n",
      " [ 0.          0.          0.         -3.14159265]\n",
      " [ 0.          0.          3.14159265  0.        ]]\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.effective_lindbladian import EffectiveLindbladian\n",
    "\n",
    "basis = get_normalized_pauli_basis(1)\n",
    "e_sys = ElementalSystem(0, basis)\n",
    "c_sys = CompositeSystem([e_sys])\n",
    "hs = np.array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, -np.pi], [0, 0, np.pi, 0]], dtype=np.float64)\n",
    "el = EffectiveLindbladian(c_sys, hs)\n",
    "print(el)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### specific properties\n",
    "The property `hs` of EffectiveLindbladian 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",
      "[[ 0.          0.          0.          0.        ]\n",
      " [ 0.          0.          0.          0.        ]\n",
      " [ 0.          0.          0.         -3.14159265]\n",
      " [ 0.          0.          3.14159265  0.        ]]\n"
     ]
    }
   ],
   "source": [
    "el = EffectiveLindbladian(c_sys, hs)\n",
    "print(f\"hs: \\n{el.hs}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The property `dim` of EffectiveLindbladian 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: {el.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 $e^L$ is TP(trace-preserving map), i.e. if and only if the first row of `hs` is zeros."
   ]
  },
  {
   "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]: [0. 0. 0. 0.]\n"
     ]
    }
   ],
   "source": [
    "print(f\"is_eq_constraint_satisfied(): {el.is_eq_constraint_satisfied()}\")\n",
    "print(f\"is_tp(): {el.is_tp()}\")\n",
    "print(f\"hs[0]: {el.hs[0]}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `is_ineq_constraint_satisfied()` function returns True, if and only if $e^L$ is CP(Complete-Positivity-Preserving), i.e. if and only if K-part is positive semidifinite matrix."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "is_eq_constraint_satisfied(): True\n",
      "is_cp(): True\n",
      "is_positive_semidefinite(): True\n"
     ]
    }
   ],
   "source": [
    "import quara.utils.matrix_util as mutil\n",
    "\n",
    "print(f\"is_eq_constraint_satisfied(): {el.is_eq_constraint_satisfied()}\")\n",
    "print(f\"is_cp(): {el.is_cp()}\")\n",
    "print(f\"is_positive_semidefinite(): {mutil.is_positive_semidefinite(el.calc_k_mat())}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### projection functions\n",
    "`calc_proj_eq_constraint()` function calculates the projection of EffectiveLindbladian on equal constraint.\n",
    "This function replaces the first row of `hs` with $[0,…,0]$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hs: \n",
      "[[ 0.          0.          0.          0.        ]\n",
      " [ 0.          0.          0.          0.        ]\n",
      " [ 0.          0.          0.         -3.14159265]\n",
      " [ 0.          0.          3.14159265  0.        ]]\n"
     ]
    }
   ],
   "source": [
    "hs = np.array(range(16), dtype=np.float64).reshape((4, 4))\n",
    "print(f\"hs: \\n{el.hs}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hs: \n",
      "[[ 0.  0.  0.  0.]\n",
      " [ 4.  5.  6.  7.]\n",
      " [ 8.  9. 10. 11.]\n",
      " [12. 13. 14. 15.]]\n"
     ]
    }
   ],
   "source": [
    "el = EffectiveLindbladian(c_sys, hs, is_physicality_required=False)\n",
    "proj_el = el.calc_proj_eq_constraint()\n",
    "print(f\"hs: \\n{proj_el.hs}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`calc_proj_ineq_constraint()` function calculates the projection of EffectiveLindbladian with hs on inequal constraint as follows:\n",
    "\n",
    "- Calculates H-part $H$, J-part $J$, and K-part $K$ from EffectiveLindbladian.\n",
    "- Executes singular value decomposition on $K$, $K = 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",
    "- $K^{\\prime} = U \\Lambda^{\\prime} U^{\\dagger}$\n",
    "- Let $\\text{HS}^{\\prime}$ be a Hilbert-Schmidt matrix representation of EffectiveLindbladian from $H, J, K^{\\prime}$.\n",
    "- The projection of EffectiveLindbladian is EffectiveLindbladian with `hs` = $\\text{HS}^{\\prime}$.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hs: \n",
      "[[ 8.12020183  1.71420693  5.06233752  7.16046811]\n",
      " [ 0.78579307 -5.04434853  2.49719848  1.93917625]\n",
      " [ 4.93766248  5.49719848 -2.88819756  4.92554488]\n",
      " [ 7.83953189  7.93917625  7.92554488 -0.18765574]]\n"
     ]
    }
   ],
   "source": [
    "el = EffectiveLindbladian(c_sys, hs, is_physicality_required=False)\n",
    "proj_el = el.calc_proj_ineq_constraint()\n",
    "print(f\"hs: \\n{proj_el.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",
      "flattened hs: [ 0.  1.  2.  3.  4.  5.  6.  7.  8.  9. 10. 11. 12. 13. 14. 15.]\n"
     ]
    }
   ],
   "source": [
    "print(f\"to_stacked_vector(): {el.to_stacked_vector()}\")\n",
    "print(f\"flattened hs: {el.hs.flatten()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If `on_para_eq_constraint` is True, then the first row of `hs` is equal to [0,…,0]. Thus, EffectiveLindbladian 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",
    "el = EffectiveLindbladian(c_sys, hs, is_physicality_required=False, on_para_eq_constraint=True)\n",
    "print(f\"to_var(): {el.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",
    "el = EffectiveLindbladian(c_sys, hs, is_physicality_required=False, on_para_eq_constraint=False)\n",
    "print(f\"to_var(): {el.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",
      "[[    0.     0.     0.     0.]\n",
      " [    0. -1021.     0.     0.]\n",
      " [    0.     0. -1021.     0.]\n",
      " [    0.     0.     0. -1021.]]\n"
     ]
    }
   ],
   "source": [
    "zero_el = el.generate_zero_obj()\n",
    "print(f\"zero: \\n{zero_el.hs}\")\n",
    "origin_el = el.generate_origin_obj()\n",
    "print(f\"origin: \\n{origin_el.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",
    "el1 = EffectiveLindbladian(c_sys, hs1, is_physicality_required=False)\n",
    "hs2 = np.array(range(16, 32), dtype=np.float64).reshape((4, 4))\n",
    "el2 = EffectiveLindbladian(c_sys, hs2, is_physicality_required=False)\n",
    "\n",
    "print(el1.hs)\n",
    "print(el2.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{(el1 + el2).hs}\")\n",
    "print(f\"subtraction: \\n{(el1 - el2).hs}\")\n",
    "print(f\"right multiplication: \\n{(2 * el1).hs}\")\n",
    "print(f\"left multiplication: \\n{(el1 * 2).hs}\")\n",
    "print(f\"division: \\n{(el1 / 2).hs}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### calc_gradient functions\n",
    "Calculates gradient of EffectiveLindbladian 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_el = el.calc_gradient(0)\n",
    "print(f\"hs: \\n{grad_el.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",
      "[[0.+0.j         0.+1.57079633j 0.-1.57079633j 0.+0.j        ]\n",
      " [0.+1.57079633j 0.+0.j         0.+0.j         0.-1.57079633j]\n",
      " [0.-1.57079633j 0.+0.j         0.+0.j         0.+1.57079633j]\n",
      " [0.+0.j         0.-1.57079633j 0.+1.57079633j 0.+0.j        ]]\n"
     ]
    }
   ],
   "source": [
    "from quara.objects.matrix_basis import get_comp_basis\n",
    "\n",
    "el = generate_effective_lindbladian_from_gate_name(\"x\", c_sys)\n",
    "converted_hs = el.convert_basis(get_comp_basis())\n",
    "print(f\"hs: \\n{converted_hs}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### calc_h_mat\n",
    "Calculates the matrix $H = \\sum_{\\alpha=1}^{d^2-1} H_\\alpha B_\\alpha$, with $H_\\alpha = \\frac{i}{2d} \\text{Tr}[L^{cb}(B_\\alpha \\otimes I - I \\otimes \\overline{B_\\alpha})]$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "calc_h_mat(): \n",
      "[[0.        +0.j 1.57079633+0.j]\n",
      " [1.57079633+0.j 0.        +0.j]]\n"
     ]
    }
   ],
   "source": [
    "el = generate_effective_lindbladian_from_gate_name(\"x\", c_sys)\n",
    "print(f\"calc_h_mat(): \\n{el.calc_h_mat()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### calc_j_mat\n",
    "Calculates the matrix $J = \\sum_{\\alpha=0}^{d^2-1} J_\\alpha B_\\alpha$, with $J_\\alpha = \\frac{i}{2d(1 + \\delta_{0,\\alpha})} \\text{Tr}[L^{cb}(B_\\alpha \\otimes I + I \\otimes \\overline{B_\\alpha})]$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "calc_j_mat(): \n",
      "[[0.+0.j 0.+0.j]\n",
      " [0.+0.j 0.+0.j]]\n"
     ]
    }
   ],
   "source": [
    "el = generate_effective_lindbladian_from_gate_name(\"x\", c_sys)\n",
    "print(f\"calc_j_mat(): \\n{el.calc_j_mat()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### calc_k_mat\n",
    "Calculates the matrix $K$, with $(\\alpha, \\beta)$ entry $K_{\\alpha, \\beta} = \\text{Tr}[L^{cb}(B_\\alpha \\otimes \\overline{B_\\beta})]$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "calc_k_mat(): \n",
      "[[0.+0.j 0.+0.j 0.+0.j]\n",
      " [0.+0.j 0.+0.j 0.+0.j]\n",
      " [0.+0.j 0.+0.j 0.+0.j]]\n"
     ]
    }
   ],
   "source": [
    "el = generate_effective_lindbladian_from_gate_name(\"x\", c_sys)\n",
    "print(f\"calc_k_mat(): \\n{el.calc_k_mat()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### calc_h_part\n",
    "Calculates H-part = $-i(H \\otimes I - I \\otimes \\bar{H})$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "calc_h_part(): \n",
      "[[ 0.          0.          0.          0.        ]\n",
      " [ 0.          0.          0.          0.        ]\n",
      " [ 0.          0.          0.         -3.14159265]\n",
      " [ 0.          0.          3.14159265  0.        ]]\n"
     ]
    }
   ],
   "source": [
    "el = generate_effective_lindbladian_from_gate_name(\"x\", c_sys)\n",
    "print(f\"calc_h_part(): \\n{el.calc_h_part()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### calc_j_part\n",
    "Calculates J-part = $J \\otimes I + I \\otimes \\bar{J}$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "calc_j_part(): \n",
      "[[0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "el = generate_effective_lindbladian_from_gate_name(\"x\", c_sys)\n",
    "print(f\"calc_j_part(): \\n{el.calc_j_part()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### calc_k_part\n",
    "Calculates K-part = $\\sum_{\\alpha, \\beta=1}^{d^2-1} K_{\\alpha, \\beta} B_\\alpha \\otimes \\overline{B_\\beta}$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "calc_k_part(): \n",
      "[[0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "el = generate_effective_lindbladian_from_gate_name(\"x\", c_sys)\n",
    "print(f\"calc_k_part(): \\n{el.calc_k_part()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### calc_d_part\n",
    "Calculates D-part = J-part + K-part"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "calc_d_part(): \n",
      "[[0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "el = generate_effective_lindbladian_from_gate_name(\"x\", c_sys)\n",
    "print(f\"calc_d_part(): \\n{el.calc_d_part()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### to_kraus_matrices\n",
    "Returns Kraus matrices of EffectiveLindbladian."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "to_kraus_matrices(): \n",
      "[((1.7724538509055159-4.030482324789019e-33j), array([[ 5.00000000e-01+0.j , -2.01094314e-17-0.5j],\n",
      "       [ 2.01094314e-17-0.5j,  5.00000000e-01+0.j ]])), ((4.0304823506953305e-33+1.7724538509055157j), array([[ 5.00000000e-01+0.00000000e+00j,  2.01094314e-17+5.00000000e-01j],\n",
      "       [-2.01094314e-17+5.00000000e-01j,  5.00000000e-01+1.54074396e-33j]]))]\n"
     ]
    }
   ],
   "source": [
    "el = generate_effective_lindbladian_from_gate_name(\"x\", c_sys)\n",
    "print(f\"to_kraus_matrices(): \\n{el.to_kraus_matrices()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### to_gate\n",
    "Generates Gate from EffectiveLindbladian."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type:\n",
      "Gate\n",
      "\n",
      "Dim:\n",
      "2\n",
      "\n",
      "HS:\n",
      "[[ 1.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00]\n",
      " [ 0.00000000e+00  1.00000000e+00  0.00000000e+00  0.00000000e+00]\n",
      " [-0.00000000e+00 -0.00000000e+00 -1.00000000e+00 -2.35127499e-16]\n",
      " [ 0.00000000e+00  0.00000000e+00  2.35127499e-16 -1.00000000e+00]]\n"
     ]
    }
   ],
   "source": [
    "el = generate_effective_lindbladian_from_gate_name(\"x\", c_sys)\n",
    "print(el.to_gate())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### some utility functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "is_tp(): True\n",
      "is_cp(): True\n"
     ]
    }
   ],
   "source": [
    "print(f\"is_tp(): {el.is_tp()}\")\n",
    "print(f\"is_cp(): {el.is_cp()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## effective_lindbladian_typical\n",
    "`generate_effective_lindbladian_object_from_gate_name_object_name()` function in `effective_lindbladian_typical` module can easily generate objects related to State.  \n",
    "The `generate_effective_lindbladian_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()`  and `get_gate_names_2qubit_asymmetric()` function. The tensor product of state_name \"a\", \"b\" is written \"a_b\".\n",
    "- `object_name` can be the following string:\n",
    "  - \"hamiltonian_vec\" - the vector representation of the Hamiltonian of a gate.\n",
    "  - \"hamiltonian_mat\" - the Hamiltonian matrix of a gate.\n",
    "  - \"effective_lindbladian_mat\" - the Hilbert-Schmidt representation matrix of an effective lindbladian.\n",
    "  - \"effective_lindbladian\" - EffectiveLindbladian object.\n",
    "- `c_sys` - CompositeSystem of objects related to EffectiveLindbladian. Specify when `object_name` is \"effective_lindbladian\".\n",
    "- `is_physicality_required` - Whether the generated object is physicality required, by default True."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "from quara.objects.gate_typical import (\n",
    "    get_gate_names,\n",
    "    get_gate_names_2qubit_asymmetric,\n",
    ")\n",
    "from quara.objects.effective_lindbladian_typical import generate_effective_lindbladian_object_from_gate_name_object_name\n",
    "\n",
    "#get_gate_names()\n",
    "#get_gate_names_2qubit_asymmetric()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### object_name = \"hamiltonian_vec\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-2.22144147  2.22144147  0.          0.        ]\n"
     ]
    }
   ],
   "source": [
    "vec = generate_effective_lindbladian_object_from_gate_name_object_name(\"x\", \"hamiltonian_vec\")\n",
    "print(vec)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### object_name = “hamiltonian_mat”"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[-1.57079633+0.j  1.57079633+0.j]\n",
      " [ 1.57079633+0.j -1.57079633+0.j]]\n"
     ]
    }
   ],
   "source": [
    "mat = generate_effective_lindbladian_object_from_gate_name_object_name(\"x\", \"hamiltonian_mat\")\n",
    "print(mat)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### object_name = “effective_lindbladian_mat”"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0.          0.          0.          0.        ]\n",
      " [ 0.          0.          0.          0.        ]\n",
      " [ 0.          0.          0.         -3.14159265]\n",
      " [ 0.          0.          3.14159265  0.        ]]\n"
     ]
    }
   ],
   "source": [
    "mat = generate_effective_lindbladian_object_from_gate_name_object_name(\"x\", \"effective_lindbladian_mat\")\n",
    "print(mat)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### object_name = “effective_lindbladian”"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type:\n",
      "EffectiveLindbladian\n",
      "\n",
      "Dim:\n",
      "2\n",
      "\n",
      "HS:\n",
      "[[ 0.          0.          0.          0.        ]\n",
      " [ 0.          0.          0.          0.        ]\n",
      " [ 0.          0.          0.         -3.14159265]\n",
      " [ 0.          0.          3.14159265  0.        ]]\n"
     ]
    }
   ],
   "source": [
    "c_sys = generate_composite_system(\"qubit\", 1)\n",
    "el = generate_effective_lindbladian_object_from_gate_name_object_name(\"x\", \"effective_lindbladian\", c_sys=c_sys)\n",
    "print(el)"
   ]
  }
 ],
 "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
}
