Exemple #1
0
    def __sup_to_minimize_with_distance_function(self, artefact,
                                                 variablesFunction):
        list_of_formula = []
        if artefact == ANTI_ALIGNMENT:
            for d in range(0, self.__max_d + 1):
                list_of_d = []
                for j in range(0, len(self.__traces)):
                    # delta_j1nnd and delta_j2nnd and ... delta_jlnnd
                    list_of_d.append(variablesFunction(j, d))
                # not di or ( dji and dji ... dji)
                not_di_or_list_of_and = Or(
                    [], [self.__vars.get(BOOLEAN_VAR_SUP, [d])],
                    [And(list_of_d, [], [])])
                list_of_formula.append(not_di_or_list_of_and)

        if artefact == MULTI_ALIGNMENT:
            for d in range(0, self.__max_d + 1):
                list_of_d = []
                for j in range(0, len(self.__traces)):
                    # not delta_j1nnd or not delta_j2nnd or ... not delta_jlnnd
                    list_of_d.append(variablesFunction(j, d))
                #  di or ( dji or dji ... dji)
                not_di_or_list_of_and = Or(
                    [self.__vars.get(BOOLEAN_VAR_SUP, [d])], [],
                    [And([], list_of_d, [])])
                list_of_formula.append(not_di_or_list_of_and)
        return list_of_formula
Exemple #2
0
def is_action(places, transitions, m0, i, m_ip, tau_it, space_between_fired):
    '''
    The is_action method used by is_run creates the formula of each instant. Which transition fired ?
    :param places (list) :
    :param transitions (list) :
    :param m0 (marking) : initial marking
    :param i (int) : instant in the run
    :param m_ip (function) : function to get the number of the boolean variables of the markings, see variablesGenerator.
    :param tau_it (function) : function to get the number of the boolean variables of the transitions, see variablesGenerator.
    :return:
    '''
    # only one transition is true at instant i
    or_formulas = []
    for t in transitions:
        or_formulas.append(
            And([tau_it([i, transitions.index(t)])], [
                tau_it([i, transitions.index(t2)])
                for t2 in transitions if t != t2
            ], []))
    formulas = [Or([], [], or_formulas)]
    # if transition t fires at instant i, then we have the good marking
    for t in transitions:
        formulas.append(
            Or([], [tau_it([i, transitions.index(t)])],
               [is_transition(places, t, i, m_ip, space_between_fired)]))
    return And([], [], formulas)
def maxDistance2(vars, diff1, diff2, max_d, size_of_run):
    list_to_size_of_run = list(range(1, size_of_run * 2 + 1))
    max_distance = max_d
    # IDEA : there are at least max_distance number of false variables
    combinaisons_of_instants = list(
        itertools.combinations(list_to_size_of_run, max_distance))
    distFalseVariables = []
    for instants in combinaisons_of_instants:
        list_distances = []
        for i in instants:
            if i <= size_of_run:
                list_distances.append(diff1([i]))
            else:
                list_distances.append(diff2([i - size_of_run]))
        list_distances2 = []
        for i in range(1, size_of_run * 2 + 1):
            if i not in instants:
                if i <= size_of_run:
                    list_distances2.append(diff1([i]))
                else:
                    list_distances2.append(diff2([i - size_of_run]))

        distFalseVariables.append(
            Or([], list_distances, [And([], list_distances2, [])]))
    return Or([], [], distFalseVariables)
Exemple #4
0
def initialisation_ReducedForAntiAlignment(transitions, silent_transitions, tau_it, lambda_jia, djiid, j, size_of_run,
                                           wait_transition, max_d):
    '''
   Initialisation of the edit distance reduced for anti-alignmet.
   This is the 3 first axioms of the _Encoding Conformance Checking Artefacts in SAT_ paper
   :param transitions (list) : list of transitions
   :param silent_transitions (list) : list of the silent transitions
   :param tau_it (fun) : function that returns the boolean variable number of the firing transition t at an instant i
   :param lambda_jia (fun) : function that returns the boolean variable number of the letter of trace j at instant i
   :param djiid (fun) : function that returns the boolean variable that says at instant i and i of we have d distance
   :param j (int) : jth trace
   :param size_of_run (int) : maximal size of a run
   :param wait_transition (transition) : to finish words
   :param max_d (int): heuristic
   :return: formula
   '''

    def t(transition):
        return transitions.index(transition)

    positives = []
    # diid is true for d = 0
    for i_m in range(0, size_of_run + 1):
        for i_t in range(0, size_of_run + 1):
            positives.append(djiid([j, i_m, i_t, 0]))

    # diid is false for 1 1 d and d >0
    negatives = [djiid([j, 0, 0, d]) for d in range(1, max_d + 1)]

    formulas = []
    for d in range(0, max_d):
        for i_m in range(0, size_of_run):
            # (i_m <> w and i_m <> tau ) <=> (d im+1 0 d+1 => d im 0 d )
            condition = [tau_it([i_m + 1, t(wait_transition)])]
            for st in silent_transitions:
                condition.append(tau_it([i_m + 1, t(st)]))
            this_condition = condition
            this_condition.append(djiid([j, i_m, 0, d]))
            i_t_null_and_i_m_cost = Or(this_condition, [djiid([j, i_m + 1, 0, d + 1])], [])
            formulas.append(i_t_null_and_i_m_cost)

            # (i_m == w or i_m == tau ) <=> (d im+1 0 d => d im 0 d )
            i_t_null_and_i_m_dont_cost = Or([djiid([j, i_m, 0, d])], [djiid([j, i_m + 1, 0, d])], [
                And([], condition, [])
            ])
            formulas.append(i_t_null_and_i_m_dont_cost)

        for i_t in range(0, size_of_run):
            # i_t <> w <=> (d 0 it+1 d+1 => d 0 it d )
            i_m_null_and_i_t_cost = Or(
                [lambda_jia([j, i_t + 1, t(wait_transition)]), djiid([j, 0, i_t, d])],
                [djiid([j, 0, i_t + 1, d + 1])], [])
            formulas.append(i_m_null_and_i_t_cost)

            # i_t == w <=> (d 0 it+1 d => d 0 it d )
            i_m_null_and_i_t_dont_cost = Or([djiid([j, 0, i_t, d])],
                                            [lambda_jia([j, i_t + 1, t(wait_transition)]),
                                             djiid([j, 0, i_t + 1, d])], [])
            formulas.append(i_m_null_and_i_t_dont_cost)
    return And(positives, negatives, formulas)
