Nota

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

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

The goal of this tutorial is to understand how the Iterative Phase Estimation (IPE) algorithm works, why would we use the IPE algorithm instead of the QPE (Quantum Phase Estimation) algorithm and how to build it with Qiskit using the same circuit exploiting reset gate and the c_if method that allows to apply gates conditioned by the values stored in a classical register, resulting from previous measurements.

Referências:

[56]:

from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, transpile, Aer
from qiskit.tools.visualization import plot_histogram
from math import pi
import matplotlib.pyplot as plt


# Conditioned gates: the c_if method¶

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

c_if is a function (actually a method of the gate class) to perform conditioned operations based on the value stored previously in a classical register. With this feature you can apply gates after a measurement in the same circuit conditioned by the measurement outcome.

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

[57]:

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')

[57]:


Destacamos que o método c_if espera como o primeiro argumento todo um registro 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).

Vamos fazer outro exemplo. Considere que queremos executar um bit flip no terceiro qubit após as medições no circuito a seguir, quando os resultados da medição de :math: q_0  e :math: q_1  são ambos de :math: 1 .

[83]:

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')

[83]:


Queremos aplicar a porta :math:”X”, apenas se ambos os resultados da medição de :math: q_1  e de :math: q_2  forem :math: 1 . Podemos fazer isso usando o método c_if, condicionando a aplicação de :math: 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 o que está na posição mais à direita.

Os 2 valores inteiros em representação decimal:

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

[84]:

print(bin(3))
print(bin(7))

0b11
0b111


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

[86]:

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')

[86]:


# IPE¶

A motivação para usar o algoritmo do IPE é que o algoritmo QPE funciona bem para circuitos de profundidade curtos mas quando o circuito começa a crescer, ele não funciona adequadamente devido aos tempos de ruído e decoerência da porta.

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.

Vamos aplicar o algoritmo do IPE para estimar a fase para a porta :math: S . Sua matriz é

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

[61]:

nq = 2
m = 2
q = QuantumRegister(nq,'q')
c = ClassicalRegister(m,'c')

qc_S = QuantumCircuit(q,c)


### Primeiro passo¶

Agora construímos o circuito quântico para a primeira etapa, ou seja, a primeira iteração do algoritmo, para estimar a fase menos significativa bit :math: varphi_m , neste caso :math: varphi_2 . Para o primeiro passo temos 3 sub-etapas:-inicialização-aplicação das portas Controlled-:math: U -medida do qubit auxiliar na base X

#### Initialization¶

The initialization consists of application the Hadamard gate to the auxiliary qubit and the preparation of the eigenstate $$|1\rangle$$.

[62]:

qc_S.h(0)
qc_S.x(1)
qc_S.draw('mpl')

[62]:


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

To implement $$CS$$ in the circuit, since $$S$$ is a phase gate, we can use the controlled phase gate $$\text{CP}(\theta)$$, with $$\theta=\pi/2$$.

[63]:

cu_circ = QuantumCircuit(2)
cu_circ.cp(pi/2,0,1)
cu_circ.draw('mpl')

[63]:


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$$.

[64]:

for _ in range(2**(m-1)):
qc_S.cp(pi/2,0,1)
qc_S.draw('mpl')

[64]:


#### 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_measure and then apply it.

[65]:

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)


In this way we obtain the phase bit $$\varphi_2$$ and store it in the classical bit $$c_0$$.

[66]:

x_measurement(qc_S, q[0], c[0])
qc_S.draw('mpl')

[66]:


### Subsequent steps (2nd step)¶

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

#### Initialization with reset¶

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

[67]:

qc_S.reset(0)
qc_S.h(0)
qc_S.draw('mpl')

[67]:


#### Phase correction (for step 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.

So, after the reset we apply the phase gate $$P(\theta)$$ with phase $$\theta=-\pi/2$$ conditioned by the classical bit $$c_0$$ ($$=\varphi_2$$) using the c_if method. So as we saw in the first part of this tutorial, we have to use the c_if method with a value of 1, as $$1_{10} = 001_{2}$$ (the subscripts $$_{10}$$ and $$_2$$ indicate the decimal and binary representations).

[68]:

qc_S.p(-pi/2,0).c_if(c,1)
qc_S.draw('mpl')

