def can_enable(tree: ProcessTree, state: ProcessTreeState) -> bool:
    if ptu.is_in_state(tree, ProcessTree.OperatorState.FUTURE, state):
        if ptu.is_root(tree):
            return True
        if ptu.is_in_state(tree.parent, ProcessTree.OperatorState.OPEN, state):
            if ptu.is_any_operator_of(tree.parent,
                                      [Operator.PARALLEL, Operator.OR]):
                return True
            elif ptu.is_operator(tree.parent, Operator.XOR):
                return frozenset(
                    map(lambda child: state[(id(child), child)],
                        tree.parent.children)) == {
                            ProcessTree.OperatorState.FUTURE
                        }
            elif ptu.is_operator(tree.parent, Operator.SEQUENCE):
                return True if tree.parent.children.index(
                    tree) == 0 else ptu.is_in_state(
                        tree.parent.children[tree.parent.children.index(tree) -
                                             1],
                        ProcessTree.OperatorState.CLOSED, state)
            elif ptu.is_operator(tree.parent, Operator.LOOP):
                return frozenset(
                    map(lambda child: state[(id(child), child)],
                        tree.parent.children)) == {
                            ProcessTree.OperatorState.FUTURE,
                            ProcessTree.OperatorState.CLOSED
                        }
    return False
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)
Пример #3
0
def _need_log_move(old_state, new_state, path) -> bool:
    if len(_obtain_leaves_from_state_path(path, include_tau=True)) > 0:
        return True
    choices = list(filter(lambda o: pt_util.is_any_operator_of(o[1], [Operator.XOR, Operator.LOOP]), old_state.keys()))
    for choice in choices:
        choice = choice[1]
        if pt_util.is_operator(choice, Operator.XOR):
            if (pt_util.is_in_state(choice, ProcessTree.OperatorState.FUTURE, old_state) or pt_util.is_in_state(choice,
                                                                                                                ProcessTree.OperatorState.CLOSED,
                                                                                                                old_state)) and \
                    old_state[(id(choice), choice)] != new_state[(id(choice), choice)]:
                return True
        elif pt_util.is_operator(choice, Operator.LOOP):
            for loop_child in choice.children:
                if (pt_util.is_in_state(loop_child, ProcessTree.OperatorState.FUTURE,
                                        old_state) or pt_util.is_in_state(loop_child,
                                                                          ProcessTree.OperatorState.CLOSED,
                                                                          old_state)) and \
                        old_state[(id(loop_child), loop_child)] != new_state[(id(loop_child), loop_child)]:
                    return True
    return False
def shortest_path_to_open(
    tree: ProcessTree, state: ProcessTreeState
) -> Tuple[List[Tuple[ProcessTree, ProcessTree.OperatorState]],
           ProcessTreeState]:
    if ptu.is_in_state(tree, ProcessTree.OperatorState.OPEN, state):
        return list(), state
    fast_path, fast_state = open_vertex(tree, state)
    if fast_state is not None:
        return fast_path, fast_state
    path, state = shortest_path_to_enable(tree, state)
    if path is not None:
        e_path, state = open_vertex(tree, state)
        path.extend(e_path)
    return path, state
def close_vertex(
    tree: ProcessTree, state: ProcessTreeState
) -> Tuple[Optional[List[Tuple[ProcessTree, ProcessTree.OperatorState]]],
           Optional[ProcessTreeState]]:
    if can_close(tree, state):
        current_state = state[(id(tree), tree)]
        path = list()
        state = copy.copy(state)
        for c in tree.children:
            if ptu.is_in_state(c, ProcessTree.OperatorState.CLOSED, state):
                e_path, state = transform_tree(
                    c, ProcessTree.OperatorState.CLOSED, state)
                path.extend(e_path)
        state[(id(tree), tree)] = ProcessTree.OperatorState.CLOSED
        path.append((tree, ProcessTree.OperatorState.CLOSED))
        if ptu.is_operator(
                tree.parent, Operator.LOOP) and tree == tree.parent.children[
                    1] and current_state == ProcessTree.OperatorState.OPEN:
            e_path, state = enable_vertex(tree.parent.children[0], state)
            path.extend(e_path)
    else:
        state, path = None, None
    return path, state
def can_open(tree: ProcessTree, state: ProcessTreeState) -> bool:
    return ptu.is_in_state(tree, ProcessTree.OperatorState.ENABLED, state)
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