Sleipnir
src/bayesnetsmileelr.cpp
00001 /*****************************************************************************
00002 * This file is provided under the Creative Commons Attribution 3.0 license.
00003 *
00004 * You are free to share, copy, distribute, transmit, or adapt this work
00005 * PROVIDED THAT you attribute the work to the authors listed below.
00006 * For more information, please see the following web page:
00007 * http://creativecommons.org/licenses/by/3.0/
00008 *
00009 * This file is a component of the Sleipnir library for functional genomics,
00010 * authored by:
00011 * Curtis Huttenhower (chuttenh@princeton.edu)
00012 * Mark Schroeder
00013 * Maria D. Chikina
00014 * Olga G. Troyanskaya (ogt@princeton.edu, primary contact)
00015 *
00016 * If you use this library, the included executable tools, or any related
00017 * code in your work, please cite the following publication:
00018 * Curtis Huttenhower, Mark Schroeder, Maria D. Chikina, and
00019 * Olga G. Troyanskaya.
00020 * "The Sleipnir library for computational functional genomics"
00021 *****************************************************************************/
00022 #include "stdafx.h"
00023 #include "bayesnet.h"
00024 #include "dataset.h"
00025 
00026 #ifndef NO_SMILE
00027 
00028 namespace Sleipnir {
00029 
00030 bool CBayesNetSmileImpl::LearnELR( const IDataset* pData, size_t iIterations, bool fZero ) {
00031     size_t          i, j, iParameters;
00032     TVecVecD        vecvecfBeta, vecvecfGradient, vecvecfPrev, vecvecfDirection, vecvecfOriginal;
00033     DSL_Dmatrix*    pMatrix;
00034     DSL_intArray    veciCoords;
00035     float           dAX, dBX, dDotNew, dDotOld, dDotON, dB;
00036 //  TTrieData       TrieData( pData, 0 );
00037     TMapData        mapData;
00038     vector<bool>    vecfHidden;
00039 
00040     if( !m_fSmileNet )
00041         return false;
00042 
00043     vecfHidden.resize( pData->GetExperiments( ) );
00044     for( i = 0; i < pData->GetExperiments( ); ++i )
00045         vecfHidden[ i ] = pData->IsHidden( i );
00046     EncodeData( pData, mapData );
00047     iParameters = ELRCountParameters( );
00048     vecvecfBeta.resize( m_SmileNet.GetNumberOfNodes( ) );
00049     vecvecfGradient.resize( m_SmileNet.GetNumberOfNodes( ) );
00050     vecvecfPrev.resize( m_SmileNet.GetNumberOfNodes( ) );
00051     vecvecfDirection.resize( m_SmileNet.GetNumberOfNodes( ) );
00052     vecvecfOriginal.resize( m_SmileNet.GetNumberOfNodes( ) );
00053     for( i = 0; i < vecvecfBeta.size( ); ++i ) {
00054         pMatrix = m_SmileNet.GetNode( (int)i )->Definition( )->GetMatrix( );
00055         vecvecfOriginal[ i ].resize( pMatrix->GetSize( ) );
00056         vecvecfDirection[ i ].resize( pMatrix->GetSize( ) );
00057         vecvecfPrev[ i ].resize( pMatrix->GetSize( ) );
00058         vecvecfGradient[ i ].resize( pMatrix->GetSize( ) );
00059         vecvecfBeta[ i ].resize( pMatrix->GetSize( ) );
00060         for( j = 0; j < vecvecfBeta[ i ].size( ); ++j )
00061             vecvecfBeta[ i ][ j ] = (float)log( (*pMatrix)[ (int)j ] ); }
00062     dAX = 0;
00063     dBX = 0.1f;
00064 
00065     copy( vecvecfBeta.begin( ), vecvecfBeta.end( ), vecvecfOriginal.begin( ) );
00066     ELRComputeGradient( vecfHidden, mapData, fZero, vecvecfGradient );
00067     copy( vecvecfGradient.begin( ), vecvecfGradient.end( ), vecvecfPrev.begin( ) );
00068     copy( vecvecfGradient.begin( ), vecvecfGradient.end( ), vecvecfDirection.begin( ) );
00069     dDotNew = ELRDot( vecvecfGradient, vecvecfPrev );
00070 
00071     for( i = 0; i < iIterations; ++i ) {
00072         g_CatSleipnir( ).notice( "CBayesNetSmile::LearnELR( %d, %d ) iteration %d/%d",
00073             iIterations, fZero, i, iIterations );
00074         if( !dDotNew )
00075             continue;
00076         ELRNormalizeDirection( vecvecfDirection );
00077         ELRLineSearch( vecfHidden, mapData, vecvecfDirection, vecvecfOriginal, vecvecfBeta, dAX, dBX, fZero );
00078         copy( vecvecfBeta.begin( ), vecvecfBeta.end( ), vecvecfOriginal.begin( ) );
00079         ELRCopyParameters( vecvecfBeta );
00080         ELRComputeGradient( vecfHidden, mapData, fZero, vecvecfGradient );
00081 
00082         dDotOld = dDotNew;
00083         dDotON = ELRDot( vecvecfGradient, vecvecfPrev );
00084         copy( vecvecfGradient.begin( ), vecvecfGradient.end( ), vecvecfPrev.begin( ) );
00085         dDotNew = ELRDot( vecvecfGradient, vecvecfPrev );
00086         dB = ( dDotNew - dDotON ) / dDotOld;
00087         if( !( ( i + 1 ) % iParameters ) || ( dB <= 0 ) )
00088             copy( vecvecfGradient.begin( ), vecvecfGradient.end( ), vecvecfDirection.begin( ) );
00089         else
00090             ELRComputeDirection( dB, vecvecfGradient, vecvecfDirection ); }
00091 
00092     return true; }
00093 
00094 size_t CBayesNetSmileImpl::ELRCountParameters( ) const {
00095     int     i;
00096     size_t  iRet;
00097 
00098     for( iRet = i = 0; i < m_SmileNet.GetNumberOfNodes( ); ++i )
00099         iRet += m_SmileNet.GetNode( i )->Definition( )->GetSize( );
00100 
00101     return iRet; }
00102 
00103 void CBayesNetSmileImpl::ELRCopyParameters( TVecVecD& vecvecfBeta ) {
00104     static const float  c_dMinimum  = log( FLT_MIN );
00105     size_t              i, j, k, iIndex, iDomains;
00106     float               dSum, dCur, dMax;
00107     DSL_nodeDefinition* pDef;
00108     DSL_Dmatrix*        pDefs;
00109 
00110     for( i = 0; i < vecvecfBeta.size( ); ++i ) {
00111         pDef = m_SmileNet.GetNode( (int)i )->Definition( );
00112         pDefs = pDef->GetMatrix( );
00113         iDomains = pDef->GetNumberOfOutcomes( );
00114         for( j = 0; j < vecvecfBeta[ i ].size( ); j += iDomains ) {
00115             dSum = 0;
00116             dMax = vecvecfBeta[ i ][ j ];
00117             for( k = 1; k < iDomains; ++k )
00118                 if( ( dCur = vecvecfBeta[ i ][ j + k ] ) > dMax )
00119                     dMax = dCur;
00120             for( k = 0; k < iDomains; ++k ) {
00121                 iIndex = j + k;
00122                 if( ( vecvecfBeta[ i ][ iIndex ] -= dMax ) < c_dMinimum )
00123                     vecvecfBeta[ i ][ iIndex ] = c_dMinimum;
00124                 dSum += exp( vecvecfBeta[ i ][ iIndex ] ); }
00125             if( dSum )
00126                 for( k = 0; k < iDomains; ++k ) {
00127                     iIndex = j + k;
00128                     (*pDefs)[ (int)iIndex ] = exp( vecvecfBeta[ i ][ iIndex ] ) / dSum; } } } }
00129 
00130 // EXPENSIVE
00131 void CBayesNetSmileImpl::ELRComputeGradient( const vector<bool>& vecfHidden, const TMapData& mapData, bool fZero,
00132     TVecVecD& vecvecfGradient ) {
00133     size_t  i, j;
00134 
00135     for( i = 0; i < vecvecfGradient.size( ); ++i )
00136         for( j = 0; j < vecvecfGradient[ i ].size( ); ++j )
00137             vecvecfGradient[ i ][ j ] = 0;
00138 
00139     for( TMapData::const_iterator iterData = mapData.begin( ); iterData != mapData.end( ); ++iterData )
00140         if( IsAnswer( iterData->first ) && FillCPTs( vecfHidden, iterData->first, fZero, false ) ) {
00141             ELRUpdateGradient( -(float)iterData->second, vecvecfGradient );
00142             m_SmileNet.GetNode( 0 )->Value( )->SetEvidence( iterData->first[ 0 ] - c_cBase );
00143             ELRUpdateGradient( (float)iterData->second, vecvecfGradient ); } }
00144 /*
00145     for( TTrieData::iterator IterData( TrieData ); !IterData.IsDone( ); IterData.Next( ) )
00146         if( IterData.GetPosition( )[ 0 ] && FillCPTs( vecfHidden, IterData.GetPosition( ), fZero, false ) ) {
00147             ELRUpdateGradient( -(float)IterData.Get( ), vecvecfGradient );
00148             m_SmileNet.GetNode( 0 )->Value( )->SetEvidence( IterData.GetPosition( )[ 0 ] - 1 );
00149             ELRUpdateGradient( (float)IterData.Get( ), vecvecfGradient ); } }
00150 */
00151 
00152 void CBayesNetSmileImpl::ELRUpdateGradient( float dRate, TVecVecD& vecvecfGradient ) {
00153     size_t              i, j;
00154     double              dSum, dPosterior;
00155     int                 k, iTmp, iDomain, iDomains, iEvidence;
00156     DSL_node*           pNode;
00157     DSL_nodeValue*      pValue;
00158     DSL_nodeDefinition* pDef;
00159     DSL_Dmatrix*        pValues;
00160     DSL_Dmatrix*        pDefs;
00161     DSL_intArray        veciParents, veciCoords;
00162 
00163     m_SmileNet.UpdateBeliefs( );
00164     for( i = 0; i < vecvecfGradient.size( ); ++i ) {
00165         pNode = m_SmileNet.GetNode( (int)i );
00166         veciParents = pNode->Parents( );
00167         pValue = pNode->Value( );
00168         iEvidence = pValue->GetEvidence( );
00169         pValues = pValue->GetMatrix( );
00170         pDef = pNode->Definition( );
00171         iDomains = pDef->GetNumberOfOutcomes( );
00172         pDefs = pDef->GetMatrix( );
00173 
00174         dSum = 0;
00175         for( j = 0,pDefs->IndexToCoordinates( iTmp = 0, veciCoords ); iTmp != DSL_OUT_OF_RANGE;
00176             ++j,iTmp = pDefs->NextCoordinates( veciCoords ) ) {
00177             iDomain = veciCoords[ veciCoords.GetSize( ) - 1 ];
00178             if( veciParents.NumItems( ) ) {
00179                 if( iEvidence == DSL_OUT_OF_RANGE )
00180                     dPosterior = (*pValues)[ iDomain ];
00181                 else if( iDomain == iEvidence ) {
00182                     dPosterior = 1;
00183                     for( k = 0; k < veciParents.NumItems( ); ++k )
00184                         dPosterior *= m_SmileNet.GetNode( veciParents[ k ] )->Value(
00185                             )->GetMatrix( )->Subscript( veciCoords[ k ] ); }
00186                 else
00187                     dPosterior = 0; }
00188             else
00189                 dPosterior = (*pValues)[ veciCoords[ 0 ] ];
00190             dSum += dPosterior;
00191             vecvecfGradient[ i ][ j ] += dRate * (float)dPosterior;
00192 
00193             if( ( iDomain + 1 ) == iDomains ) {
00194                 for( k = 0; k < iDomains; ++k ) {
00195                     veciCoords[ veciCoords.GetSize( ) - 1 ] = k;
00196                     vecvecfGradient[ i ][ k + j - iDomains + 1 ] -=
00197                         (float)( dRate * dSum * (*pDefs)[ veciCoords ] ); }
00198                 dSum = 0; } } } }
00199 
00200 float CBayesNetSmileImpl::ELRDot( const TVecVecD& vecvecfOne, const TVecVecD& vecvecfTwo ) {
00201     size_t  i, j;
00202     float   dRet;
00203 
00204     dRet = 0;
00205     for( i = 0; i < vecvecfOne.size( ); ++i )
00206         for( j = 0; j < vecvecfOne[ i ].size( ); ++j )
00207             dRet += vecvecfOne[ i ][ j ] * vecvecfTwo[ i ][ j ];
00208 
00209     return dRet; }
00210 
00211 void CBayesNetSmileImpl::ELRNormalizeDirection( TVecVecD& vecvecfDirection ) const {
00212     size_t  i, j;
00213     float   d, dSum;
00214     int     k, iDomains;
00215 
00216     for( i = 0; i < vecvecfDirection.size( ); ++i ) {
00217         iDomains = m_SmileNet.GetNode( (int)i )->Definition( )->GetNumberOfOutcomes( );
00218         for( j = 0; j < vecvecfDirection[ i ].size( ); j += iDomains ) {
00219             dSum = 0;
00220             for( k = 0; k < iDomains; ++k ) {
00221                 d = vecvecfDirection[ i ][ j + k ];
00222                 dSum += d * d; }
00223 
00224             if( dSum = sqrt( dSum ) )
00225                 for( k = 0; k < iDomains; ++k )
00226                     vecvecfDirection[ i ][ j + k ] /= dSum; } } }
00227 
00228 // EXPENSIVE
00229 float CBayesNetSmileImpl::ELRLineSearch( const vector<bool>& vecfHidden, const TMapData& mapData,
00230     const TVecVecD& vecvecfDirection, const TVecVecD& vecvecfOriginal, TVecVecD& vecvecfBeta,
00231     float& dAX, float& dBX, bool fZero ) {
00232     float   dFA, dFB, dFC, dCX;
00233 
00234     ELRBracket( vecfHidden, mapData, vecvecfDirection, vecvecfOriginal, vecvecfBeta,
00235         dAX, dBX, dCX, dFA, dFB, dFC, fZero );
00236     return ELRBrent( vecfHidden, mapData, vecvecfDirection, vecvecfOriginal, vecvecfBeta,
00237         dAX, dBX, dCX, dFA, dFB, dFC, fZero ); }
00238 
00239 float CBayesNetSmileImpl::ELREvalFunction( const vector<bool>& vecfHidden, const TMapData& mapData, float dX,
00240     const TVecVecD& vecvecfDirection, const TVecVecD& vecvecfOriginal, TVecVecD& vecvecfBeta, bool fZero  ) {
00241     size_t  i, j;
00242 
00243     for( i = 0; i < vecvecfBeta.size( ); ++i )
00244         for( j = 0; j < vecvecfBeta[ i ].size( ); ++j )
00245             vecvecfBeta[ i ][ j ] = ( dX * vecvecfDirection[ i ][ j ] ) + vecvecfOriginal[ i ][ j ];
00246     ELRCopyParameters( vecvecfBeta );
00247 
00248     return -ELRConditionalLikelihood( vecfHidden, mapData, fZero ); }
00249 
00250 float CBayesNetSmileImpl::ELRAvoidZero( float d ) {
00251     static const float  c_dTiny = 1e-10f;
00252 
00253     if( d >= 0 ) {
00254         if( d < c_dTiny )
00255             return c_dTiny; }
00256     else if( d > -c_dTiny )
00257         return -c_dTiny;
00258 
00259     return d; }
00260 
00261 void CBayesNetSmileImpl::ELRBracket( const vector<bool>& vecfHidden, const TMapData& mapData,
00262     const TVecVecD& vecvecfDirection, const TVecVecD& vecvecfOriginal, TVecVecD& vecvecfBeta, float& dAX,
00263     float& dBX, float& dCX, float& dFA, float& dFB, float& dFC, bool fZero ) {
00264     static const float  c_dGolden       = 1.618034f;
00265     static const float  c_dLimit        = 100;
00266     static const size_t c_iIterations   = 100;
00267     size_t  i;
00268     float   dR, dQ, dU, dFU, dULim;
00269 
00270     dFA = ELREvalFunction( vecfHidden, mapData, dAX, vecvecfDirection, vecvecfOriginal, vecvecfBeta, fZero );
00271     dFB = ELREvalFunction( vecfHidden, mapData, dBX, vecvecfDirection, vecvecfOriginal, vecvecfBeta, fZero );
00272     if( dFB > dFA ) {
00273         swap( dAX, dBX );
00274         swap( dFA, dFB ); }
00275 
00276     dCX = dBX + ( c_dGolden * ( dBX - dAX ) );
00277     dFC = ELREvalFunction( vecfHidden, mapData, dCX, vecvecfDirection, vecvecfOriginal, vecvecfBeta, fZero );
00278     for( i = 0; ( i < c_iIterations ) && ( dFB > dFC ); ++i ) {
00279         /* finding the minimum point dU of the extrapolated parabola*/
00280         dR = ( dBX - dAX ) * ( dFB - dFC );
00281         dQ = ( dBX - dCX ) * ( dFB - dFA );
00282         dU = dBX - ( ( ( ( dBX - dCX ) * dQ ) - ( ( dBX - dAX ) * dR ) ) / ( 2 * ELRAvoidZero( dQ - dR ) ) );
00283         dULim = dBX + ( c_dLimit * ( dCX - dBX ) );
00284 
00285         /* bx>u and u>cx, or u is between b and c */
00286         if( ( ( dBX - dU ) * ( dU - dCX ) ) > 0 ) {
00287             dFU = ELREvalFunction( vecfHidden, mapData, dU, vecvecfDirection, vecvecfOriginal, vecvecfBeta, fZero );
00288 
00289             /* the minimum is between b and c, because c is lower than b,
00290              * otherwise we can not be in the loop. So u is lower than both b
00291              * and c. We are done. */
00292             if( dFU < dFC ) {
00293                 dAX = dBX;
00294                 dFA = dFB;
00295                 dBX = dU;
00296                 dFB = dFU;
00297                 break; }
00298             /* b is lower than both a and u. we are done*/
00299             else if( dFU > dFB ) {
00300                 dCX = dU;
00301                 dFC = dFU;
00302                 break; }
00303             /* u is lower than b, but higher than c. useless.
00304              * extend it beyound c to prepare for the next iteration
00305              * u will be copied to c. */
00306 
00307             dU = dCX + ( c_dGolden * ( dCX - dBX ) );
00308             dFU = ELREvalFunction( vecfHidden, mapData, dU, vecvecfDirection, vecvecfOriginal, vecvecfBeta, fZero ); }
00309         /* u is between c and the far limit */
00310         else if( ( ( dCX - dU ) * ( dU - dULim ) ) > 0 ) {
00311             dFU = ELREvalFunction( vecfHidden, mapData, dU, vecvecfDirection, vecvecfOriginal, vecvecfBeta, fZero );
00312             /* if u is still lower than c, extend the points beyond u and shift the values */
00313             if( dFU < dFC ) {
00314                 dBX = dCX;
00315                 dCX = dU;
00316                 dU = dCX + ( c_dGolden * ( dCX - dBX ) );
00317                 dFB = dFC;
00318                 dFC = dFU;
00319                 dFU = ELREvalFunction( vecfHidden, mapData, dU, vecvecfDirection, vecvecfOriginal, vecvecfBeta,
00320                     fZero ); } }
00321         /* u is beyond the far limit. ulim is between u and c. c and ulim defines the direction. */
00322         else if( ( ( dU - dULim ) * ( dULim - dCX ) ) > 0 )
00323             dFU = ELREvalFunction( vecfHidden, mapData, dU = dULim, vecvecfDirection, vecvecfOriginal, vecvecfBeta,
00324                 fZero );
00325         /* other cases... what could be left? */
00326         else
00327             dFU = ELREvalFunction( vecfHidden, mapData, dU = dCX + ( c_dGolden * ( dCX - dBX ) ), vecvecfDirection,
00328                 vecvecfOriginal, vecvecfBeta, fZero );
00329 
00330         /*eliminate oldest point and repeat the process*/
00331         dAX = dBX;
00332         dBX = dCX;
00333         dCX = dU;
00334         dFA = dFB;
00335         dFB = dFC;
00336         dFC = dFU; } }
00337 
00338 float CBayesNetSmileImpl::ELRBrent( const vector<bool>& vecfHidden, const TMapData& mapData,
00339     const TVecVecD& vecvecfDirection, const TVecVecD& vecvecfOriginal, TVecVecD& vecvecfBeta, float& dAX,
00340     float& dBX, float dCX, float dFA, float dFB, float dFC, bool fZero ) {
00341     static const size_t c_iIterations   = 100;
00342     static const float  c_dZEPS         = 1e-8f;
00343     static const float  c_dIGolden      = 0.3819660f;
00344     static const float  c_dTolerance    = 1e-4f;
00345     /* d, e, etemp are the step. e is the step before d, etemp is the step
00346      * before e
00347      * tol,tol1,tol2 are the error tolerance. for simple thinking, consider them 0. */
00348     float   a,b,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u=0,v,w,x,xm,e,d;
00349     size_t  iter;
00350 
00351     /* a, b brackets the minimum. ensure a<=b*/
00352     if( dAX < dCX ) {
00353         a = dAX;
00354         b = dCX; }
00355     else {
00356         a = dCX;
00357         b = dAX; }
00358 
00359     /* initialize all three lowest points to the middle variable of the bracket*/
00360     e = d = b - a;
00361     x = dBX;
00362     fx = dFB;
00363     if( dFA < dFC ) {
00364         w = dAX;
00365         fw = dFA;
00366         v = dCX;
00367         fv = dFC; }
00368     else {
00369         w = dCX;
00370         fw = dFC;
00371         v = dAX;
00372         fv = dFA; }
00373 
00374     for( iter = 0; iter < c_iIterations; ++iter ) {
00375         xm = 0.5f * ( a + b );
00376         /* error tolerance:2*tol*x.  note that tol, tol1, tol2 are all positive*/
00377         tol2 = 2 * ( tol1 = ( ( c_dTolerance * fabs( x ) ) + c_dZEPS ) );
00378         /* the sum of x - xm and 0.5*(b-a) smaller than tolerance*/
00379         if( ( fw - fx ) <= ( c_dTolerance * fx ) ) {
00380             dAX = a;
00381             dBX = b;
00382             return fx; }
00383 
00384         /* e is used to check to see whether it is ok to take a parabolic step
00385          * parabolic step will not be considered if the step before previous
00386          * step was too small , made  no progress.
00387          * I'm not sure when could this happen... if progress is too small,
00388          * it should be done.... unless it's the first time */
00389         if( fabs( e ) > tol1 ) {
00390             /* fit a parabola*/
00391             r = ( x - w ) * ( fx - fv );
00392             q = ( x - v ) * ( fx - fw );
00393             p = ( ( x - v ) * q ) - ( ( x - w ) * r );
00394             q = 2 * ( q - r );
00395 
00396             /*ensure q is positive, and reverse the ratio p/q
00397              * these extra steps are used to avoid dividing by zero, making the
00398              * denominator positive ensure the later inequality holds because it is
00399              * multiplied by a positive number */
00400             if( q > 0 )
00401                 p *= -1;
00402             else
00403                 q = -q;
00404 
00405             etemp = e;
00406             /*the previouse step size*/
00407             e = d;
00408 
00409             /* after this iteration, e will be either the previous step size
00410              * (if the current step is a parabolic step), or the size of the
00411              * current larger segment, (if the current step is a GOLD step).
00412              * therefore, on the next iteration, a parabolic step will be
00413              * taken only if the parabolic step is smaller than the
00414              * previous step, or smaller than the current larger segment */
00415 
00416             /* the first part test if the current step is greater than the step
00417              * before the previous step. If yes, it may not be making progress
00418              * and may not converge using parabola, so use GOLD step instead.
00419              *
00420              * the 2nd part test the new minimum of the parabola x+p/q (which
00421              * is the old x-p/q) is outside of (a,b)
00422              * e is set to be the larger of the 2 segments */
00423             if( ( fabs( p ) >= fabs( 0.5 * q * etemp ) ) ||
00424                 ( ( p <= ( q * ( a - x ) ) ) || ( p >= ( q * ( b - x ) ) ) ) )
00425                 d = c_dIGolden * ( e = ( x >= xm ? ( a - x ) : ( b - x ) ) );
00426             /* parabola is good. update the minimum u */
00427             else {
00428                 /* parabolic step*/
00429                 d = p / q;
00430                 /* notice that u's value is not fixed yet, it's only set for
00431                  * testing purpose now. it will be fixed later
00432                  * Bad coding. Here should really make the code cleaner by using another
00433                  * variable, say uTest, or boundaryTest. */
00434                 u = x + d;
00435 
00436                 /* if the minimum is too close to a or b, step away by tol1 to
00437                  * ensure there is progress made.*/
00438                 if( ( u - a ) < tol2 )
00439                     d += tol1;
00440                 else if( ( b - u ) < tol2 )
00441                     d -= tol1; } }
00442         /* take a GOLD step in case of problem*/
00443         else
00444             d = c_dIGolden * ( e = ( ( x > xm ) ? ( a - x ) : ( b - x ) ) );
00445 
00446         /* update the new minimum
00447          * if d<tolerance, step by tolerance, because otherwise it would give
00448          * the "same" result and make no progress */
00449         if( fabs( d ) >=tol1 )
00450             u = x + d;
00451         else {
00452             if( d > 0 )
00453                 u = x + tol1;
00454             else
00455                 u = x - tol1; }
00456         fu = ELREvalFunction( vecfHidden, mapData, u, vecvecfDirection, vecvecfOriginal, vecvecfBeta, fZero );
00457 
00458         /* u is the lowest point of the function,
00459          * lower than the previous lowest point x.
00460          * so make x one of the boundary points.
00461          * then old point v will be discarded.
00462          * and one of old a,b will be discarded, and will be the 2nd lowest
00463          * point w, which was the old lowest point x.
00464          * so w will be one of the boundary points a,b. */
00465         if( fu < fx ) {
00466             if( u >= x )
00467                 a = x;
00468             else
00469                 b = x;
00470             /*update three lowest points x,v,w*/
00471             v = w;
00472             w = x;
00473             x = u;
00474             fv = fw;
00475             fw = fx;
00476             fx = fu; }
00477         /* x is still the lowest point*/
00478         else {
00479             /* we know u is between a and b from before,
00480              * so we can reduce the bracket */
00481             if( u < x )
00482                 a = u;
00483             else
00484                 b = u;
00485 
00486             /* if u is lower than 2nd lowest point w, make u the 2nd lowest
00487              * point, and w the 3rd
00488              * if the lowest point is same as the 2nd lowest point */
00489             if( ( fu <= fw ) || ( w == x ) ) {
00490                 v = w;
00491                 fv = fw;
00492                 w = u;
00493                 fw = fu; }
00494             /* if u is lower than the 3rd lowest point v,
00495              * or if the 3rd lowest point is same as the lowest or 2nd lowest point */
00496             else if( ( fu <= fv ) || ( v == x ) || ( v == w ) ) {
00497                 v = u;
00498                 fv = fu; } } }
00499 
00500     g_CatSleipnir( ).warn( "CBayesNetSmileImpl::ELRBrent( ) too many iterations" );
00501     dAX = a;
00502     dBX = b;
00503     return fx; }
00504 
00505 float CBayesNetSmileImpl::ELRConditionalLikelihood( const vector<bool>& vecfHidden, const TMapData& mapData,
00506     bool fZero ) {
00507     size_t          iCount;
00508     float           dRet;
00509     DSL_Dmatrix*    pMatrix;
00510 
00511     iCount = 0;
00512     dRet = 0;
00513     for( TMapData::const_iterator iterData = mapData.begin( ); iterData != mapData.end( ); ++iterData )
00514         if( IsAnswer( iterData->first ) && FillCPTs( vecfHidden, iterData->first, fZero, false ) ) {
00515             iCount += iterData->second;
00516             m_SmileNet.UpdateBeliefs( );
00517             pMatrix = m_SmileNet.GetNode( 0 )->Value( )->GetMatrix( );
00518             dRet += (float)( iterData->second * log( (*pMatrix)[ iterData->first[ 0 ] - c_cBase ] ) ); }
00519 /*
00520     for( TTrieData::iterator IterData( TrieData ); !IterData.IsDone( ); IterData.Next( ) )
00521         if( IterData.GetPosition( )[ 0 ] && FillCPTs( vecfHidden, IterData.GetPosition( ), fZero, false ) ) {
00522             iCount += IterData.Get( );
00523             m_SmileNet.UpdateBeliefs( );
00524             pMatrix = m_SmileNet.GetNode( 0 )->Value( )->GetMatrix( );
00525             dRet += (float)( IterData.Get( ) * log( (*pMatrix)[ IterData.GetPosition( )[ 0 ] - 1 ] ) ); }
00526 */
00527 
00528     return ( dRet / iCount ); }
00529 
00530 void CBayesNetSmileImpl::ELRComputeDirection( float dB, const TVecVecD& vecvecfGradient,
00531     TVecVecD& vecvecfDirection ) {
00532     size_t  i, j;
00533 
00534     for( i = 0; i < vecvecfDirection.size( ); ++i )
00535         for( j = 0; j < vecvecfDirection[ i ].size( ); ++j )
00536             vecvecfDirection[ i ][ j ] = vecvecfGradient[ i ][ j ] + ( dB * vecvecfDirection[ i ][ j ] ); }
00537 
00538 }
00539 
00540 #endif // NO_SMILE