Example #1
0
def apply_actlist(trace, model, parameters=None):
    """
    Apply log-skeleton based conformance checking given the list of activities of a trace
    and a log-skeleton model

    Parameters
    --------------
    trace
        List of activities of a trace
    model
        Log-skeleton model
    parameters
        Parameters of the algorithm, including:
        - the activity key (pm4py:param:activity_key)
        - the list of considered constraints (considered_constraints) among: equivalence, always_after, always_before, never_together, directly_follows, activ_freq

    Returns
    --------------
    aligned_trace
        Containing:
        - is_fit => boolean that tells if the trace is perfectly fit according to the model
        - dev_fitness => deviation based fitness (between 0 and 1; the more the trace is near to 1 the more fit is)
        - deviations => list of deviations in the model
    """
    if parameters is None:
        parameters = {}

    consid_constraints = exec_utils.get_param_value(
        Parameters.CONSIDERED_CONSTRAINTS, parameters,
        Parameters.DEFAULT_CONSIDERED_CONSTRAINTS.value)
    trace_info = trace_skel.get_trace_info(trace)

    ret = {}
    ret[Outputs.DEVIATIONS.value] = []
    dev_total = 0
    conf_total = 0

    default_considered_constraints = Parameters.DEFAULT_CONSIDERED_CONSTRAINTS.value

    i = 0
    while i < len(default_considered_constraints):
        if default_considered_constraints[i] in consid_constraints:
            if default_considered_constraints[
                    i] == DiscoveryOutputs.ACTIV_FREQ.value:
                this_constraints = {
                    x: y
                    for x, y in model[
                        default_considered_constraints[i]].items()
                }
                conf_total += len(
                    list(act for act in trace_info[i]
                         if act in this_constraints)) + len(
                             list(act for act in trace_info[i]
                                  if act not in this_constraints)) + len(
                                      list(act for act in this_constraints
                                           if min(this_constraints[act]) > 0
                                           and not act in trace))
                for act in trace_info[i]:
                    if act in this_constraints:
                        if trace_info[i][act] not in this_constraints[act]:
                            dev_total += 1
                            ret[Outputs.DEVIATIONS.value].append(
                                (default_considered_constraints[i],
                                 (act, trace_info[i][act])))
                    else:
                        dev_total += 1
                        ret[Outputs.DEVIATIONS.value].append(
                            (default_considered_constraints[i], (act, 0)))
                for act in this_constraints:
                    if min(this_constraints[act]) > 0 and not act in trace:
                        dev_total += 1
                        ret[Outputs.DEVIATIONS.value].append(
                            (default_considered_constraints[i],
                             (act, this_constraints[act])))
            elif default_considered_constraints[
                    i] == DiscoveryOutputs.NEVER_TOGETHER.value:
                this_constraints = {
                    x
                    for x in model[default_considered_constraints[i]]
                    if x[0] in trace
                }
                conf_total += len(this_constraints)
                setinte = this_constraints.intersection(trace_info[i])
                dev_total += len(setinte)
                if len(setinte) > 0:
                    ret[Outputs.DEVIATIONS.value].append(
                        (default_considered_constraints[i], tuple(setinte)))
            else:
                this_constraints = {
                    x
                    for x in model[default_considered_constraints[i]]
                    if x[0] in trace
                }
                conf_total += len(this_constraints)
                setdiff = this_constraints.difference(trace_info[i])
                dev_total += len(setdiff)
                if len(setdiff) > 0:
                    ret[Outputs.DEVIATIONS.value].append(
                        (default_considered_constraints[i], tuple(setdiff)))
        i = i + 1
    ret[Outputs.NO_DEV_TOTAL.value] = dev_total
    ret[Outputs.NO_CONSTR_TOTAL.value] = conf_total
    ret[Outputs.DEV_FITNESS.value] = 1.0 - float(dev_total) / float(
        conf_total) if conf_total > 0 else 1.0
    ret[Outputs.DEVIATIONS.value] = sorted(ret[Outputs.DEVIATIONS.value],
                                           key=lambda x: (x[0], x[1]))
    ret[Outputs.IS_FIT.value] = len(ret[Outputs.DEVIATIONS.value]) == 0
    return ret
def apply_actlist(trace, model, parameters=None):
    """
    Apply log-skeleton based conformance checking given the list of activities of a trace
    and a log-skeleton model

    Parameters
    --------------
    trace
        List of activities of a trace
    model
        Log-skeleton model
    parameters
        Parameters of the algorithm, including:
        - the activity key (pm4py:param:activity_key)
        - the list of considered constraints (considered_constraints) among: equivalence, always_after, always_before, never_together, directly_follows, activ_freq

    Returns
    --------------
    aligned_trace
        Containing:
        - is_fit => boolean that tells if the trace is perfectly fit according to the model
        - dev_fitness => deviation based fitness (between 0 and 1; the more the trace is near to 1 the more fit is)
        - deviations => list of deviations in the model
    """
    if parameters is None:
        parameters = {}

    consid_constraints = parameters[
        CONSIDERED_CONSTRAINTS] if CONSIDERED_CONSTRAINTS in parameters else DEFAULT_CONSIDERED_CONSTRAINTS
    trace_info = trace_skel.get_trace_info(trace)

    ret = {}
    ret["deviations"] = []
    dev_total = 0
    conf_total = 0

    i = 0
    while i < len(DEFAULT_CONSIDERED_CONSTRAINTS):
        if DEFAULT_CONSIDERED_CONSTRAINTS[i] in consid_constraints:
            if DEFAULT_CONSIDERED_CONSTRAINTS[i] == "activ_freq":
                this_constraints = {
                    x: y
                    for x, y in model[
                        DEFAULT_CONSIDERED_CONSTRAINTS[i]].items()
                }
                conf_total += len(
                    list(act for act in trace_info[i]
                         if act in this_constraints)) + len(
                             list(act for act in trace_info[i]
                                  if act not in this_constraints)) + len(
                                      list(act for act in this_constraints
                                           if min(this_constraints[act]) > 0
                                           and not act in trace))
                for act in trace_info[i]:
                    if act in this_constraints:
                        if trace_info[i][act] not in this_constraints[act]:
                            dev_total += 1
                            ret["deviations"].append(
                                (DEFAULT_CONSIDERED_CONSTRAINTS[i],
                                 (act, trace_info[i][act])))
                    else:
                        dev_total += 1
                        ret["deviations"].append(
                            (DEFAULT_CONSIDERED_CONSTRAINTS[i], (act, 0)))
                for act in this_constraints:
                    if min(this_constraints[act]) > 0 and not act in trace:
                        dev_total += 1
                        ret["deviations"].append(
                            (DEFAULT_CONSIDERED_CONSTRAINTS[i],
                             (act, this_constraints[act])))
            elif DEFAULT_CONSIDERED_CONSTRAINTS[i] == "never_together":
                this_constraints = {
                    x
                    for x in model[DEFAULT_CONSIDERED_CONSTRAINTS[i]]
                    if x[0] in trace
                }
                conf_total += len(this_constraints)
                setinte = this_constraints.intersection(trace_info[i])
                dev_total += len(setinte)
                if len(setinte) > 0:
                    ret["deviations"].append(
                        (DEFAULT_CONSIDERED_CONSTRAINTS[i], tuple(setinte)))
            else:
                this_constraints = {
                    x
                    for x in model[DEFAULT_CONSIDERED_CONSTRAINTS[i]]
                    if x[0] in trace
                }
                conf_total += len(this_constraints)
                setdiff = this_constraints.difference(trace_info[i])
                dev_total += len(setdiff)
                if len(setdiff) > 0:
                    ret["deviations"].append(
                        (DEFAULT_CONSIDERED_CONSTRAINTS[i], tuple(setdiff)))
        i = i + 1
    ret["no_dev_total"] = dev_total
    ret["no_constr_total"] = conf_total
    ret["dev_fitness"] = 1.0 - float(dev_total) / float(
        conf_total) if conf_total > 0 else 1.0
    ret["deviations"] = sorted(ret["deviations"], key=lambda x: (x[0], x[1]))
    ret["is_fit"] = len(ret["deviations"]) == 0
    return ret