Ejemplo n.º 1
0
 def __init__(self, var_names_and_syms={}, p_or_neg_log_p={}, p=True, cond={}, scope={}):
     non_none_scope = {var: value for var, value in list(scope.items()) if value is not None}
     if p:
         f = lambda x: -log(x)
     else:
         f = lambda x: x
     p_or_neg_log_p = MathDict({var_values___frozen_dict: f(func_value)
                                for var_values___frozen_dict, func_value in list(p_or_neg_log_p.items())
                                if set(var_values___frozen_dict.items()) >= set(non_none_scope.items())})
     PDF.__init__(self, family='DiscreteFinite', var_names_and_syms=var_names_and_syms,
                  param=dict(NegLogP=p_or_neg_log_p), cond=cond, scope=non_none_scope,
                  neg_log_dens_func=discrete_finite_neg_log_mass, norm_func=discrete_finite_norm,
                  max_func=discrete_finite_max, marg_func=discrete_finite_marg, cond_func=discrete_finite_cond,
                  sample_func=DO_NOTHING_FUNC)
Ejemplo n.º 2
0
 def __init__(self, var_names_and_syms={}, p_or_neg_log_p={}, p=True, cond={}, scope={}):
     non_none_scope = {var: value for var, value in scope.items() if value is not None}
     if p:
         f = lambda x: -log(x)
     else:
         f = lambda x: x
     p_or_neg_log_p = MathDict({var_values___frozen_dict: f(func_value)
                                for var_values___frozen_dict, func_value in p_or_neg_log_p.items()
                                if set(var_values___frozen_dict.items()) >= set(non_none_scope.items())})
     PDF.__init__(self, family='DiscreteFinite', var_names_and_syms=var_names_and_syms,
                  param=dict(NegLogP=p_or_neg_log_p), cond=cond, scope=non_none_scope,
                  neg_log_dens_func=discrete_finite_neg_log_mass, norm_func=discrete_finite_norm,
                  max_func=discrete_finite_max, marg_func=discrete_finite_marg, cond_func=discrete_finite_cond,
                  sample_func=DO_NOTHING_FUNC)
Ejemplo n.º 3
0
    def __init__(self, var_names_and_syms={}, mapping={}, param={}, cond={}, scope={}, compile=False):
        if not hasattr(self, 'Vars'):
            self.Vars = var_names_and_syms   # {var_name: var_symbol} dict
        if not hasattr(self, 'Param'):
            self.Param = param
        self.Cond = cond   # {var_name: var_value} dict, var_value can be None if conditioning is generic
        self.Scope = dict.fromkeys(set(var_names_and_syms) - set(cond))
        vars_with_fixed_scope_values = {}   # to keep track of scope variables with fixed values (i.e. points in space)
        for var, value in scope.items():
            if (var in self.Scope) and (value is not None):
                self.Scope[var] = value    # "points-in-space"
                vars_with_fixed_scope_values[var] = value
        s0 = set(vars_with_fixed_scope_values.items())
        if hasattr(mapping, 'keys'):
            self.Mapping = MathDict()
            self.CondInstances = {}
            for vars_and_values___frozen_dict, func_value in mapping.items():
                if set(vars_and_values___frozen_dict.items()) >= s0:
                    self.Mapping[vars_and_values___frozen_dict] = func_value
                    condition_instance = {}
                    for var in (set(vars_and_values___frozen_dict) & set(cond)):
                        condition_instance[var] = vars_and_values___frozen_dict[var]
                    self.CondInstances[vars_and_values___frozen_dict] = frozendict(condition_instance)
        else:
            self.Mapping = mapping

        if not hasattr(self, 'CompyledFunc'):
            self.CompyledFunc = None
        if compile:
            self.compile()
Ejemplo n.º 4
0
def p_from_neg_log_p(expr_or_dict):
    if hasattr(expr_or_dict, 'keys'):
        probs___math_dict = MathDict()
        for k, v in list(expr_or_dict.items()):
            probs___math_dict[k] = exp(-v)
        return probs___math_dict
    else:
        return exp(-expr_or_dict)
Ejemplo n.º 5
0
def discrete_finite_neg_log_mass(pmf, var_names_and_values={}):
    v = var_names_and_values.copy()
    for var, value in list(var_names_and_values.items()):
        if (value is None) or is_non_atomic_sympy_expr(value):
            del v[var]
    s0 = set(v.items())
    d = MathDict(())
    for var_names_and_values___frozen_dict, func_value in list(pmf.Param['NegLogP'].items()):
        spare_var_values = dict(s0 - set(var_names_and_values___frozen_dict.items()))
        s = set(spare_var_values.keys())
        if not(s) or (s and not(s & set(var_names_and_values___frozen_dict))):
            d[var_names_and_values___frozen_dict] = sympy_xreplace(func_value, var_names_and_values)
    return d
Ejemplo n.º 6
0
def shift_time_subscripts(obj, t, *matrix_symbols_to_shift):
    if isinstance(obj, MathDict):
        return MathDict({
            shift_time_subscripts(key, t): shift_time_subscripts(value, t)
            for key, value in list(obj.items())
        })
    elif isinstance(obj, frozendict):
        return frozendict({
            shift_time_subscripts(key, t): shift_time_subscripts(value, t)
            for key, value in list(obj.items())
        })
    elif isinstance(obj, tuple):
        if len(obj) == 2 and not (isinstance(obj[0],
                                             (int, float))) and isinstance(
                                                 obj[1], int):
            return shift_time_subscripts(obj[0], t), obj[1] + t
        else:
            return tuple(shift_time_subscripts(item, t) for item in obj)
    elif isinstance(obj, list):
        return [shift_time_subscripts(item, t) for item in obj]
    elif isinstance(obj, set):
        return {shift_time_subscripts(item, t) for item in obj}
    elif isinstance(obj, dict):
        return {
            shift_time_subscripts(key, t): shift_time_subscripts(value, t)
            for key, value in list(obj.items())
        }
    elif isinstance(obj, MatrixSymbol):
        args = obj.args
        if isinstance(args[0], tuple):
            return MatrixSymbol(shift_time_subscripts(args[0], t), args[1],
                                args[2])
        else:
            return deepcopy(obj)
    elif is_non_atomic_sympy_expr(obj):
        return obj.xreplace({
            matrix_symbol: shift_time_subscripts(matrix_symbol, t)
            for matrix_symbol in matrix_symbols_to_shift
        })
    else:
        return deepcopy(obj)
