def test_scope_expand3(self):
        tree1 = pt_utils.parse("X( a, ->(b, c))")
        tree2 = pt_utils.parse("X( a, +(b, c))")
        # log = create_event_log("ebf")
        pt_number.apply(tree1, 'D', 1)
        pt_number.apply(tree2, 'D', 1)
        align = [{'alignment': [(('t_e_0', '>>'), ('e', '>>')), (('>>', '1_s'), ('>>', '1_s')),
                                (('>>', '3_s'), ('>>', '3_s')), (('>>', '4_s'), ('>>', '4_s')),
                                (('t_b_1', 'b'), ('b', 'b')), (('>>', '4_e'), ('>>', '4_e')),
                                (('>>', '5_s'), ('>>', '5_s')), (('>>', 'c'), ('>>', 'c')),
                                (('>>', '5_e'), ('>>', '5_e')), (('>>', '3_e'), ('>>', '3_e')),
                                (('>>', '1_e'), ('>>', '1_e')), (('t_f_2', '>>'), ('f', '>>'))],
                  'cost': 12, 'visited_states': 22, 'queued_states': 27, 'traversed_arcs': 27,
                  'fitness': 0.2941176470588235}]

        s_align = se_rd_lock.apply_with_lock(align, tree1, tree2)
        g_s_align = se_rd_lock_general.apply(align, tree1, tree2, self.parameters)
        e_s_align = [{'alignment': [(('>>', '1_s'), ('>>', '1_s')), (('>>', '3_s'), ('>>', '3_s')),
                                    (('t_e_0', '>>'), ('e', '>>')), (('>>', '4_s'), ('>>', '4_s')),
                                    (('t_b_1', 'b'), ('b', 'b')), (('>>', '4_e'), ('>>', '4_e')),
                                    (('>>', '5_s'), ('>>', '5_s')), (('>>', 'c'), ('>>', 'c')),
                                    (('>>', '5_e'), ('>>', '5_e')), (('t_f_2', '>>'), ('f', '>>')),
                                    (('>>', '3_e'), ('>>', '3_e')), (('>>', '1_e'), ('>>', '1_e'))],
                      'cost': 12, 'visited_states': 22, 'queued_states': 27,
                      'traversed_arcs': 27, 'fitness': 0.2941176470588235}]

        self.assertEqual(str(s_align), str(e_s_align))
        self.assertEqual(str(g_s_align), str(e_s_align))
 def test_align_repair4(self):
     tree1 = pt_utils.parse("->( a, +(b, c)) ")
     tree2 = pt_utils.parse("->( a, X(b, c))")
     pt_number.apply(tree1, 'D', 1)
     pt_number.apply(tree2, 'D', 1)
     log = utils.create_event_log("abdc")
     alignments = [{'alignment': [(('>>', '1_s'), ('>>', '1_s')), (('>>', '2_s'), ('>>', '2_s')),
                                  (('t_a_0', 'a'), ('a', 'a')), (('>>', '2_e'), ('>>', '2_e')),
                                  (('>>', '3_s'), ('>>', '3_s')), (('>>', '3_tau_1'), ('>>', None)),
                                  (('>>', '4_s'), ('>>', '4_s')), (('>>', '5_s'), ('>>', '5_s')),
                                  (('t_b_1', 'b'), ('b', 'b')), (('t_d_2', '>>'), ('d', '>>')),
                                  (('t_c_3', 'c'), ('c', 'c')), (('>>', '4_e'), ('>>', '4_e')),
                                  (('>>', '5_e'), ('>>', '5_e')), (('>>', '3_tau_2'), ('>>', None)),
                                  (('>>', '3_e'), ('>>', '3_e')), (('>>', '1_e'), ('>>', '1_e'))],
                    'cost': 5, 'visited_states': 18, 'queued_states': 37, 'traversed_arcs': 38,
                    'fitness': 0.8076923076923077}]
     a_repair = ar_lock.apply(tree1, tree2, log, alignments, self.parameters)
     exp_a_repair = [{'alignment': [],
                      'cost': 10, 'visited_states': 18, 'queued_states': 37, 'traversed_arcs': 38,
                      'fitness': 1 - 10 / (20 + 4)}]
     # l_alignments = [{'alignment': [('>>', '1_s'), ('>>', '2_s'), ('a', 'a'), ('>>', '2_e'), ('>>', None),
     #                                ('>>', '3_s'), ('>>', '4_s'), ('b', 'b'), ('>>', '4_e'), ('d', '>>'),
     #                                ('>>', '5_s'), ('c', 'c'), ('>>', '5_e'), ('>>', '3_e'), ('>>', None),
     #                                ('>>', '1_e')], 'cost': 5, 'visited_states': 7, 'queued_states': 14,
     #                  'traversed_arcs': 14, 'fitness': 0.8076923076923077}]
     # l_a_repair = repair_alignment.apply(tree1, tree2, log, l_alignments, self.parameters_tuple_false)
     # exp_l_a_repair = [{'alignment': [('>>', '1_s'), ('>>', '2_s'), ('a', 'a'), ('>>', '2_e'), ('>>', None),
     #                                  ('>>', '6_s'), ('>>', '8_s'), ('b', '>>'), ('d', '>>'), ('c', 'c'),
     #                                  ('>>', '8_e'), ('>>', '6_e'), ('>>', None), ('>>', '1_e')], 'cost': 10,
     #                    'visited_states': 6, 'queued_states': 6, 'traversed_arcs': 5,
     #                    'fitness': 0.5833333333333333}]
     for i in range(len(alignments)):
         self.assertEqual(a_repair[i]["cost"], exp_a_repair[i]["cost"])
         self.assertEqual(a_repair[i]["fitness"], exp_a_repair[i]["fitness"])
Пример #3
0
def compute_align_grade(num, version, option, file):
    mp_trees = pd.read_excel(m_tree_file, sheet_name=SHEET_NAME)
    # logs = pd.read_excel(log_file, sheet_name=SHEET_NAME)

    align_result = list()
    for i in mp_trees:
        # log_list = logs[i]['log'].tolist()
        log_list = pd.read_csv(PATH + '/0.2/log' + i + ".csv")['log'].tolist()
        tree_list = mp_trees[i]['tree'].tolist()
        mpt_list = mp_trees[i]['m_tree'].tolist()
        align_info = pd.DataFrame(columns=[
            "optimal time", "optimal cost", "repair align time",
            "repair align cost", "grade"
        ])
        for j, m_tree in enumerate(mpt_list):
            m_tree = pt_utils.parse(m_tree)
            tree = pt_utils.parse(tree_list[j])
            log = create_event_log(log_list[j // num])
            align_info.loc[len(align_info.index)] = apply_align_on_one_pt(
                tree, m_tree, log, version, option)
        align_result.append(align_info)
        return
    with pd.ExcelWriter(file) as writer:
        for i, align in enumerate(align_result):
            align.to_excel(writer, sheet_name=SHEET_NAME[i], index=False)
Пример #4
0
    def test_compare_diff_tree_option2(self):

        result = PTUtilsTest.compare_diff_tree(" +( ->( j, k ), a, b )",
                                               " +( a, ->( j, k ), b )", 2)
        self.assertTrue(result.value)

        result = PTUtilsTest.compare_diff_tree(" *( *( j, k , τ), a, b )",
                                               " *( a, ->( j, k ), b )", 2)
        self.assertFalse(result.value)
        self.assertEqual(str(result.subtree1), str(pt_utils.parse("*( *( j, k , τ), a, b )")))
        self.assertEqual(str(result.subtree2), str(pt_utils.parse("*( a, ->( j, k ), b )")))

        result = PTUtilsTest.compare_diff_tree(" +( *( j, k, τ ), a )",
                                               " +( a, ->( j, k ), b )", 2)
        self.assertFalse(result.value)
        self.assertEqual(str(result.subtree1), str(pt_utils.parse("+( *( j, k, τ ), a )")))
        self.assertEqual(str(result.subtree2), str(pt_utils.parse("+( a, ->( j, k ), b )")))

        result = PTUtilsTest.compare_diff_tree(" +( ->( j, k ), a, X(c, d) )",
                                               " +( a, ->( j, k ), b )", 2)
        self.assertFalse(result.value)
        self.assertEqual(str(result.subtree1), str(pt_utils.parse("+( ->( j, k ), a, X(c, d) )")))
        self.assertEqual(str(result.subtree2), str(pt_utils.parse("+( a, ->( j, k ), b )")))

        result = PTUtilsTest.compare_diff_tree("X( a, *( b, f, τ ), X( g, h ) ) ",
                                               "X( a, *( b, f, τ ), +( g, h ) ) ", 2)
        self.assertEqual(str(result.subtree1), str(pt_utils.parse("X( a, *( b, f, τ ), X( g, h ) )")))
        self.assertEqual(str(result.subtree2), str(pt_utils.parse("X( a, *( b, f, τ ), +( g, h ) )")))

        result = PTUtilsTest.compare_diff_tree("->( a, *( ->( *( b, +( c, d ) ), e ), f, τ )) ",
                                               "->( a, *( ->( *( b, X( c, d ) ), e ), f, τ )) ", 2)
        self.assertEqual(str(result.subtree1), str(pt_utils.parse("*( b, +( c, d ) )")))
        self.assertEqual(str(result.subtree2), str(pt_utils.parse("*( b, X( c, d ) )")))
def test_compute_cost_time(parameters):
    tree1 = pt_utils.parse("->( a, *( *( c, X( d, e ), τ ), b, τ ) )")
    tree2 = pt_utils.parse("->( a, *( *( τ, X( d, e ), τ ), b, τ ) )")
    log = create_event_log("chcb")

    result = compute_cost_and_time(tree1, tree2, log, parameters)
    print_tree_align_compare(result)
    def test_align_repair2(self):
        tree1 = pt_utils.parse("X( a, ->(b, c)) ")
        tree2 = pt_utils.parse("X( τ, ->(b, c))")
        pt_number.apply(tree1, 'D', 1)
        pt_number.apply(tree2, 'D', 1)
        log = utils.create_event_log("")
        alignments = [{'alignment': [(('>>', '1_s'), ('>>', '1_s')), (('>>', '2_s'), ('>>', '2_s')),
                                     (('>>', 'a'), ('>>', 'a')), (('>>', '2_e'), ('>>', '2_e')),
                                     (('>>', '1_e'), ('>>', '1_e'))],
                       'cost': 2, 'visited_states': 6, 'queued_states': 6, 'traversed_arcs': 6, 'fitness': 0.0}]
        a_repair = ar_lock.apply(tree1, tree2, log, alignments, self.parameters)
        exp_a_repair = [{'alignment': [(('>>', '6_s'), ('>>', '6_s')), (('>>', '7_s'), ('>>', '7_s')),
                                       (('t_a_0', 'a'), ('>>', None)), (('>>', '7_e'), ('>>', '7_e')),
                                       (('>>', '6_e'), ('>>', '6_e'))],
                         'cost': 0, 'visited_states': 9, 'queued_states': 13, 'traversed_arcs': 13,
                         'fitness': 1}]

        # l_alignments = [
        #     {'alignment': [('>>', '1_s'), ('>>', '2_s'), ('>>', 'a'), ('>>', '2_e'), ('>>', '1_e')], 'cost': 2,
        #      'visited_states': 2, 'queued_states': 2, 'traversed_arcs': 2, 'fitness': 0.0}]
        #
        # l_a_repair = repair_alignment.apply(tree1, tree2, log, l_alignments, self.parameters_tuple_false)
        # exp_l_a_repair = [
        #     {'alignment': [('>>', '6_s'), ('>>', '7_s'), ('>>', None), ('>>', '7_e'), ('>>', '6_e')], 'cost': 0,
        #      'visited_states': 2, 'queued_states': 2, 'traversed_arcs': 2, 'fitness': 1}]

        for i in range(len(alignments)):
            self.assertEqual(list(map(lambda x: x[1], a_repair[i]["alignment"])),
                             list(map(lambda x: x[1], exp_a_repair[i]["alignment"])))
            self.assertEqual(a_repair[i]["cost"], exp_a_repair[i]["cost"])
            self.assertEqual(a_repair[i]["fitness"], exp_a_repair[i]["fitness"])
    def test_scope_expand2(self):
        tree1 = pt_utils.parse("+( a, ->(b, c))")
        tree2 = pt_utils.parse("+( a, X(b, c))")
        # log = create_event_log("bac")
        pt_number.apply(tree1, 'D', 1)
        pt_number.apply(tree2, 'D', 1)
        align = [{'alignment': [(('>>', '1_s'), ('>>', '1_s')), (('>>', '1_tau_1'), ('>>', None)),
                                (('>>', '3_s'), ('>>', '3_s')), (('>>', '2_s'), ('>>', '2_s')),
                                (('>>', '4_s'), ('>>', '4_s')), (('t_b_0', 'b'), ('b', 'b')),
                                (('>>', '4_e'), ('>>', '4_e')), (('>>', '5_s'), ('>>', '5_s')),
                                (('t_a_1', 'a'), ('a', 'a')), (('t_c_2', 'c'), ('c', 'c')),
                                (('>>', '5_e'), ('>>', '5_e')), (('>>', '2_e'), ('>>', '2_e')),
                                (('>>', '3_e'), ('>>', '3_e')), (('>>', '1_tau_2'), ('>>', None)),
                                (('>>', '1_e'), ('>>', '1_e'))], 'cost': 0, 'visited_states': 24,
                  'queued_states': 57, 'traversed_arcs': 64, 'fitness': 1}]

        s_align = se_rd_lock.apply_with_lock(align, tree1, tree2)
        g_s_align = se_rd_lock_general.apply(align, tree1, tree2, self.parameters)
        e_s_align = [{'alignment': [(('>>', '1_s'), ('>>', '1_s')), (('>>', '3_s'), ('>>', '3_s')),
                                    (('>>', '1_tau_1'), ('>>', None)), (('>>', '2_s'), ('>>', '2_s')),
                                    (('>>', '4_s'), ('>>', '4_s')), (('t_b_0', 'b'), ('b', 'b')),
                                    (('>>', '4_e'), ('>>', '4_e')), (('>>', '5_s'), ('>>', '5_s')),
                                    (('t_a_1', 'a'), ('a', 'a')), (('t_c_2', 'c'), ('c', 'c')),
                                    (('>>', '5_e'), ('>>', '5_e')), (('>>', '2_e'), ('>>', '2_e')),
                                    (('>>', '1_tau_2'), ('>>', None)), (('>>', '3_e'), ('>>', '3_e')),
                                    (('>>', '1_e'), ('>>', '1_e'))], 'cost': 0, 'visited_states': 24,
                      'queued_states': 57, 'traversed_arcs': 64, 'fitness': 1}]

        self.assertEqual(str(s_align), str(e_s_align))
        self.assertEqual(str(g_s_align), str(e_s_align))
Пример #8
0
def operator_analyse():
    from repair_alignment.process_tree.operation import pt_compare
    from pm4py.objects.process_tree.pt_operator import Operator
    opt, labels = [0, 0, 0, 0], ["Xor", "Sequence", "Parallel", "Loop"]
    for i in [(11, 15), (16, 18), (19, 21), (22, 24)]:
        sn = str(i[0]) + "-" + str(i[1])
        data = pd.read_excel(PATH + "MProcessTree.xlsx", sheet_name=sn, header=0)
        grade = pd.read_excel(PATH + "iar.xlsx", sheet_name=sn, header=0)['grade'].tolist()
        trees = data['tree']
        m_trees = data['m_tree']
        for index in range(len(grade)):
            com_res = pt_compare.apply(pt_utils.parse(trees[index]), pt_utils.parse(m_trees[index]))
            if grade[index] != 1 and com_res.subtree1.parent is not None:
                if com_res.subtree1.parent.operator == Operator.XOR:
                    opt[0] += 1
                if com_res.subtree1.parent.operator == Operator.SEQUENCE:
                    opt[1] += 1
                if com_res.subtree1.parent.operator == Operator.PARALLEL:
                    opt[2] += 1
                if com_res.subtree1.parent.operator == Operator.LOOP:
                    opt[3] += 1
    df = pd.DataFrame({"Ratio of Operators": opt}, index=["Xor", "Sequence", "Parallel", "Loop"])
    df.plot.pie(subplots=True, colors=palette, figsize=(5, 5), autopct='%.0f%%')
    import matplotlib.pyplot as plt
    # explode = (0.1, 0)  # only "explode" the 2nd slice (i.e. 'Hogs')
    # plt.pie(opt, labels=labels, autopct='%1.01f%%', startangle=90, pattern="muted")
    plt.axis('equal')  # Equal aspect ratio ensures that pie is drawn as a circle.
    plt.show()
    plt.savefig(PATH + "../figure/ParentOperatorAnalyse.png", dpi=300)
Пример #9
0
    def test_pt_depth(self):
        tree = pt_utils.parse("a")
        self.assertEqual(1, pt_mani_utils.pt_depth(tree))

        tree = pt_utils.parse("X(a, b)")
        self.assertEqual(2, pt_mani_utils.pt_depth(tree))

        tree = pt_utils.parse("X(a, ->(b, c), d)")
        self.assertEqual(3, pt_mani_utils.pt_depth(tree))

        tree = pt_utils.parse("X(a, ->(b, c, +(e, f)), *(d, X(g, h), τ))")
        self.assertEqual(4, pt_mani_utils.pt_depth(tree))
Пример #10
0
 def test_range4(self):
     tree = pt_utils.parse("+( ->( + (a, b), X(c, d)), e")
     pt_number.apply(tree, 'D', 1)
     alignments = [{
         'alignment': [('>>', None), ('>>', None), ('>>', 'b'), ('a', 'a'),
                       ('f', '>>'), ('e', 'e'), ('>>', None), ('d', 'd'),
                       ('>>', None), ('g', '>>')],
         'cost':
         12,
         'visited_states':
         12,
         'queued_states':
         27,
         'traversed_arcs':
         28,
         'fitness':
         0.6363636363636364
     }]
     ranges = to_lock_align.compute_lock_range(tree, alignments, [])
     expect_ranges = [{
         1: [[0, 9]],
         2: [[2, 7]],
         3: [[2, 3]],
         4: [[3, 3]],
         5: [[2, 2]],
         6: [[7, 7]],
         8: [[7, 7]],
         9: [[5, 5]]
     }]
     self.assertEqual(str(expect_ranges), str(ranges))
Пример #11
0
def apply(net, im, fm, parameters=None):
    """
    Transforms a WF-net to a process tree

    Parameters
    -------------
    net
        Petri net
    im
        Initial marking
    fm
        Final marking

    Returns
    -------------
    tree
        Process tree
    """
    if parameters is None:
        parameters = {}

    debug = exec_utils.get_param_value(Parameters.DEBUG, parameters, False)
    fold = exec_utils.get_param_value(Parameters.FOLD, parameters, True)

    grouped_net = group_blocks_in_net(net, parameters=parameters)

    if len(grouped_net.transitions) == 1:
        pt_str = list(grouped_net.transitions)[0].label
        pt = pt_util.parse(pt_str)
        return pt_util.fold(pt) if fold else pt
    else:
        if debug:
            from pm4py.visualization.petrinet import visualizer as pn_viz
            pn_viz.view(pn_viz.apply(grouped_net, parameters={"format": "svg"}))
        raise ValueError('Parsing of WF-net Failed')
Пример #12
0
 def test_tree_parsing(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"
     tree = pt_util.parse("->(X('a', 'b', tau), +('c', 'd'))")
     # test log generation
     log = pt_semantics.generate_log(tree)
Пример #13
0
 def test_range2(self):
     tree = pt_utils.parse("*( a, b, τ)")
     pt_number.apply(tree, 'D', 1)
     alignments = [{
         'alignment': [('>>', None), ('>>', '2_s'), ('a', 'a'),
                       ('>>', '2_e'), ('>>', '3_s'), ('b', 'b'),
                       ('>>', '3_e'), ('>>', '2_s'), ('a', 'a'),
                       ('>>', '2_e'), ('>>', '3_s'), ('b', 'b'),
                       ('>>', '3_e'), ('>>', '2_s'), ('a', 'a'),
                       ('>>', '2_e'), ('>>', None)],
         'cost':
         0,
         'visited_states':
         20,
         'queued_states':
         42,
         'traversed_arcs':
         42,
         'fitness':
         1
     }]
     ranges = to_lock_align.compute_lock_range(tree, alignments, [])
     expect_ranges = [{
         1: [[0, 16]],
         2: [[1, 3], [7, 9], [13, 15]],
         3: [[4, 6], [10, 12]]
     }]
     self.assertEqual(str(expect_ranges), str(ranges))
Пример #14
0
def read_trees_from_file(file, sheet_index=0):
    col = 1 if sheet_index == 0 else 6
    data = excel_utils.open_excel(file)
    table = data.sheets()[sheet_index]
    return list(
        map(lambda t: pt_utils.parse(t[0]),
            excel_utils.read_table_columns(table, [col])))
Пример #15
0
    def test_scope_expand4(self):
        tree1 = pt_utils.parse("*( a, X(b, c), τ)")
        tree2 = pt_utils.parse("*( a, ->(b, c), τ)")
        # log = create_event_log("abeaf")
        pt_number.apply(tree1, 'D', 1)
        pt_number.apply(tree2, 'D', 1)
        align = [{'alignment': [(('>>', '1_s'), ('>>', '1_s')), (('>>', '2_s'), ('>>', '2_s')),
                                (('t_a_0', 'a'), ('a', 'a')), (('>>', '2_e'), ('>>', '2_e')),
                                (('>>', '3_s'), ('>>', '3_s')), (('>>', '4_s'), ('>>', '4_s')),
                                (('t_b_1', 'b'), ('b', 'b')), (('>>', '4_e'), ('>>', '4_e')),
                                (('>>', '3_e'), ('>>', '3_e')), (('>>', '2_s'), ('>>', '2_s')),
                                (('t_e_2', '>>'), ('e', '>>')), (('t_a_3', 'a'), ('a', 'a')),
                                (('>>', '2_e'), ('>>', '2_e')), (('>>', '6_s'), ('>>', '6_s')),
                                (('>>', '6_skip_1'), ('>>', None)), (('>>', '6_e'), ('>>', '6_e')),
                                (('>>', '1_e'), ('>>', '1_e')), (('t_f_4', '>>'), ('f', '>>'))],
                  'cost': 10, 'visited_states': 31, 'queued_states': 50, 'traversed_arcs': 50,
                  'fitness': 0.6296296296296297}]

        s_align = se_rd_lock.apply_with_lock(align, tree1, tree2)
        g_s_align = se_rd_lock_general.apply(align, tree1, tree2, self.parameters)
        e_s_align = [{'alignment': [(('>>', '1_s'), ('>>', '1_s')), (('>>', '2_s'), ('>>', '2_s')),
                                    (('t_a_0', 'a'), ('a', 'a')), (('>>', '2_e'), ('>>', '2_e')),
                                    (('>>', '3_s'), ('>>', '3_s')), (('>>', '4_s'), ('>>', '4_s')),
                                    (('t_b_1', 'b'), ('b', 'b')), (('>>', '4_e'), ('>>', '4_e')),
                                    (('t_e_2', '>>'), ('e', '>>')), (('>>', '3_e'), ('>>', '3_e')),
                                    (('>>', '2_s'), ('>>', '2_s')), (('t_a_3', 'a'), ('a', 'a')),
                                    (('>>', '2_e'), ('>>', '2_e')), (('>>', '6_s'), ('>>', '6_s')),
                                    (('>>', '6_skip_1'), ('>>', None)), (('>>', '6_e'), ('>>', '6_e')),
                                    (('>>', '1_e'), ('>>', '1_e')), (('t_f_4', '>>'), ('f', '>>'))],
                      'cost': 10, 'visited_states': 31, 'queued_states': 50, 'traversed_arcs': 50,
                      'fitness': 0.6296296296296297}]
        e_g_s_align = [{'alignment': [(('>>', '1_s'), ('>>', '1_s')), (('>>', '2_s'), ('>>', '2_s')),
                                      (('t_a_0', 'a'), ('a', 'a')), (('>>', '2_e'), ('>>', '2_e')),
                                      (('>>', '3_s'), ('>>', '3_s')), (('>>', '4_s'), ('>>', '4_s')),
                                      (('t_b_1', 'b'), ('b', 'b')), (('>>', '4_e'), ('>>', '4_e')),
                                      (('t_e_2', '>>'), ('e', '>>')), (('>>', '3_e'), ('>>', '3_e')),
                                      (('>>', '2_s'), ('>>', '2_s')), (('t_a_3', 'a'), ('a', 'a')),
                                      (('t_f_4', '>>'), ('f', '>>')), (('>>', '2_e'), ('>>', '2_e')),
                                      (('>>', '6_s'), ('>>', '6_s')),
                                      (('>>', '6_skip_1'), ('>>', None)), (('>>', '6_e'), ('>>', '6_e')),
                                      (('>>', '1_e'), ('>>', '1_e'))],
                        'cost': 10, 'visited_states': 31, 'queued_states': 50, 'traversed_arcs': 50,
                        'fitness': 0.6296296296296297}]
        self.assertEqual(str(s_align), str(e_s_align))
        self.assertEqual(str(g_s_align), str(e_g_s_align))
Пример #16
0
def compute_align_grade1(num):
    trees = pd.read_excel(tree_file, sheet_name=SHEET_NAME)
    mp_trees = pd.read_excel(m_tree_file, sheet_name=SHEET_NAME)
    # logs = pd.read_excel(log_file, sheet_name=SHEET_NAME)

    align_result = list()
    align_result2 = list()
    align_result3 = list()
    # align_result4 = list()
    for i in trees:
        itree_list = trees[i]['tree'].tolist()
        log_list = pd.read_csv(PATH + 'log' + i + ".csv")['log'].tolist()
        # log_list = logs[i]['log'].tolist()
        tree_list = mp_trees[i]['tree'].tolist()
        mpt_list = mp_trees[i]['m_tree'].tolist()

        align_info = pd.DataFrame(columns=[
            "optimal time", "optimal cost", "repair align time",
            "repair align cost", "grade"
        ])
        align_info2 = pd.DataFrame(columns=[
            "optimal time", "optimal cost", "repair align time",
            "repair align cost", "grade"
        ])
        align_info3 = pd.DataFrame(columns=[
            "optimal time", "optimal cost", "repair align time",
            "repair align cost", "grade"
        ])
        # align_info4 = pd.DataFrame(columns=["optimal time", "optimal cost", "best worst cost",
        #                                     "repair align time", "repair align cost", "grade"])
        for k, tree in enumerate(tree_list):
            log = create_event_log(log_list[k])
            alignments = alignment_on_pt(tree, log)
            for j in range(num):
                m_tree = pt_utils.parse(mpt_list[k * num + j])
                info = apply_align_on_one_pt2(tree, m_tree, log, alignments)
                align_info.loc[len(align_info.index)] = info[0]
                align_info2.loc[len(align_info.index)] = info[1]
                align_info3.loc[len(align_info.index)] = info[2]
            # align_info4.loc[len(align_info.index)] = info[3]
        align_result.append(align_info)
        align_result2.append(align_info2)
        align_result3.append(align_info3)
        # align_result4.append(align_info4)

    with pd.ExcelWriter(PATH + 'ar.xlsx') as writer:
        for i, align in enumerate(align_result):
            align.to_excel(writer, sheet_name=SHEET_NAME[i], index=False)

    with pd.ExcelWriter(PATH + 'iar.xlsx') as writer:
        for i, align in enumerate(align_result2):
            align.to_excel(writer, sheet_name=SHEET_NAME[i], index=False)

    with pd.ExcelWriter(PATH + 'iar_ud.xlsx') as writer:
        for i, align in enumerate(align_result3):
            align.to_excel(writer, sheet_name=SHEET_NAME[i], index=False)
Пример #17
0
    def test_align_repair1(self):
        tree1 = pt_utils.parse("+( a, X( g, h ) ) ")
        tree2 = pt_utils.parse("+( a, ->( g, h ) )")
        pt_number.apply(tree1, 'D', 1)
        pt_number.apply(tree2, 'D', 1)
        log = utils.create_event_log("gah")
        alignments = [{'alignment': [(('>>', '1_s'), ('>>', '1_s')), (('>>', '1_tau_1'), ('>>', None)),
                                     (('>>', '3_s'), ('>>', '3_s')), (('>>', '2_s'), ('>>', '2_s')),
                                     (('t_g_0', '>>'), ('g', '>>')),
                                     (('t_a_1', 'a'), ('a', 'a')), (('>>', '5_s'), ('>>', '5_s')),
                                     (('t_h_2', 'h'), ('h', 'h')),
                                     (('>>', '5_e'), ('>>', '5_e')), (('>>', '3_e'), ('>>', '3_e')),
                                     (('>>', '2_e'), ('>>', '2_e')),
                                     (('>>', '1_tau_2'), ('>>', None)), (('>>', '1_e'), ('>>', '1_e'))], 'cost': 5,
                       'visited_states': 18, 'queued_states': 35, 'traversed_arcs': 35, 'fitness': 0.736842105263158}]

        a_repair = ar_lock.apply(tree1, tree2, log, alignments, self.parameters)
        exp_a_repair = [{'alignment': [(('>>', '1_s'), ('>>', '1_s')), (('>>', '1_tau_1'), ('>>', None)),
                                       (('>>', '6_s'), ('>>', '6_s')), (('>>', '7_s'), ('>>', '7_s')),
                                       (('>>', '2_s'), ('>>', '2_s')),
                                       (('t_g_0', 'g'), ('g', 'g')), (('>>', '7_e'), ('>>', '7_e')),
                                       (('>>', '8_s'), ('>>', '8_s')),
                                       (('t_a_1', 'a'), ('a', 'a')), (('t_h_1', 'h'), ('h', 'h')),
                                       (('>>', '8_e'), ('>>', '8_e')),
                                       (('>>', '6_e'), ('>>', '6_e')), (('>>', '2_e'), ('>>', '2_e')),
                                       (('>>', '1_tau_2'), ('>>', None)), (('>>', '1_e'), ('>>', '1_e'))], 'cost': 0,
                         'fitness': 1.0}]

        # l_alignments = [{'alignment': [('>>', '1_s'), ('>>', None), ('>>', '3_s'), ('g', '>>'), ('>>', '2_s'),
        #                                ('a', 'a'), ('>>', '2_e'), ('>>', '5_s'), ('h', 'h'), ('>>', '5_e'),
        #                                ('>>', '3_e'), ('>>', None), ('>>', '1_e')], 'cost': 5, 'visited_states': 7,
        #                  'queued_states': 13, 'traversed_arcs': 15, 'fitness': 0.736842105263158}]
        # l_a_repair = repair_alignment.apply(tree1, tree2, log, l_alignments, self.parameters_tuple_false)
        # exp_l_a_repair = [{'alignment': [('>>', '1_s'), ('>>', None), ('>>', '6_s'), ('>>', '7_s'), ('g', 'g'),
        #                                  ('>>', '7_e'), ('>>', '8_s'), ('a', 'a'), ('h', 'h'), ('>>', '8_e'),
        #                                  ('>>', '6_e'), ('>>', None), ('>>', '1_e')], 'cost': 0, 'visited_states': 6,
        #                    'queued_states': 13, 'traversed_arcs': 15, 'fitness': 1}]

        for i in range(len(alignments)):
            self.assertEqual(list(map(lambda x: x[1], a_repair[i]["alignment"])),
                             list(map(lambda x: x[1], exp_a_repair[i]["alignment"])))
            self.assertEqual(a_repair[i]["cost"], exp_a_repair[i]["cost"])
            self.assertEqual(a_repair[i]["fitness"], exp_a_repair[i]["fitness"])
Пример #18
0
def compute_alignment1(version, option):
    # tree_num, mutated_num, log_num, non_fit_pro = 10, 5, 5, 0.2
    # node_num = [20, 25]
    # tree = [pt_create.apply(random.randint(node_num[0], node_num[1])) for _ in range(tree_num)]
    # m_tree = [[pt_mutate.apply(tree) for _ in range(mutated_num)] for tree in tree]
    # log = [log_create.apply(tree, log_num, non_fit_pro) for tree in tree]
    # for i in range(len(tree)):
    #     for j in range(len(m_tree[0])):
    #         optimal_time, optimal_cost, best_worst_cost, ra_time, ra_cost, grade = \
    #             align_info(tree[i], m_tree[i][j], log[i], apply, option)
    data = pd.read_excel(PATH + "MProcessTree.xlsx",
                         sheet_name='16-18',
                         header=0)
    log_d = pd.read_excel(PATH + "0.2/log.xlsx", sheet_name='16-18', header=0)
    trees = data['tree']
    m_trees = data['m_tree']
    logs = log_d['log']
    optimal_time, optimal_cost, best_worst_cost = list(), list(), list()
    ra_time, ra_cost, grade = list(), list(), list()
    for i in range(len(trees)):
        info = align_info(pt_utils.parse(trees[i]), pt_utils.parse(m_trees[i]),
                          create_event_log(logs[i // 15]), version, option)
        optimal_time.append(info[0])
        optimal_cost.append(info[1])
        best_worst_cost.append(info[2])
        ra_time.append(info[3])
        ra_cost.append(info[4])
        grade.append(info[5])
        if i > 200:
            repair_align_compare(pt_utils.parse(trees[i]),
                                 pt_utils.parse(m_trees[i]),
                                 create_event_log(logs[i // 15]))
    df = pd.DataFrame({
        "optimal time": optimal_time,
        "optimal cost": optimal_cost,
        "best worst cost": best_worst_cost,
        "repair align time": ra_time,
        "repair align cost": ra_cost,
        "grade": grade
    })
    df.to_csv(PATH + "align_repair_opt2.csv")
Пример #19
0
def create_logs(pts):
    logs_list = list()
    for trees in pts:
        logs = pd.DataFrame(columns=['log'])
        for i, s_tree in enumerate(trees['tree']):
            tree = pt_utils.parse(s_tree)
            logs.loc[i] = [
                parse_string_list(
                    log_create.apply(tree, trace_num, non_fit_pro))
            ]
        logs_list.append(logs)
    return logs_list
Пример #20
0
    def test_scope_expand1(self):
        tree1 = pt_utils.parse("->( a, *( X(c, b), d, τ), e)")
        tree2 = pt_utils.parse("->( a, *(->(c, b), d, τ), e)")
        # log = create_event_log("abdce")
        pt_number.apply(tree1, 'D', 1)
        pt_number.apply(tree2, 'D', 1)
        align = [{'alignment': [(('>>', '1_s'), ('>>', '1_s')), (('>>', '2_s'), ('>>', '2_s')),
                                (('t_a_0', 'a'), ('a', 'a')), (('>>', '2_e'), ('>>', '2_e')),
                                (('>>', '3_s'), ('>>', '3_s')), (('>>', '4_s'), ('>>', '4_s')),
                                (('>>', '6_s'), ('>>', '6_s')), (('t_b_1', 'b'), ('b', 'b')),
                                (('>>', '6_e'), ('>>', '6_e')), (('>>', '4_e'), ('>>', '4_e')),
                                (('>>', '7_s'), ('>>', '7_s')), (('t_d_2', 'd'), ('d', 'd')),
                                (('>>', '7_e'), ('>>', '7_e')), (('>>', '4_s'), ('>>', '4_s')),
                                (('>>', '5_s'), ('>>', '5_s')), (('t_c_3', 'c'), ('c', 'c')),
                                (('>>', '5_e'), ('>>', '5_e')), (('>>', '4_e'), ('>>', '4_e')),
                                (('>>', '8_s'), ('>>', '8_s')), (('>>', '8_skip_1'), ('>>', None)),
                                (('>>', '8_e'), ('>>', '8_e')), (('>>', '3_e'), ('>>', '3_e')),
                                (('>>', '9_s'), ('>>', '9_s')), (('t_e_4', 'e'), ('e', 'e')),
                                (('>>', '9_e'), ('>>', '9_e')), (('>>', '1_e'), ('>>', '1_e'))],
                  'cost': 0, 'visited_states': 33, 'queued_states': 71, 'traversed_arcs': 71, 'fitness': 1}]

        s_align = se_rd_lock.apply_with_lock(align, tree1, tree2)
        g_s_align = se_rd_lock_general.apply(align, tree1, tree2, self.parameters)
        e_s_align = [{'alignment': [(('>>', '1_s'), ('>>', '1_s')), (('>>', '2_s'), ('>>', '2_s')),
                                    (('t_a_0', 'a'), ('a', 'a')), (('>>', '2_e'), ('>>', '2_e')),
                                    (('>>', '3_s'), ('>>', '3_s')), (('>>', '4_s'), ('>>', '4_s')),
                                    (('>>', '6_s'), ('>>', '6_s')), (('t_b_1', 'b'), ('b', 'b')),
                                    (('>>', '6_e'), ('>>', '6_e')), (('>>', '4_e'), ('>>', '4_e')),
                                    (('>>', '7_s'), ('>>', '7_s')), (('t_d_2', 'd'), ('d', 'd')),
                                    (('>>', '7_e'), ('>>', '7_e')), (('>>', '4_s'), ('>>', '4_s')),
                                    (('>>', '5_s'), ('>>', '5_s')), (('t_c_3', 'c'), ('c', 'c')),
                                    (('>>', '5_e'), ('>>', '5_e')), (('>>', '4_e'), ('>>', '4_e')),
                                    (('>>', '8_s'), ('>>', '8_s')), (('>>', '8_skip_1'), ('>>', None)),
                                    (('>>', '8_e'), ('>>', '8_e')), (('>>', '3_e'), ('>>', '3_e')),
                                    (('>>', '9_s'), ('>>', '9_s')), (('t_e_4', 'e'), ('e', 'e')),
                                    (('>>', '9_e'), ('>>', '9_e')), (('>>', '1_e'), ('>>', '1_e'))],
                      'cost': 0, 'visited_states': 33, 'queued_states': 71, 'traversed_arcs': 71, 'fitness': 1}]

        self.assertEqual(str(s_align), str(e_s_align))
        self.assertEqual(str(g_s_align), str(e_s_align))
Пример #21
0
    def test_align_repair3(self):
        tree1 = pt_utils.parse("->( a, X(b, c)) ")
        tree2 = pt_utils.parse("->( a, X(b, τ))")
        pt_number.apply(tree1, 'D', 1)
        pt_number.apply(tree2, 'D', 1)
        log = utils.create_event_log("a")
        alignments = [{'alignment': [(('>>', '1_s'), ('>>', '1_s')), (('>>', '2_s'), ('>>', '2_s')),
                                     (('t_a_0', 'a'), ('a', 'a')), (('>>', '2_e'), ('>>', '2_e')),
                                     (('>>', '3_s'), ('>>', '3_s')), (('>>', '4_s'), ('>>', '4_s')),
                                     (('>>', 'b'), ('>>', 'b')), (('>>', '4_e'), ('>>', '4_e')),
                                     (('>>', '3_e'), ('>>', '3_e')), (('>>', '1_e'), ('>>', '1_e'))],
                       'cost': 2, 'visited_states': 11, 'queued_states': 15, 'traversed_arcs': 15,
                       'fitness': 0.7777777777777778}]

        a_repair = ar_lock.apply(tree1, tree2, log, alignments, self.parameters)
        exp_a_repair = [{'alignment': [(('>>', '1_s'), ('>>', '1_s')), (('>>', '2_s'), ('>>', '2_s')),
                                       (('t_a_0', 'a'), ('a', 'a')), (('>>', '2_e'), ('>>', '2_e')),
                                       (('>>', '6_s'), ('>>', '6_s')), (('>>', '8_s'), ('>>', '8_s')),
                                       (('>>', 'b'), ('>>', None)), (('>>', '8_e'), ('>>', '8_e')),
                                       (('>>', '6_e'), ('>>', '6_e')), (('>>', '1_e'), ('>>', '1_e'))],
                         'cost': 0, 'visited_states': 11, 'queued_states': 15, 'traversed_arcs': 15,
                         'fitness': 1}]

        # l_alignments = [{'alignment': [('>>', '1_s'), ('>>', '2_s'), ('a', 'a'), ('>>', '2_e'), ('>>', '3_s'),
        #                                ('>>', '5_s'), ('>>', 'c'), ('>>', '5_e'), ('>>', '3_e'), ('>>', '1_e')],
        #                  'cost': 2, 'visited_states': 3, 'queued_states': 4, 'traversed_arcs': 5,
        #                  'fitness': 0.7777777777777778}]
        #
        # l_a_repair = repair_alignment.apply(tree1, tree2, log, l_alignments, self.parameters_tuple_false)
        # exp_l_a_repair = [{'alignment': [('>>', '1_s'), ('>>', '2_s'), ('a', 'a'), ('>>', '2_e'), ('>>', '6_s'),
        #                                  ('>>', '8_s'), ('>>', None), ('>>', '8_e'), ('>>', '6_e'), ('>>', '1_e')],
        #                    'cost': 0, 'visited_states': 3, 'queued_states': 4, 'traversed_arcs': 5, 'fitness': 1}]

        for i in range(len(alignments)):
            self.assertEqual(list(map(lambda x: x[1], a_repair[i]["alignment"])),
                             list(map(lambda x: x[1], exp_a_repair[i]["alignment"])))
            self.assertEqual(a_repair[i]["cost"], exp_a_repair[i]["cost"])
            self.assertEqual(a_repair[i]["fitness"], exp_a_repair[i]["fitness"])
 def test_random_create_tree(self):
     for _ in range(100):
         tree1 = pt_create.apply(random.randint(10, 35))
         tree2 = pt_utils.parse(str(tree1))
         q1, q2 = list(), list()
         q1.append(tree1)
         q2.append(tree2)
         while len(q1) != 0:
             node1 = q1.pop(0)
             node2 = q2.pop(0)
             self.assertEqual(str(node1.parent), str(node2.parent))
             self.assertEqual(str(node1.children), str(node2.children))
             for i in range(len(node1.children)):
                 q1.append(node1.children[i])
                 q2.append(node2.children[i])
Пример #23
0
def create_m_pts(pts):
    m_pts = list()
    for trees in pts:
        m_trees = pd.DataFrame(columns=[
            'tree', '#node', 'depth', 'root-op', 'm_tree', 'sub_depth'
        ])
        for i, s_tree in enumerate(trees['tree']):
            tree = pt_utils.parse(s_tree)
            for depth in depths:
                for j in range(mpt_num):
                    m_tree = pt_mutate.apply(tree, depth)
                    m_trees.loc[len(m_trees.index)] = trees.loc[i].tolist() + [
                        str(m_tree), depth
                    ]
        m_pts.append(m_trees)
    return m_pts
Пример #24
0
def parse_process_tree(tree_string: str) -> ProcessTree:
    """
    Parse a process tree from a string

    Parameters
    ----------------
    tree_string
        String representing a process tree (e.g. '-> ( 'A', O ( 'B', 'C' ), 'D' )')
        Operators are '->': sequence, '+': parallel, 'X': xor choice, '*': binary loop, 'O' or choice

    Returns
    ----------------
    tree
        Process tree
    """
    from pm4py.objects.process_tree.util import parse
    return parse(tree_string)
def export_file(orig_tree, activity_set):
    """
    Export petri net to pnml file
    :param orig_tree: string of the tree from the main algorithm
    :param activity_set: set of all the activities
    :return: pnml file
    """
    string_tree = tree_for_eval(orig_tree, activity_set)
    tree = pt_util.parse(string_tree)
    net, initial_marking, final_marking = tree_to_petri.apply(tree)
    file_name = config.data_file[:config.data_file.find('.')] + '_' + str(
        config.silhouette_threshold) + '.pnml'
    output_file = os.path.join(config.base_directory, config.data_dir,
                               file_name)
    petri_exporter.export_net(net,
                              initial_marking,
                              output_file,
                              final_marking=final_marking)
Пример #26
0
 def test_range5(self):
     tree = pt_utils.parse("+( a, X(b, τ))")
     pt_number.apply(tree, 'D', 1)
     alignments = [{
         'alignment': [('>>', None), ('>>', '5_s'), ('a', 'a'),
                       ('>>', None), ('>>', '5_e'), ('>>', None)],
         'cost':
         0,
         'visited_states':
         8,
         'queued_states':
         15,
         'traversed_arcs':
         16,
         'fitness':
         1
     }]
     ranges = to_lock_align.compute_lock_range(tree, alignments, [])
     expect_ranges = [{1: [[0, 5]], 2: [[2, 2]], 3: [[1, 4]], 5: [[1, 4]]}]
     self.assertEqual(str(expect_ranges), str(ranges))
Пример #27
0
 def test_range1(self):
     tree = pt_utils.parse("->( a, b, c)")
     pt_number.apply(tree, 'D', 1)
     alignments = [{
         'alignment': [('a', 'a'), ('b', 'b'), ('d', '>>'), ('c', 'c'),
                       ('e', '>>')],
         'cost':
         10,
         'visited_states':
         6,
         'queued_states':
         11,
         'traversed_arcs':
         11,
         'fitness':
         0.6774193548387097
     }]
     ranges = to_lock_align.compute_lock_range(tree, alignments, [])
     expect_ranges = [{1: [[0, 4]], 2: [[0, 0]], 3: [[1, 1]], 4: [[3, 3]]}]
     self.assertEqual(str(expect_ranges), str(ranges))
Пример #28
0
 def test_range3(self):
     tree = pt_utils.parse("*( +( *(->( a, b), c, τ), d), X(e, f), τ)")
     pt_number.apply(tree, 'D', 1)
     alignments = [{
         'alignment': [('>>', None), ('>>', '2_s'), ('>>', None),
                       ('>>', '4_s'), ('a', 'a'), ('d', 'd'), ('b', 'b'),
                       ('>>', '4_e'), ('>>', '7_s'), ('c', 'c'),
                       ('>>', '7_e'), ('>>', '4_s'), ('a', 'a'), ('b', 'b'),
                       ('>>', '4_e'), ('>>', None), ('>>', None),
                       ('>>', '2_e'), ('>>', '10_s'), ('e', 'e'),
                       ('>>', '10_e'), ('>>', '2_s'), ('>>', None),
                       ('>>', '4_s'), ('a', 'a'), ('b', 'b'), ('>>', '4_e'),
                       ('>>', None), ('d', 'd'), ('>>', None),
                       ('>>', '2_e'), ('>>', None)],
         'cost':
         0,
         'visited_states':
         39,
         'queued_states':
         97,
         'traversed_arcs':
         99,
         'fitness':
         1
     }]
     ranges = to_lock_align.compute_lock_range(tree, alignments, [])
     expect_ranges = [{
         1: [[0, 31]],
         2: [[1, 17], [21, 30]],
         3: [[3, 14], [23, 26]],
         4: [[3, 7], [11, 14], [23, 26]],
         5: [[4, 4], [12, 12], [24, 24]],
         6: [[6, 6], [13, 13], [25, 25]],
         7: [[8, 10]],
         9: [[5, 5], [28, 28]],
         10: [[18, 20]],
         11: [[19, 19]]
     }]
     self.assertEqual(str(ranges), str(expect_ranges))
                             '2: improved alignment repair with lock; ' \
                             '3: improved alignment repair Up to Down; '\
                             'default 3', metavar='version')
    parser.add_argument('--o', nargs='?', default=1, type=int,
                        help='1: return the smallest changed scope; '
                             '2: return the subtree of the parent of the changed scope if ' \
                             'the parent of the smallest changed scope has loop operator; '
                             'default 1', metavar='option')
    parser.add_argument('--s', nargs='?', default=False, type=bool,
                        help='indicate whether to write to file, ' \
                             'default=False', metavar='save', choices=[False, True])

    args = parser.parse_args()
    # print("start of plugin with arguments: ", args)
    #
    T1 = args.t1
    T2 = args.t2
    A1 = args.a1
    paras = args.parameter
    version = args.v
    option = args.o
    save_to_file = args.s
    tree = pt_utils.parse(
        "*( X( ->( b, c ), +( X( i, j ), X( g, h, ->( d, e, f ) ) ) ), a, τ )")
    m_tree = pt_utils.parse(
        "*( X( ->( b, c ), +( X( i, j ), X( g, h, ->( d, e, f, l ) ) ) ), a, τ )"
    )
    log = create_event_log("jfljgabc")
    a1, a2 = apply(tree, m_tree, log, version, option=option)
    print(a2)
Пример #30
0
def run_feature(row):
    pt = pt_utils.parse(row['tree'])
    m_pt = pt_utils.parse(row['m_tree'])
    com_res = pt_compare.apply(pt, m_pt, 2)

    # depth
    depth1 = pt_mani_utils.pt_depth(str(com_res.subtree1))
    depth2 = pt_mani_utils.pt_depth(str(com_res.subtree2))
    depths = [
        depth1 / pt_mani_utils.pt_depth(row['tree']),
        depth2 / pt_mani_utils.pt_depth(row['m_tree'])
    ]
    # depths = [depth1, pt_mani_utils.pt_depth(row['tree']), depth2, pt_mani_utils.pt_depth(row['m_tree'])]

    # trace fit
    t_l = set(re.findall("[a-z]", row['tree']))
    st_l = set(re.findall("[a-z]", str(com_res.subtree1)))
    nei_l = t_l - st_l
    min_fit = 1
    for trace in row['log'].strip().split(", "):
        count = 0
        for e in list(trace):
            count = count + 1 if e in nei_l else count
        min_fit = min(min_fit, count / len(trace))

    # type of operators
    ops = [pt.operator, com_res.subtree1.operator, com_res.subtree2.operator]

    # number of operators
    num_loop = len(re.findall(r'\*', row['tree'])) - len(
        re.findall(r'\*', str(com_res.subtree1)))
    num_xor = len(re.findall(r'X', row['tree'])) - len(
        re.findall(r'X', str(com_res.subtree1)))
    num_and = len(re.findall(r'\+', row['tree'])) - len(
        re.findall(r'\+', str(com_res.subtree1)))
    num_seq = len(re.findall(r'->', row['tree'])) - len(
        re.findall(r'->', str(com_res.subtree1)))
    total = num_loop + num_xor + num_seq + num_and
    # rate = [num_loop, num_xor]
    if total == 0:
        rate = [
            0, 0, 0, 0,
            len(re.findall(r'\*', str(com_res.subtree1))),
            len(re.findall(r'\*', str(com_res.subtree2)))
        ]
    else:
        rate = [
            num_loop / total, num_xor / total, num_and / total,
            num_seq / total,
            len(re.findall(r'\*', str(com_res.subtree1))),
            len(re.findall(r'\*', str(com_res.subtree2)))
        ]
    # subtree parent loop
    st = com_res.subtree1
    num_loop, num_xor = 0, 0
    while st.parent is not None:
        if st.parent.operator == Operator.LOOP:
            num_loop += 1
        if st.parent.operator == Operator.XOR:
            num_xor += 1
        st = st.parent

    return pd.Series([min_fit] + rate + ops + depths)