class WordLadder: # Create a graph from the file of four letter words def __init__(self, filename): self.word_graph = DiGraph() # Use with for opening file with open(filename) as file: d = defaultdict(list) for line in file: word = line.strip().lower() # Get the word # add 'word' in '_ord', 'w_rd', 'wo_d' and 'wor_' for i in range(4): # we know its 4 letter words temp = word[:i] + '_' + word[i+1:] d[temp].append(word) # from dictionary, make graph for l in d.values(): # For each dictionary list, # add edge between all nodes # in 'wor_', 'work' and 'word' are neighbours for frm in range(len(l)): for to in range(len(l)): if frm != to: self.word_graph.add_edge(l[frm], l[to]) @staticmethod def print_path(previous, from_word, to_word): l = [] node_id = to_word while node_id != from_word: l.append(node_id) node_id = previous[node_id] l.append(from_word) print(l[::-1]) def find_path(self, from_word, to_word): if from_word == to_word: return q = Queue() # q for BFS previous = {} # Previous to store predecessor nodes q.put(from_word) # add the start node to q previous[from_word] = None while not q.empty(): node_id = q.get() start = self.word_graph.vert_list[node_id] for neigh in start.get_neighs(): if neigh in previous: # If neighbour is visited, continue continue previous[neigh] = node_id if neigh == to_word: # Found a path self.print_path(previous, from_word, to_word) return q.put(neigh) # add neighbours to q # end of graph traversal print('No Path')
def main(): edge_to_cost = read_input("input2.txt") my_digraph = DiGraph(edge_to_cost) #print(my_digraph.node_set) #print(my_digraph.node_to_neighbor) #print(my_digraph.edge_to_cost) my_digraph.dijkstra(1, 12, early_stop=False, file_name="output2.txt")
def test_strongly_connected(self): g = DiGraph(6) g.add_edge(0, 1) g.add_edge(1, 2) g.add_edge(2, 0) g.add_edge(2, 3) g.add_edge(3, 4) g.add_edge(4, 3) g.add_edge(5, 3) self.assertTrue(DigraphHasReachableVertex(g).has_rechable_vertex())
def test_component_count(self): g = DiGraph(6) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(2, 3) g.add_edge(3, 0) g.add_edge(2, 4) g.add_edge(4, 5) g.add_edge(5, 4) self.assertEqual(StronglyConnectedComponent(g).get_component_count(), 3)
def test_component_count(self): g = DiGraph(6) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(2, 3) g.add_edge(3, 0) g.add_edge(2, 4) g.add_edge(4, 5) g.add_edge(5, 4) self.assertFalse(DigraphHasReachableVertex(g).has_rechable_vertex())
class StronglyConnectedComponent: def __init__(self, g): self.g = g self.rg = None self.done = [False]*self.g.V self.topo_order = [] self.cc_count = 0 self.cc_id = [-1]*self.g.V #Valid id are positive integeres starting from 1 self.generate_reverse_graph() self.populate_topo_order() self.populate_strongly_cc() def populate_topo_order(self): for i in range(self.rg.V): if not self.done[i]: self.topo_util(i) def get_reverse_topo_order(self): return list(reversed(self.topo_order)) def topo_util(self, v): self.done[v] = True for each in self.rg.adj(v): if not self.done[each]: self.topo_util(each) self.topo_order.append(v) def generate_reverse_graph(self): self.rg = DiGraph(self.g.V) for i in range(self.rg.V): for j in self.g.adj(i): self.rg.add_edge(j, i) def populate_strongly_cc(self): self.done = [False]*self.g.V for each in self.get_reverse_topo_order(): if not self.done[each]: self.cc_count += 1 self.cc_dfs(each) def cc_dfs(self, v): self.done[v] = True self.cc_id[v] = self.cc_count for each in self.g.adj(v): if not self.done[each]: self.cc_dfs(each) def get_component_count(self): return self.cc_count def get_component_id(self, v): return self.cc_id[v] def are_strongly_connected(self, v, w): return self.get_component_id(v) == self.get_component_id(w)
def test_length2(self): g = DiGraph(7) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(1, 3) g.add_edge(3, 4) g.add_edge(4, 5) g.add_edge(5, 3) g.add_edge(5, 0) l = SmallestCycle(g).get_smallest_cycle_length() self.assertEqual(l, 3)
def test_topo_order(self): g = DiGraph(6) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(2, 3) g.add_edge(3, 0) g.add_edge(2, 4) g.add_edge(4, 5) g.add_edge(5, 4) rto = StronglyConnectedComponent(g).get_reverse_topo_order() self.assertListEqual(rto, [4, 5, 1, 0, 3, 2])
def __init__(self, row, column): self.board = DiGraph() # Directed graph self.row = row self.column = column for r in range(row): for c in range(column): pos = (r * column) + c # For each position, find the valid moves and add as edges for neigh in self.get_neighs(r, c): self.board.add_edge(pos, neigh)
def __init__(self, g): self.g = g self.rg = None self.done = [False]*self.g.V self.topo_order = [] self.cc_count = 0 self.cc_id = [-1]*self.g.V #Valid id are positive integeres starting from 1 self.generate_reverse_graph() self.populate_topo_order() self.cc_dag = DiGraph(0) self.populate_strongly_cc_dag()
def test_does_not_exists(self): g = DiGraph(8) g.add_edge(0, 5) g.add_edge(0, 4) g.add_edge(6, 5) g.add_edge(7, 5) g.add_edge(3, 1) g.add_edge(1, 0) g.add_edge(4, 6) v = ReachableVertexDAG(g).get_reachable_vertex() self.assertEqual(v, None)
def test_topo_order(self): g = DiGraph(6) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(2, 3) g.add_edge(3, 0) g.add_edge(2, 4) g.add_edge(4, 5) g.add_edge(5, 4) rto = DigraphHasReachableVertex(g).get_reverse_topo_order() self.assertListEqual(rto, [4, 5, 1, 0, 3, 2])
def test_strongly_connected(self): g = DiGraph(6) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(2, 3) g.add_edge(3, 0) g.add_edge(2, 4) g.add_edge(4, 5) g.add_edge(5, 4) self.assertTrue(StronglyConnectedComponent(g).are_strongly_connected(0, 2)) self.assertTrue(StronglyConnectedComponent(g).are_strongly_connected(3, 2)) self.assertTrue(StronglyConnectedComponent(g).are_strongly_connected(4, 5)) self.assertFalse(StronglyConnectedComponent(g).are_strongly_connected(4, 2))
def test_topo_order(self): g = DiGraph(6) g.add_edge(2, 1) g.add_edge(1, 0) g.add_edge(0, 4) g.add_edge(4, 3) g.add_edge(3, 5) self.assertTrue(HamiltonPathDag(g).has_hamilton_path)
def from_networkx(G): """ Convert a NetworkX graph into a Zen graph object. In creating the object, the NetworkX node object and node/edge data will be copied over (a shallow copy). **Returns**: The return type depends on the input type. * :py:class:`zen.Graph` if the input graph was a :py:class:`networkx.Graph`. * :py:class:`zen.DiGraph` if the input graph was a :py:class:`networkx.DiGraph`. """ Gdest = None if type(G) == networkx.DiGraph: Gdest = DiGraph() elif type(G) == networkx.Graph: Gdest = Graph() else: raise Exception, 'Unable to convert graph object type %s' % str( type(G)) # add nodes for n, nd in G.nodes_iter(data=True): Gdest.add_node(n, nd) # add edges for x, y, ed in G.edges_iter(data=True): Gdest.add_edge(x, y, ed) return Gdest
def test_destination_is_not_reachable_if_path_does_not_exists(): dg = DiGraph() dg.add_nodes_from([1, 2, 3, 4, 5]) dg.add_edge(1, 2) dg.add_edge(2, 3) dg.add_edge(3, 4) assert not is_reachable(dg, 1, 5)
def test_get_path_returns_path_when_path_exists(): dg = DiGraph() dg.add_nodes_from([1, 2, 3, 4, 5]) dg.add_edge(1, 2) dg.add_edge(2, 3) dg.add_edge(3, 4) dg.add_edge(4, 2) assert get_path(dg, 1, 4) == [1, 2, 3, 4]
def test_bfs_on_directed_graph(): dg = DiGraph() dg.add_nodes_from([1, 2, 3, 4, 5]) dg.add_edge(1, 2) dg.add_edge(1, 3) dg.add_edge(2, 4) dg.add_edge(3, 4) assert bfs(dg, 1) == [1, 2, 3, 4]
def __init__(self, filename): self.word_graph = DiGraph() # Use with for opening file with open(filename) as file: d = defaultdict(list) for line in file: word = line.strip().lower() # Get the word # add 'word' in '_ord', 'w_rd', 'wo_d' and 'wor_' for i in range(4): # we know its 4 letter words temp = word[:i] + '_' + word[i+1:] d[temp].append(word) # from dictionary, make graph for l in d.values(): # For each dictionary list, # add edge between all nodes # in 'wor_', 'work' and 'word' are neighbours for frm in range(len(l)): for to in range(len(l)): if frm != to: self.word_graph.add_edge(l[frm], l[to])
def test_get_path_raises_path_not_found_error_if_no_path_exists(): dg = DiGraph() dg.add_nodes_from([1, 2, 3, 4, 5]) dg.add_edge(1, 2) dg.add_edge(2, 3) dg.add_edge(3, 4) dg.add_edge(4, 2) with pytest.raises(PathNotFoundError): get_path(dg, 1, 5)
def from_networkx(G): """ Convert a NetworkX graph into a Zen graph object. In creating the object, the NetworkX node object and node/edge data will be copied over (a shallow copy). **Returns**: The return type depends on the input type. * :py:class:`zen.Graph` if the input graph was a :py:class:`networkx.Graph`. * :py:class:`zen.DiGraph` if the input graph was a :py:class:`networkx.DiGraph`. """ Gdest = None if type(G) == networkx.DiGraph: Gdest = DiGraph() elif type(G) == networkx.Graph: Gdest = Graph() else: raise Exception, 'Unable to convert graph object type %s' % str(type(G)) # add nodes for n,nd in G.nodes_iter(data=True): Gdest.add_node(n,nd) # add edges for x,y,ed in G.edges_iter(data=True): Gdest.add_edge(x,y,ed) return Gdest
def test_topo_order(self): g = DiGraph(4) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(1, 3) g.add_edge(2, 3) self.assertFalse(HamiltonPathDag(g).has_hamilton_path)
def from_networkx(G): """ This function converts a graph from a networkx data structure into a Zen graph. """ Gdest = None if type(G) == networkx.DiGraph: Gdest = DiGraph() elif type(G) == networkx.Graph: Gdest = Graph() else: raise Exception, 'Unable to convert graph object type %s' % str(type(G)) # add nodes for n,nd in G.nodes_iter(data=True): Gdest.add_node(n,nd) # add edges for x,y,ed in G.edges_iter(data=True): Gdest.add_edge(x,y,ed) return Gdest
return False def cycle_undirected(g): visited = [False] * (g.num_vert + 1) for node in g: # loop through all the nodes if visited[node.key] != True: if cycle_dfs_u(g, node.key, visited, -1): return True print('No cycle') if __name__ == '__main__': g = DiGraph() g.add_edge(3, 2) g.add_edge(4, 5) g.add_edge(5, 2) g.add_edge(5, 3) g.add_edge(3, 1) g.add_edge(6, 5) # cycle_directed(g) g = NGraph() g.add_edge(1, 5) g.add_edge(4, 5) g.add_edge(4, 6) g.add_edge(3, 6) g.add_edge(3, 2) g.add_edge(2, 6)
if ret == maxim: # this is the maximum seen so far. maxim_path = m_path.copy() # NBNBNBNB: Do a copy(). path.pop() visited.remove(neigh) return maxim, maxim_path # If not connected, return (0, []) def maximum_cost_path(g, start, end): # COPIED visited = set() visited.add(start) path = [start] return _maximum_cost_path(g, start, end, visited, path, 0) if __name__ == '__main__': g = DiGraph() g.add_edge(0, 1) g.add_edge(0, 6) g.add_edge(1, 2) g.add_edge(1, 5) g.add_edge(1, 6) g.add_edge(2, 3) g.add_edge(3, 4) g.add_edge(5, 2) g.add_edge(5, 3) g.add_edge(5, 4) g.add_edge(6, 5) g.add_edge(7, 1) g.add_edge(7, 6) print(count_paths(g, 1, 5)) print(paths_with_m_edges(g, 0, 3, 4))
def initialize(evm): """ Initialize contract analysis, disassemble EVM bytecode, construct basic blocks, create DFG and CFG """ contr = Contract() dfg = DiGraph() # Data Flow Graph cfg = DiGraph() # Control Flow Graph cur_blk = BasicBlock(0) pc = 0 while pc < len(evm): op = evm[pc] if op not in opcodes.listing: raise KeyError('Invalid op. op: {:#x}, offset: {:#x}'.format(op, pc)) name = opcodes.listing[op][0] size = opcodes.operand_size(op) if size != 0: arg = int.from_bytes(evm[pc + 1:pc + 1 + size], byteorder='big') else: arg = None instr = Instruction(op, name, arg) if name == 'JUMPDEST': if len(cur_blk.instructions) > 0: contr.blocks.append(cur_blk) # Add CFG nodes, representing basic blocks cfg.graph.add_node(cur_blk.offset, blk=cur_blk) new_blk = BasicBlock(pc) cur_blk.next = new_blk cur_blk = new_blk cur_blk.offset += 1 contr.jump_destination[pc] = cur_blk contr.instructions[pc] = instr else: cur_blk.instructions.append(instr) contr.instructions[pc] = instr if opcodes.is_swap(op) or opcodes.is_dup(op): # Omit SWAP and DUP from IDG pass elif (name == 'JUMP' or name == 'JUMPI' or name == 'STOP' or name == 'RETURN' or name == 'REVERT' or name == 'INVALID' or name == 'SUICIDE'): contr.blocks.append(cur_blk) # Add CFG nodes, representing basic blocks cfg.graph.add_node(cur_blk.offset, blk=cur_blk) new_blk = BasicBlock(pc + 1) cur_blk.next = new_blk cur_blk = new_blk # Add DFG nodes, representing instructions dfg.graph.add_node(pc, instr=instr) else: # Add DFG nodes, representing instructions dfg.graph.add_node(pc, instr=instr) pc += size + 1 if len(cur_blk.instructions) > 0 or cur_blk.offset - 1 in contr.jump_destination: contr.blocks.append(cur_blk) # Add CFG nodes, representing basic blocks cfg.graph.add_node(cur_blk.offset, blk=cur_blk) else: contr.blocks[-1].next = None return contr, dfg, cfg
if to_neighbour == 1: current_v = random.choice(adj_list[current_v]) else: others = [x for x in range(len(adj_list)) if x != current_v] current_v = random.choice(others) visit_counter[current_v] += 1 page_rank_list = [(idx, el/n) for idx, el in enumerate(visit_counter)] page_rank_list.sort(key=lambda l: l[1], reverse=True) for el in page_rank_list: print(f"{el[0]} ==> PageRank = {el[1]}") # print(page_rank_list) # return visit_counter if __name__ == "__main__": adj_list = [ [1, 3, 4], [2, 4], [1, 3, 5], [2], [1, 3, 5], [1] ] g = DiGraph(6) g.create_with_adj_list(adj_list) g.print() # digraph_plot(g.adj_matrix) random_walk(g.adj_list, 100000)
def setUp(self): print 'setUp w/prob1.twef' self.graph = DiGraph() if self.graph.import_twef('examples/prob1.twef'): assert False, "import_twef() fails"
class TestDiGraph(unittest.TestCase): def setUp(self): print 'setUp w/prob1.twef' self.graph = DiGraph() if self.graph.import_twef('examples/prob1.twef'): assert False, "import_twef() fails" def testTrivial(self): self.failUnless(True) def testRouteDistanceABC(self): self.failIf(self.graph.distance('ABC') != 9) def testRouteDistanceAD(self): self.failIf(self.graph.distance('AD') != 5) def testRouteDistanceADC(self): self.failIf(self.graph.distance('ADC') != 13) def testRouteDistanceAEBCD(self): self.failIf(self.graph.distance('AEBCD') != 22) def testRouteDistanceAED(self): self.failIf(self.graph.distance('AED') >= 0) def testNRforCCwhereStopsLT3Cyclic(self): (result, routes) = self.graph.get_routes('CC', 'cyclic', 'stops', 'lt', '3') print "result == {0}".format(result) print "routes == {0}".format(routes) self.failIf(result != 0) self.failIf(set(routes) != set(['CEBC', 'CDC'])) def testNRforACwhereStopsEQ3Cyclic(self): (result, routes) = self.graph.get_routes('AC', 'cyclic', 'stops', 'eq', '3') print "result == {0}".format(result) print "routes == {0}".format(routes) self.failIf(result != 0) self.failIf(set(routes) != set(['ABCDC', 'ADCDC', 'ADEBC'])) def testRShortestAC(self): (result, distance, route) = self.graph.get_shortest_distance('A', 'C') print "result == {0}".format(result) print "distance == {0}".format(distance) print "route == {0}".format(route) self.failIf(result != 0) self.failIf(route != 'ABC') self.failIf(distance != 9) def testRShortestBB(self): (result, distance, route) = self.graph.get_shortest_distance('B', 'B') print "result == {0}".format(result) print "distance == {0}".format(distance) print "route == {0}".format(route) self.failIf(result != 0) self.failIf(route != 'BCEB') self.failIf(distance != 9) def testNRforCCwhereDistanceLT30Cyclic(self): (result, routes) = self.graph.get_routes('CC', 'cyclic', 'distance', 'lt', '30') print "result == {0}".format(result) print "routes == {0}".format(routes) self.failIf(result != 0) self.failIf(set(routes) != set(['CEBC', 'CEBCEBC', 'CEBCEBCEBC', 'CEBCDC', 'CDC', 'CDCEBC', 'CDEBC']))
def main(args): """ ThoughtWorks Interactive Graph (TWIG) Command Line Interface (CLI) """ # Initialize a log file. This is a good habit for production-quality utilities/systems. if not os.path.isdir(os.path.join(os.getcwd(), '../log')): os.makedirs('../log') log_file = os.path.join(os.getcwd(), '../log', 'trace.log') if args.append: if args.debug: logging.basicConfig(filename=log_file, level=logging.DEBUG, filemode='a', format='%(asctime)s-%(msecs)d %(name)s %(levelname)s %(message)s', datefmt='%Y%m%d %H:%M:%S') else: logging.basicConfig(filename=log_file, level=logging.WARNING, filemode='a', format='%(asctime)s-%(msecs)d %(name)s %(levelname)s %(message)s', datefmt='%Y%m%d %H:%M:%S') else: if args.debug: logging.basicConfig(filename=log_file, level=logging.DEBUG, filemode='w', format='%(asctime)s-%(msecs)d %(name)s %(levelname)s %(message)s', datefmt='%Y%m%d %H:%M:%S') else: logging.basicConfig(filename=log_file, level=logging.WARNING, filemode='w', format='%(asctime)s-%(msecs)d %(name)s %(levelname)s %(message)s', datefmt='%Y%m%d %H:%M:%S') if args.verbose: logging.debug("Logging configured for %s", log_file) now = datetime.datetime.now() logging.debug("Starting ThoughtWorks coding-test-problem-1 command at %s", str(now)) # Initialize a class DiGraph object as per the CLI-supplied (TWEF-format) filename graph = DiGraph() if graph.import_twef(args.graph_filename): logging.debug("ABORT- graph.import_twef(%s) fails", args.graph_filename) return 0 logging.debug("graph.dump():\n%s", graph.dump()) edge_list = graph.edges() logging.debug("edge_list:\n%s", edge_list) # Delegate to the appropriate command handler (for this command line's query) if args.ikind.lower() == 'route': if not cmd_route(args, graph): logging.debug("cmd_route() succeeds") else: print 'Route command failed. Something went wrong! \nConsult {0}'.format(log_file) elif args.ikind.lower() == 'num_routes': if not cmd_num_routes(args, graph): logging.debug("cmd_num_routes() succeeds") else: print 'Num_routes command failed. Something went wrong! \nConsult {0}'.format(log_file) else: print 'Unrecognized command: {0}. No handler. Giving up.'.format(args.ikind.lower()) logging.debug("Logging complete for %s. Main() is done.", log_file) return 0
def test_get_path_returns_path_when_source_and_destination_are_same(): dg = DiGraph() dg.add_nodes_from([1, 2, 3, 4, 5]) assert get_path(dg, 1, 1) == [1]
# we need 3 flags (0, 1, 2) to check if there is a cycle. # 0=not visited, 1=in the process, 2=visited for node in g.get_vertices(): visited[node] = 0 # Go through each non-visited node and start a DFS from that node for node in g.get_vertices(): if visited[node] != 2: depth_traversal(g, node, visited, topology) # Reverse the topology and print print(topology[::-1]) return topology[::-1] if __name__ == '__main__': g = DiGraph() g.add_edge(6, 3) g.add_edge(3, 7) g.add_edge(3, 2) g.add_edge(1, 2) g.add_edge(10, 1) # g.add_edge(2, 8) # g.add_edge(5, 9) # g.add_edge(5, 4) # g.add_edge(4, 8) # g.add_edge(8, 6) try: topological_sort(g) except CycleException: print('Graph contains Cycle')
def test_source_is_reachable_from_source(): dg = DiGraph() dg.add_nodes_from([1, 2, 3, 4, 5]) assert is_reachable(dg, 1, 1)
class KnightsTour: def __init__(self, row, column): self.board = DiGraph() # Directed graph self.row = row self.column = column for r in range(row): for c in range(column): pos = (r * column) + c # For each position, find the valid moves and add as edges for neigh in self.get_neighs(r, c): self.board.add_edge(pos, neigh) def get_neighs(self, row, column): # For each position, there can be up to 8 valid moves moves = [(-2, -1), (-2, 1), (-1, -2), (-1, 2), (1, -2), (1, 2), (2, -1), (2, 1)] ret = [] for x, y in moves: n_row = row + x n_clm = column + y # If a valid move, add it to return list if 0 <= n_row < self.row and 0 <= n_clm < self.column: neigh = n_row * self.column + n_clm ret.append(neigh) return ret def order_by_avail(self, start, visited): ret = [] node = self.board.vert_list[start] for neigh in node.get_neighs(): if neigh in visited: continue c = 0 for next in self.board.vert_list[neigh].get_neighs(): if next not in visited: c += 1 # Out of for loop. C can be 0 also. Still need to include in ret ret.append((neigh, c)) # wrong because ret.sort return None # return [y[0] for y in ret.sort(key=lambda x:x[1])] return [y[0] for y in sorted(ret, key=lambda x: x[1])] def solve(self, start): visited = set() path = [] # passing of path technique happens with DFS return self._solve(start, path, visited) def _solve(self, start, path, visited): path.append(start) visited.add(start) # mark this node as visited if len(visited) == self.board.num_vert: # Visited all nodes print(path) return 1 count = 0 # for neigh in node.get_neighs(): for neigh in self.order_by_avail(start, visited): if neigh in visited: # neigh may get visited after getting it as list in order_by_avail continue count += self._solve(neigh, path, visited) # if self._solve(neigh, path, visited): # solve using neigh # If solved, Done # return True # Done with start. No path found through it. visited.remove(start) path.pop() return count
g.add_edge(1, 8, 3) g.add_edge(2, 4, 8) g.add_edge(2, 5, 2) g.add_edge(3, 8, 8) g.add_edge(3, 9, 9) g.add_edge(3, 10, 4) g.add_edge(4, 11, 5) g.add_edge(5, 6, 1) g.add_edge(5, 9, 3) g.add_edge(5, 10, 9) g.add_edge(6, 7, 8) g.add_edge(9, 10, 5) g.add_edge(9, 12, 10) g.add_edge(11, 12, 2) dijkstra(g, 1) g = DiGraph() g.add_edge(1, 3, 4) g.add_edge(1, 6, 3) g.add_edge(2, 1, -1) g.add_edge(2, 5, 6) g.add_edge(3, 2, 2) g.add_edge(3, 4, 1) g.add_edge(4, 6, 2) g.add_edge(5, 3, 3) g.add_edge(5, 6, -2) g.add_edge(6, 7, -1) g.add_edge(7, 5, 8) dijkstra(g, 1)
def generate_reverse_graph(self): self.rg = DiGraph(self.g.V) for i in range(self.rg.V): for j in self.g.adj(i): self.rg.add_edge(j, i)
class DigraphHasReachableVertex: def __init__(self, g): self.g = g self.rg = None self.done = [False]*self.g.V self.topo_order = [] self.cc_count = 0 self.cc_id = [-1]*self.g.V #Valid id are positive integeres starting from 1 self.generate_reverse_graph() self.populate_topo_order() self.cc_dag = DiGraph(0) self.populate_strongly_cc_dag() def populate_topo_order(self): for i in range(self.rg.V): if not self.done[i]: self.topo_util(i, self.rg) def get_reverse_topo_order(self): return list(reversed(self.topo_order)) def topo_util(self, v, g): self.done[v] = True for each in g.adj(v): if not self.done[each]: self.topo_util(each, g) self.topo_order.append(v) def generate_reverse_graph(self): self.rg = DiGraph(self.g.V) for i in range(self.rg.V): for j in self.g.adj(i): self.rg.add_edge(j, i) def populate_strongly_cc_dag(self): self.done = [False]*self.g.V for each in self.get_reverse_topo_order(): if not self.done[each]: self.cc_count += 1 self.cc_dag.add_vertex() self.cc_dfs(each) def cc_dfs(self, v): self.done[v] = True self.cc_id[v] = self.cc_count-1 for each in self.g.adj(v): if self.done[each] and self.cc_id[each] != self.cc_id[v]: self.cc_dag.add_edge(self.cc_count-1, self.cc_id[each]) if not self.done[each]: self.cc_dfs(each) def has_rechable_vertex(self): zero_degree_count = 0 for i in range(self.cc_dag.V): if len(self.cc_dag.adj(i))==0: zero_degree_count += 1 if zero_degree_count > 1: return False if zero_degree_count == 0: return False return True
sor = sorted(sor, key=itemgetter(1), reverse=True) alphabet = [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T' ] print('Ilość iteracji:', it) for i in range(len(sor)): print('{} ==> PageRank = {:.6f}'.format(alphabet[sor[i][0]], sor[i][1])) print() if __name__ == '__main__': adj_list = [[1, 3, 4], [2, 4], [1, 3, 5], [1], [1, 3, 5], [1]] adj_list = [[4, 5, 8], [0, 2, 5], [1, 3, 4, 11], [2, 4, 7, 8, 10], [2, 6, 7, 8], [1, 6], [4, 5, 7], [3, 6, 8, 11], [3, 4, 7, 9], [8], [3, 8], [0, 7]] adj_list = [[2], [4, 6], [3, 4, 5], [5], [5, 7], [1, 2, 3, 4, 7], [5], [0, 2, 3, 5, 6]] n = len(adj_list) g = DiGraph(n) g.create_with_adj_list(adj_list) page_rank(g)