Portuguese
Idiomas
English
Bengali
French
German
Japanese
Korean
Portuguese
Spanish
Tamil

Nota

Esta página foi gerada, a partir do tutorials/simulators/1_aer_provider.ipynb.

Simuladores

Introdução

Este notebook mostra como importar o serviço do simulador Qiskit Aer e usá-lo para executar circuitos Qiskit Terra ideais (livre de ruído).

[1]:
import numpy as np

# Import Qiskit
from qiskit import QuantumCircuit
from qiskit import Aer, transpile
from qiskit.tools.visualization import plot_histogram, plot_state_city
import qiskit.quantum_info as qi

O Provedor Aer

O provedor Aer contém uma variedade de backends de simuladores de alta performance para vários métodos de simulação. Os serviços disponíveis no sistema atual podem ser visualizados usando Aer.backends

[2]:
Aer.backends()
[2]:
[AerSimulator('aer_simulator'),
 AerSimulator('aer_simulator_statevector'),
 AerSimulator('aer_simulator_density_matrix'),
 AerSimulator('aer_simulator_stabilizer'),
 AerSimulator('aer_simulator_matrix_product_state'),
 AerSimulator('aer_simulator_extended_stabilizer'),
 AerSimulator('aer_simulator_unitary'),
 AerSimulator('aer_simulator_superop'),
 QasmSimulator('qasm_simulator'),
 StatevectorSimulator('statevector_simulator'),
 UnitarySimulator('unitary_simulator'),
 PulseSimulator('pulse_simulator')]

O Simulador Aer

O principal simulador de serviço do provedor Aer é o backend AerSimulator. Um backend de simulador novo pode ser criado usando Aer.get_backend('aer_simulator').

[3]:
simulator = Aer.get_backend('aer_simulator')

O comportamento padrão do serviço AerSimulator é simular a execução de um dispositivo real. Se um QuantumCircuit contendo medições for executado ele retornará um dicionário de contagem contendo os valores finais de quaisquer registradores clássicos no circuito. O circuito pode conter portas, medições, resets, condicionais e outras instruções personalizadas do simulador que serão discutidas em outro notebook.

Simulando um circuito quântico

The basic operation runs a quantum circuit and returns a counts dictionary of measurement outcomes. Here we run a simple circuit that prepares a 2-qubit Bell-state \(\left|\psi\right\rangle = \frac{1}{\sqrt{2}}\left(\left|0,0\right\rangle + \left|1,1 \right\rangle\right)\) and measures both qubits.

[4]:
# Create circuit
circ = QuantumCircuit(2)
circ.h(0)
circ.cx(0, 1)
circ.measure_all()

# Transpile for simulator
simulator = Aer.get_backend('aer_simulator')
circ = transpile(circ, simulator)

# Run and get counts
result = simulator.run(circ).result()
counts = result.get_counts(circ)
plot_histogram(counts, title='Bell-State counts')
[4]:
../../_images/tutorials_simulators_1_aer_provider_9_0.png

Retornando resultados de medição para cada repetição (shot)

O QasmSimulator também suporta retornar uma lista de resultados de medição para cada disparo individual. Isto é habilitado configurando o argumento de memory=True em run.

[5]:
# Run and get memory
result = simulator.run(circ, shots=10, memory=True).result()
memory = result.get_memory(circ)
print(memory)
['11', '00', '00', '00', '00', '11', '11', '11', '00', '11']

Opções do Simulador Aer

O serviço AerSimulator suporta uma variedade de opções configuráveis que podem ser atualizadas usando o método set_options. Veja a documentação da API do AerSimulator para mais detalhes.

Método de Simulação

O AerSimulator suporta uma variedade de métodos de simulação, dos quais cada um contempla um conjunto diferente de instruções. O método pode ser definido manualmente utilizando a opção simulator.set_option(method=value), ou um serviço simulador com um método pré-configurado pode ser obtido diretamente do provedor Aer utilizando Aer.get_backend.

Ao simular circuitos ideais, mudar o método dentre os de simulação exata stabilizer, statevector, density_matrix e matrix_product_state não deve alterar o resultado da simulação (a não ser que ocorra variações, às vezes comuns, de probabilidades de amostragem para resultados de medições)

[6]:
# Increase shots to reduce sampling variance
shots = 10000

# Stabilizer simulation method
sim_stabilizer = Aer.get_backend('aer_simulator_stabilizer')
job_stabilizer = sim_stabilizer.run(circ, shots=shots)
counts_stabilizer = job_stabilizer.result().get_counts(0)

# Statevector simulation method
sim_statevector = Aer.get_backend('aer_simulator_statevector')
job_statevector = sim_statevector.run(circ, shots=shots)
counts_statevector = job_statevector.result().get_counts(0)

# Density Matrix simulation method
sim_density = Aer.get_backend('aer_simulator_density_matrix')
job_density = sim_density.run(circ, shots=shots)
counts_density = job_density.result().get_counts(0)

# Matrix Product State simulation method
sim_mps = Aer.get_backend('aer_simulator_matrix_product_state')
job_mps = sim_mps.run(circ, shots=shots)
counts_mps = job_mps.result().get_counts(0)

plot_histogram([counts_stabilizer, counts_statevector, counts_density, counts_mps],
               title='Counts for different simulation methods',
               legend=['stabilizer', 'statevector',
                       'density_matrix', 'matrix_product_state'])
[6]:
../../_images/tutorials_simulators_1_aer_provider_14_0.png

Método de Simulação Automática

O método padrão de simulação é o automatic que selecionará automaticamente um dos outros métodos de simulação para cada circuito baseado nas instruções desses circuitos. Um método de simulação fixo pode ser especificado adicionando o nome do método ao obter o serviço, ou definindo a opção method no serviço.

Simulação de GPU

Os simuladores statevector, density_matrix e unitary suportam execução em GPUs da NVidia. Para estes métodos, o dispositivo de simulação também pode ser configurado manualmente para CPU ou GPU usando a opção simulator.set_options(device='GPU') do serviço. Se uma GPU não estiver disponível, esta opção gerará uma exceção (ao executar o código envolvendo o simulador).

[7]:
from qiskit_aer import AerError

# Initialize a GPU backend
# Note that the cloud instance for tutorials does not have a GPU
# so this will raise an exception.
try:
    simulator_gpu = Aer.get_backend('aer_simulator')
    simulator_gpu.set_options(device='GPU')
except AerError as e:
    print(e)

O provedor Aer também conterá serviços de simuladores GPU pré-configurados se o Qiskit Aer foi instalado com suporte à GPU em um sistema compatível:

  • aer_simulator_statevector_gpu

  • aer_simulator_density_matrix_gpu

  • aer_simulator_unitary_gpu

Nota: A versão GPU do Aer pode ser instalada usando pip install qiskit-aer-gpu.

Precisão da Simulação

Uma das opções disponíveis do simulador permite definir a precisão do float para os métodos statevector, density_matrix, unitário e superop. Isso é feito usando a opção set_precision="single" ou precision="double" (padrão):

[8]:
# Configure a single-precision statevector simulator backend
simulator = Aer.get_backend('aer_simulator_statevector')
simulator.set_options(precision='single')

# Run and get counts
result = simulator.run(circ).result()
counts = result.get_counts(circ)
print(counts)
{'11': 491, '00': 533}

Definir a precisão da simulação aplica-se tanto a dispositivos de simulação para CPU quanto para GPU. Uma precisão única reduzirá pela metade a memória requerida e poderá proporcionar melhorias de desempenho em certos sistemas.

Instruções de Simulador Personalizadas

Salvando o estado do simulador

O estado do simulador pode ser salvo em uma variedade de formatos usando instruções do simulador personalizadas.

Método de Circuito

Descrição

Métodos Suportados

save_state

Salve o estado do simulador no formato nativo para o método de simulação

Todos

save_statevector

Salve o estado do simulador como um vetor de estados

"automatic", "statevector", "matrix_product_state", "extended_stabilizer"

save_stabilizer

Salve o estado do simulador como um estabilizador Clifford

"automatic", "stabilizer"

save_density_matrix

Salve o estado do simulador como uma matriz de densidade

"automatic", "statevector", "matrix_product_state", "density_matrix"

save_matrix_product_state

Salve o estado do simulador como uma matriz de estado do produto tensor

"automatic", "matrix_product_state"

save_unitary

Salvar o estado do simulador como matriz unitária do circuito executado

"automatic", "unitary"

save_superop

Salvar o estado do simulador como matriz superoperadora do circuito executado

"automatic", "superop"

Observe que essas instruções somente são suportadas pelo simulador Aer e resultarão em um erro se um circuito que as contenha for executado em um serviço não-simulador, como um dispositivo IBM Quantum.

Salvando o statevector final

Para salvar o vetor de estado final da simulação podemos anexar o circuito com a instrução save_statevector. Observe que esta instrução deve ser aplicada antes de quaisquer medições caso não desejemos salvar o estado colapsado pós-medição

[9]:
# Construct quantum circuit without measure
circ = QuantumCircuit(2)
circ.h(0)
circ.cx(0, 1)
circ.save_statevector()

# Transpile for simulator
simulator = Aer.get_backend('aer_simulator')
circ = transpile(circ, simulator)

# Run and get statevector
result = simulator.run(circ).result()
statevector = result.get_statevector(circ)
plot_state_city(statevector, title='Bell state')
[9]:
../../_images/tutorials_simulators_1_aer_provider_25_0.png

Salvando a unidade do circuito

Para salvar a matriz unitária de um QuantumCircuit, podemos acrescentar no circuito a instrução save_unitary. Observe que este circuito não pode conter medições ou resets, já que estas instruções não são suportadas pelo método de simulação "unitary"

[10]:
# Construct quantum circuit without measure
circ = QuantumCircuit(2)
circ.h(0)
circ.cx(0, 1)
circ.save_unitary()

# Transpile for simulator
simulator = Aer.get_backend('aer_simulator')
circ = transpile(circ, simulator)

# Run and get unitary
result = simulator.run(circ).result()
unitary = result.get_unitary(circ)
print("Circuit unitary:\n", np.asarray(unitary).round(5))
Circuit unitary:
 [[ 0.70711+0.j  0.70711-0.j  0.     +0.j  0.     +0.j]
 [ 0.     +0.j  0.     +0.j  0.70711+0.j -0.70711+0.j]
 [ 0.     +0.j  0.     +0.j  0.70711+0.j  0.70711-0.j]
 [ 0.70711+0.j -0.70711+0.j  0.     +0.j  0.     +0.j]]

Salvando multiplos estados

Também, podemos aplicar instruções de salvar em vários locais de um circuito. Note que ao fazer isso, nós precisamos fornecer um rótulo único para cada instrução a fim de recuperá-la nos resultados

[11]:
# Construct quantum circuit without measure
steps = 5
circ = QuantumCircuit(1)
for i in range(steps):
    circ.save_statevector(label=f'psi_{i}')
    circ.rx(i * np.pi / steps, 0)
circ.save_statevector(label=f'psi_{steps}')

# Transpile for simulator
simulator = Aer.get_backend('aer_simulator')
circ = transpile(circ, simulator)

# Run and get saved data
result = simulator.run(circ).result()
data = result.data(0)
data
[11]:
{'psi_3': Statevector([0.58778525+0.j        , 0.        -0.80901699j],
             dims=(2,)),
 'psi_2': Statevector([0.95105652+0.j        , 0.        -0.30901699j],
             dims=(2,)),
 'psi_5': Statevector([-1.+0.00000000e+00j,  0.-2.77555756e-16j],
             dims=(2,)),
 'psi_1': Statevector([1.+0.j, 0.+0.j],
             dims=(2,)),
 'psi_4': Statevector([-0.30901699+0.j        ,  0.        -0.95105652j],
             dims=(2,)),
 'psi_0': Statevector([1.+0.j, 0.+0.j],
             dims=(2,))}

Configurar o simulador para um estado personalizado

O AerSimulator permite definir um estado personalizado do simulador para vários de seus métodos de simulação, usando instruções personalizadas do simulador

Método de Circuito

Descrição

Métodos Suportados

set_statevector

Definir o estado do simulador para o vetor de estado especificado

"automatic", "statevector", "density_matrix"

set_stabilizer

Definir o estado do simulador para o estabilizador Clifford especificado

"automatic", "stabilizer"

set_density_matrix

Definir o estado do simulador para a matriz de densidade especificada

"automatic", "density_matrix"

set_unitary

Definir o estado do simulador para a matriz unitária especificada

"automatic", "unitary", "superop"

set_superop

Definir o estado do simulador para a matriz de super-operador especificada

"automatic", "superop"

Notes: * These instructions must be applied to all qubits in a circuit, otherwise an exception will be raised. * The input state must also be a valid state (statevector, density matrix, unitary etc) otherwise an exception will be raised. * These instructions can be applied at any location in a circuit and will override the current state with the specified one. Any classical register values (e.g. from preceding measurements) will be unaffected * Set state instructions are only supported by the Aer simulator and will result in an error if a circuit containing them is run on a non-simulator backend such as an IBM Quantum device.

Configurando um vetor de estados personalizado

A instrução set_statevector pode ser usada para configurar um estado personalizado Statevector. Porém, o vetor de estado de entrada deve ser válido (\(|\langle\psi|\psi\rangle|=1\))

[12]:
# Generate a random statevector
num_qubits = 2
psi = qi.random_statevector(2 ** num_qubits, seed=100)

# Set initial state to generated statevector
circ = QuantumCircuit(num_qubits)
circ.set_statevector(psi)
circ.save_state()

# Transpile for simulator
simulator = Aer.get_backend('aer_simulator')
circ = transpile(circ, simulator)

# Run and get saved data
result = simulator.run(circ).result()
result.data(0)
[12]:
{'statevector': Statevector([ 0.18572453-0.03102771j, -0.26191269-0.18155865j,
               0.12367038-0.47837907j,  0.66510011-0.4200986j ],
             dims=(2, 2))}

Usar a instrução de inicialização

Também, é possível inicializar o simulador em um vetor de estado personalizado, usando a instrução initialize; ao contrário da instrução set_statevector, que também é suportada por backends em dispositivos reais, porém é composta por instruções de reset e de portas padrão.

[13]:
# Use initilize instruction to set initial state
circ = QuantumCircuit(num_qubits)
circ.initialize(psi, range(num_qubits))
circ.save_state()

# Transpile for simulator
simulator = Aer.get_backend('aer_simulator')
circ = transpile(circ, simulator)

# Run and get result data
result = simulator.run(circ).result()
result.data(0)
[13]:
{'statevector': Statevector([ 0.18572453-0.03102771j, -0.26191269-0.18155865j,
               0.12367038-0.47837907j,  0.66510011-0.4200986j ],
             dims=(2, 2))}

Definindo uma matriz de densidade personalizada

A instrução set_density_matrix pode ser usada para definir um estado personalizado de DensityMatrix. A matriz de densidade de entrada deve ser válida (\(Tr[\rho]=1, \rho \ge 0\))

[14]:
num_qubits = 2
rho = qi.random_density_matrix(2 ** num_qubits, seed=100)
circ = QuantumCircuit(num_qubits)
circ.set_density_matrix(rho)
circ.save_state()

# Transpile for simulator
simulator = Aer.get_backend('aer_simulator')
circ = transpile(circ, simulator)

# Run and get saved data
result = simulator.run(circ).result()
result.data(0)
[14]:
{'density_matrix': DensityMatrix([[ 0.2075308 +0.j        ,  0.13161422-0.01760848j,
                  0.0442826 +0.07742704j,  0.04852053-0.01303171j],
                [ 0.13161422+0.01760848j,  0.20106116+0.j        ,
                  0.02568549-0.03689812j,  0.0482903 -0.04367912j],
                [ 0.0442826 -0.07742704j,  0.02568549+0.03689812j,
                  0.39731492+0.j        , -0.01114025-0.13426423j],
                [ 0.04852053+0.01303171j,  0.0482903 +0.04367912j,
                 -0.01114025+0.13426423j,  0.19409312+0.j        ]],
               dims=(2, 2))}

Configurando um estado estabilizador personalizado

A instrução set_stabilizer pode ser usada para definir um estado de estabilizador Clifford personalizado. O estabilizador de entrada deve ser um Clifford válido.

[15]:
# Generate a random Clifford C
num_qubits = 2
stab = qi.random_clifford(num_qubits, seed=100)

# Set initial state to stabilizer state C|0>
circ = QuantumCircuit(num_qubits)
circ.set_stabilizer(stab)
circ.save_state()

# Transpile for simulator
simulator = Aer.get_backend('aer_simulator')
circ = transpile(circ, simulator)

# Run and get saved data
result = simulator.run(circ).result()
result.data(0)
[15]:
{'stabilizer': StabilizerState(StabilizerTable: ['+ZZ', '-IZ'])}

Definindo uma unidade personalizada

A instrução set_unitary pode ser usada para definir um estado Operator unitário personalizado. A matriz unitária de entrada deve ser válida (\(U^\dagger U=\mathbb{1}\))

[16]:
# Generate a random unitary
num_qubits = 2
unitary = qi.random_unitary(2 ** num_qubits, seed=100)

# Set initial state to unitary
circ = QuantumCircuit(num_qubits)
circ.set_unitary(unitary)
circ.save_state()

# Transpile for simulator
simulator = Aer.get_backend('aer_simulator')
circ = transpile(circ, simulator)

# Run and get saved data
result = simulator.run(circ).result()
result.data(0)
[16]:
{'unitary': Operator([[-0.44885724-0.26721573j,  0.10468034-0.00288681j,
             0.4631425 +0.15474915j, -0.11151309-0.68210936j],
           [-0.37279054-0.38484834j,  0.3820592 -0.49653433j,
             0.14132327-0.17428515j,  0.19643043+0.48111423j],
           [ 0.2889092 +0.58750499j,  0.39509694-0.22036424j,
             0.49498355+0.2388685j ,  0.25404989-0.00995706j],
           [ 0.01830684+0.10524311j,  0.62584001+0.01343146j,
            -0.52174025-0.37003296j,  0.12232823-0.41548904j]],
          input_dims=(2, 2), output_dims=(2, 2))}
[17]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
qiskit-terra0.24.0.dev0+dba2eff
qiskit-aer0.11.2
qiskit-ignis0.7.1
qiskit-ibmq-provider0.20.0
qiskit0.41.0
System information
Python version3.8.11
Python compilerClang 12.0.5 (clang-1205.0.22.11)
Python builddefault, Jul 27 2021 10:46:38
OSDarwin
CPUs8
Memory (Gb)64.0
Wed Feb 15 14:35:41 2023 JST

This code is a part of Qiskit

© Copyright IBM 2017, 2023.

This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.

Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.