Självstudie: Implementera Quantum Fourier-transformering i Q#
Den här självstudien visar hur du skriver och simulerar ett grundläggande kvantprogram som fungerar på enskilda kvantbitar.
Även om Q# det främst skapades som ett högnivåprogrammeringsspråk för storskaliga kvantprogram, kan det också användas för att utforska den lägre nivån av kvantprogrammering, dvs. Mer specifikt tar den här självstudien en närmare titt på Quantum Fourier Transform (QFT), en underrutin som är integrerad i många större kvantalgoritmer.
I den här självstudien får du lära dig att:
- Definiera kvantåtgärder i Q#.
- Skriva Quantum Fourier Transform-kretsen
- Simulera en kvantåtgärd från kvantbitsallokering till mätningsutdata.
- Observera hur kvantsystemets simulerade vågfunktion utvecklas under hela åtgärden.
Kommentar
Den här lägre vyn av kvantinformationsbearbetning beskrivs ofta i termer av kvantkretsar, som representerar den sekventiella tillämpningen av grindar eller åtgärder för specifika kvantbitar i ett system. Därför kan de åtgärder med en och flera kvantbitar som du tillämpar sekventiellt enkelt representeras i kretsdiagram. Den fullständiga fourier-kvanttransformningen med tre kvantbitar som används i den här självstudien har till exempel följande representation som en krets:
Dricks
Om du vill påskynda din kvantberäkningsresa kan du kolla in Kod med Azure Quantum, en unik funktion på Azure Quantum-webbplatsen. Här kan du köra inbyggda Q# exempel eller egna Q# program, generera ny Q# kod från dina frågor, öppna och köra koden i VS Code för webben med ett klick och ställa frågor till Copilot om kvantberäkning.
Förutsättningar
Den senaste versionen av Visual Studio Code eller öppna VS Code på webben.
Den senaste versionen av Azure-tilläggetQuantum Development Kit. Installationsinformation finns i Installera QDK på VS Code.
Om du vill använda Jupyter Notebooks måste du också installera Python- och Jupyter-tillägg och det senaste Python-paketet
qsharp
. Det gör du genom att öppna en terminal och köra följande kommando:$ pip install --upgrade qsharp
Skapa en ny Q# fil
- I VS Code väljer du Fil > Ny textfil
- Spara filen som QFTcircuit.qs. Den här filen innehåller Q# koden för ditt program.
- Öppna QFTcircuit.qs.
Skriva en QFT-krets i Q#
Den första delen av den här självstudien Q# består av att definiera åtgärden Main
, som utför kvant-Fourier-transformering på tre kvantbitar. Funktionen DumpMachine
används för att observera hur den simulerade vågfunktionen i tre-qubit-systemet utvecklas under hela åtgärden. I den andra delen av självstudien lägger du till måttfunktioner och jämför kvantbitarnas tillstånd före och efter mätning.
Du skapar åtgärden steg för steg. Kopiera och klistra in koden i följande avsnitt i QFTcircuit.qs-filen .
Du kan visa den fullständiga Q# koden för det här avsnittet som referens.
Importera nödvändiga Q# bibliotek
Q# Importera relevanta Microsoft.Quantum.*
namnområden i filen.
import Microsoft.Quantum.Diagnostics.*;
import Microsoft.Quantum.Math.*;
import Microsoft.Quantum.Arrays.*;
// operations go here
Definiera åtgärder med argument och returer
Definiera sedan åtgärden Main
:
operation Main() : Unit {
// do stuff
}
Åtgärden Main()
tar aldrig argument och returnerar för tillfället ett Unit
-objekt, vilket är detsamma som att void
returnera i C# eller en tom tuppl, Tuple[()]
, i Python.
Senare ändrar du åtgärden för att returnera en matris med mätresultat.
Allokera kvantbitar
I åtgärden Q# allokerar du ett register med tre kvantbitar med nyckelordet use
. Med use
allokeras kvantbitarna automatiskt i tillståndet $\ket{0}$ .
use qs = Qubit[3]; // allocate three qubits
Message("Initial state |000>:");
DumpMachine();
Precis som i verkliga kvantberäkningar Q# kan du inte komma åt kvantbitstillstånd direkt. Åtgärden skriver dock DumpMachine
ut target datorns aktuella tillstånd, så att den kan ge värdefull insikt för felsökning och inlärning när den används tillsammans med simulatorn för fullständigt tillstånd.
Tillämpa enkla kvantbitar och kontrollerade åtgärder
Därefter tillämpar du de åtgärder som utgör Main
själva åtgärden. Q# innehåller redan många av dessa och andra grundläggande kvantåtgärder i Microsoft.Quantum.Intrinsic
namnområdet.
Kommentar
Observera att Microsoft.Quantum.Intrinsic
det inte importerades i det tidigare kodfragmentet med de andra namnrymderna, eftersom det läses in automatiskt av kompilatorn för alla Q# program.
Den första åtgärden som tillämpas är H
(Hadamard)-åtgärden till den första qubiten:
Om du vill tillämpa en åtgärd på en specifik kvantbit från ett register (till exempel en enskild Qubit
från en matris Qubit[]
) använder du standardindexanmälning.
Så att tillämpa åtgärden på H
den första kvantbiten i registret qs
tar formuläret:
H(qs[0]);
Förutom att tillämpa åtgärden på H
enskilda kvantbitar består QFT-kretsen främst av kontrollerade R1
rotationer. En R1(θ, <qubit>)
åtgärd i allmänhet lämnar komponenten $\ket{0}$ i qubiten oförändrad när en rotation av $e^{i\theta}$ tillämpas på $\ket{1}$-komponenten.
Q# gör det enkelt att villkora körningen av en åtgärd på en eller flera kontrollkvabitar. I allmänhet föregås anropet av Controlled
, och åtgärdsargumenten ändras på följande sätt:
Op(<normal args>)
$\to$ Controlled Op([<control qubits>], (<normal args>))
Observera att argumentet för kontrollkvabit måste vara en matris, även om det är för en enda qubit.
De kontrollerade åtgärderna i QFT är de R1
åtgärder som fungerar på den första kvantbiten (och styrs av den andra och tredje kvantbiten):
I filen Q# anropar du dessa åtgärder med följande instruktioner:
Controlled R1([qs[1]], (PI()/2.0, qs[0]));
Controlled R1([qs[2]], (PI()/4.0, qs[0]));
Funktionen PI()
används för att definiera rotationerna i termer av pi-radianer.
Tillämpa SWAP-åtgärden
När du har tillämpat relevanta H
åtgärder och kontrollerade rotationer på den andra och tredje kvantbiten ser kretsen ut så här:
//second qubit:
H(qs[1]);
Controlled R1([qs[2]], (PI()/2.0, qs[1]));
//third qubit:
H(qs[2]);
Slutligen tillämpar du en SWAP
åtgärd på den första och tredje kvantbiten för att slutföra kretsen. Detta är nödvändigt eftersom typen av kvant fourier-transformering matar ut kvantbitarna i omvänd ordning, så växlingarna möjliggör sömlös integrering av subrutinen i större algoritmer.
SWAP(qs[2], qs[0]);
Nu har du skrivit klart kvantbitsåtgärden på kvant fourier-transformering till din Q# åtgärd:
Frigör kvantbitar
Det sista steget är att anropa DumpMachine()
igen för att se tillståndet efter åtgärden och frigöra kvantbitarna. Kvantbitarna var i tillståndet $\ket{0}$ när du allokerade dem och måste återställas till deras ursprungliga tillstånd med hjälp av åtgärden ResetAll
.
Att kräva att alla kvantbitar uttryckligen återställs till $\ket{0}$ är en grundläggande funktion Q#i , eftersom andra åtgärder kan känna till deras tillstånd exakt när de börjar använda samma kvantbitar (en knapp resurs). Dessutom säkerställer detta att de inte är sammanflätade med andra kvantbitar i systemet. Om återställningen inte utförs i slutet av ett use
allokeringsblock kan ett körningsfel uppstå.
Lägg till följande rader i Q# filen:
Message("After:");
DumpMachine();
ResetAll(qs); // deallocate qubits
Den fullständiga QFT-åtgärden
Programmet Q# har slutförts. Din QFTcircuit.qs-fil bör nu se ut så här:
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
}
Kör QFT-kretsen
För tillfället returnerar inte åtgärden Main
något värde – åtgärden returnerar Unit
värdet. Senare ändrar du åtgärden för att returnera en matris med mätresultat (Result[]
).
- Innan du kör programmet kontrollerar du i statusfältet längst ned i VS Code att profilen target är inställd på Q#: Obegränsad. Om du vill ändra profilen target väljer du profilen target i statusfältet och väljer Obegränsad på den nedrullningsbara menyn. Om profilen target inte är inställd på Obegränsad får du ett fel när du kör programmet.
- Om du vill köra programmet väljer du Kör fil i listrutan uppspelningsikon längst upp till höger eller trycker på Ctrl+F5. Q# Programmet kör
Main()
åtgärden på standardsimulatorn. - Utdata
Message
ochDumpMachine
visas i felsökningskonsolen.
Om du är nyfiken på hur andra indatatillstånd påverkas rekommenderar vi att du experimenterar med att tillämpa andra qubit-åtgärder före transformeringen.
Lägga till mått i QFT-kretsen
Visningen från DumpMachine
funktionen visade resultatet av åtgärden, men tyvärr säger en hörnsten i kvantmekaniken att ett verkligt kvantsystem inte kan ha en DumpMachine
sådan funktion.
I stället extraheras informationen genom mätningar, som i allmänhet inte bara misslyckas med att tillhandahålla information om det fullständiga kvanttillståndet, utan också kan ändra själva systemet drastiskt.
Det finns många typer av kvantmått, men exemplet här fokuserar på de mest grundläggande: projektiva mätningar på enskilda kvantbitar. Vid mätning i en viss bas (till exempel beräkningsbasen $ { \ket{0}, \ket{1} } $), projiceras qubittillståndet på det bastillstånd som mättes, vilket förstör eventuell superposition mellan de två.
Ändra QFT-åtgärden
Om du vill implementera mått i ett Q# program använder du åtgärden M
, som returnerar en Result
typ.
Main
Ändra först åtgärden för att returnera en matris med mätresultat, , Result[]
i stället för Unit
.
operation Main() : Result[] {
Definiera och initiera Result[]
matris
Innan du allokerar kvantbitar deklarerar och binder du en matris med tre element (en Result
för varje qubit):
mutable resultArray = [Zero, size = 3];
Med mutable
nyckelordsförhandsinställningen resultArray
kan variabeln ändras senare i koden, till exempel när du lägger till dina mätresultat.
Utföra mått i en for
loop och lägga till resultat i matrisen
Efter QFT-transformeringsåtgärderna infogar du följande kod:
for i in IndexRange(qs) {
set resultArray w/= i <- M(qs[i]);
}
Funktionen IndexRange
som anropas på en matris (till exempel matrisen med kvantbitar, qs
) returnerar ett intervall över matrisens index.
Här används den i loopen for
för att sekventiellt mäta varje qubit med hjälp av -instruktionen M(qs[i])
.
Varje uppmätt Result
typ (antingen Zero
eller One
) läggs sedan till i motsvarande indexposition i resultArray
med en uppdaterings- och omtilldelningsinstruktor.
Kommentar
Syntaxen för den här instruktionen är unik för Q#, men motsvarar den liknande variabelomtilldelning resultArray[i] <- M(qs[i])
som visas på andra språk som F# och R.
Nyckelordet set
används alltid för att omtilldela variabler som är bundna med hjälp av mutable
.
Återvända resultArray
När alla tre kvantbitarna har mätts och resultaten har lagts till resultArray
i är det säkert att återställa och frigöra kvantbitarna som tidigare. Om du vill returnera måtten infogar du:
return resultArray;
Kör QFT-kretsen med måtten
Ändra nu placeringen av DumpMachine
funktionerna så att tillståndet matas ut före och efter måtten.
Den slutliga Q# koden bör se ut så här:
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) {
set resultArray w/= i <- M(qs[i]);
}
Message("After measurement: ");
DumpMachine();
ResetAll(qs);
Message("Post-QFT measurement results [qubit0, qubit1, qubit2]: ");
return resultArray;
}
Dricks
Kom ihåg att spara filen varje gång du introducerar en ändring av koden innan du kör den igen.
- Innan du kör programmet kontrollerar du i statusfältet längst ned i VS Code att profilen target är inställd på Q#: Obegränsad. Om du vill ändra profilen target väljer du profilen target i statusfältet och väljer Obegränsad på den nedrullningsbara menyn. Om profilen target inte är inställd på Obegränsad får du ett fel när du kör programmet.
- Om du vill köra programmet väljer du Kör Q# fil i listrutan uppspelningsikon längst upp till höger eller trycker på Ctrl+5. Programmet kör
Main()
åtgärden på standardsimulatorn. - Utdata
Message
ochDumpMachine
visas i felsökningskonsolen.
Dina utdata bör se ut ungefär så här:
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]
Dessa utdata illustrerar några olika saker:
- Om du jämför det returnerade resultatet med förmätningen
DumpMachine
illustrerar det uppenbarligen inte superpositionen efter QFT över bastillstånd. En mätning returnerar endast ett enskilt bastillstånd, med en sannolikhet som bestäms av amplituden för det tillståndet i systemets vågfunktion. - Från eftermätningen
DumpMachine
ser du att mätningen ändrar själva tillståndet och projicerar det från den första superpositionen över bastillstånd till det enskilda bastillståndet som motsvarar det uppmätta värdet.
Om du upprepar den här åtgärden många gånger ser du att resultatstatistiken börjar illustrera den lika viktade superpositionen av tillståndet efter QFT som ger upphov till ett slumpmässigt resultat på varje skott. Men förutom att vara ineffektiv och fortfarande ofullkomlig, skulle detta ändå bara reproducera de relativa amplituderna i bastillstånden, inte de relativa faserna mellan dem. Det senare är inte ett problem i det här exemplet, men du skulle se relativa faser visas om du får mer komplexa indata till QFT än $\ket{000}$.
Använda åtgärderna Q# för att förenkla QFT-kretsen
Som nämnts i inledningen vilar mycket av Q#"makt i det faktum att det gör att du kan abstrakta bort oron för att hantera enskilda kvantbitar.
Om du vill utveckla fullskalig, tillämplig kvantprogram, skulle det bara göra dig långsammare att oroa dig för om en H
åtgärd utförs före eller efter en viss rotation. Azure Quantum tillhandahåller åtgärden ApplyQFT
som du kan använda och tillämpa för valfritt antal kvantbitar.
Ersätt allt från den första
H
åtgärden till åtgärdenSWAP
, inklusive, med:ApplyQFT(qs);
Koden bör nu se ut så här
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) { set resultArray w/= i <- M(qs[i]); } Message("After measurement: "); DumpMachine(); ResetAll(qs); Message("Post-QFT measurement results [qubit0, qubit1, qubit2]: "); return resultArray; }
Kör programmet Q# igen och observera att utdata är samma som tidigare.
Om du vill se den verkliga fördelen med att använda Q# åtgärder ändrar du antalet kvantbitar till något annat än
3
:
mutable resultArray = [Zero, size = 4];
use qs = Qubit[4];
//...
Du kan därför använda rätt QFT för ett visst antal kvantbitar, utan att behöva oroa dig för att lägga till nya H
åtgärder och rotationer på varje kvantbit.
Relaterat innehåll
Utforska andra Q# självstudier:
- Slumptalsgenerator för kvant visar hur du skriver ett Q# program som genererar slumpmässiga tal av kvantbitar i superposition.
- Grover sökalgoritm visar hur du skriver ett Q# program som använder Grover sökalgoritm.
- Kvantsammanflätning visar hur du skriver ett Q# program som manipulerar och mäter kvantbitar och visar effekterna av superposition och sammanflätning.
- Quantum Katas är självstudier och programmeringsövningar som syftar till att lära ut elementen i kvantberäkning och Q# programmering på samma gång.