Nota
Esta página foi gerada a partir do tutorials/simulators/5_noise_transformation.ipynb.
Execute interativamente no IBM Quantum lab.
Transformação de ruídos¶
Introdução¶
Este notebook mostra como utilizar as funções utilitárias approximate_quantum_error
e approximate_noise_model
do Qiskit Aer para transformar canais de ruído quântico em um canal de ruído diferente, mais adequado.
O nosso exemplo guia é a simulação de Clifford. Um simulador de clifford pode eficientemente simular computações quânticas que incluem apenas portas de um conjunto limitado e não universal de portas (as portas de Clifford). Nem todos os ruídos quânticos podem ser adicionados a essas simulações; procuramos, portanto, encontrar um canal de ruído “próximo” que possa ser simulado num simulador de clifford.
Começamos importando as funções de transformação dos utilitários do provedor Aer
[1]:
from qiskit.providers.aer.utils import approximate_quantum_error
from qiskit.providers.aer.utils import approximate_noise_model
O nome “aproximado” sugere que essas funções geram o erro mais próximo (na métrica de Hilbert-Schmidt) possível ao dado.
Demonstramos a aproximação usando vários canais de erro padrão definidos no Qiskit.
[2]:
import numpy as np
# Import Aer QuantumError functions that will be used
from qiskit.providers.aer.noise import amplitude_damping_error
from qiskit.providers.aer.noise import reset_error
from qiskit.providers.aer.noise import pauli_error
Visão geral¶
Um canal quântico de 1 qubit é uma função \(\mathcal{C}:\mathbb{C}^{2\times2}\to\mathbb{C}^{2\times2}\) mapeando operadores de densidade para operadores de densidade (para garantir que a imagem é um operador de densidade, é necessário que \(\mathcal{C}\) seja completamente positivo e preserve o traço, CPTP).
Dados canais quânticos \(\mathcal{E}_{1},\dots,\mathcal{E}_{r}\), e probabilidades \(p_1, p_2, \dots, p_r\) tais que \(0\le p_i \le 1\) e \(p_1+\dots +p_r = 1\), um novo canal quântico \(\mathcal{C}_\mathcal{E}\) pode ser construído de tal forma que \(\mathcal{C}_\mathcal{E}(\rho)\) tem o efeito de escolher o canal \(\mathcal{E}_i\) com probabilidade \(p_i\) e aplicá-lo à \(\rho\).
A função de transformação de ruído resolve o seguinte problema de otimização: Dado a um canal \(\mathcal{C}\) (“objetivo”) e uma lista de canais \(\mathcal{E}_{1},\dots,\mathcal{E}_{r}\), encontre as probabilidades \(p_1, p_2, \dots, p_r\) minimizando \(D(\mathcal{C}, \mathcal{C}_\mathcal{E})\) de acordo com alguma métrica de distância \(D\) (a métrica Hilbert-Schmidt é usada atualmente).
Para garantir que a aproximação seja honesta, no sentido de que o canal de erro aproximado serve como um “limite superior” para o canal de erro real, adicionamos a restrição de honestidade adicional:
Onde \(\text{F}\) é uma medida de fidelidade e \(I\) é o canal identidade.
Exemplo: Aproximando o ruído de amortecimento de amplitude com ruído de reset.¶
Ruído de Amortecimento de Amplitude é descrito por um único parâmetro \(0\le \gamma \le 1\) e é dado pelos operadores de Kraus:
O erro de reset é descrito pelas probabilidades \(0\le p, q\le 1\) tais que \(p+q\le 1\) e é dado pelos operadores de Kraus:
Isto pode ser pensado como “resetar” o estado quântico do qubit afetado para \(\left|0\right\rangle\) com probabilidade \(p\), para \(\left|1\right\rangle\) com probabilidade \(q\), e não fazer nada com probabilidade \(1-(p+q)\).
Não é muito difícil determinar de forma analítica os melhores valores de \(p,q\) para aproximar um canal de amortecimento de amplitude \(\gamma\), veja os detalhes aqui. A melhor aproximação é:
[3]:
gamma = 0.23
error = amplitude_damping_error(gamma)
results = approximate_quantum_error(error, operator_string="reset")
Nós só precisávamos do código acima para realizar a aproximação real.
[4]:
print(results)
p = (1 + gamma - np.sqrt(1 - gamma)) / 2
q = 0
print("")
print("Expected results:")
print("P(0) = {}".format(1-(p+q)))
print("P(1) = {}".format(p))
print("P(2) = {}".format(q))
QuantumError on 1 qubits. Noise circuits:
P(0) = 0.8237482193044614, QasmQobjInstructions = [[{'name': 'id', 'qubits': [0]}]
P(1) = 0.17625178069553862, QasmQobjInstructions = [[{'name': 'reset', 'qubits': [0]}]
Expected results:
P(0) = 0.8237482193696062
P(1) = 0.17625178063039387
P(2) = 0
Obtivemos os resultados previstos analiticamente.
Diferentes tipos de entrada¶
A função de aproximação recebe duas entradas: O canal de erro a ser aproximado, e um conjunto de canais de erro que podem ser usados na construção da aproximação.
O canal de erro a ser aproximado pode ser dado como qualquer entrada que possa ser convertida para o objeto QuantumError
.
Como um exemplo, construímos explicitamente as matrizes de Kraus de amortecimento de amplitude e passamos para a mesma função de aproximação de antes:
[5]:
gamma = 0.23
K0 = np.array([[1,0],[0,np.sqrt(1-gamma)]])
K1 = np.array([[0,np.sqrt(gamma)],[0,0]])
results = approximate_quantum_error((K0, K1), operator_string="reset")
print(results)
QuantumError on 1 qubits. Noise circuits:
P(0) = 0.8237482193044617, QasmQobjInstructions = [[{'name': 'id', 'qubits': [0]}]
P(1) = 0.1762517806955383, QasmQobjInstructions = [[{'name': 'reset', 'qubits': [0]}]
Os operadores de erro que são usados para construir o canal de aproximação também podem ser fornecidos como uma lista, um dicionário ou uma string indicando canais codificados.
Qualquer canal pode ser uma lista de operadores de Kraus, ou objetos ‘QuantumError’.
O canal identidade não precisa ser passado diretamente; ele é sempre utilizado implicitamente.
Como um exemplo, nós aproximamos o amortecimento de amplitude usando uma representação explícita de Kraus para ruídos de reset:
[6]:
reset_to_0 = [np.array([[1,0],[0,0]]), np.array([[0,1],[0,0]])]
reset_to_1 = [np.array([[0,0],[1,0]]), np.array([[0,0],[0,1]])]
reset_kraus = (reset_to_0, reset_to_1)
gamma = 0.23
error = amplitude_damping_error(gamma)
results = approximate_quantum_error(error, operator_list=reset_kraus)
print(results)
QuantumError on 1 qubits. Noise circuits:
P(0) = 0.8237482193044614, QasmQobjInstructions = [[{'name': 'id', 'qubits': [0]}]
P(1) = 0.17625178069553862, QasmQobjInstructions = [[{'name': 'kraus', 'qubits': [0], 'params': [array([[1, 0],
[0, 0]]), array([[0, 1],
[0, 0]])]}]
Observe a diferença no canal de saída: As probabilidades são as mesmas, mas os operadores de Kraus da entrada foram convertidos em canais de Kraus gerais, que não podem ser usados em um simulador de Clifford. Por isso, é sempre melhor passar um objeto QuantumError
em vez das matrizes de Kraus, quando possível.
[7]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
Qiskit | None |
Terra | 0.14.0 |
Aer | 0.6.0 |
Ignis | None |
Aqua | None |
IBM Q Provider | 0.6.1 |
System information | |
Python | 3.7.7 (default, Mar 26 2020, 10:32:53) [Clang 4.0.1 (tags/RELEASE_401/final)] |
OS | Darwin |
CPUs | 4 |
Memory (Gb) | 16.0 |
Tue Apr 28 13:42:53 2020 EDT |
This code is a part of Qiskit
© Copyright IBM 2017, 2020.
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.
[ ]: