Guia de Migração de Algoritmos#

TL;DR#

O módulo qiskit.algorithms foi completamente refatorado para que use o primitives, na execução de circuitos, em vez da QuantumInstance, a qual está agora depreciada.

Temos 3 tipos de refatoração:

  1. Algoritmos refatorados em uma nova localização a fim de suportar primitives. Esses algoritmos têm o mesmos nomes de classe que aquelas baseadas em QuantumInstance-, mas estão em um novo sub-pacote.

    Atenção

    Cuidado com caminhos de importação!! Os algoritmos legados ainda podem ser importados diretamente de qiskit.algorithms. Até que as importações legadas sejam removidas, essa importação de conveniência não estará disponível para os algoritmos refatorados. Portanto, para importar os algoritmos refatorados, você deve sempre especificar o caminho de importação completo (por exemplo, from qiskit.algorithms.eigensolvers import VQD)

  2. Algoritmos refatorados in-place (mesmo namespace) para suportar ambos QuantumInstance e primitives. No futuro, o uso da QuantumInstance será removido.

  3. Algoritmos que estavam depreciados e que agora foram totalmente removidos do qiskit.algorithms. Estes são algoritmos que atualmente não servem como blocos de construção para aplicativos. Seu principal valor é educacional e, como tal, serão mantidos como tutoriais no manual do qiskit. Você pode consultar os tutoriais nos seguintes links:

O restante deste guia de migração se concentrará nos algoritmos com alternativas de migração dentro de qiskit.algorithms, ou seja, aqueles sob os tipos de refatoração 1 e 2.

Background#

De volta a TL;DR

O módulo qiskit.algorithms foi originalmente construído sobre a biblioteca qiskit.opflow e o utilitário QuantumInstance. O desenvolvimento do primitives introduziu um paradigma de execução de alto nível, com o Estimator para cálculo de valores esperados para observáveis e Sampler para circuitos de execução e retorno de distribuições de probabilidade. Essas ferramentas permitiram refatorar o módulo qiskit.algorithms e descontinuar ambos qiskit.opflow e QuantumInstance.

Atenção

A transição de qiskit.opflow afeta as classes que os algoritmos tomam como parte da configuração do problema. Como regra geral, a maioria das dependências qiskit.opflow tem uma substituição direta de qiskit.quantum_info. Um exemplo comum é a classe qiskit.opflow.PauliSumOp, usada para definir Hamiltonianos (por exemplo, para conectar ao VQE), que pode ser substituída por qiskit.quantum_info.SparsePauliOp. Para obter informações sobre como migrar outros objetos opflow, você pode consultar o Guia de migração Opflow.

Para obter mais informações e passos detalhados de migração, consulte:

Como escolher uma configuração primitiva para seu algoritmo#

De volta a TL;DR

As classes em qiskit.algorithms são inicializadas com qualquer implementação de qiskit.primitive.BaseSampler ou class:qiskit.primitive.BaseEstimator.

Uma vez conhecido o tipo de primitiva, você pode escolher entre as implementações primitivas que melhor se ajustam ao seu caso. Por exemplo:

  1. Para prototipagem rápida, você pode usar as reference implementations of primitives inclusas no Qiskit: qiskit.primitives.Sampler e qiskit.primitives.Estimator.

  2. Para um ajuste mais fino do algoritmo, um simulador local como a primitive implementation in Aer: qiskit_aer.primitives.Sampler e qiskit_aer.primitives.Estimator.

  3. Para executar em um hardware quântico, você pode:

Para obter informações e exemplos mais detalhados, particularmente sobre o uso de Backend Primitives, consulte o Guia de Migração de Quantum Instance.

