Пример #1
0
    def reach_fm_with_invisibles(self, marking):
        """
        Reaches the final marking using invisible transitions

        Parameters
        --------------
        marking
            Marking

        Returns
        --------------
        new_marking
            New marking (hopely equal to the final marking)
        """
        spath = None
        spath_length = sys.maxsize
        for pl in marking:
            if pl in self.dictio_spaths:
                for pl2 in self.fm:
                    if pl2 in self.dictio_spaths[pl]:
                        new_path = self.dictio_spaths[pl][pl2]
                        if len(new_path) < spath_length:
                            spath = new_path
                            spath_length = len(spath)
        if spath is not None:
            # try to fire the transitions
            for tr in spath:
                if tr in semantics.enabled_transitions(self.net, marking):
                    marking = semantics.weak_execute(tr, marking)
                else:
                    return None
            return marking
        return None
Пример #2
0
def marking_flow_petri(net,
                       im,
                       return_eventually_enabled=False,
                       parameters=None):
    """
    Construct the marking flow of a Petri net

    Parameters
    -----------------
    net
        Petri net
    im
        Initial marking
    return_eventually_enabled
        Return the eventually enabled (visible) transitions
    """
    if parameters is None:
        parameters = {}

    # set a maximum execution time of 1 day (it can be changed by providing the parameter)
    max_exec_time = exec_utils.get_param_value(Parameters.MAX_ELAB_TIME,
                                               parameters, 86400)

    start_time = time.time()

    incoming_transitions = {im: set()}
    outgoing_transitions = {}
    eventually_enabled = {}

    active = [im]
    while active:
        if (time.time() - start_time) >= max_exec_time:
            # interrupt the execution
            return incoming_transitions, outgoing_transitions, eventually_enabled
        m = active.pop()
        enabled_transitions = semantics.enabled_transitions(net, m)
        if return_eventually_enabled:
            eventually_enabled[
                m] = align_utils.get_visible_transitions_eventually_enabled_by_marking(
                    net, m)
        outgoing_transitions[m] = {}
        for t in enabled_transitions:
            nm = semantics.weak_execute(t, m)
            outgoing_transitions[m][t] = nm
            if nm not in incoming_transitions:
                incoming_transitions[nm] = set()
                if nm not in active:
                    active.append(nm)
            incoming_transitions[nm].add(t)

    return incoming_transitions, outgoing_transitions, eventually_enabled
Пример #3
0
def execute_tr(m, t, tokens_counter):
    for a in t.in_arcs:
        sp = a.source
        w = a.weight
        if sp not in m:
            tokens_counter["missing"] += w
        elif w > m[sp]:
            tokens_counter["missing"] += w - m[sp]
        tokens_counter["consumed"] += w
    for a in t.out_arcs:
        tokens_counter["produced"] += a.weight
    new_m = weak_execute(t, m)
    m = new_m
    return m, tokens_counter
def __update_heu_dict(heu_dict, heu_max_ind_dict, mm, index, h, x,
                      firing_sequence, incidence_matrix, cost_vec):
    """
    Updates the heuristics dictionary on the new marking, storing the information about the heuristics
    and the vector
    """
    x = copy(x)
    __update_heu_dict_specific_point(heu_dict, heu_max_ind_dict, mm, index, h,
                                     x)
    firing_sequence = list(firing_sequence)
    while firing_sequence:
        t = firing_sequence.pop(0)
        h, x = utils.__derive_heuristic(incidence_matrix, cost_vec, x, t, h)
        mm = semantics.weak_execute(t, mm)
        __update_heu_dict_specific_point(heu_dict, heu_max_ind_dict, mm, index,
                                         h, x)
Пример #5
0
    def enable_trans_with_invisibles(self, marking, activity):
        """
        Enables a visible transition (that is not enabled) through
        invisible transitions

        Parameters
        ----------------
        marking
            Marking
        activity
            Activity to enable

        Returns
        ---------------
        new_marking
            New marking (where the transition CAN be enabled)
        """
        corr_trans_to_act = [
            x for x in self.net.transitions if x.label == activity
        ]
        spath = None
        spath_length = sys.maxsize
        for pl in marking:
            for tr in corr_trans_to_act:
                if pl in self.dictio_spaths:
                    if tr in self.dictio_spaths[pl]:
                        new_path = self.dictio_spaths[pl][tr]
                        if len(new_path) < spath_length:
                            spath = new_path
                            spath_length = len(spath)
        if spath is not None:
            # try to fire the transitions
            for tr in spath:
                if tr in semantics.enabled_transitions(self.net, marking):
                    marking = semantics.weak_execute(tr, marking)
                else:
                    return None
            return marking
        return None
Пример #6
0
    def run(self):
        """
        Runs the thread
        """
        if self.enable_diagnostics:
            diagnostics = SimulationDiagnostics(self)
            diagnostics.start()

        from intervaltree import IntervalTree, Interval

        logging.basicConfig()
        logger = logging.getLogger(__name__)
        logger.setLevel(logging.DEBUG)

        net, im, fm, smap, source, sink, start_time = self.net, self.im, self.fm, self.map, self.source, self.sink, self.start_time
        places_interval_trees = self.places_interval_trees
        transitions_interval_trees = self.transitions_interval_trees
        cases_ex_time = self.cases_ex_time

        current_time = start_time

        self.internal_thread_start_time = time()
        rem_time = self.get_rem_time()

        acquired_places = set()
        acquired = source.semaphore.acquire(timeout=rem_time)
        if acquired:
            acquired_places.add(source)
        source.assigned_time.append(current_time)

        current_marking = im
        et = enabled_transitions(net, current_marking)

        first_event = None
        last_event = None

        while not fm <= current_marking or len(et) == 0:
            et = list(enabled_transitions(net, current_marking))
            ct = stochastic_utils.pick_transition(et, smap)

            simulated_execution_plus_waiting_time = -1
            while simulated_execution_plus_waiting_time < 0:
                simulated_execution_plus_waiting_time = smap[ct].get_value(
                ) if ct in smap else 0.0

            # establish how much time we need to wait before firing the transition
            # (it depends on the input places tokens)
            waiting_time = 0
            for arc in ct.out_arcs:
                place = arc.target
                sem_value = int(place.semaphore._value)
                rem_time = self.get_rem_time()
                acquired = place.semaphore.acquire(timeout=rem_time)
                if acquired:
                    acquired_places.add(place)
                rem_time = self.get_rem_time()
                if rem_time == 0:
                    break
                if sem_value == 0:
                    waiting_time = max(
                        waiting_time,
                        place.assigned_time.pop(0) -
                        current_time) if place.assigned_time else waiting_time

            if rem_time == 0:
                for place in acquired_places:
                    place.semaphore.release()
                break

            # if the waiting time is greater than 0, add an interval to the interval tree denoting
            # the waiting times for the given transition
            if waiting_time > 0:
                transitions_interval_trees[ct].add(
                    Interval(current_time, current_time + waiting_time))

            # get the actual execution time of the transition as a difference between simulated_execution_plus_waiting_time
            # and the waiting time
            execution_time = max(
                simulated_execution_plus_waiting_time - waiting_time, 0)

            # increase the timing based on the waiting time and the execution time of the transition
            current_time = current_time + waiting_time + execution_time

            for arc in ct.out_arcs:
                place = arc.target
                place.assigned_time.append(current_time)
                place.assigned_time = sorted(place.assigned_time)

            current_marking = weak_execute(ct, current_marking)

            if ct.label is not None:
                eve = Event({
                    xes_constants.DEFAULT_NAME_KEY:
                    ct.label,
                    xes_constants.DEFAULT_TIMESTAMP_KEY:
                    datetime.datetime.fromtimestamp(current_time)
                })
                last_event = eve
                if first_event is None:
                    first_event = last_event
                self.list_cases[self.id].append(eve)

            for arc in ct.in_arcs:
                place = arc.source
                p_ex_time = place.assigned_time.pop(0)
                if current_time - p_ex_time > 0:
                    places_interval_trees[place].add(
                        Interval(p_ex_time, current_time))
                place.assigned_time.append(current_time)
                place.assigned_time = sorted(place.assigned_time)
                place.semaphore.release()

            # sleep before starting next iteration
            sleep((waiting_time + execution_time) / self.small_scale_factor)

        if first_event is not None and last_event is not None:
            cases_ex_time.append(
                last_event[xes_constants.DEFAULT_TIMESTAMP_KEY].timestamp() -
                first_event[xes_constants.DEFAULT_TIMESTAMP_KEY].timestamp())
        else:
            cases_ex_time.append(0)

        places_to_free = set(current_marking).union(acquired_places)

        for place in places_to_free:
            place.semaphore.release()

        rem_time = self.get_rem_time()
        if rem_time > 0:
            self.terminated_correctly = True
            if self.enable_diagnostics:
                logger.info(
                    str(time()) + " terminated successfully thread ID " +
                    str(self.id))

        if self.enable_diagnostics:
            if rem_time == 0:
                if self.enable_diagnostics:
                    logger.info(
                        str(time()) + " terminated for timeout thread ID " +
                        str(self.id))

        if self.enable_diagnostics:
            diagnostics.diagn_open = False
Пример #7
0
def calculate_annotation_for_trace(trace,
                                   net,
                                   initial_marking,
                                   act_trans,
                                   activity_key,
                                   ht_perf_method="last"):
    """
    Calculate annotation for a trace in the variant, in order to retrieve information
    useful for calculate frequency/performance for all the traces belonging to the variant

    Parameters
    -----------
    trace
        Trace
    net
        Petri net
    initial_marking
        Initial marking
    act_trans
        Activated transitions during token replay of the given trace
    activity_key
        Attribute that identifies the activity (must be specified if different from concept:name)
    ht_perf_method
        Method to use in order to annotate hidden transitions (performance value could be put on the last possible
        point (last) or in the first possible point (first)

    Returns
    ----------
    annotation
        Statistics annotation for the given trace
    """
    annotations_places_trans = {}
    annotations_arcs = {}
    trace_place_stats = {}
    current_trace_index = 0
    j = 0
    marking = copy(initial_marking)
    for place in marking:
        if place not in annotations_places_trans:
            annotations_places_trans[place] = {"count": 0}
            annotations_places_trans[place][
                "count"] = annotations_places_trans[place]["count"] + marking[
                    place]
        trace_place_stats[place] = [current_trace_index] * marking[place]

    for z in range(len(act_trans)):
        enabled_trans_in_marking = semantics.enabled_transitions(net, marking)
        # print("enabled_trans_in_marking", enabled_trans_in_marking)

        for trans in enabled_trans_in_marking:
            if trans not in annotations_places_trans:
                annotations_places_trans[trans] = {
                    "count": 0,
                    "performance": [],
                    "no_of_times_enabled": 0,
                    "no_of_times_activated": 0
                }
            annotations_places_trans[trans][
                "no_of_times_enabled"] = annotations_places_trans[trans][
                    "no_of_times_enabled"] + 1

        trans = act_trans[z]
        if trans not in annotations_places_trans:
            annotations_places_trans[trans] = {
                "count": 0,
                "performance": [],
                "no_of_times_enabled": 0,
                "no_of_times_activated": 0
            }
        annotations_places_trans[trans][
            "count"] = annotations_places_trans[trans]["count"] + 1
        if trans not in enabled_trans_in_marking:
            annotations_places_trans[trans][
                "no_of_times_enabled"] = annotations_places_trans[trans][
                    "no_of_times_enabled"] + 1
        annotations_places_trans[trans][
            "no_of_times_activated"] = annotations_places_trans[trans][
                "no_of_times_activated"] + 1

        new_marking = semantics.weak_execute(trans, marking)
        if not new_marking:
            break
        marking_diff = set(new_marking).difference(set(marking))
        for place in marking_diff:
            if place not in annotations_places_trans:
                annotations_places_trans[place] = {"count": 0}
                annotations_places_trans[place][
                    "count"] = annotations_places_trans[place]["count"] + max(
                        new_marking[place] - marking[place], 1)
        marking = new_marking
        if j < len(trace):
            current_trace_index = j
            if trans.label == trace[j][activity_key]:
                j = j + 1

        in_arc_indexes = [
            trace_place_stats[arc.source][0] for arc in trans.in_arcs if
            arc.source in trace_place_stats and trace_place_stats[arc.source]
        ]
        if in_arc_indexes:
            min_in_arc_indexes = min(in_arc_indexes)
            max_in_arc_indexes = max(in_arc_indexes)
        else:
            min_in_arc_indexes = None
            max_in_arc_indexes = None
        performance_for_this_trans_execution = []

        for arc in trans.in_arcs:
            source_place = arc.source
            if arc not in annotations_arcs:
                annotations_arcs[arc] = {"performance": [], "count": 0}
                annotations_arcs[arc][
                    "count"] = annotations_arcs[arc]["count"] + 1
            if source_place in trace_place_stats and trace_place_stats[
                    source_place]:
                if trans.label or ht_perf_method == "first":
                    annotations_arcs[arc]["performance"].append([
                        current_trace_index, trace_place_stats[source_place][0]
                    ])
                    performance_for_this_trans_execution.append([[
                        current_trace_index, trace_place_stats[source_place][0]
                    ], current_trace_index - trace_place_stats[source_place][0]
                                                                 ])
                elif min_in_arc_indexes:
                    annotations_arcs[arc]["performance"].append(
                        [current_trace_index, current_trace_index])
                    performance_for_this_trans_execution.append(
                        [[current_trace_index, current_trace_index], 0])

                del trace_place_stats[source_place][0]
        for arc in trans.out_arcs:
            target_place = arc.target
            if arc not in annotations_arcs:
                annotations_arcs[arc] = {"performance": [], "count": 0}
                annotations_arcs[arc][
                    "count"] = annotations_arcs[arc]["count"] + 1
            if target_place not in trace_place_stats:
                trace_place_stats[target_place] = []

            if trans.label or ht_perf_method == "first":
                trace_place_stats[target_place].append(current_trace_index)
            elif max_in_arc_indexes:
                trace_place_stats[target_place].append(max_in_arc_indexes)

        if performance_for_this_trans_execution:
            performance_for_this_trans_execution = sorted(
                performance_for_this_trans_execution, key=lambda x: x[1])

            annotations_places_trans[trans]["performance"].append(
                performance_for_this_trans_execution[0][0])

    return annotations_places_trans, annotations_arcs
Пример #8
0
def apply(net, initial_marking, final_marking=None, parameters=None):
    """
    Do the playout of a Petrinet generating a log (extensive search; stop at the maximum
    trace length specified

    Parameters
    -----------
    net
        Petri net to play-out
    initial_marking
        Initial marking of the Petri net
    final_marking
        If provided, the final marking of the Petri net
    parameters
        Parameters of the algorithm:
            Parameters.MAX_TRACE_LENGTH -> Maximum trace length
    """
    if parameters is None:
        parameters = {}

    case_id_key = exec_utils.get_param_value(Parameters.CASE_ID_KEY,
                                             parameters,
                                             xes_constants.DEFAULT_TRACEID_KEY)
    activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY,
                                              parameters,
                                              xes_constants.DEFAULT_NAME_KEY)
    timestamp_key = exec_utils.get_param_value(
        Parameters.TIMESTAMP_KEY, parameters,
        xes_constants.DEFAULT_TIMESTAMP_KEY)
    max_trace_length = exec_utils.get_param_value(Parameters.MAX_TRACE_LENGTH,
                                                  parameters, 10)

    # assigns to each event an increased timestamp from 1970
    curr_timestamp = 10000000

    log = log_instance.EventLog()

    to_visit = [(initial_marking, ())]
    visited = set()

    while len(to_visit) > 0:
        state = to_visit.pop(0)
        if state in visited:
            continue
        visited.add(state)

        m = state[POSITION_MARKING]
        trace = state[POSITION_TRACE]
        en_t = semantics.enabled_transitions(net, m)

        if (final_marking is not None
                and m == final_marking) or len(en_t) == 0:
            if len(trace) <= max_trace_length:
                log_trace = log_instance.Trace()
                log_trace.attributes[case_id_key] = str(len(log))
                for act in trace:
                    curr_timestamp = curr_timestamp + 1
                    log_trace.append(
                        log_instance.Event({
                            activity_key:
                            act,
                            timestamp_key:
                            datetime.datetime.fromtimestamp(curr_timestamp)
                        }))
                log.append(log_trace)

        for t in en_t:
            new_m = semantics.weak_execute(t, m)
            if t.label is not None:
                new_trace = trace + (t.label, )
            else:
                new_trace = trace
            new_state = (new_m, new_trace)
            if new_state in visited or len(new_trace) > max_trace_length:
                continue
            to_visit.append(new_state)

    return log
    def run(self):
        """
        Runs the thread
        """
        net, im, fm, map, source, sink, start_time = self.net, self.im, self.fm, self.map, self.source, self.sink, self.start_time
        places_interval_trees = self.places_interval_trees
        transitions_interval_trees = self.transitions_interval_trees
        cases_ex_time = self.cases_ex_time

        current_time = start_time

        source.semaphore.acquire()
        source.assigned_time = max(source.assigned_time, current_time)

        current_marking = im
        et = enabled_transitions(net, current_marking)

        first_event = None
        while not fm <= current_marking or len(et) == 0:
            et = enabled_transitions(net, current_marking)
            ct = random.choice(list(et))

            added_value = -1
            while added_value < 0:
                added_value = map[ct].get_value() if ct in map else 0.0
            ex_time = current_time + added_value
            min_ex_time = ex_time

            for arc in ct.out_arcs:
                place = arc.target
                ex_time = max(place.assigned_time, ex_time)
                place.semaphore.acquire()

            current_time = ex_time

            for arc in ct.out_arcs:
                place = arc.target
                place.assigned_time = current_time

            if ex_time - min_ex_time > 0:
                transitions_interval_trees[ct].add(
                    Interval(min_ex_time, ex_time))

            current_marking = weak_execute(ct, current_marking)

            if ct.label is not None:
                eve = Event({
                    "concept:name":
                    ct.label,
                    "time:timestamp":
                    datetime.datetime.fromtimestamp(current_time)
                })
                last_event = eve
                if first_event is None:
                    first_event = last_event
                self.list_cases[self.id].append(eve)

            for arc in ct.in_arcs:
                place = arc.source
                p_ex_time = place.assigned_time
                if current_time - p_ex_time > 0:
                    places_interval_trees[place].add(
                        Interval(p_ex_time, current_time))
                place.assigned_time = current_time
                place.semaphore.release()
        # sink.semaphore.release()
        cases_ex_time.append(last_event['time:timestamp'].timestamp() -
                             first_event['time:timestamp'].timestamp())

        for place in current_marking:
            place.semaphore.release()
