-
Notifications
You must be signed in to change notification settings - Fork 0
/
qsp.py
72 lines (56 loc) · 2.43 KB
/
qsp.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# Copyright (C) 2024 Matthias Deiml, Daniel Peterseim - All rights reserved
import qiskit as qk
import numpy as np
from qiskit_aer import AerSimulator
from block_encoding import BlockEncoding, CPiNot
def qsp(A: BlockEncoding, angles: list) -> BlockEncoding:
x = qk.QuantumRegister(A._embedding_size, name="x")
b = qk.QuantumRegister(1, name="b")
a = qk.AncillaRegister(
max(A._U.num_ancillas, A._CX_dom.num_ancillas(), A._CX_img.num_ancillas()), name="a")
qc = qk.QuantumCircuit(x, b, a, name=A._U.name + "_qsp")
qc.h(b)
backend = AerSimulator()
opt = qk.transpile(A.simplify()._U, backend, optimization_level=3)
for (i, angle) in enumerate(angles):
if i == 0:
# qc.append(A._CX_dom.to_circuit(), x[:] + b[:] + a[:A._CX_dom.num_ancillas()])
qc.x(b)
qc.rz(2 * angle, b)
qc.x(b)
qc.append(A._U, x[:] + a[:A._U.num_ancillas])
qc.append(A._CX_img.to_circuit(), x[:] + b[:] + a[:A._CX_img.num_ancillas()])
continue
qc.rz(2 * angle, b)
if i == len(angles) - 1:
if i % 2 == 0:
qc.append(A._CX_dom.to_circuit().inverse(), x[:] + b[:] + a[:A._CX_dom.num_ancillas()])
qc.append(A._U, x[:] + a[:A._U.num_ancillas])
else:
qc.append(A._CX_img.to_circuit().inverse(), x[:] + b[:] + a[:A._CX_img.num_ancillas()])
qc.append(A._U.inverse(), x[:] + a[:A._U.num_ancillas])
elif i % 2 == 0:
qc.append(opt, x[:] + b[:] + a[:])
else:
qc.append(opt.inverse(), x[:] + b[:] + a[:])
qc.h(b)
if len(angles) % 2 == 0:
return BlockEncoding(
qc,
A._CX_dom.extend_embedding(1, False).logical_and(CPiNot(A._embedding_size + 1, [A._embedding_size])),
A._CX_dom.extend_embedding(1, False).logical_and(CPiNot(A._embedding_size + 1, [A._embedding_size])))
else:
return BlockEncoding(
qc,
A._CX_dom.extend_embedding(1, False).logical_and(CPiNot(A._embedding_size + 1, [A._embedding_size])),
A._CX_img.extend_embedding(1, False).logical_and(CPiNot(A._embedding_size + 1, [A._embedding_size])))
def Wx_to_R(angles):
"""
Convert between Wx and R conventions.
See [3]
"""
d = len(angles)-1
res = np.zeros(d)
res[0] = angles[0] + angles[-1] + (d - 1) * np.pi/2
res[1:] = angles[1:d] - np.pi/2
return res