Saltar al contenido principal

Ejecución de circuitos cuánticos

Mira el video sobre circuitos cuánticos y primitivas de Olivia Lanes, o ábrelo en una ventana separada en YouTube.

Descripción general de la lección

Esta lección será un repaso de alto nivel sobre los fundamentos de la ejecución de una computación cuántica a escala utilitaria, desde el hardware cuántico utilizado hasta los principios a considerar al diseñar un circuito cuántico. Idealmente, al final de esta lección sabrás:

  1. Qué son realmente las computadoras cuánticas de IBM®. Necesitarás conocer los fundamentos de las características del hardware para diseñar de manera óptima tus circuitos cuánticos y ejecutarlos en él.

  2. Qué es Qiskit, qué son las primitivas y cómo podemos usarlas para crear y ejecutar circuitos cuánticos.

  3. El flujo de trabajo típico que seguimos para ejecutar experimentos a escala. Esto incluye seleccionar las mejores primitivas para tu caso de uso, mapear un problema a un circuito cuántico y aplicar mitigación y supresión de errores, lo que nos permite aprovechar al máximo estas máquinas.

Hardware: procesadores cuánticos de IBM

Para entender cómo podemos tomar decisiones óptimas al diseñar circuitos cuánticos a gran escala, necesitamos conocer un poco el hardware real que ejecutará esos circuitos. Así que hablemos brevemente sobre los qubits físicos y los procesadores cuánticos de IBM.

Los procesadores cuánticos de IBM están construidos con qubits transmon superconductores, que son circuitos eléctricos compuestos por una unión Josephson y un condensador conectados en paralelo. La unión Josephson es un inductor no lineal creado a partir de dos capas superpuestas de metal superconductor con una barrera aislante entre ellas. A temperaturas muy bajas, los electrones de los superconductores se emparejan para formar lo que se conoce como un par de Cooper. Los pares de Cooper pueden atravesar espontáneamente la barrera aislante de un lado de la unión al otro mediante efecto túnel. Este comportamiento de tunelamiento da lugar a las propiedades no lineales que crean nuestro qubit.

En el chip se fabrican líneas de transmisión de microondas para entregar señales de microondas a los qubits. Cuando aplicamos pulsos de microondas altamente calibrados — con frecuencia, amplitud, forma y duración específicas — a las líneas, podemos hacer que los qubits realicen acciones concretas. Esto constituye la base de nuestras puertas cuánticas. Fabricamos el chip de modo que los qubits vecinos estén conectados en una estructura de rejilla específica llamada rejilla heavy-hex. Esta conectividad — la llamada topología — de nuestros procesadores es un factor importante a considerar al diseñar un circuito, como veremos más adelante en la lección.

Las instrucciones para el pulso de microondas viajan desde tu computadora, a través de la nube, hasta la electrónica de control a temperatura ambiente, que interpreta esas instrucciones y genera físicamente los pulsos. Después de que las cajas de control a temperatura ambiente crean los pulsos, estos viajan a través de cables hacia un refrigerador de dilución y finalmente al chip cuántico. La señal entra en los resonadores, pasa a través de un wirebond y luego fluye por la línea de transmisión hacia nuestros qubits.

IBM tiene decenas de computadoras cuánticas en todo el mundo, y recientemente hemos actualizado nuestra flota para tener exclusivamente procesadores de más de 100 qubits. Algunos de ellos se encuentran en un centro de datos cuántico de IBM en el norte del estado de Nueva York y están disponibles a través de la nube para el uso de todos — y algunos son sistemas dedicados en las instalaciones que apoyan a los socios de la IBM Quantum® Network. Puedes iniciar sesión en quantum.cloud.ibm.com para ver a qué procesadores tienes acceso.

Cada procesador muestra tres métricas de rendimiento, que discutimos en la lección anterior; a modo de recordatorio, son: conteo de qubits, EPLG y CLOPS.

  • Conteo de qubits. Esto es evidente: es el número total de qubits disponibles para usar en un procesador cuántico dado. Para un problema relativamente grande a escala utilitaria, deberás asegurarte de usar un procesador con suficientes qubits para poder abordar el problema. Pero el conteo de qubits por sí solo no es lo único que importa.

  • EPLG, o "errores por puerta en capas" (errors per layered gate). Es una medida de la calidad de los qubits y las puertas cuánticas. Mide el error promedio que introduce cada puerta en un circuito que entrelaza qubits vecinos en una cadena de 100 qubits. Quieres que sea lo más pequeño posible.

  • CLOPS, o "operaciones de capas de circuito por segundo" (circuit layer operations per second). Cuantifica la velocidad del procesador. Mide cuántas capas de un determinado circuito de referencia llamado circuito de volumen cuántico puede ejecutar una unidad de procesamiento cuántico (QPU) por unidad de tiempo. Cuanto mayor sea el número, más rápido podemos calcular.

