|
87 | 87 | "\n",
|
88 | 88 | "By increasing $N$ we can improve our estimation for $P(0)$ and thus improve our estimation for $\\theta$.\n",
|
89 | 89 | "\n",
|
90 | | - "For extimating $\\varphi$ we will need to calculate $\\langle X \\rangle$ and $\\langle Y \\rangle$ expectation values.\n", |
| 90 | + "For estimating $\\varphi$ we will need to calculate $\\langle X \\rangle$ and $\\langle Y \\rangle$ expectation values. Before prociding, let's write the code that estimates the expectation value of the $Z$ operator. Note that we will use the same function for $\\langle X \\rangle$ and $\\langle Y \\rangle,ドル with some preprocessings. \n", |
91 | 91 | "\n",
|
| 92 | + "First of all the libraries that we are going to use:\n", |
92 | 93 | "\n",
|
93 | 94 | "[1]: https://github.com/DavitKhach/quantum-algorithms-tutorials\n",
|
94 | | - "[2]: https://www.cambridge.org/am/academic/subjects/physics/quantum-physics-quantum-information-and-quantum-computation/quantum-computation-and-quantum-information-10th-anniversary-edition?format=HB" |
| 95 | + "[2]: https://www.cambridge.org/am/academic/subjects/physics/quantum-physics-quantum-information-and-quantum-computation/quantum-computation-and-quantum-information-10th-anniversary-edition?format=HB\n", |
| 96 | + "[3]: https://en.wikipedia.org/wiki/Purity_(quantum_mechanics)" |
95 | 97 | ]
|
96 | 98 | },
|
97 | 99 | {
|
98 | 100 | "cell_type": "code",
|
99 | | - "execution_count": null, |
| 101 | + "execution_count": 1, |
100 | 102 | "metadata": {},
|
101 | 103 | "outputs": [],
|
102 | | - "source": [] |
| 104 | + "source": [ |
| 105 | + "from qiskit import *\n", |
| 106 | + "import numpy as np\n", |
| 107 | + "from random import random\n", |
| 108 | + "import warnings" |
| 109 | + ] |
| 110 | + }, |
| 111 | + { |
| 112 | + "cell_type": "markdown", |
| 113 | + "metadata": {}, |
| 114 | + "source": [ |
| 115 | + "The function for $\\langle Z \\rangle$" |
| 116 | + ] |
| 117 | + }, |
| 118 | + { |
| 119 | + "cell_type": "code", |
| 120 | + "execution_count": 2, |
| 121 | + "metadata": {}, |
| 122 | + "outputs": [], |
| 123 | + "source": [ |
| 124 | + "def z_expectation_from_counts(counts, index, shots):\n", |
| 125 | + " \"\"\"\n", |
| 126 | + " Calculate Z expectation value for one qubit. e.g <ZII>, <IZI>, <ZI>\n", |
| 127 | + " :param shots: The number of executions of the quantum experiment that\n", |
| 128 | + " gave the counts.\n", |
| 129 | + " :param index: index of the qubut. If index = 0 we should take\n", |
| 130 | + " key[-1] result, because of the Qiskit indexing convention.\n", |
| 131 | + " :param counts: dict {'00': 358, '01': 311, '10': 109, '11': 246}\n", |
| 132 | + " :return: Z expectation value <Z> = P(0) - P(1) = 2P(0) - 1, where\n", |
| 133 | + " P(i) is the probability for the qubit being in the |i> state\n", |
| 134 | + " \"\"\"\n", |
| 135 | + "\n", |
| 136 | + " probability_of_0 = 0\n", |
| 137 | + "\n", |
| 138 | + " for key in counts.keys():\n", |
| 139 | + " if key[-index - 1] == '0':\n", |
| 140 | + " probability_of_0 += counts[key] / shots\n", |
| 141 | + "\n", |
| 142 | + " return 2 * probability_of_0 - 1" |
| 143 | + ] |
| 144 | + }, |
| 145 | + { |
| 146 | + "cell_type": "markdown", |
| 147 | + "metadata": {}, |
| 148 | + "source": [ |
| 149 | + "Now let's concentrate on $\\langle X \\rangle$ and $\\langle Y \\rangle$ and try to estimate $\\varphi$ with them. The expectation value for $X$ operator:\n", |
| 150 | + "\n", |
| 151 | + "$$\n", |
| 152 | + "\\langle \\psi | X |\\psi \\rangle = \\left( \\cos\\left(\\frac{\\theta}{2}\\right) \\langle 0| + e^{-i\\varphi} \\sin\\left(\\frac{\\theta}{2}\\right) \\langle 1| \\right) X \\left( \\cos\\left(\\frac{\\theta}{2}\\right) |0\\rangle + e^{i\\varphi} \\sin\\left(\\frac{\\theta}{2}\\right) |1\\rangle \\right) = \\frac{e^{i \\varphi} + e^{-i \\varphi}}{2} \\sin{\\theta} = \\cos{\\varphi} \\sin{\\theta}\n", |
| 153 | + "$$\n", |
| 154 | + "\n", |
| 155 | + "where we took into account that $X |0\\rangle = |1\\rangle$ and $X |1\\rangle = |0\\rangle$. As one can see, $\\langle X \\rangle,ドル in contrast to the $\\langle Z \\rangle,ドル has dependence on $\\varphi$ and can obtain some information about $\\varphi$ from it. For full estimation we still need expectation value of the $Y$ operator:\n", |
| 156 | + "\n", |
| 157 | + "$$\n", |
| 158 | + "\\langle \\psi | Y |\\psi \\rangle = \\left( \\cos\\left(\\frac{\\theta}{2}\\right) \\langle 0| + e^{-i\\varphi} \\sin\\left(\\frac{\\theta}{2}\\right) \\langle 1| \\right) Y \\left( \\cos\\left(\\frac{\\theta}{2}\\right) |0\\rangle + e^{i\\varphi} \\sin\\left(\\frac{\\theta}{2}\\right) |1\\rangle \\right) = -i \\frac{e^{i \\varphi} - e^{-i \\varphi}}{2} \\sin{\\theta} = \\sin{\\varphi} \\sin{\\theta}\n", |
| 159 | + "$$\n", |
| 160 | + "\n", |
| 161 | + "where we took into account that $Y |0\\rangle = i|1\\rangle$ and $Y |1\\rangle = -i|0\\rangle$. So, we have to equations:\n", |
| 162 | + "\n", |
| 163 | + "$$\n", |
| 164 | + "\\begin{cases}\n", |
| 165 | + "\\cos{\\varphi} = \\frac{\\langle X \\rangle}{\\sin{\\theta}} \\\\\n", |
| 166 | + "\\sin{\\varphi} = \\frac{\\langle Y \\rangle}{\\sin{\\theta}}\n", |
| 167 | + "\\end{cases}\n", |
| 168 | + "$$\n", |
| 169 | + "\n", |
| 170 | + "How to find $\\varphi \\in [0,2 \\pi),ドル from these two equations? Firstly we should take into account that range of usual principal value of the $\\arccos$ function is in $[0,\\pi]$. Also, if $\\sin{\\varphi} \\geq 0,ドル than 0ドル \\leq \\varphi \\leq \\pi$ and if $\\sin{\\varphi} < 0,ドル than $\\pi < \\varphi < 2\\pi$. Therefore:\n", |
| 171 | + "\n", |
| 172 | + "$$\n", |
| 173 | + "\\begin{cases}\n", |
| 174 | + "\\varphi = \\arccos{\\frac{\\langle X \\rangle}{\\sin{\\theta}}}, \\qquad \\quad \\text{if} \\quad \\sin{\\varphi} \\geq 0\\\\\n", |
| 175 | + "\\varphi = 2\\pi - \\arccos{\\frac{\\langle X \\rangle}{\\sin{\\theta}}}, \\quad \\text{if}\\quad \\sin{\\varphi} < 0\n", |
| 176 | + "\\end{cases}\n", |
| 177 | + "$$\n", |
| 178 | + "\n", |
| 179 | + "So, for estimating $\\theta$ we only need $\\langle Z \\rangle,ドル but for $\\varphi$ we will need $\\theta,ドル $\\langle X \\rangle$ and $\\langle Y \\rangle$. We already know how to estimate $\\langle Z \\rangle$ and now we are going to descuss the experimental estimation procidures for $\\langle X \\rangle$ and $\\langle Y \\rangle$. These procidures are very similar to the one that we used for $\\langle Z \\rangle$. Moreover, we will not writh seperete function for $\\langle X \\rangle$ and $\\langle Y \\rangle$ operators and we will use the same `z_expectation_from_counts` function in order to estimate them. \n", |
| 180 | + "\n", |
| 181 | + "Note that $X = HZH,ドル where $H = \\frac{1}{\\sqrt{2}}\\begin{pmatrix} 1 & 1 \\\\ 1 & -1 \\end{pmatrix}$ is the Hadamard gate. That is why\n", |
| 182 | + "\n", |
| 183 | + "$$\\left\\langle \\psi \\right| X \\left| \\psi \\right\\rangle = \\left\\langle \\psi \\right| HZH \\left| \\psi \\right\\rangle = \\left\\langle \\psi' \\right| Z \\left| \\psi' \\right\\rangle$$\n", |
| 184 | + "\n", |
| 185 | + "where $\\left| \\psi' \\right\\rangle = H \\left| \\psi \\right\\rangle$ and $\\left\\langle \\psi' \\right| = \\left( H \\left| \\psi \\right\\rangle \\right)^\\dagger = \\left\\langle \\psi \\right| H,ドル because $H^{\\dagger} = H$. In other words, $\\left\\langle \\psi \\right| X \\left| \\psi \\right\\rangle$ calculated for $\\left| \\psi \\right\\rangle$ is equal to $\\left\\langle \\psi' \\right| Z \\left| \\psi' \\right\\rangle$ calculated for $\\left| \\psi' \\right\\rangle$. Therefore we can calculate $X$ expectation value by calculating $Z$ expectation value after applying $H$ gate in order to obtain $\\left| \\psi' \\right\\rangle$.\n", |
| 186 | + "\n", |
| 187 | + "The similare thing can be done for $Y$ expectation value. Here, we should take into account $H_y = \\frac{1}{\\sqrt{2}}\\begin{pmatrix} 1 & -i \\\\ i & -1 \\end{pmatrix}$:\n", |
| 188 | + "\n", |
| 189 | + "$$\\left\\langle \\psi \\right| Y \\left| \\psi \\right\\rangle = \\left\\langle \\psi \\right| H_y Z H_y \\left| \\psi \\right\\rangle = \\left\\langle \\psi'' \\right| Z \\left| \\psi'' \\right\\rangle$$\n", |
| 190 | + "\n", |
| 191 | + "where $\\left| \\psi'' \\right\\rangle = H_y \\left| \\psi \\right\\rangle$ and $\\left\\langle \\psi' \\right| = \\left( H_y \\left| \\psi \\right\\rangle \\right)^\\dagger = \\left\\langle \\psi \\right| H_y,ドル because $H_y^{\\dagger} = H_y$. So, after aplying $H_y$ to the qubit, we should calculate the $\\left\\langle \\psi'' \\right| Z \\left| \\psi'' \\right\\rangle$ that will give as the desired $\\left\\langle \\psi \\right| Y \\left| \\psi \\right\\rangle$.\n", |
| 192 | + "\n", |
| 193 | + "Now let's write a function that will calculate the expectation value for the given Pauli operator ($I$ not included):" |
| 194 | + ] |
| 195 | + }, |
| 196 | + { |
| 197 | + "cell_type": "code", |
| 198 | + "execution_count": 3, |
| 199 | + "metadata": {}, |
| 200 | + "outputs": [], |
| 201 | + "source": [ |
| 202 | + "def one_qubit_pauli_expectation_value(qubit, circuit, backend, shots, pauli_operator):\n", |
| 203 | + " \"\"\"\n", |
| 204 | + " Expectation value of X or Y or Z operators\n", |
| 205 | + " :param pauli_operator: 'x', 'y','z' or 'X', 'Y','Z'\n", |
| 206 | + " :param qubit: entangled qubit whose Bloch angles we should estimate\n", |
| 207 | + " :param circuit: QuantumCircuit that prepares the qubit in some state\n", |
| 208 | + " :param backend: Quantum Hardware or Quantum simulator\n", |
| 209 | + " :param shots: number of circuit execution (determines the accuracy of estimation)\n", |
| 210 | + " :return: the expectation value\n", |
| 211 | + " \"\"\"\n", |
| 212 | + " if len(circuit.cregs) != 0:\n", |
| 213 | + " raise NotImplementedError(\"Circuit should not have classical registers, because that case is not implemented.\")\n", |
| 214 | + "\n", |
| 215 | + " classical_register = ClassicalRegister(1)\n", |
| 216 | + " circuit_expectation = QuantumCircuit(classical_register)\n", |
| 217 | + " \n", |
| 218 | + " # add the qregs of circuit to the circuit_expectation\n", |
| 219 | + " for qreg in circuit.qregs:\n", |
| 220 | + " circuit_expectation.add_register(qreg)\n", |
| 221 | + " \n", |
| 222 | + " circuit_expectation += circuit\n", |
| 223 | + "\n", |
| 224 | + " if pauli_operator == 'x' or pauli_operator == 'X':\n", |
| 225 | + " circuit_expectation.h(qubit)\n", |
| 226 | + " elif pauli_operator == 'y' or pauli_operator == 'Y':\n", |
| 227 | + " circuit_expectation.u(np.pi / 2, np.pi / 2, np.pi / 2, qubit) # H_y = UGate(np.pi / 2, np.pi / 2, np.pi / 2)\n", |
| 228 | + " elif pauli_operator != 'z' and pauli_operator != 'Z':\n", |
| 229 | + " # nothing should be done for the <z> case\n", |
| 230 | + " raise ValueError(f\"Pauli operator should be equal 'x', 'y','z' or 'X', 'Y','Z'. Was given {pauli_operator}\")\n", |
| 231 | + "\n", |
| 232 | + " circuit_expectation.measure(qubit, classical_register[0])\n", |
| 233 | + " counts = execute(circuit_expectation, backend, shots=shots).result().get_counts()\n", |
| 234 | + "\n", |
| 235 | + " return z_expectation_from_counts(counts, 0, shots)" |
| 236 | + ] |
| 237 | + }, |
| 238 | + { |
| 239 | + "cell_type": "markdown", |
| 240 | + "metadata": {}, |
| 241 | + "source": [ |
| 242 | + "We actually ready to write the main function for estimating the Bloch angles, but before that, we should note something. Here we are not using generalization of the Bloch sphere for the mixed states. In order words we assume that the given state is one qubit pure state. So, if we have two qubit Bell state $\\frac{1}{\\sqrt{2}}\\left(\\left|00\\right\\rangle + \\left|11\\right\\rangle \\right)$ and we want to run this procidure for estimating the Bloch angles for the first qubit the procidure should warn us that we have given not apropriate quantum state. Or if there exists some probability of errors, the code should warn us about that as well. These can be checked with this condition:\n", |
| 243 | + "\n", |
| 244 | + "$$p = \\frac{1 + \\left\\langle X \\right\\rangle + \\left\\langle Y \\right\\rangle + \\left\\langle Z \\right\\rangle}{2} \t\\approx 1$$\n", |
| 245 | + "\n", |
| 246 | + "where $p = Tr{\\rho^2}$ is the [purity][3], $\\rho$ is the [density matrix][2] of the quantum state. We are not going to derive this, because the derivation is long. All we need from this is to write one few lines that will check if $p \\approx 1$. Otherwise the quantum state is not a pure state. We are checking the approximative equality and not exact equality, becouse estimation of $P(0) = = \\lim_{N \\rightarrow \\infty} \\frac{N_0}{N}$ is not exact at the first place and hence the accuracy of the whole procidure is dependent on the number of the experiments $N$.\n", |
| 247 | + "\n", |
| 248 | + "Here is the main function that is going to estimate $\\theta$ and $\\varphi$ Bloch angles:\n", |
| 249 | + "\n", |
| 250 | + "[1]: https://github.com/DavitKhach/quantum-algorithms-tutorials\n", |
| 251 | + "[2]: https://www.cambridge.org/am/academic/subjects/physics/quantum-physics-quantum-information-and-quantum-computation/quantum-computation-and-quantum-information-10th-anniversary-edition?format=HB\n", |
| 252 | + "[3]: https://en.wikipedia.org/wiki/Purity_(quantum_mechanics)" |
| 253 | + ] |
| 254 | + }, |
| 255 | + { |
| 256 | + "cell_type": "code", |
| 257 | + "execution_count": 4, |
| 258 | + "metadata": {}, |
| 259 | + "outputs": [], |
| 260 | + "source": [ |
| 261 | + "def estimate_bloch_angles(qubit, circuit, backend, shots):\n", |
| 262 | + " \"\"\"\n", |
| 263 | + " Estimates the Bloch angles theta and phi:\n", |
| 264 | + " |psi > = cos(theta / 2 ) |0> + e^{i phi} cos(theta / 2 ) |1>\n", |
| 265 | + " :param shots: number of circuit execution (determines the accuracy of estimation)\n", |
| 266 | + " :param backend: Quantum Hardware or Quantum simulator\n", |
| 267 | + " :param qubit: entangled qubit whose Bloch angles we should estimate\n", |
| 268 | + " :param circuit: QuantumCircuit that prepares the qubit in some state\n", |
| 269 | + " :return: (theta, phi) tuple\n", |
| 270 | + " \"\"\"\n", |
| 271 | + "\n", |
| 272 | + " x_expectation_value = one_qubit_pauli_expectation_value(qubit, circuit, backend, shots, \"X\")\n", |
| 273 | + " y_expectation_value = one_qubit_pauli_expectation_value(qubit, circuit, backend, shots, \"Y\")\n", |
| 274 | + " z_expectation_value = one_qubit_pauli_expectation_value(qubit, circuit, backend, shots, \"Z\")\n", |
| 275 | + "\n", |
| 276 | + " # check if it is a pure state\n", |
| 277 | + " purity = (1 + x_expectation_value**2 + y_expectation_value**2 + z_expectation_value**2) / 2\n", |
| 278 | + " if not np.isclose(purity, 1, rtol=0, atol=1e-1):\n", |
| 279 | + " warnings.warn(f\"For not pure one qubit states Bloch angles are not defined. \"\n", |
| 280 | + " f\"The purity is equal to {purity}. The resulted estimations are not true.\")\n", |
| 281 | + "\n", |
| 282 | + " theta = 2 * np.arccos(np.sqrt((1 + z_expectation_value) / 2))\n", |
| 283 | + " # |0> or |1> state cases\n", |
| 284 | + " if np.isclose(theta, 0, rtol=0, atol=1e-2) or np.isclose(theta, np.pi / 2, rtol=0, atol=1e-2):\n", |
| 285 | + " phi = 0\n", |
| 286 | + " return theta, phi\n", |
| 287 | + " \n", |
| 288 | + " # arccos_argument should be in [-1, 1]\n", |
| 289 | + " arccos_argument = x_expectation_value / np.sin(theta)\n", |
| 290 | + " if np.isclose(arccos_argument, 1, rtol=0, atol=1e-2):\n", |
| 291 | + " arccos_argument = 1\n", |
| 292 | + " elif np.isclose(arccos_argument, -1, rtol=0, atol=1e-2):\n", |
| 293 | + " arccos_argument = -1\n", |
| 294 | + " elif abs(arccos_argument) > 1:\n", |
| 295 | + " raise ValueError(\"Value error for arccos, try to increase the shots in order to improve estimation.\")\n", |
| 296 | + " \n", |
| 297 | + " if (y_expectation_value / np.sin(theta)) > 0: # = sin(phi) > 0\n", |
| 298 | + " phi = np.arccos(arccos_argument)\n", |
| 299 | + " elif (y_expectation_value / np.sin(theta)) < 0: # = sin(phi) < 0\n", |
| 300 | + " phi = -np.arccos(x_expectation_value / np.sin(theta)) + 2 * np.pi\n", |
| 301 | + "\n", |
| 302 | + " return theta, phi" |
| 303 | + ] |
| 304 | + }, |
| 305 | + { |
| 306 | + "cell_type": "markdown", |
| 307 | + "metadata": {}, |
| 308 | + "source": [ |
| 309 | + "Now let's apply this procidure for randomly generated quantum state." |
| 310 | + ] |
| 311 | + }, |
| 312 | + { |
| 313 | + "cell_type": "code", |
| 314 | + "execution_count": 5, |
| 315 | + "metadata": {}, |
| 316 | + "outputs": [ |
| 317 | + { |
| 318 | + "name": "stdout", |
| 319 | + "output_type": "stream", |
| 320 | + "text": [ |
| 321 | + "theta = 0.7451302782183074\n", |
| 322 | + "Estimated theta = 0.7282535938401379\n", |
| 323 | + "phi = 1.3043296728659002\n", |
| 324 | + "Estimated phi = 1.2637375716904595\n" |
| 325 | + ] |
| 326 | + } |
| 327 | + ], |
| 328 | + "source": [ |
| 329 | + "backend = BasicAer.get_backend('qasm_simulator')\n", |
| 330 | + "\n", |
| 331 | + "bloch_theta = np.pi * random()\n", |
| 332 | + "bloch_phi = 2 * np.pi * random()\n", |
| 333 | + "\n", |
| 334 | + "qubit = QuantumRegister(1)\n", |
| 335 | + "circuit_one_qubit = QuantumCircuit(qubit)\n", |
| 336 | + "\n", |
| 337 | + "circuit_one_qubit.u(bloch_theta, bloch_phi, 0, qubit[0]) # creates cos(theta/2)|0> + e^{i phi}sin(theta/2)|1>\n", |
| 338 | + "\n", |
| 339 | + "estimated_theta, estimated_phi = estimate_bloch_angles(qubit[0], circuit_one_qubit, backend, shots=8192)\n", |
| 340 | + "\n", |
| 341 | + "print(\"theta = \", bloch_theta)\n", |
| 342 | + "print(\"Estimated theta = \", estimated_theta)\n", |
| 343 | + "\n", |
| 344 | + "print(\"phi = \", bloch_phi)\n", |
| 345 | + "print(\"Estimated phi = \", estimated_phi)" |
| 346 | + ] |
| 347 | + }, |
| 348 | + { |
| 349 | + "cell_type": "markdown", |
| 350 | + "metadata": {}, |
| 351 | + "source": [ |
| 352 | + "Let's try to estimate the Bloch angles when the qubit is not in a pure state and see if the function will warn us about that. We will create one of the Bell states $\\frac{1}{\\sqrt{2}}\\left(\\left| 00 \\right\\rangle + \\left| 11 \\right\\rangle \\right)$ and try to run the code for the first qubit." |
| 353 | + ] |
| 354 | + }, |
| 355 | + { |
| 356 | + "cell_type": "code", |
| 357 | + "execution_count": 8, |
| 358 | + "metadata": {}, |
| 359 | + "outputs": [ |
| 360 | + { |
| 361 | + "name": "stdout", |
| 362 | + "output_type": "stream", |
| 363 | + "text": [ |
| 364 | + "theta = 1.895609482156519\n", |
| 365 | + "Estimated theta = 1.566401781400312\n", |
| 366 | + "phi = 5.3231751793401845\n", |
| 367 | + "Estimated phi = 0\n" |
| 368 | + ] |
| 369 | + }, |
| 370 | + { |
| 371 | + "name": "stderr", |
| 372 | + "output_type": "stream", |
| 373 | + "text": [ |
| 374 | + "/home/davitkhach/anaconda3/envs/qiskit_env/lib/python3.6/site-packages/ipykernel_launcher.py:19: UserWarning: For not pure one qubit states Bloch angles are not defined. The purity is equal to 0.5003186464309692. The resulted estimations are not true.\n" |
| 375 | + ] |
| 376 | + } |
| 377 | + ], |
| 378 | + "source": [ |
| 379 | + "bloch_theta = np.pi * random()\n", |
| 380 | + "bloch_phi = 2 * np.pi * random()\n", |
| 381 | + "\n", |
| 382 | + "quantum_register = QuantumRegister(2)\n", |
| 383 | + "circuit_bell = QuantumCircuit(quantum_register)\n", |
| 384 | + "\n", |
| 385 | + "# create the Bell state\n", |
| 386 | + "circuit_bell.h(quantum_register[0])\n", |
| 387 | + "circuit_bell.cx(quantum_register[0], quantum_register[1])\n", |
| 388 | + "\n", |
| 389 | + "estimated_theta, estimated_phi = estimate_bloch_angles(quantum_register[0], circuit_bell, backend, shots=8192)\n", |
| 390 | + "\n", |
| 391 | + "print(\"theta = \", bloch_theta)\n", |
| 392 | + "print(\"Estimated theta = \", estimated_theta)\n", |
| 393 | + "\n", |
| 394 | + "print(\"phi = \", bloch_phi)\n", |
| 395 | + "print(\"Estimated phi = \", estimated_phi)" |
| 396 | + ] |
| 397 | + }, |
| 398 | + { |
| 399 | + "cell_type": "markdown", |
| 400 | + "metadata": {}, |
| 401 | + "source": [ |
| 402 | + "If you see the warning massage than the code does what we wanted from it! \n", |
| 403 | + "\n", |
| 404 | + "Now let's introduce one more interesting procidure that will help us to double check the main procidure. " |
| 405 | + ] |
103 | 406 | }
|
104 | 407 | ],
|
105 | 408 | "metadata": {
|
|
0 commit comments