Skip to main content
IBM Quantum Platform

Notas de versão do Qiskit SDK 1.3


1.3.3

Prelúdio

O Qiskit 1.3.3 é uma versão menor de correção de bugs para a série 1.3.

Correções de bugs

  • Foi corrigido um erro que fazia com que os rótulos das barreiras fossem posicionados incorretamente ao usar o parâmetro reverse_bits = True no método QuantumCircuit.draw() método. O bug fazia com que os rótulos das operações de barreira ficassem desalinhados, o que poderia causar confusão nas visualizações de circuitos. Corrigido #13609.

  • Aplicou um pequeno fator de regularização contra matrizes hermitianas mal condicionadas em representações de superoperadores.

  • As comparações de Delay incluindo aquelas dentro de circuitos, agora exigem que as unidades e o valor de duração sejam iguais. Correções #13812.

  • Corrigido um bug no CommutationChecker que poderia falhar ao verificar a relação de comutação de uma rotação Pauli de dois qubits com uma porta que não está no cache de comutação. Por exemplo:

    import numpy as np
    from qiskit.circuit.library import RXXGate, RGate
    from qiskit.circuit.commutation_library import SessionCommutationChecker as scc
    
    res = scc.commute(RGate(2, 2), [1], [], RXXGate(np.pi / 2), [0, 1], [])

    Esse comportamento foi resolvido e a relação de comutação foi calculada corretamente. Corrigido #13742.

  • Foi corrigido um bug em que QuantumCircuit.qubit_stop_time() e QuantumCircuit.qubit_duration() retornava um tempo (duração) incorreto. O problema era acionado quando alguns qubits tinham instruções, mas outros qubits estavam ociosos. Correções #8729.

  • Foi corrigido um bug na passagem do RemoveIdentityEquivalent em que as portas próximas à identidade até uma fase global eram removidas do circuito, mas a fase global do circuito não era atualizada. Em particular, RemoveIdentityEquivalent agora remove os GlobalPhaseGate não parametrizados. Correções #13778.

  • Corrigido um erro no random_clifford() que impedia a amostragem do grupo Clifford completo. Correções #13606.

  • Quando SabreLayout é usado para fazer o layout e o roteamento simultaneamente (como é o caso das opções padrão para transpile() e generate_preset_pass_manager()) em um arquivo Target ou CouplingMap com conectividade disjunta, e o circuito de entrada se encaixa em um único componente do mapa de acoplamento, a permutação de roteamento agora será rastreada corretamente.

    Anteriormente, quaisquer qubits no mapa de acoplamento que não estivessem conectados, mesmo que indiretamente, a um qubit usado pelo circuito roteado não seriam incluídos na permutação de roteamento final. Isso pode causar um comportamento surpreendente a uma grande distância do ponto de falha, mesmo que a compilação pareça ter sido bem-sucedida, como chamadas para TranspileLayout.final_index_layout() raising KeyError.

    Esse bug não afetou os back-ends que estavam totalmente conectados, como a maioria deles. Correções #13732.


1.3.2

Prelúdio

O Qiskit 1.3.2 é uma versão menor de correção de bugs para a série 1.3.

Notas sobre a atualização da síntese

  • Os plug-ins de síntese de alto nível para LinearFunction não geram mais um erro quando um objeto diferente de LinearFunction é passado para o método run . Em vez disso, eles agora retornam None, o que é consistente com outros plug-ins. Se você confiou na ocorrência desse erro, pode executar manualmente uma verificação de instância.

Correções de bugs

  • Anteriormente, o CommutationChecker armazenava em cache as relações de comutação de Instructions com float-only params como chave para consultar a relação. Isso poderia levar a resultados incorretos se a definição da instrução dependesse de informações adicionais além do atributo params como, por exemplo, no caso do atributo PauliEvolutionGate. Esse comportamento foi corrigido, e o verificador de comutação armazena em cache as comutações apenas para portas padrão nativas do Qiskit. Para portas personalizadas, essa alteração pode acarretar um custo de desempenho; no entanto, garante resultados corretos ao evitar o armazenamento em cache inseguro.

  • Foi corrigido um bug no CommutationCheckeronde a verificação das relações de comutação de uma instrução com valores não numéricos no atributo params (como no caso de PauliGate) poderia gerar um erro. Corrigido #13570.

  • O CommutationChecker não lidou corretamente com as comutações de CRXGate, CRYGate e CRZGate para ângulos de rotação da forma (4k+2)π(4k + 2)\pi, com kZk \in \mathbb Z. Nesses casos, presumiu-se incorretamente que essas portas comutam com qualquer porta. Agora, esse comportamento foi corrigido e essas portas são comutadas corretamente com qualquer porta somente quando o ângulo de rotação é um múltiplo de 4π4\pi.

  • Foi corrigido um bug que fazia com que as seguintes funções da biblioteca de circuitos produzissem erros quando chamadas com num_qubits=1: efficient_su2(), real_amplitudes(), excitation_preserving() e pauli_two_design() (para um único qubit, esses circuitos não contêm nenhuma porta de 2 qubit). Corrigido #13480.

  • Foi corrigido um bug em que qualquer instrução chamada "mcmt" era incorretamente passada para a rotina de síntese de alto nível para um MCMTGatelevando a uma falha ou a um resultado inválido. Esse problema pode ocorrer, por exemplo, ao manipular o circuito MCMT chamado "mcmt", e convertendo-o implicitamente em uma instrução (por exemplo, ao anexá-lo a outro circuito ). Corrigido #13563.

  • Foi corrigido um bug em que a síntese de fórmula de produto padrão para PauliEvolutionGate não lidava corretamente com todos os termos de identidade no operador. O termo de identidade total deveria introduzir uma fase global igual a -evolution_time, mas estava fora de um fator de 2 e poderia quebrar em tempos parametrizados. Corrigido #13625. Corrigido #13675. Corrigido #13644.

  • Foi corrigida uma inconsistência no circuito gerado pela síntese de evolução de Pauli usando SuzukiTrotter ou LieTrotter (o método padrão). Para tempos de evolução parametrizados, os circuitos resultantes continham parâmetros com uma parte complexa zero espúria, que afetava a saída de ParameterExpression.sympify(). A saída agora contém corretamente apenas valores reais. Corrigido #13642.

  • Corrigido um bug que fazia com que o PauliList.insert() com qubit=True produzisse um atributo de fase com a forma errada quando o objeto original tinha comprimento 1. Corrigido #13623.

  • Foi corrigido um bug no qasm3.Exporter que fazia com que o exportador travasse ao lidar com uma porta unitária devido a um processamento incorreto de seu campo params . Corrigido #13362.

  • Foi corrigido um erro no método Target.instruction_supported() em que os alvos com self.num_qubits==None sempre retornavam False , independentemente do conjunto de base suportado.

  • Foi corrigido um bug na passagem do UnitarySynthesis onde blocos de UnitaryGates em 3 qubits ou mais não eram sintetizados corretamente. Isso levou, por exemplo, ao fato de o circuito ser substituído pelo último bloco processado ou a panes internas ao encontrar medições após esse bloco. Corrigido #13586.

  • Corrigido um bug na passagem do UnitarySynthesis em que non-2-qubit gates seriam incluídos na base de 2 qubit disponível, fazendo com que o TwoQubitWeylDecomposition entrasse em pânico devido à incompatibilidade de dimensão.

  • Corrigido um bug em que a inicialização de SparsePauliOp com um grande número de termos de Pauli-Y (normalmente 100\geq 100 ) e nenhum coeffs explícito resultava em um coeficiente próximo a 1, mas com um erro de ponto flutuante. O coeficiente agora é corretamente 1 por padrão. Corrigido #13522.


1.3.1

Prelúdio

O Qiskit 1.3.1 é uma versão menor de correção de bugs para a série 1.3.

Notas sobre atualização de circuitos

  • O método de controle genérico para portões agora evita a tentativa de traduzir portões em uma base compatível quando o portão já é compatível. Isso pode alterar ligeiramente a síntese da porta controlada, mas não deve aumentar a contagem da porta de dois qubits.

