Exemplo n.º 1
0
def split_loop_infrequent(cut, l, activity_key):
    n = len(cut)
    new_logs = [obj.EventLog() for i in range(0, n)]
    for trace in l:
        s = cut[0]
        st = obj.Trace()
        for act in trace:
            if act in s:
                st.insert(act)
            else:
                j = 0
                for j in range(0, len(cut)):
                    if cut[j] == s:
                        break
                new_logs[j].append(st)
                st = obj.Trace()
                for partition in cut:
                    if act[activity_key] in partition:
                        s.append(partition)
        # L_j <- L_j + [st] with sigma_j = s
        j = 0
        for j in range(0, len(cut)):
            if cut[j] == s:
                break
        new_logs[j].append(st)
        if s != cut[0]:
            new_logs[0].append(obj.EventLog())

    return new_logs
Exemplo n.º 2
0
def map_(func, log):
    '''
        Maps the log according to a given lambda function.
        domain and target of the function need to be of the same type (either trace or event) otherwise, the map behaves unexpected

        Parameters
        ----------
        func
        log

        Returns
        -------

        '''
    if isinstance(log, log_inst.EventLog):
        return log_inst.EventLog(list(map(func, log)),
                                 attributes=log.attributes,
                                 classifiers=log.classifiers,
                                 omni_present=log.omni_present,
                                 extensions=log.extensions,
                                 properties=log.properties)
    elif isinstance(log, log_inst.EventStream):
        return log_inst.EventStream(list(map(func, log)),
                                    attributes=log.attributes,
                                    classifiers=log.classifiers,
                                    omni_present=log.omni_present,
                                    extensions=log.extensions,
                                    properties=log.properties)
    else:
        warnings.warn(
            'input log object not of appropriate type, map() not applied')
        return log
Exemplo n.º 3
0
def split_loop(cut, l, activity_key):
    new_logs = []
    for c in cut:  # for cut partition
        lo = obj.EventLog()
        for trace in l:  # for all traces
            j = 0
            while j in range(0, len(trace)):  # for all events
                if trace[j][activity_key] in c:
                    trace_new = obj.Trace()
                    # declared here and not above, so that we can generate multiple traces from one trace and
                    # cut (repetition)
                    # append those events that are contained in c:
                    while trace[j][activity_key] in c:
                        trace_new.append(trace[j])
                        if j + 1 < len(trace):
                            j += 1
                        else:
                            j += 1
                            break
                    lo.append(trace_new)
                else:
                    j += 1

        if len(lo) != 0:
            new_logs.append(lo)

    return new_logs
Exemplo n.º 4
0
def split_sequence(cut, l, activity_key):
    new_logs = []
    for c in cut:  # for all cut-partitions
        lo = obj.EventLog()
        for trace in l:  # for all traces in the log
            not_in_c = True
            trace_new = obj.Trace()
            for j in range(0,
                           len(trace)):  # for every event in the current trace
                if trace[j][activity_key] in c:
                    not_in_c = False
                    while trace[j][activity_key] in c:
                        trace_new.append(
                            trace[j]
                        )  # we only add the events that match the cut partition
                        if j + 1 < len(trace):
                            j += 1
                        else:
                            j += 1
                            break
                    lo.append(trace_new)
                    break
            if not_in_c:
                lo.append(trace_new)
        new_logs.append(lo)
    if len(new_logs) > 0:
        return new_logs
Exemplo n.º 5
0
def filter_(func, log):
    '''
    Filters the log according to a given lambda function.

    Parameters
    ----------
    func
    log

    Returns
    -------

    '''
    if isinstance(log, log_inst.EventLog):
        return log_inst.EventLog(list(filter(func, log)),
                                 attributes=log.attributes,
                                 classifiers=log.classifiers,
                                 omni_present=log.omni_present,
                                 extensions=log.extensions,
                                 properties=log.properties)
    elif isinstance(log, log_inst.EventStream):
        return log_inst.EventStream(list(filter(func, log)),
                                    attributes=log.attributes,
                                    classifiers=log.classifiers,
                                    omni_present=log.omni_present,
                                    extensions=log.extensions,
                                    properties=log.properties)
    else:
        warnings.warn(
            'input log object not of appropriate type, filter() not applied')
        return log