Exemple #5
0
def bodyHammingDistance_reducedForAntiAlignment(transitions, silent_transitions, vars, nbTraces, size_of_run):
    '''
    Reduced formula of hamming distance for anti-alignment
    :param transitions (list) : the transitions
    :param silent_transitions (list) : the silent transitions
    :param variables (variablesGenerator) : to creates the variables numbers
    :param nbTraces (int) : number of traces
    :param size_of_run (int) : maximal size of run
    :return: formula
    '''
    formulas = []
    for j in range(0, nbTraces):
        for i in range(1, size_of_run + 1):
            for t in range(0, len(transitions)):
                if transitions[t] not in silent_transitions:
                    # (tau_i,t and lambda_i,t ) => not diff_i
                    create_diff = Or([], [vars.get(BOOLEAN_VAR_HAMMING_DISTANCE, [j, i])], [
                        Or([],
                           [vars.get(BOOLEAN_VAR_FIRING_TRANSITION_PN, [i, t]),
                            vars.get(BOOLEAN_VAR_TRACES_ACTIONS, [j, i, t]), ], [])
                    ])
                else:
                    # tau_ti => not diff_i
                    create_diff = Or([], [vars.get(BOOLEAN_VAR_FIRING_TRANSITION_PN, [i, t]),
                                          vars.get(BOOLEAN_VAR_HAMMING_DISTANCE, [j, i])], [])
                formulas.append(create_diff)
    return formulas
Exemple #6
0
def bodyHammingDistance(transitions, silent_transitions, vars, nbTraces, size_of_run):
    '''
    Exact formula of hamming distance.
    :param transitions (list) : the transitions
    :param silent_transitions (list) : the silent transitions
    :param variables (variablesGenerator) : to creates the variables numbers
    :param nbTraces (int) : number of traces
    :param size_of_run (int) : maximal size of run
    :return: formula
    '''
    formulas = []
    for j in range(0, nbTraces):
        for i in range(1, size_of_run + 1):
            for t in range(0, len(transitions)):
                if transitions[t] not in silent_transitions:
                    create_diff = Or([],
                                     [],
                                     [
                                         And([vars.get(BOOLEAN_VAR_FIRING_TRANSITION_PN, [i, t])], [], [
                                             Or([vars.get(BOOLEAN_VAR_TRACES_ACTIONS, [j, i, t]),
                                                 vars.get(BOOLEAN_VAR_HAMMING_DISTANCE, [j, i])], [], [])
                                         ]),
                                         And([], [vars.get(BOOLEAN_VAR_FIRING_TRANSITION_PN, [i, t]),
                                                  vars.get(BOOLEAN_VAR_TRACES_ACTIONS, [j, i, t]),
                                                  vars.get(BOOLEAN_VAR_HAMMING_DISTANCE, [j, i])], [])
                                     ])
                else:
                    create_diff = Or([], [vars.get(BOOLEAN_VAR_FIRING_TRANSITION_PN, [i, t]),
                                          vars.get(BOOLEAN_VAR_HAMMING_DISTANCE, [j, i])], [])
                formulas.append(create_diff)
    return formulas
