연습 - 양자 난수 생성기 만들기

완료됨

이 단원에서는 양자 난수 생성기의 두 번째 단계를 구현합니다. 여러 임의 비트를 결합하여 더 큰 난수를 형성합니다. 이 단계는 이미 만든 임의 비트 생성기를 기반으로 합니다. 이 단계를 위해 일부 클래식 코드를 작성해야 합니다.

Q#에서 클래식 코드를 작성할 수 있나요?

예, 할 수 있습니다. 양자 컴퓨터는 특수한 작업을 수행합니다. 대부분의 작업은 일반 컴퓨터로 충분하기 때문에 모든 작업에 양자 컴퓨터를 사용하지는 않습니다.

GPU(그래픽 처리 장치) 또는 기타 특수 하드웨어와 마찬가지로 양자 컴퓨터는 가장 적합한 작업에 사용해야 합니다. 여기서는 순수 임의 비트를 생성하려고 합니다.

이러한 이유로 Q#을 사용하면 이미 알고 있는 프로그래밍 언어와 유사한 클래식 코드를 작성할 수 있습니다.

Q# 기능을 사용하여 완전한 난수 생성기를 빌드하는 방법을 살펴보겠습니다.

난수 생성기 논리 정의

이전 단원에서 빌드된 임의 비트 생성기를 제공하면 난수 생성기의 논리를 간략하게 설명해 보겠습니다.

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

예를 들어 max를 12로 설정하겠습니다. 즉, 12는 난수 생성기에서 가져올 가장 큰 숫자입니다.

0에서 12 사이의 숫자를 나타내려면 ${\lfloor ln(12) / ln(2) + 1 \rfloor}$, 즉 4비트가 필요합니다. (간단히 하기 위해 이 수식을 파생하는 방법을 건너뜁니다.)

${13_{\ decimal}}$에 해당하는 비트 문자열 ${1101_{\ binary}}$를 생성한다고 가정하겠습니다. 13은 12보다 크므로 프로세스를 반복합니다.

다음으로 ${6_{\ decimal}}$에 해당하는 비트 문자열 ${0110_{\ binary}}$를 생성합니다. 6은 12보다 작으므로 프로세스는 완료된 것입니다.

양자 난수 생성기는 숫자 6을 반환합니다.

전체 난수 생성기 만들기

여기서는 파일을 확장 RandomNumberGenerator.qs 하여 더 큰 난수를 작성합니다.

필요한 라이브러리 추가

전체 난수 생성기의 경우 세 개의 Q# 라이브러리를 포함해야 합니다. Microsoft.Quantum.MathMicrosoft.Quantum.IntrinsicMicrosoft.Quantum.Convert 다음과 같이 다음 open 지시문을 추가합니다 RandomNumberGenerator.qs.

namespace QuantumRandomNumberGenerator {
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Math;

// The rest of the code goes here.

}

양자 난수 연산 정의

여기에서 GenerateRandomNumberInRange 작업을 정의합니다. 이 작업은 GenerateRandomBit 작업을 반복적으로 호출하여 비트 문자열을 생성합니다.

다음과 같이 수정 RandomNumberGenerator.qs 합니다.

namespace QuantumRandomNumberGenerator {
    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Math;

    /// Generates a random number between 0 and `max`.
    operation GenerateRandomNumberInRange(max : Int) : Int {
        // Determine the number of bits needed to represent `max` and store it
        // in the `nBits` variable. Then generate `nBits` random bits which will
        // represent the generated random number.
        mutable bits = [];
        let nBits = BitSizeI(max);
        for idxBit in 1..nBits {
            set bits += [GenerateRandomBit()];
        }
        let sample = ResultArrayAsInt(bits);

        // Return random number if it is within the requested range.
        // Generate it again if it is outside the range.
        return sample > max ? GenerateRandomNumberInRange(max) | sample;
    }
}

