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()))]
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)
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