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:
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
A Visual Studio Code legújabb verziója, vagy nyissa meg a VS Code-ot a weben.
A Azure Quantum Development Kit (QDK) bővítmény legújabb verziója. A telepítés részleteiért lásd: QDK-bővítmény beállítása.
Ha Jupyter Notebookokat szeretne használni, telepítenie kell a Python- és Jupyter-bővítményeket , valamint a legújabb
qsharp
Python-csomagot is. Ehhez nyisson meg egy terminált, és futtassa a következő parancsot:$ pip install --upgrade qsharp
Új Q# fájl létrehozása
- A VS Code-ban válassza az Új szövegfájl fájlja > lehetőséget
- Mentse a fájlt QFTcircuit.qs néven. Ez a fájl tartalmazza a program Q# kódját.
- Nyissa meg a QFTcircuit.qs parancsot.
QFT-kapcsolatcsoport írása Q#
Az oktatóanyag első része a Q# művelet Main
meghatá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 use
együ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:
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 Controlled
van 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:
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:
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.
- 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.
- 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. - A
Message
kimenetek ésDumpMachine
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, Main
Result[]
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 qs
tö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 Zero
One
) 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 mutable
hozzá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.
- 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.
- 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. - A
Message
kimenetek ésDumpMachine
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:
- 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. - A mérés
DumpMachine
utá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.
Az első
H
művelettől kezdve a műveletig mindent cserélje le aSWAP
következőre:ApplyQFT(qs);
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; }
Futtassa újra a Q# programot, és figyelje meg, hogy a kimenet megegyezik a korábbival.
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.
Kapcsolódó tartalom
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.