Пример #10
0
def apply(net, initial_marking, final_marking=None, parameters=None):
    """
    Do the playout of a Petrinet generating a log (extensive search; stop at the maximum
    trace length specified

    Parameters
    -----------
    net
        Petri net to play-out
    initial_marking
        Initial marking of the Petri net
    final_marking
        If provided, the final marking of the Petri net
    parameters
        Parameters of the algorithm:
            Parameters.MAX_TRACE_LENGTH -> Maximum trace length
    """
    if parameters is None:
        parameters = {}

    case_id_key = exec_utils.get_param_value(Parameters.CASE_ID_KEY,
                                             parameters,
                                             xes_constants.DEFAULT_TRACEID_KEY)
    activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY,
                                              parameters,
                                              xes_constants.DEFAULT_NAME_KEY)
    timestamp_key = exec_utils.get_param_value(
        Parameters.TIMESTAMP_KEY, parameters,
        xes_constants.DEFAULT_TIMESTAMP_KEY)
    max_trace_length = exec_utils.get_param_value(Parameters.MAX_TRACE_LENGTH,
                                                  parameters, 10)
    return_elements = exec_utils.get_param_value(Parameters.RETURN_ELEMENTS,
                                                 parameters, False)
    max_marking_occ = exec_utils.get_param_value(Parameters.MAX_MARKING_OCC,
                                                 parameters, sys.maxsize)

    # assigns to each event an increased timestamp from 1970
    curr_timestamp = 10000000

    feasible_elements = []

    to_visit = [(initial_marking, (), ())]
    visited = set()

    while len(to_visit) > 0:
        state = to_visit.pop(0)

        m = state[POSITION_MARKING]
        trace = state[POSITION_TRACE]
        elements = state[POSITION_ELEMENTS]

        if (m, trace) in visited:
            continue
        visited.add((m, trace))

        en_t = semantics.enabled_transitions(net, m)

        if (final_marking is not None
                and m == final_marking) or (final_marking is None
                                            and len(en_t) == 0):
            if len(trace) <= max_trace_length:
                feasible_elements.append(elements)

        for t in en_t:
            new_elements = elements + (m, )
            new_elements = new_elements + (t, )

            counter_elements = Counter(new_elements)

            if counter_elements[m] > max_marking_occ:
                continue

            new_m = semantics.weak_execute(t, m)
            if t.label is not None:
                new_trace = trace + (t.label, )
            else:
                new_trace = trace

            new_state = (new_m, new_trace, new_elements)

            if new_state in visited or len(new_trace) > max_trace_length:
                continue
            to_visit.append(new_state)

    if return_elements:
        return feasible_elements

    log = log_instance.EventLog()
    for elements in feasible_elements:
        log_trace = log_instance.Trace()
        log_trace.attributes[case_id_key] = str(len(log))
        activities = [
            x.label for x in elements
            if type(x) is PetriNet.Transition and x.label is not None
        ]
        for act in activities:
            curr_timestamp = curr_timestamp + 1
            log_trace.append(
                log_instance.Event({
                    activity_key:
                    act,
                    timestamp_key:
                    datetime.datetime.fromtimestamp(curr_timestamp)
                }))
        log.append(log_trace)

    return log
Пример #11
0
     self.case_dict[case] = self.encode_marking(copy(self.im))
     self.missing[case] = 0
     self.remaining[case] = 0
 marking = self.decode_marking(self.case_dict[case])
 new_marking = marking
 prev_marking = None
 correct_exec = False
 numb_it = 0
 while new_marking is not None and prev_marking != new_marking:
     numb_it = numb_it + 1
     if numb_it > self.maximum_iterations_invisibles:
         break
     enabled_transitions = semantics.enabled_transitions(self.net, new_marking)
     matching_transitions = [x for x in enabled_transitions if x.label == activity]
     if matching_transitions:
         new_marking = semantics.weak_execute(matching_transitions[0], new_marking)
         self.case_dict[case] = self.encode_marking(new_marking)
         correct_exec = True
         break
     prev_marking = new_marking
     new_marking = self.enable_trans_with_invisibles(new_marking, activity)
     correct_exec = False
 if correct_exec is False:
     self.message_missing_tokens(activity, case)
     # enables one of the matching transitions
     matching_transitions = [x for x in self.net.transitions if x.label == activity]
     t = matching_transitions[0]
     for a in t.in_arcs:
         pl = a.source
         mark = a.weight
         if pl not in marking or new_marking[pl] < mark:
Пример #12
0
def calculate_annotation_for_trace(trace, initial_marking, act_trans,
                                   activity_key):
    """
    Calculate annotation for a trace in the variant, in order to retrieve information
    useful for calculate frequency/performance for all the traces belonging to the variant

    Parameters
    -----------
    trace
        Trace
    initial_marking
        Initial marking
    act_trans
        Activated transitions during token replay of the given trace
    activity_key
        Attribute that identifies the activity (must be specified if different from concept:name)

    Returns
    ----------
    annotation
        Statistics annotation for the given trace
    """
    annotations_places_trans = {}
    annotations_arcs = {}
    trace_place_stats = {}
    current_trace_index = 0
    j = 0
    marking = copy(initial_marking)
    for place in marking:
        if place not in annotations_places_trans:
            annotations_places_trans[place] = {"count": 0}
            annotations_places_trans[place][
                "count"] = annotations_places_trans[place]["count"] + marking[
                    place]
        trace_place_stats[place] = [current_trace_index] * marking[place]
    for z in range(len(act_trans)):
        trans = act_trans[z]
        if trans not in annotations_places_trans:
            annotations_places_trans[trans] = {"count": 0}
            annotations_places_trans[trans][
                "count"] = annotations_places_trans[trans]["count"] + 1

        new_marking = semantics.weak_execute(trans, marking)
        if not new_marking:
            break
        marking_diff = set(new_marking).difference(set(marking))
        for place in marking_diff:
            if place not in annotations_places_trans:
                annotations_places_trans[place] = {"count": 0}
                annotations_places_trans[place][
                    "count"] = annotations_places_trans[place]["count"] + max(
                        new_marking[place] - marking[place], 1)
        marking = new_marking
        if j < len(trace):
            current_trace_index = j
            if trans.label == trace[j][activity_key]:
                j = j + 1
        for arc in trans.in_arcs:
            source_place = arc.source
            if arc not in annotations_arcs:
                annotations_arcs[arc] = {"performance": [], "count": 0}
                annotations_arcs[arc][
                    "count"] = annotations_arcs[arc]["count"] + 1
            if source_place in trace_place_stats and trace_place_stats[
                    source_place]:
                annotations_arcs[arc]["performance"].append(
                    [current_trace_index, trace_place_stats[source_place][0]])
                del trace_place_stats[source_place][0]
        for arc in trans.out_arcs:
            target_place = arc.target
            if arc not in annotations_arcs:
                annotations_arcs[arc] = {"performance": [], "count": 0}
                annotations_arcs[arc][
                    "count"] = annotations_arcs[arc]["count"] + 1
            if target_place not in trace_place_stats:
                trace_place_stats[target_place] = []
            trace_place_stats[target_place].append(current_trace_index)

    return annotations_places_trans, annotations_arcs
Пример #13
0
def search_path_among_sol(
        sync_net: PetriNet,
        ini: Marking,
        fin: Marking,
        activated_transitions: List[PetriNet.Transition],
        skip=SKIP) -> Tuple[List[PetriNet.Transition], bool, int]:
    """
    (Efficient method) Searches a firing sequence among the X vector that is the solution of the
    (extended) marking equation

    Parameters
    ---------------
    sync_net
        Synchronous product net
    ini
        Initial marking of the net
    fin
        Final marking of the net
    activated_transitions
        Transitions that have non-zero occurrences in the X vector
    skip
        Skip transition

    Returns
    ---------------
    firing_sequence
        Firing sequence
    reach_fm
        Boolean value that tells if the final marking is reached by the firing sequence
    explained_events
        Number of explained events
    """
    reach_fm = False
    trans_empty_preset = set(t for t in sync_net.transitions
                             if len(t.in_arcs) == 0)
    trans_with_index = {}
    trans_wo_index = set()
    for t in activated_transitions:
        if properties.TRACE_NET_TRANS_INDEX in t.properties:
            trans_with_index[t.properties[
                properties.TRACE_NET_TRANS_INDEX]] = t
        else:
            trans_wo_index.add(t)
    keys = sorted(list(trans_with_index.keys()))
    trans_with_index = [trans_with_index[i] for i in keys]
    best_tuple = (0, 0, ini, list())
    open_set = [best_tuple]
    heapq.heapify(open_set)
    visited = 0
    closed = set()
    len_trace_with_index = len(trans_with_index)
    while len(open_set) > 0:
        curr = heapq.heappop(open_set)
        index = -curr[0]
        marking = curr[2]
        if marking in closed:
            continue
        if index == len_trace_with_index:
            reach_fm = True
            if curr[0] < best_tuple[0]:
                best_tuple = curr
            break
        if curr[0] < best_tuple[0]:
            best_tuple = curr
        closed.add(marking)
        corr_trans = trans_with_index[index]
        if corr_trans.sub_marking <= marking:
            visited += 1
            new_marking = semantics.weak_execute(corr_trans, marking)
            heapq.heappush(
                open_set,
                (-index - 1, visited, new_marking, curr[3] + [corr_trans]))
        else:
            enabled = copy(trans_empty_preset)
            for p in marking:
                for t in p.ass_trans:
                    if t in trans_wo_index and t.sub_marking <= marking:
                        enabled.add(t)
            for new_trans in enabled:
                visited += 1
                new_marking = semantics.weak_execute(new_trans, marking)
                heapq.heappush(
                    open_set,
                    (-index, visited, new_marking, curr[3] + [new_trans]))
    return best_tuple[-1], reach_fm, -best_tuple[0]
Пример #14
0
def search_path_among_sol(
        sync_net: PetriNet,
        ini: Marking,
        fin: Marking,
        activated_transitions: List[PetriNet.Transition],
        skip=SKIP) -> Tuple[List[PetriNet.Transition], bool, int]:
    """
    (Efficient method) Searches a firing sequence among the X vector that is the solution of the
    (extended) marking equation

    Parameters
    ---------------
    sync_net
        Synchronous product net
    ini
        Initial marking of the net
    fin
        Final marking of the net
    activated_transitions
        Transitions that have non-zero occurrences in the X vector
    skip
        Skip transition

    Returns
    ---------------
    firing_sequence
        Firing sequence
    reach_fm
        Boolean value that tells if the final marking is reached by the firing sequence
    explained_events
        Number of explained events
    """
    trans_empty_preset = set(t for t in sync_net.transitions
                             if len(t.in_arcs) == 0)
    activated_transitions = tuple(
        sorted(activated_transitions, key=lambda x: x.name))
    open_set = [(0, 0, 0, activated_transitions, ini, tuple())]
    heapq.heapify(open_set)
    firing_sequence = []
    firing_sequence_explained_events = 0
    closed = set()
    count = 0
    while len(open_set) > 0:
        curr = heapq.heappop(open_set)
        explained_events = -curr[0]
        curr_cost = curr[1]
        activated_transitions = curr[3]
        marking = curr[4]
        visited = curr[5]
        if not activated_transitions:
            if marking == fin:
                return visited, True, explained_events
        if (activated_transitions, marking) in closed:
            continue
        closed.add((activated_transitions, marking))
        possible_enabling_transitions = copy(trans_empty_preset)
        for p in marking:
            for t in p.ass_trans:
                possible_enabling_transitions.add(t)
        enabled = set(t for t in possible_enabling_transitions
                      if t.sub_marking <= marking)
        enabled = enabled.intersection(set(activated_transitions))
        vis_enabled = set(x for x in enabled if x.label[0] is not skip)
        if vis_enabled:
            enabled = vis_enabled
        if not enabled:
            if explained_events > firing_sequence_explained_events:
                firing_sequence = visited
                firing_sequence_explained_events = explained_events
        for tr in enabled:
            count = count + 1
            this_cost = 1 if tr.label[0] is skip else 0
            new_trans = list(activated_transitions)
            idx = new_trans.index(tr)
            del new_trans[idx]
            new_trans = tuple(new_trans)
            new_visited = list(visited)
            new_visited.append(tr)
            new_visited = tuple(new_visited)
            new_marking = semantics.weak_execute(tr, marking)
            new_explained_events = len(
                list(x for x in new_visited if x.label[0] is not skip))
            heapq.heappush(open_set,
                           (-new_explained_events, this_cost + curr_cost,
                            count, new_trans, new_marking, new_visited))
    return firing_sequence, False, firing_sequence_explained_events