연습 - Q#을 사용하여 다른 중첩 만들기

완료됨

이전 단원에서는 중첩과 디랙 표기법에 대해 알아보았습니다. 지금 당장은 충분한 이론입니다! 몇 가지 코드를 작성하여 Q#에서 중첩을 살펴보겠습니다.

이 단원에서는 DumpMachine 함수를 사용하여 양자 중첩을 만들고 Q#로 확률을 심도 있게 탐구해 보겠습니다. DumpMachine 함수는 대상 머신이 호출되는 지점에서 양자 시스템의 현재 상태에 대한 정보를 덤프합니다.

새 Q# 파일 만들기

  1. Visual Studio Code를 엽니다.
  2. Visual Studio Code에서 파일 > 새 텍스트 파일을 선택하고 파일을 Main.qs라는 이름으로 저장합니다.
  3. 보기 -> 명령 팔레트를 선택하고 Q#을 입력합니다. Azure Quantum QIR 대상 프로필을 설정합니다. Enter 키를 누릅니다.
  4. Q#: 제한 없음을 선택합니다.

중첩 시작

중첩에서 큐비트를 사용하여 임의 비트를 생성하는 간단한 프로그램으로 시작해 보겠습니다. DumpMachine 함수를 사용하여 프로그램의 여러 지점에서 큐비트의 상태를 확인합니다.

  1. Main.qs 파일에 다음 코드를 추가합니다.

    import Microsoft.Quantum.Diagnostics.*;
    
    operation Main() : Result {
        use q = Qubit();
        Message("Initialized qubit:");
        DumpMachine(); // First dump
        Message(" ");
        H(q);
        Message("Qubit after applying H:");
        DumpMachine(); // Second dump
        Message(" ");
        let randomBit = M(q);
        Message("Qubit after the measurement:");
        DumpMachine(); // Third dump
        Message(" ");
        Reset(q);
        Message("Qubit after resetting:");
        DumpMachine(); // Fourth dump
        Message(" ");
        return randomBit;
    }
    

    여기서는 DumpMachine을 네 번 호출합니다.

    • 큐비트가 할당된 후
    • 큐비트를 중첩에 배치한 후.
    • 큐비트의 상태를 측정한 후.
    • 큐비트를 초기화한 후.

    연산 MResetZ를 두 개의 연산 MReset으로 분할했습니다. 이는 측정 후 상태를 검사하기 위함입니다.

  2. 기본 제공 시뮬레이터에서 프로그램을 실행하려면 Main 작업 위에 있는 실행을 클릭하거나 Ctrl+F5를 누릅니다. 디버그 콘솔에 출력이 표시됩니다.

  3. DumpMachine 함수는 큐비트 레지스터의 상태를 설명하는 정보 표를 작성합니다. 구체적으로 각 기저 상태의 확률 진폭, 확률 및 위상을 라디안으로 제공합니다.

  4. 프로그램의 끝에 결과 Zero 또는 One이 표시됩니다. 각 단계를 살펴보겠습니다.

    1. 초기화된 큐비트: use 문을 통해 할당된 모든 큐비트는 $|0\rangle$ 상태로 시작합니다. 따라서 DumpMachine은 $|0\rangle$ 상태의 단일 큐비트 레지스터에 해당하는 정보를 생성합니다.

      Initialized qubit:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |0⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
      
    2. H를 적용한 후 큐비트: H를 적용한 후 큐비트를 중첩 상태 $|\psi\rangle=\frac1{\sqrt2} |0\rangle + \frac1{\sqrt2} |1\rangle$로 준비합니다.

      Qubit after applying H:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |0⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
         |1⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
      
    3. 측정 후 큐비트: 결과를 측정하고 저장한 후(Zero 또는 One일 수 있음). 예를 들어 결과 상태가 One인 경우 레지스터의 상태가 $|1\rangle$로 축소되고 더 이상 중첩되지 않습니다.

      Qubit after the measurement:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |1⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
      
    4. 재설정 후 큐비트: Reset 연산은 큐비트를 $|0\rangle$ 상태로 다시 설정합니다. 모든 Q# 연산에서는 사용하는 큐비트를 항상 $|0\rangle$ 상태로 유지하여 다른 연산에서 사용할 수 있도록 해야 합니다.

      Qubit after resetting:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |0⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
      

    참고 항목

    난수 생성기는 확률적이므로 출력이 다를 수 있습니다. 결과의 확률은 결정적이지 않습니다.

다른 유형의 중첩 상태 살펴보기

레지스터의 상태를 검사하는 방법을 배웠으므로, 큐비트의 상태를 수정하고 중첩시키는 많은 연산을 살펴볼 수 있습니다.

현재 난수 생성기는 50% 확률로 Zero 또는 One을 생성합니다. 다른 확률을 사용하여 난수를 생성하는 두 번째 예제를 살펴보겠습니다.

기울어진 임의 비트 생성기

기울어진 임의 비트 생성기를 만들려는 경우, 즉 Zero을(를) 얻을 확률이 One을(를) 얻을 확률과 다르다고 가정합니다.

예를 들어 $P$ 확률의 Zero 결과와 $1-P$ 확률의 One 결과를 표시하려고 합니다. 이러한 임의 비트 생성기를 생성하는 유효한 큐비트 상태는 다음과 같습니다.

$$|\psi\rangle=\sqrt{P}|0\rangle+\sqrt{1-P}|1\rangle$$

여기서 $\alpha=\sqrt{P}$ 및 $\beta=\sqrt{1-P}$는 각각 기본 상태 $|0\rangle$ 및 $|1\rangle$의 진폭입니다.

이 상태는 $|0\rangle$ 상태의 큐비트에$R_y(2\arccos\sqrt{P})$ 연산자를 순차적으로 적용하여 얻을 수 있습니다. 이 결과는 Q#에서 표준 라이브러리의 Ry 연산을 사용하여 얻을 수 있습니다.

단일 큐비트 연산 뒤의 수학을 자세히 알아보려면 Quantum Katas의 단일 큐비트 게이트 자습서를 확인하세요.

  1. 다음 예와 같이 Main.qs를 수정한 후 파일을 저장합니다. 이 예제에서는 $\alpha$를 대략 $\frac13$으로 선택합니다.

    import Microsoft.Quantum.Diagnostics.*;
    import Microsoft.Quantum.Math.*;
    
    operation Main() : Result {
        use q = Qubit();
        let P = 0.333333; // P is 1/3
        Ry(2.0 * ArcCos(Sqrt(P)), q);
        Message("The qubit is in the desired state.");
        Message("");
        DumpMachine(); // Dump the state of the qubit 
        Message("");
        Message("Your skewed random bit is:");
        let skewedrandomBit = M(q);
        Reset(q);
        return skewedrandomBit;
    }
    
  2. 기본 제공 시뮬레이터에서 프로그램을 실행하려면 Main 작업 위에 있는 실행을 클릭하거나 Ctrl+F5를 누릅니다. 디버그 콘솔에 출력이 표시됩니다.

  3. DumpMachine이 연산을 적용한 후 예상 상태를 표시하고 관련 확률을 표시하는 방식을 확인할 수 있습니다. Zero을(를) 얻을 확률은 약 33.33%이고 One을(를) 얻을 확률은 약 66.67%입니다. 따라서 임의 비트 생성기가 기울어집니다.

    The qubit is in the desired state.
    
    DumpMachine:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
       |0⟩ |  0.5773+0.0000𝑖 |    33.3333% |   0.0000
       |1⟩ |  0.8165+0.0000𝑖 |    66.6667% |   0.0000
    
    
    Your skewed random bit is:
    Result: "One"
    

    참고 항목

    난수 생성기는 확률적이므로 출력이 다를 수 있습니다. 결과의 확률은 결정적이지 않습니다.

다중 큐비트 중첩

이제 여러 큐비트가 있는 레지스터의 중첩을 살펴보겠습니다. 예를 들어 레지스터에 3개의 큐비트가 있는 경우 기저 상태는 다음 8개입니다.

$$|000\rangle,|001\rangle,|010\rangle,|011\rangle,|100\rangle,|101\rangle, |110\rangle,|111\rangle $$

따라서 다음과 같은 임의의 세 가지 큐비트 상태를 표현할 수 있습니다.

$$|\psi\rangle=\alpha_0|000\rangle+\alpha_1|001\rangle+\alpha_2|010\rangle+\alpha_3|011\rangle+\alpha_4|100\rangle+\alpha_5|101\rangle+\alpha_6 |110\rangle+\alpha_7|111\rangle$$

여기서 $\alpha_i$는 $\sum|\alpha_i|^2=1$을 만족하는 복소수입니다.

예를 들어 각 큐비트에 H을(를) 적용하여 균일한 중첩에 큐비트를 배치할 수 있습니다. 이 균일한 중첩을 사용하여 한 큐비트를 세 번 측정하는 대신 중첩에서 세 개의 큐비트를 측정하여 3비트 숫자를 생성하는 다른 버전의 양자 난수 생성기를 만들 수 있습니다.

기준 숫자
$\ket{000}$ 0
$\ket{001}$ 1
$\ket{010}$ 2
$\ket{011}$ 3
$\ket{100}$ 4
$\ket{101}$ 5
$\ket{110}$ 6
$\ket{111}$ 7
  1. 다음 예와 같이 Main.qs를 수정한 후 파일을 저장합니다.

    import Microsoft.Quantum.Diagnostics.*;
    import Microsoft.Quantum.Math.*;
    import Microsoft.Quantum.Convert.*;
    import Microsoft.Quantum.Arrays.*;
    
    operation Main() : Int {
        use qubits = Qubit[3];
        ApplyToEach(H, qubits);
        Message("The qubit register in a uniform superposition: ");
        DumpMachine();
        let result = ForEach(M, qubits);
        Message("Measuring the qubits collapses the superposition to a basis state.");
        DumpMachine();
        ResetAll(qubits);
        return BoolArrayAsInt(ResultArrayAsBoolArray(result));
    }
    

    여기서는 다음 세 가지 개념을 볼 수 있습니다.

    • qubits 변수는 이제 길이가 3인 Qubit 배열을 나타냅니다.
    • ApplyToEachForEach 연산은 여러 큐비트를 측정하고 작업하는 데 유용하며 코드를 적게 사용합니다. Q# 라이브러리는 양자 프로그램을 보다 효율적으로 작성할 수 있도록 하는 다양한 연산 및 함수를 제공합니다.
    • Microsoft.Quantum.Convert 라이브러리의 BoolArrayAsIntResultArrayAsBoolArray 함수는 ForEach(M, qubits)에서 반환한 이진 Result 배열을 정수로 변환합니다.
  2. 프로그램을 실행하려면 Main 작업 위에 있는 실행을 클릭하거나 Ctrl+F5를 누릅니다. 디버그 콘솔에 출력이 표시됩니다.

  3. 세 큐비트를 측정하는 행위가 어떻게 레지스터의 상태를 8개의 가능한 기저 상태 중 하나로 축소하는지 DumpMachine을 사용하여 확인할 수 있습니다. 예를 들어 3 결과를 가져오는 경우 레지스터의 상태가 $|110\rangle$로 축소되었음을 의미합니다.

    The qubit register in a uniform superposition:
    
    DumpMachine:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |000⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |001⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |010⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |011⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |100⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |101⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |110⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |111⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
    
    Measuring the qubits collapses the superposition to a basis state.
    
    DumpMachine:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |110⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    
    Result: "3"
    

    참고 항목

    난수 생성기는 확률적이므로 출력이 다를 수 있습니다. 결과의 확률은 결정적이지 않습니다.

  4. ForEach(M, qubit) 연산은 각 큐비트를 차례로 측정하여 상태를 점차 축소합니다. 각 측정 후에 중간 상태를 덤프할 수도 있습니다. 그렇게 하려면 다음 예와 같이 Main.qs를 수정한 다음 파일을 저장합니다.

    import Microsoft.Quantum.Diagnostics.*;
    import Microsoft.Quantum.Measurement.*;
    import Microsoft.Quantum.Math.*;
    import Microsoft.Quantum.Convert.*;
    
    operation Main() : Int {
        use qubits = Qubit[3];
        ApplyToEach(H, qubits);
        Message("The qubit register in a uniform superposition: ");
        DumpMachine();
        mutable results = [];
        for q in qubits {
            Message(" ");
            set results += [M(q)];
            DumpMachine();
        }
        Message(" ");
        Message("Your random number is: ");
        ResetAll(qubits);
        return BoolArrayAsInt(ResultArrayAsBoolArray(results));
    }
    
  5. 여기서는 for 루프를 사용하여 각 큐비트를 순차적으로 처리합니다. Q#에는 프로그램의 흐름을 제어하는 데 사용할 수 있는 for 루프 및 if 문과 같은 클래식 흐름 제어 기능이 있습니다.

  6. 프로그램을 실행하려면 Main 작업 위의 명령 목록에서 실행을 클릭하거나 Ctrl+F5를 누릅니다.

  7. 각 연속 측정이 양자 상태, 따라서 각 결과를 얻을 확률을 변화시키는 방식을 확인할 수 있습니다. 예를 들어 결과가 숫자 5이면 다음 출력이 표시됩니다. 각 단계를 간단히 살펴보겠습니다.

    1. 상태 준비: 레지스터의 각 큐비트에 H를 적용하여 균일한 중첩을 얻습니다.

      The qubit register in a uniform superposition: 
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
       |000⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |001⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |010⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |011⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |100⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |101⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |110⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |111⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
      
    2. 첫 번째 측정: 첫 번째 측정의 결과는 One이었습니다. 따라서 맨 오른쪽 큐비트가 Zero인 상태의 모든 진폭은 더 이상 존재하지 않습니다. 이 진폭은 $|0\rangle=|000\rangle, |2\rangle=|010\rangle, |4\rangle=|100\rangle$ 및 $|6\rangle= |110\rangle$입니다. 나머지 진폭은 정규화 조건을 충족하기 위해 증가합니다.

      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
       |001⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
       |011⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
       |101⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
       |111⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
      
    3. 두 번째 측정: 두 번째 측정의 결과는 Zero였습니다. 따라서 맨 오른쪽에서 두 번째 큐비트가 One인 상태의 모든 진폭이 사라집니다. 진폭은 $|3\rangle=|011\rangle$ 및 $|7\rangle=|111\rangle$입니다. 나머지 진폭은 정규화 조건을 충족하기 위해 증가합니다.

      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
       |001⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
       |101⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
      
    4. 세 번째 측정: 세 번째 측정의 결과는 One이었습니다. 따라서 맨 왼쪽 큐비트가 Zero인 상태의 모든 진폭이 사라집니다. 유일하게 호환되는 상태는 $|5\rangle=|101\rangle$입니다. 이 상태의 진폭 확률은 $1$입니다.

      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
       |101⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
      
      
      Your random number is: 
      Result: "5"
      

    참고 항목

    난수 생성기는 확률적이므로 출력이 다를 수 있습니다. 결과의 확률은 결정적이지 않습니다.