Tutorial: Exploración del entrelazamiento cuántico con Q#

En este tutorial, se muestra cómo escribir un programa de Q# que manipula y mide cúbits, y muestra los efectos de la superposición y el entrelazamiento. Puede preparar dos cúbits en un estado cuántico específico, aprender a operar en cúbits con para Q# cambiar su estado y demostrar los efectos de la superposición y el entrelazamiento. Cree el Q# programa de forma por pieza para introducir estados, operaciones y medidas de cúbits.

Nota

El Kit de desarrollo de Microsoft Quantum (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 kit de desarrollo de Azure Quantum (QDK moderno) para seguir desarrollando soluciones cuánticas. Para obtener más información, consulte Migración Q# del código al QDK moderno.

Estos son algunos conceptos clave para comprender antes de comenzar:

  • Mientras que los bits clásicos contienen un único valor binario, como 0 o 1, el estado de un cúbit puede ser una superposición de dos estados cuánticos, 0 y 1. Cada estado cuántico posible tiene una amplitud de probabilidad asociada.
  • El acto de medir un cúbit genera un resultado binario con una probabilidad determinada y cambia el estado del cúbit fuera de la superposición.
  • Se pueden entrelazar varios cúbits de forma que no se puedan describir de forma independiente entre sí. Es decir, lo que le suceda a un cúbit en un par entrelazado, también le sucede al otro cúbit.

En este tutorial, aprenderá a:

  • Cree Q# operaciones para inicializar un cúbit en un estado deseado.
  • Colocar un cúbit en superposición.
  • Entrelazar un par de cúbits.
  • Mida un cúbit y observe los resultados.

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 formular a Copilot cualquier pregunta sobre la computación cuántica.

Requisitos previos

Para ejecutar el ejemplo de código en Copilot para Azure Quantum, necesita:

  • Una cuenta de correo electrónico de Microsoft (MSA).

Para más información sobre Copilot, consulte Exploración de Azure Quantum.

Inicialización de un cúbit en un estado conocido

El primer paso consiste en definir una operación Q# que inicializará un cúbit en un estado conocido. Se puede llamar a para establecer un cúbit en un estado clásico, lo que significa que, cuando se mide, devuelve Zero el 100 % del tiempo o devuelve One el 100 % del tiempo. La medición de un cúbit devuelve un Q# tipo Result, que solo puede tener un valor de Zero o One.

Abra Copilot para Azure Quantum y copie el código siguiente en la ventana del editor de código. No haga clic en Ejecutar todavía; Ejecutará el código más adelante en el tutorial.

   namespace Bell {
       open Microsoft.Quantum.Intrinsic;
       open Microsoft.Quantum.Canon;

       operation SetQubitState(desired : Result, target : Qubit) : Unit {
           if desired != M(target) {
               X(target);
           }
       }
   }

El código presenta dos operaciones estándar: M y X, que transforman el estado de un cúbit.

La operación SetQubitState:

  1. Toma dos parámetros: un tipo Result, denominado desired, que representa el estado deseado para que el cúbit esté en (Zero o One) y un tipo Qubit.
  2. Realiza una operación de medición, M, que mide el estado del cúbit (Zero o One) y compara el resultado con el valor especificado en desired.
  3. Si la medición no coincide con el valor comparado, ejecuta una operación X, que invierte el estado del cúbit para que las probabilidades de que una medición devuelva Zero y One se inviertan. De este modo, SetQubitState siempre coloca el qubit de destino en el estado deseado.

Escribir una operación de prueba para probar el estado de Bell

A continuación, para mostrar el efecto de la operación SetQubitState, cree otra operación denominada TestBellState. Esta operación asignará dos cúbits, llamará SetQubitState a para establecer el primer cúbit en un estado conocido y, a continuación, medirá los cúbits para ver los resultados.

Copie el código siguiente en la ventana del editor de código, debajo de la SetQubitState operación.

operation TestBellState() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

}

En el código, las count variables y initial se establecen 1000 en y One respectivamente. El primer cúbit se inicializa en One y cada cúbit se mide 1000 veces.

