Megosztás a következőn keresztül:


Oktatóanyag: A Quantum Fourier-átalakítás implementálása Q#

Ez az oktatóanyag bemutatja, hogyan írhat és szimulálhat egy alapszintű kvantumprogramot, amely egyéni qubiteken működik.

Bár Q# elsősorban nagy léptékű kvantumprogramok magas szintű programozási nyelveként hozták létre, a kvantumprogramozás alacsonyabb szintjének, vagyis az adott qubitek közvetlen kezelésére is használható. Ez az oktatóanyag közelebbről is áttekinti a Quantum Fourier Transform (QFT) nevű alrutint, amely számos nagyobb kvantum-algoritmus szerves része.

Ebben az oktatóanyagban a következőket sajátíthatja el:

  • Kvantumműveletek definiálása a következőben Q#: .
  • A Quantum Fourier Transform-kapcsolatcsoport írása
  • Kvantumművelet szimulálása a qubit-foglalástól a mérési kimenetig.
  • Figyelje meg, hogyan fejlődik a kvantumrendszer szimulált hullámfüggése a művelet során.

Feljegyzés

A kvantuminformáció-feldolgozás ezen alacsonyabb szintű nézetét gyakran kvantumkörökben írják le, amelyek a kapuk vagy műveletek szekvenciális alkalmazását jelölik a rendszer meghatározott qubitjeire. Így az egymás után alkalmazott egy- és több qubites műveletek könnyen ábrázolhatók a kapcsolatcsoportok diagramjaiban. Az oktatóanyagban használt három qubites kvantum Fourier-transzformáció például a következő kapcsolatcsoportként jelenik meg: Quantum Fourier Transform-kapcsolatcsoport diagramja.

Tipp.

Ha fel szeretné gyorsítani a kvantum-számítástechnika folyamatát, tekintse meg az Azure Quantum-webhely egyedi funkcióját, az Azure Quantum-ot. Itt futtathat beépített mintákat vagy saját Q# programokat, új Q# kódot hozhat létre az üzeneteiből, megnyithatja és futtathatja a kódot a WEBES VS Code-ban Q#egy kattintással, és kérdéseket tehet fel a Copilotnak a kvantum-számítástechnikával kapcsolatban.

Előfeltételek

Új Q# fájl létrehozása

  1. A VS Code-ban válassza az Új szövegfájl fájlja > lehetőséget
  2. Mentse a fájlt QFTcircuit.qs néven. Ez a fájl tartalmazza a program Q# kódját.
  3. Nyissa meg a QFTcircuit.qs parancsot.

QFT-kapcsolatcsoport írása Q#

Az oktatóanyag első része a Q# művelet Mainmeghatározásából áll, amely három qubiten hajtja végre a kvantum Fourier-átalakítást. A DumpMachine függvény annak megfigyelésére szolgál, hogyan fejlődik a három qubites rendszer szimulált hullámfüggvénye a művelet során. Az oktatóanyag második részében mérési funkciókat ad hozzá, és összehasonlítja a qubitek mérés előtti és utáni állapotát.

A műveletet lépésről lépésre kell felépíteni. Másolja és illessze be a kódot a következő szakaszokban a QFTcircuit.qs fájlba.

A szakasz teljes Q# kódját hivatkozásként tekintheti meg.

Szükséges Q# kódtárak importálása

Q# A fájlon belül importálja a megfelelő Microsoft.Quantum.* névtereket.

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

// operations go here

Műveletek definiálása argumentumokkal és visszatérésekkel

Ezután adja meg a Main műveletet:

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

A Main() művelet soha nem vesz fel argumentumokat, és egyelőre egy Unit olyan objektumot ad vissza, amely hasonló a C# vagy egy üres rekord visszaadásához void a Tuple[()]Pythonban. Később módosíthatja a műveletet, hogy a mérési eredmények tömbje legyen visszaadva.

Qubitek lefoglalása

A műveleten Q# belül foglaljon le egy három qubitből álló nyilvántartást a use kulcsszóval. Ezzel useegyütt a qubitek automatikusan $\ket$ állapotban lesznek{0} lefoglalva.

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

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

