Aracılığıyla paylaş


Eğitici Kılavuz: İçinde Kuantum Fourier Dönüşümünü Uygulama Q#

Bu öğreticide, tek tek kubitler üzerinde çalışan temel bir kuantum programının nasıl yazıldığını ve simülasyonunu nasıl gerçekleştirdiğiniz gösterilir.

Öncelikle büyük ölçekli kuantum programları için üst düzey bir programlama dili olarak oluşturulmuş olsa Q# da, kuantum programlamanın alt düzeyini, yani belirli kubitleri doğrudan ele almak için de kullanılabilir. Özellikle, bu öğretici birçok büyük kuantum algoritmasının ayrılmaz bir alt parçası olan Quantum Fourier Dönüşümü'ne (QFT) daha yakından bakar.

Bu öğreticide şunların nasıl yapılacağını öğreneceksiniz:

  • içinde Q#kuantum işlemlerini tanımlayın.
  • Quantum Fourier Dönüşüm devresini yazma
  • Kubit ayırma işleminden ölçüm çıktısına kadar kuantum işlemini simüle et.
  • Kuantum sisteminin simülasyon dalga işlevinin işlem boyunca nasıl geliştiğini gözlemleyin.

Not

Kuantum bilgi işlemenin bu alt düzey görünümü genellikle bir sistemin belirli kubitlerine geçitlerin veya işlemlerin sıralı uygulamasını temsil eden kuantum devreleri açısından açıklanmaktadır. Bu nedenle, sırayla uyguladığınız tek ve çok kubitli işlemler devre diyagramlarında kolayca temsil edilebilir. Örneğin, bu öğreticide kullanılan üç kubitli kuantum Fourier dönüşümlerinin tamamı, devre olarak aşağıdaki gösterime sahiptir: Quantum Fourier Dönüşüm devresinin diyagramı.

İpucu

Kuantum bilişim yolculuğunuzu hızlandırmak istiyorsanız Azure Quantum web sitesinin benzersiz bir özelliği olan Azure Quantum ile kod bölümüne bakın. Burada yerleşik Q# örnekleri veya kendi Q# programlarınızı çalıştırabilir, istemlerinizden yeni Q# kod oluşturabilir, kodunuzu tek tıklamayla Web için VS Code'da açıp çalıştırabilir ve Copilot'a kuantum bilişimi hakkında sorular sorabilirsiniz.

Önkoşullar

Yeni Q# dosya oluşturma

  1. VS Code'da Dosya > Yeni Metin Dosyası seçeneğini seçin
  2. Dosyayı QFTcircuit.qs olarak kaydedin. Bu dosya, programınızın Q# kodunu içerir.
  3. QFTcircuit.qs dosyasını açın.

Q# içinde bir QFT devresi yaz.

Bu öğreticinin ilk bölümü, üç kubit üzerinde kuantum Fourier dönüşümünü gerçekleştiren işlemini Q#tanımlamaktırMain. DumpMachine işlevi, üç kubitli sistemin simülasyon dalga işlevinin işlem genelinde nasıl geliştiğini gözlemlemek için kullanılır. Öğreticinin ikinci bölümünde ölçüm işlevselliği ekler ve kubitlerin ölçüm öncesi ve son durumlarını karşılaştırırsınız.

İşlemi adım adım oluşturursunuz. Aşağıdaki bölümlerde yer alan kodu kopyalayıp QFTcircuit.qs dosyasına yapıştırın.

Bu bölümün tam Q# kodunu başvuru olarak görüntüleyebilirsiniz.

Gerekli Q# kitaplıkları içeri aktarın

Dosyanızın Q# içinde ilgili Microsoft.Quantum.* ad alanlarını içeri aktarın.

import Microsoft.Quantum.Diagnostics.*;
import Microsoft.Quantum.Math.*;
import Microsoft.Quantum.Arrays.*;

// operations go here

Bağımsız değişkenler ve dönüş değerleri ile işlemleri tanımla

Ardından işlemi tanımlayın Main :

operation Main() : Unit {
    // do stuff
}

İşlem Main() asla bağımsız değişken almaz ve şu anda C#'ta void döndürüldüğünde ya da Python'da boş bir tanımlama grubu, Tuple[()], döndürüldüğünde olduğuna benzer bir Unit nesnesi döndürür. Daha sonra, bir ölçüm sonuçları dizisi döndürmek için işlemi değiştirirsiniz.

Kubitleri ayır

İşlemin içinde Q# anahtar sözcüğüyle use üç kubitin bir kaydını ayırın. ile use, kubitler otomatik olarak $\ket{0}$ durumunda ayrılır.

use qs = Qubit[3]; // allocate three qubits

Message("Initial state |000>:");
DumpMachine();

Gerçek kuantum hesaplamalarında olduğu gibi Q# kubit durumlarına doğrudan erişmenize izin vermez. Ancak, DumpMachine işlemi target makinenin geçerli durumunu yazdırır, böylece tam durum simülatörüyle birlikte kullanıldığında hata ayıklama ve öğrenme için değerli içgörüler sağlayabilir.

Tek kubitli ve denetimli işlemleri uygulama

Ardından, işlemin kendisini oluşturan Main işlemleri uygularsınız. Q# zaten ad alanında Microsoft.Quantum.Intrinsic bunların çoğunu ve diğer temel kuantum işlemlerini içerir.

Not

Önceki kod parçacığında Microsoft.Quantum.Intrinsic diğer ad alanlarıyla birlikte içeri aktarılmadığını unutmayın, çünkü Q# programlarının tümü için derleyici tarafından otomatik olarak yüklenir.

İlk qubite uygulanan ilk işlem H (Hadamard) işlemidir.

Üç kubit QFT için ilk Hadamard'dan geçen bir devreyi gösteren diyagram.

Bir yazmaçtan belirli bir kubite bir işlem uygulamak için (örneğin, bir dizi Qubit[] içindeki tek Qubit), standart dizin gösterimini kullanın. Bu nedenle, kaydın H ilk kubitine qs işlemi uygulamak şu şekilde olur:

H(qs[0]);

QFT devresi, işlemi tek tek kubitlere uygulamanın H yanı sıra öncelikli olarak kontrollü R1 döndürmelerden oluşur. Genel olarak bir R1(θ, <qubit>) işlem, kubitin $\ket{0}$ bileşenini değiştirmeden bırakırken $\ket{1}$ bileşenine $e^{i\theta}$ döndürme uygular.

Q# bir işlemin çalışmasını bir veya birden çok denetim kubitine göre koşula bağlamayı kolaylaştırır. Genel olarak, çağrı Controlled ile başlar ve işlev bağımsız değişkenleri aşağıdaki gibi değişir:

Op(<normal args>) $\to$ Controlled Op([<control qubits>], (<normal args>))

Denetim kubiti bağımsız değişkeninin, tek bir kubit için olsa bile, bir dizi olması gerektiği unutulmamalıdır.

QFT'deki denetlenen işlemler, ilk kubit üzerinde işlem gerçekleştiren (ve ikinci ve üçüncü kubitler tarafından denetlenen) işlemlerdir R1 :

İlk kubit üzerinden üç-kubitli Quantum Fourier Dönüşümü devresini gösteren diyagram.

Dosyanızda Q# bu işlemleri şu ifadelerle çağırın:

Controlled R1([qs[1]], (PI()/2.0, qs[0]));
Controlled R1([qs[2]], (PI()/4.0, qs[0]));

PI() işlevi, döndürmeleri pi radyan açısından tanımlamak için kullanılır.

SWAP işlemi uygulama

İlgili H işlemlerini ve denetimli döndürmeleri ikinci ve üçüncü kubitlere uyguladıktan sonra, devre şöyle görünür:

//second qubit:
H(qs[1]);
Controlled R1([qs[2]], (PI()/2.0, qs[1]));

//third qubit:
H(qs[2]);

Son olarak, devreyi tamamlamak için birinci ve üçüncü kubitlere bir SWAP işlem uygularsınız. Kuantum Fourier dönüşümü kubitleri ters sırada çıkardığından bu işlem gereklidir, bu nedenle değiştirme işlemleri alt düğümün daha büyük algoritmalarla sorunsuz tümleştirilmesine olanak tanır.

SWAP(qs[2], qs[0]);

