├── README.md ├── HW1 ├── hw1.pdf ├── HW1_Chengqi Huang.pdf └── HW1_practice_solutions.pdf ├── HW2 ├── HW2.pdf └── hw2 DC-1.pdf ├── HW3 ├── HW3.pdf └── HW3_Chengqi Huang.pdf ├── HW4 ├── HW4.pdf └── HW4_Chengqi Huang.pdf ├── HW5 ├── HW5.pdf └── HW5_Chengqi Huang.pdf ├── HW6 ├── hw6.pdf └── HW6_Chengqi Huang.pdf ├── Project1 ├── Project1.pdf ├── __pycache__ │ └── GA_ProjectUtils.cpython-37.pyc ├── defaultItems.txt ├── knapsack.py └── GA_ProjectUtils.py ├── Project2 ├── Project2.pdf ├── __pycache__ │ ├── findX.cpython-37.pyc │ └── GA_ProjectUtils.cpython-37.pyc ├── tester.py ├── findX.py └── GA_ProjectUtils.py └── Project3 ├── Project3.pdf ├── soln_small.txt ├── __pycache__ └── GA_ProjectUtils.cpython-37.pyc ├── small.txt ├── mst.py ├── soln_medium.txt ├── GA_ProjectUtils.py └── medium.txt /README.md: -------------------------------------------------------------------------------- 1 | # CS6515-Graduate-Algorithms 2 | All Coding project & HW Assignments for CS6515 GA 3 | -------------------------------------------------------------------------------- /HW1/hw1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/HW1/hw1.pdf -------------------------------------------------------------------------------- /HW2/HW2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/HW2/HW2.pdf -------------------------------------------------------------------------------- /HW3/HW3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/HW3/HW3.pdf -------------------------------------------------------------------------------- /HW4/HW4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/HW4/HW4.pdf -------------------------------------------------------------------------------- /HW5/HW5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/HW5/HW5.pdf -------------------------------------------------------------------------------- /HW6/hw6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/HW6/hw6.pdf -------------------------------------------------------------------------------- /HW2/hw2 DC-1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/HW2/hw2 DC-1.pdf -------------------------------------------------------------------------------- /Project1/Project1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/Project1/Project1.pdf -------------------------------------------------------------------------------- /Project2/Project2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/Project2/Project2.pdf -------------------------------------------------------------------------------- /Project3/Project3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/Project3/Project3.pdf -------------------------------------------------------------------------------- /Project3/soln_small.txt: -------------------------------------------------------------------------------- 1 | 2 3 0.17 2 | 0 7 0.16 3 | 5 7 0.28 4 | 2 6 0.4 5 | 4 5 0.35 6 | 0 2 0.26 7 | 1 7 0.19 8 | -------------------------------------------------------------------------------- /HW1/HW1_Chengqi Huang.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/HW1/HW1_Chengqi Huang.pdf -------------------------------------------------------------------------------- /HW3/HW3_Chengqi Huang.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/HW3/HW3_Chengqi Huang.pdf -------------------------------------------------------------------------------- /HW4/HW4_Chengqi Huang.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/HW4/HW4_Chengqi Huang.pdf -------------------------------------------------------------------------------- /HW5/HW5_Chengqi Huang.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/HW5/HW5_Chengqi Huang.pdf -------------------------------------------------------------------------------- /HW6/HW6_Chengqi Huang.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/HW6/HW6_Chengqi Huang.pdf -------------------------------------------------------------------------------- /HW1/HW1_practice_solutions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/HW1/HW1_practice_solutions.pdf -------------------------------------------------------------------------------- /Project2/__pycache__/findX.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/Project2/__pycache__/findX.cpython-37.pyc -------------------------------------------------------------------------------- /Project1/__pycache__/GA_ProjectUtils.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/Project1/__pycache__/GA_ProjectUtils.cpython-37.pyc -------------------------------------------------------------------------------- /Project2/__pycache__/GA_ProjectUtils.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/Project2/__pycache__/GA_ProjectUtils.cpython-37.pyc -------------------------------------------------------------------------------- /Project3/__pycache__/GA_ProjectUtils.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHuang1997/CS6515-Graduate-Algorithms/HEAD/Project3/__pycache__/GA_ProjectUtils.cpython-37.pyc -------------------------------------------------------------------------------- /Project3/small.txt: -------------------------------------------------------------------------------- 1 | 8 2 | 16 3 | 4 5 0.35 4 | 4 7 0.37 5 | 5 7 0.28 6 | 0 7 0.16 7 | 1 5 0.32 8 | 0 4 0.38 9 | 2 3 0.17 10 | 1 7 0.19 11 | 0 2 0.26 12 | 1 2 0.36 13 | 1 3 0.29 14 | 2 7 0.34 15 | 6 2 0.40 16 | 3 6 0.52 17 | 6 0 0.58 18 | 6 4 0.93 19 | -------------------------------------------------------------------------------- /Project1/defaultItems.txt: -------------------------------------------------------------------------------- 1 | "zero", 100, 465 2 | "one", 85, 400 3 | "two", 55, 255 4 | "three", 45, 350 5 | "four", 130, 650 6 | "five", 190, 1000 7 | "six", 100, 455 8 | "seven", 25, 100 9 | "eight", 190, 1200 10 | "nine", 65, 320 11 | "ten", 100, 750 12 | "eleven", 45, 50 13 | "twelve", 65, 550 14 | "thirteen", 50, 100 15 | "fourteen", 70, 600 16 | "fifteen", 40, 255 -------------------------------------------------------------------------------- /Project2/tester.py: -------------------------------------------------------------------------------- 1 | import GA_ProjectUtils as util 2 | from findX import findXinA 3 | from random import randint 4 | 5 | def test(seed=None, size=None, value_override=None): 6 | findX = util.findX() 7 | 8 | if seed is None: 9 | seed = randint(1, 9999999999) 10 | 11 | if size is None: 12 | x = findX.start(seed, 10, 100000) 13 | size = findX._findX__n 14 | else: 15 | x = findX.start(seed, size, size) 16 | 17 | if value_override is not None: 18 | x = value_override 19 | 20 | try: 21 | correct_index = findX._findX__A.index(x) 22 | except ValueError: 23 | correct_index = None 24 | 25 | print(f'Seed: {seed}, Size: {size}, Index: {correct_index}, X: {x}') 26 | 27 | index, _ = findXinA(x, findX) 28 | 29 | assert index == correct_index, f"Incorrect index reported: {index} != {correct_index}" 30 | 31 | test(seed=42, size=32, value_override=-1) 32 | test(seed=42, size=32, value_override=20) 33 | test(seed=42, size=32, value_override=65) 34 | 35 | for i in range(16): 36 | test(size=i + 1) 37 | 38 | for i in range(1000): 39 | test(seed=i + 1) 40 | 41 | for _ in range(1000): 42 | test() -------------------------------------------------------------------------------- /Project2/findX.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | 5 | findX.py - Intro to Graduate Algorithms 6 | 7 | Solve the findX in an Infinite array problem using a Divide & Conquer method 8 | Your runtime must be O(log n) 9 | 10 | The array of values is indexed A[1..n] inclusive 11 | 12 | Your code MUST NOT directly reference any variables in findX. The following methods are available: 13 | 14 | findX.start(seed) -- returns the value (x) to search for within the array 15 | findX.lookup(i) -- returns A[i] or None if i>n 16 | findX.lookups() -- returns the number of calls to lookup 17 | 18 | """ 19 | #argparse allows the parsing of command line arguments 20 | import argparse 21 | #utility functions for cs 6515 projects 22 | import GA_ProjectUtils as util 23 | 24 | 25 | def findXinA(x, findX): 26 | 27 | #TODO Your Code Begins Here, DO NOT MODIFY ANY CODE ABOVE THIS LINE 28 | high_index = 1 29 | a_high = findX.lookup(high_index) 30 | while(a_high < x and a_high is not None): 31 | high_index = high_index * 2 32 | a_high = findX.lookup(high_index) 33 | if a_high is None: 34 | break 35 | low_index = high_index//2 36 | if high_index == 1: 37 | value = findX.lookup(1) 38 | if value is None: 39 | theIndex = None 40 | elif value == x: 41 | theIndex = 1 42 | else: 43 | theIndex = None 44 | 45 | else: 46 | def binary_search(low, high, v): 47 | if low <= high: 48 | mid = (high + low)//2 49 | a_mid = findX.lookup(mid) 50 | if a_mid is None: 51 | return binary_search(low, mid-1, v) 52 | else: 53 | if a_mid == v: 54 | return mid 55 | elif a_mid > x: 56 | return binary_search(low, mid-1, v) 57 | else: 58 | return binary_search(mid+1, high, v) 59 | else: 60 | return None 61 | 62 | 63 | theIndex = binary_search(low_index, high_index, x) 64 | 65 | #TODOne Your code Ends here, DO NOT MOIDFY ANYTHING BELOW THIS LINE 66 | 67 | numLookups = findX.lookups() 68 | 69 | return theIndex, numLookups 70 | 71 | 72 | def main(): 73 | """ 74 | main - DO NOT CHANGE ANYTHING BELOW THIS LINE 75 | """ 76 | # DO NOT REMOVE ANY ARGUMENTS FROM THE ARGPARSER BELOW 77 | parser = argparse.ArgumentParser(description='Find X Coding Quiz') 78 | 79 | #args for autograder, DO NOT MODIFY ANY OF THESE 80 | parser.add_argument('-a', '--autograde', help='Autograder-called (2) or not (1=default)', type=int, choices=[1, 2], default=1, dest='autograde') 81 | parser.add_argument('-s', '--seed', help='seed value for random function', type=int, default=123456, dest='seed') 82 | parser.add_argument('-l', '--nLower', help='lower bound for N', type=int, default=10, dest='nLower') 83 | parser.add_argument('-u', '--nUpper', help='upper bound for N', type=int, default=100000, dest='nUpper') 84 | 85 | args = parser.parse_args() 86 | 87 | #DO NOT MODIFY ANY OF THE FOLLOWING CODE 88 | 89 | findX = util.findX() 90 | x = findX.start(args.seed, args.nLower, args.nUpper) 91 | index, calls = findXinA(x, findX) 92 | print('findX result: x found at index {} in {} calls'.format(index, calls)) 93 | 94 | return 95 | 96 | if __name__ == '__main__': 97 | main() 98 | -------------------------------------------------------------------------------- /Project3/mst.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | mst.py Intro to Graduate Algorithms 4 | 5 | You will implement Kruskal's algorithm for finding a Minimum Spanning Tree. 6 | You will also implement the union-find data structure using path compression 7 | See [DPV] Sections 5.1.3 & 5.1.4 for details 8 | """ 9 | 10 | import argparse 11 | import GA_ProjectUtils as util 12 | 13 | class unionFind: 14 | def __init__(self, n): 15 | self.pi = [i for i in range(n)] 16 | self.rank = [0 for i in range(n)] 17 | 18 | def areConnected(self, p, q): 19 | """ 20 | return true if 2 nodes are connected or false if they are 21 | not by comparing their roots 22 | """ 23 | #TODO Your Code Goes Here 24 | if self.find(p) == self.find(q): 25 | return True 26 | else: 27 | return False 28 | 29 | def union(self, u, v): 30 | """ 31 | build union of 2 components 32 | Be sure to maintain self.rank as needed to 33 | make sure your algorithm is optimal. 34 | """ 35 | #TODO Your Code Goes Here (remove pass) 36 | u_root = self.find(u) 37 | v_root = self.find(v) 38 | if u_root == v_root: 39 | return 0 40 | if self.rank[u_root] < self.rank[v_root]: 41 | u_root,v_root = v_root,u_root 42 | 43 | self.pi[v_root] = u_root 44 | if self.rank[u_root] == self.rank[v_root]: 45 | self.rank[u_root] += 1 46 | return 0 47 | 48 | def find(self, p): 49 | """ 50 | find the root of the set containing the 51 | passed vertex p - Must use path compression! 52 | """ 53 | #TODO Your Code Goes Here 54 | if self.pi[p] != p: 55 | self.pi[p] = self.find(self.pi[p]) 56 | return self.pi[p] 57 | else: 58 | return p 59 | 60 | 61 | def kruskal(G): 62 | """ 63 | Kruskal algorithm 64 | G : graph object 65 | """ 66 | #Build unionFind Object 67 | uf = unionFind(G.numVerts) 68 | #Make MST as a set 69 | MST = set() 70 | #Get list of edges sorted by increasing weight 71 | sortedEdges = G.sortedEdges() 72 | #Go through edges in sorted order smallest, to largest 73 | for e in sortedEdges: 74 | #TODO Your Code Goes Here (remove comments if you wish) 75 | u, v = e 76 | 77 | if uf.areConnected(u, v) is True: 78 | continue 79 | 80 | uf.union(u,v) 81 | 82 | # use the following line to add an edge to the MST. 83 | # You may change it's indentation/scope within the for loop 84 | MST.add(util.buildMSTEdge(G,e)) 85 | 86 | #TODone - do not modify any other code below this line 87 | return MST, uf 88 | 89 | def main(): 90 | """ 91 | main 92 | """ 93 | #DO NOT REMOVE ANY ARGUMENTS FROM THE ARGPARSER BELOW 94 | parser = argparse.ArgumentParser(description='Minimum Spanning Tree Coding Quiz') 95 | #use this flag, or change the default here to use different graph description files 96 | parser.add_argument('-g', '--graphFile', help='File holding graph data in specified format', default='small.txt', dest='graphDataFileName') 97 | #use this flag to print the graph and resulting MST 98 | parser.add_argument('-p', '--print', help='Print the MSTs?', default=False, dest='printMST') 99 | 100 | #args for autograder, DO NOT MODIFY ANY OF THESE 101 | parser.add_argument('-a', '--autograde', help='Autograder-called (2) or not (1=default)', type=int, choices=[1, 2], default=1, dest='autograde') 102 | args = parser.parse_args() 103 | 104 | #DO NOT MODIFY ANY OF THE FOLLOWING CODE 105 | #Build graph object 106 | graph = util.build_MSTBaseGraph(args) 107 | #you may print the configuration of the graph -- only effective for graphs with up to 10 vertex 108 | #graph.printMe() 109 | 110 | #Calculate kruskal's alg for MST 111 | MST_Kruskal, uf = kruskal(graph) 112 | 113 | #verify against provided prim's algorithm results 114 | util.verify_MSTKruskalResults(args, MST_Kruskal, args.printMST) 115 | 116 | if __name__ == '__main__': 117 | main() -------------------------------------------------------------------------------- /Project3/soln_medium.txt: -------------------------------------------------------------------------------- 1 | 36 41 0.05329 2 | 53 145 0.06902 3 | 87 130 0.03684 4 | 209 211 0.01269 5 | 136 234 0.03185 6 | 50 185 0.05942 7 | 61 87 0.05163 8 | 119 145 0.05361 9 | 176 191 0.02089 10 | 23 58 0.07072 11 | 11 82 0.03687 12 | 118 124 0.063 13 | 177 186 0.03537 14 | 74 215 0.04643 15 | 171 238 0.05664 16 | 135 141 0.06693 17 | 10 175 0.07429 18 | 29 224 0.03477 19 | 56 120 0.05027 20 | 175 246 0.03569 21 | 103 174 0.03708 22 | 99 162 0.06455 23 | 106 193 0.02119 24 | 61 111 0.06739 25 | 83 232 0.06812 26 | 60 199 0.04868 27 | 68 176 0.04396 28 | 35 94 0.06254 29 | 30 179 0.0657 30 | 163 211 0.01708 31 | 121 182 0.03939 32 | 124 172 0.04713 33 | 177 189 0.03512 34 | 0 225 0.02383 35 | 165 180 0.01756 36 | 116 164 0.0406 37 | 203 249 0.04148 38 | 91 137 0.01061 39 | 78 239 0.02065 40 | 9 23 0.03526 41 | 4 78 0.02559 42 | 76 95 0.0737 43 | 114 222 0.0206 44 | 27 240 0.06581 45 | 58 68 0.04795 46 | 45 83 0.02906 47 | 30 244 0.01475 48 | 34 73 0.01812 49 | 25 60 0.03405 50 | 148 157 0.01712 51 | 109 215 0.06179 52 | 144 248 0.01527 53 | 228 241 0.01473 54 | 21 233 0.04409 55 | 66 206 0.05154 56 | 1 107 0.07484 57 | 113 223 0.04665 58 | 39 66 0.0559 59 | 49 97 0.03121 60 | 122 205 0.00647 61 | 4 55 0.06425 62 | 131 143 0.05854 63 | 53 120 0.02782 64 | 21 71 0.03782 65 | 72 189 0.03706 66 | 94 141 0.0807 67 | 59 97 0.06442 68 | 11 152 0.0414 69 | 156 205 0.05088 70 | 89 194 0.0511 71 | 69 107 0.0564 72 | 210 219 0.03728 73 | 77 138 0.07171 74 | 96 199 0.01569 75 | 112 159 0.04347 76 | 169 186 0.05624 77 | 92 235 0.0604 78 | 36 88 0.01841 79 | 158 223 0.05291 80 | 109 137 0.05083 81 | 132 235 0.05508 82 | 48 232 0.02109 83 | 130 194 0.05825 84 | 18 86 0.02813 85 | 37 76 0.02674 86 | 70 79 0.01576 87 | 138 240 0.02076 88 | 44 49 0.02107 89 | 52 187 0.03447 90 | 91 218 0.04088 91 | 151 208 0.00391 92 | 50 59 0.04226 93 | 44 204 0.01774 94 | 70 179 0.06528 95 | 38 126 0.00845 96 | 55 112 0.0459 97 | 113 198 0.05009 98 | 157 181 0.05473 99 | 6 129 0.05363 100 | 52 208 0.03135 101 | 2 86 0.0598 102 | 207 212 0.05667 103 | 17 170 0.07756 104 | 155 213 0.01559 105 | 101 139 0.03983 106 | 37 153 0.03846 107 | 142 213 0.03433 108 | 23 33 0.06032 109 | 84 174 0.0277 110 | 40 164 0.03395 111 | 16 117 0.05134 112 | 57 197 0.02583 113 | 6 236 0.05556 114 | 32 187 0.04594 115 | 89 127 0.10682 116 | 19 70 0.06872 117 | 154 238 0.02365 118 | 150 220 0.04158 119 | 128 239 0.01726 120 | 42 135 0.05008 121 | 161 186 0.06124 122 | 91 146 0.02723 123 | 41 182 0.03878 124 | 150 189 0.06046 125 | 207 221 0.02902 126 | 48 216 0.07531 127 | 171 235 0.03106 128 | 154 245 0.04011 129 | 148 230 0.04043 130 | 185 248 0.02896 131 | 10 123 0.00886 132 | 15 211 0.04 133 | 8 143 0.07437 134 | 5 102 0.03834 135 | 65 184 0.0479 136 | 110 214 0.0292 137 | 29 218 0.02524 138 | 40 190 0.03649 139 | 136 159 0.0231 140 | 134 227 0.03986 141 | 62 233 0.03192 142 | 90 173 0.06973 143 | 93 160 0.0436 144 | 67 217 0.04501 145 | 71 188 0.03894 146 | 49 225 0.03314 147 | 1 72 0.06506 148 | 9 195 0.04585 149 | 21 27 0.01873 150 | 129 166 0.03392 151 | 140 147 0.04712 152 | 93 231 0.03594 153 | 156 214 0.03435 154 | 69 173 0.05282 155 | 40 220 0.0315 156 | 17 81 0.05763 157 | 77 102 0.02737 158 | 153 241 0.04247 159 | 101 196 0.03115 160 | 200 203 0.05651 161 | 105 106 0.01034 162 | 28 242 0.02503 163 | 108 196 0.03132 164 | 64 137 0.03977 165 | 63 199 0.01821 166 | 3 153 0.04799 167 | 42 181 0.06506 168 | 54 140 0.02922 169 | 14 133 0.06649 170 | 170 223 0.03653 171 | 156 219 0.00745 172 | 155 180 0.03246 173 | 2 51 0.05083 174 | 22 56 0.01508 175 | 124 155 0.01487 176 | 202 204 0.04207 177 | 6 16 0.04529 178 | 25 111 0.05309 179 | 17 229 0.06676 180 | 20 116 0.02095 181 | 190 247 0.0668 182 | 19 174 0.01925 183 | 65 188 0.03552 184 | 80 225 0.05577 185 | 87 234 0.08302 186 | 171 213 0.06758 187 | 30 212 0.03314 188 | 43 207 0.02708 189 | 47 218 0.02914 190 | 12 35 0.06079 191 | 148 184 0.03398 192 | 201 232 0.03557 193 | 168 187 0.0408 194 | 103 192 0.04287 195 | 81 134 0.04508 196 | 158 249 0.05734 197 | 11 246 0.06678 198 | 7 157 0.00516 199 | 103 243 0.05731 200 | 121 170 0.03464 201 | 176 202 0.04299 202 | 119 134 0.04953 203 | 8 152 0.00702 204 | 24 149 0.02915 205 | 52 226 0.02384 206 | 7 125 0.02442 207 | 104 248 0.0664 208 | 207 210 0.03158 209 | 86 141 0.0564 210 | 99 147 0.03171 211 | 16 147 0.07171 212 | 5 26 0.03351 213 | 83 217 0.03695 214 | 28 198 0.00775 215 | 13 100 0.0256 216 | 12 198 0.05807 217 | 13 133 0.06257 218 | 19 100 0.06397 219 | 82 85 0.04344 220 | 37 115 0.01398 221 | 24 209 0.02802 222 | 72 203 0.0347 223 | 46 169 0.06854 224 | 122 139 0.01217 225 | 75 116 0.02706 226 | 118 197 0.06902 227 | 102 226 0.07775 228 | 31 241 0.07871 229 | 42 108 0.06664 230 | 168 231 0.00268 231 | 57 184 0.03368 232 | 58 114 0.01947 233 | 167 224 0.07521 234 | 22 34 0.03658 235 | 75 89 0.03394 236 | 104 201 0.02597 237 | 38 215 0.0529 238 | 63 237 0.04962 239 | 39 149 0.05382 240 | 160 191 0.0541 241 | 178 236 0.02867 242 | 183 215 0.03017 243 | 98 236 0.04433 244 | 146 227 0.0456 245 | 3 67 0.09725 246 | 163 222 0.05489 247 | 131 193 0.01012 248 | 133 166 0.06778 249 | 8 244 0.02711 250 | -------------------------------------------------------------------------------- /Project1/knapsack.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | 5 | knapsack.py - CS6515, Intro to Graduate Algorithms 6 | 7 | Implement a Dynamic Programming Solution to the knapsack problem. The program will be given a 8 | dictionary of items and an overall weight limit. It should select the combination of items 9 | which achieves the highest value without exceeding the weight limit. 10 | 11 | NOTE: Each item may be selected at most one time (non-repeating). 12 | 13 | About the Input: 14 | 15 | itemsDict -- a dictionary of items, where the key is an integer 1...N (inclusive), 16 | and the value is a tuple (name, weight, value) where: 17 | 18 | name is the text name of the item 19 | weight is the item weight 20 | value is the item value 21 | 22 | maxWt -- the maximum weight supported by the knapsack 23 | 24 | There is at least one item available 25 | All weights and values are >0 26 | All test cases will have a solution (at least one item can be inserted in the knapsack) 27 | 28 | """ 29 | import argparse # argparse allows the parsing of command line arguments 30 | import GA_ProjectUtils as util # utility functions for cs 6515 projects 31 | 32 | 33 | def initTable(numItems, maxWt): 34 | """ 35 | Initialize the table to be used to record the best value possible for given 36 | item idx and weight 37 | NOTE : this table must: 38 | -- be 2 dimensional (i.e. T[x][y]) 39 | -- contain a single numeric value (no tuples or other complicated abstract data types) 40 | """ 41 | # TODO Replace the following with your code to initialize the table properly 42 | 43 | T = [[0 for j in range(0, maxWt+1)] for i in range(0, numItems + 1)] 44 | return T 45 | 46 | 47 | def buildItemIter(numItems): 48 | """ 49 | Build item iterator - iterator through all available items 50 | numItems : number of items 51 | 52 | Note: the index (key value) for items are integer values 1..N 53 | """ 54 | # TODO Replace the following with your code to build the item iterator 55 | 56 | return range(1, numItems + 1) 57 | 58 | 59 | def buildWeightIter(maxWt): 60 | """ 61 | Build weight iterator - iterator of all possible integer weight values 62 | maxWt : maximum weight available 63 | """ 64 | # TODO Replace the following with your code to build the weight iterator 65 | 66 | return range(1, maxWt+1) 67 | 68 | 69 | def subProblem(T, weight, itemIDX, itemWt, itemVal): 70 | """ 71 | Define the subproblem to solve for each table entry - set the value to be maximum for a given 72 | item and weight value 73 | T : the table being populated 74 | weight : weight from iteration through possible weight values 75 | itemIDX : the index (key value) of the item from the loop iteration 76 | itemWt : the weight of the item 77 | itemVal : the value of the item 78 | """ 79 | # TODO Replace the following with your code to solve the subproblem appropriately! 80 | 81 | if itemWt > weight: 82 | T[itemIDX][weight] = T[itemIDX - 1][weight] 83 | else: 84 | T[itemIDX][weight] = max(itemVal + T[itemIDX - 1][weight - itemWt], T[itemIDX - 1][weight]) 85 | 86 | return T[itemIDX][weight] 87 | 88 | 89 | def buildResultList(T, itemsDict, maxWt): 90 | """ 91 | Construct list of items that should be chosen. 92 | T : the populated table of item values, indexed by item idx and weight 93 | itemsDict : dictionary of items Note: items are indexed 1..N 94 | maxWt : maximum weight allowed 95 | 96 | result: a list composed of item tuples 97 | """ 98 | result = [] 99 | 100 | # TODO Your code goes here to build the list of chosen items! 101 | w = maxWt 102 | for i in range(len(itemsDict), 0, -1): 103 | if T[i][w] <= 0: 104 | break 105 | if T[i][w] == T[i - 1][w]: 106 | continue 107 | else: 108 | result.append(itemsDict[i]) 109 | w = w - itemsDict[i][1] 110 | return result 111 | 112 | 113 | def knapsack(itemsDict, maxWt): 114 | """ 115 | Solve the knapsack problem for the passed list of items and max allowable weight 116 | DO NOT MODIFY THE FOLLOWING FUNCTION 117 | NOTE : There are many ways to solve this problem. You are to solve it 118 | using a 2D table, by filling in the function templates above. 119 | If not directed, do not modify the given code template. 120 | """ 121 | numItems = len(itemsDict) 122 | # initialize table properly 123 | table = initTable(numItems, maxWt) 124 | # build iterables 125 | # item iterator 126 | itemIter = buildItemIter(numItems) 127 | # weight iterator 128 | weightIter = buildWeightIter(maxWt) 129 | 130 | for itmIdx in itemIter: 131 | # query item values from list 132 | item, itemWt, itemVal = itemsDict[itmIdx] 133 | for w in weightIter: 134 | # expand table values by solving subproblem 135 | table[itmIdx][w] = subProblem(table, w, itmIdx, itemWt, itemVal) 136 | 137 | # build list of results - chosen items to maximize value for a given weight 138 | return buildResultList(table, itemsDict, maxWt) 139 | 140 | 141 | def main(): 142 | """ 143 | The main function 144 | """ 145 | # DO NOT REMOVE ANY ARGUMENTS FROM THE ARGPARSER BELOW 146 | # You may change default values, but any values you set will be overridden when autograded 147 | parser = argparse.ArgumentParser(description='Knapsack Coding Quiz') 148 | parser.add_argument('-i', '--items', help='File holding list of possible Items (name, wt, value)', 149 | default='defaultItems.txt', dest='itemsListFileName') 150 | parser.add_argument('-w', '--weight', help='Maximum (integer) weight of items allowed', type=int, default=200, 151 | dest='maxWeight') 152 | 153 | # args for autograder, DO NOT MODIFY ANY OF THESE 154 | parser.add_argument('-n', '--sName', help='Student name, used for autograder', default='GT', dest='studentName') 155 | parser.add_argument('-a', '--autograde', help='Autograder-called (2) or not (1=default)', type=int, choices=[1, 2], 156 | default=1, dest='autograde') 157 | args = parser.parse_args() 158 | 159 | # DO NOT MODIFY ANY OF THE FOLLOWING CODE 160 | itemsDict = util.buildKnapsackItemsDict(args) 161 | itemsChosen = knapsack(itemsDict, args.maxWeight) 162 | util.displayKnapSack(args, itemsChosen) 163 | 164 | 165 | if __name__ == '__main__': 166 | main() 167 | -------------------------------------------------------------------------------- /Project1/GA_ProjectUtils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Utility functions - do not modify these functions! Some of these functions may not be applicable to your project. Ignore them 4 | 5 | If you find errors post to class piazza page. 6 | 7 | """ 8 | #import time 9 | #import os 10 | #useful structure to build dictionaries of lists 11 | #from collections import defaultdict 12 | 13 | ######################################## 14 | #IO and Util functions 15 | 16 | #returns sorted version of l, and idx order of sort 17 | def getSortResIDXs(l, rev=True): 18 | from operator import itemgetter 19 | return list(zip(*sorted([(i,e) for i,e in enumerate(l)], 20 | key=itemgetter(1),reverse=rev))) 21 | 22 | 23 | #read srcFile into list of ints 24 | def readIntFileDat(srcFile): 25 | strs = readFileDat(srcFile) 26 | res = [int(s.strip()) for s in strs] 27 | return res 28 | 29 | #read srcFile into list of floats 30 | def readFloatFileDat(srcFile): 31 | strs = readFileDat(srcFile) 32 | res = [float(s.strip()) for s in strs] 33 | return res 34 | 35 | #read srcFile into list of strings 36 | def readFileDat(srcFile): 37 | import os 38 | try: 39 | f = open(srcFile, 'r') 40 | except IOError: 41 | #file doesn't exist, return empty list 42 | print(('Note : {} does not exist in current dir : {}'.format(srcFile, os.getcwd()))) 43 | return [] 44 | src_lines = f.readlines() 45 | f.close() 46 | return src_lines 47 | 48 | #write datList into fName file 49 | def writeFileDat(fName, datList): 50 | f = open(fName, 'w') 51 | for item in datList: 52 | print(item, file=f) 53 | f.close() 54 | 55 | #append record to existing file 56 | def appendFileDat(fName, dat): 57 | f = open(fName, 'a+') 58 | print(dat, file=f) 59 | f.close() 60 | 61 | 62 | ####################################### 63 | #Homework mini-project utility functions 64 | 65 | ##Knapsack 66 | 67 | #this will build a default dictionary of items, where the key is the item number (1..n) 68 | #and value is tuple of (name, item weight, value) 69 | 70 | def buildKnapsackItemsDict(args): 71 | ksItemsData = readFileDat(args.itemsListFileName) 72 | items = {} 73 | itemCount = 0 74 | for line in ksItemsData: 75 | itemCount += 1 76 | vals = line.split(',') 77 | tupleVal = (vals[0].strip(), int(vals[1].strip()), int(vals[2].strip())) 78 | items[itemCount] = tupleVal 79 | 80 | # lst = sorted(res, key = lambda x: x[0]) 81 | 82 | if args.autograde == 1: 83 | print("The following items were loaded from file {} : \nName, Integer Weight, Integer Value : ".format(args.itemsListFileName)) 84 | for k, val in items.items(): 85 | print("{0:30} Wt : {1:5} Val : {2:5} ".format(val[0],val[1],val[2])) 86 | 87 | return items 88 | 89 | #Will display results of knapsack problem 90 | def displayKnapSack(args, itemsChosen): 91 | if(len(itemsChosen)!=0): 92 | print("\n\nResults : The following items were chosen : ") 93 | lst = sorted(itemsChosen, key = lambda x: x[0]) 94 | ttlWt = 0 95 | ttlVal = 0 96 | for s in lst: 97 | ttlWt += s[1] 98 | ttlVal += s[2] 99 | print("{0:30} Wt : {1:5} Val : {2:5} ".format(s[0],s[1],s[2])) 100 | 101 | print(("For a total value of <%i> and a total weight of [%i]" % (ttlVal, ttlWt))) 102 | else : 103 | print("\n\nResults : No Items were chosen: ") 104 | 105 | ##End Knapsack 106 | 107 | ##MST 108 | #this function will load graph information from file and build the graph structure 109 | def build_MSTBaseGraph(args): 110 | #file format should be 111 | #line 0 : # of verts 112 | #line 1 : # of edges 113 | #line 2... : vert1 vert2 edgeWT 114 | MSTGraphData = readFileDat(args.graphDataFileName) 115 | numVerts = int(MSTGraphData[0].strip()) 116 | numEdges = int(MSTGraphData[1].strip()) 117 | edgeDataAra = [] 118 | for i in range(numEdges): 119 | line = MSTGraphData[i+2] 120 | vals = line.split() 121 | v1 = int(vals[0].strip()) 122 | v2 = int(vals[1].strip()) 123 | wt = float(vals[2].strip()) 124 | #print("v1 :{} v2 :{} wt : {} ".format(v1,v2,wt)) 125 | edgeDataAra.append([wt,v1,v2]) 126 | 127 | G = Graph(numVerts, edgeDataAra) 128 | return G 129 | 130 | def print_MSTResults(MST): 131 | itr = 0 132 | for E in MST: 133 | print("({:4d},{:4d}) {:2.6f} ".format(E[1][0], E[1][1], E[0]), end=" | ") 134 | itr += 1 135 | if(itr > 2): 136 | itr=0 137 | print("") 138 | print("\n") 139 | 140 | """ 141 | build a tuple holding edge weight and edge verts to add to mst 142 | """ 143 | def buildMSTEdge(G, e): 144 | wt = G.edgeWts[e] 145 | return (wt, e) 146 | 147 | 148 | def save_MSTRes(args, MST): 149 | saveName = "soln_"+args.graphDataFileName 150 | strList = [] 151 | for E in MST: 152 | strDat = "{} {} {}".format(E[1][0],E[1][1],E[0]) 153 | strList.append(strDat) 154 | writeFileDat(saveName, strList) 155 | 156 | 157 | def load_MSTRes(args): 158 | solnName = "soln_"+args.graphDataFileName 159 | resDataList = readFileDat(solnName) 160 | 161 | MST = set() 162 | for line in resDataList : 163 | vals = line.split() 164 | v1 = int(vals[0].strip()) 165 | v2 = int(vals[1].strip()) 166 | wt = float(vals[2].strip()) 167 | 168 | MST.add((wt, (v1,v2))) 169 | return MST 170 | 171 | #u 172 | def findTotalWeightOfMst(MST): 173 | totWt = 0 174 | for E in MST: 175 | totWt += E[0] 176 | 177 | return totWt 178 | 179 | #used locally 180 | def _compareTwoMSTs(MST_1, lbl1, MST_2, lbl2, printMST): 181 | wt1 = round(findTotalWeightOfMst(MST_1), 12) 182 | wt2 = round(findTotalWeightOfMst(MST_2), 12) 183 | if(abs(wt1 - wt2) < 1e-12): 184 | print("Correct: {} Weight : {} {} Wt : {} ".format(lbl1, wt1, lbl2, wt2)) 185 | return True 186 | else: 187 | diff12 = MST_1 - MST_2 188 | sizeDiff12 = len(diff12) 189 | diff21 = MST_2 - MST_1 190 | sizeDiff21 = len(diff21) 191 | print("Incorrect: {} Weight : {} {} Wt : {}".format(lbl1, wt1, lbl2, wt2)) 192 | return False 193 | 194 | 195 | """ 196 | verifies results of kruskal calculation 197 | """ 198 | def verify_MSTKruskalResults(args, MST_Kruskal, printMST=False): 199 | MST_Correct = load_MSTRes(args) 200 | 201 | if(printMST): 202 | if(len(MST_Kruskal) < 1): 203 | print("No Kruskal's Algorithm results found (Empty MST)") 204 | else : 205 | print("Kruskal's Algorithm results (Edge list of MST) : ") 206 | print_MSTResults(MST_Kruskal) 207 | print("\n") 208 | print("Correct results : ") 209 | print_MSTResults(MST_Correct) 210 | print("\n") 211 | 212 | return _compareTwoMSTs(MST_Kruskal,"Kruskal's Result", MST_Correct, "Expected Result", printMST) 213 | 214 | 215 | """ 216 | this structure will represent an undirected graph as an adjacency matrix 217 | """ 218 | class Graph: 219 | def __init__(self, numVerts, edgeDataAra): 220 | self.numVerts = numVerts 221 | self.numEdges = len(edgeDataAra) 222 | self.edgeDataAra = edgeDataAra 223 | 224 | self.edges = set() 225 | self.edgeWts = dict() 226 | 227 | # populate the graph 228 | for edge in edgeDataAra: 229 | #add edge so that lowest vert is always first 230 | if(edge[1] > edge[2]): 231 | thisEdge = (edge[2],edge[1]) 232 | else : 233 | thisEdge = (edge[1],edge[2]) 234 | 235 | self.edges.add(thisEdge) 236 | self.edgeWts[thisEdge] = edge[0] 237 | 238 | """ 239 | returns list of edges sorted in increasing weight 240 | """ 241 | def sortedEdges(self): 242 | sortedEdges = sorted(self.edges, key=lambda e:self.edgeWts[e]) 243 | return sortedEdges 244 | 245 | def buildAdjacencyMat(self): 246 | numVerts = self.numVerts 247 | graphAdjMat = [[0]*numVerts for _ in range(numVerts)] 248 | edgeDataAra = self.edgeDataAra 249 | for edge in edgeDataAra: 250 | graphAdjMat[edge[1]][edge[2]] = edge[0] 251 | graphAdjMat[edge[2]][edge[1]] = edge[0] 252 | 253 | # use adjacent matrix to represent the graph 254 | return graphAdjMat 255 | 256 | 257 | """ 258 | for debug purposes 259 | """ 260 | def printMe(self): 261 | print("Graph has :{} vertices and {} edges".format(self.numVerts,self.numEdges)) 262 | NumVerts = min(10, self.numVerts) 263 | 264 | AM = [[0.0 for _ in range(NumVerts)] for _ in range(NumVerts)] 265 | 266 | for edge in self.edges: 267 | a,b = edge 268 | if a > NumVerts: continue 269 | if b > NumVerts: continue 270 | weight = self.edgeWts[edge] 271 | AM[a][b] = weight 272 | AM[b][a] = weight 273 | 274 | print(' ', end = ' ') 275 | for i in range(NumVerts): 276 | print('{0:5d}'.format(i), end = ' ') 277 | print() 278 | 279 | for i, row in enumerate(AM): 280 | print('{0:2d}'.format(i), end=' ') 281 | for j in row: 282 | if j == 0: 283 | print(' ', end = ' ') 284 | else: 285 | print('{0:1.3f}'.format(j),end=' ') 286 | print() 287 | 288 | print() 289 | 290 | 291 | ##End MST 292 | 293 | ######################################## 294 | #Bloom Filter Project functions 295 | 296 | #this will compare the contents of the resList with the data in baseFile 297 | #and display performance 298 | def compareResults(resList, configData): 299 | baseFileName = configData['valFileName'] 300 | baseRes = readFileDat(baseFileName) 301 | if(len(baseRes) != len(resList) ): 302 | print('compareFiles : Failure : Attempting to compare different size lists') 303 | return None 304 | numFail = 0 305 | numFTrueRes = 0 306 | numFFalseRes = 0 307 | for i in range(len(resList)): 308 | if (resList[i].strip().lower() != baseRes[i].strip().lower()): 309 | resVal = resList[i].strip().lower() 310 | baseResVal = baseRes[i].strip().lower() 311 | #uncomment this to see inconsistencies 312 | #print('i : ' + str(i) + ': reslist : ' + resVal + ' | baseres : ' + baseResVal) 313 | numFail += 1 314 | if resVal == 'true' : 315 | numFTrueRes += 1 316 | else : 317 | numFFalseRes += 1 318 | if(numFail == 0): 319 | print('compareResults : Your bloom filter performs as expected') 320 | else: 321 | print(('compareResults : Number of mismatches in bloomfilter compared to validation file : ' + str(numFail) + '| # of incorrect true results : ' + str(numFTrueRes) + '| # of incorrect False results : ' + str(numFFalseRes))) 322 | if((configData['studentName'] != '') and (configData['autograde'] == 2)): 323 | gradeRes = configData['studentName'] + ', ' + str(numFail) + ', ' + str(numFTrueRes) + ', ' + str(numFFalseRes) 324 | print(('saving results for ' + gradeRes + ' to autogradeResult.txt')) 325 | appendFileDat('autogradeResult.txt', gradeRes) 326 | 327 | 328 | #this will process input configuration and return a dictionary holding the relevant info 329 | def buildBFConfigStruct(args): 330 | import time 331 | bfConfigData = readFileDat(args.configFileName) 332 | configData = dict() 333 | for line in bfConfigData: 334 | #build dictionary on non-list elements 335 | if (line[0]=='#') or ('_' in line): 336 | continue 337 | elems = line.split('=') 338 | if('name' in elems[0]): 339 | configData[elems[0]]=elems[1].strip() 340 | else : 341 | configData[elems[0]]=int(elems[1]) 342 | 343 | if ('Type 1' in configData['name']): 344 | configData['type'] = 1 345 | configData['seeds'] = buildSeedList(bfConfigData, int(configData['k'])) 346 | 347 | elif ('Type 2' in configData['name']): 348 | configData['type'] = 2 349 | aListData = [] 350 | bListData = [] 351 | listToAppend = aListData 352 | for line in bfConfigData: 353 | if (line[0]=='#'): 354 | if ('b() seeds' in line): 355 | listToAppend = bListData 356 | continue 357 | listToAppend.append(line) 358 | 359 | configData['a']= buildSeedList(aListData, int(configData['k'])) 360 | configData['b']= buildSeedList(bListData, int(configData['k'])) 361 | else : 362 | configData['type'] = -1 363 | print('unknown hash function specified in config file') 364 | 365 | configData['task'] = int(args.taskToDo) 366 | if configData['task'] != 2 : 367 | configData['genSeed'] = int(time.time()*1000.0) & 0x7FFFFFFF #(int)(tOffLong & 0x7FFFFFFF); 368 | print(('Random Time Seed is : ' + str(configData['genSeed']))) 369 | 370 | configData['inFileName'] = args.inFileName 371 | configData['outFileName'] = args.outFileName 372 | configData['configFileName'] = args.configFileName 373 | configData['valFileName'] = args.valFileName 374 | configData['studentName'] = args.studentName 375 | configData['autograde'] = int(args.autograde) 376 | 377 | for k,v in list(configData.items()): 378 | print(('Key = ' + k + ': Val = '), end=' ') 379 | print(v) 380 | 381 | return configData 382 | 383 | def buildSeedList(stringList, k): 384 | res = [0 for x in range(k)] 385 | for line in stringList: 386 | if ('_' not in line) or (line[0]=='#'): 387 | continue 388 | elems = line.split('=') 389 | araElems = elems[0].split('_') 390 | res[int(araElems[1])]=int(elems[1]) 391 | return res 392 | 393 | 394 | """ 395 | Function provided for convenience, to find next prime value from passed value 396 | Use this to find an appropriate prime size for type 2 hashes. 397 | 398 | Finds next prime value larger than n via brute force. Checks subsequent numbers 399 | until prime is found - should be much less than 160 checks for any values 400 | seen in this project since largest gap g between two primes for any 32 bit 401 | signed int is going to be g < 336, and only have to check at most every 402 | other value in gap. For more, see this article : 403 | https://en.wikipedia.org/wiki/Prime_gap 404 | 405 | n : some value 406 | return next largest prime 407 | """ 408 | def findNextPrime(n): 409 | if (n==2) : 410 | return 2 411 | if (n%2==0): 412 | n+=1 413 | #n is odd here; 336 is larger than largest gap between 2 consequtive 32 bit primes 414 | for i in range (n,(n + 336), 2): 415 | if checkIfPrime(i): 416 | return i 417 | #error no prime found returns -1 418 | return -1 419 | 420 | """ 421 | check if value is prime, return true/false 422 | n value to check 423 | """ 424 | def checkIfPrime(n): 425 | if (n < 2) : return False 426 | if (n < 4) : return True 427 | if ((n % 2 == 0) or (n % 3 == 0)): return False 428 | sqrtN = n**(.5) 429 | i = 5 430 | w = 2 431 | while (i <= sqrtN): 432 | if (n % i == 0): return False 433 | i += w 434 | #addresses mod2 and mod3 above, flip flops between looking ahead 2 and 4 (every other odd is divisible by 3) 435 | w = 6-w 436 | return True 437 | 438 | ## end bloom filter functions 439 | ###################################### 440 | 441 | ######################################## 442 | #Page Rank Functions 443 | 444 | 445 | #get file values for particular object and alpha value 446 | #results are list of nodes, list of rank values and dictionary matching node to rank value 447 | #list of nodes and list of rank values are sorted 448 | def getResForPlots(prObj, alpha): 449 | outFileName = makeResOutFileName(prObj.inFileName, alpha, prObj.sinkHandling) 450 | vNodeIDs_unsr, vRankVec_unsr = loadRankVectorData(outFileName, isTest=False) 451 | #build dictionary that links node id to rank value 452 | vNodeDict = buildValidationDict(vNodeIDs_unsr,vRankVec_unsr) 453 | 454 | #build sorted list 455 | vNodeIDs, vRankVec = getSortResIDXs(vRankVec_unsr) 456 | return vNodeIDs, vRankVec, vNodeDict 457 | 458 | #build appropriate results file name based on passed input name, alpha and sink handling flag 459 | def makeResOutFileName(inFileName,alpha,sinkHandling): 460 | nameList = inFileName.strip().split('.') 461 | namePrefix = '.'.join(nameList[:-1]) 462 | #build base output file name based on input file name and whether or not using selfloops to handle sinks 463 | outFileName = "{}_{}_{}.{}".format(namePrefix,("SL" if sinkHandling==0 else "T3"), alpha,nameList[-1]) 464 | return outFileName 465 | 466 | #builds output file names given passed file name 467 | def buildPROutFNames(fName, getVerifyNames=False): 468 | #construct ouput file names based on fName (which is input file name : i.e. 'inputstuff.txt') 469 | nameList = fName.strip().split('.') 470 | #name without extension 471 | namePrefix = '.'.join(nameList[:-1]) 472 | if getVerifyNames : 473 | #get names for verification files 474 | #file holding rank vector values 475 | voutFName = '{}-{}.{}'.format(namePrefix, 'verifyRVec',nameList[-1]) 476 | return voutFName 477 | else : 478 | #names for saving results or accessing saved results 479 | #file holding rank vector values 480 | outFName = '{}-{}.{}'.format(namePrefix, 'outputPR',nameList[-1]) 481 | return outFName 482 | 483 | 484 | #this will build a dictionary with : 485 | # keys == graph nodes and 486 | # values == list of pages accessible from key 487 | # and will also return a list of all node ids 488 | # using terminology from lecture, this builds the "out list" for each node in 489 | # file, and a list of all node ids 490 | def loadGraphADJList(fName): 491 | from collections import defaultdict 492 | #defaultDict has 0/empty list entry for non-present keys, 493 | #does not return invalid key error 494 | resDict = defaultdict(list) 495 | filedat = readFileDat(fName) 496 | allNodesSet = set() 497 | #each line has a single number, followed by a colon, followed by a list of 498 | #1 or more numbers spearated by commas 499 | #these represent node x : reachable nodes from node x 500 | for line in filedat: 501 | vals = line.strip().split(':') 502 | adjValStrs = vals[1].strip().split(',') 503 | #convert list of strings to list of ints 504 | adjVals = [int(s.strip()) for s in adjValStrs] 505 | key = int(vals[0].strip()) 506 | allNodesSet.add(key) 507 | allNodesSet.update(adjVals) 508 | resDict[key] = adjVals 509 | return resDict, list(allNodesSet) 510 | 511 | #given the base input file name 512 | #this will return a list of nodes in order of rank (if rankName file exists) 513 | #and a vector of rank values as floats (if outputName file exists) 514 | #using either base file extensions or the verification file names 515 | def loadRankVectorData(fName, isTest=False): 516 | outFName = buildPROutFNames(fName, isTest) 517 | #read rank vector as list of floats, expected to be in order of node ids 518 | rankVec = readFloatFileDat(outFName) 519 | 520 | rankedIDS = list(range(len(rankVec))) 521 | #either output, or both, might be empty list(s) if files don't exist 522 | return rankedIDS, rankVec 523 | 524 | 525 | #will save a list of nodes in order of rank, and rank values (the rank vector) for those nodes in same order 526 | #in two separate files 527 | def saveRankData(fName, rankVec=None): 528 | outFName = buildPROutFNames(fName) 529 | 530 | if(rankVec != None): 531 | writeFileDat(outFName, rankVec) 532 | print(('Rank vector saved to file {}'.format(outFName))) 533 | 534 | 535 | #build a dictionary that will have node id as key and rank vector value as value - used for verification since equal rank vector values might be in different order 536 | def buildValidationDict(nodeIDs, rankVec): 537 | vDict = {} 538 | for x in range(len(nodeIDs)): 539 | vDict[nodeIDs[x]] = rankVec[x] 540 | return vDict 541 | 542 | """ 543 | using provided output file, verify calculated page rank is the same as expected results 544 | args used for autograder version 545 | """ 546 | def verifyResults(prObj, args=None, eps=.00001): 547 | print(('\nVerifying results for input file "{}" using alpha={} and {} sink handling :\n'.format(prObj.inFileName, prObj.alpha, ('self loop' if prObj.sinkHandling==0 else 'type 3')))) 548 | #load derived values from run of page rank 549 | calcNodeIDs,calcRankVec = loadRankVectorData(prObj.outFileName, isTest=False) 550 | #load verification data 551 | vNodeIDs, vRankVec = loadRankVectorData(prObj.outFileName, isTest=True) 552 | if (len(vNodeIDs) == 0) or (len(vRankVec)==0) : 553 | print ('Validation data not found, cannot test results') 554 | return False 555 | 556 | 557 | #compare nodeID order 558 | if(len(calcNodeIDs) != len(vNodeIDs)) : 559 | print(('!!!! Error : incorrect # of nodes in calculated page rank - yours has {}; validation has {}'.format(len(calcNodeIDs),len(vNodeIDs)))) 560 | return False 561 | print('Calculated Rank vector is of appropriate length') 562 | 563 | #need to verify that rank vector sums to 1 564 | cRVecSum = sum(calcRankVec) 565 | if abs(cRVecSum - 1) > eps : 566 | print(('!!!! Error : your calculated rank vector values do not sum to 1.0 : {} '.format(cRVecSum))) 567 | return False 568 | print('Calculated Rank vector has appropriate magnitude of 1.0') 569 | 570 | #build dictionary of validation data and test data - doing this because order might be different for nodes with same rank value 571 | validDict = buildValidationDict(vNodeIDs,vRankVec) 572 | calcDict = buildValidationDict(calcNodeIDs,calcRankVec) 573 | 574 | 575 | #compare if matched - Note nodes with same rank value vector value might be out of order 576 | for x in range(len(vNodeIDs)): 577 | if abs(calcDict[vNodeIDs[x]] - validDict[vNodeIDs[x]]) > eps : 578 | print(('!!!! Error : rank vector values do not match, starting at idx {}, node {}, in validation node id list'.format(x,vNodeIDs[x]))) 579 | return False 580 | print('Rank Vector values match verification vector values') 581 | 582 | return True 583 | 584 | #autograder code 585 | def autogradePR(prObj, args, prMadeTime): 586 | print(('Running autograder on {} for prObj with input file {}'.format(args.studentName, prObj.inFileName))) 587 | 588 | 589 | #End Page Rank Functions 590 | ######################################################################### 591 | # Start findXinA Functions (Added Summer 2020 rockograziano@gatech.edu 592 | 593 | import random 594 | import math 595 | import sys 596 | 597 | class ExceededLookupsError(Exception): 598 | def __init__(self, *args): 599 | if args: 600 | self.message = args[0] 601 | else: 602 | self.message = None 603 | 604 | def __str__(self): 605 | if self.message: 606 | return '{0}'.format(self.message) 607 | else: 608 | return 'ExceededLookups: Program Exceeded the allowed number of lookups' 609 | 610 | 611 | class findX(): 612 | def __init__(self): 613 | self.__A = [] 614 | self.__n = 0 615 | self.x = 0 616 | self.__lookupCount=0 617 | self.__maxCalls = 0 618 | return 619 | 620 | def start(self, seed, nLower=10, nUpper=100000): 621 | random.seed(seed) 622 | self.__lookupCount=0 623 | self.__n = random.randint(nLower, nUpper) 624 | self.__A = random.sample(range(nUpper*2), self.__n+1) # sample extra value to avoid A[n] error 625 | self.__A.sort() 626 | self.x = self.__A[random.randint(1,self.__n)] 627 | self.__maxCalls = int(math.log(self.__n, 2)*2) + 2 628 | return self.x 629 | 630 | def lookup(self, i): 631 | self.__lookupCount += 1 632 | 633 | if self.__lookupCount > self.__maxCalls: 634 | raise ExceededLookupsError('Exceeded Maximum of {} Lookups'.format(self.__maxCalls)) 635 | 636 | #raise Exception("Exceeded Maximum Number of Lookups") 637 | 638 | if i > self.__n: 639 | return None 640 | else: 641 | return self.__A[i] 642 | 643 | def lookups(self): 644 | return self.__lookupCount 645 | 646 | #End findXinA functions 647 | ################################# 648 | -------------------------------------------------------------------------------- /Project2/GA_ProjectUtils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Utility functions - do not modify these functions! Some of these functions may not be applicable to your project. Ignore them 4 | 5 | If you find errors post to class piazza page. 6 | 7 | """ 8 | #import time 9 | #import os 10 | #useful structure to build dictionaries of lists 11 | #from collections import defaultdict 12 | 13 | ######################################## 14 | #IO and Util functions 15 | 16 | #returns sorted version of l, and idx order of sort 17 | def getSortResIDXs(l, rev=True): 18 | from operator import itemgetter 19 | return list(zip(*sorted([(i,e) for i,e in enumerate(l)], 20 | key=itemgetter(1),reverse=rev))) 21 | 22 | 23 | #read srcFile into list of ints 24 | def readIntFileDat(srcFile): 25 | strs = readFileDat(srcFile) 26 | res = [int(s.strip()) for s in strs] 27 | return res 28 | 29 | #read srcFile into list of floats 30 | def readFloatFileDat(srcFile): 31 | strs = readFileDat(srcFile) 32 | res = [float(s.strip()) for s in strs] 33 | return res 34 | 35 | #read srcFile into list of strings 36 | def readFileDat(srcFile): 37 | import os 38 | try: 39 | f = open(srcFile, 'r') 40 | except IOError: 41 | #file doesn't exist, return empty list 42 | print(('Note : {} does not exist in current dir : {}'.format(srcFile, os.getcwd()))) 43 | return [] 44 | src_lines = f.readlines() 45 | f.close() 46 | return src_lines 47 | 48 | #write datList into fName file 49 | def writeFileDat(fName, datList): 50 | f = open(fName, 'w') 51 | for item in datList: 52 | print(item, file=f) 53 | f.close() 54 | 55 | #append record to existing file 56 | def appendFileDat(fName, dat): 57 | f = open(fName, 'a+') 58 | print(dat, file=f) 59 | f.close() 60 | 61 | 62 | ####################################### 63 | #Homework mini-project utility functions 64 | 65 | ##Knapsack 66 | 67 | #this will build a default dictionary of items, where the key is the item number (1..n) 68 | #and value is tuple of (name, item weight, value) 69 | 70 | def buildKnapsackItemsDict(args): 71 | ksItemsData = readFileDat(args.itemsListFileName) 72 | items = {} 73 | itemCount = 0 74 | for line in ksItemsData: 75 | itemCount += 1 76 | vals = line.split(',') 77 | tupleVal = (vals[0].strip(), int(vals[1].strip()), int(vals[2].strip())) 78 | items[itemCount] = tupleVal 79 | 80 | # lst = sorted(res, key = lambda x: x[0]) 81 | 82 | if args.autograde == 1: 83 | print("The following items were loaded from file {} : \nName, Integer Weight, Integer Value : ".format(args.itemsListFileName)) 84 | for k, val in items.items(): 85 | print("{0:30} Wt : {1:5} Val : {2:5} ".format(val[0],val[1],val[2])) 86 | 87 | return items 88 | 89 | #Will display results of knapsack problem 90 | def displayKnapSack(args, itemsChosen): 91 | if(len(itemsChosen)!=0): 92 | print("\n\nResults : The following items were chosen : ") 93 | lst = sorted(itemsChosen, key = lambda x: x[0]) 94 | ttlWt = 0 95 | ttlVal = 0 96 | for s in lst: 97 | ttlWt += s[1] 98 | ttlVal += s[2] 99 | print("{0:30} Wt : {1:5} Val : {2:5} ".format(s[0],s[1],s[2])) 100 | 101 | print(("For a total value of <%i> and a total weight of [%i]" % (ttlVal, ttlWt))) 102 | else : 103 | print("\n\nResults : No Items were chosen: ") 104 | 105 | ##End Knapsack 106 | 107 | ##MST 108 | #this function will load graph information from file and build the graph structure 109 | def build_MSTBaseGraph(args): 110 | #file format should be 111 | #line 0 : # of verts 112 | #line 1 : # of edges 113 | #line 2... : vert1 vert2 edgeWT 114 | MSTGraphData = readFileDat(args.graphDataFileName) 115 | numVerts = int(MSTGraphData[0].strip()) 116 | numEdges = int(MSTGraphData[1].strip()) 117 | edgeDataAra = [] 118 | for i in range(numEdges): 119 | line = MSTGraphData[i+2] 120 | vals = line.split() 121 | v1 = int(vals[0].strip()) 122 | v2 = int(vals[1].strip()) 123 | wt = float(vals[2].strip()) 124 | #print("v1 :{} v2 :{} wt : {} ".format(v1,v2,wt)) 125 | edgeDataAra.append([wt,v1,v2]) 126 | 127 | G = Graph(numVerts, edgeDataAra) 128 | return G 129 | 130 | def print_MSTResults(MST): 131 | itr = 0 132 | for E in MST: 133 | print("({:4d},{:4d}) {:2.6f} ".format(E[1][0], E[1][1], E[0]), end=" | ") 134 | itr += 1 135 | if(itr > 2): 136 | itr=0 137 | print("") 138 | print("\n") 139 | 140 | """ 141 | build a tuple holding edge weight and edge verts to add to mst 142 | """ 143 | def buildMSTEdge(G, e): 144 | wt = G.edgeWts[e] 145 | return (wt, e) 146 | 147 | 148 | def save_MSTRes(args, MST): 149 | saveName = "soln_"+args.graphDataFileName 150 | strList = [] 151 | for E in MST: 152 | strDat = "{} {} {}".format(E[1][0],E[1][1],E[0]) 153 | strList.append(strDat) 154 | writeFileDat(saveName, strList) 155 | 156 | 157 | def load_MSTRes(args): 158 | solnName = "soln_"+args.graphDataFileName 159 | resDataList = readFileDat(solnName) 160 | 161 | MST = set() 162 | for line in resDataList : 163 | vals = line.split() 164 | v1 = int(vals[0].strip()) 165 | v2 = int(vals[1].strip()) 166 | wt = float(vals[2].strip()) 167 | 168 | MST.add((wt, (v1,v2))) 169 | return MST 170 | 171 | #u 172 | def findTotalWeightOfMst(MST): 173 | totWt = 0 174 | for E in MST: 175 | totWt += E[0] 176 | 177 | return totWt 178 | 179 | #used locally 180 | def _compareTwoMSTs(MST_1, lbl1, MST_2, lbl2, printMST): 181 | wt1 = round(findTotalWeightOfMst(MST_1), 12) 182 | wt2 = round(findTotalWeightOfMst(MST_2), 12) 183 | if(abs(wt1 - wt2) < 1e-12): 184 | print("Correct: {} Weight : {} {} Wt : {} ".format(lbl1, wt1, lbl2, wt2)) 185 | return True 186 | else: 187 | diff12 = MST_1 - MST_2 188 | sizeDiff12 = len(diff12) 189 | diff21 = MST_2 - MST_1 190 | sizeDiff21 = len(diff21) 191 | print("Incorrect: {} Weight : {} {} Wt : {}".format(lbl1, wt1, lbl2, wt2)) 192 | return False 193 | 194 | 195 | """ 196 | verifies results of kruskal calculation 197 | """ 198 | def verify_MSTKruskalResults(args, MST_Kruskal, printMST=False): 199 | MST_Correct = load_MSTRes(args) 200 | 201 | if(printMST): 202 | if(len(MST_Kruskal) < 1): 203 | print("No Kruskal's Algorithm results found (Empty MST)") 204 | else : 205 | print("Kruskal's Algorithm results (Edge list of MST) : ") 206 | print_MSTResults(MST_Kruskal) 207 | print("\n") 208 | print("Correct results : ") 209 | print_MSTResults(MST_Correct) 210 | print("\n") 211 | 212 | return _compareTwoMSTs(MST_Kruskal,"Kruskal's Result", MST_Correct, "Expected Result", printMST) 213 | 214 | 215 | """ 216 | this structure will represent an undirected graph as an adjacency matrix 217 | """ 218 | class Graph: 219 | def __init__(self, numVerts, edgeDataAra): 220 | self.numVerts = numVerts 221 | self.numEdges = len(edgeDataAra) 222 | self.edgeDataAra = edgeDataAra 223 | 224 | self.edges = set() 225 | self.edgeWts = dict() 226 | 227 | # populate the graph 228 | for edge in edgeDataAra: 229 | #add edge so that lowest vert is always first 230 | if(edge[1] > edge[2]): 231 | thisEdge = (edge[2],edge[1]) 232 | else : 233 | thisEdge = (edge[1],edge[2]) 234 | 235 | self.edges.add(thisEdge) 236 | self.edgeWts[thisEdge] = edge[0] 237 | 238 | """ 239 | returns list of edges sorted in increasing weight 240 | """ 241 | def sortedEdges(self): 242 | sortedEdges = sorted(self.edges, key=lambda e:self.edgeWts[e]) 243 | return sortedEdges 244 | 245 | def buildAdjacencyMat(self): 246 | numVerts = self.numVerts 247 | graphAdjMat = [[0]*numVerts for _ in range(numVerts)] 248 | edgeDataAra = self.edgeDataAra 249 | for edge in edgeDataAra: 250 | graphAdjMat[edge[1]][edge[2]] = edge[0] 251 | graphAdjMat[edge[2]][edge[1]] = edge[0] 252 | 253 | # use adjacent matrix to represent the graph 254 | return graphAdjMat 255 | 256 | 257 | """ 258 | for debug purposes 259 | """ 260 | def printMe(self): 261 | print("Graph has :{} vertices and {} edges".format(self.numVerts,self.numEdges)) 262 | NumVerts = min(10, self.numVerts) 263 | 264 | AM = [[0.0 for _ in range(NumVerts)] for _ in range(NumVerts)] 265 | 266 | for edge in self.edges: 267 | a,b = edge 268 | if a > NumVerts: continue 269 | if b > NumVerts: continue 270 | weight = self.edgeWts[edge] 271 | AM[a][b] = weight 272 | AM[b][a] = weight 273 | 274 | print(' ', end = ' ') 275 | for i in range(NumVerts): 276 | print('{0:5d}'.format(i), end = ' ') 277 | print() 278 | 279 | for i, row in enumerate(AM): 280 | print('{0:2d}'.format(i), end=' ') 281 | for j in row: 282 | if j == 0: 283 | print(' ', end = ' ') 284 | else: 285 | print('{0:1.3f}'.format(j),end=' ') 286 | print() 287 | 288 | print() 289 | 290 | 291 | ##End MST 292 | 293 | ######################################## 294 | #Bloom Filter Project functions 295 | 296 | #this will compare the contents of the resList with the data in baseFile 297 | #and display performance 298 | def compareResults(resList, configData): 299 | baseFileName = configData['valFileName'] 300 | baseRes = readFileDat(baseFileName) 301 | if(len(baseRes) != len(resList) ): 302 | print('compareFiles : Failure : Attempting to compare different size lists') 303 | return None 304 | numFail = 0 305 | numFTrueRes = 0 306 | numFFalseRes = 0 307 | for i in range(len(resList)): 308 | if (resList[i].strip().lower() != baseRes[i].strip().lower()): 309 | resVal = resList[i].strip().lower() 310 | baseResVal = baseRes[i].strip().lower() 311 | #uncomment this to see inconsistencies 312 | #print('i : ' + str(i) + ': reslist : ' + resVal + ' | baseres : ' + baseResVal) 313 | numFail += 1 314 | if resVal == 'true' : 315 | numFTrueRes += 1 316 | else : 317 | numFFalseRes += 1 318 | if(numFail == 0): 319 | print('compareResults : Your bloom filter performs as expected') 320 | else: 321 | print(('compareResults : Number of mismatches in bloomfilter compared to validation file : ' + str(numFail) + '| # of incorrect true results : ' + str(numFTrueRes) + '| # of incorrect False results : ' + str(numFFalseRes))) 322 | if((configData['studentName'] != '') and (configData['autograde'] == 2)): 323 | gradeRes = configData['studentName'] + ', ' + str(numFail) + ', ' + str(numFTrueRes) + ', ' + str(numFFalseRes) 324 | print(('saving results for ' + gradeRes + ' to autogradeResult.txt')) 325 | appendFileDat('autogradeResult.txt', gradeRes) 326 | 327 | 328 | #this will process input configuration and return a dictionary holding the relevant info 329 | def buildBFConfigStruct(args): 330 | import time 331 | bfConfigData = readFileDat(args.configFileName) 332 | configData = dict() 333 | for line in bfConfigData: 334 | #build dictionary on non-list elements 335 | if (line[0]=='#') or ('_' in line): 336 | continue 337 | elems = line.split('=') 338 | if('name' in elems[0]): 339 | configData[elems[0]]=elems[1].strip() 340 | else : 341 | configData[elems[0]]=int(elems[1]) 342 | 343 | if ('Type 1' in configData['name']): 344 | configData['type'] = 1 345 | configData['seeds'] = buildSeedList(bfConfigData, int(configData['k'])) 346 | 347 | elif ('Type 2' in configData['name']): 348 | configData['type'] = 2 349 | aListData = [] 350 | bListData = [] 351 | listToAppend = aListData 352 | for line in bfConfigData: 353 | if (line[0]=='#'): 354 | if ('b() seeds' in line): 355 | listToAppend = bListData 356 | continue 357 | listToAppend.append(line) 358 | 359 | configData['a']= buildSeedList(aListData, int(configData['k'])) 360 | configData['b']= buildSeedList(bListData, int(configData['k'])) 361 | else : 362 | configData['type'] = -1 363 | print('unknown hash function specified in config file') 364 | 365 | configData['task'] = int(args.taskToDo) 366 | if configData['task'] != 2 : 367 | configData['genSeed'] = int(time.time()*1000.0) & 0x7FFFFFFF #(int)(tOffLong & 0x7FFFFFFF); 368 | print(('Random Time Seed is : ' + str(configData['genSeed']))) 369 | 370 | configData['inFileName'] = args.inFileName 371 | configData['outFileName'] = args.outFileName 372 | configData['configFileName'] = args.configFileName 373 | configData['valFileName'] = args.valFileName 374 | configData['studentName'] = args.studentName 375 | configData['autograde'] = int(args.autograde) 376 | 377 | for k,v in list(configData.items()): 378 | print(('Key = ' + k + ': Val = '), end=' ') 379 | print(v) 380 | 381 | return configData 382 | 383 | def buildSeedList(stringList, k): 384 | res = [0 for x in range(k)] 385 | for line in stringList: 386 | if ('_' not in line) or (line[0]=='#'): 387 | continue 388 | elems = line.split('=') 389 | araElems = elems[0].split('_') 390 | res[int(araElems[1])]=int(elems[1]) 391 | return res 392 | 393 | 394 | """ 395 | Function provided for convenience, to find next prime value from passed value 396 | Use this to find an appropriate prime size for type 2 hashes. 397 | 398 | Finds next prime value larger than n via brute force. Checks subsequent numbers 399 | until prime is found - should be much less than 160 checks for any values 400 | seen in this project since largest gap g between two primes for any 32 bit 401 | signed int is going to be g < 336, and only have to check at most every 402 | other value in gap. For more, see this article : 403 | https://en.wikipedia.org/wiki/Prime_gap 404 | 405 | n : some value 406 | return next largest prime 407 | """ 408 | def findNextPrime(n): 409 | if (n==2) : 410 | return 2 411 | if (n%2==0): 412 | n+=1 413 | #n is odd here; 336 is larger than largest gap between 2 consequtive 32 bit primes 414 | for i in range (n,(n + 336), 2): 415 | if checkIfPrime(i): 416 | return i 417 | #error no prime found returns -1 418 | return -1 419 | 420 | """ 421 | check if value is prime, return true/false 422 | n value to check 423 | """ 424 | def checkIfPrime(n): 425 | if (n < 2) : return False 426 | if (n < 4) : return True 427 | if ((n % 2 == 0) or (n % 3 == 0)): return False 428 | sqrtN = n**(.5) 429 | i = 5 430 | w = 2 431 | while (i <= sqrtN): 432 | if (n % i == 0): return False 433 | i += w 434 | #addresses mod2 and mod3 above, flip flops between looking ahead 2 and 4 (every other odd is divisible by 3) 435 | w = 6-w 436 | return True 437 | 438 | ## end bloom filter functions 439 | ###################################### 440 | 441 | ######################################## 442 | #Page Rank Functions 443 | 444 | 445 | #get file values for particular object and alpha value 446 | #results are list of nodes, list of rank values and dictionary matching node to rank value 447 | #list of nodes and list of rank values are sorted 448 | def getResForPlots(prObj, alpha): 449 | outFileName = makeResOutFileName(prObj.inFileName, alpha, prObj.sinkHandling) 450 | vNodeIDs_unsr, vRankVec_unsr = loadRankVectorData(outFileName, isTest=False) 451 | #build dictionary that links node id to rank value 452 | vNodeDict = buildValidationDict(vNodeIDs_unsr,vRankVec_unsr) 453 | 454 | #build sorted list 455 | vNodeIDs, vRankVec = getSortResIDXs(vRankVec_unsr) 456 | return vNodeIDs, vRankVec, vNodeDict 457 | 458 | #build appropriate results file name based on passed input name, alpha and sink handling flag 459 | def makeResOutFileName(inFileName,alpha,sinkHandling): 460 | nameList = inFileName.strip().split('.') 461 | namePrefix = '.'.join(nameList[:-1]) 462 | #build base output file name based on input file name and whether or not using selfloops to handle sinks 463 | outFileName = "{}_{}_{}.{}".format(namePrefix,("SL" if sinkHandling==0 else "T3"), alpha,nameList[-1]) 464 | return outFileName 465 | 466 | #builds output file names given passed file name 467 | def buildPROutFNames(fName, getVerifyNames=False): 468 | #construct ouput file names based on fName (which is input file name : i.e. 'inputstuff.txt') 469 | nameList = fName.strip().split('.') 470 | #name without extension 471 | namePrefix = '.'.join(nameList[:-1]) 472 | if getVerifyNames : 473 | #get names for verification files 474 | #file holding rank vector values 475 | voutFName = '{}-{}.{}'.format(namePrefix, 'verifyRVec',nameList[-1]) 476 | return voutFName 477 | else : 478 | #names for saving results or accessing saved results 479 | #file holding rank vector values 480 | outFName = '{}-{}.{}'.format(namePrefix, 'outputPR',nameList[-1]) 481 | return outFName 482 | 483 | 484 | #this will build a dictionary with : 485 | # keys == graph nodes and 486 | # values == list of pages accessible from key 487 | # and will also return a list of all node ids 488 | # using terminology from lecture, this builds the "out list" for each node in 489 | # file, and a list of all node ids 490 | def loadGraphADJList(fName): 491 | from collections import defaultdict 492 | #defaultDict has 0/empty list entry for non-present keys, 493 | #does not return invalid key error 494 | resDict = defaultdict(list) 495 | filedat = readFileDat(fName) 496 | allNodesSet = set() 497 | #each line has a single number, followed by a colon, followed by a list of 498 | #1 or more numbers spearated by commas 499 | #these represent node x : reachable nodes from node x 500 | for line in filedat: 501 | vals = line.strip().split(':') 502 | adjValStrs = vals[1].strip().split(',') 503 | #convert list of strings to list of ints 504 | adjVals = [int(s.strip()) for s in adjValStrs] 505 | key = int(vals[0].strip()) 506 | allNodesSet.add(key) 507 | allNodesSet.update(adjVals) 508 | resDict[key] = adjVals 509 | return resDict, list(allNodesSet) 510 | 511 | #given the base input file name 512 | #this will return a list of nodes in order of rank (if rankName file exists) 513 | #and a vector of rank values as floats (if outputName file exists) 514 | #using either base file extensions or the verification file names 515 | def loadRankVectorData(fName, isTest=False): 516 | outFName = buildPROutFNames(fName, isTest) 517 | #read rank vector as list of floats, expected to be in order of node ids 518 | rankVec = readFloatFileDat(outFName) 519 | 520 | rankedIDS = list(range(len(rankVec))) 521 | #either output, or both, might be empty list(s) if files don't exist 522 | return rankedIDS, rankVec 523 | 524 | 525 | #will save a list of nodes in order of rank, and rank values (the rank vector) for those nodes in same order 526 | #in two separate files 527 | def saveRankData(fName, rankVec=None): 528 | outFName = buildPROutFNames(fName) 529 | 530 | if(rankVec != None): 531 | writeFileDat(outFName, rankVec) 532 | print(('Rank vector saved to file {}'.format(outFName))) 533 | 534 | 535 | #build a dictionary that will have node id as key and rank vector value as value - used for verification since equal rank vector values might be in different order 536 | def buildValidationDict(nodeIDs, rankVec): 537 | vDict = {} 538 | for x in range(len(nodeIDs)): 539 | vDict[nodeIDs[x]] = rankVec[x] 540 | return vDict 541 | 542 | """ 543 | using provided output file, verify calculated page rank is the same as expected results 544 | args used for autograder version 545 | """ 546 | def verifyResults(prObj, args=None, eps=.00001): 547 | print(('\nVerifying results for input file "{}" using alpha={} and {} sink handling :\n'.format(prObj.inFileName, prObj.alpha, ('self loop' if prObj.sinkHandling==0 else 'type 3')))) 548 | #load derived values from run of page rank 549 | calcNodeIDs,calcRankVec = loadRankVectorData(prObj.outFileName, isTest=False) 550 | #load verification data 551 | vNodeIDs, vRankVec = loadRankVectorData(prObj.outFileName, isTest=True) 552 | if (len(vNodeIDs) == 0) or (len(vRankVec)==0) : 553 | print ('Validation data not found, cannot test results') 554 | return False 555 | 556 | 557 | #compare nodeID order 558 | if(len(calcNodeIDs) != len(vNodeIDs)) : 559 | print(('!!!! Error : incorrect # of nodes in calculated page rank - yours has {}; validation has {}'.format(len(calcNodeIDs),len(vNodeIDs)))) 560 | return False 561 | print('Calculated Rank vector is of appropriate length') 562 | 563 | #need to verify that rank vector sums to 1 564 | cRVecSum = sum(calcRankVec) 565 | if abs(cRVecSum - 1) > eps : 566 | print(('!!!! Error : your calculated rank vector values do not sum to 1.0 : {} '.format(cRVecSum))) 567 | return False 568 | print('Calculated Rank vector has appropriate magnitude of 1.0') 569 | 570 | #build dictionary of validation data and test data - doing this because order might be different for nodes with same rank value 571 | validDict = buildValidationDict(vNodeIDs,vRankVec) 572 | calcDict = buildValidationDict(calcNodeIDs,calcRankVec) 573 | 574 | 575 | #compare if matched - Note nodes with same rank value vector value might be out of order 576 | for x in range(len(vNodeIDs)): 577 | if abs(calcDict[vNodeIDs[x]] - validDict[vNodeIDs[x]]) > eps : 578 | print(('!!!! Error : rank vector values do not match, starting at idx {}, node {}, in validation node id list'.format(x,vNodeIDs[x]))) 579 | return False 580 | print('Rank Vector values match verification vector values') 581 | 582 | return True 583 | 584 | #autograder code 585 | def autogradePR(prObj, args, prMadeTime): 586 | print(('Running autograder on {} for prObj with input file {}'.format(args.studentName, prObj.inFileName))) 587 | 588 | 589 | #End Page Rank Functions 590 | ######################################################################### 591 | # Start findXinA Functions (Added Summer 2020 rockograziano@gatech.edu 592 | 593 | import random 594 | import math 595 | import sys 596 | 597 | class ExceededLookupsError(Exception): 598 | def __init__(self, *args): 599 | if args: 600 | self.message = args[0] 601 | else: 602 | self.message = None 603 | 604 | def __str__(self): 605 | if self.message: 606 | return '{0}'.format(self.message) 607 | else: 608 | return 'ExceededLookups: Program Exceeded the allowed number of lookups' 609 | 610 | 611 | class findX(): 612 | def __init__(self): 613 | self.__A = [] 614 | self.__n = 0 615 | self.x = 0 616 | self.__lookupCount=0 617 | self.__maxCalls = 0 618 | return 619 | 620 | def start(self, seed, nLower=10, nUpper=100000): 621 | random.seed(seed) 622 | self.__lookupCount=0 623 | self.__n = random.randint(nLower, nUpper) 624 | self.__A = random.sample(range(nUpper*2), self.__n+1) # sample extra value to avoid A[n] error 625 | self.__A.sort() 626 | self.x = self.__A[random.randint(1,self.__n)] 627 | self.__maxCalls = int(math.log(self.__n, 2)*2) + 2 628 | return self.x 629 | 630 | def lookup(self, i): 631 | self.__lookupCount += 1 632 | 633 | if self.__lookupCount > self.__maxCalls: 634 | raise ExceededLookupsError('Exceeded Maximum of {} Lookups'.format(self.__maxCalls)) 635 | 636 | #raise Exception("Exceeded Maximum Number of Lookups") 637 | 638 | if i > self.__n: 639 | return None 640 | else: 641 | return self.__A[i] 642 | 643 | def lookups(self): 644 | return self.__lookupCount 645 | 646 | #End findXinA functions 647 | ################################# 648 | -------------------------------------------------------------------------------- /Project3/GA_ProjectUtils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Utility functions - do not modify these functions! Some of these functions may not be applicable to your project. Ignore them 4 | 5 | If you find errors post to class piazza page. 6 | 7 | """ 8 | #import time 9 | #import os 10 | #useful structure to build dictionaries of lists 11 | #from collections import defaultdict 12 | 13 | ######################################## 14 | #IO and Util functions 15 | 16 | #returns sorted version of l, and idx order of sort 17 | def getSortResIDXs(l, rev=True): 18 | from operator import itemgetter 19 | return list(zip(*sorted([(i,e) for i,e in enumerate(l)], 20 | key=itemgetter(1),reverse=rev))) 21 | 22 | 23 | #read srcFile into list of ints 24 | def readIntFileDat(srcFile): 25 | strs = readFileDat(srcFile) 26 | res = [int(s.strip()) for s in strs] 27 | return res 28 | 29 | #read srcFile into list of floats 30 | def readFloatFileDat(srcFile): 31 | strs = readFileDat(srcFile) 32 | res = [float(s.strip()) for s in strs] 33 | return res 34 | 35 | #read srcFile into list of strings 36 | def readFileDat(srcFile): 37 | import os 38 | try: 39 | f = open(srcFile, 'r') 40 | except IOError: 41 | #file doesn't exist, return empty list 42 | print(('Note : {} does not exist in current dir : {}'.format(srcFile, os.getcwd()))) 43 | return [] 44 | src_lines = f.readlines() 45 | f.close() 46 | return src_lines 47 | 48 | #write datList into fName file 49 | def writeFileDat(fName, datList): 50 | f = open(fName, 'w') 51 | for item in datList: 52 | print(item, file=f) 53 | f.close() 54 | 55 | #append record to existing file 56 | def appendFileDat(fName, dat): 57 | f = open(fName, 'a+') 58 | print(dat, file=f) 59 | f.close() 60 | 61 | 62 | ####################################### 63 | #Homework mini-project utility functions 64 | 65 | ##Knapsack 66 | 67 | #this will build a default dictionary of items, where the key is the item number (1..n) 68 | #and value is tuple of (name, item weight, value) 69 | 70 | def buildKnapsackItemsDict(args): 71 | ksItemsData = readFileDat(args.itemsListFileName) 72 | items = {} 73 | itemCount = 0 74 | for line in ksItemsData: 75 | itemCount += 1 76 | vals = line.split(',') 77 | tupleVal = (vals[0].strip(), int(vals[1].strip()), int(vals[2].strip())) 78 | items[itemCount] = tupleVal 79 | 80 | # lst = sorted(res, key = lambda x: x[0]) 81 | 82 | if args.autograde == 1: 83 | print("The following items were loaded from file {} : \nName, Integer Weight, Integer Value : ".format(args.itemsListFileName)) 84 | for k, val in items.items(): 85 | print("{0:30} Wt : {1:5} Val : {2:5} ".format(val[0],val[1],val[2])) 86 | 87 | return items 88 | 89 | #Will display results of knapsack problem 90 | def displayKnapSack(args, itemsChosen): 91 | if(len(itemsChosen)!=0): 92 | print("\n\nResults : The following items were chosen : ") 93 | lst = sorted(itemsChosen, key = lambda x: x[0]) 94 | ttlWt = 0 95 | ttlVal = 0 96 | for s in lst: 97 | ttlWt += s[1] 98 | ttlVal += s[2] 99 | print("{0:30} Wt : {1:5} Val : {2:5} ".format(s[0],s[1],s[2])) 100 | 101 | print(("For a total value of <%i> and a total weight of [%i]" % (ttlVal, ttlWt))) 102 | else : 103 | print("\n\nResults : No Items were chosen: ") 104 | 105 | ##End Knapsack 106 | 107 | ##MST 108 | #this function will load graph information from file and build the graph structure 109 | def build_MSTBaseGraph(args): 110 | #file format should be 111 | #line 0 : # of verts 112 | #line 1 : # of edges 113 | #line 2... : vert1 vert2 edgeWT 114 | MSTGraphData = readFileDat(args.graphDataFileName) 115 | numVerts = int(MSTGraphData[0].strip()) 116 | numEdges = int(MSTGraphData[1].strip()) 117 | edgeDataAra = [] 118 | for i in range(numEdges): 119 | line = MSTGraphData[i+2] 120 | vals = line.split() 121 | v1 = int(vals[0].strip()) 122 | v2 = int(vals[1].strip()) 123 | wt = float(vals[2].strip()) 124 | #print("v1 :{} v2 :{} wt : {} ".format(v1,v2,wt)) 125 | edgeDataAra.append([wt,v1,v2]) 126 | 127 | G = Graph(numVerts, edgeDataAra) 128 | return G 129 | 130 | def print_MSTResults(MST): 131 | itr = 0 132 | for E in MST: 133 | print("({:4d},{:4d}) {:2.6f} ".format(E[1][0], E[1][1], E[0]), end=" | ") 134 | itr += 1 135 | if(itr > 2): 136 | itr=0 137 | print("") 138 | print("\n") 139 | 140 | """ 141 | build a tuple holding edge weight and edge verts to add to mst 142 | """ 143 | def buildMSTEdge(G, e): 144 | wt = G.edgeWts[e] 145 | return (wt, e) 146 | 147 | 148 | def save_MSTRes(args, MST): 149 | saveName = "soln_"+args.graphDataFileName 150 | strList = [] 151 | for E in MST: 152 | strDat = "{} {} {}".format(E[1][0],E[1][1],E[0]) 153 | strList.append(strDat) 154 | writeFileDat(saveName, strList) 155 | 156 | 157 | def load_MSTRes(args): 158 | solnName = "soln_"+args.graphDataFileName 159 | resDataList = readFileDat(solnName) 160 | 161 | MST = set() 162 | for line in resDataList : 163 | vals = line.split() 164 | v1 = int(vals[0].strip()) 165 | v2 = int(vals[1].strip()) 166 | wt = float(vals[2].strip()) 167 | 168 | MST.add((wt, (v1,v2))) 169 | return MST 170 | 171 | #u 172 | def findTotalWeightOfMst(MST): 173 | totWt = 0 174 | for E in MST: 175 | totWt += E[0] 176 | 177 | return totWt 178 | 179 | #used locally 180 | def _compareTwoMSTs(MST_1, lbl1, MST_2, lbl2, printMST): 181 | wt1 = round(findTotalWeightOfMst(MST_1), 12) 182 | wt2 = round(findTotalWeightOfMst(MST_2), 12) 183 | if(abs(wt1 - wt2) < 1e-12): 184 | print("Correct: {} Weight : {} {} Wt : {} ".format(lbl1, wt1, lbl2, wt2)) 185 | return True 186 | else: 187 | diff12 = MST_1 - MST_2 188 | sizeDiff12 = len(diff12) 189 | diff21 = MST_2 - MST_1 190 | sizeDiff21 = len(diff21) 191 | print("Incorrect: {} Weight : {} {} Wt : {}".format(lbl1, wt1, lbl2, wt2)) 192 | return False 193 | 194 | 195 | """ 196 | verifies results of kruskal calculation 197 | """ 198 | def verify_MSTKruskalResults(args, MST_Kruskal, printMST=False): 199 | MST_Correct = load_MSTRes(args) 200 | 201 | if(printMST): 202 | if(len(MST_Kruskal) < 1): 203 | print("No Kruskal's Algorithm results found (Empty MST)") 204 | else : 205 | print("Kruskal's Algorithm results (Edge list of MST) : ") 206 | print_MSTResults(MST_Kruskal) 207 | print("\n") 208 | print("Correct results : ") 209 | print_MSTResults(MST_Correct) 210 | print("\n") 211 | 212 | return _compareTwoMSTs(MST_Kruskal,"Kruskal's Result", MST_Correct, "Expected Result", printMST) 213 | 214 | 215 | """ 216 | this structure will represent an undirected graph as an adjacency matrix 217 | """ 218 | class Graph: 219 | def __init__(self, numVerts, edgeDataAra): 220 | self.numVerts = numVerts 221 | self.numEdges = len(edgeDataAra) 222 | self.edgeDataAra = edgeDataAra 223 | 224 | self.edges = set() 225 | self.edgeWts = dict() 226 | 227 | # populate the graph 228 | for edge in edgeDataAra: 229 | #add edge so that lowest vert is always first 230 | if(edge[1] > edge[2]): 231 | thisEdge = (edge[2],edge[1]) 232 | else : 233 | thisEdge = (edge[1],edge[2]) 234 | 235 | self.edges.add(thisEdge) 236 | self.edgeWts[thisEdge] = edge[0] 237 | 238 | """ 239 | returns list of edges sorted in increasing weight 240 | """ 241 | def sortedEdges(self): 242 | sortedEdges = sorted(self.edges, key=lambda e:self.edgeWts[e]) 243 | return sortedEdges 244 | 245 | def buildAdjacencyMat(self): 246 | numVerts = self.numVerts 247 | graphAdjMat = [[0]*numVerts for _ in range(numVerts)] 248 | edgeDataAra = self.edgeDataAra 249 | for edge in edgeDataAra: 250 | graphAdjMat[edge[1]][edge[2]] = edge[0] 251 | graphAdjMat[edge[2]][edge[1]] = edge[0] 252 | 253 | # use adjacent matrix to represent the graph 254 | return graphAdjMat 255 | 256 | 257 | """ 258 | for debug purposes 259 | """ 260 | def printMe(self): 261 | print("Graph has :{} vertices and {} edges".format(self.numVerts,self.numEdges)) 262 | NumVerts = min(10, self.numVerts) 263 | 264 | AM = [[0.0 for _ in range(NumVerts)] for _ in range(NumVerts)] 265 | 266 | for edge in self.edges: 267 | a,b = edge 268 | if a > NumVerts: continue 269 | if b > NumVerts: continue 270 | weight = self.edgeWts[edge] 271 | AM[a][b] = weight 272 | AM[b][a] = weight 273 | 274 | print(' ', end = ' ') 275 | for i in range(NumVerts): 276 | print('{0:5d}'.format(i), end = ' ') 277 | print() 278 | 279 | for i, row in enumerate(AM): 280 | print('{0:2d}'.format(i), end=' ') 281 | for j in row: 282 | if j == 0: 283 | print(' ', end = ' ') 284 | else: 285 | print('{0:1.3f}'.format(j),end=' ') 286 | print() 287 | 288 | print() 289 | 290 | 291 | ##End MST 292 | 293 | ######################################## 294 | #Bloom Filter Project functions 295 | 296 | #this will compare the contents of the resList with the data in baseFile 297 | #and display performance 298 | def compareResults(resList, configData): 299 | baseFileName = configData['valFileName'] 300 | baseRes = readFileDat(baseFileName) 301 | if(len(baseRes) != len(resList) ): 302 | print('compareFiles : Failure : Attempting to compare different size lists') 303 | return None 304 | numFail = 0 305 | numFTrueRes = 0 306 | numFFalseRes = 0 307 | for i in range(len(resList)): 308 | if (resList[i].strip().lower() != baseRes[i].strip().lower()): 309 | resVal = resList[i].strip().lower() 310 | baseResVal = baseRes[i].strip().lower() 311 | #uncomment this to see inconsistencies 312 | #print('i : ' + str(i) + ': reslist : ' + resVal + ' | baseres : ' + baseResVal) 313 | numFail += 1 314 | if resVal == 'true' : 315 | numFTrueRes += 1 316 | else : 317 | numFFalseRes += 1 318 | if(numFail == 0): 319 | print('compareResults : Your bloom filter performs as expected') 320 | else: 321 | print(('compareResults : Number of mismatches in bloomfilter compared to validation file : ' + str(numFail) + '| # of incorrect true results : ' + str(numFTrueRes) + '| # of incorrect False results : ' + str(numFFalseRes))) 322 | if((configData['studentName'] != '') and (configData['autograde'] == 2)): 323 | gradeRes = configData['studentName'] + ', ' + str(numFail) + ', ' + str(numFTrueRes) + ', ' + str(numFFalseRes) 324 | print(('saving results for ' + gradeRes + ' to autogradeResult.txt')) 325 | appendFileDat('autogradeResult.txt', gradeRes) 326 | 327 | 328 | #this will process input configuration and return a dictionary holding the relevant info 329 | def buildBFConfigStruct(args): 330 | import time 331 | bfConfigData = readFileDat(args.configFileName) 332 | configData = dict() 333 | for line in bfConfigData: 334 | #build dictionary on non-list elements 335 | if (line[0]=='#') or ('_' in line): 336 | continue 337 | elems = line.split('=') 338 | if('name' in elems[0]): 339 | configData[elems[0]]=elems[1].strip() 340 | else : 341 | configData[elems[0]]=int(elems[1]) 342 | 343 | if ('Type 1' in configData['name']): 344 | configData['type'] = 1 345 | configData['seeds'] = buildSeedList(bfConfigData, int(configData['k'])) 346 | 347 | elif ('Type 2' in configData['name']): 348 | configData['type'] = 2 349 | aListData = [] 350 | bListData = [] 351 | listToAppend = aListData 352 | for line in bfConfigData: 353 | if (line[0]=='#'): 354 | if ('b() seeds' in line): 355 | listToAppend = bListData 356 | continue 357 | listToAppend.append(line) 358 | 359 | configData['a']= buildSeedList(aListData, int(configData['k'])) 360 | configData['b']= buildSeedList(bListData, int(configData['k'])) 361 | else : 362 | configData['type'] = -1 363 | print('unknown hash function specified in config file') 364 | 365 | configData['task'] = int(args.taskToDo) 366 | if configData['task'] != 2 : 367 | configData['genSeed'] = int(time.time()*1000.0) & 0x7FFFFFFF #(int)(tOffLong & 0x7FFFFFFF); 368 | print(('Random Time Seed is : ' + str(configData['genSeed']))) 369 | 370 | configData['inFileName'] = args.inFileName 371 | configData['outFileName'] = args.outFileName 372 | configData['configFileName'] = args.configFileName 373 | configData['valFileName'] = args.valFileName 374 | configData['studentName'] = args.studentName 375 | configData['autograde'] = int(args.autograde) 376 | 377 | for k,v in list(configData.items()): 378 | print(('Key = ' + k + ': Val = '), end=' ') 379 | print(v) 380 | 381 | return configData 382 | 383 | def buildSeedList(stringList, k): 384 | res = [0 for x in range(k)] 385 | for line in stringList: 386 | if ('_' not in line) or (line[0]=='#'): 387 | continue 388 | elems = line.split('=') 389 | araElems = elems[0].split('_') 390 | res[int(araElems[1])]=int(elems[1]) 391 | return res 392 | 393 | 394 | """ 395 | Function provided for convenience, to find next prime value from passed value 396 | Use this to find an appropriate prime size for type 2 hashes. 397 | 398 | Finds next prime value larger than n via brute force. Checks subsequent numbers 399 | until prime is found - should be much less than 160 checks for any values 400 | seen in this project since largest gap g between two primes for any 32 bit 401 | signed int is going to be g < 336, and only have to check at most every 402 | other value in gap. For more, see this article : 403 | https://en.wikipedia.org/wiki/Prime_gap 404 | 405 | n : some value 406 | return next largest prime 407 | """ 408 | def findNextPrime(n): 409 | if (n==2) : 410 | return 2 411 | if (n%2==0): 412 | n+=1 413 | #n is odd here; 336 is larger than largest gap between 2 consequtive 32 bit primes 414 | for i in range (n,(n + 336), 2): 415 | if checkIfPrime(i): 416 | return i 417 | #error no prime found returns -1 418 | return -1 419 | 420 | """ 421 | check if value is prime, return true/false 422 | n value to check 423 | """ 424 | def checkIfPrime(n): 425 | if (n < 2) : return False 426 | if (n < 4) : return True 427 | if ((n % 2 == 0) or (n % 3 == 0)): return False 428 | sqrtN = n**(.5) 429 | i = 5 430 | w = 2 431 | while (i <= sqrtN): 432 | if (n % i == 0): return False 433 | i += w 434 | #addresses mod2 and mod3 above, flip flops between looking ahead 2 and 4 (every other odd is divisible by 3) 435 | w = 6-w 436 | return True 437 | 438 | ## end bloom filter functions 439 | ###################################### 440 | 441 | ######################################## 442 | #Page Rank Functions 443 | 444 | 445 | #get file values for particular object and alpha value 446 | #results are list of nodes, list of rank values and dictionary matching node to rank value 447 | #list of nodes and list of rank values are sorted 448 | def getResForPlots(prObj, alpha): 449 | outFileName = makeResOutFileName(prObj.inFileName, alpha, prObj.sinkHandling) 450 | vNodeIDs_unsr, vRankVec_unsr = loadRankVectorData(outFileName, isTest=False) 451 | #build dictionary that links node id to rank value 452 | vNodeDict = buildValidationDict(vNodeIDs_unsr,vRankVec_unsr) 453 | 454 | #build sorted list 455 | vNodeIDs, vRankVec = getSortResIDXs(vRankVec_unsr) 456 | return vNodeIDs, vRankVec, vNodeDict 457 | 458 | #build appropriate results file name based on passed input name, alpha and sink handling flag 459 | def makeResOutFileName(inFileName,alpha,sinkHandling): 460 | nameList = inFileName.strip().split('.') 461 | namePrefix = '.'.join(nameList[:-1]) 462 | #build base output file name based on input file name and whether or not using selfloops to handle sinks 463 | outFileName = "{}_{}_{}.{}".format(namePrefix,("SL" if sinkHandling==0 else "T3"), alpha,nameList[-1]) 464 | return outFileName 465 | 466 | #builds output file names given passed file name 467 | def buildPROutFNames(fName, getVerifyNames=False): 468 | #construct ouput file names based on fName (which is input file name : i.e. 'inputstuff.txt') 469 | nameList = fName.strip().split('.') 470 | #name without extension 471 | namePrefix = '.'.join(nameList[:-1]) 472 | if getVerifyNames : 473 | #get names for verification files 474 | #file holding rank vector values 475 | voutFName = '{}-{}.{}'.format(namePrefix, 'verifyRVec',nameList[-1]) 476 | return voutFName 477 | else : 478 | #names for saving results or accessing saved results 479 | #file holding rank vector values 480 | outFName = '{}-{}.{}'.format(namePrefix, 'outputPR',nameList[-1]) 481 | return outFName 482 | 483 | 484 | #this will build a dictionary with : 485 | # keys == graph nodes and 486 | # values == list of pages accessible from key 487 | # and will also return a list of all node ids 488 | # using terminology from lecture, this builds the "out list" for each node in 489 | # file, and a list of all node ids 490 | def loadGraphADJList(fName): 491 | from collections import defaultdict 492 | #defaultDict has 0/empty list entry for non-present keys, 493 | #does not return invalid key error 494 | resDict = defaultdict(list) 495 | filedat = readFileDat(fName) 496 | allNodesSet = set() 497 | #each line has a single number, followed by a colon, followed by a list of 498 | #1 or more numbers spearated by commas 499 | #these represent node x : reachable nodes from node x 500 | for line in filedat: 501 | vals = line.strip().split(':') 502 | adjValStrs = vals[1].strip().split(',') 503 | #convert list of strings to list of ints 504 | adjVals = [int(s.strip()) for s in adjValStrs] 505 | key = int(vals[0].strip()) 506 | allNodesSet.add(key) 507 | allNodesSet.update(adjVals) 508 | resDict[key] = adjVals 509 | return resDict, list(allNodesSet) 510 | 511 | #given the base input file name 512 | #this will return a list of nodes in order of rank (if rankName file exists) 513 | #and a vector of rank values as floats (if outputName file exists) 514 | #using either base file extensions or the verification file names 515 | def loadRankVectorData(fName, isTest=False): 516 | outFName = buildPROutFNames(fName, isTest) 517 | #read rank vector as list of floats, expected to be in order of node ids 518 | rankVec = readFloatFileDat(outFName) 519 | 520 | rankedIDS = list(range(len(rankVec))) 521 | #either output, or both, might be empty list(s) if files don't exist 522 | return rankedIDS, rankVec 523 | 524 | 525 | #will save a list of nodes in order of rank, and rank values (the rank vector) for those nodes in same order 526 | #in two separate files 527 | def saveRankData(fName, rankVec=None): 528 | outFName = buildPROutFNames(fName) 529 | 530 | if(rankVec != None): 531 | writeFileDat(outFName, rankVec) 532 | print(('Rank vector saved to file {}'.format(outFName))) 533 | 534 | 535 | #build a dictionary that will have node id as key and rank vector value as value - used for verification since equal rank vector values might be in different order 536 | def buildValidationDict(nodeIDs, rankVec): 537 | vDict = {} 538 | for x in range(len(nodeIDs)): 539 | vDict[nodeIDs[x]] = rankVec[x] 540 | return vDict 541 | 542 | """ 543 | using provided output file, verify calculated page rank is the same as expected results 544 | args used for autograder version 545 | """ 546 | def verifyResults(prObj, args=None, eps=.00001): 547 | print(('\nVerifying results for input file "{}" using alpha={} and {} sink handling :\n'.format(prObj.inFileName, prObj.alpha, ('self loop' if prObj.sinkHandling==0 else 'type 3')))) 548 | #load derived values from run of page rank 549 | calcNodeIDs,calcRankVec = loadRankVectorData(prObj.outFileName, isTest=False) 550 | #load verification data 551 | vNodeIDs, vRankVec = loadRankVectorData(prObj.outFileName, isTest=True) 552 | if (len(vNodeIDs) == 0) or (len(vRankVec)==0) : 553 | print ('Validation data not found, cannot test results') 554 | return False 555 | 556 | 557 | #compare nodeID order 558 | if(len(calcNodeIDs) != len(vNodeIDs)) : 559 | print(('!!!! Error : incorrect # of nodes in calculated page rank - yours has {}; validation has {}'.format(len(calcNodeIDs),len(vNodeIDs)))) 560 | return False 561 | print('Calculated Rank vector is of appropriate length') 562 | 563 | #need to verify that rank vector sums to 1 564 | cRVecSum = sum(calcRankVec) 565 | if abs(cRVecSum - 1) > eps : 566 | print(('!!!! Error : your calculated rank vector values do not sum to 1.0 : {} '.format(cRVecSum))) 567 | return False 568 | print('Calculated Rank vector has appropriate magnitude of 1.0') 569 | 570 | #build dictionary of validation data and test data - doing this because order might be different for nodes with same rank value 571 | validDict = buildValidationDict(vNodeIDs,vRankVec) 572 | calcDict = buildValidationDict(calcNodeIDs,calcRankVec) 573 | 574 | 575 | #compare if matched - Note nodes with same rank value vector value might be out of order 576 | for x in range(len(vNodeIDs)): 577 | if abs(calcDict[vNodeIDs[x]] - validDict[vNodeIDs[x]]) > eps : 578 | print(('!!!! Error : rank vector values do not match, starting at idx {}, node {}, in validation node id list'.format(x,vNodeIDs[x]))) 579 | return False 580 | print('Rank Vector values match verification vector values') 581 | 582 | return True 583 | 584 | #autograder code 585 | def autogradePR(prObj, args, prMadeTime): 586 | print(('Running autograder on {} for prObj with input file {}'.format(args.studentName, prObj.inFileName))) 587 | 588 | 589 | #End Page Rank Functions 590 | ######################################################################### 591 | # Start findXinA Functions (Added Summer 2020 rockograziano@gatech.edu 592 | 593 | import random 594 | import math 595 | import sys 596 | 597 | class ExceededLookupsError(Exception): 598 | def __init__(self, *args): 599 | if args: 600 | self.message = args[0] 601 | else: 602 | self.message = None 603 | 604 | def __str__(self): 605 | if self.message: 606 | return '{0}'.format(self.message) 607 | else: 608 | return 'ExceededLookups: Program Exceeded the allowed number of lookups' 609 | 610 | 611 | class findX(): 612 | def __init__(self): 613 | self.__A = [] 614 | self.__n = 0 615 | self.x = 0 616 | self.__lookupCount=0 617 | self.__maxCalls = 0 618 | return 619 | 620 | def start(self, seed, nLower=10, nUpper=100000): 621 | random.seed(seed) 622 | self.__lookupCount=0 623 | self.__n = random.randint(nLower, nUpper) 624 | self.__A = random.sample(range(nUpper*2), self.__n+1) # sample extra value to avoid A[n] error 625 | self.__A.sort() 626 | self.x = self.__A[random.randint(1,self.__n)] 627 | self.__maxCalls = int(math.log(self.__n, 2)*2) + 2 628 | return self.x 629 | 630 | def lookup(self, i): 631 | if not isinstance(i, int): 632 | raise TypeError('x must be an integer') 633 | 634 | if i < 1: 635 | raise ValueError('x must be > 0') 636 | 637 | self.__lookupCount += 1 638 | 639 | if self.__lookupCount > self.__maxCalls: 640 | raise ExceededLookupsError('Exceeded Maximum of {} Lookups'.format(self.__maxCalls)) 641 | 642 | if i > self.__n: 643 | return None 644 | else: 645 | return self.__A[i] 646 | 647 | def lookups(self): 648 | return self.__lookupCount 649 | 650 | #End findXinA functions 651 | ################################# 652 | -------------------------------------------------------------------------------- /Project3/medium.txt: -------------------------------------------------------------------------------- 1 | 250 2 | 1273 3 | 244 246 0.11712 4 | 239 240 0.10616 5 | 238 245 0.06142 6 | 235 238 0.07048 7 | 233 240 0.07634 8 | 232 248 0.10223 9 | 231 248 0.10699 10 | 229 249 0.10098 11 | 228 241 0.01473 12 | 226 231 0.07638 13 | 223 242 0.10184 14 | 223 249 0.10898 15 | 222 225 0.09842 16 | 220 247 0.10309 17 | 219 221 0.06535 18 | 218 224 0.05993 19 | 218 227 0.09192 20 | 217 232 0.09613 21 | 216 232 0.08738 22 | 214 219 0.04104 23 | 214 221 0.10444 24 | 213 235 0.09305 25 | 213 238 0.10707 26 | 212 214 0.09024 27 | 212 219 0.08099 28 | 212 221 0.08320 29 | 212 244 0.04321 30 | 211 222 0.06192 31 | 211 225 0.10649 32 | 210 212 0.05813 33 | 210 214 0.07099 34 | 210 219 0.03728 35 | 210 221 0.03659 36 | 210 244 0.10062 37 | 209 211 0.01269 38 | 209 222 0.07357 39 | 209 225 0.11652 40 | 208 226 0.04662 41 | 208 231 0.08821 42 | 207 210 0.03158 43 | 207 212 0.05667 44 | 207 214 0.10119 45 | 207 219 0.06878 46 | 207 221 0.02902 47 | 207 244 0.09218 48 | 206 209 0.11467 49 | 205 207 0.10606 50 | 205 210 0.07932 51 | 205 214 0.07345 52 | 205 219 0.05157 53 | 205 221 0.08879 54 | 204 222 0.09626 55 | 204 225 0.05003 56 | 204 231 0.11432 57 | 203 249 0.04148 58 | 202 204 0.04207 59 | 202 209 0.10956 60 | 202 211 0.09692 61 | 202 222 0.05440 62 | 202 225 0.06056 63 | 201 216 0.11363 64 | 201 217 0.11118 65 | 201 232 0.03557 66 | 201 248 0.06668 67 | 200 203 0.05651 68 | 200 223 0.09984 69 | 200 249 0.06335 70 | 199 237 0.06767 71 | 198 223 0.09036 72 | 198 242 0.03037 73 | 197 230 0.09937 74 | 196 205 0.05718 75 | 196 214 0.08233 76 | 196 219 0.08903 77 | 195 238 0.11390 78 | 195 245 0.09286 79 | 194 220 0.11551 80 | 193 243 0.09306 81 | 192 243 0.07897 82 | 191 202 0.06216 83 | 191 204 0.07061 84 | 191 222 0.09234 85 | 191 225 0.11446 86 | 191 231 0.11935 87 | 190 220 0.04330 88 | 190 247 0.06680 89 | 189 200 0.11303 90 | 189 203 0.05779 91 | 189 220 0.09403 92 | 189 249 0.08557 93 | 188 230 0.05191 94 | 188 233 0.08575 95 | 188 240 0.09560 96 | 187 208 0.06557 97 | 187 226 0.03660 98 | 187 231 0.04215 99 | 187 248 0.11716 100 | 186 189 0.05775 101 | 186 203 0.10305 102 | 186 249 0.11195 103 | 185 201 0.06956 104 | 185 232 0.10259 105 | 185 248 0.02896 106 | 184 188 0.07566 107 | 184 197 0.05351 108 | 184 230 0.04691 109 | 183 215 0.03017 110 | 182 198 0.07870 111 | 182 223 0.08452 112 | 182 242 0.10811 113 | 181 184 0.08764 114 | 181 188 0.10778 115 | 181 196 0.11674 116 | 181 230 0.05963 117 | 180 213 0.03355 118 | 179 193 0.10256 119 | 179 212 0.09146 120 | 179 244 0.07050 121 | 178 236 0.02867 122 | 177 186 0.03537 123 | 177 189 0.03512 124 | 177 203 0.06820 125 | 177 249 0.07806 126 | 176 191 0.02089 127 | 176 202 0.04299 128 | 176 204 0.06123 129 | 176 222 0.07243 130 | 176 225 0.09939 131 | 175 246 0.03569 132 | 174 179 0.09292 133 | 174 192 0.07813 134 | 174 243 0.07415 135 | 172 180 0.08119 136 | 172 197 0.09121 137 | 172 213 0.05932 138 | 172 235 0.07388 139 | 171 172 0.06889 140 | 171 180 0.10106 141 | 171 213 0.06758 142 | 171 235 0.03106 143 | 171 238 0.05664 144 | 171 245 0.11526 145 | 170 182 0.06422 146 | 170 198 0.10237 147 | 170 223 0.03653 148 | 170 229 0.10924 149 | 170 249 0.11264 150 | 169 177 0.08571 151 | 169 186 0.05624 152 | 169 189 0.08899 153 | 169 190 0.09320 154 | 169 220 0.10104 155 | 168 187 0.04080 156 | 168 204 0.11515 157 | 168 208 0.08885 158 | 168 226 0.07555 159 | 168 231 0.00268 160 | 168 248 0.10481 161 | 167 224 0.07521 162 | 166 236 0.09479 163 | 165 171 0.11685 164 | 165 172 0.09828 165 | 165 180 0.01756 166 | 165 191 0.10673 167 | 165 213 0.05003 168 | 164 190 0.07043 169 | 164 194 0.07229 170 | 164 220 0.05001 171 | 164 247 0.09969 172 | 163 202 0.09825 173 | 163 209 0.02235 174 | 163 211 0.01708 175 | 163 222 0.05489 176 | 163 225 0.11682 177 | 162 192 0.09472 178 | 161 169 0.10571 179 | 161 177 0.07299 180 | 161 186 0.06124 181 | 161 189 0.10748 182 | 161 229 0.10509 183 | 161 249 0.11843 184 | 160 168 0.06839 185 | 160 176 0.06571 186 | 160 187 0.10794 187 | 160 191 0.05410 188 | 160 202 0.08639 189 | 160 204 0.06352 190 | 160 225 0.11314 191 | 160 231 0.06647 192 | 159 234 0.05490 193 | 159 239 0.10493 194 | 158 170 0.05722 195 | 158 200 0.07196 196 | 158 203 0.09121 197 | 158 223 0.05291 198 | 158 229 0.09925 199 | 158 249 0.05734 200 | 157 181 0.05473 201 | 157 184 0.04716 202 | 157 188 0.10501 203 | 157 197 0.07152 204 | 157 230 0.05597 205 | 156 196 0.08377 206 | 156 205 0.05088 207 | 156 207 0.07567 208 | 156 210 0.04409 209 | 156 212 0.08418 210 | 156 214 0.03435 211 | 156 219 0.00745 212 | 156 221 0.07280 213 | 155 165 0.05001 214 | 155 171 0.07487 215 | 155 172 0.04996 216 | 155 180 0.03246 217 | 155 197 0.11679 218 | 155 213 0.01559 219 | 155 235 0.09681 220 | 155 238 0.11940 221 | 154 171 0.08024 222 | 154 195 0.11016 223 | 154 235 0.09296 224 | 154 238 0.02365 225 | 154 245 0.04011 226 | 153 228 0.05583 227 | 153 241 0.04247 228 | 152 179 0.10233 229 | 152 207 0.08799 230 | 152 210 0.10636 231 | 152 212 0.05852 232 | 152 221 0.11655 233 | 152 244 0.03365 234 | 152 246 0.09510 235 | 151 168 0.09264 236 | 151 187 0.06861 237 | 151 208 0.00391 238 | 151 226 0.04792 239 | 151 231 0.09202 240 | 150 164 0.09115 241 | 150 169 0.06638 242 | 150 177 0.08428 243 | 150 186 0.08087 244 | 150 189 0.06046 245 | 150 190 0.06182 246 | 150 203 0.11351 247 | 150 220 0.04158 248 | 149 163 0.07447 249 | 149 206 0.10265 250 | 149 209 0.05363 251 | 149 211 0.05830 252 | 149 222 0.11405 253 | 149 225 0.10995 254 | 148 157 0.01712 255 | 148 181 0.05620 256 | 148 184 0.03398 257 | 148 188 0.08809 258 | 148 197 0.07085 259 | 148 230 0.04043 260 | 147 162 0.09416 261 | 147 166 0.11877 262 | 146 218 0.06252 263 | 146 224 0.11387 264 | 146 227 0.04560 265 | 145 146 0.10595 266 | 144 168 0.09650 267 | 144 185 0.03018 268 | 144 187 0.11380 269 | 144 201 0.08140 270 | 144 204 0.11540 271 | 144 231 0.09846 272 | 144 232 0.11686 273 | 144 248 0.01527 274 | 143 152 0.07831 275 | 143 175 0.10421 276 | 143 179 0.08905 277 | 143 193 0.06865 278 | 143 212 0.11875 279 | 143 244 0.07554 280 | 143 246 0.07590 281 | 142 154 0.11701 282 | 142 155 0.04818 283 | 142 165 0.04797 284 | 142 171 0.08119 285 | 142 172 0.09299 286 | 142 180 0.04124 287 | 142 195 0.08901 288 | 142 213 0.03433 289 | 142 235 0.11123 290 | 142 238 0.10237 291 | 140 147 0.04712 292 | 140 162 0.10969 293 | 139 156 0.06665 294 | 139 196 0.04593 295 | 139 205 0.01814 296 | 139 210 0.09743 297 | 139 214 0.08428 298 | 139 219 0.06833 299 | 139 221 0.10596 300 | 138 151 0.11903 301 | 138 188 0.10136 302 | 138 226 0.11064 303 | 138 233 0.09598 304 | 138 239 0.11352 305 | 138 240 0.02076 306 | 137 145 0.11708 307 | 137 146 0.03524 308 | 137 183 0.11008 309 | 137 215 0.11222 310 | 137 218 0.04325 311 | 137 224 0.10278 312 | 137 227 0.07930 313 | 136 159 0.02310 314 | 136 234 0.03185 315 | 135 141 0.06693 316 | 135 181 0.07362 317 | 135 230 0.11174 318 | 134 137 0.10296 319 | 134 145 0.10314 320 | 134 146 0.06821 321 | 134 227 0.03986 322 | 133 166 0.06778 323 | 132 154 0.08146 324 | 132 171 0.07460 325 | 132 235 0.05508 326 | 132 238 0.06935 327 | 131 143 0.05854 328 | 131 179 0.09728 329 | 131 193 0.01012 330 | 131 243 0.10112 331 | 130 194 0.05825 332 | 130 234 0.11697 333 | 129 133 0.07141 334 | 129 147 0.08531 335 | 129 166 0.03392 336 | 129 178 0.11909 337 | 129 236 0.09707 338 | 128 136 0.11358 339 | 128 159 0.09153 340 | 128 173 0.11948 341 | 128 239 0.01726 342 | 126 183 0.08912 343 | 126 215 0.05899 344 | 125 148 0.04208 345 | 125 157 0.02917 346 | 125 172 0.11220 347 | 125 181 0.08041 348 | 125 184 0.05816 349 | 125 197 0.05633 350 | 125 230 0.08248 351 | 124 142 0.06118 352 | 124 155 0.01487 353 | 124 165 0.05177 354 | 124 171 0.08584 355 | 124 172 0.04713 356 | 124 180 0.03552 357 | 124 197 0.10321 358 | 124 213 0.03033 359 | 124 235 0.10482 360 | 123 175 0.07983 361 | 123 246 0.10306 362 | 122 139 0.01217 363 | 122 156 0.05505 364 | 122 196 0.05144 365 | 122 205 0.00647 366 | 122 207 0.11241 367 | 122 210 0.08536 368 | 122 214 0.07516 369 | 122 219 0.05638 370 | 122 221 0.09525 371 | 121 158 0.08749 372 | 121 170 0.03464 373 | 121 182 0.03939 374 | 121 198 0.07031 375 | 121 223 0.04530 376 | 121 242 0.09371 377 | 120 145 0.09428 378 | 120 161 0.09789 379 | 120 229 0.08292 380 | 119 120 0.10342 381 | 119 134 0.04953 382 | 119 137 0.09676 383 | 119 145 0.05361 384 | 119 146 0.07143 385 | 119 227 0.07465 386 | 118 124 0.06300 387 | 118 142 0.11650 388 | 118 151 0.10687 389 | 118 155 0.07746 390 | 118 165 0.08159 391 | 118 172 0.08663 392 | 118 180 0.07699 393 | 118 184 0.11388 394 | 118 197 0.06902 395 | 118 208 0.10634 396 | 118 213 0.09204 397 | 117 140 0.10873 398 | 117 147 0.11794 399 | 117 167 0.09427 400 | 117 178 0.06290 401 | 117 236 0.08473 402 | 116 164 0.04060 403 | 116 190 0.07925 404 | 116 194 0.08583 405 | 116 220 0.08021 406 | 116 247 0.07638 407 | 115 153 0.05126 408 | 115 228 0.08124 409 | 115 241 0.06730 410 | 114 163 0.05526 411 | 114 176 0.08339 412 | 114 191 0.10158 413 | 114 202 0.07319 414 | 114 204 0.11526 415 | 114 209 0.07685 416 | 114 211 0.06713 417 | 114 222 0.02060 418 | 114 225 0.11896 419 | 113 121 0.05379 420 | 113 158 0.09842 421 | 113 170 0.07229 422 | 113 182 0.08536 423 | 113 198 0.05009 424 | 113 223 0.04665 425 | 113 242 0.05551 426 | 112 128 0.09960 427 | 112 136 0.05632 428 | 112 159 0.04347 429 | 112 234 0.08047 430 | 112 239 0.10722 431 | 110 122 0.05351 432 | 110 139 0.06016 433 | 110 156 0.03963 434 | 110 196 0.05323 435 | 110 205 0.05391 436 | 110 207 0.11522 437 | 110 210 0.08364 438 | 110 212 0.11550 439 | 110 214 0.02920 440 | 110 219 0.04680 441 | 110 221 0.11114 442 | 109 126 0.09332 443 | 109 137 0.05083 444 | 109 146 0.08420 445 | 109 183 0.06517 446 | 109 215 0.06179 447 | 109 218 0.07179 448 | 108 110 0.06803 449 | 108 122 0.08214 450 | 108 135 0.11644 451 | 108 139 0.07724 452 | 108 156 0.10525 453 | 108 181 0.10766 454 | 108 196 0.03132 455 | 108 205 0.08755 456 | 108 214 0.09401 457 | 108 219 0.11157 458 | 107 130 0.11436 459 | 107 173 0.08976 460 | 107 200 0.08254 461 | 107 203 0.11594 462 | 106 123 0.11362 463 | 106 131 0.02227 464 | 106 143 0.06821 465 | 106 179 0.11930 466 | 106 193 0.02119 467 | 106 243 0.10940 468 | 106 246 0.11883 469 | 105 106 0.01034 470 | 105 123 0.10392 471 | 105 131 0.03234 472 | 105 143 0.07217 473 | 105 193 0.03141 474 | 105 243 0.11674 475 | 105 246 0.11604 476 | 104 144 0.08161 477 | 104 185 0.07936 478 | 104 201 0.02597 479 | 104 217 0.09568 480 | 104 232 0.04888 481 | 104 248 0.06640 482 | 103 174 0.03708 483 | 103 192 0.04287 484 | 103 243 0.05731 485 | 102 138 0.09831 486 | 102 187 0.09374 487 | 102 226 0.07775 488 | 102 240 0.11740 489 | 101 108 0.05491 490 | 101 110 0.07783 491 | 101 122 0.05090 492 | 101 125 0.10521 493 | 101 139 0.03983 494 | 101 156 0.09930 495 | 101 157 0.10869 496 | 101 181 0.10336 497 | 101 196 0.03115 498 | 101 205 0.05734 499 | 101 214 0.10662 500 | 101 219 0.10279 501 | 100 103 0.06580 502 | 100 133 0.08099 503 | 100 174 0.06827 504 | 100 192 0.07056 505 | 99 129 0.10765 506 | 99 140 0.05150 507 | 99 147 0.03171 508 | 99 162 0.06455 509 | 98 117 0.11425 510 | 98 178 0.05183 511 | 98 236 0.04433 512 | 97 144 0.07138 513 | 97 160 0.08756 514 | 97 168 0.10904 515 | 97 176 0.10973 516 | 97 185 0.07779 517 | 97 191 0.11562 518 | 97 202 0.08870 519 | 97 204 0.04951 520 | 97 225 0.05664 521 | 97 231 0.10938 522 | 97 248 0.08598 523 | 96 199 0.01569 524 | 96 237 0.06553 525 | 95 115 0.09423 526 | 95 153 0.11710 527 | 95 216 0.11785 528 | 94 141 0.08070 529 | 94 198 0.09053 530 | 94 242 0.09095 531 | 93 97 0.07550 532 | 93 144 0.08371 533 | 93 160 0.04360 534 | 93 168 0.03641 535 | 93 176 0.10570 536 | 93 185 0.11051 537 | 93 187 0.07640 538 | 93 191 0.09704 539 | 93 202 0.11502 540 | 93 204 0.07908 541 | 93 226 0.11188 542 | 93 231 0.03594 543 | 93 248 0.09608 544 | 92 122 0.11702 545 | 92 132 0.07972 546 | 92 139 0.11349 547 | 92 171 0.08961 548 | 92 172 0.09296 549 | 92 205 0.11628 550 | 92 235 0.06040 551 | 91 109 0.06129 552 | 91 119 0.09388 553 | 91 134 0.09544 554 | 91 137 0.01061 555 | 91 145 0.11905 556 | 91 146 0.02723 557 | 91 218 0.04088 558 | 91 224 0.09863 559 | 91 227 0.06960 560 | 90 113 0.11828 561 | 90 173 0.06973 562 | 90 233 0.10517 563 | 90 242 0.10115 564 | 89 116 0.06089 565 | 89 127 0.10682 566 | 89 130 0.10584 567 | 89 164 0.07494 568 | 89 194 0.05110 569 | 88 98 0.08567 570 | 88 182 0.09779 571 | 87 111 0.11190 572 | 87 130 0.03684 573 | 87 136 0.10342 574 | 87 194 0.08273 575 | 87 234 0.08302 576 | 86 108 0.11578 577 | 86 135 0.10345 578 | 86 141 0.05640 579 | 85 152 0.10662 580 | 85 175 0.11147 581 | 85 246 0.09698 582 | 84 100 0.09532 583 | 84 103 0.05747 584 | 84 106 0.11963 585 | 84 131 0.10014 586 | 84 174 0.02770 587 | 84 179 0.06994 588 | 84 192 0.10034 589 | 84 193 0.09844 590 | 84 243 0.07221 591 | 83 95 0.11982 592 | 83 104 0.08511 593 | 83 201 0.09238 594 | 83 217 0.03695 595 | 83 232 0.06812 596 | 82 85 0.04344 597 | 82 152 0.06590 598 | 82 175 0.11914 599 | 82 207 0.10290 600 | 82 212 0.10888 601 | 82 244 0.09913 602 | 82 246 0.09265 603 | 81 119 0.08225 604 | 81 134 0.04508 605 | 81 146 0.11254 606 | 81 227 0.07588 607 | 81 229 0.10166 608 | 80 97 0.08938 609 | 80 149 0.09615 610 | 80 202 0.11386 611 | 80 204 0.10423 612 | 80 225 0.05577 613 | 79 84 0.09700 614 | 79 110 0.11633 615 | 79 174 0.10110 616 | 79 179 0.07431 617 | 79 212 0.11328 618 | 79 214 0.09294 619 | 78 112 0.10817 620 | 78 128 0.03633 621 | 78 138 0.09955 622 | 78 159 0.11389 623 | 78 239 0.02065 624 | 78 240 0.09536 625 | 77 78 0.10966 626 | 77 102 0.02737 627 | 77 138 0.07171 628 | 77 151 0.11765 629 | 77 187 0.10655 630 | 77 208 0.11848 631 | 77 226 0.08175 632 | 77 240 0.09031 633 | 76 95 0.07370 634 | 76 115 0.03658 635 | 76 153 0.04395 636 | 76 228 0.09469 637 | 76 241 0.08004 638 | 75 89 0.03394 639 | 75 116 0.02706 640 | 75 164 0.04846 641 | 75 190 0.10387 642 | 75 194 0.06452 643 | 75 220 0.09669 644 | 75 247 0.10191 645 | 74 109 0.10730 646 | 74 126 0.07749 647 | 74 183 0.05190 648 | 74 215 0.04643 649 | 73 120 0.10775 650 | 73 145 0.09149 651 | 72 107 0.11731 652 | 72 150 0.08210 653 | 72 177 0.06434 654 | 72 186 0.09359 655 | 72 189 0.03706 656 | 72 200 0.08158 657 | 72 203 0.03470 658 | 72 220 0.10329 659 | 72 249 0.07452 660 | 71 135 0.10448 661 | 71 148 0.09121 662 | 71 157 0.10574 663 | 71 181 0.08837 664 | 71 184 0.09326 665 | 71 188 0.03894 666 | 71 230 0.05108 667 | 71 233 0.07728 668 | 71 240 0.11683 669 | 70 79 0.01576 670 | 70 84 0.08129 671 | 70 100 0.11309 672 | 70 174 0.08574 673 | 70 179 0.06528 674 | 70 212 0.11795 675 | 70 214 0.10735 676 | 70 244 0.11957 677 | 69 107 0.05640 678 | 69 128 0.11896 679 | 69 173 0.05282 680 | 68 114 0.06736 681 | 68 160 0.10388 682 | 68 165 0.10769 683 | 68 176 0.04396 684 | 68 191 0.04982 685 | 68 202 0.07329 686 | 68 204 0.10336 687 | 68 222 0.06811 688 | 67 83 0.07338 689 | 67 112 0.11331 690 | 67 217 0.04501 691 | 66 149 0.07561 692 | 66 206 0.05154 693 | 66 209 0.11107 694 | 65 71 0.06843 695 | 65 125 0.10535 696 | 65 138 0.11370 697 | 65 148 0.07162 698 | 65 151 0.10304 699 | 65 157 0.08838 700 | 65 181 0.10922 701 | 65 184 0.04790 702 | 65 188 0.03552 703 | 65 197 0.09301 704 | 65 208 0.10677 705 | 65 230 0.05007 706 | 65 240 0.11415 707 | 64 91 0.04394 708 | 64 109 0.06144 709 | 64 119 0.06813 710 | 64 134 0.09237 711 | 64 137 0.03977 712 | 64 145 0.07791 713 | 64 146 0.04384 714 | 64 183 0.09898 715 | 64 215 0.11174 716 | 64 218 0.08298 717 | 64 227 0.08490 718 | 63 96 0.02231 719 | 63 199 0.01821 720 | 63 237 0.04962 721 | 62 71 0.10901 722 | 62 78 0.11140 723 | 62 90 0.08635 724 | 62 128 0.11744 725 | 62 138 0.09478 726 | 62 188 0.11357 727 | 62 233 0.03192 728 | 62 239 0.10804 729 | 62 240 0.07405 730 | 61 87 0.05163 731 | 61 89 0.09050 732 | 61 111 0.06739 733 | 61 130 0.06867 734 | 61 194 0.07466 735 | 61 234 0.10977 736 | 60 63 0.06637 737 | 60 96 0.05690 738 | 60 111 0.08712 739 | 60 199 0.04868 740 | 60 237 0.11595 741 | 59 80 0.06845 742 | 59 97 0.06442 743 | 59 144 0.08084 744 | 59 185 0.06135 745 | 59 204 0.10796 746 | 59 225 0.08326 747 | 59 248 0.08763 748 | 58 68 0.04795 749 | 58 114 0.01947 750 | 58 163 0.07425 751 | 58 176 0.06845 752 | 58 191 0.08507 753 | 58 202 0.06778 754 | 58 204 0.10891 755 | 58 209 0.09540 756 | 58 211 0.08501 757 | 58 222 0.02759 758 | 57 65 0.06750 759 | 57 118 0.08024 760 | 57 125 0.06349 761 | 57 148 0.06092 762 | 57 151 0.10773 763 | 57 157 0.06773 764 | 57 172 0.11673 765 | 57 181 0.11710 766 | 57 184 0.03368 767 | 57 188 0.10123 768 | 57 197 0.02583 769 | 57 208 0.11002 770 | 57 230 0.08049 771 | 56 73 0.05918 772 | 56 119 0.11916 773 | 56 120 0.05027 774 | 56 145 0.08552 775 | 56 161 0.11851 776 | 55 67 0.08505 777 | 55 78 0.08955 778 | 55 112 0.04590 779 | 55 128 0.09745 780 | 55 136 0.10111 781 | 55 159 0.08414 782 | 55 217 0.11852 783 | 55 239 0.09744 784 | 54 99 0.08037 785 | 54 117 0.08936 786 | 54 140 0.02922 787 | 54 147 0.07003 788 | 53 56 0.05542 789 | 53 73 0.10372 790 | 53 81 0.11179 791 | 53 119 0.07620 792 | 53 120 0.02782 793 | 53 134 0.10851 794 | 53 145 0.06902 795 | 53 229 0.09315 796 | 52 77 0.10533 797 | 52 93 0.09973 798 | 52 102 0.10130 799 | 52 151 0.03422 800 | 52 168 0.06388 801 | 52 187 0.03447 802 | 52 208 0.03135 803 | 52 226 0.02384 804 | 52 231 0.06392 805 | 51 70 0.07990 806 | 51 79 0.06984 807 | 51 86 0.10847 808 | 51 110 0.11491 809 | 51 133 0.11676 810 | 51 214 0.10713 811 | 50 59 0.04226 812 | 50 80 0.10173 813 | 50 97 0.10154 814 | 50 104 0.11784 815 | 50 144 0.08851 816 | 50 185 0.05942 817 | 50 201 0.09673 818 | 50 232 0.11667 819 | 50 248 0.08802 820 | 49 59 0.08296 821 | 49 80 0.08196 822 | 49 93 0.08739 823 | 49 97 0.03121 824 | 49 144 0.10234 825 | 49 160 0.08334 826 | 49 176 0.08610 827 | 49 185 0.10833 828 | 49 191 0.09628 829 | 49 202 0.05875 830 | 49 204 0.02568 831 | 49 222 0.10927 832 | 49 225 0.03314 833 | 49 248 0.11708 834 | 48 50 0.09958 835 | 48 83 0.08782 836 | 48 104 0.06005 837 | 48 144 0.11407 838 | 48 185 0.09500 839 | 48 201 0.03841 840 | 48 216 0.07531 841 | 48 217 0.11710 842 | 48 232 0.02109 843 | 48 248 0.10057 844 | 47 64 0.10444 845 | 47 91 0.06658 846 | 47 109 0.07505 847 | 47 137 0.06569 848 | 47 146 0.09071 849 | 47 167 0.11422 850 | 47 218 0.02914 851 | 47 224 0.05238 852 | 46 161 0.07892 853 | 46 169 0.06854 854 | 46 177 0.11118 855 | 46 186 0.07689 856 | 45 48 0.11127 857 | 45 67 0.06225 858 | 45 76 0.11037 859 | 45 83 0.02906 860 | 45 95 0.10135 861 | 45 104 0.11417 862 | 45 217 0.04535 863 | 45 232 0.09323 864 | 44 49 0.02107 865 | 44 59 0.09573 866 | 44 68 0.11930 867 | 44 80 0.10281 868 | 44 93 0.06793 869 | 44 97 0.03365 870 | 44 144 0.09765 871 | 44 160 0.06268 872 | 44 168 0.10433 873 | 44 176 0.07613 874 | 44 185 0.10945 875 | 44 191 0.08240 876 | 44 202 0.05971 877 | 44 204 0.01774 878 | 44 222 0.11370 879 | 44 225 0.05336 880 | 44 231 0.10384 881 | 44 248 0.11288 882 | 43 82 0.08576 883 | 43 152 0.08933 884 | 43 156 0.10122 885 | 43 207 0.02708 886 | 43 210 0.05763 887 | 43 212 0.07554 888 | 43 219 0.09405 889 | 43 221 0.03765 890 | 43 244 0.10274 891 | 42 86 0.09639 892 | 42 101 0.09688 893 | 42 108 0.06664 894 | 42 135 0.05008 895 | 42 141 0.08880 896 | 42 157 0.11467 897 | 42 181 0.06506 898 | 42 196 0.09113 899 | 41 81 0.11854 900 | 41 88 0.06374 901 | 41 121 0.07816 902 | 41 170 0.09973 903 | 41 182 0.03878 904 | 41 198 0.10323 905 | 40 75 0.07166 906 | 40 89 0.10329 907 | 40 116 0.05100 908 | 40 150 0.07051 909 | 40 164 0.03395 910 | 40 190 0.03649 911 | 40 194 0.10624 912 | 40 220 0.03150 913 | 40 247 0.07741 914 | 39 66 0.05590 915 | 39 80 0.10277 916 | 39 149 0.05382 917 | 39 206 0.10412 918 | 39 209 0.10654 919 | 39 211 0.11209 920 | 38 74 0.06907 921 | 38 109 0.09245 922 | 38 126 0.00845 923 | 38 183 0.08279 924 | 38 215 0.05290 925 | 37 76 0.02674 926 | 37 95 0.09352 927 | 37 115 0.01398 928 | 37 153 0.03846 929 | 37 228 0.07596 930 | 37 241 0.06139 931 | 36 41 0.05329 932 | 36 88 0.01841 933 | 36 98 0.08515 934 | 36 182 0.09055 935 | 35 36 0.08804 936 | 35 41 0.10606 937 | 35 88 0.07142 938 | 35 94 0.06254 939 | 35 141 0.11388 940 | 35 198 0.10645 941 | 34 53 0.08565 942 | 34 56 0.04399 943 | 34 73 0.01812 944 | 34 120 0.09075 945 | 34 145 0.07784 946 | 33 58 0.09102 947 | 33 114 0.08593 948 | 33 163 0.10678 949 | 33 222 0.10644 950 | 32 52 0.07988 951 | 32 77 0.11466 952 | 32 93 0.07410 953 | 32 102 0.09251 954 | 32 104 0.10076 955 | 32 144 0.07333 956 | 32 151 0.11408 957 | 32 160 0.11627 958 | 32 168 0.05434 959 | 32 185 0.10165 960 | 32 187 0.04594 961 | 32 201 0.11801 962 | 32 208 0.11121 963 | 32 226 0.07421 964 | 32 231 0.05700 965 | 32 248 0.07367 966 | 31 37 0.09487 967 | 31 115 0.08730 968 | 31 153 0.10769 969 | 31 228 0.07913 970 | 31 241 0.07871 971 | 30 43 0.10126 972 | 30 70 0.10835 973 | 30 79 0.10818 974 | 30 82 0.10926 975 | 30 143 0.08740 976 | 30 152 0.04565 977 | 30 156 0.11364 978 | 30 179 0.06570 979 | 30 207 0.08708 980 | 30 210 0.09124 981 | 30 212 0.03314 982 | 30 214 0.11280 983 | 30 219 0.11146 984 | 30 221 0.11496 985 | 30 244 0.01475 986 | 29 47 0.02921 987 | 29 64 0.10752 988 | 29 91 0.06429 989 | 29 109 0.09440 990 | 29 137 0.06803 991 | 29 146 0.08191 992 | 29 167 0.10821 993 | 29 218 0.02524 994 | 29 224 0.03477 995 | 29 227 0.10208 996 | 28 35 0.10487 997 | 28 41 0.10902 998 | 28 94 0.08477 999 | 28 113 0.05483 1000 | 28 121 0.07801 1001 | 28 170 0.10987 1002 | 28 182 0.08584 1003 | 28 198 0.00775 1004 | 28 223 0.09677 1005 | 28 242 0.02503 1006 | 27 62 0.07419 1007 | 27 65 0.07207 1008 | 27 71 0.05107 1009 | 27 138 0.07814 1010 | 27 184 0.11544 1011 | 27 188 0.03989 1012 | 27 230 0.08817 1013 | 27 233 0.04883 1014 | 27 240 0.06581 1015 | 26 55 0.09933 1016 | 26 77 0.03854 1017 | 26 78 0.09413 1018 | 26 102 0.04190 1019 | 26 138 0.09654 1020 | 26 217 0.11910 1021 | 26 226 0.11644 1022 | 26 239 0.11461 1023 | 26 240 0.11097 1024 | 25 60 0.03405 1025 | 25 63 0.09366 1026 | 25 96 0.08879 1027 | 25 111 0.05309 1028 | 25 199 0.07779 1029 | 24 39 0.07951 1030 | 24 66 0.08457 1031 | 24 80 0.11814 1032 | 24 114 0.10397 1033 | 24 149 0.02915 1034 | 24 163 0.05034 1035 | 24 206 0.09602 1036 | 24 209 0.02802 1037 | 24 211 0.03696 1038 | 24 222 0.09835 1039 | 24 225 0.11996 1040 | 23 33 0.06032 1041 | 23 58 0.07072 1042 | 23 68 0.07437 1043 | 23 114 0.07960 1044 | 23 176 0.11709 1045 | 23 195 0.08090 1046 | 23 222 0.09692 1047 | 22 34 0.03658 1048 | 22 53 0.07033 1049 | 22 56 0.01508 1050 | 22 73 0.04871 1051 | 22 120 0.06464 1052 | 22 145 0.09324 1053 | 21 27 0.01873 1054 | 21 62 0.07424 1055 | 21 65 0.07811 1056 | 21 71 0.03782 1057 | 21 138 0.09594 1058 | 21 184 0.11666 1059 | 21 188 0.04280 1060 | 21 230 0.08276 1061 | 21 233 0.04409 1062 | 21 240 0.08207 1063 | 20 40 0.07068 1064 | 20 75 0.02897 1065 | 20 89 0.05690 1066 | 20 116 0.02095 1067 | 20 127 0.11837 1068 | 20 164 0.06088 1069 | 20 190 0.09529 1070 | 20 194 0.09349 1071 | 20 220 0.10072 1072 | 20 247 0.07725 1073 | 19 70 0.06872 1074 | 19 79 0.08364 1075 | 19 84 0.03540 1076 | 19 100 0.06397 1077 | 19 103 0.05319 1078 | 19 174 0.01925 1079 | 19 179 0.08733 1080 | 19 192 0.09085 1081 | 19 243 0.09323 1082 | 18 35 0.11609 1083 | 18 51 0.11645 1084 | 18 86 0.02813 1085 | 18 94 0.11772 1086 | 18 141 0.06466 1087 | 17 41 0.10519 1088 | 17 81 0.05763 1089 | 17 121 0.09728 1090 | 17 134 0.10171 1091 | 17 158 0.10542 1092 | 17 170 0.07756 1093 | 17 182 0.09423 1094 | 17 223 0.11337 1095 | 17 229 0.06676 1096 | 16 54 0.07406 1097 | 16 98 0.11623 1098 | 16 99 0.10210 1099 | 16 117 0.05134 1100 | 16 129 0.09325 1101 | 16 140 0.07952 1102 | 16 147 0.07171 1103 | 16 166 0.11475 1104 | 16 178 0.06981 1105 | 16 236 0.07388 1106 | 15 24 0.04507 1107 | 15 39 0.09051 1108 | 15 49 0.10519 1109 | 15 58 0.10462 1110 | 15 66 0.11797 1111 | 15 80 0.08217 1112 | 15 114 0.09104 1113 | 15 149 0.04256 1114 | 15 163 0.05589 1115 | 15 202 0.08786 1116 | 15 204 0.11074 1117 | 15 209 0.04580 1118 | 15 211 0.04000 1119 | 15 222 0.07726 1120 | 15 225 0.07498 1121 | 14 18 0.07335 1122 | 14 51 0.09603 1123 | 14 86 0.09145 1124 | 14 129 0.10737 1125 | 14 133 0.06649 1126 | 14 166 0.08096 1127 | 13 19 0.08927 1128 | 13 100 0.02560 1129 | 13 103 0.08741 1130 | 13 129 0.10843 1131 | 13 133 0.06257 1132 | 13 162 0.11602 1133 | 13 174 0.09377 1134 | 13 192 0.08128 1135 | 12 28 0.06032 1136 | 12 35 0.06079 1137 | 12 36 0.08058 1138 | 12 41 0.06364 1139 | 12 88 0.07461 1140 | 12 94 0.08239 1141 | 12 113 0.09906 1142 | 12 121 0.08542 1143 | 12 170 0.11918 1144 | 12 182 0.06361 1145 | 12 198 0.05807 1146 | 12 242 0.08457 1147 | 11 30 0.08689 1148 | 11 43 0.10208 1149 | 11 82 0.03687 1150 | 11 85 0.06928 1151 | 11 143 0.08708 1152 | 11 152 0.04140 1153 | 11 175 0.09935 1154 | 11 207 0.11101 1155 | 11 212 0.09716 1156 | 11 244 0.07397 1157 | 11 246 0.06678 1158 | 10 105 0.11028 1159 | 10 106 0.11976 1160 | 10 123 0.00886 1161 | 10 175 0.07429 1162 | 10 246 0.09977 1163 | 9 23 0.03526 1164 | 9 33 0.08216 1165 | 9 58 0.10398 1166 | 9 68 0.09604 1167 | 9 114 0.11445 1168 | 9 142 0.10955 1169 | 9 195 0.04585 1170 | 8 11 0.04709 1171 | 8 30 0.03985 1172 | 8 43 0.09334 1173 | 8 82 0.07286 1174 | 8 85 0.11331 1175 | 8 143 0.07437 1176 | 8 152 0.00702 1177 | 8 179 0.09533 1178 | 8 207 0.09011 1179 | 8 210 0.10661 1180 | 8 212 0.05604 1181 | 8 221 0.11895 1182 | 8 244 0.02711 1183 | 8 246 0.09709 1184 | 7 42 0.11616 1185 | 7 57 0.06795 1186 | 7 65 0.09235 1187 | 7 71 0.11091 1188 | 7 101 0.10577 1189 | 7 125 0.02442 1190 | 7 148 0.02175 1191 | 7 157 0.00516 1192 | 7 181 0.05778 1193 | 7 184 0.04976 1194 | 7 188 0.10982 1195 | 7 197 0.06984 1196 | 7 230 0.06107 1197 | 6 16 0.04529 1198 | 6 54 0.11235 1199 | 6 98 0.09893 1200 | 6 99 0.11022 1201 | 6 117 0.08821 1202 | 6 129 0.05363 1203 | 6 140 0.10829 1204 | 6 147 0.07924 1205 | 6 166 0.06998 1206 | 6 178 0.07007 1207 | 6 236 0.05556 1208 | 5 26 0.03351 1209 | 5 32 0.11054 1210 | 5 55 0.11131 1211 | 5 67 0.10880 1212 | 5 77 0.05505 1213 | 5 102 0.03834 1214 | 5 104 0.11574 1215 | 5 217 0.09458 1216 | 5 226 0.11433 1217 | 4 5 0.11184 1218 | 4 26 0.08347 1219 | 4 55 0.06425 1220 | 4 77 0.10733 1221 | 4 78 0.02559 1222 | 4 112 0.08751 1223 | 4 128 0.04751 1224 | 4 138 0.11375 1225 | 4 159 0.10114 1226 | 4 239 0.03883 1227 | 4 240 0.11344 1228 | 3 37 0.08512 1229 | 3 45 0.11902 1230 | 3 67 0.09725 1231 | 3 76 0.08069 1232 | 3 115 0.09861 1233 | 3 153 0.04799 1234 | 3 228 0.07635 1235 | 3 241 0.07024 1236 | 2 14 0.08765 1237 | 2 18 0.07425 1238 | 2 42 0.11456 1239 | 2 51 0.05083 1240 | 2 79 0.11759 1241 | 2 86 0.05980 1242 | 2 108 0.09627 1243 | 2 110 0.11746 1244 | 2 141 0.11373 1245 | 1 72 0.06506 1246 | 1 107 0.07484 1247 | 1 130 0.10203 1248 | 1 150 0.10908 1249 | 1 164 0.11039 1250 | 1 189 0.09582 1251 | 1 194 0.11069 1252 | 1 200 0.09550 1253 | 1 203 0.08567 1254 | 1 220 0.10428 1255 | 0 15 0.05719 1256 | 0 24 0.10191 1257 | 0 44 0.06471 1258 | 0 49 0.04849 1259 | 0 58 0.09955 1260 | 0 59 0.10657 1261 | 0 68 0.11816 1262 | 0 80 0.06821 1263 | 0 97 0.07705 1264 | 0 114 0.09610 1265 | 0 149 0.09659 1266 | 0 160 0.11714 1267 | 0 163 0.09368 1268 | 0 176 0.08927 1269 | 0 191 0.10711 1270 | 0 202 0.04678 1271 | 0 204 0.05476 1272 | 0 209 0.09511 1273 | 0 211 0.08438 1274 | 0 222 0.07573 1275 | 0 225 0.02383 1276 | --------------------------------------------------------------------------------