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
Targetno transpilador. Vários passes agora suportam o trabalho direto com um objetoTargeto que torna o transpilador robusto em relação aos tipos de backends que ele pode usar. - A introdução do
qiskit.primitivesmódulo. Essas APIs oferecem diferentes níveis de abstração para computar resultados de interesse deQuantumCircuite usar backends. Por exemplo, oBaseEstimatordefine 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, oBaseSamplercalcula 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
Operatorclasse,Operator.from_circuit()para criar um novo objetoOperatorobjeto a partir de um arquivoQuantumCircuit. Embora isso fosse possível normalmente usando o construtor padrão, o métodoOperator.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 conjuntoLayout. 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
operatorterá os qubits permutados com base no layout, de modo que seja idêntico ao que é retornado porOperator(circuit)antes da transpilação. -
Adicionado um novo método
DAGCircuit.copy_empty_like()à classeDAGCircuitclasse. Esse método é usado para criar uma nova cópia de um objetoDAGCircuitexistente 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 anteriorqiskit.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 deCXGateeSwapGateportas). -
Adicionada uma nova passagem de transpilador
CollectLinearFunctionsque coleta blocos deCXGateeSwapGateconsecutivos em um circuito e substitui cada bloco por uma portaLinearFunctionporta. -
Adicionada uma nova passagem de transpilador
LinearFunctionsSynthesisque sintetiza qualquerLinearFunctionportas usando o algoritmo Patel-Markov-Hayes. Quando combinado com a passagemCollectLinearFunctionstranspiler, isso permite coletar blocos deCXGateeSwapGateem um circuito e sintetizá-los novamente usando o algoritmo Patel-Markov-Hayes. -
Adicionada uma nova passagem de transpilador
LinearFunctionsToPermutationsque substitui umLinearFunctiongate por um circuitoPermutationsempre que possível. -
FlowController(comoConditionalController) agora podem ser aninhadas dentro de uma instânciaPassManagerao usar o métodoPassManager.append()método. Isso permite o uso de lógica aninhada para controlar a execução de passes na seçãoPassManager. 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
pmPassManagersó executará oBasisTranslator(na etapaunroll) em cada iteração do loop se ounroll_conditionfor atendido. -
Os construtores para os arquivos
ZFeatureMapeZZFeatureMaptêm um novo argumento de palavra-chaveparameter_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
ZFeatureMapo circuito prefixou todos os seus parâmetros internos com o prefixo"my_prefix". -
A
TemplateOptimizationtranspiler pass agora pode trabalhar com objetosGatecom objetos que tenham parâmetrosParameterExpressionparâmetros. Um exemplo ilustrativo do uso deParameters comTemplateOptimizationé 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,DAGInNodeeDAGOutNodeagora 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 denumpy.uniquepara 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()à classeSparsePauliOppara testar a equivalência de umSparsePauliOpcom outro objetoSparsePauliOpobjeto. 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
BackendV2e forneceu umTargetpara cada backend.BackendV2as versões baseadas em todos os back-ends existentes são adicionadas, exceto para três back-ends antigos:FakeRueschlikon,FakeTenerifeeFakeTokyo, 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 emBackendV2.Esses novos back-ends falsos do V2 permitirão o teste e o desenvolvimento de novos recursos introduzidos pelo
BackendV2eTargetcomo 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,FakeRomeeFakeSantiago, que podem ser encontrados no móduloqiskit.providers.fake_provider, agora podem ser usados como backends nos experimentos do Pulse, pois agora incluem umPulseDefaultscriado a partir de um instantâneo das propriedades da máquina IBM Quantum equivalente. -
O passe
ConsolidateBlockstem um novo argumento de palavra-chave em seu construtor,target. Esse argumento é usado para especificar um objetoTargetque representa o alvo de compilação para a passagem. Se for especificado, ele substitui obasis_gateskwarg. Se um alvo for especificado, a passagem respeitará as portas e os qubits para as instruções definidas no alvoTargetao decidir quais portas serão consolidadas em uma unitária. -
A classe
Targettem 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 classeTarget. -
Foi adicionado um novo kwarg,
metadata_serializer, à funçãoqpy.dump()para especificar uma subclasseJSONEncoderpersonalizada para uso ao serializar o atributoQuantumCircuit.metadatae um kwarg duplometadata_deserializerà funçãoqpy.load()para especificar uma subclasseJSONDecoder. Por padrão, odump()eload()tentarão serializar e desserializar JSON com o codificador e decodificador json padrão do stdlib. ComoQuantumCircuit.metadatapode 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 argumentometadata_serializerparadump()permite que os usuários especifiquem umJSONEncoderpersonalizado que será usado com a chamada internajson.dump()para serializar oQuantumCircuit.metadatadicionário. Isso pode então ser combinado com o novo argumentometadata_deserializerda funçãoqpy.load()para decodificar essas codificações JSON personalizadas. Semetadata_serializerfor especificado emdump()masmetadata_deserializernão for especificado emload()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
DenseLayouttem um novo argumento de palavra-chave em seu construtor,target. Esse argumento é usado para especificar um objetoTargetque representa o alvo de compilação para a passagem. Se for especificado, ele substitui os outros argumentos no construtor,coupling_mapebackend_prop. -
A classe
Targettem 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 tuplaqargs. -
Um novo passe
DynamicalDecouplingPaddingfoi adicionado ao móduloqiskit.transpiler.passesmódulo. Essa nova passagem substitui a passagem existenteDynamicalDecouplingexistente para trabalhar com o novo fluxo de trabalho de agendamento no transpilador. É uma subclasse da passagemBasePaddinge depende da execução de passagens de agendamento e análise de alinhamento antes dela em umPassManager. Essa nova passagem pode receber um argumentopulse_alignmentque 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 emBackendConfiguration.timing_constraints. Além disso, o passe também tem uma opçãoextra_slack_distributionpara 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égiasplit_edgesdivide 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 quandopulse_alignment> 1. -
A classe
Z2Symmetriesagora 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()à classeSparsePauliOpque trunca as partes reais e imaginárias dos coeficientes individualmente. Isso é diferente do métodoSparsePauliOp.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 passagemGatesInBasispassagem do transpilador. Esse novo argumento pode ser usado para especificar opcionalmente um objetoTargetque representa o backend. Quando definido, esseTargetserá usado para determinar se umDAGCircuitcontém portas fora do conjunto de base e o argumentobasis_gatesnã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-terracom 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
GradienteQFIpodem agora calcular a parte imaginária dos gradientes do valor de expectativa. Ao usar uma base de medição diferente, ou seja-Yem vez deZ, podemos medir a parte imaginária dos gradientes. A base de medição pode ser definida com o argumentoaux_meas_op.Para os gradientes,
aux_meas_op = Zcalcula0.5Re[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉]eaux_meas_op = -Ycalcula0.5Im[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉]. Para os QFIs,aux_meas_op = Zcalcula4Re[(dω⟨<ψ(ω)|)(dω|ψ(ω)〉)]eaux_meas_op = -Ycalcula4Im[(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
InstructionDurationsagora tem suporte para trabalhar com parâmetros de uma instrução. Cada entrada em um objetoInstructionDurationsagora consiste em uma tupla de(inst_name, qubits, duration, parameters, unit). Isso permite que umInstructionDurationsdefina 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
stylena função de gaveta de circuitocircuit_drawer()eQuantumCircuit.draw()método,iqx_dark. Quandostylefor definido comoiqx_darkcom o backend da gavetampl, 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 dematplotlibperguntandoif 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
qiskitfoi 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 campomemoryde um objeto de entradaResultobjeto. Por exemplo, se o argumento de entradaresultfor um objeto qiskitResultobtido 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
StochasticSwapforam 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ãotranspile()quando executado comoptimization_level0, 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 ambienteRAYON_NUM_THREADScomo um valor inteiro. Por exemplo, a configuraçãoRAYON_NUM_THREADS=4executará oStochasticSwapcom 4 threads. -
Uma nova variável de ambiente
QISKIT_FORCE_THREADSestá 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 doStochasticSwapmas provavelmente será usado em outras partes do Qiskit no futuro. Quando essa variável env é definida comoTRUE, 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, emStochasticSwapse a passagem estiver sendo executada como parte de uma chamadatranspile()chamada com > 1 circuito que está sendo executado em paralelo commultiprocessingpor meio deparallel_map()oStochasticSwapnã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á definirQISKIT_FORCE_THREADS=TRUE. -
Novas classes de back-end falsas estão disponíveis em
qiskit.providers.fake_provider. Isso inclui versões simuladas deibm_cairo,ibm_hanoi,ibmq_kolkata,ibm_nairobieibm_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 queInitializesem que a redefinição seja aplicada automaticamente.Por exemplo, para preparar um qubit no estado :
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
Optimize1qGatesa passagem do transpiler agora tem suporte para otimizar oU1Gate,U2Gate, ePhaseGatecom 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()ePauliList.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 forframe='h'(padrão), ele fará a evolução da imagem de Heisenberg de um Pauli por um Clifford ( ) e, se forframe='s', ele fará a evolução da imagem de Schrödinger de um Pauli por um Clifford ( ). 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 emdecompose_cliffordsignificativamente 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 doQuantumCircuit, que abstrai os detalhes da execução subjacente em umBackend. 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 classeBaseEstimatore 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(vejaBaseSamplerpara a definição da classe abstrata) eEstimator(vejaBaseEstimatorpara a definição da classe abstrata). As implementações de referência estão incluídas no móduloqiskit.primitivese são criadas usando o móduloqiskit.quantum_infoque 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 arquivoBackend. -
Adicionado um novo módulo,
qiskit.qpyque contém a funcionalidade anteriormente exposta emqiskit.circuit.qpy_serialization. As funções públicas anteriormente expostas emqiskit.circuit.qpy_serialization,dump()eload()agora estão disponíveis nesse novo módulo (embora ainda possam ser acessadas emqiskit.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 depulseScheduleeScheduleBlockalém dos objetosQuantumCircuitobjetos que ele suporta atualmente. -
Adicionado um novo atributo,
qubit_propertiesà classeTargetclasse. Esse atributo contém uma lista de objetosQubitPropertiesobjetos para cada qubit no alvo. Por exemplo:target.qubit_properties[2]conterá o
QubitPropertiespara o qubit número 2 no alvo.Para os
BackendV2autores, se você estava definindo anteriormenteQubitPropertiesdiretamente em sua implementaçãoBackendV2substituindo oBackendV2.qubit_properties()isso ainda funcionará bem. No entanto, se você mover a definição para o objeto subjacenteTargetsubjacente e remover a implementação especializada doBackendV2.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 limiteQuantumCircuit. Ele se origina de um método privado,_eval_aux_ops(), da classeqiskit.algorithms.VQEmas a nova funçãoeval_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
BasisTranslatorfoi 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
DenseLayoutagora é 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 ambienteRAYON_NUM_THREADScomo um valor inteiro. Por exemplo, a configuraçãoRAYON_NUM_THREADS=4executará aDenseLayoutcom 4 threads. -
Os cálculos internos de
Statevector.expectation_value()eDensityMatrix.expectation_value()foram reimplementados na linguagem de programação Rust. Essa nova implementação é multithread e, por padrão, para umStatevectorouDensityMatrix>= 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 ambienteRAYON_NUM_THREADScomo um valor inteiro. Por exemplo, a configuraçãoRAYON_NUM_THREADS=4usará 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
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
UnitarySynthesistranspiler pass tem um novo argumento de palavra-chave em seu construtor,target. Isso pode ser usado para especificar opcionalmente um objetoTargetque representa o alvo de compilação para a passagem. Quando especificado, ele substituirá os valores definidos parabasis_gates,coupling_mapebackend_props. -
A classe
UnitarySynthesisPlugintem um novo atributo opcional que as implementações podem adicionar,supports_target. Se um plug-in tiver esse atributo definido comoTrue, um objetoTargetserá passado no payloadoptionsno campotarget. A expectativa é que esse objetoTargetseja usado no lugar decoupling_map,gate_lengths,basis_gatesegate_errors. -
Introduziu um novo fluxo de trabalho de passagem do transpiler para criar
PassManagerobjetos para agendamento deQuantumCircuitobjetos no transpiler. No novo fluxo de trabalho, os passes de agendamento e alinhamento são todosAnalysisPassque apenas atualizam o conjunto de propriedades do gerenciador de passes, especificamente o novo item do conjunto de propriedadesnode_start_time, que mantém a hora de início absoluta de cada opnode. UmTransformationPassseparado, comoPadDelayé 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 passagemDAGCircuitinstâ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 tornascheduling -> alignment -> padding, onde aDAGCircuitatualização ocorre somente no final com a passagempadding.Para aqueles que estão criando objetos personalizados
PassManagerpersonalizados que envolvam programação de circuitos, será necessário ajustar seuPassManagerpara inserir um dosBasePaddingpasses (atualmentePadDelayouPadDynamicalDecouplingpodem 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étodorun()de seu método personalizadoPassManager.Por exemplo, se você estava construindo seu
PassManagercom 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
ConstrainedReschedulepass. A passagemConstrainedRescheduleconsidera tanto as restrições de alinhamento de hardware que podem ser definidas em um objetoBackendConfigurationpulse_alignmenteacquire_alignment. Essa nova classe substitui a classeAlignMeasurespois 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çãoacquire_alignmentpara o passeConstrainedRescheduleele é um substituto imediato deAlignMeasuresquando emparelhado com um novo passeBasePadding. -
Adicionadas duas novas passagens de transpilador
ALAPScheduleAnalysiseASAPScheduleAnalysisque substituem as passagensALAPScheduleeASAPSchedulecomo 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 passagemBasePaddingpara 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_latencyidê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 └─────────┘ 0from 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_2começa antes da porta X condicional emq_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
AcquireChanneleMemorySlot, 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
PadDynamicalDecouplingque substitui a passagemDynamicalDecouplingcomo 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()eplot_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()eplot_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 retworkxspring_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çãoqubit_coordinatespara 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()eplot_circuit_layout()agora podem funcionar com um backend baseado emBackendV2com base em um backend. Anteriormente, essas funções só funcionavam comBaseBackendou backends baseados emBackendV1baseados em backends. -
Adicionada uma nova passagem de transpilador,
SetIOLatency. Essa passagem recebe dois argumentosclbit_write_latencyeconditional_latencypara 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
PadDelayfoi adicionada. Essa passagem preenche o tempo ocioso nos fios do qubit comDelayinstruçõ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 (comoALAPScheduleAnalysisouASAPScheduleAnalysis) e de quaisquer passagens de alinhamento (comoConstrainedReschedule) a serem executadas antes doPadDelay. -
A passagem
VF2Layouttranspiler tem um novo argumento de palavra-chave,target, que é usado para fornecer umTargetpara a passagem. Quando especificado, oTargetserá usado pelo passe para todas as informações sobre o dispositivo de destino. Se for especificada, a opçãotargetterá prioridade sobre os argumentoscoupling_mapeproperties. -
Permitir callables como otimizadores em
VQEeQAOA. Agora, o otimizador pode ser um dos otimizadores do Qiskit, comoSPSAou 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 resultA 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, comotranspile()eassemble()) em um subprocesso iniciado fora doparallel_map()é possível que o despacho paralelo executado dentro deparallel_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 chamarparallel_map()a partir de um processo principal deve funcionar bem; ou você pode chamar manualmente o módulomultiprocessingda 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,ClbiteAncillaQubitagora 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
retworkxteve seu requisito de versão aumentado para 0.11.0, em vez de 0.10.1. Isso melhora o desempenho da passagem de transpilaçãoConsolidateBlocks. -
A versão mínima compatível do
symengineagora é 0.9.0. Isso foi necessário para melhorar a compatibilidade com o módulopickledo Python, que é usado internamente como parte do envio paralelo com oparallel_map(). -
O valor padrão de
QISKIT_PARALLELquando executado com Python 3.9 em Linux agora está definido comoTRUE. Isso significa que, ao executar oparallel_map()ou funções que o chamam internamente, comotranspile()eassemble()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 ambienteQISKIT_PARALLELcomoFALSEou definindo a opçãoparallelcomoFalseno 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 emqiskit.circuit.libraryfoi removida. Ele foi originalmente preterido na versão 0.16.0. Em vez disso, a classeGMSdeve ser usada, pois ela permite que você crie uma porta MS equivalente a 2 qubits, além de umMSGatepara qualquer número de qubits. -
O método
mirror(), anteriormente obsoleto, da classeInstructionfoi removido. Ele foi originalmente preterido na versão 0.15.0. Em vez disso, você deve usarInstruction.reverse_ops(). -
O método
num_ancilla_qubits(), anteriormente obsoleto, doqiskit.circuit.library.PiecewiseLinearPauliRotationseqiskit.circuit.library.WeightedAdderfoi removido. Ele foi originalmente preterido na versão 0.16.0. Em vez disso, devem ser usados os métodosPiecewiseLinearPauliRotations.num_ancillas()eWeightedAdder.num_ancillas(). -
O argumento
reverse, anteriormente obsoleto, no construtor da classePolynomialPauliRotationsfoi removido. Ele foi originalmente preterido na versão 0.15.0. Em vez disso, você deve usar o métodoQuantumCircuit.reverse_bits()para reverter oPolynomialPauliRotationscircuito, se necessário. -
O argumento
angle, anteriormente obsoleto, nos construtores dos objetosC3SXGateeC3XGatefoi 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étodoC3XGate.power(). -
Suporte para o uso de objetos
np.ndarraycomo parte do atributoparamsde um objetoGatefoi 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 deGatee permitir explicitamente uma entradanp.ndarraysobrecarregando o métodovalidate_parameter()método. -
Um novo extra
csp-layout-passfoi adicionado ao destino de instalação dopip install qiskit-terrae também está incluído no extraall. 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 doCSPLayouttranspiler 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 comandopip install) como alvoqiskit-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
AmplitudeEstimatoragora herda a classeABCda biblioteca padrão Python. Isso exige que qualquer subclasse implemente o métodoestimate()quando anteriormente isso não era necessário. Isso foi feito porque a intenção original da classe era ser sempre uma classe filha deABC, já que oestimate()é necessário para a operação de um objetoAmplitudeEstimatorobjeto. No entanto, se você estava definindo anteriormente uma subclasseAmplitudeEstimatorque não implementouestimate()isso agora resultará em um erro. -
O erro gerado por
HoareOptimizerse a dependência opcionalz3não estiver disponível foi alterado deTranspilerErrorparaMissingOptionalLibraryError(que é tanto umQiskitErrore umImportError). 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 objetoResultagora marginalizará o campomemorydos dados do experimento se ele estiver definido na entradaResult. Anteriormente, o campomemoryna entrada não era marginalizado. Essa alteração foi feita porque o comportamento anterior fazia com que o campocountsnão correspondesse ao campomemorydepois que omarginal_counts()fosse chamado. Se o comportamento anterior for desejado, ele poderá ser restaurado definindomarginalize_memory=Nonecomo um argumento paramarginal_counts()o que não marginalizará o campomemory. -
A passagem do
StochasticSwappode 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ê executoutranspile()comoptimization_level0, 1 (o padrão) ou 2 com um valor definido paraseed_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
StochasticSwapque 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
nameda classePauliEvolutionGatefoi 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 é umPauliEvolutionGate. 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.labelatributo. Se um circuito com umPauliEvolutionGatefor 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_costqiskit.algorithms.VQE.get_optimal_circuitqiskit.algorithms.VQE.get_optimal_vectorqiskit.algorithms.VQE.optimal_paramsqiskit.algorithms.HamiltonianPhaseEstimationResult.most_likely_phaseqiskit.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.VariationalAlgorithmagora é definida como uma classe base abstrata (ABC) que exigirá que as classes que herdarem dela definam um método getter e setterVariationalAlgorithm.initial_point. -
O kwarg
pass_managerpara a funçãotranspile()foi removido. Ele foi originalmente preterido na versão 0.13.0. A maneira preferida de transpilar um circuito com um objetoPassManagerpersonalizado é usar o métodorun()do objetoPassManagerobjeto. -
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 diretamenteScheduleouScheduleBlockespecificando um objetoParameterpara o argumento do pulso paramétrico. -
O módulo
qiskit.circuit.library.probability_distributionsfoi 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ãoUniformDistribution,NormalDistributioneLogNormalDistribution. 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.FakeMumbaiV2foi renomeada paraFakeMumbaiFractionalCXpara diferenciá-la doBackendV2com base em um backend falso para o dispositivo IBM Mumbai,qiskit.test.mock.backends.FakeMumbaiV2. Se você dependia anteriormente da classeFakeMumbaiV2para obter um backend falso que tinha aplicações fracionárias deCXGatedefinidas em seu destino, você precisará usar a classeFakeMumbaiFractionalCX, pois aFakeMumbaiV2não terá mais essas definições extras de porta em seu arquivoTarget. -
O resolvedor usado por
QuantumCircuit.append()(e, consequentemente, todos os métodos que adicionam uma instrução em umQuantumCircuit) 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 corretosQuantumCircuito 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 publicQuantumCircuit.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_passmanagerspara todos os níveis de otimização 2 e 3, conforme gerado porlevel_2_pass_manager()elevel_3_pass_manager()foram alterados para executar oVF2Layoutpor padrão antes da passagem de layout. A passagemVF2Layoutverificará 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 deTrivialLayouteCSPLayoutpara tentar encontrar um layout perfeito. Isso resultará em um comportamento potencialmente diferente quando otranspile()é 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 quecircuit.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, especificandolayout_method="trivial"ao chamartranspile(). -
O gerenciador de passes predefinido para o nível de otimização 1 (ao chamar
transpile()comoptimization_level=1ou quando nenhum argumentooptimization_levelé definido), conforme gerado porlevel_1_pass_manager()foi alterado para queVF2Layoutseja chamado por padrão para verificar rapidamente se um layout perfeito pode ser encontrado antes da chamada doDenseLayout. No entanto, diferentemente dos níveis de otimização 2 e 3, um layout trivial ainda é tentado antes da execuçãoVF2Layoute, se for um mapeamento perfeito, a saída deVF2Layoutserá usado.
Notas de descontinuação
-
O argumento
max_creditsparaexecute()e todas as configurações deQobj(por exemplo.QasmQobjConfigePulseQobjConfig), 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 chamandoexecute()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
orderno construtor da classeSuzukiTrotterestá obsoleto e não funcionará mais em uma versão futura. As fórmulas de produto usadas peloSuzukiTrottersó são definidas quando a ordem é par, pois as fórmulas de produto de Suzuki são simétricas. -
Os kwargs
qregs,cregs,layouteglobal_phasepara as classesMatplotlibDrawer,TextDrawingeQCircuitImagee o kwargcalibrationspara a classeMatplotlibDrawerestã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()ecircuit_to_instruction()(e seus métodos de circuito associadosQuantumCircuit.to_gate()eQuantumCircuit.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
CXGateeCPhaseGatebem como entreCXGateeCRZGate. -
Foi corrigido um problema em que a execução do operador
==entre doisSparsePauliOpgerava 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
ValueErrorem vez de retornarFalse. -
Corrigido o suporte em
transpile()para passar um objetoInstructionScheduleMappara o objeto subjacentePassManagersubjacente com base na funçãoTargetparaBackendV2baseados em backends. Anteriormente, a funçãotranspile()não fazia esse processamento e qualquer passagem do transpilador que não suportasse trabalhar com um objetoTargetainda não teriam acesso às calibrações de pulso padrão para as instruções de umBackendV2backend. -
O
AmplitudeAmplifieragora está disponível corretamente no módulo raizqiskit.algorithmsdiretamente. Anteriormente, ele não era incluído nas classes reexportadas do módulo raiz e só podia ser acessado emqiskit.algorithms.amplitude_amplifiers. Corrigido #7751. -
Correção de um problema com o backend
mplpara a função de gaveta de circuitocircuit_drawer()e o métodoQuantumCircuit.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 deQuantumCircuit. 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 stringdiagonalera 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 oDensityMatrixdo 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
textpara a função de gaveta de circuitocircuit_drawer()e o métodoQuantumCircuit.draw()quando os portões que usam texto lateral, como oCPhaseGateeRZZGatecom condições clássicas definidas não eram exibidas corretamente. Corrigido #7532. -
Foi corrigido um problema com a função
circuit_drawer()função edraw()do métodoQuantumCircuit. Ao usar a opçãoreverse_bitscom as opçõesmpl,latexoutext, 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 argumentoqubitsque 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 trivialPaulipara o argumentoopertivesse uma fase não trivial. Corrigido #7441. -
Uma expressão opflow que contém a identidade de Pauli
opflow.Inão produz mais umIGatequando 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
PauliGatenão insere mais umIGatepara Paulis com o rótulo"I". -
PauliSumOpos testes de igualdade agora lidam com o caso em que um dos itens comparados é um únicoPauliOp. Por exemplo,0 * X + I == Iagora é avaliado como True, enquanto era False antes desta versão. -
Foi corrigido um problema com o
ALAPScheduleeASAPScheduleao 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
ParameterExpressionparametrizadores de instrução na passagem doRZXCalibrationBuilderpassagem do transpilador. Anteriormente, se um parâmetro de instrução incluísse um limiteParameterExpressiona passagem não seria capaz de lidar com isso corretamente. -
Parou o analisador em
QuantumCircuit.from_qasm_str()efrom_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