잠시 새 코드를 검토해 보겠습니다.

  • 최대 정수를 표현하는 데 필요한 비트 수를 계산해야 합니다 max. 라이브러리의 Microsoft.Quantum.Math 함수는 BitSizeI 정수를 나타내는 데 필요한 비트 수로 변환합니다.
  • GenerateRandomNumberInRange 작업은 for 루프를 사용하여 max보다 작거나 같은 값을 생성할 때까지 난수를 생성합니다. 루프는 for 다른 프로그래밍 언어의 for 루프와 정확히 동일하게 작동합니다.
  • 변수 bits 는 변경 가능한 변수입니다. 변경 가능한 변수는 계산 중에 변경될 수 있는 변수입니다. set 지시문을 사용하여 변경 가능한 변수의 값을 변경할 수 있습니다.
  • 이 함수는 ResultArrayAsInt 라이브러리에서 Microsoft.Quantum.Convert 제공됩니다. 이 함수는 비트 문자열을 양의 정수로 변환합니다.

진입점 정의

이제 프로그램이 난수를 생성할 수 있습니다. 여기에서 프로그램 진입점을 정의합니다.

다음과 같이 파일을 수정 RandomNumberGenerator.qs 합니다.

namespace QuantumRandomNumberGenerator {
    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Math;

    @EntryPoint()
    operation Main() : Int {
        let max = 100;
        Message($"Sampling a random number between 0 and {max}: ");

        // Generate random number in the 0..max range.
        return GenerateRandomNumberInRange(max);
    }

    /// Generates a random number between 0 and `max`.
    operation GenerateRandomNumberInRange(max : Int) : Int {
        // Determine the number of bits needed to represent `max` and store it
        // in the `nBits` variable. Then generate `nBits` random bits which will
        // represent the generated random number.
        mutable bits = [];
        let nBits = BitSizeI(max);
        for idxBit in 1..nBits {
            set bits += [GenerateRandomBit()];
        }
        let sample = ResultArrayAsInt(bits);

        // Return random number if it is within the requested range.
        // Generate it again if it is outside the range.
        return sample > max ? GenerateRandomNumberInRange(max) | sample;
    }

    operation GenerateRandomBit() : Result {
        // Allocate a qubit.
        use q = Qubit();

        // Set the qubit into superposition of 0 and 1 using the Hadamard operation
        H(q);

        // At this point the qubit `q` has 50% chance of being measured in the
        // |0〉 state and 50% chance of being measured in the |1〉 state.
        // Measure the qubit value using the `M` operation, and store the
        // measurement value in the `result` variable.
        let result = M(q);

        // Reset qubit to the |0〉 state.
        // Qubits must be in the |0〉 state by the time they are released.
        Reset(q);

        // Return the result of the measurement.
        return result;
    }
}

let 지시문은 계산 도중 변경되지 않는 변수를 선언합니다. 학습을 위해 여기서는 최대값을 100으로 정의합니다.

참고 항목

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

프로그램 실행

새 난수 생성기를 사용해 보겠습니다.

  1. 프로그램을 실행하기 전에 대상 프로필을 무제한으로 설정해야 합니다. 보기 - 명령 팔레트를 선택하고, QIR을 검색하고, Q#을 선택합니다. Azure Quantum QIR 대상 프로필을 설정한 다음, Q#: 무제한을 선택합니다.>
  2. 기본 제공 시뮬레이터에서 로컬로 프로그램을 테스트하려면 오른쪽 위에 있는 재생 아이콘 드롭다운에서 Q# 파일 실행을 선택하거나 Ctrl+F5를 누릅니다. 출력이 디버그 콘솔에 표시됩니다.
  3. 프로그램을 다시 실행하여 다른 결과를 확인합니다.

참고 항목

대상 프로필이 Unrestricted설정되지 않은 경우 프로그램을 실행할 때 오류가 발생합니다.

축하합니다! 이제 고전 논리를 Q#과 결합하여 양자 난수 생성기를 만드는 방법을 알았습니다.

보너스 연습

생성된 난수를 0이 아니라 최소 수 min보다 크게 요구하도록 프로그램을 수정합니다.