Execute trabalhos de computação quântica híbrida com perfil adaptável target

A computação híbrida combina processos de computação clássica e quântica para resolver problemas complexos.

Na computação híbrida, o código clássico controla a execução de operações quânticas com base em medições de circuito intermediário, enquanto os qubits físicos permanecem ativos. Você pode usar técnicas de programação comuns, como condicionais aninhados, loops e chamadas de função, em um único programa quântico para executar problemas complexos, reduzindo o número de disparos necessários. Com técnicas de reutilização de qubit, programas maiores podem ser executados em máquinas usando um número menor de qubits.

Este artigo explica como enviar trabalhos híbridos para o Azure Quantum usando o QIR Adaptive RItarget perfil. O perfil RI target adaptativo oferece suporte para medições de circuito médio, fluxo de controle baseado em medição, redefinição de qubit e computação inteira clássica.

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.
  • Se você quiser enviar Q# programas autônomos, você precisa dos seguintes pré-requisitos:
  • Se você deseja enviar Python + Q# programas, você precisa dos seguintes pré-requisitos:
    • Um ambiente Python com Python e Pip instalados.

    • O Azure Quantum azure-quantum e qsharp pacotes.

      pip install --upgrade azure-quantum qsharp
      

Suportado targets

Para executar trabalhos de computação quântica híbrida, você precisa selecionar um provedor quântico que suporte o perfil RI target adaptável.

Atualmente, o perfil adaptável target no Azure Quantum é suportado no Quantinuumtargets.

Envio de trabalhos de RI adaptáveis

Para enviar trabalhos de computação quântica híbrida, você precisa configurar o target perfil como QIR Adaptive RI, onde RI significa "qubit Reset e Integer computations".

O QIR Adaptive RItarget perfil oferece suporte para medições de circuito médio, fluxo de controle baseado em medição, redefinição de qubit e computação inteira clássica.

Você pode enviar trabalhos quânticos híbridos para o Azure Quantum como Q# programas autônomos ou Python + Q# . Para configurar o perfil para trabalhos quânticos target híbridos, consulte as seções a seguir.

Para configurar o target perfil para trabalhos híbridos no Visual Studio Code, execute estas etapas:

  1. Abra um Q# programa no Visual Studio Code.
  2. Selecione Exibir -> Paleta de Comandos e digiteQ#: Defina o perfil QIR target do Azure Quantum. Prima Enter.
  3. Selecione QIR Adaptive RI.

Depois de definir QIR Adaptive RI como target perfil, você pode enviar seu programa como um trabalho quântico Q# híbrido para a Quantinuum.

  1. Selecione Exibir -> Paleta de Comandos e digite Q#: Conectar-se a um espaço de trabalho do Azure Quantum. Prima Enter.
  2. Selecione Conta do Azure e siga as instruções para se conectar ao seu diretório, assinatura e espaço de trabalho preferidos.
  3. Quando estiver conectado, no painel Explorer, expanda Espaços de trabalho quânticos.
  4. Expanda seu espaço de trabalho e expanda o provedor Quantinuum .
  5. Selecione qualquer Quantinuum disponível target, por exemplo quantinuum.sim.h1-1e.
  6. Selecione o ícone de reprodução à direita do nome para começar a target enviar o programa atual Q# .
  7. Adicione um nome para identificar o trabalho e o número de disparos.
  8. Pressione Enter para enviar o trabalho. O status do trabalho é exibido na parte inferior da tela.
  9. Expanda Trabalhos e passe o mouse sobre seu trabalho, que exibe os horários e o status do seu trabalho.

Funcionalidades suportadas

A tabela a seguir lista os recursos com suporte para computação quântica híbrida com Quantinuum no Azure Quantum.

Funcionalidade suportada Notas
Valores dinâmicos Boóis e inteiros cujo valor depende de um resultado de medição
Ciclos Apenas loops limitados classicamente
Fluxo de controle arbitrário Utilização de ramificações if/else
Medição no meio do circuito Utiliza recursos de registro clássicos
Reutilização de Qubit Suportado
Computação clássica em tempo real Aritmética de inteiros assinados de 64 bits
Utiliza recursos de registro clássicos

O QDK fornece targetfeedback específico quando Q# os recursos de idioma não são suportados para o .target Se o seu Q# programa contiver recursos não suportados ao executar trabalhos quânticos híbridos, você receberá uma mensagem de erro em tempo de design. Para obter mais informações, consulte a página wiki do QIR.

Nota

Você precisa selecionar o perfil apropriado QIR Adaptive RItarget para obter feedback apropriado ao usar Q# recursos que o target não suporta.

Para ver os recursos suportados em ação, copie o código a seguir em um Q# arquivo e adicione os trechos de código subsequentes.

import Microsoft.Quantum.Measurement.*;
import Microsoft.Quantum.Math.*;
import Microsoft.Quantum.Convert.*;

operation Main() : Result {
    use (q0, q1) = (Qubit(), Qubit());
    H(q0);
    let r0 = MResetZ(q0);

    // Copy here the code snippets below to see the supported features 
    // in action.
    // Supported features include dynamic values, classically-bounded loops, 
    // arbitrary control flow, and mid-circuit measurement.

    r0
}

Quantinuum suporta boóis dinâmicos e inteiros, o que significa boóis e inteiros que dependem dos resultados da medição. Note que r0 é um Result tipo que pode ser usado para gerar bool dinâmico e valores inteiros.

        let dynamicBool = r0 != Zero; 
        let dynamicBool = ResultAsBool(r0); 
        let dynamicInt = dynamicBool ? 0 | 1; 

