def tn_cdf(x, intervals, mean=0, var=1): """ CDF of a truncated normal distribution [Parameters] x <float> : Return the value at x intervals <list np.ndarray> : [L, U] or [[L1, U1], [L2, U2],...] mean <float> var <float> [Returns] float : CDF of TN """ intervals = np.array(intervals) if len(intervals.shape) == 1: intervals = np.array([intervals,]) n_intervals = len(intervals) # number of intervals sd = math.sqrt(var) # standard deviation # locate the interval that contains x for i in range(n_intervals): if intervals[i][0] <= x <= intervals[i][1]: x_index = i break else: # raise ValueError(f'tn_cdf at x={x} is undefined.\nintervals={intervals}') raise ValueError("error! x:", x, ", intervals:", intervals) norm_intervals = (intervals - mean) / sd # normalized intervals # calculate the sum(delta) in order delta = [0,] for i in range(n_intervals): diff = mp.ncdf(norm_intervals[i][1]) - mp.ncdf(norm_intervals[i][0]) delta.append(delta[-1] + diff) numerator = mp.ncdf((x-mean)/sd) - mp.ncdf(norm_intervals[x_index][0]) + delta[x_index] denominator = delta[-1] return float(numerator / denominator)
def norm_interval(lower, upper): r""" A multiprecision evaluation of .. math:: \Phi(U) - \Phi(L) Parameters ---------- lower : float The lower limit $L$ upper : float The upper limit $U$ """ if lower > 0 and upper > 0: return mp.ncdf(-lower) - mp.ncdf(-upper) else: return mp.ncdf(upper) - mp.ncdf(lower)
def pivot(A, bh, list_active_set, list_zk, list_bhz, etaj, etajTy, cov, tn_mu, type): tn_sigma = np.sqrt(np.dot(np.dot(etaj.T, cov), etaj))[0][0] z_interval = [] for i in range(len(list_active_set)): if type == 'As': if np.array_equal(np.sign(bh), np.sign(list_bhz[i])): z_interval.append([list_zk[i], list_zk[i + 1] - 1e-10]) if type == 'A': if np.array_equal(A, list_active_set[i]): z_interval.append([list_zk[i], list_zk[i + 1] - 1e-10]) new_z_interval = [] for each_interval in z_interval: if len(new_z_interval) == 0: new_z_interval.append(each_interval) else: sub = each_interval[0] - new_z_interval[-1][1] if abs(sub) < 0.01: new_z_interval[-1][1] = each_interval[1] else: new_z_interval.append(each_interval) z_interval = new_z_interval numerator = 0 denominator = 0 for each_interval in z_interval: al = each_interval[0] ar = each_interval[1] denominator = denominator + mp.ncdf((ar - tn_mu)/tn_sigma) - mp.ncdf((al - tn_mu)/tn_sigma) if etajTy >= ar: numerator = numerator + mp.ncdf((ar - tn_mu)/tn_sigma) - mp.ncdf((al - tn_mu)/tn_sigma) elif (etajTy >= al) and (etajTy < ar): numerator = numerator + mp.ncdf((etajTy - tn_mu)/tn_sigma) - mp.ncdf((al - tn_mu)/tn_sigma) if denominator != 0: return float(numerator/denominator) else: return None
def truncnorm_cdf(observed, lower, upper): r""" Compute the truncated normal distribution function. .. math:: \frac{\Phi(U) - \Phi(T)}{\Phi(U) - \Phi(L)} where $T$ is `observed`, $L$ is `lower_bound` and $U$ is `upper_bound`. Parameters ---------- observed : float lower : float upper : float Returns ------- P : float """ x, a, b = observed, lower, upper x = max(x, a) x = min(x, b) #a = max(min(a, 5), -5) #b = max(min(b, 5), -5) #x = max(min(x, 5), -5) #if a==b: # return 1. if a > 0 and b > 0: Fx, Fa, Fb = mp.ncdf(-x), mp.ncdf(-a), mp.ncdf(-b) return float((Fa - Fx) / (Fa - Fb)) else: Fx, Fa, Fb = mp.ncdf(x), mp.ncdf(a), mp.ncdf(b) return float((Fx - Fa) / (Fb - Fa))
def pivot_with_specified_interval(z_interval, etaj, etajTy, cov, tn_mu): tn_sigma = np.sqrt(np.dot(np.dot(etaj.T, cov), etaj))[0][0] numerator = 0 denominator = 0 for each_interval in z_interval: al = each_interval[0] ar = each_interval[1] denominator = denominator + mp.ncdf((ar - tn_mu)/tn_sigma) - mp.ncdf((al - tn_mu)/tn_sigma) if etajTy >= ar: numerator = numerator + mp.ncdf((ar - tn_mu)/tn_sigma) - mp.ncdf((al - tn_mu)/tn_sigma) elif (etajTy >= al) and (etajTy < ar): numerator = numerator + mp.ncdf((etajTy - tn_mu)/tn_sigma) - mp.ncdf((al - tn_mu)/tn_sigma) if denominator != 0: return float(numerator/denominator) else: return None
def f(z_interval, etajTy, mu, tn_sigma): numerator = 0 denominator = 0 for each_interval in z_interval: al = each_interval[0] ar = each_interval[1] denominator = denominator + mp.ncdf((ar - mu) / tn_sigma) - mp.ncdf( (al - mu) / tn_sigma) if etajTy >= ar: numerator = numerator + mp.ncdf((ar - mu) / tn_sigma) - mp.ncdf( (al - mu) / tn_sigma) elif (etajTy >= al) and (etajTy < ar): numerator = numerator + mp.ncdf( (etajTy - mu) / tn_sigma) - mp.ncdf((al - mu) / tn_sigma) if denominator != 0: return float(numerator / denominator) else: return np.Inf
def truncnorm_cdf(observed, lower, upper): r""" Compute the truncated normal distribution function. .. math:: \frac{\Phi(U) - \Phi(T)}{\Phi(U) - \Phi(L)} where $T$ is `observed`, $L$ is `lower_bound` and $U$ is `upper_bound`. Parameters ---------- observed : float lower : float upper : float Returns ------- P : float """ x, a, b = observed, lower, upper x = max(x, a) x = min(x, b) if a > 0 and b > 0: Fx, Fa, Fb = mp.ncdf(-x), mp.ncdf(-a), mp.ncdf(-b) return float( ( Fa - Fx ) / ( Fa - Fb ) ) else: Fx, Fa, Fb = mp.ncdf(x), mp.ncdf(a), mp.ncdf(b) return float( ( Fx - Fa ) / ( Fb - Fa ) )
def inference(data, segment_index, global_list_conditioning_matrix, sigma, first_segment_index, second_segment_index): x = np.array(data) n = len(x) x = x.reshape((x.shape[0], 1)) vector_1_C_a = np.zeros(n) vector_1_C_b = np.zeros(n) n_a = 0 n_b = 0 for i in range(n): if segment_index[i] == second_segment_index: n_a = n_a + 1 vector_1_C_a[i] = 1.0 elif segment_index[i] == first_segment_index: n_b = n_b + 1 vector_1_C_b[i] = 1.0 vector_1_C_a = np.reshape(vector_1_C_a, (vector_1_C_a.shape[0], 1)) vector_1_C_b = np.reshape(vector_1_C_b, (vector_1_C_b.shape[0], 1)) first_element = np.dot(vector_1_C_a.T, x)[0][0] second_element = np.dot(vector_1_C_b.T, x)[0][0] tau = first_element / n_a - second_element / n_b if tau < 0: temp = vector_1_C_a vector_1_C_a = vector_1_C_b vector_1_C_b = temp temp = n_a n_a = n_b n_b = temp first_element = np.dot(vector_1_C_a.T, x)[0][0] second_element = np.dot(vector_1_C_b.T, x)[0][0] tau = first_element / n_a - second_element / n_b big_sigma = sigma * sigma * np.identity(n) eta_a_b = vector_1_C_a / n_a - vector_1_C_b / n_b c_vector = np.dot(big_sigma, eta_a_b) / ( (np.dot(eta_a_b.T, np.dot(big_sigma, eta_a_b)))[0][0]) z = np.dot((np.identity(n) - np.dot(c_vector, eta_a_b.T)), x) L_prime = np.NINF U_prime = np.Inf L_tilde = np.NINF U_tilde = np.Inf list_2_range = [] range_tau_greater_than_zero = [0, np.Inf] for matrix in global_list_conditioning_matrix: c_T_A_c = np.dot(c_vector.T, np.dot(matrix, c_vector))[0][0] z_T_A_c = np.dot(z.T, np.dot(matrix, c_vector))[0][0] c_T_A_z = np.dot(c_vector.T, np.dot(matrix, z))[0][0] z_T_A_z = np.dot(z.T, np.dot(matrix, z))[0][0] a = c_T_A_c b = z_T_A_c + c_T_A_z c = z_T_A_z if -error_threshold <= a <= error_threshold: a = 0 if -error_threshold <= b <= error_threshold: b = 0 if -error_threshold <= c <= error_threshold: c = 0 x_T_A_x = np.dot(x.T, np.dot(matrix, x))[0][0] x_T_A_c = np.dot(x.T, np.dot(matrix, c_vector))[0][0] c_T_A_x = np.dot(c_vector.T, np.dot(matrix, x))[0][0] if a == 0: if b == 0: if c > 0: print('z_T_A_z > 0') elif b < 0: temporal_lower_bound = -c / b L_prime = max(L_prime, temporal_lower_bound) if L_prime > tau: print('L_prime > tau') elif b > 0: temporal_upper_bound = -c / b U_prime = min(U_prime, temporal_upper_bound) if U_prime < tau: print('U_prime < tau') else: delta = b**2 - 4 * a * c check_delta = (x_T_A_c + c_T_A_x)**2 - 4 * c_T_A_c * x_T_A_x if abs(delta - check_delta) > 1e-8: print('delta - check_delta') if -error_threshold <= delta <= error_threshold: delta = 0 if delta == 0: if a > 0: print('c_T_A_c > 0 and delta = 0') elif delta < 0: if a > 0: print('c_T_A_c > 0 and delta < 0') elif delta > 0: if a > 0: x_lower = (-b - np.sqrt(delta)) / (2 * a) x_upper = (-b + np.sqrt(delta)) / (2 * a) if x_lower > x_upper: print('x_lower > x_upper') L_tilde = max(L_tilde, x_lower) U_tilde = min(U_tilde, x_upper) else: x_1 = (-b - np.sqrt(delta)) / (2 * a) x_2 = (-b + np.sqrt(delta)) / (2 * a) x_low = min(x_1, x_2) x_up = max(x_1, x_2) list_2_range.append([x_low, x_up]) final_list_range = intersect_range([L_prime, U_prime], [L_tilde, U_tilde], range_tau_greater_than_zero, list_2_range) if len(final_list_range) == 0: print('NO SOLUTION') return None numerator = 0 denominator = 0 tn_sigma = np.sqrt(np.dot(eta_a_b.T, np.dot(big_sigma, eta_a_b))[0][0]) for each_final_range in final_list_range: al = each_final_range[0] ar = each_final_range[1] denominator = denominator + (mp.ncdf(ar / tn_sigma) - mp.ncdf(al / tn_sigma)) if tau >= ar: numerator = numerator + (mp.ncdf(ar / tn_sigma) - mp.ncdf(al / tn_sigma)) elif (tau >= al) and (tau < ar): numerator = numerator + (mp.ncdf(tau / tn_sigma) - mp.ncdf(al / tn_sigma)) if denominator != 0: F = numerator / denominator return 1 - F else: print('denominator = 0', final_list_range, tau, tn_sigma) return None
def Phi(x): return( mp.ncdf(x) )
def inference(opt_funct_set, opt_funct, eta_vec, eta_T_x, cov, n): # big_sigma = sigma * sigma * np.identity(n) tn_sigma = np.sqrt(np.dot(eta_vec.T, np.dot(cov, eta_vec))[0][0]) list_interval = [] for k, func_cost in opt_funct_set.items(): a = func_cost[0] - opt_funct[0] b = func_cost[1] - opt_funct[1] c = func_cost[2] - opt_funct[2] a = check_zero(a) b = check_zero(b) c = check_zero(c) if (a == 0) and (b != 0): print('a == 0 and b != 0') if a == 0: continue # c = c - cost x_1, x_2 = quadratic_solver(a, b, c) if (x_1 is None) and (x_2 is None): if a < 0: print('negative a') continue elif x_1 == x_2: if a > 0: list_interval.append([np.NINF, x_1]) elif a < 0: list_interval.append([x_2, np.Inf]) else: if a > 0: list_interval.append([x_1, x_2]) elif a < 0: list_interval.append([np.NINF, x_1]) list_interval.append([x_2, np.Inf]) sorted_list_interval = sorted(list_interval) union_interval = [sorted_list_interval[0]] for element in sorted_list_interval: no_of_ranges, returned_interval = union(union_interval[-1], element) if no_of_ranges == 2: union_interval[-1] = returned_interval[0] union_interval.append(returned_interval[1]) else: union_interval[-1] = returned_interval z_interval = [[np.NINF, union_interval[0][0]]] for i in range(len(union_interval) - 1): z_interval.append([union_interval[i][1], union_interval[i + 1][0]]) z_interval.append([union_interval[-1][1], np.Inf]) # print(z_interval) negative_eta = - abs(eta_T_x) positive_eta = abs(eta_T_x) numerator_1 = 0 numerator_2 = 0 denominator = 0 for each_interval in z_interval: al = each_interval[0] ar = each_interval[1] denominator = denominator + (mp.ncdf(ar / tn_sigma) - mp.ncdf(al / tn_sigma)) if negative_eta >= ar: numerator_1 = numerator_1 + (mp.ncdf(ar / tn_sigma) - mp.ncdf(al / tn_sigma)) elif (negative_eta >= al) and (negative_eta < ar): numerator_1 = numerator_1 + (mp.ncdf(negative_eta / tn_sigma) - mp.ncdf(al / tn_sigma)) if positive_eta >= ar: numerator_2 = numerator_2 + (mp.ncdf(ar / tn_sigma) - mp.ncdf(al / tn_sigma)) elif (positive_eta >= al) and (positive_eta < ar): numerator_2 = numerator_2 + (mp.ncdf(positive_eta / tn_sigma) - mp.ncdf(al / tn_sigma)) if denominator != 0: p_value = numerator_1 / denominator + (1 - numerator_2 / denominator) return float(p_value) else: return None