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 factor_marginalize(factor, var): """ Returns factor after variables in var have been marginalized out. Args: factor: factor to be marginalized var: numpy array of variables to be marginalized over Returns: marginalized factor """ out = copy.deepcopy(factor) """ YOUR CODE HERE HINT: Use the code from lab1 """ out.var = np.setdiff1d(factor.var, var) map_out = np.argmax(out.var[:, None] == factor.var[None, :], axis=-1) out.card = factor.card[map_out] out.val = np.zeros(np.prod(out.card)) assignments_in = index_to_assignment(np.arange(int(np.prod(factor.card))), factor.card) idx_out = assignment_to_index(assignments_in[:, map_out], out.card) for i in range(out.val.shape[0]): out.val[i] = np.sum(factor.val[idx_out == i]) """ END YOUR CODE HERE """ return out
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_product(A, B): """Compute product of two factors. Suppose A = phi(X_1, X_2), B = phi(X_2, X_3), the function should return phi(X_1, X_2, X_3) """ 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) out.val = A.val[idxA] * B.val[idxB] """ YOUR CODE HERE You should populate the .val field with the factor product Hint: The code for this function should be very short (~1 line). Try to understand what the above lines are doing, in order to implement subsequent parts. """ return out
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
def factor_max_marginalize(factor, var): """Marginalize over a list of variables by taking the max. Args: factor (Factor): Input factor var (List): Variable to marginalize out. Returns: out: Factor with variables in 'var' marginalized out. The factor's .val_argmax field should be a list of dictionary that keep track of the maximizing values of the marginalized variables. e.g. when out.val_argmax[i][j] = k, this means that when assignments of out is index_to_assignment[i], variable j has a maximizing value of k. See test_lab1.py::test_factor_max_marginalize() for an example. """ out = Factor() """ YOUR CODE HERE Marginalize out the variables given in var. You should make use of val_argmax to keep track of the location with the maximum probability. """ 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 = [] out.val_argmax = [] for single_var in var: index.append(np.where(factor.var == single_var)) delete_assignment = np.delete(assignment, index, axis=1) out.val = np.zeros(np.prod(out.card)) for i in np.unique(delete_assignment, axis=0): index_set = np.array(np.where(np.all(i == delete_assignment, axis=1))) index_set_max_index = np.argmax(factor.val[index_set]) max_index_assignment = index_set[:, index_set_max_index][0] single_assignment = assignment_to_index(i, out.card) out.val[single_assignment] = factor.val[max_index_assignment] temp_dict = {} for single_var in var: index = np.argwhere(factor.var == single_var)[0][0] temp_dict[single_var] = assignment[max_index_assignment][index] out.val_argmax.append(temp_dict) return out