/
dataBase.py
206 lines (198 loc) · 8.4 KB
/
dataBase.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
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
import time
import HumanTime
def choose(n, k):
'Gives the value of n choose k by building Pascals triangle row by row, (much faster than calculating factorials)'
vec = [1]
for _ in range(n):
vec = [
v1 + v2
for i, (v1, v2) in enumerate(zip([0] + vec, vec + [0]))
if i <= k
]
return vec[-1]
def valid(a, b, c, d):
return nonRedundant(a, b, c, d) and relativelyPrime(a, b, c, d)
def apery(a, b, c, d):
'Takes a quad as input and returns the Apery set assuming were working mod the minimum element'
workingMod = min(a,b,c,d)
intList = [0 for _ in range(workingMod)]
p = 0
while any(x == 0 for x in intList[1:]): # while at least one element of the aspery set has not been found
if isAttainable4(a, b, c, d, p): # if p is attainable by <a,b,c,d>
eqClass = p%workingMod
for val in range(1, workingMod): # val will take on every integer value from 1 to workingMod - 1
if eqClass == val and intList[val] == 0: # if the attainable is in val eq class and is the first one found
intList [val] = p # we alter its index in intList and that effectively marks it when revisited by the above line
p += 1
return tuple(sorted(intList)) # not sorting will result in elements being ordered according to equivilent class instead of ascending order
def isAttainable4(a, b, c, d, val):
for i in range(int(val/a) + 1):
for j in range(int(val/b) + 1):
for k in range(int(val/c) + 1):
for l in range(int(val/d) + 1):
if i*a + j*b + k*c + l*d == val:
return True
return False
def relativelyPrime(a, b, c, d):
lst = [a, b, c, d]
bol = False
for i in lst:
for j in lst:
if i != j and relPrimePair(i, j):
bol = True
return bol
def relPrimePair(a, b):
if a < b:
minn = a
else:
minn = b
gcf = 1
for val in range(2, minn):
if a%val == 0 and b%val == 0:
gcf = val
if val == 1:
return True
return False
def nonRedundant(a, b, c, d):
if not isAttainable(a, b, c, d) and not isAttainable(a, b, d, c) and not isAttainable(a, c, d, b) and not isAttainable(b, c, d, a):
return True
def isAttainable(a, b, c, val):
for i in range(int(val/a)):
for j in range(int(val/b)):
for k in range(int(val/c)):
if i*a + j*b + k*c == val:
return True
return False
def progress(ctime, ttime, p):
'Responsible for printing the percentage of data that has been loaded into memoty'
if time.time() > p:
p = time.time() + 1
print(f'{100*ctime/ttime:.2f}%')
return p
from collections.abc import Mapping, Container
from sys import getsizeof
def deep_getsizeof(o, ids):
""" Find the memory footprint of a Python object
This is a recursive function that drills down a Python object graph
like a dictionary holding nested dictionaries with lists of lists
and tuples and sets.
The sys.getsizeof function does a shallow size of only. It counts each
object inside a container as pointer only regardless of how big it
really is.
:param o: the object
:param ids:
:return:
"""
d = deep_getsizeof
if id(o) in ids:
return 0
r = getsizeof(o)
ids.add(id(o))
if isinstance(o, str) or isinstance(0, str):
return r
if isinstance(o, Mapping):
return r + sum(d(k, ids) + d(v, ids) for k, v in o.items())
if isinstance(o, Container):
return r + sum(d(x, ids) for x in o)
return r
def format_bytes(size):
# 2**10 = 1024
power = 2**10
n = 0
power_labels = {0 : '', 1: 'kilo', 2: 'mega', 3: 'giga', 4: 'tera'}
while size > power:
size /= power
n += 1
return size, power_labels[n]+'bytes'
def duplicates(a, b, c, d):
tup = (a,b,c,d)
for i in range(len(tup)):
for j in range(len(tup)):
if i != j and tup[i] == tup[j]:
return True
def main(infile, mem = True, UF = True):
'''This function takes a file generated by quads.py and loads it into memory
Those files (nquad.txt) contain pertinant information about all sets where every element is > 2 and < n+1
The second for loop loads all this information into memory and the while loop alows for an arbitrary amount of quaries to be made by the user
If all four elements share a gcd greater than one, this information will be displayed
If three elements share a gcd greater than one, this information will also be displayed
Otherwise it will display True if symmetry holds or False if the set is asymmetric'''
itime = time.time()
myStr = ''
for char in infile:
if char.isnumeric():
myStr += char
else:
break
first = eval(myStr)
inc = 1
p = time.time()
r = open(infile)
tmp = []
retDict = dict()
lines = 0
tLines = choose(first - 2, 4) * 6 # The total number of lines for nquad.txt if n-2 choose 4 * 6 because there are n-2 choose 4 sets and the text file uses six lines to store each of the four elements with its result on a fifth line and a blank line between itsself and the next set.
for item in r.readlines():
lines += 1
if item != '\n':
tmp.append(item)
else:
retDict[(eval(tmp[0]), eval(tmp[1]), eval(tmp[2]), eval(tmp[3]))] = tmp[4]
#if valid(eval(tmp[0]), eval(tmp[1]), eval(tmp[2]), eval(tmp[3])) and tmp[4] == 'False':
# print(eval(tmp[0]), eval(tmp[1]), eval(tmp[2]), eval(tmp[3]))
tmp = []
p = progress(lines, tLines, p)
tme = HumanTime.TimeAutoShort(time.time() - itime, 2)
if mem:
tup = format_bytes(deep_getsizeof(retDict, set()))
print(f'It took {tme} to load and used {tup[0]:.2f} {tup[1]} of memory')
else:
print(f'It took {tme} to load')
print('Type "done" to terminate your query session"')
r.close()
UI = ''
bol = False
if UF == True:
while type(UI) != str or UI.lower() != 'done':
try:
UI = input(f'\nEnter a comma seperated list of four natural numbers \u2264 {first}:\t')
if UI.lower() == 'done':
break
UI = eval((UI))
if type(UI) == tuple:
if len(UI) == 4:
UI = tuple(sorted(UI))
if duplicates(UI[0], UI[1], UI[2], UI[3]):
print('\n' + 8 * '\t' + 'All elements must be unique')
elif any([x < 0 for x in UI]):
print('\n' + 8 * '\t' + 'All values must be positive')
elif 0 in UI:
print('\n' + 8 * '\t' + 'Sets should not contain 0')
elif any([x in UI for x in [1, 2]]):
print('\n' + 8 * '\t' + 'True')
elif UI in retDict:
ans = retDict[UI]
if 'all' not in ans.lower():
print('\n' + 8 * '\t' + ans + f'\nThe Apery set of <{str(UI)[1:-1]}> is <{str(apery(UI[0],UI[1],UI[2],UI[3]))[1:-1]}>')
else:
print('\n' + 8 * '\t' + retDict[UI])
else:
print('\n' + 8 * '\t' + 'That quad is not in the database')
else:
print('\n' + 8 * '\t' + f'The tuple {UI} does not have four elements')
else:
print('\n' + 8 * '\t' + f'Expected tuple but got {type(UI)}')
except:
print('\n' + 8 * '\t' + 'What you entered could not be recognized, please try again')
print('\n' + 8 * '\t' + 'Have a nice day!\n')
#else:
# for tup in UF:
# print(f'{tup} = {retDict[tup]}')
#main('50quad.txt', [(3,4,5,6), (3,4,5,7), (3,4,5,8), (3,4,5,9), (3,4,5,10), (3,4,5,11), (3,4,5,12), (4,5,6,7), (4,5,6,8), (4,5,6,9), (4,5,6,10), (4,5,6,11), (4,5,6,12), (4,5,6,13)])
main('100quad.txt')
#for val in range(10, 110, 10):
# main(f'{val}quad.txt', True)
#r = ['ladsf', 34134, 93204.2341, 'erw', (';', 'lqkwjer'), {'r' : 4}, {'resdfq', 32948}]
#tup = format_bytes(deep_getsizeof(r, set()))
#print(f'{tup[0]} {tup[1]}')
#print(apery(4,6,9,12))