La operación TestBellState:

  1. Establece variables para el contador y el estado de cúbit inicial.
  2. Llama a la instrucción use para inicializar dos cúbits.
  3. Recorre las iteraciones de count. Para cada bucle:
    1. Llama a SetQubitState para establecer un valor initial especificado en el primer cúbit.
    2. Llama de nuevo a SetQubitState para establecer el segundo cúbit en estado Zero.
    3. Usa la operación M para medir cada cúbit.
    4. Almacena el número de mediciones de cada cúbit que devuelve One.
  4. Una vez completado el bucle, llama de nuevo a SetQubitState para restablecer los cúbits a un estado conocido (Zero) y así permitir que otros usuarios asignen los cúbits con un estado conocido. Esto es necesario para la instrucción use.
  5. Por último, usa la Message función para imprimir los resultados en las ventanas de salida de Copilot antes de devolver los resultados.

Ejecución del código en Copilot para Azure Quantum

Antes de pasar a los procedimientos de superposición y entrelazamiento, puede probar el código hasta este punto para ver la inicialización y medición de los cúbits.

Para ejecutar el código como un programa independiente, el Q# compilador de Copilot debe saber dónde iniciar el programa. Esto se hace en el Q# archivo agregando directamente una @EntryPoint() operación anterior a la que desea ejecutar primero. Por ejemplo, en este caso es la TestBellState operación .

Nota:

@EntryPoint() solo es necesario para programas de Q# independientes. Cuando se ejecuta un Q# programa en Jupyter Notebooks o se llama a un Q# programa desde un archivo host de Python, no es necesario y se producirá un error si se incluye.

Agregue inmediatamente antes TestBellState de la @EntryPoint() operación y el Q# programa hasta este punto debería tener este aspecto:

namespace Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

    operation SetQubitState(desired : Result, target : Qubit) : Unit {
        if desired != M(target) {
            X(target);
        }
    }

    @EntryPoint()
    operation TestBellState() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = One;

        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
            
            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
        
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }
}

Copie y pegue el ejemplo de código completo en la ventana Código de Copilot para Azure Quantum , establezca la diapositiva del número de capturas en "1" y haga clic en Ejecutar. Los resultados se muestran en el histograma y en los campos Resultados .

Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 1000
Q2 - Ones: 0

Dado que los cúbits aún no se han manipulado, han conservado sus valores iniciales: el primer cúbit devuelve One cada vez y el segundo cúbit devuelve Zero.

Si cambia el valor de initial a y vuelve a Zero ejecutar el programa, debe observar que el primer cúbit también devuelve Zero cada vez.

Q1 - Zeros: 1000
Q1 - Ones: 0
Q2 - Zeros: 1000
Q2 - Ones: 0

Colocación de un qubit en superposición

Actualmente, los cúbits del programa están en un estado clásico, es decir, son 1 o 0. Lo sabe porque el programa inicializa los cúbits en un estado conocido y no ha agregado ningún proceso para manipularlos. Antes de entrelazar los cúbits, colocará el primer cúbit en un estado de superposición, donde una medida del cúbit devolverá Zero aproximadamente el 50 % del tiempo y One aproximadamente el 50 % del tiempo. Conceptualmente, el cúbit se puede considerar como tener una probabilidad igual de medir o ZeroOne.

Para colocar un cúbit en superposición, Q# proporciona la operación H, o Hadamard. Recuerde la X operación de Inicializar un cúbit en un procedimiento de estado conocido anteriormente, que voltea un cúbit de 0 a 1 (o viceversa); la H operación voltea el cúbit a medio camino en un estado de probabilidades iguales de Zero o One. Cuando se mide, un cúbit en superposición debe devolver aproximadamente un número igual de resultados Zero y One.

Modifique el código de la TestBellState operación restableciendo el valor inicial en One e insertando una línea para la H operación:

for test in 1..count {
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        H(q1);                // Add the H operation after initialization and before measurement

        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2); 
        ...

Ahora, al ejecutar el programa, puede ver los resultados del primer cúbit en la superposición.

Q1 - Zeros: 523            // results will vary
Q1 - Ones: 477
Q2 - Zeros: 1000
Q2 - Ones: 0

Cada vez que ejecute el programa, los resultados del primer cúbit variarán ligeramente, pero estarán cercanos a One y Zero el 50% de las veces, mientras que los resultados del segundo cúbit permanecerán en Zero todo el tiempo.

Q1 - Zeros: 510           
Q1 - Ones: 490
Q2 - Zeros: 1000
Q2 - Ones: 0

