Esempio n. 1
0
    def test_importingExportingPetri(self):
        # to avoid static method warnings in tests,
        # that by construction of the unittest package have to be expressed in such way
        self.dummy_variable = "dummy_value"
        imported_petri1, marking1, fmarking1 = petri_importer.import_net(
            os.path.join(INPUT_DATA_DIR, "running-example.pnml"))
        soundness = check_soundness.check_petri_wfnet_and_soundness(
            imported_petri1)
        del soundness
        petri_exporter.export_net(
            imported_petri1, marking1,
            os.path.join(OUTPUT_DATA_DIR, "running-example.pnml"))
        imported_petri2, marking2, fmarking2 = petri_importer.import_net(
            os.path.join(OUTPUT_DATA_DIR, "running-example.pnml"))
        soundness = check_soundness.check_petri_wfnet_and_soundness(
            imported_petri2)
        del soundness

        self.assertEqual(sorted([x.name for x in imported_petri1.places]),
                         sorted([x.name for x in imported_petri2.places]))
        self.assertEqual(sorted([x.name for x in imported_petri1.transitions]),
                         sorted([x.name for x in imported_petri2.transitions]))
        self.assertEqual(
            sorted(
                [x.source.name + x.target.name for x in imported_petri1.arcs]),
            sorted(
                [x.source.name + x.target.name for x in imported_petri2.arcs]))
        self.assertEqual([x.name for x in marking1],
                         [x.name for x in marking2])
        os.remove(os.path.join(OUTPUT_DATA_DIR, "running-example.pnml"))
Esempio n. 2
0
 def test_importingPetriLogAlignment(self):
     # to avoid static method warnings in tests,
     # that by construction of the unittest package have to be expressed in such way
     self.dummy_variable = "dummy_value"
     imported_petri1, marking1, fmarking1 = petri_importer.import_net(
         os.path.join(INPUT_DATA_DIR, "running-example.pnml"))
     soundness = check_soundness.check_petri_wfnet_and_soundness(
         imported_petri1)
     del soundness
     log = xes_importer.import_log(
         os.path.join(INPUT_DATA_DIR, "running-example.xes"))
     final_marking = petri.petrinet.Marking()
     for p in imported_petri1.places:
         if not p.out_arcs:
             final_marking[p] = 1
     for trace in log:
         cf_result = state_equation_a_star.apply(trace, imported_petri1,
                                                 marking1,
                                                 final_marking)['alignment']
         is_fit = True
         for couple in cf_result:
             if not (couple[0] == couple[1]
                     or couple[0] == ">>" and couple[1] is None):
                 is_fit = False
         if not is_fit:
             raise Exception("should be fit")
Esempio n. 3
0
def execute_script():
    # loads the log
    log = xes_importer.apply(
        os.path.join("..", "tests", "input_data", "receipt.xes"))
    # apply the simple miner
    net, im, fm = simple_miner.apply(log, classic_output=True)
    # checks if the Petri net is a sound workflow net
    is_sound_wfnet = check_petri_wfnet_and_soundness(net)
    print("is_sound_wfnet = ", is_sound_wfnet)
Esempio n. 4
0
 def test_importingPetriLogTokenReplay(self):
     # to avoid static method warnings in tests,
     # that by construction of the unittest package have to be expressed in such way
     self.dummy_variable = "dummy_value"
     imported_petri1, marking1, fmarking1 = petri_importer.import_net(
         os.path.join(INPUT_DATA_DIR, "running-example.pnml"))
     soundness = check_soundness.check_petri_wfnet_and_soundness(imported_petri1)
     del soundness
     log = xes_importer.import_log(os.path.join(INPUT_DATA_DIR, "running-example.xes"))
     aligned_traces = token_replay.apply_log(log, imported_petri1, marking1, fmarking1)
     del aligned_traces
Esempio n. 5
0
    def obtainPetriNetThroughImdf(self, log_name):
        # to avoid static method warnings in tests,
        # that by construction of the unittest package have to be expressed in such way
        self.dummy_variable = "dummy_value"
        if ".xes" in log_name:
            log = xes_importer.import_log(log_name)
        else:
            event_log = csv_importer.import_event_stream(log_name)
            log = log_conv_fact.apply(event_log)
        net, marking, final_marking = inductive_miner.apply(log)
        soundness = check_soundness.check_petri_wfnet_and_soundness(net)
        del soundness

        return log, net, marking, final_marking
Esempio n. 6
0
    def obtainPetriNetThroughAlphaMiner(self, log_name):
        # to avoid static method warnings in tests,
        # that by construction of the unittest package have to be expressed in such way
        self.dummy_variable = "dummy_value"

        if ".xes" in log_name:
            trace_log = xes_importer.import_log(log_name)
        else:
            event_log = csv_importer.import_log(log_name)
            trace_log = log_transform.transform_event_log_to_trace_log(
                event_log)
        net, marking, fmarking = alpha_factory.apply(trace_log)
        soundness = check_soundness.check_petri_wfnet_and_soundness(net)
        del soundness

        return trace_log, net, marking, fmarking
Esempio n. 7
0
    def obtainPetriNetThroughAlphaMiner(self, log_name):
        # to avoid static method warnings in tests,
        # that by construction of the unittest package have to be expressed in such way
        self.dummy_variable = "dummy_value"

        if ".xes" in log_name:
            log = xes_importer.apply(log_name)
        else:
            df = pd.read_csv(log_name)
            df = dataframe_utils.convert_timestamp_columns_in_df(df)
            log = log_conversion.apply(df)
        net, marking, fmarking = alpha_alg.apply(log)
        soundness = check_soundness.check_petri_wfnet_and_soundness(net)
        del soundness

        return log, net, marking, fmarking
Esempio n. 8
0
    def obtainPetriNetThroughImdf(self,
                                  log_name,
                                  variant=inductive_miner.DEFAULT_VARIANT):
        # to avoid static method warnings in tests,
        # that by construction of the unittest package have to be expressed in such way
        self.dummy_variable = "dummy_value"
        if ".xes" in log_name:
            log = xes_importer.apply(log_name)
        else:
            df = pd.read_csv(log_name)
            df = dataframe_utils.convert_timestamp_columns_in_df(df)
            log = log_conversion.apply(df)
        # apply dummily the test to all the available variants
        net, marking, final_marking = inductive_miner.apply(
            log, variant=inductive_miner.DFG_BASED)
        net, marking, final_marking = inductive_miner.apply(log,
                                                            variant=variant)
        soundness = check_soundness.check_petri_wfnet_and_soundness(net)
        del soundness

        return log, net, marking, final_marking
Esempio n. 9
0
    def obtainPetriNetThroughImdf(self,
                                  log_name,
                                  variant=inductive_miner.DEFAULT_VARIANT):
        # to avoid static method warnings in tests,
        # that by construction of the unittest package have to be expressed in such way
        self.dummy_variable = "dummy_value"
        if ".xes" in log_name:
            log = xes_importer.import_log(log_name)
        else:
            event_log = csv_importer.import_event_stream(log_name)
            log = log_conv_fact.apply(event_log)
        # apply dummily the test to all the available variants
        net, marking, final_marking = inductive_miner.apply(
            log, variant=inductive_miner.DFG_BASED_OLD_VERSION)
        net, marking, final_marking = inductive_miner.apply(
            log, variant=inductive_miner.DFG_BASED)
        net, marking, final_marking = inductive_miner.apply(log,
                                                            variant=variant)
        soundness = check_soundness.check_petri_wfnet_and_soundness(net)
        del soundness

        return log, net, marking, final_marking
Esempio n. 10
0
                pmutil.constants.PARAMETER_CONSTANT_ATTRIBUTE_KEY: activity_key
            }
            t1 = time.time()
            alpha_model, alpha_initial_marking, alpha_final_marking = alpha.apply(
                log, parameters=parameters_discovery)
            pnml_exporter.export_net(alpha_model,
                                     alpha_initial_marking,
                                     os.path.join(
                                         pnmlFolder,
                                         logNamePrefix + "_alpha.pnml"),
                                     final_marking=alpha_final_marking)
            t2 = time.time()
            print("time interlapsed for calculating Alpha Model", (t2 - t1))
            print(
                "alpha is_sound_wfnet",
                check_soundness.check_petri_wfnet_and_soundness(alpha_model,
                                                                debug=True))

            t1 = time.time()
            heu_model, heu_initial_marking, heu_final_marking = heuristics_miner.apply(
                log, parameters=parameters_discovery)
            pnml_exporter.export_net(heu_model,
                                     heu_initial_marking,
                                     os.path.join(
                                         pnmlFolder,
                                         logNamePrefix + "_alpha.pnml"),
                                     final_marking=heu_final_marking)
            t2 = time.time()
            print("time interlapsed for calculating Heuristics Model",
                  (t2 - t1))
            print(
                "heuristics is_sound_wfnet",
Esempio n. 11
0
def get_s_components_from_petri(net,
                                im,
                                fm,
                                rec_depth=0,
                                curr_s_comp=None,
                                visited_places=None,
                                list_s_components=None):
    """
    Gets the S-components from a Petri net

    Parameters
    -------------
    net
        Petri net
    im
        Initial marking
    fm
        Final marking
    curr_s_comp
        Current S component
    visited_places
        Visited places
    list_s_components
        List of S-components

    Returns
    --------------
    s_components
        List of S-components
    """
    MAX_REC_DEPTH = 6
    if list_s_components is None:
        list_s_components = []
    if len(im) > 1 or len(fm) > 1:
        return list_s_components
    if not check_petri_wfnet_and_soundness(net):
        return list_s_components
    source = list(im.keys())[0]
    if curr_s_comp is None:
        curr_s_comp = [source]
    if visited_places is None:
        visited_places = []
    something_changed = True
    while something_changed and rec_depth < MAX_REC_DEPTH:
        something_changed = False
        places_to_visit = sorted(list(set(curr_s_comp[len(visited_places):])),
                                 key=lambda x: len(x.out_arcs),
                                 reverse=True)
        for place_to_visit in places_to_visit:
            visited_places.append(place_to_visit)
            target_trans = sorted(list(
                set([arc.target for arc in place_to_visit.out_arcs])),
                                  key=lambda x: len(x.out_arcs))
            for trans in target_trans:
                visited_places_names = [x.name for x in visited_places]
                target_trans_target = list(
                    set([
                        arc.target for arc in trans.out_arcs
                        if arc.target.name not in visited_places_names
                    ]))
                if target_trans_target:
                    something_changed = True
                    if len(target_trans_target) == 1:
                        new_place = target_trans_target[0]
                        curr_s_comp.append(new_place)
                    else:
                        for new_place in target_trans_target:
                            [new_curr_s_comp, new_visited_places
                             ] = deepcopy([curr_s_comp, visited_places])
                            new_curr_s_comp.append(new_place)
                            list_s_components = get_s_components_from_petri(
                                net,
                                im,
                                fm,
                                rec_depth=rec_depth + 1,
                                curr_s_comp=new_curr_s_comp,
                                visited_places=new_visited_places,
                                list_s_components=list_s_components)

    if not set([place.name for place in curr_s_comp]) in list_s_components:
        list_s_components.append(set([place.name for place in curr_s_comp]))

    return list_s_components
Esempio n. 12
0
def apply(log, parameters=None):
    """
    Returns a log from which a sound workflow net could be extracted taking into account
    a discovery algorithm returning models only with visible transitions

    Parameters
    ------------
    log
        Trace log
    parameters
        Possible parameters of the algorithm, including:
            discovery_algorithm -> Discovery algorithm to consider, possible choices: alphaclassic
            max_no_variants -> Maximum number of variants to consider to return a Petri net

    Returns
    ------------
    filtered_log
        Filtered trace log
    """
    if parameters is None:
        parameters = {}
    discovery_algorithm = parameters[
        "discovery_algorithm"] if "discovery_algorithm" in parameters else "alphaclassic"
    max_no_variants = parameters[
        "max_no_variants"] if "max_no_variants" in parameters else 20
    all_variants_dictio = variants_filter.get_variants(log,
                                                       parameters=parameters)
    all_variants_list = []
    for var in all_variants_dictio:
        all_variants_list.append([var, len(all_variants_dictio[var])])
    all_variants_list = sorted(all_variants_list,
                               key=lambda x: (x[1], x[0]),
                               reverse=True)
    considered_variants = []
    considered_traces = []

    i = 0
    while i < min(len(all_variants_list), max_no_variants):
        variant = all_variants_list[i][0]

        considered_variants.append(variant)
        considered_traces.append(all_variants_dictio[variant][0])
        filtered_log = TraceLog(considered_traces)
        net = None
        initial_marking = None
        final_marking = None
        if discovery_algorithm == "alphaclassic" or discovery_algorithm == "alpha":
            net, initial_marking, final_marking = alpha_miner.apply(
                filtered_log, parameters=parameters)
        is_sound = check_soundness.check_petri_wfnet_and_soundness(net)
        if not is_sound:
            del considered_variants[-1]
            del considered_traces[-1]
        else:
            try:
                alignments = alignment_factory.apply(filtered_log, net,
                                                     initial_marking,
                                                     final_marking)
                del alignments
                fitness = replay_fitness_factory.apply(filtered_log,
                                                       net,
                                                       initial_marking,
                                                       final_marking,
                                                       parameters=parameters)
                if fitness["log_fitness"] < 0.99999:
                    del considered_variants[-1]
                    del considered_traces[-1]
            except TypeError:
                del considered_variants[-1]
                del considered_traces[-1]
        i = i + 1

    sound_log = TraceLog()
    if considered_variants:
        sound_log = variants_filter.apply(log,
                                          considered_variants,
                                          parameters=parameters)

    return sound_log
Esempio n. 13
0
     }
 ]
 print("log")
 for j in log_param_list:
     print(j)
     auto_log = utils.discover_annotated_automaton(log, j)
     net_log, im_log, fm_log = sb.petri_net_synthesis(auto_log)
     print("# of trans: ", len(auto_log.transitions))
     print("# of states: ", len(auto_log.states))
     ev = evaluation_factory.apply(log, net_log, im_log, fm_log)
     ev['fitness'] = ev['fitness']['averageFitness']
     print("fitness: ", round(ev['fitness']['averageFitness'], 2))
     print("precision: ", round(ev['precision'], 2))
     print("simplicity: ", round(ev['simplicity'], 2))
     print("generalization: ", round(ev['generalization'], 2))
     soundness_log = check_soundness.check_petri_wfnet_and_soundness(
         net_log)
     if soundness_log:
         fitness = replay_factory.apply(log, net_log, im_log, fm_log)
         ev['align_fitness'] = fitness['averageFitness']
     else:
         ev['align_fitness'] = -1
     wr.writerow([
         j,
         len(auto_log.transitions),
         len(auto_log.states), soundness_log,
         round(ev['fitness'], 2),
         round(ev['align_fitness'], 2),
         round(ev['precision'], 2),
         round(ev['simplicity'], 2),
         round(ev['generalization'], 2)
     ], round(ev['fscore'], 2), round(ev['metricsAverageWeight'], 2))
def apply(df, parameters=None):
    """
    Returns a Pandas dataframe from which a sound workflow net could be extracted taking into account
    a discovery algorithm returning models only with visible transitions

    Parameters
    ------------
    df
        Pandas dataframe
    parameters
        Possible parameters of the algorithm, including:
            max_no_variants -> Maximum number of variants to consider to return a Petri net

    Returns
    ------------
    filtered_df
        Filtered dataframe
    """
    if parameters is None:
        parameters = {}

    if PARAMETER_CONSTANT_CASEID_KEY not in parameters:
        parameters[PARAMETER_CONSTANT_CASEID_KEY] = CASE_CONCEPT_NAME
    if PARAMETER_CONSTANT_ACTIVITY_KEY not in parameters:
        parameters[PARAMETER_CONSTANT_ACTIVITY_KEY] = DEFAULT_NAME_KEY
    if PARAMETER_CONSTANT_TIMESTAMP_KEY not in parameters:
        parameters[PARAMETER_CONSTANT_TIMESTAMP_KEY] = DEFAULT_TIMESTAMP_KEY
    if PARAMETER_CONSTANT_ATTRIBUTE_KEY not in parameters:
        parameters[PARAMETER_CONSTANT_ATTRIBUTE_KEY] = parameters[
            PARAMETER_CONSTANT_ACTIVITY_KEY]

    caseid_glue = parameters[PARAMETER_CONSTANT_CASEID_KEY]
    activity_key = parameters[PARAMETER_CONSTANT_ACTIVITY_KEY]
    timest_key = parameters[PARAMETER_CONSTANT_TIMESTAMP_KEY]

    max_no_variants = parameters[
        "max_no_variants"] if "max_no_variants" in parameters else 20

    variants_df = case_statistics.get_variants_df(df, parameters=parameters)
    parameters["variants_df"] = variants_df

    variant_stats = case_statistics.get_variant_statistics(
        df, parameters=parameters)

    all_variants_list = []
    for var in variant_stats:
        all_variants_list.append([var["variant"], var[caseid_glue]])

    all_variants_list = sorted(all_variants_list,
                               key=lambda x: (x[1], x[0]),
                               reverse=True)

    considered_variants = []
    considered_traces = []

    i = 0
    while i < min(len(all_variants_list), max_no_variants):
        variant = all_variants_list[i][0]

        considered_variants.append(variant)

        filtered_df = variants_filter.apply(df,
                                            considered_variants,
                                            parameters=parameters)

        dfg_frequency = dfg_util.get_dfg_graph(filtered_df,
                                               measure="frequency",
                                               perf_aggregation_key="median",
                                               case_id_glue=caseid_glue,
                                               activity_key=activity_key,
                                               timestamp_key=timest_key)

        net, initial_marking, final_marking = alpha_miner.apply_dfg(
            dfg_frequency, parameters=parameters)

        is_sound = check_soundness.check_petri_wfnet_and_soundness(net)
        if not is_sound:
            del considered_variants[-1]
        else:
            traces_of_this_variant = variants_filter.apply(
                df, [variant], parameters=parameters).groupby(caseid_glue)
            traces_of_this_variant_keys = list(
                traces_of_this_variant.groups.keys())
            trace_of_this_variant = traces_of_this_variant.get_group(
                traces_of_this_variant_keys[0])

            this_trace = transform.transform_event_log_to_trace_log(
                pandas_df_imp.convert_dataframe_to_event_log(
                    trace_of_this_variant),
                case_glue=caseid_glue)[0]
            if not activity_key == DEFAULT_NAME_KEY:
                for j in range(len(this_trace)):
                    this_trace[j][DEFAULT_NAME_KEY] = this_trace[j][
                        activity_key]
            considered_traces.append(this_trace)
            filtered_log = TraceLog(considered_traces)

            try:
                alignments = alignment_factory.apply(filtered_log, net,
                                                     initial_marking,
                                                     final_marking)
                del alignments
                fitness = replay_fitness_factory.apply(filtered_log,
                                                       net,
                                                       initial_marking,
                                                       final_marking,
                                                       parameters=parameters)
                if fitness["log_fitness"] < 0.99999:
                    del considered_variants[-1]
                    del considered_traces[-1]
            except TypeError:
                del considered_variants[-1]
                del considered_traces[-1]

        i = i + 1

    return variants_filter.apply(df,
                                 considered_variants,
                                 parameters=parameters)