{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "181c5e62",
      "metadata": {
        "id": "181c5e62"
      },
      "source": [
        "# QBronze 1.3 — Operaciones con qubits reales y múltiples qubits\n",
        "\n",
        "Este cuaderno desarrolla ejercicios sobre operadores cuánticos reales, rotaciones, reflexiones, producto tensorial, CNOT y orden de qubits.\n",
        "\n",
        "Usaremos dos convenciones de manera explícita:\n",
        "\n",
        "1. **Orden lógico matemático:** $|\\text{primer qubit},\\text{segundo qubit}\\rangle$, por ejemplo $|10\\rangle$.\n",
        "2. **Orden de impresión tipo Qiskit:** al medir, la cadena suele imprimirse como $c[n-1]\\cdots c[1]c[0]$. Por eso conviene leer con cuidado qué qubit fue medido en qué bit clásico.\n",
        "\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "648e8597",
      "metadata": {
        "id": "648e8597"
      },
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "from math import sqrt, pi, cos, sin, log2, floor\n",
        "from collections import Counter\n",
        "\n",
        "np.set_printoptions(precision=6, suppress=True)\n",
        "\n",
        "ket0 = np.array([1.0, 0.0])\n",
        "ket1 = np.array([0.0, 1.0])\n",
        "\n",
        "I = np.eye(2)\n",
        "X = np.array([[0.0, 1.0], [1.0, 0.0]])\n",
        "Z = np.array([[1.0, 0.0], [0.0, -1.0]])\n",
        "H = (1 / sqrt(2)) * np.array([[1.0, 1.0], [1.0, -1.0]])\n",
        "\n",
        "def tensor(*vectors_or_matrices):\n",
        "    \"\"\"Producto tensorial en el orden escrito: A ⊗ B ⊗ C.\"\"\"\n",
        "    result = np.array([1.0])\n",
        "    for item in vectors_or_matrices:\n",
        "        result = np.kron(result, item)\n",
        "    return result\n",
        "\n",
        "def norm2(state):\n",
        "    \"\"\"Norma al cuadrado: suma |amplitud|^2.\"\"\"\n",
        "    return float(np.vdot(state, state).real)\n",
        "\n",
        "def probs(state):\n",
        "    \"\"\"Probabilidades de medición en la base computacional.\"\"\"\n",
        "    return np.abs(state) ** 2\n",
        "\n",
        "def basis_state(bitstring):\n",
        "    \"\"\"Vector base |bitstring⟩ en orden lógico de izquierda a derecha.\"\"\"\n",
        "    n = len(bitstring)\n",
        "    index = int(bitstring, 2)\n",
        "    v = np.zeros(2**n)\n",
        "    v[index] = 1.0\n",
        "    return v\n",
        "\n",
        "def bitstrings(n):\n",
        "    return [format(i, f\"0{n}b\") for i in range(2**n)]\n",
        "\n",
        "def show_state(state, n=None, tol=1e-10):\n",
        "    \"\"\"Representación textual compacta de un vector de estado.\"\"\"\n",
        "    if n is None:\n",
        "        n = int(round(log2(len(state))))\n",
        "    terms = []\n",
        "    for amp, bits in zip(state, bitstrings(n)):\n",
        "        if abs(amp) > tol:\n",
        "            terms.append(f\"{amp:+.6g}|{bits}⟩\")\n",
        "    return \" \".join(terms) if terms else \"0\"\n",
        "\n",
        "def sample_counts(state, shots=1024, seed=7, qiskit_order=False):\n",
        "    \"\"\"Muestreo de una distribución de medición. Si qiskit_order=True, invierte las etiquetas.\"\"\"\n",
        "    rng = np.random.default_rng(seed)\n",
        "    p = probs(state)\n",
        "    n = int(round(log2(len(state))))\n",
        "    outcomes = rng.choice(2**n, p=p/p.sum(), size=shots)\n",
        "    labels = []\n",
        "    for i in outcomes:\n",
        "        bits = format(i, f\"0{n}b\")\n",
        "        labels.append(bits[::-1] if qiskit_order else bits)\n",
        "    return dict(sorted(Counter(labels).items()))\n",
        "\n",
        "def is_valid_quantum_state(v, tol=1e-9):\n",
        "    return abs(norm2(np.asarray(v, dtype=float)) - 1.0) < tol\n",
        "\n",
        "\n",
        "def R(theta):\n",
        "    \"\"\"Rotación plana usual por ángulo theta sobre el vector de amplitudes reales.\"\"\"\n",
        "    return np.array([[np.cos(theta), -np.sin(theta)],\n",
        "                     [np.sin(theta),  np.cos(theta)]])\n",
        "\n",
        "def RY_qiskit(theta):\n",
        "    \"\"\"Matriz RY(theta) con la convención estándar de circuitos: rota el vector real por theta/2.\"\"\"\n",
        "    return np.array([[np.cos(theta/2), -np.sin(theta/2)],\n",
        "                     [np.sin(theta/2),  np.cos(theta/2)]])\n",
        "\n",
        "def cnot_matrix(control=0, target=1, n=2):\n",
        "    \"\"\"Matriz CNOT en orden lógico de bits de izquierda a derecha.\"\"\"\n",
        "    size = 2**n\n",
        "    M = np.zeros((size, size))\n",
        "    for i, bits in enumerate(bitstrings(n)):\n",
        "        b = list(bits)\n",
        "        if b[control] == '1':\n",
        "            b[target] = '0' if b[target] == '1' else '1'\n",
        "        j = int(''.join(b), 2)\n",
        "        M[j, i] = 1.0\n",
        "    return M"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8268c6f7",
      "metadata": {
        "id": "8268c6f7"
      },
      "source": [
        "## 1. Rotar un qubit real 120 grados\n",
        "\n",
        "En circuitos cuánticos se usa la compuerta $RY(\\theta)$, cuya matriz es\n",
        "\n",
        "$$\n",
        "RY(\\theta)=\n",
        "\\begin{pmatrix}\n",
        "\\cos(\\theta/2)&-\\sin(\\theta/2)\\\\\n",
        "\\sin(\\theta/2)&\\cos(\\theta/2)\n",
        "\\end{pmatrix}.\n",
        "$$\n",
        "\n",
        "Si partimos de $|0\\rangle=(1,0)^T$, entonces\n",
        "\n",
        "$$\n",
        "RY(\\theta)|0\\rangle=\\cos(\\theta/2)|0\\rangle+\\sin(\\theta/2)|1\\rangle.\n",
        "$$\n",
        "\n",
        "Si queremos que el vector real forme un ángulo geométrico de\n",
        "\n",
        "$$\n",
        "120^\\circ=\\frac{2\\pi}{3},\n",
        "$$\n",
        "\n",
        "entonces necesitamos\n",
        "\n",
        "$$\n",
        "\\frac{\\theta}{2}=\\frac{2\\pi}{3}\n",
        "\\quad\\Longrightarrow\\quad\n",
        "\\theta=\\frac{4\\pi}{3}.\n",
        "$$\n",
        "\n",
        "La instrucción correspondiente sería conceptualmente:\n",
        "\n",
        "```python\n",
        "qc.ry(2*2*pi/3, q[0])\n",
        "```"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a3651f01",
      "metadata": {
        "id": "a3651f01"
      },
      "outputs": [],
      "source": [
        "angle_geometrico = 2*pi/3\n",
        "parametro_RY = 2 * angle_geometrico\n",
        "\n",
        "state = RY_qiskit(parametro_RY) @ ket0\n",
        "print(\"ángulo geométrico deseado:\", angle_geometrico)\n",
        "print(\"parámetro de RY:\", parametro_RY)\n",
        "print(\"estado obtenido:\", show_state(state, n=1))\n",
        "print(\"vector:\", state)\n",
        "print(\"esperado: [cos(2π/3), sin(2π/3)] =\", [cos(2*pi/3), sin(2*pi/3)])"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b86baa03",
      "metadata": {
        "id": "b86baa03"
      },
      "source": [
        "## 2. La compuerta $Z$ sobre $|0\\rangle$\n",
        "\n",
        "La compuerta $Z$ es\n",
        "\n",
        "$$\n",
        "Z=\\begin{pmatrix}\n",
        "1&0\\\\\n",
        "0&-1\n",
        "\\end{pmatrix}.\n",
        "$$\n",
        "\n",
        "Aplicada sobre $|0\\rangle$:\n",
        "\n",
        "$$\n",
        "Z|0\\rangle=\n",
        "\\begin{pmatrix}\n",
        "1&0\\\\\n",
        "0&-1\n",
        "\\end{pmatrix}\n",
        "\\begin{pmatrix}1\\\\0\\end{pmatrix}\n",
        "=\n",
        "\\begin{pmatrix}1\\\\0\\end{pmatrix}\n",
        "=|0\\rangle.\n",
        "$$\n",
        "\n",
        "Aplicada sobre $|1\\rangle$:\n",
        "\n",
        "$$\n",
        "Z|1\\rangle=-|1\\rangle.\n",
        "$$\n",
        "\n",
        "La compuerta $Z$ no cambia $|0\\rangle$, pero cambia el signo de $|1\\rangle$."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "81699742",
      "metadata": {
        "id": "81699742"
      },
      "outputs": [],
      "source": [
        "print(\"Z|0> =\", show_state(Z @ ket0, n=1))\n",
        "print(\"Z|1> =\", show_state(Z @ ket1, n=1))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0d728b17",
      "metadata": {
        "id": "0d728b17"
      },
      "source": [
        "## 3. Evaluar $HZH|0\\rangle$\n",
        "\n",
        "Calculamos paso a paso, de derecha a izquierda:\n",
        "\n",
        "$$\n",
        "HZH|0\\rangle = H\\bigl(Z(H|0\\rangle)\\bigr).\n",
        "$$\n",
        "\n",
        "Primero:\n",
        "\n",
        "$$\n",
        "H|0\\rangle=\\frac{|0\\rangle+|1\\rangle}{\\sqrt{2}}.\n",
        "$$\n",
        "\n",
        "Luego:\n",
        "\n",
        "$$\n",
        "Z\\left(\\frac{|0\\rangle+|1\\rangle}{\\sqrt{2}}\\right)\n",
        "=\\frac{Z|0\\rangle+Z|1\\rangle}{\\sqrt{2}}\n",
        "=\\frac{|0\\rangle-|1\\rangle}{\\sqrt{2}}\n",
        "=|-\\rangle.\n",
        "$$\n",
        "\n",
        "Finalmente:\n",
        "\n",
        "$$\n",
        "H|-\\rangle=|1\\rangle.\n",
        "$$\n",
        "\n",
        "Entonces:\n",
        "\n",
        "$$\n",
        "HZH|0\\rangle=|1\\rangle.\n",
        "$$\n",
        "\n",
        "De hecho,\n",
        "\n",
        "$$\n",
        "HZH=X.\n",
        "$$"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a3cb22b7",
      "metadata": {
        "id": "a3cb22b7"
      },
      "outputs": [],
      "source": [
        "HZH = H @ Z @ H\n",
        "print(\"HZH =\")\n",
        "print(HZH)\n",
        "print(\"X =\")\n",
        "print(X)\n",
        "print(\"HZH|0> =\", show_state(HZH @ ket0, n=1))\n",
        "print(\"HZH|1> =\", show_state(HZH @ ket1, n=1))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "72a6ce8d",
      "metadata": {
        "id": "72a6ce8d"
      },
      "source": [
        "## 4. Reflexiones, rotaciones y afirmaciones verdaderas\n",
        "\n",
        "En el plano real:\n",
        "\n",
        "- Una rotación pura tiene determinante $+1$.\n",
        "- Una reflexión tiene determinante $-1$.\n",
        "- Si $F$ es una reflexión, entonces aplicar la misma reflexión dos veces devuelve el estado original:\n",
        "\n",
        "$$\n",
        "F^2=I.\n",
        "$$\n",
        "\n",
        "La matriz de Hadamard tiene determinante $-1$, por lo que no es una rotación pura en el plano real: es una reflexión. Además,\n",
        "\n",
        "$$\n",
        "H^2=I.\n",
        "$$\n",
        "\n",
        "También:\n",
        "\n",
        "$$\n",
        "|0\\rangle=(1,0),\\qquad |1\\rangle=(0,1).\n",
        "$$\n",
        "\n",
        "Su producto punto es 0, por lo que el ángulo entre ellos es $90^\\circ$."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "6ace561c",
      "metadata": {
        "id": "6ace561c"
      },
      "outputs": [],
      "source": [
        "print(\"det(H) =\", np.linalg.det(H))\n",
        "print(\"H^2 =\")\n",
        "print(H @ H)\n",
        "print(\"producto punto <0|1> =\", np.dot(ket0, ket1))\n",
        "\n",
        "# Ejemplo de rotación por 30 grados: su determinante es +1.\n",
        "rot = R(pi/6)\n",
        "print(\"det(R(pi/6)) =\", np.linalg.det(rot))\n",
        "print(\"R(pi/6)^2 no es identidad, salvo ángulos especiales:\")\n",
        "print(rot @ rot)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9a0443bd",
      "metadata": {
        "id": "9a0443bd"
      },
      "source": [
        "## 5. Dimensión de un sistema con $n$ qubits\n",
        "\n",
        "Un qubit tiene 2 estados base:\n",
        "\n",
        "$$\n",
        "|0\\rangle,\\ |1\\rangle.\n",
        "$$\n",
        "\n",
        "Dos qubits tienen 4 estados base:\n",
        "\n",
        "$$\n",
        "|00\\rangle,\\ |01\\rangle,\\ |10\\rangle,\\ |11\\rangle.\n",
        "$$\n",
        "\n",
        "En general, $n$ qubits tienen\n",
        "\n",
        "$$\n",
        "2^n\n",
        "$$\n",
        "\n",
        "estados base. Por tanto, el vector de estado tiene dimensión $2^n$.\n",
        "\n",
        "Para $n=5$:\n",
        "\n",
        "$$\n",
        "2^5=32.\n",
        "$$"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "2dea2298",
      "metadata": {
        "id": "2dea2298"
      },
      "outputs": [],
      "source": [
        "for n in range(1, 8):\n",
        "    print(f\"{n} qubits -> dimensión {2**n}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d697e555",
      "metadata": {
        "id": "d697e555"
      },
      "source": [
        "## 6. CNOT sobre una superposición\n",
        "\n",
        "Usamos el orden lógico\n",
        "\n",
        "$$\n",
        "|\\text{primer qubit},\\text{segundo qubit}\\rangle.\n",
        "$$\n",
        "\n",
        "La compuerta CNOT con primer qubit como control y segundo como objetivo cumple:\n",
        "\n",
        "$$\n",
        "|00\\rangle\\mapsto |00\\rangle,\n",
        "\\quad\n",
        "|01\\rangle\\mapsto |01\\rangle,\n",
        "\\quad\n",
        "|10\\rangle\\mapsto |11\\rangle,\n",
        "\\quad\n",
        "|11\\rangle\\mapsto |10\\rangle.\n",
        "$$\n",
        "\n",
        "Si el estado inicial es\n",
        "\n",
        "$$\n",
        "\\frac{|01\\rangle+|11\\rangle}{\\sqrt{2}},\n",
        "$$\n",
        "\n",
        "aplicamos CNOT término por término:\n",
        "\n",
        "$$\n",
        "|01\\rangle\\mapsto |01\\rangle,\n",
        "\\qquad\n",
        "|11\\rangle\\mapsto |10\\rangle.\n",
        "$$\n",
        "\n",
        "Por tanto,\n",
        "\n",
        "$$\n",
        "CNOT\\left(\\frac{|01\\rangle+|11\\rangle}{\\sqrt{2}}\\right)\n",
        "=\n",
        "\\frac{|01\\rangle+|10\\rangle}{\\sqrt{2}}.\n",
        "$$"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "016b166d",
      "metadata": {
        "id": "016b166d"
      },
      "outputs": [],
      "source": [
        "CNOT_12 = cnot_matrix(control=0, target=1, n=2)\n",
        "state = (basis_state(\"01\") + basis_state(\"11\")) / sqrt(2)\n",
        "result = CNOT_12 @ state\n",
        "print(\"Estado inicial:\", show_state(state, n=2))\n",
        "print(\"Estado final:\", show_state(result, n=2))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "41b983c6",
      "metadata": {
        "id": "41b983c6"
      },
      "source": [
        "## 7. Crear $(|00\\rangle+|01\\rangle)/\\sqrt{2}$ con un Hadamard\n",
        "\n",
        "Con el orden de impresión usado por muchos entornos de circuitos, aplicar $H$ a `q[0]` desde $|00\\rangle$ produce una superposición en el bit menos significativo:\n",
        "\n",
        "$$\n",
        "|00\\rangle \\xrightarrow{H\\text{ en }q[0]} \\frac{|00\\rangle+|01\\rangle}{\\sqrt{2}}.\n",
        "$$\n",
        "\n",
        "La instrucción conceptual es:\n",
        "\n",
        "```python\n",
        "qc.h(0)\n",
        "```\n",
        "\n",
        "La interpretación correcta depende del orden de lectura de los bits."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "562adcdc",
      "metadata": {
        "id": "562adcdc"
      },
      "outputs": [],
      "source": [
        "# En orden lógico |q1 q0>, aplicar H sobre q0 equivale a I ⊗ H.\n",
        "state = basis_state(\"00\")\n",
        "result = tensor(I, H) @ state\n",
        "print(\"Estado final:\", show_state(result, n=2))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b3c1f35a",
      "metadata": {
        "id": "b3c1f35a"
      },
      "source": [
        "## 8. Cambiar una correlación perfecta a anticorrelación\n",
        "\n",
        "El estado de Bell\n",
        "\n",
        "$$\n",
        "|\\Phi^+\\rangle=\\frac{|00\\rangle+|11\\rangle}{\\sqrt{2}}\n",
        "$$\n",
        "\n",
        "está correlacionado: las mediciones posibles son $00$ y $11$.\n",
        "\n",
        "Si aplicamos $X$ al primer qubit:\n",
        "\n",
        "$$\n",
        "X\\otimes I:\n",
        "\\quad\n",
        "|00\\rangle\\mapsto |10\\rangle,\n",
        "\\quad\n",
        "|11\\rangle\\mapsto |01\\rangle.\n",
        "$$\n",
        "\n",
        "Entonces\n",
        "\n",
        "$$\n",
        "(X\\otimes I)|\\Phi^+\\rangle\n",
        "=\n",
        "\\frac{|10\\rangle+|01\\rangle}{\\sqrt{2}}.\n",
        "$$\n",
        "\n",
        "Ahora las mediciones posibles son $10$ y $01$, es decir, resultados anticorrelacionados."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "3168cdc5",
      "metadata": {
        "id": "3168cdc5"
      },
      "outputs": [],
      "source": [
        "phi_plus = (basis_state(\"00\") + basis_state(\"11\")) / sqrt(2)\n",
        "anti = tensor(X, I) @ phi_plus\n",
        "print(\"Bell correlacionado:\", show_state(phi_plus, n=2))\n",
        "print(\"Después de X en el primer qubit:\", show_state(anti, n=2))\n",
        "print(\"Muestreo:\", sample_counts(anti, shots=1000, seed=4))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e29beb6d",
      "metadata": {
        "id": "e29beb6d"
      },
      "source": [
        "## 9. Aplicar $H$ sólo al segundo qubit de tres qubits\n",
        "\n",
        "Si partimos de\n",
        "\n",
        "$$\n",
        "|000\\rangle\n",
        "$$\n",
        "\n",
        "y aplicamos $H$ únicamente al segundo qubit, los otros qubits se comportan como si se les aplicara identidad:\n",
        "\n",
        "$$\n",
        "I\\otimes H\\otimes I.\n",
        "$$\n",
        "\n",
        "Entonces:\n",
        "\n",
        "$$\n",
        "|000\\rangle\n",
        "\\xrightarrow{I\\otimes H\\otimes I}\n",
        "|0\\rangle\\otimes \\frac{|0\\rangle+|1\\rangle}{\\sqrt{2}}\\otimes |0\\rangle\n",
        "=\n",
        "\\frac{|000\\rangle+|010\\rangle}{\\sqrt{2}}.\n",
        "$$\n",
        "\n",
        "Sólo cambia el qubit sobre el que se aplica la compuerta."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "bff70ab6",
      "metadata": {
        "id": "bff70ab6"
      },
      "outputs": [],
      "source": [
        "state = basis_state(\"000\")\n",
        "result = tensor(I, H, I) @ state\n",
        "print(\"Resultado:\", show_state(result, n=3))\n",
        "print(\"Probabilidades no nulas:\")\n",
        "for bits, p in zip(bitstrings(3), probs(result)):\n",
        "    if p > 1e-12:\n",
        "        print(bits, p)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fb630bea",
      "metadata": {
        "id": "fb630bea"
      },
      "source": [
        "## 10. Compuertas controladas por 0\n",
        "\n",
        "Una compuerta controlada usualmente se activa cuando el control está en $|1\\rangle$.\n",
        "Si se desea activar una compuerta cuando el control está en $|0\\rangle$, se usa el patrón:\n",
        "\n",
        "$$\n",
        "X \\;\\longrightarrow\\; \\text{control sobre }1 \\;\\longrightarrow\\; X.\n",
        "$$\n",
        "\n",
        "La primera $X$ cambia $|0\\rangle$ a $|1\\rangle$. La compuerta controlada se activa. La segunda $X$ restaura el valor original del control.\n",
        "\n",
        "Esto es útil para entender por qué sí es posible aplicar una NOT a un objetivo dependiendo de que otro qubit esté en $|0\\rangle$."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "6e076331",
      "metadata": {
        "id": "6e076331"
      },
      "outputs": [],
      "source": [
        "def controlled_on_zero_not_state(control_bit, target_bit):\n",
        "    \"\"\"Demuestra el efecto clásico de un NOT controlado por control=0.\"\"\"\n",
        "    if control_bit == 0:\n",
        "        target_bit = 1 - target_bit\n",
        "    return control_bit, target_bit\n",
        "\n",
        "for c in [0, 1]:\n",
        "    for t in [0, 1]:\n",
        "        print(f\"entrada control={c}, target={t} -> salida {controlled_on_zero_not_state(c, t)}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "677cb9b4",
      "metadata": {
        "id": "677cb9b4"
      },
      "source": [
        "## 11. Resumen operativo del módulo\n",
        "\n",
        "Resultados clave:\n",
        "\n",
        "$$\n",
        "RY(\\theta)|0\\rangle=\\cos(\\theta/2)|0\\rangle+\\sin(\\theta/2)|1\\rangle.\n",
        "$$\n",
        "\n",
        "$$\n",
        "Z|0\\rangle=|0\\rangle,\n",
        "\\qquad\n",
        "Z|1\\rangle=-|1\\rangle.\n",
        "$$\n",
        "\n",
        "$$\n",
        "HZH=X.\n",
        "$$\n",
        "\n",
        "$$\n",
        "\\dim(\\text{sistema de }n\\text{ qubits})=2^n.\n",
        "$$\n",
        "\n",
        "$$\n",
        "CNOT|a,b\\rangle=|a,b\\oplus a\\rangle.\n",
        "$$"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "name": "python",
      "version": "3.x"
    },
    "title": "QBronze 1.3 — Operaciones con qubits reales y múltiples qubits",
    "colab": {
      "provenance": []
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}