-
Ensimmäinen kvanttityö
Ensimmäisen kvanttilaskentatyön ajaminen kvanttitietokoneilla LUMIn kautta
Jos olet hakenut projektiin, tullut hyväksytyksi, määrittänyt SSH-avaimesi ja saanut pääsyn LUMIin, seuraava vaihe on ajaa ensimmäinen kvanttilaskentatyösi oikealla kvanttitietokoneella! Tämä opas kertoo tarkalleen, miten se tehdään. Ainoa asia, joka sinun tarvitsee tietää, on projektinumerosi!
Ympäristön määrittäminen
Ensimmäinen vaihe sen jälkeen, kun olet kirjautunut LUMIin (päätteellä komennolla ssh lumi), on ympäristön määrittäminen. Oletusympäristö ensimmäisellä kirjautumiskerralla LUMIin ei tarjoa tarvittavia työkaluja kvanttitehtävien lähettämiseen, joten käyttöön on luotu kvanttiohjelmistopino, joka asettaa oikeat Python-virtuaaliympäristöt ja oikeat ympäristömuuttujat. Tätä käytetään LUMIn LMOD-järjestelmän kautta moduleja käyttäen.
Jotta voit käyttää kvanttiohjelmistopinoa, sinun täytyy ensin ladata Quantum-moduulipuu.
Vaihtoehtoisesti voit saavuttaa saman tuloksen lataamalla Local-quantum-moduulin.
Tämän jälkeen voit nähdä saatavilla olevien modulien luettelon komennolla module avail. Kvanttimoduulien pitäisi näkyä ylimpänä! Tässä läpikäynnissä käytetään Qiskitiä, joten seuraava vaihe on ladata moduuli nykyiseen ympäristöömme komennolla
Ensimmäisen kvanttiohjelman luominen
Seuraava vaihe on luoda kvanttipiirisi! Tässä luodaan yksinkertainen Bellin tila kahden kubitin välille, mikä havainnollistaa niiden välistä lomittumista! Tähän käytämme Qiskitiä, mutta vaiheet ovat hyvin samankaltaiset myös Cirqissä. On hyvä käytäntö työskennellä projektisi scratch-hakemistossa, johon voit siirtyä komennolla cd /scratch/project_xxx lisäämällä oman projektinumerosi.
Vinkki!
Voit nähdä LUMI-työtilasi nopeasti komennolla
lumi-workspaces
Luodaan ensin Python-tiedosto komennolla nano first_quantum_job.py. Tässä käytämme nanoa, mutta jos olet tottunut siihen, voit käyttää myös vimiä tai emacsia. Tämä avaa nano-tekstieditorin; hyödylliset komennot näkyvät alareunassa, ja tallennus sekä poistuminen tapahtuvat näppäinyhdistelmällä CTRL-X + Y.
Kirjastojen tuominen
Tuodaan ensin oikeat Python-kirjastot.
import os
from qiskit import QuantumCircuit, QuantumRegister, transpile
from iqm.qiskit_iqm import IQMProvider
Piirin luominen
Kvanttipiiri luodaan määrittelemällä QuantumRegister, joka sisältää kubittimme ja klassiset bittimme. Koska tämä piiri tarvitsee vain 2 kubittia, luomme vain koon 2 QuantumRegisterin. Tässä määritellään myös shotien määrä. Shotien määrä tarkoittaa sitä, kuinka monta kertaa kvanttipiiri suoritetaan. Teemme tämän, koska kvanttitietokoneet ovat probabilistisia koneita, ja toistamalla kokeen monta kertaa voimme päästä lähelle determinististä tulosta, jotta voimme tehdä johtopäätöksiä. Hyvä shotien määrä ensimmäiseen kvanttityöhösi on shots = 1000. Shotien määrän kasvattaminen lisää tulostesi tarkkuutta.
shots = 1000 # Number of repetitions of the Quantum Circuit
qreg = QuantumRegister(2, "qB")
circuit = QuantumCircuit(qreg, name='Bell pair circuit')
Nyt lisäämme piiriin portteja. Tässä ensimmäiseen kubittiin eli kvanttirekisterin ensimmäiseen kubittiin lisätään Hadamard-portti. Sen jälkeen lisätään controlled-x-portti kahdella argumentilla, koska kyseessä on kahden kubitin portti.
circuit.h(qreg[0]) # Hadamard gate on the first qubit in the Quantum Register
circuit.cx(qreg[1], qreg[0]) # Controlled-X gate between the second qubit and first qubit
circuit.measure_all() # Measure all qubits in the Quantum Register.
Huomaa, että measure_all() luo oman ClassicalRegisterin!
Nyt piiri on luotu! Jos haluat, voit nähdä miltä piirisi näyttää lisäämällä print-lauseen print(circuit.draw()) ja ajamalla Python-skriptin nopeasti.
Taustajärjestelmän asettaminen
Ensin meidän täytyy asettaa provider ja backend. Provider on palvelu, joka tarjoaa rajapinnan kvanttitietokoneeseen, ja backend tarjoaa työkalut, joita tarvitaan kvanttityön lähettämiseen. HELMI_CORTEX_URL on päätepiste Helmeen (5 kubitin kone), kun taas Q50_CORTEX_URL on päätepiste Q50:een (50 kubitin kone). Tämä ympäristömuuttuja asetetaan automaattisesti, kun ladataan mikä tahansa kvanttilaskennan moduuli, kuten fiqci-vtt-qiskit-moduuli.
Piirin transpilointi
Tässä seuraavassa vaiheessa juuri luomasi kvanttipiiri hajotetaan (transpiloidaan) sen kantaporteiksi. Nämä kantaportit ovat varsinaiset kvanttiportit kvanttitietokoneella. Hajotusprosessi tarkoittaa sitä, että yllä olevat Hadamard- ja controlled-x-portit muunnetaan sellaiseen muotoon, joka voidaan fyysisesti ajaa kvanttitietokoneella. Helmelle ja Q50:lle kantaportit ovat lomittava controlled-z-portti ja yhden kubitin phased-rx-portti. Qiskitissä nämä on määritelty backendissä, ja ne voidaan tulostaa komennolla backend.operation_names. Lisätietoja määrityksistä on kohdassa Topologian yleiskuva.
print(circuit_decomposed.draw()) nähdäksesi, miltä se näyttää!
Valinnainen kubittikartoitus
Tämä on valinnainen vaihe, mutta siitä voi olla hyötyä, jos haluat saada kvanttitietokoneesta parhaan mahdollisen hyödyn irti. Tämä on Python-sanakirja, joka yksinkertaisesti kertoo, mitkä kvanttirekisterin kubitit tulee kartoittaa millekin fyysiselle kubitille.
Esimerkiksi tässä kartoitamme kvanttirekisterin ensimmäisen kubitin Helmen ensimmäiseen kubittiin, QB1:een, joka sijaitsee nollannessa kohdassa Qiskitin nollaindeksoinnin vuoksi. Toinen kubitti kartoitetaan sitten QB3:een. Tässä olemme hyödyntäneet Helmen topologiaa. Sama prosessi voidaan soveltaa muihin kvanttitietokoneisiin, esimerkiksi Q50:een.

