Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Aprenda a enviar un circuito cuántico de Qiskit con el Kit de desarrollo de Azure Quantum (QDK). Puede enviar circuitos Qiskit a Azure Quantum mediante el Kit de desarrollo de Azure Quantum (QDK) y Jupyter Notebook en Visual Studio Code (VS Code). También puede probar los circuitos mediante el simulador disperso local. El QDK admite las versiones 1 y 2 de Qiskit.
Para más información, consulte Circuitos cuánticos.
Requisitos previos
Para obtener más información sobre la instalación, consulte Configuración de la extensión QDK.
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 las extensiones de Azure Quantum Development Kit, Pythony Jupyter instaladas.
La biblioteca
qdkPython con los extrasazureyqiskit, y el paqueteipykernel.python -m pip install --upgrade "qdk[azure,qiskit]" ipykernel
Crear un nuevo cuaderno de Jupyter Notebook
- En VS Code, abra el menú Ver y elija Paleta de comandos.
- Introduzca y seleccione Crear: Nuevo Jupyter Notebook.
- VS Code detecta y muestra 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 usando el selector de kernel ubicado en la esquina 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:
from qdk.azure import Workspace
from qdk.azure.qiskit import AzureQuantumProvider
from qiskit import QuantumCircuit
from qiskit.visualization import plot_histogram
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.
- Seleccione el área de trabajo de Azure Quantum y vaya a Información general.
- Copie los parámetros Id. de recurso y Ubicación .
Agregue una nueva celda en el cuaderno 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.simulator
- ionq.qpu.aria-1
- ionq.qpu.forte-1
- ionq.qpu.forte-enterprise-1
- quantinuum.sim.h2-1sc
- quantinuum.sim.h2-2sc
- quantinuum.sim.h2-1e
- quantinuum.sim.h2-2e
- quantinuum.qpu.h2-1
- quantinuum.qpu.h2-2
- rigetti.sim.qvm
- rigetti.qpu.ankaa-3
- rigetti.qpu.cepheus-1-36q
Ejecución de un circuito simple
En una nueva celda, cree un circuito Qiskit simple.
# 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
Selección de para target ejecutar el programa
Ejecución en el simulador de IonQ
Antes de ejecutar el circuito en hardware real, pruebe 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 compatibles con 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=8)
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=8, success=True, meas_level=2, data=ExperimentResultData(counts={'000': 4, '111': 4}, memory=['000', '000', '000', '000', '111', '111', '111', '111'], probabilities={'000': 0.5, '111': 0.5}), header=QobjExperimentHeader(name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits=3, metadata={}), status=JobStatus.DONE, name='Qiskit Sample - 3-qubit GHZ circuit')], date=None, status=None, header=None, error_data=None)
Dado que el resultado es un tipo de objeto específico del paquete Qiskit, use result.get_counts y plot_histogram para visualizar los resultados. Para representar todas las etiquetas de cadena de bits posibles, agregue las etiquetas a counts.
counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
{'000': 4, '001': 0, '010': 0, '011': 0, '100': 0, '101': 0, '110': 0, '111': 4}
También puede usar la get_memory función para mostrar datos de captura individuales del trabajo:
result.get_memory(circuit)
['000', '000', '000', '000', '111', '111', '111', '111']
Nota:
En IonQ targets, si envía un trabajo con un número impar de disparos, el número de disparos se redondea hacia abajo hasta el número par más cercano. Por ejemplo, si especifica 9 disparos, los resultados mostrarán los datos de 8 disparos.
Estimación del costo del trabajo
Estime el coste de ejecutar un trabajo antes de llevarlo a cabo en la QPU.
Para obtener los detalles de precios más actuales, consulte Precios de IonQ o busque el área de trabajo y vea las opciones de precios en la pestaña Proveedor del área de trabajo a través de: 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.aria-1" al get_backend método :
qpu_backend = provider.get_backend("ionq.qpu.aria-1")
Envíe el circuito para que se ejecute en Azure Quantum, obtenga los resultados y, a continuación, ejecútelo 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=100)
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.qpu.aria-1', 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}
Importante
No se pueden enviar varios circuitos en un solo trabajo. Como solución alternativa, puede llamar al backend.run método 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
Para obtener más información sobre la instalación, consulte Configuración de la extensión QDK.
Un Python entorno con Python y Pip instalado.
VS Code con el Kit de desarrollo de Azure Quantum y Python las extensiones instaladas.
El paquete
qdkPython con las extrasqiskityjupyter.python pip install "qdk[qiskit,jupyter]"
Ejecución de un circuito básico
En VS Code, abra un nuevo Python archivo para crear y ejecutar un circuito básico con el simulador disperso integrado desde el qsharp módulo.
# load the required imports
from qdk import qsharp
from qsharp.interop.qiskit import QSharpBackend
from qiskit.circuit.random import random_circuit
# define and display the circuit
circuit = random_circuit(2, 2, measure=True)
print(circuit)
# run the circuit using the built-in sparse simulator
backend = QSharpBackend()
job = backend.run(circuit)
counts = job.result().get_counts()
print(counts)
Para ejecutar el programa, seleccione el icono Ejecutar en la esquina superior derecha y seleccione Ejecutar Python archivo. La salida se muestra en una nueva ventana de terminal.
┌─────────────────────────┐┌─┐
q_0: ─■───────────┤0 ├┤M├───
│P(0.79983) │ (XX-YY)(1.9337,1.7385) │└╥┘┌─┐
q_1: ─■───────────┤1 ├─╫─┤M├
└─────────────────────────┘ ║ └╥┘
c: 2/═════════════════════════════════════════╩══╩═
0 1
{'11': 680, '00': 344}
Generación de QIR para el circuito
Desde ese mismo circuito, se puede generar QIR que se emplea para ejecutarse en hardware cuántico.
Nota:
Para generar QIR, todas las mediciones deben almacenarse en los registros. Si hay registros sin usar, se genera un error. Además, se produce un error al intentar generar QIR con un Unrestrictedtarget perfil. El perfil de Unrestricted solo es válido para la simulación. Debe usar TargetProfile.Base, TargetProfile.Adaptive_RIo TargetProfile.Adaptive_RIF. Puede sobrescribir el target_profile en la llamada backend.qir(...) para cambiar perfiles.
Importar
QSharpErroryTargetProfilefrom qdk.qsharp import QSharpError, TargetProfilePara generar QIR, modifique la salida:
print(backend.qir(circuit, target_profile=TargetProfile.Adaptive_RI))
El código debería tener ahora un aspecto similar al siguiente:
# load the required imports
from qdk import qsharp
from qsharp import QSharpError, TargetProfile
from qsharp.interop.qiskit import QSharpBackend
from qiskit.circuit.random import random_circuit
# define and display the circuit
circuit = random_circuit(2, 2, measure=True)
print(circuit)
# generate QIR for the circuit
print(backend.qir(circuit, target_profile=TargetProfile.Adaptive_RI))
La salida del código debe tener este aspecto:
┌────────────┐ ┌─┐
q_0: ┤ Rx(2.7195) ├─■───────────┤M├───
└──┬─────┬───┘ │U1(5.5924) └╥┘┌─┐
q_1: ───┤ Tdg ├─────■────────────╫─┤M├
└─────┘ ║ └╥┘
c: 2/════════════════════════════╩══╩═
0 1
%Result = type opaque
%Qubit = type opaque
define void @ENTRYPOINT__main() #0 {
block_0:
call void @__quantum__qis__rx__body(double 2.7194945105768586, %Qubit* inttoptr (i64 0 to %Qubit*))
call void @__quantum__qis__rz__body(double 2.796204066686262, %Qubit* inttoptr (i64 0 to %Qubit*))
call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__rz__body(double -2.796204066686262, %Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__rz__body(double 2.796204066686262, %Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
call void @__quantum__rt__array_record_output(i64 2, i8* null)
call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
ret void
}
declare void @__quantum__qis__rx__body(double, %Qubit*)
declare void @__quantum__qis__rz__body(double, %Qubit*)
declare void @__quantum__qis__t__adj(%Qubit*)
declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
declare void @__quantum__rt__array_record_output(i64, i8*)
declare void @__quantum__rt__result_record_output(%Result*, i8*)
attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
attributes #1 = { "irreversible" }
; module flags
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10}
!0 = !{i32 1, !"qir_major_version", i32 1}
!1 = !{i32 7, !"qir_minor_version", i32 0}
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
!3 = !{i32 1, !"dynamic_result_management", i1 false}
!4 = !{i32 1, !"classical_ints", i1 true}
!5 = !{i32 1, !"qubit_resetting", i1 true}
!6 = !{i32 1, !"classical_floats", i1 false}
!7 = !{i32 1, !"backwards_branching", i1 false}
!8 = !{i32 1, !"classical_fixed_points", i1 false}
!9 = !{i32 1, !"user_functions", i1 false}
!10 = !{i32 1, !"multiple_target_branching", i1 false}
No todos los programas se pueden ejecutar en todo el hardware. Aquí, si intenta usar target el Base perfil, obtendrá errores detallados sobre qué partes del programa no se admiten.
try:
backend.qir(qc, target_profile=TargetProfile.Base)
except QSharpError as e:
print(e)