コード例 #1
0
ファイル: classic.py プロジェクト: Javert899/pm4py-distr
    def calculate_fitness_with_alignments(self, net, im, fm, log, parameters=None):
        if parameters is None:
            parameters = {}

        sum_fitness = 0

        variants = log_variants_filter.get_variants_from_log_trace_idx(log, parameters=parameters)
        var_list = [[x, y] for x, y in variants.items()]

        result = self.perform_alignments_net_variants(net, im, fm, var_list=var_list, parameters=parameters)
        total_cases = 0
        total_fit_cases = 0

        best_worst_cost = state_equation_a_star.get_best_worst_cost(net, im, fm, parameters={})

        for index_variant, variant in enumerate(variants):
            total_cases = total_cases + len(variants[variant])
            if result[variant] is not None:
                fitness = self.fitness_alignment_internal(best_worst_cost, variant, result[variant]["cost"])
                sum_fitness = sum_fitness + fitness * len(variants[variant])

                if result[variant]["cost"] < 10000:
                    total_fit_cases = total_fit_cases + len(variants[variant])

        if total_cases > 0:
            perc_fit_traces = float(100.0 * total_fit_cases) / float(total_cases)

            return {"averageFitness": float(sum_fitness) / float(total_cases), "percFitTraces": perc_fit_traces}
        return {"averageFitness": 0.0, "percFitTraces": 0.0}
コード例 #2
0
 def __variantTable(self, eventLog):
     
     data = pd.DataFrame(variants_filter.get_variants_from_log_trace_idx(eventLog, parameters=None).items())
     data.columns = ['Variants','Traces']
     data['Variants'] = data['Variants'].apply(lambda r: r.split(','))
     data.index.name = 'VariantID'
     
     return data
コード例 #3
0
ファイル: classic.py プロジェクト: iliam/pm4py-distr
    def calculate_fitness_with_tbr(self, net, im, fm, log, parameters=None):
        if parameters is None:
            parameters = {}
        variants = log_variants_filter.get_variants_from_log_trace_idx(
            log, parameters=parameters)
        var_list = [[x, y] for x, y in variants.items()]

        parameters["enable_parameters_precision"] = False
        parameters["consider_remaining_in_fitness"] = True

        result = self.perform_tbr_net_variants(net,
                                               im,
                                               fm,
                                               var_list=var_list,
                                               parameters=parameters)
        total_cases = 0
        total_fit_cases = 0
        sum_of_fitness = 0
        total_m = 0
        total_r = 0
        total_c = 0
        total_p = 0

        for index_variant, variant in enumerate(variants):
            if result[index_variant] is not None:
                sum_of_fitness = sum_of_fitness + len(
                    variants[variant]) * result[index_variant]["trace_fitness"]
                total_m = total_m + len(variants[variant]) * result[
                    index_variant]["missing_tokens"]
                total_r = total_r + len(variants[variant]) * result[
                    index_variant]["remaining_tokens"]
                total_c = total_c + len(variants[variant]) * result[
                    index_variant]["consumed_tokens"]
                total_p = total_p + len(variants[variant]) * result[
                    index_variant]["produced_tokens"]

                total_cases = total_cases + len(variants[variant])
                if result[index_variant]["trace_is_fit"]:
                    total_fit_cases = total_fit_cases + len(variants[variant])

        if total_cases > 0:
            perc_fit_traces = float(
                100.0 * total_fit_cases) / float(total_cases)
            average_fitness = float(sum_of_fitness) / float(total_cases)
            log_fitness = 0.5 * (1 - total_m / total_c) + 0.5 * (
                1 - total_r / total_p)

            return {
                "perc_fit_traces": perc_fit_traces,
                "average_trace_fitness": average_fitness,
                "log_fitness": log_fitness
            }

        return {
            "perc_fit_traces": 0.0,
            "average_trace_fitness": 0.0,
            "log_fitness": 0.0
        }
