Come inviare un circuito con Qiskit ad Azure Quantum

Informazioni su come inviare un circuito quantistico Qiskit usando il azure-quantumPython pacchetto. È possibile inviare circuiti Qiskit ad Azure Quantum usando il notebook di Azure Quantum, che ha un pacchetto predefinito azure-quantumPython o dal computer locale.

Per altre informazioni, vedere Circuiti quantistici.

Nota

Microsoft Quantum Development Kit (QDK classico) non sarà più supportato dopo il 30 giugno 2024. Se si è uno sviluppatore QDK esistente, è consigliabile passare al nuovo Kit di sviluppo quantistico di Azure (QDK moderno) per continuare a sviluppare soluzioni quantistiche. Per altre informazioni, vedere Eseguire la migrazione del codice Q# al QDK moderno.

Prerequisiti

Per informazioni dettagliate sull'installazione, vedere Installazione del QDK moderno in VS Code.

  • Un'area di lavoro di Azure Quantum nella sottoscrizione di Azure. Per creare un'area di lavoro, vedere Creare un'area di lavoro di Azure Quantum.

  • Ambiente Python con Python e Pip installato.

  • VS Code con le estensioni Azure Quantum Development Kit, Pythone Jupyter installate.

  • Il pacchetto Azure Quantum azure-quantum con il tag [qiskit] e i qsharp pacchetti e.ipykernel

    python -m pip install --upgrade azure-quantum[qiskit] qsharp ipykernel 
    

    Nota

    Se il kernel ipykernel Jupyter Python non viene rilevato, VS Code richiederà di installarlo.

Creare una nuova Jupyter Notebook

  1. In VS Code selezionare Visualizza > riquadro comandi e selezionare Crea: Nuovo Jupyter Notebook.
  2. In alto a destra VS Code rileverà e visualizzerà la versione di Python e l'ambiente virtuale Python selezionato per il notebook. Se sono presenti più Python ambienti, potrebbe essere necessario selezionare un kernel usando la selezione kernel in alto a destra. Se non è stato rilevato alcun ambiente, vedere Jupyter Notebooks in VS Code per informazioni sulla configurazione.

Caricare le importazioni necessarie

Nella prima cella del notebook eseguire il codice seguente per caricare le importazioni necessarie:

import azure.quantum
from qiskit import QuantumCircuit
from qiskit.visualization import plot_histogram
from azure.quantum.qiskit import AzureQuantumProvider

Connessione al servizio Azure Quantum

Per connettersi al servizio Azure Quantum, è necessario l'ID risorsa e il percorso dell'area di lavoro Azure Quantum. Accedere all'account Azure, https://portal.azure.com, passare all'area di lavoro di Azure Quantum e copiare i valori dall'intestazione.

Come recuperare l'ID risorsa e la posizione da un'area di lavoro di Azure Quantum

Aggiungere una nuova cella e usare le informazioni sull'account per creare Workspace e AzureQuantumProvider oggetti per connettersi all'area di lavoro di Azure Quantum.

workspace = Workspace(  
    resource_id = "", # Add the resourceID of your workspace
    location = "" # Add the location of your workspace (for example "westus")
    )

provider = AzureQuantumProvider(workspace)

Elencare tutti i back-end

È ora possibile stampare tutti i back-end di calcolo quantistico disponibili nell'area di lavoro:

print("This workspace's targets:")
for backend in provider.backends():
    print("- " + backend.name())
This workspace's targets:
- ionq.qpu
- ionq.qpu.aria-1
- ionq.simulator
- microsoft.estimator
- quantinuum.hqs-lt-s1
- quantinuum.hqs-lt-s1-apival
- quantinuum.hqs-lt-s2
- quantinuum.hqs-lt-s2-apival
- quantinuum.hqs-lt-s1-sim
- quantinuum.hqs-lt-s2-sim
- quantinuum.qpu.h1-1
- quantinuum.sim.h1-1sc
- quantinuum.sim.h1-1e
- rigetti.sim.qvm
- rigetti.qpu.ankaa-2

Eseguire un circuito semplice

Creare prima di tutto un circuito Qiskit semplice da eseguire.

# Create a Quantum Circuit acting on the q register
circuit = QuantumCircuit(3, 3)
circuit.name = "Qiskit Sample - 3-qubit GHZ circuit"
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.measure([0,1,2], [0, 1, 2])

# Print out the circuit
circuit.draw()
     ┌───┐          ┌─┐      
q_0: ┤ H ├──■───────┤M├──────
     └───┘┌─┴─┐     └╥┘┌─┐   
