def check_source_and_sink_reachability(net, unique_source, unique_sink): """ Checks reachability of the source and the sink place from all simulation nodes (places/transitions) of the Petri net Parameters ------------- net Petri net unique_source Unique source place of the Petri net unique_sink Unique sink place of the Petri net Returns ------------- boolean Boolean value that is true if each node is in a path from the source place to the sink place """ import networkx as nx graph, unique_source_corr, unique_sink_corr, inv_dictionary = create_networkx_undirected_graph( net, unique_source, unique_sink) if unique_source_corr is not None and unique_sink_corr is not None: nodes_list = list(graph.nodes()) finish_to_sink = list(nx.ancestors(graph, unique_sink_corr)) connected_to_source = list(nx.descendants(graph, unique_source_corr)) if len(finish_to_sink) == len(nodes_list) - 1 and len( connected_to_source) == len(nodes_list) - 1: return True return False
def connected(student_answer): """ Checks if the student_answer petri net is a (weakly) connected graph. """ # Turn PetriNet object into NetworkX directed graph normal_graph, _, _, table = create_networkx_undirected_graph( student_answer, None, None) if nx.is_connected(normal_graph): return {'correct': True} else: return {'correct': False, 'feedback': 'Graph is not connected.'}
def create_networkx_graph(net, initial_marking, final_marking): nx_graph, unique_source_corr, unique_sink_corr, inv_dict = \ networkx_graph.create_networkx_undirected_graph(net, initial_marking, final_marking) inv_inv_dict = {y: x for x, y in inv_dict.items()} return nx_graph, inv_inv_dict