자습서: Q#에서 양자 난수 생성기 구현

양자 역학의 특성을 활용하여 난수를 생성하는 기본 양자 프로그램을 Q#으로 작성하는 방법을 알아봅니다.

이 자습서에서는 다음 방법에 대해 알아봅니다.

  • Q# 프로젝트를 만듭니다.
  • Q#에서 양자 프로그램을 작성하기 위한 개발 환경을 준비합니다.
  • Q# 프로그램 구성 방법을 이해합니다.
  • 큐빗 및 중첩을 사용하여 양자 난수 생성기를 빌드합니다.

사전 요구 사항

  • 선호하는 언어 및 개발 환경을 사용하여 QDK(Quantum Development Kit)를 설치합니다. 이 자습서에서는 세 가지 형식으로 솔루션을 제공합니다.
    • Q# 독립 실행형
    • Q# 및 Python
    • Q# 및 C #
  • QDK가 이미 설치된 경우 QDK(및 해당하는 경우 Python qsharp 패키지)를 최신 버전으로 업데이트했는지 확인합니다.

Q# 프로젝트 만들기

가장 먼저 해야 할 일은 새 Q# 프로젝트를 만드는 것입니다. 이 자습서에서는 VS Code가 있는 Q# 애플리케이션을 기반으로 하는 환경을 사용합니다. 하지만 사용자가 원하는 IDE도 사용할 수 있습니다.

Visual Studio Code에서 새 프로젝트를 만들려면 다음을 수행합니다.

  1. 보기 - >명령 팔레트를 클릭하고 Q#: 새 프로젝트 만들기를 선택합니다.
  2. 독립 실행형 콘솔 애플리케이션을 선택합니다.
  3. 프로젝트를 저장할 위치를 선택하고, 이름을 Qrng로 지정하고, 프로젝트 만들기를 선택합니다.
  4. 프로젝트가 만들어지면 오른쪽 아래에서 새 프로젝트 열기...를 선택합니다.

이렇게 하면 프로젝트 파일인 Qrng.csproj와 애플리케이션을 작성하는 데 사용할 Q# 애플리케이션 템플릿 Program.qs 등, 두 개의 파일이 생성됩니다.

Q# 연산 작성

이제 Program.qs 파일의 내용을 다음 코드로 바꿉니다.

namespace Qrng {
    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Math;
    open Microsoft.Quantum.Measurement;
    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    
    operation SampleQuantumRandomNumberGenerator() : Result {
        // Allocate a qubit        
        use q = Qubit();  
        // Put the qubit to superposition
        // It now has a 50% chance of being measured 0 or 1  
        H(q);      
        // Measure the qubit value            
        return M(q); 
    }
}

이제 새 코드를 살펴보겠습니다.

  • 먼저 필요한 함수 및 작업에 대해 Q# 라이브러리에서 open 필요한 네임스페이스를 지정합니다.
  • 입력 없이 Result 형식의 값을 생성하는 SampleQuantumRandomNumberGenerator 연산을 정의합니다. Result 형식은 측정 결과를 나타내며 두 가지 가능한 값은 Zero 또는 One입니다.
  • use 키워드를 사용하여 단일 큐비트를 할당합니다.
  • H(Hadamard) 연산을 사용하여 큐비트를 동등 중첩에 배치합니다.
  • M 연산을 사용하여 큐비트를 측정하고 측정된 값(Zero 또는 One)을 반환합니다.

양자 컴퓨팅 이해 문서에서 살펴본 대로 큐비트는 중첩될 수 있는 양자 정보의 단위입니다. 측정할 때 큐비트는 0 상태 또는 1 상태일 수 있습니다. 하지만 측정 전 큐비트 상태는 측정값이 0 또는 1일 수 있는 확률을 나타냅니다. 이 예제에서는 측정 전에 큐비트가 같은 중첩에 있습니다. 즉, 0 읽기의 확률이 50%, 1 읽기의 확률이 50%입니다. 이 확률을 사용하여 난수를 생성할 수 있습니다.

사용자 정의 SampleQuantumRandomNumberGenerator 연산에는 Q#에 네이티브인 Qubit 데이터 형식이 도입됩니다. Qubituse 문으로만 할당할 수 있습니다. 할당되는 경우 큐비트는 항상 Zero 상태입니다.

H 연산을 사용하여 큐비트를 중첩 상태로 전환하고 M 연산으로 측정하면 코드가 호출될 때마다 다른 결과 값이 반환됩니다.

블로흐 구를 사용하여 코드 시각화

Bloch 구의 북극은 클래식 0 값을 나타내고, 남극은 클래식 1 값을 나타냅니다. 모든 중첩은 구의 점으로 표현할 수 있습니다(화살표로 표시). 화살표의 끝부분이 극에 가까울수록 측정 시 큐비트가 해당 극에 할당된 클래식 값으로 축소될 확률이 높아집니다. 예를 들어 다음 그림에서 빨간색 화살표로 표현되는 큐비트 상태는 측정될 경우 0 값을 제공할 확률이 높습니다.

0을 측정할 확률이 높은 큐비트 상태를 보여 주는 다이어그램

이 표현을 사용하여 코드가 하는 일을 시각화할 수 있습니다.

  • 먼저 0 상태에서 초기화된 큐비트로 시작하고, H 연산을 적용하여 01의 확률이 동일한 동등 중첩을 만듭니다.
hadamard 게이트를 적용하여 중첩에서 큐비트의 준비를 보여 주는 다이어그램
  • 그런 다음, 큐비트를 측정하고 출력을 저장합니다.
큐비트의 측정 및 출력 저장을 보여 주는 다이어그램

측정 결과는 임의이고 01을 측정할 확률은 동일하므로 완전히 임의 비트를 얻었습니다. 이 연산을 여러 번 호출하여 정수를 만들 수 있습니다. 예를 들어 이 연산을 세 번 호출하여 세 개의 임의 비트를 얻으면 임의의 3비트 숫자(즉, 0~7 사이의 임의 숫자)를 빌드할 수 있습니다.

완전한 난수 생성기 만들기

이제 임의 비트를 생성하는 Q# 연산이 있으므로 여러 임의 비트를 결합하여 완전한 양자 난수 생성기를 빌드할 수 있습니다. 프로그램을 독립 실행형 Q# 애플리케이션으로 실행하거나 Python 또는 .NET에서 호스트 프로그램을 사용하여 Q# 코드를 호출할 수 있습니다.

난수 생성기 논리 정의

먼저, 임의 비트 생성기가 이미 있는 경우의 난수 생성기 논리를 간략하게 살펴보겠습니다.

  1. 생성하려는 최대 수로 max를 정의합니다.
  2. 생성해야 하는 임의 비트의 수를 정의합니다. 이 작업은 max까지 정수를 표현해야 하는 비트 수(numBits)를 계산하여 수행됩니다.
  3. 길이가 numBits인 임의 비트 문자열을 생성합니다.
  4. 비트 문자열이 max보다 큰 숫자를 나타내는 경우 3단계로 돌아갑니다.
  5. 그렇지 않으면 프로세스가 완료된 것입니다. 생성된 숫자를 정수로 반환합니다.

작업 정의

다음으로 for 루프를 사용하여 SampleQuantumRandomNumberGenerator 작업을 반복적으로 호출하고 비트 문자열을 빌드하는 SampleRandomNumberInRange 작업을 정의합니다.

Program.qs를 수정하여 새 작업을 추가합니다.

namespace Qrng {

    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Measurement;
    open Microsoft.Quantum.Math;
    open Microsoft.Quantum.Convert;

    operation SampleQuantumRandomNumberGenerator() : Result {
        // Allocate a qubit        
        use q = Qubit();  
        // Put the qubit to superposition
        // It now has a 50% chance of being measured 0 or 1  
        H(q);      
        // Measure the qubit value            
        return M(q);           
    }

    operation SampleRandomNumberInRange(max : Int) : Int {
        mutable output = 0; 
        repeat {
            mutable bits = []; 
            for idxBit in 1..BitSizeI(max) {
                set bits += [SampleQuantumRandomNumberGenerator()]; 
            }
            set output = ResultArrayAsInt(bits);
        } until (output <= max);
        return output;
    }
}