O Quantinuum suporta boóis e inteiros dinâmicos, no entanto, não suporta valores dinâmicos para outros tipos de dados, como duplo. Copie o código a seguir para ver comentários sobre as limitações dos valores dinâmicos.

        let dynamicDouble = r0 == One ? 1. | 0.; // cannot use a dynamic double value
        let dynamicInt = r0 == One ? 1 | 0;
        let dynamicDouble = IntAsDouble(dynamicInt); // cannot use a dynamic double value
        let dynamicRoot = Sqrt(dynamicDouble); // cannot use a dynamic double value

Embora não haja suporte para valores dinâmicos para alguns tipos de dados, esses tipos de dados ainda podem ser usados com valores estáticos.

    let staticRoot = Sqrt(4.0);
    let staticBigInt = IntAsBigInt(2);

Mesmo os valores dinâmicos dos tipos suportados não podem ser usados em determinadas situações. Por exemplo, o Quantinuum não suporta matrizes dinâmicas, ou seja, matrizes cujo tamanho depende de um resultado de medição. O Quantinuum também não suporta loops limitados dinamicamente. Copie o código a seguir para ver as limitações dos valores dinâmicos.

        let dynamicInt = r0 == Zero ? 2 | 4;
        let dynamicallySizedArray = [0, size = dynamicInt]; // cannot use a dynamically-sized array
        let staticallySizedArray = [0, size = 10];
        // Loops with a dynamic condition are not supported by Quantinuum.
        for _ in 0..dynamicInt {
            Rx(PI(), q1);
        }
        
        // Loops with a static condition are supported.
        let staticInt = 3;
        for _ in 0..staticInt {  
            Rx(PI(), q1);  
        }

O Quantinuum suporta o fluxo de controle, incluindo if/else ramificação, usando condições estáticas e dinâmicas. A ramificação em condições dinâmicas também é conhecida como ramificação baseada em resultados de medição.

        let dynamicInt = r0 == Zero ? 0 | 1; 
        if dynamicInt > 0 {
            X(q1);
        }
        let staticInt = 1;
        if staticInt > 5 {
            Y(q1);
        } else {
            Z(q1);
        }

Quantinuum suporta loops com condições clássicas e incluindo if expressões.

        for idx in 0..3 {
            if idx % 2 == 0 {
                Rx(ArcSin(1.), q0);
                Rz(IntAsDouble(idx) * PI(), q1)
            } else {
                Ry(ArcCos(-1.), q1);
                Rz(IntAsDouble(idx) * PI(), q1)
            }
        }

O Quantinuum suporta medição de circuito médio, ou seja, ramificação com base nos resultados da medição.

        if r0 == One {
            X(q1);
        }
        let r1 = MResetZ(q1);
        if r0 != r1 {
            let angle = PI() + PI() + PI()* Sin(PI()/2.0);
            Rxx(angle, q0, q1);
        } else {
            Rxx(PI() + PI() + 2.0 * PI() * Sin(PI()/2.0), q1, q0);
        }

Estimativa do custo de um trabalho de computação quântica híbrida

Você pode estimar o custo de executar um trabalho de computação quântica híbrida no hardware Quantinuum executando-o primeiro em um emulador.

Após uma execução bem-sucedida no emulador:

  1. No espaço de trabalho do Azure Quantum, selecione Gerenciamento de tarefas.
  2. Selecione o trabalho enviado.
  3. No pop-up Detalhes do trabalho, selecione Estimativa de custo para visualizar quantos eHQCs (créditos do emulador Quantinuum) foram usados. Esse número se traduz diretamente no número de HQCs (créditos quânticos Quantinuum) necessários para executar o trabalho no hardware Quantinuum.

Estimativa de custos

Nota

O Quantinuum desenrola todo o circuito e calcula o custo em todos os caminhos de código, sejam eles executados condicionalmente ou não.

Amostras de computação quântica híbrida

Os exemplos a seguir podem ser encontrados no repositório de exemplos de Q# código. Eles demonstram o conjunto de recursos atual para a computação quântica híbrida.

Código de repetição de três qubits

Este exemplo demonstra como criar um código de repetição de três qubits que pode ser usado para detetar e corrigir erros de inversão de bits.

Ele aproveita recursos de computação híbrida integrada para contar o número de vezes que a correção de erros foi executada enquanto o estado de um registro de qubit lógico é coerente.

Você pode encontrar o exemplo de código aqui.

Estimativa iterativa da fase

Este programa de exemplo demonstra uma estimativa de fase iterativa dentro do Q#. Ele usa estimativa de fase iterativa para calcular um produto interno entre dois vetores de 2 dimensões codificados em um target qubit e um qubit ancilla. Um qubit de controle adicional também é inicializado, que é o único qubit usado para medição.

O circuito começa codificando o par de vetores no qubit e no target qubit ancilla. Em seguida, ele aplica um operador Oracle a todo o registro, controlado pelo qubit de controle, que é configurado no estado $\ket +$. O operador Oracle controlado gera uma fase no estado $\ket 1$ do qubit de controle. Isso pode ser lido aplicando uma porta H ao qubit de controle para tornar a fase observável durante a medição.

Você pode encontrar o exemplo de código aqui.

Nota

Este código de exemplo foi escrito por membros da equipe KPMG Quantum na Austrália e se enquadra em uma licença MIT. Ele demonstra capacidades expandidas e faz uso de loops limitados, chamadas de função clássicas em tempo de execução, instruções if condicionais aninhadas, medições de QIR Adaptive RItargets circuito médio e reutilização de qubit.