def __generate_condition_func(zero_conds: List[Condition], var: Variable, var_with_lo: Variable, var_output: Variable):
    var_is_zero = False
    var_with_lo_is_zero = False
    for zcond in zero_conds:
        if zcond.check_contains_var(var, ConditionState.IS_ZERO):
            var_is_zero = True
        elif zcond.check_contains_var(var_with_lo, ConditionState.IS_ZERO):
            var_with_lo_is_zero = True

    if var_is_zero and var_with_lo_is_zero:
        return [Condition.create_zero_condition(Side(var_output.clone()))]
    elif (var_is_zero and not var_with_lo_is_zero) or (not var_is_zero and var_with_lo_is_zero):
        return [Condition.create_non_zero_condition(Side(var_output.clone()))]
    else:  # (not var_is_zero and not var_with_lo_is_zero)
        return [Condition.create_zero_condition(Side(var_output.clone())),
                Condition.create_non_zero_condition(Side(var_output.clone()))]
Ejemplo n.º 2
0
    def make_zero_condition(self) -> Union[Condition, NoReturn]:

        if self.__left.is_empty() and not self.__right.is_empty():
            non_zero_side = self.__right
        elif not self.__left.is_empty() and self.__right.is_empty():
            non_zero_side = self.__left
        else:
            raise Exception("One side must be not empty in transition")

        return Condition.create_zero_condition(non_zero_side)
Ejemplo n.º 3
0
    def _estimate_internal(
            self, append_system_fn: Callable[['SystemTransition'],
                                             None]) -> None:
        count_triviality = 0
        count_with_unknowns = 0
        self.dump_system('start estimation')

        some_transitions_removed = True
        while some_transitions_removed:
            logger.debug("Start analyse from last transition")
            some_transitions_removed = False
            for x in range(len(self.__transitions) - 1, -1, -1):
                transition = self.__transitions[x]
                logger.debug("Analyse transition {}".format(transition))
                left = transition.get_left_side()
                right = transition.get_right_side()

                assert len(left) > 0 and len(right) > 0

                # 2 sides does not have unknowns
                if not left.contains_unknown() and not right.contains_unknown(
                ):
                    count_triviality += 1
                    logger.debug(
                        "Transition {} is triviality".format(transition))
                    continue

                is_left_non_zero = self._is_side_non_zero(left)
                is_right_non_zero = self._is_side_non_zero(right)

                if is_left_non_zero and is_right_non_zero:
                    logger.debug(
                        "Both sides '{}' and '{}' are not zero".format(
                            left, right))
                    # do nothing, just increase counter
                    count_with_unknowns += 1
                    continue
                elif is_left_non_zero and not is_right_non_zero:
                    logger.debug(
                        "Left side '{}' is NON ZERO. Rigth is undefined '{}'".
                        format(left, right))
                    # fixed left side - not fork
                    nz = Condition.create_non_zero_condition(right.copy())
                    logger.debug("Create non zero condition '{}'".format(nz))
                    self._conds_non_zero.append(nz)
                    count_with_unknowns += 1
                    continue
                elif not is_left_non_zero and is_right_non_zero:
                    logger.debug(
                        "Right side '{}' is NON ZERO. Left is undefined '{}'".
                        format(right, left))
                    # fixed right side - not fork
                    nz = Condition.create_non_zero_condition(left.copy())
                    logger.debug("Create non zero condition: '{}'".format(nz))
                    self._conds_non_zero.append(nz)
                    count_with_unknowns += 1
                    continue
                else:
                    fork = False
                    # both sides not zero
                    # check that they does not contain unkwowns
                    if not left.contains_unknown(
                    ) or not right.contains_unknown():
                        logger.info(
                            'Left or right sides does not contains UNKNOWN')
                        # need divide in two cases: zero and not zero
                        # zero case
                    else:
                        logger.info(
                            "Left and right contains UNKNOWN and sides in undefined. 'Fork' will processing"
                        )
                        fork = True

                    new_system = self.__clone(is_fork=fork)
                    # create non zero condition and add them to new system
                    # logger.debug("Creating new conditions for non zero case")
                    left_nzc = Condition.create_non_zero_condition(left.copy())
                    right_nzc = Condition.create_non_zero_condition(
                        right.copy())
                    logger.debug(
                        "New non zero conditions '{}' and '{}'".format(
                            left_nzc, right_nzc))
                    new_system._conds_non_zero.append(left_nzc)
                    new_system._conds_non_zero.append(right_nzc)
                    append_system_fn(new_system)
                    logger.debug("New system with id {} added to queue".format(
                        new_system._id))

                    # logger.debug("Creating new conditions for zero case")
                    left_zc = Condition.create_zero_condition(left.copy())
                    right_zc = Condition.create_zero_condition(right.copy())
                    logger.debug("New zero conditions '{}' and '{}'".format(
                        left_zc, right_zc))
                    self._use_and_append_zero_cond(left_zc)
                    self._use_and_append_zero_cond(right_zc)
                    some_transitions_removed = False
                    res = 1
                    while res > 0:
                        res = self._remove_empty_transitions()
                        res += self._analyse_and_generate_new_conditions()
                        some_transitions_removed |= bool(res)
                    if some_transitions_removed:
                        break
                    continue

        self._mark = None
        for tr in self.__transitions:
            if self._mark is None:
                self._mark = Symbol(tr.get_probability())
            else:
                self._mark *= Symbol(tr.get_probability())

        N = Symbol('N')
        amount = self._count_special_equal_conds()
        for i in range(amount):
            if self._mark is None:
                self._mark = N
            else:
                self._mark *= N
        if self._mark is not None:
            collector.make_node_leaf(self._node, self._mark)
            self.save_node(self._node)

        self.dump_system('Estimated with mark {}'.format(str(self._mark)))
        return