Ejemplo n.º 7
0
class MathFunc:
    def __init__(self, var_names_and_syms={}, mapping={}, param={}, cond={}, scope={}, compile=False):
        if not hasattr(self, 'Vars'):
            self.Vars = var_names_and_syms   # {var_name: var_symbol} dict
        if not hasattr(self, 'Param'):
            self.Param = param
        self.Cond = cond   # {var_name: var_value} dict, var_value can be None if conditioning is generic
        self.Scope = dict.fromkeys(set(var_names_and_syms) - set(cond))
        vars_with_fixed_scope_values = {}   # to keep track of scope variables with fixed values (i.e. points in space)
        for var, value in scope.items():
            if (var in self.Scope) and (value is not None):
                self.Scope[var] = value    # "points-in-space"
                vars_with_fixed_scope_values[var] = value
        s0 = set(vars_with_fixed_scope_values.items())
        if hasattr(mapping, 'keys'):
            self.Mapping = MathDict()
            self.CondInstances = {}
            for vars_and_values___frozen_dict, func_value in mapping.items():
                if set(vars_and_values___frozen_dict.items()) >= s0:
                    self.Mapping[vars_and_values___frozen_dict] = func_value
                    condition_instance = {}
                    for var in (set(vars_and_values___frozen_dict) & set(cond)):
                        condition_instance[var] = vars_and_values___frozen_dict[var]
                    self.CondInstances[vars_and_values___frozen_dict] = frozendict(condition_instance)
        else:
            self.Mapping = mapping

        if not hasattr(self, 'CompyledFunc'):
            self.CompyledFunc = None
        if compile:
            self.compile()

    def __repr__(self):
        return 'MathFunc %s' % repr(self.Mapping)

    def copy(self, deep=False):
        if deep:
            math_func = deepcopy(self)
        else:
            math_func = shallowcopy(self)
            math_func.Cond = deepcopy(math_func.Cond)   # need to be careful with Cond and Scope
            math_func.Scope = deepcopy(math_func.Scope)   # need to be careful with Cond and Scope
        math_func.CompyledFunc = None   # remove compiled version because changes are likely to be made on the copy
        return math_func

    def at(self, vars_and_values___dict={}, **kw_vars_and_values___dict):
        vars_and_values___dict = combine_dict_and_kwargs(vars_and_values___dict, kw_vars_and_values___dict)
        for var in (set(self.Vars) & set(vars_and_values___dict)):
            vars_and_values___dict[self.Vars[var]] = vars_and_values___dict[var]
        conds = self.Cond.copy()
        scope = self.Scope.copy()
        for var, value in vars_and_values___dict.items():
            if var in conds:
                conds.update({var: value})
            if var in scope:
                scope.update({var: value})
        conds = sympy_xreplace(conds, vars_and_values___dict)
        scope = sympy_xreplace(scope, vars_and_values___dict)
        if hasattr(self.Mapping, 'keys'):
            mapping = {}
            for vars_and_values___frozen_dict, func_value in self.Mapping.items():
                other_items___dict = dict(set(vars_and_values___frozen_dict.items()) -
                                          set(vars_and_values___dict.items()))
                if not (set(other_items___dict) and set(vars_and_values___dict)):
                    mapping[frozendict(set(vars_and_values___frozen_dict.items()) - set(conds.items()))] =\
                        sympy_xreplace(func_value, vars_and_values___dict)
        else:
            mapping = sympy_xreplace(self.Mapping, vars_and_values___dict)
        return MathFunc(self.Vars.copy(), mapping, cond=conds, scope=scope)

    def compile(self):
        self.CompyledFunc = CompyledFunc(merge_dicts_ignoring_dup_keys_and_none_values(self.Vars, self.Param),
                                         self.Mapping)

    def __call__(self, var_and_param_names_and_values={}, **kw_var_and_param_names_and_values):
        var_and_param_names_and_values = combine_dict_and_kwargs(var_and_param_names_and_values,
                                                                 kw_var_and_param_names_and_values)
        if var_and_param_names_and_values:
            if self.CompyledFunc is None:
                self.compile()
            return self.CompyledFunc(var_and_param_names_and_values)
        elif isinstance(self.Mapping, MathDict):
            return self.Mapping()
        else:
            return self.Mapping

    def optim(self, max_or_min=max, leave_unoptimized=None):
        if max_or_min is max:
            comp = ge
        else:
            comp = le
        if leave_unoptimized:
            comparison_bases = {}
            conditioned_and_unoptimized_vars = set(self.Cond) | set(leave_unoptimized)
            for vars_and_values___frozen_dict in self.Mapping:
                comparison_basis = {}
                for var in (set(vars_and_values___frozen_dict) & conditioned_and_unoptimized_vars):
                    comparison_basis[var] = vars_and_values___frozen_dict[var]
                comparison_bases[vars_and_values___frozen_dict] = frozendict(comparison_basis)
        else:
            comparison_bases = self.CondInstances
        optim_values = {}
        for vars_and_values___frozen_dict, func_value in self.Mapping.items():
            comparison_basis = comparison_bases[vars_and_values___frozen_dict]
            if comparison_basis in optim_values:
                optim_values[comparison_basis] = max_or_min(optim_values[comparison_basis], func_value)
            else:
                optim_values[comparison_basis] = func_value
        optims = {}
        for vars_and_values___frozen_dict, func_value in self.Mapping.items():
            if comp(func_value, optim_values[comparison_bases[vars_and_values___frozen_dict]]):
                optims[vars_and_values___frozen_dict] = func_value
        return MathFunc(self.Vars.copy(), optims, cond=self.Cond.copy(), scope=self.Scope.copy())

    def marg(self, *marginalized_vars, **kwargs):
        itself = lambda x: x
        if 'transf' in kwargs:
            transf_func = kwargs['transf']
        else:
            transf_func = itself
        if 'reduce_func' in kwargs:
            reduce_func = kwargs['reduce_func']
        else:
            reduce_func = add
        if 'rev_transf' in kwargs:
            rev_transf_func = kwargs['rev_transf']
        else:
            rev_transf_func = itself
        var_names_and_symbols___dict = self.Vars.copy()   # just to be careful
        scope = self.Scope.copy()   # just to be careful
        mapping = self.Mapping.copy()   # just to be careful
        for marginalized_var in marginalized_vars:
            del var_names_and_symbols___dict[marginalized_var]
            del scope[marginalized_var]
            d = {}
            for vars_and_values___frozen_dict, func_value in mapping.items():
                marginalized_var_value = vars_and_values___frozen_dict[marginalized_var]
                fd = frozendict(set(vars_and_values___frozen_dict.items()) -
                                {(marginalized_var, marginalized_var_value)})
                if fd in d:
                    d[fd] = reduce_func(d[fd], transf_func(func_value))
                else:
                    d[fd] = transf_func(func_value)
            mapping = {k: rev_transf_func(v) for k, v in d.items()}
        return MathFunc(var_names_and_symbols___dict, mapping, cond=self.Cond.conds(), scope=scope)

    def cond(self, conds={}, **kw_conds):
        conds = combine_dict_and_kwargs(conds, kw_conds)
        mapping = {}
        s0 = set(conds.items())
        for vars_and_values___frozen_dict, func_value in self.Mapping().items():
            s = set(vars_and_values___frozen_dict.items())
            if s >= s0:
                mapping[frozendict(s - s0)] = func_value
        new_conds = self.Cond.copy()
        new_conds.update(conds)
        new_scope = self.Scope.copy()
        for var in conds:
            del new_scope[var]
        return MathFunc(self.Vars.copy(), mapping, cond=new_conds, scope=new_scope)

    def op(self, op=mul, other=None, r=False, **kwargs):
        if isinstance(other, MathFunc):
            conds = merge_dicts_ignoring_dup_keys_and_none_values(self.Cond, other.Cond)
            scope = merge_dicts_ignoring_dup_keys_and_none_values(self.Scope, other.Scope)
            for var in (set(conds) & set(scope)):
                del conds[var]
            var_names_and_symbols = merge_dicts_ignoring_dup_keys_and_none_values(self.Vars, other.Vars)
            other_mapping = other.Mapping
        else:
            var_names_and_symbols = self.Vars.copy()
            conds = self.Cond.copy()
            scope = self.Scope.copy()
            other_mapping = other
        if isinstance(self.Mapping, MathDict):
            mapping = self.Mapping.op(op, other_mapping, r=r, **kwargs)
        elif isinstance(other_mapping, MathDict):
            mapping = other_mapping.op(op, self.Mapping, r=not r, **kwargs)
        else:
            mapping = op(self.Mapping, other_mapping, **kwargs)
        return MathFunc(var_names_and_symbols, mapping, conds, scope)

    # Operations on Self alone:
    def __index__(self):
        return self.op(op=index)

    def __int__(self):
        return self.op(op=int)

    def __long__(self):
        return self.op(op=long)

    def __hex__(self):
        return self.op(op=hex)

    def __float__(self):
        return self.op(op=float)

    def __complex__(self):
        return self.op(op=complex)

    def __pos__(self):
        return self.op(op=pos)

    def __neg__(self):
        return self.op(op=neg)

    def __abs__(self):
        return self.op(op=abs)

    # Rich Comparisons
    def __lt__(self, other):
        return self.op(op=lt, other=other)

    def __le__(self, other):
        return self.op(op=le, other=other)

    def __eq__(self, other):
        return self.op(op=eq, other=other)

    def __ne__(self, other):
        return self.op(op=ne, other=other)

    def __ge__(self, other):
        return self.op(op=ge, other=other)

    def __gt__(self, other):
        return self.op(op=gt, other=other)

    # Bit-Wise Operations
    def __add__(self, other):
        return self.op(op=add, other=other)

    def __radd__(self, other):
        return self + other

    def __sub__(self, other):
        return self.op(op=sub, other=other)

    def __rsub__(self, other):
        return (-self) + other

    def __mul__(self, other):
        return self.op(op=mul, other=other)

    def __rmul__(self, other):
        return self * other

    def __div__(self, other):
        return self.op(op=div, other=other)

    def __rdiv__(self, other):
        return self.op(op=div, other=other, r=True)

    def __truediv__(self, other):
        return self.op(op=truediv, other=other)

    def __rtruediv__(self, other):
        return self.op(op=truediv, other=other, r=True)

    def __floordiv__(self, other):
        return self.op(op=floordiv, other=other)

    def __rfloordiv__(self, other):
        return self.op(op=floordiv, other=other, r=True)

    def __mod__(self, other):
        return self.op(op=mod, other=other)

    def __rmod__(self, other):
        return self.op(op=mod, other=other, r=True)

    def __pow__(self, power):
        return self.op(op=pow, other=power)

    def __rpow__(self, other):
        return self.op(op=pow, other=other, r=True)

    def allclose(self, other, rtol=1e-5, atol=1e-8):
        return all(self.op(op=sympy_allclose, other=other, rtol=rtol, atol=atol).Mapping.values())

    def pprint(self):
        print('MATHEMATICAL FUNCTION')
        print('_____________________')
        print("VARIABLES' SYMBOLS:")
        pprint(self.Vars)
        print('conds:')
        pprint(self.Cond)
        print('SCOPE:')
        pprint(self.Scope)
        print('MAPPING:')
        sympy_print(self.Mapping)