Portuguese
Idiomas
English
Bengali
French
German
Japanese
Korean
Portuguese
Spanish
Tamil

Nota

Esta página foi gerada a partir de tutorials/textbook/01_IQPE.ipynb.

Algoritmo de Estimativa de Fase Quântica Iterativa

O objetivo desse tutorial é entender como o algoritmo de Estimativa de Fase Iterativa (IPE) funciona, porque usaríamos o algoritmo IPE em vez do algoritmo QPE (Estimativa de Fase Quântica) e como construí-lo com o Qiskit usando o mesmo circuito explorando a porta de reset e o método c_if que permite aplicar portas condicionadas pelos valores armazenados em um registrador clássico, resultantes de medições anteriores.

Referências

[1]:
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, execute, assemble, Aer
from qiskit.tools.visualization import plot_histogram
from math import pi
import matplotlib.pyplot as plt

Portas condicionadas: o método c_if

Antes de iniciar o algoritmo IPE, daremos um breve tutorial sobre o método condicional Qiskit, c_if, conforme se avança na construção do circuito IPE.

c_if é uma função (na verdade um método da classe porta) para realizar operações condicionadas baseadas no valor anteriormente armazenado em um registrador clássico. Com esta funcionalidade, você pode aplicar portas após uma medição no mesmo circuito condicionado pelo resultado da medição.

Por exemplo, o código a seguir executará a porta \(X\) se o valor do registrador clássico for \(0\).

[2]:
q = QuantumRegister(1,'q')
c = ClassicalRegister(1,'c')
qc = QuantumCircuit(q, c)
qc.h(0)
qc.measure(0,0)
qc.x(0).c_if(c, 0)
qc.draw(output='mpl')
[2]:
../../_images/tutorials_textbook_01_IQPE_4_0.png

Ressaltamos que o método c_if espera como o primeiro argumento todo um registrador clássico, não um único bit clássico (ou uma lista de bits clássicos), e como o segundo argumento um valor na representação decimal (um inteiro não negativo), não o valor de um único bit, 0 ou 1 (ou uma lista/cadeia de dígitos binários).

Let’s make another example. Consider that we want to perform a bit flip on the third qubit after the measurements in the following circuit, when the results of the measurement of \(q_0\) and \(q_1\) are both \(1\).

[3]:
q = QuantumRegister(3,'q')
c = ClassicalRegister(3,'c')
qc = QuantumCircuit(q, c)
qc.h(q[0])
qc.h(q[1])
qc.h(q[2])
qc.barrier()
qc.measure(q,c)
qc.draw('mpl')
[3]:
../../_images/tutorials_textbook_01_IQPE_6_0.png

Queremos aplicar a porta \(X\) somente se ambos os resultados da medição de \(q_0\) e \(q_1\) forem \(1\). Podemos fazer isso usando o método c_if, condicionando a aplicação de \(X\) dependendo do valor passado como argumento para c_if.

Teremos que codificar o valor para passar para o método c_if tal que ele verificará os valores 011 e 111 (em representação binária), uma vez que não importa como \(q_2\) é medido.

Os 2 valores inteiros em representação decimal:

2a2e67c25a3d45adbd03ab933ad9d577

Podemos verificar as soluções usando o método bin() em python (o prefixo 0b indica o formato binário).

[4]:
print(bin(3))
print(bin(7))
0b11
0b111

Por isso, temos que aplicar \(X\) a \(q_2\) utilizando c_if duas vezes, uma para cada valor correspondente a 011 e 111.

[5]:
q = QuantumRegister(3,'q')
c = ClassicalRegister(3,'c')
qc = QuantumCircuit(q, c)
qc.h(0)
qc.h(1)
qc.h(2)
qc.barrier()
qc.measure(q,c)

qc.x(2).c_if(c, 3) # for the 011 case
qc.x(2).c_if(c, 7) # for the 111 case

qc.draw(output='mpl')
[5]:
../../_images/tutorials_textbook_01_IQPE_12_0.png

IPE

The motivation for using the IPE algorithm is that QPE algorithm works fine for short depth circuits but when the circuit starts to grow, it doesn’t work properly due to gate noise and decoherence times.