Exemplo n.º 6
0
def __transform_event_stream_to_event_log(
        log,
        case_glue=Parameters.CASE_ID_KEY.value,
        include_case_attributes=True,
        case_attribute_prefix=Parameters.CASE_ATTRIBUTE_PREFIX.value,
        enable_deepcopy=False):
    """
    Converts the event stream to an event log

    Parameters
    ----------
    log: :class:`pm4py.log.log.EventLog`
        An event stream
    case_glue:
        Case identifier. Default is 'case:concept:name'
    include_case_attributes:
        Default is True
    case_attribute_prefix:
        Default is 'case:'
    enable_deepcopy
        Enables deepcopy (avoid references between input and output objects)

    Returns
        -------
    log : :class:`pm4py.log.log.EventLog`
        An event log
    """
    if enable_deepcopy:
        log = deepcopy(log)

    traces = {}
    for orig_event in log:
        event = copy(orig_event)
        glue = event[case_glue]
        if glue not in traces:
            trace_attr = {}
            if include_case_attributes:
                for k in event.keys():
                    if k.startswith(case_attribute_prefix):
                        trace_attr[k.replace(case_attribute_prefix,
                                             '')] = event[k]
                if xes.DEFAULT_TRACEID_KEY not in trace_attr:
                    trace_attr[xes.DEFAULT_TRACEID_KEY] = glue
            traces[glue] = log_instance.Trace(attributes=trace_attr)

        if include_case_attributes:
            for k in list(event.keys()):
                if k.startswith(case_attribute_prefix):
                    del event[k]

        traces[glue].append(event)
    return log_instance.EventLog(traces.values(),
                                 attributes=log.attributes,
                                 classifiers=log.classifiers,
                                 omni_present=log.omni_present,
                                 extensions=log.extensions,
                                 properties=log.properties)
Exemplo n.º 7
0
def split_parallel(cut, l, activity_key):
    new_logs = []
    for c in cut:
        lo = obj.EventLog()
        for trace in l:
            new_trace = obj.Trace()
            for event in trace:
                if event[activity_key] in c:
                    new_trace.append(event)
            lo.append(new_trace)
        new_logs.append(lo)
    return new_logs
Exemplo n.º 8
0
def split_xor(cut, l, activity_key):
    new_logs = []
    for c in cut:  # for cut partition
        lo = obj.EventLog()
        for i in range(0, len(l)):  # for trace in log
            fits = True
            for j in range(0, len(l[i])):  # for event in trace
                if l[i][j][activity_key] not in c:
                    fits = False  # if not every event fits the current cut-partition, we don't add it's trace
            if fits:
                lo.append(l[i])
        new_logs.append(lo)

    return new_logs  # new_logs is a list that contains logs
Exemplo n.º 9
0
def empty_trace_filtering(l, f):
    enough_traces = False
    empty_traces_present, counter = __count_empty_traces(l)
    if counter >= len(l) * f:
        enough_traces = True

    if empty_traces_present:
        new_log = obj.EventLog()
        for trace in l:
            if len(trace) != 0:
                new_log.append(trace)
        return empty_traces_present, enough_traces, new_log
    else:
        return False, False, l
Exemplo n.º 10
0
def apply_from_variants_list(var_list,
                             petri_net,
                             initial_marking,
                             final_marking,
                             parameters=None):
    """
    Apply the alignments from the specification of a list of variants in the log

    Parameters
    -------------
    var_list
        List of variants (for each item, the first entry is the variant itself, the second entry may be the number of cases)
    petri_net
        Petri net
    initial_marking
        Initial marking
    final_marking
        Final marking
    parameters
        Parameters of the algorithm (same as 'apply' method, plus 'variant_delimiter' that is , by default)

    Returns
    --------------
    dictio_alignments
        Dictionary that assigns to each variant its alignment
    """
    if parameters is None:
        parameters = {}

    log = log_implementation.EventLog()
    dictio_alignments = {}
    for varitem in var_list:
        variant = varitem[0]
        trace = variants_util.variant_to_trace(variant, parameters=parameters)
        log.append(trace)

    alignment = apply(log, petri_net, initial_marking, final_marking)

    for index, varitem in enumerate(var_list):
        variant = varitem[0]
        dictio_alignments[variant] = alignment[index]

    return dictio_alignments
Exemplo n.º 11
0
def sort_log(
        log: log_inst.EventLog,
        key,
        reverse: bool = False
) -> Union[log_inst.EventLog, log_inst.EventStream]:
    """
    Sorts the event log according to a given key.

    Parameters
    ----------
    log
        event log object; either EventLog or EventStream
    key
        sorting key
    reverse
        indicates whether sorting should be reversed or not

    Returns
    -------
        sorted event log if object provided is correct; original log if not correct
    """
    if type(log) not in [pd.DataFrame, EventLog, EventStream]:
        raise Exception(
            "the method can be applied only to a traditional event log!")

    if isinstance(log, log_inst.EventLog):
        return log_inst.EventLog(sorted(log, key=key, reverse=reverse),
                                 attributes=log.attributes,
                                 classifiers=log.classifiers,
                                 omni_present=log.omni_present,
                                 extensions=log.extensions,
                                 properties=log.properties)
    elif isinstance(log, log_inst.EventStream):
        return log_inst.EventStream(sorted(log, key=key, reverse=reverse),
                                    attributes=log.attributes,
                                    classifiers=log.classifiers,
                                    omni_present=log.omni_present,
                                    extensions=log.extensions,
                                    properties=log.properties)
    else:
        warnings.warn(
            'input log object not of appropriate type, sorted() not applied')
        return log
