Skip to main content
IBM Quantum Platform

Notas de versão do Qiskit 0.35


0.35.0

Terra 0.20.0

Prelúdio

Os destaques da versão do Qiskit Terra 0.20.0 são:

  • A introdução de módulos multithread escritos em Rust para acelerar o desempenho de determinadas partes do Qiskit Terra e melhorar o dimensionamento com um número maior de qubits. No entanto, ao compilar o Qiskit a partir da fonte, agora é necessário um compilador Rust.
  • Mais suporte nativo para trabalhar com um Target no transpilador. Vários passes agora suportam o trabalho direto com um objeto Target o que torna o transpilador robusto em relação aos tipos de backends que ele pode usar.
  • A introdução do qiskit.primitives módulo. Essas APIs oferecem diferentes níveis de abstração para computar resultados de interesse de QuantumCircuit e usar backends. Por exemplo, o BaseEstimator define uma interface abstrata para estimar um valor de expectativa de um observável. Isso pode ser usado para criar algoritmos e aplicativos de nível superior que são construídos usando a estimativa de valores de expectativa sem precisar se preocupar com a implementação do cálculo do valor de expectativa. Esse desacoplamento permite que a implementação melhore a velocidade e a qualidade, ao mesmo tempo em que adere à interface abstrata definida. Da mesma forma, o BaseSampler calcula distribuições de quase-probabilidade a partir de medições de circuitos. Outras primitivas serão introduzidas no futuro.

Esta versão não tem mais suporte para Python 3.6. Com essa versão, são necessários os sites Python 3.7 a Python 3.10.