La importancia de cada una de estas métricas varía según la aplicación específica, y en lecciones futuras veremos ejemplos reales para comprender cómo cada uno de estos factores puede afectar el resultado de un cálculo.

Software: Qiskit y Qiskit Runtime

Para convertir tu problema cuántico en instrucciones para una computadora cuántica, usarás Qiskit, el kit de desarrollo de software de código abierto diseñado para trabajar con computadoras cuánticas, desarrollado por IBM. También existe el Ecosistema Qiskit — una colección de tutoriales de software y funciones que se construyen sobre o extienden las funcionalidades principales de Qiskit — y Qiskit Runtime — un servicio de computación cuántica y modelo de programación que permite a los usuarios diseñar y optimizar sus cargas de trabajo cuánticas y ejecutarlas de manera eficiente usando las Primitivas de Qiskit Runtime.

Una primitiva es un pequeño bloque constructivo que puedes usar para diseñar un circuito o trabajo más grande. Las dos primitivas más importantes para nosotros son el sampler y el estimator, que discutiremos con más profundidad en breve.

Con el lanzamiento reciente de Qiskit v1.0, Qiskit se ha vuelto más eficiente y estable que nunca. Así que, para quienes están empezando, ¡llegaron en el momento perfecto! Para quienes ya están familiarizados con Qiskit, deberán descargar e instalar la versión más reciente. Para una guía de instalación completa, visita la guía Instalar Qiskit.

Circuitos cuánticos

Ahora estamos listos para hablar sobre la base de los programas cuánticos: los circuitos cuánticos. Esta sección solo servirá como repaso — si no estás familiarizado con los circuitos cuánticos, te recomendamos aprenderlos con mayor profundidad visitando la lección Circuitos cuánticos en el curso "Fundamentos de la información cuántica" antes de continuar.

Un circuito cuántico es una red de puertas cuánticas y mediciones conectadas por cables que representan qubits, como se muestra a continuación. Los circuitos cuánticos se pueden leer como una partitura musical, de izquierda a derecha, comenzando en el tiempo 0 a la izquierda. Los qubits virtuales — aquellos que aún no han sido asignados a un qubit físico en un procesador — se listan en orden creciente de arriba hacia abajo.

Las puertas se representan por diferentes símbolos en los cables de los qubit(s) involucrados. Las puertas de un solo qubit — como una puerta Hadamard, representada a continuación (la caja con la H) — afectan solo al qubit en cuyo cable están colocadas. Las puertas de múltiples qubits — como una puerta CNOT, también mostrada a continuación (el signo más en el círculo con una línea conectada a q0) — afectan a dos o más qubits. En la puerta CNOT representada, el estado de q1 cambia según el estado de q0. Después de que se realizan todas las puertas, podemos medir los qubits, indicados por las puertas negras con el símbolo de medición. Los resultados de las mediciones se escriben en registros clásicos, el bus "meas" de doble línea que aparece a continuación.

Ejemplo de circuito cuántico simple

Una característica importante de un circuito es su profundidad. La profundidad de un circuito cuántico es el número mínimo de "capas" de puertas cuánticas, ejecutadas en paralelo, necesarias para completar el circuito. Las puertas cuánticas pueden ejecutarse en paralelo (al mismo tiempo) siempre que no compartan ningún qubit. Pero si dos o más puertas actúan sobre el mismo qubit, no podemos realizarlas en paralelo — deben realizarse en dos capas separadas, una después de la otra.

Hay otra manera, menos obvia, de determinar la profundidad de un circuito, jugando a una especie de juego. Las reglas son simples: comenzando desde cualquier cable de qubit en la izquierda, debes desplazarte hacia la derecha y contar el número de puertas que encuentras en tu camino. Puedes saltar a un cable vecino solo cuando esté conectado al cable actual mediante una puerta de múltiples qubits. El objetivo es maximizar el número de puertas que encuentras a lo largo del camino. Este número máximo también resulta ser la profundidad del circuito.