La inicialización del primer cúbit en Zero devuelve resultados similares.

Q1 - Zeros: 504           
Q1 - Ones: 496
Q2 - Zeros: 1000
Q2 - Ones: 0

Nota

Al mover el control deslizante en Copilot para Azure Quantum y aumentar el número de tomas, puede ver cómo los resultados de la superposición varían ligeramente sobre la distribución de las tomas.

Entrelazamiento de dos qubits

Como se mencionó anteriormente, los cúbits entrelazados están conectados de modo que no se puedan describir de forma independiente entre sí. Es decir, la operación que le suceda a un cúbit, también le sucede al cúbit entrelazado. Esto permite conocer el estado resultante de un cúbit sin medirlo, simplemente midiendo el estado del otro cúbit. (En este ejemplo se usan dos cúbits; sin embargo, también es posible entrelazar tres o más cúbits).

Para habilitar el entrelazamiento, Q# proporciona la operación CNOT, que significa Controlled-NOT. El resultado de ejecutar esta operación en dos cúbits es la inversión del segundo cúbit si el primero es One.

Agregue la operación CNOT al programa inmediatamente después de la operación H. El programa completo debería tener este aspecto:

namespace Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

       operation SetQubitState(desired : Result, target : Qubit) : Unit {
           if desired != M(target) {
               X(target);
           }
       }

    @EntryPoint()
    operation TestBellState() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = Zero;

        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
        
            H(q1);            
            CNOT(q1, q2);      // Add the CNOT operation after the H operation

            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
        
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }
}

Ahora, al ejecutar el programa, debería ver algo parecido a:

Q1 - Zeros: 502           // results will vary
Q1 - Ones: 498
Q2 - Zeros: 502
Q2 - Ones: 498

Observe que las estadísticas del primer cúbit no han cambiado (todavía hay una probabilidad de ~50/50 de una Zero o One después de la medición), pero los resultados de la medición del segundo cúbit siempre son los mismos que la medida del primer cúbit, independientemente de cuántas veces ejecute el programa. La operación CNOT ha entrelazado los dos cúbits, de modo que lo que le sucede a uno, le sucede al otro.

Requisitos previos

Para desarrollar y ejecutar el ejemplo de código en el entorno de desarrollo local:

Creación de un nuevo Q# archivo

  1. Abra Visual Studio Code y seleccione Archivo > nuevo archivo de texto para crear un nuevo archivo.
  2. Guarde el archivo como CreateBellStates.qs. Este archivo contendrá el Q# código del programa.

Inicialización de un cúbit en un estado conocido

El primer paso consiste en definir una operación Q# que inicializará un cúbit en un estado conocido. Se puede llamar a esta operación para poner un cúbit en un estado clásico, lo que significa que o bien devuelve Zero el 100 % de las veces, o devuelve One el 100 % de las veces. Zero y One son valors de Q# que representan los únicos dos resultados posibles de la medida de un cúbit.

Abra CreateBellStates.qs y copie el código siguiente:

   namespace Bell {
       open Microsoft.Quantum.Intrinsic;
       open Microsoft.Quantum.Canon;

       operation SetQubitState(desired : Result, target : Qubit) : Unit {
           if desired != M(target) {
               X(target);
           }
       }
   }

El código presenta dos operaciones estándar: M y X, que transforman el estado de un cúbit.

La operación SetQubitState:

  1. Toma dos parámetros: un tipo Result, denominado desired, que representa el estado deseado para que el cúbit esté en (Zero o One) y un tipo Qubit.
  2. Realiza una operación de medición, M, que mide el estado del cúbit (Zero o One) y compara el resultado con el valor especificado en desired.
  3. Si la medición no coincide con el valor comparado, ejecuta una operación X, que invierte el estado del cúbit para que las probabilidades de que una medición devuelva Zero y One se inviertan. De este modo, SetQubitState siempre coloca el qubit de destino en el estado deseado.

Escribir una operación de prueba para probar el estado de Bell

A continuación, para mostrar el efecto de la operación SetQubitState, cree otra operación denominada TestBellState. Esta operación asignará dos cúbits, llamará SetQubitState a para establecer el primer cúbit en un estado conocido y, a continuación, medirá los cúbits para ver los resultados.

Agregue la siguiente operación a su archivo CreateBellStates.qs después de la operación SetQubitState:

