Ćwiczenie— część 2 — tworzenie kwantowego generatora liczb losowych

Ukończone

W tej lekcji zaimplementujesz drugą fazę kwantowego generatora liczb losowych: łącząc wiele losowych bitów w celu utworzenia większej liczby losowej. Ta faza opiera się na generatorze bitów losowych, który został już utworzony w poprzedniej lekcji.

Łączenie wielu losowych bitów w celu utworzenia większej liczby

W poprzedniej lekcji utworzono generator bitów losowych, który generuje losowy bit, umieszczając kubit w superpozycję i mierząc go.

Po zmierzeniu kubitu otrzymasz losowy bit (0 lub 1) z równym 50% prawdopodobieństwem. Wartość tego bitu jest naprawdę losowa, nie ma możliwości poznania tego, co otrzymujesz po pomiarze. Ale jak można użyć tego zachowania, aby wygenerować większe liczby losowe?

Załóżmy, że powtarzasz ten proces cztery razy, generując następującą sekwencję cyfr binarnych:

$${0, 1, 1, 0}$$

Jeśli połączysz te bity w ciąg bitów, możesz utworzyć większą liczbę. W tym przykładzie sekwencja bitowa ${0110}$ jest równa liczbie sześć w postaci dziesiętnej.

$${0110_{\ binary} \equiv 6_{\ decimal}}$$

W przypadku wielokrotnego powtarzania tego procesu można połączyć wiele bitów, aby utworzyć dowolną dużą liczbę.

Definiowanie logiki generatora liczb losowych

Określmy, jaka powinna być logika generatora liczb losowych, pod warunkiem, że generator bitów losowych został utworzony w poprzedniej lekcji:

  1. Zdefiniuj max jako maksymalną liczbę, którą chcesz wygenerować.
  2. Zdefiniuj liczbę bitów losowych, które należy wygenerować, obliczając liczbę bitów , nBitsnależy wyrazić liczby całkowite do max.
  3. Wygeneruj losowy ciąg bitowy o długości nBits.
  4. Jeśli ciąg bitowy reprezentuje liczbę większą niż max, wróć do kroku trzeciego.
  5. W przeciwnym razie proces zostanie zakończony. Zwróć wygenerowaną liczbę jako liczbę całkowitą.

Załóżmy na przykład, że wartość max wynosi 12. Oznacza to, że 12 jest największą liczbą, którą chcesz uzyskać z generatora liczb losowych.

Potrzebujesz ${\lfloor ln(12) / ln(2) + 1 \rfloor}$, lub 4 bity do reprezentowania liczby z zakresu od 0 do 12. (W celu zwięzłości pomijamy sposób tworzenia tego równania).

Załóżmy, że wygenerujesz ciąg bitowy ${1101_{\ binary}}$, który jest odpowiednikiem ciągu ${13_{\ decimal}}$. Ponieważ 13 jest większe niż 12, należy powtórzyć proces.

Następnie wygenerujesz ciąg bitowy ${0110_{\ binary}}$, który jest odpowiednikiem ciągu ${6_{\ decimal}}$. Ponieważ 6 jest mniejsze niż 12, proces jest zakończony.

Kwantowy generator liczb losowych zwraca liczbę 6.

Tworzenie kompletnego generatora liczb losowych

W tym miejscu rozszerzysz Main.qs plik, aby utworzyć większe liczby losowe.

Importowanie wymaganych bibliotek

Najpierw należy zaimportować wymagane przestrzenie nazw z biblioteki Q# Standard do programu. Kompilator języka Q# ładuje wiele typowych funkcji i operacji automatycznie, jednak w przypadku kompletnego kwantowego generatora liczb losowych potrzebne są pewne dodatkowe funkcje i operacje z dwóch przestrzeni nazw języka Q#: Microsoft.Quantum.Mathi Microsoft.Quantum.Convert.

Skopiuj i wklej następujące import dyrektywy na początku Main.qs pliku:

import Microsoft.Quantum.Convert.*;
import Microsoft.Quantum.Math.*;

Zmień nazwę operacji na MainGenerateRandomBit