A valós kvantumszámításokhoz hasonlóan Q# nem teszi lehetővé a qubitállapotok közvetlen elérését. A DumpMachine művelet azonban kinyomtatja a target gép aktuális állapotát, így értékes betekintést nyújthat a hibakereséshez és a tanuláshoz, ha a teljes állapotú szimulátorral együtt használják.

Egy qubites és szabályozott műveletek alkalmazása

Ezután alkalmazza a műveletet alkotó Main műveleteket. Q# már tartalmaz sok ilyen és más alapvető kvantumműveletet a Microsoft.Quantum.Intrinsic névtérben.

Feljegyzés

Vegye figyelembe, hogy Microsoft.Quantum.Intrinsic a korábbi kódrészlet nem importálta a többi névtérrel együtt, mivel a fordító automatikusan betölti az összes Q# programhoz.

Az első alkalmazott művelet a H (Hadamard) művelet az első qubitre:

Három qubites QFT-kapcsolatcsoportot ábrázoló diagram az első Hadamardon keresztül.

Ha egy műveletet egy adott qubitre szeretne alkalmazni egy regiszterből (például egy Qubit tömbből Qubit[]), használjon szabványos indexjelezést. A műveletet tehát a H regiszter qs első qubitre való alkalmazása a következő formában történik:

H(qs[0]);

A művelet egyes qubitekre való alkalmazása H mellett a QFT-kapcsolatcsoport elsősorban szabályozott R1 forgásokból áll. Egy R1(θ, <qubit>) művelet általában változatlanul hagyja a qubit $\ket{0}$ összetevőjét, miközben $e^{i\theta}$ forgást alkalmaz a $\ket{1}$ összetevőre.

Q# megkönnyíti egy művelet futtatásának kondicioncióját egy vagy több vezérlési qubiten. A hívás általában a következővel Controlledvan előtaggal elosztva, és a művelet argumentumai a következőképpen változnak:

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

Vegye figyelembe, hogy a vezérlő qubit argumentumának tömbnek kell lennie, még akkor is, ha egyetlen qubitről van szó.

A QFT szabályozott műveletei az R1 első qubiten (és a második és a harmadik qubit által vezérelt) műveletek:

Diagram a három qubites Quantum Fourier Transform kapcsolatcsoportról az első qubiten keresztül.

Q# A fájlban hívja meg ezeket a műveleteket az alábbi utasításokkal:

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

A PI() függvény a pi radiánok forgásának meghatározására szolgál.

SWAP művelet alkalmazása

Miután a megfelelő H műveleteket és szabályozott forgatásokat alkalmazta a második és a harmadik qubitre, az áramkör a következőképpen néz ki:

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

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

Végül egy műveletet alkalmaz SWAP az első és a harmadik qubitre a kapcsolatcsoport befejezéséhez. Ez a művelet azért szükséges, mert a kvantum Fourier-transzformáció fordított sorrendben adja ki a qubiteket, így a felcserélések lehetővé teszik az alrutin zökkenőmentes integrációját nagyobb algoritmusokba.

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

Most befejezte a kvantum Fourier-transzformáció qubitszintű műveleteinek írását a Q# műveletbe:

Három qubites Quantum Fourier Transform kapcsolatcsoportot bemutató ábra.

Qubitek felszabadítása

Az utolsó lépés a művelet utáni állapot ismételt meghívása DumpMachine() és a qubitek felszabadítása. A qubitek $\ket{0}$ állapotban voltak, amikor lefoglalta őket, és a művelettel ResetAll vissza kell állítani a kezdeti állapotukat.

Annak megkövetelése, hogy az összes qubitet explicit módon állítsa vissza a $\ket{0}$ értékre, annak alapvető funkciója Q#, hogy más műveletek pontosan tudják az állapotukat, amikor ugyanazokat a qubiteket (szűkös erőforrást) kezdik használni. Emellett az alaphelyzetbe állításuk biztosítja, hogy nincsenek összekapcsolva a rendszer más qubitjeivel. Ha az alaphelyzetbe állítást nem egy use foglalási blokk végén hajtják végre, futásidejű hiba fordulhat elő.

Adja hozzá a következő sorokat a Q# fájlhoz:

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

ResetAll(qs); // deallocate qubits

A teljes QFT-művelet

A Q# program befejeződött. A QFTcircuit.qs fájlnak így kell kinéznie:

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

}                                                                                                                                                                               