이제 새 작업을 검토해 보겠습니다.

  • max까지 정수를 표현하는 데 필요한 비트 수를 계산하기 위해 BitSizeI 함수를 제공합니다.
  • SampleRandomNumberInRange 작업은 repeat 루프를 사용하여 max보다 작거나 같은 값을 생성할 때까지 난수를 생성합니다.
  • repeat 내의 for 루프는 다른 프로그래밍 언어의 for 루프와 정확히 동일하게 작동합니다.
  • 이 예제에서 outputbits변경 가능한 변수입니다. 변경 가능한 변수는 계산 중에 변경될 수 있는 변수입니다. set 지시문을 사용하여 변경 가능한 변수의 값을 변경할 수 있습니다.
  • ResultArrayAsInt 함수는 비트 문자열을 양의 정수로 변환합니다.

이제 Qrng 프로그램이 난수를 생성할 수 있습니다.

난수 생성기 프로그램 실행

최종 버전의 Q# 코드를 사용하여

namespace Qrng {

    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Measurement;
    open Microsoft.Quantum.Math;
    open Microsoft.Quantum.Convert;

    operation SampleQuantumRandomNumberGenerator() : Result {
        // Allocate a qubit        
        use q = Qubit();  
        // Put the qubit to superposition
        // It now has a 50% chance of being measured 0 or 1  
        H(q);      
        // Measure the qubit value            
        return M(q);           
    }

    operation SampleRandomNumberInRange(max : Int) : Int {
        mutable output = 0; 
        repeat {
            mutable bits = []; 
            for idxBit in 1..BitSizeI(max) {
                set bits += [SampleQuantumRandomNumberGenerator()]; 
            }
            set output = ResultArrayAsInt(bits);
        } until (output <= max);
        return output;
    }
}

기본 설정 언어 및 환경에 대한 탭을 선택하고 Q# 프로그램의 실행 또는 호출을 위한 지침을 따릅니다.

독립 실행형 Q# 애플리케이션에는 컴파일러가 Q# 프로그램을 시작할 위치를 알 수 있도록 EntryPoint가 필요합니다. 전체 Q# 애플리케이션을 만들려면 다음 진입점을 Q# 프로그램 Program.qs에 추가합니다.

namespace Qrng {

    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Measurement;
    open Microsoft.Quantum.Math;
    open Microsoft.Quantum.Convert;

    operation SampleQuantumRandomNumberGenerator() : Result {
        // Allocate a qubit.
        use q = Qubit();
        // Put the qubit to superposition.
        H(q);
        // It now has a 50% chance of being measured 0 or 1.
        // Measure the qubit value.
        return M(q);
    }

    operation SampleRandomNumberInRange(max : Int) : Int {
        mutable output = 0; 
        repeat {
            mutable bits = []; 
            for idxBit in 1..BitSizeI(max) {
                set bits += [SampleQuantumRandomNumberGenerator()]; 
            }
            set output = ResultArrayAsInt(bits);
        } until (output <= max);
        return output;
    }

    @EntryPoint()
    operation SampleRandomNumber() : Int {
        let max = 50;
        Message($"Sampling a random number between 0 and {max}: ");
        return SampleRandomNumberInRange(max);
    }
}

프로그램은 프로젝트 구성 및 명령줄 옵션에 따라 시뮬레이터 또는 리소스 예측 도구에서 @EntryPoint() 특성으로 표시된 작업 또는 함수를 실행합니다.

Visual Studio에서 Ctrl + F5를 눌러 스크립트를 실행하기만 하면 됩니다.

VS Code에서 터미널에 다음을 입력하여 Program.qs를 처음으로 빌드합니다.

dotnet build

후속 실행 시, 다시 빌드할 필요가 없습니다. 실행하려면 다음 명령을 입력하고 Enter 키를 누릅니다.

dotnet run --no-build

참고

이 코드 조각은 현재 사용 가능한 Azure Quantum 하드웨어 대상에서는 실행되지 않습니다. 호출 가능 ResultArrayAsInt에는 전체 계산 프로필이 있는 QPU가 필요하기 때문입니다

다음 단계

다른 Q# 자습서 살펴보기: