''' The original file (program) 'closure.py' is from http://web.stanford.edu/class/cs145/ for the fall 206 offering. The program is used in Jupyter notebook in lectuers 05 and 06 to compute and display results of some set operations. The program appears to comply with Python 2. I revised the program so it works with Python 3. The main changes are as follows. 1. Change tuple parameters to separate individual parameters, e.g., def fd_to_str((lhs, rhs)): to def fd_to_str(lhs, rhs) because Python 3 doesn't support tuple unpacking any more. 2. Because of the above change, I had to make a few other changes. See 'diff' below for details. Xiannong Meng 2017-07-03 Here is the diff of the two versions. (my_root) [bash xmeng@polaris lectures05-06]$ diff closure.py ../../../cs145-stanford/lectures/lecture05-6/closure.py 17c17 < def fd_to_str(lhs,rhs): return ",".join(to_set(lhs)) + " -> " + ",".join(to_set(rhs)) --- > def fd_to_str((lhs,rhs)): return ",".join(to_set(lhs)) + " -> " + ",".join(to_set(rhs)) 19c19 < #def fds_to_str(fds): return "\n\t".join(map(fd_to_str, fds)) --- > def fds_to_str(fds): return "\n\t".join(map(fd_to_str, fds)) 29,32c29 < print("FDs:") < for fd in fds: < (lhs, rhs) = map(to_set, fd) < print("\n=> \t" + fd_to_str(lhs, rhs)) --- > print("FDs = \t" + fds_to_str(fds)) 35c32 < def fd_applies(x, lhs, rhs): return to_set(lhs).issubset(x) --- > def fd_applies(x, (lhs,rhs)): return to_set(lhs).issubset(x) 47c44 < print("Using FD " + fd_to_str(lhs, rhs)) --- > print("Using FD " + fd_to_str(fd)) ''' # A = set(["name", "category"]) # These are the attribute set. # fds = [ (set(["name"]),"color"), # (set(["category"]), "department"), # (set(["color", "category"]), "price") ] def to_set(x): """Convert input int, string, list, tuple, set -> set""" if type(x) == set: return x elif type(x) in [list, set]: return set(x) elif type(x) in [str, int]: return set([x]) else: raise Exception("Unrecognized type.") def fd_to_str(lhs,rhs): return ",".join(to_set(lhs)) + " -> " + ",".join(to_set(rhs)) #def fds_to_str(fds): return "\n\t".join(map(fd_to_str, fds)) def set_to_str(x): return "{" + ",".join(x) + "}" def fd_applies_to(fd, x): lhs, rhs = map(to_set, fd) return lhs.issubset(x) def print_setup(A, fds): print("Attributes = " + set_to_str(A)) print("FDs:") for fd in fds: (lhs, rhs) = map(to_set, fd) print("\n=> \t" + fd_to_str(lhs, rhs)) """Does the FD apply""" def fd_applies(x, lhs, rhs): return to_set(lhs).issubset(x) def compute_closure(x, fds, verbose=False): bChanged = True # We will repeat until there are no changes. x_ret = x.copy() # Make a copy of the input to hold x^{+} while bChanged: bChanged = False # Must change on each iteration for fd in fds: # loop through all the FDs. (lhs, rhs) = map(to_set, fd) # recall: lhs -> rhs if fd_applies_to(fd, x_ret) and not rhs.issubset(x_ret): x_ret = x_ret.union(rhs) if verbose: print("Using FD " + fd_to_str(lhs, rhs)) print("\t Updated x to " + set_to_str(x_ret)) bChanged = True return x_ret def is_fd_implied(fds, lhs, rhs, verbose=False): """Check if lhs -> rhs is implied by the given set of fds""" xp = compute_closure(lhs,fds,verbose=verbose) if verbose: print(set_to_str(lhs) +"+ = "+ set_to_str(xp)) return to_set(rhs).issubset(xp) def is_superkey(A,B,fds, verbose=False): """Check if A is a super key in B according to the fds""" return is_fd_implied(fds, A, B) import itertools def is_key(A,B,fds,verbose=False): """Check if A is a key in B wrt to fds""" m=len(A) subsets = set(itertools.combinations(A, m-1)) return is_superkey(A,B,fds) and all(not is_superkey(set(SA),B,fds) for SA in subsets) # # Key example from lecture # def key_example(): xmC=set(["A","B"]) xmB=set(["A","C"]) xmA=set(["B","C"]) B =set(["A","B","C"]) fd1=(xmC,"C"); fd2=(xmB,"B"); fd3=(xmA,"A") fds=[fd1,fd2,fd3] return is_key(xmA,B,fds) and is_key(xmB,B,fds) and is_key(xmC,B,fds) from IPython.core.display import display_html, HTML def to_html_table(res, style=None): html = '' html += ''.join(res.keys) + '' html += ''.join([''.join([str(cell) for cell in row]) for row in list(res)]) return html + '' def display_side_by_side(l, r): s = "display: inline-block;" html = to_html_table(l, style=s) + ' ' + to_html_table(r, style=s) display_html(HTML(data=html))