예제 #1
0
 def _array_to_val(self, var_obj, x, edges):
     prob_tables, util_tables = np.split(x.copy(), 2)
     valuations = []
     for p, u in zip(np.split(prob_tables, len(edges)),
                     np.split(util_tables, len(edges))):
         valuations.append(Valuation(Factor(var_obj, p), Factor(var_obj,
                                                                u)))
     return valuations
예제 #2
0
def get_const_valuation_with_v(v, variables, is_log):
    """ return a constant valuation with scope v, (all ones, all zero) """
    for var in variables:
        if var.label == v:
            if is_log:  # transform back to log scale
                # return Valuation(Factor({var}, ONE), Factor({var}, ONE)).log()
                return Valuation(Factor({var}, ONE), Factor({var}, ZERO)).log()
            else:
                # return Valuation(Factor({var}, ONE), Factor({var}, ONE))
                return Valuation(Factor({var}, ONE), Factor({var}, ZERO))
예제 #3
0
def get_const_with_vars(var_labels, variables, is_valuation, is_log):
    var_set = {var for var in variables if var.label in var_labels}
    if is_valuation:
        const_linear = Valuation(Factor(var_set.copy(), ONE),
                                 Factor(var_set.copy(), ZERO))
    else:
        const_linear = Factor(var_set.copy(), ONE)
    if is_log:
        return const_linear.log()
    else:
        return const_linear
예제 #4
0
def factor_to_valuation(factor, factor_type, const_shift=False):
    if const_shift:
        # (P, P) = (P,0)*(1,1), (1, U+1) = (1,U)*(1,1) shift valuation by (1,1) adding utility by 1
        return Valuation(factor.copy(),
                         factor.copy()) if factor_type == 'P' else Valuation(
                             Factor(factor.vars.copy(), 1.0),
                             factor.copy() + Factor(factor.vars.copy(), 1.0))

    else:
        # (P,0) := (P, 1e-300), (1,U)
        return Valuation(factor.copy(), Factor(
            factor.vars.copy(), ZERO)) if factor_type == 'P' else Valuation(
                Factor(factor.vars.copy(), 1.0), factor.copy())
예제 #5
0
    def Gibbs_Sampling(self, initials=None, stopSamples=1):
        """Gibbs sampling procedure for discrete graphical model "model"
		"""
        # state = state if state is not None else [np.random.randint(Xi.states) for Xi in self.X]
        # TODO: timing check
        term = copy.deepcopy(initials)
        for sam in range(NUM_SAMPLES):
            for j in range(stopSamples):
                # TODO if out of time, break
                for Xi in self.X:
                    p = Factor([], 1.0)
                    for f in self.factorsWith(Xi, False):
                        cvar = f.vars - [Xi]
                        p *= f.condition2(cvar, [term[sam][v] for v in cvar])
                    p /= p.sum()
                    term[sam][Xi] = p.sample()[0]
        return term
