Skip to main content
IBM Quantum Platform

Notas de versão do Qiskit 0.40


0.40.0

Esta versão substitui oficialmente o projeto do provedor Qiskit IBMQ como parte do metapacote Qiskit. Isso significa que, em uma versão futura, o pip install qiskit não incluirá mais automaticamente o qiskit-ibmq-provider. Se você estiver instalando ou listando qiskit como uma dependência para obter qiskit-ibmq-provider, deverá atualizar para incluir explicitamente qiskit-ibmq-provider também. Isso está sendo feito à medida que o projeto Qiskit avança em direção a um modelo em que o pacote qiskit contém apenas a funcionalidade central comum para criar e compilar circuitos, programas e aplicativos quânticos. Os pacotes que se baseiam nesse núcleo ou vinculam o Qiskit a hardware ou simuladores poderão ser instalados como pacotes separados.

Terra 0.23.0

Prelúdio

O Qiskit Terra 0.23.0 é uma versão de recursos importantes que inclui uma grande quantidade de novos recursos e correções de bugs. Os destaques desse lançamento são:

Esta versão também descontinua o suporte para execução com Python 3.7. Um DeprecationWarning agora será emitido se você executar o Qiskit com Python 3.7. O suporte para Python 3.7 será removido como parte da versão 0.25.0 (atualmente planejada para ser lançada em julho de 2023), momento em que você precisará do Python 3.8 ou mais recente para usar o Qiskit.

Novos Recurso

  • Os pulsos em qiskit.pulse.library

    pode ser inicializado com o novo parâmetro angle, de modo que dois parâmetros de flutuação podem ser fornecidos: amp e angle. A inicialização com o complexo amp ainda é suportada.

  • A classe AdaptVQE tem um novo atributo, eigenvalue_historyque é usado para rastrear a menor energia obtida por iteração do AdaptVQE. Por exemplo:

    from qiskit.algorithms.minimum_eigensolvers import VQE
    from qiskit.algorithms.minimum_eigensolvers.adapt_vqe import AdaptVQE
    from qiskit.algorithms.optimizers import SLSQP
    from qiskit.circuit.library import EvolvedOperatorAnsatz
    from qiskit.opflow import PauliSumOp
    from qiskit.primitives import Estimator
    from qiskit.quantum_info import SparsePauliOp
    from qiskit.utils import algorithm_globals
    
    excitation_pool = [
        PauliSumOp(
            SparsePauliOp(["IIIY", "IIZY"], coeffs=[0.5 + 0.0j, -0.5 + 0.0j]), coeff=1.0
        ),
        PauliSumOp(
            SparsePauliOp(["ZYII", "IYZI"], coeffs=[-0.5 + 0.0j, 0.5 + 0.0j]), coeff=1.0
        ),
        PauliSumOp(
            SparsePauliOp(
                ["ZXZY", "IXIY", "IYIX", "ZYZX", "IYZX", "ZYIX", "ZXIY", "IXZY"],
                coeffs=[
                    -0.125 + 0.0j,
                    0.125 + 0.0j,
                    -0.125 + 0.0j,
                    0.125 + 0.0j,
                    0.125 + 0.0j,
                    -0.125 + 0.0j,
                    0.125 + 0.0j,
                    -0.125 + 0.0j,
                ],
            ),
            coeff=1.0,
        ),
    ]
    ansatz = EvolvedOperatorAnsatz(excitation_pool, initial_state=self.initial_state)
    optimizer = SLSQP()
    h2_op = PauliSumOp.from_list(
        [
            ("IIII", -0.8105479805373266),
            ("ZZII", -0.2257534922240251),
            ("IIZI", +0.12091263261776641),
            ("ZIZI", +0.12091263261776641),
            ("IZZI", +0.17218393261915543),
            ("IIIZ", +0.17218393261915546),
            ("IZIZ", +0.1661454325638243),
            ("ZZIZ", +0.1661454325638243),
            ("IIZZ", -0.2257534922240251),
            ("IZZZ", +0.16892753870087926),
            ("ZZZZ", +0.17464343068300464),
            ("IXIX", +0.04523279994605788),
            ("ZXIX", +0.04523279994605788),
            ("IXZX", -0.04523279994605788),
            ("ZXZX", -0.04523279994605788),
        ]
    )
    
    algorithm_globals.random_seed = 42
    calc = AdaptVQE(VQE(Estimator(), ansatz, self.optimizer))
    res = calc.compute_minimum_eigenvalue(operator=h2_op)
    
    print(calc.eigenvalue_history)

    o valor retornado de calc.history deve ser aproximadamente [-1.85727503] , pois há uma única iteração.

  • O registro de tempo de execução ao executar o AdaptVQE foi aprimorado. Ao executar a classe agora, as mensagens de registro de nível DEBUG e INFO serão emitidas à medida que a classe for executada.

  • Adição de uma nova passagem de transpilador, CollectAndCollapse, para coletar e consolidar blocos de nós em um circuito. Essa passagem foi projetada para ser uma classe de base geral para coleta e consolidação de blocos combinados. Para ser completamente geral, o trabalho de coletar e recolher os blocos é feito por meio de funções fornecidas durante a instanciação da passagem. Por exemplo, a seção CollectLinearFunctions foi atualizado para herdar de CollectAndCollapse e coleta blocos de CXGate e SwapGate e substitui cada bloco por um LinearFunction. O CollectCliffords que agora também é baseado em CollectAndCollapse, coleta blocos de portas "Clifford" e substitui cada bloco por um Clifford.

    A interface também suporta a opção do_commutative_analysis, que permite explorar a comutatividade entre portas para coletar blocos maiores de nós. Por exemplo, coletar blocos de portas CX no circuito a seguir:

    qc = QuantumCircuit(2)
    qc.cx(0, 1)
    qc.z(0)
    qc.cx(1, 0)

    o uso do site do_commutative_analysis permite consolidar os dois portões CX, já que o primeiro portão CX e o portão Z se deslocam.

  • Adição de uma nova classe BlockCollector que implementa várias estratégias de coleta e uma nova classe BlockCollapser que implementa várias estratégias de colapso. Atualmente, BlockCollector inclui a estratégia de coletar avidamente todas as portas que aderem a uma determinada função de filtro (por exemplo, coletar todas as portas Clifford) e BlockCollapser inclui a estratégia de consolidar todas as portas em um bloco em um único objeto (por exemplo, um bloco de portas Clifford pode ser consolidado em um único Clifford).

  • Foi adicionada uma nova CollectCliffords que coleta blocos de portas de Clifford e consolida esses blocos em qiskit.quantum_info.Clifford objetos. Essa passagem é herdada de CollectAndCollapse e, em particular, suporta a opção do_commutative_analysis. Ele também oferece suporte a duas opções adicionais: split_blocks e min_block_size. Consulte as notas de versão de CollectAndCollapse e CollectLinearFunctions para obter mais detalhes.

  • A passagem CollectLinearFunctions transpiler pass tem vários argumentos novos em seu construtor:

    • do_commutative_analysiso que significa que a comutatividade entre os portões pode ser explorada para coletar blocos maiores de nós.

    • split_blockspermite a divisão dos blocos coletados em sub-blocos sobre subconjuntos de qubits distintos. Por exemplo, no circuito a seguir:

      qc = QuantumCircuit(4)
      qc.cx(0, 2)
      qc.cx(1, 3)
      qc.cx(2, 0)
      qc.cx(3, 1)
      qc.cx(1, 3)

      o bloco único de portas CX sobre os qubits {0, 1, 2, 3} pode ser dividido em dois sub-blocos distintos, um sobre os qubits {0, 2} e outro sobre os qubits {1, 3}.

    • min_block_sizepermite especificar o tamanho mínimo do bloco a ser consolidado; os blocos com menos portas não serão modificados. Por exemplo, no circuito a seguir:

      qc = QuantumCircuit(4)
      qc.cx(1, 2)
      qc.cx(2, 1)

      as duas portas CX serão consolidadas quando min_block_size for 1 ou 2, e permanecerão inalteradas quando min_block_size for 3 ou maior.

  • Adição de um algoritmo de síntese eficiente em termos de profundidade synth_cnot_depth_line_kms() para circuitos reversíveis lineares LinearFunction sobre a arquitetura linear do vizinho mais próximo, seguindo o documento: https://arxiv.org/abs/quant-ph/0701194.

  • O método DAGCircuit.replace_block_with_op() agora retornará o novo DAGOpNode que é criado quando o bloco é substituído. Anteriormente, a chamada desse método não retornava nada.

  • Adição de um algoritmo de síntese eficiente em termos de profundidade synth_permutation_depth_lnn_kms() para Permutation sobre a arquitetura linear do vizinho mais próximo, seguindo o documento: https://arxiv.org/abs/quant-ph/0701194

  • Adicionada uma nova classe PermutationGate para representar a lógica de permutação como um elemento de circuito. Ao contrário do elemento de biblioteca de circuitos Permutation existente, que tinha uma definição estática, essa nova classe evita a síntese de um circuito de permutação quando ele é declarado. Isso atrasa a síntese real para o transpilador. Ele também permite o uso de vários algoritmos diferentes para sintetizar permutações, que estão disponíveis como plug-ins de permutação de síntese de alto nível.

    Outro recurso importante do PermutationGate é que ele implementa a interface __array__ para retornar com eficiência uma matriz unitária para uma permutação.

  • Inclusão de vários plug-ins de síntese de alto nível para sintetizar permutações:

    • BasicSynthesisPermutationaplica-se a arquiteturas totalmente conectadas e baseia-se na classificação. Esse é o algoritmo usado anteriormente para a construção de circuitos quânticos para permutações.
    • ACGSynthesisPermutationaplica-se a arquiteturas totalmente conectadas, mas é baseado no método de Alon, Chung e Graham. Ele sintetiza qualquer permutação na profundidade 2 (medida em termos de SWAPs).
    • KMSSynthesisPermutationaplica-se a arquiteturas lineares do vizinho mais próximo e corresponde ao método Kutin, Moulton, Smithline recentemente adicionado.

    Por exemplo:

    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import PermutationGate
    from qiskit.transpiler import PassManager
    from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig, HighLevelSynthesis
    from qiskit.transpiler.passes.synthesis.plugin import HighLevelSynthesisPluginManager
    
    # Create a permutation and add it to a quantum circuit
    perm = PermutationGate([4, 6, 3, 7, 1, 2, 0, 5])
    qc = QuantumCircuit(8)
    qc.append(perm, range(8))
    
    # Print available plugin names for synthesizing permutations
    # Returns ['acg', 'basic', 'default', 'kms']
    print(HighLevelSynthesisPluginManager().method_names("permutation"))
    
    # Default plugin for permutations
    # Returns a quantum circuit with size 6 and depth 3
    qct = PassManager(HighLevelSynthesis()).run(qc)
    print(f"Default: {qct.size() = }, {qct.depth() = }")
    
    # KMSSynthesisPermutation plugin for permutations
    # Returns a quantum circuit with size 18 and depth 6
    # but adhering to the linear nearest-neighbor architecture.
    qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("kms", {})]))).run(qc)
    print(f"kms: {qct.size() = }, {qct.depth() = }")
    
    # BasicSynthesisPermutation plugin for permutations
    # Returns a quantum circuit with size 6 and depth 3
    qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("basic", {})]))).run(qc)
    print(f"basic: {qct.size() = }, {qct.depth() = }")
    
    # ACGSynthesisPermutation plugin for permutations
    # Returns a quantum circuit with size 6 and depth 2
    qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("acg", {})]))).run(qc)
    print(f"acg: {qct.size() = }, {qct.depth() = }")
  • Foram adicionadas novas classes para os algoritmos Quantum Fisher Information (QFI) e Quantum Geometric Tensor (QGT) usando primitives, qiskit.algorithms.gradients.QFI e qiskit.algorithms.gradients.LinCombQGTno módulo de gradientes: qiskit.algorithms.gradients. Por exemplo:

    from qiskit.circuit import QuantumCircuit, Parameter
    from qiskit.algorithms.gradients import LinCombQGT, QFI
    
    estimator = Estimator()
    a, b = Parameter("a"), Parameter("b")
    qc = QuantumCircuit(1)
    qc.h(0)
    qc.rz(a, 0)
    qc.rx(b, 0)
    
    parameter_value = [[np.pi / 4, 0]]
    
    qgt = LinCombQGT(estimator)
    qgt_result = qgt.run([qc], parameter_value).result()
    
    qfi = QFI(qgt)
    qfi_result = qfi.run([qc], parameter_value).result()
  • Adição de um novo argumento de palavra-chave, derivative_type, ao construtor do arquivo LinCombEstimatorGradient. Esse argumento recebe um enum DerivativeType que permite especificar o cálculo apenas das partes reais ou imaginárias do gradiente.

  • Adição de uma nova opção circuit_reverse_bits ao arquivo de configuração do usuário. Isso permite que os usuários definam um booleano para o comportamento padrão preferido do argumento reverse_bits dos desenhistas de circuito QuantumCircuit.draw() e circuit_drawer(). Por exemplo, adicionar uma seção ao arquivo de configuração do usuário no local padrão ~/.qiskit/settings.conf com:

    [default]
    circuit_reverse_bits = True

    alterará o padrão para exibir os bits na ordem inversa.

  • Adicionada uma nova classe Z2Symmetries to qiskit.quantum_info que é usada para identificar quaisquer Z2Z_2 simetrias de uma entrada SparsePauliOp.

  • Adição de uma nova diretriz de pulso TimeBlockade. Essa diretriz tem comportamento quase idêntico ao da instrução de atraso, mas será removida antes da execução. Essa diretiva deve ser usada internamente no construtor de pulsos e ajuda a ScheduleBlock representar instruções com intervalos de tempo absolutos. Isso permite que o construtor de pulsos converta Schedule em ScheduleBlock, em vez de envolver as Call instruções.

  • Adição de algoritmos primitivos habilitados para Variational Quantum Time Evolution que implementam a interface para Quantum Time Evolution. A classe qiskit.algorithms.VarQRTE é usada para a evolução do tempo quântico real e a classe qiskit.algorithms.VarQITE é usada para a evolução do tempo quântico imaginário de acordo com um princípio variacional passado.

    Cada algoritmo aceita um princípio variacional que implementa a ImaginaryVariationalPrinciple interface abstrata. As seguintes implementações estão incluídas:

    Por exemplo:

    from qiskit.algorithms import TimeEvolutionProblem, VarQITE
    from qiskit.algorithms.time_evolvers.variational import ImaginaryMcLachlanPrinciple
    from qiskit.circuit.library import EfficientSU2
    from qiskit.quantum_info import SparsePauliOp
    import numpy as np
    
    observable = SparsePauliOp.from_list(
        [
            ("II", 0.2252),
            ("ZZ", 0.5716),
            ("IZ", 0.3435),
            ("ZI", -0.4347),
            ("YY", 0.091),
            ("XX", 0.091),
        ]
    )
    
    ansatz = EfficientSU2(observable.num_qubits, reps=1)
    init_param_values = np.zeros(len(ansatz.parameters))
    for i in range(len(ansatz.parameters)):
        init_param_values[i] = np.pi / 2
    var_principle = ImaginaryMcLachlanPrinciple()
    time = 1
    evolution_problem = TimeEvolutionProblem(observable, time)
    var_qite = VarQITE(ansatz, var_principle, init_param_values)
    evolution_result = var_qite.evolve(evolution_problem)
  • Foram adicionadas regras para a conversão de XXPlusYYGate e XXMinusYYGate para outros portões do site SessionEquivalenceLibrary. Isso permite a execução de transpile() direcionado a um backend ou Target que usa essas portas.

  • Adicionados dois novos backends falsos, FakePrague e FakeSherbrooke ao módulo qiskit.providers.fake_provider módulo. FakePrague fornece um backend com um instantâneo das propriedades do backend IBM Prague Egret R1 e FakeSherbrooke fornece um backend com um instantâneo das propriedades do backend IBM Sherbrooke Eagle R3.

  • Foi adicionado um novo argumento de palavra-chave, allow_unknown_parameters, ao ParameterExpression.bind() e ParameterExpression.subs() métodos. Quando definido, esse novo argumento permite passar um dicionário contendo parâmetros desconhecidos para esses métodos sem causar um erro. Anteriormente, isso sempre gerava um erro sem nenhuma maneira de desativar esse comportamento.

  • O argumento BaseEstimator.run() do método observables agora aceita um tipo de entrada str ou uma sequência de str , além dos outros tipos já aceitos. Quando usado, o formato da string de entrada deve corresponder à representação da string Pauli aceita pelo construtor para objetos Pauli objetos.

  • Adicionado um novo método construtor QuantumCircuit.from_instructions() que permite criar um objeto QuantumCircuit a partir de um iterável de instruções. Por exemplo:

    from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
    from qiskit.circuit.quantumcircuitdata import CircuitInstruction
    from qiskit.circuit import Measure
    from qiskit.circuit.library import HGate, CXGate
    
    
    qr = QuantumRegister(2)
    cr = ClassicalRegister(2)
    instructions = [
        CircuitInstruction(HGate(), [qr[0]], []),
        CircuitInstruction(CXGate(), [qr[0], qr[1]], []),
        CircuitInstruction(Measure(), [qr[0]], [cr[0]]),
        CircuitInstruction(Measure(), [qr[1]], [cr[1]]),
    ]
    circuit = QuantumCircuit.from_instructions(instructions)
    circuit.draw("mpl")
    _images/legacy_release_notes-3.png
  • A classe Clifford agora recebe um argumento opcional da palavra-chave copy em seu construtor. Se definido como False, um StabilizerTable fornecido como entrada não será copiado, mas será usado diretamente. Isso pode trazer benefícios de desempenho, se os dados da tabela nunca forem alterados por nenhum outro meio.

  • O desempenho do Clifford.compose() foi bastante aprimorado para todos os números de qubits. Para operadores de 20 qubits, o aumento de velocidade é da ordem de 100 vezes.

  • Adição de uma nova função de síntese synth_clifford_layers()para sintetizar um Clifford em camadas. O algoritmo é baseado em S. Bravyi, D. Maslov, Hadamard-free circuits expose the structure of the Clifford group, arxiv:2003.09412. Isso decompõe o Clifford em 8 camadas de portas, incluindo duas camadas de portas CZ e uma camada de portas CX. Por exemplo, um circuito Clifford de 5 qubits é decomposto nas seguintes camadas:

         ┌─────┐┌─────┐┌────────┐┌─────┐┌─────┐┌─────┐┌─────┐┌────────┐
    q_0:0    ├┤0    ├┤0       ├┤0    ├┤0    ├┤0    ├┤0    ├┤0
         │     ││     ││        ││     ││     ││     ││     ││        │
    q_1:1    ├┤1    ├┤1       ├┤1    ├┤1    ├┤1    ├┤1    ├┤1
         │     ││     ││        ││     ││     ││     ││     ││        │
    q_2:2 S2 ├┤2 CZ ├┤2 CX_dg ├┤2 H2 ├┤2 S1 ├┤2 CZ ├┤2 H1 ├┤2 Pauli ├
         │     ││     ││        ││     ││     ││     ││     ││        │
    q_3:3    ├┤3    ├┤3       ├┤3    ├┤3    ├┤3    ├┤3    ├┤3
         │     ││     ││        ││     ││     ││     ││     ││        │
    q_4:4    ├┤4    ├┤4       ├┤4    ├┤4    ├┤4    ├┤4    ├┤4
         └─────┘└─────┘└────────┘└─────┘└─────┘└─────┘└─────┘└────────┘

    Esse método permitirá decompor um Clifford em profundidade de 2 qubits 7n+27n+2 para conectividade linear do vizinho mais próximo (LNN).

  • Os tipos de retorno para os métodos power() em várias classes de porta da biblioteca padrão foram atualizados para retornar objetos de porta mais específicos que resultam em uma saída com menos perdas e mais eficiente. Por exemplo, a execução de power() agora retorna uma instância IGate em vez de UnitaryGate como era feito anteriormente.

    A lista completa dos tipos de saída que foram aprimorados é a seguinte:

  • O EquivalenceLibrary agora é representado internamente como um PyDiGraph, esse objeto gráfico subjacente pode ser acessado a partir do novo atributo graph atributo. Esse atributo destina-se a ser usado internamente no Qiskit e, portanto, deve ser sempre copiado antes de ser modificado pelo usuário para evitar possível corrupção do gráfico de equivalência interno.

  • O método do construtor Operator.from_circuit() agora reverterá a permutação de saída causada pelo estágio de mapeamento de roteamento/troca do transpilador. Por padrão, se um circuito transpilado tiver portas Swap inseridas, a matriz de saída terá essa permutação invertida, de modo que a matriz retornada será equivalente ao circuito original não transpilado. Se você quiser desativar esse comportamento padrão, o argumento da palavra-chave ignore_set_layout pode ser definido como True para fazer isso (além do comportamento anterior de ignorar o layout inicial da transpilação). Se você quiser definir manualmente um layout final, poderá usar o novo argumento da palavra-chave final_layout para passar um objeto Layout a ser usado para a permutação de saída.

  • Foi adicionado suporte à passagem GateDirection para lidar com a passagem do transpilador simétrico RXXGate, RYYGate, e RZZGate simétricas. Agora, a passagem manipulará corretamente esses portões e simplesmente inverterá a ordem dos qargs no lugar, sem nenhuma outra modificação.

  • Foi adicionado suporte ao uso do operador de exponenciação Python, **, com objetos Gate agora é suportado. Isso equivale a executar o método Gate.power() no objeto.

    Por exemplo:

    from qiskit.circuit.library import XGate
    
    sx = XGate() ** 0.5
  • Adicionada nova forma de pulso GaussianSquareDrag ao qiskit.pulse.library módulo. Esse formato de pulso é semelhante ao GaussianSquare mas usa a forma Drag durante sua subida e descida. A correção da forma do pulso DRAG pode suprimir parte do espectro de frequência da subida e da descida do pulso, o que pode ajudar a evitar a excitação dos qubits espectadores quando eles estiverem próximos em frequência da frequência de acionamento do pulso.

  • Adição de um novo argumento de palavra-chave, method, aos construtores do FiniteDiffEstimatorGradient e FiniteDiffSamplerGradient classes. O argumento method aceita uma cadeia de caracteres para indicar o método de cálculo a ser usado para o gradiente. Há três métodos disponíveis: "central", "forward" e "backward". A definição dos métodos é a seguinte:

    Método
    Cálculo
    "central"f(x+e)f(xe)2e\frac{f(x+e)-f(x-e)}{2e}
    "forward"f(x+e)f(x)e\frac{f(x+e) - f(x)}{e}
    "backward"f(x)f(xe)e\frac{f(x)-f(x-e)}{e}

    em que ee é o epsilon de deslocamento.

  • Todas as classes de gradiente em qiskit.algorithms.gradients agora preservam operações não parametrizadas em vez de tentar desenrolá-las. Isso permite avaliar gradientes em portas personalizadas e opacas que os primitivos individuais podem manipular e mantém um nível mais alto de abstração para síntese e compilação otimizadas após a construção dos circuitos de gradiente.

  • Adicionado um TranslateParameterizedGates para mapear somente as portas parametrizadas em um circuito para uma base especificada, mas deixando as portas não parametrizadas intactas. A passagem primeiro tenta desenrolar e, por fim, traduz se uma porta parametrizada não puder ser desenrolada posteriormente.

  • A passagem do CollectCliffords a passagem do transpilador foi expandida para coletar e combinar blocos de "clifford gates" em objetos Clifford onde "clifford gates" agora também podem incluir objetos do tipo LinearFunction, Clifford, e PauliGate. Por exemplo:

    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import LinearFunction, PauliGate
    from qiskit.quantum_info.operators import Clifford
    from qiskit.transpiler.passes import CollectCliffords
    from qiskit.transpiler import PassManager
    
    # Create a Clifford
    cliff_circuit = QuantumCircuit(2)
    cliff_circuit.cx(0, 1)
    cliff_circuit.h(0)
    cliff = Clifford(cliff_circuit)
    
    # Create a linear function
    lf = LinearFunction([[0, 1], [1, 0]])
    
    # Create a pauli gate
    pauli_gate = PauliGate("XYZ")
    
    # Create a quantum circuit with the above and also simple clifford gates.
    qc = QuantumCircuit(4)
    qc.cz(0, 1)
    qc.append(cliff, [0, 1])
    qc.h(0)
    qc.append(lf, [0, 2])
    qc.append(pauli_gate, [0, 2, 1])
    qc.x(2)
    
    # Run CollectCliffords transpiler pass
    qct = PassManager(CollectCliffords()).run(qc)

    Todos os portões serão coletados e combinados em um único Clifford. Assim, o circuito final consiste em um único Clifford objeto.

  • CouplingMap agora é implicitamente iterável, com a iteração sendo idêntica à iteração através da saída de CouplingMap.get_edges(). Em outras palavras,

    from qiskit.transpiler import CouplingMap
    coupling = CouplingMap.from_line(3)
    list(coupling) == list(coupling.get_edges())

    agora funcionará como esperado, assim como outras iterações. Isso é puramente uma conveniência sintática.

  • Adicionada uma nova função synth_cnot_count_full_pmh() que é usada para sintetizar circuitos reversíveis lineares para arquiteturas all-to-all usando o método Patel, Markov e Hayes. Essa função é idêntica à função qiskit.transpiler.synthesis.cnot_synth() disponível, mas tem um nome mais descritivo e está posicionada de forma mais lógica na árvore de pacotes. Essa nova função substitui a função herdada, que provavelmente será descontinuada em uma versão futura.

  • InstructionScheduleMap foi atualizado para armazenar dados de calibração de back-end no formato PulseQobj JSON e invoca a conversão quando os dados são acessados pela primeira vez, ou seja, conversão preguiçosa. Essa atualização da lógica interna melhora drasticamente o desempenho do backend de carregamento, especialmente com muitas entradas de calibração.

  • Foi adicionado o novo módulo qiskit.pulse.calibration_entries . Contém várias classes de wrapper para diferentes representações de programação de pulsos.

    • ScheduleDef
    • CallableDef
    • PulseQobjDef

    Essas classes implementam os métodos get_schedule() e get_signature() que retornam a programação de pulsos e os nomes dos parâmetros a serem atribuídos, respectivamente. Essas classes são gerenciadas internamente pelo InstructionScheduleMap ou backend Targete, portanto, não aparecerão em programas típicos de usuários.

  • Introduziu uma nova subclasse ScalableSymbolicPulse, como uma subclasse de SymbolicPulse. A nova subclasse se comporta da mesma forma que SymbolicPulseexceto pelo fato de pressupor que o envelope do pulso inclui um pré-fator de amplitude complexa da forma ampei×angle\text{amp} * e^{i \times \text{angle}}. Essa forma de envelope corresponde a muitos pulsos comuns, incluindo todos os pulsos da biblioteca Qiskit Pulse (que também foram convertidos para representação em amp, angle nesta versão).

    A nova subclasse elimina a natureza não exclusiva da representação amp, angle e compara corretamente os pulsos de acordo com sua amplitude complexa.

  • Foi adicionado um novo argumento de palavra-chave, dtype, ao método PauliSumOp.from_list() método. Quando especificado, esse argumento pode ser usado para especificar o dtype da matriz numpy alocada para o SparsePauliOp usada internamente pelo sistema construído PauliSumOp.

  • Foi adicionado o suporte à importação de programas do OpenQASM 3 para o Qiskit. Isso pode ser acessado mais facilmente usando as funções qasm3.loads() e qasm3.load()para carregar um programa diretamente de uma cadeia de caracteres e indiretamente de um nome de arquivo, respectivamente. Por exemplo, agora é possível fazer:

    from qiskit import qasm3
    
    circuit = qasm3.loads("""
      OPENQASM 3.0;
      include "stdgates.inc";
    
      qubit q;
      qubit[5] qr;
      bit c;
      bit[5] cr;
    
      h q;
      c = measure q;
    
      if (c) {
        h qr[0];
        cx qr[0], qr[1];
        cx qr[0], qr[2];
        cx qr[0], qr[3];
        cx qr[0], qr[4];
      } else {
        h qr[4];
        cx qr[4], qr[3];
        cx qr[4], qr[2];
        cx qr[4], qr[1];
        cx qr[4], qr[0];
      }
      cr = measure qr;
    """)

    Isso carregará o programa em uma instância QuantumCircuit na variável circuit.

    Nem todos os recursos do OpenQASM 3 são compatíveis no início, porque o Qiskit ainda não tem uma maneira de representar o processamento de dados clássico avançado. Os recursos do importador aumentarão junto com os recursos do restante do Qiskit. O conjunto inicial de recursos do importador é aproximadamente o mesmo conjunto de recursos que seria produzido pelo exportador (qasm3.dump() e qasm3.dumps()).

    Observe que o suporte do Qiskit para OpenQASM 3 não tem o objetivo de fornecer uma representação totalmente sem perdas de QuantumCircuits. Para isso, considere usar qiskit.qpy.

  • As primitives-definidas pelas classes de gradiente BaseEstimatorGradient e BaseSamplerGradient foram atualizadas para simplificar a extensão da interface básica. Há três novos métodos internos substituíveis, _preprocess(), _postprocess() e _run_unique(). _preprocess() permite que uma subclasse personalize os circuitos e parâmetros de gradiente de entrada, _postprocess permite personalizar o resultado de saída e _run_unique permite calcular o gradiente de um circuito com parâmetros exclusivos.

  • A passagem do SabreLayout melhorou muito o desempenho, pois foi reescrito em Rust. Como parte dessa reescrita, a passagem foi transformada de uma passagem de análise para uma passagem de transformação que executará o layout e o roteamento. Isso foi feito não apenas para melhorar o desempenho do tempo de execução, mas também para melhorar a qualidade dos resultados. A funcionalidade anterior da passagem como uma passagem de análise pode ser mantida definindo manualmente o argumento routing_pass ou usando o novo argumento skip_routing .

  • A passagem SabreLayout transpiler pass tem um novo argumento de construtor layout_trials. Esse argumento é usado para controlar quantas sementes de gerador de números aleatórios serão tentadas para execução SabreLayout com. Quando definido, o algoritmo de layout do SABRE é executado layout_trials número de vezes e o resultado de melhor qualidade (medido pelo menor número de portas de troca adicionadas) é selecionado. Esses testes de sementes são executados em paralelo usando multithreading para minimizar a possível sobrecarga de desempenho da execução do layout várias vezes. Por padrão, se isso não for especificado, a SabreLayout usará como padrão o número de CPUs físicas disponíveis no sistema local.

  • Adicionadas duas novas classes SciPyRealEvolver e SciPyImaginaryEvolver que implementam métodos de integração para a evolução temporal de um estado quântico. O valor e o desvio padrão dos observáveis, bem como os momentos em que são avaliados, podem ser consultados como TimeEvolutionResult.observables e TimeEvolutionResult.times. Por exemplo:

    from qiskit.algorithms.time_evolvers.time_evolution_problem import TimeEvolutionProblem
    from qiskit.quantum_info import SparsePauliOp
    from qiskit.quantum_info.states.statevector import Statevector
    from qiskit.algorithms import SciPyImaginaryEvolver
    
    initial_state = Statevector.from_label("+++++")
    hamiltonian = SparsePauliOp("ZZZZZ")
    evolution_problem = TimeEvolutionProblem(hamiltonian, 100, initial_state, {"Energy":hamiltonian})
    classic_evolver = SciPyImaginaryEvolver(num_timesteps=300)
    result = classic_evolver.evolve(evolution_problem)
    print(result.observables)
  • Adicionada a passagem SolovayKitaev para executar o algoritmo Solovay-Kitaev para aproximar unitários de um único qubit usando um conjunto de portas discretas. Em combinação com o tradutor de base, isso permite converter qualquer circuito unitário em um conjunto de portas discretas universais, que pode ser implementado de forma tolerante a falhas.

    Essa passagem pode, por exemplo, ser usada após a compilação para portas U e CX:

    from qiskit import transpile
    from qiskit.circuit.library import QFT
    from qiskit.transpiler.passes.synthesis import SolovayKitaev
    
    qft = QFT(3)
    
    # optimize to general 1-qubit unitaries and CX
    transpiled = transpile(qft, basis_gates=["u", "cx"], optimization_level=1)
    
    skd = SolovayKitaev()  # uses T Tdg and H as default basis
    discretized = skd(transpiled)
    
    print(discretized.count_ops())

    A decomposição também pode ser usada com o plug-in de síntese unitária, como o método "sk" na passagem UnitarySynthesis transpiler pass:

    from qiskit import QuantumCircuit
    from qiskit.quantum_info import Operator
    from qiskit.transpiler.passes import UnitarySynthesis
    
    circuit = QuantumCircuit(1)
    circuit.rx(0.8, 0)
    unitary = Operator(circuit).data
    
    unitary_circ = QuantumCircuit(1)
    unitary_circ.unitary(unitary, [0])
    
    synth = UnitarySynthesis(basis_gates=["h", "s"], method="sk")
    out = synth(unitary_circ)
    
    out.draw('mpl')
    _images/legacy_release_notes-4.png
  • A geração de circuitos aleatórios com qiskit.circuit.random.random_circuit() agora é significativamente mais rápida para circuitos grandes.

  • A geração de circuitos aleatórios com qiskit.circuit.random.random_circuit() agora produzirá todas as portas "padrão" na biblioteca de circuitos do Qiskit (qiskit.circuit.library). Isso inclui duas portas de 4 qubits C3SXGate e RC3XGatee os valores permitidos de max_operands foram expandidos de acordo.

  • A passagem Optimize1qGatesDecomposition transpiler pass tem um novo argumento de palavra-chave, target, em seu construtor. Esse argumento pode ser usado para especificar um objeto Target que representa o destino da compilação. Se usado, ele substitui o argumento basis para determinar se uma instrução no circuito está presente no backend de destino.

  • A passagem UnrollCustomDefinitions transpiler pass tem um novo argumento de palavra-chave, target, em seu construtor. Esse argumento pode ser usado para especificar um objeto Target que representa o destino da compilação. Se usado, ele substitui o argumento basis_gates para determinar se uma instrução no circuito está presente no backend de destino.

  • Adicionada a classe ReverseEstimatorGradient para uma avaliação clássica e rápida de gradientes de valor de expectativa com base em retropropagação ou gradientes de modo reverso. Essa classe usa vetores de estado e, portanto, fornece gradientes exatos, mas aumenta exponencialmente o tamanho do sistema. Ele foi projetado para o cálculo rápido de referência de sistemas de menor porte. Ele pode, por exemplo, ser usado como:

    from qiskit.circuit.library import EfficientSU2
    from qiskit.quantum_info import SparsePauliOp
    from qiskit.algorithms.gradients import ReverseEstimatorGradient
    
    observable = SparsePauliOp.from_sparse_list([("ZZ", [0, 1], 1)], num_qubits=10)
    circuit = EfficientSU2(num_qubits=10)
    values = [i / 100 for i in range(circuit.num_parameters)]
    gradient = ReverseEstimatorGradient()
    
    result = gradient.run([circuit], [observable], [values]).result()
  • Foi adicionado um novo argumento de palavra-chave, use_dag , ao construtor da classe OneQubitEulerDecomposer classe. Quando use_dag estiver definido como True , a saída do decompositor será um objeto DAGCircuit em vez de um objeto QuantumCircuit objeto. Isso é útil para passagens de transpiladores que usam OneQubitEulerDecomposer (como Optimize1qGatesDecomposition), pois trabalhar diretamente com um DAGCircuit evita a sobrecarga de conversão entre QuantumCircuit e DAGCircuit.

  • Foi adicionada a capacidade de os passes de análise definirem pesos heurísticos personalizados para os atributos VF2Layout e VF2PostLayout passagens do transpilador. Se uma passagem de análise definir a chave vf2_avg_error_map no conjunto de propriedades, seu valor será usado para os pesos de erro, em vez das taxas de erro do backend Target (ou BackendProperties para BackendV1). O valor deve ser uma instância ErrorMap , em que cada valor representa a taxa de erro média para todas as operações de 1 ou 2 qubits nesses qubits. Se um valor for NaN, a borda correspondente será tratada como uma borda ideal (ou qubit para operações 1q ). Por exemplo, um mapa de erros criado como:

    from qiskit.transpiler.passes.layout.vf2_utils import ErrorMap
    
    error_map = ErrorMap(3)
    error_map.add_error((0, 0), 0.0024)
    error_map.add_error((0, 1), 0.01)
    error_map.add_error((1, 1), 0.0032)

    descreve um alvo de 2 qubits, em que a taxa média de erro 1q é 0.0024 no qubit 0 e 0.0032 no qubit 1, a taxa média de erro 2q para portas que operam em (0, 1) é 0.01, e (1, 0) não é compatível com o alvo. Isso será usado para pontuação se for definido para a chave vf2_avg_error_map no conjunto de propriedades quando VF2Layout e VF2PostLayout forem executados. Por exemplo:

    from qiskit.transpiler import AnalysisPass, PassManager, Target
    from qiskit.transpiler.passes import VF2Layout
    from qiskit.transpiler.passes.layout.vf2_utils import ErrorMap
    from qiskit.circuit.library import CZGate, UGate
    from qiskit.circuit import Parameter
    
    class CustomVF2Scoring(AnalysisPass):
      """Set custom score for vf2."""
    
      def run(self, dag):
        error_map = ErrorMap(3)
        error_map.add_error((0, 0), 0.0024)
        error_map.add_error((0, 1), 0.01)
        error_map.add_error((1, 1), 0.0032)
        self.property_set["vf2_avg_error_map"] = error_map
    
    
    target = Target(num_qubits=2)
    target.add_instruction(
        UGate(Parameter('theta'), Parameter('phi'), Parameter('lam')),
        {(0,): None, (1,): None}
    )
    target.add_instruction(
        CZGate(), {(0, 1): None}
    )
    
    vf2_pass = VF2Layout(target=target, seed=1234568942)
    pm = PassManager([CustomVF2Scoring(), vf2_pass])

    Isso será executado VF2Layout com a pontuação personalizada de error_map para um 2 qubit Target que não contém nenhuma taxa de erro.

