Skip to main content
IBM Quantum Platform

Notas de versão do Qiskit SDK 2.1


2.1.2

Prelúdio

O Qiskit 2.1.2 é um pequeno patch de lançamento que corrige vários erros encontrados na série 2.1.

Correções de bugs

  • No Qiskit 2.1.0, a passagem VF2PostLayout foi adicionada ao estágio optimization do gerenciador de passagens predefinidas quando optimization_level=3. Entretanto, a saída do passador nunca foi aplicada ao circuito. Esta versão remove o passe do estágio optimization do gerenciador de passes predefinido para economizar o custo do tempo de execução. No Qiskit 2.2.0, a passagem fará parte do estágio optimization e a saída será aplicada se a passagem encontrar um layout melhor.

  • Foi corrigido um problema na passagem do VF2Layout onde, mesmo com um conjunto de sementes fixo, a saída da passagem era potencialmente não determinística; especificamente se o circuito de entrada tivesse qualquer qubits ativo que contivesse apenas operações de qubit único. Corrigido #14729

  • Foi corrigido um erro no PassManager.run() em que a função callback não era chamada durante a execução com vários circuitos. Agora, a chamada de retorno é acionada corretamente para cada passagem em cada circuito, inclusive na execução paralela.

  • As passagens do transpilador incorporado que definem a propriedade final_layout agora tratarão corretamente a atualização desse campo se ele já estiver definido. Isso pode ser observado como o método TranspileLayout.routing_permutation agora retorna uma permutação correta depois de executar mais de uma passagem que define final_layout.

    Isso não afetou nenhuma chamada normal para transpile() ou generate_preset_pass_manager() usando os plug-ins internos do Qiskit; nenhum pipeline construído dessa forma tentaria definir final_layout mais de uma vez.

  • Foi corrigido um erro em Target.instruction_supported() em que a verificação da ordem dos qubits da instrução era ignorada quando o método era chamado com os argumentos operation_name e parameters que correspondiam a uma instrução existente.

  • Foi corrigido um erro de correção ao exportar circuitos com instruções de atraso usando unidades ps para QASM3.

  • Corrigido um caso de borda na exibição do QFT circuito. Anteriormente, quando QFT.inverse() era chamado e, em seguida, os atributos do circuito QFT eram modificados, o nome do QFT era exibido como "IQFT_dg". Isso estava incorreto e agora mostra corretamente "IQFT". Corrigido #14758.

  • Foi corrigido um vazamento de memória na coordenação do uso de qk_circuit_get_instruction e qk_circuit_instruction_clear.

  • Esclarecida a mensagem de erro para versões inválidas especificadas em qpy.dump() para facilitar a ação.

  • Foi corrigido um problema com a função generate_preset_pass_manager() em que ela ignorava incorretamente os dados de restrições de tempo contidos em um objeto Target fornecido quando o argumento backend não era definido. Corrigido #14329

  • Corrigido um erro no SparsePauliOp.simplify() em que o método removia os termos de Pauli com base nas magnitudes de seus coeficientes antes de combinar as duplicatas. Isso causou um comportamento incorreto em dois casos extremos importantes:

    1. Quando vários termos de Pauli idênticos tinham coeficientes pequenos que estavam individualmente abaixo do limite de simplificação, mas cuja soma excedia o limite, esses termos eram removidos incorretamente.
    2. Quando vários termos de Pauli idênticos tinham coeficientes acima do limite, mas somados a quase zero, eles eram mantidos incorretamente.

    Consulte #14194 para obter mais detalhes.


2.1.1

Prelúdio

O Qiskit 2.1.1 é um pequeno patch de lançamento que corrige vários erros encontrados na série 2.1.

Correções de bugs

  • Foi corrigido um bug na verificação de DAGOpNode onde a comparação de dois objetos DAGOpNode que contêm uma instrução BoxOp instrução. Anteriormente, o atributo BoxOp.unit não era considerado como parte da verificação de igualdade, o que poderia fazer com que dois nós desiguais fossem avaliados como iguais.

  • Corrigido o aviso de descontinuidade do site Python 3.9 para que ele seja corretamente identificado como sendo causado pelo código do usuário ao importar o Qiskit. Anteriormente, ele não era identificado como sendo causado pelo código do usuário, o que significava que os filtros de aviso padrão do Python não exibiam o aviso ao usuário.

  • Foi corrigido o comportamento do argumento max_trials para VF2Layout quando definido como None ou um número negativo. A passagem foi documentada como limitando a pesquisa a ser baseada no tamanho do circuito ou do alvo se a opção foi definida como None, e como aceitando valores negativos para especificar uma pesquisa ilimitada. No entanto, em 2.1.0, esse comportamento foi alterado incorretamente, de modo que None executou uma pesquisa sem limites e o uso de um número negativo gerou um erro. Esses descuidos foram corrigidos para que o passe se comporte conforme documentado e seja consistente com as versões anteriores.

  • Correção de um problema nos plug-ins de síntese de alto nível MCXSynthesis1DirtyKG24 e MCXSynthesis2DirtyKG24 para MCXGateem que os plug-ins não consideravam os qubits auxiliares limpos disponíveis como qubits auxiliares sujos disponíveis. Em particular, o plug-in MCXSynthesis2DirtyKG24 não se aplicava quando um qubits auxiliar limpo e um qubits auxiliar sujo estavam disponíveis.

  • Correção de uma regressão de desempenho ao criar incrementalmente ParameterExpression combinando um grande número de subexpressões. Corrigido #14653


2.1.0

Prelúdio

