Estructura de un Q# programa

En este artículo se exploran los componentes generales que componen un Q# programa. Tenga en cuenta que Q# los programas escritos en Jupyter Notebooks no usan algunos de estos componentes: estas diferencias se describen en cada sección.

Considere el programa de Q# siguiente:

namespace Superposition {

    @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(q);
        // We reset the qubit before releasing it.
        Reset(q);
        // Finally, we return the result of the measurement.
        return result;
    }
}

Simplemente leyendo los comentarios (//), puede indicar que este programa asigna un cúbit, aplica una operación para colocarla en superposición, mide el estado del cúbit, la restablece y devuelve el resultado.

Para ejecutar este programa en Visual Studio Code, consulte Introducción a Q# los programas y VS Code.

Espacios de nombres de usuario

Q# Normalmente, los programas comienzan con un espacio de nombres con nombre de usuario, como

namespace Superposition {
    // Your code goes here.
}

Los espacios de nombres ayudan a organizar la funcionalidad relacionada. Los espacios de nombres son con nombre de usuario y solo puede haber uno namespace por archivo qsharp (*.qs).

La Q# biblioteca estándar tiene espacios de nombres predefinidos que contienen funciones y operaciones que puede usar en programas cuánticos. Para obtener más información, consulte Espacios de nombres integrados.

Los cuadernos de Jupyter Notebook no usan espacios de nombres de usuario.

EntryPoint()

El @EntryPoint() atributo indica al Q# compilador dónde empezar a ejecutar el programa. En los programas con varias definiciones de función y operación, @EntryPoint() se puede colocar antes de que cualquiera de las funciones o las operaciones y el flujo de programa comiencen desde allí y continúen secuencialmente.

    ...
    @EntryPoint()
    operation MeasureOneQubit() : Result {
        ...

Los cuadernos de Jupyter Notebook no usan puntos de entrada.

Comando %%qsharp

De forma predeterminada, Q# los programas de Jupyter Notebook usan el kernel de Python de ipykernel . Para agregar Q# código a una celda de cuaderno, debe usar el %%qsharp comando , que está habilitado con el qsharp paquete de Python. Por ejemplo, el código de ejemplo anterior de un Jupyter Notebook tiene este aspecto:

import qsharp
%%qsharp

    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(q);
        // We reset the qubit before releasing it.
        Reset(q);
        // Display the result
        Message($"Result is {result}");
        // Finally, we return the result of the measurement.
        return result;
    
    }
    MeasureOneQubit();

Tenga en cuenta la ausencia de un espacio de nombres de usuario o , @EntryPoint()que no son necesarios para jupyter Notebooks. En lugar de un punto de entrada, se llama a la operación directamente en la última línea. Tenga en cuenta también que se agregó una Message instrucción al código Jupyter Notebook para mostrar el resultado. Al ejecutar el programa anterior Q# en VS Code, el simulador integrado muestra el resultado de forma predeterminada.

Al usar el %%qsharp comando :

  • Primero debe ejecutar import qsharp para habilitar el comando %%qsharp.
  • El %%qsharp comando tiene como ámbito toda la celda en la que aparece. Tenga en cuenta que cambia el tipo de celda del cuaderno de Python a Q#.
  • El código de Q# que sigue al comando debe seguir la sintaxis de codificación estándar de Q#. Por ejemplo, se indican comentarios mediante // en lugar de dentro %%qsharp de # las celdas, y las líneas de código deben terminar con un punto y coma ;.
  • El comando %%qsharp no puede ir precedido ni seguido de una instrucción de Python dentro de su celda.

Para obtener un ejemplo de cómo trabajar con un programa de Jupyter Notebook, consulte Introducción a Q# los programas y VS Code.

Tipos

Q# proporciona muchos tipos integrados que son comunes a la mayoría de los lenguajes, incluidos Int, Double, Booly String, junto con tipos específicos de la computación cuántica. Por ejemplo, el Result tipo representa el resultado de cualquier medida de cúbit y puede tener uno de los dos valores posibles definidos: One y Zero. En el programa de ejemplo, la operación MeasureOneQubit() espera un tipo de valor devuelto de Result y la M operación mide el cúbit y devuelve .Result

...
// operation definition expecting a return type of Result
operation MeasureOneQubit() : Result {
    ...
    // Now we measure the qubit in Z-basis, returning a Result type
    let result = M(q);
    ...
}

Q# también proporciona tipos que definen intervalos, matrices y tuplas. Podemos definir incluso nuestros propios tipos personalizados.

Asignación de bits cuánticos

En Q#, los cúbits se asignan mediante la palabra clave use.

En nuestro ejemplo se define un único cúbit:

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

pero también puede asignar varios cúbits y acceder a cada uno a través de su índice:

...
use qubits = Qubit[2];
X(qubits[1]);
H(qubits[0]);
...

De manera predeterminada, cada cúbit que asignamos con la palabra clave use comienza en el estado cero. Cada cúbit debe restablecerse de nuevo el estado cero antes de que se libere al final del programa. No se puede restablecer un cúbit desencadena un error en tiempo de ejecución.

// Reset a qubit.
Reset(q);
...

Operaciones cuánticas

Una vez asignado, un cúbit se puede pasar a las operaciones y funciones, también conocidos como invocables. 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. En nuestro ejemplo, la operación única es básicamente todo el programa. No toma parámetros y espera un tipo de valor devuelto de Result:

operation MeasureOneQubit() : Result {
    ...
}

Este es un ejemplo básico que no toma ningún parámetro y espera ningún valor devuelto. El Unit valor es equivalente a NULL en otros idiomas.

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

La Q# biblioteca estándar también proporciona operaciones que puede usar en los programas, por ejemplo, Hadamard o la H operación que se usa en el programa de ejemplo. 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.

Medición de cúbits

Hay muchos tipos de medidas cuánticas, pero Q# se centra en las mediciones projectivas en cúbits individuales, también conocidos como mediciones 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.

Nuestro programa de ejemplo usa la M operación , que realiza una medida de un único cúbit en la base Pauli Z y devuelve un Result tipo.

Espacios de nombres integrados

La biblioteca estándar Q# usa espacios de nombres integrados que contienen funciones y operaciones que puede usar en programas cuánticos. Por ejemplo, el espacio de nombres Microsoft.Quantum.Intrinsic contiene operaciones y funciones usadas habitualmente, como M, para medir los resultados y Message, para mostrar mensajes de usuario en cualquier parte del programa.

Puede llamar a una función o operación especificando el espacio de nombres completo, o use una open instrucción para que todas las funciones y operaciones de ese espacio de nombres estén disponibles y para facilitar la lectura del código. Estos dos ejemplos llaman a la misma operación:

 Microsoft.Quantum.Intrinsic.Message("Hello quantum world!");
open Microsoft.Quantum.Intrinsic;
Message("Hello quantum world!");

Observe que en el programa de ejemplo no hay instrucciones open ni llamadas con espacios de nombres completos. Esto se debe a que el Q# entorno de desarrollo carga automáticamente dos espacios de nombres de forma predeterminada, Microsoft.Quantum.Core y Microsoft.Quantum.Intrinsic , que contienen funciones y operaciones que se usan habitualmente.

Puede aprovechar el Microsoft.Quantum.Measurement espacio de nombres y usar la MResetZ operación para optimizar el código en el programa de ejemplo. MResetZ combina las operaciones de medición y restablecimiento en un paso, como en el ejemplo siguiente:

namespace Superposition {

    // open the namespace for the MResetZ operation
    open Microsoft.Quantum.Measurement;

    @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);   
        // Measure and reset the qubit, and return the result value   
        return MResetZ(q);
    }
    
}