Guía de usuario para el lenguaje de programación cuántica Q#

El lenguaje de programación cuántica Q# forma parte del kit de desarrollo de Quantum de Microsoft, el cual proporciona una compatibilidad total con el IDE, así como herramientas para la visualización y el análisis de los programas. Con Q# y el kit de desarrollo de Quantum (QDK), puede escribir los programas cuánticos y ejecutarlos en hardware cuántico real mediante Azure Quantum.

Para más información, consulte cómo configurar el entorno de desarrollo cuántico y cómo enviar trabajos de Q# a Azure Quantum.

La guía de usuario de Q# contiene:

  • Formas de ejecutar un programa de Q#: un programa de Q# se puede ejecutar como una aplicación independiente o con un programa host adicional, escrito en Python o en un lenguaje .NET.

  • Programas de Q# de prueba y depuración: al igual que con la programación clásica, es esencial poder comprobar que los programas cuánticos actúan según lo previsto y poder diagnosticar comportamientos incorrectos. El kit de desarrollo de Quantum para probar y depurar programas cuánticos.

  • La guía del lenguaje Q#: Q# es un lenguaje independiente que ofrece un alto nivel de abstracción. No hay ninguna noción de un estado cuántico o un circuito; en su lugar, Q# implementa programas en términos de instrucciones y expresiones, de forma muy similar a los lenguajes de programación clásicos. La guía del lenguaje Q# proporciona especificación y documentación completa del lenguaje de programación cuántica Q#.

  • Documentación de simuladores cuánticos: los simuladores cuánticos son programas de software que se ejecutan en equipos clásicos y actúan como máquina de destino para los programas de Q#. Permiten ejecutar y probar programas cuánticos en equipos clásicos.

  • La documentación de biblioteca de Q#: el kit de desarrollo de Quantum proporciona funcionalidad adicional específica del dominio a través de paquetes NuGet que se pueden agregar a los proyectos de Q#. La documentación incluye operaciones, funciones, tipos definidos por el usuario, ejemplos y conceptos que constituyen la biblioteca estándar de Q#, así como las bibliotecas de química cuántica, aprendizaje automático cuántico y valores numéricos cuánticos.

¿Qué hay en un programa de Q#?

Vamos a explorar las partes generales que se encuadran en un programa de Q#. Considere el programa de Q# siguiente:

namespace HelloQuantum {

    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;


    @EntryPoint()
    operation SayHelloQ() : Unit {
        Message("Hello quantum world!");
    }
}

EntryPoint indica al compilador de Q# dónde empezar a ejecutar el programa. El programa imprime este mensaje:

    Hello quantum world!

Espacios de nombres

Por lo general, los archivos de Q# comienzan con un espacio de nombres. Este es un ejemplo:

namespace HelloQuantum {
    // Your code goes here.
}

Los espacios de nombres ayudan a organizar la funcionalidad relacionada. Su uso es importante cuando utilizamos bibliotecas de Q# en nuestros programas y cuando escribimos nuestras propias bibliotecas.

Bibliotecas

Q# hace un uso extenso de las bibliotecas. Una biblioteca es un paquete que contiene funciones y operaciones que se pueden usar en programas cuánticos.

Por ejemplo, la biblioteca Microsoft.Quantum.Chemistry nos ayuda a realizar cálculos cuánticos relacionados con la química. Existen varias bibliotecas estándar que incluyen todo tipo de operaciones básicas.

Cuando se llama a una función u operación desde una biblioteca, debemos especificar el espacio de nombres de la biblioteca. Este es un ejemplo que llama a la función Message de la biblioteca de Microsoft.Quantum.Intrinsic para imprimir un mensaje en la consola:

namespace HelloQuantum {

    @EntryPoint()
    operation SayHelloQ() : Unit {
        Microsoft.Quantum.Intrinsic.Message("Hello quantum world!");
    }
}

Lo más habitual es usar la directiva open para que el código sea más conciso y resulte más fácil de leer.

Este ejemplo hace lo mismo que el ejemplo anterior, salvo que aquí se usa la directiva open para incluir el espacio de nombres Microsoft.Quantum.Intrinsic en el programa:

namespace HelloQuantum {

    open Microsoft.Quantum.Intrinsic;

    @EntryPoint()
    operation SayHelloQ() : Unit {
        Message("Hello quantum world!");
    }
}

Aquí, simplemente especificamos Message y el compilador entiende a qué espacio de nombres pertenece.

La documentación de Q# proporciona información de referencia completa de cada biblioteca integrada. Para obtener más información, consulte la documentación de las bibliotecas de Q#.

Tipos

Q# proporciona muchos tipos integrados que ya conocemos (como Int, Double, Bool y String), además de otros tipos que son específicos de la computación cuántica. Por ejemplo, el tipo Result representa el resultado de la medición de un cúbit y puede tener uno de dos valores posibles: One y Zero. Q# también proporciona tipos que definen intervalos, matrices y tuplas. Podemos definir incluso nuestros propios tipos personalizados.