예제 #6
0
    def _eval_util_gradients(self, node_from, node_to):
        eu_from = self.mg.message_graph.node[node_from]['bound'].util
        eu_to = self.mg.message_graph.node[node_to]['bound'].util
        prob_bound_tot = self._eval_prob_bound_norms()

        sc = self.mg.message_graph.edge[node_from][node_to]['sc']
        pm_eu_from = self.mg.message_graph.node[node_from][
            'pseudo_belief'].util
        pm_eu_to = self.mg.message_graph.node[node_to]['pseudo_belief'].util

        eucomp_from = self.mg.message_graph.node[node_from]['fs'][0].util
        pcomp_from = self.mg.message_graph.node[node_from]['fs'][0].prob
        eucomp_to = self.mg.message_graph.node[node_to]['fs'][0].util
        pcomp_to = self.mg.message_graph.node[node_to]['fs'][0].prob

        if eu_to == 0 and eu_from == 0:  # both zero no update
            temp = pm_eu_to.marginal(sc)
            gradient = Factor(temp.v, 0.0)
        elif eu_to == 0:  # eu_to zero A = 0
            neg_eu_position = eucomp_from.t <= 0.0
            B = pm_eu_from * pcomp_from / eucomp_from
            B.t[neg_eu_position] = 0.0
            finite_positions = np.isfinite(B.t)
            B.t[~finite_positions] = 0.0
            B = B.marginal(sc)
            B *= self._eval_util_bound_norms(node_from)
            gradient = -B  # a unit of cost
        elif eu_from == 0:  # eu_from zero B = 0
            neg_eu_position = eucomp_to.t <= 0.0
            A = pm_eu_to * pcomp_to / eucomp_to
            A.t[neg_eu_position] = 0.0
            finite_positions = np.isfinite(A.t)
            A.t[~finite_positions] = 0.0
            A = A.marginal(sc)
            A *= self._eval_util_bound_norms(node_to)
            gradient = A  # a unit of cost
        else:  # both non-zero
            neg_eu_position = eucomp_to.t <= 0.0
            A = pm_eu_to * pcomp_to / eucomp_to
            A.t[neg_eu_position] = 0.0
            finite_positions = np.isfinite(A.t)
            A.t[~finite_positions] = 0.0
            A = A.marginal(sc)
            A *= self._eval_util_bound_norms(node_to)

            neg_eu_position = eucomp_from.t <= 0.0
            B = pm_eu_from * pcomp_from / eucomp_from
            B.t[neg_eu_position] = 0.0
            finite_positions = np.isfinite(B.t)
            B.t[~finite_positions] = 0.0
            B = B.marginal(sc)
            B *= self._eval_util_bound_norms(node_from)
            gradient = A - B
        return gradient * prob_bound_tot  # negative of gradient
예제 #7
0
    def _eval_weight_gradients_per_var(self, v_w, nodes):
        wgts = []
        Hcond = []

        for node in nodes:
            sc = self.mg.message_graph.node[node]['sc']
            mu_p = self.mg.message_graph.node[node]['pseudo_belief'].marginal(sc)
            # mu_p = self.mg.message_graph.node[node]['pseudo_belief']
            elimvars_in_node = sorted(sc, key=lambda x: self.elim_order.index(x))
            v_w_ind = elimvars_in_node.index(v_w)

            mu_p_temp1 = mu_p.marginal(elimvars_in_node[v_w_ind:])  # P(xi, xi+1~)
            if type(mu_p_temp1) is not Factor:
                mu_p_temp1 = Factor({}, mu_p_temp1)

            if np.all(mu_p_temp1.t == 0):  # when mu_u_temp1 is all zero factor, raise assertion error
                H1_p = 0.0
            else:
                H1_p = mu_p_temp1.entropy()

            if v_w_ind + 1 < len(elimvars_in_node):
                mu_p_temp2 = mu_p.marginal(elimvars_in_node[v_w_ind + 1:])  # P(xi+1 , xi+2 ~)
                if type(mu_p_temp2) is not Factor:
                    mu_p_temp2 = Factor({}, mu_p_temp2)
                if np.all(mu_p_temp2.t == 0):
                    H2_p = 0.0
                else:
                    H2_p = mu_p_temp2.entropy()
            else:
                H2_p = 0.0

            wgts.append(self.mg.message_graph.node[node]['w'][v_w])
            Hcond.append(H1_p - H2_p)  # conditional entropy

        Hbar = 0.0
        for i in range(len(wgts)):
            Hbar += wgts[i] * Hcond[i]
        gradient = [w_i*(Hcond[ind] - Hbar) for ind, w_i in enumerate(wgts)]

        if self.verbose:
            print('wgts:', wgts)
            print('Hcond:', Hcond)
            print('Hbar:', Hbar)
            print('grad:', gradient)

        if debug:
            assert np.all(np.isfinite(gradient))
        return gradient
예제 #8
0
    def _eval_weight_gradients_per_var(self, v_w, nodes):
        wgts = []
        Hcond_u = []
        Hcond_p = []

        for node in nodes:
            sc = self.mg.message_graph.node[node]['sc']
            mu_p = self.mg.message_graph.node[node][
                'pseudo_belief'].prob.marginal(sc)
            mu_u = self.mg.message_graph.node[node][
                'pseudo_belief'].util.marginal(sc)
            elimvars_in_node = sorted(sc,
                                      key=lambda x: self.elim_order.index(x))
            v_w_ind = elimvars_in_node.index(v_w)

            mu_p_temp1 = mu_p.marginal(
                elimvars_in_node[v_w_ind:])  # P(xi, xi+1~)
            if type(mu_p_temp1) is not Factor:
                mu_p_temp1 = Factor({}, mu_p_temp1)
            H1_p = mu_p_temp1.entropy()

            mu_u_temp1 = mu_u.marginal(
                elimvars_in_node[v_w_ind:])  # P(xi, xi+1~)
            if type(mu_u_temp1) is not Factor:
                mu_u_temp1 = Factor({}, mu_u_temp1)
            if np.all(
                    mu_u_temp1.t == 0
            ):  # when mu_u_temp1 is all zero factor, raise assertion error
                H1_u = 0.0
            else:
                H1_u = mu_u_temp1.entropy()

            if v_w_ind + 1 < len(elimvars_in_node):
                mu_p_temp2 = mu_p.marginal(
                    elimvars_in_node[v_w_ind + 1:])  # P(xi+1 , xi+2 ~)
                if type(mu_p_temp2) is not Factor:
                    mu_p_temp2 = Factor({}, mu_p_temp2)
                H2_p = mu_p_temp2.entropy()

                mu_u_temp2 = mu_u.marginal(
                    elimvars_in_node[v_w_ind + 1:])  # P(xi+1 , xi+2 ~)
                if type(mu_u_temp2) is not Factor:
                    mu_u_temp2 = Factor({}, mu_u_temp2)
                if np.all(mu_u_temp2.t == 0):
                    H2_u = 0.0
                else:
                    H2_u = mu_u_temp2.entropy()
            else:
                H2_p = 0.0
                H2_u = 0.0

            wgts.append(self.mg.message_graph.node[node]['w'][v_w])
            H_p_cond = H1_p - H2_p
            H_u_cond = H1_u - H2_u
            Hcond_p.append(H_p_cond)  # conditional entropy
            Hcond_u.append(H_u_cond)  # conditional entropy

        Hbar_u = 0.0
        Hbar_p = 0.0
        for m, node in enumerate(nodes):
            Hbar_u += wgts[m] * Hcond_u[m] * self._eval_util_bound_norms(node)
            Hbar_p += wgts[m] * Hcond_p[m] * (
                self._eval_util_bound_norms() -
                self._eval_util_bound_norms(node))

        gradient = []
        for m, node in enumerate(nodes):
            grad = Hcond_u[m] * self._eval_util_bound_norms(node) - Hbar_u
            grad += Hcond_p[m] * (self._eval_util_bound_norms() -
                                  self._eval_util_bound_norms(node)) - Hbar_p
            grad *= wgts[m]
            grad *= self._eval_prob_bound_norms(
            )  # todo pull out this term with objective?
            gradient.append(grad)

        if self.verbose:
            print('wgts:', wgts)
            print('Hcond_p:', Hcond_p)
            print('Hcond_u:', Hcond_p)
            print('Hbar_u:', Hbar_u)
            print('Hbar_p:', Hbar_p)
            print('grad:', gradient)

        if debug:
            assert np.all(np.isfinite(gradient))
        return gradient
예제 #9
0
def get_const_factor_with_v(v, variables, is_log):
    """ return a constant factor with scope v, all ones (in linear) or all zero (in log) """
    for var in variables:
        if var.label == v:
            return Factor({var}, 0.0) if is_log else Factor({var}, 1.0)