W przypadku pełnego generatora liczb losowych użyjesz ponownie operacji zdefiniowanej w poprzedniej lekcji. Jednak nazwa Main operacji jest punktem wejścia programu i powinna być unikatowa. Aby uniknąć nieporozumień, musisz zmienić nazwę Main operacji na GenerateRandomBit.

Operacja GenerateRandomBit powinna wyglądać następująco:

    operation GenerateRandomBit() : Result {
        // Allocate a qubit.
        use q = Qubit();
    
        // Set the qubit into superposition of 0 and 1 using the Hadamard 
        H(q);
    
        // Measure the qubit and store the result.
    
        let result = M(q);
    
        // Reset qubit to the |0〉 state.
        Reset(q);
    
        // Return the result of the measurement.
        return result;
    }

Definiowanie kwantowej operacji liczb losowych

Teraz zdefiniujesz operację GenerateRandomNumberInRange. Ta operacja wielokrotnie wywołuje operację GenerateRandomBit, aby utworzyć ciąg bitów.

Skopiuj następujący kod i wklej go przed operacją GenerateRandomBit do Main.qs pliku:

    /// 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;
    }

Poświęćmy chwilę na przejrzenie nowego kodu.

  • Musisz obliczyć liczbę bitów potrzebnych do wyrażenia liczb całkowitych do max. Funkcja BitSizeI z Microsoft.Quantum.Math biblioteki konwertuje liczbę całkowitą na liczbę bitów potrzebnych do jej reprezentowania.
  • Operacja GenerateRandomNumberInRange używa pętli for do generowania liczb losowych do momentu wygenerowania takiej liczby, która jest równa lub mniejsza niż max. Pętla for działa dokładnie tak samo jak pętla for w innych językach programowania.
  • Zmienna bits jest zmienną modyfikowalnym. Zmienna modyfikowalna to taka, która może się zmienić podczas obliczania. Aby zmienić wartość zmiennej modyfikowalnej, należy użyć dyrektywy set.
  • Funkcja ResultArrayAsInt pochodzi z Microsoft.Quantum.Convert biblioteki. Ta funkcja konwertuje ciąg bitowy na dodatnią liczbę całkowitą.

Dodawanie punktu wejścia

Na koniec dodasz punkt wejścia do programu. Domyślnie kompilator języka Q# szuka Main operacji i rozpoczyna przetwarzanie, niezależnie od tego, gdzie się znajduje. Operacja Main wywołuje operację GenerateRandomNumberInRange , aby wygenerować losową liczbę z zakresu od 0 do max liczby. W tym przykładzie zdefiniujesz maksymalną wartość jako 100.

Skopiuj i wklej następujący kod do pliku Main.qs :

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);
}

Końcowy program

Plik Main.qs powinien wyglądać następująco:

import Microsoft.Quantum.Convert.*;
import Microsoft.Quantum.Math.*;

    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);
    
        // 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.
        Reset(q);
    
        // Return the result of the measurement.
        return result;
    }

Uruchamianie programu

Wypróbujmy nasz nowy generator liczb losowych.

  1. Przed uruchomieniem programu należy ustawić profil docelowy na Wartość Bez ograniczeń. Wybierz pozycję Wyświetl>paletę poleceń, wyszukaj pozycję QIR, wybierz pozycję Q#: Ustaw profil docelowy usługi Azure Quantum QIR, a następnie wybierz pozycję Q#: nieograniczone.
  2. Aby uruchomić program, wybierz pozycję Uruchom z listy poleceń powyżej Main operacji lub naciśnij Ctrl+F5. Dane wyjściowe zostaną wyświetlone w konsoli debugowania.
  3. Uruchom ponownie program, aby zobaczyć inny wynik.

Uwaga

Jeśli profil docelowy nie jest ustawiony na Unrestricted, podczas uruchamiania programu zostanie wyświetlony błąd.

Gratulacje! Teraz już wiesz, jak połączyć klasyczną logikę z językiem Q#, aby utworzyć kwantowy generator liczb losowych.

Ćwiczenie dodatkowe

Spróbuj zmodyfikować program, aby wymagać również wygenerowanej liczby losowej większej niż minimalna liczba, minzamiast zera.