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