def CreateDirectedEdges(self, points, gr, layer_width): """ Take each key (ie. point) in the graph and for that point create an edge to every point downstream of it where the weight of the edge is the tuple (distance, angle) """ for z0, x0, Q0 in points: for z1, x1, Q1 in points: dz = z1 - z0 # no fabs because we check arrow direction if dz > 0.0: # make sure arrow in right direction if dz - layer_width < distance_threshold: # only adjacents dx = math.fabs(x1 - x0) if dx > 5 * bar_width: continue # Weights are negative to in order to use shortest path # algorithms on the graph. weight = -1 * math.hypot(dz, dx) edge = ((z0, x0, Q0), (z1, x1, Q1)) gr.add_edge(edge, wt=weight) # Ensure that it is already transitively reduced assert len(critical.transitive_edges(gr)) == 0 return gr
def _remove_useless_deps(graph): """ Remove useless dependencies such as: A->B->C, A->C. In such a case, A->C is useless. Such edge will be removed in the given graph. """ useless_edges = transitive_edges(graph) for edge in set(useless_edges): _LOGGER.info("Removing useless dependency: %s", edge) graph.del_edge(edge)
def reducegraph(edges): g = digraph() nodes = set() for (x, y) in edges: if x not in nodes: nodes.add(x) g.add_node(x) if y not in nodes: nodes.add(y) g.add_node(y) g.add_edge((x,y)) for (x,y) in transitive_edges(g): if (x,y) in edges: edges.remove((x,y)) return edges
def tldGraph(edgeList, dotPath, aspectRatio): # Graph creation gr = digraph() # Compute nodes from list of edges nodes = set() for edge in edgeList: nodes.add(edge[0]) nodes.add(edge[1]) # Add nodes to graph gr.add_nodes(list(nodes)) # Add edges to graph for edge in edgeList: gr.add_edge(edge) # Compute transitive edges tr = transitive_edges(gr) # Only display non-transitive edges ntrEdges = set(list(edgeList)).difference(set(tr)) # Visualization dgr = pydot.Dot(graph_type='digraph') dgr.set_ranksep(0.2) dgr.set_nodesep(0.05) # dgr.set_ratio(1) dgr.set_ratio(aspectRatio) dgr.set_margin(0) # dgr.set_aspect(1) # AW < 14 dgr.set_node_defaults(fontname="Arial") for edge in ntrEdges: dgr.add_edge(pydot.Edge(edge[0], edge[1])) # Draw as PDF dgr.write_pdf(dotPath)
def test_transitivity(self): G = generate_test_graph() G.add_edge((2, 5), 1) #add another transitive edge assert transitive_edges(G) == [(1, 3), (2, 5)]
def test_transitivity_with_cycle(self): G = generate_test_graph() G.add_edge((5, 2), 3) #add cycle assert transitive_edges(G) == []
def test_transitivity(self): G = generate_test_graph() G.add_edge((2,5),1)#add another transitive edge assert transitive_edges(G) == [(1,3),(2,5)]
def test_transitivity_with_cycle(self): G = generate_test_graph() G.add_edge((5,2),3)#add cycle assert transitive_edges(G) == []
def convert_history(files, tasks, releases, objects): """Converts the Synergy history between two releases to a Git compatible one.""" log.basicConfig(filename="convert_history.log", level=log.DEBUG) file_objects = [ccm_cache.get_object(o) for o in objects] log.info("Looking for cycles in the File History graph") while find_cycle(files): cycle = find_cycle(files) log.info("\tA cycle was found!") log.info("\tCycle: %s" % ", ".join(cycle)) # Find the newest file newest = max( cycle, key=lambda x: [ fileobject.get_integrate_time() for fileobject in file_objects if fileobject.get_objectname() == x ][0], ) log.info("\tObject %s is the newest in the cycle: it should not have successors!" % newest) # Remove the outgoing link from the newest file for successor in files.neighbors(newest): if successor in cycle: files.del_edge((newest, successor)) log.info("\tRemoved the %s -> %s edge" % (newest, successor)) log.info("Remove transitive edges in the File History graph") for edge in transitive_edges(files): if edge in files.edges(): files.del_edge(edge) else: log.warning("Weird, transitive edge not found!") log.info("Sanitize tasks") sanitized_tasks = _sanitize_tasks(tasks) log.info("Create commits graph") commits = create_commits_graph(files, sanitized_tasks, releases) # Uncomment for debug... (remember import) # hack = {'previous': releases.edges()[0]} # htg.commit_graph_to_image(commits, hack, tasks, name='Pre-'+releases.edges()[1]) log.info("Looking for cycles in the Commits graph") while find_cycle(commits): log.info("Finding strictly connected components") cycle = max(mutual_accessibility(commits).values(), key=len) # cycle = find_cycle(commits) log.info("\tA cycle was found!") log.info("\tCycle: %s" % ", ".join(cycle)) log.info("Find the nodes in the cycle going from one task to another") culpript_edges = [] for task in cycle: for obj in tasks.links(task): for neighbor in files.neighbors(obj): if neighbor not in tasks.links(task) and tasks.links(neighbor)[0] in cycle: culpript_edges.append((obj, neighbor)) log.info("\tAdding culpript edge (%s, %s)" % (obj, neighbor)) log.info("Connect the nodes found") culpript_nodes = set() for head, tail in culpript_edges: culpript_nodes.add(head) culpript_nodes.add(tail) for head, tail in permutations(culpript_nodes, 2): if tasks.links(head)[0] == tasks.links(tail)[0] and (head, tail) not in culpript_edges: log.info("\tAdding edge (%s, %s)" % (head, tail)) culpript_edges.append((head, tail)) reduced_digraph = digraph() reduced_digraph.add_nodes(culpript_nodes) [reduced_digraph.add_edge(edge) for edge in culpript_edges] shortest_cycle = max(mutual_accessibility(reduced_digraph).values(), key=len) log.info("Cycle in objects: %s" % shortest_cycle) candidate_cuts = [] # Find the tasks t = set() for node in shortest_cycle: t.add(tasks.links(node)[0]) log.info("T: %s" % str(t)) for i in t: log.info("Cuts for task %s" % i) # Find the objects in the cycle belonging to task i obj_in_task = set(tasks.links(i)) & set(shortest_cycle) log.info("Objects in cycle and task: %s" % obj_in_task) if len(obj_in_task) < 15: if len(obj_in_task) > 1: for j in range(1, len(obj_in_task) / 2 + 1): candidate_cuts.extend([k for k in combinations(obj_in_task, j)]) else: log.info("Cycle too long...") pass log.info("Candidate_cuts: %s" % str(candidate_cuts)) # Find the cut to break the cycle cut = _find_cut(candidate_cuts, cycle, tasks, files, releases) if not cut: # Make a qualified guess of a cut with the shortest walk of files in the tasks walk, node = _find_shortest_incident_or_neighbor_walk(shortest_cycle, cycle, files, tasks) new_cut = walk new_cut.append(node) candidate_cuts.insert(0, tuple(new_cut)) log.info("Candidate cuts: %s", candidate_cuts) cut = _find_cut(candidate_cuts, cycle, tasks, files, releases) if not cut: # Error! This should not happen log.info("Cut not found.") log.shutdown() raise Exception("Cut not found") tasks, task, task_name = _apply_cut(cut, tasks) commits = create_commits_graph(files, tasks, releases) else: log.info("No cycles found") log.shutdown() return commits
sys.path.append('..') import pygraph from pygraph.algorithms.critical import transitive_edges, critical_path #demo of the critical path algorithm and the transitivity detection algorithm G = pygraph.digraph() G.add_node('A') G.add_node('B') G.add_node('C') G.add_node('D') G.add_node('E') G.add_node('F') G.add_edge('A','B',1) G.add_edge('A','C',2) G.add_edge('B','C',10) G.add_edge('B','D',2) G.add_edge('B','E',8) G.add_edge('C','D',7) G.add_edge('C','E',3) G.add_edge('E','D',1) G.add_edge('D','F',3) G.add_edge('E','F',1) #add this edge to add a cycle #G.add_edge('E','A',1) print transitive_edges(G) print critical_path(G)
def convert_history(files, tasks, releases, fileobjects): """Converts the Synergy history between two releases to a Git compatible one.""" #print "Look for cycles in the File History graph" while find_cycle(files): cycle = find_cycle(files) #print "A cycle was found!" #print "Cycle:", cycle # Find the newest file newest = max(cycle, key=lambda x: [fileobject.get_integrate_time() for fileobject in fileobjects if fileobject.get_objectname == x][0]) #print "Object %s is the newest in the cycle: it should not have successors!" % newest # Remove the outgoing link from the newest file for successor in files.neighbors(newest): if successor in cycle: files.del_edge((newest, successor)) #print "Removed the %s -> %s edge" % (newest, successor) [files.del_edge(edge) for i, edge in transitive_edges(files)] #print "Removed transitive edges from the File History graph." sanitized_tasks = _sanitize_tasks(tasks) #print "Tasks hypergraph sanitized." commits = create_commits_graph(files, sanitized_tasks, releases) #print "First commits graph created." # Cycles detection while find_cycle(commits): cycle = find_cycle(commits) #print "Cycles found!" #print "Cycle:", cycle # Generate the reduced file history graph reduced_graph = _create_reduced_graph(files, tasks, cycle) #print "Reduced graph:", reduced_graph # Find the longest cycle in the reduced graph longest_cycle = max(mutual_accessibility(reduced_graph).values(), key=len) candidate_cuts = [] for edge in zip(longest_cycle, longest_cycle[1:] + longest_cycle[0:1]): node1, node2 = edge # Find to which task the edge belongs to if tasks.links(node1) == tasks.links(node2): task = tasks.links(node1)[0] # Find which cuts are compatible and add them to the candidates list candidate_cuts.extend( [cut for cut in _find_cuts(tasks.links(task)) if (node1 in cut and node2 not in cut) or (node2 in cut and node2 not in cut)]) #print "Candidate_cuts:", candidate_cuts for (counter, cut) in enumerate(candidate_cuts): #print "Cut:", cut # Apply the cut task = tasks.links(cut[0])[0] # All the nodes in the cut belong to the same task and there are no overlapping tasks task_name = "" for i in count(1): task_name = task + "_" + str(i) if task_name not in tasks.edges(): #print "Adding task", task_name tasks.add_edge(task_name) break for node in cut: #print "Unlinking file %s from task %s" % (node, task) tasks.unlink(node, task) tasks.graph.del_edge(((node,'n'), (task,'h'))) # An ugly hack to work around a bug in pygraph #print "Linking file %s to task %s" % (node, task_name) tasks.link(node, task_name) # If no more cycles are found in the updated reduced graph then break commits2 = create_commits_graph(files, tasks, releases) cycle2 = find_cycle(commits2) if set(cycle) & set(cycle2) == set(cycle): # Undo the changes! #print "The cycle was not removed. Undoing changes..." #print "\tDeleting task", task_name tasks.del_edge(task_name) for node in cut: #print "\tLinking file %s to task %s" % (node, task) tasks.link(node, task) #print "Done." else: #print "Cut found." commits = create_commits_graph(files, tasks, releases) break #else: # Error! This should not happen #print "Cut not found." #else: #print "No cycles found" return commits
def convert_history(files, tasks, releases, objects): """Converts the Synergy history between two releases to a Git compatible one.""" log.basicConfig(filename='convert_history.log', level=log.DEBUG) file_objects = [ccm_cache.get_object(o) for o in objects] log.info("Looking for cycles in the File History graph") while find_cycle(files): cycle = find_cycle(files) log.info("\tA cycle was found!") log.info("\tCycle: %s" % ", ".join(cycle)) # Find the newest file newest = max(cycle, key=lambda x: [ fileobject.get_integrate_time() for fileobject in file_objects if fileobject.get_objectname() == x ][0]) log.info( "\tObject %s is the newest in the cycle: it should not have successors!" % newest) # Remove the outgoing link from the newest file for successor in files.neighbors(newest): if successor in cycle: files.del_edge((newest, successor)) log.info("\tRemoved the %s -> %s edge" % (newest, successor)) log.info("Remove transitive edges in the File History graph") for edge in transitive_edges(files): if edge in files.edges(): files.del_edge(edge) else: log.warning("Weird, transitive edge not found!") log.info("Sanitize tasks") sanitized_tasks = _sanitize_tasks(tasks) log.info("Create commits graph") commits = create_commits_graph(files, sanitized_tasks, releases) # Uncomment for debug... (remember import) #hack = {'previous': releases.edges()[0]} #htg.commit_graph_to_image(commits, hack, tasks, name='Pre-'+releases.edges()[1]) log.info("Looking for cycles in the Commits graph") while find_cycle(commits): log.info("Finding strictly connected components") cycle = max(mutual_accessibility(commits).values(), key=len) #cycle = find_cycle(commits) log.info("\tA cycle was found!") log.info("\tCycle: %s" % ", ".join(cycle)) log.info("Find the nodes in the cycle going from one task to another") culpript_edges = [] for task in cycle: for obj in tasks.links(task): for neighbor in files.neighbors(obj): if neighbor not in tasks.links(task) and tasks.links( neighbor)[0] in cycle: culpript_edges.append((obj, neighbor)) log.info("\tAdding culpript edge (%s, %s)" % (obj, neighbor)) log.info("Connect the nodes found") culpript_nodes = set() for head, tail in culpript_edges: culpript_nodes.add(head) culpript_nodes.add(tail) for head, tail in permutations(culpript_nodes, 2): if tasks.links(head)[0] == tasks.links(tail)[0] and ( head, tail) not in culpript_edges: log.info("\tAdding edge (%s, %s)" % (head, tail)) culpript_edges.append((head, tail)) reduced_digraph = digraph() reduced_digraph.add_nodes(culpript_nodes) [reduced_digraph.add_edge(edge) for edge in culpript_edges] shortest_cycle = max(mutual_accessibility(reduced_digraph).values(), key=len) log.info("Cycle in objects: %s" % shortest_cycle) candidate_cuts = [] # Find the tasks t = set() for node in shortest_cycle: t.add(tasks.links(node)[0]) log.info("T: %s" % str(t)) for i in t: log.info("Cuts for task %s" % i) # Find the objects in the cycle belonging to task i obj_in_task = set(tasks.links(i)) & set(shortest_cycle) log.info("Objects in cycle and task: %s" % obj_in_task) if len(obj_in_task) < 15: if len(obj_in_task) > 1: for j in range(1, len(obj_in_task) / 2 + 1): candidate_cuts.extend( [k for k in combinations(obj_in_task, j)]) else: log.info("Cycle too long...") pass if len(candidate_cuts) < 50: log.info("Candidate_cuts: %s" % str(candidate_cuts)) # Find the cut to break the cycle cut = _find_cut(candidate_cuts, cycle, tasks, files, releases) if not cut: log.info("Shortest cycle cut didn't work, next option...") # Make a qualified guess of a cut with the shortest walk of files in the tasks walk, node = _find_shortest_incident_or_neighbor_walk( shortest_cycle, cycle, files, tasks) log.info("Shortest incident or neighbor walk from {0}: {1}".format( node, walk)) new_cut = walk new_cut.append(node) candidate_cuts.insert(0, tuple(new_cut)) log.info("Candidate cuts: %s", candidate_cuts) cut = _find_cut(candidate_cuts, cycle, tasks, files, releases) if not cut: # Error! This should not happen log.info("Cut not found.") log.shutdown() raise Exception("Cut not found") tasks, task, task_name = _apply_cut(cut, tasks) commits = create_commits_graph(files, tasks, releases) else: log.info("No cycles found") log.shutdown() return commits
print "Breadth first search" print "Spanning tree" print bfs print "level-based ordering" print bfsord print "\n" print "Accessibility" access= accessibility(gr) print access print "Mutual accessibility" maccess= mutual_accessibility(gr) print maccess print "\n" print "Traversal" trav= traversal(gr, 'A', 'pre') for t in trav: print t print "Transitive Edges" tredges= transitive_edges(gr) print tredges print "\n" print "shortest_path_bellman_ford" short= shortest_path_bellman_ford(gr, 'A') print short print "shortest_path" shrt= shortest_path(gr, 'A') print shrt