Como enviar um circuito com o Qiskit para o Azure Quantum

Saiba como enviar um circuito quântico qiskit usando o azure-quantumPython pacote . Você pode enviar circuitos do Qiskit para o Azure Quantum usando o notebook do Azure Quantum, que tem um pacote interno azure-quantumPython ou de seu computador local.

Para mais informações, consulte Circuitos quânticos.

Observação

O Microsoft Quantum Development Kit (QDK Clássico) não terá mais suporte após 30 de junho de 2024. Se você for um desenvolvedor de QDK existente, recomendamos que faça a transição para o novo QDK (Kit de Desenvolvimento Quântico do Azure) para continuar desenvolvendo soluções quânticas. Para obter mais informações, consulte Migrar seu código Q# para o QDK moderno.

Pré-requisitos

Para obter detalhes da instalação, consulte Instalando o QDK moderno no VS Code.

  • Um espaço de trabalho do Azure Quantum em sua assinatura do Azure. Para criar um espaço de trabalho, consulte Criar um espaço de trabalho no Azure Quantum.

  • Um Python ambiente com Python e Pip instalados.

  • VS Code com as extensões do Kit de Desenvolvimento do Azure Quantum, Pythone jupyter instaladas.

  • O pacote do Azure Quantum azure-quantum com a marca [qiskit] e os qsharp pacotes e ipykernel .

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

    Observação

    Se o kernel ipykernel do Jupyter Python não for detectado, o VS Code solicitará que você o instale.

Criar um novo Jupyter Notebook

  1. No VS Code, selecione Exibir > paleta de comandos e selecione Criar: Novo Jupyter Notebook.
  2. No canto superior direito, o VS Code detectará e exibirá a versão do Python e o ambiente virtual Python que foi selecionado para o notebook. Se você tiver vários Python ambientes, talvez seja necessário selecionar um kernel usando o seletor de kernel no canto superior direito. Se nenhum ambiente foi detectado, consulte Jupyter Notebooks no VS Code para obter informações de instalação.

Carregar as importações necessárias

Na primeira célula do notebook, execute o seguinte código para carregar as importações necessárias:

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

Conectar ao serviço do Azure Quantum

Para se conectar ao serviço do Azure Quantum, você precisa da ID do recurso e da localização do workspace do Azure Quantum. Faça logon em sua conta do Azure, https://portal.azure.com, navegue até o workspace do Azure Quantum e copie os valores do cabeçalho.

Como recuperar a ID do recurso e o local de um workspace do Azure Quantum

Adicione uma nova célula e use as informações da conta para criar Workspace objetos e AzureQuantumProvider para se conectar ao workspace do 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)

Listar todos os back-ends

Agora você pode imprimir todos os back-ends de computação quântica que estão disponíveis em seu workspace:

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

Executar um circuito simples

Primeiro, crie um circuito Qiskit simples para ser executado.

# 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 

Selecione um target para executar seu programa

Executar no simulador do IonQ

Antes de executar em hardware real, vamos testar o circuito no simulador. Use get_backend para criar um Backend objeto para se conectar ao back-end do Simulador IonQ:

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

Os back-ends IonQ dão suporte a portões de um conjunto de portões definido, que são compilados para serem executados de modo ideal no hardware. Se o circuito contiver portões que não estão nesta lista, você precisará transcompilar para o com gateset suporte usando a transpile função fornecida pelo Qiskit:

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

A função transpile retorna um novo objeto de circuito em que os portões são decompostos em portões com suporte no back-end especificado.

Agora você pode executar o programa por meio do serviço do Azure Quantum e obter o resultado. A célula a seguir envia um trabalho que executa o circuito com 100 disparos:

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

Para aguardar até que o trabalho seja concluído e retornar os resultados, execute:

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

Como o resultado é um objeto nativo do pacote do Qiskit, você pode usar o result.get_counts e o plot_histogram do Qiskit para visualizar os resultados. Para garantir que todos os rótulos de bitstring possíveis sejam representados, adicione-os 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 do circuito do Qiskit no Simulador do IonQ

Estimar o custo do trabalho

Antes de executar um trabalho na QPU, você pode estimar quanto custa executar. Para estimar o custo da execução de um trabalho na QPU, você pode usar o método estimate_cost:

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

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

Isso imprime o custo estimado em US$.

Para obter os detalhes de preços mais atuais, consulte Preços do IonQ ou localize seu workspace e exiba as opções de preço na guia "Provedor" do workspace por meio de: aka.ms/aq/myworkspaces.

Executar na QPU do IonQ