Ejemplo de circuito de nueve capas

Dado que las puertas cuánticas tardan tiempo en implementarse, la profundidad de un circuito corresponde aproximadamente al tiempo necesario para que una computadora cuántica ejecute el circuito. Algunas máquinas son más adecuadas para circuitos de gran profundidad que otras, debido a los tiempos de decoherencia de los qubits en el procesador. Por eso, necesitamos conocer la profundidad de un circuito para saber si puede ejecutarse en un dispositivo particular.

Diseño de un circuito cuántico: patrones de Qiskit

Entonces, ¿cómo procedemos para diseñar y ejecutar un circuito cuántico? La manera más fácil de entender un flujo de trabajo típico de computación cuántica es a través de los patrones de Qiskit. Los patrones de Qiskit son un marco conceptual que permite a los usuarios ejecutar cargas de trabajo cuánticas implementando ciertos pasos con herramientas modulares. Esto permite que las tareas de computación cuántica sean realizadas por una poderosa infraestructura de computación heterogénea (CPU/GPU/QPU). Los pasos pueden realizarse como servicio e incorporar gestión de recursos, lo que permite la composabilidad fluida de nuevas capacidades a medida que se desarrollan.

Estos son los pasos principales, que los usuarios experimentados de Qiskit probablemente reconocerán.

  1. Mapear. Este paso formaliza cómo tomamos un problema general que nos interesa y averiguamos cómo mapearlo a una computadora cuántica en forma de circuito cuántico.

  2. Optimizar. En este paso usamos el Transpiler de Qiskit para enrutar y distribuir el circuito en hardware de qubits físicos reales. Esto incluye traducir las puertas cuánticas individuales en secuencias de operaciones que se realizan en el hardware, así como una optimización en la distribución de las puertas.

  3. Ejecutar. Las primitivas de Qiskit Runtime proporcionan la interfaz con el hardware de IBM Quantum que permite ejecutar los circuitos transpilados. Este paso también incluye el uso de técnicas de supresión y mitigación de errores, que en gran medida pueden abstraerse del usuario.

  4. Post-procesar. En este paso se procesan los datos del propio procesador cuántico, proporcionando al usuario resultados útiles sobre el problema original. Básicamente, esto abarca cualquier análisis adicional de los datos adquiridos.

Mapear

El paso de Mapear esencialmente plantea la pregunta: "¿Cómo traduzco mi problema a un circuito cuántico que pueda ejecutarse razonablemente en hardware cuántico?" No hay duda de que el mapeo es un problema difícil y un área activa de investigación. No existe un método infalible que garantice el éxito, pero hay pautas recomendadas y ejemplos de problemas que ya sabemos cómo mapear.

La primera pauta es dejar que las computadoras clásicas hagan el trabajo en el que son mejores. Las tareas que son fáciles para las computadoras clásicas probablemente no se beneficiarán de una computadora cuántica. Las computadoras cuánticas son para problemas que son difíciles de resolver de manera clásica. Por supuesto, si es tu primera vez usando Qiskit o una computadora cuántica, no te preocupes por encontrar un problema computacionalmente complejo. Divídelo en problemas más pequeños y manejables que puedas aprender a abordar antes de ir directamente a un proyecto a escala utilitaria.

A continuación, traduce los resultados de tu problema que quieres medir o entender en un valor esperado o una función de costo. Una función de costo es una función específica del problema que define el objetivo del problema como algo que debe minimizarse o maximizarse. Puede usarse para ver qué tan bien está funcionando un estado o solución de prueba con respecto a ese objetivo. Esta noción puede aplicarse a diversas aplicaciones en química, aprendizaje automático, finanzas, optimización, etc. — no importa necesariamente desde qué área estés abordando el problema.

Ten también en cuenta que el hardware que vas a usar tiene una topología específica, como discutimos en la sección de hardware. Algunos qubits están conectados y otros no — necesitarás mapear tu problema a un circuito que respete la topología heavy-hex de los procesadores cuánticos de IBM.

