# Iterative phase estimation¶

Note

Click here to view this tutorial as an interactive Jupyter notebook in IBM Quantum Lab (requires sign-in).

The goal of this exercise is to understand how the Iterative Phase Estimation (IPE) algorithm uses dynamic circuits, and why would we use the IPE algorithm instead of the QPE (Quantum Phase Estimation) algorithm. We demonstrate how to perform this algorithm with Qiskit using circuits containing `reset`

in order to apply gates conditioned by the values resulting from previous measurements and stored in a classical register.

If you want to learn more about iterative phase estimation, visit the references below.

**References**

Qiskit Textbook, Section 2 of Lab 4: Iterative Phase Estimation (IPE) Algorithm

Exploiting dynamic quantum circuits in a quantum algorithm with superconducting qubits

Arbitrary accuracy iterative phase estimation algorithm as a two qubit benchmark

## Preamble¶

```
import os
from typing import Any, List, Dict, Union
import numpy as np
import matplotlib.pyplot as plt
from qiskit import Aer, QuantumCircuit, QuantumRegister, ClassicalRegister, transpile, execute
from qiskit.tools.visualization import plot_histogram
from qiskit_ibm_provider import IBMProvider
import warnings
warnings.filterwarnings("ignore")
pi = np.pi
```

```
# define backend to request
# Note: This can be any hub/group/project that has access to the required device and Qiskit Runtime.\n",
hub = "<hub>"
group = "<group>"
project = "<project>"
backend_name = "<your backend>"
hgp = f"{hub}/{group}/{project}"
```

```
# load backend
provider = IBMProvider()
backend = provider.get_backend(backend_name, instance=hgp)
backend_sim = Aer.get_backend('aer_simulator')
#backend = least_busy(provider.backends(dynamic_circuits=True))
print(f"Using backend {backend.name}")
```

## Iterative phase estimation¶

The motivation for using the IPE algorithm is that the Quantum Phase Estimation 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.

The detailed explanation of how the algorithm works can be found in Iterative Phase Estimation (IPE) Algorithm. To understand QPE in depth, you can see also Ch.3.6 Quantum Phase Estimation.

### IPE example with a 1-qubit gate for ¶

We want to apply the IPE algorithm to estimate the phase for a 1-qubit operator . For example, here we use the -gate.

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

That is, the -gate adds a phase to the state , leaving unchanged the phase of the state

In the following, we will use the notation and terms used in Section 2 of lab 4 of the Qiskit Textbook.

To estimate the phase for the eigenstate , we should find (where ). Therefore, to estimate the phase we need exactly two phase bits, i.e., , since . Therefore, .

Remember from the theory that for the IPE algorithm, is also the number of iterations, so we need only iterations or steps.

First, we initialize the circuit. IPE works with only one auxiliary qubit, instead of counting qubits of the QPE algorithm. Therefore, we need two qubits: one auxiliary qubit, and one for the eigenstate of -gate, as well as a classical register of two bits, for the phase bits , .

## IPE - First step¶

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 , which in this case is . For the first step we have four sub-steps:

qubit initialization

initialization

application of the Controlled- gates

measure of the auxiliary qubit in the x-basis

```
qubits = [0, 1]
shots = 1000
nq = 2
m = 2
```

```
qr = QuantumRegister(2,'q')
c0 = ClassicalRegister(1,'c0')
c1 = ClassicalRegister(1, 'c1')
qc_S = QuantumCircuit(qr, c0, c1)
```

## Eigenstate initialization¶

The initialization consists of applying the Hadamard gate to the auxiliary qubit, and the preparation of the eigenstate .

```
def initialize_eigenstate(qc):
"""Initialize the eigenstate and prepare our ancilla qubit"""
qc.h(0)
qc.x(1)
initialize_eigenstate(qc_S)
qc_S.draw('mpl')
```

## Application of the Controlled- gates¶

We now have to apply times the Controlled- operators (see also in the Qiskit documentation Two-qubit gates), that, in this example, is the Controlled- gate ( for short).

