Esempio n. 1
0
def token_replay_event(trans_list, net, marking, is_inv):
    """Performs token replay for a transition given the current marking.
    """
    debug_msg = 'Token replaying event {} at marking {}'
    debug_msg = debug_msg.format(trans_list[0].label, marking)
    logger.debug(debug_msg)

    marking_seq = list()
    enabled_trans = list(semantics.enabled_transitions(net, marking))
    target_trans = trans_list.pop(0)
    replayed = False
    while not replayed:
        if target_trans in enabled_trans:
            new_marking = semantics.execute(target_trans, net, marking)
            marking_seq.append(new_marking)
            break

        elif pm_extra.has_invisible(enabled_trans, is_inv):
            marking_seq_i = token_pull(target_trans, net, marking, is_inv)
            if marking_seq_i is not None:
                marking = marking_seq_i[-1]
                new_marking = semantics.execute(target_trans, net, marking)
                marking_seq_i.append(new_marking)
                marking_seq = marking_seq_i
                break

        # try next transition
        if trans_list:
            target_trans = trans_list.pop(0)
        # finished trying to replay transition
        else:
            marking_seq = None
            break

    return marking_seq
Esempio n. 2
0
def get_visible_transitions_eventually_enabled_by_marking(net, marking):
    """
    Get visible transitions eventually enabled by marking (passing possibly through hidden transitions)

    Parameters
    ----------
    net
        Petri net
    marking
        Current marking
    """
    all_enabled_transitions = list(semantics.enabled_transitions(net, marking))
    visible_transitions = set()
    visited_transitions = set()

    for i in range(len(all_enabled_transitions)):
        t = all_enabled_transitions[i]
        if t not in visited_transitions:
            if t.label is not None:
                visible_transitions.add(t)
            else:
                marking_copy = copy(marking)
                if semantics.is_enabled(t, net, marking_copy):
                    new_marking = semantics.execute(t, net, marking_copy)
                    new_enabled_transitions = list(semantics.enabled_transitions(net, new_marking))
                    all_enabled_transitions = all_enabled_transitions + new_enabled_transitions
            visited_transitions.add(t)

    return visible_transitions
Esempio n. 3
0
def log_to_tel(net, initial_marking, final_marking, tel):
    '''
    set enabled into the log based on replaying on net

    Parameters
    ----------
    :param net: petri net
    :param log: tel object

    Returns
    --------
    translucent event log
    '''

    for trace in tel:
        m = initial_marking
        for event in trace:
            act = event['concept:name']

            for trans in net.transitions:
                if act == trans.label:
                    t = trans
                    break

            en = semantics.enabled_transitions(net, m)
            event.set_enabled(frozenset(en))
            if m == final_marking:
                break
            m = semantics.execute(t, net, m)  # find enabled activity

    return tel
def is_sequence_possible(net, transition_sequence):
    """
    Helper function used to run a sequence of transitions.
    Returns [a,b,c] where
    a = True if sequence of transitions is possible in net
    b = the index of the transition that is not possible if a = False
    c = label of transition if a transition was not found in the network else False
    """
    # Get marking object
    current_marking = get_marking(net)

    # Create a mapping from label to transition objects
    transition_dict = {}
    for transition in net.transitions:
        if transition.name in transition_sequence:
            transition_dict[transition.name] = transition

    index = 0
    for transition_label in transition_sequence:
        # Transition not found
        if transition_label not in transition_dict.keys():
            return [False, 0, transition_label]

        transition = transition_dict[transition_label]
        # Transition not enabled, sequence impossible
        if not semantics.is_enabled(transition, net, current_marking):
            return [False, index, False]
        # Fire the transition to enter next marking
        current_marking = semantics.execute(transition, net, current_marking)
        index += 1

    # Sequence possible
    return [True, 0, False]
Esempio n. 5
0
def apply_playout(net,
                  initial_marking,
                  no_traces=100,
                  max_trace_length=100,
                  case_id_key=xes_constants.DEFAULT_TRACEID_KEY,
                  activity_key=xes_constants.DEFAULT_NAME_KEY,
                  timestamp_key=xes_constants.DEFAULT_TIMESTAMP_KEY,
                  final_marking=None):
    """
    Do the playout of a Petrinet generating a log

    Parameters
    ----------
    net
        Petri net to play-out
    initial_marking
        Initial marking of the Petri net
    no_traces
        Number of traces to generate
    max_trace_length
        Maximum number of events per trace (do break)
    case_id_key
        Trace attribute that is the case ID
    activity_key
        Event attribute that corresponds to the activity
    timestamp_key
        Event attribute that corresponds to the timestamp
    final_marking
        If provided, the final marking of the Petri net
    """
    # assigns to each event an increased timestamp from 1970
    curr_timestamp = 10000000
    log = log_instance.EventLog()
    for i in range(no_traces):
        trace = log_instance.Trace()
        trace.attributes[case_id_key] = str(i)
        marking = copy(initial_marking)
        while len(trace) < max_trace_length:
            if not semantics.enabled_transitions(
                    net, marking):  # supports nets with possible deadlocks
                break
            all_enabled_trans = semantics.enabled_transitions(net, marking)
            if final_marking is not None and marking == final_marking:
                trans = choice(list(all_enabled_trans.union({None})))
            else:
                trans = choice(list(all_enabled_trans))
            if trans is None:
                break
            if trans.label is not None:
                event = log_instance.Event()
                event[activity_key] = trans.label
                event[timestamp_key] = datetime.datetime.fromtimestamp(
                    curr_timestamp)
                trace.append(event)
                # increases by 1 second
                curr_timestamp += 1
            marking = semantics.execute(trans, net, marking)
        log.append(trace)
    return log
Esempio n. 6
0
    def play(self):
        self.generatedTraces = set()
        self.potentials = Queue()

        marking_count = dict()
        for mark in self.initial_marking:
            marking_count[mark] = 1

        self.potentials.put_nowait(
            PotentialTrace(marking=copy(self.initial_marking),
                           firingSequence=list(),
                           marking_count=marking_count))

        while not self.potentials.empty():
            potential = self.potentials.get_nowait()
            marking = potential.getMarking()
            firingSeq = potential.getFiringSequence()

            enabled_trans = semantics.enabled_transitions(self.net, marking)
            for enabled_tran in enabled_trans:
                new_marking = semantics.execute(enabled_tran, self.net,
                                                marking)
                new_firingSeq = copy(firingSeq)

                discard = False
                marking_count = copy(potential.getMarkingCount())
                for mark in new_marking:
                    if mark not in marking:
                        if mark in marking_count.keys():
                            marking_count[mark] = marking_count[mark] + 1
                            if marking_count[mark] > self.max_loop:
                                discard = True
                        else:
                            marking_count[mark] = 1

                if enabled_tran.label == None:
                    invs = potential.getInvCounter() + 1
                else:
                    new_firingSeq.append(str(enabled_tran))
                    invs = 0

                if new_marking == self.final_marking:
                    self.generatedTraces.add(tuple(new_firingSeq))
                else:
                    if len(
                            new_firingSeq
                    ) < self.maxTraceLength and invs < self.rep_inv_thresh and not discard:
                        self.potentials.put_nowait(
                            PotentialTrace(marking=new_marking,
                                           firingSequence=new_firingSeq,
                                           inv_counter=invs,
                                           marking_count=marking_count))
        return self.generatedTraces
Esempio n. 7
0
def enable_hidden_transitions(net, marking, activated_transitions,
                              visited_transitions, all_visited_markings,
                              hidden_transitions_to_enable, t):
    """
    Actually enable hidden transitions on the Petri net

    Parameters
    -----------
    net
        Petri net
    marking
        Current marking
    activated_transitions
        All activated transitions during the replay
    visited_transitions
        All visited transitions by the recursion
    all_visited_markings
        All visited markings
    hidden_transitions_to_enable
        List of hidden transition to enable
    t
        Transition against we should check if they are enabled
    """
    j_indexes = [0] * len(hidden_transitions_to_enable)
    for z in range(10000000):
        something_changed = False
        for k in range(
                j_indexes[z % len(hidden_transitions_to_enable)],
                len(hidden_transitions_to_enable[
                    z % len(hidden_transitions_to_enable)])):
            t3 = hidden_transitions_to_enable[
                z % len(hidden_transitions_to_enable)][j_indexes[
                    z % len(hidden_transitions_to_enable)]]
            if not t3 == t:
                if semantics.is_enabled(t3, net, marking):
                    if t3 not in visited_transitions:
                        marking = semantics.execute(t3, net, marking)
                        activated_transitions.append(t3)
                        visited_transitions.add(t3)
                        all_visited_markings.append(marking)
                        something_changed = True
            j_indexes[z % len(hidden_transitions_to_enable)] = j_indexes[
                z % len(hidden_transitions_to_enable)] + 1
            if semantics.is_enabled(t, net, marking):
                break
        if semantics.is_enabled(t, net, marking):
            break
        if not something_changed:
            break
    return [
        marking, activated_transitions, visited_transitions,
        all_visited_markings
    ]
Esempio n. 8
0
def acyclic_net_variants(net,
                         initial_marking,
                         final_marking,
                         activity_key=xes_util.DEFAULT_NAME_KEY):
    """
    Given an acyclic accepting Petri net, initial and final marking extracts a set of variants (in form of traces)
    replayable on the net.
    Warning: this function is based on a marking exploration. If the accepting Petri net contains loops, the method
    will not work properly as it stops the search if a specific marking has already been encountered.

    Parameters
    ----------
    :param net: An acyclic workflow net
    :param initial_marking: The initial marking of the net.
    :param final_marking: The final marking of the net.
    :param activity_key: activity key to use

    Returns
    -------
    :return: variants: :class:`list` Set of variants - in the form of Trace objects - obtainable executing the net

    """
    active = {(initial_marking, ())}
    visited = set()
    variants = set()
    while active:
        curr_marking, curr_partial_trace = active.pop()
        curr_pair = (curr_marking, curr_partial_trace)
        enabled_transitions = semantics.enabled_transitions(net, curr_marking)
        for transition in enabled_transitions:
            if transition.label is not None:
                next_partial_trace = curr_partial_trace + (transition.label, )
            else:
                next_partial_trace = curr_partial_trace
            next_marking = semantics.execute(transition, net, curr_marking)
            next_pair = (next_marking, next_partial_trace)

            if next_marking == final_marking:
                variants.add(next_partial_trace)
            else:
                # If the next marking is not in visited, if the next marking+partial trace is different from the current one+partial trace
                if next_pair not in visited and curr_pair != next_pair:
                    active.add(next_pair)
        visited.add(curr_pair)
    trace_variants = []
    for variant in variants:
        trace = Trace()
        for activity_label in variant:
            trace.append(Event({activity_key: activity_label}))
        trace_variants.append(trace)
    return trace_variants
def make_enabledlog_alphaminer(log_file_path, output_file_name):
    '''
    Convert XES to XES++ based on alpha miner (event log with enabled activities)
    (for test)

    Parameters
    ----------
    log_file_path
        log's file path to be changed into XES++

    output_file_name
        output file (XES++)'s name

    '''

    log = xes_importer.import_log(log_file_path)
    net, initial_marking, final_marking = alpha_miner.apply(log)

    doc = ET.parse(log_file_path)
    root = doc.getroot()

    for glob in root.iter("global"):
        if glob.attrib["scope"] == "event":
            enabled = ET.SubElement(glob, "string")
            enabled.set("key", "enabled")
            enabled.set("value", "enabled")

    for trace in root.iter("trace"):
        m = ini.discover_initial_marking(net)
        for event in trace.iter("event"):
            for string in event.iter("string"):
                if string.attrib["key"] == "concept:name":
                    act = string.attrib["value"]  # act: current activity in the event log
                    break
            for trans in net.transitions:
                if act == trans.label:
                    t = trans
                    break
            en = semantics.enabled_transitions(net, m)
            enabled = ET.SubElement(event, "string")
            enabled.set("key", "enabled")
            enabled.set("value", en) #write on the XES file
            if m == final_marking:
                break
            m = semantics.execute(t, net, m)


    doc.write(output_file_name, encoding="utf-8", xml_declaration=True)
