def get_sobol_indices(coefficients, indices, max_order=2): num_terms, num_qoi = coefficients.shape variance = np.zeros(num_qoi) assert num_terms == indices.shape[1] interactions = dict() interaction_values = [] interaction_terms = [] kk = 0 for ii in range(num_terms): index = indices[:, ii] var_contribution = coefficients[ii, :]**2 non_constant_vars = np.where(index > 0)[0] key = hash_array(non_constant_vars) if len(non_constant_vars) > 0: variance += var_contribution if len(non_constant_vars) > 0 and len(non_constant_vars) <= max_order: if key in interactions: interaction_values[interactions[key]] += var_contribution else: interactions[key] = kk interaction_values.append(var_contribution) interaction_terms.append(non_constant_vars) kk += 1 interaction_terms = np.asarray(interaction_terms).T interaction_values = np.asarray(interaction_values) return interaction_terms, interaction_values / variance
def get_coefficients_for_plotting(pce, qoi_idx): coeff = pce.get_coefficients()[:, qoi_idx] indices = pce.indices.copy() assert coeff.shape[0] == indices.shape[1] num_vars = pce.num_vars() degree = -1 indices_dict = dict() max_degree = indices.sum(axis=0).max() for ii in range(indices.shape[1]): key = hash_array(indices[:, ii]) indices_dict[key] = ii i = 0 degree_breaks = [] coeff_sorted = [] degree_indices_set = np.empty((num_vars, 0)) for degree in range(max_degree+1): nterms = nchoosek(num_vars+degree, degree) if nterms < 1e6: degree_indices = compute_hyperbolic_level_indices( num_vars, degree, 1.) else: 'Could not plot coefficients of terms with degree >= %d' % degree break degree_indices_set = np.hstack((degree_indices_set, indices)) for ii in range(degree_indices.shape[1]-1, -1, -1): index = degree_indices[:, ii] key = hash_array(index) if key in indices_dict: coeff_sorted.append(coeff[indices_dict[key]]) else: coeff_sorted.append(0.0) i += 1 degree_breaks.append(i) return np.array(coeff_sorted), degree_indices_set, degree_breaks
def multiply_multivariate_polynomials(indices1, coeffs1, indices2, coeffs2): """ TODO: instead of using dictionary to colect terms consider using unique_indices,repeated_idx=np.unique( indices[active_idx,:],axis=1,return_inverse=True) as is done in multivariate_polynomials.conditional_moments_of_polynomial_chaos_expansion. Choose which one is faster Parameters ---------- index : multidimensional index multidimensional index specifying the polynomial degree in each dimension Returns ------- """ num_vars = indices1.shape[0] num_indices1 = indices1.shape[1] num_indices2 = indices2.shape[1] assert num_indices1 == coeffs1.shape[0] assert num_indices2 == coeffs2.shape[0] assert num_vars == indices2.shape[0] indices_dict = dict() max_num_indices = num_indices1 * num_indices2 indices = np.empty((num_vars, max_num_indices), int) coeffs = np.empty((max_num_indices), float) kk = 0 for ii in range(num_indices1): index1 = indices1[:, ii] coeff1 = coeffs1[ii] for jj in range(num_indices2): index = index1 + indices2[:, jj] key = hash_array(index) coeff = coeff1 * coeffs2[jj] if key in indices_dict: coeffs[indices_dict[key]] += coeff else: indices_dict[key] = kk indices[:, kk] = index coeffs[kk] = coeff kk += 1 indices = indices[:, :kk] coeffs = coeffs[:kk] return indices, coeffs
def group_like_terms(coeffs, indices): if coeffs.ndim == 1: coeffs = coeffs[:, np.newaxis] num_vars, num_indices = indices.shape indices_dict = {} for ii in range(num_indices): key = hash_array(indices[:, ii]) if not key in indices_dict: indices_dict[key] = [coeffs[ii], ii] else: indices_dict[key] = [indices_dict[key][0] + coeffs[ii], ii] new_coeffs = np.empty((len(indices_dict), coeffs.shape[1])) new_indices = np.empty((num_vars, len(indices_dict)), dtype=int) ii = 0 for key, item in indices_dict.items(): new_indices[:, ii] = indices[:, item[1]] new_coeffs[ii] = item[0] ii += 1 return new_coeffs, new_indices
def add_polynomials(indices_list, coeffs_list): """ Add many polynomials together. Example: p1 = x1**2+x2+x3, p2 = x2**2+2*x3 p3 = p1+p2 return the degrees of each term in the the polynomial p3 = x1**2+x2+3*x3+x2**2 [2, 1, 1, 2] and the coefficients of each of these terms [1., 1., 3., 1.] Parameters ---------- indices_list : list [np.ndarray (num_vars,num_indices_i)] List of polynomial indices. indices_i may be different for each polynomial coeffs_list : list [np.ndarray (num_indices_i,num_qoi)] List of polynomial coefficients. indices_i may be different for each polynomial. num_qoi must be the same for each list element. Returns ------- indices: np.ndarray (num_vars,num_terms) the polynomial indices of the polynomial obtained from summing the polynomials. This will be the union of the indices of the input polynomials coeffs: np.ndarray (num_terms,num_qoi) the polynomial coefficients of the polynomial obtained from summing the polynomials """ num_polynomials = len(indices_list) assert num_polynomials == len(coeffs_list) indices_dict = dict() indices = [] coeff = [] ii = 0 kk = 0 for jj in range(indices_list[ii].shape[1]): assert coeffs_list[ii].ndim == 2 assert coeffs_list[ii].shape[0] == indices_list[ii].shape[1] index = indices_list[ii][:, jj] indices_dict[hash_array(index)] = kk indices.append(index) coeff.append(coeffs_list[ii][jj, :].copy()) kk += 1 for ii in range(1, num_polynomials): #print indices_list[ii].T,num_polynomials assert coeffs_list[ii].ndim == 2 assert coeffs_list[ii].shape[0] == indices_list[ii].shape[1] for jj in range(indices_list[ii].shape[1]): index = indices_list[ii][:, jj] key = hash_array(index) if key in indices_dict: nn = indices_dict[key] coeff[nn] += coeffs_list[ii][jj, :] else: indices_dict[key] = kk indices.append(index) coeff.append(coeffs_list[ii][jj, :].copy()) kk += 1 indices = np.asarray(indices).T coeff = np.asarray(coeff) return indices, coeff