Exemple #7
0
    def __getDiffTracesCentroids(self, chi_jia, diffl_ji, diffm_ji,
                                 lambda_jia):
        '''
        This function that defines the difference between the traces and its centroid and calls
        __maxDiffTracesCentroids().
        :param chi_jia (function)
        :param diff_ji (function)
        :param lambda_jia (function)
        :return: list of formula
        '''
        formulas = []
        for j in range(0, len(self.__traces)):
            aDiffPerInstant = []
            for i in range(1, self.__size_of_run + 1):
                # for each instant, a transition is true and there is or not a diff
                for t in range(0, len(self.__transitions)):
                    # if silent transition : diffjit is false
                    if self.__transitions[t] in self.__silent_transititons:
                        indexOfWaitModel = self.__transitions.index(
                            self.__wait_transition_model)
                        indexOfWaitTrace = self.__transitions.index(
                            self.__wait_transition_trace)
                        diffjit = Or([
                            diffl_ji([j, i]),
                            lambda_jia([j, i, indexOfWaitModel]),
                            lambda_jia([j, i, indexOfWaitTrace])
                        ], [chi_jia([j, i, t])], [])
                    # chi_jia => lambda_jia or diff_ji
                    elif self.__transitions[t] == self.__wait_transition_model:
                        diffjit = Or([diffl_ji([j, i]),
                                      lambda_jia([j, i, t])],
                                     [chi_jia([j, i, t])], [])
                    elif self.__transitions[t] == self.__wait_transition_trace:
                        diffjit = Or([diffm_ji([j, i])], [chi_jia([j, i, t])],
                                     [])
                    else:
                        indexOfWaitTrace = self.__transitions.index(
                            self.__wait_transition_trace)
                        diffjit = Or([], [], [
                            Or([lambda_jia([j, i, t])], [chi_jia([j, i, t])], [
                                And([diffl_ji([j, i]),
                                     diffm_ji([j, i])], [], [])
                            ]),
                            And([
                                diffm_ji([j, i]),
                                lambda_jia([j, i, indexOfWaitTrace]),
                                chi_jia([j, i, t])
                            ], [], [])
                        ])
                    aDiffPerInstant.append(diffjit)
            diffPerJ = And([], [], aDiffPerInstant)
            formulas.append(diffPerJ)

        # then there is maximal number of diff :
        self.__maxDiffTracesCentroids(formulas)
        return formulas
Exemple #8
0
def for_hamming_distance_aux_supd_multi(vars, lenTraces, max_d, size_of_run):
    list_of_formula=[]
    list_to_size_of_run= list(range(1,size_of_run+1))
    not_d_or_and_diff=[]
    for j in range (0, lenTraces):
        for d in range(1,min(max_d + 1,size_of_run+1)):
            combinaisons_of_instants=list(itertools.combinations(list_to_size_of_run,d))
            and_sub_instants=[]
            for sub_list_of_instants in combinaisons_of_instants:
                instants_to_combine=[]
                for instant in list(sub_list_of_instants):
                    instants_to_combine.append(vars.get(BOOLEAN_VAR_HAMMING_DISTANCE, [j, instant]))
                and_sub_instants.append(Or([],instants_to_combine,[]))
            not_d_or_and_diff.append(Or([vars.get(BOOLEAN_VAR_HAMMING_SUP_AUX, [j, d])], [], [And([], [], and_sub_instants)]))
    list_of_formula.append(And([],[],not_d_or_and_diff))
    return list_of_formula
Exemple #9
0
 def __maxDiffTracesCentroids(self, formulas):
     '''
     This function uses self.__max_d that determines the maximal distance of the trace to its centroid.
     Idea of the threshold : there are at least N diff variables false per trace.
     :param formulas (list of formula to fill)
     :return: void
     '''
     # this function uses combinations of itertools to get all the combinations : this is better than parameter
     # at_most of pysat library
     list_to_size_of_run = list(range(1, (self.__size_of_run * 2) + 1))
     max_distance = (self.__size_of_run * 2) - self.__max_d
     # IDEA : there are at least max_distance number of false variables
     combinaisons_of_instants = list(
         itertools.combinations(list_to_size_of_run, max_distance))
     for j in range(0, len(self.__traces)):
         distFalseVariables = []
         for instants in combinaisons_of_instants:
             list_distances = []
             for i in instants:
                 if i <= self.__size_of_run:
                     list_distances.append(
                         self.__vars.get(BOOLEAN_VAR_DIFF_l, [j, i]))
                 else:
                     list_distances.append(
                         self.__vars.get(BOOLEAN_VAR_DIFF_m,
                                         [j, (i - self.__size_of_run)]))
             distFalseVariables.append(And([], list_distances, []))
         formulas.append(Or([], [], distFalseVariables))
Exemple #10
0
 def is_action_for_j(j, trace_places, pn_transitions, trace_transitions, i,
                     m_ip, tau_it):
     '''
     The is_action method used by is_run creates the formula of each instant. Which transition fired ?
     :param places (list) :
     :param pn_transitions (list) : we need all the alphabet to refuse transitions that aren't in trace
     :param trace_transitions (list) : transitions of the trace
     :param i (int) : instant in the run
     :param m_ip (function) : function to get the number of the boolean variables of the markings, see variablesGenerator.
     :param tau_it (function) : function to get the number of the boolean variables of the transitions, see variablesGenerator.
     :return:
     '''
     # only one transition is true at instant i
     # lazy comment : this verifies that alphabet is complet : all action not executed has to be taken into account
     or_formulas = []
     formulas = []
     label_transitions = [t.label for t in pn_transitions]
     copie_transitions = [t for t in pn_transitions]
     transitions_already_done = []
     for t in trace_transitions:
         if t not in transitions_already_done:
             other_transitions_with_same_label = []
             for t2 in trace_transitions:
                 if t2.label == t.label:
                     other_transitions_with_same_label.append(t2)
                     transitions_already_done.append(t2)
             if t.label in label_transitions:
                 index_of_t = label_transitions.index(t.label)
             else:
                 index_of_t = None  # should never happen
             copie_transitions.remove(
                 pn_transitions[(label_transitions.index(t.label))])
             or_formulas.append(And([tau_it([j, i, index_of_t])], [], []))
             implication = []
             for t2 in other_transitions_with_same_label:
                 implication.append(
                     is_transition_for_j(j, trace_places, t2, i, m_ip))
             formulas.append(
                 Or([], [tau_it([j, i, index_of_t])], implication))
     formulas.append(Or([], [], or_formulas))
     formulas.append(
         And([], [
             tau_it([j, i, pn_transitions.index(r)])
             for r in copie_transitions
         ], []))
     return And([], [], formulas)