Esempio n. 10
0
def get_visible_transitions_eventually_enabled_by_marking(net, marking):
    """
    Get visible transitions eventually enabled by marking (passing possibly through hidden transitions)
    Parameters
    ----------
    net
        Petri net
    marking
        Current marking
    """
    all_enabled_transitions = sorted(list(
        semantics.enabled_transitions(net, marking)),
                                     key=lambda x: (str(x.name), id(x)))
    initial_all_enabled_transitions_marking_dictio = {}
    all_enabled_transitions_marking_dictio = {}
    for trans in all_enabled_transitions:
        all_enabled_transitions_marking_dictio[trans] = marking
        initial_all_enabled_transitions_marking_dictio[trans] = marking
    visible_transitions = set()
    visited_transitions = set()

    i = 0
    while i < len(all_enabled_transitions):
        t = all_enabled_transitions[i]
        marking_copy = copy(all_enabled_transitions_marking_dictio[t])

        if repr([t, marking_copy]) not in visited_transitions:
            if t.label is not None:
                visible_transitions.add(t)
            else:
                if semantics.is_enabled(t, net, marking_copy):
                    new_marking = semantics.execute(t, net, marking_copy)
                    new_enabled_transitions = sorted(list(
                        semantics.enabled_transitions(net, new_marking)),
                                                     key=lambda x:
                                                     (str(x.name), id(x)))
                    for t2 in new_enabled_transitions:
                        all_enabled_transitions.append(t2)
                        all_enabled_transitions_marking_dictio[
                            t2] = new_marking
            visited_transitions.add(repr([t, marking_copy]))
        i = i + 1

    return visible_transitions
Esempio n. 11
0
    def play(self):
        self.generatedTraces = set()
        for sample in range(self.samples):
            firingSeq = list()
            marking = self.initial_marking
            while marking != self.final_marking:
                enabled_trans = semantics.enabled_transitions(
                    self.net, marking)
                if len(enabled_trans) > 0:
                    tran = random.choice([i for i in enabled_trans])

                    if tran.label != None:
                        firingSeq.append(str(tran))
                    marking = semantics.execute(tran, self.net, marking)
                    self.generatedTraces.add(tuple(firingSeq))
                else:
                    firingSeq = list()
                    marking = self.initial_marking
        return self.generatedTraces
Esempio n. 12
0
def apply_playout(net, initial_marking, no_traces=100, max_trace_length=100):
    """
    Do the playout of a Petrinet generating a log

    Parameters
    ----------
    net
        Petri net to play-out
    initial_marking
        Initial marking of the Petri net
    no_traces
        Number of traces to generate
    max_trace_length
        Maximum number of events per trace (do break)
    """
    # assigns to each event an increased timestamp from 1970
    curr_timestamp = 10000000
    log = log_instance.EventLog()
    for i in range(no_traces):
        trace = log_instance.Trace()
        trace.attributes["concept:name"] = str(i)
        marking = copy(initial_marking)
        for j in range(100000):
            if not semantics.enabled_transitions(net, marking):
                break
            all_enabled_trans = semantics.enabled_transitions(net, marking)
            all_enabled_trans = list(all_enabled_trans)
            shuffle(all_enabled_trans)
            trans = all_enabled_trans[0]
            if trans.label is not None:
                event = log_instance.Event()
                event["concept:name"] = trans.label
                event["time:timestamp"] = datetime.datetime.fromtimestamp(
                    curr_timestamp)
                trace.append(event)
                # increases by 1 second
                curr_timestamp = curr_timestamp + 1
            marking = semantics.execute(trans, net, marking)
            if len(trace) > max_trace_length:
                break
        if len(trace) > 0:
            log.append(trace)
    return log
Esempio n. 13
0
def apply_playout(net, initial_marking, no_traces=100, max_trace_length=100,
                  case_id_key=xes_constants.DEFAULT_TRACEID_KEY,
                  activity_key=xes_constants.DEFAULT_NAME_KEY, timestamp_key=xes_constants.DEFAULT_TIMESTAMP_KEY,
                  final_marking=None, smap=None, log=None, return_visited_elements=False):
    """
    Do the playout of a Petrinet generating a log

    Parameters
    ----------
    net
        Petri net to play-out
    initial_marking
        Initial marking of the Petri net
    no_traces
        Number of traces to generate
    max_trace_length
        Maximum number of events per trace (do break)
    case_id_key
        Trace attribute that is the case ID
    activity_key
        Event attribute that corresponds to the activity
    timestamp_key
        Event attribute that corresponds to the timestamp
    final_marking
        If provided, the final marking of the Petri net
    smap
        Stochastic map
    log
        Log
    """
    if final_marking is None:
        # infer the final marking from the net
        final_marking = final_marking_discovery.discover_final_marking(net)
    if smap is None:
        if log is None:
            raise Exception("please provide at least one between stochastic map and log")
        smap = replay.get_map_from_log_and_net(log, net, initial_marking, final_marking,
                                               parameters={Parameters.ACTIVITY_KEY: activity_key,
                                                           Parameters.TIMESTAMP_KEY: timestamp_key})
    # assigns to each event an increased timestamp from 1970
    curr_timestamp = 10000000
    all_visited_elements = []

    for i in range(no_traces):
        visited_elements = []
        visible_transitions_visited = []
        marking = copy(initial_marking)

        while len(visible_transitions_visited) < max_trace_length:
            visited_elements.append(marking)

            if not semantics.enabled_transitions(net, marking):  # supports nets with possible deadlocks
                break
            all_enabled_trans = semantics.enabled_transitions(net, marking)
            if final_marking is not None and marking == final_marking:
                en_t_list = list(all_enabled_trans.union({None}))
            else:
                en_t_list = list(all_enabled_trans)

            trans = stochastic_utils.pick_transition(en_t_list, smap)

            if trans is None:
                break

            visited_elements.append(trans)
            if trans.label is not None:
                visible_transitions_visited.append(trans)

            marking = semantics.execute(trans, net, marking)

        all_visited_elements.append(tuple(visited_elements))

    if return_visited_elements:
        return all_visited_elements

    log = log_instance.EventLog()

    for index, visited_elements in enumerate(all_visited_elements):
        trace = log_instance.Trace()
        trace.attributes[case_id_key] = str(index)
        for element in visited_elements:
            if type(element) is PetriNet.Transition and element.label is not None:
                event = log_instance.Event()
                event[activity_key] = element.label
                event[timestamp_key] = datetime.datetime.fromtimestamp(curr_timestamp)
                trace.append(event)
                # increases by 1 second
                curr_timestamp += 1
        log.append(trace)

    return log
Esempio n. 14
0
def build_reachability_graph(net,
                             init_marking,
                             is_inv,
                             staterep=default_staterep):
    """
    Build reachability graph and keep track of to and from states connected by 
    invisible transitions.

    :param net: the petrinet 
    :param init_marking: initial marking
    :param is_inv: function that indicate if a transition is invisible
    :type is_inv: function
    :staterep: function that gives a state a string representation
    :return reachability graph, list of (from_state, inv_tran, to_state)
    """

    # BFS with queue
    mark_queue = [init_marking]

    rg = ts.TransitionSystem(name='Reachability graph of {}'.format(net.name))
    inv_states = list()

    init_state = ts.TransitionSystem.State(staterep(repr(init_marking)))
    init_state.data['disc'] = 0
    rg.states.add(init_state)

    # mapping visited states to marking
    mark_to_state = dict()
    mark_to_state[init_marking] = init_state

    while mark_queue and len(rg.states) < MAX_RG_STATE:
        cur_mark = mark_queue.pop(0)
        cur_state = mark_to_state[cur_mark]
        enabled_trans = list(semantics.enabled_transitions(net, cur_mark))

        # workout the transition arc weight
        n_vis = len(list(map(lambda t: not is_inv(t), enabled_trans)))
        weight = 1. / n_vis if n_vis > 0 else 0

        for t in enabled_trans:
            next_mark = semantics.execute(t, net, cur_mark)
            next_state = mark_to_state.get(next_mark, None)

            if next_state is None:
                next_state = ts.TransitionSystem.State(
                    staterep(repr(next_mark)))
                # discovered one step away from parent node
                next_state.data['disc'] = cur_state.data['disc'] + 1
                rg.states.add(next_state)
                mark_to_state[next_mark] = next_state
                mark_queue.append(next_mark)

            # doesnt matter that invisible transitions also get weight since
            # they will be removed ultimately as well
            data = {'weight': weight}
            t_label = t.label if t.name is not None else None
            rg_t = add_arc_from_to(t_label, cur_state, next_state, rg, data)

            if is_inv(t):
                inv_states.append((cur_state, rg_t, next_state))

    if mark_queue:
        msg = 'Computation of reachability graph surpass the max number of states: {}'.format(
            MAX_RG_STATE)
        warnings.warn(msg, category=UserWarning)

    return rg, inv_states
Esempio n. 15
0
    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()
Esempio n. 16
0
    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
Esempio n. 17
0
def apply_trace(trace, net, initial_marking, final_marking, trans_map, enable_place_fitness, place_fitness,
                places_shortest_path_by_hidden, consider_remaining_in_fitness, activity_key="concept:name",
                try_to_reach_final_marking_through_hidden=True, stop_immediately_unfit=False,
                walk_through_hidden_trans=True, post_fix_caching=None,
                marking_to_activity_caching=None):
    """
    Apply the token replaying algorithm to a trace

    Parameters
    ----------
    trace
        Trace in the event log
    net
        Petri net
    initial_marking
        Initial marking
    final_marking
        Final marking
    trans_map
        Map between transitions labels and transitions
    enable_place_fitness
        Enable fitness calculation at place level
    place_fitness
        Current dictionary of places associated with unfit traces
    places_shortest_path_by_hidden
        Shortest paths between places by hidden transitions
    consider_remaining_in_fitness
        Boolean value telling if the remaining tokens should be considered in fitness evaluation
    activity_key
        Name of the attribute that contains the activity
    try_to_reach_final_marking_through_hidden
        Boolean value that decides if we shall try to reach the final marking through hidden transitions
    stop_immediately_unfit
        Boolean value that decides if we shall stop immediately when a non-conformance is detected
    walk_through_hidden_trans
        Boolean value that decides if we shall walk through hidden transitions in order to enable visible transitions
    post_fix_caching
        Stores the post fix caching object
    marking_to_activity_caching
        Stores the marking-to-activity cache
    """
    trace_activities = [event[activity_key] for event in trace]
    act_trans = []
    transitions_with_problems = []
    vis_mark = []
    activating_transition_index = {}
    activating_transition_interval = []
    used_postfix_cache = False
    marking = copy(initial_marking)
    vis_mark.append(marking)
    missing = 0
    consumed = 0
    produced = 0
    for i in range(len(trace)):
        if ENABLE_POSTFIX_CACHE and (str(trace_activities) in post_fix_caching.cache and
                                     hash(marking) in post_fix_caching.cache[str(trace_activities)]):
            trans_to_act = post_fix_caching.cache[str(trace_activities)][hash(marking)]["trans_to_activate"]
            for z in range(len(trans_to_act)):
                t = trans_to_act[z]
                act_trans.append(t)
            used_postfix_cache = True
            marking = post_fix_caching.cache[str(trace_activities)][hash(marking)]["final_marking"]
            break
        else:
            prev_len_activated_transitions = len(act_trans)
            if ENABLE_MARKTOACT_CACHE and (hash(marking) in marking_to_activity_caching.cache and
                                           trace[i][activity_key] in marking_to_activity_caching.cache[hash(marking)]
                                           and trace[i - 1][activity_key] ==
                                           marking_to_activity_caching.cache[hash(marking)][trace[i][activity_key]]
                                           ["previousActivity"]):
                this_end_marking = marking_to_activity_caching.cache[hash(marking)][trace[i][activity_key]][
                    "end_marking"]
                this_act_trans = marking_to_activity_caching.cache[hash(marking)][trace[i][activity_key]][
                    "this_activated_transitions"]
                this_vis_markings = marking_to_activity_caching.cache[hash(marking)][trace[i][activity_key]][
                    "this_visited_markings"]
                act_trans = act_trans + this_act_trans
                vis_mark = vis_mark + this_vis_markings
                marking = copy(this_end_marking)
            else:
                if trace[i][activity_key] in trans_map:
                    t = trans_map[trace[i][activity_key]]
                    if walk_through_hidden_trans and not semantics.is_enabled(t, net,
                                                                              marking):
                        visited_transitions = set()
                        prev_len_activated_transitions = len(act_trans)
                        [net, marking, act_trans, vis_mark] = apply_hidden_trans(t, net,
                                                                                 marking,
                                                                                 places_shortest_path_by_hidden,
                                                                                 act_trans,
                                                                                 0,
                                                                                 visited_transitions,
                                                                                 vis_mark)
                    if not semantics.is_enabled(t, net, marking):
                        transitions_with_problems.append(t)
                        if stop_immediately_unfit:
                            missing = missing + 1
                            break
                        [m, tokens_added] = add_missing_tokens(t, marking)
                        missing = missing + m
                        if enable_place_fitness:
                            for place in tokens_added.keys():
                                if place in place_fitness:
                                    place_fitness[place]["underfed_traces"].add(trace)
                    c = get_consumed_tokens(t)
                    p = get_produced_tokens(t)
                    consumed = consumed + c
                    produced = produced + p
                    if semantics.is_enabled(t, net, marking):
                        marking = semantics.execute(t, net, marking)
                        act_trans.append(t)
                        vis_mark.append(marking)
            del trace_activities[0]
            if len(trace_activities) < MAX_POSTFIX_SUFFIX_LENGTH:
                activating_transition_index[str(trace_activities)] = {"index": len(act_trans),
                                                                      "marking": hash(marking)}
            if i > 0:
                activating_transition_interval.append(
                    [trace[i][activity_key], prev_len_activated_transitions, len(act_trans),
                     trace[i - 1][activity_key]])
            else:
                activating_transition_interval.append(
                    [trace[i][activity_key], prev_len_activated_transitions, len(act_trans),
                     ""])

    if try_to_reach_final_marking_through_hidden and not used_postfix_cache:
        for i in range(MAX_IT_FINAL):
            if not break_condition_final_marking(marking, final_marking):
                hidden_transitions_to_enable = get_req_transitions_for_final_marking(marking, final_marking,
                                                                                     places_shortest_path_by_hidden)

                for group in hidden_transitions_to_enable:
                    for t in group:
                        if semantics.is_enabled(t, net, marking):
                            marking = semantics.execute(t, net, marking)
                            act_trans.append(t)
                            vis_mark.append(marking)
                    if break_condition_final_marking(marking, final_marking):
                        break
            else:
                break

        # try to reach the final marking in a different fashion, if not already reached
        if not break_condition_final_marking(marking, final_marking):
            if len(final_marking) == 1:
                sink_place = list(final_marking)[0]

                connections_to_sink = []
                for place in marking:
                    if place in places_shortest_path_by_hidden and sink_place in places_shortest_path_by_hidden[place]:
                        connections_to_sink.append([place, places_shortest_path_by_hidden[place][sink_place]])
                connections_to_sink = sorted(connections_to_sink, key=lambda x: len(x[1]))

                for i in range(MAX_IT_FINAL):
                    for j in range(len(connections_to_sink)):
                        for z in range(len(connections_to_sink[j][1])):
                            t = connections_to_sink[j][1][z]
                            if semantics.is_enabled(t, net, marking):
                                marking = semantics.execute(t, net, marking)
                                act_trans.append(t)
                                vis_mark.append(marking)
                                continue
                            else:
                                break

    marking_before_cleaning = copy(marking)

    remaining = 0
    for p in marking:
        if p in final_marking:
            marking[p] = max(0, marking[p] - final_marking[p])
            if enable_place_fitness:
                if marking[p] > 0:
                    if p in place_fitness:
                        if trace not in place_fitness[p]["underfed_traces"]:
                            place_fitness[p]["overfed_traces"].add(trace)
        remaining = remaining + marking[p]
    if consider_remaining_in_fitness:
        is_fit = (missing == 0) and (remaining == 0)
    else:
        is_fit = (missing == 0)

    if consumed > 0 and produced > 0:
        trace_fitness = (1.0 - float(missing) / float(consumed)) * (1.0 - float(remaining) / float(produced))
    else:
        trace_fitness = 1.0

    if is_fit:
        for suffix in activating_transition_index:
            if suffix not in post_fix_caching.cache:
                post_fix_caching.cache[suffix] = {}
            if activating_transition_index[suffix]["marking"] not in post_fix_caching.cache[suffix]:
                post_fix_caching.cache[suffix][activating_transition_index[suffix]["marking"]] = \
                    {"trans_to_activate": act_trans[activating_transition_index[suffix]["index"]:],
                     "final_marking": marking}
        for trans in activating_transition_interval:
            activity = trans[0]
            start_marking_index = trans[1]
            end_marking_index = trans[2]
            previous_activity = trans[3]
            if end_marking_index < len(vis_mark):
                start_marking_object = vis_mark[start_marking_index]
                start_marking_hash = hash(start_marking_object)
                end_marking_object = vis_mark[end_marking_index]
                if activity in trans_map:
                    this_activated_trans = act_trans[start_marking_index:end_marking_index]
                    this_visited_markings = vis_mark[start_marking_index + 1:end_marking_index + 1]

                    if start_marking_hash not in marking_to_activity_caching.cache:
                        marking_to_activity_caching.cache[start_marking_hash] = {}
                    if activity not in marking_to_activity_caching.cache[start_marking_hash]:
                        marking_to_activity_caching.cache[start_marking_hash][activity] = {
                            "start_marking": start_marking_object, "end_marking": end_marking_object,
                            "this_activated_transitions": this_activated_trans,
                            "this_visited_markings": this_visited_markings,
                            "previousActivity": previous_activity}

    return [is_fit, trace_fitness, act_trans, transitions_with_problems, marking_before_cleaning,
            get_visible_transitions_eventually_enabled_by_marking(net, marking_before_cleaning)]
Esempio n. 18
0
        all_enabled_trans = list(all_enabled_trans)
        shuffle(all_enabled_trans)
        trans = all_enabled_trans[0]
        if trans.label is not None:
            event = log_instance.Event()
            event[activity_key] = trans.label
            results.append([
                case_num, event[activity_key],
                datetime.now() + timedelta(seconds=env.now)
            ])
            yield env.process(
                getattr(case,
                        str(trans.label).replace(" ", ""))())
            event[timestamp_key] = curr_timestamp
            trace.append(event)
        marking = semantics.execute(trans, net, marking)
        if len(trace) > max_trace_length:
            break
    if len(trace) > 0:
        log.append(trace)

        results.append([
            case_num, "case end",
            datetime.now() + timedelta(seconds=env.now)
        ])

    for row in results:
        thewriter.writerow(row)

    f.close()
    return log
Esempio n. 19
0
def token_pull(trans, net, marking, is_inv):
    """Perform token pull given a marking and a visible transition that we would like to execute. Algorithmically speaking,
    it corresponds to a BFS for a marking that enables the transition.

    :param trans: visible transition that we would like to execute
    :param net: petri net model
    :param marking: current marking
    :param is_inv: function that says if a transition is invisible
    :return: sequence of markings that leads to the enabling of transition or None if transition cannot be eventually enabled
    """
    debug_msg = 'Performing token pull at marking {} for target transition {}'
    debug_msg = debug_msg.format(marking, trans)
    logger.debug(debug_msg)

    def retrieve_marking_seq(node):
        debug_msg = 'Recursing from {} to get marking seq'
        debug_msg = debug_msg.format(node[0])
        logger.debug(debug_msg)

        marking_seq = list()
        while node[2] is not None: # parent is not the start marking
            marking_seq.insert(0, node[0])
            par_node = node[2]
            node = par_node
        return marking_seq

    enabled_trans = list(semantics.enabled_transitions(net, marking))
    enabled_trans = list(filter(is_inv, enabled_trans))
    start_node = (
        marking,                # current marking
        enabled_trans,          # enabled invisible transitions at marking
        None                    # parent node
    )
    queue = [start_node]
    visited = set()
    visited.add(marking)
    while queue:
        node = queue[0]
        cur_marking, enabled_trans, parent_node = node
        try:
            inv_tran = enabled_trans.pop(0)
            new_marking = semantics.execute(inv_tran, net, cur_marking)
            new_enabled_trans = list(semantics.enabled_transitions(net, new_marking))

            # check if the target transition is in the enabled transitions
            if trans in new_enabled_trans:
                # we are done since new_marking enables the target transitions
                # recurse back to get the sequence of markings that led to the transition to become enabled
                marking_seq = retrieve_marking_seq(node) + [new_marking]

                debug_msg = 'Recursed marking sequence: {}'
                debug_msg = debug_msg.format(marking_seq)
                logger.debug(debug_msg)

                return marking_seq

            # filter out all visible transitions and add to queue if there are enabled invisible transitions
            # also filter out transitions that lead to an already visited marking
            filtered_enabled = list()
            for t in new_enabled_trans:
                is_inv_t = is_inv(t)
                new_marking_t = semantics.execute(t, net, cur_marking)
                to_new_marking = new_marking_t not in visited
                if is_inv_t and to_new_marking:
                    filtered_enabled.append(t)
                    visited.add(to_new_marking)

            if len(filtered_enabled):
                # add new_marking to queue
                new_node = (
                    new_marking,
                    filtered_enabled,
                    node
                )
                queue.append(new_node)

        except:
            queue.pop(0)

    # cannot enable target transition
    return None
Esempio n. 20
0
def apply_trace(trace,
                net,
                initial_marking,
                final_marking,
                trans_map,
                enable_pltr_fitness,
                place_fitness,
                transition_fitness,
                notexisting_activities_in_model,
                places_shortest_path_by_hidden,
                consider_remaining_in_fitness,
                activity_key="concept:name",
                try_to_reach_final_marking_through_hidden=True,
                stop_immediately_unfit=False,
                walk_through_hidden_trans=True,
                post_fix_caching=None,
                marking_to_activity_caching=None,
                is_reduction=False,
                thread_maximum_ex_time=MAX_DEF_THR_EX_TIME,
                enable_postfix_cache=False,
                enable_marktoact_cache=False,
                cleaning_token_flood=False,
                s_components=None):
    """
    Apply the token replaying algorithm to a trace

    Parameters
    ----------
    trace
        Trace in the event log
    net
        Petri net
    initial_marking
        Initial marking
    final_marking
        Final marking
    trans_map
        Map between transitions labels and transitions
    enable_pltr_fitness
        Enable fitness calculation at place/transition level
    place_fitness
        Current dictionary of places associated with unfit traces
    transition_fitness
        Current dictionary of transitions associated with unfit traces
    notexisting_activities_in_model
        Map that stores the notexisting activities in the model
    places_shortest_path_by_hidden
        Shortest paths between places by hidden transitions
    consider_remaining_in_fitness
        Boolean value telling if the remaining tokens should be considered in fitness evaluation
    activity_key
        Name of the attribute that contains the activity
    try_to_reach_final_marking_through_hidden
        Boolean value that decides if we shall try to reach the final marking through hidden transitions
    stop_immediately_unfit
        Boolean value that decides if we shall stop immediately when a non-conformance is detected
    walk_through_hidden_trans
        Boolean value that decides if we shall walk through hidden transitions in order to enable visible transitions
    post_fix_caching
        Stores the post fix caching object
    marking_to_activity_caching
        Stores the marking-to-activity cache
    is_reduction
        Expresses if the token-based replay is called in a reduction attempt
    thread_maximum_ex_time
        Alignment threads maximum allowed execution time
    enable_postfix_cache
        Enables postfix cache
    enable_marktoact_cache
        Enables marking to activity cache
    cleaning_token_flood
        Decides if a cleaning of the token flood shall be operated
    s_components
        S-components of the Petri net (if workflow net)
    """
    trace_activities = [event[activity_key] for event in trace]
    act_trans = []
    transitions_with_problems = []
    vis_mark = []
    activating_transition_index = {}
    activating_transition_interval = []
    used_postfix_cache = False
    marking = copy(initial_marking)
    vis_mark.append(marking)
    missing = 0
    consumed = 0
    sum_tokens_im = 0
    for place in initial_marking:
        sum_tokens_im = sum_tokens_im + initial_marking[place]
    sum_tokens_fm = 0
    for place in final_marking:
        sum_tokens_fm = sum_tokens_fm + final_marking[place]
    produced = sum_tokens_im
    current_event_map = {}
    current_remaining_map = {}
    for i in range(len(trace)):
        if enable_postfix_cache and (
                str(trace_activities) in post_fix_caching.cache
                and hash(marking)
                in post_fix_caching.cache[str(trace_activities)]):
            trans_to_act = post_fix_caching.cache[str(trace_activities)][hash(
                marking)]["trans_to_activate"]
            for z in range(len(trans_to_act)):
                t = trans_to_act[z]
                act_trans.append(t)
            used_postfix_cache = True
            marking = post_fix_caching.cache[str(trace_activities)][hash(
                marking)]["final_marking"]
            break
        else:
            prev_len_activated_transitions = len(act_trans)
            if enable_marktoact_cache and (
                    hash(marking) in marking_to_activity_caching.cache
                    and trace[i][activity_key]
                    in marking_to_activity_caching.cache[hash(marking)]
                    and trace[i - 1][activity_key]
                    == marking_to_activity_caching.cache[hash(marking)][
                        trace[i][activity_key]]["previousActivity"]):
                this_end_marking = marking_to_activity_caching.cache[hash(
                    marking)][trace[i][activity_key]]["end_marking"]
                this_act_trans = marking_to_activity_caching.cache[hash(
                    marking)][trace[i]
                              [activity_key]]["this_activated_transitions"]
                this_vis_markings = marking_to_activity_caching.cache[hash(
                    marking)][trace[i][activity_key]]["this_visited_markings"]
                act_trans = act_trans + this_act_trans
                vis_mark = vis_mark + this_vis_markings
                marking = copy(this_end_marking)
            else:
                if trace[i][activity_key] in trans_map:
                    current_event_map.update(trace[i])
                    t = trans_map[trace[i][activity_key]]
                    if walk_through_hidden_trans and not semantics.is_enabled(
                            t, net, marking):
                        visited_transitions = set()
                        prev_len_activated_transitions = len(act_trans)
                        [net, marking, act_trans,
                         vis_mark] = apply_hidden_trans(
                             t, net, marking, places_shortest_path_by_hidden,
                             act_trans, 0, visited_transitions, vis_mark)
                    is_initially_enabled = True
                    old_marking_names = [x.name for x in list(marking.keys())]
                    if not semantics.is_enabled(t, net, marking):
                        is_initially_enabled = False
                        transitions_with_problems.append(t)
                        if stop_immediately_unfit:
                            missing = missing + 1
                            break
                        [m, tokens_added] = add_missing_tokens(t, marking)
                        missing = missing + m
                        if enable_pltr_fitness:
                            for place in tokens_added.keys():
                                if place in place_fitness:
                                    place_fitness[place][
                                        "underfed_traces"].add(trace)
                            if trace not in transition_fitness[t][
                                    "underfed_traces"]:
                                transition_fitness[t]["underfed_traces"][
                                    trace] = list()
                            transition_fitness[t]["underfed_traces"][
                                trace].append(current_event_map)
                    elif enable_pltr_fitness:
                        if trace not in transition_fitness[t]["fit_traces"]:
                            transition_fitness[t]["fit_traces"][trace] = list()
                        transition_fitness[t]["fit_traces"][trace].append(
                            current_event_map)
                    c = get_consumed_tokens(t)
                    p = get_produced_tokens(t)
                    consumed = consumed + c
                    produced = produced + p
                    if semantics.is_enabled(t, net, marking):
                        marking = semantics.execute(t, net, marking)
                        act_trans.append(t)
                        vis_mark.append(marking)
                    if not is_initially_enabled and cleaning_token_flood:
                        # here, a routine for cleaning token flood shall go
                        new_marking_names = [
                            x.name for x in list(marking.keys())
                        ]
                        new_marking_names_diff = [
                            x for x in new_marking_names
                            if x not in old_marking_names
                        ]
                        new_marking_names_inte = [
                            x for x in new_marking_names
                            if x in old_marking_names
                        ]
                        for p1 in new_marking_names_inte:
                            for p2 in new_marking_names_diff:
                                for comp in s_components:
                                    if p1 in comp and p2 in comp:
                                        place_to_delete = [
                                            place
                                            for place in list(marking.keys())
                                            if place.name == p1
                                        ]
                                        if len(place_to_delete) == 1:
                                            del marking[place_to_delete[0]]
                                            if not place_to_delete[
                                                    0] in current_remaining_map:
                                                current_remaining_map[
                                                    place_to_delete[0]] = 0
                                            current_remaining_map[
                                                place_to_delete[
                                                    0]] = current_remaining_map[
                                                        place_to_delete[0]] + 1
                        pass
                else:
                    if not trace[i][
                            activity_key] in notexisting_activities_in_model:
                        notexisting_activities_in_model[trace[i]
                                                        [activity_key]] = {}
                    notexisting_activities_in_model[
                        trace[i][activity_key]][trace] = current_event_map
            del trace_activities[0]
            if len(trace_activities) < MAX_POSTFIX_SUFFIX_LENGTH:
                activating_transition_index[str(trace_activities)] = {
                    "index": len(act_trans),
                    "marking": hash(marking)
                }
            if i > 0:
                activating_transition_interval.append([
                    trace[i][activity_key], prev_len_activated_transitions,
                    len(act_trans), trace[i - 1][activity_key]
                ])
            else:
                activating_transition_interval.append([
                    trace[i][activity_key], prev_len_activated_transitions,
                    len(act_trans), ""
                ])

    if try_to_reach_final_marking_through_hidden and not used_postfix_cache:
        for i in range(MAX_IT_FINAL1):
            if not break_condition_final_marking(marking, final_marking):
                hidden_transitions_to_enable = get_req_transitions_for_final_marking(
                    marking, final_marking, places_shortest_path_by_hidden)

                for group in hidden_transitions_to_enable:
                    for t in group:
                        if semantics.is_enabled(t, net, marking):
                            marking = semantics.execute(t, net, marking)
                            act_trans.append(t)
                            vis_mark.append(marking)
                    if break_condition_final_marking(marking, final_marking):
                        break
            else:
                break

        # if i > DebugConst.REACH_ITF1:
        #    DebugConst.REACH_ITF1 = i

        # try to reach the final marking in a different fashion, if not already reached
        if not break_condition_final_marking(marking, final_marking):
            if len(final_marking) == 1:
                sink_place = list(final_marking)[0]

                connections_to_sink = []
                for place in marking:
                    if place in places_shortest_path_by_hidden and sink_place in places_shortest_path_by_hidden[
                            place]:
                        connections_to_sink.append([
                            place,
                            places_shortest_path_by_hidden[place][sink_place]
                        ])
                connections_to_sink = sorted(connections_to_sink,
                                             key=lambda x: len(x[1]))

                for i in range(MAX_IT_FINAL2):
                    for j in range(len(connections_to_sink)):
                        for z in range(len(connections_to_sink[j][1])):
                            t = connections_to_sink[j][1][z]
                            if semantics.is_enabled(t, net, marking):
                                marking = semantics.execute(t, net, marking)
                                act_trans.append(t)
                                vis_mark.append(marking)
                                continue
                            else:
                                break

                # if i > DebugConst.REACH_ITF2:
                #    DebugConst.REACH_ITF2 = i

    if break_condition_final_marking(marking, final_marking):
        consumed = consumed + sum_tokens_fm

    marking_before_cleaning = copy(marking)

    remaining = 0
    for p in marking:
        if p in final_marking:
            marking[p] = max(0, marking[p] - final_marking[p])
            if enable_pltr_fitness:
                if marking[p] > 0:
                    if p in place_fitness:
                        if trace not in place_fitness[p]["underfed_traces"]:
                            place_fitness[p]["overfed_traces"].add(trace)
        remaining = remaining + marking[p]

    for p in current_remaining_map:
        if enable_pltr_fitness:
            if p in place_fitness:
                if trace not in place_fitness[p][
                        "underfed_traces"] and trace not in place_fitness[p][
                            "overfed_traces"]:
                    place_fitness[p]["overfed_traces"].add(trace)
        remaining = remaining + current_remaining_map[p]

    if consider_remaining_in_fitness:
        is_fit = (missing == 0) and (remaining == 0)
    else:
        is_fit = (missing == 0)

    if consumed > 0 and produced > 0:
        #trace_fitness = (1.0 - float(missing) / float(consumed)) * (1.0 - float(remaining) / float(produced))
        trace_fitness = 0.5 * (1.0 -
                               float(missing) / float(consumed)) + 0.5 * (
                                   1.0 - float(remaining) / float(produced))
    else:
        trace_fitness = 1.0

    if is_fit:
        for suffix in activating_transition_index:
            if suffix not in post_fix_caching.cache:
                post_fix_caching.cache[suffix] = {}
            if activating_transition_index[suffix][
                    "marking"] not in post_fix_caching.cache[suffix]:
                post_fix_caching.cache[suffix][activating_transition_index[suffix]["marking"]] = \
                    {"trans_to_activate": act_trans[activating_transition_index[suffix]["index"]:],
                     "final_marking": marking}
        for trans in activating_transition_interval:
            activity = trans[0]
            start_marking_index = trans[1]
            end_marking_index = trans[2]
            previous_activity = trans[3]
            if end_marking_index < len(vis_mark):
                start_marking_object = vis_mark[start_marking_index]
                start_marking_hash = hash(start_marking_object)
                end_marking_object = vis_mark[end_marking_index]
                if activity in trans_map:
                    this_activated_trans = act_trans[
                        start_marking_index:end_marking_index]
                    this_visited_markings = vis_mark[start_marking_index +
                                                     1:end_marking_index + 1]

                    if start_marking_hash not in marking_to_activity_caching.cache:
                        marking_to_activity_caching.cache[
                            start_marking_hash] = {}
                    if activity not in marking_to_activity_caching.cache[
                            start_marking_hash]:
                        marking_to_activity_caching.cache[start_marking_hash][
                            activity] = {
                                "start_marking": start_marking_object,
                                "end_marking": end_marking_object,
                                "this_activated_transitions":
                                this_activated_trans,
                                "this_visited_markings": this_visited_markings,
                                "previousActivity": previous_activity
                            }

    return [
        is_fit, trace_fitness, act_trans, transitions_with_problems,
        marking_before_cleaning,
        get_visible_transitions_eventually_enabled_by_marking(
            net,
            marking_before_cleaning), missing, consumed, remaining, produced
    ]
Esempio n. 21
0
def apply_hidden_trans(t, net, marking, places_shortest_paths_by_hidden,
                       act_tr, rec_depth, visit_trans, vis_mark):
    """
    Apply hidden transitions in order to enable a given transition

    Parameters
    ----------
    t
        Transition to eventually enable
    net
        Petri net
    marking
        Marking
    places_shortest_paths_by_hidden
        Shortest paths between places connected by hidden transitions
    act_tr
        All activated transitions
    rec_depth
        Current recursion depth
    visit_trans
        All visited transitions by hiddenTrans method
    vis_mark
        All visited markings
    """
    if rec_depth >= MAX_REC_DEPTH_HIDTRANSENABL or t in visit_trans:
        return [net, marking, act_tr, vis_mark]
    # if rec_depth > DebugConst.REACH_MRH:
    #    DebugConst.REACH_MRH = rec_depth
    visit_trans.add(t)
    marking_at_start = copy(marking)
    places_with_missing = get_places_with_missing_tokens(t, marking)
    hidden_transitions_to_enable = get_hidden_transitions_to_enable(
        marking, places_with_missing, places_shortest_paths_by_hidden)

    if hidden_transitions_to_enable:
        [marking, act_tr, visit_trans,
         vis_mark] = enable_hidden_transitions(net, marking, act_tr,
                                               visit_trans, vis_mark,
                                               hidden_transitions_to_enable, t)
        if not semantics.is_enabled(t, net, marking):
            hidden_transitions_to_enable = get_hidden_transitions_to_enable(
                marking, places_with_missing, places_shortest_paths_by_hidden)
            for z in range(len(hidden_transitions_to_enable)):
                for k in range(len(hidden_transitions_to_enable[z])):
                    t4 = hidden_transitions_to_enable[z][k]
                    if not t4 == t:
                        if t4 not in visit_trans:
                            if not semantics.is_enabled(t4, net, marking):
                                [net, marking, act_tr,
                                 vis_mark] = apply_hidden_trans(
                                     t4, net, marking,
                                     places_shortest_paths_by_hidden, act_tr,
                                     rec_depth + 1, visit_trans, vis_mark)
                            if semantics.is_enabled(t4, net, marking):
                                marking = semantics.execute(t4, net, marking)
                                act_tr.append(t4)
                                visit_trans.add(t4)
                                vis_mark.append(marking)
        if not semantics.is_enabled(t, net, marking):
            if not (marking_at_start == marking):
                [net, marking, act_tr, vis_mark] = apply_hidden_trans(
                    t, net, marking, places_shortest_paths_by_hidden, act_tr,
                    rec_depth + 1, visit_trans, vis_mark)

    return [net, marking, act_tr, vis_mark]