Correções de bugs


1.3.0

Prelúdio

A versão do Qiskit 1.3.0 traz grandes melhorias de desempenho e qualidade para o transpilador. Foram introduzidos muitos novos recursos, correções e aprimoramentos nessa nova versão do Qiskit, com destaque para os seguintes:

  • As principais estruturas de dados para transpilação no Qiskit foram portadas internamente para o Rust. Isso inclui componentes como o DAGCircuit, Target, EquivalenceLibrary, e outros. As APIs públicas para todas essas estruturas de dados permanecem inalteradas, mas o desempenho após as reescritas melhorou.

  • A maioria das passagens do transpilador usadas pelo gerenciador de passagens predefinidas foi portada para o Rust, resultando em uma melhoria média de 6x no tempo de execução geral em comparação com o Qiskit 1.2.4 ao executar os benchmarks de benchpress. Alguns dos passes particularmente impactantes que se beneficiaram muito com as reescritas foram o BasisTranslator, CommutationAnalysis, ConsolidateBlocks, e UnitarySynthesis. Você pode consultar as notas de versão do recurso para obter uma lista completa dos passes portados.

  • Aprimoramentos na biblioteca de circuitos que aumentam a qualidade da compilação e a velocidade de construção de circuitos. As operações agora são diferenciadas em:

    • Operações estruturais, que têm uma decomposição exclusiva e são representadas como funções que retornam um QuantumCircuit (por exemplo: real_amplitudes()). A maioria dessas funções é construída em Rust, resultando em um tempo de execução de construção de circuito significativamente mais rápido.
    • As operações abstratas, que podem ser implementadas usando diferentes decomposições, são representadas como Gate ou Instruction (por exemplo: PauliEvolutionGate). Isso permite criar um circuito quântico abstrato e deixar que o compilador escolha a decomposição ideal.

    O uso de uma descrição abstrata do circuito é especialmente eficiente em combinação com os aprimoramentos da passagem do HighLevelSynthesis que agora pode levar em conta os qubits auxiliares ociosos para encontrar a melhor decomposição disponível para uma determinada porta.

  • A versão mínima compatível com Python agora é 3.9, pois Python 3.8 teve sua vida útil encerrada em 2024-10. O suporte oficial para Python 3.13 também foi adicionado nesta versão.

Recursos dos circuitos

  • Aprimoramos a funcionalidade do CommutationChecker para incluir suporte às seguintes portas parametrizadas com parâmetros livres: RXXGate, RYYGate, RZZGate, RZXGate, RXGate, RYGate, RZGate, PhaseGate, U1Gate, CRXGate, CRYGate, CRZGate, CPhaseGate. Antes, eles eram compatíveis apenas com parâmetros vinculados.

  • Adicionada uma nova função quantum_volume() para gerar um objeto de volume quântico QuantumCircuit conforme definido em A. Cross et al. Validação de computadores quânticos usando circuitos de modelos aleatórios, Phys. Rev. A 100, 032328 (2019). Essa nova função difere da classe QuantumVolume existente, pois retorna um objeto QuantumCircuit em vez de criar um objeto de subclasse. A segunda é que essa nova função é multithread e implementada em rust, portanto, gera o circuito de saída ~10x mais rápido do que a classe QuantumVolume classe.

  • Melhorou o desempenho do tempo de execução da construção da classe QuantumVolume com o argumento classical_permutation definido como True. Internamente, ele agora chama a função quantum_volume() que é escrita em Rust e é ~10x mais rápida ao gerar um circuito de volume quântico.

  • Adicionada uma nova função de manipulação de circuito pauli_twirl_2q_gates() que pode ser usada para aplicar o giro de Pauli a um determinado circuito. Isso só funciona para girar um conjunto fixo de portas de dois qubits, atualmente CXGate, ECRGate, CZGate, iSwapGate. Por exemplo:

    from qiskit.circuit import QuantumCircuit, pauli_twirl_2q_gates
    
    qc = QuantumCircuit(2)
    qc.cx(0, 1)
    twirled_circuit = pauli_twirl_2q_gates(qc, seed=123456)
    twirled_circuit.draw("mpl")
    _images/release_notes-1.png
  • Adicionadas portas aritméticas binárias para adição no local de dois registros nn -qubit, ou seja, abaa+b|a\rangle |b\rangle \mapsto |a\rangle |a+b\rangle. A porta ModularAdderGate implementa o módulo de adição 2n2^n, o HalfAdderGate inclui um qubit de carry-out, e o FullAdderGate inclui um qubit de carry-in e um qubit de carry-out. Consulte a respectiva documentação para obter detalhes e exemplos.

    Em contraste com os circuitos de biblioteca existentes, como o CDKMRippleCarryAddero manuseio da porta abstrata permite que o compilador (ou usuário) selecione a síntese de porta ideal, dependendo do contexto do circuito.

  • Adicionado o MultiplierGate para multiplicação de dois registros nn -qubit, ou seja, ab0abab|a\rangle |b\rangle |0\rangle \mapsto |a\rangle |b\rangle |a \cdot b\rangle. Consulte a documentação da classe para obter detalhes e exemplos.

  • Os circuitos quânticos de lógica booleana em qiskit.circuit.library agora têm representações equivalentes como objetos Gate permitindo seu uso com a HighLevelSynthesis passagem de transpilador e infraestrutura de plug-in.

  • Implementações especializadas de __eq__() foram adicionadas para todas as portas de circuito da biblioteca padrão. A maioria dos portões padrão já era especializada nesse método, mas alguns não eram, o que poderia causar lentidão significativa em locais inesperados.

  • Adicionado evolved_operator_ansatz(), hamiltonian_variational_ansatz(), e qaoa_ansatz() à biblioteca de circuitos para implementar circuitos variacionais com base em evoluções de operadores. evolved_operator_ansatz() e qaoa_ansatz() são funcionalmente equivalentes a EvolvedOperatorAnsatz e QAOAAnsatzmas geralmente com melhor desempenho.

    O hamiltonian_variational_ansatz() foi projetado para pegar um único Hamiltoniano e dividi-lo automaticamente em termos comutáveis para implementar um ansatz variacional Hamiltoniano. Isso já podia ser feito manualmente usando o botão EvolvedOperatorAnsatzmas agora é mais conveniente de usar.

  • Adicionado grover_operator() para construir um circuito de operador de Grover, usado no algoritmo de Grover e na estimativa/amplificação de amplitude, por exemplo. Essa função é semelhante à GroverOperatormas não exige que você escolha a implementação da porta X multicontrolada e, em vez disso, permite que o compilador determine a decomposição ideal. Além disso, ele não envolve o circuito em uma porta opaca e é mais rápido porque são necessárias menos decomposições para a transpilação.

    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import grover_operator
    
    oracle = QuantumCircuit(2)
    oracle.z(0)  # good state = first qubit is |1>
    grover_op = grover_operator(oracle, insert_barriers=True)
    grover_op.draw('mpl')
    _images/release_notes-2.png
  • Um novo atributo de dados, qiskit.circuit.CONTROL_FLOW_OP_NAMESestá disponível para localizar e verificar facilmente se uma determinada Instruction é uma operação de fluxo de controle por nome.

  • A biblioteca de equivalência padrão (SessionEquivalenceLibrary) agora tem regras que podem converter diretamente entre a biblioteca padrão do Qiskit 2q interações contínuas do tipo Ising (por exemplo CPhaseGate, RZZGate, RZXGate, e assim por diante) usando relações de equivalência local. Anteriormente, várias dessas conversões eram feitas por meio de um formulário 2-CX, o que resultava em uma geração de circuitos menos eficiente.

    Nota

    Em geral, o BasisTranslator não tem a garantia de encontrar a "melhor" relação de equivalência para um determinado Targetmas sempre encontrará uma equivalência se ela existir. Contamos com passagens de ressíntese e otimização de porta mais caras no transpilador para melhorar o resultado. Atualmente, essas passagens não são tão eficazes para conjuntos de bases com uma interação de dois qubits continuamente parametrizada quanto para interações discretas de dois qubits supercontroladas.

  • Foi adicionado um novo argumento "apply_synthesis" a Decomposeque permite que a passagem do transpilador aplique a síntese de alto nível para decompor objetos que são definidos apenas por uma rotina de síntese. Por exemplo:

    from qiskit import QuantumCircuit
    from qiskit.quantum_info import Clifford
    from qiskit.transpiler.passes import Decompose
    
    cliff = Clifford(HGate())
    circuit = QuantumCircuit(1)
    circuit.append(cliff, [0])
    
    # Clifford has no .definition, it is only defined by synthesis
    nothing_happened = Decompose()(circuit)
    
    # this internally runs the HighLevelSynthesis pass to decompose the Clifford
    decomposed = Decompose(apply_synthesis=True)(circuit)
  • Adicionada a função iqp() para construir circuitos de tempo polinomial quântico instantâneo (IQP). Além da classe IQP existente, a função também permite a construção de circuitos IQP aleatórios:

    from qiskit.circuit.library import random_iqp
    
    random_iqp = random_iqp(num_qubits=4)
    random_iqp.draw('mpl')
    _images/release_notes-3.png
  • Adicionado o MCMTGate para representar uma operação de vários controles e vários alvos como uma porta. Essa representação de porta do circuito existente MCMT permite que o compilador selecione a melhor implementação disponível de acordo com o número e o estado dos qubits auxiliares presentes no circuito.

    A implementação desejada pode ser escolhida especificando-se o plug-in de síntese de alto nível:

    from qiskit import QuantumCircuit, transpile
    from qiskit.circuit.library import MCMTGate, HGate
    from qiskit.transpiler.passes import HLSConfig  # used for the synthesis config
    
    mcmt = MCMTGate(HGate(), num_ctrl_qubits=5, num_target_qubits=3)
    
    circuit = QuantumCircuit(20)
    circuit.append(mcmt, range(mcmt.num_qubits))
    
    config = HLSConfig(mcmt=["vchain"])  # alternatively use the "noaux" method
    synthesized = transpile(circuit, hls_config=config)

    Além disso, o MCMTGate também suporta estados de controle personalizados (ou seja, abertos) dos qubits de controle.

  • Como parte da modernização da biblioteca de circuitos, cada um dos seguintes circuitos quânticos também é representado como um objeto Gate ou pode ser construído usando um método de síntese:

  • A classe CommutationChecker foi reescrita em Rust. Essa classe mantém a mesma funcionalidade e API pública de antes, mas agora é significativamente mais rápida na maioria dos casos.

  • PauliFeatureMap e ZZFeatureMap agora suportam a especificação do emaranhamento como um dicionário em que as chaves representam o número de qubits e os valores são listas de tuplas de números inteiros que definem quais qubits estão emaranhados uns com os outros. Isso permite mais flexibilidade na construção de mapas de recursos adaptados a algoritmos quânticos específicos. Exemplo de uso:

    from qiskit.circuit.library import PauliFeatureMap
    entanglement = {
      1: [(0,), (2,)],
      2: [(0, 1), (1, 2)],
      3: [(0, 1, 2)],
    }
    qc = PauliFeatureMap(3, reps=2, paulis=['Z', 'ZZ', 'ZZZ'], entanglement=entanglement, insert_barriers=True)
    qc.decompose().draw('mpl')
  • O método count_ops() em QuantumCircuit foi reescrito em Rust. Agora, ele é executado de 3 a 9 vezes mais rápido.

  • Funções de biblioteca de circuitos adicionadas pauli_feature_map(), z_feature_map(), zz_feature_map() para construir circuitos de mapas de recursos de Pauli. Essas funções são aproximadamente 8x mais rápidas do que os objetos atuais da biblioteca de circuitos, PauliFeatureMap, ZFeatureMap, e ZZFeatureMape as substituirão no futuro.

    As funções podem ser usadas como substitutos:

    from qiskit.circuit.library import pauli_feature_map, PauliFeatureMap
    
    fm = pauli_feature_map(20, paulis=["z", "xx", "yyy"])
    also_fm = PauliFeatureMap(20, paulis=["z", "xx", "yyy"]).decompose()

