U prvim dvama nastavcima serijala o kvantnim računalima objasnili smo:
- osnovne principe rada takvih računala i primjer postojećega kvantnog računala
- instalaciju Microsoftovog alata Microsoft QDK namijenjenoga simulaciji kvantnoga računala na „klasičnom“ digitalnom računalu.
Budući da je drugi nastavak završen instalacijom MQDK paketa na računalo i osnovnom provjerom njegovoga rada (prikazom standardne pozdravne poruke korisniku), danas ćemo otići korak dalje i predstaviti prve prave „kvantne“ primjere programskoga kôda. Na taj način konačno će postati uočljiva razlika između programiranja digitalnog i kvantnog računala.
Glavni dio programskoga kôda u alatu MQDK uvijek se piše u posebnom, kvantno orijentiranom programskom jeziku Q#, dok se „pomoćni“ dijelovi pripremaju u jezicima C# ili Python.
Generiranje slučajnoga broja
Generiranje i korištenje slučajnoga broja jest nešto što se vrlo često koristi u različitim analizama i simulacijama na računalu. Kako bi takav broj zaista bio nešto slučajno, tijekom vremena razvijeni su (i još uvijek se razvijaju) različiti algoritmi za generiranje slučajnoga broja na digitalnom računalu.
Naravno, slučajni brojevi potrebni su i kod različitih vrsti obrada na kvantnim računalima, ali je situacija oko njihovog generiranja ovdje potpuno drugačija. Nastajanje slučajnoga broja u samoj je osnovi korištenja kvantnih računala, što će prikazati i sljedeći primjer.
namespace RandomTest {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Measurement;
operation SampleQuantumRandomNumberGenerator() : Result {
using (q = Qubit()) { // Allocate a qubit.
H(q); // Put the qubit to superposition.
// It now has a 50% chance of being 0 or 1.
return MResetZ(q); // Measure the qubit value.
}
}
operation SampleRandomNumberInRange(max : Int) : Int {
mutable bits = new Result[0];
for (idxBit in 1..BitSizeI(max)) {
set bits += [SampleQuantumRandomNumberGenerator()];
}
let sample = ResultArrayAsInt(bits);
return sample > max
? SampleRandomNumberInRange(max)
| sample;
}
@EntryPoint()
operation SampleRandomNumber() : Int {
let max = 50;
Message($"Sampling a random number between 0 and {max}: ");
return SampleRandomNumberInRange(max);
}
}
Prethodni primjer sastoji se od triju funkcija:
- SampleQuantumRandomNumberGenerator
- SampleRandomNumberInRange
- SampleRandomNumber.
Prva funkcija SampleQuantumRandomNumberGenerator demonstira jednu od ključnih razlika u funkcioniranju kvantnih računala. Nakon deklaracije jednog qubita postavljamo ga u vrijednost superpozicije. Prema načinu na koji djeluju kvantna računala rezultat izvođenja prethodne operacije ima 50 % vjerojatnosti da bude vrijednost 0, odnosno 50 % vjerojatnosti da bude vrijednost 1. Upravo to nam je potrebno za slučajno generiranje vrijednosti 0 ili 1.
Slika 1. Primjer generiranja slučajnoga broja na kvantnom računalu pomoću programskoga jezika Q#
Budući da su stvarnim primjerima potrebne vrijednosti slučajnih brojeva izvan osnovnog raspona binarnih vrijednosti, druga po redu funkcija SampleRandomNumberInRange koristi se prije spomenutom osnovnom funkcijom za pripremu tražene vrijednosti u zadanom rasponu od 0 do zadanog broja. Rezultat se priprema kao polje bitova, a svaku slučajnu vrijednost pojedinoga bita generira prva funkcija.
Na kraju, treća funkcija SampleRandomNumber predstavlja glavni dio programa zadužen za poziv funkcije za generiranje slučajnoga broja u zadanom rasponu vrijednosti te prikazuje dobivenu vrijednost slučajnoga broja.
Tijekom korištenja ovim primjerom ne treba zaboraviti kako rezultati prve funkcije nisu u stvarnosti nastali na kvantnim principima, jer u slučaju korištenja alatom MQDK u stvari nije na raspolaganju pravi kvantni mehanizam za generiranje slučajnoga broja. Umjesto toga koristi se simulacijom djelovanja qubita na klasičnom digitalnom računalu. Ipak, na temelju primjera moguće je razumjeti koliko je generiranje slučajnoga broja jednostavno i pouzdano (u smislu dobivanja zaista slučajne vrijednosti) na pravom kvantnom računalu.
Drugi važan primjer čiju ćemo simulaciju demonstrirati u alatu MQDK predstavlja primjer „teleportacije“ vrijednosti između qubita. Pod kvantnom „teleportacijom“ podrazumijeva se prijenos kvantne informacije o stanju qubita između lokacija bez potrebe za stvarnim prijenosom fizičkih dijelova. Kao i u slučaju generiranja slučajnih vrijednosti ne treba zaboraviti da je ovdje ponovo riječ o simulaciji pravih fizičkih procesa na kvantnom računalu.
Slika 2. Primjer “teleportacije” u alatu MQDK
namespace Microsoft.Quantum.Samples.Teleportation {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Measurement;
//////////////////////////////////////////////////////////////////////////
// Introduction //////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Quantum teleportation provides a way of moving a quantum state from one
// location to another without having to move physical particle(s) along
// with it. This is done with the help of previously shared quantum
// entanglement between the sending and the receiving locations and
// classical communication.
//////////////////////////////////////////////////////////////////////////
// Teleportation /////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/// # Summary
/// Sends the state of one qubit to a target qubit by using
/// teleportation.
///
/// Notice that after calling Teleport, the state of `msg` is
/// collapsed.
///
/// # Input
/// ## msg
/// A qubit whose state we wish to send.
/// ## target
/// A qubit initially in the |0〉 state that we want to send
/// the state of msg to.
operation Teleport (msg : Qubit, target : Qubit) : Unit {
using (register = Qubit()) {
// Create some entanglement that we can use to send our message.
H(register);
CNOT(register, target);
// Encode the message into the entangled pair.
CNOT(msg, register);
H(msg);
// Measure the qubits to extract the classical data we need to
// decode the message by applying the corrections on
// the target qubit accordingly.
// We use MResetZ from the Microsoft.Quantum.Measurement namespace
// to reset our qubits as we go.
if (MResetZ(msg) == One) { Z(target); }
// We can also use library functions such as IsResultOne to write
// out correction steps. This is especially helpful when composing
// conditionals with other functions and operations, or with partial
// application.
if (IsResultOne(MResetZ(register))) { X(target); }
}
}
// One can use quantum teleportation circuit to send an unobserved
// (unknown) classical message from source qubit to target qubit
// by sending specific (known) classical information from source
// to target.
/// # Summary
/// Uses teleportation to send a classical message from one qubit
/// to another.
///
/// # Input
/// ## message
/// If `true`, the source qubit (`here`) is prepared in the
/// |1〉 state, otherwise the source qubit is prepared in |0〉.
///
/// ## Output
/// The result of a Z-basis measurement on the teleported qubit,
/// represented as a Bool.
operation TeleportClassicalMessage (message : Bool) : Bool {
// Ask for some qubits that we can use to teleport.
using ((msg, target) = (Qubit(), Qubit())) {
// Encode the message we want to send.
if (message) {
X(msg);
}
// Use the operation we defined above.
Teleport(msg, target);
// Check what message was sent.
return MResetZ(target) == One;
}
}
// One can also use quantum teleportation to send any quantum state
// without losing any information. The following sample shows
// how a randomly picked non-trivial state (|-> or |+>)
// gets moved from one qubit to another.
/// # Summary
/// Uses teleportation to send a randomly picked |-> or |+> state
/// to another.
operation TeleportRandomMessage () : Unit {
// Ask for some qubits that we can use to teleport.
using ((msg, target) = (Qubit(), Qubit())) {
PrepareRandomMessage(msg);
// Use the operation we defined above.
Teleport(msg, target);
// Report message received:
if (IsPlus(target)) { Message("Received |+>"); }
if (IsMinus(target)) { Message("Received |->"); }
// Reset all of the qubits that we used before releasing
// them.
Reset(msg);
Reset(target);
}
}
}
Osim prethodnog, glavnog dijela kôda zaduženoga za teleportaciju, koji je ponovo sastavljen od osnovne funkcije Teleport i „nadređenih“ funkcija TeleportClassicalMessage odnosno TeleportRandomMessage, primjer sadrži i nekoliko dodatnih funkcija kojim se koristi prethodni „glavni“ dio programskoga kôda. Taj pomoćni dio ima sljedeći oblik:
namespace Microsoft.Quantum.Samples.Teleportation {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Math;
/// # Summary
/// Sets the qubit's state to |+⟩.
operation SetToPlus(q: Qubit) : Unit {
Reset(q);
H(q);
}
/// # Summary
/// Sets the qubit's state to |−⟩.
operation SetToMinus(q: Qubit) : Unit {
Reset(q);
X(q);
H(q);
}
/// # Summary
/// Returns true if qubit is |+> (assumes qubit is either |+> or |->)
operation IsPlus(q: Qubit) : Bool {
return (Measure([PauliX], [q]) == Zero);
}
/// # Summary
/// Returns true if qubit is |-> (assumes qubit is either |+> or |->)
operation IsMinus(q: Qubit) : Bool {
return (Measure([PauliX], [q]) == One);
}
/// # Summary
/// Randomly prepares the qubit into |+> or |->
operation PrepareRandomMessage(q: Qubit) : Unit {
let choice = RandomInt(2);
if (choice == 0) {
Message("Sending |->");
SetToMinus(q);
} else {
Message("Sending |+>");
SetToPlus(q);
}
}
}
Na kraju, tu je i glavni te ujedno najkraći dio programa zadužen za prijenos osam poruka pomoću „teleportacije“, koji ima sljedeći oblik:
namespace Microsoft.Quantum.Samples.Teleportation {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
@EntryPoint()
operation RunProgram () : Unit {
for (idxRun in 1 .. 8) {
let sent = Random([0.5, 0.5]) == 0;
let received = TeleportClassicalMessage(sent);
Message($"Round {idxRun}: Sent {sent}, got {received}.");
Message(sent == received ? "Teleportation successful!" | "");
}
}
}
Rezultati izvođenja prikazani su u nastavku.
Round 1: Sent False, got False.
Teleportation successful!
Round 2: Sent False, got False.
Teleportation successful!
Round 3: Sent False, got False.
Teleportation successful!
Round 4: Sent True, got True.
Teleportation successful!
Round 5: Sent True, got True.
Teleportation successful!
Round 6: Sent False, got False.
Teleportation successful!
Round 7: Sent True, got True.
Teleportation successful!
Round 8: Sent False, got False.
Teleportation successful!
U ovom su slučaju „teleportacijom“ prenošene samo logičke vrijednosti, ali bi se uz odgovarajuće kodiranje polaznih podataka mogle prenijeti i drugačije vrijednosti, što se može koristiti u različitim područjima.