En resumen, el sistema de tipos Q# es bastante sencillo, en el sentido de que no hay una noción explícita de clases o interfaces como a la que estamos acostumbrados en lenguajes clásicos como C# o Java.

Asignación de bits cuánticos

En Q#, los cúbits se asignan mediante la palabra clave use. Podemos asignar uno o varios bits cuánticos a la vez.

Este es un ejemplo en el que se asigna un bit cuántico:

// Allocate a qubit.
use q = Qubit();

// Do something with q here.

De manera predeterminada, cada cúbit que asignamos con la palabra clave use comienza en el estado cero.

Operaciones cuánticas

Una vez asignado, un cúbit se puede pasar a las operaciones y funciones, también conocidos como invocables. En cierto modo, esto es todo lo que un programa de Q# puede hacer con un cúbit. Las operaciones son los bloques de creación básicos de un programa de Q#. Una operación Q# es una subrutina cuántica. es decir, es una rutina invocable que contiene operaciones cuánticas que modifican el estado del registro de bits cuánticos.

Para definir una operación de Q#, hay que especificar un nombre para la operación, así como sus entradas y su salida correspondientes. Este es un ejemplo básico:

operation SayHelloQ() : Unit {
    Message("Hello quantum world!");
}

Aquí, SayHelloQ es el nombre de la operación. Toma cero argumentos como entrada y devuelve el tipo Unit, lo que significa que la operación no devuelve ninguna información.

Las bibliotecas de Q# también proporcionan operaciones que puede usar en los programas, por ejemplo, la operación de Hadamard o H. Dado un cúbit en Z, la operación H coloca el cúbit en una superposición uniforme. Una vez en la superposición, el bit cuántico tiene un 50 % de probabilidades de medirse como cero o como uno.

Todas las acciones directas sobre el estado de un cúbit se definen mediante invocables intrínsecos como X y H; es decir, los invocables cuyas implementaciones no se definen en Q# sino que las define la máquina de destino. Lo que realmente hacen estas operaciones solo se concreta en la máquina de destino que elige para ejecutar el programa de Q# específico. Para obtener más información, consulte Implementación de programas de Q#.

Por ejemplo, si ejecuta el programa en el simulador de estado completo, el simulador realiza las operaciones matemáticas correspondientes al sistema cuántico simulado. Pero, en el futuro, cuando la máquina de destino sea un equipo cuántico real, la llamada a estas operaciones en Q# se dirigirá al equipo cuántico para que realice las operaciones reales correspondientes en el hardware cuántico real. Por ejemplo, en un equipo cuántico con iones atrapados, las operaciones cuánticas se realizan mediante pulsaciones de láser sincronizadas con precisión.

Un programa de Q# vuelve a combinar estas operaciones según lo definido por una máquina de destino para crear nuevas operaciones de nivel superior que expresen el cálculo cuántico. De este modo, Q# facilita la expresión de la lógica subyacente a los algoritmos cuánticos e híbridos cuánticos-clásicos, mientras se mantiene general con relación a la estructura de un simulador o una máquina de destino.

Medición de cúbits

Hay muchos tipos de medidas cuánticas, pero Q# se centra en las medidas de proyección en cúbits únicos, también conocido como medidas de Pauli. Después de medir en una base determinada (por ejemplo, la base de cálculo $\ket{0},\ket{1}$), el estado del cúbit se proyecta en el estado base que se midió, lo que destruye cualquier superposición entre los dos.

En Q#, las mediciones de Pauli se realizan aplicando la operación Measure, que realiza una medición conjunta de uno o más cúbits en las bases de Pauli especificadas. La operación Measure devuelve un tipo Result.

Nota:

Si la matriz de base y la matriz del cúbit tienen longitudes diferentes, se producirá un error en la operación Measure.

Para implementar una medida en la base computacional $\ket{0},\ket{1}$, también puede usar la operación M, que realiza una medición de un solo cúbit en la base Z de Pauli. Por lo tanto, la operación M es equivalente a aplicar Measure([PauliZ], [qubit]).

Un ejemplo sencillo es el siguiente programa, que asigna un cúbit en el estado $\ket{0}$ y, a continuación, le aplica una operación Hadamard H y mide el resultado en la base PauliZ.

@EntryPoint()
operation MeasureOneQubit() : Result {
    // Allocate a qubit, by default it is in zero state      
    use q = Qubit();  
    // We apply a Hadamard operation H to the state
    // It now has a 50% chance of being measured 0 or 1  
    H(q);      
    // Now we measure the qubit in Z-basis.
    let result = M(qubit);
    // We reset the qubit before releasing it.
    if result == One { X(qubit); }
    // Finally, we return the result of the measurement.
    return result;
    
}

Para realizar mediciones más allá de una sola medida conjunta, el espacio de nombres Microsoft.Quantum.Measurement incluye operaciones más específicas. Por ejemplo, la operación MultiM toma una matriz de cúbits y devuelve una matriz de resultados de medidas en la base computacional.

Pasos siguientes