Exemplo n.º 12
0
def sort_(func, log, reverse=False):
    if isinstance(log, log_inst.EventLog):
        return log_inst.EventLog(sorted(log, key=func, reverse=reverse),
                                 attributes=log.attributes,
                                 classifiers=log.classifiers,
                                 omni_present=log.omni_present,
                                 extensions=log.extensions,
                                 properties=log.properties)
    elif isinstance(log, log_inst.EventStream):
        return log_inst.EventStream(sorted(log, key=func, reverse=reverse),
                                    attributes=log.attributes,
                                    classifiers=log.classifiers,
                                    omni_present=log.omni_present,
                                    extensions=log.extensions,
                                    properties=log.properties)
    else:
        warnings.warn(
            'input log object not of appropriate type, map() not applied')
        return log
Exemplo n.º 13
0
def split_sequence_infrequent(cut, l, activity_key):
    # write L_1,...,L_n like in second line of code on page 206
    n = len(cut)
    new_logs = [obj.EventLog() for j in range(0, n)]
    ignore = []
    split_points_list = [0] * len(l)
    for i in range(0, n):
        split_point = 0
        # write our ignore list with all elements from past cut partitions
        if i != 0:
            for element in cut[i-1]:
                ignore.append(element)
        for j in range(len(l)):
            trace = l[j]
            new_split_point = find_split_point(trace, cut[i], split_points_list[j], ignore, activity_key)
            cutted_trace = cut_trace_between_two_points(trace, split_points_list[j], new_split_point)
            filtered_trace = filter_trace_on_cut_partition(cutted_trace, cut[i], activity_key)
            new_logs[i].append(filtered_trace)
            split_points_list[j] = new_split_point
    return new_logs
Exemplo n.º 14
0
def filter_log(
        f: Callable[[Any], bool], log: log_inst.EventLog
) -> Union[log_inst.EventLog, log_inst.EventStream]:
    """
    Filters the log according to a given (lambda) function.

    Parameters
    ----------
    f
        function that specifies the filter criterion, may be a lambda
    log
        event log; either EventLog or EventStream Object

    Returns
    -------
    log
        filtered event log if object provided is correct; original log if not correct

    """
    if type(log) not in [pd.DataFrame, EventLog, EventStream]:
        raise Exception(
            "the method can be applied only to a traditional event log!")

    if isinstance(log, log_inst.EventLog):
        return log_inst.EventLog(list(filter(f, log)),
                                 attributes=log.attributes,
                                 classifiers=log.classifiers,
                                 omni_present=log.omni_present,
                                 extensions=log.extensions,
                                 properties=log.properties)
    elif isinstance(log, log_inst.EventStream):
        return log_inst.EventStream(list(filter(f, log)),
                                    attributes=log.attributes,
                                    classifiers=log.classifiers,
                                    omni_present=log.omni_present,
                                    extensions=log.extensions,
                                    properties=log.properties)
    else:
        warnings.warn(
            'input log object not of appropriate type, filter() not applied')
        return log
Exemplo n.º 15
0
def split_xor_infrequent(cut, l, activity_key):
    # TODO think of empty logs
    # creating the empty L_1,...,L_n from the second code-line on page 205
    n = len(cut)
    new_logs = [obj.EventLog() for i in range(0, n)]
    for trace in l:                                                 # for all traces
        number_of_events_in_trace = 0
        index_of_cut_partition = 0
        i = 0
        # use i as index here so that we can write in L_i
        for i in range(0, len(cut)):                                # for all cut partitions
            temp_counter = 0
            for event in trace:                                     # for all events in current trace
                if event[activity_key] in cut[i]:                 # count amount of events from trace in partition
                    temp_counter += 1
            if temp_counter > number_of_events_in_trace:
                number_of_events_in_trace = temp_counter
                index_of_cut_partition = i
        filtered_trace = filter_trace_on_cut_partition(trace, cut[index_of_cut_partition], activity_key)
        new_logs[index_of_cut_partition].append(filtered_trace)
    return new_logs
Exemplo n.º 16
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
Exemplo n.º 17
0
def apply(net: PetriNet, initial_marking: Marking, final_marking: Marking = None,
          parameters: Optional[Dict[Union[str, Parameters], Any]] = None) -> EventLog:
    """
    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
            Parameters.PETRI_SEMANTICS -> Petri net semantics
    """
    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)
    semantics = exec_utils.get_param_value(Parameters.PETRI_SEMANTICS, parameters, petri_net.semantics.ClassicSemantics())

    # 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, net, 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
Exemplo n.º 18
0
def apply_playout(net, initial_marking, no_traces=100, max_trace_length=100,
                  initial_timestamp=10000000, initial_case_id=0,
                  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, return_visited_elements=False, semantics=petri_net.semantics.ClassicSemantics()):
    """
    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)
    initial_timestamp
        Increased timestamp from 1970 for the first event
    initial_case_id
        Case id of the first event
    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
    semantics
        Semantics of the Petri net to be used (default: petri_net.semantics.ClassicSemantics())
    """
    # assigns to each event an increased timestamp from 1970
    curr_timestamp = initial_timestamp
    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:
                trans = choice(list(all_enabled_trans.union({None})))
            else:
                trans = choice(list(all_enabled_trans))
            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+initial_case_id)
        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