{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "11ea9666",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Solucionador de optimización - una función Qiskit de Q-CTRL Fire Opal\"\n",
        "description: \"Empiece a resolver problemas de optimización a escala industrial con el solucionador de optimización Fire Opal de Q-CTRL\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore Sachdeva */}\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dde95705",
      "metadata": {},
      "source": [
        "<span id=\"optimization-solver-a-qiskit-function-by-q-ctrl-fire-opal\" />\n",
        "\n",
        "# Solucionador de optimización: una función Qiskit de Q-CTRL Fire Opal\n",
        "\n",
        "*Consulte la [referencia de la API](/docs/api/functions/q-ctrl-optimization-solver)*\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Las funciones Qiskit son una función experimental disponible únicamente para los usuarios de los planes IBM Quantum® Premium Plan, Flex Plan y On-Prem (a través de IBM Quantum Platform API). Se trata de versiones preliminares sujetas a cambios.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "40c2085c",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "{/*\n",
        "  DO NOT EDIT THIS CELL!!!\n",
        "  This cell's content is generated automatically by a script. Anything you add\n",
        "  here will be removed next time the notebook is run. To add new content, create\n",
        "  a new cell before or after this one.\n",
        "  */}\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Versiones del paquete\">\n",
        "    El código de esta página se ha desarrollado teniendo en cuenta los siguientes requisitos.\n",
        "    Recomendamos utilizar estas versiones o posteriores.\n",
        "\n",
        "    ```\n",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    sympy~=1.14.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e30c7881",
      "metadata": {},
      "source": [
        "<span id=\"overview\" />\n",
        "\n",
        "## Visión general\n",
        "\n",
        "Con el solucionador de optimización Fire Opal, puede resolver problemas de optimización a gran escala en hardware cuántico sin necesidad de conocimientos cuánticos. Basta con introducir la definición del problema de alto nivel y el Solver se encarga del resto. Todo el flujo de trabajo tiene en cuenta el ruido y aprovecha [la gestión del rendimiento de Fire Opal](/docs/guides/q-ctrl-performance-management). El Solver ofrece sistemáticamente soluciones precisas a los problemas clásicos más complejos, incluso a escala de dispositivo completo en las mayores QPU de IBM®.\n",
        "\n",
        "El Solver es flexible y se puede utilizar para resolver problemas de optimización combinatoria definidos como funciones objetivo o grafos arbitrarios. No es necesario asignar los problemas a la topología del dispositivo. Tanto los problemas sin restricciones como los que tienen restricciones son resolubles, siempre que las restricciones puedan formularse como términos de penalización. Los ejemplos incluidos en esta guía muestran cómo resolver un problema de optimización a escala industrial, tanto sin restricciones como con restricciones, utilizando diferentes tipos de datos de entrada para el Solver. El primer ejemplo se refiere a un problema de corte máximo definido en un grafo regular de 3 con 156 nodos, mientras que el segundo ejemplo aborda un problema de cobertura mínima de vértices con 50 nodos definido mediante una función de coste.\n",
        "\n",
        "Para acceder al Optimization Solver, [póngase en contacto con Q-CTRL](https://form.typeform.com/to/uOAVDnGg?typeform-source=q-ctrl.com).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5f761442",
      "metadata": {},
      "source": [
        "<span id=\"function-description\" />\n",
        "\n",
        "## Descripción de la función\n",
        "\n",
        "El Solver optimiza y automatiza por completo todo el algoritmo, desde la supresión de errores a nivel de hardware hasta la asignación eficaz de problemas y la optimización clásica en bucle cerrado. Entre bastidores, la canalización del Solver reduce los errores en cada etapa, lo que permite mejorar el rendimiento necesario para escalar de forma significativa. El flujo de trabajo subyacente se inspira en el Algoritmo de Optimización Cuántica Aproximada (QAOA), que es un algoritmo híbrido cuántico-clásico. Para un resumen detallado del flujo de trabajo completo del Optimization Solver, consulte [el manuscrito publicado](https://arxiv.org/abs/2406.01743).\n",
        "\n",
        "![Visualización del flujo de trabajo del Optimization Solver](https://quantum.cloud.ibm.com/docs/images/guides/qctrl-optimization/solver_workflow.svg)\n",
        "\n",
        "Para resolver un problema genérico con el Optimization Solver:\n",
        "\n",
        "1. Defina su problema como una función objetivo, un gráfico o una cadena de spin `SparsePauliOp` .\n",
        "2. Conéctese a la función a través del Catálogo de Funciones Qiskit.\n",
        "3. Ejecute el problema con el Solver y obtenga los resultados.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d20af236",
      "metadata": {},
      "source": [
        "<span id=\"accepted-problem-formats\" />\n",
        "\n",
        "### Formatos de problemas admitidos\n",
        "\n",
        "* Representación de la expresión polinómica de una función objetivo. Idealmente creado en Python con un objeto SymPy Poly existente y formateado en una cadena utilizando [sympy.srepr](https://docs.sympy.org/latest/tutorials/intro-tutorial/printing.html#srepr).\n",
        "* Representación gráfica de un tipo de problema específico. El gráfico debe crearse utilizando la biblioteca networkx en Python. A continuación, debe convertirse en una cadena utilizando la función networkx `[nx.readwrite.json_graph.adjacency_data](http://nx.readwrite.json_graph.adjacency_data.)`.\n",
        "* Representación en cadena de un problema concreto. La cadena de giro debe representarse como un objeto `SparsePauliOp` ; consulte la [documentación](/docs/api/qiskit/qiskit.quantum_info.SparsePauliOp) para obtener más detalles.\n",
        "\n",
        "<Admonition type=\"note\" title=\"¿Esta función es compatible con todos los servidores de fondo de IBM?\">\n",
        "  Si deseas utilizar un backend que esta función no admite actualmente, [ponte en contacto con Q-CTRL](https://form.typeform.com/to/iuujEAEI?typeform-source=q-ctrl.com) para que lo incorporen.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1165f4f0",
      "metadata": {},
      "source": [
        "<span id=\"benchmarks\" />\n",
        "\n",
        "## Referencias comparativas\n",
        "\n",
        "[Los resultados de pruebas comparativas publicadas](https://arxiv.org/abs/2406.01743) demuestran que el Solver resuelve con éxito problemas con más de 120 qubits, superando incluso resultados publicados anteriormente sobre recocido cuántico y dispositivos de iones atrapados. Las siguientes métricas de referencia proporcionan una indicación aproximada de la precisión y el escalado de los tipos de problemas basándose en algunos ejemplos. Las métricas reales pueden diferir en función de varias características del problema, como el número de términos de la función objetivo (densidad) y su localización, el número de variables y el orden polinómico.\n",
        "\n",
        "El \"Número de qubits\" indicado no es una limitación rígida, sino que representa umbrales aproximados en los que se puede esperar una precisión de solución extremadamente consistente. Se han resuelto con éxito problemas de mayor envergadura, por lo que se recomienda realizar pruebas más allá de estos límites.\n",
        "\n",
        "Se admite la conectividad arbitraria de qubits en todos los tipos de problemas.\n",
        "\n",
        "| Tipo de problema                                  | Número de qubits | Ejemplo                                                                 | Precisión | Tiempo total (s) | Tiempo de ejecución (s) | Número de iteraciones |\n",
        "| ------------------------------------------------- | ---------------- | ----------------------------------------------------------------------- | --------- | ---------------- | ----------------------- | --------------------- |\n",
        "| Problemas cuadráticos de conexión dispersa        | 156              | 3-corte máximo regular                                                  | 100 %     | 1764             | 293                     | 16                    |\n",
        "| Optimización binaria de orden superior            | 156              | Modelo Ising de espín-cristal                                           | 100 %     | 1461             | 272                     | 16                    |\n",
        "| Problemas cuadráticos densamente conectados       | 50               | Max-Cut totalmente conectado                                            | 100 %     | 1758             | 268                     | 6                     |\n",
        "| Problema restringido con términos de penalización | 50               | Cubierta de vértices mínima ponderada con una densidad de aristas del 8 | 100 %     | 1074             | 215                     | 10                    |\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "73390a19",
      "metadata": {},
      "source": [
        "<span id=\"get-started\" />\n",
        "\n",
        "## Cómo empezar\n",
        "\n",
        "Primero, autentíquese utilizando su [clave API IBM Quantum](http://quantum.cloud.ibm.com/). A continuación, selecciona la función de Qiskit de la siguiente manera. (En este fragmento de código se da por hecho que ya has [guardado tu cuenta](/docs/guides/functions-get-started#install-qiskit-functions-catalog-client) en tu entorno local.)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "95a715d2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[QiskitFunction(qunova/hivqe-chemistry),\n",
              " QiskitFunction(global-data-quantum/quantum-portfolio-optimizer),\n",
              " QiskitFunction(algorithmiq/tem),\n",
              " QiskitFunction(qedma/qesem),\n",
              " QiskitFunction(multiverse/singularity),\n",
              " QiskitFunction(ibm/circuit-function),\n",
              " QiskitFunction(q-ctrl/optimization-solver),\n",
              " QiskitFunction(colibritd/quick-pde),\n",
              " QiskitFunction(q-ctrl/performance-management),\n",
              " QiskitFunction(kipu-quantum/iskay-quantum-optimizer)]"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "\n",
        "catalog = QiskitFunctionsCatalog(channel=\"ibm_quantum_platform\")\n",
        "\n",
        "# Verify that you have access to the function\n",
        "catalog.list()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "8acf84f6",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Access Function\n",
        "solver = catalog.load(\"q-ctrl/optimization-solver\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e8837f5f",
      "metadata": {},
      "source": [
        "<span id=\"example-unconstrained-optimization\" />\n",
        "\n",
        "## Ejemplo: Optimización sin restricciones\n",
        "\n",
        "Resuelve el problema [del corte máximo](https://en.wikipedia.org/wiki/Maximum_cut) (max-cut). El siguiente ejemplo muestra las capacidades del Solver en un problema de corte máximo en un grafo no ponderado de 156 nodos y 3 aristas regulares, aunque también se pueden resolver problemas en grafos ponderados.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a699235b",
      "metadata": {},
      "source": [
        "Además de `qiskit-ibm-catalog`, también utilizará los siguientes paquetes para ejecutar este ejemplo: `networkx` y `numpy`. Puedes instalar estos paquetes descomentando la siguiente celda si estás ejecutando este ejemplo en un notebook usando el kernel IPython.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "a74fe6a9",
      "metadata": {},
      "outputs": [],
      "source": [
        "# %pip install networkx numpy"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a41c4a0d",
      "metadata": {},
      "source": [
        "<span id=\"1-define-the-problem\" />\n",
        "\n",
        "### 1. Definir el problema\n",
        "\n",
        "Puedes resolver un problema de corte máximo definiendo un problema de grafos y especificando `problem_type='maxcut'`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "d56e1440",
      "metadata": {},
      "outputs": [],
      "source": [
        "import networkx as nx\n",
        "import numpy as np\n",
        "\n",
        "# Generate a random graph with 156 nodes\n",
        "maxcut_graph = nx.random_regular_graph(d=3, n=156, seed=8)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "0a7255e1",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/q-ctrl-optimization-solver/extracted-outputs/0a7255e1-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Optionally, visualize the graph\n",
        "nx.draw_networkx(\n",
        "    maxcut_graph, nx.kamada_kawai_layout(maxcut_graph), node_size=100\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e42a8d55",
      "metadata": {},
      "source": [
        "El Solver acepta una cadena como entrada de definición del problema.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "2546e3e5",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Convert graph to string\n",
        "problem_as_str = nx.readwrite.json_graph.adjacency_data(maxcut_graph)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0ab6f24f",
      "metadata": {},
      "source": [
        "<span id=\"2-run-the-problem\" />\n",
        "\n",
        "### 2. Ejecuta el problema\n",
        "\n",
        "Cuando utilice el método de entrada basado en gráficos, especifique el tipo de problema.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "16c66d64",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Solve the problem\n",
        "maxcut_job = solver.run(\n",
        "    problem=problem_as_str,\n",
        "    problem_type=\"maxcut\",\n",
        "    backend_name=backend_name,  # E.g. \"ibm_fez\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "48069093",
      "metadata": {},
      "source": [
        "Comprueba [el estado](/docs/guides/functions-get-started#check-job-status) de tu carga de trabajo de Qiskit Function o obtén [los resultados](/docs/guides/functions-get-started#retrieve-results) de la siguiente manera:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "856fe992",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "34b53970-d95a-4e24-8763-fc6f3d112843\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QUEUED\n"
          ]
        }
      ],
      "source": [
        "# Print the ID so you can use it later, if necessary\n",
        "print(maxcut_job.job_id)\n",
        "\n",
        "# Get job status\n",
        "print(maxcut_job.status())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "74f48eab",
      "metadata": {},
      "source": [
        "<span id=\"3-retrieve-the-result\" />\n",
        "\n",
        "### 3. Recuperar el resultado\n",
        "\n",
        "Recuperar el valor de corte óptimo del diccionario de resultados.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Es posible que haya cambiado la asignación de las variables a la cadena de bits. El diccionario de salida contiene un `variables_to_bitstring_index_map` subdiccionario, que ayuda a verificar el orden.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "6b571411",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Optimal cut value: 210.0\n"
          ]
        }
      ],
      "source": [
        "# Poll for results\n",
        "maxcut_result = maxcut_job.result()\n",
        "\n",
        "# Take the absolute value of the solution since the cost function is minimized\n",
        "qctrl_maxcut = abs(maxcut_result[\"solution_bitstring_cost\"])\n",
        "\n",
        "# Print the optimal cut value found by the Optimization Solver\n",
        "print(f\"Optimal cut value: {qctrl_maxcut}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "508e29b0",
      "metadata": {},
      "source": [
        "Puede verificar la exactitud del resultado resolviendo el problema de forma clásica con solucionadores de código abierto como [PuLP](https://coin-or.github.io/pulp/) si el grafo no está densamente conectado. Los problemas de alta densidad pueden requerir solucionadores clásicos avanzados para validar la solución.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e2817b13",
      "metadata": {},
      "source": [
        "<span id=\"example-constrained-optimization\" />\n",
        "\n",
        "## Ejemplo: Optimización con restricciones\n",
        "\n",
        "El ejemplo anterior de «max-cut» es un problema habitual de optimización binaria cuadrática sin restricciones. El solucionador de optimización de Q-CTRL se puede utilizar para diversos tipos de problemas, incluida la optimización con restricciones. Se pueden resolver problemas de cualquier tipo introduciendo la formulación del problema expresada como un polinomio, en el que las restricciones se modelan como términos de penalización.\n",
        "\n",
        "El siguiente ejemplo muestra cómo construir una función de coste para un problema de optimización con restricciones, la [cobertura mínima de vértices](https://en.wikipedia.org/wiki/Vertex_cover) (MVC).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a9fbc0e9",
      "metadata": {},
      "source": [
        "Además de los paquetes `qiskit-ibm-catalog` y `qiskit` , también utilizará los siguientes paquetes para ejecutar este ejemplo: `numpy`, `networkx`, y `sympy`. Puedes instalar estos paquetes descomentando la siguiente celda si estás ejecutando este ejemplo en un notebook usando el kernel IPython.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "c6428fd0",
      "metadata": {},
      "outputs": [],
      "source": [
        "# %pip install numpy networkx sympy"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "98d3bfd3",
      "metadata": {},
      "source": [
        "<span id=\"1-define-the-problem\" />\n",
        "\n",
        "### 1. Definir el problema\n",
        "\n",
        "Define un problema MVC aleatorio generando un grafo con nodos ponderados aleatoriamente.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "c2ce65e3",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/q-ctrl-optimization-solver/extracted-outputs/c2ce65e3-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "import networkx as nx\n",
        "from sympy import symbols, Poly, srepr\n",
        "\n",
        "# To change the weights, change the seed to any integer.\n",
        "rng_seed = 18\n",
        "_rng = np.random.default_rng(rng_seed)\n",
        "node_count = 50\n",
        "edge_probability = 0.08\n",
        "mvc_graph = nx.erdos_renyi_graph(\n",
        "    node_count, edge_probability, seed=rng_seed, directed=False\n",
        ")\n",
        "\n",
        "# add node weights\n",
        "for i in mvc_graph.nodes:\n",
        "    mvc_graph.add_node(i, weight=_rng.random())\n",
        "\n",
        "# Optionally, visualize the graph\n",
        "nx.draw_networkx(mvc_graph, nx.kamada_kawai_layout(mvc_graph), node_size=200)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "89c91472",
      "metadata": {},
      "source": [
        "Un modelo de optimización estándar para MVC ponderado puede formularse como sigue. En primer lugar, hay que añadir una penalización para cualquier caso en que una arista no esté conectada a un vértice del subconjunto. Por lo tanto, $n_i = 1$ si el vértice $i$ está en la cubierta (es decir, en el subconjunto) y $n_i = 0$ en caso contrario. En segundo lugar, el objetivo es minimizar el número total de vértices en el subconjunto, que puede representarse mediante la siguiente función:\n",
        "\n",
        "$\\textbf{Minimize}\\qquad y = \\sum_{i\\in V} \\omega_i n_i$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "91586ee9",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Construct the cost function.\n",
        "variables = symbols([f\"n[{i}]\" for i in range(node_count)])\n",
        "cost_function = Poly(0, variables)\n",
        "\n",
        "for i in mvc_graph.nodes():\n",
        "    weight = mvc_graph.nodes[i].get(\"weight\", 0)\n",
        "    cost_function += variables[i] * weight"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9d01684b",
      "metadata": {},
      "source": [
        "Ahora cada arista del grafo debe incluir al menos un punto final de la cubierta, lo que se puede expresar como la desigualdad:\n",
        "\n",
        "$n_i + n_j \\ge 1 \\texttt{ for all } (i,j)\\in E$\n",
        "\n",
        "Cualquier caso en el que una arista no esté conectada al vértice de cobertura debe penalizarse. Esto puede representarse en la función de costes añadiendo una penalización de la forma $P(1-n_i-n_j+n_i n_j)$ donde $P$ es una constante de penalización positiva. Por lo tanto, una alternativa no restringida a la desigualdad restringida para MVC ponderado es:\n",
        "\n",
        "$\\textbf{Minimize}\\qquad y = \\sum_{i\\in V}\\omega_i n_i + P(\\sum_{(i,j)\\in E}(1 - n_i - n_j + n_i n_j))$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "1ff1ffcc",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Add penalty term.\n",
        "penalty_constant = 2\n",
        "for i, j in mvc_graph.edges():\n",
        "    cost_function += penalty_constant * (\n",
        "        1 - variables[i] - variables[j] + variables[i] * variables[j]\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9fd0ba9e",
      "metadata": {},
      "source": [
        "<span id=\"2-run-the-problem\" />\n",
        "\n",
        "### 2. Ejecuta el problema\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "f380b56d",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Solve the problem\n",
        "mvc_job = solver.run(\n",
        "    problem=srepr(cost_function),\n",
        "    backend_name=backend_name,  # E.g. \"ibm_fez\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d154c226",
      "metadata": {},
      "source": [
        "Comprueba [el estado](/docs/guides/functions-get-started#check-job-status) de tu carga de trabajo de Qiskit Function o obtén [los resultados](/docs/guides/functions-get-started#retrieve-results) de la siguiente manera:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "6de77b14",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QUEUED\n"
          ]
        }
      ],
      "source": [
        "print(mvc_job.status())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8a95618e",
      "metadata": {},
      "source": [
        "<span id=\"3-get-the-result\" />\n",
        "\n",
        "### 3. Obtenga el resultado\n",
        "\n",
        "Recuperar la solución y analizar los resultados. Como este problema tiene nodos ponderados, la solución no es simplemente el número mínimo de nodos cubiertos. En su lugar, el coste de la solución representa la suma de los pesos de los vértices incluidos en la cubierta de vértices. Representa el \"coste\" o \"peso\" total de cubrir todas las aristas del grafo utilizando los vértices seleccionados.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "a924bf93",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Solution cost: 10.248198273708624\n"
          ]
        }
      ],
      "source": [
        "mvc_result = mvc_job.result()\n",
        "qctrl_cost = mvc_result[\"solution_bitstring_cost\"]\n",
        "\n",
        "# Print results\n",
        "print(f\"Solution cost: {qctrl_cost}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e9ec2e67",
      "metadata": {},
      "source": [
        "<span id=\"get-support\" />\n",
        "\n",
        "## Obtener soporte\n",
        "\n",
        "Si tiene alguna pregunta o problema, póngase en [contacto con Q-CTRL](https://form.typeform.com/to/iuujEAEI?typeform-source=q-ctrl.com).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "993aa226c6ec9f5e",
      "metadata": {},
      "source": [
        "<span id=\"changelog\" />\n",
        "\n",
        "## Registro de cambios\n",
        "\n",
        "* 11/02/2026: Ahora ofrecemos asistencia para `ibm_miami`\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5a6a25c8",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximos pasos\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendaciones\">\n",
        "  * Solicite acceso al [solucionador de optimización Q-CTRL](/functions?id=q-ctrl-optimization-solver).\n",
        "  * Consulta la [referencia](/docs/api/functions/q-ctrl-optimization-solver) de la API de esta función de Qiskit.\n",
        "  * Pruebe el tutorial [Resolver problemas de optimización binaria de orden superior con el Solucionador de Optimización de Q-CTRL](/docs/tutorials/solve-higher-order-binary-optimization-problems-with-q-ctrls-optimization-solver).\n",
        "  * Revisión [Sachdeva, N., et al. (2024).  La optimización cuántica mediante un ordenador cuántico de 127 qubits con modelo de puerta IBM puede superar a los annealers cuánticos en problemas de optimización binaria no triviales. arXiv Preimpresión arXiv:2406.01743](https://arxiv.org/abs/2406.01743).\n",
        "  * Reseña [Loco, D., et al. (2026).  Predicción práctica de sitios de hidratación en bolsillos proteicos para el descubrimiento de fármacos en un ordenador cuántico. arXiv Preimpresión arXiv:2512.08390](https://arxiv.org/abs/2512.08390).\n",
        "  * Revise el caso práctico [de Mazda](https://q-ctrl.com/case-study/tackling-a-costly-bottleneck-in-automotive-design).\n",
        "  * Revise el caso práctico [de Network Rail](https://q-ctrl.com/case-study/accelerating-the-schedule-for-quantum-enhanced-rail).\n",
        "  * Revise el estudio de caso [del Ejército Australiano](https://q-ctrl.com/case-study/improving-army-logistics-with-quantum-computing).\n",
        "  * Revise el estudio de caso [de Transport for New South Wales](https://q-ctrl.com/case-study/delivering-quantum-computing-for-faster-commuting).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "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"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}