Por ahora, lo más importante a tener en cuenta es que esta etapa requiere práctica. Necesitas tener un buen entendimiento no solo de tu problema, sino también de las capacidades del hardware — y en lecciones futuras veremos ejemplos y casos de uso específicos para ver cómo equilibrar todas estas consideraciones.

Optimizar

A continuación, necesitaremos elegir un procesador cuántico que tenga suficientes qubits de calidad suficientemente alta como para ejecutar nuestro circuito cuántico. Toma estas decisiones guiándote por las tres métricas que discutimos en la sección de hardware: conteo de qubits, EPLG y CLOPS.

Luego optimizamos nuestro circuito para el hardware seleccionado. Primero, necesitamos distribuir y enrutar nuestro circuito de manera eficiente. La distribución (layout) se refiere a mapear los qubits virtuales del circuito a los qubits físicos del procesador. El enrutamiento (routing) se refiere a ajustar el circuito para que la conectividad entre los qubits virtuales del circuito coincida con la conectividad de los qubits físicos del procesador. Hay un par de cosas a tener en cuenta durante la etapa de distribución y enrutamiento.

  1. No todos los qubits están conectados. Algunos están muy lejos unos de otros en el chip, y necesitamos reducir o eliminar las interacciones de larga distancia siempre que sea posible. Podrías aplicar una secuencia de puertas SWAP entre qubits vecinos para mover la información de los qubits, pero las puertas SWAP son costosas y propensas a errores, por lo que puede haber mejores formas de hacerlo. Intenta evitar demasiadas puertas SWAP costosas.

  2. La distribución y el enrutamiento son procesos iterativos. Puedes hacerlos a mano, pero también existe una herramienta de Qiskit llamada mapomatic, que puede hacer recomendaciones para una distribución de qubits físicos basándose en tasas de error aproximadas. El Transpiler (que discutiremos en breve) también puede hacer una sugerencia informada.

A continuación, podemos componer secuencias de puertas de un qubit que actúan sobre el mismo qubit en puertas simples — y a veces también podemos eliminar puertas innecesarias o combinaciones de puertas. Por ejemplo, algunas combinaciones de puertas pueden reducirse a combinaciones más simples — y de hecho, a veces una combinación de puertas puede equivaler a la operación identidad, por lo que simplemente podemos eliminarlas. Puedes hacer esto automáticamente usando el Transpiler de Qiskit — pero también puedes hacerlo manualmente, puerta por puerta, si deseas más control.

Una vez que hemos mejorado la distribución del circuito, el enrutamiento y los conteos de puertas — ya sea a mano o usando el Transpiler — generalmente queremos visualizar nuestro circuito para asegurarnos de que el timing de todas las puertas tenga sentido. Hay un argumento que puedes indicar en el Transpiler para visualizar la línea de tiempo de tu circuito y asegurarte de que todo esté alineado de la manera que esperarías.

Transpiler de Qiskit

Como se menciónó anteriormente, el Transpiler de Qiskit puede usarse para ayudar en las etapas iniciales del flujo de trabajo de patrones. Ahora profundicemos en sus capacidades con más detalle. Puede reescribir un circuito de entrada dado para que coincida con la topología de un dispositivo cuántico específico y optimizar el circuito para su ejecución y resiliencia frente al ruido. También reescribe un circuito dado en las puertas base del procesador cuántico específico que hayas seleccionado usar.

Qiskit tiene cuatro canales de transpilación integrados correspondientes a diferentes niveles de optimización, y a menos que ya estés familiarizado con la optimización de circuitos cuánticos, te recomendamos usar uno de ellos. Por defecto, el proceso de transpilación incluye estos seis pasos:

  1. Inicialización. Esta etapa ejecuta los pasos iniciales que se requieren antes de comenzar a incrustar el circuito en el backend. Esto generalmente implica desplegar instrucciones personalizadas y convertir el circuito a solo puertas de uno y dos qubits.

  2. Distribución (Layout). Esta etapa mapea los qubits virtuales del circuito a los qubits físicos de un backend. Consulta Layout Stage para más detalles.

  3. Enrutamiento (Routing). Esta etapa se ejecuta después de que se ha aplicado una distribución e inyecta puertas (como puertas swap) en el circuito original para hacerlo compatible con la conectividad del backend. Consulta Routing Stage para más detalles.

  4. Traducción (Translation). Esta etapa traduce las puertas del circuito al conjunto de puertas base del backend de destino. Consulta Translation Stage para más detalles.

  5. Optimización. Esta etapa ejecuta el bucle de optimización principal repetidamente hasta que se alcanza una condición (como llegar a cierta profundidad objetivo). Tenemos cuatro niveles de optimización diferentes para elegir, descritos a continuación.

  6. Planificación (Scheduling). Esta etapa es para cualquier pase de planificación con conciencia del hardware. A alto nivel, la planificación puede entenderse como la inserción de retrasos en el circuito para dar cuenta del tiempo de inactividad en los qubits entre la ejecución de instrucciones.

Hay cuatro niveles de optimización que van de 0 a 3, donde los niveles de optimización más altos requieren más tiempo y esfuerzo computacional, pero pueden producir un circuito mejor. El nivel de optimización 0 está diseñado para experimentos de caracterización de dispositivos y, como tal, solo mapea el circuito de entrada a las restricciones del backend de destino, sin realizar ninguna optimización. El nivel de optimización 3 dedica el mayor esfuerzo a optimizar el circuito. Sin embargo, dado que muchas de las técnicas de optimización del Transpiler se basan en heurísticas, dedicar más esfuerzo computacional no siempre resulta en una mejora en la calidad del circuito de salida. Si esto es de mayor interés, consulta la documentación del transpiler en la documentación de Qiskit.

Supresión de errores

El primer paso para reducir errores en un circuito es optimizar la distribución, el enrutamiento y minimizar el conteo de puertas, lo que ya hemos hecho, ya sea usando el Transpiler o por nuestra cuenta. Ahora hablemos de métodos más sofisticados de supresión de errores.

La supresión de errores se refiere a una clase de técnicas que transforman un circuito durante la compilación para minimizar los errores. Se distingue de la mitigación de errores, que discutiremos más adelante en la sección "Ejecutar" a continuación. Las dos formas más comunes de supresión de errores que usamos son el desacoplamiento dinámico y el Pauli twirling:

  1. El desacoplamiento dinámico se utiliza para cancelar efectivamente parte del ruido ambiental que se introduce cuando un qubit está inactivo. Al aplicar una serie de puertas en momentos específicos, puedes hacer que el ruido que se acumula en una parte del período de inactividad cancele aproximadamente el ruido en la otra parte.
  2. El Pauli twirling es una forma de insertar puertas aleatorias no para cancelar el ruido, como en el desacoplamiento dinámico, sino para simplificarlo. Al insertar puertas aleatorias, se evita que los efectos de diferentes errores se acumulen tan rápido y hace que el ruido sea más fácil de caracterizar, ya que ahora tiene una naturaleza estocástica. Este método también forma la base de una poderosa técnica de mitigación de errores, que discutiremos a continuación.

Ejecutar

Ahora estamos listos para ejecutar el programa cuántico. Las primitivas de Qiskit Runtime proporcionan una interfaz con el hardware de IBM Quantum, y también abstraen la supresión y mitigación de errores del usuario. Hay dos primitivas para elegir: el Sampler y el Estimator.

El Sampler de Qiskit Runtime ejecuta el circuito múltiples veces en un dispositivo cuántico, realizando mediciones en cada ejecución, y reconstruye la distribución de probabilidad a partir de las cadenas de bits recuperadas. Cuantas más ejecuciones (o shots) realice, más precisos serán los resultados, pero esto requiere más tiempo y recursos cuánticos. Específicamente, calcula la probabilidad de obtener cada estado de la base estándar posible midiendo el estado preparado por el circuito.

El Estimator de Qiskit Runtime usa un proceso algebraico complejo para estimar el valor esperado en un dispositivo cuántico real, descomponiendo el observable en una combinación de otros observables con bases propias conocidas.

El paso de Ejecutar es también cuando podemos seleccionar la estrategia de mitigación de errores. La mitigación de errores se refiere a técnicas que permiten a los usuarios reducir los errores del circuito modelando el ruido del dispositivo que estaba presente en el momento de la ejecución. Típicamente, esto resulta en una sobrecarga de pre-procesamiento cuántico relacionada con el entrenamiento del modelo y una sobrecarga de post-procesamiento clásico para mitigar los errores en los resultados brutos usando el modelo generado. A cambio de esta sobrecarga, podemos obtener resultados mucho más precisos.

Hay múltiples técnicas que podemos implementar para la mitigación de errores. Discutiremos tres, en orden creciente de resiliencia a los errores, pero también, en consecuencia, en orden creciente de costo computacional. Ten en cuenta, sin embargo, que esta es un área activa de investigación — por lo que probablemente continuaremos inventando nuevas y mejorando las antiguas.

En el nivel de resiliencia 0, el Transpiler no hace nada a tu circuito.

En el nivel 1, introduce un método llamado Twirled Readout Error eXtinction (T-REX). T-REX usa Pauli twirling, como se discutió en la sección de supresión de errores. Como se menciónó, insertar puertas aleatorias en el circuito puede hacer que incluso el ruido muy complicado y difícil de modelar parezca estocástico y sea mucho más fácil de contabilizar o restar en el post-procesamiento.

En el nivel de resiliencia 2, se agrega la Extrapolación de Ruido Cero (Zero Noise Extrapolation, ZNE). Esta es una técnica popular con la que hemos tenido mucho éxito recientemente. La idea detrás de ZNE puede ser un poco sorprendente — ¡en realidad añadimos ruido encima del que ya existe! Pero esto nos permite extrapolar en la dirección inversa, para predecir cómo serían los resultados si hubiera cada vez menos ruido.

Añadir ruido puede lograrse de varias maneras diferentes. Por ejemplo, podemos alargar las puertas para hacerlas más largas y, por lo tanto, más propensas a errores, o ejecutar más puertas que en última instancia resulten en una operación identidad, de modo que el circuito no cambie funcionalmente pero deliberadamente muestreemos más ruido. Sin embargo, debes hacer esto para cada circuito y cada valor esperado que quieras registrar — por lo que puedes ver cómo puede volverse computacionalmente costoso.

Un tipo específico de ZNE se llama Amplificación Probabilística de Errores (Probabilistic Error Amplification, PEA). Una vez que hemos aprendido un modelo de ruido para una puerta, PEA funciona muestreando errores de ese modelo de ruido e inyectándolos deliberadamente en el circuito. Esto aún no está disponible en Qiskit, pero lo estará más adelante este año.

La forma final de mitigación de errores que discutiremos es la Cancelación Probabilística de Errores (Probabilistic Error Cancellation, PEC). En lugar de estar en el tercer nivel de resiliencia, PEC es una capacidad especial que debes activar manualmente en Qiskit, porque los recursos computacionales requeridos no escalan muy bien en comparación con las otras técnicas de mitigación de errores. Comienzas aprendiendo sobre el ruido que afecta a tu circuito — ejecuta circuitos de aprendizaje de ruido o de caracterización de ruido para cada capa única de puertas de dos qubits en tu circuito. Estos resultados te permiten describir el ruido en términos de operadores de Pauli. Una vez que conoces estos términos de ruido, puedes modificar tus circuitos para que efectivamente tengan las puertas de Pauli opuestas incorporadas para cancelar estos canales de ruido. En ciertos aspectos, el proceso es similar a cómo funcionan los auriculares con cancelación de ruido. Sin embargo, esta forma de deshacer el ruido es muy costosa, con un tiempo de ejecución que crece rápida y exponencialmente con el número de puertas, por lo que puede no ser la mejor opción para un circuito muy grande.

Post-procesar

La etapa de post-procesamiento es donde visualizamos y analizamos la salida de nuestro circuito cuántico. Hay una serie de herramientas de Qiskit disponibles para hacerlo, como los módulos de visualización e información cuántica (quantum-info). No los cubriremos aquí, pero veremos estos módulos en acción a medida que nos adentremos en algunos ejemplos de aplicaciones en lecciones futuras.

Conclusión

Esperamos que esta lección te haya dado un recorrido veloz por las principales consideraciones y el flujo de trabajo que usamos cuando queremos ejecutar una computación cuántica a escala utilitaria. Estuvo repleta de información, y gran parte de ella no se asimilará hasta que veamos algunos ejemplos reales donde estos conceptos teóricos se pongan en práctica. Así que eso es lo que será el resto del curso. ¡Después de todo, este curso no se llama Computación Cuántica en la Práctica por nada!

La próxima vez, veremos un ejemplo específico de cómo usar el flujo de trabajo de patrones de Qiskit para diseñar y ejecutar un circuito cuántico que resuelva el problema clásico de la teoría de grafos llamado MaxCut.