parent
2f7b0e518f
commit
67b1e61d8c
@ -0,0 +1,298 @@
|
|||||||
|
from pyqpanda import *
|
||||||
|
import math
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
|
def MAJ(a, b, c):
|
||||||
|
circ = QCircuit()
|
||||||
|
circ.insert(CNOT(c, b))
|
||||||
|
circ.insert(CNOT(c, a))
|
||||||
|
circ.insert(Toffoli(a, b, c))
|
||||||
|
return circ
|
||||||
|
|
||||||
|
|
||||||
|
def UMA(a, b, c):
|
||||||
|
circ = QCircuit()
|
||||||
|
circ.insert(Toffoli(a, b, c))
|
||||||
|
circ.insert(CNOT(c, a))
|
||||||
|
circ.insert(CNOT(a, b))
|
||||||
|
return circ
|
||||||
|
|
||||||
|
|
||||||
|
def MAJ2(a, b, c):
|
||||||
|
lena = len(a)
|
||||||
|
lenb = len(b)
|
||||||
|
if a == 0:
|
||||||
|
raise RuntimeError("Empty List")
|
||||||
|
if not lena == lenb:
|
||||||
|
raise RuntimeError("Length error")
|
||||||
|
|
||||||
|
circ = QCircuit()
|
||||||
|
circ.insert(MAJ(c, a[0], b[0]))
|
||||||
|
for i in range(1, lena):
|
||||||
|
circ.insert(MAJ(b[i-1], a[i], b[i]))
|
||||||
|
return circ
|
||||||
|
|
||||||
|
|
||||||
|
def Adder(a, b, c):
|
||||||
|
lena = len(a)
|
||||||
|
lenb = len(b)
|
||||||
|
if a == 0:
|
||||||
|
raise RuntimeError("Empty List")
|
||||||
|
if not lena == lenb:
|
||||||
|
raise RuntimeError("Length error")
|
||||||
|
|
||||||
|
circ = QCircuit()
|
||||||
|
circ.insert(MAJ(c, a[0], b[0]))
|
||||||
|
|
||||||
|
for i in range(1, lena):
|
||||||
|
circ.insert(MAJ(b[i-1], a[i], b[i]))
|
||||||
|
|
||||||
|
for i in range(lena-1, 0, -1):
|
||||||
|
circ.insert(MAJ(b[i-1], a[i], b[i]))
|
||||||
|
|
||||||
|
circ.insert(UMA(c, a[0], b[0]))
|
||||||
|
return circ
|
||||||
|
|
||||||
|
|
||||||
|
def isCarry(a, b, c, carry):
|
||||||
|
circ = QCircuit()
|
||||||
|
circ.insert(MAJ2(a, b, c))
|
||||||
|
circ.insert(CNOT(b[-1], carry))
|
||||||
|
circ.insert(MAJ2(a, b, c).dagger())
|
||||||
|
return circ
|
||||||
|
|
||||||
|
|
||||||
|
def bindData(qlist, data):
|
||||||
|
i = 0
|
||||||
|
circ = QCircuit()
|
||||||
|
while data >= 1:
|
||||||
|
if data & 1 == 1:
|
||||||
|
circ.insert(X(qlist[i]))
|
||||||
|
data >>= 1
|
||||||
|
i += 1
|
||||||
|
return circ
|
||||||
|
|
||||||
|
|
||||||
|
def constModAdd(qa, C, M, qb, qs1):
|
||||||
|
circ = QCircuit()
|
||||||
|
q_num = len(qa)
|
||||||
|
tmp_value = (1 << q_num)-M+C
|
||||||
|
|
||||||
|
circ.insert(bindData(qb, tmp_value))\
|
||||||
|
.insert(isCarry(qa, qb, qs1[1], qs1[0]))\
|
||||||
|
.insert(bindData(qb, tmp_value))
|
||||||
|
|
||||||
|
tmp_circ1 = QCircuit()
|
||||||
|
|
||||||
|
tmp_circ1.insert(bindData(qb, tmp_value))
|
||||||
|
tmp_circ1.insert(Adder(qa, qb, qs1[1]))
|
||||||
|
tmp_circ1.insert(bindData(qb, tmp_value))
|
||||||
|
tmp_circ1 = tmp_circ1.control([qs1[0]])
|
||||||
|
|
||||||
|
circ.insert(tmp_circ1)
|
||||||
|
circ.insert(X(qs1[0]))
|
||||||
|
|
||||||
|
tmp_circ2 = QCircuit()
|
||||||
|
tmp_circ2.insert(bindData(qb, C))
|
||||||
|
tmp_circ2.insert(Adder(qa, qb, qs1[1]))
|
||||||
|
tmp_circ2.insert(bindData(qb, C))
|
||||||
|
tmp_circ2 = tmp_circ2.control([qs1[0]])
|
||||||
|
|
||||||
|
circ.insert(tmp_circ2)
|
||||||
|
circ.insert(X(qs1[0]))
|
||||||
|
|
||||||
|
tmp_value = (1 << q_num)-C
|
||||||
|
|
||||||
|
circ.insert(bindData(qb, tmp_value))\
|
||||||
|
.insert(isCarry(qa, qb, qs1[1], qs1[0]))\
|
||||||
|
.insert(bindData(qb, tmp_value))\
|
||||||
|
.insert(X(qs1[0]))
|
||||||
|
|
||||||
|
return circ
|
||||||
|
|
||||||
|
|
||||||
|
def constModMul(qa, const_num, M, qs1, qs2, qs3):
|
||||||
|
circ = QCircuit()
|
||||||
|
qnum = len(qa)
|
||||||
|
|
||||||
|
for i in range(0, qnum):
|
||||||
|
tmp_circ = QCircuit()
|
||||||
|
tmp = const_num * pow(2, i) % M
|
||||||
|
tmp_circ.insert(constModAdd(qs1, tmp, M, qs2, qs3))
|
||||||
|
tmp_circ = tmp_circ.control([qa[i]])
|
||||||
|
circ.insert(tmp_circ)
|
||||||
|
|
||||||
|
for i in range(0, qnum):
|
||||||
|
circ.insert(CNOT(qa[i], qs1[i]))\
|
||||||
|
.insert(CNOT(qs1[i], qa[i]))\
|
||||||
|
.insert(CNOT(qa[i], qs1[i]))
|
||||||
|
|
||||||
|
Crev = modReverse(const_num, M)
|
||||||
|
|
||||||
|
tmp_circ1 = QCircuit()
|
||||||
|
tmp_circ2 = QCircuit()
|
||||||
|
|
||||||
|
for i in range(0, qnum):
|
||||||
|
tmp = Crev * pow(2, i) % M
|
||||||
|
tmp_circ1 = QCircuit()
|
||||||
|
tmp_circ1.insert(constModAdd(qs1, tmp, M, qs2, qs3))
|
||||||
|
tmp_circ1 = tmp_circ1.control([qa[i]])
|
||||||
|
tmp_circ2.insert(tmp_circ1)
|
||||||
|
|
||||||
|
circ.insert(tmp_circ2.dagger())
|
||||||
|
|
||||||
|
return circ
|
||||||
|
|
||||||
|
|
||||||
|
def constModExp(qa, qb, base, M, qs1, qs2, qs3):
|
||||||
|
circ = QCircuit()
|
||||||
|
qnum = len(qa)
|
||||||
|
tmp = base
|
||||||
|
|
||||||
|
for i in range(0, qnum):
|
||||||
|
circ.insert(constModMul(qb, tmp, M, qs1, qs2, qs3).control([qa[i]]))
|
||||||
|
tmp = tmp * tmp % M
|
||||||
|
|
||||||
|
return circ
|
||||||
|
|
||||||
|
|
||||||
|
def qft(qlist):
|
||||||
|
circ = QCircuit()
|
||||||
|
qnum = len(qlist)
|
||||||
|
for i in range(0, qnum):
|
||||||
|
circ.insert(H(qlist[qnum-1-i]))
|
||||||
|
for j in range(i+1, qnum):
|
||||||
|
circ.insert(
|
||||||
|
CR(qlist[qnum-1-j], qlist[qnum-1-i], math.pi/(1 << (j-i))))
|
||||||
|
|
||||||
|
for i in range(0, qnum//2):
|
||||||
|
circ.insert(CNOT(qlist[i], qlist[qnum - 1 - i]))
|
||||||
|
circ.insert(CNOT(qlist[qnum - 1 - i], qlist[i]))
|
||||||
|
circ.insert(CNOT(qlist[i], qlist[qnum - 1 - i]))
|
||||||
|
|
||||||
|
return circ
|
||||||
|
|
||||||
|
|
||||||
|
def gcd(m, n):
|
||||||
|
if not n:
|
||||||
|
return m
|
||||||
|
else:
|
||||||
|
return gcd(n, m % n)
|
||||||
|
|
||||||
|
|
||||||
|
def modReverse(c, m):
|
||||||
|
if (c == 0):
|
||||||
|
raise RecursionError('c is zero!')
|
||||||
|
|
||||||
|
if (c == 1):
|
||||||
|
return 1
|
||||||
|
|
||||||
|
m1 = m
|
||||||
|
quotient = []
|
||||||
|
quo = m // c
|
||||||
|
remainder = m % c
|
||||||
|
|
||||||
|
quotient.append(quo)
|
||||||
|
|
||||||
|
while (remainder != 1):
|
||||||
|
m = c
|
||||||
|
c = remainder
|
||||||
|
quo = m // c
|
||||||
|
remainder = m % c
|
||||||
|
quotient.append(quo)
|
||||||
|
|
||||||
|
if (len(quotient) == 1):
|
||||||
|
return m - quo
|
||||||
|
|
||||||
|
if (len(quotient) == 2):
|
||||||
|
return 1 + quotient[0] * quotient[1]
|
||||||
|
|
||||||
|
rev1 = 1
|
||||||
|
rev2 = quotient[-1]
|
||||||
|
reverse_list = quotient[0:-1]
|
||||||
|
reverse_list.reverse()
|
||||||
|
for i in reverse_list:
|
||||||
|
rev1 = rev1 + rev2 * i
|
||||||
|
temp = rev1
|
||||||
|
rev1 = rev2
|
||||||
|
rev2 = temp
|
||||||
|
|
||||||
|
if ((len(quotient) % 2) == 0):
|
||||||
|
return rev2
|
||||||
|
|
||||||
|
return m1 - rev2
|
||||||
|
|
||||||
|
|
||||||
|
def plotBar(xdata, ydata):
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
fig.set_size_inches(6, 6)
|
||||||
|
fig.set_dpi(100)
|
||||||
|
|
||||||
|
rects = ax.bar(xdata, ydata, color='b')
|
||||||
|
|
||||||
|
for rect in rects:
|
||||||
|
height = rect.get_height()
|
||||||
|
plt.text(rect.get_x() + rect.get_width() / 2, height,
|
||||||
|
str(height), ha="center", va="bottom")
|
||||||
|
|
||||||
|
plt.title("Origin Q", loc='right', alpha=0.5)
|
||||||
|
plt.ylabel('Times')
|
||||||
|
plt.xlabel('States')
|
||||||
|
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
def reorganizeData(measure_qubits, quick_meausre_result):
|
||||||
|
xdata = []
|
||||||
|
ydata = []
|
||||||
|
|
||||||
|
for i in quick_meausre_result:
|
||||||
|
xdata.append(i)
|
||||||
|
ydata.append(quick_meausre_result[i])
|
||||||
|
|
||||||
|
return xdata, ydata
|
||||||
|
|
||||||
|
|
||||||
|
def shorAlg(base, M):
|
||||||
|
if ((base < 2) or (base > M - 1)):
|
||||||
|
raise('Invalid base!')
|
||||||
|
|
||||||
|
if (gcd(base, M) != 1):
|
||||||
|
raise('Invalid base! base and M must be mutually prime')
|
||||||
|
|
||||||
|
binary_len = 0
|
||||||
|
while M >> binary_len != 0:
|
||||||
|
binary_len = binary_len + 1
|
||||||
|
|
||||||
|
machine = init_quantum_machine(QMachineType.CPU_SINGLE_THREAD)
|
||||||
|
|
||||||
|
qa = machine.qAlloc_many(binary_len*2)
|
||||||
|
qb = machine.qAlloc_many(binary_len)
|
||||||
|
|
||||||
|
qs1 = machine.qAlloc_many(binary_len)
|
||||||
|
qs2 = machine.qAlloc_many(binary_len)
|
||||||
|
qs3 = machine.qAlloc_many(2)
|
||||||
|
|
||||||
|
prog = QProg()
|
||||||
|
|
||||||
|
prog.insert(X(qb[0]))
|
||||||
|
prog.insert(single_gate_apply_to_all(H, qa))
|
||||||
|
prog.insert(constModExp(qa, qb, base, M, qs1, qs2, qs3))
|
||||||
|
prog.insert(qft(qa).dagger())
|
||||||
|
|
||||||
|
directly_run(prog)
|
||||||
|
result = quick_measure(qa, 100)
|
||||||
|
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
xdata, ydata = reorganizeData(qa, result)
|
||||||
|
plotBar(xdata, ydata)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
base = 7
|
||||||
|
N = 15
|
||||||
|
shorAlg(base, N)
|
Loading…
Reference in new issue