Exemple #11
0
        def is_action_centroid(j, places, transitions, i, m_jip, tau_jip, c_kt,
                               chi_jk, nb_clusters):
            '''
            @see pnToFormula.py, is_action_centroid says if transition is fired.
            :param j (int) : index of trace
            :param places (list) : places of the petri net, indexes are important
            :param transitions (list) : transitions of the petri net, indexes are important
            :param i (int) : instant in the run of the centroid
            :param m_jip (function) : @see variablesGenerator.py, function chi_jk gets BOOLEAN_VAR_CHI_MARKINGS variables
            :param tau_jip (function) : @see variablesGenerator.py, function chi_jk gets BOOLEAN_VAR_CHI_TRANSITIONS
             variables
            :param c_kt (function) : @see variablesGenerator.py, function chi_jk gets BOOLEAN_VAR_K_CONTAINS_T variables
            :param chi_jk (function) : @see variablesGenerator.py, function chi_jk gets BOOLEAN_VAR_J_IN_K variables
            :param nb_clusters (int) : number of cluster
            :return:
            '''
            # a transition fires and only one
            aTransitionPerInstant = [
                And([tau_jip([j, i, t])], [
                    tau_jip([j, i, t2])
                    for t2 in range(len(transitions)) if t != t2
                ], []) for t in range(len(transitions))
            ]
            formulas = [Or([], [], aTransitionPerInstant)]

            # runs is_transition for the fired transition
            indexOfTraceWait = transitions.index(self.__wait_transition_trace)
            for t in range(len(transitions)):
                # WAIT_TRANSITION_TRACE is forbidden for centroid
                if t == indexOfTraceWait:
                    formulas.append(And([], [tau_jip([j, i, t])], []))
                else:
                    formulas.append(
                        Or([], [tau_jip([j, i, t])], [
                            And([], [], [
                                is_transition_centroid(
                                    j, places, transitions[t], i, m_jip),
                                in_cluster_of_j(t, c_kt, j, chi_jk,
                                                nb_clusters)
                            ])
                        ]))
            return And([], [], formulas)
def distanceNets(vars, size_of_run, tau1, tau2, pn1_transitions,
                 pn2_transitions, w1, w2):
    formula = []
    vars.add(BOOLEAN_VAR_DIFF1, [(1, size_of_run + 1)])
    vars.add(BOOLEAN_VAR_DIFF2, [(1, size_of_run + 1)])

    for i in range(1, size_of_run + 1):
        for t1 in pn1_transitions:
            '''
            listOfSameLabels=[tau2([i,pn2_transitions.index(t2)]) for t2 in pn2_transitions if t2.label==t1.label]
            listOfSameLabels.append(vars.getFunction(BOOLEAN_VAR_DIFF)([i]))
            formula.append(Or(listOfSameLabels,[tau1([i,pn1_transitions.index(t1)]) ],[]))

            '''
            if t1 != w1:
                listOfSameLabels = [
                    tau2([i, pn2_transitions.index(t2)])
                    for t2 in pn2_transitions if t2.label == t1.label
                ]
                listOfSameLabels.append(tau2([i, pn2_transitions.index(w2)]))
                formula.append(
                    Or(listOfSameLabels,
                       [tau1([i, pn1_transitions.index(t1)])], [
                           And([
                               vars.getFunction(BOOLEAN_VAR_DIFF1)([i]),
                               vars.getFunction(BOOLEAN_VAR_DIFF2)([i])
                           ], [], [])
                       ]))
                formula.append(
                    Or([vars.getFunction(BOOLEAN_VAR_DIFF1)([i])], [
                        tau2([i, pn2_transitions.index(w2)]),
                        tau1([i, pn1_transitions.index(t1)])
                    ], []))
            else:
                formula.append(
                    Or([
                        vars.getFunction(BOOLEAN_VAR_DIFF2)([i]),
                        tau2([i, pn2_transitions.index(w2)])
                    ], [tau1([i, pn1_transitions.index(t1)])], []))

    return And([], [], formula)
Exemple #13
0
 def in_cluster_of_j(tr, c_kt, j, chi_jk, nb_clusters):
     '''
     Subfunction of __createCentroids. in_cluster_of_j function affects a transition to the cluster of the trace.
     :param tr (Transition)
     :param c_kt (function) : @see variablesGenerator.py, function c_kt(k,t) gets BOOLEAN_VAR_K_CONTAINS_T
     variables
     :param j (int) : index of the current trace
     :param chi_jk (function) : @see variablesGenerator.py, function chi_jk gets BOOLEAN_VAR_J_IN_K variables
     :param nb_clusters (int) : number of cluster
     :return:
     '''
     # BOOLEAN_VAR_J_IN_K => BOOLEAN_VAR_K_CONTAINS_T
     return And([], [], [
         Or([c_kt([k, tr])], [chi_jk([j, k])], [])
         for k in range(0, nb_clusters)
     ])
