<jupyter_start><jupyter_text>Оценка pi ($\pi$) с использованием квантового алгоритма оценки фазы  Оценка pi ($\pi$) с использованием квантового алгоритма оценки фазы.  1. Краткий обзор [квантового алгоритма оценки фазы](https://qiskit.org/textbook/ch-algorithms/quantum-phase-estimation.html)Quantum Phase Estimation (QPE) is a quantum algorithm that forms the building block of many more complex quantum algorithms. At its core, QPE solves a fairly straightforward problem: given an operator $U$ and a quantum state $\vert\psi\rangle$ that is an eigenvalue of $U$ with $U\vert\psi\rangle = \exp\left(2 \pi i  \theta\right)\vert\psi\rangle$, can we obtain an estimate of $\theta$?Ответ положительный. Алгоритм QPE дает нам $2^n\theta$, где $n$ — количество кубитов, которое мы используем для оценки фазы $\theta$. 2. Оценка $\pi$В этой демонстрации мы выбираем $$U = p(\theta), \vert\psi\rangle = \vert1\rangle$$, где $$ p(\theta) = \begin{bmatrix} 1 &amp; 0\ 0 &amp; \ exp(i\theta) \end{bmatrix} $$ — один из квантовых вентилей, доступных в Qiskit, а $$p(\theta)\vert1\rangle = \exp(i\theta)\vert1\rangle.$$Выбрав фазу для нашего вентиля $\theta = 1$, мы можем найти $\pi$, используя следующие два соотношения:1. На выходе алгоритма QPE мы измеряем оценку для $2^n\theta$. Тогда $\theta = \text{измерено} / 2^n$2. Из приведенного выше определения вентиля $p(\theta)$ мы знаем, что $2\pi\theta = 1 \Rightarrow \pi = 1 / 2\theta$Комбинируя эти два соотношения, $\pi = 1 / \left(2 \times (\text{(измерено)}/2^n)\right)$.Для подробного понимания алгоритма QPE обратитесь к посвященной ему главе в учебнике Qiskit, расположенном по адресу [qiskit.org/textbook](https://qiskit.org/textbook/ch-algorithms/quantum-phase-estimation.html) .  3. Время писать код Начнем с импорта необходимых библиотек.<jupyter_code>## import the necessary tools for our work
from IPython.display import clear_output
from  qiskit import *
from qiskit.visualization import plot_histogram
import numpy as np
import matplotlib.pyplot as plotter
from qiskit.tools.monitor import job_monitor
# Visualisation settings
import seaborn as sns, operator
sns.set_style("dark")

pi = np.pi<jupyter_output><empty_output><jupyter_text>Функция `qft_dagger` вычисляет обратное квантовое преобразование Фурье. Для подробного понимания этого алгоритма см. посвященную ему главу в [учебнике Qiskit](https://qiskit.org/textbook/ch-algorithms/quantum-fourier-transform.html) .<jupyter_code>## Code for inverse Quantum Fourier Transform
## adapted from Qiskit Textbook at
## qiskit.org/textbook

def qft_dagger(circ_, n_qubits):
    """n-qubit QFTdagger the first n qubits in circ"""
    for qubit in range(int(n_qubits/2)):
        circ_.swap(qubit, n_qubits-qubit-1)
    for j in range(0,n_qubits):
        for m in range(j):
            circ_.cp(-np.pi/float(2**(j-m)), m, j)
        circ_.h(j)<jupyter_output><empty_output><jupyter_text>Следующая функция, `qpe_pre` , подготавливает начальное состояние для оценки. Обратите внимание, что начальное состояние создается путем применения вентиля Адамара ко всем кубитам, кроме последнего, и установки последнего кубита в $\vert1\rangle$.<jupyter_code>## Code for initial state of Quantum Phase Estimation
## adapted from Qiskit Textbook at qiskit.org/textbook
## Note that the starting state is created by applying 
## H on the first n_qubits, and setting the last qubit to |psi> = |1>

def qpe_pre(circ_, n_qubits):
    circ_.h(range(n_qubits))
    circ_.x(n_qubits)

    for x in reversed(range(n_qubits)):
        for _ in range(2**(n_qubits-1-x)):
            circ_.cp(1, n_qubits-1-x, n_qubits)<jupyter_output><empty_output><jupyter_text>Затем мы пишем быструю функцию `run_job` для запуска квантовой схемы и возврата результатов.<jupyter_code>## Run a Qiskit job on either hardware or simulators

def run_job(circ, backend, shots=1000, optimization_level=0):
    t_circ = transpile(circ, backend, optimization_level=optimization_level)
    qobj = assemble(t_circ, shots=shots)
    job = backend.run(qobj)
    job_monitor(job)
    return job.result().get_counts()<jupyter_output><empty_output><jupyter_text>Затем загрузите свою учетную запись, чтобы использовать облачный симулятор или реальные устройства.<jupyter_code>## Load your IBMQ account if 
## you'd like to use the cloud simulator or real quantum devices
my_provider = IBMQ.load_account()
simulator_cloud = my_provider.get_backend('ibmq_qasm_simulator')
device = my_provider.get_backend('ibmq_16_melbourne')
simulator = Aer.get_backend('qasm_simulator')<jupyter_output><empty_output><jupyter_text>Наконец, мы объединяем все вместе в функции `get_pi_estimate` , которая использует `n_qubits` для получения оценки $\pi$.<jupyter_code>## Function to estimate pi
## Summary: using the notation in the Qiskit textbook (qiskit.org/textbook),
## do quantum phase estimation with the 'phase' operator U = p(theta) and |psi> = |1>
## such that p(theta)|1> = exp(2 x pi x i x theta)|1>
## By setting theta = 1 radian, we can solve for pi
## using 2^n x 1 radian = most frequently measured count = 2 x pi

def get_pi_estimate(n_qubits):

    # create the circuit
    circ = QuantumCircuit(n_qubits + 1, n_qubits)
    # create the input state
    qpe_pre(circ, n_qubits)
    # apply a barrier
    circ.barrier()
    # apply the inverse fourier transform
    qft_dagger(circ, n_qubits)
    # apply  a barrier
    circ.barrier()
    # measure all but the last qubits
    circ.measure(range(n_qubits), range(n_qubits))

    # run the job and get the results
    counts = run_job(circ, backend=simulator, shots=10000, optimization_level=0)
    # print(counts) 

    # get the count that occurred most frequently
    max_counts_result = max(counts, key=counts.get)
    max_counts_result = int(max_counts_result, 2)
    
    # solve for pi from the measured counts
    theta = max_counts_result/2**n_qubits
    return (1./(2*theta))<jupyter_output><empty_output><jupyter_text>Теперь запустите функцию `get_pi_estimate` с различным количеством кубитов и распечатайте оценки.<jupyter_code># estimate pi using different numbers of qubits
nqs = list(range(2,12+1))
pi_estimates = []
for nq in nqs:
    thisnq_pi_estimate = get_pi_estimate(nq)
    pi_estimates.append(thisnq_pi_estimate)
    print(f"{nq} qubits, pi ≈ {thisnq_pi_estimate}")<jupyter_output>Job Status: job has successfully run
2 qubits, pi ≈ 2.0
Job Status: job has successfully run
3 qubits, pi ≈ 4.0
Job Status: job has successfully run
4 qubits, pi ≈ 2.6666666666666665
Job Status: job has successfully run
5 qubits, pi ≈ 3.2
Job Status: job has successfully run
6 qubits, pi ≈ 3.2
Job Status: job has successfully run
7 qubits, pi ≈ 3.2
Job Status: job has successfully run
8 qubits, pi ≈ 3.1219512195121952
Job Status: job has successfully run
9 qubits, pi ≈ 3.1604938271604937
Job Status: job has successfully run
10 qubits, pi ≈ 3.1411042944785277
Job Status: job has successfully run
11 qubits, pi ≈ 3.1411042944785277
Job Status: job has successfully run
12 qubits, pi ≈ 3.1411042944785277<jupyter_text>И постройте все результаты.<jupyter_code>plotter.plot(nqs, [pi]*len(nqs), '--r')
plotter.plot(nqs, pi_estimates, '.-', markersize=12)
plotter.xlim([1.5, 12.5])
plotter.ylim([1.5, 4.5])
plotter.legend(['$\pi$', 'estimate of $\pi$'])
plotter.xlabel('Number of qubits', fontdict={'size':20})
plotter.ylabel('$\pi$ and estimate of $\pi$', fontdict={'size':20})
plotter.tick_params(axis='x', labelsize=12)
plotter.tick_params(axis='y', labelsize=12)
plotter.show()
import qiskit
qiskit.__qiskit_version__<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.107535425771421, 'fraction_numerical': 0.027546020394649717, 'mean_word_length': 4.918495297805642, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 38, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '17593', 'license': 'Apache-2.0', 'n_tokens_mistral': 2885, 'n_tokens_neox': 2916, 'n_words': 790, 'path': 'notebooks_ru/ch-demos/piday-code.ipynb', 'repo_name': 'gitlocalize/platypus', 'size': '7551'}