def benchmark(pnml, engine, recursion_limit=None): # Set the recursion limit. if recursion_limit: previous_recursion_limit = sys.getrecurstionlimit sys.setrecursionlimit(recursion_limit) # Parse the pnml file to generate. pns = PetriNet.from_pnml(engine, pnml) print('%i Petri Net(s) found in the pnml file.' % len(pns)) # Benchmark tests. for id_, pn in pns.items(): print('Generate the state space for "%s".' % id_) start = time.time() state_space = pn.state_space() elapsed = time.time() - start print('\t%i state(s), computed in %f[s]' % (len(state_space), elapsed)) # Reset the recursion limit. if recursion_limit: sys.setrecursionlimit(previous_recursion_limit)
def generate_pnml(self, filename=None): filename = filename or self.get_def_pnml_name() net_name = os.path.basename(filename) net_id = net_name.replace(' ','_').lower() net = PetriNet(net_id=net_id,name=net_name) # Comenzamos con los Places (i.e. un place por cada inecuación) nbr_places = 0 places_list = [] for idx, place in enumerate(self.facets,1): nbr_places += 1 place_id = "place-%04d"%idx place_label = "%s"%place marking = abs(place.offset) Place(net, place_id, label=place_label, marking=marking) # Seguimos con las Transitions (i.e. una transition por cada variable) # Se crearán tantas transiciones como dimensiones del espacio nbr_transitions = 0 for idx in xrange(self.dim): if idx in self.reversed_dictionary: transition_id = self.reversed_dictionary.get(idx).replace(' ','_') transition_label = self.reversed_dictionary.get(idx) else: transition_id = 'trans-%04d'%(idx+1) transition_label = 'Transition %04d'%(idx+1) Transition(net, transition_id, label=transition_label) # Los arcos se arman relacionando los places con las transitions # Para cada inecuación, se crean un arco hacia la transition # (i.e. variable) con peso igual al coef que la acompaña # Salvo que sea 0, claro. # Para las transiciones que no tienen # al menos un elemento en el preset y uno en el postset # (i.e un arco que venga de una place y otra que salga hacia otro place) # le creamos un place ficticio para ponerlo en su pre y/o post needs_preset = set(range(self.dim)) needs_postset = set(range(self.dim)) arcs_list = [] seen_arcs = [] for pl_id,place in enumerate(self.facets,1): # Contamos desde uno place_id = 'place-%04d'%(pl_id) for tr_id, value in enumerate(place.normal): # Si es cero no crear el arco if not value: continue if tr_id in self.reversed_dictionary: transition_id = self.reversed_dictionary.get(tr_id).replace(' ','_') else: transition_id = 'trans-%04d'%(tr_id+1) if value > 0: if tr_id in needs_preset: # Puede que ya le hayamos creado un arco # entrante needs_preset.remove(tr_id) arc_id = 'arc-P%04d-T%s'%(pl_id,transition_id) # El arco sale de un place y va hacia una transition from_id = place_id to_id = transition_id else: if tr_id in needs_postset: # Puede que ya le hayamos creado un arco # saliente needs_postset.remove(tr_id) arc_id = 'arc-T%s-P%04d'%(transition_id,pl_id) from_id = transition_id to_id = place_id value = abs(value) # No debería pasar, pero por las dudas, # evitemos crear arcos repetidos if (from_id, to_id) in seen_arcs: print 'El arco está repetido!: ', from_id, to_id continue else: seen_arcs.append((from_id, to_id)) Arc(net, arc_id, from_id, to_id, value=value) # Generamos los places y arcos para los bucles de las transitions # desconectadas loops_list = [] for idx,tr_id in enumerate(needs_preset | needs_postset): pl_id = nbr_places + idx + 1 place_id = "place-%04d"%(pl_id) place_label = 'Dummy place %04d'%(idx+1) if tr_id in needs_preset: marking = 1 elif tr_id in needs_postset: marking = 0 else: raise Exception('No necesita pre ni post!') Place(net, place_id, place_label, marking) if tr_id in self.reversed_dictionary: transition_id = self.reversed_dictionary.get(tr_id).replace(' ','_') else: transition_id = 'trans-%04d'%(tr_id) if tr_id in needs_preset: # Si necesita preset, nos indica que la transición se puede # disparar siempre, por lo que generamos un loop # con el dummy-place arc_id = 'arc-P%04d-T%s'%(pl_id,transition_id) Arc(net, arc_id, transition_id,place_id, 1) Arc(net, arc_id, place_id, transition_id, 1) elif tr_id in needs_postset: # Lo agregamos al postset de la transición como una # especie de "/dev/null" donde tirar los markings generados arc_id = 'arc-T%s-P%04d'%(tr_id,pl_id) Arc(net, arc_id, transition_id,place_id, 1) net.save(filename=filename) logger.info('Generated the PNML %s', filename) return True