Hyppää sisältöön

Docs CSC now features an automatic Finnish translation. Click here for more information.

Warning!

Puhti and Mahti are being decommissioned in stages, and their storage areas will become fully unavailable from 15 October 2026. Clean up unnecessary files and move any data you need to keep by 31 August 2026. See the Roihu data migration guide for instructions on transferring your data to Roihu.

Puhti computing services have been decommissioned and no new jobs are accepted or executed on its compute nodes. Puhti login nodes and storage services are planned to remain available until 15 October 2026.

Q20-palvelu MyCSC:ssä

Q20-palvelussa on tällä hetkellä joitakin ongelmia projekteille, joilla on Q20-resursseja. Jos et löydä Aalto-Q20-palvelua tai kohtaat muita ongelmia, ota yhteyttä CSC:n asiakastukeen osoitteessa servicedesk@csc.fi.

Ensimmäisen kvanttilaskentatyön ajaminen kvanttitietokoneilla LUMIn kautta

Jos olet hakenut projektia, 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 näyttää tarkalleen, miten se tehdään. Ainoa tieto, jonka tarvitset, on projektinumerosi!

Ympäristön määrittäminen

Ensimmäinen vaihe sen jälkeen, kun olet kirjautunut LUMIin (komennolla ssh lumi terminaalissasi), on ympäristön määrittäminen. Oletusympäristö ensimmäisellä kirjautumiskerralla LUMIin ei tarjoa tarvittavia työkaluja kvanttitöiden lähettämiseen, joten 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.

module use /appl/local/quantum/modulefiles

Vaihtoehtoisesti voit saavuttaa saman tuloksen lataamalla Local-quantum-moduulin.

module load Local-quantum

Tämän jälkeen voit nähdä saatavilla olevien modulejen luettelon komennolla module avail. Kvanttimoduulien pitäisi olla listan kärjessä! Tässä läpikäynnissä käytetään Qiskitiä, joten seuraava vaihe on ladata moduuli nykyiseen ympäristöömme komennolla

module load fiqci-vtt-qiskit

Ensimmäisen kvanttiohjelman luominen

Seuraava vaihe on luoda kvanttipiirisi! Tässä luodaan yksinkertainen Bellin tila kahden kubitin välille, mikä havainnollistaa niiden 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 korvaamalla xxx projektinumerollasi.

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 osaat, 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. Myös ajokertojen määrä eli shots määritellään tässä. Shots tarkoittaa sitä, kuinka monta kertaa kvanttipiiri suoritetaan. Teemme näin, koska kvanttitietokoneet ovat probabilistisia koneita, ja toistamalla kokeen monta kertaa voimme päästä lähelle determinististä tulosta, jotta voimme tehdä johtopäätöksiä. Hyvä määrä shots-arvolle ensimmäisessä kvanttilaskentatyössäsi on shots = 1000. Shots-arvon 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! Halutessasi 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. Huomaa, että Aalto Q20:n provider-nimi on radiance20 ja VTT Q50:n q50. Q20_CORTEX_URL on päätepiste Q20:een, kun taas Q50_CORTEX_URL on päätepiste Q50:een. Tämä ympäristömuuttuja asetetaan automaattisesti, kun lataat minkä tahansa kvanttilaskentamoduulin, kuten fiqci-vtt-qiskit-moduulin.

# Accessing Q20

Q20_CORTEX_URL = os.getenv('Q20_CORTEX_URL')
provider_q20 = IQMProvider(Q20_CORTEX_URL)
backend_q20 = provider_q20.get_backend()
# Accessing Q50

Q50_CORTEX_URL = os.getenv('Q50_CORTEX_URL')
provider_q50 = IQMProvider(Q50_CORTEX_URL, quantum_computer="q50")
backend_q50 = provider_q50.get_backend()

Piirin transpilointi

Tässä seuraavassa vaiheessa juuri luomasi kvanttipiiri hajotetaan (transpiloidaan) kantaporteikseen. Nämä kantaportit ovat varsinaiset kvanttiportit kvanttitietokoneella. Hajotusprosessissa yllä olevat Hadamard- ja controlled-x-portit muunnetaan muotoon, joka voidaan fyysisesti ajaa kvanttitietokoneella. Q20:lle 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

circuit_decomposed = transpile(circuit, backend=backend)
Voit myös tulostaa piirisi kuten aiemmin komennolla 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.

qubit_mapping = {
                qreg[0]: 0,
                qreg[1]: 3,
            }

Esimerkiksi tässä kartoitamme kvanttirekisterin ensimmäisen kubitin Q20:n ensimmäiseen kubittiin, QB1:een, joka sijaitsee nollannessa paikassa Qiskitin nollaindeksoinnin vuoksi. Toinen kubitti kartoitetaan sitten QB4:ään. Sama prosessi voidaan soveltaa myös muihin kvanttitietokoneisiin, esimerkiksi Q50:een.

Q20's node mapping

Piiriimme toteuttamamme kahden kubitin Controlled-X-portti on tällä hetkellä kvanttirekisterimme kahdesta kubitista toisessa, qreg[1]:ssä. Q20:n topologian vuoksi tämä täytyy kartoittaa Q20:n QB4:ään. Yhden kubitin Hadamard-portti voidaan kartoittaa mihin tahansa QB4:ään kytkettyyn kubittiin. Näitä ovat QB1, QB3, QB5 ja QB9; 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 transpiloida piirin käyttäen määritettyä kubittikartoitusta, voit tehdä seuraavasti:

circuit_decomposed = transpile(circuit, backend=backend, initial_layout=qubit_mapping)

Työn lähettäminen

Nyt voimme ajaa kvanttityömme!

job = backend.run(circuit_decomposed, shots=shots)

Työn tilan tarkastelu

Voit tarkastella työsi tilaa komennolla

job.status()

Tulokset

Ennen lähettämistä meidän täytyy varmistaa, että voimme saada tuloksia! Kvanttityö palauttaa niin sanotut counts-tulokset. Counts ovat niiden tulosten kertymä, jotka saadaan 1000 ajokerrasta QPU:lla. Jokaisella kerralla, kun piiri lähetetään suoritettavaksi, palautetaan binäärinen tila, joka lisätään 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 % counts-arvoista 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 mittauksia, joissa tilat ovat |01> ja |10>.

Tulostaaksesi tulokset lisää:

counts = job.result().get_counts()
print(counts)

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äajonhallinnan kautta. Kvanttitietokoneiden (Q20, Q50) käyttö on mahdollista mistä tahansa LUMI-partitiosta. Samassa hakemistossa, johon olet tallentanut kvanttiohjelmasi, voit lähettää työn SLURMille seuraavasti:

# Using Q20

module use /appl/local/quantum/modulefiles
module --ignore_cache load "fiqci-vtt-qiskit"
export DEVICES=("radiance20")
srun --account project_xxx -t 00:15:00 -c 1 -n 1 --partition q_fiqci bash -c "source $RUN_SETUP && python -u first_quantum_job.py"
# Using Q50

module use /appl/local/quantum/modulefiles
module --ignore_cache load "fiqci-vtt-qiskit"
export DEVICES=("Q50")
srun --account project_xxx -t 00:15:00 -c 1 -n 1 --partition q_fiqci bash -c "source $RUN_SETUP && python -u first_quantum_job.py"

Muista lisätä oma projektitilisi!

Tämä lähettää työn interaktiivisesti, mikä tarkoittaa, että tuloste tulostetaan suoraan terminaalin näytölle. Halutessasi voit lähettää työn myös komennolla sbatch käyttäen tätä runkoeräskriptiä. 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

export DEVICES=("radiance20")

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än voi lähettää komennolla sbatch batch_script.sh samassa hakemistossa kuin Python-tiedostosi. SLURM-jonossa olevia töitä voi seurata komennolla squeue -u username, ja työn valmistuttua tulokset löytyvät tiedostosta quantumjob.oxxxxx. Tämän voi tulostaa terminaaliin komennolla cat. Jotta voit ajaa työn Q20:llä tai Q50:llä, sinun täytyy määrittää tarvitsemasi laitteet. Tässä radiance20 tarkoittaa Aalto Q20:tä ja Q50 tarkoittaa VTT Q50:tä.

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())

Q20_CORTEX_URL = os.getenv('Q20_CORTEX_URL')

provider_q20 = IQMProvider(Q20_CORTEX_URL)
backend_q20 = provider_q20.get_backend()

# Retrieving backend information
# print(f'Native operations: {backend_q20.operation_names}')
# print(f'Number of qubits: {backend_q20.num_qubits}')
# print(f'Coupling map: {backend_q20.coupling_map}')

transpiled_circuit = transpile(circuit, backend_q20)

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)

Suomenkielinen tekoälykäännös

Sisällössä voi esiintyä virheellistä tietoa tekoälykäännöksestä johtuen.

Klikkaa tästä antaaksesi palautetta