def __get_end_activity_set_binary_tree(pt: ProcessTree,
                                       ea_set=None) -> Set[str]:
    assert pt.children is None or len(pt.children) <= 2
    if ea_set is None:
        ea_set = set()
    if is_leaf(pt) and not is_tau_leaf(pt):
        ea_set.add(pt.label)
    elif not is_tau_leaf(pt):
        assert len(pt.children) == 2
        tau_in_language_sub_pt_1 = __check_empty_sequence_accepted(
            pt.children[0])
        tau_in_language_sub_pt_2 = __check_empty_sequence_accepted(
            pt.children[1])

        if pt.operator == Operator.SEQUENCE:
            if not tau_in_language_sub_pt_2:
                return __get_end_activity_set_binary_tree(
                    pt.children[1], ea_set)
            else:
                for c in pt.children:
                    ea_set.union(__get_end_activity_set_binary_tree(c, ea_set))
        elif pt.operator == Operator.PARALLEL or pt.operator == Operator.XOR:
            for c in pt.children:
                ea_set.union(__get_end_activity_set_binary_tree(c, ea_set))
        elif pt.operator == Operator.LOOP:
            if not tau_in_language_sub_pt_1:
                return __get_end_activity_set_binary_tree(
                    pt.children[0], ea_set)
            else:
                for c in pt.children:
                    ea_set.union(__get_end_activity_set_binary_tree(c, ea_set))
    return ea_set
def get_number_inner_nodes(pt: ProcessTree) -> int:
    if is_leaf(pt):
        return 0
    else:
        res = 1
        for c in pt.children:
            res += get_number_inner_nodes(c)
        return res
def __get_activity_set(pt: ProcessTree, a_set=None) -> Set[str]:
    if a_set is None:
        a_set = set()
    if is_leaf(pt):
        a_set.add(pt.label)
    else:
        for c in pt.children:
            __get_activity_set(c, a_set)
    return a_set
def get_process_tree_height(pt: ProcessTree) -> int:
    """
    calculates from the given node the max height downwards
    :param pt: process tree node
    :return: height
    """
    if is_leaf(pt):
        return 1
    else:
        return 1 + max([get_process_tree_height(x) for x in pt.children])
Exemple #5
0
def can_close(tree: ProcessTree, state: ProcessTreeState) -> bool:
    if ptu.is_leaf(tree):
        return ptu.is_in_state(tree, ProcessTree.OperatorState.OPEN, state)
    elif ptu.is_any_operator_of(tree, {Operator.SEQUENCE, Operator.PARALLEL, Operator.XOR}):
        return frozenset(map(lambda child: state[(id(child), child)], tree.children)) == {
            ProcessTree.OperatorState.CLOSED}
    elif ptu.is_any_operator_of(tree, {Operator.OR}):
        return frozenset(map(lambda child: state[(id(child), child)], tree.children)) == {
            ProcessTree.OperatorState.CLOSED, ProcessTree.OperatorState.FUTURE}
    elif ptu.is_operator(tree, Operator.LOOP):
        return ptu.is_in_state(tree.children[0], ProcessTree.OperatorState.CLOSED, state) and ptu.is_in_state(
            tree.children[1], ProcessTree.OperatorState.FUTURE, state)
Exemple #6
0
def shortest_path_to_close(tree: ProcessTree, state: ProcessTreeState) -> Tuple[
    List[Tuple[ProcessTree, ProcessTree.OperatorState]], ProcessTreeState]:
    if ptu.is_in_state(tree, ProcessTree.OperatorState.CLOSED, state):
        return list(), state
    fast_path, fast_state = close_vertex(tree, state)
    if fast_state is not None:
        return fast_path, fast_state
    path, state = shortest_path_to_open(tree, state)
    if ptu.is_leaf(tree):
        e_path, state = close_vertex(tree, state)
        path.extend(e_path)
        return path, state
    elif ptu.is_any_operator_of(tree, {Operator.SEQUENCE, Operator.PARALLEL}):
        for c in tree.children:
            e_path, state = shortest_path_to_close(c, state)
            path.extend(e_path)
    elif ptu.is_operator(tree, Operator.LOOP):
        if state[(id(tree.children[0]), tree.children[0])] in {ProcessTree.OperatorState.ENABLED,
                                                               ProcessTree.OperatorState.OPEN}:
            e_path, state = shortest_path_to_close(tree.children[0], state)
            path.extend(e_path)
        elif state[(id(tree.children[1]), tree.children[1])] in {ProcessTree.OperatorState.ENABLED,
                                                                 ProcessTree.OperatorState.OPEN}:
            e_path, state = shortest_path_to_close(tree.children[1], state)
            path.extend(e_path)
            e_path, state = shortest_path_to_open(tree.children[0], state)
            path.extend(e_path)
            e_path, state = shortest_path_to_close(tree.children[0], state)
            path.extend(e_path)
    elif tree.operator in {Operator.XOR, Operator.OR}:
        busy = False
        for c in tree.children:
            if state[(id(c), c)] in {ProcessTree.OperatorState.ENABLED, ProcessTree.OperatorState.OPEN}:
                e_path, state = shortest_path_to_close(c, state)
                path.extend(e_path)
                busy = True
        if not busy:
            cur_path, cur_state, cur_path_costs = list(), copy.copy(state), sys.maxsize
            for c in tree.children:
                if state[(id(c), c)] != ProcessTree.OperatorState.CLOSED:
                    candidate_p, candidate_s = shortest_path_to_close(c, state)
                    candidate_costs = len(list(filter(lambda t: t[0].operator is None and t[0].label is not None and t[
                        1] == ProcessTree.OperatorState.OPEN, candidate_p)))
                    if candidate_costs < cur_path_costs:
                        cur_path, cur_state, cur_path_costs = candidate_p, candidate_s, candidate_costs
            path.extend(cur_path)
            state = cur_state
    e_path, state = close_vertex(tree, state)
    path.extend(e_path)
    return path, state
def __check_empty_sequence_accepted(pt: ProcessTree) -> bool:
    if is_leaf(pt):
        if is_tau_leaf(pt):
            return True
        else:
            return False
    else:
        assert len(pt.children) == 2
        if pt.operator == Operator.SEQUENCE or pt.operator == Operator.PARALLEL:
            return __check_empty_sequence_accepted(pt.children[0]) and __check_empty_sequence_accepted(pt.children[1])
        elif pt.operator == Operator.XOR:
            return __check_empty_sequence_accepted(pt.children[0]) or __check_empty_sequence_accepted(pt.children[1])
        else:
            assert pt.operator == Operator.LOOP
            return __check_empty_sequence_accepted(pt.children[0])