A explicação detalhada de como o algoritmo funciona pode ser encontrada em Algoritmo de Estimativa de Fase Iterativa (IPE) <https://qiskit.org/textbook/ch-labs/Lab04_IterativePhaseEstimation.html#2-iterative-phase-estimation-ipe-algorithm> __. Para entender o QPE em profundidade, você pode ver também Ch.3.6 Estimativa de Fase Quântica <https://qiskit.org/textbook/ch-algorithms/quantum-phase-estimation.html> __.

Exemplo do IPE com uma porta de 1 qubit para \(U\)

Queremos aplicar o algoritmo IPE para estimar a fase para um operador de 1-qubit :math:` U . Por exemplo, aqui utilizamos a porta :math:`S.

Let’s apply the IPE algorithm to estimate the phase for \(S\)-gate. Its matrix is

\[\begin{split} S = \begin{bmatrix} 1 & 0\\ 0 & e^\frac{i\pi}{2}\\ \end{bmatrix}\end{split}\]

Ou seja, a porta \(S\) adiciona uma fase \(\pi/2\) ao estado \(|1\rangle\), deixando inalterada a fase do estado \(|0\rangle\)

\[S|1\rangle = e^\frac{i\pi}{2}|1\rangle\]

No seguinte, utilizaremos a notação e os termos utilizados na Seção 2 do laboratório 4 <https://qiskit.org/textbook/ch-labs/Lab04_IterativePhaseEstimation.html#2-iterative-phase-estimation-ipe-algorithm> __.

Let’s consider to estimate the phase \(\phi=\frac{\pi}{2}\) for the eigenstate \(|1\rangle\), we should find \(\varphi=\frac{1}{4}\) (where \(\phi = 2 \pi \varphi\)). Therefore to estimate the phase we need exactly 2 phase bits, i.e. \(m=2\), since \(1/2^2=1/4\). So \(\varphi=0.\varphi_1\varphi_2\).

Lembre-se da teoria de que para o algoritmo IPE, \(m\) é também o número de iterações, portanto, precisamos de apenas \(2\) iterações ou etapas.

Primeiro, inicializamos o circuito. O IPE trabalha com apenas 1 qubit auxiliar, em vez de \(m\) qubits de contagem do algoritmo QPE. Por isso, precisamos de 2 qubits, 1 qubit auxiliar e 1 para o autoestado da porta \(U\), e um registrador clássico de 2 bits, para os bits de fase \(\varphi_1\), \(\varphi_2\).

[6]:
nq = 2
m = 2
q = QuantumRegister(nq,'q')
c = ClassicalRegister(m,'c')

qc_S = QuantumCircuit(q,c)

Primeiro passo

Now we build the quantum circuit for the first step, that is, the first iteration of the algorithm, to estimate the least significant phase bit \(\varphi_m\), in this case \(\varphi_2\). For the first step we have 3 sub-steps: - initialization - application of the Controlled-\(U\) gates - measure of the auxiliary qubit in x-basis

Inicialização

A inicialização consiste da aplicação da porta Hadamard no qubit auxiliar e da preparação do autoestado \(|1\rangle\).

[7]:
qc_S.h(0)
qc_S.x(1)
qc_S.draw('mpl')
[7]:
../../_images/tutorials_textbook_01_IQPE_16_0.png

Application of the Controlled-\(U\) gates

Then we have to apply \(2^t\) times the Controlled-\(U\) operators (see also in the docs Two qubit gates), that, in this example, is the Controlled-\(S\) gate (\(CS\) for short).

Para implementar \(CS\) no circuito, já que \(S\) é um porta de fase, podemos usar a porta de fase controlada \(\text{CP}(\theta)\), com \(\theta=\pi/2\).

[8]:
cu_circ = QuantumCircuit(2)
cu_circ.cp(pi/2,0,1)
cu_circ.draw('mpl')
[8]:
../../_images/tutorials_textbook_01_IQPE_18_0.png

Let’s apply \(2^t\) times \(\text{CP}(\pi/2)\). Since for the first step \(t=m-1\), and \(m=2\), we have \(2^t=2\).

[9]:
for _ in range(2**(m-1)):
    qc_S.cp(pi/2,0,1)
qc_S.draw('mpl')
[9]:
../../_images/tutorials_textbook_01_IQPE_20_0.png

Medição na base x

