El Blog de QPath
Computación cuántica práctica con QuantumPath®: Generador de números aleatorios de 3 cúbits
En el artículo sobre QuantumPath® “qSOA®: tecnología para la integración dinámica de los sistemas software híbridos cuántico-clásicos” se resalta la importancia de la integración de sistemas híbridos cuántico-clásicos para lograr la condición de solución híbrida lista para la industria. En dicho artículo se pone como ejemplo una fracción de un algoritmo QRNG (Quantum Random Number Generator) sencillo.
En el presente artículo vamos a presentar el ejemplo completo, una prueba de concepto completa, en el que se integrará un circuito QRNG en un aplicativo de software clásico. El cliente clásico será responsable de la llamada al circuito cuántico y la recogida y postproceso del dato. En QuantumPath® este proceso se realizará de forma agnóstica, a partir del diseño del circuito (que una vez diseñado y disponible en QPath® se podrá reutilizar cada vez que el cliente lo necesite), su flujo de control y la codificación del resultado, y el cliente podrá lanzar la ejecución en cualquiera de los computadores cuánticos disponibles en la plataforma de forma totalmente transparente.
Números aleatorios y pseudoaleatorios
Los números aleatorios están presentes en múltiples elementos que nos rodean, desde comportamientos de la propia naturaleza, hasta programas informáticos. En este segundo caso cobran una especial relevancia al ser necesarios para diversos campos de aplicación, como pueden ser el análisis estadístico, sistemas de seguridad, o la elección de un elemento perteneciente a un conjunto.
Un ejemplo claro de esto lo podemos encontrar en un sorteo, como puede ser la lotería, en el que los usuarios cuentan con una serie de papeletas numeradas las cuales, si resultan coincidir con un valor generado de manera aleatoria, serán premiadas. No cabe duda de que, si el número de la papeleta ganadora se obtiene por un método tradicional mecánico, como puede ser introducir bolas en un recipiente y extraerlas una a una, se conseguirá un número perfectamente aleatorio. Sin embargo, pese a lo que se puede pensar en una primera instancia, esto no es igual en un ordenador.
Aunque existan funciones que aparentemente generan números aleatorios, en realidad no generan números verdaderamente aleatorios. Esto se debe a la naturaleza determinista de la propia computadora clásica, la cual no hace otra cosa que, dados unos inputs, realizar una serie de operaciones definidas previamente para crear un número aparentemente aleatorio como output. Para la generación de estos números se pueden escoger diferentes parámetros para operar con ellos y tratar de obtener un valor lo más aleatorio posible; como podría ser la hora a la que se realice la ejecución, número de serie del PC, o el idioma de este. Sin embargo, en el caso que se encontraran los valores específicos de esos parámetros (valores semilla) y se generara de nuevo un número, este sería exactamente igual al anterior. Independientemente del número de veces que se ejecutara el programa. Este comportamiento/resultado lo tenemos asumido como usual porque así funcionan los ordenadores clásicos.
Ante esta situación, si se quiere conseguir un número verdaderamente aleatorio, no se puede recurrir a un generador determinista, por lo que se debe optar por el uso de comportamientos característicos de la propia naturaleza, como pueden ser los electrones y, por tanto, de la probabilística inherente a la computación cuántica.
Generación de número aleatorio con computación cuántica
Mientras que en computación clásica la unidad básica de información es el bit (con sus estados binarios 0 y 1), en la computación cuántica existe el cúbit, el cual se puede encontraren el estado 0, 1, o en una combinación lineal de ambos llamada superposición.
Conociendo esto y que, al realizar la medida de un cúbit en superposición este colapsa a un estado base 0 o 1, se puede generar un número aleatorio aplicando una puerta Hadamard y midiendo a continuación. La dimensión del número que se quiera obtener dependerá del número de cúbits utilizados siguiendo la lógica de 2n, siendo la base los dos estados posibles tras la medición (0 o 1), y el número de cúbits utilizados. Según se
muestra en la siguiente tabla:
Tabla 1 Dimensión del número en función de los cúbits
Ejemplo práctico con QuantumPath®
Para plasmar lo explicado anteriormente, aunque en QPath® el límite máximo de cúbits lo determina la capacidad de cada ordenador o simulador cuántico a utilizar, para simplificar el ejemplo se mostrará la creación de un número de 3 cúbits, es decir, un valor completamente aleatorio entre el 0 y el 7.
Una vez creada la solución en QuantumPath®, esta deberá contener el circuito que se muestra a continuación. Donde se hace uso de tres cúbits a los que se les aplica una puerta Hadamard para ponerlos en estado de superposición, y realizar la medición.
Figura 1 Circuito cuántico de números aleatorios
Tras esto el flujo del circuito describe el comportamiento que tendrá a nivel de ejecución. Al estar las tecnologías cuánticas basadas en la probabilidad, es común lanzar el circuito numerosas veces para obtener un resultado representativo. Sin embargo, en este caso no se quiere ejecutar un complejo algoritmo en el que puede haber fallos intermedios y cuyo resultado pueda verse afectado, si no que se busca un número una sola ocasión.
Podríamos hacer una analogía con tirar un dado. Si se quiere obtener uno de los seis números que contiene, se podría lanzar 100 veces y quedarnos con el número que más se ha repetido, o hacerlo una sola vez (una sola ejecución del circuito), y seleccionar ese resultado de un número aleatorio como válido.
En el caso de que se quiera optar por realizar una sola iteración, podemos observar cómo cada vez que se ejecuta esta operación, el número generado es diferente, obteniendo en la primera el número en binario 000, equivalente en decimal al 0, mientras que en la segunda el 101, o en decimal el 5.
Figura 2 Histograma resultado tras un lanzamiento
Por otro lado, en el caso que se quieran obtener un conjunto de números aleatorios, y no importe el orden en el que se reciban, se puede ejecutar el mismo circuito con un número de ejecuciones determinadas, como en el siguiente ejemplo donde se buscan 100 números aleatorios entre el 0 y el 7. Observando en esta ocasión todas las posibilidades de números desde el 000 hasta el 111, junto con el número de veces que ha salido como resultado de la generación aleatoria
Figura 3Histograma resultado tras múltiples lanzamientos
Ejemplo práctico con qSOA®
Gracias a las funcionalidades de QuantumPath® y la flexibilidad de qSOA® existirán múltiples contextos en los que desarrollar sistemas híbridos que puedan emplear números verdaderamente aleatorios. En este artículo, nos centraremos en dos posibles formas de explotar los activos del problema:
1) Mediante un diseño gráfico asistido del circuito y su flujo. Ejecutarlo y validar sus resultados gráficamente. Y posteriormente lanzar la ejecución desde el cliente rico desarrollado en Python y explotar los resultados.
2) Desde el propio cliente rico, generar dinámicamente los activos necesarios para componer los activos y posteriormente ejecutarlos.
Implementemos el ejemplo propuesto.
La solución se puede integrar como un sistema híbrido clásico-cuántico gracias a qSOA® y, como se va a mostrar a continuación, mediante el SDK QuantumPath® en Python. Todo ello dentro de un entorno como puede ser un Jupyter Notebook. Como prerrequisito, deberemos tener instalado el paquete QuantumPathQSOAPySDK y contar con acceso a la plataforma de QPath®. Es importante remarcar que, para trabajar con QPath®, exclusivamente necesitará ese paquete y un entorno de trabajo Python. Nada más. Dado que todos los potenciales proveedores de tecnología cuántica son responsabilidad de QuantumPath®, el desarrollador no se tendrá que preocupar por ello gracias a su capacidad agnóstica.
Para acceder a QuantumPath®, si no dispone de una suscripción, le recomendamos que se registre en la free developer subscription. Para más información en cómo preparar el entorno, acceda a la documentación del producto.
Prepararlo todo: la solución QuantumPath®
Antes de iniciar el proceso de creación del circuito en sí, se debe preparar la solución que albergará el circuito y su flujo. También se seleccionarán los diferentes proveedores de máquinas cuánticas y simuladores disponibles en QuantumPath®. Para posteriormente ejecutar los aplicativos creados en cualquiera de ellos sin tener que preocuparse por las diferentes naturalezas de cada arquitectura. Realizando todo este proceso de manera completamente agnóstica.
Figura 4 Detalles de la solución QuantumPath®
Contexto 1: desarrollo visual de los activos. Integración con qSOA®
En este contexto, la creación del circuito y del flujo se puede realizar desde la interfaz de QuantumPath® de forma totalmente explícita y asistida con los diseñadores, como se muestra a continuación:
Figura 5 Diseño del circuito en QuantumPath®
Prosiguiendo con el flujo asociado al circuito, marcando la casilla de publicar en qSOA®:
Figura 6 Diseño del flujo en QuantumPath®
Este contexto aporta la ventaja de que todo el diseño se hace asistido por QuantumPath® y puede ser probado y testeado con sus herramientas. De tal manera que el producto final, solamente tiene que ser explotado como un caso de uso ante el sistema clásico con el que lo integraremos.
Finalmente, llega la integración con qSOA®, donde prepararemos la ejecución y obtendremos los resultados. En lugar de escribir un código muy escueto, escribamos un “cliente rico” que estará preparado para otros circuitos y flujos, de tal manera que los datos que pueden variar se puedan pedir por pantalla o recogerlos de cualquier otro tipo de proceso…
# PLATFORM CONNECTION
from QuantumPathQSOAPySDK import QSOAPlatform
qsoa = QSOAPlatform(input(‘Username’), input(‘Password(SHA-256)’))
# REQUEST THE SOLUTION
solutionList = qsoa.getQuantumSolutionList()
solutionList = {y: x for x, y in solutionList.items()}
print(‘Solution List:’, list(solutionList.keys()))
solution = solutionList[input(‘SolutionName: ‘)]
# SHOW THE DIFFERENT QUANTUM DEVICES OF THE
SOLUTION
deviceList = qsoa.getQuantumDeviceList(solution)
deviceList = {y: x for x, y in deviceList.items()}
print(‘Device List:’, list(deviceList.keys()))
device =
deviceList[input(‘Device Name: ‘)]
# REQUEST THE FLOW
flowList = qsoa.getQuantumFlowList(solution)
flowList = {y: x for x, y in flowList.items()}
print(‘Flow List:’, list(flowList.keys()))
flow =
flowList[input(‘Flow Name: ‘)]
# EXECUTION
applicationName = input(‘Application Name: ‘)
application = qsoa.runQuantumApplicationSync(applicationName, solution, flow, device)
# PROCESS RESULTS
execution = qsoa.getQuantumExecutionResponse(application)
qsoa.representResults(execution)
Contexto 2: desarrollo dinámico de los activos, integración completa con qSOA®
De forma similar al contexto 1, pero en este caso los activos los definiremos de forma dinámica. La opción dinámica tiene como ventajas que tanto su diseño inicial, como refactorizaciones posteriores, se pueden realizar modificando el circuito y/o el flujo a partir de requisitos de negocio si fuera el caso.
Respecto al programa anterior, de forma similar se realiza la conexión a la plataforma…
# PLATFORM CONNECTION
from QuantumPathQSOAPySDK import QSOAPlatform
qsoa = QSOAPlatform(input(‘Username’), input(‘Password(SHA-256)’))
# REQUEST THE SOLUTION
solutionList = qsoa.getQuantumSolutionList()
solutionList = {y: x for x, y in solutionList.items()}
print(‘Solution List:’, list(solutionList.keys()))
solution = solutionList[input(‘Solution Name: ‘)]
y a partir de aquí viene los cambios: se desarrolla el cuerpo del circuito mediante las funciones del API asignadas para ello, construyendo el lenguaje visual de la siguiente forma:
# CREATE ASSET: circuit and main flow
# DEVELOPMENT OF THE CIRCUIT VL
circuit = qsoa.CircuitGates()
circuit.h([0, 1, 2])
circuit.measure()
circuitName = input(‘Circuit Name: ‘)
circuitNamespace = input(‘Circuit Namespace: ‘)
circuitDescription = input(‘Circuit Description: ‘)
circuitBody = circuit
circuitType = ‘GATES’
circuitLevel = ‘VL’
qsoa.createAssetSync(solution, circuitName, circuitNamespace, circuitDescription, circuitBody, circuitType, circuitLevel)
# CREATE FLOW ASSET
flowName = input(‘Flow Name: ‘)
flowNamespace = circuitNamespace
flowDescription = input(‘Flow Description: ‘)
flowBody = ‘ABSTRACT(START,);CIRCUIT(‘ + flowNamespace + ‘.’ + circuitName + ‘);ABSTRACT(END,);’
flowLevel = ‘IL’
assetFlow = qsoa.createAssetFlowSync(solution, flowName, flowNamespace, flowDescription, flowBody, flowLevel, publish=True)
flow = assetFlow.getIdAsset()
Finalmente se procede a la ejecución en el ordenador cuántico, la recogida de resultados, y su representación gráfica. Como se puede observar, de nuevo es una parte común a todos los contextos. En esta ocasión se va a ejecutar dos veces: indicando en cada ocasión el dispositivo cuántico y mostrando el número obtenido.
# QUANTUM DEVICES
deviceList = qsoa.getQuantumDeviceList(solution)
deviceList = {y: x for x, y in deviceList.items()}
print(‘Device List:’, list(deviceList.keys()))
for i in range(2):
# EXECUTION
applicationName = input(‘Application Name: ‘)
device = deviceList[input(‘Device Name: ‘)]
application = qsoa.runQuantumApplicationSync(applicationName, solution, flow, device)
# RESULTS
execution = qsoa.getQuantumExecutionResponse(application)
print(‘Random Numer:’, int(list(list(execution.getHistogram().values())[0].keys())[0], 2))
qsoa.representResults(execution)
Como se puede ver en la imagen superior, se vuelven a obtener números completamente aleatorios. Mostrando así cómo se puede integrar el mundo cuántico con el clásico y ofrecer soluciones reales a problemas que la computación clásica no puede resolver satisfactoriamente.
Hay que remarcar, que todos los assets generados con qSOA® quedan almacenados en la solución y pueden ser gestionados desde el entorno visual que aporta a la plataforma Q Assets Compositor®. Lo que permite poder seguir gestionando el ciclo de vida gráficamente también. El diccionario de assets se puede explotar con todos los casos de usos conocidos de la informática clásica, y su gestión quedará definida por el negocio.