コード例 #4
0
def get_transition_performance_with_token_replay(log, net, im, fm):
    """
    Gets the transition performance through the usage of token-based replay

    Parameters
    -------------
    log
        Event log
    net
        Petri net
    im
        Initial marking
    fm
        Final marking

    Returns
    --------------
    transition_performance
        Dictionary where each transition label is associated to performance measures
    """
    variants_idx = variants_module.get_variants_from_log_trace_idx(log)
    aligned_traces = token_replay.apply(log, net, im, fm)
    element_statistics = performance_map.single_element_statistics(
        log, net, im, aligned_traces, variants_idx)

    transition_performance = {}
    for el in element_statistics:
        if type(el) is PetriNet.Transition and el.label is not None:
            if "log_idx" in element_statistics[
                    el] and "performance" in element_statistics[el]:
                if len(element_statistics[el]["performance"]) > 0:
                    transition_performance[str(el)] = {
                        "all_values": [],
                        "case_association": {},
                        "mean": 0.0,
                        "median": 0.0
                    }
                    for i in range(len(element_statistics[el]["log_idx"])):
                        if not element_statistics[el]["log_idx"][
                                i] in transition_performance[str(
                                    el)]["case_association"]:
                            transition_performance[str(
                                el)]["case_association"][element_statistics[el]
                                                         ["log_idx"][i]] = []
                        transition_performance[str(el)]["case_association"][
                            element_statistics[el]["log_idx"][i]].append(
                                element_statistics[el]["performance"][i])
                        transition_performance[str(el)]["all_values"].append(
                            element_statistics[el]["performance"][i])
                    transition_performance[str(el)]["all_values"] = sorted(
                        transition_performance[str(el)]["all_values"])
                    if transition_performance[str(el)]["all_values"]:
                        transition_performance[str(el)]["mean"] = mean(
                            transition_performance[str(el)]["all_values"])
                        transition_performance[str(el)]["median"] = median(
                            transition_performance[str(el)]["all_values"])
    return transition_performance
コード例 #5
0
ファイル: classic.py プロジェクト: Leogomat/pm4py-distr
    def calculate_precision_with_tbr(self, net, im, fm, log, parameters=None):
        from pm4py import util as pmutil
        from pm4py.algo.conformance.tokenreplay import factory as token_replay
        from pm4py.objects import log as log_lib
        from pm4py.evaluation.precision import utils as precision_utils

        if parameters is None:
            parameters = {}

        sum_at = 0.0
        sum_ee = 0.0

        prefixes, prefix_count = precision_utils.get_log_prefixes(log)
        print("got prefixes")
        prefixes_keys = list(prefixes.keys())
        fake_log = precision_utils.form_fake_log(prefixes_keys)
        print("got fake log")

        variants = log_variants_filter.get_variants_from_log_trace_idx(
            fake_log, parameters=parameters)
        print("got variants from fake log")
        var_list = [[x, y] for x, y in variants.items()]
        print("got var list")

        parameters["enable_parameters_precision"] = True
        parameters["consider_remaining_in_fitness"] = False

        aligned_traces = self.perform_tbr_net_variants(net,
                                                       im,
                                                       fm,
                                                       var_list=var_list,
                                                       parameters=parameters)
        print("got aligned traces")

        for i in range(len(aligned_traces)):
            if aligned_traces[i]["trace_is_fit"]:
                log_transitions = set(prefixes[prefixes_keys[i]])
                activated_transitions_labels = set([
                    x for x in aligned_traces[i]
                    ["enabled_transitions_in_marking_labels"] if x != "None"
                ])
                sum_at += len(activated_transitions_labels) * prefix_count[
                    prefixes_keys[i]]
                escaping_edges = activated_transitions_labels.difference(
                    log_transitions)
                sum_ee += len(escaping_edges) * prefix_count[prefixes_keys[i]]

        if sum_at > 0:
            precision = 1 - float(sum_ee) / float(sum_at)

        return precision
コード例 #6
0
 def __variantTable(self, eventLog):
     
     """
     Create a table containing the following attributes: VariantID, Variants and Traces
 
     :param eventLog: an eventLog object obtained from the pm4py library
     :return: a pandas DataFrame with the mentioned attributes
     """
     
     data = pd.DataFrame(variants_filter.get_variants_from_log_trace_idx(eventLog, parameters=None).items())
     data.columns = ['Variants','Traces']
     data['Variants'] = data['Variants'].apply(lambda r: r.split(','))
     data.index.name = 'VariantID'
     
     return data
