static DoubleMatrix funExactLambda_b(const DoubleMatrix &dvecAlp, const DoubleMatrix &dvecB, const DoubleMatrix &dvecY, const bool withD){ // Updated 1-8-01 Alyssa // fixed for const correctness DoubleMatrix term1(1, dvecB.nr()), term2(1, dvecB.nr()); const double *pdAlp = dvecAlp.data(); const double *pdB = dvecB.data(); const double *pdY = dvecY.data(); double *pdTerm1 = term1.data(); double *pdTerm2 = term2.data(); term1.fill(0.0); term2.fill(0.0); pdTerm1[0] = 1.0/pdB[0] -0.5 * (pow(pdB[0],-2.0)*pow((pdY[0]-pdAlp[1]-pdB[1]),2.0) +pow(pdB[0],-2.0)*pow((pdY[1]-pdAlp[1]-pdB[1]),2.0)); pdTerm1[1] = -(pdY[0]+pdY[1]-2.0*pdAlp[1]-2.0*pdB[1])/pdB[0] ; if( withD ){ //pdAns[0] = 1.0/pdB[0] - pow((1.0 - pdAlp[1] - pdB[1]*pdB[1]), 2.0) + pdB[0]/pdAlp[0]; //pdAns[1] = -2.0 * (1.0 - pdAlp[1] - pdB[1]) / pdB[0] + pdB[1]/pdAlp[0]; pdTerm2[0] = pdB[0]/pdAlp[0]; pdTerm2[1] = pdB[1]/pdAlp[0]; return add( term1, term2 ); } else{ return term1; } }
void symmetrize(const DoubleMatrix& L, DoubleMatrix& Sym) { int m = L.nr(); int n = L.nc(); assert(m==n); assert(Sym.nr() == m); assert(Sym.nc() == n); const double* pL = L.data(); double* pS = Sym.data(); if( &L != &Sym ) { std::copy(pL, pL+m*n, pS); } int j,i; for( j=0; j<n; j++ ) { // Copy the lower triangle data into the resulting matrix's upper triangle for( i=0; i<j; i++ ) { pS[i+j*m] = pL[j+i*m]; } } }
void AkronItimesCTest::testAkronItimesCVal() { const int m = 2; const int n = 3; const int k = 1; int i; double seq[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}; DoubleMatrix A(m,n); DoubleMatrix I = identity(n); DoubleMatrix C(n*n,k); std::copy(seq, seq+m*n, A.data()); std::copy(seq, seq+n*n*k, C.data()); DoubleMatrix AIC = AkronItimesC(A,I,C); CPPUNIT_ASSERT_EQUAL(m*n, AIC.nr()); CPPUNIT_ASSERT_EQUAL(k, AIC.nc()); DoubleMatrix ABC = AkronBtimesC(A,I,C); CPPUNIT_ASSERT_EQUAL(m*n, ABC.nr()); CPPUNIT_ASSERT_EQUAL(k, ABC.nc()); //std::cout << "ABC=" << ABC << std::endl; //std::cout << "AIC=" << AIC << std::endl; for( i = 0; i < m*n*k; i++ ) { CPPUNIT_ASSERT_EQUAL(ABC.data()[i], AIC.data()[i]); } }
void multiply(const DoubleMatrix &X, const DoubleMatrix &Y, DoubleMatrix& Z) { assert(&X!=&Z); assert(&Y!=&Z); if( X.isEmpty() || Y.isEmpty() ) return; // // Row Major Matrices // // C = alpha * A * B + beta * C --- (1) // // A : m by k lda (stride) = k // B : k by n ldb (stride) = n // C : m by n ldc (stride) = n // // Column Major Matrices // // Z = alpha * X * Y + beta * C --- (2) // Z = C^t // = alpha * B^t * A^t + beta * C^t --- (3) // // X = B^t : n by k ldx (stride) = n // Y = A^t : k by m ldy (stride) = k // Z = C^t : n by m ldz (stride) = n // int m = Y.nc(); int k = X.nc(); int n = X.nr(); Z.resize( n, m ); assert( X.nr() == n ); assert( X.nc() == k ); assert( Y.nr() == k ); assert( Y.nc() == m ); assert( Z.nr() == n ); assert( Z.nc() == m ); const double * pX = X.data(); const double * pY = Y.data(); double * pZ = Z.data(); int lda = n; int ldb = k; int ldc = n; cblas_dgemm( CblasColMajor, CblasNoTrans, CblasNoTrans, n, m, k, ALPHA, pX, lda, pY, ldb , BETA, pZ, ldc ); }
static void replaceIth( DoubleMatrix &target, int ith, const DoubleMatrix &data ) { assert(target.nc() == data.nc()); assert( ith >= 0 && ith < target.nr()); double *pTarget = target.data(); const double *pData = data.data(); int j; for( j=0; j<target.nc(); j++ ) { pTarget[j*target.nr()+ith] = pData[j]; } return; }
void lambdaTest::test( SpkModel<double> &model, const DoubleMatrix &dvecY, const DoubleMatrix &dvecAlp, const DoubleMatrix &dvecB, double lambdaOut, DoubleMatrix &lambda_alpOut, DoubleMatrix &lambda_bOut, const bool withD) { DoubleMatrix exactTemp; double dblexactTemp; int i; lambdaOut = lambda(model, dvecY, dvecAlp, dvecB, withD); lambda_alpOut = lambda_alp(model, dvecY, dvecAlp, dvecB, withD); lambda_bOut = lambda_b(model, dvecY, dvecAlp, dvecB, withD); dblexactTemp = funExactLambda(dvecAlp, dvecB, dvecY, withD); CPPUNIT_ASSERT_DOUBLES_EQUAL( dblexactTemp, lambdaOut, 0.0001); exactTemp = funExactLambda_alp(dvecAlp, dvecB, dvecY, withD); for( i=0; i<exactTemp.nr()*exactTemp.nc(); i++ ) { CPPUNIT_ASSERT_DOUBLES_EQUAL( exactTemp.data()[i], lambda_alpOut.data()[i], 0.0001 ); } exactTemp = funExactLambda_b(dvecAlp, dvecB, dvecY, withD); for( i=0; i<exactTemp.nr()*exactTemp.nc(); i++ ) { CPPUNIT_ASSERT_DOUBLES_EQUAL( exactTemp.data()[i], lambda_bOut.data()[i], 0.0001 ); } }
static double compareAgainst( const DoubleMatrix &dvecZ, // column vector const DoubleMatrix &dvecH, // column vector const DoubleMatrix &dmatQ, // symmetric matrix Q(x) const DoubleMatrix &dmatInvQ // inverse of Q ) { assert( dvecZ.nc() == 1 ); assert( dvecH.nc() == 1 ); assert( dmatQ.nr() == dmatQ.nc() ); assert( hasPosDet( dmatQ ) ); DoubleMatrix dmatQ2PI( dmatQ.nr(), dmatQ.nc() ); const double *pQ = dmatQ.data(); double *pQ2PI = dmatQ2PI.data(); for( int i=0; i<dmatQ.nr()*dmatQ.nc(); i++ ) pQ2PI[i] = pQ[i] * 2.0 * PI; // Compute det(Q2PI) = b * 2^c . double b; long c; det( dmatQ2PI , &b, &c ); // Compute log(det(Q2PI)). double dTerm1 = log( b ) + c * log( 2.0 ); DoubleMatrix dmatR = subtract( dvecZ, dvecH ); DoubleMatrix term2 = multiply(multiply(transpose(dmatR),dmatInvQ), dmatR); double dTerm2 = oneByOneToScalar(term2); return (dTerm1 + dTerm2) / 2.0; }
static DoubleMatrix elsq_x_x( const DoubleMatrix &dvecX, // parameter const DoubleMatrix &dvecZ, // data const DoubleMatrix &dvecH, // h(x) const DoubleMatrix &dmatH_x, const DoubleMatrix &dmatH_x_x, const DoubleMatrix &dmatQ, // Q(x) const DoubleMatrix &dmatQ_x, const DoubleMatrix &dmatQinv, // Q(x)inv const DoubleMatrix &dmatQinv_x, const DoubleMatrix &dmatQinv_x_x ) { using namespace std; DoubleMatrix term1, term2, term1sub2div2, term3, term4, term5, term4add5, term6, term6div2, term7, term8, term9, term7add8div2, term7add8div2Trans; DoubleMatrix ZsubH, tranZsubH, identX; DoubleMatrix dmatElsq_x_x; ZsubH = subtract(dvecZ, dvecH); tranZsubH = transpose(ZsubH); identX = identity(dvecX.nr()); term1 = AkronBtimesC(transpose(rvec(dmatQ)), identX, dmatQinv_x_x); term2 = multiply(transpose(dmatQinv_x), dmatQ_x); term1sub2div2 = divByScalar( add(term1, term2), -2.0 ); term3 = mulByScalar( AkronBtimesC(multiply(tranZsubH,dmatQinv), identX, dmatH_x_x), -1.0); term4 = AkronBtimesC(tranZsubH, transpose(dmatH_x), dmatQinv_x); term5 = multiply(multiply(transpose(dmatH_x),dmatQinv),dmatH_x); term4add5 = subtract( term5, term4 ); term6 = AkronBtimesC( transpose(rvec(multiply(ZsubH,tranZsubH))), identX, dmatQinv_x_x ); term6div2 = divByScalar(term6, 2.0); term7 = AkronBtimesC( transpose(dmatH_x), transpose(ZsubH), dmatQinv_x ); term8 = AkronBtimesC( transpose(ZsubH), transpose(dmatH_x), dmatQinv_x ); term7add8div2 = divByScalar( add(term7, term8), -2.0 ); term7add8div2Trans = transpose(term7add8div2); dmatElsq_x_x = add( term1sub2div2, add( term3, add(term4add5, add(term6div2, term7add8div2Trans)))); return dmatElsq_x_x; }
static bool check(DoubleMatrix dmatB, int rows, int cols, int d1, int d2, int d3, int d4, int d5, int d6, int d7, int d8, int d9) { using namespace std; bool isOkay = true; int m = dmatB.nr(); int n = dmatB.nc(); double *pdB = dmatB.data(); if( m != rows || n != n ){ isOkay = false; return isOkay; } int d[9]; d[0] = d1; d[1] = d2; d[2] = d3; d[3] = d4; d[4] = d5; d[5] = d6; d[6] = d7; d[7] = d8; d[8] = d9; for( int i=0; i<rows*cols && isOkay; i++ ){ if( d[i] != pdB[i] ){ cout << "d[" << i << "] received was " << d[i] << endl; cout << "mat[" << i << "] was " << pdB[i] << endl; dmatB.print(); isOkay = false; } } return isOkay; }
const DoubleMatrix backDiv(const DoubleMatrix &dmatA, const DoubleMatrix &dmatB) { // A is assumed to be square. int m = dmatA.nr(); int n = dmatA.nc(); assert( m == n ); // B is m by l matrix, where l is the number of right hand sides. int l = dmatB.nc(); assert( dmatB.nr() == m ); if( dmatA.isEmpty() || dmatB.isEmpty() ) return DoubleMatrix( 0, 0 ); //============================================================== // First decompose A into LU such that A = P * L * U, // where P is the permutation matrix, // L is the lower triangle and the U the upper triangle. // // We use CLAPACK's DGETRF() which does LU decomposition // with partial (ie. row interchanges only) pivoting. //============================================================== // enum CBLAS_ORDER order =: (CblasColMajor | CblasRowMajor) // // If order = CblasColMajor, the array, a, is assumed to // hold each matrix A's column in the contiguous manner // in memory (ie. A is said to be in the column major order). // If order = CblasRowMajor, the array, a, is assumed to // hold each matrix A's row in the contiguous manner // in memory (ie. A is said to be in the row major order). enum CBLAS_ORDER order = CblasColMajor; // double *a // // (on entry) a points to the elements of matrix A(m,n) // in the column major order if "order" = CblasColMajor, // or in the row major order if "order" = CblasRowMajor. // // (on exit) The lower triangle (j<=i) is replaced by L // and the upper triangle (j>i) is replaced by U. double a[m*n]; copy( dmatA.data(), dmatA.data()+m*n, a ); // int lda // // The leading dimension of A. // If A is in the column major order, lda = m. // If A is in the row major order, lda = n. int lda = m; // int ipiv(m) // // (on exit) The i-th row in A was interchanged with the row // indicated by the value in ipiv[i]. int ipiv[m]; int info = clapack_dgetrf( order, m, n, a, lda, ipiv ); if( info < 0 ) { char mess[ SpkError::maxMessageLen() ]; snprintf( mess, SpkError::maxMessageLen(), "Solution of a system of linear equations using the LU decomposition failed: \n the %s argument to the function that performs the LU decomposition had an illegal value.", intToOrdinalString( -info, ONE_IS_FIRST_INT ).c_str() ); throw SpkException( SpkError::SPK_UNKNOWN_ERR, mess, __LINE__, __FILE__ ); } else if( info > 0 ) { char mess[ SpkError::maxMessageLen() ]; snprintf( mess, SpkError::maxMessageLen(), "Solution of a system of linear equations using the LU decomposition failed: \nthe %s diagonal element of U is exactly zero.", intToOrdinalString( info, ONE_IS_FIRST_INT ).c_str() ); throw SpkException( SpkError::SPK_NOT_POS_DEF_ERR, mess, __LINE__, __FILE__ ); } //============================================================== // Solve A x = B for x using the LU computed in the previous // step. // Note that A is now assumed to be square: m = n. //============================================================== // int rhs // // The number of right hand sides (ie. the number of columns of B). int nrhs = l; // int ldb // The leading dimension of B. // If B is in the column major order, ldb = m. // If B is in the row major order, ldb = l. int ldb = m; // double *x // // (on entry) x points to the elements of B in the column major // order if "order" = CblasColMajor or in the row major otherwise. // (on exit) x points to the solution matrix, x (m=n by l). DoubleMatrix X( dmatB ); double * x = X.data();// This points to b on entry and contains the solution x upon exit info = clapack_dgetrs( order, CblasNoTrans, n, nrhs, a, lda, ipiv, x, ldb ); if( info < 0 ) { char mess[ SpkError::maxMessageLen() ]; snprintf( mess, SpkError::maxMessageLen(), "Solution of a system of linear equations using the LU decomposition failed: \nthe %s argument to the function that solves the equations had an illegal value.", intToOrdinalString( -info, ONE_IS_FIRST_INT ).c_str() ); throw SpkException( SpkError::SPK_UNKNOWN_ERR, mess, __LINE__, __FILE__ ); } return X; }
void ppdOpt( SpdModel& model, Optimizer& optInfo, const DoubleMatrix& dvecXLow, const DoubleMatrix& dvecXUp, const DoubleMatrix& dvecXIn, DoubleMatrix* pdvecXOut, const DoubleMatrix& dvecXStep, const DoubleMatrix& dvecAlp, const DoubleMatrix& dvecAlpStep, double* pdPhiTildeOut, DoubleMatrix* pdrowPhiTilde_xOut, DoubleMatrix* pdmatPhiTilde_x_xOut ) { //------------------------------------------------------------ // Preliminaries. //------------------------------------------------------------ using namespace std; // If no evaluation is requested, return immediately. if ( !pdvecXOut && !pdPhiTildeOut && !pdrowPhiTilde_xOut && !pdmatPhiTilde_x_xOut ) { return; } // Get the number of design parameters. int nX = dvecXIn.nr(); //------------------------------------------------------------ // Validate the inputs (Debug mode). //------------------------------------------------------------ // Check the length of the design parameter vector. assert( nX == model.getNDesPar() ); //------------------------------------------------------------ // Validate the inputs (All modes). //------------------------------------------------------------ // [Revisit - Warm Start Disabled - Mitch] // In order to simplify the testing of this function, // warm starts have been disabled for now. if ( optInfo.getIsWarmStart() ) { throw SpkException( SpkError::SPK_USER_INPUT_ERR, "The input Optimizer object requested a warm start, which have been disabled for now.", __LINE__, __FILE__ ); } //------------------------------------------------------------ // Prepare the values required to calculate the output values. //------------------------------------------------------------ // If this value is required to calculate the output values, // initialize it so that it wil be calculated. Otherwise, // set its pointer to zero so that it won't be calculated. DoubleMatrix dvecXOutTemp; DoubleMatrix* pdvecXOutTemp = &dvecXOutTemp; if ( pdvecXOut || pdmatPhiTilde_x_xOut ) { dvecXOutTemp.resize( nX, 1 ); } else { pdvecXOutTemp = 0; } // If this value is required to calculate the output values, // initialize it so that it wil be calculated. Otherwise, // set its pointer to zero so that it won't be calculated. double dNegLogOut; double* pdNegLogOut = &dNegLogOut; if ( pdPhiTildeOut || pdrowPhiTilde_xOut || pdmatPhiTilde_x_xOut ) { dNegLogOut = 0.0; } else { pdNegLogOut = 0; } // If this value is required to calculate the output values, // initialize it so that it wil be calculated. Otherwise, // set its pointer to zero so that it won't be calculated. DoubleMatrix drowNegLog_xOut; DoubleMatrix* pdrowNegLog_xOut = &drowNegLog_xOut; if ( pdrowPhiTilde_xOut || pdmatPhiTilde_x_xOut ) { drowNegLog_xOut.resize( 1, nX ); } else { pdrowNegLog_xOut = 0; } //------------------------------------------------------------ // Prepare the objective function. //------------------------------------------------------------ // Construct the objective function, which will evaluate the // negative logarithm of the population determinant criterion. PpdOptObj ppdOptObj( nX, &model, &dvecAlp, &dvecAlpStep ); //------------------------------------------------------------ // Handle nonzero iterations for the optimization problem. //------------------------------------------------------------ // If the number of iterations is not zero, then optimize the // objective function to determine the optimal parameter value. if ( optInfo.getNMaxIter() > 0 ) { try { // The criterion phi is maximized by finding // the minumum of its negative logarithm. quasiNewtonAnyBox( ppdOptObj, optInfo, dvecXLow, dvecXUp, dvecXIn, pdvecXOutTemp, pdNegLogOut, pdrowNegLog_xOut ); } catch( SpkException& e ) { throw e.push( SpkError::SPK_UNKNOWN_ERR, "Optimization of the population determinant criterion failed.", __LINE__, __FILE__ ); } catch( const std::exception& stde ) { throw SpkException( stde, "A standard exception occurred during the optimization of the population determinant criterion.", __LINE__, __FILE__ ); } catch( ... ) { throw SpkException( SpkError::SPK_UNKNOWN_ERR, "An unknown exception occurred during the optimization of the population determinant criterion.", __LINE__, __FILE__ ); } } //------------------------------------------------------------ // Handle zero iterations for the optimization problem. //------------------------------------------------------------ // If the number of iterations is zero, then the final // value for the parameter is equal to its initial value. if ( optInfo.getNMaxIter() == 0 ) { // Set the final value. dvecXOutTemp = dvecXIn; try { // Evaluate the negative logarithm of the criterion phi, // and/or its derivative, at the final value. if ( pdPhiTildeOut || pdrowPhiTilde_xOut ) { // The objective function must be called first to set x. ppdOptObj.function( dvecXOutTemp, pdNegLogOut ); // Calculate the derivative, if necessary. if ( pdrowPhiTilde_xOut ) { ppdOptObj.gradient( pdrowNegLog_xOut ); } } } catch( SpkException& e ) { throw e.push( SpkError::SPK_UNKNOWN_ERR, "Evaluation of the population determinant criterion failed.", __LINE__, __FILE__ ); } catch( const std::exception& stde ) { throw SpkException( stde, "A standard exception occurred during the evaluation of the population determinant criterion.", __LINE__, __FILE__ ); } catch( ... ) { throw SpkException( SpkError::SPK_UNKNOWN_ERR, "An unknown exception occurred during the evaluation of the population determinant criterion.", __LINE__, __FILE__ ); } } //------------------------------------------------------------ // Finish up. //------------------------------------------------------------ // Don't set any of the values if the maximum number of // iterations was reached. if ( optInfo.getIsTooManyIter() ) { return; } // Set the final parameter value, if necessary. if ( pdvecXOut ) { *pdvecXOut = dvecXOutTemp; } // Calculate and set the final population determinant criterion // value, if necessary. double dPhiTildeOutTemp; if ( pdPhiTildeOut || pdrowPhiTilde_xOut || pdmatPhiTilde_x_xOut ) { // Calculate // // phiTilde(x) = exp[ - negLogVal(x) ] // // at x = xOut. dPhiTildeOutTemp = exp( -dNegLogOut ); if ( pdPhiTildeOut ) { *pdPhiTildeOut = dPhiTildeOutTemp; } } // Calculate and set the first derivative of the population // determinant criterion at the final parameter value, if necessary. DoubleMatrix drowPhiTilde_xOutTemp; if ( pdrowPhiTilde_xOut || pdmatPhiTilde_x_xOut ) { // Calculate // // phiTilde_x(x) = - exp[ - negLogVal(x) ] * negLogVal_x(x) // // = - phiTilde(x) * negLogVal_x(x) // // at x = xOut. drowPhiTilde_xOutTemp.resize( 1, nX ); mulByScalar( drowNegLog_xOut, -dPhiTildeOutTemp, drowPhiTilde_xOutTemp ); if ( pdrowPhiTilde_xOut ) { *pdrowPhiTilde_xOut = drowPhiTilde_xOutTemp; } } // Calculate and set the second derivative of the population // determinant criterion at the final parameter value, if necessary. if ( pdmatPhiTilde_x_xOut ) { // [Revisit - Hessian Mixes Analytic and Approximate Derivatives - Mitch] // Would it be better to approximate the Hessian, phiTilde_x_x(x), // by taking finite differences of the full derivative, phiTilde_x(x), // rather than approximating one term in the Hessian, negLog_x_xOut(x), // by taking finite differences of negLog_x(x)? // // Calculate // // phiTilde_x_x(x) = exp[ - negLogVal(x) ] * // // - - // | T | // | - negLogVal_x_x(x) + negLogVal_x(x) * negLogVal_x(x) | // | | // - - // // = phiTilde(x) * // // - - // | T | // | - negLogVal_x_x(x) + negLogVal_x(x) * negLogVal_x(x) | // | | // - - // // at x = xOut. // // Calculate the central difference of the analytic derivative // of the negative log of the criterion. DoubleMatrix dmatNegLog_x_xTilde; PpdOptObj_xFuncObj ppdOptObj_xFuncObj( &ppdOptObj ); try { dmatNegLog_x_xTilde = centdiff<PpdOptObj_xFuncObj>( ppdOptObj_xFuncObj, dvecXOutTemp, dvecXStep ); } catch( SpkException& e ) { throw e.push( SpkError::SPK_UNKNOWN_ERR, "Evaluation of the Hessian of the population determinant criterion failed.", __LINE__, __FILE__ ); } catch( const std::exception& stde ) { throw SpkException( stde, "A standard exception occurred during the evaluation of the Hessian of the population determinant criterion.", __LINE__, __FILE__ ); } catch( ... ) { throw SpkException( SpkError::SPK_UNKNOWN_ERR, "An unknown exception occurred during the evaluation of the Hessian of the population determinant criterion.", __LINE__, __FILE__ ); } // Switch the order of differentiation so that the central // difference comes before the analytic derivative. DoubleMatrix dmatNegLog_xTilde_x; dmatNegLog_xTilde_x = transposeDerivative( drowNegLog_xOut, dmatNegLog_x_xTilde ); DoubleMatrix dvecNegLogVal_xTrans; DoubleMatrix temp1; DoubleMatrix temp2; // Construct the second derivative of the population // determinant criterion. transpose( drowNegLog_xOut, dvecNegLogVal_xTrans ); multiply( dvecNegLogVal_xTrans, drowNegLog_xOut, temp1 ); subtract( temp1, dmatNegLog_xTilde_x, temp2 ); mulByScalar( temp2, dPhiTildeOutTemp, *pdmatPhiTilde_x_xOut ); } }
extern void spk_non_par( size_t level , SpkModel< CppAD::AD<double> > &admodel , SpkModel<double> &model , const DoubleMatrix &N , const DoubleMatrix &y , const DoubleMatrix &max_itr , const DoubleMatrix &epsilon , const DoubleMatrix &blow , const DoubleMatrix &bup , const DoubleMatrix &Bin , DoubleMatrix &Bout , DoubleMatrix &lamout , DoubleMatrix &Pout ) { // temporary indices size_t i, j, k; // temporary double pointer double *ptr; const double *ptr_c; // number of discrete measure points size_t J = Bin.nc(); // number of random effects size_t n = blow.nr(); // ------------ Arguments to non_par::opt_measure -------------------- assert( max_itr.nr() == 2 ); mat2cpp::matrix<size_t> maxitr(2, 1); maxitr(0, 0) = size_t( *(max_itr.data() + 0) ); maxitr(1, 0) = size_t( *(max_itr.data() + 1) ); assert( epsilon.nr() == 5 ); mat2cpp::matrix<double> eps(5, 1); eps(0, 0) = *(epsilon.data() + 0); eps(1, 0) = *(epsilon.data() + 1); eps(2, 0) = *(epsilon.data() + 2); eps(3, 0) = *(epsilon.data() + 3); eps(4, 0) = *(epsilon.data() + 4); // input likelihood function Like like(admodel, model, N, y, n); // input number of individuals in the population size_t M = N.nr(); // input lower limit for the random effects mat2cpp::matrix<double> xLow(1, n); ptr_c = blow.data(); for(k = 0; k < n; k++) xLow(0, k) = ptr_c[k]; // input upper limit for the random effects mat2cpp::matrix<double> xUp(1, n); ptr_c = bup.data(); for(k = 0; k < n; k++) xUp(0, k) = ptr_c[k]; // input and return discrete measure points mat2cpp::matrix<double> X(J, n); ptr_c = Bin.data(); for(j = 0; j < J; j++) { for(k = 0; k < n; k++) X(j, k) = ptr_c[k + j * n]; } // return weight corresponding to each measure oint mat2cpp::matrix<double> lambda(J, 1); // return convergence information mat2cpp::matrix<double> info; // return status message const char *msg; // ----------------------------------------------------------------- msg = non_par::opt_measure( level, maxitr, eps, &like, M, xLow, xUp, X, lambda, info ); // ----------------------------------------------------------------- if( strcmp(msg, "ok") != 0 ) { throw SpkException( SpkError::SPK_NON_PAR_ERR, msg, __LINE__, __FILE__ ); } // determine number of discrete measure points assert( n == X.size2() ); J = X.size1(); // dimension the return matrices Bout.resize(n, J); lamout.resize(J, 1); Pout.resize(M, J); // retrun elements of Bout ptr = Bout.data(); for(j = 0; j < J; j++) { for(k = 0; k < n; k++) ptr[k + j * n] = X(j, k); } // return elements of lamout ptr = lamout.data(); for(j = 0; j < J; j++) ptr[j] = lambda(j, 0); // return elements of Pout mat2cpp::matrix<double> beta(1, n); mat2cpp::matrix<double> psi(M, 1); ptr = Pout.data(); for(j = 0; j < J; j++) { for(k = 0; k < n; k++) beta(0, k) = X(j, k); psi = like(beta); for(i = 0; i < M; i++) ptr[ i + j * M ] = psi(i, 0); } // Check for measure points that are constrained checkMeasurePoints( eps(0, 0), xLow, xUp, X ); return; }
static double oneByOneToScalar( const DoubleMatrix &dmatA ){ assert( dmatA.nr() == 1 ); assert( dmatA.nc() == 1 ); return (dmatA.data())[0]; }
const DoubleMatrix elsq_x(const DoubleMatrix &dvecR, // m size vector, z - h const DoubleMatrix &dmatQ, // m by m symmetric, positive definite const DoubleMatrix &dmatQinv, // m by m symmetric, positive definite const DoubleMatrix &dmatH_x, // m by n matrix const DoubleMatrix &dmatQ_x // m*m by n matrix ) { using namespace std; // x: m by 1 // z: m by 1 // h: m by 1 // Q: m by m // invQ:m by m // h_x: m by n // Q_x: m*m by n const int m = dvecR.nr(); const int n = dmatQ_x.nc(); double val; assert( dmatQ.nr() == m ); assert( dmatQ.nc() == m ); assert( dmatQinv.nr() == m ); assert( dmatQinv.nc() == m ); assert( dmatH_x.nr() == m ); assert( dmatH_x.nc() == n ); assert( dmatQ_x.nr() == m*m ); assert( dmatQ_x.nc() == n ); transpose(dvecR, dvecRTrans); multiply(dvecRTrans, dmatQinv, drowW); transpose( rvec( dmatQinv ), rvecQinvTrans ); multiply(rvecQinvTrans, dmatQ_x, drowTerm1); assert(drowTerm1.nr()== 1); assert(drowTerm1.nc()== n); multiply(drowW, dmatH_x, drowTerm2); assert(drowTerm2.nr()== 1); assert(drowTerm2.nc()== n); // // The loop below untangles the following statement // for eliminating matrix object constructions and taking advantage of // Q being symmetric. // // DoubleMatrix dmatTerm3 = AkronBtimesC( drowW, rvecQinvTrans, dmatQ_x ); // // Let w be (z-h). // // The orignal formula // 0.5 [w^T kron w^T] partial_x(Qinv) --- (eq. 1) // // is equivalent to: // 0.5 partial_x(k) [ w^T Qinv w ] --- (eq. 2) // =0.5 SUM [ w(i) w(j) partial_x(k)(Q(i,j)) ], over 1<=i<=m and 1<=j<=m. // // For Q being symmetric, the following is true: // w(i) w(j) partial_x(k)(Q(i,j)) == w(j) w(i) partial_x(k)(Q(j,i)) // // const double* pW = drowW.data(); const double* pQ_x = dmatQ_x.data(); drowTerm3.resize(1,n); drowTerm3.fill(0.0); double* pTerm3 = drowTerm3.data(); for( int k=0; k<n; k++ ) { for( int j=0; j<m; j++ ) { for( int i=0; i<m; i++ ) { if( i<=j ) { val = pW[i] * pW[j] * pQ_x[ j*m+i+k*m*m ] / 2.0; drowTerm3.data()[k] += val; if( i<j ) pTerm3[k] += val; } } } } subtract( subtract(mulByScalar(drowTerm1, 0.5), drowTerm2 ) ,drowTerm3, drowAns ); // elsq_x returns a 1 by n matrix assert(drowAns.nr()==1); assert(drowAns.nc()==n); return drowAns; }
const DoubleMatrix multiply(const DoubleMatrix &X, const DoubleMatrix &Y) { DoubleMatrix Z(X.nr(), Y.nc()); multiply(X,Y,Z); return Z; }
void ppedOpt( SpdModel& model, Optimizer& xOptInfo, const DoubleMatrix& dvecXLow, const DoubleMatrix& dvecXUp, const DoubleMatrix& dvecXIn, DoubleMatrix* pdvecXOut, const DoubleMatrix& dvecXStep, Optimizer& alpOptInfo, const DoubleMatrix& dvecAlpLow, const DoubleMatrix& dvecAlpUp, const DoubleMatrix& dvecAlpIn, DoubleMatrix* pdvecAlpOut, const DoubleMatrix& dvecAlpStep, double* pdPhiTildeOut, DoubleMatrix* pdrowPhiTilde_xOut, DoubleMatrix* pdmatPhiTilde_x_xOut ) { //------------------------------------------------------------ // Preliminaries. //------------------------------------------------------------ using namespace std; // If no evaluation is requested, return immediately. if ( !pdvecXOut && !pdPhiTildeOut && !pdrowPhiTilde_xOut && !pdmatPhiTilde_x_xOut ) { return; } // Get the number of design and fixed population parameters. int nX = dvecXIn.nr(); int nAlp = dvecAlpIn.nr(); //------------------------------------------------------------ // Validate the inputs (Debug mode). //------------------------------------------------------------ // Check the length of the design parameter vector. assert( nX == model.getNDesPar() ); //------------------------------------------------------------ // Validate the inputs (All modes). //------------------------------------------------------------ // [Revisit - Warm Start Disabled - Mitch] // In order to simplify the testing of this function, // warm starts have been disabled for now. if ( xOptInfo.getIsWarmStart() || alpOptInfo.getIsWarmStart() ) { throw SpkException( SpkError::SPK_USER_INPUT_ERR, "One of the input Optimizer objects requested a warm start, which have been disabled for now.", __LINE__, __FILE__ ); } //------------------------------------------------------------ // Prepare the values required to calculate the output values. //------------------------------------------------------------ // If this value is required to calculate the output values, // initialize it so that it wil be calculated. Otherwise, // set its pointer to zero so that it won't be calculated. DoubleMatrix dvecXOutTemp; DoubleMatrix* pdvecXOutTemp = &dvecXOutTemp; if ( pdvecXOut ) { dvecXOutTemp.resize( nX, 1 ); } else { pdvecXOutTemp = 0; } // If this value is required to calculate the output values, // initialize it so that it wil be calculated. Otherwise, // set its pointer to zero so that it won't be calculated. DoubleMatrix dvecAlpOutTemp; DoubleMatrix* pdvecAlpOutTemp = &dvecAlpOutTemp; if ( pdvecAlpOut ) { dvecAlpOutTemp.resize( nAlp, 1 ); } else { pdvecAlpOutTemp = 0; } // If this value is required to calculate the output values, // initialize it so that it wil be calculated. Otherwise, // set its pointer to zero so that it won't be calculated. double dLTildeOut; double* pdLTildeOut = &dLTildeOut; if ( pdPhiTildeOut || pdrowPhiTilde_xOut || pdmatPhiTilde_x_xOut ) { dLTildeOut = 0.0; } else { pdLTildeOut = 0; } // If this value is required to calculate the output values, // initialize it so that it wil be calculated. Otherwise, // set its pointer to zero so that it won't be calculated. DoubleMatrix drowLTilde_xOut; DoubleMatrix* pdrowLTilde_xOut = &drowLTilde_xOut; if ( pdrowPhiTilde_xOut || pdmatPhiTilde_x_xOut ) { drowLTilde_xOut.resize( 1, nX ); } else { pdrowLTilde_xOut = 0; } // If this value is required to calculate the output values, // initialize it so that it wil be calculated. Otherwise, // set its pointer to zero so that it won't be calculated. DoubleMatrix dmatLTilde_x_xOut; DoubleMatrix* pdmatLTilde_x_xOut = &dmatLTilde_x_xOut; if ( pdmatPhiTilde_x_xOut ) { dmatLTilde_x_xOut.resize( nX, nX ); } else { pdmatLTilde_x_xOut = 0; } //------------------------------------------------------------ // Set arguments related to using ppkaOpt for optimal design. //------------------------------------------------------------ // ppkaOpt solves a two-level optimization problem, where the second // level is made up of multiple optimization problems that are all // solved for each iteration of the first level. The length of the // vector N specifies the number of optimation problems that must be // solved at the second level. In this use of ppkaOpt, the first // level optimization is over the design parameter vector x, while the // second level is over the fixed population vector alp. Since there // is only a single fixed population vector alp, N has length one. Its // only value is one because lTilde requires that there be at least // one data value, but this criterion itself does not depend on the data. int nIndPped = 1; int nY_iPped = 1; DoubleMatrix dvecN( nIndPped, 1 ); DoubleMatrix dvecY( nY_iPped, 1 ); dvecN.fill( (double) nY_iPped ); dvecY.fill( 0.0 ); // Choose the modified Laplace approximation. enum Objective objective = MODIFIED_LAPLACE; // Construct a model that evaluates first order approximations for // the mean and covariance of the data, maps individual to population // parameters, and maps population to design parameters. FoMapsParSpkModel ppedOptModel( &model, dvecAlpStep.toValarray() ); //------------------------------------------------------------ // Optimize the modified Laplace approximation for the negative log of phi(x). //------------------------------------------------------------ // The criterion phi(x) is optimized by replacing the definition of // lambda(alp, b) and mapObj(b) by the negative natural logarithm // of the integral with respect to alp and then calls the function // ppkaOpt to optimize the Laplace approximation for the integral. try { ppkaOpt( ppedOptModel, objective, dvecN, dvecY, xOptInfo, dvecXLow, dvecXUp, dvecXIn, &dvecXOutTemp, dvecXStep, alpOptInfo, dvecAlpLow, dvecAlpUp, dvecAlpIn, &dvecAlpOutTemp, dvecAlpStep, &dLTildeOut, &drowLTilde_xOut, &dmatLTilde_x_xOut ); } catch( SpkException& e ) { throw e.push( SpkError::SPK_UNKNOWN_ERR, "Optimization of the population expected determinant criterion failed.", __LINE__, __FILE__ ); } catch( const std::exception& stde ) { throw SpkException( stde, "A standard exception occurred during the optimization of the population expected determinant criterion.", __LINE__, __FILE__ ); } catch( ... ) { throw SpkException( SpkError::SPK_UNKNOWN_ERR, "An unknown exception occurred during the optimization of the population expected determinant criterion.", __LINE__, __FILE__ ); } //------------------------------------------------------------ // Finish up. //------------------------------------------------------------ // Don't set any of the values if the maximum number of // iterations was reached for either optimization level. if ( xOptInfo.getIsTooManyIter() || alpOptInfo.getIsTooManyIter() ) { return; } // Set the final design parameter value, if necessary. if ( pdvecXOut ) { *pdvecXOut = dvecXOutTemp; } // Set the final fixed population parameter value, if necessary. if ( pdvecAlpOut ) { *pdvecAlpOut = dvecAlpOutTemp; } // Calculate and set the final population expected determinant // criterion value, if necessary. double dPhiTildeOutTemp; if ( pdPhiTildeOut || pdrowPhiTilde_xOut || pdmatPhiTilde_x_xOut ) { // Calculate // // phiTilde(x) = exp[ - LTilde(x) ] // // at x = xOut. dPhiTildeOutTemp = exp( -dLTildeOut ); if ( pdPhiTildeOut ) { *pdPhiTildeOut = dPhiTildeOutTemp; } } // Calculate and set the first derivative of the population // expected determinant criterion at the final parameter value, // if necessary. DoubleMatrix drowPhiTilde_xOutTemp; if ( pdrowPhiTilde_xOut || pdmatPhiTilde_x_xOut ) { // Calculate // // phiTilde_x(x) = - exp[ - LTilde(x) ] * LTilde_x(x) // // = - phiTilde(x) * LTilde_x(x) // // at x = xOut. drowPhiTilde_xOutTemp.resize( 1, nX ); mulByScalar( drowLTilde_xOut, -dPhiTildeOutTemp, drowPhiTilde_xOutTemp ); if ( pdrowPhiTilde_xOut ) { *pdrowPhiTilde_xOut = drowPhiTilde_xOutTemp; } } // Calculate and set the second derivative of the population // expected determinant criterion at the final parameter value, if necessary. if ( pdmatPhiTilde_x_xOut ) { // [Revisit - Hessian Mixes Analytic and Approximate Derivatives - Mitch] // Would it be better to approximate the Hessian, phiTilde_x_x(x), // by taking finite differences of the full derivative, phiTilde_x(x), // rather than approximating one term in the Hessian, LTilde_x_xOut(x), // by taking finite differences of LTilde_x(x)? // // Calculate // // phiTilde_x_x(x) = exp[ - LTilde(x) ] * // // - - // | T | // | - LTilde_x_x(x) + LTilde_x(x) * LTilde_x(x) | // | | // - - // // = phiTilde(x) * // // - - // | T | // | - LTilde_x_x(x) + LTilde_x(x) * LTilde_x(x) | // | | // - - // // at x = xOut. // DoubleMatrix dvecLTilde_xTrans; DoubleMatrix temp1; DoubleMatrix temp2; transpose( drowLTilde_xOut, dvecLTilde_xTrans ); multiply( dvecLTilde_xTrans, drowLTilde_xOut, temp1 ); subtract( temp1, dmatLTilde_x_xOut, temp2 ); mulByScalar( temp2, dPhiTildeOutTemp, *pdmatPhiTilde_x_xOut ); } }