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 Qiskit para o Azure Quantum usando o bloco de azure-quantumPython anotações do Azure Quantum, que tem pacote interno, ou de sua máquina local.

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

Pré-requisitos

Para obter detalhes da instalação, consulte Instalando o QDK 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 do Azure Quantum.

  • Um Python ambiente com Python e Pip instalado.

  • VS Code com o Azure Quantum Development Kit Pythone as extensões Jupyter instaladas.

  • O pacote Azure Quantum azure-quantumPython com a tag [qiskit].

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

    Importante

    Certifique-se de ter a versão mais recente do Qiskit. Para obter mais informações, consulte Atualizar o pacote azure-quantumPython.

    Nota

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

Criar um novo Jupyter Notebook

  1. No VS Code, selecione View > Command palette e selecione Create: New Jupyter Notebook.
  2. No canto superior direito, o VS Code detetará e exibirá a versão e Python 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 detetado, consulte Jupyter Notebooks no VS Code para obter informações de configuração.

Carregue as importações necessárias

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

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

Conectar-se ao serviço Azure Quantum

Para se conectar ao serviço Azure Quantum, você precisa da ID do recurso e do local do seu espaço de trabalho do Azure Quantum.

  1. Inicie sessão na sua conta do Azure, https://portal.azure.com,

  2. Selecione seu espaço de trabalho do Azure Quantum e navegue até Visão geral.

  3. Copie os parâmetros nos campos.

    Captura de tela do Visual Studio Code mostrando como expandir o painel de visão geral do seu Quantum Workspace.

Adicione uma nova célula em seu bloco de anotações e use as informações da sua conta para criar Workspace e AzureQuantumProvider objetos para se conectar ao seu espaço de trabalho 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 disponíveis em seu espaço de trabalho:

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

Execute um circuito simples

Primeiro, crie um circuito Qiskit simples para executar.

# 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 o programa

Executar no simulador IonQ

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

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

Os back-ends IonQ suportam portas de um conjunto de portas definido, que são compiladas para serem executadas de forma otimizada no hardware. Se o seu circuito contém portões que não estão nesta lista, você precisa transpilar para o suportado gateset 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 onde os portões são decompostos em portões que são suportados no back-end especificado.

Agora você pode executar o programa por meio do serviço 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=8)
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=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)

Como o resultado é um objeto nativo do pacote Qiskit, você pode usar o Qiskit result.get_counts e plot_histogram visualizar os resultados. Para certificar-se de que todos os rótulos de cadeia de bits possíveis estão representados, adicione-os ao 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}

Resultado do circuito Qiskit no IonQ Simulator

Você também pode usar a get_memory() função para exibir dados de captura individuais do trabalho

result.get_memory(circuit)
['000', '000', '000', '000', '111', '111', '111', '111']

Nota

No IonQ targets, se você enviar um trabalho com um número ímpar de disparos, os resultados serão arredondados para baixo para o próximo número par. Por exemplo, se você especificar 9 disparos, os resultados exibirão dados para 8 disparos.

Estimar o custo do trabalho

Antes de executar um trabalho na QPU, você deve estimar quanto custa para ser executado.

Para obter os detalhes de preços mais atuais, consulte Preços IonQ ou encontre seu espaço de trabalho e veja as opções de preços na guia "Provedor" do seu espaço de trabalho via: aka.ms/aq/myworkspaces.

Executar em IonQ QPU

Para se conectar ao hardware real (uma unidade de processador quântico target"ionq.qpu.aria-1" get_backend (QPU)), basta fornecer o nome do método:

qpu_backend = provider.get_backend("ionq.qpu.aria-1")

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

Nota

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

Resultado do circuito Qiskit na QPU IonQ

Importante

Atualmente, não há suporte para o envio de vários circuitos em um único trabalho. Como solução alternativa, você pode chamar o método para enviar cada circuito de forma assíncrona backend.run e, em seguida, 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

  • Uma conta do Azure com uma subscrição ativa. Se não tiver uma conta do Azure, registe-se gratuitamente e inscreva-se numa subscrição pré-paga.
  • Um espaço de trabalho do Azure Quantum. Para obter mais informações, consulte Criar um espaço de trabalho do Azure Quantum.

Criar um novo bloco de notas na sua área de trabalho

  1. Faça logon no portal do Azure e selecione o espaço de trabalho criado na etapa anterior.
  2. Na folha esquerda, selecione Blocos de Notas.
  3. Clique em Meus Blocos de Anotações e clique em Adicionar Novo.
  4. Digite um nome para o arquivo, por exemplo Qiskit.ipynb, e clique em Criar arquivo.

Quando o novo bloco de notas é aberto, cria automaticamente o código para a primeira célula, com base na sua subscrição e nas informações da área de trabalho.

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

Nota

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

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

Carregue 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-se ao serviço Azure Quantum

Em seguida, crie um AzureQuantumProvider objeto usando o Workspace objeto da célula anterior para se conectar ao seu espaço de trabalho 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 circuit objeto. Este exemplo é um gerador de bits aleatórios quânticos simples. 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 toda a computação targetsquântica, ou back-ends, que estão disponíveis em seu espaço de trabalho. Adicione uma nova 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.simulator
- ionq.qpu.aria-1
- microsoft.estimator
- quantinuum.qpu.h1-1
- quantinuum.sim.h1-1sc
- quantinuum.sim.h1-1e
- rigetti.sim.qvm

Selecione um target para executar o programa

Para verificar seu código antes de executá-lo em hardware quântico real, você pode usar o simulador quântico IonQ, ionq.simulator.

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

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

Executar no simulador IonQ

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

# Submit the circuit to run on Azure Quantum
job = simulator_backend.run(circuit, shots=8)
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='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)

Como esse result tipo é um objeto nativo do pacote Qiskit, você pode usar o Qiskit result.get_counts e plot_histogram visualizar os resultados. Para certificar-se de que todos os rótulos de cadeia de bits possíveis estão representados, adicione-os ao 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}

Resultado do circuito Qiskit no IonQ Simulator

Você também pode usar a get_memory() função para exibir dados de captura individuais do trabalho

result.get_memory(circuit)
['000', '000', '000', '000', '111', '111', '111', '111']

Nota

No IonQ targets, se você enviar um trabalho com um número ímpar de disparos, os resultados serão arredondados para baixo para o próximo número par. Por exemplo, se você especificar 9 disparos, os resultados exibirão dados para 8 disparos.

Estimar o custo do trabalho

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

Para obter os detalhes de preços mais atuais, consulte Preços IonQ ou localize seu espaço de trabalho e visualize as opções de preços na folha Provedores do seu espaço de trabalho.

Executar em IonQ QPU

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

Nota

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

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

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

Quando o trabalho terminar, 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 Qiskit na QPU IonQ

Importante

Atualmente, não há suporte para o envio de vários circuitos em um único trabalho. Como solução alternativa, você pode chamar o método para enviar cada circuito de forma assíncrona backend.run e, em seguida, 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óximos passos