Novos Recurso

  • Foi adicionado um novo método de construção para a classe Operator classe, Operator.from_circuit() para criar um novo objeto Operator objeto a partir de um arquivo QuantumCircuit. Embora isso fosse possível normalmente usando o construtor padrão, o método Operator.from_circuit() fornece opções adicionais para ajustar como o operador é criado. Principalmente, isso permite que você altere a ordem dos qubits com base em um conjunto Layout. Por exemplo:

    from qiskit.circuit import QuantumCircuit
    from qiskit import transpile
    from qiskit.transpiler import CouplingMap
    from qiskit.quantum_info import Operator
    
    circuit = QuantumCircuit(3)
    circuit.h(0)
    circuit.cx(0, 1)
    circuit.cx(1, 2)
    
    cmap = CouplingMap.from_line(3)
    out_circuit = transpile(circuit, initial_layout=[2, 1, 0], coupling_map=cmap)
    operator = Operator.from_circuit(out_circuit)

    a variável operator terá os qubits permutados com base no layout, de modo que seja idêntico ao que é retornado por Operator(circuit) antes da transpilação.

  • Adicionado um novo método DAGCircuit.copy_empty_like() à classe DAGCircuit classe. Esse método é usado para criar uma nova cópia de um objeto DAGCircuit existente com a mesma estrutura, mas sem nenhuma instrução. Esse método é o mesmo que o método privado _copy_circuit_metadata(), mas agora faz parte da API pública da classe.

  • As classes de backend falso e provedor falso, que estavam disponíveis anteriormente em qiskit.test.mock , agora também podem ser acessadas em um novo módulo: qiskit.providers.fake_provider. Esse novo módulo substitui o módulo anterior qiskit.test.mock , que será descontinuado no Qiskit 0.21.0.

  • Adicionada uma nova classe de porta, LinearFunctionque codifica eficientemente uma função linear (ou seja, uma função que pode ser representada por uma sequência de CXGate e SwapGate portas).

  • Adicionada uma nova passagem de transpilador CollectLinearFunctions que coleta blocos de CXGate e SwapGate consecutivos em um circuito e substitui cada bloco por uma porta LinearFunction porta.

  • Adicionada uma nova passagem de transpilador LinearFunctionsSynthesis que sintetiza qualquer LinearFunction portas usando o algoritmo Patel-Markov-Hayes. Quando combinado com a passagem CollectLinearFunctions transpiler, isso permite coletar blocos de CXGate e SwapGate em um circuito e sintetizá-los novamente usando o algoritmo Patel-Markov-Hayes.

  • Adicionada uma nova passagem de transpilador LinearFunctionsToPermutations que substitui um LinearFunction gate por um circuito Permutation sempre que possível.

  • FlowController (como ConditionalController) agora podem ser aninhadas dentro de uma instância PassManager ao usar o método PassManager.append() método. Isso permite o uso de lógica aninhada para controlar a execução de passes na seção PassManager. Por exemplo:

    from qiskit.transpiler import ConditionalController, PassManager
    from qiskit.transpiler.passes import (
      BasisTranslator, GatesInBasis, Optimize1qGatesDecomposition, FixedPoint, Depth
    )
    from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel
    
    pm = PassManager()
    
    def opt_control(property_set):
        return not property_set["depth_fixed_point"]
    
    def unroll_condition(property_set):
        return not property_set["all_gates_in_basis"]
    
    depth_check = [Depth(), FixedPoint("depth")]
    opt = [Optimize1qGatesDecomposition(['rx', 'ry', 'rz', 'rxx'])]
    unroll = [BasisTranslator(sel, ['rx', 'ry', 'rz', 'rxx'])]
    unroll_check = [GatesInBasis(['rx', 'ry', 'rz', 'rxx'])]
    flow_unroll = [ConditionalController(unroll, condition=unroll_condition)]
    
    pm.append(depth_check + opt + unroll_check + flow_unroll, do_while=opt_control)

    O objeto pm PassManager só executará o BasisTranslator (na etapa unroll ) em cada iteração do loop se o unroll_condition for atendido.

  • Os construtores para os arquivos ZFeatureMap e ZZFeatureMap têm um novo argumento de palavra-chave parameter_prefix. Esse novo argumento é usado para definir o prefixo dos parâmetros do circuito de codificação de dados. Por exemplo:

    from qiskit.circuit.library import ZFeatureMap
    
    feature_map = ZFeatureMap(feature_dimension=4, parameter_prefix="my_prefix")
    feature_map.decompose().draw('mpl')

    o circuito gerado ZFeatureMap o circuito prefixou todos os seus parâmetros internos com o prefixo "my_prefix".

  • A TemplateOptimization transpiler pass agora pode trabalhar com objetos Gate com objetos que tenham parâmetros ParameterExpression parâmetros. Um exemplo ilustrativo do uso de Parameters com TemplateOptimization é o seguinte:

    from qiskit import QuantumCircuit, transpile, schedule
    from qiskit.circuit import Parameter
    
    from qiskit.transpiler import PassManager
    from qiskit.transpiler.passes import TemplateOptimization
    
    # New contributions to the template optimization
    from qiskit.transpiler.passes.calibration import RZXCalibrationBuilder, rzx_templates
    
    from qiskit.test.mock import FakeCasablanca
    backend = FakeCasablanca()
    
    phi = Parameter('φ')
    
    qc = QuantumCircuit(2)
    qc.cx(0,1)
    qc.p(2*phi, 1)
    qc.cx(0,1)
    print('Original circuit:')
    print(qc)
    
    pass_ = TemplateOptimization(**rzx_templates.rzx_templates(['zz2']))
    qc_cz = PassManager(pass_).run(qc)
    print('ZX based circuit:')
    print(qc_cz)
    
    # Add the calibrations
    pass_ = RZXCalibrationBuilder(backend)
    cal_qc = PassManager(pass_).run(qc_cz.bind_parameters({phi: 0.12}))
    
    # Transpile to the backend basis gates
    cal_qct = transpile(cal_qc, backend)
    qct = transpile(qc.bind_parameters({phi: 0.12}), backend)
    
    # Compare the schedule durations
    print('Duration of schedule with the calibration:')
    print(schedule(cal_qct, backend).duration)
    print('Duration of standard with two CNOT gates:')
    print(schedule(qct, backend).duration)

    outputs

    Original circuit:
    
    q_0: ──■──────────────■──
         ┌─┴─┐┌────────┐┌─┴─┐
    q_1: ┤ X ├┤ P(2*φ) ├┤ X ├
         └───┘└────────┘└───┘
    ZX based circuit:
                                             ┌─────────────┐            »
    q_0: ────────────────────────────────────┤0            ├────────────»
         ┌──────────┐┌──────────┐┌──────────┐│  Rzx(2.0*φ) │┌──────────┐»
    q_1:Rz(-π/2) ├┤ Rx(-π/2) ├┤ Rz(-π/2) ├┤1            ├┤ Rx(-2*φ) ├»
         └──────────┘└──────────┘└──────────┘└─────────────┘└──────────┘»
    «
    «q_0: ────────────────────────────────────────────────
    «     ┌──────────┐┌──────────┐┌──────────┐┌──────────┐
    «q_1:Rz(-π/2) ├┤ Rx(-π/2) ├┤ Rz(-π/2) ├┤ P(2.0*φ)
    «     └──────────┘└──────────┘└──────────┘└──────────┘
    Duration of schedule with the calibration:
    1600
    Duration of standard with two CNOT gates:
    6848
  • O DAGOpNode, DAGInNode e DAGOutNode agora definem um método __repr__ personalizado que gera uma representação. De acordo com a documentação do site Python, a saída é uma representação de string que é aproximadamente equivalente à string Python usada para criar um objeto equivalente.

  • O desempenho do método SparsePauliOp.simplify() melhorou muito ao substituir o uso de numpy.unique para computar elementos exclusivos de uma matriz por uma nova função semelhante implementada em Rust que não pré-classifica a matriz.

  • Adicionado um novo método equiv() à classe SparsePauliOp para testar a equivalência de um SparsePauliOp com outro objeto SparsePauliOp objeto. Ao contrário do operador == , que compara os operadores em termos de elementos, equiv() compara se dois operadores são equivalentes ou não. Por exemplo:

    op = SparsePauliOp.from_list([("X", 1), ("Y", 1)])
    op2 = SparsePauliOp.from_list([("X", 1), ("Y", 1), ("Z", 0)])
    op3 = SparsePauliOp.from_list([("Y", 1), ("X", 1)])
    
    print(op == op2)  # False
    print(op == op3)  # False
    print(op.equiv(op2))  # True
    print(op.equiv(op3))  # True
  • Adicionadas novas classes de back-end falsas a partir de snapshots dos sistemas IBM Quantum com base na BackendV2 e forneceu um Target para cada backend. BackendV2 as versões baseadas em todos os back-ends existentes são adicionadas, exceto para três back-ends antigos: FakeRueschlikon, FakeTenerife e FakeTokyo , pois eles não têm arquivos de snapshots disponíveis, que são necessários para criar uma nova classe de back-end falsa baseada em BackendV2.

    Esses novos back-ends falsos do V2 permitirão o teste e o desenvolvimento de novos recursos introduzidos pelo BackendV2 e Target como o aprimoramento do transpilador.

  • Adicionada uma nova classe de porta XXMinusYYGate à biblioteca de circuitos (qiskit.circuit.library) para a interação XX-YY. Essa porta pode ser usada para implementar a porta bSwap e seus poderes. Ela também surge na simulação de modelos fermiônicos supercondutores.

  • Adicionada uma nova classe de porta, XXPlusYYGateà biblioteca de circuitos (qiskit.circuit.library). Essa porta é uma interação XX+YY parametrizada de 2 qubits, também conhecida como porta XY, e é baseada na porta descrita em https://arxiv.org/abs/1912.04424.

  • Os backends falsos FakeBogota, FakeManila, FakeRome e FakeSantiago , que podem ser encontrados no módulo qiskit.providers.fake_provider , agora podem ser usados como backends nos experimentos do Pulse, pois agora incluem um PulseDefaults criado a partir de um instantâneo das propriedades da máquina IBM Quantum equivalente.

  • O passe ConsolidateBlocks tem um novo argumento de palavra-chave em seu construtor, target. Esse argumento é usado para especificar um objeto Target que representa o alvo de compilação para a passagem. Se for especificado, ele substitui o basis_gates kwarg. Se um alvo for especificado, a passagem respeitará as portas e os qubits para as instruções definidas no alvo Target ao decidir quais portas serão consolidadas em uma unitária.

  • A classe Target tem um novo método, instruction_supported() que é usado para consultar o destino para ver se uma instrução (a combinação de uma operação e o(s) qubit(s) em que é executada) é compatível com o back-end modelado pela classe Target.

  • Foi adicionado um novo kwarg, metadata_serializer, à função qpy.dump() para especificar uma subclasse JSONEncoder personalizada para uso ao serializar o atributo QuantumCircuit.metadata e um kwarg duplo metadata_deserializer à função qpy.load() para especificar uma subclasse JSONDecoder . Por padrão, o dump() e load() tentarão serializar e desserializar JSON com o codificador e decodificador json padrão do stdlib. Como QuantumCircuit.metadata pode conter qualquer dicionário Python, mesmo aqueles com conteúdo não serializável em JSON pelo codificador padrão, levará a circuitos que não podem ser serializados. O novo argumento metadata_serializer para dump() permite que os usuários especifiquem um JSONEncoder personalizado que será usado com a chamada interna json.dump() para serializar o QuantumCircuit.metadata dicionário. Isso pode então ser combinado com o novo argumento metadata_deserializer da função qpy.load() para decodificar essas codificações JSON personalizadas. Se metadata_serializer for especificado em dump() mas metadata_deserializer não for especificado em load() o QPY será carregado, mas os metadados do circuito poderão não ser totalmente reconstruídos.

    Por exemplo, se você quiser definir uma serialização personalizada para metadados e depois carregá-la, poderá fazer algo como:

    from qiskit.qpy import dump, load
    from qiskit.circuit import QuantumCircuit, Parameter
    import json
    import io
    
    class CustomObject:
        """Custom string container object."""
    
        def __init__(self, string):
            self.string = string
    
        def __eq__(self, other):
            return self.string == other.string
    
    class CustomSerializer(json.JSONEncoder):
        """Custom json encoder to handle CustomObject."""
    
        def default(self, o):
            if isinstance(o, CustomObject):
                return {"__type__": "Custom", "value": o.string}
            return json.JSONEncoder.default(self, o)
    
    class CustomDeserializer(json.JSONDecoder):
        """Custom json decoder to handle CustomObject."""
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, object_hook=self.object_hook, **kwargs)
    
        def object_hook(self, o):
            """Hook to override default decoder."""
            if "__type__" in o:
                obj_type = o["__type__"]
                if obj_type == "Custom":
                    return CustomObject(o["value"])
            return o
    
    theta = Parameter("theta")
    qc = QuantumCircuit(2, global_phase=theta)
    qc.h(0)
    qc.cx(0, 1)
    qc.measure_all()
    circuits = [qc, qc.copy()]
    circuits[0].metadata = {"key": CustomObject("Circuit 1")}
    circuits[1].metadata = {"key": CustomObject("Circuit 2")}
    with io.BytesIO() as qpy_buf:
        dump(circuits, qpy_buf, metadata_serializer=CustomSerializer)
        qpy_buf.seek(0)
        new_circuits = load(qpy_buf, metadata_deserializer=CustomDeserializer)
  • O passe DenseLayout tem um novo argumento de palavra-chave em seu construtor, target. Esse argumento é usado para especificar um objeto Target que representa o alvo de compilação para a passagem. Se for especificado, ele substitui os outros argumentos no construtor, coupling_map e backend_prop.

  • A classe Target tem um novo método, operation_names_for_qargs(). Esse método é usado para obter os nomes das operações (ou seja, a chave de pesquisa no destino) para as operações em uma determinada tupla qargs .

  • Um novo passe DynamicalDecouplingPadding foi adicionado ao módulo qiskit.transpiler.passes módulo. Essa nova passagem substitui a passagem existente DynamicalDecoupling existente para trabalhar com o novo fluxo de trabalho de agendamento no transpilador. É uma subclasse da passagem BasePadding e depende da execução de passagens de agendamento e análise de alinhamento antes dela em um PassManager. Essa nova passagem pode receber um argumento pulse_alignment que representa uma restrição de hardware para o tempo de início da forma de onda. O espaçamento entre as portas que compõem uma sequência de desacoplamento dinâmico é agora ajustado para satisfazer essa restrição, de modo que o circuito possa ser executado no hardware com a restrição. Esse valor geralmente é encontrado em BackendConfiguration.timing_constraints. Além disso, o passe também tem uma opção extra_slack_distribution para controlar como distribuir a folga extra quando a duração da sequência de desacoplamento dinâmico criada for menor do que o tempo ocioso do circuito que você deseja preencher com a sequência. O padrão é middle , que é idêntico ao comportamento convencional. A nova estratégia split_edges divide uniformemente a folga extra no início e no final da sequência, em vez de adicioná-la ao intervalo no meio da sequência. Isso pode resultar em um melhor cancelamento de ruído, especialmente quando pulse_alignment > 1.

  • A classe Z2Symmetries agora expõe as tolerâncias de limite usadas para cortar pequenas partes reais e imaginárias dos coeficientes. Com isso, é possível controlar como os coeficientes do operador cônico são simplificados. Por exemplo:

    from qiskit.opflow import Z2Symmetries
    from qiskit.quantum_info import Pauli
    
    z2_symmetries = Z2Symmetries(
        symmetries=[Pauli("IIZI"), Pauli("IZIZ"), Pauli("ZIII")],
        sq_paulis=[Pauli("IIXI"), Pauli("IIIX"), Pauli("XIII")],
        sq_list=[1, 0, 3],
        tapering_values=[1, -1, -1],
        tol=1e-10,
    )

    Por padrão, os coeficientes são cortados com uma tolerância de tol=1e-14.

  • Adicionado um método chop() à classe SparsePauliOp que trunca as partes reais e imaginárias dos coeficientes individualmente. Isso é diferente do método SparsePauliOp.simplify() que remove um coeficiente somente se o valor absoluto estiver próximo de 0. Por exemplo:

    >>> from qiskit.quantum_info import SparsePauliOp
    >>> op = SparsePauliOp(["X", "Y", "Z"], coeffs=[1+1e-17j, 1e-17+1j, 1e-17])
    >>> op.simplify()
    SparsePauliOp(['X', 'Y'],
                  coeffs=[1.e+00+1.e-17j, 1.e-17+1.e+00j])
    >>> op.chop()
    SparsePauliOp(['X', 'Y'],
                  coeffs=[1.+0.j, 0.+1.j])

    Observe que o método chop não acumula os coeficientes do mesmo Paulis, por exemplo

    >>> op = SparsePauliOp(["X", "X"], coeffs=[1+1e-17j, 1e-17+1j)
    >>> op.chop()
    SparsePauliOp(['X', 'X'],
                  coeffs=[1.+0.j, 0.+1.j])
  • Foi adicionado um novo kwarg, target, ao construtor da passagem GatesInBasis passagem do transpilador. Esse novo argumento pode ser usado para especificar opcionalmente um objeto Target que representa o backend. Quando definido, esse Target será usado para determinar se um DAGCircuit contém portas fora do conjunto de base e o argumento basis_gates não será usado.

  • Adição de suporte parcial para execução nas plataformas ppc64le e s390x Linux. Esta versão começará a publicar binários pré-compilados para as plataformas ppc64le e s390x Linux em todas as versões do Python. No entanto, ao contrário de outras plataformas compatíveis, nem todas as dependências upstream do Qiskit são compatíveis com essas plataformas ainda. Portanto, pode ser necessário um compilador C/C++ para criar e instalar essas dependências, e um simples pip install qiskit-terra com apenas um ambiente Python em funcionamento não será suficiente para instalar o Qiskit. Além disso, essas mesmas restrições nos impedem de testar as rodas pré-compiladas antes de publicá-las, portanto, as mesmas garantias de suporte à plataforma que existem para as outras plataformas não se aplicam aqui.

  • O Gradient e QFI podem agora calcular a parte imaginária dos gradientes do valor de expectativa. Ao usar uma base de medição diferente, ou seja -Y em vez de Z, podemos medir a parte imaginária dos gradientes. A base de medição pode ser definida com o argumento aux_meas_op .

    Para os gradientes, aux_meas_op = Z calcula 0.5Re[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉] e aux_meas_op = -Y calcula 0.5Im[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉]. Para os QFIs, aux_meas_op = Z calcula 4Re[(dω⟨<ψ(ω)|)(dω|ψ(ω)〉)] e aux_meas_op = -Y calcula 4Im[(dω⟨<ψ(ω)|)(dω|ψ(ω)〉)]. Por exemplo:

    from qiskit import QuantumRegister, QuantumCircuit
    from qiskit.opflow import CircuitStateFn, Y
    from qiskit.opflow.gradients.circuit_gradients import LinComb
    from qiskit.circuit import Parameter
    
    a = Parameter("a")
    b = Parameter("b")
    params = [a, b]
    
    q = QuantumRegister(1)
    qc = QuantumCircuit(q)
    qc.h(q)
    qc.rz(params[0], q[0])
    qc.rx(params[1], q[0])
    op = CircuitStateFn(primitive=qc, coeff=1.0)
    
    aux_meas_op = -Y
    
    prob_grad = LinComb(aux_meas_op=aux_meas_op).convert(operator=op, params=params)
  • A classe InstructionDurations agora tem suporte para trabalhar com parâmetros de uma instrução. Cada entrada em um objeto InstructionDurations agora consiste em uma tupla de (inst_name, qubits, duration, parameters, unit). Isso permite que um InstructionDurations defina durações para uma instrução com um determinado valor de parâmetro para considerar diferentes durações com diferentes valores de parâmetro em uma instrução que usa um parâmetro numérico.

  • Adicionado um novo valor para o argumento da palavra-chave style na função de gaveta de circuito circuit_drawer() e QuantumCircuit.draw() método, iqx_dark. Quando style for definido como iqx_dark com o backend da gaveta mpl , a visualização de saída usará um esquema de cores semelhante ao esquema de cores do modo escuro usado pelo compositor IBM Quantum. Por exemplo:

    from qiskit.circuit import QuantumCircuit
    from matplotlib.pyplot import show
    
    circuit = QuantumCircuit(2)
    circuit.h(0)
    circuit.cx(0, 1)
    circuit.p(0.2, 1)
    
    circuit.draw("mpl", style="iqx-dark")
  • Vários verificadores de dependência preguiçosos foram adicionados ao novo módulo qiskit.utils.optionalsque podem ser usados para consultar se determinada funcionalidade do Qiskit está disponível. Por exemplo, você pode perguntar se o Qiskit detectou a presença de matplotlib perguntando if qiskit.utils.optionals.HAS_MATPLOTLIB. Esses objetos só tentam importar suas dependências quando são consultados, portanto, você pode usá-los no código de tempo de execução sem afetar o tempo de importação.

  • O tempo de importação do qiskit foi significativamente aprimorado, especialmente para aqueles com muitas das dependências opcionais do Qiskit Terra instaladas.

  • A função marginal_counts() agora suporta a marginalização do campo memory de um objeto de entrada Result objeto. Por exemplo, se o argumento de entrada result for um objeto qiskit Result obtido de uma medição de 4 qubits, podemos marginalizar o primeiro qubit com:

    print(result.results[0].data.memory)
    marginal_result = marginal_counts(result, [0])
    print(marginal_result.results[0].data.memory)

    A saída é:

    ['0x0', '0x1', '0x2', '0x3', '0x4', '0x5', '0x6', '0x7']
    ['0x0', '0x1', '0x0', '0x1', '0x0', '0x1', '0x0', '0x1']
  • Os componentes internos do algoritmo StochasticSwap foram reimplementados para serem multithread e agora estão escritos na linguagem de programação Rust em vez de Cython. Isso aumenta significativamente o desempenho do tempo de execução da passagem do compilador e, por extensão transpile() quando executado com optimization_level 0, 1 e 2. Por padrão, a passagem usará até o número de CPUs lógicas em seu sistema local, mas você pode controlar o número de threads usados pela passagem definindo a variável de ambiente RAYON_NUM_THREADS como um valor inteiro. Por exemplo, a configuração RAYON_NUM_THREADS=4 executará o StochasticSwap com 4 threads.

  • Uma nova variável de ambiente QISKIT_FORCE_THREADS está disponível para que os usuários controlem diretamente se as partes potencialmente multithread do código do Qiskit serão executadas em vários threads. Atualmente, isso é usado apenas pela passagem do StochasticSwap mas provavelmente será usado em outras partes do Qiskit no futuro. Quando essa variável env é definida como TRUE , qualquer código multithread no Qiskit Terra sempre usará vários threads, independentemente de quaisquer outras condições de tempo de execução que possam ter feito com que a função usasse uma única variante de thread. Por exemplo, em StochasticSwap se a passagem estiver sendo executada como parte de uma chamada transpile() chamada com > 1 circuito que está sendo executado em paralelo com multiprocessing por meio de parallel_map() o StochasticSwap não usará vários threads para evitar o possível excesso de assinatura de recursos da CPU. No entanto, se você quiser usar vários threads na passagem junto com vários processos, poderá definir QISKIT_FORCE_THREADS=TRUE.

  • Novas classes de back-end falsas estão disponíveis em qiskit.providers.fake_provider. Isso inclui versões simuladas de ibm_cairo, ibm_hanoi, ibmq_kolkata, ibm_nairobi e ibm_washington. Assim como os outros backends falsos, eles incluem instantâneos de dados de calibração e erro obtidos do sistema real e podem ser usados para testes, compilação e simulação locais.

  • Introduziu uma nova classe StatePreparation. Essa classe permite que os usuários preparem um estado desejado da mesma forma que Initialize sem que a redefinição seja aplicada automaticamente.

    Por exemplo, para preparar um qubit no estado (01)/2(|0\rangle - |1\rangle) / \sqrt{2} :

    import numpy as np
    from qiskit import QuantumCircuit
    
    circuit = QuantumCircuit(1)
    circuit.prepare_state([1/np.sqrt(2), -1/np.sqrt(2)], 0)
    circuit.draw()

    A saída é a seguinte:

         ┌─────────────────────────────────────┐
    q_0: ┤ State Preparation(0.70711,-0.70711)
         └─────────────────────────────────────┘
  • A passagem do Optimize1qGates a passagem do transpiler agora tem suporte para otimizar o U1Gate, U2Gate, e PhaseGate com parâmetros não vinculados em um circuito. Anteriormente, se esses portões tivessem parâmetros não vinculados, a passagem não os usaria. Por exemplo:

    from qiskit import QuantumCircuit
    from qiskit.circuit import Parameter
    from qiskit.transpiler import PassManager
    from qiskit.transpiler.passes import Optimize1qGates, Unroller
    
    phi = Parameter('φ')
    alpha = Parameter('α')
    
    qc = QuantumCircuit(1)
    qc.u1(2*phi, 0)
    qc.u1(alpha, 0)
    qc.u1(0.1, 0)
    qc.u1(0.2, 0)
    
    pm = PassManager([Unroller(['u1', 'cx']), Optimize1qGates()])
    nqc = pm.run(qc)

    serão combinados ao circuito com apenas uma porta de um único qubit:

    qc = QuantumCircuit(1)
    qc.u1(2*phi + alpha + 0.3, 0)
  • Os métodos Pauli.evolve() e PauliList.evolve() agora têm um novo argumento de palavra-chave, frame, que é usado para realizar uma evolução de um Pauli por um Clifford. Se for frame='h' (padrão), ele fará a evolução da imagem de Heisenberg de um Pauli por um Clifford ( P=CPCP' = C^\dagger P C ) e, se for frame='s' , ele fará a evolução da imagem de Schrödinger de um Pauli por um Clifford ( P=CPCP' = C P C^\dagger ). A última opção produz um cálculo mais rápido e também é útil em determinados casos. Essa nova opção torna o cálculo do método de decomposição de Clifford com ganância em decompose_clifford significativamente mais rápido.

  • Adicionado um novo módulo ao Qiskit: qiskit.primitives. O módulo de primitivos é onde são definidas as APIs que fornecem diferentes abstrações em torno da computação de determinadas funções comuns do QuantumCircuit , que abstrai os detalhes da execução subjacente em um Backend. Isso permite que os algoritmos e aplicativos de nível superior se concentrem na execução do cálculo, não precisem se preocupar com a execução e o processamento dos resultados e tenham uma interface padronizada para cálculos comuns. Por exemplo, a estimativa de um valor de expectativa de um circuito quântico e observável pode ser realizada por qualquer classe que implemente a classe BaseEstimator e consumida de maneira padronizada, independentemente da implementação subjacente. Os aplicativos podem então ser escritos usando diretamente a interface primitiva.

    Para começar, o módulo contém dois tipos de primitivos, o Sampler (veja BaseSampler para a definição da classe abstrata) e Estimator (veja BaseEstimator para a definição da classe abstrata). As implementações de referência estão incluídas no módulo qiskit.primitives e são criadas usando o módulo qiskit.quantum_info que realizam a simulação ideal da operação primitiva. A expectativa é que os pacotes de provedores ofereçam suas próprias implementações dessas interfaces para provedores que possam implementar o protocolo de forma nativa e eficiente (normalmente usando um tempo de execução clássico). Além disso, no futuro, para provedores que não ofereçam uma implementação nativa das primitivas, será fornecido um método que permitirá a construção de objetos primitivos a partir de um arquivo Backend.

  • Adicionado um novo módulo, qiskit.qpyque contém a funcionalidade anteriormente exposta em qiskit.circuit.qpy_serialization. As funções públicas anteriormente expostas em qiskit.circuit.qpy_serialization, dump() e load() agora estão disponíveis nesse novo módulo (embora ainda possam ser acessadas em qiskit.circuit.qpy_serialization , mas isso será descontinuado em uma versão futura). Esse novo módulo foi adicionado no interesse da direção futura do formato de arquivo QPY, que, em versões futuras, suportará a representação de pulse Schedule e ScheduleBlock além dos objetos QuantumCircuit objetos que ele suporta atualmente.

  • Adicionado um novo atributo, qubit_properties à classe Target classe. Esse atributo contém uma lista de objetos QubitProperties objetos para cada qubit no alvo. Por exemplo:

    target.qubit_properties[2]

    conterá o QubitProperties para o qubit número 2 no alvo.

    Para os BackendV2 autores, se você estava definindo anteriormente QubitProperties diretamente em sua implementação BackendV2 substituindo o BackendV2.qubit_properties() isso ainda funcionará bem. No entanto, se você mover a definição para o objeto subjacente Target subjacente e remover a implementação especializada do BackendV2.qubit_properties() especializada, isso permitirá o uso de propriedades de qubit no transpilador e também manterá a compatibilidade da API com sua implementação anterior.

  • Adicionada uma nova função, qiskit.algorithms.eval_observables()que é usada para avaliar observáveis com um limite QuantumCircuit. Ele se origina de um método privado, _eval_aux_ops(), da classe qiskit.algorithms.VQE mas a nova função eval_observables() é agora mais geral, de modo que pode ser usada em outros algoritmos, por exemplo, algoritmos de evolução temporal.

  • A estratégia de pesquisa de base na passagem do BasisTranslator foi modificada para uma variante da busca Dijkstra, o que melhora muito o desempenho do tempo de execução da passagem ao tentar atingir uma base inalcançável.

  • A passagem do DenseLayout agora é multithread, o que melhora muito o desempenho do tempo de execução da passagem. Por padrão, ele usará o número de CPUs lógicas em seu sistema local, mas você pode controlar o número de threads usados pela passagem definindo a variável de ambiente RAYON_NUM_THREADS como um valor inteiro. Por exemplo, a configuração RAYON_NUM_THREADS=4 executará a DenseLayout com 4 threads.

  • Os cálculos internos de Statevector.expectation_value() e DensityMatrix.expectation_value() foram reimplementados na linguagem de programação Rust. Essa nova implementação é multithread e, por padrão, para um Statevector ou DensityMatrix >= 19 qubits, gerará um pool de threads com o número de CPUs lógicas disponíveis no sistema local. É possível controlar o número de threads usados definindo a variável de ambiente RAYON_NUM_THREADS como um valor inteiro. Por exemplo, a configuração RAYON_NUM_THREADS=4 usará apenas 4 threads no pool de threads.

  • Foi adicionado um novo construtor SparsePauliOp.from_sparse_list() que recebe um iterável, em que os elementos representam termos de Pauli que são esparsos, de modo que "XIIIIIIIIIIIIIIIX" agora pode ser escrito como ("XX", [0, 16]). Por exemplo, o operador

H=X0Z3+2Y1Y4H = X_0 Z_3 + 2 Y_1 Y_4

pode agora ser construído como

op = SparsePauliOp.from_sparse_list([("XZ", [0, 3], 1), ("YY", [1, 4], 2)], num_qubits=5)
# or equivalently, as previously
op = SparsePauliOp.from_list([("IZIIX", 1), ("YIIYI", 2)])

Isso facilita a construção de operadores muito esparsos em muitos qubits, como costuma ser o caso dos Hamiltonianos de Ising.

  • A passagem UnitarySynthesis transpiler pass tem um novo argumento de palavra-chave em seu construtor, target. Isso pode ser usado para especificar opcionalmente um objeto Target que representa o alvo de compilação para a passagem. Quando especificado, ele substituirá os valores definidos para basis_gates, coupling_map e backend_props.

  • A classe UnitarySynthesisPlugin tem um novo atributo opcional que as implementações podem adicionar, supports_target. Se um plug-in tiver esse atributo definido como True , um objeto Target será passado no payload options no campo target . A expectativa é que esse objeto Target seja usado no lugar de coupling_map, gate_lengths, basis_gates e gate_errors.

  • Introduziu um novo fluxo de trabalho de passagem do transpiler para criar PassManager objetos para agendamento de QuantumCircuit objetos no transpiler. No novo fluxo de trabalho, os passes de agendamento e alinhamento são todos AnalysisPass que apenas atualizam o conjunto de propriedades do gerenciador de passes, especificamente o novo item do conjunto de propriedades node_start_time, que mantém a hora de início absoluta de cada opnode. Um TransformationPass separado, como PadDelay é usado posteriormente para aplicar o agendamento ao DAG. Esse novo fluxo de trabalho é mais eficiente e pode corrigir restrições adicionais de tempo expostas por um backend.

    Anteriormente, a cadeia de passagens teria sido implementada como scheduling -> alignment , que eram ambas passagens de transformação, portanto, havia várias instâncias recriadas durante cada passagem DAGCircuit instâncias recriadas durante cada passagem. Além disso, o agendamento ocorreu em cada passagem para obter o horário de início da instrução. Agora, a cadeia de passes necessária se torna scheduling -> alignment -> padding , onde a DAGCircuit atualização ocorre somente no final com a passagem padding .

    Para aqueles que estão criando objetos personalizados PassManager personalizados que envolvam programação de circuitos, será necessário ajustar seu PassManager para inserir um dos BasePadding passes (atualmente PadDelay ou PadDynamicalDecoupling podem ser usados) no final da cadeia de passagens de programação. Sem a passagem de preenchimento, as passagens de agendamento não serão refletidas no circuito de saída do método run() de seu método personalizado PassManager.

    Por exemplo, se você estava construindo seu PassManager com algo como:

    from qiskit.transpiler import PassManager
    from qiskit.transpiler.passes import TimeUnitConversion, ALAPSchedule, ValidatePulseGates, AlignMeasures
    
    pm = PassManager()
    scheduling = [
        ALAPSchedule(instruction_durations), PadDelay()),
        ValidatePulseGates(granularity=timing_constraints.granularity, min_length=timing_constraints.min_length),
        AlignMeasures(alignment=timing_constraints.acquire_alignment),
    ]
    pm.append(scheduling)

    em vez disso, você pode usar:

    from qiskit.transpiler import PassManager
    from qiskit.transpiler.passes import TimeUnitConversion, ALAPScheduleAnalysis, ValidatePulseGates, AlignMeasures, PadDelay
    
    pm = PassManager()
    scheduling = [
        ALAPScheduleAnalysis(instruction_durations), PadDelay()),
        ConstrainedReschedule(acquire_alignment=timing_constraints.acquire_alignment, pulse_alignment=timing_constraints.pulse_alignment),
        ValidatePulseGates(granularity=timing_constraints.granularity, min_length=timing_constraints.min_length),
        PadDelay()
    ]
    pm.append(scheduling)

    que será mais eficiente e também alinhará as instruções com base em quaisquer restrições de hardware.

  • Adicionada uma nova passagem de transpilador ConstrainedReschedule pass. A passagem ConstrainedReschedule considera tanto as restrições de alinhamento de hardware que podem ser definidas em um objeto BackendConfigurationpulse_alignment e acquire_alignment. Essa nova classe substitui a classe AlignMeasures pois executa o mesmo alinhamento (por meio do conjunto de propriedades) para instruções de medição, além do alinhamento geral de instruções. Ao definir o argumento de restrição acquire_alignment para o passe ConstrainedReschedule ele é um substituto imediato de AlignMeasures quando emparelhado com um novo passe BasePadding .

  • Adicionadas duas novas passagens de transpilador ALAPScheduleAnalysis e ASAPScheduleAnalysis que substituem as passagens ALAPSchedule e ASAPSchedule como parte do fluxo de trabalho reformulado do transpiler para schedling. As novas passagens realizam o mesmo agendamento, mas no conjunto de propriedades e contam com uma passagem BasePadding para ajustar o circuito com base em toda a análise de alinhamento do agendamento.

    O comportamento padrão dessas passagens também alinha a ordem de tempo com a ordem topológica dos nós DAG. Essa alteração pode afetar o resultado do agendamento se ele incluir operações condicionais ou medir simultaneamente dois qubits com o mesmo registro clássico (caso extremo). Para reproduzir o comportamento convencional, defina clbit_write_latency idêntico ao comprimento da instrução de medição.

    Por exemplo, considere o agendamento de um circuito de entrada como:

         ┌───┐┌─┐
    q_0: ┤ X ├┤M├──────────────
         └───┘└╥┘   ┌───┐
    q_1: ──────╫────┤ X ├──────
               ║    └─╥─┘   ┌─┐
    q_2: ──────╫──────╫─────┤M├
               ║ ┌────╨────┐└╥┘
    c: 1/══════╩═╡ c_0=0x1 ╞═╩═
               0 └─────────┘ 0
    from qiskit import QuantumCircuit
    from qiskit.transpiler import InstructionDurations, PassManager
    from qiskit.transpiler.passes import ALAPScheduleAnalysis, PadDelay, SetIOLatency
    from qiskit.visualization.timeline import draw
    
    circuit = QuantumCircuit(3, 1)
    circuit.x(0)
    circuit.measure(0, 0)
    circuit.x(1).c_if(0, 1)
    circuit.measure(2, 0)
    
    durations = InstructionDurations([("x", None, 160), ("measure", None, 800)])
    
    pm = PassManager(
        [
          SetIOLatency(clbit_write_latency=800, conditional_latency=0),
          ALAPScheduleAnalysis(durations),
          PadDelay(),
        ]
    )
    draw(pm.run(circuit))

    Como você pode ver na visualização da linha do tempo, a medição em q_2 começa antes da porta X condicional em q_1, o que parece ser oposto à ordem topológica do nó. Esse comportamento também é esperado porque o acesso de gravação do clbit ocorre na borda final da instrução de medida e o acesso de leitura da porta condicional ocorre na borda inicial da instrução. Assim, a ordem topológica é preservada no intervalo de tempo do registro clássico, que não é capturado pela visualização da linha do tempo. Entretanto, isso pressupõe um projeto de microarquitetura específico, e o circuito não precisa ser programado dessa forma.

    Usando a configuração padrão de passes, o circuito é programado como abaixo.

    from qiskit import QuantumCircuit
    from qiskit.transpiler import InstructionDurations, PassManager
    from qiskit.transpiler.passes import ALAPScheduleAnalysis, PadDelay
    from qiskit.visualization.timeline import draw
    
    circuit = QuantumCircuit(3, 1)
    circuit.x(0)
    circuit.measure(0, 0)
    circuit.x(1).c_if(0, 1)
    circuit.measure(2, 0)
    
    durations = InstructionDurations([("x", None, 160), ("measure", None, 800)])
    
    pm = PassManager([ALAPScheduleAnalysis(durations), PadDelay()])
    draw(pm.run(circuit))

    Observe que o clbit fica bloqueado durante todo o intervalo de instruções de medição. Esse comportamento foi projetado com base no Qiskit Pulse, no qual a instrução de aquisição usa AcquireChannel e MemorySlot , que não podem se sobrepor a outras instruções, ou seja, é proibido o acesso simultâneo à memória a partir de instruções diferentes. Isso também sempre alinha a ordem de tempo com a ordem do nó topológico.

  • Adicionada uma nova passagem de transpilador PadDynamicalDecoupling que substitui a passagem DynamicalDecoupling como parte do fluxo de trabalho reformulado do transpiler para agendamento. Essa nova passagem inserirá sequências de desacoplamento dinâmico no circuito de acordo com qualquer análise de programação e alinhamento que tenha ocorrido em passagens anteriores.

  • A função plot_gate_map() função de visualização e as funções criadas com base nela, plot_error_map() e plot_circuit_layout()têm um novo argumento de palavra-chave, qubit_coordinates. Esse argumento recebe uma sequência de coordenadas 2D a serem usadas para plotar cada qubit no backend que está sendo visualizado. Se especificada, essa sequência deverá ter um comprimento igual ao número de qubits no backend e será usada em vez do comportamento padrão.

  • A função plot_gate_map() função de visualização e as funções criadas com base nela, plot_error_map() e plot_circuit_layout()agora podem plotar qualquer backend, não apenas aqueles com o número de qubits igual a um dos backends IBM. Isso se baseia na função retworkx spring_layout() para gerar o layout da visualização. Se o layout padrão não funcionar com o gráfico de acoplamento específico de um backend, você poderá usar a função qubit_coordinates para definir um layout personalizado.

  • A função plot_gate_map() função de visualização e as funções criadas com base nela, plot_error_map() e plot_circuit_layout()agora podem funcionar com um backend baseado em BackendV2 com base em um backend. Anteriormente, essas funções só funcionavam com BaseBackend ou backends baseados em BackendV1 baseados em backends.

  • Adicionada uma nova passagem de transpilador, SetIOLatency. Essa passagem recebe dois argumentos clbit_write_latency e conditional_latency para definir a latência de E/S para bits clássicos e condições clássicas em um backend. Essa passagem definirá esses valores no conjunto de propriedades do gerenciador de passagens para permitir que as passagens subsequentes de programação e alinhamento corrijam essas latências e forneçam uma saída de programação mais precisa de um circuito dinâmico.

  • Uma nova passagem de transpilador PadDelay foi adicionada. Essa passagem preenche o tempo ocioso nos fios do qubit com Delay instruções. Essa passagem faz parte do novo fluxo de trabalho para agendar passagens no transpilador e depende de uma passagem de análise de agendamento (como ALAPScheduleAnalysis ou ASAPScheduleAnalysis) e de quaisquer passagens de alinhamento (como ConstrainedReschedule) a serem executadas antes do PadDelay.

  • A passagem VF2Layout transpiler tem um novo argumento de palavra-chave, target , que é usado para fornecer um Target para a passagem. Quando especificado, o Target será usado pelo passe para todas as informações sobre o dispositivo de destino. Se for especificada, a opção target terá prioridade sobre os argumentos coupling_map e properties .

  • Permitir callables como otimizadores em VQE e QAOA. Agora, o otimizador pode ser um dos otimizadores do Qiskit, como SPSA ou um callable com a seguinte assinatura:

    from qiskit.algorithms.optimizers import OptimizerResult
    
    def my_optimizer(fun, x0, jac=None, bounds=None) -> OptimizerResult:
        # Args:
        #     fun (callable): the function to minimize
        #     x0 (np.ndarray): the initial point for the optimization
        #     jac (callable, optional): the gradient of the objective function
        #     bounds (list, optional): a list of tuples specifying the parameter bounds
    
        result = OptimizerResult()
        result.x = # optimal parameters
        result.fun = # optimal function value
        return result

    A assinatura acima também permite passar diretamente qualquer minimizador SciPy, por exemplo, como

    from functools import partial
    from scipy.optimize import minimize
    
    optimizer = partial(minimize, method="L-BFGS-B")

