Nota
Esta página foi gerada a partir do tutorials/simulators/4_custom_gate_noise.ipynb.
Execute interativamente no IBM Quantum lab.
Aplicando ruído às portas unitárias personalizadas¶
Introdução¶
Este notebook mostra como adicionar portas unitárias customizadas a um circuito quântico, e usá-las para simulações de ruído no Qiskit Aer.
[1]:
from qiskit import transpile, QuantumCircuit
import qiskit.quantum_info as qi
from qiskit.providers.aer import AerSimulator
from qiskit.providers.aer.noise import NoiseModel, amplitude_damping_error
from qiskit.tools.visualization import plot_histogram
Criando operadores de matriz¶
Podemos utilizar a classe Operator
no qiskit.quantum_info
para representar operadores de matriz arbitrários. Se o operador for unitário, pode ser adicionado a um circuito quântico e usado para simulação no Qiskit Aer.
Vamos criar dois operadores para uma porta CNOT e uma porta iSWAP:
[2]:
# CNOT matrix operator with qubit-0 as control and qubit-1 as target
cx_op = qi.Operator([[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 1, 0, 0]])
# iSWAP matrix operator
iswap_op = qi.Operator([[1, 0, 0, 0],
[0, 0, 1j, 0],
[0, 1j, 0, 0],
[0, 0, 0, 1]])
Nota: A matriz é especificada em relação ao tensor \(U_{b}\otimes U_{a}\) para qubits especificados pela lista [a, b]
.
Usando operadores nos circuitos¶
Demonstraremos como eles podem ser utilizados num circuito. Vamos considerar um exemplo de implementação de uma porta CNOT decomposta em termos de portas de qubit únicos e da porta iSWAP, da seguinte forma.
[3]:
# CNOT in terms of iSWAP and single-qubit gates
cx_circ = QuantumCircuit(2, name='cx<iSWAP>')
# Add gates
cx_circ.sdg(1)
cx_circ.h(1)
cx_circ.sdg(0)
cx_circ.unitary(iswap_op, [0, 1], label='iswap')
cx_circ.sdg(0)
cx_circ.h(0)
cx_circ.sdg(0)
cx_circ.unitary(iswap_op, [0, 1], label='iswap')
cx_circ.s(1)
print(cx_circ)
┌─────┐ ┌────────┐┌─────┐┌───┐┌─────┐┌────────┐
q_0: ┤ SDG ├─────┤0 ├┤ SDG ├┤ H ├┤ SDG ├┤0 ├─────
├─────┤┌───┐│ iswap │└─────┘└───┘└─────┘│ iswap │┌───┐
q_1: ┤ SDG ├┤ H ├┤1 ├───────────────────┤1 ├┤ S ├
└─────┘└───┘└────────┘ └────────┘└───┘
Note que atribuímos uma etiqueta opcional de "iswap"
para a unidade quando ela for inserida. Isto nos permite identificar esta unidade em um Qiskit Aer NoiseModel
para que possamos adicionar erros a estas portas unitárias personalizadas, em simulações de circuitos com ruído.
Podemos confirmar que este circuito retorna a saída correta usando a classe Operator
como um simulador para o circuito:
[4]:
# Simulate the unitary for the circuit using Operator:
unitary = qi.Operator(cx_circ)
print(unitary)
Operator([[1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
[0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
[0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j]],
input_dims=(2, 2), output_dims=(2, 2))
E para confirmar que a saída está correta, podemos calcular a fidelidade média da porta:
[5]:
f_ave = qi.average_gate_fidelity(cx_op, unitary)
print("Average Gate Fidelity: F = {:f}".format(f_ave))
Average Gate Fidelity: F = 1.000000
Criando um unitário personalizado em um modelo com ruído¶
O Qiskit Aer AerSimulator
suporta a simulação de operadores unitários arbitrários, diretamente como especificado pelo "unitário"
nas portas da base.
[6]:
'unitary' in AerSimulator().configuration().basis_gates
[6]:
True
Isso nos permite adicionar modelos com ruído às unidades arbitrárias em nossa simulação, quando as identificamos usando o argumento opcional label
do QuantumCircuit.unitary
.
Agora vamos fazer isso criando um NoiseModel
que inclui um canal de erro quântico na nossa porta personalizada para iSWAP. Para nosso exemplo, vamos criar um erro 2-qubit, composto por dois canais com amortecimento com amplitude de um single-qubit e parâmetros de amortecimento distintos. Por agora, partiremos do princípio de que todas as outras instruções são ideais.
[7]:
# Error parameters
param_q0 = 0.05 # damping parameter for qubit-0
param_q1 = 0.1 # damping parameter for qubit-1
# Construct the error
qerror_q0 = amplitude_damping_error(param_q0)
qerror_q1 = amplitude_damping_error(param_q1)
iswap_error = qerror_q1.tensor(qerror_q0)
# Build the noise model by adding the error to the "iswap" gate
noise_model = NoiseModel()
noise_model.add_all_qubit_quantum_error(iswap_error, 'iswap')
Note que quando adicionamos um erro a um rótulo personalizado como "iswap"
o NoiseModel
não sabe a que porta este rótulo se deve aplicar, então devemos adicionar manualmente a sequência de caracteres da porta desejada, ao modelo de ruído basis_gates
. Isto garante que o compilador irá rolar para as portas corretas, para a simulação do modelo com ruído. Isto pode ser feito usando a função NoiseModel.add_basis_gates
:
[8]:
noise_model.add_basis_gates(['unitary'])
print(noise_model.basis_gates)
['cx', 'id', 'u3', 'unitary']
Por padrão, as portas da base de um modelo com ruído são ['cx','id','u3']
mais quaisquer portas da base padrão do AerSimulator
, que são adicionadas ao modelo de ruído.
Simulando um modelo com ruído unitário personalizado¶
Primeiramente, vamos pegar o nosso circuito CX anterior, adicionar uma porta Hadamard inicial e uma medição final, para criar um circuito de preparação do estado de Bell que poderemos simular no AerSimulator
, tanto para o caso ideal quanto para o com ruído:
[9]:
# Bell state circuit where iSWAPS should be inserted at barrier locations
bell_circ = QuantumCircuit(2, 2, name='bell')
bell_circ.h(0)
bell_circ.append(cx_circ, [0, 1])
bell_circ.measure([0,1], [0,1])
print(bell_circ)
┌───┐┌────────────┐┌─┐
q_0: ┤ H ├┤0 ├┤M├───
└───┘│ cx<iSWAP> │└╥┘┌─┐
q_1: ─────┤1 ├─╫─┤M├
└────────────┘ ║ └╥┘
c: 2/════════════════════╩══╩═
0 1
Saída ideal¶
Primeiro, vamos ver o resultado ideal. Como isso gera um estado de Bell, esperamos dois picos para 00 e 11.
[10]:
# Create ideal simulator backend and transpile circuit
sim_ideal = AerSimulator()
tbell_circ = transpile(bell_circ, sim_ideal)
ideal_result = sim_ideal.run(tbell_circ).result()
ideal_counts = ideal_result.get_counts(0)
plot_histogram(ideal_counts,
title='Ideal output for iSWAP bell-state preparation')
[10]:

Execução do circuito com ruído¶
Finalmente, vamos simulá-lo com nosso modelo de ruído personalizado. Como há um pequeno erro de amortecimento de amplitude nas portas de 2 qubits, esperamos pequenos picos adicionais para as probabilidades dos resultado 01 e 10.
[11]:
# Create noisy simulator and transpile circuit
sim_noise = AerSimulator(noise_model=noise_model)
tbell_circ_noise = transpile(bell_circ, sim_noise)
# Run on the simulator without noise
noise_result = sim_noise.run(tbell_circ_noise).result()
noise_counts = noise_result.get_counts(bell_circ)
plot_histogram(noise_counts,
title='Noisy output for iSWAP bell-state preparation')
[11]:

[12]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
Qiskit | 0.25.0 |
Terra | 0.17.0 |
Aer | 0.8.0 |
Ignis | 0.6.0 |
Aqua | 0.9.0 |
IBM Q Provider | 0.12.2 |
System information | |
Python | 3.7.7 (default, May 6 2020, 04:59:01) [Clang 4.0.1 (tags/RELEASE_401/final)] |
OS | Darwin |
CPUs | 6 |
Memory (Gb) | 32.0 |
Fri Apr 02 12:12:41 2021 EDT |
This code is a part of Qiskit
© Copyright IBM 2017, 2021.
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.
[ ]: