def test_get_multiplied(self): factor1 = Factor([self.random_variables[0], self.random_variables[1]]) factor2 = Factor([self.random_variables[1], self.random_variables[2]]) factor1.add_value([1, 3], 10).add_value([1, 4], 20).add_value([2, 4], 30) factor2.add_value([3, 2], 5).add_value([4, 2], 2) product_factor = factor1.get_multiplied(factor2) self.assertEqual(product_factor.get_value({ 'x': 1, 'y': 3, 'z': 2 }), 50) self.assertEqual(product_factor.get_value({ 'x': 1, 'y': 4, 'z': 2 }), 40) self.assertEqual(product_factor.get_value({ 'x': 2, 'y': 4, 'z': 2 }), 60) self.assertEqual(product_factor.get_value({'x': 1, 'y': 5, 'z': 2}), 0) self.assertEqual(product_factor.get_value({'x': 2, 'y': 5, 'z': 2}), 0) self.assertEqual(product_factor.get_value({'x': 2, 'y': 5, 'z': 2}), 0)
def generate_complete(nb_vars, delta): model = GraphicalModel() interaction = delta * np.random.uniform( -1.0, 1.0, nb_vars*(nb_vars-1)) bias = np.random.uniform(-0.1, 0.1, [nb_vars]) for i in range(nb_vars): model.add_variable(ith_object_name('V', i)) for i in range(nb_vars): for j in range(i+1, nb_vars): beta = interaction[i * nb_vars + j ] log_values = np.array([beta, -beta, -beta, beta]).reshape([2,2]) factor = Factor( name = ijth_object_name('F', i, j), variables = [ith_object_name('V', i), ith_object_name('V', j)], log_values = log_values) model.add_factor(factor) for i in range(nb_vars): factor = Factor( name = ith_object_name('B', i), variables = [ith_object_name('V', i)], log_values = np.array([bias[i], -bias[i]])) model.add_factor(factor) return model
def test_add_factors(self): graphical_model = GraphicalModel() factor1 = Factor([RandomVariable('x', (1, 2))]) factor2 = Factor( [RandomVariable('y', (2, 3, 4)), RandomVariable('z', (2, ))]) factor3 = Factor( [RandomVariable('x', (1, 2)), RandomVariable('z', (2, ))]) graphical_model.add_factor(factor1).add_factor(factor2).add_factor( factor3) print(graphical_model.random_variables)
def test_cycle(self): xy_factor = Factor( [self.random_variables[0], self.random_variables[1]]) xz_factor = Factor( [self.random_variables[0], self.random_variables[2]]) yz_factor = Factor( [self.random_variables[1], self.random_variables[2]]) graphical_model = GraphicalModel() graphical_model.add_factor(xy_factor).add_factor(xz_factor).add_factor( yz_factor) marginal_inference = MpMarginalInference(graphical_model) marginal_inference.get_marginal_factor([self.random_variables[0]], {})
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.random_variables = [ RandomVariable('a', (1, 2)), RandomVariable('b', (3, 4, 5)), RandomVariable('c', (2, )), RandomVariable('d', (1, 2, 3, 4, 5, 6)), ] self.factors = [ Factor([self.random_variables[0]]), Factor([self.random_variables[0], self.random_variables[1]]), Factor([self.random_variables[1], self.random_variables[2]]) ]
def _generate_two_variables_model(self): x_factor = Factor([self.random_variables[0]]) x_factor.add_value([1], 1).add_value([2], 2) y_factor = Factor([self.random_variables[1]]) y_factor.add_value([3], 5).add_value([4], 10).add_value([5], 15) xy_factor = Factor( [self.random_variables[0], self.random_variables[1]]) xy_factor.add_value([1, 3], 10).add_value([1, 4], 10).add_value([2, 5], 20) graphical_model = GraphicalModel() graphical_model.add_factor(x_factor).add_factor(y_factor).add_factor( xy_factor) return graphical_model
def _generate_three_variables_model(self): xy_factor = Factor( [self.random_variables[0], self.random_variables[1]]) xy_factor.add_value([1, 3], 5).add_value([1, 4], 20).add_value([2, 5], 30) xz_factor = Factor( [self.random_variables[0], self.random_variables[2]]) xz_factor.add_value([1, 2], 10).add_value([2, 2], 20) yz_factor = Factor( [self.random_variables[1], self.random_variables[2]]) yz_factor.add_value([3, 2], 10).add_value([4, 2], 20).add_value([5, 2], 30) graphical_model = GraphicalModel() graphical_model.add_factor(xy_factor).add_factor(xz_factor).add_factor( yz_factor) return graphical_model
def _get_clique_factors(jt_cliques, factors): """ Assign node factors to cliques in the junction tree and derive the clique factors. Args: jt_cliques: list of junction tree maximal cliques e.g. [[x1, x2, x3], [x2, x3], ... ] factors: list of factors from the original graph Returns: list of clique factors where the factor(jt_cliques[i]) = clique_factors[i] """ clique_factors = [Factor() for _ in jt_cliques] """ YOUR CODE HERE """ for i in range(len(clique_factors)): jt_clique = jt_cliques[i] temp_factor = factors.copy() for factor in temp_factor: ret = list(set(jt_clique).intersection(list(factor.var))) if sorted(ret) == sorted(list(factor.var)): clique_factors[i] = factor_product(clique_factors[i], factor) factors.remove(factor) """ END YOUR CODE HERE """ assert len(clique_factors) == len( jt_cliques ), 'there should be equal number of cliques and clique factors' return clique_factors
def _update_reparameterization_for_(self, variable): belief_from_ = dict() log_average_belief = 0.0 average_weight = 0.0 for rvar in self.variables_replicated_from_[variable]: belief_from_[rvar] = self.get_marginals_upper_to_(rvar) belief_from_[rvar].marginalize_except_([rvar]) belief_from_[rvar].variables = [variable] belief_from_[rvar].normalize() log_average_belief = ( log_average_belief + self.holder_weights_for_[rvar] * belief_from_[rvar].log_values) converge_flag = True for rvar in self.variables_replicated_from_[variable]: if np.sum( np.abs(-belief_from_[rvar].log_values + log_average_belief)) > 1e-2: converge_flag = False temp_log_val = (self.holder_weights_for_[rvar]) * ( -belief_from_[rvar].log_values + log_average_belief) temp = Factor("", [rvar], log_values=temp_log_val) self.factor_upper_to_[rvar].product(temp) return converge_flag
def factor_marginalize(factor, var): """Sums over a list of variables. Args: factor (Factor): Input factor var (List): Variables to marginalize out Returns: out: Factor with variables in 'var' marginalized out. """ out = Factor() """ YOUR CODE HERE Marginalize out the variables given in var """ out.var = np.setxor1d(factor.var, np.array(var)) for out_var in out.var: index = np.where(factor.var == out_var) out.card = np.append(out.card, factor.card[index]) assignment = factor.get_all_assignments() index = [] for single_var in var: index.append(np.where(factor.var == single_var)) assignment = np.delete(assignment, index, axis=1) out.val = np.zeros(np.prod(out.card)) for i in np.unique(assignment, axis=0): index_set = np.array(np.where(np.all(i == assignment, axis=1))) single_assignment = assignment_to_index(i, out.card) out.val[single_assignment] = np.sum(factor.val[index_set]) return out
def factor_sum(A, B): """Same as factor_product, but sums instead of multiplies """ if A.is_empty(): return B if B.is_empty(): return A # Create output factor. Variables should be the union between of the # variables contained in the two input factors out = Factor() out.var = np.union1d(A.var, B.var) # Compute mapping between the variable ordering between the two factors # and the output to set the cardinality out.card = np.zeros(len(out.var), np.int64) mapA = np.argmax(out.var[None, :] == A.var[:, None], axis=-1) mapB = np.argmax(out.var[None, :] == B.var[:, None], axis=-1) out.card[mapA] = A.card out.card[mapB] = B.card # For each assignment in the output, compute which row of the input factors # it comes from out.val = np.zeros(np.prod(out.card)) assignments = out.get_all_assignments() idxA = assignment_to_index(assignments[:, mapA], A.card) idxB = assignment_to_index(assignments[:, mapB], B.card) """ YOUR CODE HERE You should populate the .val field with the factor sum. The code for this should be very similar to the factor_product(). """ out.val = A.val[idxA] + B.val[idxB] return out
def test_get_max_marginalized(self): init_factor = Factor(self.random_variables) init_factor.add_value([1, 3, 2], 10).add_value([1, 4, 2], 5).add_value([1, 5, 2], 2) init_factor.add_value([2, 4, 2], 20).add_value([2, 5, 2], 30) factor, assignment = init_factor.get_max_marginalized( [self.random_variables[0]]) marginalized_variables = [ self.random_variables[1], self.random_variables[2] ] self.assertEqual(20, factor.get_value({'y': 4, 'z': 2})) self.assertEqual(30, factor.get_value({'y': 5, 'z': 2})) self.assertEqual(10, factor.get_value({'y': 3, 'z': 2})) variable_permutation = list( map(lambda x: factor.random_variables.index(x), marginalized_variables)) mapped_assignment = {} for key, value in assignment.items(): mapped_key = tuple( map(lambda x: key[variable_permutation[x]], range(len(key)))) mapped_assignment[mapped_key] = value self.assertEqual({ (3, 2): (1, ), (4, 2): (2, ), (5, 2): (2, ) }, mapped_assignment) factor, assignment = init_factor.get_max_marginalized( self.random_variables) self.assertEqual(30, factor.get_value([])) self.assertEqual({(): (2, 5, 2)}, assignment)
def _sample_step(nodes, proposal_factors): """ Performs one iteration of importance sampling where it should sample a sample for each node. The sampling should be done in topological order. Args: nodes: numpy array of nodes. nodes are sampled in the order specified in nodes proposal_factors: dictionary of proposal factors where proposal_factors[1] returns the sample distribution for node 1 Returns: dictionary of node samples where samples[1] return the scalar sample for node 1. """ samples = {} """ YOUR CODE HERE: Use np.random.choice """ evidence = {} fac = Factor() for node in nodes: fac = factor_evidence(proposal_factors[node], evidence) n = np.random.choice(fac.card[0], 1, p=fac.val) samples[node] = n evidence[node] = n """ END YOUR CODE HERE """ assert len(samples.keys()) == len(nodes) return samples
def test_two_variables(self): x_factor = Factor([self.random_variables[0]]) x_factor.add_value([1], 1).add_value([2], 2) y_factor = Factor([self.random_variables[1]]) y_factor.add_value([3], 5).add_value([4], 10).add_value([5], 15) xy_factor = Factor( [self.random_variables[0], self.random_variables[1]]) xy_factor.add_value([1, 3], 10).add_value([1, 4], 10).add_value([2, 5], 20) graphical_model = GraphicalModel() graphical_model.add_factor(x_factor).add_factor(y_factor).add_factor( xy_factor) marginal_inference = MpMarginalInference(graphical_model) marginal_factor = marginal_inference.get_marginal_factor( self.random_variables[0]) self.assertAlmostEqual(0.2, marginal_factor.get_value([1])) self.assertAlmostEqual(0.8, marginal_factor.get_value([2]))
def test_get_value(self): factor = Factor(self.random_variables) factor.add_value([1, 3, 2], 10).add_value([2, 4, 2], 20).add_value([2, 5, 2], 30) self.assertEqual(factor.get_value([1, 3, 2]), 10) self.assertEqual(factor.get_value([2, 4, 2]), 20) self.assertEqual(factor.get_value([2, 5, 2]), 30) self.assertEqual(factor.get_value([1, 4, 2]), 0) self.assertEqual(factor.get_value([2, 3, 2]), 0)
def _makeFactor(self, node, observed, log): nodes = np.array([node] + self.network.parents[node]) probs = self.network.probabilities[node].values nodes_in_observed = nodes[np.in1d(nodes, observed.keys())] if nodes_in_observed.size > 0: if nodes.size > nodes_in_observed.size: factor = Factor(nodes, probs, self.network) log.write("\nReduce\n") log.write(str(factor)) log.write("Evidence: " + str(observed) + "\n\n") return factor.reduce(nodes_in_observed, observed) else: return Factor() else: return Factor(nodes, probs, self.network)
def test_marginal_y_three_variables(self): x_factor = Factor([self.random_variables[0]]) x_factor.add_value([1], 1).add_value([2], 2) xy_factor = Factor( [self.random_variables[0], self.random_variables[1]]) xy_factor.add_value([1, 3], 5).add_value([1, 4], 20).add_value([2, 5], 30) xz_factor = Factor( [self.random_variables[0], self.random_variables[2]]) xz_factor.add_value([1, 2], 12).add_value([2, 2], 20) graphical_model = GraphicalModel() graphical_model.add_factor(x_factor).add_factor(xy_factor).add_factor( xz_factor) marginal_inference = MpMarginalInference(graphical_model) marginal_factor = marginal_inference.get_marginal_factor( self.random_variables[1]) self.assertAlmostEqual(0.04, marginal_factor.get_value([3])) self.assertAlmostEqual(0.16, marginal_factor.get_value([4])) self.assertAlmostEqual(0.8, marginal_factor.get_value([5]))
def test_get_constant_multiplied(self): factor = Factor(self.random_variables) factor.add_value([1, 3, 2], 10).add_value([2, 4, 2], 20).add_value([2, 5, 2], 30) factor = factor.get_constant_multiplied(2) self.assertEqual(factor.get_value([1, 3, 2]), 20) self.assertEqual(factor.get_value([2, 4, 2]), 40) self.assertEqual(factor.get_value([2, 5, 2]), 60) self.assertEqual(factor.get_value([1, 4, 2]), 0) self.assertEqual(factor.get_value([2, 3, 2]), 0)
def generate_grid(nb_vars, delta): model = GraphicalModel() grid_size = int(nb_vars**0.5) interaction = delta * np.random.uniform(-1.0, 1.0, 2*grid_size*(grid_size-1)) bias = np.random.uniform(-0.1, 0.1, [grid_size,grid_size]) for i in range(grid_size): for j in range(grid_size): model.add_variable(ijth_object_name('V', i,j)) edge_set = [] for x in range(grid_size*grid_size): q, m = divmod(x, grid_size) if m != grid_size-1: edge_set.append([x,x+1]) if q != grid_size-1: edge_set.append([x,x+grid_size]) for i, e in enumerate(edge_set): beta = interaction[i] q1, m1 = divmod(e[0], grid_size) V1 = ijth_object_name('V', q1,m1) q2, m2 = divmod(e[1],grid_size) V2 = ijth_object_name('V', q2,m2) log_values = np.array([beta, -beta, -beta, beta]).reshape([2,2]) factor = Factor(name = ith_object_name('F', i), variables = [V1, V2], log_values = log_values) model.add_factor(factor) for i in range(grid_size): for j in range(grid_size): log_values = np.array([bias[i,j], -bias[i,j]]) model.add_factor(Factor(name = ith_object_name('B', i*grid_size + j), variables = [ijth_object_name('V', i,j)], log_values = log_values)) return model
def test_get_inverse(self): factor = Factor(self.random_variables) factor.add_value([1, 3, 2], 10).add_value([2, 4, 2], 20).add_value([2, 5, 2], 30) factor = factor.get_inverse() self.assertEqual(factor.get_value([1, 3, 2]), 1 / 10) self.assertEqual(factor.get_value([2, 4, 2]), 1 / 20) self.assertEqual(factor.get_value([2, 5, 2]), 1 / 30) self.assertEqual(factor.get_value([1, 4, 2]), float("inf")) self.assertEqual(factor.get_value([2, 3, 2]), float("inf"))
def compute_marginals_naive(V, factors, evidence): """Computes the marginal over a set of given variables Args: V (int): Single Variable to perform inference on factors (List[Factor]): List of factors representing the graphical model evidence (Dict): Observed evidence. evidence[k] = v indicates that variable k has the value v. Returns: Factor representing the marginals """ output = Factor() # compute the joint distribution joint_distribution = compute_joint_distribution(factors) variables = factors[0].var for factor_index in range(1, len(factors)): variables = np.union1d(variables, factors[factor_index].var) evidence_keys = list(evidence.keys()) evidence_keys.append(V) variables_need_marginalize = np.setxor1d(variables, np.array(evidence_keys)) after_marginalize = factor_marginalize(joint_distribution, variables_need_marginalize) after_observe = observe_evidence([after_marginalize], evidence)[0] ##Normalize normalize_sum = np.sum(after_observe.val) after_observe.val /= normalize_sum # delete evidence, evidence value inequal to evidence needs to be delete, also card, also var assignment = after_observe.get_all_assignments() for evid in evidence: temp_value = evidence[evid] delete_index = np.array(np.where(after_observe.var == evid))[0][0] assignment_delete_index = np.array( np.where(assignment[:, delete_index] != temp_value)) after_observe.var = np.delete(after_observe.var, delete_index) after_observe.card = np.delete(after_observe.card, delete_index) after_observe.val = np.delete(after_observe.val, assignment_delete_index, axis=0) assignment = np.delete(assignment, assignment_delete_index, axis=0) assignment = np.delete(assignment, delete_index, axis=1) output = after_observe """ YOUR CODE HERE Compute the marginal. Output should be a factor. Remember to normalize the probabilities! """ return output
def test_get_normalized(self): factor = Factor(self.random_variables) factor.add_value([1, 3, 2], 10).add_value([2, 4, 2], 20).add_value([2, 5, 2], 30) factor = factor.get_normalized() self.assertAlmostEquals(1 / 6, factor.get_value([1, 3, 2])) self.assertAlmostEquals(1 / 3, factor.get_value([2, 4, 2])) self.assertAlmostEquals(1 / 2, factor.get_value([2, 5, 2])) self.assertAlmostEquals(0, factor.get_value([1, 4, 2])) self.assertAlmostEquals(0, factor.get_value([1, 5, 2])) self.assertAlmostEquals(0, factor.get_value([2, 3, 2]))
def test_get_sum_marginalized(self): init_factor = Factor(self.random_variables) init_factor.add_value([1, 3, 2], 10).add_value([1, 4, 2], 5).add_value([1, 5, 2], 2) init_factor.add_value([2, 4, 2], 20).add_value([2, 5, 2], 30) factor = init_factor.get_sum_marginalized([self.random_variables[0]]) self.assertEqual(25, factor.get_value({'y': 4, 'z': 2})) self.assertEqual(32, factor.get_value({'y': 5, 'z': 2})) self.assertEqual(10, factor.get_value({'y': 3, 'z': 2})) factor = init_factor.get_sum_marginalized(self.random_variables) self.assertEqual(67, factor.get_value([]))
def cal_prop_dist(nodes, proposal_factors): # I choose factors in the following way: factor.var = [0,1,2] means p(x2|x0, x1). So when we want to choose q(x2), \ # we just need to find p(x2|x0, x1) = q(x2), we use factor.var[-1] == node fac = Factor() factors = proposal_factors.copy() for node in nodes: for index in factors: if node == factors[index].var[-1]: fac = factor_product(fac, factors[index]) factors.pop(index) break return fac
def ComputeMarginal(jt_cliques, jt_edges, jt_clique_factors, msg): output = [] for i in range(len(jt_cliques)): Neighbors_i = Find_Neighbors(jt_edges, i) msg_product = Factor() for j in range(len(Neighbors_i)): msg_product = factor_product(msg_product, msg[Neighbors_i[j]][i]) msg_product = factor_product(jt_clique_factors[i], msg_product) normalize_sum = np.sum(msg_product.val) msg_product.val = msg_product.val / (normalize_sum * 1.0) output.append(msg_product) return output
def main(): f1 = Factor(['Trav'], [['t', 'f']], [0.05, 0.95]) f2 = Factor(['Fraud', 'Trav'], [['t', 't', 'f', 'f'], ['t', 'f', 't', 'f']], [0.01, 0.004, 0.99, 0.996]) f3 = Factor(['FP', 'Fraud', 'Trav'], [['t', 't', 't', 't', 'f', 'f', 'f', 'f'], ['t', 't', 'f', 'f', 't', 't', 'f', 'f'], ['t', 'f', 't', 'f', 't', 'f', 't', 'f']], [0.9, 0.1, 0.9, 0.01, 0.1, 0.9, 0.1, 0.99]) f4 = Factor(['IP', 'Fraud', 'OC'], [['t', 't', 't', 't', 'f', 'f', 'f', 'f'], ['t', 't', 'f', 'f', 't', 't', 'f', 'f'], ['t', 'f', 't', 'f', 't', 'f', 't', 'f']], [0.02, 0.011, 0.01, 0.001, 0.98, 0.989, 0.99, 0.999]) f5 = Factor(['CRP', 'OC'], [['t', 't', 'f', 'f'], ['t', 'f', 't', 'f']], [0.1, 0.001, 0.9, 0.999]) f6 = Factor(['OC'], [['t', 'f']], [0.6, 0.4]) factorList = [f1, f2, f3, f4, f5, f6] quaryList = ['Fraud'] hiddenVariables = ['Trav', 'FP', 'Fraud', 'IP', 'OC', 'CRP'] evidenceList1 = dict(IP='t') evidenceList2 = dict(IP='t', CRP='t') Factor.inference(factorList, quaryList, hiddenVariables, evidenceList1) Factor.inference(factorList, quaryList, hiddenVariables, evidenceList2)
def generate_uai(model_name): model = GraphicalModel() model.name=model_name with open(UAI_PATH+model_name+'.uai') as f: a = f.readlines() content = [] for c in a: content.extend(c.split()) cnt = 1 nb_vars = int(content[cnt]) cardinalities = dict() for t in range(nb_vars): cnt += 1 newvar = 'V' + str(t) model.add_variable(newvar) cardinalities[newvar] = int(content[cnt]) cnt += 1 nfactors = int(content[cnt]) factor_variables = dict() for t in range(nfactors): cnt += 1 newfac_name = 'F' + str(t) factor_size = int(content[cnt]) factor_variables[newfac_name] = [] for t2 in range(factor_size): cnt += 1 factor_variables[newfac_name].append('V' + str(content[cnt])) for t in range(nfactors): cnt += 1 value_num = int(content[cnt]) newfac_name = 'F' + str(t) values = [] for vt2 in range(value_num): cnt += 1 values.append(float(content[cnt])) values = np.reshape( values, [cardinalities[var] for var in factor_variables[newfac_name]]) factor = Factor( name = newfac_name, variables = factor_variables[newfac_name], values = values) model.add_factor(factor) return model
def _get_conditional_probability(nodes, edges, factors, evidence, initial_samples, num_iterations, num_burn_in): """ Returns the conditional probability p(Xf | Xe) where Xe is the set of observed nodes and Xf are the query nodes i.e. the unobserved nodes. The conditional probability is approximated using Gibbs sampling. Args: nodes: numpy array of nodes e.g. [x1, x2, ...]. edges: numpy array of edges e.g. [i, j] implies that nodes[i] is the parent of nodes[j]. factors: dictionary of Factors e.g. factors[x1] returns the conditional probability of x1 given all other nodes. evidence: dictionary of evidence e.g. evidence[x4] returns the provided evidence for x4. initial_samples: dictionary of initial samples to initialize Gibbs sampling. num_iterations: number of sampling iterations num_burn_in: number of burn-in iterations Returns: returns Factor of conditional probability. """ assert num_iterations > num_burn_in conditional_prob = Factor() """ YOUR CODE HERE """ for factor_index in factors: factors[factor_index] = factor_evidence(factors[factor_index],evidence) remove_nodes = list(evidence.keys()) for node in remove_nodes: initial_samples.pop(node) index = np.argwhere(nodes == node) nodes = np.delete(nodes,index) total_run = num_burn_in + num_iterations sample_result = np.zeros([total_run, len(nodes)]) for i in range(total_run): initial_samples = _sample_step(nodes, factors, initial_samples) sample_result[i] = np.array(list(initial_samples.values())) # set freq dict freq = {} for i in range(len(factors[0].val)): freq[i] = 0 card = factors[0].card for i in range(num_burn_in,num_iterations): index = assignment_to_index(sample_result[i],card) freq[index] += 1 freq_arr = np.array(list(freq.values())) freq_arr = freq_arr/np.sum(freq_arr) conditional_prob.var = factors[0].var conditional_prob.card = card conditional_prob.val = freq_arr """ END YOUR CODE HERE """ return conditional_prob
def _update_mean_fields(self): variable_order = np.random.permutation(self.model.variables) for var in variable_order: next_mean_field = Factor.full_like_(self.mean_fields[var], 0.0) for fac in self.model.get_adj_factors(var): tmp = Factor(name = 'tmp', variables = [var], values = np.ones(self.model.get_cardinality_for_(var))) tmp = product_over_(tmp, *[self.mean_fields[var1] for var1 in fac.variables if var1 != var]) tmp.transpose_by_(fac.variables) tmp.log_values = fac.log_values * tmp.values next_mean_field = next_mean_field + tmp.marginalize_except_([var], inplace = False) self.mean_fields[var] = next_mean_field.exp(inplace = False).normalize(inplace = False) self.mean_fields[var].log_values = np.nan_to_num(self.mean_fields[var].log_values)
def factor_product(A, B): """ Computes the factor product of A and B e.g. A = f(x1, x2); B = f(x1, x3); out=f(x1, x2, x3) = f(x1, x2)f(x1, x3) Args: A: first Factor B: second Factor Returns: Returns the factor product of A and B """ out = Factor() """ YOUR CODE HERE, HINT: copy from lab2 part 1! """ if A.is_empty(): return B if B.is_empty(): return A out = Factor() # Set the variables of the output out.var = np.union1d(A.var, B.var) # Set the cardinality of the output out.card = np.zeros(len(out.var), np.int64) mapA = np.argmax(out.var[None, :] == A.var[:, None], axis=-1) mapB = np.argmax(out.var[None, :] == B.var[:, None], axis=-1) out.card[mapA] = A.card out.card[mapB] = B.card # Initialize the factor values to zero out.val = np.zeros(np.prod(out.card)) assignments = out.get_all_assignments() idxA = assignment_to_index(assignments[:, mapA], A.card) idxB = assignment_to_index(assignments[:, mapB], B.card) # Populate the factor values out.val = A.val[idxA] * B.val[idxB] """ END YOUR CODE HERE """ return out