Recursos primitivos

  • O suporte para dados de nível 1 foi adicionado ao BackendSamplerV2assim como o suporte para a passagem de opções para o método run() do pacote BackendV2. As opções de execução podem ser especificadas por meio de uma entrada "run_options" dentro do dicionário options passado para BackendSamplerV2. A entrada "run_options" deve ser um dicionário que mapeia os nomes dos argumentos para valores a serem passados para o método run() do backend. Quando um "meas_level = 1 " for definido nas opções de execução, os resultados do backend serão tratados como resultados de nível 1 em vez de matrizes de bits (o formato de nível 2).

  • Estimator e StatevectorEstimator retornam valores de expectativa de forma estocástica se o circuito de entrada incluir uma reinicialização para alguns subsistemas. O resultado não era reproduzível anteriormente, mas agora pode ser reproduzido se uma semente aleatória for definida. Por exemplo:

    from qiskit.primitives import StatevectorEstimator
    
    estimator = StatevectorEstimator(seed=123)

    ou:

    from qiskit.primitives import Estimator
    
    estimator = Estimator(options={"seed":123})

OpenQASM Características

Recursos do QPY

  • Adição de um novo formato QPY versão 13 que adiciona uma representação nativa do Qiskit de ParameterExpression objetos.

Recursos de informação quântica

  • O desempenho do SparsePauliOp.from_operator() foi otimizado com base nos métodos de aprimoramento do algoritmo introduzidos no Qiskit 1.0. Agora é aproximadamente cinco vezes mais rápido do que antes para matrizes totalmente densas, levando aproximadamente 40ms para decompor um operador 10q envolvendo todos os termos Pauli.

  • Foi adicionado um novo argumento assume_unitary ao qiskit.quantum_info.Operator.power(). Quando True, usamos um método mais rápido baseado na decomposição de Schur para elevar um Operator a uma potência fracionária.

  • Adicionado SparsePauliOp.to_sparse_list() para converter um operador em um formato de lista esparsa. Isso funciona de forma inversa a SparsePauliOp.from_sparse_list(). Por exemplo:

    from qiskit.quantum_info import SparsePauliOp
    
    op = SparsePauliOp(["XIII", "IZZI"], coeffs=[1, 2])
    sparse = op.to_sparse_list()  # [("X", [3], 1), ("ZZ", [1, 2], 2)]
    
    other = SparsePauliOp.from_sparse_list(sparse, op.num_qubits)
    print(other == op)  # True
  • O desempenho do Pauli.to_label() melhorou significativamente para Paulis grandes.

  • O método Operator.power() tem um novo parâmetro branch_cut_rotation. Isso pode ser usado para deslocar o ponto de corte da raiz, o que pode afetar qual matriz é escolhida como raiz principal. Por padrão, ele é definido como uma pequena rotação positiva para tornar as raízes dos operadores com um valor próprio real negativo (como os operadores Pauli) mais estáveis em relação às diferenças de precisão numérica.

  • Uma nova classe observável foi adicionada. SparseObservable representa observáveis como uma soma de termos, semelhante a SparsePauliOpmas com duas diferenças fundamentais:

    1. Cada termo completo é armazenado como (efetivamente) uma série de pares (qubit, bit_term) , sem armazenar qubits que passam pela identidade desse termo. Isso melhora significativamente o uso da memória de observáveis, como a soma ponderada de Paulis iciZi\sum_i c_i Z_i.
    2. O alfabeto de termos de um único qubit é supercompleto para o espaço do operador; ele pode representar operadores Pauli (como SparsePauliOp), mas também projetores nos estados próprios dos operadores de Pauli, como 00\lvert 0\rangle\langle 0\rangle. Esses projetores podem ser medidos em hardware com a mesma eficiência que seu operador Pauli correspondente, mas SparsePauliOp exigiria um número exponencial de termos para representar 00n{\lvert0\rangle\langle0\rvert}^{\otimes n} em nn qubits, enquanto SparseObservable precisa de apenas um único termo.

    Você pode construir e manipular SparseObservable usando uma interface familiar aos usuários de SparsePauliOp:

    from qiskit.quantum_info import SparseObservable
    
    obs = SparseObservable.from_sparse_list([
      ("XZY", (2, 1, 0), 1.5j),
      ("+-", (100, 99), 0.5j),
      ("01", (50, 49), 0.5),
    ])

    SparseObservable não é suportado atualmente como um formato de entrada para as primitivas (qiskit.primitives), mas esperamos expandir essas interfaces para incluí-las no futuro.