operation TestBellState() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

}

En el código, las count variables y initial se establecen 1000 en y One respectivamente. El primer cúbit se inicializa en One y cada cúbit se mide 1000 veces.

La operación TestBellState:

  1. Toma dos parámetros: count, el número de veces que se ejecuta una medición y initial, el estado deseado para inicializar el cúbit.
  2. Llama a la instrucción use para inicializar dos cúbits.
  3. Recorre las iteraciones de count. Para cada bucle:
    1. Llama a SetQubitState para establecer un valor initial especificado en el primer cúbit.
    2. Llama de nuevo a SetQubitState para establecer el segundo cúbit en estado Zero.
    3. Usa la operación M para medir cada cúbit.
    4. Almacena el número de mediciones de cada cúbit que devuelve One.
  4. Una vez completado el bucle, llama de nuevo a SetQubitState para restablecer los cúbits a un estado conocido (Zero) y así permitir que otros usuarios asignen los cúbits con un estado conocido. Esto es necesario para la instrucción use.
  5. Por último, usa la función Message para imprimir un mensaje en la consola antes de devolver los resultados.

Ejecución del código

Antes de pasar a los procedimientos de superposición y entrelazamiento, pruebe el código hasta este punto para ver la inicialización y la medición de los cúbits.

Esto se hace en el Q# archivo agregando una @EntryPoint() instrucción directamente anterior a la operación que desea ejecutar. Por ejemplo, en este caso es la TestBellState operación .

Nota:

@EntryPoint() solo es necesario para programas de Q# independientes. Cuando se ejecuta un Q# programa en Jupyter Notebooks o se llama a un Q# programa desde un archivo host de Python, no es necesario y se producirá un error si se incluye.

Ahora, el aspecto del archivo CreateBellStates.qs será parecido a este:

namespace Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

       operation SetQubitState(desired : Result, target : Qubit) : Unit {
           if desired != M(target) {
               X(target);
           }
       }

    @EntryPoint()
    operation TestBellState() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = One;

        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
            
            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
        
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }
}

Antes de ejecutar el programa, debe establecer el perfil de destino en Sin restricciones. Seleccione Ver-> Paleta de comandos, busque QIR, seleccione Q#: Establezca el perfil de destino de Azure Quantum QIR y, a continuación, seleccione Q#: sin restricciones.

Para ejecutar el programa, seleccione Ejecutar Q# archivo en la lista desplegable icono de reproducción en la parte superior derecha o presione Ctrl+F5. El programa ejecuta la operación o función marcada con el @EntryPoint() atributo en el simulador predeterminado.

Nota

Si el perfil de destino no está establecido en Sin restricciones, obtendrá un error al ejecutar el programa.

La salida aparece en la consola de depuración.

Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 1000
Q2 - Ones: 0

Dado que los cúbits aún no se han manipulado, han conservado sus valores iniciales: el primer cúbit devuelve One cada vez y el segundo cúbit devuelve Zero.

Si cambia el valor de initial a y vuelve a Zero ejecutar el programa, debe observar que el primer cúbit también devuelve Zero cada vez.

Q1 - Zeros: 1000
Q1 - Ones: 0
Q2 - Zeros: 1000
Q2 - Ones: 0

Sugerencia

Recuerde guardar el archivo cada vez que introduzca un cambio en el código antes de volver a ejecutarlo.

Colocación de un qubit en superposición

Actualmente, los cúbits del programa están en un estado clásico, es decir, son 1 o 0. Lo sabe porque el programa inicializa los cúbits en un estado conocido y no ha agregado ningún proceso para manipularlos. Antes de entrelazar los cúbits, colocará el primer cúbit en un estado de superposición, donde una medida del cúbit devolverá Zero el 50 % de las veces, y One el 50 % de las veces. Conceptualmente, el cúbit se puede considerar a medio camino entre Zero y One.

Para colocar un cúbit en superposición, Q# proporciona la operación H, o Hadamard. Recuerde la X operación de Inicializar un cúbit en un procedimiento de estado conocido anteriormente, que voltea un cúbit de Zero a One (o viceversa); la H operación voltea el cúbit a medio camino en un estado de probabilidades iguales de Zero o One. Cuando se mide, un cúbit en superposición debe devolver aproximadamente un número igual de resultados Zero y One.

