Example #1
0
 def __call__(self, activities_to_keep) -> EventLog:
     f = EventLog()
     for e in self.log:
         if e.get_activity_name() in activities_to_keep:
             f.add_event(e)
     self.log = f
     return self.log
Example #2
0
	def test_prepare_log(self):

		lg = EventLog()

		lg.add_trace(1, ['a', 'b', 'g', 'h', 'i', 'j', 'k'])
		lg.add_trace(2, ['a', 'b', 'g', 'h', 'j', 'i', 'k'])
		lg.add_trace(3, ['a', 'b', 'g', 'h', 'i', 'k'])
		lg.add_trace(4, ['a', 'b', 'g', 'h', 'j', 'k'])
		lg.add_trace(5, ['a', 'b', 'c', 'd', 'e', 'h', 'i', 'k'])
		lg.add_trace(6, ['a', 'b', 'c', 'd', 'e', 'f', 'c', 'd',
						 'e', 'h', 'i', 'k'])

		miner = InductiveMiner(lg)

		result = [	['a', 'b', 'g', 'h', 'i', 'j', 'k'],
					['a', 'b', 'g', 'h', 'j', 'i', 'k'],
					['a', 'b', 'g', 'h', 'i', 'k'],
					['a', 'b', 'g', 'h', 'j', 'k'],
					['a', 'b', 'c', 'd', 'e', 'h', 'i', 'k'],
					['a', 'b', 'c', 'd', 'e', 'f', 'c', 'd', 'e', 'h', 'i', 'k']]

		result.sort()
		miner.log.sort()

		self.assertListEqual(miner.log, result)
Example #3
0
 def __call__(self, ending_activity) -> EventLog:
     f = EventLog()
     for t in self.log.get_traces():
         if t[-1].get_activity_name() is ending_activity:
             for e in t:
                 f.add_event(e)
     self.log = f
     return self.log
Example #4
0
 def __call__(self, first_activity, second_activity) -> EventLog:
     f = EventLog()
     for t in self.log.get_traces():
         contains_df = False
         for e1, e2 in zip(t[:-1], t[1:]):
             if e1.get_activity_name(
             ) is first_activity and e2.get_activity_name(
             ) is second_activity:
                 contains_df = True
                 break
         if contains_df:
             for e in t:
                 f.add_event(e)
     self.log = f
     return self.log
Example #5
0
	def test_simple_example(self):
		lg = EventLog()

		lg.add_trace(1, ['a', 'b', 'g', 'h', 'i', 'j', 'k'])
		lg.add_trace(2, ['a', 'b', 'g', 'h', 'j', 'i', 'k'])
		lg.add_trace(3, ['a', 'b', 'g', 'h', 'i', 'k'])
		lg.add_trace(4, ['a', 'b', 'g', 'h', 'j', 'k'])
		lg.add_trace(5, ['a', 'b', 'c', 'd', 'e', 'h', 'i', 'k'])
		lg.add_trace(6, ['a', 'b', 'c', 'd', 'e', 'f', 'c', 'd',
						 'e', 'h', 'i', 'k'])

		miner = InductiveMiner(lg)
		tree = miner.discover()

		tree.print_tree()
		dot.draw_process_tree(tree, format='pdf')
Example #6
0
    def test_find_loop(self):
        log = [['d', 'e'], ['d', 'e', 'f', 'g', 'd', 'e']]

        tree = ProcessTree(InductiveMiner(EventLog()), log, discover=False)

        split = tree.find_loop()
        list(map(lambda sub: sub.sort(), split))
        print(split)
        self.assertListEqual(split, [['d', 'e'], ['f', 'g']])
Example #7
0
    def test_find_seq(self):
        log = [['a', 'x', 'b', 'c'], ['a', 'x', 'c', 'b'],
               ['a', 'x', 'd', 'e'], ['a', 'x', 'd', 'e', 'f', 'd', 'e']]

        tree = ProcessTree(InductiveMiner(EventLog()), log, discover=False)

        split = tree.find_seq()
        self.assertListEqual(split, [['a', 'x']])
        self.fail()
Example #8
0
	def test_tree_to_net(self):
		lg = EventLog()

		lg.add_trace(1, ['a', 'b', 'g', 'h', 'i', 'j', 'k'])
		lg.add_trace(2, ['a', 'b', 'g', 'h', 'j', 'i', 'k'])
		lg.add_trace(3, ['a', 'b', 'g', 'h', 'i', 'k'])
		lg.add_trace(4, ['a', 'b', 'g', 'h', 'j', 'k'])
		lg.add_trace(5, ['a', 'b', 'c', 'd', 'e', 'h', 'i', 'k'])
		lg.add_trace(6, ['a', 'b', 'c', 'd', 'e', 'f', 'c', 'd',
						 'e', 'h', 'i', 'k'])

		miner = InductiveMiner(lg)
		tree = miner.discover()

		tree.print_tree()
		# dot.draw_process_tree(tree, format='pdf')

		net = miner.tree_to_petri_net(tree)
		dot.draw_petri_net(net, 'process_tree_to_net')
Example #9
0
	def test_split_loop_cut(self):
		log = [['d', 'e', 'f', 'g', 'd', 'e'],
			   ['d', 'e']]

		miner = InductiveMiner(EventLog())

		ll, lr = miner.split_log([['d', 'e'], ['f', 'g']], Cut.LOOP, log)

		self.assertListEqual(ll, [['d', 'e']])
		self.assertListEqual(lr, [['f', 'g'], []])
Example #10
0
	def test_split_para_cut(self):
		log = [['a', 'b'],
			   ['b', 'a'],
			   ['a']]

		miner = InductiveMiner(EventLog())

		ll, lr = miner.split_log([['a'], ['b']], Cut.PARA, log)

		self.assertListEqual(ll, [['a']])
		self.assertListEqual(lr, [['b'], []])
Example #11
0
	def test_split_max_seq_cut(self):
		log = [['a', 'x', 'b', 'c'],
			   ['a', 'x', 'c', 'b'],
			   ['a', 'd', 'e'],
			   ['a', 'x', 'd', 'e', 'f', 'd', 'e']]

		miner = InductiveMiner(EventLog())

		max_seq_split = [['a'], ['x'], [['b', 'c'], ['d', 'e', 'f']]]

		logs = miner.split_log(max_seq_split, Cut.SEQ, log)
		print(logs)
Example #12
0
	def test_split_excl_cut(self):
		log = [['a', 'b'],
			   ['d', 'e', 'f', 'd','e'],
			   ['d', 'e']]

		miner = InductiveMiner(EventLog())

		ll, lr = miner.split_log([['a', 'b'], ['d', 'e', 'f']], Cut.EXCL, log)

		self.assertListEqual(ll, [['a', 'b']])
		self.assertListEqual(lr, [['d', 'e', 'f', 'd','e'],
								  ['d', 'e']])
Example #13
0
    def prepare_log(self, event_log: EventLog) -> list:
        """
		Convert EventLog into simple list structure.
		:param event_log: EventLog
		:return: list
		"""

        log = []
        for trace in event_log.get_traces():
            red_trace = []
            [red_trace.append(event['activity_name']) for event in trace]
            log.append(red_trace)
        return log
Example #14
0
    def test_find_para(self):
        log = [['a', 'b'], ['a', 'b'], ['b', 'a']]

        # log = [['supervisor signature',  # i
        # 		'sign application'],  # j
        # 		['sign application',  # j
        # 		'supervisor signature']]  # i

        tree = ProcessTree(InductiveMiner(EventLog()), log, discover=False)

        split = tree.find_para()
        split.sort()
        print(split)
        self.assertListEqual(split, [['a'], ['b']])
Example #15
0
    def test_find__max_seq(self):
        log = [['a', 'x', 'b', 'c'], ['a', 'x', 'c', 'b'],
               ['a', 'x', 'd', 'e'], ['a', 'x', 'd', 'e', 'f', 'd', 'e']]

        tree = ProcessTree(InductiveMiner(EventLog()), log, discover=False)

        split = tree.find_seq()
        list(map(lambda sub: sub.sort(), split))
        for ele in split:
            for sub in ele:
                if isinstance(sub, list):
                    sub.sort()
        # split.sort()
        self.assertListEqual(split,
                             [['a'], ['x'], [['b', 'c'], ['d', 'e', 'f']]])
Example #16
0
    def test_find_cuts(self):
        log4 = [['a', 'b', 'g', 'h', 'i', 'j', 'k'],
                ['a', 'b', 'g', 'h', 'j', 'i', 'k'],
                ['a', 'b', 'g', 'h', 'i', 'k'], ['a', 'b', 'g', 'h', 'j', 'k'],
                ['a', 'b', 'c', 'd', 'e', 'h', 'i', 'k'],
                ['a', 'b', 'c', 'd', 'e', 'f', 'c', 'd', 'e', 'h', 'i', 'k']]

        log2 = [['a', 'b', 'c'], ['a', 'c', 'b'], ['a', 'd', 'e'],
                ['a', 'd', 'e', 'f', 'd', 'e']]

        miner = InductiveMiner(EventLog())
        tree = ProcessTree(miner, log2)
        print()
        tree.print_tree()

        dot.draw_process_tree(tree)
Example #17
0
 def __call__(self, name: str, value) -> EventLog:
     f = EventLog()
     for e in self.log:
         if isinstance(value, list):
             if e[name] in value:
                 f.add_event(e)
         else:
             if e[name] is value:
                 f.add_event(e)
     self.log = f
     return self.log
Example #18
0
	def test_loop_of_one(self):
		lg = EventLog()
		lg.add_trace(1, ['a', 'b', 'b', 'c'])
		lg.add_trace(2, ['a', 'c'])

		miner = InductiveMiner(lg)
		tree = miner.discover()

		print()
		tree.print_tree()
		dot.draw_process_tree(tree, 'single_loop', format='pdf')
Example #19
0
	def test_split_seq_cut(self):
		log = [['a', 'x', 'b', 'c'],
			   ['a', 'x', 'c', 'b'],
			   ['a', 'x', 'd', 'e'],
			   ['d', 'e'],
			   ['a', 'x', 'd', 'e', 'f', 'd', 'e']]

		lg = EventLog()

		miner = InductiveMiner(lg)

		ll, lr = miner.split_log([['a', 'x'], ['b', 'c', 'd', 'e', 'f']],
								 Cut.SEQ,
								log)


		self.assertListEqual(ll, [['a', 'x'], []])
		self.assertListEqual(lr, [['b', 'c'], ['c', 'b'], ['d', 'e'],
								  ['d', 'e', 'f', 'd', 'e']])
Example #20
0
def __parse_xes_file(context, tree):

    log = None
    trace_idx = None
    event = None
    trace_count = 0  #for trace_id

    for action, elem in tqdm(context):

        if action == __START:  # starting to read

            parent = tree[
                elem.getparent()] if elem.getparent() in tree else None

            if elem.tag.endswith(c.STR):
                if parent is not None:
                    tree = __parse_attribute(elem, parent, elem.get(c.KEY),
                                             elem.get(c.VAL), tree)
                continue

            elif elem.tag.endswith(c.DTE):
                try:
                    date = __parse_date_ciso(elem.get(c.VAL))
                    tree = __parse_attribute(elem, parent, elem.get(c.KEY),
                                             date, tree)
                except TypeError:
                    logging.info("failed to parse date: " +
                                 str(elem.get(c.VAL)))
                except ValueError:
                    logging.info("failed to parse date: " +
                                 str(elem.get(c.VAL)))
                continue

            elif elem.tag.endswith(c.BOL):
                if parent is not None:
                    str_val = str(elem.get(c.VAL)).lower()
                    if str_val == 'true':
                        bool_val = True
                    elif str_val == 'false':
                        bool_val = False
                    else:
                        raise ValueError("failed to parse bool: " +
                                         str(elem.get(c.VAL)))
                    tree = __parse_attribute(elem, parent, elem.get(c.KEY),
                                             bool_val, tree)
                continue

            elif elem.tag.endswith(c.INT):
                if parent is not None:
                    int_val = int(elem.get(c.VAL))
                    tree = __parse_attribute(elem, parent, elem.get(c.KEY),
                                             int_val, tree)
                continue

            elif elem.tag.endswith(c.FLT):
                if parent is not None:
                    float_val = float(elem.get(c.VAL))
                    tree = __parse_attribute(elem, parent, elem.get(c.KEY),
                                             float_val, tree)
                continue

            elif elem.tag.endswith(c.EVE):
                if event is not None:
                    raise SyntaxError(
                        'file contains <event> in another <event> tag')
                if trace_idx is None:
                    raise SyntaxError(
                        'file contains a <event> element outside of a <trace> element (trace_id is None)'
                    )
                event = Event()
                tree[elem] = event
                continue

            elif elem.tag.endswith(c.TRC):
                if trace_idx is not None:
                    raise SyntaxError(
                        'file contains <trace> in another <trace> tag')
                trace_idx = trace_count
                trace_count += 1
                log.add_trace(trace_idx)
                tree[elem] = log.traces[trace_idx]
                continue

            elif elem.tag.endswith(c.EXT):
                if log is None:
                    raise SyntaxError('extension found outside of <log> tag')
                if elem.get(c.NME) is not None and elem.get(
                        c.PRX) is not None and elem.get(c.URI) is not None:
                    log.extensions[elem.attrib[c.NME]] = {
                        c.PRX: elem.attrib[c.PRX],
                        c.URI: elem.attrib[c.URI]
                    }
                continue

            elif elem.tag.endswith(c.GLB):
                if log is None:
                    raise SyntaxError('global found outside of <log> tag')
                if elem.get(c.SCP) is not None:
                    log.globals[elem.attrib[c.SCP]] = {}
                    tree[elem] = log.globals[elem.get(c.SCP)]
                continue

            elif elem.tag.endswith(c.CLS):
                if log is None:
                    raise SyntaxError('classifier found outside of <log> tag')
                if elem.get(c.KYS) is not None:
                    name, attributes = elem.attrib[c.NME], elem.attrib[c.KYS]
                    # resolve special case; refactor with __parse_classifier
                    if "'" in attributes:
                        attributes = re.findall(r'\'(.*?)\'', attributes)
                    else:
                        attributes = attributes.split()
                    log.classifiers[name] = attributes
                continue

            elif elem.tag.endswith(c.LOG):
                if log is not None:
                    raise SyntaxError('file contains > 1 <log> tags')
                log = EventLog()
                tree[elem] = log.attributes
                continue

        elif action == __END:

            __clear_element(elem, tree)

            if elem.tag.endswith(c.EVE):
                if trace_idx is not None:
                    log.add_event(event, trace_idx)
                    event = None
                continue

            elif elem.tag.endswith(c.TRC):
                trace_idx = None
                continue

            elif elem.tag.endswith(c.LOG):
                continue

    return log
Example #21
0
	def test_extended_example(self):
		lg = EventLog()

		lg.add_trace(1, ['submit application',  # a
						 'review application',  # b
						 'fast forwarding',  # g
						 'final review',  # h
						 'supervisor signature',  # i
						 'sign application',  # j
						 'close application'])  # k
		lg.add_trace(2, ['submit application',  # a
						 'review application',  # b
						 'fast forwarding',  # c
						 'final review',  # h
						 'sign application',  # j
						 'supervisor signature',  # i
						 'close application'])  # k
		lg.add_trace(3, ['submit application',  # a
						 'review application',  # b
						 'fast forwarding',  # g
						 'final review',  # h
						 'supervisor signature',  # i
						 'close application'])  # k
		lg.add_trace(4, ['submit application',  # a
						 'review application',  # b
						 'fast forwarding',  # g
						 'final review',  # h
						 'sign application',  # j
						 'close application'])  # k
		lg.add_trace(5, ['submit application',  # a
						 'review application',  # b
						 'check documents',  # c
						 'check financial status',  # d
						 'write report',  # e
						 'final review',  # h
						 'supervisor signature',  # i
						 'close application'])  # k
		lg.add_trace(6, ['submit application',  # a
						 'review application',  # b
						 'check documents',  # c
						 'check financial status',  # d
						 'write report',  # e
						 'reject report',  # f
						 'check documents',  # c
						 'check financial status',  # d
						 'write report',  # e
						 'final review',  # h
						 'supervisor signature',  # i
						 'close application'])  # k

		miner = InductiveMiner(lg)
		tree = miner.discover()

		g = Graph()
		g = g.from_log(miner.log)
		d = dot.draw_graph(g)
		dot.render_dot(d, 'dfg_process_tree')

		tree.print_tree()
		dot.draw_process_tree(tree, 'example', format='pdf')