Ejemplo n.º 1
0
def _apply_base_case(log, root, act_key):
    if len(log) == 0:
        operator = pt.ProcessTree(parent=root)
        return operator
    else:
        operator = pt.ProcessTree(parent=root, label=log[0][0][act_key])
        return operator
Ejemplo n.º 2
0
def _flower(alphabet, root):
    operator = pt.ProcessTree(operator=pt.Operator.LOOP, parent=root)
    operator.children.append(pt.ProcessTree(parent=operator))
    xor = pt.ProcessTree(operator=pt.Operator.XOR)
    operator.children.append(xor)
    for a in alphabet:
        xor.children.append(pt.ProcessTree(label=a, parent=xor))
    return operator
Ejemplo n.º 3
0
 def create_process_tree(self):
     self.tree = process_tree.ProcessTree()
     self.set_activity_labels = [item for item in self.alphabet]
     while (self.total_activities + 2 > len(self.set_activity_labels)):
         self.set_activity_labels.append("τ")
     step = 1
     activity = self.assign_root_opeartor()
     step += 1
     while (self.total_activities > 0):
         activity = self.add_node(activity)
         step += 1
Ejemplo n.º 4
0
    def create_process_tree(self):
        self.tree = process_tree.ProcessTree()
        self.set_activity_labels = []
        p = 1
        # create labels
        while (self.total_activities > len(self.set_activity_labels)):
            # pairwise product
            l = itertools.product(self.alphabet, repeat=p)
            for item in l:
                label = ""
                for element in item:
                    label += str(element)
                self.set_activity_labels.append(label)
            p += 1
        step = 1
        activity = self.assign_root_opeartor()
        step += 1

        while (self.total_activities > 0):
            activity = self.add_node(activity)
            step += 1
Ejemplo n.º 5
0
def _add_operator_recursive(operator, threshold, act_key, logs, use_msd):
    if operator.operator != pt.Operator.LOOP:
        for log in logs:
            operator.children.append(
                inductive_miner(
                    log,
                    discover_dfg.apply(
                        log,
                        parameters={
                            constants.PARAMETER_CONSTANT_ACTIVITY_KEY: act_key
                        }), threshold, operator, act_key, use_msd))
    else:
        operator.children.append(
            inductive_miner(
                logs[0],
                discover_dfg.apply(
                    logs[0],
                    parameters={
                        constants.PARAMETER_CONSTANT_ACTIVITY_KEY: act_key
                    }), threshold, operator, act_key, use_msd))
        logs = logs[1:]
        if len(logs) == 1:
            operator.children.append(
                inductive_miner(
                    logs[0],
                    discover_dfg.apply(
                        logs[0],
                        parameters={
                            constants.PARAMETER_CONSTANT_ACTIVITY_KEY: act_key
                        }), threshold, operator, act_key, use_msd))
        else:
            operator.children.append(
                _add_operator_recursive(
                    pt.ProcessTree(operator=pt.Operator.XOR, parent=operator),
                    threshold, act_key, logs, use_msd))
    return operator
Ejemplo n.º 6
0
    def add_node(self, next_activity):
        """
        Add nodes to current tree. The general procedure is as follows:
        Select a random leaf (leaves have label). Next step, and opertor is chosen.
        The chosen operator then replaces the leaf, whereby the old label is then add as a leaf to the manipulated node.
        Then, next activity is added as a second leaf to the new operator node or a silent acticity (tau) is added.
        :return: Next activity
        """
        # Need to select random node that is not a silent activity
        leaf_silent = True
        while (leaf_silent):
            leaf = random.choice(self.tree._get_leaves())
            if leaf.label is not None:
                leaf_silent = False
        operator_nok = True
        while (operator_nok):
            operator = self.select_operator()
            if self.total_activities > 1:
                operator_nok = False
            else:
                if operator != "loop":
                    operator_nok = False
        activity = leaf._get_label()
        leaf._set_label(None)
        leaf._set_operator(assign_operator(operator))
        # Will be an tau added?
        silent_activity = False
        if random.random() < self.parameters["silent"]:
            silent_activity = True
        # add two children
        if operator == "loop":
            leaf._set_operator(pt_operator.Operator.SEQUENCE)
            root_loop = process_tree.ProcessTree(pt_operator.Operator.LOOP)
            root_loop.parent = leaf
            leaf._children.append(root_loop)
            new_node = process_tree.ProcessTree(label=activity)
            new_node.parent = root_loop
            root_loop._children.append(new_node)
            activity = next_activity
            if silent_activity:
                new_node = process_tree.ProcessTree(label=None)
                new_node.parent = root_loop
                root_loop._children.append(new_node)
            else:
                new_node = process_tree.ProcessTree(label=activity)
                new_node.parent = root_loop
                root_loop._children.append(new_node)
                activity = self.get_next_activity(activity)
            new_node = process_tree.ProcessTree(label=activity)
            new_node.parent = leaf
            leaf._children.append(new_node)
            self.total_activities -= 1
        else:
            if silent_activity and operator == "choice":
                number = random.choice([0, 1])
                if number == 0:
                    new_node = process_tree.ProcessTree(label=None)
                    new_node.parent = leaf
                    leaf._children.append(new_node)
                    new_node = process_tree.ProcessTree(label=activity)
                    new_node.parent = leaf
                    leaf._children.append(new_node)
                else:
                    new_node = process_tree.ProcessTree(label=activity)
                    new_node.parent = leaf
                    leaf._children.append(new_node)
                    new_node = process_tree.ProcessTree(label=None)
                    new_node.parent = leaf
                    leaf._children.append(new_node)
            else:
                new_node = process_tree.ProcessTree(label=activity)
                new_node.parent = leaf
                leaf._children.append(new_node)
                activity = next_activity
                new_node = process_tree.ProcessTree(label=activity)
                new_node.parent = leaf
                leaf._children.append(new_node)

        self.total_activities -= 2
        if silent_activity and operator == "choice":
            return next_activity
        else:
            return self.get_next_activity(activity)
Ejemplo n.º 7
0
    def assign_root_opeartor(self):
        activity = "a"
        # is a silent activity chosen
        silent_activity = False
        if random.random() < self.parameters["silent"]:
            silent_activity = True
        root = self.tree._get_root()
        operator = self.select_operator()
        root.operator = assign_operator(operator)
        # if operator is loop, we use a special structure, otherwise 2
        if operator == "loop":
            root.operator = pt_operator.Operator.SEQUENCE
            root_loop = process_tree.ProcessTree(
                operator=pt_operator.Operator.LOOP)
            root_loop.parent = root
            root._children.append(root_loop)
            new_node = process_tree.ProcessTree(label=activity)
            new_node.parent = root_loop
            root_loop._children.append(new_node)
            activity = self.get_next_activity(activity)
            if silent_activity:
                new_node = process_tree.ProcessTree(label=None)
                new_node.parent = root_loop
                root_loop._children.append(new_node)

            else:
                new_node = process_tree.ProcessTree(label=activity)
                new_node.parent = root_loop
                root_loop._children.append(new_node)
                activity = self.get_next_activity(activity)
            new_node = process_tree.ProcessTree(label=activity)
            new_node.parent = root
            root._children.append(new_node)
            self.total_activities -= 1
        else:
            if silent_activity and operator == "choice":
                number = random.choice([0, 1])
                if number == 0:
                    new_node = process_tree.ProcessTree(label=None)
                    new_node.parent = root
                    root._children.append(new_node)
                    new_node = process_tree.ProcessTree(label=activity)
                    new_node.parent = root
                    root._children.append(new_node)
                else:
                    new_node = process_tree.ProcessTree(label=activity)
                    new_node.parent = root
                    root._children.append(new_node)
                    new_node = process_tree.ProcessTree(label=None)
                    new_node.parent = root
                    root._children.append(new_node)
            else:
                new_node = process_tree.ProcessTree(label=activity)
                new_node.parent = root
                root._children.append(new_node)
                activity = self.get_next_activity(activity)
                new_node = process_tree.ProcessTree(label=activity)
                new_node.parent = root
                root._children.append(new_node)
        # always two children are added
        self.total_activities -= 2
        return self.get_next_activity(activity)
Ejemplo n.º 8
0
def parse_recursive(string_rep, depth_cache, depth):
    """
    Parse a string provided by the user to a process tree
    (recursive method)

    Parameters
    ------------
    string_rep
        String representation of the process tree
    depth_cache
        Depth cache of the algorithm
    depth
        Current step depth

    Returns
    -----------
    node
        Process tree object
    """
    string_rep = string_rep.strip()
    node = None
    operator = None
    if string_rep.startswith(pt_op.Operator.LOOP.value):
        operator = pt_op.Operator.LOOP
        string_rep = string_rep[len(pt_op.Operator.LOOP.value):]
    elif string_rep.startswith(pt_op.Operator.PARALLEL.value):
        operator = pt_op.Operator.PARALLEL
        string_rep = string_rep[len(pt_op.Operator.PARALLEL.value):]
    elif string_rep.startswith(pt_op.Operator.XOR.value):
        operator = pt_op.Operator.XOR
        string_rep = string_rep[len(pt_op.Operator.XOR.value):]
    elif string_rep.startswith(pt_op.Operator.OR.value):
        operator = pt_op.Operator.OR
        string_rep = string_rep[len(pt_op.Operator.OR.value):]
    elif string_rep.startswith(pt_op.Operator.SEQUENCE.value):
        operator = pt_op.Operator.SEQUENCE
        string_rep = string_rep[len(pt_op.Operator.SEQUENCE.value):]
    if operator is not None:
        parent = None if depth == 0 else depth_cache[depth - 1]
        node = pt.ProcessTree(operator=operator, parent=parent)
        depth_cache[depth] = node
        if parent is not None:
            parent.children.append(node)
        depth += 1
        string_rep = string_rep.strip()
        assert (string_rep[0] == '(')
        parse_recursive(string_rep[1:], depth_cache, depth)
    else:
        label = None
        if string_rep.startswith('\''):
            string_rep = string_rep[1:]
            escape_ext = string_rep.find('\'')
            label = string_rep[0:escape_ext]
            string_rep = string_rep[escape_ext + 1:]
        else:
            assert (string_rep.startswith('tau') or string_rep.startswith('τ') or string_rep.startswith(u'\u03c4'))
            if string_rep.startswith('tau'):
                string_rep = string_rep[len('tau'):]
            elif string_rep.startswith('τ'):
                string_rep = string_rep[len('τ'):]
            elif string_rep.startswith(u'\u03c4'):
                string_rep = string_rep[len(u'\u03c4'):]
        parent = None if depth == 0 else depth_cache[depth - 1]
        node = pt.ProcessTree(operator=operator, parent=parent, label=label)
        if parent is not None:
            parent.children.append(node)

        while string_rep.strip().startswith(')'):
            depth -= 1
            string_rep = (string_rep.strip())[1:]
        if len(string_rep.strip()) > 0:
            parse_recursive((string_rep.strip())[1:], depth_cache, depth)
    return node
Ejemplo n.º 9
0
def inductive_miner(log, dfg, threshold, root, act_key, use_msd):
    alphabet = pm4py.get_attribute_values(log, act_key)
    start_activities = get_starters.get_start_activities(
        log, parameters={constants.PARAMETER_CONSTANT_ACTIVITY_KEY: act_key})
    end_activities = get_ends.get_end_activities(
        log, parameters={constants.PARAMETER_CONSTANT_ACTIVITY_KEY: act_key})
    empty_traces = pm4py.filter_log(lambda trace: len(trace) == 0, log)
    if len(empty_traces) == 0:
        if _is_base_case_act(log, act_key) or _is_base_case_silent(log):
            return _apply_base_case(log, root, act_key)
        pre, post = dfg_utils.get_transitive_relations(dfg, alphabet)
        cut = sequence_cut.detect(alphabet, pre, post)
        if cut is not None:
            return _add_operator_recursive(
                pt.ProcessTree(pt.Operator.SEQUENCE, root), threshold, act_key,
                sequence_cut.project(log, cut, act_key), use_msd)
        cut = xor_cut.detect(dfg, alphabet)
        if cut is not None:
            return _add_operator_recursive(
                pt.ProcessTree(pt.Operator.XOR, root), threshold, act_key,
                xor_cut.project(log, cut, act_key), use_msd)
        cut = concurrent_cut.detect(
            dfg,
            alphabet,
            start_activities,
            end_activities,
            msd=msdw_algo.derive_msd_witnesses(
                log,
                msd_algo.apply(log,
                               parameters={
                                   constants.PARAMETER_CONSTANT_ACTIVITY_KEY:
                                   act_key
                               }),
                parameters={
                    constants.PARAMETER_CONSTANT_ACTIVITY_KEY: act_key
                }) if use_msd else None)
        if cut is not None:
            return _add_operator_recursive(
                pt.ProcessTree(pt.Operator.PARALLEL, root), threshold, act_key,
                concurrent_cut.project(log, cut, act_key), use_msd)
        cut = loop_cut.detect(dfg, alphabet, start_activities, end_activities)
        if cut is not None:
            return _add_operator_recursive(
                pt.ProcessTree(pt.Operator.LOOP, root), threshold, act_key,
                loop_cut.project(log, cut, act_key), use_msd)
    if len(empty_traces) > 0:
        nempty = pm4py.filter_log(lambda t: len(t) > 0, log)
        return _add_operator_recursive(pt.ProcessTree(pt.Operator.XOR,
                                                      root), threshold,
                                       act_key, [EventLog(), nempty], use_msd)
    aopt = activity_once_per_trace.detect(log, alphabet, act_key)
    if aopt is not None:
        operator = pt.ProcessTree(operator=pt.Operator.PARALLEL, parent=root)
        operator.children.append(
            pt.ProcessTree(operator=None, parent=operator, label=aopt))
        return _add_operator_recursive(
            operator, threshold, act_key,
            activity_once_per_trace.project(log, aopt, act_key), use_msd)
    act_conc = activity_concurrent.detect(log, alphabet, act_key, use_msd)
    if act_conc is not None:
        return _add_operator_recursive(
            pt.ProcessTree(pt.Operator.PARALLEL, root), threshold, act_key,
            activity_concurrent.project(log, act_conc, act_key), use_msd)
    stl = strict_tau_loop.detect(log, start_activities, end_activities,
                                 act_key)
    if stl is not None:
        return _add_operator_recursive(pt.ProcessTree(pt.Operator.LOOP,
                                                      root), threshold,
                                       act_key, [stl, EventLog()], use_msd)
    tl = tau_loop.detect(log, start_activities, act_key)
    if tl is not None:
        return _add_operator_recursive(pt.ProcessTree(pt.Operator.LOOP,
                                                      root), threshold,
                                       act_key, [tl, EventLog()], use_msd)
    return _flower(alphabet, root)