forked from tiagomsleao/ShorAlgQiskit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTest_classical_after_quantum.py
More file actions
144 lines (109 loc) · 5.26 KB
/
Copy pathTest_classical_after_quantum.py
File metadata and controls
144 lines (109 loc) · 5.26 KB
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
""" This file allows to test the calculations done after creating the quantum circuit
It implements the continued fractions to find a possible r and then:
If r found is odd, tries next approximation of the continued fractions method
If r found is even, tries to get the factors of N and then:
If the factors are found, exits
If the factors are not found, asks user if he wants to continue looking (only if already tried too many times it exits automatically)
"""
""" Imports to Python functions """
import math
import array
import fractions
import numpy as np
import sys
""" Function to apply the continued fractions to find r and the gcd to find the desired factors"""
def get_factors(x_value,t_upper,N,a):
if x_value<=0:
print('x_value is <= 0, there are no continued fractions\n')
return False
print('Running continued fractions for this case\n')
""" Calculate T and x/T """
T = pow(2,t_upper)
x_over_T = x_value/T
""" Cycle in which each iteration corresponds to putting one more term in the
calculation of the Continued Fraction (CF) of x/T """
""" Initialize the first values according to CF rule """
i=0
b = array.array('i')
t = array.array('f')
b.append(math.floor(x_over_T))
t.append(x_over_T - b[i])
while i>=0:
"""From the 2nd iteration onwards, calculate the new terms of the CF based
on the previous terms as the rule suggests"""
if i>0:
b.append( math.floor( 1 / (t[i-1]) ) )
t.append( ( 1 / (t[i-1]) ) - b[i] )
""" Calculate the CF using the known terms """
aux = 0
j=i
while j>0:
aux = 1 / ( b[j] + aux )
j = j-1
aux = aux + b[0]
"""Get the denominator from the value obtained"""
frac = fractions.Fraction(aux).limit_denominator()
den=frac.denominator
print('Approximation number {0} of continued fractions:'.format(i+1))
print("Numerator:{0} \t\t Denominator: {1}\n".format(frac.numerator,frac.denominator))
""" Increment i for next iteration """
i=i+1
if (den%2) == 1:
if i>=15:
print('Returning because have already done too much tries')
return False
print('Odd denominator, will try next iteration of continued fractions\n')
continue
""" If denominator even, try to get factors of N """
""" Get the exponential a^(r/2) """
exponential = 0
if den<1000:
exponential=pow(a , (den/2))
""" Check if the value is too big or not """
if math.isinf(exponential)==1 or exponential>1000000000:
print('Denominator of continued fraction is too big!\n')
aux_out = input('Input number 1 if you want to continue searching, other if you do not: ')
if aux_out != '1':
return False
else:
continue
"""If the value is not to big (infinity), then get the right values and
do the proper gcd()"""
putting_plus = int(exponential + 1)
putting_minus = int(exponential - 1)
one_factor = math.gcd(putting_plus,N)
other_factor = math.gcd(putting_minus,N)
""" Check if the factors found are trivial factors or are the desired
factors """
if one_factor==1 or one_factor==N or other_factor==1 or other_factor==N:
print('Found just trivial factors, not good enough\n')
""" Check if the number has already been found, use i-1 because i was already incremented """
if t[i-1]==0:
print('The continued fractions found exactly x_final/(2^(2n)) , leaving funtion\n')
return False
if i<15:
aux_out = input('Input number 1 if you want to continue searching, other if you do not: ')
if aux_out != '1':
return False
else:
""" Return if already too much tries and numbers are huge """
print('Returning because have already done too many tries\n')
return False
else:
print('The factors of {0} are {1} and {2}\n'.format(N,one_factor,other_factor))
print('Found the desired factors!\n')
return True
""" Main program """
if __name__ == '__main__':
print('Forcing a case of the AP3421 lectures, with N=143, a=5, x_value=1331 and 11 qubits used to get x_value.')
print('Check main in source file to change\n')
""" These numbers can be changed to check the desired case. The values that are here by default is to test
the case of the slide 28 of lecture 10 of the AP3421 course. The fucntion get_dactors does the continued
fractions for ( x_value / ( 2^(number_qubits_used_to_get_x_value) ) )
"""
N = 143
a = 5
number_qubits_used_to_get_x_value = 11
x_value = 1331
# To check the case of slide 27 of lecture 10 of the AP3421 course, just change x_value to 101
d=get_factors(int(x_value),int(number_qubits_used_to_get_x_value),int(N),int(a))