Skip to content

Commit 52f5099

Browse files
committed
estimation prob workflow
1 parent 36fce7c commit 52f5099

File tree

1 file changed

+315
-0
lines changed

1 file changed

+315
-0
lines changed

Estimation problem workflow.ipynb

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Estimation problem workflow\n",
8+
"\n",
9+
"For a multivariate random variable $X$ and a real-valued function $f$ the goal is to compute \n",
10+
"\n",
11+
"$$\n",
12+
" \\mathbb{E}[f(X)], \\text{ where } f: \\mathbb{R}^n \\mapsto I \\subset \\mathbb R\n",
13+
"$$\n",
14+
"\n",
15+
"Here, this is achieved using quantum amplitude estimation (QAE), based on a $\\mathcal{A}$ operator in the format\n",
16+
"\n",
17+
"$$\n",
18+
" \\mathcal{A}|0\\rangle = \\sqrt{1 - a}|\\Psi_0\\rangle + \\sqrt{a}|\\Psi_1\\rangle\n",
19+
" = \\sum_{\\hat x = 0}^{2^n - 1} \\sqrt{p_{\\phi(\\hat x)} (1 - \\hat f(\\phi(\\hat x)))} |x\\rangle |0\\rangle\n",
20+
" + \\sum_{\\hat x = 0}^{2^n - 1} \\sqrt{p_{\\phi(\\hat x)} \\hat f(\\phi(\\hat x))} |x\\rangle |1\\rangle\n",
21+
"$$\n",
22+
"\n",
23+
"To revert the scalings from $f$ to $\\hat f$ and possible post-processing from the function approximation, the result of QAE, $\\tilde a$, is mapped to the result via a post-processing function $\\eta$\n",
24+
"\n",
25+
"$$\n",
26+
"\\mathbb{E}[f(X)] = \\eta(a) \\approx \\eta(\\tilde a)\n",
27+
"$$\n",
28+
"\n",
29+
"**Notes:**\n",
30+
"\n",
31+
"An amplitude function $F$ of a function $\\hat f$ is a mapping\n",
32+
"\n",
33+
"$$\n",
34+
"F: |x\\rangle|0\\rangle \\mapsto \\sqrt{1 - \\hat f(x)}|x\\rangle|0\\rangle + \\sqrt{\\hat f(x)}|x\\rangle|1\\rangle\n",
35+
"$$\n",
36+
"\n",
37+
"where\n",
38+
"\n",
39+
"$$\n",
40+
"\\hat f: \\mathbb{N}_0 \\rightarrow [0, 1].\n",
41+
"$$\n",
42+
"\n",
43+
"If we have a function $f$ that does not act on these spaces we must normalize the image and apply an affine transformation from the input domain to $\\mathbb{N}_0$. Let the function $f$ be defined on $2^n$ equidistant points in $[a, b]$:\n",
44+
"\n",
45+
"$$\n",
46+
"f: [a, b] \\rightarrow [c, d]\n",
47+
"$$\n",
48+
"\n",
49+
"then the rescaled version is\n",
50+
"\n",
51+
"$$\n",
52+
"\\hat f(x) = \\frac{f(\\phi(x)) - c}{d - c}\n",
53+
"$$\n",
54+
"\n",
55+
"where $\\phi(x) = a + (b - a) x / 2^n$ is the affine transformation.\n",
56+
"\n",
57+
"The normalized function $\\hat f$ can be implemented in different manners. In general this requires a post-processing step, $\\zeta$:\n",
58+
"\n",
59+
"$$\n",
60+
"\\hat f \\approx \\zeta(T\\hat f)\n",
61+
"$$\n",
62+
"\n",
63+
"where $T\\hat f$ is the amplitude we can map onto the qubits.\n",
64+
"One example is a Taylor approximation of $\\sin^2$ which can be mapped to qubits using RY gates.\n",
65+
"\n",
66+
"Examples:\n",
67+
"\n",
68+
"* quadratic terms can be approximated with\n",
69+
" $$\n",
70+
" ax^2 \\approx \\sin^2(c\\sqrt{a}x) / c^2\n",
71+
" $$\n",
72+
" where the sine part is estimated with amplitude estimation and the rescaling is $\\zeta(x) = x/c^2$\n",
73+
" \n",
74+
"* linear terms can be approximated as\n",
75+
" $$\n",
76+
" ax \\approx \\zeta\\left( \\sin^2\\left(\\frac{\\pi}{4} + \\frac{\\pi c}{2} \\left(f(x) - \\frac{1}{2}\\right)\\right) \\right) \n",
77+
" $$\n",
78+
" with\n",
79+
" $$\n",
80+
" \\zeta(x) = \\frac{2}{\\pi c}\\left(x - \\frac{1}{2}\\right) + \\frac{1}{2}\n",
81+
" $$\n",
82+
"\n",
83+
"Let $\\tilde a$ be the output of amplitude estimation, then in general we have to apply a post-processing in the form of\n",
84+
"\n",
85+
"$$\n",
86+
"c + (d - c) \\zeta(\\tilde a)\n",
87+
"$$"
88+
]
89+
},
90+
{
91+
"cell_type": "markdown",
92+
"metadata": {},
93+
"source": [
94+
"## Defining the random variable\n",
95+
"\n",
96+
"The distribution of the random variable is loaded from the circuit library. The function will be evaluated on the x-values ``[0, ..., 2 ** num_qubits - 1]``. "
97+
]
98+
},
99+
{
100+
"cell_type": "code",
101+
"execution_count": null,
102+
"metadata": {},
103+
"outputs": [],
104+
"source": [
105+
"from qiskit.circuit.library import NormalDistribution\n",
106+
"X = NormalDistribution(num_qubits=3, mu=1, sigma=0.5, bounds=(0, 2))"
107+
]
108+
},
109+
{
110+
"cell_type": "markdown",
111+
"metadata": {},
112+
"source": [
113+
"## Defining the objective function"
114+
]
115+
},
116+
{
117+
"cell_type": "markdown",
118+
"metadata": {},
119+
"source": [
120+
"### Workflow #1\n",
121+
"\n",
122+
"Similar to the oracle compiler: take a Python function and synthesize the circuit automatically."
123+
]
124+
},
125+
{
126+
"cell_type": "code",
127+
"execution_count": null,
128+
"metadata": {},
129+
"outputs": [],
130+
"source": [
131+
"def classical_f(x):\n",
132+
" if x > 1:\n",
133+
" return x ** 2\n",
134+
" return x\n",
135+
"\n",
136+
"\n",
137+
"from qiskit.circuit.library import AmplitudeFunction\n",
138+
"f = AmplitudeFunction(classical_f, domain=(0, 2)) # domain must be the same as the bounds of the probability dist\n",
139+
"post_processing = f.post_processing # c + (d - c) zeta"
140+
]
141+
},
142+
{
143+
"cell_type": "markdown",
144+
"metadata": {},
145+
"source": [
146+
"### Workflow #2\n",
147+
"\n",
148+
"Similar to the `UnivariatePiecewiseLinearObjective`, specify the function and construct the circuit from this information. Includes rescalings."
149+
]
150+
},
151+
{
152+
"cell_type": "code",
153+
"execution_count": null,
154+
"metadata": {},
155+
"outputs": [],
156+
"source": [
157+
"from qiskit.circuit.library import LinearAmplitudeFunction\n",
158+
"f = LinearAmplitudeFunction(num_state_qubits=3, \n",
159+
" slope=[-1, 1],\n",
160+
" offset=[1, 0],\n",
161+
" breakpoints=[0, 1],\n",
162+
" domain=(0, 2))"
163+
]
164+
},
165+
{
166+
"cell_type": "markdown",
167+
"metadata": {},
168+
"source": [
169+
"### Workflow #3\n",
170+
"\n",
171+
"Manual."
172+
]
173+
},
174+
{
175+
"cell_type": "code",
176+
"execution_count": null,
177+
"metadata": {},
178+
"outputs": [],
179+
"source": [
180+
"from qiskit.circuit.library import PiecewiseLinearPauliRotations\n",
181+
"\n",
182+
"slopes = np.array([-1, 1])\n",
183+
"offsets = np.array([1, 0])\n",
184+
"breakpoints = np.array([0, 1])\n",
185+
"domain = (0, 2)\n",
186+
"num_state_qubits = 3\n",
187+
"N = 2 ** num_state_qubits\n",
188+
"\n",
189+
"# apply rescaling to the right domain \n",
190+
"phi_inv = lambda x: (x - domain[0]) / (domain[1] - domain[0]) * N\n",
191+
"breakpoints = phi_inv(breakpoints)\n",
192+
"slopes = (domain[1] - domain[0]) / (N - 1) * slopes\n",
193+
"# offsets remain the same\n",
194+
"\n",
195+
"# apply normalization of the image space\n",
196+
"offsets = (offsets - fmin) / (fmax - fmin)\n",
197+
"slopes = slopes / (fmax - fmin)\n",
198+
"\n",
199+
"# apply taylor \n",
200+
"offsets *= c * np.pi / 2\n",
201+
"slopes *= c * np.pi / 2\n",
202+
"\n",
203+
"f = PiecewiseLinearPauliRotations(num_state_qubits, \n",
204+
" breakpoints=breakpoints,\n",
205+
" slopes=2 * slopes, \n",
206+
" offsets=2 * offsets) "
207+
]
208+
},
209+
{
210+
"cell_type": "markdown",
211+
"metadata": {},
212+
"source": [
213+
"### Conclusion\n",
214+
"\n",
215+
"Option #2 makes sense for now. This means porting most of the `UnivariatePiecewiseLinearObjective` to the circuit library."
216+
]
217+
},
218+
{
219+
"cell_type": "markdown",
220+
"metadata": {},
221+
"source": [
222+
"## Defining the A operator\n",
223+
"\n",
224+
"### Workflow #1\n",
225+
"\n",
226+
"Stack together the function circuit and probability distribution circuit."
227+
]
228+
},
229+
{
230+
"cell_type": "code",
231+
"execution_count": null,
232+
"metadata": {},
233+
"outputs": [],
234+
"source": [
235+
"from qiskit.circuit import QuantumCircuit\n",
236+
"\n",
237+
"A = QuantumCircuit(f.num_qubits)\n",
238+
"A.compose(X, inplace=True)\n",
239+
"A.compose(f, inplace=True)"
240+
]
241+
},
242+
{
243+
"cell_type": "markdown",
244+
"metadata": {},
245+
"source": [
246+
"### Workflow #2\n",
247+
"\n",
248+
"Can introduce a class for that but I don't really think the work it does justifies a class, see rather the section about encapsulating the entire workflow."
249+
]
250+
},
251+
{
252+
"cell_type": "code",
253+
"execution_count": null,
254+
"metadata": {},
255+
"outputs": [],
256+
"source": [
257+
"from qiskit.circuit.library import EstimationProblem # or aqua algorithms\n",
258+
"\n",
259+
"A = EstimationProblem(f, X) # but here f is not the circuit but a function! and we do all the synthesisa"
260+
]
261+
},
262+
{
263+
"cell_type": "markdown",
264+
"metadata": {},
265+
"source": [
266+
"## Run QAE\n",
267+
"\n",
268+
"QAE in the basic form takes the $\\mathcal{A}$ operator and a post processing function."
269+
]
270+
},
271+
{
272+
"cell_type": "code",
273+
"execution_count": null,
274+
"metadata": {},
275+
"outputs": [],
276+
"source": [
277+
"from qiskit import Aer\n",
278+
"from qiskit.aqua.algorithms import AmplitudeEstimation\n",
279+
"\n",
280+
"ae = AmplitudeEstimation(num_eval_qubits=4, state_in=A, post_processing=f.post_processing)\n",
281+
"result = ae.run(Aer.get_backend('qasm_simulator'))"
282+
]
283+
},
284+
{
285+
"cell_type": "markdown",
286+
"metadata": {},
287+
"source": [
288+
"## Encapsulating the workflow\n",
289+
"\n",
290+
"Add a class that is fully equivalent to `UnivariatePiecewiseLineaObjective`? Essentially this means accepting the probabilit"
291+
]
292+
}
293+
],
294+
"metadata": {
295+
"kernelspec": {
296+
"display_name": "Python 3.7.7 64-bit ('py377': conda)",
297+
"language": "python",
298+
"name": "python37764bitpy377condada92b85e600c45a79ff7c5f35e6f13ab"
299+
},
300+
"language_info": {
301+
"codemirror_mode": {
302+
"name": "ipython",
303+
"version": 3
304+
},
305+
"file_extension": ".py",
306+
"mimetype": "text/x-python",
307+
"name": "python",
308+
"nbconvert_exporter": "python",
309+
"pygments_lexer": "ipython3",
310+
"version": "3.7.7"
311+
}
312+
},
313+
"nbformat": 4,
314+
"nbformat_minor": 4
315+
}

0 commit comments

Comments
 (0)