double NormalEquations::Evaluate() { // If nothing changed ... if (!meanChange && !varChange) return likelihood; // (2pi)^(-k/2) likelihood = includeLikelihoodConstant ? constant : 0.0; // deviation from predicted scores in linear model if (meanChange) CalculateResiduals(); // The variance matrix A (varMatrix) if (varChange) CalculateCovariances(); // and its cholesky decomposition are updated if (varChange) cholesky.FastDecompose(varMatrix); // This is cholesky.x = Inv(A) * residuals cholesky.BackSubst(residuals); // Add e ^ [- 0.5 * (yi - ui)T * A^-1 * (yi - ui)] likelihood -= 0.5 * residuals.InnerProduct(cholesky.x); // Det(A[i]^-1/2) = -Det(sqrt(A)) = -Det(L) likelihood -= cholesky.lnDeterminantL(); // Flag that allows us to check for redundant calculations init = true; return likelihood; }
void NormalEquations::Diagnostics() { CalculateResiduals(); CalculateCovariances(); cholesky.BackSubst(residuals); rawQ = residuals.InnerProduct(cholesky.x); Q = sqrt(2.0 * rawQ) - sqrt(2.0 * residuals.dim - 1.0); Qi.Dimension(residuals.dim); Matrix M; Vector v, r; Cholesky chol; for (int i = 0; i < residuals.dim; i++) { M = varMatrix; v = M[i]; M.DeleteColumn(i); M.DeleteRow(i); v.DeleteDimension(i); chol.Decompose(M); chol.BackSubst(v); double var = varMatrix[i][i] - v.InnerProduct(chol.x); r = residuals; r.DeleteDimension(i); chol.BackSubst(r); Qi[i] = residuals[i] - v.InnerProduct(chol.x); Qi[i] = Qi[i] * Qi[i] / var; } }
/* Documented in optimized_target_freq.h */ int Blast_OptimizeTargetFrequencies(double x[], int alphsize, int *iterations, const double q[], const double row_sums[], const double col_sums[], int constrain_rel_entropy, double relative_entropy, double tol, int maxits) { int its; /* number of iterations that have been performed */ int n; /* number of target frequencies; the size of x */ int mA; /* number of linear constraints */ int m; /* total number of constraints */ double values[2]; /* values of the nonlinear functions at this iterate */ double ** grads = NULL; /* gradients of the nonlinear functions at this iterate */ ReNewtonSystem * newton_system = NULL; /* factored matrix of the linear system to be solved at this iteration */ double * z = NULL; /* dual variables (Lagrange multipliers) */ double * resids_x = NULL; /* dual residuals (gradient of Lagrangian) */ double * resids_z = NULL; /* primal (constraint) residuals */ double rnorm; /* norm of the residuals for the current iterate */ double * old_scores = NULL; /* a scoring matrix, with lambda = 1, generated from q, row_sums and col_sums */ double * workspace = NULL; /* A vector for intermediate computations */ int converged; /* true if Newton's method converged to a *minimizer* (strong second-order point) */ int status; /* the return status */ n = alphsize * alphsize; mA = 2 * alphsize - 1; m = constrain_rel_entropy ? mA + 1 : mA; newton_system = ReNewtonSystemNew(alphsize); if (newton_system == NULL) goto error_return; resids_x = (double *) malloc(n * sizeof(double)); if (resids_x == NULL) goto error_return; resids_z = (double *) malloc((mA + 1) * sizeof(double)); if (resids_z == NULL) goto error_return; /* z must be initialized to zero */ z = (double *) calloc( mA + 1, sizeof(double)); if (z == NULL) goto error_return; old_scores = (double *) malloc(n * sizeof(double)); if (old_scores == NULL) goto error_return; workspace = (double *) malloc(n * sizeof(double)); if (workspace == NULL) goto error_return; grads = Nlm_DenseMatrixNew(2, n); if (grads == NULL) goto error_return; ComputeScoresFromProbs(old_scores, alphsize, q, row_sums, col_sums); /* Use q as the initial value for x */ memcpy(x, q, n * sizeof(double)); its = 0; /* Initialize the iteration count. Note that we may converge in zero iterations if the initial x is optimal. */ while (its <= maxits) { /* Compute the residuals */ EvaluateReFunctions(values, grads, alphsize, x, q, old_scores, constrain_rel_entropy); CalculateResiduals(&rnorm, resids_x, alphsize, resids_z, values, grads, row_sums, col_sums, x, z, constrain_rel_entropy, relative_entropy); /* and check convergence; the test correctly handles the case in which rnorm is NaN (not a number). */ if ( !(rnorm > tol) ) { /* We converged at the current iterate */ break; } else { /* we did not converge, so increment the iteration counter and start a new iteration */ if (++its <= maxits) { /* We have not exceeded the maximum number of iterations; take a Newton step. */ double alpha; /* a positive number used to scale the Newton step. */ FactorReNewtonSystem(newton_system, x, z, grads, constrain_rel_entropy, workspace); SolveReNewtonSystem(resids_x, resids_z, newton_system, workspace); /* Calculate a value of alpha that ensure that x is positive */ alpha = Nlm_StepBound(x, n, resids_x, 1.0 / .95); alpha *= 0.95; Nlm_AddVectors(x, n, alpha, resids_x); Nlm_AddVectors(z, m, alpha, resids_z); } } } converged = 0; if (its <= maxits && rnorm <= tol) { /* Newton's iteration converged */ if ( !constrain_rel_entropy || z[m - 1] < 1 ) { /* and the final iterate is a minimizer */ converged = 1; } } status = converged ? 0 : 1; *iterations = its; goto normal_return; error_return: status = -1; *iterations = 0; normal_return: Nlm_DenseMatrixFree(&grads); free(workspace); free(old_scores); free(z); free(resids_z); free(resids_x); ReNewtonSystemFree(&newton_system); return status; }