def dag(graph): # explore: find cyclic path # # Input: node # path # # Output: True iff there is a cyclic path starting at node, and # whole 1st elements coincide with path def explore(node, path=[]): explored.add(node) linked = adjacency[node] for succ in linked: if succ == node: continue if succ in path: return True if explore(succ, path + [node]): return True return False m, _, adjacency = create_adjacency(graph, False) explored = set() for a, _ in adjacency.items(): if not a in explored: if explore(a): return -1 return 1
def hdag(graph): def clone(adj): copy = {} for k,v in adj.items(): copy[k]=v return copy _,_,adj = create_adjacency(graph,back=False,self=False) ordered = topological_order(clone(adj)) # use clone because topological_order destroys its parameter for a,b in zip(ordered[:-1],ordered[1:]): if not b in adj[a]: return (-1,[]) return (1,ordered)
def cc(graph): def explore(a, adjacency, explored, component): explored.add(a) component.append(a) for b in adjacency[a]: if not b in explored: explore(b, adjacency, explored, component) return sorted(list(set(component))) m, _, adjacency = create_adjacency(graph) explored = set() components = {} # The connected components, with one element as key for a, _ in adjacency.items(): if not a in explored: component = explore(a, adjacency, explored, []) for c in component: components[c] = component count = 0 uniques = [] duplicates = [] for k, v in components.items(): if k in uniques: duplicates.append(k) else: for vv in v: uniques.append(vv) count += 1 for d in duplicates: del components[d] # a few sanity checks nodes = sorted(list(set([v for k, vs in components.items() for v in vs]))) assert len(nodes) == m, '{0} not {1}'.format(len(nodes), m) v0 = 0 for v in nodes: assert v == v0 + 1 v0 = v return count, components
def bip(graph): red = set() blue = set() # colour # # Attempt to assign this node, and all reachable nodes, to one colour or t'other # # Inputs: node The node we are assigning # isBlue Indicates whether we are trying Red or Blue def colour(node, isBlue): if isBlue: if node in red: return False if node in blue: return True blue.add(node) else: if node in blue: return False if node in red: return True red.add(node) for link in adjacency[node]: if not colour(link, not isBlue): return False return True _, _, adjacency = create_adjacency(graph, back=True, self=False) # Purge isolated nodes for k in [k for k, v in adjacency.items() if len(v) == 0]: adjacency.pop(k) # Try to colour nodes for node in adjacency.keys(): if node in red or node in blue: continue red.add(node) for link in adjacency[node]: coloured = colour(link, True) if not coloured: return -1 return 1 # assume bipartite unless we fail
# # This is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This software is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Emacs. If not, see <http://www.gnu.org/licenses/> # # TS Topological sort from align import topological_order from helpers import parse_graph, create_adjacency, format_list if __name__ == '__main__': with open(r'C:\Users\Simon\Downloads\rosalind_ts.txt') as f: g = parse_graph(f) _, _, adj = create_adjacency(g, back=False) for k, v in adj.items(): if k in v: v.remove(k) t = topological_order(adj) print(format_list(t))