Neste guia, abordaremos 3 configurações comuns diferentes para algoritmos que determinam qual importação primitiva você deve selecionar:

  1. Executando um algoritmo com um simulador de vetor de estado (ou seja, usando a MatrixExpectation legada de qiskit.opflow), quando você desejar um resultado ideal sem ruído de execução:

    • Primitivas Aer com simulador de vetores de estado (consulte o exemplo de QAOA):

    from qiskit.primitives import Sampler, Estimator
    
    • Primitivas Aer com simulador de vetores de estado (consulte o exemplo de QAOA):

    from qiskit_aer.primitives import Sampler, Estimator
    
    sampler = Sampler(backend_options={"method": "statevector"})
    estimator = Estimator(backend_options={"method": "statevector"})
    
  2. Executando um algoritmo usando um simulador/dispositivo com ruído de shot (ou seja, usando a classe legada PauliExpectation do módulo qiskit.opflow):

    • Primitivas de Referência com shots (consulte exemplos de VQE):

    from qiskit.primitives import Sampler, Estimator
    
    sampler = Sampler(options={"shots": 100})
    estimator = Estimator(options={"shots": 100})
    
    # or...
    sampler = Sampler()
    job = sampler.run(circuits, shots=100)
    
    estimator = Estimator()
    job = estimator.run(circuits, observables, shots=100)
    
    • Primitivas Aer com configuração padrão (consulte exemplos de VQE):

    from qiskit_aer.primitives import Sampler, Estimator
    
    • Primitivas IBM’s Qiskit Runtime com configuração padrão (consulte o exemplo de VQD):

    from qiskit_ibm_runtime import Sampler, Estimator
    