q_1: ─────┤ X ├──■───╫─┤M├───
          └───┘┌─┴─┐ ║ └╥┘┌─┐
q_2: ──────────┤ X ├─╫──╫─┤M├
               └───┘ ║  ║ └╥┘
c: 3/════════════════╩══╩══╩═
                     0  1  2 

Selezionare un target oggetto per eseguire il programma

Eseguire nel simulatore IonQ

Prima di eseguire su hardware reale, è possibile testare il circuito nel simulatore. Usare get_backend per creare un Backend oggetto per connettersi al back-end del simulatore IonQ:

simulator_backend = provider.get_backend("ionq.simulator")

I back-end IonQ supportano i gate da un gateset definito, che vengono compilati per essere eseguiti in modo ottimale nell'hardware. Se il circuito contiene porte che non sono presenti in questo elenco, è necessario traspilare nell'oggetto supportato usando la transpile funzione fornita gateset da Qiskit:

from qiskit import transpile
circuit = transpile(circuit, simulator_backend)

La funzione transpile restituisce un nuovo oggetto circuito in cui i cancelli vengono decomposti in cancelli supportati nel back-end specificato.

È ora possibile eseguire il programma tramite il servizio Azure Quantum e ottenere il risultato. La cella seguente invia un processo che esegue il circuito con 100 scatti:

job = simulator_backend.run(circuit, shots=100)
job_id = job.id()
print("Job id", job_id)
Job id 00000000-0000-0000-0000-000000000000

Per attendere il completamento del processo e restituire i risultati, eseguire:

result = job.result()
print(result)
Result(backend_name='ionq.simulator', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='00000000-0000-0000-0000-000000000000', success=True, results=[ExperimentResult(shots=100, success=True, meas_level=2, data=ExperimentResultData(counts={'000': 50, '111': 50}, probabilities={'000': 0.5, '111': 0.5}), header=QobjExperimentHeader(meas_map='[0, 1, 2]', name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits='3', qiskit='True'))])

Poiché il risultato è un oggetto nativo del pacchetto Qiskit, è possibile usare result.get_countse plot_histogram di Qiskit per visualizzare i risultati. Per assicurarsi che tutte le etichette di stringa di bit possibili siano rappresentate, aggiungerle a counts.

counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
{'000': 50, '001': 0, '010': 0, '011': 0, '100': 0, '101': 0, '110': 0, '111': 50}

Risultato del circuito Qiskit nel simulatore IonQ

Stimare il costo del processo

Prima di eseguire un processo nella QPU, è possibile stimare la quantità di costi da eseguire. Per stimare il costo dell'esecuzione di un processo nella QPU, è possibile usare il metodo estimate_cost:

backend = provider.get_backend("ionq.qpu")
cost = backend.estimate_cost(circuit, shots=1024)

print(f"Estimated cost: {cost.estimated_total}")

In questo modo viene stampato il costo stimato in USD.

Per i dettagli più aggiornati sui prezzi, vedere i prezzi di IonQ oppure trovare l'area di lavoro e visualizzare le opzioni relative ai prezzi nella scheda "Provider" dell'area di lavoro tramite: aka.ms/aq/myworkspaces.

Esecuzione nella QPU di IonQ

Per connettersi all'hardware target"ionq.qpu"get_backend reale (un'unità del processore quantistico)), specificare semplicemente il nome del metodo:

qpu_backend = provider.get_backend("ionq.qpu")

Inviare il circuito da eseguire in Azure Quantum, ottenere i risultati ed eseguire plot_histogram per tracciare i risultati.

Nota

Il tempo necessario per eseguire un circuito nella QPU può variare a seconda dei tempi di coda correnti.

# Submit the circuit to run on Azure Quantum
job = qpu_backend.run(circuit, shots=1024)
job_id = job.id()
print("Job id", job_id)

# Get the job results (this method waits for the Job to complete):
result = job.result()
print(result)
counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
Job id 00000000-0000-0000-0000-000000000000
Job Status: job has successfully run
Result(backend_name='ionq.simulator', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='00000000-0000-0000-0000-000000000000', success=True, results=[ExperimentResult(shots=1024, success=True, meas_level=2, data=ExperimentResultData(counts={'0': 505, '1': 6, '2': 1, '3': 1, '4': 1, '5': 10, '6': 11, '7': 488}, probabilities={'0': 0.4932, '1': 0.0059, '2': 0.001, '3': 0.001, '4': 0.001, '5': 0.0098, '6': 0.0117, '7': 0.4766}), header=QobjExperimentHeader(name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits='3', qiskit='True'))])
{'000': 505, '001': 6, '010': 1, '011': 1, '100': 1, '101': 10, '110': 11, '111': 488}

