Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

add reduction

  • Loading branch information...
commit efa1d080b618866247ff161e0ea4bddd96d21911 1 parent f3c2574
@drewverlee authored
Showing with 171 additions and 2 deletions.
  1. +9 −2 README.md
  2. +97 −0 distance_orcale.py
  3. +65 −0 reduction_k_clique_to_decision.py
View
11 README.md
@@ -120,8 +120,15 @@ While many of the techinques are overkill for my small projects there
are definatly concepts they were definatly concepts that will be useful
on future larger projects.
-Is your credit card valid?
-========================================================================
+Reductions
+=======================================================================
++ reduction_k_clique_to_decision.py
++ Algorithms
++ Udacity
+
+Reductions in school are usually done only theortically. Well thats no fun!
+With Udacity's help i was able to code my reduction in python
+
Where is the rest?
=====================
Didn't you do a lot more? Yes, I did. But for Honor Code reasons I thought it
View
97 distance_orcale.py
@@ -0,0 +1,97 @@
+#
+# In the shortest-path oracle described in Andrew Goldberg's
+# interview, each node has a label, which is a list of some other
+# nodes in the network and their distance to these nodes. These lists
+# have the property that
+#
+# (1) for any pair of nodes (x,y) in the network, their lists will
+# have at least one node z in common
+#
+# (2) the shortest path from x to y will go through z.
+#
+# Given a graph G that is a balanced binary tree, preprocess the graph to
+# create such labels for each node. Note that the size of the list in
+# each label should not be larger than log n for a graph of size n.
+#
+#
+# create_labels takes in a balanced binary tree and the root element
+# and returns a dictionary, mapping each node to its label
+#
+# a label is a dictionary mapping another node and the distance to
+# that node
+#
+
+def create_labels(binarytreeG, root):
+ labels = {}
+ if root not in binarytreeG: return labels
+ frontier = [(None,root)]
+ while frontier:
+ (parent,cnode) = frontier.pop(0)
+ labels[cnode] = dict()
+ if parent:
+ for key in labels[parent].keys():
+ labels[cnode][key] = labels[parent][key] + binarytreeG[parent][cnode]
+ labels[cnode][cnode] = 0
+ for child in binarytreeG[cnode]:
+ if child != parent:
+ frontier.append((cnode,child))
+ return labels
+
+#######
+# Testing
+#
+
+def get_distances(G, labels):
+ # labels = {a:{b: distance from a to b,
+ # c: distance from a to c}}
+ # create a mapping of all distances for
+ # all nodes
+ distances = {}
+ for start in G:
+ # get all the labels for my starting node
+ label_node = labels[start]
+ s_distances = {}
+ for destination in G:
+ shortest = float('inf')
+ # get all the labels for the destination node
+ label_dest = labels[destination]
+ # and then merge them together, saving the
+ # shortest distance
+ for intermediate_node, dist in label_node.iteritems():
+ # see if intermediate_node is our destination
+ # if it is we can stop - we know that is
+ # the shortest path
+ if intermediate_node == destination:
+ shortest = dist
+ break
+ other_dist = label_dest.get(intermediate_node)
+ if other_dist is None:
+ continue
+ if other_dist + dist < shortest:
+ shortest = other_dist + dist
+ s_distances[destination] = shortest
+ distances[start] = s_distances
+ return distances
+
+def make_link(G, node1, node2, weight=1):
+ if node1 not in G:
+ G[node1] = {}
+ (G[node1])[node2] = weight
+ if node2 not in G:
+ G[node2] = {}
+ (G[node2])[node1] = weight
+ return G
+
+def test():
+ edges = [(1, 2), (1, 3), (2, 4), (2, 5), (3, 6), (3, 7),
+ (4, 8), (4, 9), (5, 10), (5, 11), (6, 12), (6, 13)]
+ tree = {}
+ for n1, n2 in edges:
+ make_link(tree, n1, n2)
+ labels = create_labels(tree, 1)
+ distances = get_distances(tree, labels)
+ assert distances[1][2] == 1
+ assert distances[1][4] == 2
+
+test()
+
View
65 reduction_k_clique_to_decision.py
@@ -0,0 +1,65 @@
+# Decision problems are often just as hard as as actually returning an answer.
+# Show how a k-clique can be found using a solution to the k-clique decision
+# problem. Write a Python function that takes a graph G and a number k
+# as input, and returns a list of k nodes from G that are all connected
+# in the graph. Your function should make use of "k_clique_decision(G, k)",
+# which takes a graph G and a number k and answers whether G contains a k-clique.
+# We will also provide the standard routines for adding and removing edges from a graph.
+
+# Returns a list of all the subsets of a list of size k
+def k_subsets(lst, k):
+ if len(lst) < k:
+ return []
+ if len(lst) == k:
+ return [lst]
+ if k == 1:
+ return [[i] for i in lst]
+ return k_subsets(lst[1:],k) + map(lambda x: x + [lst[0]], k_subsets(lst[1:], k-1))
+
+# Checks if the given list of nodes forms a clique in the given graph.
+def is_clique(G, nodes):
+ for pair in k_subsets(nodes, 2):
+ if pair[1] not in G[pair[0]]:
+ return False
+ return True
+
+# Determines if there is clique of size k or greater in the given graph.
+def k_clique_decision(G, k):
+ nodes = G.keys()
+ for i in range(k, len(nodes) + 1):
+ for subset in k_subsets(nodes, i):
+ if is_clique(G, subset):
+ return True
+ return False
+
+def make_link(G, node1, node2):
+ if node1 not in G:
+ G[node1] = {}
+ (G[node1])[node2] = 1
+ if node2 not in G:
+ G[node2] = {}
+ (G[node2])[node1] = 1
+ return G
+
+def break_link(G, node1, node2):
+ if node1 not in G:
+ print "error: breaking link in a non-existent node"
+ return
+ if node2 not in G:
+ print "error: breaking link in a non-existent node"
+ return
+ if node2 not in G[node1]:
+ print "error: breaking non-existent link"
+ return
+ if node1 not in G[node2]:
+ print "error: breaking non-existent link"
+ return
+ del G[node1][node2]
+ del G[node2][node1]
+ return G
+
+def k_clique(G, k):
+ if not k_clique_decision(G, k):
+ return False
+ for i in
+ # your code herekkkkkkkkkkk
Please sign in to comment.
Something went wrong with that request. Please try again.