3. Running an algorithm on an Aer simulator using a custom instruction (i.e., using qiskit.opflow's legacy AerPauliExpectation):

  • Primitivas Aer com shots=None, approximation=True (consulte o exemplo de TrotterQRTE):

from qiskit_aer.primitives import Sampler, Estimator

sampler = Sampler(run_options={"approximation": True, "shots": None})
estimator = Estimator(run_options={"approximation": True, "shots": None})

Eigensolvers mínimos#

De volta a TL;DR

Os algoritmos eigensolver mínimos pertencem ao primeiro tipo de refatoração listado acima (Algoritmos refatorados em um novo local para suportar primitives). Em vez de uma QuantumInstance, qiskit.algorithms.minimum_eigensolvers agora são inicializados usando uma instância de Sampler ou Estimator primitivo, dependendo do algoritmo. As classes legadas ainda podem ser encontradas em qiskit.algorithms.minimum_eigen_solvers.

Atenção

Para as classes qiskit.algorithms.minimum_eigensolvers, dependendo do caminho de importação, você acessará a implementação baseada em primitiva ou baseada em instância quântica. Você tem que ter muito cuidado, porque o nome da classe não muda.

  • Antigas importações (baseadas em instancia Quantum): from qiskit.algorithms import VQE, QAOA, NumPyMinimumEigensolver

  • Novas importações (baseadas em Primitives): from qiskit.algorithms.minimum_eigensolvers import VQE, SamplingVQE, QAOA, NumPyMinimumEigensolver

VQE#

A classe legada qiskit.algorithms.minimum_eigen_solvers.VQE foi dividida de acordo com os casos de uso:

Nota

Além de receber uma instância Estimator em vez de uma QuantumInstance, a nova assinatura VQE sofreu as seguintes alterações:

  1. Os parâmetros expectation e include_custom foram removidos, já que esta funcionalidade agora é definida no nível de Estimator.

  2. O parâmetro gradient agora usa uma instância de uma classe de gradiente baseada em primitiva de qiskit.algorithms.gradients em vez da classe qiskit.opflow.gradients.Gradient herdada.

  3. O parâmetro max_evals_grouped foi removido, pois pode ser definido diretamente na classe optimizer.

  4. O estimator, ansatz e optimizer são os únicos parâmetros que podem ser definidos posicionalmente (e nesta ordem), todos os outros se tornaram argumentos keyword-only.

Nota

A nova classe VQEResult não inclui mais o estado, pois esta saída só foi útil no caso de operadores diagonais. No entanto, se estiver disponível como parte da classe SamplingVQEResult da nova classe SamplingVQE’s .

Exemplo de VQD

[Legacy] Usando Quantum Instance:

from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import SPSA
from qiskit.circuit.library import TwoLocal
from qiskit.opflow import PauliSumOp
from qiskit.utils import QuantumInstance
from qiskit_aer import AerSimulator

ansatz = TwoLocal(2, 'ry', 'cz')
opt = SPSA(maxiter=50)

# shot-based simulation
backend = AerSimulator()
qi = QuantumInstance(backend=backend, shots=2048, seed_simulator=42)
vqe = VQE(ansatz, optimizer=opt, quantum_instance=qi)

hamiltonian = PauliSumOp.from_list([("XX", 1), ("XY", 1)])
result = vqe.compute_minimum_eigenvalue(hamiltonian)

print(result.eigenvalue)
(-0.9775390625+0j)

[Updated] Usando Primitives:

from qiskit.algorithms.minimum_eigensolvers import VQE  # new import!!!
from qiskit.algorithms.optimizers import SPSA
from qiskit.circuit.library import TwoLocal
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives import Estimator
from qiskit_aer.primitives import Estimator as AerEstimator

ansatz = TwoLocal(2, 'ry', 'cz')
opt = SPSA(maxiter=50)

# shot-based simulation
estimator = Estimator(options={"shots": 2048})
vqe = VQE(estimator, ansatz, opt)

# another option
aer_estimator = AerEstimator(run_options={"shots": 2048, "seed": 42})
vqe = VQE(aer_estimator, ansatz, opt)

hamiltonian = SparsePauliOp.from_list([("XX", 1), ("XY", 1)])
result = vqe.compute_minimum_eigenvalue(hamiltonian)

print(result.eigenvalue)
-0.986328125
Exemplo de VQE aplicado a CVaR (SamplingVQE)

[Legacy] Usando Quantum Instance:

from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import SLSQP
from qiskit.circuit.library import TwoLocal
from qiskit.opflow import PauliSumOp, CVaRExpectation
from qiskit.utils import QuantumInstance
from qiskit_aer import AerSimulator

ansatz = TwoLocal(2, 'ry', 'cz')
opt = SLSQP(maxiter=50)

# shot-based simulation
backend = AerSimulator()
qi = QuantumInstance(backend=backend, shots=2048)
expectation = CVaRExpectation(alpha=0.2)
vqe = VQE(ansatz, optimizer=opt, expectation=expectation, quantum_instance=qi)

# diagonal Hamiltonian
hamiltonian = PauliSumOp.from_list([("ZZ",1), ("IZ", -0.5), ("II", 0.12)])
result = vqe.compute_minimum_eigenvalue(hamiltonian)

print(result.eigenvalue.real)
-1.38

[Updated] Usando Primitives:

from qiskit.algorithms.minimum_eigensolvers import SamplingVQE # new import!!!
from qiskit.algorithms.optimizers import SPSA
from qiskit.circuit.library import TwoLocal
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives import Sampler
from qiskit_aer.primitives import Sampler as AerSampler

ansatz = TwoLocal(2, 'ry', 'cz')
opt = SPSA(maxiter=50)

# shot-based simulation
sampler = Sampler(options={"shots": 2048})
vqe = SamplingVQE(sampler, ansatz, opt, aggregation=0.2)

# another option
aer_sampler = AerSampler(run_options={"shots": 2048, "seed": 42})
vqe = SamplingVQE(aer_sampler, ansatz, opt, aggregation=0.2)

# diagonal Hamiltonian
hamiltonian = SparsePauliOp.from_list([("ZZ",1), ("IZ", -0.5), ("II", 0.12)])
result = vqe.compute_minimum_eigenvalue(hamiltonian)

print(result.eigenvalue.real)
-1.38

Para obter exemplos de código completos, consulte os seguintes tutoriais atualizados:

QAOA#

A classe qiskit.algorithms.minimum_eigen_solvers.QAOA legada usada para estender qiskit.algorithms.minimum_eigen_solvers.VQE, mas agora, a qiskit.algorithms.minimum_eigensolvers.QAOA estende :class: qiskit.algorithms.minimum_eigensolvers.SamplingVQE. Por esta razão, o novo QAOA suporta apenas operadores diagonais.

Nota

Além de receber uma instância de Sampler em vez de uma QuantumInstance, a nova assinatura da classe QAOA sofreu as seguintes alterações:

  1. Os parâmetros expectation e include_custom foram removidos. Em troca, o parâmetro aggregation foi adicionado (costumava ser definido através de uma expectation adaptada).

  2. O parâmetro gradient agora usa uma instância de uma classe de gradiente baseada em primitiva de qiskit.algorithms.gradients em vez da classe qiskit.opflow.gradients.Gradient herdada.

  3. O parâmetro max_evals_grouped foi removido, pois pode ser definido diretamente na classe optimizer.

  4. O sampler e optimizer são os únicos parâmetros que podem ser definidos posicionalmente (e nesta ordem), todos os outros se tornaram parâmetros keyword-only.

Nota

Se você deseja executar QAOA em um operador não diagonal, pode usar a QAOAAnsatz com qiskit.algorithms.minimum_eigensolvers.VQE, mas tenha em mente que não haverá resultado de estado. Se seu aplicativo requer a distribuição de probabilidade final, você pode instanciar um Sampler e executá-lo com o circuito ideal após a VQE.

Exemplo de QAOA

[Legacy] Usando Quantum Instance:

from qiskit.algorithms import QAOA
from qiskit.algorithms.optimizers import COBYLA
from qiskit.opflow import PauliSumOp
from qiskit.utils import QuantumInstance
from qiskit_aer import AerSimulator

# exact statevector simulation
backend = AerSimulator()
qi = QuantumInstance(backend=backend, shots=None,
        seed_simulator = 42, seed_transpiler = 42,
        backend_options={"method": "statevector"})

optimizer = COBYLA()
qaoa = QAOA(optimizer=optimizer, reps=2, quantum_instance=qi)

# diagonal operator
qubit_op = PauliSumOp.from_list([("ZIII", 1),("IZII", 1), ("IIIZ", 1), ("IIZI", 1)])
result = qaoa.compute_minimum_eigenvalue(qubit_op)

print(result.eigenvalue.real)
-4.0

[Updated] Usando Primitives:

from qiskit.algorithms.minimum_eigensolvers import QAOA
from qiskit.algorithms.optimizers import COBYLA
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives import Sampler
from qiskit_aer.primitives import Sampler as AerSampler

# exact statevector simulation
sampler = Sampler()

# another option
sampler = AerSampler(backend_options={"method": "statevector"},
                     run_options={"shots": None, "seed": 42})

optimizer = COBYLA()
qaoa = QAOA(sampler, optimizer, reps=2)

# diagonal operator
qubit_op = SparsePauliOp.from_list([("ZIII", 1),("IZII", 1), ("IIIZ", 1), ("IIZI", 1)])
result = qaoa.compute_minimum_eigenvalue(qubit_op)

print(result.eigenvalue)
-3.999999832366272

Para obter exemplos de código completos, consulte os seguintes tutoriais atualizados:

NumPyMinimumEigensolver#

Como este é um solucionador clássico, o fluxo de trabalho não mudou entre a implementação antiga e a nova. No entanto, a importação mudou de qiskit.algorithms.minimum_eigen_solvers.NumPyMinimumEigensolver para qiskit.algorithms.minimum_eigensolvers.NumPyMinimumEigensolver para se adequar às novas interfaces e classes de resultados.

Exemplo de NumPyMinimumEigensolver

[Legacy] Usando Quantum Instance:

from qiskit.algorithms import NumPyMinimumEigensolver
from qiskit.opflow import PauliSumOp

solver = NumPyMinimumEigensolver()

hamiltonian = PauliSumOp.from_list([("XX", 1), ("XY", 1)])
result = solver.compute_minimum_eigenvalue(hamiltonian)

print(result.eigenvalue)
-1.4142135623730958

[Updated] Usando Primitives:

from qiskit.algorithms.minimum_eigensolvers import NumPyMinimumEigensolver
from qiskit.quantum_info import SparsePauliOp

solver = NumPyMinimumEigensolver()

hamiltonian = SparsePauliOp.from_list([("XX", 1), ("XY", 1)])
result = solver.compute_minimum_eigenvalue(hamiltonian)

print(result.eigenvalue)
-1.414213562373095

Para obter exemplos de código completos, consulte os seguintes tutoriais atualizados:

Eigensolver#

De volta a TL;DR

Os algoritmos eigensolver também pertencem ao primeiro tipo de refatoração (Algoritmos refatorados em um novo local para suportar primitives). Em vez de uma QuantumInstance, qiskit.algorithms.eigensolvers eles agora são inicializados usando uma instância de Sampler ou Estimator primitivo, ou uma sub-rotina baseada em primitivo, dependendo do algoritmo. As classes legadas ainda podem ser encontradas em qiskit.algorithms.eigen_solvers.

Atenção

Para as classes de qiskit.algorithms.eigensolvers, dependendo do caminho de importação, você acessará a implementação baseada em primitivas ou baseada em instância quântica. Você tem que ter muito cuidado, porque o nome da classe não muda.

  • Antigo caminho de importação (Instância Quantum): from qiskit.algorithms import VQD, NumPyEigensolver

  • Novo caminho de importação (Primitivas): from qiskit.algorithms.eigensolvers import VQD, NumPyEigensolver

VQD#

A nova classe qiskit.algorithms.eigensolvers.VQD é inicializada com uma instância de Estimator ao invés de uma QuantumInstance. Além disso, ela usa uma instância de uma classe de fidelidade de estado de mod:qiskit.algorithms.state_fidelities, como a Sampler baseada em ComputeUncompute.

Nota

Além de receber uma instância de Estimator em vez de uma QuantumInstance, a nova assinatura da VQD sofreu as seguintes alterações:

  1. Os parâmetros expectation e include_custom foram removidos, já que esta funcionalidade agora é definida no nível de Estimator.

  2. O parâmetro personalizado fidelity foi adicionado e o parâmetro personalizado gradient foi removido, pois as classes atuais em qiskit.algorithms.gradients não podem lidar com gradientes de fidelidade de estado.

  3. O parâmetro max_evals_grouped foi removido, pois pode ser definido diretamente na classe optimizer.

  4. O estimator, fidelity, ansatz e optimizer são os únicos parâmetros que podem ser definidos posicionalmente (e nesta ordem), todos os outros se tornaram parâmetros keyword-only.

Nota

Da mesma forma que o VQE, a nova classe VQDResult não inclui mais o estado. Se sua aplicação exige a distribuição de probabilidade final, você pode instanciar um Sampler e executá-lo com o circuito ideal para o estado excitado desejado após executar a classe VQD.

Exemplo de VQD

[Legacy] Usando Quantum Instance:

from qiskit import IBMQ
from qiskit.algorithms import VQD
from qiskit.algorithms.optimizers import SLSQP
from qiskit.circuit.library import TwoLocal
from qiskit.opflow import PauliSumOp
from qiskit.utils import QuantumInstance

ansatz = TwoLocal(3, rotation_blocks=["ry", "rz"], entanglement_blocks="cz", reps=1)
optimizer = SLSQP(maxiter=10)
hamiltonian = PauliSumOp.from_list([("XXZ", 1), ("XYI", 1)])

# example executing in cloud simulator
provider = IBMQ.load_account()
backend = provider.get_backend("ibmq_qasm_simulator")
qi = QuantumInstance(backend=backend)

vqd = VQD(ansatz, k=3, optimizer=optimizer, quantum_instance=qi)
result = vqd.compute_eigenvalues(operator=hamiltonian)

print(result.eigenvalues)
[ 0.01765114+0.0e+00j -0.58507654+0.0e+00j -0.15003642-2.8e-17j]

[Updated] Usando Primitives:

from qiskit_ibm_runtime import Sampler, Estimator, QiskitRuntimeService, Session
from qiskit.algorithms.eigensolvers import VQD
from qiskit.algorithms.optimizers import SLSQP
from qiskit.algorithms.state_fidelities import ComputeUncompute
from qiskit.circuit.library import TwoLocal
from qiskit.quantum_info import SparsePauliOp

ansatz = TwoLocal(3, rotation_blocks=["ry", "rz"], entanglement_blocks="cz", reps=1)
optimizer = SLSQP(maxiter=10)
hamiltonian = SparsePauliOp.from_list([("XXZ", 1), ("XYI", 1)])

# example executing in cloud simulator
service = QiskitRuntimeService(channel="ibm_quantum")
backend = service.backend("ibmq_qasm_simulator")

with Session(service=service, backend=backend) as session:
    estimator = Estimator()
    sampler = Sampler()
    fidelity = ComputeUncompute(sampler)
    vqd = VQD(estimator, fidelity, ansatz, optimizer, k=3)
    result = vqd.compute_eigenvalues(operator=hamiltonian)

print(result.eigenvalues)
[ 0.01765114+0.0e+00j -0.58507654+0.0e+00j -0.15003642-2.8e-17j]

Para obter exemplos de código completos, consulte o seguinte tutorial atualizado:

NumPyEigensolver#

Da mesma forma que a contraparte do minimum eigensolver, uma vez que este é um solucionador clássico, o fluxo de trabalho não mudou entre a implementação antiga e a nova. No entanto, a importação mudou de qiskit.algorithms.eigen_solvers.NumPyEigensolver para qiskit.algorithms.eigensolvers.MinimumEigensolver para se adequar às novas interfaces e classes de resultado.

Exemplo de NumPyEigensolver

**[Legacy]: **

from qiskit.algorithms import NumPyEigensolver
from qiskit.opflow import PauliSumOp

solver = NumPyEigensolver(k=2)

hamiltonian = PauliSumOp.from_list([("XX", 1), ("XY", 1)])
result = solver.compute_eigenvalues(hamiltonian)

print(result.eigenvalues)
[-1.41421356 -1.41421356]

[Updated]:

from qiskit.algorithms.eigensolvers import NumPyEigensolver
from qiskit.quantum_info import SparsePauliOp

solver = NumPyEigensolver(k=2)

hamiltonian = SparsePauliOp.from_list([("XX", 1), ("XY", 1)])
result = solver.compute_eigenvalues(hamiltonian)

print(result.eigenvalues)
[-1.41421356 -1.41421356]

Time Evolvers#

De volta a TL;DR

Os evoluidores de tempo são o último grupo de algoritmos a passar pelo primeiro tipo de refatoração (Algoritmos refatorados em um novo local para suportar primitives). Em vez de QuantumInstance, qiskit.algorithms.time_evolvers agora são inicializados usando uma instância da primitiva Estimator. As classes legadas ainda podem ser encontradas em qiskit.algorithms.evolvers.

Além da migração, o módulo foi substancialmente expandido para incluir Variational Quantum Time Evolution (VarQTE).

TrotterQRTE#

Atenção

Para a classe qiskit.algorithms.time_evolvers.TrotterQRTE, dependendo do caminho de importação, você acessará a implementação baseada em primitiva ou baseada em instância quântica. Você tem que ter muito cuidado, porque o nome da classe não muda.

  • Antigo caminho de importação (Quantum Instance): from qiskit.algorithms import TrotterQRTE

  • Novo caminho de importação (Primitives): from qiskit.algorithms.time_evolvers import TrotterQRTE

Nota

Além de receber uma instância de Estimator em vez de uma QuantumInstance, a nova assinatura da VQD sofreu as seguintes alterações:

  1. O parâmetro expectation foi removido, já que esta funcionalidade agora é definida no nível Estimator.

  2. Os parâmetros num_timesteps foram adicionados, para permitir definir o número de etapas em que o tempo de evolução completo é dividido.

Exemplo de TrotterQRTE

[Legacy] Usando Quantum Instance:

from qiskit.algorithms import EvolutionProblem, TrotterQRTE
from qiskit.circuit import QuantumCircuit
from qiskit.opflow import PauliSumOp, AerPauliExpectation
from qiskit.utils import QuantumInstance
from qiskit_aer import AerSimulator

operator = PauliSumOp.from_list([("X", 1),("Z", 1)])
initial_state = QuantumCircuit(1) # zero
time = 1
evolution_problem = EvolutionProblem(operator, 1, initial_state)

# Aer simulator using custom instruction
backend = AerSimulator()
quantum_instance = QuantumInstance(backend=backend)
expectation = AerPauliExpectation()

# LieTrotter with 1 rep
trotter_qrte = TrotterQRTE(expectation=expectation, quantum_instance=quantum_instance)
evolved_state = trotter_qrte.evolve(evolution_problem).evolved_state

print(evolved_state)
CircuitStateFn(
   ┌─────────────────────┐
q: ┤ exp(-it (X + Z))(1) ├
   └─────────────────────┘
)

[Updated] Usando Primitives:

from qiskit.algorithms.time_evolvers import TimeEvolutionProblem, TrotterQRTE  # note new import!!!
from qiskit.circuit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit_aer.primitives import Estimator as AerEstimator

operator = SparsePauliOp.from_list([("X", 1),("Z", 1)])
initial_state = QuantumCircuit(1) # zero
time = 1
evolution_problem = TimeEvolutionProblem(operator, 1, initial_state)

# Aer simulator using custom instruction
estimator = AerEstimator(run_options={"approximation": True, "shots": None})

# LieTrotter with 1 rep
trotter_qrte = TrotterQRTE(estimator=estimator)
evolved_state = trotter_qrte.evolve(evolution_problem).evolved_state

print(evolved_state.decompose())
   ┌───────────┐┌───────────┐
q: ┤ exp(it X) ├┤ exp(it Z) ├
   └───────────┘└───────────┘

Amplificadores de Amplitude#

De volta a TL;DR

Os algoritmos amplificadores de amplitude pertencem ao segundo tipo de refatoração (Algoritmos refatorados no local). Em vez de uma classe QuantumInstance, qiskit.algorithms.amplitude_amplifiers agora são inicializados usando uma instância de qualquer primitiva «Sampler», por exemplo Sampler.

Nota

O módulo completo qiskit.algorithms.amplitude_amplifiers foi refatorado no lugar. Não há necessidade de alterar os caminhos de importação.

Exemplo de Grover

[Legacy] Usando Quantum Instance:

from qiskit.algorithms import Grover
from qiskit.utils import QuantumInstance

qi = QuantumInstance(backend=backend)
grover = Grover(quantum_instance=qi)

[Updated] Usando Primitives:

from qiskit.algorithms import Grover
from qiskit.primitives import Sampler

grover = Grover(sampler=Sampler())

Para obter exemplos de código completos, consulte os seguintes tutoriais atualizados:

Estimadores de Amplitude#

De volta a TL;DR

Da mesma forma que os amplificadores de amplitude, os estimadores de amplitude também pertencem ao segundo tipo de refatoração (Algoritmos refatorados no local). Em vez de uma classe QuantumInstance, qiskit.algorithms.amplitude_estimators agora são inicializados usando uma instância de qualquer primitiva «Sampler», por exemplo Sampler.

Nota

O módulo completo qiskit.algorithms.amplitude_estimators foi refatorado no local. Não há necessidade de alterar os caminhos de importação.

Exemplos de IAE

[Legacy] Usando Quantum Instance:

from qiskit.algorithms import IterativeAmplitudeEstimation
from qiskit.utils import QuantumInstance

qi = QuantumInstance(backend=backend)
iae = IterativeAmplitudeEstimation(
    epsilon_target=0.01,  # target accuracy
    alpha=0.05,  # width of the confidence interval
    quantum_instance=qi
)

[Updated] Usando Primitives:

from qiskit.algorithms import IterativeAmplitudeEstimation
from qiskit.primitives import Sampler

iae = IterativeAmplitudeEstimation(
    epsilon_target=0.01,  # target accuracy
    alpha=0.05,  # width of the confidence interval
    sampler=Sampler()
)

Para obter exemplos de código completos, consulte os seguintes tutoriais atualizados:

Estimadores de fase#

De volta a TL;DR

Finalmente, os estimadores de fase são o último grupo de algoritmos a passar pelo primeiro tipo de refatoração (Algoritmos refatorados no local). Em vez de uma classe QuantumInstance, qiskit.algorithms.phase_estimators agora são inicializados usando uma instância de qualquer primitiva «Sampler», por exemplo Sampler.

Nota

O módulo qiskit.algorithms.phase_estimators completo foi refatorado. Não há necessidade de alterar os caminhos de importação.

Exemplo de IPE

[Legacy] Usando Quantum Instance:

from qiskit.algorithms import IterativePhaseEstimation
from qiskit.utils import QuantumInstance

qi = QuantumInstance(backend=backend)
ipe = IterativePhaseEstimation(
    num_iterations=num_iter,
    quantum_instance=qi
)

[Updated] Usando Primitives:

from qiskit.algorithms import IterativePhaseEstimation
from qiskit.primitives import Sampler

ipe = IterativePhaseEstimation(
    num_iterations=num_iter,
    sampler=Sampler()
)

Para obter exemplos de código completos, consulte os seguintes tutoriais atualizados: