Portuguese
Idiomas
English
Bengali
French
German
Japanese
Korean
Portuguese
Spanish
Tamil

Nota

Esta página foi gerada, a partir do tutorials/algorithms/09_qaoa.ipynb.

Algoritmo De Estimação De Fase Quântica Iterativa

O objetivo desse tutorial é explicar como o algoritmo do Processo Iterativo de Fases (IPE) funciona, porque usaríamos o algoritmo IPE ao invés do QPE (Estimativa de Fase Quântica) e como compilá-lo com o Qiskit usando a porta lógica de reset do circuito exploratório e o método «c_if» que permite aplicar portas lógicas resultantes dos valores armazenados em um registrador clássico, obtidos de medições anteriores.

Referências:

Conditioned gates: the c_if method

Before starting the IPE algorithm, we will give a brief tutorial about the Qiskit conditional method, c_if, as it goes into building the IPE circuit.

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

Por exemplo, o código a seguir executará a porta :math:` X ` se o valor do registro clássico for de :math:` 0 `.

[1]:
from qiskit import QuantumCircuit

qc = QuantumCircuit(1, 1)
qc.h(0)
qc.measure(0,0)
qc.x(0).c_if(0, 0)
qc.draw(output='mpl')
[1]:
../../_images/tutorials_algorithms_09_IQPE_3_0.png

We highlight that the method c_if expects as the first argument a whole classical register, not a single classical bit (or a list of classical bits), and as the second argument a value in decimal representation (a non-negative integer), not the value of a single bit, 0, or 1 (or a list/string of binary digits).

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\).

[2]:
from qiskit import QuantumRegister, ClassicalRegister

q = QuantumRegister(3, 'q')
c = ClassicalRegister(3, 'c')
qc = QuantumCircuit(q, c)

qc.h([0, 1, 2])
qc.barrier()
qc.measure(q, c)

qc.draw('mpl')
[2]:
../../_images/tutorials_algorithms_09_IQPE_5_0.png

We want to apply the \(X\) gate, only if both the results of the measurement of \(q_0\) and \(q_1\) are \(1\). We can do this using the c_if method, conditioning the application of \(X\) depending on the value passed as argument to c_if.

We will have to encode the value to pass to the c_if method such that it will check the values 011 and 111 (in binary representation), since it does not matter what \(q_2\) is measured as.

Os 2 valores inteiros em representação decimal:

19381f524ba7494e919d627154d1f6a7

We can check the solutions using the bin() method in python (the prefix 0b indicates the binary format).

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

So we have to apply \(X\) to \(q_2\) using c_if two times, one for each value corresponding to 011 and 111.

[4]:
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')
[4]:
../../_images/tutorials_algorithms_09_IQPE_11_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 Iterativo de Estimação de Fase (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 Quantum Phase Estimation <https://qiskit.org/textbook/ch-algorithms/quantum-phase-estimation.html> __.

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

Queremos aplicar o algoritmo do 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 :math:` S ` adiciona uma fase :math:` pi/2 ` ao estado :math:` | 1rangle`, deixando inalterada a fase do estado :math:` | 0rangle `

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

No seguinte, utilizaremos a notação e os termos utilizados em 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 do IPE, :math:` m ` é também o número de iterações, portanto, precisamos de apenas :math:` 2 ` iterações ou etapas.

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

[5]:
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 na aplicação do portão Hadamard no qubit auxiliar e da preparação do autoestado \(|1\rangle\).

[6]:
qc_S.h(0)
qc_S.x(1)
qc_S.draw('mpl')
[6]:
../../_images/tutorials_algorithms_09_IQPE_15_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\), uma vez que \(S\) é um portão de fase, podemos usar o portão de fase controlada \(\text{CP}(\theta)\), com \(\theta=\pi/2\).

[7]:
from math import pi

cu_circ = QuantumCircuit(2)
cu_circ.cp(pi/2, 0, 1)
cu_circ.draw('mpl')
[7]:
../../_images/tutorials_algorithms_09_IQPE_17_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\).

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

Measure in X-basis

Finally, we perform the measurement of the auxiliary qubit in X-basis. So we will define a function to perform the x_measurement and then apply it.

[9]:
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 armazená-lo na bit clássico \(c_0\).

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

Passos subsequentes (segundo 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 Control-\(U\) gates - measure of the auxiliary qubit in X-basis

Inicialização com reset

As we want to perform an iterative algorithm in the same circuit, we need to reset the auxiliary qubit \(q_0\) after the measument gate and initialize it again as before to recycle the qubit.

[11]:
qc_S.reset(0)
qc_S.h(0)
qc_S.draw('mpl')
[11]:
../../_images/tutorials_algorithms_09_IQPE_25_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 o portão de fase \(P(\theta)\) com fase \(\theta=-\pi/2\) condicionada pelo bit clássico \(c_0\) (\(=\varphi_2\)) usando o método c_if. Então, 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 representações decimais e binárias).

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

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

We apply the \(CU\) operations as we did in the first step. For the second step we have \(t=m-2\), hence \(2^t=1\). So we apply \(\text{CP}(\pi/2)\) once. And then we perform the X-measurement of the qubit \(q_0\), storing the result, the phase bit \(\varphi_1\), in the bit \(c_1\) of classical register.

[13]:
## 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

[14]:
qc_S.draw('mpl')
[14]:
../../_images/tutorials_algorithms_09_IQPE_31_0.png

Let’s sample the circuit with Qiskit Aer’s Sampler primitive, a local simulator without noise that runs locally.

[15]:
import matplotlib.pyplot as plt

from qiskit.tools.visualization import plot_histogram
from qiskit_aer.primitives import Sampler

sampler = Sampler()

job = sampler.run(qc_S)
result = job.result()

dist0 = result.quasi_dists[0]

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

fig, ax = plt.subplots(1,2)
plot_histogram(dist0, ax=ax[0])
plot_histogram(dist1, ax=ax[1])
plt.tight_layout()
../../_images/tutorials_algorithms_09_IQPE_33_0.png

Na imagem temos os mesmos histogramas mas à esquerda temos no eixo x a string com bits de fase \(\varphi_1\),:math: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 um portão de 2-qubit

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 é, o portão \(CT\) adiciona a 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 passos \(3\) uma vez que \(m=3\), e não vamos repetir todas as explicações. Portanto, para obter detalhes, consulte o exemplo acima para o portão \(U\).

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

[16]:
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 nós 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 eigenstate (autoestado / estado inerente) \(|11\rangle\).

[17]:
qc.h(0)
qc.x([1, 2])
qc.draw('mpl')
[17]:
../../_images/tutorials_algorithms_09_IQPE_38_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\) é um portão de fase, podemos usar o portão de fase multi-controlado \(\text{MCP}(\theta)\), com \(\theta=\pi/4\).

[18]:
cu_circ = QuantumCircuit(nq)
cu_circ.mcp(pi/4, [0, 1], 2)
cu_circ.draw('mpl')
[18]:
../../_images/tutorials_algorithms_09_IQPE_40_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\).

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

Measure in X-basis

Finally, we perform the measurement of the auxiliary qubit in X-basis. We can use the x_measurement function defined above in the example for 1-qubit gate. In this way we have obtained the phase bit \(\varphi_3\) and stored it in the classical bit \(c_0\).

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

Passos subsequentes (segundo, terceiro)

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 um «sub-passo» adicional de correção de fase.

Inicialização com reset

[21]:
qc.reset(0)
qc.h(0)
qc.draw('mpl')
[21]:
../../_images/tutorials_algorithms_09_IQPE_46_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 de valor \(\theta=-\pi/2\), condicionada no bit clássico \(c_0\) (\(=\varphi_3\)).

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

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

We apply the \(CU\) operations as we did in the first step. For the second step we have \(t=m-2\), hence \(2^t=2\). So we apply \(\text{MCP}(\pi/4)\) \(2\) times. And then we perform the X-measurement of the qubit \(q_0\), storing the phase bit \(\varphi_2\) in the bit \(c_1\).

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

Todos os sub-passos do terceiro passo

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

Then at the 3rd step we have to perform the phase correction of \(-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}\), thus we have to apply 2 conditioned phase corrections, one conditioned by \(\varphi_3\) (\(=c_0\)) and the other by \(\varphi_2\)(\(=c_1\)). To do this we have to apply the following: - gate \(P(-\pi/4)\) conditioned by \(c_0=1\), that is, by \(c=001\) (c_if with value \(1\)) - gate \(P(-\pi/2)\) conditioned by \(c_1=1\), that is, the gate is applied when \(c=010\) (c_if with values \(2\)) - gate \(P(-3\pi/4)\) conditioned by \(c_1=1\) and \(c_0=1\) that is, the gate is applied when \(c=011\) (c_if with values \(3\))

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

[24]:
# 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/2, 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')
[24]:
../../_images/tutorials_algorithms_09_IQPE_52_0.png

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

[25]:
result = sampler.run(qc).result()
dist0 = result.quasi_dists[0]

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

fig, ax = plt.subplots(1,2)
plot_histogram(dist0, ax=ax[0])
plot_histogram(dist1, ax=ax[1])
plt.tight_layout()
../../_images/tutorials_algorithms_09_IQPE_54_0.png

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

[26]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
qiskit-terra0.23.0.dev0+1b4fed3
qiskit-aer0.11.1
qiskit-nature0.5.0
System information
Python version3.9.13
Python compilerClang 12.0.0
Python buildmain, Oct 13 2022 16:12:30
OSDarwin
CPUs4
Memory (Gb)32.0
Fri Dec 09 16:18:07 2022 CET

This code is a part of Qiskit

© Copyright IBM 2017, 2022.

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.