Finalmente, procedemos com a medição do qubit auxiliar na base-x. Então definiremos uma função para realizar a medida_x e então aplicá-la.

[10]:
def x_measurement(qc, qubit, cbit):
    """Measure 'qubit' in the X-basis, and store the result in 'cbit'"""
    qc.h(qubit)
    qc.measure(qubit, cbit)

Desta forma obtemos o bit de fase \(\varphi_2\) e o armazenamos no bit clássico \(c_0\).

[11]:
x_measurement(qc_S, q[0], c[0])
qc_S.draw('mpl')
[11]:
../../_images/tutorials_textbook_01_IQPE_24_0.png

Passos subsequentes (2° passo)

Now we build the quantum circuit for the other remaining steps, in this example, only the second one. In these steps we have 4 sub-steps: the 3 sub-steps as in the first step and, in the middle, the additional step of the phase correction - initialization with reset - phase correction - application of the Controlled-\(U\) gates - measure of the auxiliary qubit in x-basis

Inicialização com reset

Como queremos realizar um algoritmo iterativo no mesmo circuito, precisamos reiniciar o qubit auxiliar \(q0\) após a porta de medição e inicializá-lo novamente como antes para reciclar o qubit.

[12]:
qc_S.reset(0)
qc_S.h(0)
qc_S.draw('mpl')
[12]:
../../_images/tutorials_textbook_01_IQPE_26_0.png

Correção de fase (para o passo 2)

As seen in the theory, in order to extract the phase bit \(\varphi_{1}\), we perform a phase correction of \(-\pi\varphi_2/2\). Of course, we need to apply the phase correction in the circuit only if the phase bit \(\varphi_2=1\), i.e. we have to apply the phase correction of \(-\pi/2\) only if the classical bit \(c_0\) is 1.

Então, após o reset aplicamos a porta de fase \(P(\theta)\) com fase \(\theta=-\pi/2\) condicionada pelo bit clássico \(c_0\) (\(=\varphi_2\)) usando o método c_if. Logo, como vimos na primeira parte deste tutorial, temos que usar o método c_if com um valor de 1, como em \(1_{10} = 001_{2}\) (os subscritos \(_{10}\) e \(_2\) indicam as representações decimal e binária).

[13]:
qc_S.p(-pi/2,0).c_if(c,1)
qc_S.draw('mpl')
[13]:
../../_images/tutorials_textbook_01_IQPE_28_0.png

Application of the Controlled-\(U\) gates and x-measurement (for step 2)

Aplicamos as operações \(CU\) assim como fizemos no primeiro passo. Para o segundo passo temos \(t=m-2\), daí \(2^t=1\). Então aplicamos \(\text{CP}(\pi/2)\) uma vez. E então realizamos a x-medição do qubit \(q_0\), armazenando o resultado, o bit de phase \(\varphi_1\), no bit \(c_1\) do registrador clássico.

[14]:
## 2^t c-U operations (with t=m-2)
for _ in range(2**(m-2)):
    qc_S.cp(pi/2,0,1)

x_measurement(qc_S, q[0], c[1])

Et voilà, temos nosso circuito final

[15]:
qc_S.draw('mpl')
[15]:
../../_images/tutorials_textbook_01_IQPE_32_0.png

Let’s execute the circuit with the qasm_simulator, the simulator without noise that run locally.

[16]:
sim = Aer.get_backend('qasm_simulator')
count0 = execute(qc_S, sim).result().get_counts()

key_new = [str(int(key,2)/2**m) for key in list(count0.keys())]
count1 = dict(zip(key_new, count0.values()))

fig, ax = plt.subplots(1,2)
plot_histogram(count0, ax=ax[0])
plot_histogram(count1, ax=ax[1])
plt.tight_layout()

Na imagem temos os mesmos histogramas mas à esquerda temos no eixo x a string com bits de fase \(\varphi_1\), \(\varphi_2\) e à direita a fase real \(\varphi\) em representação decimal.

Como esperávamos encontramos \(\varphi=\frac{1}{4}=0.25\) com uma probabilidade de \(100\%\).

Exemplo de IPE com uma porta de 2 qubits

Now, we want to apply the IPE algorithm to estimate the phase for a 2-qubit gate \(U\). For this example, let’s consider the controlled version of the \(T\) gate, i.e. the gate \(U=\textrm{Controlled-}T\) (that from now we will express more compactly with \(CT\)). Its matrix is

\[\begin{split} CT = \begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & e^\frac{i\pi}{4}\\ \end{bmatrix}\end{split}\]

Isto é, a porta \(CT\) adiciona uma fase \(\pi/4\) para o estado \(|11\rangle\), deixando inalterada a fase dos outros estados de base computacional \(|00\rangle\), \(|01\rangle\), \(|10\rangle\).

Let’s consider to estimate the phase \(\phi=\pi/4\) for the eigenstate \(|11\rangle\), we should find \(\varphi=1/8\), since \(\phi = 2 \pi \varphi\). Therefore to estimate the phase we need exactly 3 classical bits, i.e. \(m=3\), since \(1/2^3=1/8\). So \(\varphi=0.\varphi_1\varphi_2\varphi_3\).

Como feito com o exemplo para o operador de 1 qubit \(U\), seguiremos os mesmos passos, mas desta vez teremos \(3\) passos já que \(m=3\), e não vamos repetir todas as explicações. Portanto, para obter detalhes, consulte o exemplo acima para a porta de 1 qubit \(U\).

Primeiro, inicializamos o circuito com 3 qubits, 1 para o qubit auxiliar e 2 para a porta de 2 qubits, e 3 bits clássicos para armazenar os bits de fase \(\varphi_1\), \(\varphi_2\), \(\varphi_3\).

[17]:
nq = 3    # number of qubits
m = 3    # number of classical bits
q = QuantumRegister(nq,'q')
c = ClassicalRegister(m,'c')

qc = QuantumCircuit(q,c)

Primeiro passo

Agora construímos o circuito quântico para a primeira etapa, para estimar o bit de fase menos significativo \(\varphi_m=\varphi_3\).

Inicialização

Nós inicializamos o qubit auxiliar e os outros qubits com o estado inerente \(|11\rangle\).

[18]:
qc.h(0)
qc.x([1,2])
qc.draw('mpl')
[18]:
../../_images/tutorials_textbook_01_IQPE_39_0.png

Application of the Controlled-\(U\) gates

Then we have to apply multiple times the \(CU\) operator, that, in this example, is the Controlled-\(CT\) gate (\(CCT\) for short).

Para implementar \(CCT\) no circuito, dado que \(T\) é uma porta de fase, podemos usar a porta de fase multi-controlada \(\text{MCP}(\theta)\), com \(\theta=\pi/4\).

[19]:
cu_circ = QuantumCircuit(nq)
cu_circ.mcp(pi/4,[0,1],2)
cu_circ.draw('mpl')
[19]:
../../_images/tutorials_textbook_01_IQPE_41_0.png

Let’s apply \(2^t\) times \(\text{MCP}(\pi/4)\). Since for the first step \(t=m-1\) and \(m=3\), we have \(2^t=4\).

[20]:
for _ in range(2**(m-1)):
    qc.mcp(pi/4,[0,1],2)
qc.draw('mpl')
[20]:
../../_images/tutorials_textbook_01_IQPE_43_0.png

Medição na base x

Finalmente, realizamos a medida do qubit auxiliar na base x. Podemos usar a função x_measurement definida acima, no exemplo de uma porta de 1 qubit. Dessa forma, obtemos o bit de fase \(\varphi_3\) e podemos guardá-lo no bit clássico \(c_0\).

[21]:
x_measurement(qc, q[0], c[0])
qc.draw('mpl')
[21]:
../../_images/tutorials_textbook_01_IQPE_45_0.png

Passos subsequentes (2°, 3°)

Agora, construímos o circuito quântico para os outros passos restantes, o segundo e o terceiro. Como dito no primeiro exemplo, nesses passos temos uma subetapa adicional de correção de fase.

Inicialização com reset

[22]:
qc.reset(0)
qc.h(0)
qc.draw('mpl')
[22]:
../../_images/tutorials_textbook_01_IQPE_47_0.png

Correção de fase (para o passo 2)

Para extrair o bit de fase \(\varphi_{2}\), fazemos uma correção de fase de \(-\pi\varphi_3/2\).

Então, após fazer o reset, aplicamos a porta de fase \(P(\theta)\) com fase \(\theta=-\pi/2\), condicionada pelo bit clássico \(c_0\) (\(=\varphi_3\)).

[23]:
qc.p(-pi/2,0).c_if(c,1)
qc.draw('mpl')
[23]:
../../_images/tutorials_textbook_01_IQPE_49_0.png

Application of the Controlled-\(U\) gates and x-measurement (for step 2)

Nós aplicamos as operações \(CU\) como no primeiro passo. Já no segundo passo, temos \(t=m-2\), de modo que \(2^t=2\). Então aplicamos \(\text{MCP}(\pi/4)\) \(2\) vezes. E então realizamos a medida em x do qubit \(q_0\), guardando o bit de fase \(\varphi_2\) no bit \(c_1\).

[24]:
for _ in range(2**(m-2)):
    qc.mcp(pi/4,[0,1],2)
x_measurement(qc, q[0], c[1])
qc.draw('mpl')
[24]:
../../_images/tutorials_textbook_01_IQPE_51_0.png

Todos os subpassos do 3° passo

Para o 3° e último passo, realizamos o reset e a inicialização do qubit auxiliar como feito no segundo passo.

Então, no 3° passo, realizamos uma correção de fase de \(-2\pi 0.0\varphi_{2}\varphi_{3}= -2\pi \left(\frac{\varphi_2}{4}+\frac{\varphi_3}{8}\right)=-\frac{\varphi_2\pi}{2}-\frac{ \varphi_3\pi}{4}\), portanto precisamos aplicar 2 correções de fase condicionadas, uma condicionada por \(\varphi_3\) (\(=c_0\)) e a outra por \(\varphi_2\)(\(=c_1\)). Para fazer isso, precisamos aplicar o seguinte: - porta \(P(-\pi/4)\) condicionado por \(c_0=1\), ou seja, by \(c=001\) (c_if com valor \(1\)) - porta \(P(-\pi/2)\) condicionado por \(c_1=1\), ou seja, a porta é aplicaca quando \(c=010\) (c_if com valores \(2\)) - porta \(P(-3\pi/4)\) condicionado por \(c_1=1\) e \(c_0=1\) ou seja, a porta é aplicada quando \(c=011\) (c_if com valores \(3\))

Em seguida, as operações \(CU\): aplicamos \(2^t\) vezes a porta \(\text{MCP}(\pi/4)\) e desde o 3° passo \(t=m-3=0\), aplicamos a porta apenas uma vez.

[25]:
# initialization of qubit q0
qc.reset(0)
qc.h(0)

# phase correction
qc.p(-pi/4,0).c_if(c,1)

qc.p(-pi/2,0).c_if(c,2)
qc.p(-3*pi/4,0).c_if(c,3)

# c-U operations
for _ in range(2**(m-3)):
    qc.mcp(pi/4,[0,1],2)

# X measurement
qc.h(0)
qc.measure(0,2)

qc.draw('mpl')
[25]:
../../_images/tutorials_textbook_01_IQPE_53_0.png

Agora, executamos o circuito com o simulador sem ruído.

[26]:
count0 = execute(qc, sim).result().get_counts()

key_new = [str(int(key,2)/2**m) for key in list(count0.keys())]
count1 = dict(zip(key_new, count0.values()))

fig, ax = plt.subplots(1,2)
plot_histogram(count0, ax=ax[0])
plot_histogram(count1, ax=ax[1])
fig.tight_layout()

Obtivemos probabilidade de \(100\%\) de encontrar \(\varphi=0.125\), isto é, \(1/8\), como esperado.

[27]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
/opt/miniconda3/envs/qiskit/lib/python3.9/site-packages/qiskit/aqua/operators/operator_globals.py:48: DeprecationWarning: `from_label` is deprecated and will be removed no earlier than 3 months after the release date. Use Pauli(label) instead.
  X = make_immutable(PrimitiveOp(Pauli.from_label('X')))

Version Information

Qiskit SoftwareVersion
Qiskit0.24.1
Terra0.17.3
Aer0.7.6
Ignis0.5.2
Aqua0.8.2
IBM Q Provider0.13.1
System information
Python3.9.5 (default, May 18 2021, 12:31:01) [Clang 10.0.0 ]
OSDarwin
CPUs4
Memory (Gb)16.0
Fri Jul 02 06:38:27 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.