A QFT-kapcsolatcsoport futtatása

A művelet egyelőre Main nem ad vissza értéket – a művelet értéket ad Unit vissza. Később módosítja a műveletet, hogy a mérési eredmények tömbje (Result[]) legyen visszaadva.

  1. A program futtatása előtt ellenőrizze a VS Code alján található állapotsoron, hogy a target profil a következőre Q#van állítva: Korlátlan. A target profil módosításához válassza ki a profilt target az állapotsoron, és válassza a Nem korlátozva lehetőséget a legördülő menüből. Ha a target profil nincs Korlátlanállapotban, a program futtatásakor hibát kap.
  2. A program futtatásához válassza Q# futtatása lehetőséget a lejátszás ikon jobb felső részén, vagy nyomja le a Ctrl+F5 billentyűkombinációt. A program az Main() alapértelmezett szimulátoron futtatja a műveletet.
  3. A Message kimenetek és DumpMachine a kimenetek megjelennek a hibakeresési konzolon.

Ha kíváncsi arra, hogy más bemeneti állapotok milyen hatással vannak, javasoljuk, hogy kísérletezzen más qubitműveletek alkalmazásával az átalakítás előtt.

Mérések hozzáadása a QFT-kapcsolatcsoporthoz

A DumpMachine függvény kijelzője a művelet eredményeit mutatta, de sajnos a kvantummechanika egyik sarokköve azt állítja, hogy egy valódi kvantumrendszer nem rendelkezhet ilyen DumpMachine függvénnyel. Ehelyett az információkat méréseken keresztül nyerik ki, amelyek általában nem csak a teljes kvantumállapotról nyújtanak információt, hanem magát a rendszert is drasztikusan megváltoztathatják.

Számos kvantummérés létezik, de az alábbi példa a legalapvetőbbre összpontosít: az egy qubiten végzett projektív mérésekre. Ha egy adott alapon végzett mérés (például a számítási alap $ { \ket{0}, \ket{1} } $), a qubit állapota a mért alapállapotra lesz kivetítve, így a kettő közötti szuperpozíciót megsemmisíti.

A QFT-művelet módosítása

A programon belüli Q# mérések végrehajtásához használja a M műveletet, amely egy típust Result ad vissza.

Először módosítsa a műveletet úgy, MainResult[]hogy a Unit mérési eredmények tömbje helyett egy tömböt adjon vissza.

operation Main() : Result[] {

Tömb definiálása és inicializálása Result[]

A qubitek kiosztása előtt deklaráljon és kösse össze a háromelemű tömböt (minden qubithez egyet Result ):

mutable resultArray = [Zero, size = 3];

A mutable kulcsszó-előbontás resultArray lehetővé teszi a változó módosítását a kód későbbi részében, például a mérési eredmények hozzáadásakor.

Mérések végrehajtása ciklusban for , és eredmények hozzáadása tömbhöz

A QFT-átalakítási műveletek után szúrja be a következő kódot:

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

A IndexRange tömböt meghívó függvény (például qubitek qstömbje) egy tartományt ad vissza a tömb indexei felett. Itt a for ciklusban használják az egyes qubitek egymás utáni mérésére a M(qs[i]) utasítás használatával. Ezután minden mért Result típus (vagy ZeroOne) hozzáadódik a megfelelő indexpozícióhoz resultArray egy frissítési és újbóli hozzárendelési utasítással.

Feljegyzés

Ennek az utasításnak a szintaxisa egyedi Q#, de megfelel a más nyelvekben, például az F# és az R nyelvben látott hasonló változó-hozzárendelésnek resultArray[i] <- M(qs[i]) .

A kulcsszó set mindig a változók mutablehozzárendelésére szolgál.

Visszatérés resultArray

A három qubit mérésével és az eredmények resultArray-hoz való hozzáadásával biztonságosan alaphelyzetbe állíthatja és felszabadíthatja a qubiteket, mint korábban. A mérések visszaadásához szúrja be a következőt:

return resultArray;

A QFT-kapcsolatcsoport futtatása a mérésekkel

Most módosítsa a függvények elhelyezését úgy DumpMachine , hogy a mérések előtti és utáni állapotot adja ki. A végleges Q# kódnak így kell kinéznie:

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;

}

Tipp.

Ne felejtse el menteni a fájlt minden alkalommal, amikor módosítja a kódot, mielőtt újra futtatja.

  1. A program futtatása előtt ellenőrizze a VS Code alján található állapotsoron, hogy a target profil a következőre Q#van állítva: Korlátlan. A target profil módosításához válassza ki a profilt target az állapotsoron, és válassza a Nem korlátozva lehetőséget a legördülő menüből. Ha a target profil nincs Korlátlanállapotban, a program futtatásakor hibát kap.
  2. A program futtatásához válassza Q# futtatása lehetőséget a jobb felső sarokban található lejátszás ikon legördülő menüből, vagy nyomja le a Ctrl+5 billentyűkombinációt. A program az Main() alapértelmezett szimulátoron futtatja a műveletet.
  3. A Message kimenetek és DumpMachine a kimenetek megjelennek a hibakeresési konzolon.

A kimenetnek a következőhöz hasonlóan kell kinéznie:

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]

Ez a kimenet néhány különböző dolgot szemléltet:

  1. Ha összehasonlítja a visszaadott eredményt az előmérési DumpMachine, az egyértelműen nem a QFT utáni szuperpozíciót az alapállapotok alapján. A mérés csak egy alapállapotot ad vissza, amelynek valószínűségét az adott állapot amplitúdója határozza meg a rendszer hullámfüggvényében.
  2. A mérés DumpMachineutáni állapotból láthatja, hogy a mérés magát az állapotot módosítja , és az alapállapotok feletti kezdeti szuperpozícióból a mért értéknek megfelelő egyetlen alapállapotra vetít.

Ha többször megismételi ezt a műveletet, az eredménystatisztikák elkezdik szemléltetni a QFT utáni állapot egyenlően súlyozott szuperpozícióját, amely véletlenszerű eredményt ad minden egyes lövéshez. Azonban amellett, hogy nem hatékony és még mindig tökéletlen, ez mégis csak az alapállapotok relatív amplitúdóit reprodukálná, nem pedig a közöttük lévő relatív fázisokat. Ez utóbbi nem jelent problémát ebben a példában, de relatív fázisok jelennek meg, ha összetettebb bemenetet ad a QFT-hez, mint $\ket{000}$.

Q# A műveletek használatával egyszerűsítheti a QFT-kapcsolatcsoportot

Ahogy a bevezetésben említettük, a hatalom nagy része Q#abban rejlik, hogy lehetővé teszi az egyes qubitek kezelésével kapcsolatos aggodalmak absztrakcióját. Valóban, ha teljes körű, alkalmazható kvantumprogramokat szeretne fejleszteni, és azzal foglalkozik, hogy egy H művelet egy adott rotáció előtt vagy után megy-e, csak lelassítaná. Az Azure Quantum biztosítja a ApplyQFT műveletet, amelyet tetszőleges számú qubithez használhat és alkalmazhat.

  1. Az első H művelettől kezdve a műveletig mindent cserélje le a SWAP következőre:

    ApplyQFT(qs);
    
  2. A kódnak így kell kinéznie

    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. Futtassa újra a Q# programot, és figyelje meg, hogy a kimenet megegyezik a korábbival.

  4. A műveletek használatának Q# valódi előnyeinek megtekintéséhez módosítsa a qubitek számát a következőn kívülre 3:

mutable resultArray = [Zero, size = 4];

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

Így tetszőleges számú qubithez alkalmazhatja a megfelelő QFT-t anélkül, hogy minden qubithez új H műveleteket és forgatásokat kellene hozzáadnia.

További Q# oktatóanyagok:

  • A kvantum véletlenszerű számgenerátor bemutatja, hogyan írhat olyan Q# programot, amely véletlenszerű számokat hoz létre qubitből szuperpozícióban.
  • A Grover keresési algoritmusa bemutatja, hogyan írhat olyan Q# programot, amely a Grover keresési algoritmusát használja.
  • A kvantum-összefonódás bemutatja, hogyan írhat olyan Q# programot, amely manipulálja és méri a qubiteket, és bemutatja a szuperpozíció és az összefonódás hatásait.
  • A Quantum Katas öngyors oktatóanyagok és programozási gyakorlatok, amelyek célja a kvantum-számítástechnika és Q# a programozás elemeinek egyidejű tanítása.