コード例 #7
0
    def perform_tbr_net_log(self, net, im, fm, log, parameters=None):
        if parameters is None:
            parameters = {}
        variants = log_variants_filter.get_variants_from_log_trace_idx(log, parameters=parameters)
        var_list = [[x, y] for x,y in variants.items()]

        result = self.perform_tbr_net_variants(net, im, fm, var_list=var_list, parameters=parameters)

        al_idx = {}
        for index_variant, variant in enumerate(variants):
            for trace_idx in variants[variant]:
                al_idx[trace_idx] = result[index_variant]

        tbr = []
        for i in range(len(log)):
            tbr.append(al_idx[i])

        return tbr
コード例 #8
0
ファイル: classic.py プロジェクト: Javert899/pm4py-distr
    def perform_alignments_tree_log(self, tree, log, parameters=None):
        if parameters is None:
            parameters = {}
        variants = log_variants_filter.get_variants_from_log_trace_idx(log, parameters=parameters)
        var_list = [[x, y] for x, y in variants.items()]

        result = self.perform_alignments_tree_variants(tree, var_list=var_list, parameters=parameters)

        al_idx = {}
        for index_variant, variant in enumerate(variants):
            for trace_idx in variants[variant]:
                al_idx[trace_idx] = result[variant]

        alignments = []
        for i in range(len(log)):
            alignments.append(al_idx[i])

        return alignments
コード例 #9
0
def apply(log, aligned_traces, parameters=None):
    """
    Gets the alignment table visualization from the alignments output

    Parameters
    -------------
    log
        Event log
    aligned_traces
        Aligned traces
    parameters
        Parameters of the algorithm

    Returns
    -------------
    gviz
        Graphviz object
    """
    if parameters is None:
        parameters = {}

    variants_idx_dict = variants_filter.get_variants_from_log_trace_idx(log, parameters=parameters)

    variants_idx_list = []
    for variant in variants_idx_dict:
        variants_idx_list.append((variant, variants_idx_dict[variant]))
    variants_idx_list = sorted(variants_idx_list, key=lambda x: len(x[1]), reverse=True)

    image_format = parameters["format"] if "format" in parameters else "png"

    table_alignments_list = ["digraph {\n", "tbl [\n", "shape=plaintext\n", "label=<\n"]
    table_alignments_list.append("<table border='0' cellborder='1' color='blue' cellspacing='0'>\n")

    table_alignments_list.append("<tr><td>Variant</td><td>Alignment</td></tr>\n")

    for index, variant in enumerate(variants_idx_list):
        al_tr = aligned_traces[variant[1][0]]
        table_alignments_list.append("<tr>")
        table_alignments_list.append(
            "<td><font point-size='9'>Variant " + str(index + 1) + " (" + str(len(variant[1])) + " occurrences)<br />" + variant[
                0] + "</font></td>")
        table_alignments_list.append("<td><font point-size='6'><table border='0'><tr>")
        for move in al_tr['alignment']:
            move_descr = str(move[1]).replace(">", "&gt;")
            if not move[0][0] == ">>" or move[0][1] == ">>":
                table_alignments_list.append("<td bgcolor=\"green\">" + move_descr + "</td>")
            elif move[0][1] == ">>":
                table_alignments_list.append("<td bgcolor=\"violet\">" + move_descr + "</td>")
            elif move[0][0] == ">>":
                table_alignments_list.append("<td bgcolor=\"gray\">" + move_descr + "</td>")
        table_alignments_list.append("</tr></table></font></td>")
        table_alignments_list.append("</tr>")

    table_alignments_list.append("</table>\n")
    table_alignments_list.append(">];\n")
    table_alignments_list.append("}\n")

    table_alignments = "".join(table_alignments_list)

    filename = tempfile.NamedTemporaryFile(suffix='.gv')

    gviz = Source(table_alignments, filename=filename.name)
    gviz.format = image_format

    return gviz
コード例 #10
0
ファイル: factory.py プロジェクト: lvzheqi/pm4py-source
def apply_log(log, petri_net, initial_marking, final_marking, parameters=None, version=VERSION_STATE_EQUATION_A_STAR):
    """
    apply alignments to a trace
    Parameters
    -----------
    log
        object of the form :class:`pm4py.log.log.Trace` trace of events
    petri_net
        :class:`pm4py.objects.petri.petrinet.PetriNet` the model to use for the alignment
    initial_marking
        :class:`pm4py.objects.petri.petrinet.Marking` initial marking of the net
    final_marking
        :class:`pm4py.objects.petri.petrinet.Marking` final marking of the net
    version
        :class:`str` selected variant of the algorithm, possible values: {\'state_equation_a_star\'}
    parameters
        :class:`dict` parameters of the algorithm,
        for key \'state_equation_a_star\':
            pm4py.util.constants.PARAMETER_CONSTANT_ACTIVITY_KEY -> Attribute in the log that contains the activity
            pm4py.algo.conformance.alignments.versions.state_equation_a_star.PARAM_MODEL_COST_FUNCTION ->
            mapping of each transition in the model to corresponding synchronous costs
            pm4py.algo.conformance.alignments.versions.state_equation_a_star.PARAM_SYNC_COST_FUNCTION ->
            mapping of each transition in the model to corresponding model cost
            pm4py.algo.conformance.alignments.versions.state_equation_a_star.PARAM_TRACE_COST_FUNCTION ->
            mapping of each index of the trace to a positive cost value
    Returns
    -----------
    alignment
        :class:`dict` with keys **alignment**, **cost**, **visited_states**, **queued_states** and
        **traversed_arcs**
        The alignment is a sequence of labels of the form (a,t), (a,>>), or (>>,t)
        representing synchronous/log/model-moves.
    """
    if parameters is None:
        parameters = dict()
    activity_key = parameters[
        PARAMETER_CONSTANT_ACTIVITY_KEY] if PARAMETER_CONSTANT_ACTIVITY_KEY in parameters else DEFAULT_NAME_KEY
    model_cost_function = parameters[
        PARAM_MODEL_COST_FUNCTION] if PARAM_MODEL_COST_FUNCTION in parameters else None
    sync_cost_function = parameters[
        PARAM_SYNC_COST_FUNCTION] if PARAM_SYNC_COST_FUNCTION in parameters else None
    if model_cost_function is None or sync_cost_function is None:
        # reset variables value
        model_cost_function = dict()
        sync_cost_function = dict()
        for t in petri_net.transitions:
            if t.label is not None:
                model_cost_function[t] = ali.utils.STD_MODEL_LOG_MOVE_COST
                sync_cost_function[t] = 0
            else:
                model_cost_function[t] = 1

    parameters[pm4py.util.constants.PARAMETER_CONSTANT_ACTIVITY_KEY] = activity_key
    parameters[
        PARAM_MODEL_COST_FUNCTION] = model_cost_function
    parameters[
        PARAM_SYNC_COST_FUNCTION] = sync_cost_function
    best_worst_cost = VERSIONS_COST[version](petri_net, initial_marking, final_marking, parameters=parameters)

    variants = variants_module.get_variants_from_log_trace_idx(log, parameters=parameters)
    one_tr_per_var = []
    for index_variant, variant in enumerate(variants):
        one_tr_per_var.append(log[variants[variant][0]])
    all_alignments = list(map(
        lambda trace: apply_trace(trace, petri_net, initial_marking, final_marking, parameters=copy(parameters),
                                  version=version), one_tr_per_var))

    al_idx = {}
    for index_variant, variant in enumerate(variants):
        for trace_idx in variants[variant]:
            al_idx[trace_idx] = all_alignments[index_variant]

    alignments = []
    for i in range(len(log)):
        alignments.append(al_idx[i])

    # assign fitness to traces

    for index, align in enumerate(alignments):
        unfitness_upper_part = align['cost']
        if unfitness_upper_part == 0:
            align['fitness'] = 1
        elif (len(log[index]) + best_worst_cost) > 0:
            align['fitness'] = 1 - align['cost'] / (
                        len(log[index]) * ali.utils.STD_MODEL_LOG_MOVE_COST + best_worst_cost)
        else:
            align['fitness'] = 0
    return alignments
コード例 #11
0
ファイル: factory.py プロジェクト: oli-on-tour/pm4py-source
def apply_multiprocessing(log,
                          net,
                          initial_marking,
                          final_marking,
                          parameters=None,
                          variant=TOKEN_REPLAY):
    if parameters is None:
        parameters = {}
    if pmutil.constants.PARAMETER_CONSTANT_ACTIVITY_KEY not in parameters:
        parameters[pmutil.constants.
                   PARAMETER_CONSTANT_ACTIVITY_KEY] = xes_util.DEFAULT_NAME_KEY
    if pmutil.constants.PARAMETER_CONSTANT_TIMESTAMP_KEY not in parameters:
        parameters[
            pmutil.constants.
            PARAMETER_CONSTANT_TIMESTAMP_KEY] = xes_util.DEFAULT_TIMESTAMP_KEY
    if pmutil.constants.PARAMETER_CONSTANT_CASEID_KEY not in parameters:
        parameters[
            pmutil.constants.
            PARAMETER_CONSTANT_CASEID_KEY] = log_util.CASE_ATTRIBUTE_GLUE

    petri_string = petri_exporter.export_petri_as_string(
        net, initial_marking, final_marking)

    variants_idxs = parameters[
        VARIANTS_IDX] if VARIANTS_IDX in parameters else None
    if variants_idxs is None:
        variants_idxs = variants_module.get_variants_from_log_trace_idx(
            log, parameters=parameters)
    variants_list = [[x, len(y)] for x, y in variants_idxs.items()]

    no_cores = mp.cpu_count()

    petri_net_string = petri_exporter.export_petri_as_string(
        net, initial_marking, final_marking)

    n = math.ceil(len(variants_list) / no_cores)

    variants_list_split = list(chunks(variants_list, n))

    # Define an output queue
    output = mp.Queue()

    processes = [
        mp.Process(target=VERSIONS_MULTIPROCESSING[variant](
            output, x, petri_net_string, parameters=parameters))
        for x in variants_list_split
    ]

    # Run processes
    for p in processes:
        p.start()

    results = []
    for p in processes:
        result = output.get()
        results.append(result)

    al_idx = {}
    for index, el in enumerate(variants_list_split):
        for index2, var_item in enumerate(el):
            variant = var_item[0]
            for trace_idx in variants_idxs[variant]:
                al_idx[trace_idx] = results[index][index2]

    replayed_cases = []
    for i in range(len(log)):
        replayed_cases.append(al_idx[i])

    return replayed_cases
コード例 #12
0
def get_decorations(log,
                    net,
                    initial_marking,
                    final_marking,
                    parameters=None,
                    measure="frequency",
                    ht_perf_method="last"):
    """
    Calculate decorations in order to annotate the Petri net

    Parameters
    -----------
    log
        Trace log
    net
        Petri net
    initial_marking
        Initial marking
    final_marking
        Final marking
    parameters
        Parameters associated to the algorithm
    measure
        Measure to represent on the process model (frequency/performance)
    ht_perf_method
        Method to use in order to annotate hidden transitions (performance value could be put on the last possible
        point (last) or in the first possible point (first)

    Returns
    ------------
    decorations
        Decorations to put on the process model
    """
    if parameters is None:
        parameters = {}

    aggregation_measure = None
    if "aggregationMeasure" in parameters:
        aggregation_measure = parameters["aggregationMeasure"]

    activity_key = parameters[
        PARAM_ACTIVITY_KEY] if PARAM_ACTIVITY_KEY in parameters else log_lib.util.xes.DEFAULT_NAME_KEY
    timestamp_key = parameters[
        PARAM_TIMESTAMP_KEY] if PARAM_TIMESTAMP_KEY in parameters else "time:timestamp"

    parameters_variants = {PARAM_ACTIVITY_KEY: activity_key}
    variants_idx = variants_module.get_variants_from_log_trace_idx(
        log, parameters=parameters_variants)
    variants = variants_module.convert_variants_trace_idx_to_trace_obj(
        log, variants_idx)

    parameters_tr = {PARAM_ACTIVITY_KEY: activity_key, "variants": variants}

    # do the replay
    aligned_traces = token_replay.apply(log,
                                        net,
                                        initial_marking,
                                        final_marking,
                                        parameters=parameters_tr)

    # apply petri_reduction technique in order to simplify the Petri net
    # net = reduction.apply(net, parameters={"aligned_traces": aligned_traces})

    element_statistics = performance_map.single_element_statistics(
        log,
        net,
        initial_marking,
        aligned_traces,
        variants_idx,
        activity_key=activity_key,
        timestamp_key=timestamp_key,
        ht_perf_method=ht_perf_method)

    aggregated_statistics = performance_map.aggregate_statistics(
        element_statistics,
        measure=measure,
        aggregation_measure=aggregation_measure)

    return aggregated_statistics
コード例 #13
0
def get_map_from_log_and_net(log,
                             net,
                             initial_marking,
                             final_marking,
                             force_distribution=None,
                             parameters=None):
    """
    Get transition stochastic distribution map given the log and the Petri net

    Parameters
    -----------
    log
        Event log
    net
        Petri net
    initial_marking
        Initial marking of the Petri net
    final_marking
        Final marking of the Petri net
    force_distribution
        If provided, distribution to force usage (e.g. EXPONENTIAL)
    parameters
        Parameters of the algorithm, including:
            PARAM_ACTIVITY_KEY -> activity name
            PARAM_TIMESTAMP_KEY -> timestamp key

    Returns
    -----------
    stochastic_map
        Map that to each transition associates a random variable
    """
    stochastic_map = {}

    if parameters is None:
        parameters = {}

    activity_key = parameters[
        PARAM_ACTIVITY_KEY] if PARAM_ACTIVITY_KEY in parameters else log_lib.util.xes.DEFAULT_NAME_KEY
    timestamp_key = parameters[
        PARAM_TIMESTAMP_KEY] if PARAM_TIMESTAMP_KEY in parameters else "time:timestamp"

    parameters_variants = {PARAM_ACTIVITY_KEY: activity_key}
    variants_idx = variants_module.get_variants_from_log_trace_idx(
        log, parameters=parameters_variants)
    variants = variants_module.convert_variants_trace_idx_to_trace_obj(
        log, variants_idx)

    parameters_tr = {PARAM_ACTIVITY_KEY: activity_key, "variants": variants}

    # do the replay
    aligned_traces = token_replay.apply(log,
                                        net,
                                        initial_marking,
                                        final_marking,
                                        parameters=parameters_tr)

    element_statistics = performance_map.single_element_statistics(
        log,
        net,
        initial_marking,
        aligned_traces,
        variants_idx,
        activity_key=activity_key,
        timestamp_key=timestamp_key,
        parameters={"business_hours": True})

    for el in element_statistics:
        if type(
                el
        ) is PetriNet.Transition and "performance" in element_statistics[el]:
            values = element_statistics[el]["performance"]

            rand = RandomVariable()
            rand.calculate_parameters(values,
                                      force_distribution=force_distribution)

            no_of_times_enabled = element_statistics[el]['no_of_times_enabled']
            no_of_times_activated = element_statistics[el][
                'no_of_times_activated']

            if no_of_times_enabled > 0:
                rand.set_weight(
                    float(no_of_times_activated) / float(no_of_times_enabled))
            else:
                rand.set_weight(0.0)

            stochastic_map[el] = rand

    return stochastic_map
コード例 #14
0
def apply_log_multiprocessing(log,
                              petri_net,
                              initial_marking,
                              final_marking,
                              parameters=None,
                              version=VERSION_STATE_EQUATION_A_STAR):
    if parameters is None:
        parameters = dict()

    if not (check_soundness.check_wfnet(petri_net)
            and check_soundness.check_relaxed_soundness_net_in_fin_marking(
                petri_net, initial_marking, final_marking)):
        raise Exception(
            "trying to apply alignments on a Petri net that is not a relaxed sound workflow net!!"
        )

    activity_key = parameters[
        PARAMETER_CONSTANT_ACTIVITY_KEY] if PARAMETER_CONSTANT_ACTIVITY_KEY in parameters else DEFAULT_NAME_KEY
    model_cost_function = parameters[
        PARAM_MODEL_COST_FUNCTION] if PARAM_MODEL_COST_FUNCTION in parameters else None
    sync_cost_function = parameters[
        PARAM_SYNC_COST_FUNCTION] if PARAM_SYNC_COST_FUNCTION in parameters else None
    if model_cost_function is None or sync_cost_function is None:
        # reset variables value
        model_cost_function = dict()
        sync_cost_function = dict()
        for t in petri_net.transitions:
            if t.label is not None:
                model_cost_function[t] = align_utils.STD_MODEL_LOG_MOVE_COST
                sync_cost_function[t] = 0
            else:
                model_cost_function[t] = 1

    parameters[
        pm4py.util.constants.PARAMETER_CONSTANT_ACTIVITY_KEY] = activity_key
    parameters[PARAM_MODEL_COST_FUNCTION] = model_cost_function
    parameters[PARAM_SYNC_COST_FUNCTION] = sync_cost_function
    parameters_best_worst = copy(parameters)
    if PARAM_MAX_ALIGN_TIME_TRACE in parameters_best_worst:
        del parameters_best_worst[PARAM_MAX_ALIGN_TIME_TRACE]

    best_worst_cost = VERSIONS_COST[version](petri_net,
                                             initial_marking,
                                             final_marking,
                                             parameters=parameters_best_worst)

    variants_idxs = parameters[
        VARIANTS_IDX] if VARIANTS_IDX in parameters else None
    if variants_idxs is None:
        variants_idxs = variants_module.get_variants_from_log_trace_idx(
            log, parameters=parameters)
    variants_list = [[x, len(y)] for x, y in variants_idxs.items()]

    no_cores = mp.cpu_count()

    petri_net_string = petri_exporter.export_petri_as_string(
        petri_net, initial_marking, final_marking)

    n = math.ceil(len(variants_list) / no_cores)

    variants_list_split = list(chunks(variants_list, n))

    # Define an output queue
    output = mp.Queue()

    processes = [
        mp.Process(target=VERSIONS_VARIANTS_LIST_MPROCESSING[version](
            output, x, petri_net_string, parameters=parameters))
        for x in variants_list_split
    ]

    # Run processes
    for p in processes:
        p.start()

    results = []
    for p in processes:
        result = output.get()
        results.append(result)

    al_idx = {}
    for index, el in enumerate(variants_list_split):
        for index2, var_item in enumerate(el):
            variant = var_item[0]
            for trace_idx in variants_idxs[variant]:
                al_idx[trace_idx] = results[index][variant]

    alignments = []
    for i in range(len(log)):
        alignments.append(al_idx[i])

    # assign fitness to traces
    for index, align in enumerate(alignments):
        if align is not None:
            unfitness_upper_part = align[
                'cost'] // align_utils.STD_MODEL_LOG_MOVE_COST
            if unfitness_upper_part == 0:
                align['fitness'] = 1
            elif (len(log[index]) + best_worst_cost) > 0:
                align['fitness'] = 1 - (
                    (align['cost'] // align_utils.STD_MODEL_LOG_MOVE_COST) /
                    (len(log[index]) + best_worst_cost))
            else:
                align['fitness'] = 0

    return alignments
コード例 #15
0
def apply_log(log,
              petri_net,
              initial_marking,
              final_marking,
              parameters=None,
              version=VERSION_STATE_EQUATION_A_STAR):
    """
    apply alignments to a log
    Parameters
    -----------
    log
        object of the form :class:`pm4py.log.log.EventLog` event log
    petri_net
        :class:`pm4py.objects.petri.petrinet.PetriNet` the model to use for the alignment
    initial_marking
        :class:`pm4py.objects.petri.petrinet.Marking` initial marking of the net
    final_marking
        :class:`pm4py.objects.petri.petrinet.Marking` final marking of the net
    version
        :class:`str` selected variant of the algorithm, possible values: {\'state_equation_a_star\'}
    parameters
        :class:`dict` parameters of the algorithm,
        for key \'state_equation_a_star\':
            pm4py.util.constants.PARAMETER_CONSTANT_ACTIVITY_KEY -> Attribute in the log that contains the activity
            pm4py.algo.conformance.alignments.versions.state_equation_a_star.PARAM_MODEL_COST_FUNCTION ->
            mapping of each transition in the model to corresponding synchronous costs
            pm4py.algo.conformance.alignments.versions.state_equation_a_star.PARAM_SYNC_COST_FUNCTION ->
            mapping of each transition in the model to corresponding model cost
            pm4py.algo.conformance.alignments.versions.state_equation_a_star.PARAM_TRACE_COST_FUNCTION ->
            mapping of each index of the trace to a positive cost value
    Returns
    -----------
    alignment
        :class:`list` of :class:`dict` with keys **alignment**, **cost**, **visited_states**, **queued_states** and
        **traversed_arcs**
        The alignment is a sequence of labels of the form (a,t), (a,>>), or (>>,t)
        representing synchronous/log/model-moves.
    """
    if parameters is None:
        parameters = dict()

    if not (check_soundness.check_wfnet(petri_net)
            and check_soundness.check_relaxed_soundness_net_in_fin_marking(
                petri_net, initial_marking, final_marking)):
        raise Exception(
            "trying to apply alignments on a Petri net that is not a relaxed sound workflow net!!"
        )

    start_time = time.time()
    activity_key = parameters[
        PARAMETER_CONSTANT_ACTIVITY_KEY] if PARAMETER_CONSTANT_ACTIVITY_KEY in parameters else DEFAULT_NAME_KEY
    model_cost_function = parameters[
        PARAM_MODEL_COST_FUNCTION] if PARAM_MODEL_COST_FUNCTION in parameters else None
    sync_cost_function = parameters[
        PARAM_SYNC_COST_FUNCTION] if PARAM_SYNC_COST_FUNCTION in parameters else None
    max_align_time = parameters[
        PARAM_MAX_ALIGN_TIME] if PARAM_MAX_ALIGN_TIME in parameters else DEFAULT_MAX_ALIGN_TIME
    max_align_time_case = parameters[
        PARAM_MAX_ALIGN_TIME_TRACE] if PARAM_MAX_ALIGN_TIME_TRACE in parameters else DEFAULT_MAX_ALIGN_TIME_TRACE

    if model_cost_function is None or sync_cost_function is None:
        # reset variables value
        model_cost_function = dict()
        sync_cost_function = dict()
        for t in petri_net.transitions:
            if t.label is not None:
                model_cost_function[t] = align_utils.STD_MODEL_LOG_MOVE_COST
                sync_cost_function[t] = 0
            else:
                model_cost_function[t] = 1

    parameters[
        pm4py.util.constants.PARAMETER_CONSTANT_ACTIVITY_KEY] = activity_key
    parameters[PARAM_MODEL_COST_FUNCTION] = model_cost_function
    parameters[PARAM_SYNC_COST_FUNCTION] = sync_cost_function
    parameters_best_worst = copy(parameters)
    if PARAM_MAX_ALIGN_TIME_TRACE in parameters_best_worst:
        del parameters_best_worst[PARAM_MAX_ALIGN_TIME_TRACE]

    best_worst_cost = VERSIONS_COST[version](petri_net,
                                             initial_marking,
                                             final_marking,
                                             parameters=parameters_best_worst)

    variants_idxs = parameters[
        VARIANTS_IDX] if VARIANTS_IDX in parameters else None
    if variants_idxs is None:
        variants_idxs = variants_module.get_variants_from_log_trace_idx(
            log, parameters=parameters)

    one_tr_per_var = []
    variants_list = []
    for index_variant, variant in enumerate(variants_idxs):
        variants_list.append(variant)

    for variant in variants_list:
        one_tr_per_var.append(log[variants_idxs[variant][0]])

    all_alignments = []
    for trace in one_tr_per_var:
        this_max_align_time = min(max_align_time_case,
                                  (max_align_time -
                                   (time.time() - start_time)) * 0.5)
        parameters[PARAM_MAX_ALIGN_TIME_TRACE] = this_max_align_time
        all_alignments.append(
            apply_trace(trace,
                        petri_net,
                        initial_marking,
                        final_marking,
                        parameters=copy(parameters),
                        version=version))

    al_idx = {}
    for index_variant, variant in enumerate(variants_idxs):
        for trace_idx in variants_idxs[variant]:
            al_idx[trace_idx] = all_alignments[index_variant]

    alignments = []
    for i in range(len(log)):
        alignments.append(al_idx[i])

    # assign fitness to traces
    for index, align in enumerate(alignments):
        if align is not None:
            unfitness_upper_part = align[
                'cost'] // align_utils.STD_MODEL_LOG_MOVE_COST
            if unfitness_upper_part == 0:
                align['fitness'] = 1
            elif (len(log[index]) + best_worst_cost) > 0:
                align['fitness'] = 1 - (
                    (align['cost'] // align_utils.STD_MODEL_LOG_MOVE_COST) /
                    (len(log[index]) + best_worst_cost))
            else:
                align['fitness'] = 0
    return alignments