Exemple #14
0
def is_transition(places, transition, i, m_ip, space_between_fired):
    '''
    The is_transition method used by is_action creates the formula of a firing transition. Which marking is needed ?
    :param places (list) :
    :param transitions (list) :
    :param i (int) : instant in the run
    :param m_ip (function) : function to get the number of the boolean variables of the markings, see variablesGenerator.
    :return:
    '''
    formulas = []
    prePlaces = [a.source for a in transition.in_arcs]
    postPlaces = [a.target for a in transition.out_arcs]

    for p in places:
        if p in prePlaces and p in postPlaces:
            formulas.append(
                And([
                    m_ip([i, places.index(p)]),
                    m_ip([i - space_between_fired,
                          places.index(p)])
                ], [], []))
        elif p in prePlaces and p not in postPlaces:
            formulas.append(
                And([m_ip([i - space_between_fired,
                           places.index(p)])], [m_ip([i, places.index(p)])],
                    []))
        elif p not in prePlaces and p in postPlaces:
            formulas.append(
                And([m_ip([i, places.index(p)])],
                    [m_ip([i - space_between_fired,
                           places.index(p)])], []))
        elif p not in prePlaces and p not in postPlaces:
            formulas.append(
                Or([], [], [
                    And([
                        m_ip([i, places.index(p)]),
                        m_ip([i - space_between_fired,
                              places.index(p)])
                    ], [], []),
                    And([], [
                        m_ip([i, places.index(p)]),
                        m_ip([i - space_between_fired,
                              places.index(p)])
                    ], [])
                ]))
    return And([], [], formulas)
Exemple #15
0
 def __commonTransitions(self, common_kkt, ckt):
     '''
     When two clusters share a transition, BOOLEAN_VAR_COMMON_T are True.
     :paramc common_kkt (function)
     :param ckt (function)
     :return list of formula
     '''
     listOfCommunTransitionsFormulas = []
     for k1 in range(0, self.__nb_clusters):
         for k2 in range(k1 + 1, self.__nb_clusters):
             for t in range(len(self.__transitions)):
                 # (c_k1t and c_k2t) => common_k1k2t
                 haveATransitionInCommon = Or(
                     [common_kkt([k1, k2, t])],
                     [ckt([k1, t]), ckt([k2, t])], [])
                 listOfCommunTransitionsFormulas.append(
                     haveATransitionInCommon)
     return listOfCommunTransitionsFormulas
def numberOfWaitInRun(vars, size_of_run, tau1, pn1_transitions, w1, we):
    list_to_size_of_run = list(range(1, size_of_run * 2 + 1))
    minw1 = int((size_of_run) / 2)
    # IDEA : there are at least max_distance number of w1 variables to false
    combinaisons_of_instants = list(
        itertools.combinations(list_to_size_of_run, minw1))
    w1ToTrue = []
    for instants in combinaisons_of_instants:
        listOfW1ToTrue = []
        for i in instants:
            if i <= int(size_of_run):
                listOfW1ToTrue.append(tau1([i, pn1_transitions.index(w1)]))
            else:
                listOfW1ToTrue.append(
                    tau1([i - int(size_of_run),
                          pn1_transitions.index(we)]))
        w1ToTrue.append(And(listOfW1ToTrue, [], []))
    return Or([], [], w1ToTrue)
Exemple #17
0
 def is_transition_centroid(j, places, tr, i, m_ip):
     '''
     This function verifies marking to fire transition of a centroid.
     :param j (int) : index of centroid
     :param places (list) : list of places
     :param tr (Transition) : transition that wants to fire
     :param i (int) : instant of firing
     :param m_ip (function) : @see @variablesGenerator.py function to get BOOLEAN_VAR_CHI_MARKINGS variables
     '''
     formulas = []
     prePlaces = [a.source for a in tr.in_arcs]
     postPlaces = [a.target for a in tr.out_arcs]
     # token game
     for p in places:
         if p in prePlaces and p in postPlaces:
             formulas.append(
                 And([
                     m_ip([j, i, places.index(p)]),
                     m_ip([j, i - 1, places.index(p)])
                 ], [], []))
         elif p in prePlaces and p not in postPlaces:
             formulas.append(
                 And([m_ip([j, i - 1, places.index(p)])],
                     [m_ip([j, i, places.index(p)])], []))
         elif p not in prePlaces and p in postPlaces:
             formulas.append(
                 And([m_ip([j, i, places.index(p)])],
                     [m_ip([j, i - 1, places.index(p)])], []))
         elif p not in prePlaces and p not in postPlaces:
             formulas.append(
                 Or([], [], [
                     And([
                         m_ip([j, i, places.index(p)]),
                         m_ip([j, i - 1, places.index(p)])
                     ], [], []),
                     And([], [
                         m_ip([j, i, places.index(p)]),
                         m_ip([j, i - 1, places.index(p)])
                     ], [])
                 ]))
     return And([], [], formulas)
Exemple #18
0
 def __tracesInAClusterOnly(self, inC_j, chi_jk):
     '''
     Verifies that j is in a unique cluster or any
     :param inC_j (function)
     :param chi_jk (function)
     '''
     formulas = []
     for j in range(0, len(self.__traces)):
         inCorNot = []
         for k1 in range(0, self.__nb_clusters):
             # if in k1 then not in other k
             inCorNot.append(
                 And([inC_j([j]), chi_jk([j, k1])], [
                     chi_jk([j, k])
                     for k in range(0, self.__nb_clusters) if k != k1
                 ], []))
         # if in any k, then not inC
         allKNot = [chi_jk([j, k]) for k in range(0, self.__nb_clusters)]
         allKNot.append(inC_j([j]))
         inCorNot.append(And([], allKNot, []))
         formulas.append(Or([], [], inCorNot))
     return formulas
Exemple #19
0
def recursionEditDistance_reducedForMultiAlignment(transitions, silent_transitions, tau_it, lambda_jia, djiid, j,
                                                   size_of_run,
                                                   wait_transition, max_d):
    '''
    Initialisation of the edit distance reduced for multi-alignment.
    This is the 2 lasts axioms of the _Encoding Conformance Checking Artefacts in SAT_ paper
    :param transitions (list) : list of transitions
    :param silent_transitions (list) : list of the silent transitions
    :param tau_it (fun) : function that returns the boolean variable number of the firing transition t at an instant i
    :param lambda_jia (fun) : function that returns the boolean variable number of the letter of trace j at instant i
    :param djiid (fun) : function that returns the boolean variable that says at instant i and i of we have d distance
    :param j (int) : jth trace
    :param size_of_run (int) : maximal size of a run
    :param wait_transition (transition) : to finish words
    :param max_d (int): heuristic
    :return: formula
    '''

    def t(transition):
        return transitions.index(transition)

    formulas = []
    for i_m in range(0, size_of_run):
        for i_t in range(0, size_of_run):
            for d in range(0, max_d):
                # letters are equals i_t+1 == i_m+1 => (d i_t i_m d => d i_t+1 i_m+1 d)
                letters_are_equals = Or([djiid([j, i_m + 1, i_t + 1, d+1])], [djiid([j, i_m, i_t, d+1])],
                                        [And([], [],
                                             [Or([], [tau_it([i_m + 1, t]), lambda_jia([j, i_t + 1, t])], []) for t in
                                              range(0, len(transitions))]
                                             )])
                formulas.append(letters_are_equals)

                # letters are diff : i_t+1 == i_m+1 => (d i_t i_m d => d i_t+1 i_m+1 d)
                condition = [tau_it([i_m + 1, t(wait_transition)]), lambda_jia([j, i_t + 1, t(wait_transition)])]
                for st in silent_transitions:
                    condition.append(tau_it([i_m + 1, t(st)]))
                condition.append(djiid([j, i_m + 1, i_t + 1, d + 1]))
                letters_are_diff = Or(condition,
                                      [djiid([j, i_m + 1, i_t, d]), djiid([j, i_m, i_t + 1, d])],
                                      [And([tau_it([i_m + 1, t]), lambda_jia([j, i_t + 1, t])], [], []) for
                                       t in range(0, len(transitions))])
                formulas.append(letters_are_diff)

                # ( u_t == w and u_m <> w) => ( d i_m i_t d => d i_m+1 i_t d
                finish_run_of_model = Or([tau_it([i_m + 1, t(wait_transition)]), djiid([j, i_m + 1, i_t + 1, d])],
                                         [lambda_jia([j, i_t + 1, t(wait_transition)]), djiid([j, i_m + 1, i_t, d])],
                                         [])
                formulas.append(finish_run_of_model)

                # ( u_m == w and u_t <> w) => ( d i_m i_t d => d i_m i_t+1 d
                condition=[tau_it([i_m + 1, t(wait_transition)])]
                for st in silent_transitions:
                    condition.append(tau_it([i_m + 1, t(st)]))
                finish_run_of_trace = Or(
                    [lambda_jia([j, i_t + 1, t(wait_transition)]), djiid([j, i_m + 1, i_t + 1, d])],
                    [ djiid([j, i_m, i_t + 1, d])], [
                        And([], condition,[])
                    ])
                formulas.append(finish_run_of_trace)
    return formulas
def apply(net1, m01, mf1, net2, m02, mf2, size_of_run, d, silent_label=None):

    vars = vg.VariablesGenerator()
    #we=add_wait_net_end(net1,"wf")
    w1 = add_wait_net(net1, "wf")
    adapted_size_of_run = size_of_run * size_of_run + size_of_run
    pn1_formula, pn1_places, pn1_transitions, pn1_silent_transitions = petri_net_to_SAT(
        net1,
        m01,
        mf1,
        vars,
        adapted_size_of_run,
        reach_final=True,
        label_m=BOOLEAN_VAR_MARKING_PN_1,
        label_t=BOOLEAN_VAR_FIRING_TRANSITION_PN_1,
        silent_transition=silent_label,
        space_between_fired=1 + size_of_run)
    print("etape1")

    pn1_force_wait_transitions = force_wait_transition(vars, w1,
                                                       pn1_transitions,
                                                       adapted_size_of_run,
                                                       size_of_run + 1)
    print("etape2")
    w2 = add_wait_net(net2, "wf")
    pn2_formula, pn2_places, pn2_transitions, pn2_silent_transitions = petri_net_to_SAT(
        net2,
        m02,
        mf2,
        vars,
        adapted_size_of_run,
        reach_final=True,
        label_m=BOOLEAN_VAR_MARKING_PN_2,
        label_t=BOOLEAN_VAR_FIRING_TRANSITION_PN_2,
        silent_transition=silent_label)
    dist_formulas = distanceNets(
        vars, adapted_size_of_run,
        vars.getFunction(BOOLEAN_VAR_FIRING_TRANSITION_PN_1),
        vars.getFunction(BOOLEAN_VAR_FIRING_TRANSITION_PN_2), pn1_transitions,
        pn2_transitions, w1, w2)
    print("etape3")

    maxDist_formulas = maxDistance(vars, vars.getFunction(BOOLEAN_VAR_DIFF1),
                                   vars.getFunction(BOOLEAN_VAR_DIFF2), d,
                                   adapted_size_of_run)
    #notTooManyW=numberOfWaitInRun(vars,size_of_run,vars.getFunction(BOOLEAN_VAR_FIRING_TRANSITION_PN_1),pn1_transitions,w1,we)
    print("etape4")
    from pm4py.visualization.petrinet import factory as vizu
    #vizu.apply(net2,m02,mf2).view()
    listOfForAll = vars.getAll(BOOLEAN_VAR_MARKING_PN_1) + vars.getAll(
        BOOLEAN_VAR_FIRING_TRANSITION_PN_1)
    listOfExist = vars.getAll(BOOLEAN_VAR_MARKING_PN_2) + vars.getAll(
        BOOLEAN_VAR_FIRING_TRANSITION_PN_2) + vars.getAll(
            BOOLEAN_VAR_DIFF1) + vars.getAll(BOOLEAN_VAR_DIFF2)

    full_formula = Or([], [], [
        And([], [], [pn1_formula, pn1_force_wait_transitions]).negation(),
        And([], [], [dist_formulas, maxDist_formulas, pn2_formula])
    ])
    print("etape5")
    cnf = full_formula.operatorToCnf(vars.iterator)
    print("etape6")
    listOfExist += list(range(vars.iterator, full_formula.nbVars))
    writeQDimacs(full_formula.nbVars, listOfForAll, listOfExist, cnf)
    print("mais voila")
    runCadet()
    positives, negatives = cadetOutputQDimacs()
    for var in positives:
        if vars.getVarName(var) != None and vars.getVarName(var).startswith(
                "tau1_ia"):
            print(
                vars.getVarName(var), pn1_transitions[int(
                    vars.getVarName(var).split(", ")[1].split("]")[0])])

    print("....")
    for var in negatives:
        if vars.getVarName(var) != None and vars.getVarName(var).startswith(
                "tau1_ia"):
            print(
                vars.getVarName(var), pn1_transitions[int(
                    vars.getVarName(var).split(", ")[1].split("]")[0])])
Exemple #21
0
    def __createCentroids(self, m0, mf):
        '''
        Create formula of the subnet centroids. There are one centroid per trace and transitions are affected to cluster.
        As the number of cluster is limited, centroid will naturally be joined : traces are clustered that way.
        Centroids finally are run of the model that allows alignments. When alignment are found, transitions go in
        clusters.
        Creates BOOLEAN_VAR_CHI_MARKINGS, BOOLEAN_VAR_CHI_TRANSITIONS, BOOLEAN_VAR_K_CONTAINS_T, BOOLEAN_VAR_J_IN_K
        boolean variables.
        This function has subfunctions because formula differ from normal petri nets (@see pnToFormula).
        :param m0 (Marking)
        '''
        def in_cluster_of_j(tr, c_kt, j, chi_jk, nb_clusters):
            '''
            Subfunction of __createCentroids. in_cluster_of_j function affects a transition to the cluster of the trace.
            :param tr (Transition)
            :param c_kt (function) : @see variablesGenerator.py, function c_kt(k,t) gets BOOLEAN_VAR_K_CONTAINS_T
            variables
            :param j (int) : index of the current trace
            :param chi_jk (function) : @see variablesGenerator.py, function chi_jk gets BOOLEAN_VAR_J_IN_K variables
            :param nb_clusters (int) : number of cluster
            :return:
            '''
            # BOOLEAN_VAR_J_IN_K => BOOLEAN_VAR_K_CONTAINS_T
            return And([], [], [
                Or([c_kt([k, tr])], [chi_jk([j, k])], [])
                for k in range(0, nb_clusters)
            ])

        def is_transition_centroid(j, places, tr, i, m_ip):
            '''
            This function verifies marking to fire transition of a centroid.
            :param j (int) : index of centroid
            :param places (list) : list of places
            :param tr (Transition) : transition that wants to fire
            :param i (int) : instant of firing
            :param m_ip (function) : @see @variablesGenerator.py function to get BOOLEAN_VAR_CHI_MARKINGS variables
            '''
            formulas = []
            prePlaces = [a.source for a in tr.in_arcs]
            postPlaces = [a.target for a in tr.out_arcs]
            # token game
            for p in places:
                if p in prePlaces and p in postPlaces:
                    formulas.append(
                        And([
                            m_ip([j, i, places.index(p)]),
                            m_ip([j, i - 1, places.index(p)])
                        ], [], []))
                elif p in prePlaces and p not in postPlaces:
                    formulas.append(
                        And([m_ip([j, i - 1, places.index(p)])],
                            [m_ip([j, i, places.index(p)])], []))
                elif p not in prePlaces and p in postPlaces:
                    formulas.append(
                        And([m_ip([j, i, places.index(p)])],
                            [m_ip([j, i - 1, places.index(p)])], []))
                elif p not in prePlaces and p not in postPlaces:
                    formulas.append(
                        Or([], [], [
                            And([
                                m_ip([j, i, places.index(p)]),
                                m_ip([j, i - 1, places.index(p)])
                            ], [], []),
                            And([], [
                                m_ip([j, i, places.index(p)]),
                                m_ip([j, i - 1, places.index(p)])
                            ], [])
                        ]))
            return And([], [], formulas)

        def is_action_centroid(j, places, transitions, i, m_jip, tau_jip, c_kt,
                               chi_jk, nb_clusters):
            '''
            @see pnToFormula.py, is_action_centroid says if transition is fired.
            :param j (int) : index of trace
            :param places (list) : places of the petri net, indexes are important
            :param transitions (list) : transitions of the petri net, indexes are important
            :param i (int) : instant in the run of the centroid
            :param m_jip (function) : @see variablesGenerator.py, function chi_jk gets BOOLEAN_VAR_CHI_MARKINGS variables
            :param tau_jip (function) : @see variablesGenerator.py, function chi_jk gets BOOLEAN_VAR_CHI_TRANSITIONS
             variables
            :param c_kt (function) : @see variablesGenerator.py, function chi_jk gets BOOLEAN_VAR_K_CONTAINS_T variables
            :param chi_jk (function) : @see variablesGenerator.py, function chi_jk gets BOOLEAN_VAR_J_IN_K variables
            :param nb_clusters (int) : number of cluster
            :return:
            '''
            # a transition fires and only one
            aTransitionPerInstant = [
                And([tau_jip([j, i, t])], [
                    tau_jip([j, i, t2])
                    for t2 in range(len(transitions)) if t != t2
                ], []) for t in range(len(transitions))
            ]
            formulas = [Or([], [], aTransitionPerInstant)]

            # runs is_transition for the fired transition
            indexOfTraceWait = transitions.index(self.__wait_transition_trace)
            for t in range(len(transitions)):
                # WAIT_TRANSITION_TRACE is forbidden for centroid
                if t == indexOfTraceWait:
                    formulas.append(And([], [tau_jip([j, i, t])], []))
                else:
                    formulas.append(
                        Or([], [tau_jip([j, i, t])], [
                            And([], [], [
                                is_transition_centroid(
                                    j, places, transitions[t], i, m_jip),
                                in_cluster_of_j(t, c_kt, j, chi_jk,
                                                nb_clusters)
                            ])
                        ]))
            return And([], [], formulas)

        def is_run_centroid(j, size_of_run, m0, mf, m_jip, tau_jip, c_kt,
                            chi_jk, nb_clusters, transitions, places):
            '''
            Initialization of centroids. There is a run per trace. This run represents alignment of the trace to the
            model. If trace is clusterised then transition of it run are containing in the centroid of its cluster.
            :param j (int) : index of trace
            :param size_of_run (int) : maximal size of the run, prefix
            :param m0 (Marking) : initial marking
            :param m_jip (function) : @see variablesGenerator.py, function chi_jk gets BOOLEAN_VAR_CHI_MARKINGS variables
            :param tau_jip (function) : @see variablesGenerator.py, function chi_jk gets BOOLEAN_VAR_CHI_TRANSITIONS
             variables
            :param c_kt (function) : @see variablesGenerator.py, function chi_jk gets BOOLEAN_VAR_K_CONTAINS_T variables
            :param chi_jk (function) : @see variablesGenerator.py, function chi_jk gets BOOLEAN_VAR_J_IN_K variables
            :param nb_clusters (int) : number of cluster
            :param transitions (list) : list of Transitions
            :param places (list) : list of Places
            :return:
            '''
            positives = [m_jip([j, 0, places.index(m)]) for m in m0]
            for m in mf:
                positives.append(m_jip([j, size_of_run, places.index(m)]))
            negatives = [
                m_jip([j, 0, places.index(m)]) for m in places if m not in m0
            ]
            formulas = [
                is_action_centroid(j, places, transitions, i, m_jip, tau_jip,
                                   c_kt, chi_jk, nb_clusters)
                for i in range(1, size_of_run + 1)
            ]
            run_of_pn = And(positives, negatives, formulas)
            return run_of_pn

        # .....................................................................................
        # here starts __createCentroids function
        centroidsFormulas = []
        for j in range(0, len(self.__traces)):
            centroidOfJ = is_run_centroid(
                j, self.__size_of_run, m0, mf,
                self.__vars.getFunction(BOOLEAN_VAR_CHI_MARKINGS),
                self.__vars.getFunction(BOOLEAN_VAR_CHI_TRANSITIONS),
                self.__vars.getFunction(BOOLEAN_VAR_K_CONTAINS_T),
                self.__vars.getFunction(BOOLEAN_VAR_J_IN_K),
                self.__nb_clusters, self.__transitions, self.__places)
            centroidIfClusterised = Or(
                [], [self.__vars.get(BOOLEAN_VAR_J_CLUSTERISED, [j])],
                [centroidOfJ])
            centroidsFormulas.append(centroidIfClusterised)
        return centroidsFormulas