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:
Suporte para importação de programas do OpenQASM 3 e criação de
QuantumCircuitobjetos do programa de entrada por meio de duas novas funçõesqiskit.qasm3.load()eqiskit.qasm3.loads().Aprimoramentos na biblioteca de algoritmos de síntese incluídos no Qiskit. Isso inclui as seguintes novas funções de síntese:
Síntese de Clifford
Síntese de funções lineares:
Síntese de permutação:
SolovayKitaevDecompositiondetalhado em: https://arxiv.org/abs/quant-ph/0505030Novos plug-ins para
HighLevelSynthesis:
ACGSynthesisPermutationKMSSynthesisPermutationBasicSynthesisPermutationNovo plug-in para
UnitarySynthesisMelhorias de desempenho para
SabreLayout. A passagem agora é escrita principalmente em Rust, o que pode levar a uma melhoria no tempo de execução; no entanto, a maior melhoria está na qualidade do resultado (em média, menosSwapGategates introduzidos peloSabreSwap). Por exemplo, a execução deSabreLayouteSabreSwapem circuitos Bernstein Vazirani direcionados para o backendFakeSherbrookeproduz os seguintes resultados:![]()
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.librarypode ser inicializado com o novo parâmetro
angle, de modo que dois parâmetros de flutuação podem ser fornecidos:ampeangle. A inicialização com o complexoampainda é suportada. -
A classe
AdaptVQEtem 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.historydeve ser aproximadamente[-1.85727503], pois há uma única iteração. -
O registro de tempo de execução ao executar o
AdaptVQEfoi aprimorado. Ao executar a classe agora, as mensagens de registro de nívelDEBUGeINFOserã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çãoCollectLinearFunctionsfoi atualizado para herdar deCollectAndCollapsee coleta blocos deCXGateeSwapGatee substitui cada bloco por umLinearFunction. OCollectCliffordsque agora também é baseado emCollectAndCollapse, coleta blocos de portas "Clifford" e substitui cada bloco por umClifford.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_analysispermite 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
BlockCollectorque implementa várias estratégias de coleta e uma nova classeBlockCollapserque implementa várias estratégias de colapso. Atualmente,BlockCollectorinclui 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) eBlockCollapserinclui 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 únicoClifford). -
Foi adicionada uma nova
CollectCliffordsque coleta blocos de portas de Clifford e consolida esses blocos emqiskit.quantum_info.Cliffordobjetos. Essa passagem é herdada deCollectAndCollapsee, em particular, suporta a opçãodo_commutative_analysis. Ele também oferece suporte a duas opções adicionais:split_blocksemin_block_size. Consulte as notas de versão deCollectAndCollapseeCollectLinearFunctionspara obter mais detalhes. -
A passagem
CollectLinearFunctionstranspiler 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_sizefor 1 ou 2, e permanecerão inalteradas quandomin_block_sizefor 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 linearesLinearFunctionsobre 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 novoDAGOpNodeque é 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()paraPermutationsobre a arquitetura linear do vizinho mais próximo, seguindo o documento: https://arxiv.org/abs/quant-ph/0701194 -
Adicionada uma nova classe
PermutationGatepara representar a lógica de permutação como um elemento de circuito. Ao contrário do elemento de biblioteca de circuitosPermutationexistente, 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.QFIeqiskit.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 arquivoLinCombEstimatorGradient. Esse argumento recebe um enumDerivativeTypeque permite especificar o cálculo apenas das partes reais ou imaginárias do gradiente. -
Adição de uma nova opção
circuit_reverse_bitsao arquivo de configuração do usuário. Isso permite que os usuários definam um booleano para o comportamento padrão preferido do argumentoreverse_bitsdos desenhistas de circuitoQuantumCircuit.draw()ecircuit_drawer(). Por exemplo, adicionar uma seção ao arquivo de configuração do usuário no local padrão~/.qiskit/settings.confcom:[default] circuit_reverse_bits = Truealterará o padrão para exibir os bits na ordem inversa.
-
Adicionada uma nova classe
Z2Symmetriestoqiskit.quantum_infoque é usada para identificar quaisquer simetrias de uma entradaSparsePauliOp. -
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 aScheduleBlockrepresentar instruções com intervalos de tempo absolutos. Isso permite que o construtor de pulsos convertaScheduleemScheduleBlock, em vez de envolver asCallinstruçõ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 classeqiskit.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
ImaginaryVariationalPrincipleinterface 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
XXPlusYYGateeXXMinusYYGatepara outros portões do siteSessionEquivalenceLibrary. Isso permite a execução detranspile()direcionado a um backend ouTargetque usa essas portas. -
Adicionados dois novos backends falsos,
FakePragueeFakeSherbrookeao móduloqiskit.providers.fake_providermódulo.FakePraguefornece um backend com um instantâneo das propriedades do backend IBM Prague Egret R1 eFakeSherbrookefornece 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, aoParameterExpression.bind()eParameterExpression.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étodoobservablesagora aceita um tipo de entradastrou uma sequência destr, 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 objetosPauliobjetos. -
Adicionado um novo método construtor
QuantumCircuit.from_instructions()que permite criar um objetoQuantumCircuita 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")
-
A classe
Cliffordagora recebe um argumento opcional da palavra-chavecopyem seu construtor. Se definido comoFalse, umStabilizerTablefornecido 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 umCliffordem 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
Cliffordem profundidade de 2 qubits 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 depower()agora retorna uma instânciaIGateem vez deUnitaryGatecomo era feito anteriormente.A lista completa dos tipos de saída que foram aprimorados é a seguinte:
-
O
EquivalenceLibraryagora é representado internamente como umPyDiGraph, esse objeto gráfico subjacente pode ser acessado a partir do novo atributographatributo. 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-chaveignore_set_layoutpode ser definido comoTruepara 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-chavefinal_layoutpara passar um objetoLayouta ser usado para a permutação de saída. -
Foi adicionado suporte à passagem
GateDirectionpara lidar com a passagem do transpilador simétricoRXXGate,RYYGate, eRZZGatesimé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 objetosGateagora é suportado. Isso equivale a executar o métodoGate.power()no objeto.Por exemplo:
from qiskit.circuit.library import XGate sx = XGate() ** 0.5 -
Adicionada nova forma de pulso
GaussianSquareDragaoqiskit.pulse.librarymódulo. Esse formato de pulso é semelhante aoGaussianSquaremas usa a formaDragdurante 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 doFiniteDiffEstimatorGradienteFiniteDiffSamplerGradientclasses. O argumentomethodaceita 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étodoCálculo"central""forward""backward"em que é o epsilon de deslocamento.
-
Todas as classes de gradiente em
qiskit.algorithms.gradientsagora 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
TranslateParameterizedGatespara 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
CollectCliffordsa passagem do transpilador foi expandida para coletar e combinar blocos de "clifford gates" em objetosCliffordonde "clifford gates" agora também podem incluir objetos do tipoLinearFunction,Clifford, ePauliGate. 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 únicoCliffordobjeto. -
CouplingMapagora é implicitamente iterável, com a iteração sendo idêntica à iteração através da saída deCouplingMap.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çãoqiskit.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. -
InstructionScheduleMapfoi 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.ScheduleDefCallableDefPulseQobjDef
Essas classes implementam os métodos
get_schedule()eget_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 peloInstructionScheduleMapou backendTargete, portanto, não aparecerão em programas típicos de usuários. -
Introduziu uma nova subclasse
ScalableSymbolicPulse, como uma subclasse deSymbolicPulse. A nova subclasse se comporta da mesma forma queSymbolicPulseexceto pelo fato de pressupor que o envelope do pulso inclui um pré-fator de amplitude complexa da forma . 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 emamp,anglenesta versão).A nova subclasse elimina a natureza não exclusiva da representação
amp,anglee compara corretamente os pulsos de acordo com sua amplitude complexa. -
Foi adicionado um novo argumento de palavra-chave,
dtype, ao métodoPauliSumOp.from_list()método. Quando especificado, esse argumento pode ser usado para especificar odtypeda matriz numpy alocada para oSparsePauliOpusada internamente pelo sistema construídoPauliSumOp. -
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()eqasm3.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
QuantumCircuitna variávelcircuit.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()eqasm3.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 usarqiskit.qpy. -
As
primitives-definidas pelas classes de gradienteBaseEstimatorGradienteBaseSamplerGradientforam 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,_postprocesspermite personalizar o resultado de saída e_run_uniquepermite calcular o gradiente de um circuito com parâmetros exclusivos. -
A passagem do
SabreLayoutmelhorou 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 argumentorouting_passou usando o novo argumentoskip_routing. -
A passagem
SabreLayouttranspiler pass tem um novo argumento de construtorlayout_trials. Esse argumento é usado para controlar quantas sementes de gerador de números aleatórios serão tentadas para execuçãoSabreLayoutcom. Quando definido, o algoritmo de layout do SABRE é executadolayout_trialsnú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, aSabreLayoutusará como padrão o número de CPUs físicas disponíveis no sistema local. -
Adicionadas duas novas classes
SciPyRealEvolvereSciPyImaginaryEvolverque 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 comoTimeEvolutionResult.observableseTimeEvolutionResult.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
SolovayKitaevpara 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
UnitarySynthesistranspiler 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')
-
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 qubitsC3SXGateeRC3XGatee os valores permitidos demax_operandsforam expandidos de acordo. -
A passagem
Optimize1qGatesDecompositiontranspiler pass tem um novo argumento de palavra-chave,target, em seu construtor. Esse argumento pode ser usado para especificar um objetoTargetque representa o destino da compilação. Se usado, ele substitui o argumentobasispara determinar se uma instrução no circuito está presente no backend de destino. -
A passagem
UnrollCustomDefinitionstranspiler pass tem um novo argumento de palavra-chave,target, em seu construtor. Esse argumento pode ser usado para especificar um objetoTargetque representa o destino da compilação. Se usado, ele substitui o argumentobasis_gatespara determinar se uma instrução no circuito está presente no backend de destino. -
Adicionada a classe
ReverseEstimatorGradientpara 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 classeOneQubitEulerDecomposerclasse. Quandouse_dagestiver definido comoTrue, a saída do decompositor será um objetoDAGCircuitem vez de um objetoQuantumCircuitobjeto. Isso é útil para passagens de transpiladores que usamOneQubitEulerDecomposer(comoOptimize1qGatesDecomposition), pois trabalhar diretamente com umDAGCircuitevita a sobrecarga de conversão entreQuantumCircuiteDAGCircuit. -
Foi adicionada a capacidade de os passes de análise definirem pesos heurísticos personalizados para os atributos
VF2LayouteVF2PostLayoutpassagens do transpilador. Se uma passagem de análise definir a chavevf2_avg_error_mapno conjunto de propriedades, seu valor será usado para os pesos de erro, em vez das taxas de erro do backendTarget(ouBackendPropertiesparaBackendV1). O valor deve ser uma instânciaErrorMap, 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 forNaN, 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.0024no qubit 0 e0.0032no 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 chavevf2_avg_error_mapno conjunto de propriedades quandoVF2LayouteVF2PostLayoutforem 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
VF2Layoutcom a pontuação personalizada deerror_mappara um 2 qubitTargetque 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
ampcomplexo com umanglefinito resultará emPulseErroragora. Por exemplo, em vez de chamarGaussian(duration=100,sigma=20,amp=0.5j), deve-se usarGaussian(duration=100,sigma=20,amp=0.5,angle=np.pi/2)agora. O envelope de pulso que costumava ser definido comoamp * ...é, por sua vez, definido comoamp * 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óduloqiskit.transpiler.passesfoi removida. Ele foi originalmente descontinuado como parte da versão do Qiskit Terra 0.16.0 (16/10/2020). Em vez disso, a passagemBasisTranslatortranspiler pass deve ser usado para traduzir um circuito em uma base apropriada com umRXXGate -
EquivalenceLibraryque são inicializados com o atributobasenão terão mais uma referência compartilhada com o objetoEquivalenceLibrarypassado. Em versões anteriores, se você alterasse o endereçobasedepois que ele fosse usado para criar uma novaEquivalenceLibraryambas as instâncias refletiriam essa alteração. Esse não é mais o caso e as atualizações embasenão serão mais refletidas no novoEquivalenceLibrary. 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_libcom: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_libtambém incluía a definição deSXGatedepois que ela foi adicionada ao siteoriginal_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 classeEquivalenceLibraryclasse, especialmente quando há várias execuções da passagem doBasisTranslatorpassagem do transpilador. -
O argumento
initial_statepara o construtor da classeNLocaljuntamente com a atribuição direta ao atributoNLocal.initial_statedeve ser umQuantumCircuitagora. 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ãoprecisionfoi 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 siteScalableSymbolicPulse, que foi tratado com a adição de um atributoclass_name_sizeao cabeçalho dos objetos despejadosSymbolicPulsedespejados. -
O método
__hash__para oSymbolicPulsefoi 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 usarSymbolicPulseem situações em que um objeto hashable era necessário. Isso significa que o método internohash()e o uso deSymbolicPulsecomo chaves em dicionários ou membros de conjuntos não funcionarão mais. -
Os nomes das
Register(que incluem instâncias deQuantumRegistereClassicalRegigster) 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 controladascu1,cu3emcu1foram 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 geraisp(),u(),cp()ecu(). As classes de portasU1Gate,U2GateeU3Gateainda estão disponíveis para uso comQuantumCircuit.append()portanto, os back-ends ainda podem oferecer suporte a bases com essas portas explicitamente fornecidas. -
Os métodos
QuantumCircuitcombineeextendforam 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 deQuantumCircuit.compose()que deveriam ser usadas em seu lugar.A remoção do
extendtambém significa que os operadores+e+=não estão mais definidos paraQuantumCircuit. Em vez disso, você pode usar os operadores&e&=, respectivamente, que usamQuantumCircuit.compose(). -
As funções anteriormente obsoletas:
qiskit.circuit.measure.measure()eqiskit.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 oQuantumCircuit.measure()eQuantumCircuit.reset()do objetoQuantumCircuitdo objeto que deseja anexar umMeasureouReseta uma operação. -
Os métodos anteriormente obsoletos de
ParameterViewque foram herdados desetforam removidos deParameterView, o tipo retornado porQuantumCircuit.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
ParameterViewagora é um tipo de visualização de sequência geral e não é mais compatível com essas operaçõesset. -
Os métodos de conversão NetworkX para os métodos de conversão
DAGCircuiteDAGDependencyclasses:DAGCircuit.to_networkx(),DAGCircuit.from_networkx(), eDAGDependency.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 noDAGCircuite/ou rustworkx. No entanto, desde aquela época, tanto oDAGCircuite o rustworkx amadureceram e oferecem mais funcionalidades, e oDAGCircuitestá fortemente acoplado ao rustworkx para sua operação e o fato de esses métodos conversores fornecerem funcionalidade limitada e, portanto, foram removidos. -
tweedledumfoi removido como um requisito essencial do Qiskit Terra. A funcionalidade fornecida (qiskit.circuit.classicalfunction) ainda estará disponível se o sitetweedledumfor instalado manualmente, como por exemplo:pip install tweedledumEssa alteração foi feita porque o desenvolvimento do
tweedledumdiminuiu 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_PYLATEXeHAS_PDFTOCAIROnão são mais expostos a partir deqiskit.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 passagemDecomposejuntamente com seu atributo correspondenteDecompose.gatefoi 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 argumentogates_to_decomposepara o construtor junto com o atributoDecompose.gates_to_decompose. O argumento e o atributogates_to_decomposedevem 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 doMCMTeMCMTVChainfoi removido. Ele foi descontinuado a partir da versão do Qiskit Terra 0.19.0 (dezembro de 2021). Usar o argumentolabelnessas classes era um comportamento indefinido, pois elas são subclasses deQuantumCircuitem vez deInstruction. Isso faria com que o rótulo atribuído fosse geralmente ignorado. Se você precisar atribuir umlabela uma instância deMCMTouMCMTVChainvocê deve convertê-los em uma instância deGatecomto_gate()e, em seguida, atribuir o rótulo desejado ao atributolabelatributo. 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
retworkxdo Qiskit foi removida e substituída pela bibliotecarustworkx. Esses são os mesmos pacotes, masrustworkxé o novo nome pararetworkx, 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
SabreLayoutdo compilador foi alterado. O passe não é mais umAnalysisPasse, por padrão, calcula o layout inicial, aplica-o ao circuito e também executaSabreSwapinternamente e aplicará o mapeamento de troca e definirá a propriedadefinal_layoutcom a permutação causada pelas inserções de troca. Isso significa que, para usuários que executamSabreLayoutcomo parte de um aplicativo personalizadoPassManagerpersonalizado precisarão ajustar o gerenciador de passes para levar isso em conta (a menos que estejam definindo o argumentorouting_passparaSabreLayout). Essa alteração foi feita com o objetivo de melhorar a qualidade do resultado, pois a qualidade do layout e do roteamento é altamente acopladaSabreLayoutagora 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
SabreLayoutaplicará o layout e você não precisará mais do estágio de incorporação. Como alternativa, você pode especificar o argumentorouting_passque reverteráSabreLayoutao seu comportamento anterior. Por exemplo, se você quiser executar oSabreLayoutcomo 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á
SabreLayoutexecutado como uma passagem de análise e apenas definirá o conjunto de propriedadeslayout. A abordagem final é aproveitar o argumentoskip_routingemSabreLayout; quando esse argumento for definido comoTrue, 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 siteSabreLayoutainda 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 argumentorouting_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 passagemSabreLayoutem 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 oqiskit.qpypara salvar o circuito e, em seguida, carregá-lo usando a versão atual. Como alternativa, você pode definir explicitamente o argumentorouting_passcomo uma instância deSabreSwappara espelhar o comportamento anterior deSabreLayout: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_trialsemSabreLayoutem versões anteriores ao ajustar o uso para essa forma, você precisará definir o argumentotrialsno construtorSabreSwapse quiser manter a saída anterior com uma semente fixa. -
O circuito exato retornado por
qiskit.circuit.random.random_circuitpara 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 viapip install qiskit-terra[toqm], foi atualizado da versão0.0.4para0.1.0. Para usar o método de roteamentotoqmcomtranspile()agora você deve usar a versão0.1.0ou mais recente do qiskit-toqm. As versões mais antigas não são mais detectáveis pelo transpilador. -
A saída
QuasiDistributiondo métodoSampler.runfoi 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 bits000,001,010,011,100,101,110e111), 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 doBaseSampler. -
O comportamento do construtor de pulsos quando um
Scheduleé chamado foi atualizado. As programações chamadas são internamente convertidas emScheduleBlocke, agora, o mecanismo de referência é sempre aplicado, em vez de anexar as programações incluídas pela instruçãoCallinstruçã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, aCallinstrução eSchedulenã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 porCallpoderá acessar oScheduleBlock.referencespara recuperar o programa chamado. -
RZXCalibrationBuildereRZXCalibrationBuilderNoEchoforam atualizados para gerarScheduleBlock. Essa alteração garante que os circuitos transpilados sejam sempre compatíveis com o QPY. Se você estiver usando diretamente o métodorescale_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çãoPlaycom 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
LinearFunctionsSynthesisestá obsoleta e será removida em uma versão futura. Ela foi substituída pela classe mais geralHighLevelSynthesismais geral, que deve ser usada em seu lugar. Por exemplo, você pode instanciar uma instância deHighLevelSynthesisque se comportará da mesma forma queLinearFunctionSynthesiswith: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 chamartranspile()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()oumultiprocessingda biblioteca padrão Python se quiser executar isso em paralelo. -
A versão antiga da gaveta de pulsos presente no site
qiskit.visualization.pulsefoi descontinuada e será removida em uma versão futura. Isso inclui as classesScheduleDrawere :class`WaveformDrawer`. Esse módulo foi substituído pela gavetaqiskit.visualization.pulse_v2e a API típica do usuáriopulse_drawer()ePulseBlock.draw()já foram atualizadas internamente para usarqiskit.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 gavetaqiskit.visualization.pulse_v2, que não exige que os objetosInstruciontenham seu próprio método de desenho. Se você precisar desenhar uma instrução de pulso, deverá usar opulse_drawer()em vez disso. -
A importação
qiskit.circuit.qpy_serializationestá obsoleta, pois o QPY foi promovido ao nível superior. Você deve importar os mesmos objetos deqiskit.qpyem vez disso. O caminho antigo será removido em um futuro do Qiskit Terra. -
O objeto
qiskit.IBMQestá obsoleto. Esse objeto de alias redireciona o acesso ao atributo paraqiskit.providers.ibmq.IBMQ. Como o pacoteqiskit-ibmq-providerfoi substituído pelo pacoteqiskit-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 aliasqiskit.IBMQ, deve atualizar seu uso para usar diretamente oqiskit.providers.ibmq.IBMQ(e também considerar a migração para oqiskit-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()eqiskit.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 doStatevector.draw()eDensityMatrix.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 subclassesQuantumRegistereClassicalRegister. A descontinuação se deve ao fato de que o métodoqasm()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_formatestá 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()eqiskit.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çõesqiskit.synthesis.synth_clifford_full()eqiskit.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(consulteamplitude_estimators) para o uso com primitivos construídos a partir do móduloBaseSampler(comoSamplereBackendSampler). 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()eDAGCircuit.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 emfloat,QuantumCircuit.add_calibrations()usava os parâmetros fornecidos como estão. Isso poderia causar um erro ao executartranspile()em umQuantumCircuitcom portas de pulso, pois os parâmetros das calibrações poderiam ser mantidos como objetosParameterExpresion. -
Foi corrigido um problema de desserialização no sistema (
qiskit.qpy)load()do QPY, onde os circuitos contendo portas da classeMCXGate,MCXGrayCode,MCXRecursive, eMCXVChainfalhariam 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étodoBackendSampleragora define os atributosshotsestddev_upper_boundda classeQuasiDistribution. 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 ( em vez de ) é usado para verificar se um determinado parâmetro está próximo de uma fração/potência de . Corrigido o número 7166. -
Corrigido o suporte no módulo
primitivespara execução de objetosQuantumCircuitcom instruções de fluxo de controle (por exemploIfElseOp). Anteriormente, as classes de baseBaseSamplereBaseEstimatornã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 deBaseSamplerouBaseEstimatoruse instruções de fluxo de controle. -
Foi corrigido um problema no método
PauliOp.matmul(), que retornava resultados incorretos comiI. 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étodosQuantumCircuitcomo os métodosappend(). 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 argumentoclbits. 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 comoptimization_leveldefinido como1,2, ou3e nenhum argumentobackend,basis_gates, outargetespecificado. 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 argumentosbackend,basis_gatesoutargetna chamadatranspile()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 comoptimization_level=3e nenhum argumentobackend,basis_gatesoutargetespecificado. 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 argumentosbackend,basis_gatesoutargetna chamadatranspile()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
LinCombSamplerGradientem que ele potencialmente gerava um erro quando executado com a classeSamplerda classeqiskit-aer. -
Foi corrigido um problema com o
NumPyEigensolvere, por extensãoNumPyMinimumEigensolverem que a solução paraBaseOperatorsubclasses diferentes deOperatorcausava um erro. -
Foi corrigido um problema na saída de metadados do
primitivesem 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
QobjToInstructionConverterquando 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
PVQDem 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
TwoQubitWeylDecompositionagora é compatível com o protocolopickle. Anteriormente, a desserialização falhava e gerava umTypeError. Consulte #7312. -
Foi corrigido um problema com o método
LocalReadoutMitigator.quasi_probabilities()em que o argumentoshotsnã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
ClifforddeQuantumCircuitsque contêm outros objetosCliffordobjetos. -
Foi corrigido um problema com a classe
TwoQubitWeylDecomposition(e suas subclasses) para permitir que a biblioteca padrão Pythonpickleserialize 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
RZXCalibrationBuilderem 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