To implement in the circuit, since is a phase gate, we can use the controlled phase gate , with .

```
theta = 1 * np.pi / 2
```

```
cu_circ = QuantumCircuit(2)
cu_circ.cp(theta,0,1)
cu_circ.draw('mpl')
```

Let’s apply times . Since for the first step , and , we have .

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

## Measure in the x-basis¶

Finally, we perform the measurement of the auxiliary qubit in the x-basis.

In this way we obtain the phase bit and store it in the classical bit .

Note

The eigenvectors of the Hadamard gate are the basis vectors of the x-basis.

```
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)
x_measurement(qc_S, qr[0], c0)
qc_S.draw('mpl')
```

## Subsequent steps - Second step¶

Now we build the quantum circuit for the other remaining steps (in this example, only the second one). In these steps we have four sub-steps: the three 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- gates

measurement of the auxiliary qubit in x-basis

### Reset the auxiliary qubit¶

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

We use the built-in `qc.reset`

operation to perform a reset of qubit 0, followed by the Hadamard operation.

```
def reset_auxiliary(qc):
qc.reset(0)
qc.h(0)
reset_auxiliary(qc_S)
qc_S.draw('mpl')
```

### Phase correction (for step 2)¶

As seen in the theory, in order to extract the phase bit , we perform a phase correction of . Of course, we need to apply the phase correction in the circuit only if the phase bit , i.e., we have to apply the phase correction of only if the classical bit is 1.

So, after the reset we apply the phase gate with phase conditioned by the classical bit ()

```
with qc_S.if_test((c0, 1)):
qc_S.p(-np.pi/2,0)
qc_S.draw('mpl')
```

### Apply the controlled- gates and x-measurement (for step 2)¶

We apply the operations as we did in the first step. For the second step we have , hence . We therefore apply once, and then we perform the x-measurement of the qubit , storing the result, the phase bit , in bit of the classical register.

```
## 2^t c-U operations (with t=m-2)
for _ in range(2**(m-2)):
qc_S.cp(theta,0,1)
x_measurement(qc_S, qr[0], c1)
```

We now have our final circuit!

```
qc_S.draw('mpl')
```

Let’s execute the circuit with the `qasm_simulator`

, the simulator
without noise that runs locally.

```
count = execute(qc_S, backend_sim).result().get_counts()
count
```

```
{'0 1': 1024}
```

```
count0 = execute(qc_S, backend_sim).result().get_counts()
plot_histogram(count0)
```

```
count0
```

```
{'0 1': 1024}
```

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

As we expected, we have found with a probability.

## Run on real hardware¶

```
qc_S_backend = transpile(qc_S, backend, initial_layout=qubits, optimization_level=1)
qc_S_backend.draw(output="mpl")
```

```
real_ipe_job = backend.run(qc_S_backend, dynamic=True, shots=shots)
print(f"IPE job id: {real_ipe_job.job_id()}")
```

```
IPE job id: cdlf4v6h8o8scshbikqg
```

```
real_counts0 = real_ipe_job.result().get_counts()
plot_histogram(real_counts0)
```

As expected, we estimate the correct result of `01`

the majority of the time.

Now that we have estimated the phase of the gate, let’s try finding the phase of another gate. Recall that we implemented IPE for `S`

using the gate. Choose a new instance of the gate that can be estimated with two bits of precision and rerun.

After you have mastered IPE for two bits of precision, try adding a third bit. Modify the code of this exercise to add another round of IPE.

```
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
```

### Version Information

Qiskit Software | Version |
---|---|

`qiskit-terra` | 0.23.0 |

`qiskit-aer` | 0.11.4 |

`qiskit-ignis` | 0.7.0 |

`qiskit-ibmq-provider` | 0.20.0.dev0+4f1f8c6 |

`qiskit` | 0.36.1 |

System information | |

Python version | 3.9.5 |

Python compiler | Clang 10.0.0 |

Python build | default, May 18 2021 12:31:01 |

OS | Darwin |

CPUs | 8 |

Memory (Gb) | 32.0 |

Tue Nov 08 19:22:46 2022 EST |

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