Exemple #1
0
def get_all_footprints(tree, parameters=None):
    """
    Gets all the footprints for the nodes of the tree

    Parameters
    -----------------
    tree
        Process tree
    parameters
        Parameters of the algorithm

    Returns
    ----------------
    dictio
        Dictionary that associates a footprint to each node of the tree
    """
    if parameters is None:
        parameters = {}

    # for each node of the bottom up, proceed to getting the footprints
    bottomup = bottomup_disc.get_bottomup_nodes(tree, parameters=parameters)
    footprints_dictio = {}
    for i in range(len(bottomup)):
        footprints_dictio[bottomup[i]] = get_footprints(bottomup[i], footprints_dictio)

    return footprints_dictio
Exemple #2
0
def apply(tree: ProcessTree, parameters : Optional[Dict[Union[str, Parameters], Any]] = None) -> EventLog:
    """
    Performs an extensive playout of the process tree

    Parameters
    -------------
    tree
        Process tree
    parameters
        Possible parameters, including:
        - Parameters.MIN_TRACE_LENGTH => minimum length of a trace (default: 1)
        - Parameters.MAX_TRACE_LENGTH => maximum length of a trace (default: min_allowed_trace_length)
        - Parameters.MAX_LOOP_OCC => maximum number of occurrences for a loop (default: MAX_TRACE_LENGTH)
        - Parameters.ACTIVITY_KEY => activity key
        - Parameters.MAX_LIMIT_NUM_TRACES => maximum number to the limit of traces; the playout shall stop when the number is reached (default: 100000)
    Returns
    -------------
    log
        Event log
    """
    if parameters is None:
        parameters = {}

    activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY, parameters, xes_constants.DEFAULT_NAME_KEY)
    # to save memory in the returned log, allocate each activity once. to know the list of activities of the
    # process tree, use the footprints module
    fp_tree = fp_discovery.apply(tree, parameters=parameters)
    activities = fp_tree["activities"]
    activities = {act: Event({activity_key: act}) for act in activities}

    min_allowed_trace_length = bottomup_discovery.get_min_trace_length(tree, parameters=parameters)
    min_trace_length = exec_utils.get_param_value(Parameters.MIN_TRACE_LENGTH, parameters, 1)
    max_trace_length = exec_utils.get_param_value(Parameters.MAX_TRACE_LENGTH, parameters, min_allowed_trace_length)
    max_loop_occ = exec_utils.get_param_value(Parameters.MAX_LOOP_OCC, parameters, int(max_trace_length / 2))
    max_limit_num_traces = exec_utils.get_param_value(Parameters.MAX_LIMIT_NUM_TRACES, parameters, 100000)
    return_set_strings = exec_utils.get_param_value(Parameters.RETURN_SET_STRINGS, parameters, False)

    bottomup = bottomup_discovery.get_bottomup_nodes(tree, parameters=parameters)
    min_rem_dict = bottomup_discovery.get_min_rem_dict(tree, parameters=parameters)
    max_rem_dict = bottomup_discovery.get_max_rem_dict(tree, parameters=parameters)

    playout_dictio = {}
    for i in range(len(bottomup)):
        get_playout(bottomup[i], playout_dictio, min_trace_length, max_trace_length, max_loop_occ, min_rem_dict,
                    max_rem_dict, max_limit_num_traces)
    tree_playout_traces = playout_dictio[tree][TRACES]

    if return_set_strings:
        return tree_playout_traces

    log = EventLog()
    for tr0 in tree_playout_traces:
        trace = Trace()
        for act in tr0:
            trace.append(activities[act])
        log.append(trace)

    return log
Exemple #3
0
def apply(pt: ProcessTree, align_result: Union[typing.AlignmentResult, typing.ListAlignments],
          parameters: Optional[Dict[Any, Any]] = None) -> ProcessTree:
    """
    Annotate a process tree with frequency information (number of events / number of cases),
    given the results of an alignment performed on the process tree.

    Parameters
    ----------------
    pt
        Process tree
    parameters
        Parameters of the algorithm, including:
        - Parameters.NUM_EVENTS_PROPERTY => number of events
        - Parameters.NUM_CASES_PROPERTY => number of cases

    Returns
    ----------------
    pt
        Annotated process tree
    """
    if parameters is None:
        parameters = {}

    num_events_property = exec_utils.get_param_value(Parameters.NUM_EVENTS_PROPERTY, parameters, "num_events")
    num_cases_property = exec_utils.get_param_value(Parameters.NUM_CASES_PROPERTY, parameters, "num_cases")
    bottomup_nodes = bottomup.get_bottomup_nodes(pt, parameters=parameters)

    all_paths_open_enabled_events = []
    all_paths_open_enabled_cases = []
    for trace in align_result:
        state = trace["state"]
        paths = []
        while state.parent is not None:
            if state.path:
                paths.append(state.path)
            state = state.parent
        paths.reverse()
        paths_enabled = [y[0] for x in paths for y in x if y[1] is ProcessTree.OperatorState.ENABLED]
        paths_open = [y[0] for x in paths for y in x if y[1] is ProcessTree.OperatorState.OPEN if
                      y[0] not in paths_enabled]
        all_paths_open_enabled_events = all_paths_open_enabled_events + paths_enabled + paths_open
        all_paths_open_enabled_cases = all_paths_open_enabled_cases + list(set(paths_enabled + paths_open))
    all_paths_open_enabled_events_counter = Counter(all_paths_open_enabled_events)
    all_paths_open_enabled_cases_counter = Counter(all_paths_open_enabled_cases)

    for node in bottomup_nodes:
        node._properties[num_events_property] = all_paths_open_enabled_events_counter[node]
        node._properties[num_cases_property] = all_paths_open_enabled_cases_counter[node]

    return pt
Exemple #4
0
def apply(tree: ProcessTree,
          trace: Trace,
          parameters: Optional[Dict[Any, Any]] = None,
          **kwargs) -> ProcessTree:
    """
    Reduce a process tree replacing the skippable elements that have empty intersection with the
    trace.

    Parameters
    -----------------
    tree
        Process tree
    trace
        Trace of an event log
    parameters
        Parameters of the algorithm, possible values: Parameters.ACTIVITY_KEY

    Returns
    ------------------
    tree
        Reduced process tree
    """
    if parameters is None:
        parameters = {}

    activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY,
                                              parameters,
                                              xes_constants.DEFAULT_NAME_KEY)
    activities = set(x[activity_key] for x in trace)

    tree = deepcopy(tree)
    from pm4py.algo.discovery.footprints.tree.variants import bottomup as footprints

    bottomup_nodes = bottomup.get_bottomup_nodes(tree)
    fps = footprints.get_all_footprints(tree)
    fps = {id(x): y for x, y in fps.items()}

    return reduce(bottomup_nodes, fps, activities)
Exemple #5
0
                    alignments_clean)["average_trace_fitness"]
                if fitness_al_clean < fitness_im_clean:
                    print("ALERT")
                    input()
                else:
                    print("OK ALIGNMENTS", fitness_al_clean)

            precision_im_clean = pm4py.algo.conformance.footprints.util.evaluation.fp_precision(
                fp_log, fp_tree_clean)
            precision_im = pm4py.algo.conformance.footprints.util.evaluation.fp_precision(
                fp_log, fp_tree_im)
            precision_imf = pm4py.algo.conformance.footprints.util.evaluation.fp_precision(
                fp_log, fp_tree_imf)
            precision_imd = pm4py.algo.conformance.footprints.util.evaluation.fp_precision(
                fp_log, fp_tree_imd)
            print("IMCLEAN fp-fitness=%.3f fp-precision=%.3f" %
                  (fitness_im_clean, precision_im_clean))
            print("IM fp-fitness=%.3f fp-precision=%.3f" %
                  (fitness_im, precision_im))
            print("IMf fp-fitness=%.3f fp-precision=%.3f" %
                  (fitness_imf, precision_imf))
            print("IMd fp-fitness=%.3f fp-precision=%.3f" %
                  (fitness_imd, precision_imd))
        except:
            bottomup_nodes = bottomup_disc.get_bottomup_nodes(tree_im_clean)
            for node in bottomup_nodes:
                if node.parent is None:
                    print(node, node.parent)
            traceback.print_exc()
            input()
Exemple #6
0
def apply(tree, conf_results, parameters=None):
    """
    Projects conformance results on top of the process tree

    Parameters
    --------------
    tree
        Process tree
    conf_results
        Conformance results (footprints on the entire log vs entire model)
    parameters
        Parameters of the algorithm

    Returns
    --------------
    color_map
        Color map to be provided to the visualization
    """
    if parameters is None:
        parameters = {}

    start_activities = {}
    end_activities = {}

    if type(conf_results) is list:
        raise Exception(
            "the visualization can only be applied with total footprints (not trace-by-trace)!"
        )
    elif type(conf_results) is dict:
        footprints = conf_results
        start_activities = conf_results[START_ACTIVITIES]
        end_activities = conf_results[END_ACTIVITIES]
    else:
        footprints = conf_results

    bottomup_nodes = bottomup_util.get_bottomup_nodes(tree,
                                                      parameters=parameters)
    labels_dictio = {
        x.label: x
        for x in bottomup_nodes if x.operator is None and x.label is not None
    }
    all_fp_dictio = bottomup_discovery.get_all_footprints(
        tree, parameters=parameters)
    conf_colors = {}

    for res in start_activities:
        if res in labels_dictio:
            conf_colors[labels_dictio[res]] = FP_START_END_DEV_COLOR

    for res in end_activities:
        if res in labels_dictio:
            conf_colors[labels_dictio[res]] = FP_START_END_DEV_COLOR

    for res in footprints:
        if res[0] in labels_dictio and res[1] in labels_dictio:
            conf_colors[labels_dictio[res[0]]] = FP_DEV_COLOR
            conf_colors[labels_dictio[res[1]]] = FP_DEV_COLOR
            for n in bottomup_nodes:
                if res[0] in all_fp_dictio[n][
                        Outputs.ACTIVITIES.value] and res[1] in all_fp_dictio[
                            n][Outputs.ACTIVITIES.value]:
                    conf_colors[n] = FP_DEV_COLOR
                    break

    return conf_colors