Inicio rápido: Envío de un circuito con Cirq a Azure Quantum

Aprenda a usar el paquete azure-quantum Python para enviar circuitos cuánticos de Cirq a un destino de computación cuántica de IonQ o Honeywell mediante el servicio Azure Quantum. Para más información, consulte Circuitos cuánticos.

Prerrequisitos

  • Para trabajar en Azure Quantum, necesita una suscripción de Azure. Si no tiene una suscripción a Azure, cree una cuenta gratuita.
  • Cree un área de trabajo de Azure Quantum y habilite su proveedor preferido, Honeywell o IonQ (o ambos), para este escenario. Para más información, consulte Creación de un área de trabajo de Azure Quantum.

Instalación del paquete azure-quantum de Python

El paquete de Python azure-quantum contiene la funcionalidad necesaria para conectarse al área de trabajo de Azure Quantum y enviar circuitos cuánticos a destinos de computación cuántica, como IonQ y Honeywell.

  1. Instale Python 3.6 o posterior en caso de que aún no lo haya hecho.

  2. Instale PIP y asegúrese de que tiene la versión 19.2 o posterior.

    Si usa Miniconda o Anaconda, también puede crear un nuevo entorno; para ello, descargue el archivo environment.yml y ejecute lo siguiente:

    conda env create -f environment.yml
    

    Esto crea un nuevo entorno de Conda que puede activar con lo siguiente:

    conda activate azurequantum
    
  3. Instale el paquete azure-quantum con pip: Use la marca --upgrade para asegurarse de obtener la última versión.

    pip install --upgrade azure-quantum[cirq]
    
  4. Inicie su editor de código preferido o una herramienta de Python interactiva, como VS Code, Jupyter o iPython.

Carga de las importaciones necesarias

En primer lugar, ejecute la siguiente celda para cargar las importaciones necesarias:

from azure.quantum.cirq import AzureQuantumService

Conexión al servicio Azure Quantum

Para conectarse al servicio Azure Quantum, el programa necesitará 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

Pegue los valores en el constructor AzureQuantumService siguiente para crear un objeto service que se conecte al área de trabajo de Azure Quantum. También puede especificar un destino predeterminado, en este caso, el simulador de IonQ:

service = AzureQuantumService(
    resource_id="",
    location="",
    default_target="ionq.simulator"
)

Enumeración de todos los destinos

Ahora puede enumerar todos los destinos a los que tiene acceso, incluido el tiempo de cola actual y la disponibilidad.

print(service.targets())
[<Target name="ionq.qpu", avg. queue time=345 s, Available>,
<Target name="ionq.simulator", avg. queue time=4 s, Available>,
<Target name="honeywell.hqs-lt-s1", avg. queue time=0 s, Available>,
<Target name="honeywell.hqs-lt-s1-apival", avg. queue time=0 s, Available>,
<Target name="honeywell.hqs-lt-s2", avg. queue time=313169 s, Available>,
<Target name="honeywell.hqs-lt-s2-apival", avg. queue time=0 s, Available>,
<Target name="honeywell.hqs-lt-s1-sim", avg. queue time=1062 s, Available>]

Ejecución de un circuito simple

A continuación, cree un circuito de Cirq simple para ejecutarlo. Este circuito usa la raíz cuadrada de la puerta X, nativa del sistema de hardware de IonQ.

import cirq

q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit(
    cirq.X(q0)**0.5,             # Square root of X
    cirq.CX(q0, q1),              # CNOT
    cirq.measure(q0, q1, key='b') # Measure both qubits
)
print(circuit)
0: ───X^0.5───@───M────────
              │   │
1: ───────────X───M────────

Ahora puede ejecutar el programa a través del servicio Azure Quantum y obtener el resultado. La celda siguiente envía un trabajo (al simulador de IonQ predeterminado) que ejecuta el circuito con 100 tomas, espera hasta que se complete el trabajo y devuelve los resultados.

result = service.run(program=circuit, repetitions=100)

Esto devuelve un objeto cirq.Result.

print(result)
    b=1001100101100001000011011101000011010100010111100011001000100100010000001110010010101110110000011010, 1001100101100001000011011101000011010100010111100011001000100100010000001110010010101110110000011010

Ejecución en la QPU de IonQ

El trabajo anterior se ejecutó en el simulador predeterminado, "ionq.simulator". Sin embargo, también puede ejecutarlo en el procesador de hardware de IonQ, una unidad de procesador cuántico (QPU). Para ejecutarlo en la QPU de IonQ, proporcione "ionq.qpu" como argumento target:

result = service.run(
    program=circuit,
    repetitions=100,
    target="ionq.qpu",
    timeout_seconds=500 # Set timeout to accommodate queue time on QPU
)

De nuevo, esto devuelve un objeto cirq.Result.

print(result)
b=0101011011011111100001011101101011011110100010000000011110111000100100110110101100110001001111101111, 0101011011011111100001011101101011011110100010000000011110111000100100110110101100110001001111101111

Modelo asincrónico con trabajos

