def _validate_no_group_cycles(member_graph): # verify no group cycles (i.e. group A in group B and vice versa) group_cycles = nx.recursive_simple_cycles(member_graph) if group_cycles: raise exceptions.DSLParsingLogicException( exceptions.ERROR_GROUP_CYCLE, 'Illegal group cycles found: {0}'.format(group_cycles))
def test_bidirectional(self): """ m1 <-> m2 -> m3 """ self.g.add_edge('m1','m2') self.g.add_edge('m2','m3') self.g.add_edge('m3','m2') self.g.add_edge('m3','m4') # remove any models that done have links #for # determine cycles cycles = n.recursive_simple_cycles(self.g) for cycle in cycles: # remove edges that form cycles self.g.remove_edge(cycle[0],cycle[1]) # perform toposort order = n.topological_sort(self.g) # re-add bidirectional dependencies (i.e. cycles) for cycle in cycles: # find index of inverse link for i in xrange(0,len(order)-1): if order[i] == cycle[1] and order[i+1] == cycle[0]: order.insert(i+2, cycle[1]) order.insert(i+3,cycle[0]) break self.assertTrue(''.join(order) == 'm1m2m3m2m3m4')
def update_cycle_counts(self, time_step): """ This method makes use of the recursive_simple_cycles() function of NetworkX to offload all the work of finding cycles in the graph. Yay! The lengths of the cycles are added to the ProductRuleNet's field named cycle_counts. NOTE: the list the algorithm returns is of list of nodes in the cycle where the last one is dropped because it is the same as the first. Thus a (sub) list of length 2 is not a self-loop, but a path from one node to another and back and cycles must be of length two or greater. """ cycles = networkx.recursive_simple_cycles(self.net) self.cycle_counts = {} for i in cycles: length = len(i) try: self.cycle_counts[length] += 1 except: self.cycle_counts[length] = 1 # If there are no cycles, this run is dead and we need to send word if len(cycles) == 0: self.has_cycles = False return False else: return True
def test_simple_graph_with_reported_bug(self): G = nx.DiGraph() edges = [ (0, 2), (0, 3), (1, 0), (1, 3), (2, 1), (2, 4), (3, 2), (3, 4), (4, 0), (4, 1), (4, 5), (5, 0), (5, 1), (5, 2), (5, 3), ] G.add_edges_from(edges) cc = sorted(nx.simple_cycles(G)) assert len(cc) == 26 rcc = sorted(nx.recursive_simple_cycles(G)) assert len(cc) == len(rcc) for c in cc: assert any(self.is_cyclic_permutation(c, rc) for rc in rcc) for rc in rcc: assert any(self.is_cyclic_permutation(rc, c) for c in cc)
def get_cycle_complexity(self): """ This function looks at the cycles that are longer than two. """ cycles = networkx.recursive_simple_cycles(self.net) complexities = {} # keys are lengths, entries are # of distinct rules. rule_owners = {} for cycle in cycles: if len(cycle) > 2: length = len(cycle) types = {} owners = {} for rule in cycle: type = str(rule.get_input()) + "-" +str(rule.get_output()) owner = rule.get_owner() try: types[type] += 1 except: types[type] = 1 try: owners[owner] +=1 except: owners[owner] = 1 count_owners = len(owners.keys()) count_types = len(types.keys()) try: complexities[length].append((count_types,count_owners)) except: complexities[length] = [(count_types,count_owners)] return complexities
def test_bidirectional(self): """ m1 <-> m2 -> m3 """ self.g.add_edge('m1', 'm2') self.g.add_edge('m2', 'm3') self.g.add_edge('m3', 'm2') self.g.add_edge('m3', 'm4') # remove any models that done have links #for # determine cycles cycles = n.recursive_simple_cycles(self.g) for cycle in cycles: # remove edges that form cycles self.g.remove_edge(cycle[0], cycle[1]) # perform toposort order = n.topological_sort(self.g) # re-add bidirectional dependencies (i.e. cycles) for cycle in cycles: # find index of inverse link for i in xrange(0, len(order) - 1): if order[i] == cycle[1] and order[i + 1] == cycle[0]: order.insert(i + 2, cycle[1]) order.insert(i + 3, cycle[0]) break self.assertTrue(''.join(order) == 'm1m2m3m2m3m4')
def test_simple_graph_with_reported_bug(self): G = nx.DiGraph() edges = [ (0, 2), (0, 3), (1, 0), (1, 3), (2, 1), (2, 4), (3, 2), (3, 4), (4, 0), (4, 1), (4, 5), (5, 0), (5, 1), (5, 2), (5, 3), ] G.add_edges_from(edges) cc = sorted(nx.simple_cycles(G)) assert_equal(len(cc), 26) rcc = sorted(nx.recursive_simple_cycles(G)) assert_equal(len(cc), len(rcc)) for c in cc: assert_true(any(self.is_cyclic_permutation(c, rc) for rc in rcc)) for rc in rcc: assert_true(any(self.is_cyclic_permutation(rc, c) for c in cc))
def test_recursive_simple_and_not(self): for k in range(2,10): G=self.worst_case_graph(k) cc=sorted(nx.simple_cycles(G)) rcc=sorted(nx.recursive_simple_cycles(G)) assert_equal(len(cc),len(rcc)) for c in cc: assert_true(any(self.is_cyclic_permutation(c,rc) for rc in rcc))
def return_cycles(self): """ A direct route to the NetworkX simple cycles finding function. This method is only ever used in debugging because the method update_cycle_counts() below packages the information in a more useful way """ return networkx.recursive_simple_cycles(self.net)
def elements_graph_topological_sort(self): try: return nx.topological_sort(self.element_graph) except nx.NetworkXUnfeasible: # Cycle detected cycle = nx.recursive_simple_cycles(self.element_graph)[0] names = [str(e.name) for e in cycle] names.append(str(names[0])) ex = exceptions.DSLParsingLogicException( exceptions.ERROR_CODE_CYCLE, 'Parsing failed. Circular dependency detected: {0}'.format( ' --> '.join(names))) ex.circular_dependency = names raise ex
def elements_graph_topological_sort(self): try: return nx.topological_sort(self.element_graph) except nx.NetworkXUnfeasible: # Cycle detected cycle = nx.recursive_simple_cycles(self.element_graph)[0] names = [str(e.name) for e in cycle] names.append(str(names[0])) ex = exceptions.DSLParsingLogicException( exceptions.ERROR_CODE_CYCLE, 'Parsing failed. Circular dependency detected: {0}' .format(' --> '.join(names))) ex.circular_dependency = names raise ex
def determine_execution_order(self): """ determines the order in which models will be executed. def get_link(self): return [self.__from_lc,self.__from_item], [self.__to_lc,self.__to_item] """ g = net.DiGraph() # add models as graph nodes #for name,model in self.__models.iteritems(): # g.add_node(model.get_id()) # create links between these nodes for id, link in self.__links.iteritems(): f, t = link.get_link() from_node = f[0].get_id() to_node = t[0].get_id() g.add_edge(from_node, to_node) # determine cycles cycles = net.recursive_simple_cycles(g) for cycle in cycles: # remove edges that form cycles g.remove_edge(cycle[0],cycle[1]) # perform toposort order = net.topological_sort(g) # re-add bidirectional dependencies (i.e. cycles) for cycle in cycles: # find index of inverse link for i in xrange(0,len(order)-1): if order[i] == cycle[1] and order[i+1] == cycle[0]: order.insert(i+2, cycle[1]) order.insert(i+3,cycle[0]) break # return execution order return order
def determine_execution_order(self): """ determines the order in which models will be executed. def get_link(self): return [self.__from_lc,self.__from_item], [self.__to_lc,self.__to_item] """ g = net.DiGraph() # add models as graph nodes #for name,model in self.__models.iteritems(): # g.add_node(model.get_id()) # create links between these nodes for id, link in self.__links.iteritems(): f, t = link.get_link() from_node = f[0].get_id() to_node = t[0].get_id() g.add_edge(from_node, to_node) # determine cycles cycles = net.recursive_simple_cycles(g) for cycle in cycles: # remove edges that form cycles g.remove_edge(cycle[0], cycle[1]) # perform toposort order = net.topological_sort(g) # re-add bidirectional dependencies (i.e. cycles) for cycle in cycles: # find index of inverse link for i in xrange(0, len(order) - 1): if order[i] == cycle[1] and order[i + 1] == cycle[0]: order.insert(i + 2, cycle[1]) order.insert(i + 3, cycle[0]) break # return execution order return order
def _create_loops(self): points = [] g_cities = nx.DiGraph() for city in self.cities: city = self.cities.get(city) g_cities.add_node('f-' + str(city.id), bipartite=0) g_cities.add_node('t-' + str(city.id), bipartite=1) points.append([city.x, city.y]) points = np.array(points) vor = Voronoi(points, incremental=True) for point in vor.ridge_points: self.cities[point[0]].add_neighbor(self.cities[point[1]]) self.cities[point[1]].add_neighbor(self.cities[point[0]]) g_cities.add_edge('f-' + str(self.cities[point[0]]), 't-' + str(self.cities[point[1]])) g_cities.add_edge('f-' + str(self.cities[point[1]]), 't-' + str(self.cities[point[0]])) temp = bipartite.maximum_matching(g_cities) print(temp) del g_cities islands = nx.DiGraph() i = 0 for key, value in temp.items(): # connect cities ... self.cities[int(key[2:])].connect_to(self.cities[int(value[2:])]) islands.add_edge(self.cities[int(key[2:])], self.cities[int(value[2:])]) i += 1 if (i >= temp.__len__() / 2): break for i, c in enumerate(nx.recursive_simple_cycles(islands)): # for i, c in enumerate(nx.simple_cycles(islands)): loop = Loop(c, i) self._loops.append(loop) self.loops.add(i)
node_groups = [] trues = [] ands = [] # Pseudocode # Go through graph in reverse order # Get all the direct descendants of a node # These must be conflicts or dependencies # So And([list of direct descendants]) # Inside the And we also may have Or, which would be the optional dependency groups # Then get the direct descendents of these nodes etc. etc. # Eventually we will have translated the whole graph structure to a SAT problem, can solve this and get what we need # to install cycles = nx.recursive_simple_cycles(G) for cycle in cycles: G.remove_nodes_from(cycle[1:]) for n in G.nodes(data=True): direct_descendants = G[n[0]].keys() nodes = G.nodes(data=True) node_descendant = [] var_groups = {} for descendant in direct_descendants: if 'conflict' in nodes[descendant].keys( ) and nodes[descendant]['conflict'] is True: v = Bool(descendant) node_descendant.append(Not(v)) var_mapping[descendant] = v elif 'required' in nodes[descendant].keys(
# -*- coding:utf8 -*- import networkx as nx import matplotlib.pyplot as plt G = nx.DiGraph() edgelist = [] with open('D:\Test\data\GUARANTEECIRCLE.del', mode='rb') as f: for line in f: data = line.decode('gbk', 'ignore').strip().split("|") if data[0] is not None and data[1] is not None and len( data[0]) > 0 and len(data[1]) > 0: # print(data[0], data[1]) G.add_edge(data[0], data[1]) # edgelist.append((data[0], data[1])) # edgelist = [('a', 'c'), ('a', 'e'), ('b', 'a'), ('c', 'd'), ('d', 'b'), ('e', 'b')] nx.draw(G, with_labels=True) plt.show() G.add_edges_from(edgelist) print(list(nx.recursive_simple_cycles(G)))