Notas da Atualização

  • Ao inicializar qualquer uma das classes de pulso em qiskit.pulse.library:

    fornecer um argumento amp complexo com um angle finito resultará em PulseError agora. Por exemplo, em vez de chamar Gaussian(duration=100,sigma=20,amp=0.5j) , deve-se usar Gaussian(duration=100,sigma=20,amp=0.5,angle=np.pi/2) agora. O envelope de pulso que costumava ser definido como amp * ... é, por sua vez, definido como amp * exp(1j * angle) * .... Essa alteração foi feita para oferecer melhor suporte aos experimentos Qiskit, nos quais a amplitude e o ângulo dos pulsos são calibrados em experimentos separados.

  • Para Python 3.7 singledispatchmethod agora é uma dependência. Isso foi adicionado para permitir o aproveitamento do mecanismo de envio de métodos na biblioteca padrão das versões mais recentes do Python. Se você estiver em Python >= 3.8, não será necessária nenhuma dependência extra.

  • A passagem do transpilador MSBasisDecomposer , anteriormente obsoleta, disponível por meio do módulo qiskit.transpiler.passes foi removida. Ele foi originalmente descontinuado como parte da versão do Qiskit Terra 0.16.0 (16/10/2020). Em vez disso, a passagem BasisTranslator transpiler pass deve ser usado para traduzir um circuito em uma base apropriada com um RXXGate

  • EquivalenceLibrary que são inicializados com o atributo base não terão mais uma referência compartilhada com o objeto EquivalenceLibrary passado. Em versões anteriores, se você alterasse o endereço base depois que ele fosse usado para criar uma nova EquivalenceLibrary ambas as instâncias refletiriam essa alteração. Esse não é mais o caso e as atualizações em base não serão mais refletidas no novo EquivalenceLibrary. Por exemplo, se você criou uma biblioteca de equivalência com:

    import math
    
    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import XGate
    from qiskit.circuit.equivalence import EquivalenceLibrary
    
    original_lib = EquivalenceLibrary()
    qc = QuantumCircuit(1)
    qc.rx(math.pi, 0)
    original_lib.add_equivalence(XGate(), qc)
    new_lib = EquivalenceLibrary(base=original_lib)

    se você modificou o site original_lib com:

    import from qiskit.circuit.library import SXGate
    
    qc = QuantumCircuit(1)
    qc.rx(math.pi / 2, 0)
    original_lib.add_equivalence(SXGate(), qc)

    em versões anteriores, o site new_lib também incluía a definição de SXGate depois que ela foi adicionada ao site original_lib, mas nesta versão isso não será mais o caso. Essa alteração foi feita devido à mudança na estrutura de dados interna para um gráfico, o que melhorou o desempenho da classe EquivalenceLibrary classe, especialmente quando há várias execuções da passagem do BasisTranslator passagem do transpilador.

  • O argumento initial_state para o construtor da classe NLocal juntamente com a atribuição direta ao atributo NLocal.initial_state deve ser um QuantumCircuit agora. Não há mais suporte para o uso de outros tipos para esse argumento e atributo. O suporte para outros tipos foi descontinuado como parte da versão do Qiskit Terra 0.18.0 (julho de 2021).

  • As gavetas da matriz LaTeX (por exemplo, array_to_latex, Statevector.draw('latex')) agora usam a mesma função sympy que a gaveta da convenção ket. Isso significa que ele pode renderizar alguns números de forma diferente das versões anteriores, mas proporcionará uma experiência mais consistente. Por exemplo, ele pode identificar novos fatores ou racionalizar denominadores onde não o fez anteriormente. O padrão precision foi alterado de 5 para 10.

  • A versão do formato de versão QPY emitida por dump() foi aumentada para a versão 6. Essa nova versão de formato é incompatível com as versões anteriores e resultará em um erro ao tentar carregá-la com um desserializador que não seja capaz de lidar com o QPY versão 6. Essa alteração foi necessária para dar suporte à introdução do site ScalableSymbolicPulse , que foi tratado com a adição de um atributo class_name_size ao cabeçalho dos objetos despejados SymbolicPulse despejados.

  • O método __hash__ para o SymbolicPulse foi removido. Isso foi feito para refletir a natureza mutável (por meio da atribuição de parâmetros) dessa classe, o que poderia resultar em erros ao usar SymbolicPulse em situações em que um objeto hashable era necessário. Isso significa que o método interno hash() e o uso de SymbolicPulse como chaves em dicionários ou membros de conjuntos não funcionarão mais.

  • Os nomes das Register (que incluem instâncias de QuantumRegister e ClassicalRegigster) não estão mais restritos a serem identificadores válidos de OpenQASM 2. Isso está sendo feito porque a restrição é excessivamente rigorosa à medida que o Qiskit se torna mais desacoplado de OpenQASM 2, e mesmo a especificação OpenQASM 3 não é tão restritiva. Se você dependia de registros com nomes de identificadores OpenQASM 2 válidos, precisará começar a escapar os nomes. Uma versão simplista disso poderia ser feita, por exemplo, por:

    import re
    import string
    
    def escape(name: str) -> str:
      out = re.sub(r"\W", "_", name, flags=re.ASCII)
      if not out or out[0] not in string.ascii_lowercase:
        return "reg_" + out
      return out
  • Os métodos QuantumCircuitu1 , u2, u3, e suas variantes controladas cu1, cu3 e mcu1 foram removidos após sua descontinuação no Qiskit Terra 0.16.0. Isso foi feito para remover os nomes de portais que geralmente eram específicos do site IBM, em favor dos métodos mais gerais p(), u(), cp() e cu(). As classes de portas U1Gate, U2Gate e U3Gate ainda estão disponíveis para uso com QuantumCircuit.append()portanto, os back-ends ainda podem oferecer suporte a bases com essas portas explicitamente fornecidas.

  • Os métodos QuantumCircuitcombine e extend foram removidos após sua descontinuação no Qiskit Terra 0.17.0. Isso foi feito porque essas funções eram simplesmente versões menos poderosas de QuantumCircuit.compose()que deveriam ser usadas em seu lugar.

    A remoção do extend também significa que os operadores + e += não estão mais definidos para QuantumCircuit. Em vez disso, você pode usar os operadores & e &= , respectivamente, que usam QuantumCircuit.compose().

  • As funções anteriormente obsoletas: qiskit.circuit.measure.measure() e qiskit.circuit.reset.reset() foram removidas. Essas funções foram descontinuadas na versão do Qiskit Terra 0.19.0 (dezembro de 2021). Em vez disso, você deve usar o QuantumCircuit.measure() e QuantumCircuit.reset() do objeto QuantumCircuit do objeto que deseja anexar um Measure ou Reset a uma operação.

  • Os métodos anteriormente obsoletos de ParameterView que foram herdados de set foram removidos de ParameterView, o tipo retornado por QuantumCircuit.parameters. Os métodos específicos que foram removidos são:

    • add()
    • difference()
    • difference_update()
    • discard()
    • intersection()
    • intersection_update()
    • issubset()
    • issuperset()
    • symmetric_difference()
    • symmetric_difference_update()
    • union()
    • update()

    juntamente com o suporte para os operadores do Python :

    • ixor: ^=
    • isub: -=
    • ior: |=

    Eles foram descontinuados na versão do Qiskit Terra 0.17.0 (abril de 2021). O tipo ParameterView agora é um tipo de visualização de sequência geral e não é mais compatível com essas operações set .

  • Os métodos de conversão NetworkX para os métodos de conversão DAGCircuit e DAGDependency classes: DAGCircuit.to_networkx(), DAGCircuit.from_networkx(), e DAGDependency.to_networkx() foram removidos. Esses métodos foram originalmente descontinuados como parte da versão do Qiskit Terra 0.21.0 (junho de 2022). O Qiskit tem usado o rustworkx como biblioteca de gráficos desde a versão do qiskit-terra 0.12.0 e, desde então, a função de conversão NetworkX tem sido um processo com perdas. Elas foram originalmente adicionadas para que os usuários pudessem aproveitar a biblioteca de algoritmos NetworkX’s para aproveitar a funcionalidade não presente no DAGCircuit e/ou rustworkx. No entanto, desde aquela época, tanto o DAGCircuit e o rustworkx amadureceram e oferecem mais funcionalidades, e o DAGCircuit está fortemente acoplado ao rustworkx para sua operação e o fato de esses métodos conversores fornecerem funcionalidade limitada e, portanto, foram removidos.

  • tweedledum foi removido como um requisito essencial do Qiskit Terra. A funcionalidade fornecida (qiskit.circuit.classicalfunction) ainda estará disponível se o site tweedledum for instalado manualmente, como por exemplo:

    pip install tweedledum

    Essa alteração foi feita porque o desenvolvimento do tweedledum diminuiu a ponto de não acompanhar as novas versões do Python e do sistema operacional, e estava impedindo que alguns usuários do Qiskit instalassem o Qiskit.

  • Os verificadores opcionais preguiçosos HAS_MATPLOTLIB, HAS_PIL, HAS_PYLATEX e HAS_PDFTOCAIRO não são mais expostos a partir de qiskit.visualizationtendo sido descontinuados no Qiskit Terra 0.21. O local canônico para esses (e muitos outros verificadores preguiçosos) é qiskit.utils.optionalse todos os quatro objetos podem ser encontrados lá.

  • O argumento gate , anteriormente obsoleto, para o construtor da passagem Decompose juntamente com seu atributo correspondente Decompose.gate foi removido. O argumento e o atributo foram descontinuados como parte da versão do Qiskit Terra 0.19.0 (dezembro de 2021). Em vez disso, deve ser usado o argumento gates_to_decompose para o construtor junto com o atributo Decompose.gates_to_decompose . O argumento e o atributo gates_to_decompose devem funcionar da mesma forma, mas têm um nome mais explícito e também permitem a especificação de listas de portas, em vez de suportar apenas uma única porta.

  • O argumento label , anteriormente obsoleto, para o construtor do MCMT e MCMTVChain foi removido. Ele foi descontinuado a partir da versão do Qiskit Terra 0.19.0 (dezembro de 2021). Usar o argumento label nessas classes era um comportamento indefinido, pois elas são subclasses de QuantumCircuit em vez de Instruction. Isso faria com que o rótulo atribuído fosse geralmente ignorado. Se você precisar atribuir um label a uma instância de MCMT ou MCMTVChain você deve convertê-los em uma instância de Gate com to_gate() e, em seguida, atribuir o rótulo desejado ao atributo label atributo. Por exemplo:

    from qiskit.circuit.library import MCMT, XGate
    
    mcmt_circuit = MCMT(XGate(), 3, 2)
    mcmt_gate = mcmt_circuit.to_gate()
    mcmt_gate.label = "Custom MCMT X"
  • A dependência retworkx do Qiskit foi removida e substituída pela biblioteca rustworkx . Esses são os mesmos pacotes, mas rustworkx é o novo nome para retworkx , que foi renomeado como parte da versão combinada 0.12.0. Se você já estava usando o retworkx 0.12.0 com o Qiskit, então já instalou o rustworkx (o retworkx 0.12.0 era apenas um shim de redirecionamento para compatibilidade com versões anteriores). Essa alteração foi feita para migrar para o novo nome de pacote, que será o único pacote compatível no futuro.

  • O comportamento padrão da passagem do SabreLayout do compilador foi alterado. O passe não é mais um AnalysisPass e, por padrão, calcula o layout inicial, aplica-o ao circuito e também executa SabreSwap internamente e aplicará o mapeamento de troca e definirá a propriedade final_layout com a permutação causada pelas inserções de troca. Isso significa que, para usuários que executam SabreLayout como parte de um aplicativo personalizado PassManager personalizado precisarão ajustar o gerenciador de passes para levar isso em conta (a menos que estejam definindo o argumento routing_pass para SabreLayout). Essa alteração foi feita com o objetivo de melhorar a qualidade do resultado, pois a qualidade do layout e do roteamento é altamente acoplada SabreLayout agora executará vários testes de sementes paralelos e, para calcular qual semente fornece os melhores resultados, ele precisa executar o layout e o roteamento juntos. Há três maneiras de ajustar o uso em seu gerenciador de passes personalizado. A primeira é evitar o uso de incorporação em seu gerenciador de passagens predefinidas. Se você estava executando anteriormente algo como:

    from qiskit.transpiler import PassManager
    from qiskit.transpiler.preset_passmanagers import common
    from qiskit.transpiler.passes.SabreLayout
    
    pm = PassManager()
    pm.append(SabreLayout(coupling_map)
    pm += common.generate_embed_passmanager(coupling_map)

    para calcular o layout e depois aplicá-lo (o que normalmente era seguido pelo roteamento), você pode ajustar o uso para simplesmente ser:

    from qiskit.transpiler import PassManager
    from qiskit.transpiler.preset_passmanagers import common
    from qiskit.transpiler.passes.SabreLayout
    
    pm = PassManager()
    pm.append(SabreLayout(coupling_map)

    as SabreLayout aplicará o layout e você não precisará mais do estágio de incorporação. Como alternativa, você pode especificar o argumento routing_pass que reverterá SabreLayout ao seu comportamento anterior. Por exemplo, se você quiser executar o SabreLayout como ele era executado em versões anteriores, você pode fazer algo como:

    from qiskit.transpiler.passes import SabreSwap, SabreLayout
    routing_pass = SabreSwap(
        coupling_map, "decay", seed=seed, fake_run=True
    )
    layout_pass = SabreLayout(coupling_map, routing_pass=routing_pass, seed=seed)

    que terá SabreLayout executado como uma passagem de análise e apenas definirá o conjunto de propriedades layout . A abordagem final é aproveitar o argumento skip_routing em SabreLayout; quando esse argumento for definido como True , ele ignorará a aplicação do layout encontrado e a inserção das portas de troca do roteamento. No entanto, isso tem uma penalidade de tempo de execução, pois o site SabreLayout ainda estará computando o roteamento, mas não usará esses dados. As duas primeiras abordagens descritas não têm custos adicionais associados a elas.

  • Os layouts calculados pela passagem SabreLayout (quando executado sem o argumento routing_pass ) com um valor de semente fixo podem mudar em relação às versões anteriores. Isso é causado por um novo gerador de números aleatórios que está sendo usado como parte da reescrita da passagem SabreLayout em Rust, o que melhorou significativamente o desempenho. Se você depende de uma saída consistente, pode executar a passagem em uma versão anterior do Qiskit e usar o qiskit.qpy para salvar o circuito e, em seguida, carregá-lo usando a versão atual. Como alternativa, você pode definir explicitamente o argumento routing_pass como uma instância de SabreSwap para espelhar o comportamento anterior de SabreLayout:

    from qiskit.transpiler.passes import SabreSwap, SabreLayout
    
    
    routing_pass = SabreSwap(
        coupling_map, "decay", seed=seed, fake_run=True
    )
    layout_pass = SabreLayout(coupling_map, routing_pass=routing_pass, seed=seed)

    que espelhará o comportamento do passe na versão anterior. Observe que, se você estava usando o argumento swap_trials em SabreLayout em versões anteriores ao ajustar o uso para essa forma, você precisará definir o argumento trials no construtor SabreSwap se quiser manter a saída anterior com uma semente fixa.

  • O circuito exato retornado por qiskit.circuit.random.random_circuit para uma determinada semente foi alterado. Isso se deve a melhorias na eficiência da geração interna de números aleatórios para a função.

  • O requisito de versão para o pacote de recursos opcionais qiskit-toqm, instalável via pip install qiskit-terra[toqm], foi atualizado da versão 0.0.4 para 0.1.0. Para usar o método de roteamento toqm com transpile() agora você deve usar a versão 0.1.0 ou mais recente do qiskit-toqm. As versões mais antigas não são mais detectáveis pelo transpilador.

  • A saída QuasiDistribution do método Sampler.run foi atualizado para filtrar todos os estados com probabilidade zero. Agora, se um estado válido estiver faltando na saída do dicionário, pode-se presumir que ele tenha uma probabilidade 0. Anteriormente, todos os resultados possíveis para um determinado número de bits (por exemplo, para um resultado de 3 bits 000, 001, 010, 011, 100, 101, 110 e 111), mesmo que a probabilidade de um determinado estado fosse 0. Essa alteração foi feita para reduzir o tamanho da saída, pois, para um número maior de bits, o tamanho da saída pode ser muito grande. Além disso, a filtragem dos resultados de probabilidade zero torna a saída consistente com outras implementações do BaseSampler.

  • O comportamento do construtor de pulsos quando um Schedule é chamado foi atualizado. As programações chamadas são internamente convertidas em ScheduleBlock e, agora, o mecanismo de referência é sempre aplicado, em vez de anexar as programações incluídas pela instrução Call instrução. Observe que o bloco convertido não precisa recuperar o contexto de alinhamento original. Trata-se simplesmente de uma sequência alinhada ASAP de instruções de pulso com intervalos de tempo absolutos. Essa é uma atualização da representação interna dos programas de pulso chamados e, portanto, não há alterações na API. No entanto, a Call instrução e Schedule não aparecem mais no programa de pulso do construtor. Essa alteração garante que os blocos de programação gerados sejam sempre compatíveis com o QPY. Se você estiver filtrando as instruções do cronograma de saída por Callpoderá acessar o ScheduleBlock.references para recuperar o programa chamado.

  • RZXCalibrationBuilder e RZXCalibrationBuilderNoEcho foram atualizados para gerar ScheduleBlock. Essa alteração garante que os circuitos transpilados sejam sempre compatíveis com o QPY. Se você estiver usando diretamente o método rescale_cr_inst()de outro programa ou de uma subclasse de passe para redimensionar o pulso de ressonância cruzada do dispositivo, agora esse método foi transformado em uma macro de criação de pulso, e você precisará usar esse método no contexto do criador de pulso para adotar a nova versão. A chamada do método injeta uma instrução de reprodução no programa de pulso de contexto, em vez de retornar uma instrução Play com o pulso esticado.

Notas de descontinuação

  • O suporte para a execução do Qiskit com Python 3.7 foi descontinuado e será removido na versão qiskit-terra 0.25.0. Isso significa que, a partir da versão 0.25.0, você precisará atualizar a versão Python que está usando para Python 3.8 ou superior.

  • A classe LinearFunctionsSynthesis está obsoleta e será removida em uma versão futura. Ela foi substituída pela classe mais geral HighLevelSynthesis mais geral, que deve ser usada em seu lugar. Por exemplo, você pode instanciar uma instância de HighLevelSynthesis que se comportará da mesma forma que LinearFunctionSynthesis with:

    from qiskit.transpiler.passes import HighLevelSynthesis
    from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig
    
    HighLevelSynthesis(
        HLSConfig(
            linear_function=[("default", {})],
            use_default_on_unspecified=False,
        )
    )
  • O suporte à passagem de listas de valores de argumentos para a função transpile() está obsoleto e será removido na versão 0.25.0. Isso está sendo feito para facilitar a redução significativa da sobrecarga da execução paralela para transpilar vários circuitos de uma só vez. Se estiver usando essa funcionalidade atualmente, você pode chamar transpile() várias vezes em vez disso. Por exemplo, se você estava fazendo algo como:

    from qiskit.transpiler import CouplingMap
    from qiskit import QuantumCircuit
    from qiskit import transpile
    
    qc = QuantumCircuit(2)
    qc.h(0)
    qc.cx(0, 1)
    qc.measure_all()
    cmaps = [CouplingMap.from_heavy_hex(d) for d in range(3, 15, 2)]
    results = transpile([qc] * 6, coupling_map=cmaps)

    em vez disso, você deve executar algo como:

    from itertools import cycle
    from qiskit.transpiler import CouplingMap
    from qiskit import QuantumCircuit
    from qiskit import transpile
    
    qc = QuantumCircuit(2)
    qc.h(0)
    qc.cx(0, 1)
    qc.measure_all()
    cmaps = [CouplingMap.from_heavy_hex(d) for d in range(3, 15, 2)]
    
    results = []
    for qc, cmap in zip(cycle([qc]), cmaps):
        results.append(transpile(qc, coupling_map=cmap))

    Você também pode aproveitar parallel_map() ou multiprocessing da biblioteca padrão Python se quiser executar isso em paralelo.

  • A versão antiga da gaveta de pulsos presente no site qiskit.visualization.pulse foi descontinuada e será removida em uma versão futura. Isso inclui as classes ScheduleDrawer e :class`WaveformDrawer`. Esse módulo foi substituído pela gaveta qiskit.visualization.pulse_v2 e a API típica do usuário pulse_drawer() e PulseBlock.draw() já foram atualizadas internamente para usar qiskit.visualization.pulse_v2.

  • O método pulse.Instruction.draw() foi preterido e será removido em uma versão futura. A necessidade desse método foi substituída pela gaveta qiskit.visualization.pulse_v2 , que não exige que os objetos Instrucion tenham seu próprio método de desenho. Se você precisar desenhar uma instrução de pulso, deverá usar o pulse_drawer() em vez disso.

  • A importação qiskit.circuit.qpy_serialization está obsoleta, pois o QPY foi promovido ao nível superior. Você deve importar os mesmos objetos de qiskit.qpy em vez disso. O caminho antigo será removido em um futuro do Qiskit Terra.

  • O objeto qiskit.IBMQ está obsoleto. Esse objeto de alias redireciona o acesso ao atributo para qiskit.providers.ibmq.IBMQ. Como o pacote qiskit-ibmq-provider foi substituído pelo pacote qiskit-ibm-provider , que mantém seu próprio namespace, a manutenção desse alias não é mais relevante com o novo pacote. Se você dependia do alias qiskit.IBMQ , deve atualizar seu uso para usar diretamente o qiskit.providers.ibmq.IBMQ (e também considerar a migração para o qiskit-ibm-provider, consulte o guia de migração para obter mais detalhes).

  • Vários métodos públicos dos conversores Qobj de pulso foram preteridos e, em uma versão futura, não poderão mais ser chamados diretamente. A lista de métodos é a seguinte:

    Em InstructionToQobjConverter,

    • convert_acquire()
    • convert_bundled_acquires()
    • convert_set_frequency()
    • convert_shift_frequency()
    • convert_set_phase()
    • convert_shift_phase()
    • convert_delay()
    • convert_play()
    • convert_snapshot()

    Em QobjToInstructionConverter,

    • convert_acquire()
    • convert_set_phase()
    • convert_shift_phase()
    • convert_set_frequency()
    • convert_shift_frequency()
    • convert_delay()
    • bind_pulse()
    • convert_parametric()
    • convert_snapshot()

    Em vez de chamar qualquer um desses métodos diretamente, eles serão implicitamente selecionados quando uma instância do conversor for chamada diretamente. Por exemplo:

    converter = QobjToInstructionConverter()
    converter(pulse_qobj)
  • As funções qiskit.visualization.state_visualization.num_to_latex_ket() e qiskit.visualization.state_visualization.num_to_latex_terms() foram preteridas e serão removidas em uma versão futura. Essas funções foram usadas principalmente internamente pela saída LaTeX do Statevector.draw() e DensityMatrix.draw() que não está mais usando essa função e está aproveitando o sympy para isso. Se você estava usando essas funções, deveria deixar de usar as funções nsimplify() latex() do Sympy.

  • O método Register.qasm() está obsoleto e será removido em uma versão futura. Esse método é encontrado nas subclasses QuantumRegister e ClassicalRegister. A descontinuação se deve ao fato de que o método qasm() promove uma visão falsa da parte responsável pela conversão segura para OpenQASM 2; um único objeto sozinho não tem o contexto para fornecer uma conversão segura, como, por exemplo, se o seu nome entra em conflito após o escape para produzir um identificador válido.

  • A expressão regular class-variable Register.name_format está obsoleta e será removida em uma versão futura. Os nomes dos registros agora podem ser qualquer cadeia de caracteres Python válida, portanto, a expressão regular não tem mais utilidade.

  • As funções qiskit.quantum_info.synthesis.decompose_clifford() e qiskit.quantum_info.synthesis.decompose_cnot_dihedral() estão obsoletas e serão removidas em uma versão futura. Elas são substituídas pelas duas funções qiskit.synthesis.synth_clifford_full() e qiskit.synthesis.synth_cnotdihedral_full() respectivamente.

Correções de bugs

  • Foi corrigido um problema no método PauliOp.adjoint() em que o método retornava o valor correto para Paulis com coeficientes complexos, por exemplo: PauliOp(Pauli("iX")). Corrigido #9433.

  • Foi corrigido um problema com os algoritmos de estimativa de amplitude no módulo qiskit.algorithms.amplitude_estimators (consulte amplitude_estimators) para o uso com primitivos construídos a partir do módulo BaseSampler (como Sampler e BackendSampler). Anteriormente, os resultados da medição eram expandidos para mais bits do que os realmente medidos, o que, no caso de oráculos com mais de um qubit, levava a possíveis erros na detecção dos estados quânticos "bons" dos oráculos.

  • Foi corrigido um problema em que os métodos QuantumCircuit.add_calibrations() e DAGCircuit.add_calibrations() apresentavam uma incompatibilidade no comportamento da lógica de formatação de parâmetros. Anteriormente, DAGCircuit.add_calibrations() tentava converter todos os parâmetros em float, QuantumCircuit.add_calibrations() usava os parâmetros fornecidos como estão. Isso poderia causar um erro ao executar transpile() em um QuantumCircuit com portas de pulso, pois os parâmetros das calibrações poderiam ser mantidos como objetos ParameterExpresion .

  • Foi corrigido um problema de desserialização no sistema (qiskit.qpy) load() do QPY, onde os circuitos contendo portas da classe MCXGate, MCXGrayCode, MCXRecursive, e MCXVChain falhariam na desserialização. Corrigido #9390.

  • Foi corrigido um problema no TensoredOp.to_matrix() em que o coeficiente global do operador era multiplicado à matriz final mais de uma vez. Agora, o coeficiente global é aplicado corretamente, independentemente do número de operadores ou estados com tensão. Corrigido #9398.

  • A saída do método run() do método BackendSampler agora define os atributos shots e stddev_upper_bound da classe QuasiDistribution. Anteriormente, esses atributos estavam ausentes, o que impedia alguns pós-processamentos usando a saída. Corrigido #9311

  • O método exportador OpenQASM 2 QuantumCircuit.qasm() agora emitirá números de ponto flutuante de maior precisão para parâmetros de porta por padrão. Além disso, um limite mais restrito ( 1e121e-12 em vez de 1e61e-6 ) é usado para verificar se um determinado parâmetro está próximo de uma fração/potência de π\pi. Corrigido o número 7166.

  • Corrigido o suporte no módulo primitives para execução de objetos QuantumCircuit com instruções de fluxo de controle (por exemplo IfElseOp). Anteriormente, as classes de base BaseSampler e BaseEstimator não conseguiam normalizar corretamente esses circuitos. No entanto, a execução desses circuitos depende da implementação específica das instruções de fluxo de controle de suporte primitivo. Isso apenas corrigiu o suporte para permitir que uma implementação específica de BaseSampler ou BaseEstimator use instruções de fluxo de controle.

  • Foi corrigido um problema no método PauliOp.matmul() , que retornava resultados incorretos com iI. Corrigido #8680.

  • Foi corrigido um problema com a classe Approximate Quantum Compiler (AQC) que fazia com que ele retornasse um circuito incorreto quando a unidade de entrada tinha um determinante de -1. Corrigido #9327

  • Foi corrigido um problema com o método QuantumCircuit.compose() em que ele rejeitava incorretamente especificadores válidos de qubit ou clbit. Isso foi corrigido para que o método agora aceite o mesmo conjunto de especificadores qubit e clbit que outros métodos QuantumCircuit como os métodos append(). Corrigido #8691.

  • Foi corrigido um problema com o método QuantumCircuit.compose() em que ele mapeava incorretamente os registros em condições no circuito fornecido para completar os registros na base. Anteriormente, o mapeamento era muito impreciso; os bits usados em cada condição não estavam sujeitos ao mapeamento e, em vez disso, era feita uma tentativa imprecisa de encontrar um registro correspondente. Isso também pode fazer com que uma condição em um registro menor seja expandida para um registro maior, o que não é uma transformação válida. Agora, uma condição em um único bit ou em um registro será composta para estar exatamente nos bits definidos pelo argumento clbits . Um novo registro de aliasing será adicionado ao circuito básico para facilitar isso, se necessário. Corrigido #6583.

  • Foi corrigido um problema com a função transpile() quando executada com optimization_level definido como 1, 2, ou 3 e nenhum argumento backend, basis_gates, ou target especificado. Se o circuito de entrada tivesse passagens de portas de um único qubit que pudessem ser simplificadas, o circuito de saída não seria tão otimizado quanto possível, pois essas passagens de portas de um único qubit não teriam sido removidas. Isso poderia ter sido corrigido anteriormente especificando os argumentos backend, basis_gates ou target na chamada transpile() mas agora o resultado será o mais simplificado possível sem conhecer as portas de destino permitidas. Corrigido #9217

  • Foi corrigido um problema com a função transpile() quando executada com optimization_level=3 e nenhum argumento backend, basis_gates ou target especificado. Se o circuito de entrada contivesse quaisquer blocos de 2 qubits que fossem equivalentes a uma matriz de identidade, o circuito de saída não seria tão otimizado quanto possível e ainda conteria esse bloco de identidade. Isso poderia ter sido corrigido anteriormente especificando os argumentos backend, basis_gates ou target na chamada transpile() mas agora o resultado será o mais simplificado possível sem conhecer as portas de destino permitidas. Corrigido #9217

  • Foi corrigido um problema com o LinCombSamplerGradient em que ele potencialmente gerava um erro quando executado com a classe Sampler da classe qiskit-aer.

  • Foi corrigido um problema com o NumPyEigensolver e, por extensão NumPyMinimumEigensolver em que a solução para BaseOperator subclasses diferentes de Operator causava um erro.

  • Foi corrigido um problema na saída de metadados do primitives em que a lista fazia cópias por referência e todos os elementos eram atualizados com o mesmo valor a cada iteração.

  • Foi corrigido um problema com o site QobjToInstructionConverter quando vários backends são chamados e eles acidentalmente têm o mesmo nome de pulso na biblioteca de pulsos. Esse era um caso extremo que só poderia ser causado quando uma instância do conversor fosse reutilizada em vários back-ends (esse não era um padrão de uso típico).

  • Foi corrigido um problema com a classe PVQD em que a função de perda estava elevando incorretamente a fidelidade ao quadrado. Isso foi corrigido para que a função de perda corresponda à definição na definição original do algoritmo.

  • Foi corrigido um bug no QPY (qiskit.qpy) em que os circuitos que continham registros cujos bits ocorriam no circuito após bits soltos não eram desserializados. Consulte #9094.

  • A classe TwoQubitWeylDecomposition agora é compatível com o protocolo pickle . Anteriormente, a desserialização falhava e gerava um TypeError. Consulte #7312.

  • Foi corrigido um problema com o método LocalReadoutMitigator.quasi_probabilities() em que o argumento shots não era usado. Ele agora é usado para definir o número de disparos no objeto de retorno.

  • Foi corrigida uma regressão na construção de objetos Clifford de QuantumCircuits que contêm outros objetos Clifford objetos.

  • Foi corrigido um problema com a classe TwoQubitWeylDecomposition (e suas subclasses) para permitir que a biblioteca padrão Python pickle serialize essas classes. Isso corrigiu parcialmente o número 7312

  • QuantumCircuit.qasm() agora escapará corretamente dos nomes de portas e registros que colidem com as palavras-chave reservadas do OpenQASM 2. Correções #5043.

  • Foi corrigido um problema no RZXCalibrationBuilder em que a sequência de pulsos ECR estava desalinhada. Corrigido #9013.

  • Foi corrigido um problema com a função pulse_drawer() em que, em alguns casos, a visualização de saída omitia alguns dos canais em uma programação. Corrigido #8981.

Aer 0.11.2

Nenhuma mudança

IBM 0.19.2

Nenhuma mudança

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