Envío de un circuito con Qiskit a Azure Quantum

Obtenga información sobre cómo enviar un circuito cuántico qiskit mediante el azure-quantumPython paquete. Puede enviar circuitos Qiskit a Azure Quantum mediante el cuaderno de Azure Quantum, que tiene un paquete integrado azure-quantumPython o desde la máquina local.

Para más información, consulte Circuitos cuánticos.

Nota

El Kit de desarrollo de Microsoft Quantum (QDK clásico) ya no se admitirá después del 30 de junio de 2024. Si es un desarrollador de QDK existente, se recomienda realizar la transición al nuevo kit de desarrollo de Azure Quantum (QDK moderno) para seguir desarrollando soluciones cuánticas. Para obtener más información, consulte Migración del código de Q# al QDK moderno.

Requisitos previos

Para obtener más información sobre la instalación, consulte Instalación del QDK moderno en VS Code.

  • Un área de trabajo de Azure Quantum en la suscripción de Azure. Para crear un área de trabajo, consulte Creación de un área de trabajo de Azure Quantum.

  • Un Python entorno con Python y Pip instalado.

  • VS Code con el Kit de desarrollo de Azure Quantum, Pythony las extensiones de Jupyter instaladas.

  • El paquete de Azure Quantum azure-quantum con la etiqueta [qiskit] y los qsharp paquetes y ipykernel .

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

    Nota

    Si no se detecta el kernel ipykernel de JupyterPython, VS Code le pedirá que lo instale.

Crear un nuevo cuaderno de Jupyter Notebook

  1. En VS Code, seleccione Ver > paleta de comandos y seleccione Crear: Nuevo Jupyter Notebook.
  2. En la parte superior derecha, VS Code detectará y mostrará la versión de Python y el entorno virtual Python seleccionado para el cuaderno. Si tiene varios Python entornos, es posible que tenga que seleccionar un kernel mediante el selector de kernel en la parte superior derecha. Si no se detectó ningún entorno, consulte Jupyter Notebooks in VS Code (Cuadernos de Jupyter Notebook en VS Code ) para obtener información de configuración.

Carga de las importaciones necesarias

En la primera celda del cuaderno, ejecute el código siguiente para cargar las importaciones necesarias:

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

Conexión al servicio Azure Quantum

Para conectarse al servicio Azure Quantum, necesita el identificador de recurso y la ubicación del área de trabajo de Azure Quantum. Inicie sesión en su cuenta de Azure, https://portal.azure.com, vaya al área de trabajo de Azure Quantum y copie los valores del encabezado.

Cómo recuperar el identificador de recurso y la ubicación de un área de trabajo de Azure Quantum

Agregue una nueva celda y use la información de la cuenta para crear Workspace objetos y AzureQuantumProvider conectarse al área de trabajo de 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)

Enumeración de todos los back-end

Ahora puede imprimir todos los back-end de computación cuántica que están disponibles en el área de trabajo:

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

Ejecución de un circuito simple

En primer lugar, cree un circuito de Qiskit simple para ejecutarlo.

# 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 

Seleccione un target para ejecutar el programa.

Ejecución en el simulador de IonQ

Antes de ejecutarse en hardware real, vamos a probar el circuito en el simulador. Use get_backend para crear un Backend objeto para conectarse al back-end del simulador de IonQ:

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

Los back-end de IonQ admiten puertas de un conjunto de puertas definido, que se compilan para ejecutarse de forma óptima en el hardware. Si el circuito contiene puertas que no están en esta lista, debe transpile en el compatible gateset mediante la transpile función proporcionada por Qiskit:

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

La función transpile devuelve un nuevo objeto de circuito donde las puertas se descompone en puertas que se admiten en el back-end especificado.

Ahora puede ejecutar el programa a través del servicio Azure Quantum y obtener el resultado. La celda siguiente envía un trabajo que ejecuta el circuito con 100 tomas:

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

Para esperar hasta que se complete el trabajo y devolver los resultados, ejecute:

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'))])

Dado que el resultado es un objeto nativo del paquete de Qiskit, puede usar los objetos result.get_counts y plot_histogram de Qiskit para visualizar los resultados. Para asegurarse de que se representan todas las etiquetas de cadena de bits posibles, agréguelas 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}

Resultado del circuito de Qiskit en el simulador de IonQ

Estimación del costo del trabajo

Antes de ejecutar un trabajo en la QPU, puede calcular cuánto cuesta ejecutar. Para calcular el costo de ejecutar un trabajo en la QPU, puede usar el método estimate_cost.

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

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

El costo estimado se muestra en USD.

Para obtener los precios más actuales, consulte los precios de IonQ o vaya a su área de trabajo y consulte las opciones de precios en la hoja "Proveedores" en: aka.ms/aq/myworkspaces.

Ejecución en la QPU de IonQ

Para conectarse al hardware real (una unidad de procesador cuántico (QPU), simplemente proporcione el nombre del target"ionq.qpu" al get_backend método :

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

Envíe el circuito para que se ejecute en Azure Quantum, obtenga los resultados y ejecútelos plot_histogram para trazar los resultados.

Nota:

El tiempo necesario para ejecutar un circuito en la QPU puede variar en función de los tiempos de cola actuales.

# 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}

Resultado del circuito de Qiskit en la QPU de IonQ

Importante

Actualmente, no se admite el envío de varios circuitos en un solo trabajo. Como solución alternativa, puede llamar al método backend.run para enviar cada circuito de forma asincrónica y, a continuación, capturar los resultados de cada trabajo. Por ejemplo:

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

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

Requisitos previos

Creación de un cuaderno en el área de trabajo

  1. Inicie sesión en Azure Portal y seleccione el área de trabajo que creó en el paso anterior.
  2. En la hoja izquierda, seleccione Cuadernos.
  3. Haga clic en Mis cuadernos y, luego, en Agregar nuevo.
  4. Escriba un nombre para el archivo, por ejemplo Qiskit.ipynb, y haga clic en Crear archivo.

Cuando se abre el cuaderno nuevo, este crea automáticamente el código de la primera celda, en función de la información de la suscripción y del área de trabajo.

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

Nota

A menos que se indique lo contrario, debe ejecutar cada celda en orden a medida que se cree para evitar problemas de compilación.

Haga clic en el icono triangular "reproducir" situado a la izquierda de la celda para ejecutar el código.

Carga de las importaciones necesarias

En primer lugar, tendrá que importar algunos módulos adicionales.

Haga clic en + Código para agregar una nueva celda y, a continuación, agregue y ejecute el código siguiente:

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

Conexión al servicio Azure Quantum

A continuación, cree un AzureQuantumProvider objeto mediante el Workspace objeto de la celda anterior para conectarse al área de trabajo de Azure Quantum. Agregue una nueva celda con el código siguiente:

provider = AzureQuantumProvider(workspace)

Definición de un circuito simple

En una nueva celda, cree un objeto circuit. Este ejemplo es un generador cuántico de bits aleatorios simple. Agregue el código siguiente para definir y mostrar el 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 

Enumerar todos targets

Ahora puede mostrar todos los back-end de computación targetscuántica que están disponibles en el área de trabajo. Añada una nueva celda y ejecute la siguiente línea:

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

Seleccione un target para ejecutar el programa.

Para comprobar el código antes de ejecutarlo en hardware cuántico real, puede usar el simulador de cuántico de IonQ, ionq.simulator.

Agregue una nueva celda y cree un objeto para representar el simulador targetcuántico de IonQ:

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

Ejecución en el simulador de IonQ

Para ejecutar el circuito en el simulador, agregue el código siguiente. En este ejemplo se usa el run método de target para enviar el trabajo y, a continuación, se supervisa el estado del trabajo.

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

Cuando el trabajo se ejecute correctamente, obtenga los resultados del trabajo y los muestre:

# 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'))])

Dado que este tipo result es un objeto nativo del paquete de Qiskit, puede usar los objetos result.get_counts y plot_histogram de Qiskit y para visualizar los resultados. Para asegurarse de que se representan todas las etiquetas de cadena de bits posibles, agréguelas 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}

Resultado del circuito de Qiskit en el simulador de IonQ

Estimación del costo del trabajo

Antes de ejecutar un trabajo en hardware cuántico real o en una unidad de procesamiento cuántico (QPU), puede calcular cuánto cuesta ejecutar.

En primer lugar, vuelva a obtener la lista de proveedores disponibles:

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

A continuación, cree un objeto para representar el equipo cuántico de IonQ:

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

Para calcular el costo de ejecutar un trabajo en la QPU, agregue y ejecute una nueva celda mediante el estimate_cost método de target:

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

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

Muestra el costo estimado en USD.

Para ver la información sobre precios más actual, consulte Precios de IonQ o vaya a su área de trabajo y consulte las opciones de precios en la hoja Proveedores.

Ejecución en la QPU de IonQ

Después de ejecutar el trabajo correctamente en el simulador de IonQ y calcular el costo de QPU, es el momento de ejecutar el circuito en el hardware.

Nota:

El tiempo necesario para ejecutar un circuito en la QPU puede variar en función de los tiempos de cola actuales. Para ver el tiempo medio de cola de un elemento target , seleccione la hoja Proveedores del área de trabajo.

Use el mismo método run y las mismas operaciones que usó anteriormente con el validador de API para enviar y supervisar el trabajo:

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

Cuando finalice el trabajo, obtenga los resultados del trabajo como antes y muestranlos en un gráfico:

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}

Resultado del circuito de Qiskit en la QPU de IonQ

Importante

Actualmente, no se admite el envío de varios circuitos en un solo trabajo. Como solución alternativa, puede llamar al método backend.run para enviar cada circuito de forma asincrónica y, a continuación, capturar los resultados de cada trabajo. Por ejemplo:

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

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

Pasos siguientes