Piiriimme toteuttamamme kahden kubitin Controlled-X-portti on tällä hetkellä kvanttirekisterimme toisessa kubitissa, qreg[1]. Helmen topologian vuoksi tämä täytyy kartoittaa Helmen QB3:een. Yhden kubitin Hadamard-portti voidaan kartoittaa mihin tahansa ulommista kubiteista, QB1, QB2, QB4, QB5; tässä valitsemme QB1:n.
Huomaa, että tämä vaihe on täysin valinnainen. transpile-funktion käyttö tekee kartoituksen automaattisesti backendiin tallennettujen tietojen perusteella. Kubittikartoituksen syöttäminen käsin antaa käyttäjälle vain enemmän hallintaa.
Jos haluat transpiloda piirin käyttäen määritettyä kubittikartoitusta, voit tehdä seuraavasti:
Työn lähettäminen
Nyt voimme ajaa kvanttityömme!
Työn tilan tarkastelu
Voit tarkastella työsi tilaa komennolla
Tulokset
Ennen lähettämistä meidän täytyy varmistaa, että voimme saada tuloksia! Kvanttityö palauttaa niin sanotut counts-arvot. Counts tarkoittaa niiden tulosten kertymää, jotka saadaan siitä 1000 kerrasta, kun piiri lähetetään QPU:lle. Joka kerta kun piiri lähetetään, palautetaan binäärinen tila, joka lisätään sitten laskuriin. Tässä tapauksessa, koska lähetämme 2 kubitin piirin, mahdollisia lopputiloja on 4: 00, 11, 01, 10. Odotettujen tulosten pitäisi olla, että noin 50 % countseista on tilassa 00 ja 50 % tilassa 11. Kubittien tilat ovat siis lomittuneet: jos yhden kubitin mitataan olevan tilassa |0>, myös toinen romahtaa välittömästi samaan tilaan, ja päinvastoin. Koska oikeat kvanttitietokoneet eivät ole täydellisiä, näet todennäköisesti myös joitakin mittauksia, joissa tilat ovat |01> ja |10>.
Tulosta tulokset lisäämällä:
Voit myös tulostaa koko job.result()-olion, joka sisältää kaikki tiedot työsi tuloksista.
Tallenna tiedostosi
Kun olet tehnyt ensimmäisen kvanttiohjelmasi, muista tallentaa! CTRL+X ja sitten Y tallentaa tiedoston.
Työn ajaminen LUMIn kautta
Jotta voit ajaa kvanttiohjelmasi LUMIssa, sinun täytyy lähettää työ LUMIn SLURM-eräajastimen kautta. Kvanttitietokoneiden (Helmi, Q50) käyttö tapahtuu q_fiqci-partitiolla. Samassa hakemistossa, johon olet tallentanut kvanttiohjelmasi, voit lähettää työn SLURMille seuraavasti:
Muista lisätä oma projektitilisi!
Tämä lähettää työn interaktiivisesti, mikä tarkoittaa, että tuloste kirjoitetaan suoraan päätenäyttöön. Halutessasi voit lähettää sen myös komennolla sbatch käyttäen tätä eräajoskriptin runkoa. Luo skripti batch_script.sh komennolla nano kuten aiemmin.
#!/bin/bash -l
#SBATCH --job-name=quantumjob # Job name
#SBATCH --output=quantumjob.o%j # Name of stdout output file
#SBATCH --error=quantumjob.e%j # Name of stderr error file
#SBATCH --partition=q_fiqci # Partition (queue) name
#SBATCH --ntasks=1 # One task (process)
#SBATCH --mem-per-cpu=2G # memory allocation
#SBATCH --cpus-per-task=1 # Number of cores (threads)
#SBATCH --time=00:05:00 # Run time (hh:mm:ss)
#SBATCH --account=project_xxx # Project for billing
module use /appl/local/quantum/modulefiles
module load fiqci-vtt-qiskit/17.8
export DEVICES=("Q5")
source $RUN_SETUP
python -u first_quantum_job.py
#!/bin/bash -l
#SBATCH --job-name=quantumjob # Job name
#SBATCH --output=quantumjob.o%j # Name of stdout output file
#SBATCH --error=quantumjob.e%j # Name of stderr error file
#SBATCH --partition=q_fiqci # Partition (queue) name
#SBATCH --ntasks=1 # One task (process)
#SBATCH --mem-per-cpu=2G # memory allocation
#SBATCH --cpus-per-task=1 # Number of cores (threads)
#SBATCH --time=00:05:00 # Run time (hh:mm:ss)
#SBATCH --account=project_xxx # Project for billing
module use /appl/local/quantum/modulefiles
module load fiqci-vtt-qiskit
export DEVICES=("Q50")
source $RUN_SETUP
python -u first_quantum_job.py
Tämä voidaan lähettää komennolla sbatch batch_script.sh samassa hakemistossa kuin Python-tiedostosi. SLURM-jonossa olevia töitä voidaan seurata komennolla squeue -u username, ja työn valmistuttua tulokset löytyvät tiedostosta quantumjob.oxxxxx. Tämä voidaan tulostaa päätteeseen komennolla cat.
Jotta voit ajaa työn Helmellä tai Q50:llä, sinun täytyy määrittää tarvitsemasi laitteet. Tässä Q5 tarkoittaa Helmeä ja Q50 tarkoittaa 50 kubitin konetta.
Onnittelut!
Onnittelut! Olet juuri ajanut ensimmäisen työsi kvanttitietokoneella.
Koko Python-skripti löytyy alta.
import os
from qiskit import QuantumCircuit, QuantumRegister, transpile
from iqm.qiskit_iqm import IQMProvider
shots = 1000
qreg = QuantumRegister(2, "QB")
circuit = QuantumCircuit(qreg, name='Bell pair circuit')
circuit.h(qreg[0])
circuit.cx(qreg[0], qreg[1])
circuit.measure_all()
# Uncomment if you wish to print the circuit
# print(circuit.draw())
HELMI_CORTEX_URL = os.getenv('HELMI_CORTEX_URL')
provider_helmi = IQMProvider(HELMI_CORTEX_URL)
backend_helmi = provider_helmi.get_backend()
# Retrieving backend information
# print(f'Native operations: {backend_helmi.operation_names}')
# print(f'Number of qubits: {backend_helmi.num_qubits}')
# print(f'Coupling map: {backend_helmi.coupling_map}')
transpiled_circuit = transpile(circuit, backend_helmi)
job = backend.run(transpiled_circuit, shots=shots)
result = job.result()
# You can retrieve the job at a later date with backend.retrieve_job(job_id)
# Uncomment the following lines to get more information about your submitted job
# print("Job ID: ", job.job_id())
# print(result.circuits)
# exp_result = result._get_experiment("circuit_name")
# print("Calibration Set ID: ", exp_result.calibration_set_id)
# print(result.parameters.qubit_mapping)
# print(result.parameters.shots)
counts = result.get_counts()
print(counts)
import os
from qiskit import QuantumCircuit, QuantumRegister, transpile
from iqm.qiskit_iqm import IQMProvider
shots = 1000
qreg = QuantumRegister(2, "QB")
circuit = QuantumCircuit(qreg, name='Bell pair circuit')
circuit.h(qreg[0])
circuit.cx(qreg[0], qreg[1])
circuit.measure_all()
# Uncomment if you wish to print the circuit
# print(circuit.draw())
Q50_CORTEX_URL = os.getenv('Q50_CORTEX_URL')
provider_q50 = IQMProvider(Q50_CORTEX_URL, quantum_computer="q50")
backend_q50 = provider_q50.get_backend()
# Retrieving backend information
# print(f'Native operations: {backend_q50.operation_names}')
# print(f'Number of qubits: {backend_q50.num_qubits}')
# print(f'Coupling map: {backend_q50.coupling_map}')
transpiled_circuit = transpile(circuit, backend_q50)
job = backend_q50.run(transpiled_circuit, shots=shots)
result = job.result()
# You can retrieve the job at a later date with backend.retrieve_job(job_id)
# Uncomment the following lines to get more information about your submitted job
# print("Job ID: ", job.job_id())
# print(result.circuits)
# exp_result = job.result()._get_experiment("circuit_name")
# print("Calibration Set ID: ", result.parameters.calibration_set_id)
# print(result.parameters.qubit_mapping)
# print(result.parameters.shots)
counts = result.get_counts()
print(counts)