Recursos de síntese

  • Funções de síntese adicionadas synth_mcx_gray_code() e synth_mcx_noaux_v24() que sintetizam portas X multicontroladas. Essas funções não requerem qubits de ancilla adicionais.

  • Funções de síntese adicionadas synth_c3x() e synth_c4x() que sintetizam X-gates com 3 e 4 controles, respectivamente.

  • Adicione uma função de síntese synth_mcx_n_dirty_i15() que sintetiza uma porta X multicontrolada com kk controles usando k2k - 2 qubits auxiliares sujos, produzindo um circuito com no máximo 8k68 * k - 6 portas CX, por Iten et. al. (arXiv:1501.06911).

  • Adicione uma função de síntese synth_mcx_n_clean_m15() que sintetiza um portão X multicontrolado com kk controles usando k2k - 2 qubits auxiliares limpos, produzindo um circuito com no máximo 6k66 * k - 6 portões CX, por Maslov ( arXiv:1508.03273 ).

  • Adicione uma função de síntese synth_mcx_1_clean_b95() que sintetiza um portão X multicontrolado com kk controles usando um único qubit auxiliar limpo, produzindo um circuito com no máximo 16k816 * k - 8 portões CX, por Barenco et al. ( arXiv:quant-ph/9503016 ).

  • Adicionado adder_qft_d00(), adder_ripple_c04(), e adder_ripple_v95() para sintetizar as portas do somador, ModularAdderGate, HalfAdderGate, e FullAdderGate.

  • Adicionado multiplier_cumulative_h18() e multiplier_qft_r17() para sintetizar o MultiplierGate.

  • Adicionado synth_mcmt_vchain() para sintetizar a porta multialvo de controle múltiplo com um número linear de portas Toffoli e k-1 qubits auxiliares para k qubits de controle, juntamente com o plug-in de síntese de alto nível MCMTSynthesisVChain.

  • Adicionada uma estrutura de plug-in de síntese de alto nível para o MCMTGateincluindo o MCMTSynthesisNoAux (para nenhum qubits auxiliar), o já mencionado MCMTSynthesisVChain (usando num_control - 1 qubits auxiliares) e o MCMTSynthesisDefault para permitir que o compilador escolha a decomposição ideal.

  • A função random_clifford() foi portada para o Rust, melhorando o tempo de execução em um fator de 3.

  • Adicionado ProductFormula.expand()que permite visualizar a expansão de uma fórmula de produto em um formato Pauli esparso. Por exemplo, podemos consultar o formato de uma expansão de Trotter de segunda ordem de um Hamiltoniano como:

    from qiskit.quantum_info import SparsePauliOp
    from qiskit.circuit.library import PauliEvolutionGate
    from qiskit.synthesis.evolution import SuzukiTrotter
    
    hamiltonian = SparsePauliOp(["IX", "XI", "ZZ"], coeffs=[-1, -1, 1])
    evo = PauliEvolutionGate(hamiltonian, time=3.14)
    trotter = SuzukiTrotter(order=2)
    print(trotter.expand(evo))

    que imprimirá

    [('X', [0], -3.14), ('X', [1], -3.14), ('ZZ', [0, 1], 6.28),
    ('X', [1], -3.14), ('X', [0], -3.14)]
  • Adicionada a estrutura do plug-in para o arquivo PauliEvolutionGate. O plug-in padrão, PauliEvolutionSynthesisDefaultconstrói o circuito como antes, mas com mais rapidez, pois usa internamente o Rust. Quanto maior o circuito (por exemplo. pelo tamanho do hamiltoniano, pelo número de intervalos de tempo ou pela ordem de Suzuki-Trotter), maior será o aumento de velocidade. Por exemplo, um Hamiltoniano de Heisenberg de 100 qubits com 10 passos de tempo e uma fórmula de Trotter de 4ª ordem agora é construído ~9.4x mais rápido. O novo plug-in, PauliEvolutionSynthesisRustiqusa o algoritmo de síntese descrito no artigo " Faster and shorter synthesis of Hamiltonian simulation circuits" de (de) Brugière e Martiel " e está implementado no Rustiq. Por exemplo:

    from qiskit.circuit import QuantumCircuit
    from qiskit.quantum_info import SparsePauliOp
    from qiskit.circuit.library import PauliEvolutionGate
    from qiskit.compiler import transpile
    from qiskit.transpiler.passes import HLSConfig
    
    op = SparsePauliOp(["XXX", "YYY", "IZZ"])
    qc = QuantumCircuit(4)
    qc.append(PauliEvolutionGate(op), [0, 1, 3])
    config = HLSConfig(PauliEvolution=[("rustiq", {"upto_phase": False})])
    tqc = transpile(qc, basis_gates=["cx", "u"], hls_config=config)
    tqc.draw(output='mpl')
    _images/release_notes-4.png

    Esse trecho de código usa o plug-in do Rustiq para sintetizar PauliEvolutionGate objetos no circuito quântico qc. O plug-in é chamado com a opção adicional upto_phase = False, permitindo que você obtenha circuitos menores à custa da possibilidade de não preservar a fase global. Para obter a lista completa de opções compatíveis, consulte a documentação do PauliEvolutionSynthesisRustiq.

  • Porto synth_cz_depth_line_mr() para Rust. Essa função sintetiza um circuito CZ para conectividade linear do vizinho mais próximo (LNN), com base no método de Maslov e Roetteler. Em uma matriz binária 350x350, a implementação do Rust produz um aumento de velocidade de cerca de 30x.

  • Port synth_permutation_reverse_lnn_kms() para o Rust, que sintetiza uma permutação reversa para a arquitetura LNN usando o método Kutin, Moulton, Smithline.

  • Adicionado um novo argumento preserve_order a ProductFormulaque permite reordenar os termos de Pauli no Hamiltoniano antes da expansão da fórmula do produto, para comprimir a profundidade do circuito final. Ao definir isso como False, um termo da forma

Z0Z1+X1X2+Y2Y3Z_0 Z_1 + X_1 X_2 + Y_2 Y_3

serão reordenados para

Z0Z1+Y2Y3+X1X2Z_0 Z_1 + Y_2 Y_3 + X_1 X_2

o que fará com que as rotações RZZ e RYY sejam aplicadas em paralelo, em vez de três rotações sequenciais na primeira parte.

Essa opção pode ser definida por meio da interface do plug-in:

from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import PauliEvolutionGate
from qiskit.quantum_info import SparsePauliOp
from qiskit.synthesis.evolution import SuzukiTrotter
from qiskit.transpiler.passes import HLSConfig

op = SparsePauliOp(["XXII", "IYYI", "IIZZ"])
time, reps = 0.1, 1

synthesis = SuzukiTrotter(order=2, reps=reps)
hls_config = HLSConfig(PauliEvolution=[("default", {"preserve_order": False})])

circuit = QuantumCircuit(op.num_qubits)
circuit.append(PauliEvolutionGate(op, time), circuit.qubits)

tqc = transpile(circuit, basis_gates=["u", "cx"], hls_config=hls_config)
tqc.draw('mpl')
_images/release_notes-5.png

Recursos do Transpiler

  • Adicione o argumento matrix_based à passagem do CollectCliffords transpiler pass. Se o novo parâmetro matrix_based=True, a passagem do CollectCliffords pode coletar portas unitárias que são portas de Clifford para determinados parâmetros, por exemplo RZGate portas com ângulos que são múltiplos de π/2\pi / 2.

  • A passagem RemoveIdentityEquivalent a passagem do transpilador agora é executada como parte dos gerenciadores de passagem predefinidos nos níveis de otimização 2 e 3. A passagem é executada durante os estágios init e optimization , porque as otimizações que ela aplica são válidas em ambos os estágios e a passagem é rápida de executar.

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

    Assim como:

    • MCXSynthesisDefaultpara escolher o método de síntese mais eficiente com base no número de qubits de ancilla limpos e sujos disponíveis.

    Como exemplo, considere a transpilação do circuito a seguir:

    from qiskit.circuit import QuantumCircuit
    from qiskit.compiler import transpile
    
    qc = QuantumCircuit(7)
    qc.x(0)
    qc.mcx([0, 1, 2, 3], [4])
    qc.mcx([0, 1, 2, 3, 4], [5])
    qc.mcx([0, 1, 2, 3, 4, 5], [6])
    
    transpile(qc).draw('mpl', fold=-1)
    _images/release_notes-6.png

    Para a primeira porta MCX, os qubits 5 e 6 podem ser usados como ancilares limpos, e o melhor método de síntese disponível synth_mcx_n_clean_m15 será escolhido. Para a segunda porta MCX, o qubit 6 pode ser usado como um ancilla limpo, o método synth_mcx_n_clean_m15 não se aplica mais, portanto, o método synth_mcx_1_clean_b95 será escolhido. Para a terceira porta MCX, não há qubits de ancilla, e o método synth_mcx_noaux_v24 será escolhido.

  • A passagem do SabreLayout foi atualizada para executar mais duas ou três tentativas de layout por padrão, independentemente do valor do argumento da palavra-chave layout_trials . Um layout trivial e seu reverso estão incluídos para todos os backends, assim como o DenseLayout que foi adicionado em 1.2.0. Além disso, os maiores anéis em um gráfico de conectividade hexagonal pesado do backend IBM são adicionados se os backends tiverem 127, 133 ou 156 qubits. Isso pode fornecer um bom ponto de partida para alguns circuitos nesses backends comumente executados, enquanto para todos os outros é apenas um "teste aleatório" adicional.

  • O DAGCircuit foi reimplementado em Rust. Essa reescrita da classe Python deve ser totalmente compatível com a API da implementação anterior do Python. Embora a classe tenha sido implementada anteriormente usando o rustworkx, para o qual a estrutura de gráfico de dados subjacente existe no Rust, a implementação da classe e de todos os dados foi feita em Python. Essa nova versão do DAGCircuit armazena representações nativas do Rust para todos os seus dados e é mais eficiente em termos de memória devido à representação comprimida de qubit e clbit projetada para instruções em repouso. Ele também permite que as passagens do transpilador manipulem totalmente um DAGCircuit do Rust, permitindo melhorias no desempenho.

  • Um novo argumento qubits_initially_zero foi adicionado a qiskit.compiler.transpile(), generate_preset_pass_manager(), e para PassManagerConfig. Se definido com o valor padrão de True, presume-se que os qubits estejam inicialmente no estado 0|0\rangle, o que pode permitir oportunidades adicionais de otimização para passagens individuais do transpilador. Em particular, a passagem do HighLevelSynthesis transpilador escolherá uma decomposição melhor para cada MCXGate porta em um circuito quando um qubit auxiliar ocioso no estado 0|0\rangle estiver disponível.

    No entanto, há casos em que qubits_initially_zero deve ser definido como False, como ao transpilar para backends que não inicializam corretamente os qubits ou ao chamar manualmente as passagens do transpilador em subcircuitos de um circuito quântico maior.

  • O construtor da passagem HighLevelSynthesis transpiler pass agora aceita um argumento adicional: qubits_initially_zero. Se definido como True, o passe assume que os qubits estão inicialmente no estado 0|0\rangle. Além disso, a passagem mantém o controle dos qubits auxiliares limpos e sujos durante a execução e passa essas informações para os plug-ins usando os kwargs num_clean_ancillas e num_dirty_ancillas.

  • Melhoria no tratamento de qubits ancilla na passagem do HighLevelSynthesis passagem do transpilador. Por exemplo, um circuito pode ter portas personalizadas cujas definições incluem MCXGates. Agora, os algoritmos de síntese para os MCXGates podem usar os qubits ancilla disponíveis no circuito global, mas fora das definições das portas personalizadas.

  • Adicionado um novo método DAGCircuit.control_flow_op_nodes() que fornece um caminho rápido para obter todos os DAGOpNode em um DAGCircuit que contêm um ControlFlowOp. Isso era possível antes de usar o método DAGCircuit.op_nodes() e passando a classe ControlFlowOp como um filtro, mas essa nova função executará a operação mais rapidamente.

  • A maioria das passagens do transpilador usadas nos gerenciadores de passagem predefinidos retornados por generate_preset_pass_manager() e usados internamente por transpile() foi portada para o Rust. Isso melhorou significativamente o desempenho do tempo de execução de cada passagem, o que levou a uma melhoria significativa na eficiência operacional geral do transpilador. A lista de passes portados para o Rust nesta versão é a seguinte:

  • Adicionada uma nova passagem de transpilador, RemoveIdentityEquivalent que é usada para remover portas que são equivalentes a uma identidade até uma certa tolerância. Por exemplo, se você tivesse um circuito como:

    _images/release_notes-7.png

    a execução do passe eliminaria a CPhaseGate:

    from qiskit.circuit import QuantumCircuit
    from qiskit.transpiler.passes import RemoveIdentityEquivalent
    
    qc = QuantumCircuit(2)
    qc.cp(1e-20, 0, 1)
    
    removal_pass = RemoveIdentityEquivalent()
    result = removal_pass(qc)
    result.draw("mpl")
    _images/release_notes-8.png
  • A passagem ConsolidateBlocks agora executará o equivalente à passagem Collect2qBlocks internamente, caso não tenha sido executada em um gerenciador de passagens antes da passagem. Anteriormente, Collect2qBlocks ou Collect1qRuns teve que ser executado antes de ConsolidateBlocks para ConsolidateBlocks para fazer qualquer coisa. Ao fazer a coleta internamente, a sobrecarga da passagem é reduzida. Se Collect2qBlocks ou Collect1qRuns forem executados antes de ConsolidateBlocksas execuções coletadas por esses passes do conjunto de propriedades serão usadas e não haverá alteração no comportamento do passe.

  • O RemoveDiagonalGatesBeforeMeasure a passagem do transpilador foi atualizada para incluir mais portas diagonais: PhaseGate, CPhaseGate, CSGate, CSdgGate e CCZGate. Além disso, o código do RemoveDiagonalGatesBeforeMeasure foi portado para o Rust e agora é x20 mais rápido para um circuito de 20 qubits.

Recursos de visualização

  • A função timeline_drawer() visualization tem um novo argumento target, usado para especificar um Target objeto para a visualização. Por padrão, a função usou o Instruction.duration para obter a duração de uma determinada instrução, mas a especificação do destino aproveitará os detalhes de tempo dentro do destino.

Problemas Conhecidos

  • Ao usar os formatos QPY 10, 11 ou 12 com circuitos que contêm ParameterExpressions, se a versão do pacote symengine instalada no ambiente que gerou a carga útil (qpy.dump()) não corresponder à versão do symengine instalada no ambiente em que a carga é carregada (qpy.load()), você receberá um erro. Se você encontrar esse erro, instale a versão symengine da mensagem de erro antes de chamar qpy.load(). As versões 13 ou posteriores do formato QPY (ou anteriores à 10) não terão esse problema. Portanto, se você estiver serializando ParameterExpression como parte de seu circuito ou qualquer objeto ScheduleBlock objetos, é recomendável que você use a versão 13 para evitar esse problema no futuro.

Notas da Atualização

  • As classes a seguir agora usam a operação X\sqrt{X} para diagonalizar o operador Pauli-Y: PauliEvolutionGate, EvolvedOperatorAnsatz, e PauliFeatureMap. Anteriormente, essas classes usavam HSH S ou RX(π/2)R_X(-\pi/2) como transformação de base. Usar a operação X\sqrt{X}, representada pelo símbolo SXGate é mais eficiente, pois usa apenas uma única porta implementada como singleton.

    Se você estava confiando no uso anterior do portão, recomendamos construir os circuitos com o Qiskit 1.2 e exportá-los com qpy.dump()ou escrever um código personalizado TransformationPassque realize a tradução para sua porta de mudança de base desejada.

  • A versão mínima compatível do Python agora é 3.9, que foi aumentada em relação à versão mínima de suporte anterior de 3.8. Essa alteração foi necessária porque o projeto cPython upstream não é mais compatível com Python 3.8.

Notas sobre atualização de circuitos

  • A classe QuantumVolume gerará circuitos com diferentes matrizes unitárias e permutações para um determinado valor de semente da versão anterior do Qiskit. Isso se deve ao uso de um novo gerador interno de números aleatórios para a geração do circuito, que gerará o circuito mais rapidamente. Se você precisar de um circuito exato com a mesma semente, poderá usar a versão anterior do Qiskit e gerar o circuito com o argumento flatten=True e exportar o circuito com qpy.dump() e, em seguida, carregá-lo com esta versão.

Notas sobre a atualização dos primitivos

  • Ao usar BackendSamplerV2os metadados do circuito não são mais limpos antes de passar os circuitos para o método run() da instância BackendV2 da instância envolvida. Se você estava confiando nesse comportamento, pode limpar manualmente os metadados antes de chamar o BackendSamplerV2.run() chamando circuit.metadata.clear()

Notas de atualização do QPY

  • A função qpy.dump() agora emite a versão 13 do formato por padrão. Isso significa que as cargas úteis geradas com essa função por padrão são compatíveis apenas com o Qiskit 1.3.0 ou posterior. Se a carga útil precisar ser carregada por uma versão anterior do Qiskit, use o sinalizador version em qpy.dump() para emitir a versão apropriada. Consulte Compatibilidade do QPY para obter mais detalhes.

Notas sobre a atualização do Transpiler

  • DAGNode (e suas subclasses DAGInNode, DAGOutNode, e DAGOpNode) não retornam mais referências ao mesmo objeto subjacente dos métodos DAGCircuit métodos. Isso nunca foi uma garantia de que todos os nós retornados seriam referências compartilhadas ao mesmo objeto. No entanto, com a migração do DAGCircuit para o Rust, uma nova instância do DAGNode é gerada em tempo real quando um nó é retornado para Python. Esses objetos serão avaliados como iguais usando == ou verificações semelhantes que dependem de __eq__ , mas não serão mais identificados como o mesmo objeto.

  • As DAGOpNode retornadas do DAGCircuit não são mais referências compartilhadas aos dados subjacentes armazenados no DAG. Na versão anterior, era possível fazer algo como:

    for node in dag.op_nodes():
        node.op = new_op

    no entanto, esse tipo de mutação sempre foi insalubre, pois poderia quebrar o cache interno do DAG e causar corrupção da estrutura de dados. Em vez disso, você deve usar a API fornecida pelo DAGCircuit para mutação, como DAGCircuit.substitute_node() ou DAGCircuit.substitute_node_with_dag(). Por exemplo, o bloco de código acima se tornaria:

    for node in dag.op_nodes():
      dag.substitute_node(node, new_op)

    Isso é semelhante a uma nota de atualização de 1.2.0 em que isso foi observado para a mutação do atributo DAGOpNode.op e não do atributo DAGOpNode em si. No entanto, em 1.3 isso se estende a todo o objeto, não apenas ao atributo op interno. Em geral, esse tipo de mutação sempre foi infundado e não foi apoiado, mas poderia ter funcionado anteriormente em alguns casos.

  • O transpile() agora pressupõe que os qubits estão inicialmente no estado 0|0\rangle. Para evitar essa suposição, é possível definir o argumento qubits_initially_zero como False.

Notas de descontinuação

  • O módulo qiskit.pulse e todos os seus recursos associados agora estão obsoletos e serão removidos no Qiskit 2.0.0. Isso ocorre porque o principal provedor de back-end com suporte a pulso é o IBM e o acesso em nível de pulso é atualmente compatível apenas com um subconjunto de back-ends do IBM e não é compatível com suas arquiteturas mais recentes. Da mesma forma, eles anunciaram que o acesso em nível de pulso será removido em 2025. Sem o maior provedor que usa o recurso com suporte ao acesso de pulso, a importância do recurso para a Qiskit é significativamente reduzida e, em comparação com a sobrecarga de manutenção contínua do pacote que está sendo removido.

    A descontinuação inclui todo o código de pulso em qiskit.pulse bem como a funcionalidade dependente ou relacionada ao pulse, como visualização de pulso, serialização e suporte à calibração personalizada. Para obter mais detalhes, consulte as seções de depreciação abaixo.

    O pacote Pulse como um todo, juntamente com os componentes diretamente relacionados no Qiskit, será movido para o repositório Qiskit Dynamics para permitir ainda mais a simulação de pulso e controle de baixo nível. A Qiskit 1.x continuará a oferecer suporte ao qiskit.pulse até o fim de sua vida útil.

Circuitos obsoletos

  • O atributo Instruction.condition e o método Instruction.c_if() método. Eles serão removidos no Qiskit 2.0, juntamente com quaisquer usos no modelo de dados do Qiskit. Essa funcionalidade foi substituída pela classe IfElseOp que pode ser usada para descrever uma condição clássica em um circuito. Por exemplo, um circuito que usa Instruction.c_if() como:

    from qiskit.circuit import QuantumCircuit
    
    qc = QuantumCircuit(2, 2)
    qc.h(0)
    qc.x(0).c_if(0, 1)
    qc.z(1.c_if(1, 0)
    qc.measure(0, 0)
    qc.measure(1, 1)

    Pode ser reescrito como:

    qc = QuantumCircuit(2, 2)
    qc.h(0)
    with qc.if_test((qc.clbits[0], True)):
        qc.x(0)
    with qc.if_test((qc.clbits[1], False)):
        qc.z(1)
    qc.measure(0, 0)
    qc.measure(1, 1)

    A agora obsoleta passagem ConvertConditionsToIfOps pode ser usado para automatizar essa conversão para circuitos existentes.


  • Como parte da descontinuação do pacote Qiskit Pulse, as seguintes dependências também estão descontinuadas:

  • O QuantumCircuit.unit e QuantumCircuit.duration foram descontinuados e serão removidos no Qiskit 2.0.0. Esses atributos foram usados para rastrear a duração estimada e a unidade dessa duração a ser executada no circuito. No entanto, os valores desses atributos sempre foram limitados, pois só seriam preenchidos corretamente se o transpilador fosse executado com as configurações corretas. A duração também era apenas uma suposição baseada no caminho mais longo na soma da duração de DAGCircuit e nunca levaria em conta corretamente o fluxo de controle ou as condicionais no circuito.

  • O DAGCircuit.unit e DAGCircuit.duration foram descontinuados e serão removidos no Qiskit 2.0.0. Esses atributos foram usados para rastrear a duração estimada e a unidade dessa duração a ser executada no circuito. No entanto, os valores desses atributos sempre foram limitados, pois só seriam preenchidos corretamente se o transpilador fosse executado com as configurações corretas. A duração também era apenas uma suposição baseada no caminho mais longo na soma da duração de DAGCircuit e nunca levaria em conta corretamente o fluxo de controle ou as condicionais no circuito.

  • O Instruction.duration e Instruction.unit foram descontinuados e serão removidos no Qiskit 2.0.0. Isso inclui a configuração dos argumentos unit ou duration para qualquer qiskit.circuit.Instruction ou subclasse. Esses atributos foram usados para anexar uma duração de execução personalizada e uma unidade para essa duração a uma instrução individual. No entanto, a fonte de verdade da duração de um portão é o BackendV2 Target que contém a duração de cada instrução suportada no backend. A duração de uma instrução não é algo que normalmente pode ser ajustado pelo usuário e é uma propriedade imutável do backend. Se você estava usando esse recurso anteriormente para experimentar diferentes durações de gates, poderá alterar o campo InstructionProperties.duration em um determinado campo Target para definir uma duração personalizada para uma instrução em um backend (a unidade está sempre em segundos no campo Target).

Descontinuidade de provedores

  • O método BasicSimulator.configuration() está obsoleto e será removido em 2.0.0. Esse método retornou uma instância herdada de providers.models.BackendConfiguration que faz parte do modelo obsoleto de BackendV1 . Esse modelo foi substituído por BackendV2em que as restrições são armazenadas diretamente na instância de back-end ou no Target (backend.target).

    Aqui está um guia rápido para acessar os atributos mais comuns do BackendConfiguration no BackendV2 modelo:

    BackendV1 model (deprecated) ------------> BackendV2 model
    ----------------------------               ---------------
    backend.configuration().backend_name       backend.name
    backend.configuration().backend_version    backend.backend_version
    backend.configuration().n_qubits           backend.num_qubits
    backend.configuration().num_qubits         backend.num_qubits
    backend.configuration().basis_gates        backend.target.operation_names (*)
    backend.configuration().coupling_map       backend.target.build_coupling_map()
    backend.configuration().local              No representation
    backend.configuration().simulator          No representation
    backend.configuration().conditional        No representation
    backend.configuration().open_pulse         No representation     
    backend.configuration().memory             No representation      
    backend.configuration().max_shots          No representation      

    (*) Observe que Backend.target.operation_names inclui basis_gates e instruções adicionais que não são de porta; em algumas implementações, pode ser necessário filtrar a saída.

    Consulte este guia para obter mais informações sobre a migração para o modelo BackendV2 modelo.


  • Como parte da descontinuação do pacote Qiskit Pulse, todas as funcionalidades relacionadas ao pulso na qiskit.providers.BackendV2 classe estão sendo descontinuadas. Isso inclui os seguintes métodos:

    Consequentemente, os métodos de canal correspondentes no qiskit.providers.BackendV2Converter e qiskit.providers.fake_provider.GenericBackendV2 também estão sendo descontinuados.

    Além disso, os argumentos pulse_channels e calibrate_instructions no método BackendV2 estão sendo descontinuados.

  • O argumento defaults está sendo preterido da função qiskit.providers.convert_to_target() função.

Depreciações do QPY

Depreciações do Transpiler

  • Depreciado StochasticSwap que foi substituído por SabreSwap. Se a classe for chamada a partir da função transpile, a alteração seria, por exemplo:

    from qiskit import transpile
    from qiskit.circuit import QuantumCircuit
    from qiskit.transpiler import CouplingMap
    from qiskit.providers.fake_provider import GenericBackendV2
    
    
    qc = QuantumCircuit(4)
    qc.h(0)
    qc.cx(0, range(1, 4))
    qc.measure_all()
    
    cmap = CouplingMap.from_heavy_hex(3)
    backend = GenericBackendV2(num_qubits=cmap.size(), coupling_map=cmap)
    
    tqc = transpile(
        qc,
        routing_method="stochastic",
        layout_method="dense",
        seed_transpiler=12342,
        target=backend.target
    )

    para:

    tqc = transpile(
        qc,
        routing_method="sabre",
        layout_method="sabre",
        seed_transpiler=12342,
        target=backend.target
    )

    Já para um gerente de passes, a mudança seria:

    passmanager = PassManager(StochasticSwap(coupling, 20, 13))
    new_qc = passmanager.run(qc)

    para:

    passmanager = PassManager(SabreSwap(backend.target, "basic"))
    new_qc = passmanager.run(qc)
  • A passagem do transpilador ConvertConditionsToIfOps foi descontinuado e será removido no Qiskit 2.0.0. Essa classe está obsoleta porque o modelo de dados subjacente para Instruction.condition do qual essa passagem está convertendo foi descontinuada e será removida em 2.0.0.

  • O fornecimento de portas personalizadas por meio do argumento basis_gates está obsoleto tanto para o transpile() e generate_preset_pass_manager(). Essa funcionalidade será removida no Qiskit 2.0. As portas personalizadas ainda são compatíveis com o modelo Target e podem ser fornecidas por meio do argumento target . É possível criar uma Target do zero ou usar o método Target.from_configuration() com o argumento custom_name_mapping . Por exemplo:

    from qiskit.circuit.library import XGate
    from qiskit.transpiler.target import Target
    
    basis_gates = ["my_x", "cx"]
    custom_name_mapping = {"my_x": XGate()}
    target = Target.from_configuration(
        basis_gates=basis_gates, num_qubits=2, custom_name_mapping=custom_name_mapping
    )

  • Como parte da descontinuação do pacote Qiskit Pulse, os aspectos relacionados ao pulso na qiskit.transpiler.Target classe estão sendo descontinuados. Dentre eles:


    Além disso, as seguintes passagens do transpiler também estão sendo descontinuadas:

  • O argumento inst_map em generate_preset_pass_manager(), from_configuration(), PassManagerConfig inicializador e generate_scheduling() está sendo preterido.

  • O argumento calibration em métodos InstructionProperties() está sendo preterido.

  • O seguinte transpile() e generate_preset_pass_manager() são preteridos em favor da definição de um argumento personalizado Target: instruction_durations, timing_constraints, e backend_properties. Esses argumentos podem ser usados para criar um alvo com Target.from_configuration():

    Target.from_configuration(
         ...
         backend_properties = backend_properties,
         instruction_durations = instruction_durations,
         timing_constraints = timing_constraints
    )
  • O método PassManagerConfig.from_backend() deixará de oferecer suporte a entradas do tipo BackendV1 no parâmetro backend em uma versão futura, não antes de 2.0. BackendV1 está obsoleto e as implementações devem migrar para BackendV2.

Páginas Obsoletos

Correções de bugs

  • Foi corrigida uma regressão de desempenho em QuantumCircuit.assign_parameters() introduzida no Qiskit 1.2.0 ao chamar o método em um loop apertado, o que fazia com que apenas um pequeno número de parâmetros de um circuito altamente paramétrico fosse vinculado a cada iteração. Se possível, é ainda mais eficiente chamar assign_parameters() apenas uma vez, com todas as atribuições ao mesmo tempo, pois isso reduz a proporção de tempo gasto na normalização da entrada e na sobrecarga de verificação de erros.

  • Para BasicSimulatora entrada basis_gates na instância de configuração retornada pelo método configuration() agora é uma lista em vez de uma instância dict_keys , correspondendo ao tipo esperado e permitindo que a instância de configuração seja copiada em profundidade.

  • Foi corrigido um problema com DAGCircuit.apply_operation_back() e DAGCircuit.apply_operation_front() onde, anteriormente, se você definisse um objeto Clbit para a entrada do argumento qargs , ele seria aceito silenciosamente. Isso foi corrigido para que a incompatibilidade de tipos seja identificada corretamente e uma exceção seja levantada.

  • Corrigido um decorador ausente no C3SXGate que o fazia falhar se o Gate.to_matrix() fosse chamado. A matriz de porta agora está retornando como esperado.

  • Foi corrigido um erro no QuantumCircuit.assign_parameters()que ocorria ao atribuir parâmetros a portas padrão cuja definição já havia sido acionada. Nesse caso, os novos valores não foram propagados corretamente para as instâncias do portão. Embora o circuito em si ainda tenha sido compilado conforme o esperado, a inspeção das operações individuais ainda mostraria o parâmetro antigo.

    Por exemplo:

    from qiskit.circuit.library import EfficientSU2
    
    circuit = EfficientSU2(2, flatten=True)
    circuit.assign_parameters([1.25] * circuit.num_parameters, inplace=True)
    print(circuit.data[0].operation.params)  # would print θ[0] instead of 1.25

    Corrigido #13478.

  • Corrigido um bug com o emaranhamento de "circular" e "sca" para NLocal circuitos e seus derivados. Para blocos de emaranhamento de mais de 2 qubits, o emaranhamento circular estava perdendo algumas conexões. Por exemplo, para 4 qubits e um tamanho de bloco de 3, o código usado anteriormente:

    [(2, 3, 0), (0, 1, 2), (1, 2, 3)]

    mas agora está adicionando corretamente as conexões (3, 0, 1) :

    [(2, 3, 0), (3, 0, 1), (0, 1, 2), (1, 2, 3)]

    Dessa forma, os emaranhados "circular" e "sca" usam blocos de emaranhamento num_qubits por camada.

  • Adicione mais portas de Clifford à passagem do CollectCliffords passagem do transpilador. Em particular, adicionamos os portões ECRGate, DCXGate, iSwapGate, SXGate e SXdgGate a essa passagem do transpilador.

  • Foi corrigido um erro no QuantumCircuit.decompose() em que os objetos que podiam ser sintetizados com HighLevelSynthesis eram primeiro sintetizados e depois decompostos imediatamente (ou seja, eram decompostos duas vezes em vez de uma). Isso afetou portões como MCXGate ou Clifford, entre outros.

  • Corrigido um bug no QuantumCircuit.decompose()em que os objetos de alto nível sem uma definição não eram decompostos se fossem explicitamente definidos por meio do argumento "gates_to_decompose" . Por exemplo, anteriormente, o seguinte não executava uma decomposição, mas agora funciona como esperado:

    from qiskit import QuantumCircuit
    from qiskit.quantum_info import Clifford
    from qiskit.transpiler.passes import Decompose
    
    cliff = Clifford(HGate())
    circuit = QuantumCircuit(1)
    circuit.append(cliff, [0])
    
    decomposed = Decompose(gates_to_decompose=["clifford"])(circuit)
  • Anteriormente, a passagem do HighLevelSynthesis pass do transpilador sintetizava uma instrução para a qual um plug-in de síntese estava disponível, independentemente de a instrução já ser suportada pelo destino ou por uma parte da instrução explicitamente passada basis_gates. Esse comportamento foi corrigido, de modo que essas instruções já suportadas não são mais sintetizadas.

  • A passagem de transpilação InverseCancellation agora irá recursar em ControlFlowOp operações presentes em um QuantumCircuit. Anteriormente, a passagem ignorava os pares de portas inversas dentro dos blocos de fluxo de controle que poderiam ter sido cancelados. Consulte #13437 para obter mais detalhes.

  • Corrigir um bug no Isometry devido a uma asserção desnecessária, que levou a um erro em UnitaryGate.control() quando o UnitaryGate tinha mais de dois qubits.

  • O atributo QuantumCircuit.parameters agora estará corretamente vazio ao usar QuantumCircuit.copy_empty_like() em um circuito paramétrico. Anteriormente, um cache interno era copiado sem invalidação. Correção #12617.

  • QuantumCircuit.depth() agora tratará corretamente as operações que não têm operandos, como GlobalPhaseGate.

  • QuantumCircuit.depth() agora contará as variáveis e os clbits usados em expressões em tempo real como parte do cálculo de profundidade.

  • Corrigir a passagem do SolovayKitaev ao carregar aproximações básicas de um arquivo .npy existente. Anteriormente, o carregamento de uma aproximação armazenada que permitia reduções adicionais (por exemplo, devido a cancelamentos de portas) podia causar uma falha no tempo de execução. Além disso, a diferença de fase global do produto de porta U(2) e da representação SO(3) foi perdida durante um procedimento de salvar e recarregar. Correções Qiskit/qiskit#12576.

  • Foi corrigido um erro quando SparsePauliOp.paulis é definido como um PauliList com fase diferente de zero, em que as chamadas subsequentes a vários métodos SparsePauliOp produziam resultados incorretos. Agora, quando SparsePauliOp.paulis é definido como um PauliList com fase diferente de zero, a fase é absorvida em SparsePauliOp.coeffse a fase da entrada PauliList é definida como zero.

  • Foi corrigido um bug no site qiskit.visualization.pulse_v2.interface.draw que não desenhava programações de pulso quando a função draw era chamada com um argumento BackendV2 argumento. Como o backend do V2 não informa as frequências dos canais de hardware, o desenho gerado mostrará "no freq" abaixo do rótulo de cada canal.

  • Foi corrigido um problema com dag_drawer() e DAGCircuit.draw() quando se tentava visualizar uma instância DAGCircuit que continha Var para a qual o visualizador gerava uma exceção. Esse comportamento foi corrigido e a visualização esperada será gerada.

  • O passe VF2Layout geraria uma exceção quando fornecido com uma instância Target sem restrições de conectividade. Esse seria o caso das metas da Aer 0.13. O problema agora está corrigido.

  • Corrige um erro ao chamar o método Gate.repeat(). Consulte #11990 para obter mais detalhes.

  • Foi corrigido um bug que fazia com que o Statevector.expectation_value() produzisse resultados incorretos para o operador de identidade quando o vetor de estado não era normalizado.

  • O construtor GenericBackendV2 estava permitindo que você criasse backends malformados porque aceitava basis gates que não podiam ser alocados no tamanho de backend especificado. Ou seja, um backend com um único qubit não deve aceitar uma base com portas de dois qubits.

  • ParameterExpression foi atualizado de modo que as instâncias totalmente vinculadas que se comparam às instâncias dos tipos numéricos incorporados do Python (como float e int) também têm valores de hash que correspondem aos das outras instâncias. Essa alteração garante que esses tipos possam ser usados de forma intercambiável como chaves de dicionário. Consulte #12488.

  • O analisador OpenQASM 2 (qiskit.qasm2) agora pode tratar condicionais com inteiros que não cabem em um inteiro de 64 bits. Corrigido #12773.

  • As portas personalizadas (aquelas decorrentes de uma instrução gate ) em programas importados do OpenQASM 2 agora terão uma Gate.to_matrix() implementação. Anteriormente, eles não tinham definição de matriz, o que significa que as viagens de ida e volta pelo site OpenQASM 2 poderiam perder desnecessariamente a capacidade de derivar a matriz de porta. Observe, no entanto, que a matriz é calculada ao encontrar recursivamente as matrizes das definições de porta interna, como faz o Operator o que pode ser menos eficiente do que antes da ida e volta.

  • Anteriormente, DAGCircuit.replace_block_with_op() permitia colocar uma operação de n-qubit em um bloco de m qubits, deixando o DAG em um estado inválido. Esse comportamento foi corrigido, e a tentativa gerará uma mensagem de erro DAGCircuitError.

  • Fixo Operator.power() quando chamado com potências não inteiras em uma matriz cuja forma Schur não é diagonal (por exemplo, a maioria das matrizes não unitárias).

  • Operator.power() agora retornará de forma mais confiável o valor principal esperado de uma potência de matriz fracionária de uma matriz unitária com um valor próprio 1-1. Isso é complicado em geral, pois os efeitos de arredondamento de ponto flutuante podem fazer com que uma matriz tenha um autovalor no lado negativo do corte de ramificação (mesmo que sua relação matemática exata não tenha), e a imprecisão em várias chamadas BLAS pode encontrar falsamente o lado errado do corte de ramificação.

    Operator.power() agora desloca o local do corte de ramificação para potências de matriz para uma pequena rotação complexa longe de 1-1. Isso não resolve o problema, apenas o desloca para um local onde é muito menos provável que ele seja perceptível para os tipos de operadores que normalmente aparecem. Use o novo parâmetro branch_cut_rotation para ter mais controle sobre isso.

    Consulte #13305.

  • Corrigido um não-determinismo baseado em processo no SparsePauliOp.to_matrix(). A ordem exata das operações de ponto flutuante na soma variava anteriormente por processo, mas agora será idêntica entre diferentes invocações do mesmo script. Consulte #13413.

  • Target.has_calibration() foi atualizado de modo a não gerar uma exceção para uma instrução que tenha sido adicionada ao destino com None para suas propriedades de instrução. Correções #12525.

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