Para se conectar ao hardware real (uma QPU ( Unidade de Processador Quântico ), basta fornecer o nome do target"ionq.qpu" ao get_backend método :

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

Envie o circuito para ser executado no Azure Quantum, obtenha os resultados e execute plot_histogram para plotar os resultados.

Observação

O tempo necessário para executar um circuito na QPU pode variar dependendo dos tempos de fila atuais.

# 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 do circuito do Qiskit na QPU do IonQ

Importante

Atualmente, não há suporte para o envio de vários circuitos em apenas um trabalho. Como solução alternativa, você pode chamar o método backend.run para enviar cada circuito de modo assíncrono e buscar os resultados de cada trabalho. Por exemplo:

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

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

Pré-requisitos

Criar um notebook em seu workspace

  1. Faça logon no portal do Azure e selecione o workspace que você criou na etapa anterior.
  2. No painel à esquerda, selecione Notebooks.
  3. Clique em Meus Notebooks e em Adicionar Novo.
  4. Digite um nome para o arquivo, por exemplo, Qiskit.ipynb, e clique em Criar arquivo.

Quando o novo notebook é aberto, ele cria automaticamente o código da primeira célula com base na assinatura e nas informações do workspace.

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

Observação

Salvo indicação em contrário, você deve executar cada célula na ordem em que a cria para evitar problemas de compilação.

Clique no ícone triangular "reproduzir" à esquerda da célula para executar o código.

Carregar as importações necessárias

Primeiro, você precisará importar alguns módulos adicionais.

Clique em + Código para adicionar uma nova célula e, em seguida, adicione e execute o seguinte código:

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

Conectar ao serviço do Azure Quantum

Em seguida, crie um AzureQuantumProvider objeto usando o Workspace objeto da célula anterior para se conectar ao workspace do Azure Quantum. Adicione uma nova célula com o seguinte código:

provider = AzureQuantumProvider(workspace)

Definir um circuito simples

Em uma nova célula, crie um objeto circuit. Este exemplo é um gerador de bits aleatório simples do Quantum. Adicione o seguinte código para definir e exibir o 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 

Listar tudo targets

Agora você pode exibir todos os back-ends ou de computação targetsquântica que estão disponíveis em seu workspace. Adicione uma célula e execute a seguinte linha:

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

Selecione um target para executar seu programa

Para verificar o seu código antes de executar no hardware quântico real, você pode usar o simulador quântico do IonQ, ionq.simulator.

Adicione uma nova célula e crie um objeto para representar o simulador targetquântico do IonQ:

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

Executar no simulador do IonQ

Para executar o circuito no simulador, adicione o código a seguir. Este exemplo usa o run método do target para enviar seu trabalho e monitora o trabalho status.

# 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 o trabalho for executado com êxito, obtenha os resultados do trabalho e exiba-os:

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

Como esse tipo result é um objeto nativo do pacote do Qiskit, você pode usar o result.get_counts e o plot_histogram do Qiskit para visualizar os resultados. Para garantir que todos os rótulos de bitstring possíveis sejam representados, adicione-os 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 do circuito do Qiskit no Simulador do IonQ

Estimar o custo do trabalho

Antes de executar um trabalho no hardware quântico real ou em uma QPU ( unidade de processamento quântico ), você pode estimar quanto custa executar.

Primeiro, obtenha a lista de provedores disponíveis novamente:

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

Em seguida, crie um objeto para representar o computador quântico do IonQ:

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

Para estimar o custo da execução de um trabalho na QPU, adicione e execute uma nova célula usando o estimate_cost método do target:

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

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

Isso exibe o custo estimado em US$.

Para obter os detalhes de preços mais atuais, confira Preços do IonQ ou encontre o seu workspace e visualize as opções de preços da folha Provedores do seu workspace.

Executar na QPU do IonQ

Depois de executar seu trabalho com êxito no simulador IonQ e estimar o custo da QPU, é hora de executar o circuito no hardware.

Observação

O tempo necessário para executar um circuito na QPU pode variar dependendo dos tempos de fila atuais. Você pode exibir o tempo médio da fila para um target selecionando a folha Provedores do workspace.

Use o mesmo método run e operações que você usou anteriormente com o validador de API para enviar e monitor seu trabalho:

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

Quando o trabalho for concluído, obtenha os resultados do trabalho como antes e exiba-os em um 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 do circuito do Qiskit na QPU do IonQ

Importante

Atualmente, não há suporte para o envio de vários circuitos em apenas um trabalho. Como solução alternativa, você pode chamar o método backend.run para enviar cada circuito de modo assíncrono e buscar os resultados de cada trabalho. Por exemplo:

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

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

Próximas etapas