def updateVectors(self, decay_values, last_activation, token_counts, activated_places, current_time): """ Update Decay Values """ for place in self.net.places: if last_activation[str(place)] == -1: decay_values[str(place)] = 0.0 else: delta = time_delta_seconds(last_activation[str(place)], current_time) decay_values[str(place)] = self.decay_functions[str( place)].decay(delta) """ Update Token Counts """ for place in activated_places: token_counts[str(place)] += 1 return decay_values, token_counts
def getMaxTraceDuration(self): """ trace duration is measured in seconds """ max_trace_duration = 0 for trace in self.log: if len(trace) < 2: self.ignored_traces.add(trace.attributes['concept:name']) seconds = time_delta_seconds(trace[0]['time:timestamp'], trace[-1]['time:timestamp']) if seconds > max_trace_duration: max_trace_duration = seconds if max_trace_duration <= 0: raise ValueError( 'The maximum trace duration of the event log is smaller or equal to 0ms' ) return max_trace_duration
def enhance(self, log_wrapper: LogWrapper): """ Enhance a given petri net based on an event log. :param log_wrapper: Event log under consideration as LogWrapper :return: None """ """ Standard Enhancement """ beta = float(10) reactivation_deltas = {} for place in self.net.places: reactivation_deltas[str(place)] = list() log_wrapper.iterator_reset() last_activation = {} pbar = tqdm(total=log_wrapper.num_traces, desc="Replay for Process Model Enhancement") while log_wrapper.iterator_hasNext(): trace = log_wrapper.iterator_next() pbar.update(1) for place in self.net.places: if place in self.initial_marking: last_activation[str(place)] = trace[0]['time:timestamp'] else: last_activation[str(place)] = -1 """ Replay and estimate parameters """ places_shortest_path_by_hidden = get_places_shortest_path_by_hidden( self.net, self.MAX_REC_DEPTH) marking = copy(self.initial_marking) for event in trace: if event[self.activity_key] in self.trans_map.keys(): activated_places = [] toi = self.trans_map[event[self.activity_key]] """ If Transition of interest is not enabled yet, then go through hidden""" if not semantics.is_enabled(toi, self.net, marking): _, _, act_trans, _ = apply_hidden_trans( toi, self.net, copy(marking), places_shortest_path_by_hidden, [], 0, set(), [copy(marking)]) for act_tran in act_trans: for arc in act_tran.out_arcs: activated_places.append(arc.target) marking = semantics.execute( act_tran, self.net, marking) """ If Transition of interest is STILL not enabled yet, then naively add missing token to fulfill firing rule """ if not semantics.is_enabled(toi, self.net, marking): for arc in toi.in_arcs: if arc.source not in marking: marking[arc.source] += 1 """ Fire transition of interest """ for arc in toi.out_arcs: activated_places.append(arc.target) marking = semantics.execute(toi, self.net, marking) """ Marking is gone - transition could not be fired ...""" if marking is None: raise ValueError("Invalid Marking - Transition " + toi + " could not be fired.") """ Update Time Recordings """ for activated_place in activated_places: if last_activation[str(activated_place)] != -1: time_delta = time_delta_seconds( last_activation[str(activated_place)], event['time:timestamp']) if time_delta > 0: # noinspection PyUnboundLocalVariable reactivation_deltas[str(place)].append( time_delta) last_activation[str( activated_place)] = event['time:timestamp'] pbar.close() """ Calculate decay function parameter """ for place in self.net.places: if len(reactivation_deltas[str(place)]) > 1: self.decay_functions[str(place)] = LinearDecay( alpha=1 / np.mean(reactivation_deltas[str(place)]), beta=beta) else: self.decay_functions[str(place)] = LinearDecay( alpha=1 / log_wrapper.max_trace_duration, beta=beta) """ Get resource keys to store """ self.resource_keys = log_wrapper.getResourceKeys()
def decay_replay(self, log_wrapper: LogWrapper, resources: list = None): """ Decay Replay on given event log. :param log_wrapper: Input event log as LogWrapper to be replayed. :param resources: Resource keys to count (must have been counted during Petri net enhancement already!), as a list :return: list of timed state samples as JSON, list of timed state sample objects """ tss = list() tss_objs = list() decay_values = {} token_counts = {} marks = {} last_activation = {} """ Initialize Resource Counter """ count_resources = False resource_counter = None if log_wrapper.resource_keys is not None: count_resources = True resource_counter = dict() for key in log_wrapper.resource_keys.keys(): resource_counter[key] = 0 """ ---> """ log_wrapper.iterator_reset() pbar = tqdm(total=log_wrapper.num_traces, desc="Decay Replay on Event Log") while log_wrapper.iterator_hasNext(): trace = log_wrapper.iterator_next() pbar.update(1) resource_count = copy(resource_counter) """ Reset all counts for the next trace """ for place in self.net.places: if place in self.initial_marking: last_activation[str(place)] = trace[0]['time:timestamp'] else: last_activation[str(place)] = -1 for place in self.net.places: decay_values[str(place)] = 0.0 token_counts[str(place)] = 0.0 marks[str(place)] = 0.0 """ ----------------------------------> """ places_shortest_path_by_hidden = get_places_shortest_path_by_hidden( self.net, self.MAX_REC_DEPTH) marking = copy(self.initial_marking) """ Initialize counts based on initial marking """ for place in marking: decay_values[str(place)] = self.decay_functions[str( place)].decay(t=0) token_counts[str(place)] += 1 marks[str(place)] = 1 """ ----------------------------------> """ """ Replay """ time_recent = None init_time = None for event_id in range(len(trace)): event = trace[event_id] if event_id == 0: init_time = event['time:timestamp'] time_past = time_recent time_recent = event['time:timestamp'] if event[self.activity_key] in self.trans_map.keys(): activated_places = list() toi = self.trans_map[event[self.activity_key]] """ If Transition of interest is not enabled yet, then go through hidden""" if not semantics.is_enabled(toi, self.net, marking): _, _, act_trans, _ = apply_hidden_trans( toi, self.net, copy(marking), places_shortest_path_by_hidden, [], 0, set(), [copy(marking)]) for act_tran in act_trans: for arc in act_tran.out_arcs: activated_places.append(arc.target) marking = semantics.execute( act_tran, self.net, marking) """ If Transition of interest is STILL not enabled yet, then naively add missing token to fulfill firing rule""" if not semantics.is_enabled(toi, self.net, marking): for arc in toi.in_arcs: if arc.source not in marking: marking[arc.source] += 1 """ Fire transition of interest """ for arc in toi.out_arcs: activated_places.append(arc.target) marking = semantics.execute(toi, self.net, marking) """ Marking is gone - transition could not be fired ...""" if marking is None: raise ValueError("Invalid Marking - Transition '" + str(toi) + "' could not be fired.") """ ----->""" """ Update Time Recordings """ for activated_place in activated_places: last_activation[str( activated_place)] = event['time:timestamp'] """ Count Resources""" if count_resources and resources is not None: for resource_key in resources: if resource_key in event.keys(): val = resource_key + "_:_" + event[resource_key] if val in resource_count.keys(): resource_count[val] += 1 """ Update Vectors and create TimedStateSamples """ if time_past is not None: decay_values, token_counts = self.__updateVectors( decay_values=decay_values, last_activation=last_activation, token_counts=token_counts, activated_places=activated_places, current_time=time_recent) next_event_id = self.__findNextEventId(event_id, trace) if next_event_id is not None: next_event = trace[next_event_id][ self.activity_key] else: next_event = None if count_resources: timedstatesample = TimedStateSample( time_delta_seconds(init_time, time_recent), copy(decay_values), copy(token_counts), copy(marking), copy(self.place_list), resource_count=copy(resource_count), resource_indices=log_wrapper.getResourceKeys()) else: timedstatesample = TimedStateSample( time_delta_seconds(init_time, time_recent), copy(decay_values), copy(token_counts), copy(marking), copy(self.place_list)) timedstatesample.setLabel(next_event) tss.append(timedstatesample.export()) tss_objs.append(timedstatesample) pbar.close() return tss, tss_objs