[68]:


#### 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-measurment of the qubit $$q_0$$, storing the result, the phase bit $$\varphi_1$$, in the bit $$c_1$$ of classical register.

[69]:

## 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à, we have our final circuit

[70]:

qc_S.draw('mpl')

[70]:


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

[71]:

sim = Aer.get_backend('qasm_simulator')
count0 = sim.run(transpile(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()


In the picture we have the same histograms but on the left we have on the x-axis the string with phase bits $$\varphi_1$$, $$\varphi_2$$ and on the right the actual phase $$\varphi$$ in decimal representation.

As we expected we have found $$\varphi=\frac{1}{4}=0.25$$ with a $$100\%$$ probability.

## IPE example with a 2-qubit gate¶

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 complactly 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}$

That is, the $$CT$$ gate adds a phase $$\pi/4$$ to the state $$|11\rangle$$, leaving unchanged the phase of the other computational basis states $$|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$$.

As done with the example for the 1-qubit $$U$$ operator we will go through the same steps but this time we will have $$3$$ steps since $$m=3$$, and we will not repeat all the explanations. So for details see the above example for 1-qubit $$U$$ gate.

First, we initialize the circuit with 3 qubits, 1 for the auxiliary qubit and 2 for the 2-qubit gate, and 3 classical bits to store the phase bits $$\varphi_1$$, $$\varphi_2$$, $$\varphi_3$$.

[72]:

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¶

Now we build the quantum circuit for the first step, to estimate the least significant phase bit $$\varphi_m=\varphi_3$$.

#### Initialization¶

We initialize the auxiliary qubit and the other qubits with the eigenstate $$|11\rangle$$.

[73]:

qc.h(0)
qc.x([1,2])
qc.draw('mpl')

[73]:


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

To implement $$CCT$$ in the circuit, since $$T$$ is a phase gate, we can use the multi-controlled phase gate $$\text{MCP}(\theta)$$, with $$\theta=\pi/4$$.

[74]:

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

[74]:


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$$.

[75]:

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

[75]:


#### Measure in x-basis¶

Finally, we perform the measurenment 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$$.

[76]:

x_measurement(qc, q[0], c[0])
qc.draw('mpl')

[76]:


### Subsequent steps (2nd, 3rd)¶

Now we build the quantum circuit for the other remaining steps, the second and the third ones. As said in the first example, in these steps we have the additional sub-step of the phase correction.

#### Initialization with reset¶

[77]:

qc.reset(0)
qc.h(0)
qc.draw('mpl')

[77]:


#### Phase correction (for step 2)¶

In order to extract the phase bit $$\varphi_{2}$$, we perform a phase correction of $$-\pi\varphi_3/2$$.

So, after the reset we apply the phase gate $$P(\theta)$$ with phase $$\theta=-\pi/2$$ conditioned by the classical bit $$c_0$$ ($$=\varphi_3$$).

[78]:

qc.p(-pi/2,0).c_if(c,1)
qc.draw('mpl')

[78]:


#### 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$$.

[79]:

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

[79]:


#### All substeps of the 3rd step¶

For the 3rd and last step, we perform the reset and initialization of the auxiliary qubit as done in the second step.

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$$)

Next, the $$CU$$ operations: we apply $$2^t$$ times the $$\text{MCP}(\pi/4)$$ gate and since at the 3rd step $$t=m-3=0$$, we apply the gate only once.

[80]:

# 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')

[80]:


Now, we execute the circuit with the simulator without noise.

[81]:

count0 = sim.run(transpile(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])
plt.tight_layout()


We have obtained $$100\%$$ probability to find $$\varphi=0.125$$, that is, $$1/8$$, as expected.

[82]:

import qiskit.tools.jupyter
%qiskit_version_table


### Version Information

Qiskit SoftwareVersion
Qiskit0.26.0
Terra0.17.3
Aer0.8.2
Ignis0.6.0
Aqua0.9.1
IBM Q Provider0.13.1
System information
Python3.7.9 (default, Aug 31 2020, 07:22:35) [Clang 10.0.0 ]
OSDarwin
CPUs8
Memory (Gb)32.0
Wed Jun 02 13:39:10 2021 EDT