Tutorial: Implementación de un generador cuántico de números aleatorios en Q#
Nota
Microsoft Quantum Development Kit (QDK clásico) ya no se admitirá después del 30 de junio de 2024. Si es un desarrollador de QDK existente, se recomienda realizar la transición al nuevo Azure Quantum Development Kit (QDK moderno) para seguir desarrollando soluciones cuánticas. Para obtener más información, consulte Migración Q# del código al QDK moderno.
Aprenda a escribir un programa cuántico básico en Q# que aproveche la naturaleza de la mecánica cuántica para generar un número aleatorio.
En este tutorial:
- Create un Q# programa.
- Revise los componentes principales de un Q# programa.
- Defina la lógica de un problema.
- Combine operaciones clásicas y cuánticas para resolver un problema.
- Trabajar con bits cuánticos y con la superposición para crear un generador de números aleatorios cuántico
Sugerencia
Si desea acelerar el recorrido de la computación cuántica, consulte Código con Azure Quantum, una característica única del sitio web de Azure Quantum. Aquí puede ejecutar ejemplos integrados Q# o sus propios Q# programas, generar código nuevo Q# a partir de las indicaciones, abrir y ejecutar el código en VS Code para la Web con un solo clic y hacer preguntas a Copilot sobre la computación cuántica.
Requisitos previos
Para ejecutar el ejemplo de código en Copilot en Azure Quantum:
- Una cuenta de correo electrónico de Microsoft (MSA).
Para desarrollar y ejecutar el ejemplo de código en Visual Studio Code:
La versión más reciente de Visual Studio Code o abra VS Code en la Web.
La versión más reciente de la extensión de Azure Quantum Development Kit . Para obtener más información sobre la instalación, consulte Instalación del QDK moderno en VS Code.
Si quiere usar cuadernos de Jupyter Notebook, también debe instalar Python y extensiones de Jupyter y el paquete de Python más reciente
qsharp
. Para ello, abra un terminal y ejecute el siguiente comando:$ pip install --upgrade qsharp
Definir el problema
Los equipos clásicos no generan números aleatorios, sino números seudoaleatorios. Un generador de números seudoaleatorios genera una secuencia determinista de números a partir de un valor inicial cualquiera, que es el valor de inicialización. Para aproximarse de mejor forma a los valores aleatorios, este valor de inicialización suele ser la hora actual del reloj de la CPU.
Por otro lado, los equipos cuánticos pueden generar números realmente aleatorios. Esto se debe a que la medición de un cúbit en superposición es un proceso probabilístico. El resultado de la medida es aleatorio y no hay ninguna manera de predecir el resultado. Este es el principio básico de los generadores de números aleatorios cuánticos.
Un cúbit es una unidad de información cuántica que puede estar en superposición. Cuando se mide, un cúbit solo puede estar en el estado 0 o en el estado 1. Sin embargo, antes de la medida, el estado del cúbit representa la probabilidad de leer un 0 o un 1 al tomar una medida.
Para comenzar, tome un cúbit en estado base, por ejemplo, cero. El primer paso del generador de números aleatorios es usar una operación Hadamard para colocar el cúbit en una superposición igual. La medida de este estado da como resultado un cero o uno con una probabilidad del 50 % de cada resultado, un bit realmente aleatorio.
No hay forma de saber lo que obtendrá después de la medición del cúbit en superposición y el resultado es un valor diferente cada vez que se invoca el código. ¿Pero cómo puede usar este comportamiento para generar números aleatorios mayores?
Supongamos que repetimos el proceso cuatro veces, generando así esta secuencia de dígitos binarios:
$${0, 1, 1, 0}$$
Si concatenamos, o combinamos, estos bits en una cadena de bits, podremos formar un número más grande. En este ejemplo, la secuencia de bits ${0110}$ equivale a seis decimal.
$${0110_{\ binario} \equiv 6_{\ decimal}}$$
Si repite este proceso muchas veces, puede combinar varios bits para formar un número grande. Ahora puede proporcionar su superior con ese número como contraseña segura, ya que puede estar seguro de que ningún hacker espacial podría determinar los resultados de la secuencia de medidas.
Definición de la lógica del generador de números aleatorios
Vamos a describir la lógica de un generador de números aleatorios, siempre que tengamos un generador de bits aleatorio:
- Definir
max
como el número máximo que quiere generar. - Definir el número de bits aleatorios que necesita generar. Esto se realiza calculando cuántos bits (
nBits
) necesitamos expresar en enteros hasta llegar amax
. - Generar una cadena de bits aleatorios que tenga una longitud de
nBits
. - Si la cadena de bits representa un número mayor que
max
, hay que volver al paso tres. - Si no, el proceso habrá finalizado. Devolver el número generado como un entero.
Como ejemplo, vamos a establecer max
en 12. Es decir, 12 es el número más grande que desea usar como contraseña segura.
Necesita ${\lfloor ln(12) / ln(2) + 1 \rfloor}$ o 4 bits que representen un número entre cero y 12. (en aras de una mayor brevedad, omitiremos el paso para derivar esta ecuación).
Supongamos que generamos la cadena de bits ${1101_{\ binario}}$, que equivale a ${13_{\ decimal}}$. Como 13 es mayor que 12, repetimos el proceso.
Ahora, generamos la cadena de bits ${0110_{\ binario}}$, que equivale a ${6_{\ decimal}}$. Dado que 6 es menor que 12, el proceso se ha completado.
El generador de números aleatorios cuánticos devolverá el número 6 como contraseña. En la práctica, establezca un número más grande como máximo, ya que los números inferiores son fáciles de descifrar simplemente probando todas las contraseñas posibles. De hecho, para aumentar la dificultad de adivinar o descifrar la contraseña, puede usar código ASCII para convertir binario en texto y generar una contraseña mediante números, símbolos y letras en mayúsculas y minúsculas mezcladas.
Escribir un generador de bits aleatorio
El primer paso es escribir una Q# operación que genera un bit aleatorio. Esta operación será uno de los bloques de creación del generador de números aleatorios.
operation GenerateRandomBit() : Result {
// Allocate a qubit.
use q = Qubit();
// Set the qubit into superposition of 0 and 1 using the Hadamard
H(q);
// At this point the qubit `q` has 50% chance of being measured in the
// |0〉 state and 50% chance of being measured in the |1〉 state.
// Measure the qubit value using the `M` operation, and store the
// measurement value in the `result` variable.
let result = M(q);
// Reset qubit to the |0〉 state.
// Qubits must be in the |0〉 state by the time they are released.
Reset(q);
// Return the result of the measurement.
return result;
}
Ahora, eche un vistazo al nuevo código.
- Defina la operación
GenerateRandomBit
, que no toma ninguna entrada y genera un valor de tipoResult
. El tipoResult
representa el resultado de una medición y puede tener dos valores posibles:Zero
oOne
. - Asigne un solo cúbit con la
use
palabra clave . Cuando se asigna un cúbit, siempre está en el estadoZero
. - La operación se usa
H
para colocar el cúbit en una superposición igual. - La operación se usa
M
para medir el cúbit, devolver el valor medido (Zero
oOne
). - La operación se usa
Reset
para restablecer el cúbit al estado |0〉.
Al colocar el cúbit en superposición con la operación H
y medirlo con la operación M
, el resultado será un valor diferente cada vez que se invoque el código.
Visualización del Q# código con la esfera bloch
En la esfera Bloch, el polo norte representa el valor clásico 0 y el polo sur representa el valor clásico 1. Cualquier superposición se puede representar mediante un punto en la esfera (representado con una flecha). Cuanto más cerca esté el extremo de la flecha a un polo, mayor será la probabilidad de que el cúbit caiga en el valor clásico asignado a ese polo cuando se mida. Por ejemplo, el estado del cúbit representado por la flecha en la ilustración siguiente tiene más probabilidades de dar el valor 0 si lo medimos.
Puede usar esta representación para visualizar lo que está haciendo el código:
En primer lugar, empiece con un cúbit inicializado en el estado 0 y aplique una operación
H
para crear una superposición igual en la que las probabilidades de 0 y 1 sean las mismas.A continuación, se mide el cúbit y se guarda el resultado:
Como el resultado de la medición es aleatorio y las probabilidades de medir 0 y 1 son las mismas, ha obtenido un bit completamente aleatorio. Puede llamar a esta operación varias veces para crear enteros. Por ejemplo, si llama a la operación tres veces para obtener tres bits aleatorios, puede crear números de 3 bits aleatorios (es decir, un número aleatorio entre 0 y 7).
Escribir un generador de números aleatorios completo
En primer lugar, debe agregar los espacios de nombres necesarios Q# al programa. Para el generador de números aleatorios completo, debe incluir tres Q# espacios de nombres:
Microsoft.Quantum.Math
,Microsoft.Quantum.Intrinsic
yMicrosoft.Quantum.Convert
.open Microsoft.Quantum.Convert; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Math;
A continuación, defina la
GenerateRandomNumberInRange
operación. Esta operación llama repetidamente a la operaciónGenerateRandomBit
para generar una cadena de bits./// Generates a random number between 0 and `max`. operation GenerateRandomNumberInRange(max : Int) : Int { // Determine the number of bits needed to represent `max` and store it // in the `nBits` variable. Then generate `nBits` random bits which will // represent the generated random number. mutable bits = []; let nBits = BitSizeI(max); for idxBit in 1..nBits { set bits += [GenerateRandomBit()]; } let sample = ResultArrayAsInt(bits); // Return random number if it is within the requested range. // Generate it again if it is outside the range. return sample > max ? GenerateRandomNumberInRange(max) | sample; }
Paremos un momento a revisar el nuevo código.
- Debe calcular el número de bits necesarios para expresar enteros hasta
max
. LaBitSizeI
función delMicrosoft.Quantum.Math
espacio de nombres convierte un entero en el número de bits necesarios para representarlo. - La operación
SampleRandomNumberInRange
usa un buclefor
para generar números aleatorios hasta llegar a uno que sea igual o menor quemax
. Elfor
bucle funciona exactamente igual que unfor
bucle en otros lenguajes de programación. - La variable es una variable
bits
mutable. Una variable mutable es aquella que puede cambiar durante el cálculo. Para cambiar el valor de una variable mutable, usamos la directivaset
. - La
ResultArrayAsInt
función procede delMicrosoft.Quantum.Convert
espacio de nombres . Esta función convierte la cadena de bits en un entero positivo.
- Debe calcular el número de bits necesarios para expresar enteros hasta
Por último, agregue un punto de entrada. En este ejemplo, la
Main
operación es el punto de entrada del programa. Llama a laGenerateRandomNumberInRange
operación para generar un número aleatorio entre 0 y 100.@EntryPoint() operation Main() : Int { let max = 100; Message($"Sampling a random number between 0 and {max}: "); // Generate random number in the 0..max range. return GenerateRandomNumberInRange(max); }
La directiva
let
declara variables que no cambian durante el cálculo. Aquí definimos el valor máximo como 100.El código completo del generador de números aleatorios es el siguiente:
namespace QuantumRandomNumberGenerator {
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Math;
@EntryPoint()
operation Main() : Int {
let max = 100;
Message($"Sampling a random number between 0 and {max}: ");
// Generate random number in the 0..max range.
return GenerateRandomNumberInRange(max);
}
/// Generates a random number between 0 and `max`.
operation GenerateRandomNumberInRange(max : Int) : Int {
// Determine the number of bits needed to represent `max` and store it
// in the `nBits` variable. Then generate `nBits` random bits which will
// represent the generated random number.
mutable bits = [];
let nBits = BitSizeI(max);
for idxBit in 1..nBits {
set bits += [GenerateRandomBit()];
}
let sample = ResultArrayAsInt(bits);
// Return random number if it is within the requested range.
// Generate it again if it is outside the range.
return sample > max ? GenerateRandomNumberInRange(max) | sample;
}
operation GenerateRandomBit() : Result {
// Allocate a qubit.
use q = Qubit();
// Set the qubit into superposition of 0 and 1 using the Hadamard
H(q);
// At this point the qubit `q` has 50% chance of being measured in the
// |0〉 state and 50% chance of being measured in the |1〉 state.
// Measure the qubit value using the `M` operation, and store the
// measurement value in the `result` variable.
let result = M(q);
// Reset qubit to the |0〉 state.
// Qubits must be in the |0〉 state by the time they are released.
Reset(q);
// Return the result of the measurement.
return result;
}
}
Ejecución del programa generador de números aleatorios
Puede ejecutar el programa en Copilot en Azure Quantum y en Visual Studio Code como una aplicación independiente Q# o mediante un programa host de Python.
Puede probar el Q# código con Copilot en Azure Quantum de forma gratuita: todo lo que necesita es una cuenta de correo electrónico de Microsoft (MSA). Para más información sobre Copilot en Azure Quantum, consulte Exploración de Azure Quantum.
Abra Copilot en Azure Quantum en el explorador.
Copie y pegue el código siguiente en el editor de código.
namespace Tutorial { open Microsoft.Quantum.Convert; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Math; @EntryPoint() operation Main() : Int { let max = 100; Message($"Sampling a random number between 0 and {max}: "); // Generate random number in the 0..max range. return GenerateRandomNumberInRange(max); } /// # Summary /// Generates a random number between 0 and `max`. operation GenerateRandomNumberInRange(max : Int) : Int { // Determine the number of bits needed to represent `max` and store it // in the `nBits` variable. Then generate `nBits` random bits which will // represent the generated random number. mutable bits = []; let nBits = BitSizeI(max); for idxBit in 1..nBits { set bits += [GenerateRandomBit()]; } let sample = ResultArrayAsInt(bits); // Return random number if it is within the requested range. // Generate it again if it is outside the range. return sample > max ? GenerateRandomNumberInRange(max) | sample; } /// # Summary /// Generates a random bit. operation GenerateRandomBit() : Result { // Allocate a qubit. use q = Qubit(); // Set the qubit into superposition of 0 and 1 using the Hadamard // operation `H`. H(q); // At this point the qubit `q` has 50% chance of being measured in the // |0〉 state and 50% chance of being measured in the |1〉 state. // Measure the qubit value using the `M` operation, and store the // measurement value in the `result` variable. let result = M(q); // Reset qubit to the |0〉 state. // Qubits must be in the |0〉 state by the time they are released. Reset(q); // Return the result of the measurement. return result; // Note that Qubit `q` is automatically released at the end of the block. } }
Seleccione el número de tomas que se van a ejecutar y haga clic en Ejecutar.
Los resultados se muestran en el histograma y en los campos Resultados .
Haga clic en Explicar código para preguntar a Copilot para explicarle el código.
Sugerencia
Desde Copilot en Azure Quantum, puede abrir el programa en VS Code para la Web haciendo clic en el botón del logotipo de VS Code en la esquina derecha del editor de código.
Nota
Este fragmento de código no se ejecuta actualmente en ningún hardware targetsde Azure Quantum disponible, ya que el invocable ResultArrayAsInt
requiere una QPU con un perfil de cálculo completo.
Pasos siguientes
Explore otros tutoriales de Q#:
- El entrelazamiento cuántico muestra cómo escribir un Q# programa que manipula y mide cúbits y muestra los efectos de la superposición y el entrelazamiento.
- El algoritmo de búsqueda de Grover muestra cómo escribir un Q# programa que usa el algoritmo de búsqueda de Grover.
- Quantum Fourier Transforms explora cómo escribir un Q# programa que direccione directamente cúbits específicos.
- Quantum Katas son tutoriales autodirigido y ejercicios de programación destinados a enseñar los elementos de la computación cuántica y Q# la programación al mismo tiempo.
Comentarios
https://aka.ms/ContentUserFeedback.
Próximamente: A lo largo de 2024 iremos eliminando gradualmente las Cuestiones de GitHub como mecanismo de retroalimentación para el contenido y lo sustituiremos por un nuevo sistema de retroalimentación. Para más información, consulta:Enviar y ver comentarios de