Problemas Conhecidos

  • Durante a execução parallel_map() (que é feito internamente por funções sensíveis ao desempenho, como transpile() e assemble()) em um subprocesso iniciado fora do parallel_map()é possível que o despacho paralelo executado dentro de parallel_map() fique suspenso e nunca retorne. Isso se deve a problemas de upstream no CPython em torno do método padrão para iniciar subprocessos em Linux e macOS com Python 3.7 (consulte https://bugs.python.org/issue40379 para obter mais detalhes). Se isso acontecer, você terá duas opções: remover os processos paralelos aninhados, pois chamar parallel_map() a partir de um processo principal deve funcionar bem; ou você pode chamar manualmente o módulo multiprocessing da biblioteca padrão do CPython para executar o envio paralelo semelhante a partir de um subprocesso, mas use os métodos de lançamento "spawn" ou "forkserver" para evitar a possibilidade de as coisas ficarem presas e nunca retornarem.

Notas da Atualização

  • As classes Qubit, Clbit e AncillaQubit agora têm o atributo __slots__ . Isso é para reduzir o uso da memória. Como efeito colateral, eles não podem mais ter dados arbitrários anexados a eles como atributos. É muito improvável que isso tenha algum efeito sobre o código downstream além dos benefícios de desempenho.

  • A dependência principal retworkx teve seu requisito de versão aumentado para 0.11.0, em vez de 0.10.1. Isso melhora o desempenho da passagem de transpilação ConsolidateBlocks.

  • A versão mínima compatível do symengine agora é 0.9.0. Isso foi necessário para melhorar a compatibilidade com o módulo pickle do Python, que é usado internamente como parte do envio paralelo com o parallel_map().

  • O valor padrão de QISKIT_PARALLEL quando executado com Python 3.9 em Linux agora está definido como TRUE. Isso significa que, ao executar o parallel_map() ou funções que o chamam internamente, como transpile() e assemble()a função será executada em vários processos e deverá ter melhor desempenho em tempo de execução. Essa alteração foi feita porque os problemas com a confiabilidade do despacho paralelo parecem ter sido resolvidos (consulte #6188 para obter mais detalhes). Se ainda encontrar problemas por causa disso, você poderá desativar o multiprocessamento e reverter para o comportamento padrão anterior definindo a variável de ambiente QISKIT_PARALLEL como FALSE ou definindo a opção parallel como False no arquivo de configuração do usuário (registre também um problema para que possamos rastrear quaisquer problemas relacionados ao multiprocessamento).

  • A classe de porta MSGate , anteriormente obsoleta, encontrada em qiskit.circuit.library foi removida. Ele foi originalmente preterido na versão 0.16.0. Em vez disso, a classe GMS deve ser usada, pois ela permite que você crie uma porta MS equivalente a 2 qubits, além de um MSGate para qualquer número de qubits.

  • O método mirror() , anteriormente obsoleto, da classe Instruction foi removido. Ele foi originalmente preterido na versão 0.15.0. Em vez disso, você deve usar Instruction.reverse_ops().

  • O método num_ancilla_qubits() , anteriormente obsoleto, do qiskit.circuit.library.PiecewiseLinearPauliRotations e qiskit.circuit.library.WeightedAdder foi removido. Ele foi originalmente preterido na versão 0.16.0. Em vez disso, devem ser usados os métodos PiecewiseLinearPauliRotations.num_ancillas() e WeightedAdder.num_ancillas() .

  • O argumento reverse , anteriormente obsoleto, no construtor da classe PolynomialPauliRotations foi removido. Ele foi originalmente preterido na versão 0.15.0. Em vez disso, você deve usar o método QuantumCircuit.reverse_bits() para reverter o PolynomialPauliRotations circuito, se necessário.

  • O argumento angle , anteriormente obsoleto, nos construtores dos objetos C3SXGate e C3XGate foi removido. Ele foi originalmente preterido na versão 0.17.0. Em vez disso, para portas X controladas por 3 frações, você pode usar o método C3XGate.power() .

  • Suporte para o uso de objetos np.ndarray como parte do atributo params de um objeto Gate foi removido. Isso foi descontinuado desde o Qiskit Terra 0.16.0 e agora não funcionará mais. Em vez disso, deve-se criar uma nova subclasse de Gate e permitir explicitamente uma entrada np.ndarray sobrecarregando o método validate_parameter() método.

  • Um novo extra csp-layout-pass foi adicionado ao destino de instalação do pip install qiskit-terra e também está incluído no extra all . Isso não tem efeito no Qiskit Terra 0.20, mas a partir do Qiskit Terra 0.21, as dependências necessárias apenas para a passagem do CSPLayout transpiler pass serão rebaixadas de requisitos para opcionais e instaladas por este extra. Você pode preparar um pacote que dependa dessa passagem definindo seus requisitos (ou o comando pip install ) como alvo qiskit-terra[csp-layout-pass].

  • O suporte para execução com Python 3.6 foi removido. Para executar o Qiskit, você precisa de uma versão mínima do Python do 3.7.

  • A classe AmplitudeEstimator agora herda a classe ABC da biblioteca padrão Python. Isso exige que qualquer subclasse implemente o método estimate() quando anteriormente isso não era necessário. Isso foi feito porque a intenção original da classe era ser sempre uma classe filha de ABC, já que o estimate() é necessário para a operação de um objeto AmplitudeEstimator objeto. No entanto, se você estava definindo anteriormente uma subclasse AmplitudeEstimator que não implementou estimate() isso agora resultará em um erro.

  • O erro gerado por HoareOptimizer se a dependência opcional z3 não estiver disponível foi alterado de TranspilerError para MissingOptionalLibraryError (que é tanto um QiskitError e um ImportError). Isso foi feito para ser consistente com as outras dependências opcionais.

  • Em Linux, o suporte mínimo à biblioteca foi aumentado da VM manylinux2010 para manylinux2014. Isso reflete mudanças semelhantes no Numpy e no Scipy. Não deve haver nenhum efeito significativo para a maioria dos usuários, a menos que seu sistema ainda contenha uma versão muito antiga do glibc.

  • A função marginal_counts() quando chamada com uma entrada de objeto Result agora marginalizará o campo memory dos dados do experimento se ele estiver definido na entrada Result. Anteriormente, o campo memory na entrada não era marginalizado. Essa alteração foi feita porque o comportamento anterior fazia com que o campo counts não correspondesse ao campo memory depois que o marginal_counts() fosse chamado. Se o comportamento anterior for desejado, ele poderá ser restaurado definindo marginalize_memory=None como um argumento para marginal_counts() o que não marginalizará o campo memory .

  • A passagem do StochasticSwap pode retornar resultados diferentes com o mesmo valor de semente definido. Isso se deve à reescrita interna da passagem do transpilador para melhorar o desempenho do tempo de execução. No entanto, isso significa que, se você executou transpile() com optimization_level 0, 1 (o padrão) ou 2 com um valor definido para seed_transpiler , você poderá obter uma saída com um mapeamento de swap diferente presente após a atualização para o Qiskit Terra 0.20.0.

  • Para compilar o Qiskit Terra a partir da fonte, agora é necessário um compilador Rust. Isso se deve à reescrita interna da passagem do StochasticSwap que melhora muito o desempenho do tempo de execução do transpilador. O compilador rust pode ser facilmente instalado usando o rustup, que pode ser encontrado aqui: https://rustup.rs/

  • O atributo name da classe PauliEvolutionGate foi alterado para ser sempre "PauliEvolution". Essa alteração foi feita para ser consistente com outras portas no Qiskit e permite que outras partes do Qiskit identifiquem rapidamente quando uma determinada operação em um circuito é um PauliEvolutionGate. Por exemplo, ele permite o desenrolamento para portas de evolução Pauli.

    Anteriormente, o nome continha os operadores que foram desenvolvidos, o que agora está disponível por meio do atributo PauliEvolutionGate.label atributo. Se um circuito com um PauliEvolutionGate for desenhado, o portão ainda mostrará a mesma informação, quais portões estão sendo desenvolvidos.

  • Os métodos anteriormente obsoletos:

    • qiskit.algorithms.VQE.get_optimal_cost
    • qiskit.algorithms.VQE.get_optimal_circuit
    • qiskit.algorithms.VQE.get_optimal_vector
    • qiskit.algorithms.VQE.optimal_params
    • qiskit.algorithms.HamiltonianPhaseEstimationResult.most_likely_phase
    • qiskit.algorithms.PhaseEstimationResult.most_likely_phase

    que foram originalmente descontinuados na versão do Qiskit Terra 0.18.0 foram removidos e não funcionarão mais.

  • A classe qiskit.algorithms.VariationalAlgorithm agora é definida como uma classe base abstrata (ABC) que exigirá que as classes que herdarem dela definam um método getter e setter VariationalAlgorithm.initial_point .

  • O kwarg pass_manager para a função transpile() foi removido. Ele foi originalmente preterido na versão 0.13.0. A maneira preferida de transpilar um circuito com um objeto PassManager personalizado é usar o método run() do objeto PassManager objeto.

  • A classe ParametrizedSchedule , anteriormente obsoleta, foi removida e não existe mais. Essa classe foi descontinuada como parte da versão 0.17.0. Em vez de usar essa classe, você pode parametrizar diretamente Schedule ou ScheduleBlock especificando um objeto Parameter para o argumento do pulso paramétrico.

  • O módulo qiskit.circuit.library.probability_distributions foi removido e não existe mais, de acordo com o aviso de depreciação do qiskit-terra 0.17.0 (lançado em 1º de abril de 2021). As classes afetadas são UniformDistribution, NormalDistribution e LogNormalDistribution. Todos eles são movidos para a biblioteca qiskit-finance, em seu módulo de biblioteca de circuitos: qiskit_finance.circuit.library.probability_distributions.

  • A classe anterior qiskit.test.mock.fake_mumbai_v2.FakeMumbaiV2 foi renomeada para FakeMumbaiFractionalCX para diferenciá-la do BackendV2 com base em um backend falso para o dispositivo IBM Mumbai, qiskit.test.mock.backends.FakeMumbaiV2. Se você dependia anteriormente da classe FakeMumbaiV2 para obter um backend falso que tinha aplicações fracionárias de CXGate definidas em seu destino, você precisará usar a classe FakeMumbaiFractionalCX , pois a FakeMumbaiV2 não terá mais essas definições extras de porta em seu arquivo Target.

  • O resolvedor usado por QuantumCircuit.append() (e, consequentemente, todos os métodos que adicionam uma instrução em um QuantumCircuit) para converter especificadores de bits foi alterado para torná-lo mais rápido e confiável. Certas construções, como:

    import numpy as np
    from qiskit import QuantumCircuit
    
    qc = QuantumCircuit(1, 1)
    qc.measure(np.array([0]), np.array([0]))

    agora funcionarão onde antes geravam um erro, mas certas entradas patológicas, como:

    from sympy import E, I, pi
    qc.x(E ** (I * pi))

    agora gerarão erros onde antes podiam ocasionalmente (erroneamente) ser bem-sucedidos. Para quase todos os usos corretos, não deve haver nenhuma alteração perceptível, exceto por uma aceleração geral.

  • O método interno semipúblico QuantumCircuit._append() não verifica mais os tipos de suas entradas e assume que não há duplicatas inválidas em suas listas de argumentos. Essa função é usada por determinadas partes internas do Qiskit e de outras bibliotecas para criar instâncias o mais rápido possível, ignorando a verificação de erros quando os dados já são conhecidos como corretos QuantumCircuit o mais rápido possível, ignorando a verificação de erros quando já se sabe que os dados estão corretos. Em geral, os usuários ou funções que recebem dados do usuário devem usar o método public QuantumCircuit.append() que resolve especificadores de bits inteiros, transmite seus argumentos e verifica se as entradas estão corretas.

  • O Cython não é mais uma dependência de compilação do Qiskit Terra e não precisa mais ser instalado ao compilar o Qiskit Terra a partir do código-fonte.

  • Os gerenciadores de passagens predefinidos em qiskit.transpiler.preset_passmanagers para todos os níveis de otimização 2 e 3, conforme gerado por level_2_pass_manager() e level_3_pass_manager() foram alterados para executar o VF2Layout por padrão antes da passagem de layout. A passagem VF2Layout verificará rapidamente se um layout perfeito pode ser encontrado e substitui o que foi feito anteriormente para os níveis de otimização 2 e 3, que usavam uma combinação de TrivialLayout e CSPLayout para tentar encontrar um layout perfeito. Isso resultará em um comportamento potencialmente diferente quando o transpile() é chamado por padrão, pois remove um caminho padrão para todos os níveis de otimização >=2 do uso de um layout trivial (em que circuit.qubits[0] é mapeado para o qubit físico 0, circuit.qubits[1] é mapeado para o qubit físico 1, etc.), supondo que o layout trivial seja perfeito. Se o seu caso de uso depender do layout trivial, você poderá solicitá-lo explicitamente ao transpilar, especificando layout_method="trivial" ao chamar transpile().

  • O gerenciador de passes predefinido para o nível de otimização 1 (ao chamar transpile() com optimization_level=1 ou quando nenhum argumento optimization_level é definido), conforme gerado por level_1_pass_manager() foi alterado para que VF2Layout seja chamado por padrão para verificar rapidamente se um layout perfeito pode ser encontrado antes da chamada do DenseLayout. No entanto, diferentemente dos níveis de otimização 2 e 3, um layout trivial ainda é tentado antes da execução VF2Layout e, se for um mapeamento perfeito, a saída de VF2Layout será usado.

Notas de descontinuação

  • O argumento max_credits para execute()e todas as configurações de Qobj (por exemplo. QasmQobjConfig e PulseQobjConfig), está obsoleto e será removido em uma versão futura. O sistema de crédito não está em uso nos back-ends do IBM Quantum há dois anos e a opção não tem efeito. Nenhuma alternativa é necessária. Por exemplo, se você estivesse chamando execute() como:

    job = execute(qc, backend, shots=4321, max_credits=10)

    você pode simplesmente omitir o argumento max_credits :

    job = execute(qc, backend, shots=4321)
  • O uso de um número inteiro ímpar para o argumento order no construtor da classe SuzukiTrotter está obsoleto e não funcionará mais em uma versão futura. As fórmulas de produto usadas pelo SuzukiTrotter só são definidas quando a ordem é par, pois as fórmulas de produto de Suzuki são simétricas.

  • Os kwargs qregs, cregs, layout e global_phase para as classes MatplotlibDrawer, TextDrawing e QCircuitImage e o kwarg calibrations para a classe MatplotlibDrawer estão obsoletos e serão removidos em uma versão posterior.

Correções de bugs

  • Correção de um erro nas funções de conversão de circuitos circuit_to_gate() e circuit_to_instruction() (e seus métodos de circuito associados QuantumCircuit.to_gate() e QuantumCircuit.to_instruction()) ao atuar em um circuito com bits sem registro ou bits em mais de um registro.

  • Foi corrigido um problema em que chamar QuantumCircuit.copy() nos circuitos "body" de uma operação de fluxo de controle criada com a interface do construtor gerava um erro. Por exemplo, isso era anteriormente um erro, mas agora retornará com êxito:

    from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
    
    qreg = QuantumRegister(4)
    creg = ClassicalRegister(1)
    circ = QuantumCircuit(qreg, creg)
    
    with circ.if_test((creg, 0)):
        circ.h(0)
    
    if_else_instruction, _, _ = circ.data[0]
    true_body = if_else_instruction.params[0]
    true_body.copy()
  • Adicionada uma entrada ausente da biblioteca de equivalência de sessão padrão entre CXGate e CPhaseGate bem como entre CXGate e CRZGate.

  • Foi corrigido um problema em que a execução do operador == entre dois SparsePauliOp gerava um erro quando os dois operadores tinham números diferentes de coeficientes. Por exemplo:

    op = SparsePauliOp.from_list([("X", 1), ("Y", 1)])
    op2 = SparsePauliOp.from_list([("X", 1), ("Y", 1), ("Z", 0)])
    print(op == op2)

    Anteriormente, isso geraria um ValueError em vez de retornar False.

  • Corrigido o suporte em transpile() para passar um objeto InstructionScheduleMap para o objeto subjacente PassManager subjacente com base na função Target para BackendV2 baseados em backends. Anteriormente, a função transpile() não fazia esse processamento e qualquer passagem do transpilador que não suportasse trabalhar com um objeto Target ainda não teriam acesso às calibrações de pulso padrão para as instruções de um BackendV2 backend.

  • O AmplitudeAmplifier agora está disponível corretamente no módulo raiz qiskit.algorithms diretamente. Anteriormente, ele não era incluído nas classes reexportadas do módulo raiz e só podia ser acessado em qiskit.algorithms.amplitude_amplifiers. Corrigido #7751.

  • Correção de um problema com o backend mpl para a função de gaveta de circuito circuit_drawer() e o método QuantumCircuit.draw() em que as portas com condições não eram exibidas corretamente quando um número suficiente de portas fazia com que a gaveta se dobrasse em uma segunda linha. Corrigido: #7752.

  • Foi corrigido um problema em que o método HHL.construct_circuit() , sob determinadas condições, não retornava um valor correto de QuantumCircuit. Anteriormente, a função apresentava um erro de arredondamento no cálculo de quantos qubits eram necessários para representar os valores próprios, o que causava uma saída incorreta do circuito.

  • Corrigido um bug de endianness em BaseReadoutMitigator.expectation_value() quando uma string diagonal era passada. Agora ele será interpretado corretamente como little endian da mesma forma que o restante do Qiskit Terra, em vez de big endian.

  • Foi corrigido um problema com a função quantum_info.partial_trace() quando a função foi solicitada a rastrear nenhum subsistema, ela agora retornará corretamente o DensityMatrix do estado de entrada com todas as dimensões restantes, em vez de gerar um erro. Corrigido #7613

  • Correção de um problema com o backend text para a função de gaveta de circuito circuit_drawer() e o método QuantumCircuit.draw() quando os portões que usam texto lateral, como o CPhaseGate e RZZGate com condições clássicas definidas não eram exibidas corretamente. Corrigido #7532.

  • Foi corrigido um problema com a função circuit_drawer() função e draw() do método QuantumCircuit. Ao usar a opção reverse_bits com as opções mpl, latex ou text , os bits sem registros não eram exibidos na ordem correta. Corrigido #7303.

  • Corrigido um problema no método LocalReadoutMitigator.assignment_matrix() em que o método rejeitava anteriormente um valor de entrada para o argumento qubits que não fosse uma sequência trivial de qubits no formato: [0, 1, 2, ..., n-1]. Isso foi corrigido, de modo que agora qualquer lista de índices de qubit a ser medida é aceita pelo método.

  • Foi corrigido um problema no cálculo do valor de expectativa do método StabilizerState.expectation_value() no cálculo do valor de expectativa do método, em que o valor de expectativa de saída seria incorreto se o operador de entrada do argumento tivesse uma fase não trivial Pauli para o argumento oper tivesse uma fase não trivial. Corrigido #7441.

  • Uma expressão opflow que contém a identidade de Pauli opflow.I não produz mais um IGate quando convertida em um circuito. Essa mudança corrige uma diferença de expectativa; a porta de identidade no circuito indica um atraso, mas no opflow esperamos uma identidade matemática, ou seja, nenhuma operação.

  • O PauliGate não insere mais um IGate para Paulis com o rótulo "I".

  • PauliSumOp os testes de igualdade agora lidam com o caso em que um dos itens comparados é um único PauliOp. Por exemplo, 0 * X + I == I agora é avaliado como True, enquanto era False antes desta versão.

  • Foi corrigido um problema com o ALAPSchedule e ASAPSchedule ao trabalhar com instruções que tinham calibrações de pulso personalizadas (ou seja, portas de pulso) definidas. Anteriormente, as passagens de programação não usavam a duração da calibração de pulso personalizada para essas instruções, o que resultava na geração de uma programação incorreta para o circuito. Isso foi corrigido, de modo que agora as passagens de agendamento usarão a duração da calibração de pulso personalizada para qualquer instrução no circuito que tenha uma calibração personalizada.

  • Corrigido o suporte ao uso de ParameterExpression parametrizadores de instrução na passagem do RZXCalibrationBuilder passagem do transpilador. Anteriormente, se um parâmetro de instrução incluísse um limite ParameterExpression a passagem não seria capaz de lidar com isso corretamente.

  • Parou o analisador em QuantumCircuit.from_qasm_str() e from_qasm_file() de aceitar programas OpenQASM que se identificavam como sendo de uma versão de linguagem diferente de 2.0. Esse analisador é apenas para OpenQASM 2.0; o suporte para circuitos importados de OpenQASM 3.0 será adicionado em uma versão futura.

  • O exportador OpenQASM 3, qasm3.Exporter, agora escapará dos nomes de registros e parâmetros que colidirem com as palavras-chave reservadas do OpenQASM 3, gerando um novo nome exclusivo. Os registros e parâmetros com o mesmo nome não terão mais conflitos de nomes na saída de código do exportador OpenQASM 3. Corrigido #7742.

Aer 0.10.3

Nenhuma mudança

Ignis 0.7.0

Nenhuma mudança

IBM 0.18.3

Nenhuma mudança

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