Risultato del circuito Qiskit su IonQ QPU

Importante

L'invio di più circuiti in un singolo processo non è attualmente supportato. Come soluzione alternativa è possibile chiamare il backend.run metodo per inviare ogni circuito in modo asincrono, quindi recuperare i risultati di ogni processo. Ad esempio:

jobs = []
for circuit in circuits:
    jobs.append(backend.run(circuit, shots=N))

results = []
for job in jobs:
    results.append(job.result())

Prerequisiti

Creare un nuovo notebook nell'area di lavoro

  1. Accedere al portale di Azure e selezionare l'area di lavoro creata nel passaggio precedente.
  2. A sinistra selezionare Notebook.
  3. Fare clic su Notebook personali e quindi su Aggiungi nuovo.
  4. Digitare un nome per il file, ad esempio Qiskit.ipynb, e fare clic su Crea file.

Quando si apre un nuovo notebook, il codice per la prima cella viene creato automaticamente, in base alle informazioni relative alla sottoscrizione e all'area di lavoro.

from azure.quantum import Workspace
workspace = Workspace ( 
    resource_id = "", # Add your resource_id 
    location = ""  # Add your workspace location (for example, "westus") 
)

Nota

Se non diversamente specificato, è necessario eseguire ogni cella in ordine durante la creazione per evitare problemi di compilazione.

Fare clic sull'icona triangolare "play" a sinistra della cella per eseguire il codice.

Caricare le importazioni necessarie

Prima di tutto, è necessario importare alcuni moduli aggiuntivi.

Fare clic su + Codice per aggiungere una nuova cella, quindi aggiungere ed eseguire il codice seguente:

from qiskit import QuantumCircuit
from qiskit.visualization import plot_histogram
from azure.quantum.qiskit import AzureQuantumProvider

Connessione al servizio Azure Quantum

Creare quindi un AzureQuantumProvider oggetto usando l'oggetto Workspace della cella precedente per connettersi all'area di lavoro di Azure Quantum. Aggiungere una nuova cella con il codice seguente:

provider = AzureQuantumProvider(workspace)

Definire un circuito semplice

In una nuova cella creare un oggetto circuit. Questo esempio è un semplice generatore quantistico di bit casuali. Aggiungere il codice seguente per definire e visualizzare il circuito:

# Create a Quantum Circuit acting on the q register
circuit = QuantumCircuit(3, 3)
circuit.name = "Qiskit Sample - 3-qubit GHZ circuit"
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.measure([0, 1, 2], [0, 1, 2])

# Print out the circuit
circuit.draw()
     ┌───┐          ┌─┐      
q_0: ┤ H ├──■───────┤M├──────
     └───┘┌─┴─┐     └╥┘┌─┐   
q_1: ─────┤ X ├──■───╫─┤M├───
          └───┘┌─┴─┐ ║ └╥┘┌─┐
q_2: ──────────┤ X ├─╫──╫─┤M├
               └───┘ ║  ║ └╥┘
c: 3/════════════════╩══╩══╩═
                     0  1  2 

Elenca tutto targets

È ora possibile visualizzare tutti i back-end di calcolo targetsquantistico o disponibili nell'area di lavoro. Aggiungere una nuova cella ed eseguire la riga seguente:

print("This workspace's targets:")
for backend in provider.backends():
    print("- " + backend.name())
This workspace's targets:
- ionq.qpu
- ionq.simulator
- ionq.qpu.aria-1
- microsoft.estimator
- quantinuum.qpu.h1-1
- quantinuum.sim.h1-1sc
- quantinuum.sim.h1-1e
- rigetti.sim.qvm
- rigetti.qpu.ankaa-2

Selezionare un target oggetto per eseguire il programma

Per controllare il codice prima di eseguire l'hardware quantistico effettivo, è possibile usare il simulatore quantistico IonQ, ionq.simulator.

Aggiungere una nuova cella e creare un oggetto per rappresentare il simulatore quantistico targetIonQ :

# Get IonQ quantum simulator target:
simulator_backend = provider.get_backend("ionq.simulator")

Eseguire nel simulatore IonQ

Per eseguire il circuito nel simulatore, aggiungere il codice seguente. In questo esempio viene usato il run metodo di target per inviare il processo e quindi viene monitorato lo stato del processo.

# Submit the circuit to run on Azure Quantum
job = simulator_backend.run(circuit, shots=100)
job_id = job.id()
print("Job id", job_id)

Quando il processo viene eseguito correttamente, ottenere i risultati del processo e visualizzarli:

# Get the job results:
result = job.result()
print(result)
Result(backend_name='ionq.simulator', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='7d909574-98d4-11ec-b382-00155d957f5d', success=True, results=[ExperimentResult(shots=100, success=True, meas_level=2, data=ExperimentResultData(counts=defaultdict(<class 'int'>, {'000': 50, '111': 50}), probabilities=defaultdict(<class 'int'>, {'000': 0.5, '111': 0.5})), header=QobjExperimentHeader(meas_map='[0, 1, 2]', name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits='3', qiskit='True'))])

Poiché questo tipo result è un oggetto nativo del pacchetto Qiskit, è possibile usare result.get_counts e plot_histogram di Qiskit per visualizzare i risultati. Per assicurarsi che tutte le etichette di stringa di bit possibili siano rappresentate, aggiungerle a counts.

counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
{'000': 50, '001': 0, '010': 0, '011': 0, '100': 0, '101': 0, '110': 0, '111': 50}

Risultato del circuito Qiskit nel simulatore IonQ

Stimare il costo del processo

Prima di eseguire un processo su hardware quantistico effettivo o su un'unità di elaborazione quantistica (QPU), è possibile stimare il costo di esecuzione.

Per prima cosa, ottenere di nuovo l'elenco dei provider disponibili:

print("This workspace's targets:")
for backend in provider.backends():
    print("- " + backend.name())
This workspace's targets:
- ionq.qpu
- ionq.simulator
- ionq.qpu.aria-1
- microsoft.estimator
- quantinuum.qpu.h1-1
- quantinuum.sim.h1-1sc
- quantinuum.sim.h1-1e
- rigetti.sim.qvm
- rigetti.qpu.ankaa-2

Creare quindi un oggetto per rappresentare il computer quantistico IonQ:

qpu_backend = provider.get_backend("ionq.qpu")

Per stimare il costo dell'esecuzione di un processo nella QPU, aggiungere ed eseguire una nuova cella usando il estimate_cost metodo di target:

cost = qpu_backend.estimate_cost(circuit, shots=100)

print(f"Estimated cost: {cost.estimated_total}")

In questo modo si visualizza il costo stimato in USD.

Per i dettagli sui prezzi più correnti, vedere Prezzi di IonQ o trovare la propria area di lavoro e visualizzare le opzioni relative ai prezzi nel pannello Provider dell'area di lavoro.

Esecuzione nella QPU di IonQ

Dopo aver eseguito correttamente il processo nel simulatore IonQ e aver stimato il costo della QPU, è il momento di eseguire il circuito sull'hardware.

Nota

Il tempo necessario per eseguire un circuito nella QPU varia a seconda dei tempi di coda correnti. È possibile visualizzare il tempo medio della coda per un target oggetto selezionando il pannello Provider dell'area di lavoro.

Usare lo stesso metodo run e le stesse operazioni usati in precedenza con il validator dell'API per inviare e monitorare il processo:

# Submit the circuit to run on Azure Quantum
job = qpu_backend.run(circuit, shots=1024)
job_id = job.id()
print("Job id", job_id)

Al termine del processo, ottenere i risultati del processo come prima e visualizzarli in un grafico:

result = job.result()
print(result)
counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
Job id 910b5ac8-98cd-11ec-b3ba-00155d5528cf
Job Status: job has successfully run
Result(backend_name='ionq.simulator', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='Job id 54e8c740-98d9-11ec-b382-00155d957f5d', success=True, results=[ExperimentResult(shots=1024, success=True, meas_level=2, data=ExperimentResultData(counts={'0': 505, '1': 6, '2': 1, '3': 1, '4': 1, '5': 10, '6': 11, '7': 488}, probabilities={'0': 0.4932, '1': 0.0059, '2': 0.001, '3': 0.001, '4': 0.001, '5': 0.0098, '6': 0.0117, '7': 0.4766}), header=QobjExperimentHeader(name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits='3', qiskit='True'))])
{'000': 505, '001': 6, '010': 1, '011': 1, '100': 1, '101': 10, '110': 11, '111': 488}

Risultato del circuito Qiskit in IonQ QPU

Importante

L'invio di più circuiti in un singolo processo non è attualmente supportato. Come soluzione alternativa è possibile chiamare il backend.run metodo per inviare ogni circuito in modo asincrono, quindi recuperare i risultati di ogni processo. Ad esempio:

jobs = []
for circuit in circuits:
    jobs.append(backend.run(circuit, shots=N))

results = []
for job in jobs:
    results.append(job.result())

Passaggi successivi