Modifique el código de la operación TestBellState para incluir la operación H:

    for test in 1..count {
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
            
            H(q1);                // Add the H operation after initialization and before measurement

            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2); 
            ...

Ahora, al ejecutar el programa, puede ver los resultados del primer cúbit en superposición:

Q1 - Zeros: 523            // results will vary
Q1 - Ones: 477
Q2 - Zeros: 1000
Q2 - Ones: 0

Cada vez que ejecute el programa, los resultados del primer cúbit variarán ligeramente, pero estarán cerca del 50 % de One y el 50 % de Zero, mientras que los resultados del segundo cúbit permanecerán como Zero todo el tiempo.

Q1 - Zeros: 510           
Q1 - Ones: 490
Q2 - Zeros: 1000
Q2 - Ones: 0

La inicialización del primer cúbit en Zero devuelve resultados similares.

Q1 - Zeros: 504           
Q1 - Ones: 496
Q2 - Zeros: 1000
Q2 - Ones: 0

Entrelazamiento de dos qubits

Como se mencionó anteriormente, los cúbits entrelazados están conectados de modo que no se puedan describir de forma independiente entre sí. Es decir, la operación que le suceda a un cúbit, también le sucede al cúbit entrelazado. Esto permite conocer el estado resultante de un cúbit sin medirlo, simplemente midiendo el estado del otro cúbit. (En este ejemplo se usan dos cúbits; sin embargo, también es posible entrelazar tres o más cúbits).

Para habilitar el entrelazamiento, Q# proporciona la operación CNOT, que significa Controlled-NOT. El resultado de ejecutar esta operación en dos cúbits es la inversión del segundo cúbit si el primero es One.

Agregue la operación CNOT al programa inmediatamente después de la operación H. El programa completo debería tener este aspecto:

namespace Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

       operation SetQubitState(desired : Result, target : Qubit) : Unit {
           if desired != M(target) {
               X(target);
           }
       }

    @EntryPoint()
    operation TestBellState() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = One;

        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
        
            H(q1);            
            CNOT(q1, q2);      // Add the CNOT operation after the H operation

            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
        
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }
}

Q1 - Zeros: 502           
Q1 - Ones: 498       // results will vary
Q2 - Zeros: 502
Q2 - Ones: 498

Las estadísticas del primer cúbit no han cambiado (50/50 de probabilidades de Zero o One después de medir) pero el resultado del segundo cúbit es siempre igual que lo que se midió para el primer cúbit. Nuestra operación CNOT ha entrelazado los dos cúbits, de modo que lo que le suceda a uno, le sucede al otro.

Trazado del histograma de frecuencia

Vamos a visualizar la distribución de los resultados obtenidos de ejecutar el programa cuántico varias veces. El histograma de frecuencia ayuda a visualizar la distribución de probabilidad de estos resultados.

  1. Seleccione Ver -> Paleta de comandos, o presione Ctrl+Mayús+P y escriba "histograma" que debería mostrar la Q#opción : Ejecutar archivo y mostrar histograma . Seleccione esta opción para abrir la Q# ventana del histograma.

  2. Escriba una serie de tomas para ejecutar el programa, por ejemplo, 100 tomas y presione Entrar. El histograma se mostrará en la Q# ventana del histograma.

  3. Cada barra del histograma corresponde a un posible resultado y su altura representa el número de veces que se observa el resultado. En este caso, hay 50 resultados únicos diferentes. Tenga en cuenta que, para cada resultado, los resultados de medición para el primer y el segundo cúbit siempre son los mismos.

    Captura de pantalla de la Q# ventana del histograma en Visual Studio Code.

    Sugerencia

    Puede hacer zoom en el histograma mediante la rueda del mouse o un gesto del panel de seguimiento. Al acercar el gráfico, puede desplazarse hacia el gráfico presionando "Alt" mientras se desplaza.

  4. Haga clic en una barra para mostrar el porcentaje de ese resultado.

  5. Haga clic en el icono de configuración de la parte superior izquierda para mostrar las opciones. Puede mostrar los 10 primeros resultados, los 25 mejores resultados o todos los resultados. También puede ordenar los resultados de alto a bajo o bajo a alto.

    Captura de pantalla de la Q# ventana del histograma en Visual Studio Code que muestra cómo mostrar la configuración.

Pasos siguientes

Explore otros tutoriales de Q#: