// Find a point in space with high density. void TChain::find_center(double* const center, gsl_matrix *const cov, gsl_matrix *const inv_cov, double* det_cov, double dmax, unsigned int iterations) const { // Check that the matrices are the correct size /*assert(cov->size1 == N); assert(cov->size2 == N); assert(inv_cov->size1 == N); assert(inv_cov->size2 == N);*/ // Choose random point in chain as starting point gsl_rng *r; seed_gsl_rng(&r); long unsigned int index_tmp = gsl_rng_uniform_int(r, length); const double *x_tmp = get_element(index_tmp); for(unsigned int i=0; i<N; i++) { center[i] = x_tmp[i]; } // Iterate double *sum = new double[N]; double weight; for(unsigned int i=0; i<iterations; i++) { // Set mean of nearby points as center weight = 0.; for(unsigned int n=0; n<N; n++) { sum[n] = 0.; } for(unsigned int k=0; k<length; k++) { x_tmp = get_element(k); if(metric_dist2(inv_cov, x_tmp, center, N) < dmax*dmax) { for(unsigned int n=0; n<N; n++) { sum[n] += w[k] * x_tmp[n]; } weight += w[k]; } } for(unsigned int n=0; n<N; n++) { center[n] = sum[n] / (double)weight; } dmax *= 0.9; } //for(unsigned int n=0; n<N; n++) { std::cout << " " << center[n]; } //std::cout << std::endl; gsl_rng_free(r); delete[] sum; }
// Uses a variant of the bounded harmonic mean approximation to determine the evidence. // Essentially, the regulator chosen is an ellipsoid with radius nsigma standard deviations // along each principal axis. The regulator is then 1/V inside the ellipsoid and 0 without, // where V is the volume of the ellipsoid. In this form, the harmonic mean approximation // has finite variance. See Gelfand & Dey (1994) and Robert & Wraith (2009) for details. double TChain::get_ln_Z_harmonic(bool use_peak, double nsigma_max, double nsigma_peak, double chain_frac) const { // Get the covariance and determinant of the chain gsl_matrix* Sigma = gsl_matrix_alloc(N, N); gsl_matrix* invSigma = gsl_matrix_alloc(N, N); double detSigma; stats.get_cov_matrix(Sigma, invSigma, &detSigma); // Determine the center of the prior volume to use double* mu = new double[N]; if(use_peak) { // Use the peak density as the center find_center(mu, Sigma, invSigma, &detSigma, nsigma_peak, 5); //density_peak(mu, nsigma_peak); } else { // Get the mean from the stats class for(unsigned int i=0; i<N; i++) { mu[i] = stats.mean(i); } } // Sort elements in chain by distance from center, filtering out values of L which are not finite std::vector<TChainSort> sorted_indices; sorted_indices.reserve(length); unsigned int filt_length = 0; for(unsigned int i=0; i<length; i++) { if(!(isnan(L[i]) || is_inf_replacement(L[i]))) { TChainSort tmp_el; tmp_el.index = i; tmp_el.dist2 = metric_dist2(invSigma, get_element(i), mu, N); sorted_indices.push_back(tmp_el); filt_length++; } } unsigned int npoints = (unsigned int)(chain_frac * (double)filt_length); std::partial_sort(sorted_indices.begin(), sorted_indices.begin() + npoints, sorted_indices.end()); // Determine <1/L> inside the prior volume double sum_invL = 0.; double tmp_invL; double nsigma = sqrt(sorted_indices[npoints-1].dist2); unsigned int tmp_index = sorted_indices[0].index;; double L_0 = L[tmp_index]; //std::cout << "index_0 = " << sorted_indices[0].index << std::endl; for(unsigned int i=0; i<npoints; i++) { if(sorted_indices[i].dist2 > nsigma_max * nsigma_max) { nsigma = nsigma_max; break; } tmp_index = sorted_indices[i].index; tmp_invL = w[tmp_index] / exp(L[tmp_index] - L_0); //std::cout << w[tmp_index] << ", " << L[tmp_index] << std::endl; //if(isnan(tmp_invL)) { // std::cout << "\t\tL, L_0 = " << L[tmp_index] << ", " << L_0 << std::endl; //} if((tmp_invL + sum_invL > 1.e100) && (i != 0)) { nsigma = sqrt(sorted_indices[i-1].dist2); break; } sum_invL += tmp_invL; } // Determine the volume normalization (the prior volume) double V = sqrt(detSigma) * 2. * pow(SQRTPI * nsigma, (double)N) / (double)(N) / gsl_sf_gamma((double)(N)/2.); // Return an estimate of ln(Z) double lnZ = log(V) - log(sum_invL) + log(total_weight) + L_0; if(isnan(lnZ)) { std::cout << std::endl; std::cout << "NaN Error! lnZ = " << lnZ << std::endl; std::cout << "\tsum_invL = e^(" << -L_0 << ") * " << sum_invL << " = " << exp(-L_0) * sum_invL << std::endl; std::cout << "\tV = " << V << std::endl; std::cout << "\ttotal_weight = " << total_weight << std::endl; std::cout << std::endl; } else if(is_inf_replacement(lnZ)) { std::cout << std::endl; std::cout << "inf Error! lnZ = " << lnZ << std::endl; std::cout << "\tsum_invL = e^(" << -L_0 << ") * " << sum_invL << " = " << exp(-L_0) * sum_invL << std::endl; std::cout << "\tV = " << V << std::endl; std::cout << "\ttotal_weight = " << total_weight << std::endl; std::cout << "\tnsigma = " << nsigma << std::endl; std::cout << "\tIndex\tDist^2:" << std::endl; for(unsigned int i=0; i<10; i++) { std::cout << sorted_indices[i].index << "\t\t" << sorted_indices[i].dist2 << std::endl; std::cout << " "; const double *tmp_x = get_element(sorted_indices[i].index); for(unsigned int k=0; k<N; k++) { std::cout << " " << tmp_x[k]; } std::cout << std::endl; } std::cout << "mu ="; for(unsigned int i=0; i<N; i++) { std::cout << " " << mu[i]; } std::cout << std::endl; } // Cleanup gsl_matrix_free(Sigma); gsl_matrix_free(invSigma); delete[] mu; return lnZ; }
// Find a point in space with high density. void TChain::find_center(double* const center, gsl_matrix *const cov, gsl_matrix *const inv_cov, double* det_cov, double dmax, unsigned int iterations) const { // Check that the matrices are the correct size /*assert(cov->size1 == N); assert(cov->size2 == N); assert(inv_cov->size1 == N); assert(inv_cov->size2 == N);*/ // Choose random point in chain as starting point gsl_rng *r; seed_gsl_rng(&r); long unsigned int index_tmp = gsl_rng_uniform_int(r, length); const double *x_tmp = get_element(index_tmp); for(unsigned int i=0; i<N; i++) { center[i] = x_tmp[i]; } //std::cout << "center #0:"; //for(unsigned int n=0; n<N; n++) { std::cout << " " << center[n]; } //std::cout << std::endl; /*double *E_k = new double[N]; double *E_ij = new double[N*N]; for(unsigned int n1=0; n1<N; n1++) { E_k[n1] = 0.; for(unsigned int n2=0; n2<N; n2++) { E_ij[n1 + N*n2] = 0.; } }*/ // Iterate double *sum = new double[N]; double weight; for(unsigned int i=0; i<iterations; i++) { // Set mean of nearby points as center weight = 0.; for(unsigned int n=0; n<N; n++) { sum[n] = 0.; } for(unsigned int k=0; k<length; k++) { x_tmp = get_element(k); if(metric_dist2(inv_cov, x_tmp, center, N) < dmax*dmax) { for(unsigned int n=0; n<N; n++) { sum[n] += w[k] * x_tmp[n]; } weight += w[k]; // Calculate the covariance /*if(i == iterations - 1) { for(unsigned int n1=0; n1<N; n1++) { E_k[n1] += w[k] * x_tmp[n1]; for(unsigned int n2=0; n2<N; n2++) { E_ij[n1 + N*n2] += w[k] * x_tmp[n1] * x_tmp[n2]; } } }*/ } } //std::cout << "center #" << i+1 << ":"; for(unsigned int n=0; n<N; n++) { center[n] = sum[n] / (double)weight; }//std::cout << " " << center[n]; } //std::cout << " (" << weight << ")" << std::endl; dmax *= 0.9; } for(unsigned int n=0; n<N; n++) { std::cout << " " << center[n]; } std::cout << std::endl; // Calculate the covariance matrix of the enclosed points /*double tmp; for(unsigned int i=0; i<N; i++) { for(unsigned int j=i; j<N; j++) { tmp = (E_ij[i + N*j] - E_k[i]*E_k[j]/(double)weight) / (double)weight; gsl_matrix_set(cov, i, j, tmp); if(i != j) { gsl_matrix_set(cov, j, i, tmp); } } }*/ // Get the inverse of the covariance /*int s; gsl_permutation* p = gsl_permutation_alloc(N); gsl_matrix* LU = gsl_matrix_alloc(N, N); gsl_matrix_memcpy(LU, cov); gsl_linalg_LU_decomp(LU, p, &s); gsl_linalg_LU_invert(LU, p, inv_cov); // Get the determinant of the covariance *det_cov = gsl_linalg_LU_det(LU, s); // Cleanup gsl_matrix_free(LU); gsl_permutation_free(p); delete[] E_k; delete[] E_ij;*/ gsl_rng_free(r); delete[] sum; }