En el caso de los circuitos de ejecución prolongada, puede ser útil ejecutarlos de forma asincrónica. El método service.create_job devuelve un objeto Job, que puede usar para obtener los resultados después de que el trabajo se haya ejecutado correctamente.

job = service.create_job(
    program=circuit,
    repetitions=100,
    target="ionq.simulator"
)

Para comprobar el estado, use job.status():

print(job.status())
'completed'

Para esperar a que se complete el trabajo y, a continuación, obtener los resultados, use la llamada de bloqueo job.results():

result = job.results()
print(result)
00: 0.5
11: 0.5

Tenga en cuenta que no devuelve un objeto cirq.Result. En su lugar, devuelve un objeto de resultado específico del simulador de IonQ y usa probabilidades de estado en lugar de datos de toma.

type(result)
cirq_ionq.results.SimulatorResult

Para convertirlo en un objeto cirq.Result, use result.to_cirq_result():

print(result.to_cirq_result())
b=1110101111111110111000011101011111001100010000001011011101001111001111001101100111010000001100011100, 1110101111111110111000011101011111001100010000001011011101001111001111001101100111010000001100011100

Instalación del paquete azure-quantum de Python

El paquete de Python azure-quantum contiene la funcionalidad necesaria para conectarse al área de trabajo de Azure Quantum y enviar circuitos cuánticos a destinos de computación cuántica, como IonQ y Honeywell.

  1. Instale Python 3.6 o posterior en caso de que aún no lo haya hecho.

  2. Instale PIP y asegúrese de que tiene la versión 19.2 o posterior.

    Si usa Miniconda o Anaconda, también puede crear un nuevo entorno; para ello, descargue el archivo environment.yml y ejecute lo siguiente:

    conda env create -f environment.yml
    

    Esto crea un nuevo entorno de Conda que puede activar con lo siguiente:

    conda activate azurequantum
    
  3. Instale el paquete azure-quantum con pip: Use la marca --upgrade para asegurarse de obtener la última versión.

    pip install --upgrade azure-quantum[cirq]
    
  4. Inicie su editor de código preferido o una herramienta de Python interactiva, como VS Code, Jupyter o iPython.

Carga de las importaciones necesarias

En primer lugar, ejecute la siguiente celda para cargar las importaciones necesarias:

from azure.quantum.cirq import AzureQuantumService

Conexión al servicio Azure Quantum

Para conectarse al servicio Azure Quantum, el programa necesitará 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

Pegue los valores en el constructor AzureQuantumService siguiente para crear un objeto service que se conecte al área de trabajo de Azure Quantum. También puede especificar un destino predeterminado:

from azure.quantum.cirq import AzureQuantumService
service = AzureQuantumService(
    resource_id="",
    location="",
    default_target="honeywell.hqs-lt-s1-apival"
)

Enumeración de todos los destinos

Ahora puede enumerar todos los destinos a los que tiene acceso, incluido el tiempo de cola actual y la disponibilidad.

print(service.targets())
[<Target name="ionq.qpu", avg. queue time=345 s, Available>,
<Target name="ionq.simulator", avg. queue time=4 s, Available>,
<Target name="honeywell.hqs-lt-s1", avg. queue time=0 s, Available>,
<Target name="honeywell.hqs-lt-s1-apival", avg. queue time=0 s, Available>,
<Target name="honeywell.hqs-lt-s2", avg. queue time=313169 s, Available>,
<Target name="honeywell.hqs-lt-s2-apival", avg. queue time=0 s, Available>,
<Target name="honeywell.hqs-lt-s1-sim", avg. queue time=1062 s, Available>]

Ejecución de un circuito simple en el validador de API

Nota

El destino del validador de API de Honeywell siempre devolverá 0 en la medición.

A continuación, cree un circuito de Cirq simple para ejecutarlo.

import cirq

q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit(
    cirq.H(q0), # Hadamard
    cirq.CNOT(q0, q1), # CNOT
    cirq.measure(q0, q1, key='b') # Measure both qubits
)
print(circuit)
0: ───H───@───M────────
          │   │
1: ───────X───M────────

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, espera hasta que se complete el trabajo y devuelve los resultados.

result = service.run(program=circuit, repetitions=100)

Esto devuelve un objeto cirq.Result.

print(result)
    b=0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Puede trazar los resultados en un histograma:

pl.hist(result.data)
pl.ylabel("Counts")
pl.xlabel("Result")

Flujo de trabajo asincrónico mediante trabajos

En el caso de los circuitos de ejecución prolongada, puede ser útil ejecutarlos de forma asincrónica. El método service.create_job devuelve un objeto Job, que puede usar para obtener los resultados después de que el trabajo se haya ejecutado correctamente.

job = service.create_job(
    program=circuit,
    repetitions=100
)

Para comprobar el estado, use job.status():

print(job.status())
'Waiting'

Para esperar a que se complete el trabajo y, a continuación, obtener los resultados, use la llamada de bloqueo job.results():

result = job.results()
print(result)
    {'m_b': ['00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00']}

Tenga en cuenta que no devuelve un objeto cirq.Result. En su lugar, devuelve un diccionario de resultados de medición en formato de cadena de bits, indexados por clave de medición.