void Stabilisator::update_pi(CplexSolver & solver, DoubleVector const & pi) { DoubleVector rc; solver.rc(rc); _pi_bar = pi; int n_rows((int) _pi_bar.size()); // std::cout << "avg = " << avg / _pi_bar.size() << std::endl; _dual_cost.assign(4 * _pi_bar.size(), 0); _cost.assign(4 * _pi_bar.size(), 0); _indexes.assign(4 * _pi_bar.size(), 0); int index(-1); for (int row(0); row < n_rows; ++row) { _cost[++index] = gamma1(row); _dual_cost[index] = dseta_m(); _indexes[index] = index; _cost[++index] = delta1(row); _dual_cost[index] = epsilon_m(); _indexes[index] = index; _cost[++index] = -delta2(row); _dual_cost[index] = epsilon_p(); _indexes[index] = index; _cost[++index] = -gamma2(row); _dual_cost[index] = dseta_p(); _indexes[index] = index; } solver.chgObj(_indexes, _cost); }
std::string ThreeSstarCoeffs::str() const { std::stringstream ss; for (int i=0; i<nb_stages(); ++i) { ss << std::setw(2) << i << ": " << std::setw(9) << delta(i) << std::setw(9) << beta(i) << std::setw(9) << gamma1(i) << std::setw(9) << gamma2(i) << std::setw(9) << gamma3(i); ss << std::endl; } return ss.str(); }
RcppExport SEXP nsem3b(SEXP data, SEXP theta, SEXP Sigma, SEXP modelpar, SEXP control ) { // srand ( time(NULL) ); /* initialize random seed: */ Rcpp::NumericVector Theta(theta); Rcpp::NumericMatrix D(data); unsigned nobs = D.nrow(), k = D.ncol(); mat Data(D.begin(), nobs, k, false); // Avoid copying Rcpp::NumericMatrix V(Sigma); mat S(V.begin(), V.nrow(), V.ncol()); S(0,0) = 1; mat iS = inv(S); double detS = det(S); Rcpp::List Modelpar(modelpar); // Rcpp::IntegerVector _nlatent = Modelpar["nlatent"]; unsigned nlatent = _nlatent[0]; Rcpp::IntegerVector _ny0 = Modelpar["nvar0"]; unsigned ny0 = _ny0[0]; Rcpp::IntegerVector _ny1 = Modelpar["nvar1"]; unsigned ny1 = _ny1[0]; Rcpp::IntegerVector _ny2 = Modelpar["nvar2"]; unsigned ny2 = _ny2[0]; Rcpp::IntegerVector _npred0 = Modelpar["npred0"]; unsigned npred0 = _npred0[0]; Rcpp::IntegerVector _npred1 = Modelpar["npred1"]; unsigned npred1 = _npred1[0]; Rcpp::IntegerVector _npred2 = Modelpar["npred2"]; unsigned npred2 = _npred2[0]; Rcpp::List Control(control); Rcpp::NumericVector _lambda = Control["lambda"]; double lambda = _lambda[0]; Rcpp::NumericVector _niter = Control["niter"]; double niter = _niter[0]; Rcpp::NumericVector _Dtol = Control["Dtol"]; double Dtol = _Dtol[0]; rowvec mu0(ny0), lambda0(ny0); rowvec mu1(ny1), lambda1(ny1); rowvec mu2(ny2), lambda2(ny2); rowvec beta0(npred0); rowvec beta1(npred1); rowvec beta2(npred2); rowvec gamma(2); rowvec gamma2(2); unsigned pos=0; for (unsigned i=0; i<ny0; i++) { mu0(i) = Theta[pos]; pos++; } for (unsigned i=0; i<ny1; i++) { mu1(i) = Theta[pos]; pos++; } for (unsigned i=0; i<ny2; i++) { mu2(i) = Theta[pos]; pos++; } for (unsigned i=0; i<ny0; i++) { lambda0(i) = Theta[pos]; pos++; } lambda1(0) = 1; for (unsigned i=1; i<ny1; i++) { lambda1(i) = Theta[pos]; pos++; } lambda2(0) = 1; for (unsigned i=1; i<ny2; i++) { lambda2(i) = Theta[pos]; pos++; } for (unsigned i=0; i<npred0; i++) { beta0(i) = Theta[pos]; pos++; } for (unsigned i=0; i<npred1; i++) { beta1(i) = Theta[pos]; pos++; } for (unsigned i=0; i<npred2; i++) { beta2(i) = Theta[pos]; pos++; } gamma(0) = Theta[pos]; gamma(1) = Theta[pos+1]; gamma2(0) = Theta[pos+2]; gamma2(1) = Theta[pos+3]; // cerr << "mu0=" << mu0 << endl; // cerr << "mu1=" << mu1 << endl; // cerr << "mu2=" << mu2 << endl; // cerr << "lambda0=" << lambda0 << endl; // cerr << "lambda1=" << lambda1 << endl; // cerr << "lambda2=" << lambda2 << endl; // cerr << "beta0=" << beta0 << endl; // cerr << "beta1=" << beta1 << endl; // cerr << "beta2=" << beta2 << endl; // cerr << "gamma=" << gamma << endl; // cerr << "gamma2=" << gamma2 << endl; mat lap(nobs,4); for (unsigned i=0; i<nobs; i++) { rowvec newlap = laNRb(Data.row(i), iS, detS, mu0, mu1, mu2, lambda0, lambda1, lambda2, beta0,beta1, beta2, gamma, gamma2, Dtol,niter,lambda); lap.row(i) = newlap; } List res; res["indiv"] = lap; res["logLik"] = sum(lap.col(0)) + (3-V.nrow())*log(2.0*datum::pi)*nobs/2; res["norm0"] = (3-V.nrow())*log(2*datum::pi)/2; return res; }
//---------------------- float tmVisThreshC1_MixtureModeling2::differenceGamma (int i) { return gamma1(i)-gamma2(i); }
//---------------------- float tmVisThreshC1_MixtureModeling2::gamma (int i) { return gamma1(i)+gamma2(i); }
void mlalign_TKF91(mlalign_Nucleotide *as, size_t na, mlalign_Nucleotide *bs, size_t nb, double lambda, double mu, double tau, double pi[mlalign_NUMBER_OF_BASES], mlalign_Site *alignment, size_t *n, double *score) { /***********************/ /* initialize matrices */ /***********************/ size_t rows = na + 1; size_t cols = nb + 1; auto idxM = diagonalizedIndexer(rows, cols, VECSIZE); auto idxA = identityIndexer(na); auto idxB = identityIndexer(nb); auto idxP1 = identityIndexer(mlalign_NUMBER_OF_BASES); auto idxP2 = rowMajorIndexer(mlalign_NUMBER_OF_BASES, mlalign_NUMBER_OF_BASES); auto idx2 = identityIndexer(2); // Allocate enough bytes for the matrices and properly align that. // We won't use vector because // 1) it initializes every element to 0 // 2) has some extra payload we won't need (e.g. capacity and size for bounds checks) // 3) we don't resize const size_t doubles_per_matrix = to_next_multiple(idxM(rows - 1, cols - 1) + 1, VECSIZE); std::unique_ptr<double[]> buffer(new double[3 * doubles_per_matrix + VECSIZE]); auto M0 = reinterpret_cast<double*>( to_next_multiple( reinterpret_cast<size_t>(buffer.get()), VECSIZE * sizeof(double))); auto M1 = M0 + doubles_per_matrix; auto M2 = M1 + doubles_per_matrix; assert(M0 - buffer.get() < static_cast<std::ptrdiff_t>(VECSIZE)); // // Memoization // const double beta = (1 - std::exp((lambda - mu) * tau)) / (mu - lambda * std::exp((lambda - mu) * tau)); const double delta = 1 / (1 - pi[0] * pi[0] - pi[1] * pi[1] - pi[2] * pi[2] - pi[3] * pi[3]); const double lambda_div_mu = lambda / mu; const double lambda_mul_beta = lambda * beta; double p_desc_1 = p_desc(1, beta, lambda, mu, tau); double M0_factor[mlalign_NUMBER_OF_BASES]; double M1_factor[mlalign_NUMBER_OF_BASES * mlalign_NUMBER_OF_BASES]; double M2_factor[mlalign_NUMBER_OF_BASES]; double p_desc_inv_n[2]; for (size_t i = 0; i < 2; ++i) { p_desc_inv_n[idx2(i)] = p_desc_inv(i, beta, lambda, mu, tau); } for (size_t i = 0; i < mlalign_NUMBER_OF_BASES; ++i) { const auto a = static_cast<mlalign_Nucleotide>(i); M0_factor[idxP1(a)] = std::log(lambda_div_mu * pi[idxP1(a)] * p_desc_inv_n[idx2(0)]); } for (size_t i = 0; i < mlalign_NUMBER_OF_BASES; ++i) { for (size_t j = 0; j < mlalign_NUMBER_OF_BASES; ++j) { const auto a = static_cast<mlalign_Nucleotide>(i); const auto b = static_cast<mlalign_Nucleotide>(j); M1_factor[idxP2(a, b)] = std::log(lambda_div_mu * pi[idxP1(a)] * std::max(p_trans(a, b, delta, pi, tau) * p_desc_1, pi[idxP1(b)] * p_desc_inv_n[idx2(1)])); } } for (size_t i = 0; i < mlalign_NUMBER_OF_BASES; ++i) { const auto b = static_cast<mlalign_Nucleotide>(i); M2_factor[idxP1(b)] = std::log(pi[idxP1(b)] * lambda_mul_beta); } size_t ix = idxM(0, 0); // We'll reuse ix throughout this function for caching idx calculations M0[ix] = -std::numeric_limits<double>::max(); M1[ix] = std::log(gamma2(0, lambda, mu) * zeta(1, beta, lambda)); M2[ix] = -std::numeric_limits<double>::max(); double accum = 0.0; for (size_t i = 1; i < rows; i++) { ix = idxM(i, 0); accum += std::log(pi[idxP1(as[idxA(i-1)])] * p_desc_inv_n[idx2(0)]); M0[ix] = std::log(gamma2(i, lambda, mu) * zeta(i, beta, lambda)) + accum; M1[ix] = -std::numeric_limits<double>::max(); M2[ix] = -std::numeric_limits<double>::max(); } accum = 0.0; for (size_t j = 1; j < cols; j++) { ix = idxM(0, j); accum += std::log(pi[idxP1(bs[idxB(j-1)])]); M0[ix] = -std::numeric_limits<double>::max(); M1[ix] = -std::numeric_limits<double>::max(); M2[ix] = std::log(gamma2(0, lambda, mu) * zeta(j + 1, beta, lambda)) + accum; } /****************/ /* DP algorithm */ /****************/ // TODO: Implement these in circular queues. size_t top[3] = { 0, 0, SIZE_MAX }; size_t bottom[3] { 1, 0, SIZE_MAX }; // This is tricky. We store the corrected offsets for diagonals offset -1 and -2 (7, 3 resp.) and the // uncorrected (e.g. not aligned) offset for the current diagonal (which is 7 + 2 = 9). // We inititialize with the values for diagonal 2, 1 and 0, we start at diagonal = 2 anyway. size_t diagonal_offsets[3] = { 2*VECSIZE + 1, 2*VECSIZE - 1, VECSIZE - 1 }; const size_t number_of_diagonals = rows + cols - 1; for (size_t diagonal = 2; diagonal < number_of_diagonals; ++diagonal) { // Topmost and bottommost row index of the diagonal, // skipping the already initialized first row and column (diagonal - 1 for that reason). // It's helpful for intuition to visualize this (rows=7, cols=6): // // 3 7 11 15 19 // 8 12 16 20 24 // 5 17 21 25 32 // 18 22 26 33 40 // 23 27 34 41 44 // 28 35 42 45 48 // 36 43 46 49 52 // // diagonal | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | // bottom_without_first | 1 | 2 | 3 | 4 | 5 | 6 | 6 | 6 | // top_without_first | 1 | 1 | 1 | 1 | 2 | 3 | 4 | 5 | // // We will then iterate over the diagonal through the indices // [top_without_first, bottom_without_first] inclusive. Column // indices are easily computed from the diagonal and row index. // We start with diagonal = 2, e.g. the third diagonal, because // it's the first containing uninitialized values. // const size_t bottom_without_first = std::min(diagonal - 1, rows - 1); const size_t top_without_first = diagonal - std::min(diagonal - 1, cols - 1); std::rotate(top, top + 2, top + 3); // This pushes all elements on further back std::rotate(bottom, bottom + 2, bottom + 3); bottom[0] = std::min(diagonal, rows - 1); top[0] = diagonal - std::min(diagonal, cols - 1); const size_t length_of_diagonal = bottom[0] + 1 - top[0]; // We have to correct the diagonal offset for the alignment rules layed out in diagonalizedIndexer. // 1. If the diagonal starts in the first row (top[0]=0), then the offset must have alignment -1. // 2. If the diagonal doesn't start in the first row, then the offset must have alignment 0. diagonal_offsets[0] += top[0] == 0 ? VECSIZE - 1 - diagonal_offsets[0] % VECSIZE : (VECSIZE - diagonal_offsets[0] % VECSIZE) % VECSIZE; assert((top[0] == 0 && diagonal_offsets[0] % VECSIZE == VECSIZE - 1) || (top[0] != 0 && diagonal_offsets[0] % VECSIZE == 0)); // INDEX EXPLANATIONS // row_offset offset of the row where the current SIMD vector begins // i index into the SIMD vector // col index of the column where the currently processed vector element is located in the DP matrix // row index of the row where the currently processed vector element is located in the DP matrix // Step in vector size over diagonal entries for (size_t row_offset = top_without_first; row_offset <= bottom_without_first; row_offset += VECSIZE) { // Copy the factors values from the lookuptable into the vector // Apparently it is not better to copy into temp memory and the use loaddvec, but it is faster to just use the [] operator. dvec factors[3]; for (size_t i = 0; i < VECSIZE; ++i) { const size_t row = row_offset + i; const size_t col = diagonal - row; if (row > bottom_without_first) { // We would load from somewhere out of the matrix, so we just leave the // other vector elements untouched break; } const mlalign_Nucleotide a = as[idxA(row - 1)]; const mlalign_Nucleotide b = bs[idxB(col - 1)]; factors[0][i] = M0_factor[idxP1(a)]; factors[1][i] = M1_factor[idxP2(a, b)]; factors[2][i] = M2_factor[idxP1(b)]; } // Compute the indexes of the top, left and top left cells and load them. const size_t ix_top = diagonal_offsets[1] + row_offset - 1 - top[1]; assert(ix_top == idxM(row_offset - 1, diagonal - row_offset)); const dvec max_top[3] = { loaddvec(M0 + ix_top), loaddvec(M1 + ix_top), loaddvec(M2 + ix_top), }; const size_t ix_topleft = diagonal_offsets[2] + row_offset - 1 - top[2]; assert(ix_topleft == idxM(row_offset - 1, diagonal - row_offset - 1)); const dvec max_topleft[3] = { loaddvec(M0 + ix_topleft), loaddvec(M1 + ix_topleft), loaddvec(M2 + ix_topleft), }; // Against all symmetry M0 isn't part of the formula. const size_t ix_left = ix_top + 1; assert(ix_left == idxM(row_offset, diagonal - row_offset - 1)); const dvec max_left[2] = { loaddvec(M1 + ix_left), loaddvec(M2 + ix_left), }; // Maxima for each cells on top/topleft/left of the calculated cell const dvec mt = maxdvec(max_top[0], maxdvec(max_top[1], max_top[2])); const dvec mtl = maxdvec(max_topleft[0], maxdvec(max_topleft[1], max_topleft[2])); const dvec ml = maxdvec(max_left[0], max_left[1]); // Vectorised add const dvec m0v = factors[0] + mt; const dvec m1v = factors[1] + mtl; const dvec m2v = factors[2] + ml; // Write back to matrix const size_t occupied_vector_elements = std::min(bottom_without_first + 1 - row_offset, VECSIZE); ix = diagonal_offsets[0] + row_offset - top[0]; assert(ix % VECSIZE == 0); assert(ix == idxM(row_offset, diagonal - row_offset)); storedvec(M0 + ix, m0v, occupied_vector_elements); storedvec(M1 + ix, m1v, occupied_vector_elements); storedvec(M2 + ix, m2v, occupied_vector_elements); } std::rotate(diagonal_offsets, diagonal_offsets + 2, diagonal_offsets + 3); diagonal_offsets[0] = diagonal_offsets[1] + length_of_diagonal; } /****************/ /* Backtracking */ /****************/ ix = idxM(na, nb); *n = 0; *score = std::exp(std::max({M0[ix], M1[ix], M2[ix]})); size_t cur = max_idx({M0[ix], M1[ix], M2[ix]}); for (size_t i = na, j = nb; i > 0 || j > 0;) { mlalign_Site site = {mlalign_Gap, mlalign_Gap}; switch (cur) { case 0: // insert assert(i > 0); site.a = as[--i]; site.b = mlalign_Gap; ix = idxM(i, j); cur = max_idx({M0[ix], M1[ix], M2[ix]}); break; case 1: // substitution assert(i > 0); assert(j > 0); site.a = as[--i]; site.b = bs[--j]; ix = idxM(i, j); cur = max_idx({M0[ix], M1[ix], M2[ix]}); break; case 2: // deletion assert(j > 0); site.a = mlalign_Gap; site.b = bs[--j]; ix = idxM(i, j); cur = max_idx({M1[ix], M2[ix]}) + 1; break; default: assert(0); } alignment[(*n)++] = site; // Doesn't get any scarier } // The alignment is reversed, so we have to undo that. for (size_t i = 0; i < (*n) / 2; ++i) { std::swap(alignment[i], alignment[*n - i - 1]); } }