A versão do Qiskit v2.1 apresenta vários aprimoramentos importantes em áreas-chave, incluindo a API C, os recursos do transpilador e a usabilidade do circuito quântico. Além disso, inclui muitos aprimoramentos gerais e correções de bugs. Os principais destaques incluem:

  • Extensões da API C: Com base no trabalho iniciado na versão anterior, o Qiskit v2.1 adiciona suporte para a criação e a interação com circuitos quânticos por meio de funções da API C, suportando a adição de portas padrão, instruções padrão e portas unitárias. Também foi adicionado nesta versão um conjunto de funções C para criar e manipular um objeto Target como preparação para oferecer suporte a um fluxo de trabalho completo de transpilação baseado em API C na próxima versão. Além disso, QkComplex64 agora é definido como um struct, servindo como uma representação independente de compilador para números complexos ao trabalhar com a API C do Qiskit. O arquivo de cabeçalho da API C também foi atualizado para que seja geralmente compatível com o uso nativo em C++.
  • Suporte ao conjunto de base Clifford+T: A transpilação de circuitos para um alvo com portas Clifford+T agora é suportada imediatamente. Por trás disso, se o conjunto de bases consistir apenas em portas Clifford+T, o Qiskit garante que as passagens apropriadas para lidar com essas portas sejam adicionadas aos gerenciadores de passagens predefinidos. Essa é uma etapa inicial para oferecer suporte à transpilação para back-ends tolerantes a falhas.
  • Aprimoramentos para BoxOp: Esta versão adiciona a capacidade de anexar anotações personalizadas às BoxOp dando ainda mais suporte ao conceito de declarações de caixa do OpenQASM 3 no Qiskit. Isso também inclui a serialização de anotações nos formatos QASM e QPY. Além disso, foi adicionado o suporte ao uso de durações de alongamento em caixas.
  • Python 3.9 depreciação: Python 3.9 está obsoleto a partir do Qiskit v2.1 e não será mais compatível com o Qiskit v2.3.

Para obter mais detalhes sobre os itens acima e muito mais, consulte as notas de versão abaixo e visite a documentação atualizada.

Recursos da API C

  • A API do Qiskit C ( qiskit.h ) agora suporta a criação e a interação com circuitos quânticos. A API em C dos circuitos gira em torno do tipo QkCircuit opaco que representa o circuito. O tipo QkCircuit permite criar um circuito com qualquer elemento de circuito definido nativamente no modelo de dados Rust interno do Qiskit para QuantumCircuit. Atualmente, isso inclui portões padrão, Measure, Delay, Reset, Barrier, e UnitaryGate. Os recursos da API C de circuitos serão expandidos em versões futuras, à medida que mais do modelo de dados do Qiskit for adicionado nativamente ao modelo de dados interno do Rust, permitindo que ele seja usado na API C.

    Por exemplo, você pode usar a API C para criar um estado de 1000 qubit GHZ:

    #include <qiskit.h>
    
    int main() {
        // Create an empty circuit with 1000 qubits and 1000 clbits
        QkCircuit *qc = qk_circuit_new(1000, 1000);
    
        // Add a Hadamard Gate on Qubit 0
        uint32_t one_qubit[1] = {0,};
        qk_circuit_gate(qc, QkGate_H, one_qubit, NULL); // The NULL pointer is for the parameter array.
                                                        // Since Hadamard doesn't have parameters it
                                                        // is never accessed.
    
        // Add the CX Gates:
        uint32_t qubits[2] = {0, 0};
        uint32_t num_qubits = qk_circuit_num_qubits(qc);
        for (int i = 1; i<num_qubits; i++) {
            qubits[1] = i;
            qk_circuit_gate(qc, QkGate_CX, qubits, NULL);
        }
    
        // Add the measurements:
        uint32_t num_clbits = qk_circuit_num_clbits(qc);
    
        for (uint32_t i = 0; i<num_clbits; i++) {
            qk_circuit_measure(qc, i, i);
        }
        qk_circuit_free(qc);
        return 0;
    }
  • A API C do Qiskit ( qiskit.h ) agora suporta a criação de um Target para representar um alvo de transpilação. Por exemplo:

    #include <qiskit.h>
    #include <math.h>
    
    int main() {
        // Create a Target with 3 qubits
        QkTarget *target = qk_target_new(3);
    
        // Create a Target Entry for a CX Gate
        QkTargetEntry *cx_entry = qk_target_entry_new(QkGate_CX);
        // Define properties for CX between qubits (0, 1) with a duration of 1.93e-9 sec and error rate 3.17e-10.
        uint32_t qargs[2] = {0, 1};
        qk_target_entry_add_property(cx_entry, qargs, 2, 1.93e-9, 3.17e-10);
        // Define properties for cx between qubits (1, 0) with a duration of 1.27e-9 sec and no error.
        uint32_t rev_qargs[2] = {1, 2};
        qk_target_entry_add_property(cx_entry, rev_qargs, 2, 1.27e-9, NAN);
        // Add the cx entry to the target.
        QkExitCode result_cx = qk_target_add_instruction(target, cx_entry);
        // Add global ideal Y gate entry to the target
        QkExitCode result_y = qk_target_add_instruction(target, qk_target_entry_new(QkGate_Y));
        // Create a Target entry for a Measurement with increasing duration and error as the qubit indices increase
        QkTargetEntry *measure = qk_target_entry_new_measure();
        for (uint32_t i = 0; i< qk_target_num_qubits(target); i++) {
            uint32_t q[1] = {i};
            qk_target_entry_add_property(measure, q, 1, 1e-6 * (i + 1), 1e-3 * (i + 1));
        }
        QkExitCode result_measure = qk_target_add_instruction(target, measure);
        return 0;
    }
    
  • Foi adicionado suporte para consultar as informações da versão do Qiskit a partir da API C usando as seguintes macros:

    • QISKIT_VERSION_MAJOR número da versão principal: Contém o número da versão principal.
    • QISKIT_VERSION_MINOR número da versão secundária: Contém o número da versão secundária.
    • QISKIT_VERSION_PATCH número da versão do patch: contém o número da versão do patch.
    • QISKIT_VERSION versão do arquivo: Contém uma representação numérica das informações da versão, que pode ser usada para comparações.
    • QISKIT_VERSION_NUMERIC(M,m,p) macro semelhante a uma função que retorna a versão " M.m.p " como um valor numérico, que pode ser usado para comparações.

    Por exemplo, para verificar se a versão atual é, no mínimo, 2.1.0, você pode usar:

    if (QISKIT_VERSION >= QISKIT_VERSION_NUMERIC(2, 1, 0)) {
        // Code for version 2.1.0 or later
    }
  • Compatibilidade com C++ ativada para a API C. O cabeçalho gerado agora permite chamar objetos e funções diretamente do C++. Por exemplo, um observável de 100 qubits com o termo XYZ nos primeiros 3 qubits pode ser construído como

    #include <iostream>
    #include <complex>
    #include <vector>
    #include <qiskit.h>
    
    int main() {
        uint32_t num_qubits = 100;
    
        // Use smart pointer with custom deleter to manage QkObs memory
        QkObs *obs = qk_obs_zero(num_qubits);
    
        // Construct the observable term
        std::complex<double> coeff_complex = 2.0;
        QkComplex64 coeff = qk_complex64_from_native(coeff_complex);
        std::vector<QkBitTerm> bit_terms = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
        std::vector<uint32_t> indices = {0, 1, 2};
    
        QkObsTerm term {
            .coeff      = coeff,
            .len        = bit_terms.size(),
            .bit_terms  = bit_terms.data(),
            .indices    = indices.data(),
            .num_qubits = num_qubits
        };
    
        qk_obs_add_term(obs.get(), &term);
    
        // Print observable properties
        std::cout << "num_qubits: " << qk_obs_num_qubits(obs) << "\n";
        std::cout << "num_terms: "  << qk_obs_num_terms(obs)  << "\n";
    
        qk_obs_free(obs);
        return 0;
    }

Recursos dos circuitos

  • Adicionada uma função random_circuit_from_graph() que gera um circuito aleatório que induz o mesmo gráfico de interação que o especificado por interaction_graph.

    A probabilidade de desenhar aleatoriamente uma borda do gráfico de interação como uma porta de dois qubits pode ser definida pelo usuário no atributo de peso de uma borda no gráfico de interação de entrada. Se o usuário não definir a probabilidade, cada borda será desenhada uniformemente. Ou seja, cada porta de dois qubits representada por uma borda no gráfico de interação tem a mesma probabilidade de ser adicionada ao circuito aleatório. Se apenas um subconjunto de probabilidades de borda for definido, o site ValueError será acionado.

    Neste exemplo, cp_map é uma lista de bordas com pesos arbitrários.

    from qiskit.circuit.random.utils import random_circuit_from_graph
    import rustworkx as rx
    pydi_graph = rx.PyDiGraph()
    n_q = 5
    cp_map = [(0, 1, 0.18), (1, 2, 0.15), (2, 3, 0.15), (3, 4, 0.22)]
    pydi_graph.extend_from_weighted_edge_list(cp_map)
    # cp_map can be passed in directly as interaction_graph
    qc = random_circuit_from_graph(interaction_graph = pydi_graph,
      min_2q_gate_per_edge = 1,
      max_operands = 2,
      measure = True,
      conditional = True,
      reset = True,
      seed = 0,
      insert_1q_oper = True,
      prob_conditional = 0.21,
      prob_reset = 0.1)
    qc.draw(output='mpl')
    _images/release_notes-1.png
  • Adicionado um novo método QuantumCircuit método: QuantumCircuit.has_control_flow_op() para verificar se um objeto QuantumCircuit contém alguma operação de fluxo de controle.

  • Um novo módulo qiskit.circuit.annotation e objeto principal Annotation foram adicionados.

    As anotações são uma forma de marcar instruções (atualmente apenas BoxOp) com dados locais, personalizados pelo usuário. Esses dados devem ser consumidos por passes de transpiladores personalizados. As anotações oferecem uma maneira de anexar dados a instruções específicas, em vez de usar o objeto global-context PropertySet durante a compilação.

    Todos os objetos Annotation os objetos têm um campo namespace . Essa chave de cadeia de caracteres é usada para pesquisas, de modo que os consumidores possam saber se eles lidam com uma anotação específica ou não. No momento, não há métodos para consultar qualquer semântica abstrata de uma Annotation mas espera-se que esses métodos sejam expandidos no futuro.

    Consulte qiskit.circuit.annotation para uma discussão completa sobre os recursos e casos de uso.

  • BoxOp (criadas por QuantumCircuit.box()) agora podem ser anotadas com instâncias Annotation personalizadas. A igualdade de duas caixas depende do fato de as anotações serem iguais.

    Normalmente, isso é feito passando uma lista de anotações como o único argumento posicional ao usar QuantumCircuit.box() na forma de gerenciador de contexto:

    from qiskit.circuit import annotation, QuantumCircuit
    
    class MyAnnotation(annotation.Annotation):
        namespace = "my.annotation"
    
        def __eq__(self, other):
            return isinstance(other, MyAnnotation)
    
    qc = QuantumCircuit()
    with qc.box([MyAnnotation()]):
        pass
  • O método UnitaryGate.control() agora usa internamente qs_decomposition() em vez de Isometry para a decomposição usada para definir o controle UnitaryGate. Essa alteração reduz o número de CXGate usados no definition para o ControlledGate em aproximadamente 2x.

  • Aprimorou a síntese de um sistema multicontrolado U1Gatepara que ela não cresça exponencialmente com o número de controles.

  • O atributo BoxOp.duration agora pode ser um expr.Expr com o tipo Durationassim como Delay.duration. Isso inclui também o suporte Stretch durante a duração de um BoxOp.

Recursos primitivos

OpenQASM Características

  • qasm3.dump() e qasm3.dumps() têm um novo argumento annotation_handlers , que é usado para fornecer instâncias de annotation.OpenQASM3Serializer para o processo de exportação OpenQASM 3, que pode serializar objetos Annotation personalizados para OpenQASM 3.

  • Quando o qiskit_qasm3_import>=0.6.0 estiver instalado, qasm3.load() e qasm3.loads() têm um novo argumento annotation_handlers , que é usado para fornecer instâncias de annotation.OpenQASM3Serializer para o processo de importação do OpenQASM 3, que pode desserializar objetos Annotation personalizados de OpenQASM 3. Atualmente, esse suporte está limitado a box statements, pois esse é o único lugar em que o Qiskit pode representar anotações em seu modelo de dados.

Recursos do QPY

  • Adicionado um novo formato QPY versão 15 que inclui suporte para os novos objetos Annotation com suporte de serializadores e desserializadores externos. O formato permite que esses serializadores tenham estado, e locais seguros no formato binário são alocados para os objetos de estado personalizados e representações de anotações personalizadas.

  • qpy.dump() e qpy.load() agora têm um argumento opcional annotation_factories , que é usado para fornecer funções de construtor de annotation.QPYSerializer objetos para lidar com Annotation subclasses. Eles devem ser fornecidos pelo usuário, de forma semelhante a metadata_serializer, pois, em geral, o Qiskit não pode saber sobre todos os possíveis objetos definidos externamente Annotation definidos externamente.

  • Adicionada uma nova função get_qpy_version() ao módulo qpy módulo. Essa função inspecionará um arquivo QPY e recuperará a versão do formato QPY usada na carga útil. A versão é retornada como um número inteiro, que pode ser usado para fins de registro ou depuração. veja #14201.

Recursos de informação quântica

  • Uma nova classe, PauliLindbladMapque é uma parametrização baseada em Pauli de um subconjunto de mapas lineares de operadores multiqubit, usada em aplicativos de aprendizado de ruído. Espera-se que essa classe forme a espinha dorsal de algoritmos aprimorados de aprendizado de ruído e forneça um controle melhor e mais eficiente sobre os modelos de ruído em versões futuras do Qiskit.

  • Introduziu o QubitSparsePauli e QubitSparsePauliList que representam os mesmos conceitos que Pauli e PauliList respectivamente, mas armazenam apenas termos não idênticos, de maneira análoga a SparseObservable. Essas classes destinam-se principalmente a serem usadas com o novo PauliLindbladMap.

Recursos de síntese

  • Foi adicionado um novo algoritmo de síntese para HalfAdderGate que não requer qubits auxiliares e tem melhor contagem de CX em comparação com adder_qft_d00():

  • Adicionadas novas decomposições para MCXGate utilização de ancillae limpa, melhorando a profundidade e a eficiência do circuito:

    Exemplo de uso:

    from qiskit.synthesis.multi_controlled import synth_mcx_1_clean_kg24
    
    n_ctrls = 10
    qc = synth_mcx_1_clean_kg24(n_ctrls)
    qc.draw()
  • A síntese de portas multicontroladas CZGate foi aprimorada para reduzir a contagem de portas sintetizadas; em alguns casos, é possível obter uma redução de até 99%. Isso foi feito aproveitando a síntese aprimorada em torno do MCXGate com a síntese CZGate também.

  • Aprimorou o plug-in padrão para sintetizar AnnotatedOperation objetos. O aprimoramento é especialmente útil ao criar e transpilar circuitos controlados com portas controladas dentro deles. Por exemplo:

    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import CXGate
    from qiskit.compiler import transpile
    
    inner = QuantumCircuit(5)
    inner.append(CXGate().control(3, annotated=True), [0, 1, 2, 3, 4])
    controlled_inner_gate = inner.to_gate().control(2, annotated=True)
    qc = QuantumCircuit(15)
    qc.append(controlled_inner_gate, [0, 1, 2, 3, 4, 5, 6])
    qct = transpile(qc, basis_gates=["cx", "u"])

    Esse código cria um circuito quântico qc que contém um circuito quântico de 2 controles com um CX-gate de 3 controles dentro dele. Com o aprimoramento, o número de portas CX no circuito transpilado é reduzido de 378 para 30. Observe que, ao especificar annotated=True ao definir a lógica de controle, as portas controladas são criadas como operações anotadas. Isso evita a síntese ansiosa, permite que o transpilador detecte que o controlled_inner_gate é equivalente a um X-gate com 6 controles e escolha o melhor método de síntese disponível para X-gates multicontrolados, especialmente utilizando os qubits ancilla disponíveis.

  • A função adder_qft_d00()usada para sintetizar ModularAdderGate e HalfAdderGate agora aceita um parâmetro adicional annotated. Se True, a porta QFT inversa nos somadores é implementada como uma operação anotada, permitindo que o transpilador aplique otimizações adicionais.

  • A Decomposição Quântica de Shannon (qs_decomposition()) agora inclui uma otimização que reduz a contagem de CXGate no caso de a unitária de entrada ser uma unitária controlada.

  • A função de síntese synth_mcx_1_clean_b95() agora produz um circuito com menos CX-gates.

  • A classe SolovayKitaevDecomposition agora tem argumentos adicionais no inicializador, o que permite que ela seja construída diretamente a partir de um conjunto de basis_gates e um depth para as aproximações básicas.

  • Adicionado SolovayKitaevDecomposition.save_basic_approximations() para salvar o conjunto de aproximações básicas que a classe usa em um formato binário. Essa alteração, combinada com os novos argumentos do inicializador, permite que os usuários ignorem o uso explícito de generate_basic_approximations() e confiar apenas em SolovayKitaevDecomposition.

Recursos do Transpiler

  • A função generate_preset_pass_manager() agora gera um gerenciador de passagem especial quando o conjunto de base consiste apenas em portas Clifford+T. Formalmente, um conjunto de bases de Clifford+T deve conter apenas portas de Clifford, juntamente com TGate, TdgGate, ou ambos. A lista completa de portas Clifford suportadas pode ser obtida usando get_clifford_gate_names().

    Por exemplo:

    from qiskit.circuit import QuantumCircuit
    from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
    from qiskit.quantum_info import get_clifford_gate_names
    
    basis_gates = get_clifford_gate_names() + ["t", "tdg"]
    pm = generate_preset_pass_manager(basis_gates=basis_gates)
    
    qc = QuantumCircuit(1)
    qc.rx(0.8, 0)
    qct = pm.run(qc)
    print(qct.count_ops())

    Resultaria em:

    OrderedDict([('h', 10210), ('t', 4508), ('tdg', 4503), ('sdg', 943), ('s', 941)])

    Anteriormente, o gerenciador de passagens gerado não conseguia lidar com o exemplo acima porque não conseguia decompor portas de rotação de um único qubit em portas Clifford+T UGate em portas Clifford+T. Entretanto, o novo gerenciador de passagens usa a decomposição Solovay-Kitaev para aproximar as portas de rotação de um único qubit usando as portas H, T e Tdg e chama a passagem BasisTranslator transpiler para traduzir ainda mais as portas para o conjunto de base de destino. O novo gerenciador de passagens também tem outras alterações para permitir uma tradução mais eficiente em portas Clifford+T.

    É importante observar que o conjunto de portas de base Clifford+T especificado deve ser universal, caso contrário, a transpilação pode não ser bem-sucedida. Embora o conjunto de portas ["h", "t", "tdg"] ou mesmo ["h", "t"] seja suficiente para a universalidade, recomenda-se adicionar mais portas Clifford ao conjunto, se possível, pois, caso contrário, a tradução poderá ser menos eficiente. Por exemplo, se a porta S não for incluída, as portas S poderão ser decompostas em pares de portas T (ou seja, as portas Clifford poderão ser decompostas em portas não-Clifford, o que pode não ser o comportamento desejado).

    A seguir, um exemplo um pouco maior:

    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import QFTGate
    from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
    
    qc = QuantumCircuit(4)
    qc.append(QFTGate(4), [0, 1, 2, 3])
    
    basis_gates = ["cx", "s", "sdg", "h", "t", "tdg"]
    pm = generate_preset_pass_manager(basis_gates=basis_gates, optimization_level=2)
    
    qc = QuantumCircuit(4)
    qc.append(QFTGate(4), [0, 1, 2, 3])
    
    qct = pm.run(qc)
    print(qct.count_ops())

    Resultaria em:

    OrderedDict([('h', 96510), ('tdg', 42396), ('t', 42389), ('s', 8240), ('sdg', 8235), ('cx', 12)])
  • Adição de um novo plug-in de síntese de alto nível HalfAdderSynthesisR25 para sintetizar um arquivo HalfAdderGate. O novo plug-in é baseado em adder_ripple_r25().

    O HalfAdderSynthesisDefault também foi atualizado para seguir a seguinte sequência de sintetizadores de meio somador: "HalfAdder.ripple_r25" quando há 3\leq 3 qubits, "HalfAdder.ripple_c04" quando um qubit auxiliar está disponível e "HalfAdder.ripple_r25" em todos os casos restantes.

  • Foram adicionados vários plug-ins de síntese de alto nível para sintetizar um MCXGate:

    A classe MCXSynthesisDefault também foi atualizada para executar a seguinte sequência de métodos de síntese do MCX até que o primeiro seja bem-sucedido: : "mcx.2_clean_kg24", "mcx.1_clean_kg24", "mcx.n_clean_m15", "mcx.n_dirty_i15"`, ``"mcx.2_dirty_kg24", "mcx.1_dirty_kg24", "mcx.1_clean_b95", "mcx.noaux_v24". Os métodos são ordenados de forma que os de melhor qualidade sejam aplicados primeiro.

  • VF2PostLayout foi adicionado ao final do estágio de otimização padrão ao usar o nível de otimização 3.

  • Adicionada uma nova passagem de otimização do OptimizeCliffordT que mescla pares de T-gates consecutivos em S-gates e pares de Tdg-gates consecutivos em Sdg-gates. Essa otimização é particularmente eficaz para reduzir a contagem de T após a decomposição de Solovay-Kitaev, que produz várias portas T ou Tdg consecutivas. Por exemplo:

    from qiskit.circuit import QuantumCircuit
    from qiskit.transpiler.passes import SolovayKitaev, OptimizeCliffordT
    
    qc = QuantumCircuit(1)
    qc.rx(0.8, 0)
    
    # Run Solovay-Kitaev pass on qc
    transpiled = SolovayKitaev()(qc)
    print(transpiled.count_ops().get("t", 0) + transpiled.count_ops().get("tdg", 0))
    # Should print 12779
    
    # Run Clifford+T optimization
    optimized = OptimizeCliffordT()(transpiled)
    print(optimized.count_ops().get("t", 0) + optimized.count_ops().get("tdg", 0))
    # Should print 9011
  • Adicionado o passe ContextAwareDynamicalDecoupling que implementa um desacoplamento dinâmico sensível ao contexto com base em sequências Walsh-Hadamard. As sequências de atraso inseridas serão mutuamente ortogonais às sequências nos qubits vizinhos e levarão em conta os espectadores de controle/alvo das portas CX e ECR. Consulte arXiv:2403.06852 para obter mais informações.

    Exemplo:

    from qiskit.circuit.library import QFT
    from qiskit.transpiler import PassManager, CouplingMap
    from qiskit.transpiler.passes import ALAPScheduleAnalysis, ContextAwareDynamicalDecoupling
    from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
    from qiskit.providers.fake_provider import GenericBackendV2
    
    num_qubits = 10
    circuit = QFT(num_qubits)
    circuit.measure_all()
    
    target = GenericBackendV2(
        100,
        basis_gates=["id", "rz", "sx", "x", "ecr"],
        coupling_map=CouplingMap.from_grid(10, 10)
    ).target
    
    pm = generate_preset_pass_manager(optimization_level=2, target=target)
    dd = PassManager([
        ALAPScheduleAnalysis(target=target),
        ContextAwareDynamicalDecoupling(target=target),
    ])
    
    transpiled = pm.run(circuit)
    with_dd = dd.run(transpiled)
    
    with_dd.draw("mpl", idle_wires=False)
    _images/release_notes-2.png
  • Foram adicionados os seguintes atributos à classe DAGCircuit para permitir a consulta do número de variáveis de extensão: num_stretches, num_captured_stretches e num_declared_stretches.

  • Adicionado um novo plug-in de síntese unitária CliffordUnitarySynthesis que tenta sintetizar uma determinada porta unitária verificando se ela pode ser representada por um Clifford e, nesse caso, retorna um circuito que implementa essa unitária e consiste apenas em portas Clifford.

    O plug-in é chamado pela passagem UnitarySynthesis transpiler pass quando o parâmetro method é definido como "clifford".

    Além disso, o parâmetro plugin_config de UnitarySynthesis pode ser usado para passar os seguintes parâmetros específicos do plug-in:

    • min_qubits: o número mínimo de qubits a ser considerado (o valor padrão é 1).
    • max_qubits: o número máximo de qubits a ser considerado (o valor padrão é 3).

    Por exemplo:

    import math
    
    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import UnitaryGate
    from qiskit.quantum_info import Operator
    from qiskit.transpiler.passes import UnitarySynthesis
    
    # clifford unitary over 2 qubits
    c2 = QuantumCircuit(2)
    c2.h(0)
    c2.rz(math.pi / 4, 1)
    c2.rz(math.pi / 4, 1)
    c2.sdg(1)
    uc2 = UnitaryGate(Operator(c2).data)
    
    # non-clifford unitary over 2 qubits
    n2 = QuantumCircuit(2)
    n2.h(0)
    n2.rz(math.pi / 4, 1)
    n2.sdg(1)
    un2 = UnitaryGate(Operator(n2).data)
    
    # quantum circuit with two unitary gates
    qc = QuantumCircuit(3)
    qc.append(uc2, [2, 1])
    qc.append(un2, [0, 2])
    
    transpiled = UnitarySynthesis(method="clifford")(qc)
    transpiled.draw("mpl")
    _images/release_notes-3.png

    A execução do código acima ressintetiza a primeira porta unitária em portas Clifford, enquanto a segunda porta permanece inalterada.

    Se modificarmos o exemplo acima da seguinte forma:

    config = {"min_qubits": 3}
    transpiled = UnitarySynthesis(method="clifford", plugin_config=config)(qc)

    então ambas as portas unitárias permanecem inalteradas.

Recursos de visualização

  • Introduzimos estilos personalizados para a função dag_drawer() função. Isso permite que você passe um dicionário para o parâmetro style com atributos personalizados que alteram o estilo do DAG que a função retorna. Por exemplo:

    from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
    from qiskit.converters import circuit_to_dag
    from qiskit.visualization import dag_drawer
    
    q = QuantumRegister(3, 'q')
    c = ClassicalRegister(3, 'c')
    circ = QuantumCircuit(q, c)
    circ.h(q[0])
    circ.cx(q[0], q[1])
    circ.measure(q[0], c[0])
    circ.rz(0.5, q[1]).c_if(c, 2)
    
    dag = circuit_to_dag(circ)
    
    style = {
        "inputnodecolor": "pink",
        "outputnodecolor": "lightblue",
        "opnodecolor": "red",
    }
    
    dag_drawer(dag, style=style)

Notas da Atualização

  • A biblioteca python-dateutil não é mais uma dependência do Qiskit. Como o Qiskit v2.0 nada na biblioteca estava usando o python-dateutil e o Qiskit não dependia mais da biblioteca. Esta versão o remove da lista de dependências para que não seja instalado automaticamente como um pré-requisito para usar o Qiskit. Se você estava contando com o Qiskit para instalar o dateutil como uma dependência, agora precisará garantir que está instalando-o manualmente (o que é uma prática recomendada para dependências diretas).

  • sympy não é mais um requisito para a instalação do Qiskit. Após a migração para um mecanismo simbólico baseado em Rust para a classe ParameterExpression os usos do SymPy estão isolados em alguns utilitários de visualização, na passagem do TemplateOptimization passagem do transpilador, ParameterExpression.sympify() (que é explicitamente para a interoperabilidade do SymPy ) e SparsePauliOp.simplify() se estiver usando coeficientes parametrizados. Essa funcionalidade não é a mais usada, portanto, o SymPy agora é tratado como uma dependência opcional e essas funções gerarão uma MissingOptionalLibraryError se forem usadas e o SymPy não estiver instalado.

  • A dependência de symengine que era usada para criar objetos ParameterExpression foi removida. Ele foi substituído por um mecanismo simbólico interno e não é mais necessário para a funcionalidade principal do Qiskit. A única exceção é que o symengine foi incorporado aos formatos QPY 10, 11 e 12, portanto, ainda é necessário se você estiver desserializando esses formatos. A dependência do symengine para o qpy.load() foi explicitamente tornada opcional em 2.0.0, mas se você dependia anteriormente da instalação do symengine por padrão para essa funcionalidade, agora precisará instalá-lo manualmente para carregar a carga útil. Se você estivesse usando ParameterExpression.sympify() para obter um objeto de expressão de mecanismo de simulação de um objeto ParameterExpression isso agora retornará uma expressão sympy . Se você precisar usar isso com o symengine, poderá aproveitar o symengine.sympify para converter a expressão sympy em uma expressão do symengine.

Notas sobre atualização de circuitos

  • O atributo definition do atributo HalfAdderGate foi alterado para usar internamente adder_ripple_r25() para gerar a definição da porta para um circuito mais eficiente sem qubits auxiliares. Se a definição antiga for desejada por algum motivo, você poderá usar diretamente a função adder_qft_d00() que gerará um circuito equivalente ao que definition retornaria em versões anteriores.

  • O circuito retornado pela função excitation_preserving() e pela classe ExcitationPreserving agora são construídos usando um único circuito XXPlusYYGate. Essa é uma mudança em relação às versões anteriores que usavam um RXXGate seguido de um RYYGate. Essa nova construção de circuito é equivalente, mas usa menos portas que, por definição, preservam a excitação de forma mais simples.

  • Os definition atributos de várias portas padrão foram atualizados de acordo com os seguintes princípios:

    • Quando disponível, uma definição que use portas Clifford é preferível a definições que incluam portas não-Clifford.
    • Quando disponível, uma definição que usa portas Clifford+T é preferível a uma que usa um UGate.
    • O uso de PhaseGate é preferível a U1Gate.
    • O uso de UGate é preferível a `U2Gate e `U3Gate.

    Crucialmente, o seguinte invariante ainda se mantém: ao expandir recursivamente as definições de porta, qualquer porta pode ser expressa usando apenas a base ["cx", "u"] . As definições de todas as portas padrão são todas equivalentes, portanto, nenhuma semântica por trás das portas muda, apenas a construção exata do circuito retornado para algumas portas não é mais exatamente a mesma. Essa alteração foi necessária para dar suporte à transpilação de Clifford+T.

  • O Qiskit agora usa sua própria biblioteca de expressão simbólica baseada em Rust para implementar os componentes internos do ParameterExpression e Parameter. Como esta é uma nova implementação do mecanismo de matemática simbólica principal usado para o ParameterExpression pode haver pequenas diferenças no comportamento exato de algumas funcionalidades. Ele deve sempre produzir resultados equivalentes para a API documentada. Abra uma issue se houver algum problema de correção encontrado.

Notas sobre a atualização da API C

  • A forma como os números complexos são expostos na API C do Qiskit foi alterada. Anteriormente, QkComplex64 era um typedef dependente do compilador que permitia passar tipos complexos nativos por ponteiro para a API do Qiskit (por exemplo, como double complex*). Embora isso fosse conveniente, essa abordagem dependia implicitamente de suposições de layout de memória que não são estritamente garantidas.

    O Qiskit v2.1 agora expõe o QkComplex64 { double re; double im; } como um struct, para garantir que o layout da memória seja sempre compatível e para obter um suporte mais amplo do compilador. Por conveniência, são fornecidos os conversores dependentes do compilador qk_complex64_from_native e qk_complex64_to_native , que permitem a conversão do struct para um número complexo nativo. Observe que isso só funciona em plataformas compatíveis com double complex ou para compiladores MSVC que usam _Dcomplex.

    Por exemplo:

    #include <qiskit.h>
    #include <math.h>
    #include <stdio.h>
    #include <complex.h>
    
    int main(int argc, char *argv[]) {
        // platform-independent constructions:
        QkComplex64 coeff = {5.0, 3.0};
    
        // ... or using converter
        // double complex native = 5.0 + I * 3; // uses C11 standard, does not work on MSVC
        // QkComplex64 coeff = qk_complex64_from_native(&native);  // convert from native
    
        uint32_t num_qubits = 100;
        QkObs *obs = qk_obs_zero(num_qubits);
        QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
        uint32_t indices[3] = {0, 1, 2};
        QkObsTerm term = {coeff, 3, bit_terms, indices, num_qubits};
        qk_obs_add_term(obs, &term);
        printf("num_qubits: %u\n", qk_obs_num_qubits(obs));
        printf("num_terms: %lu\n", qk_obs_num_terms(obs));
    
        qk_obs_free(obs);
        return 0;
    }

Notas de atualização do QPY

  • A versão padrão do QPY emitida por qpy.dump() foi alterada para a versão 15 mais recente do QPY. Se você precisar gerar uma versão de formato mais antiga por algum motivo, poderá usar o argumento da palavra-chave version em qpy.dump() para especificar uma versão mais antiga a ser gerada.

Notas sobre a atualização da síntese

  • O formato de serialização para aproximações básicas nos algoritmos Solovay-Kitaev foi alterado de .npy para outro formato binário, com base em serde e bincode do Rust. Todas as rotinas que carregam aproximações básicas (como generate_basic_approximations(), SolovayKitaevDecomposition.load_basic_approximations() ou o inicializador de SolovayKitaev) ainda suportam o carregamento do formato legado. Qualquer novo arquivo, entretanto, será armazenado no novo formato. Se você dependia do formato antigo, faça o downgrade do Qiskit para < 2.2 e armazene os arquivos necessários.

  • Os valores padrão para SolovayKitaev (e classes relacionadas) aumentaram para depth=12 e reps=5. Isso se deve ao fato de a implementação subjacente estar agora em Rust, o que nos permite aumentar a precisão padrão e, ao mesmo tempo, ser significativamente mais rápida do que a versão anterior do Python.

Notas sobre a atualização do Transpiler

  • Os plug-ins de layout integrados para os gerenciadores de passagem atuais não conterão mais seu componente principal (por exemplo, uma instância SabreLayout para o estágio "sabre" ) se não forem fornecidas restrições de acoplamento. Anteriormente, os plug-ins construíam instâncias inválidas de suas passagens de layout, supondo que a lógica separada impediria que as passagens fossem executadas e gerassem exceções.

    Isso não deve ter nenhum efeito significativo sobre o uso dos gerenciadores de passes predefinidos ou dos plug-ins, pois nunca foi válido chamar os passes em um estado inválido.

Notas de descontinuação

  • O suporte para a execução do Qiskit com Python 3.9 foi descontinuado e será removido na versão do Qiskit v2.3. A versão 2.3.0 é a primeira versão após Python 3.9 entrar em fim de vida útil e não ter mais suporte [1]. Isso significa que, a partir da versão 2.3.0, será necessário atualizar a versão Python que você está usando para Python 3.9 ou superior.

    [1] https://devguide.python.org/versions/

Circuitos obsoletos

Correções de bugs

  • Corrigido um bug na função dag_drawer() e no método DAGCircuit.draw() em que a definição do argumento da palavra-chave style=plain não mostrava rótulos de circuito para os nós do DAG na visualização.

  • Foi corrigido um erro no método QuantumCircuit.assign_parameters() em que os parâmetros que não eram usados no circuito e eram passados como cadeias de caracteres não eram ignorados quando o argumento strict=False era definido. Consulte a edição nº 13933 para obter mais detalhes.

  • Correção de casos extremos na configuração do Makefile para Windows, em que a variável de ambiente predefinida OS não correspondia à saída do comando uname -s .

  • Corrigido o atributo name do atributo OrGateque anteriormente estava incorretamente definido como a cadeia de caracteres "and" em vez do valor esperado "or" , que agora é retornado. Esse valor incorreto "and" entrava em conflito com o AndGate.name e poderia ter levado a vários problemas relacionados ao uso do Orgate e a diferenciá-lo de um AndGate.

  • Foi corrigido um bug na função qpy.load() em que podia ocorrer falha na desserialização de circuitos cujos parâmetros haviam sido reatribuídos a parâmetros com os mesmos nomes. Corrigidos os números 13720, 13720 e 13720.

  • Corrigido o GenericBackendV2 para incluir agora BoxOp como um tipo de instrução compatível no GenericBackendV2.target quando o argumento da palavra-chave control_flow=True é definido no construtor.

  • Ao sintetizar uma porta MCXGate porta com 3 controles, a função de síntese synth_mcx_n_dirty_i15() costumava exigir um qubit auxiliar, produzindo um circuito com 5 qubits (3 de controle, 1 de destino e 1 auxiliar). Entretanto, o algoritmo de síntese real não faz uso desse qubit auxiliar. Esse comportamento agora foi corrigido: o circuito sintetizado tem mais de 4 qubits (3 de controle e 1 de destino), permitindo que a função de síntese seja aplicada em um número um pouco maior de casos.

  • O QuantumCircuit.draw() e circuit_drawer() agora renderizará as instruções BoxOp instruções em um QuantumCircuit na mesma fatia vertical se os vãos verticais não se sobrepuserem, agora são renderizadas na mesma fatia vertical, quando possível.

  • Corrigido o método QuantumCircuit.draw() e a função circuit_drawer() no modo "mpl" para inserir menos espaço estranho dentro da borda esquerda ao desenhar BoxOp instâncias em um QuantumCircuit.

Outras observações

  • Adição de um novo alvo de dependência extra opcional qpy-compat. Esse destino deve ser usado se você planeja carregar arquivos qpy arquivos usando formatos QPY mais antigos. O destino instala requisitos extras usados para carregar arquivos QPY usando versões de formato < 13. If you are only using newer QPY format versions you do no need to install this. The qpy.dump() only generates QPY > =13 Isso só é necessário para carregar arquivos gerados com versões mais antigas (anteriores a 2.0.0 ) do Qiskit. Você pode instalar essa nova variante opcional com pip install qiskit[qpy-compat].

  • Os pesos relativos dos componentes "básico" e "antecipado" do SabreSwap e SabreLayout foram modificados quando o rastreamento de conjunto estendido está ativo (como sempre está em SabreLayoute, por padrão, está em SabreSwap). O componente heurístico relacionado à distância entre os qubits em uma porta individual na camada frontal agora não é mais enfraquecido proporcionalmente ao número de portas na camada frontal; esse comportamento foi uma escolha histórica, mas, em circuitos grandes, tem o efeito acidental de fazer com que a camada frontal seja praticamente ignorada, o que é desastroso para a eficiência.

    As melhorias de roteamento resultantes devem ser mais perceptíveis para circuitos que podem ser estratificados com frequência em camadas de mais de 20 portas paralelas de dois qubits.

Esta página foi útil?
Relate um bug, erro de digitação ou solicite conteúdo no GitHub.