// [[Rcpp::export]] mat randWalkTrain(const mat& X, const mat& A, const colvec& Z, const colvec& theta, int trainit, const colvec& sigma, const colvec& etaRange, const mat& V, bool verbose) { double logAccept; int p = theta.size() - 1; int n = X.n_rows; colvec eigval; mat eigvec; eig_sym(eigval, eigvec, V); mat R = eigvec * diagmat(sqrt(eigval)); colvec Y = rautologistic_(X, A, theta); colvec Ynew(n); colvec thetaold = theta; colvec thetanew = theta; colvec normvec(p + 1); mat estimates(trainit + 1, p + 1); estimates.row(0) = theta.t(); colvec beta = theta.subvec(0, p - 1); double eta = theta[p]; colvec Xbeta = X * beta; colvec mu = exp(Xbeta); mu = mu / (1 + mu); double Zsum = as_scalar(Z.t() * A * Z); int onepct = 0.01 * trainit; int pct = 1; RNGScope scope; Function rnorm("rnorm"), runif("runif"); for (int i = 1; i < trainit + 1; i++) { do { normvec = as<colvec>(rnorm(p + 1)); thetanew = thetaold + R * normvec; } while(thetanew[p] < etaRange[0] || thetanew[p] > etaRange[1]); Ynew = rautologistic_(X, A, thetanew); colvec betaold = thetaold.subvec(0, p - 1); colvec betanew = thetanew.subvec(0, p - 1); double etaold = thetaold[p]; double etanew = thetanew[p]; colvec Xbetaold = X * betaold; colvec Xbetanew = X * betanew; colvec muold = exp(Xbetaold); muold = muold / (1 + muold); colvec munew = exp(Xbetanew ); munew = munew / (1 + munew); double Ynewsum = as_scalar(Ynew.t() * A * Ynew); double Ysum = as_scalar(Y.t() * A * Y); logAccept = as_scalar(0.5 * (eta * (Ynewsum - Ysum) + etanew * (Zsum - Ynewsum) + etaold * (Ysum - Zsum)) + trans(Ynew - Y) * Xbeta + trans(Z - Ynew) * Xbetanew + trans(Y - Z) * Xbetaold + etaold * trans(Z - Y) * A * muold + etanew * trans(Ynew - Z) * A * munew + eta * trans(Y - Ynew) * A * mu) + accu((square(betaold) - square(betanew)) / (2 * sigma)); if (as_scalar(log(as<double>(runif(1)))) < logAccept) { estimates.row(i) = thetanew.t(); thetaold = thetanew; Y = Ynew; } else estimates.row(i) = thetaold.t(); if (verbose && i % onepct == 0) { Rcout << "\rTraining progress: |"; for (int j = 1; j <= pct; j++) Rcout << "+"; for (int j = 1; j < (100 - pct); j++) Rcout << " "; Rcout << "| " << pct << "%"; pct++; R_FlushConsole(); } } if (verbose) Rcout << std::endl << std::endl; return estimates.rows(1, trainit); }
#include <armadillo> #include "catch.hpp" using namespace arma; TEST_CASE("fn_cumsum_1") { colvec a = linspace<colvec>(1,5,6); rowvec b = linspace<rowvec>(1,5,6); colvec c = { 1.0000, 2.8000, 5.4000, 8.8000, 13.0000, 18.0000 }; REQUIRE( accu(abs(cumsum(a) - c )) == Approx(0.0) ); REQUIRE( accu(abs(cumsum(b) - c.t())) == Approx(0.0) ); REQUIRE_THROWS( b = cumsum(a) ); } TEST_CASE("fn_cumsum_2") { mat A = { { -0.78838, 0.69298, 0.41084, 0.90142 }, { 0.49345, -0.12020, 0.78987, 0.53124 }, { 0.73573, 0.52104, -0.22263, 0.40163 } };
// How is that for a descriptive function name??? colvec symmetricTridiagonalFrancisAlgorithmWithWilkinsonShift(colvec a, colvec b) { float epsilon = 0.001f; // turned off currently int passes = 3; int pass = 0; unsigned long long int count = 0; int m = a.n_elem - 1; while (0<m) { ++pass; float s, c; float d = (a(m-1) - a(m)) * 0.5f; if (d == 0) { s = a(m) - abs(b(m)); } else { s = a(m) - pow(b(m),2) / (d + sgn(d)*sqrt(d*d + b(m)*b(m))); } float x = a(0) - s; float y = b(1); for (int k=0; k<=m-1; ++k) { if (1 < m) { // givens rotation float r = hypot(y,x); c = x/r; s = y/r; } else { // Orthogonal diagonalization of a symmetric 2x2 matrix // http://scipp.ucsc.edu/~haber/ph116A/diag2x2_11.pdf float theta; theta = 0.5f * atan2(2*b(1),a(0)-a(1)); s = sin(theta); c = cos(theta); } float w = c*x - s*y; d = a(k) - a(k+1); float z = (2*c*b(k+1) + d*s)*s; a(k) -= z; a(k+1) += z; b(k+1) = d*c*s + (c*c - s*s)*b(k); x = b(k+1); if (0 < k) { b(k) = w; } if (k < m-1) { y = -s*b(k+2); b(k+2) *= c; if (abs(c) > 1) { cout << c << endl; } } // Do not need to calculate Q. Do not need eigenvectors. } count += m; // cout << abs(b(m)) << " " << epsilon*(abs(a(m-1)) + abs(a(m))) << endl; float smallThing = epsilon*(abs(a(m-1)) + abs(a(m))); if (isnan(smallThing)) { cout << "Not a number!" << endl; } if (abs(b(m)) < smallThing) { // check for convergence // --m; // temporarily turned off, to make iterations until m is decreased constant } if (pass == passes) { --m; pass = 0; } } // cout << "diagonal" << endl << a.t() << endl; cout << "off diagonal" << endl << b.t() << endl; cout << "inner loop iterations : " << count << endl; // total number of inner loop iterations performed return a; }