Şimdi kuantum Fourier dönüşümünün kubit düzeyindeki işlemlerini işleminize yazmayı tamamladınız Q# :

Üç kubit Quantum Fourier Dönüşümü için bir bağlantı hattını gösteren diyagram.

Kubitleri serbest bırakma

Son adım, işlem sonrası durumunu görmek ve kubitleri serbest bırakmak için yeniden çağırmaktır DumpMachine() . Kubitleri tahsis ettiğinizde $\ket{0}$ durumundaydı ve ResetAll işlemi kullanılarak ilk durumlarına sıfırlanmaları gerekiyor.

Tüm kubitlerin açıkça $\ket{0}$ olarak sıfırlanması zorunluluğu, diğer işlemlerin Q#aynı kubitleri (kıt kaynak) kullanmaya başladığında durumlarını tam olarak bilmesini sağladığından temel bir özelliğidir. Ayrıca bunları sıfırlamak, sistemdeki diğer kübitlerle dolanık olmamalarını garanti eder. Sıfırlama bir use ayırma bloğunun sonunda gerçekleştirilmezse bir çalışma zamanı hatası ortaya çıkabilir.

Dosyanıza Q# aşağıdaki satırları ekleyin:

Message("After:");
DumpMachine();

ResetAll(qs); // deallocate qubits

Tam QFT işlemi

Program Q# tamamlandı. QFTcircuit.qs dosyanız şu şekilde görünmelidir:

import Microsoft.Quantum.Diagnostics.*;
import Microsoft.Quantum.Math.*;
import Microsoft.Quantum.Arrays.*;

operation Main() : Unit {

    use qs = Qubit[3]; // allocate three qubits

    Message("Initial state |000>:");
    DumpMachine();

    //QFT:
    //first qubit:
    H(qs[0]);
    Controlled R1([qs[1]], (PI()/2.0, qs[0]));
    Controlled R1([qs[2]], (PI()/4.0, qs[0]));

    //second qubit:
    H(qs[1]);
    Controlled R1([qs[2]], (PI()/2.0, qs[1]));

    //third qubit:
    H(qs[2]);

    SWAP(qs[2], qs[0]);

    Message("After:");
    DumpMachine();

    ResetAll(qs); // deallocate qubits

}                                                                                                                                                                               

QFT devresini çalıştırma

Şimdilik işlem Main herhangi bir değer döndürmez, işlem değer döndürür Unit . Daha sonra, işlemi bir ölçüm sonuçları dizisi (Result[]) döndürecek şekilde değiştirirsiniz.

  1. Programı çalıştırmadan önce, VS Code'un altındaki durum çubuğunda profilin target olarak ayarlandığını Q#doğrulayın: Sınırsız. Profili değiştirmek target için durum çubuğundan target profili seçin ve açılan menüden Kısıtlanmamış'ı seçin. profili Kısıtlanmamışolarak ayarlanmamışsa, programı çalıştırdığınızda bir hata alırsınız.
  2. Programınızı çalıştırmak için sağ üst köşedeki oynatma simgesi açılır menüsünden Dosyayı Çalıştır'ı seçin veya Ctrl+F5 tuşlarına basın. Program, Main() işlemi varsayılan simülatörde çalıştırır.
  3. Message ve DumpMachine çıkışları hata ayıklama konsolunda görünür.

Diğer giriş durumlarının nasıl etkilendiğini merak ediyorsanız, dönüştürmeden önce diğer kubit işlemlerini uygulamayı denemeniz tavsiye edilir.

QFT bağlantı hattına ölçüm ekleme

DumpMachine işlevinden görüntülenen görüntüde işlemin sonuçları gösterilir, ancak ne yazık ki kuantum mekaniğinin bir köşe taşı, gerçek bir kuantum sisteminin böyle bir DumpMachine işlevine sahip olmadığını belirtir. Bunun yerine, bilgiler ölçümler aracılığıyla ayıklanır ve genel olarak sadece tam kuantum durumu hakkında bilgi sağlamamakla kalmaz, aynı zamanda sistemi de önemli ölçüde değiştirebilir.

Birçok tür kuantum ölçümü vardır, ancak buradaki örnek en temel ölçümlere odaklanır: tek kubitlerdeki yansıtıcı ölçümler. Belirli bir temelde ölçüldükten sonra (örneğin, hesaplama temeli $ { \ket{0}, \ket{1} } $), kubit durumu ölçülen temel duruma yansıtılır ve bu nedenle ikisi arasındaki süper konum yok edilir.

QFT işlemini değiştirme

Bir Q# programı içinde ölçümler uygulamak için, Result türünü döndüren M işlemini kullanın.

İlk olarak, Main işlemini Unit yerine bir ölçüm sonuçları dizisi döndürecek şekilde değiştirin Result[].

operation Main() : Result[] {

Dizi tanımlama ve başlatma Result[]

Kubitleri ayırmadan önce üç öğeli bir dizi (her kubit için bir tane Result ) bildirin ve bağlayın:

mutable resultArray = [Zero, size = 3];

mutable Anahtar sözcük prefacing resultArray değişkeninin kodda daha sonra değiştirilmesini sağlar, örneğin ölçüm sonuçlarınızı eklerken.

Döngüde for ölçümler yapma ve diziye sonuç ekleme

QFT dönüştürme işlemlerden sonra aşağıdaki kodu ekleyin:

for i in IndexRange(qs) {
    resultArray w/= i <- M(qs[i]);
}

Bir IndexRange dizide çağrılan işlev (örneğin kubit dizisi), qsdizinin dizinleri üzerinde bir aralık döndürür. Burada, for deyimini kullanarak her kubiti sıralı olarak ölçmek için M(qs[i]) döngüsünde kullanılır. Ölçülen her Result türü (ya Zero ya da One), 'resultArray' içindeki ilgili dizin konumuna bir güncelleme ve yeniden atama ifadesi ile eklenir.

Not

Bu deyimin söz dizimi Q# için benzersizdir, ancak F# ve R gibi diğer dillerde görülen benzer değişken yeniden atama yapısına resultArray[i] <- M(qs[i]) karşılık gelir.

Anahtar sözcük set, mutable ile bağlı değişkenleri yeniden atamak için her zaman kullanılır.

Dönmek resultArray

Üç kubitin de ölçülmesi ve sonuçların resultArray'a eklenmesiyle, kubitleri daha önce olduğu gibi sıfırlayabilir ve serbest bırakabilirsiniz. Ölçümleri döndürmek için şunu ekleyin:

return resultArray;

Ölçümlerle QFT devresini çalıştırma

DumpMachine işlevlerinin yerleşimini şimdi değiştirerek ölçümlerin öncesi ve sonrası durumu çıktıya verin. Son Q# kodunuz şu şekilde görünmelidir:

import Microsoft.Quantum.Diagnostics.*;
import Microsoft.Quantum.Math.*;
import Microsoft.Quantum.Arrays.*;

operation Main() : Result[] {

    mutable resultArray = [Zero, size = 3];

    use qs = Qubit[3];

    //QFT:
    //first qubit:
    H(qs[0]);
    Controlled R1([qs[1]], (PI()/2.0, qs[0]));
    Controlled R1([qs[2]], (PI()/4.0, qs[0]));

    //second qubit:
    H(qs[1]);
    Controlled R1([qs[2]], (PI()/2.0, qs[1]));

    //third qubit:
    H(qs[2]);

    SWAP(qs[2], qs[0]);

    Message("Before measurement: ");
    DumpMachine();

    for i in IndexRange(qs) {
        resultArray w/= i <- M(qs[i]);
    }

    Message("After measurement: ");
    DumpMachine();

    ResetAll(qs);
    Message("Post-QFT measurement results [qubit0, qubit1, qubit2]: ");
    return resultArray;

}

İpucu

Yeniden çalıştırmadan önce kodda her değişiklik eklediğinizde dosyanızı kaydetmeyi unutmayın.

  1. Programı çalıştırmadan önce, VS Code'un altındaki durum çubuğunda profilin target olarak ayarlandığını Q#doğrulayın: Sınırsız. Profili değiştirmek target için durum çubuğundan target profili seçin ve açılan menüden Kısıtlanmamış'ı seçin. profili Kısıtlanmamışolarak ayarlanmamışsa, programı çalıştırdığınızda bir hata alırsınız.
  2. Programınızı çalıştırmak için sağ üst köşedeki oynatma simgesi açılır menüsünden 'Dosyayı çalıştır' seçeneğini seçin veya Ctrl+5 tuşlarına basın. Program, Main() işlemi varsayılan simülatörde çalıştırır.
  3. Message ve DumpMachine çıkışları hata ayıklama konsolunda görünür.

Çıktınız şuna benzer görünmelidir:

Before measurement: 

 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

After measurement: 

 Basis | Amplitude      | Probability | Phase
 -----------------------------------------------
 |010⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000

Post-QFT measurement results [qubit0, qubit1, qubit2]: 

[Zero, One, Zero]

Bu çıkış birkaç farklı şeyi gösterir:

  1. Ölçüm öncesi DumpMachineile döndürülen sonucu karşılaştırdığınızda, QFT sonrası süperpozisyonun temel durumlar üzerindeki açıkça gösterilmediği görülmektedir. Ölçüm, sistemin dalga işlevindeki bu durumun genliği tarafından belirlenen bir olasılıkla yalnızca tek bir temel durum döndürür.
  2. Ölçüm DumpMachinesonrası durumundan ölçümün durumu değiştirdiğini ve bunu temel durumlar üzerinden ilk süper pozisyondan ölçülen değere karşılık gelen tek temel duruma yansıttığını görürsünüz.

Bu işlemi birçok kez tekrarlarsanız, sonuç istatistiklerinin, her çekimde rastgele bir sonuca neden olan QFT sonrası durumun eşit ağırlıklı süperpozisyonunu göstermeye başladığını göreceksiniz. Ancak, verimsiz ve hala kusurlu olmasının yanı sıra, bu, yalnızca temel durumların göreli genliklerini yeniden üretir, durumlar arasındaki göreli fazları değil. İkincisi bu örnekte bir sorun değildir, ancak QFT'ye $\ket{000}$ durumundan daha karmaşık bir giriş verildiğinde göreli fazların ortaya çıktığını görürdünüz.

QFT devresini basitleştirmek için Q# işlemlerini kullanın

Girişte belirtildiği gibi, Q#'nin gücünün çoğu, bireysel kubitlerle ilgilenme endişelerini ortadan kaldırmanıza olanak sağlaması gerçeğinden gelmektedir. Aslında, tam ölçekli, geçerli kuantum programları geliştirmek istiyorsanız, bir işlemin belirli bir H döndürmeden önce mi yoksa sonra mı geçeceği konusunda endişelenmeniz sizi yalnızca yavaşlatır. Azure Quantum, istediğiniz sayıda kubit için kullanabileceğiniz ve uygulayabileceğiniz işlemi sağlar ApplyQFT .

  1. İlk H işlemden SWAP işlemine kadar her şeyi, dahil, şununla değiştirin:

    ApplyQFT(qs);
    
  2. Kodunuz şimdi şöyle görünmelidir

    import Microsoft.Quantum.Diagnostics.*;
    import Microsoft.Quantum.Math.*;
    import Microsoft.Quantum.Arrays.*;
    
    operation Main() : Result[] {
    
        mutable resultArray = [Zero, size = 3];
    
        use qs = Qubit[3];
    
        //QFT:
        //first qubit:
    
        ApplyQFT(qs);
    
        Message("Before measurement: ");
        DumpMachine();
    
        for i in IndexRange(qs) {
            resultArray w/= i <- M(qs[i]);
        }
    
        Message("After measurement: ");
        DumpMachine();
    
        ResetAll(qs);
        Message("Post-QFT measurement results [qubit0, qubit1, qubit2]: ");
        return resultArray;
    
    }
    
  3. Q# Programı yeniden çalıştırın ve çıkışın öncekiyle aynı olduğuna dikkat edin.

  4. Q# işlemlerini kullanmanın gerçek avantajını görmek için kubit sayısını, 3 dışındaki bir değere değiştirin.

mutable resultArray = [Zero, size = 4];

use qs = Qubit[4];
//...

Böylece, her kubite yeni H işlemler ve döndürmeler ekleme konusunda endişelenmenize gerek kalmadan, belirli sayıda kubit için uygun QFT'yi uygulayabilirsiniz.

Diğer Q# öğreticileri keşfedin: