Sleipnir
src/bayesnetfn.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 "statistics.h"
00025 
00026 namespace Sleipnir {
00027 
00028 #ifndef NO_SMILE
00029 
00030 // CBayesNetFNNode //////////////////////////////////////////////////////////
00031 
00032 const char  CBayesNetFNNode::c_szType[] = "type";
00033 
00034 CBayesNetFNNode* CBayesNetFNNode::Open( DSL_node* pNode ) {
00035     static const CBayesNetFNNode*   c_pDefault  = new CBayesNetFNNodeDiscrete( );
00036     static const CBayesNetFNNode*   c_apTypes[] = {
00037         new CBayesNetFNNodeDiscrete( ),
00038         new CBayesNetFNNodeGaussian( ),
00039         new CBayesNetFNNodeBeta( ),
00040         new CBayesNetFNNodeExponential( ),
00041         new CBayesNetFNNodeMOG( ),
00042         NULL };
00043     CBayesNetFNNode*    pRet;
00044     int                 i, j, iDim;
00045     const char*         szType;
00046     DSL_Dmatrix*        pMatrix;
00047 
00048     if( ( i = pNode->Info( ).UserProperties( ).FindProperty( c_szType ) ) < 0 )
00049         pRet = c_pDefault->New( pNode );
00050     else {
00051         pRet = NULL;
00052         szType = pNode->Info( ).UserProperties( ).GetPropertyValue( i );
00053         for( i = 0; c_apTypes[ i ]; ++i )
00054             if( !strcmp( szType, c_apTypes[ i ]->GetType( ) ) ) {
00055                 pRet = c_apTypes[ i ]->New( pNode );
00056                 break; } }
00057     pMatrix = pNode->Definition( )->GetMatrix( );
00058     if( pRet ) {
00059         DSL_intArray    veciDims    = pMatrix->GetDimensions( );
00060 
00061         iDim = ( veciDims.GetSize( ) > 1 ) ? 1 : 0;
00062         pRet->m_strName = pNode->Info( ).Header( ).GetId( );
00063         pRet->m_Params.Initialize( iDim ? veciDims[ 0 ] : 1, veciDims[ iDim ] );
00064         for( i = 0; (size_t)i < pRet->m_Params.GetRows( ); ++i ) {
00065             if( iDim )
00066                 veciDims[ 0 ] = i;
00067             for( j = 0; (size_t)j < pRet->m_Params.GetColumns( ); ++j ) {
00068                 veciDims[ iDim ] = j;
00069                 pRet->m_Params.Set( i, j, (float)(*pMatrix)[ veciDims ] ); } } }
00070 
00071     return pRet; }
00072 
00073 const string& CBayesNetFNNode::GetName( ) const {
00074 
00075     return m_strName; }
00076 
00077 unsigned char CBayesNetFNNode::GetParameters( ) const {
00078 
00079     return (unsigned char)m_Params.GetColumns( ); }
00080 
00081 void CBayesNetFNNode::Reverse( ) {
00082     size_t          iCol, iRow;
00083     vector<float>   vecdRow;
00084 
00085     vecdRow.resize( m_Params.GetColumns( ) );
00086     for( iRow = 0; iRow < m_Params.GetRows( ); ++iRow ) {
00087         for( iCol = 0; iCol < vecdRow.size( ); ++iCol )
00088             vecdRow[ iCol ] = m_Params.Get( iRow, vecdRow.size( ) - iCol - 1 );
00089         for( iCol = 0; iCol < vecdRow.size( ); ++iCol )
00090             m_Params.Set( iRow, iCol, vecdRow[ iCol ] ); } }
00091 
00092 bool CBayesNetFNNode::Save( DSL_node* pNode ) const {
00093     int             i;
00094     size_t          iCol, iRow;
00095     DSL_Dmatrix*    pMatrix     = pNode->Definition( )->GetMatrix( );
00096     DSL_intArray    veciDims    = pMatrix->GetDimensions( );
00097 
00098     if( m_strName != pNode->Info( ).Header( ).GetId( ) )
00099         return false;
00100     if( ( i = pNode->Info( ).UserProperties( ).FindProperty( c_szType ) ) < 0 )
00101         pNode->Info( ).UserProperties( ).AddProperty( c_szType, GetType( ) );
00102     else
00103         pNode->Info( ).UserProperties( ).ChangePropertyValue( i, GetType( ) );
00104 
00105     i = ( veciDims.GetSize( ) > 1 ) ? 1 : 0;
00106     for( iRow = 0; iRow < m_Params.GetRows( ); ++iRow ) {
00107         if( i )
00108             veciDims[ 0 ] = (int)iRow;
00109         for( iCol = 0; iCol < m_Params.GetColumns( ); ++iCol ) {
00110             veciDims[ i ] = (int)iCol;
00111             (*pMatrix)[ veciDims ] = m_Params.Get( iRow, iCol ); } }
00112 
00113     return true; }
00114 
00115 bool CBayesNetFNNode::Learn( const vector<size_t>& veciCounts ) {
00116     vector<float>   vecdRow;
00117     size_t          iRow, iCol, iSum;
00118 
00119     if( veciCounts.size( ) != m_Params.GetColumns( ) )
00120         return false;
00121 
00122     iSum = veciCounts.size( );
00123     for( iCol = 0; iCol < veciCounts.size( ); ++iCol )
00124         iSum += veciCounts[ iCol ];
00125     vecdRow.resize( veciCounts.size( ) );
00126     for( iCol = 0; iCol < vecdRow.size( ); ++iCol )
00127         vecdRow[ iCol ] = ( veciCounts[ iCol ] + 1.0f ) / iSum;
00128     for( iRow = 0; iRow < m_Params.GetRows( ); ++iRow )
00129         for( iCol = 0; iCol < m_Params.GetColumns( ); ++iCol )
00130             m_Params.Set( iRow, iCol, vecdRow[ iCol ] );
00131 
00132     return true; }
00133 
00134 // CBayesNetFNNodeDiscrete //////////////////////////////////////////////////
00135 
00136 void CBayesNetFNNodeDiscrete::Randomize( ) {
00137     size_t      iCol, iRow, iSum;
00138     vector<int> veciRow;
00139 
00140     veciRow.resize( m_Params.GetColumns( ) );
00141     for( iRow = 0; iRow < m_Params.GetRows( ); ++iRow ) {
00142         for( iSum = iCol = 0; iCol < veciRow.size( ); ++iCol )
00143             iSum += ( veciRow[ iCol ] = rand( ) );
00144         for( iCol = 0; iCol < veciRow.size( ); ++iCol )
00145             m_Params.Set( iRow, iCol, (float)veciRow[ iCol ] / iSum ); } }
00146 
00147 bool CBayesNetFNNodeDiscrete::Learn( const IDataset* pData, size_t iNode, size_t iZero ) {
00148     CFullMatrix<size_t> MatCounts;
00149     vector<size_t>      veciSums;
00150     size_t              i, j, iAnswer, iVal;
00151 
00152     veciSums.resize( m_Params.GetRows( ) );
00153     MatCounts.Initialize( m_Params.GetRows( ), m_Params.GetColumns( ) );
00154     for( i = 0; i < MatCounts.GetRows( ); ++i ) {
00155 #pragma warning( disable : 4267 )
00156         veciSums[ i ] = MatCounts.GetColumns( );
00157 #pragma warning( default : 4267 )
00158         for( j = 0; j < MatCounts.GetColumns( ); ++j )
00159             MatCounts.Set( i, j, 1 ); }
00160     for( i = 0; i < pData->GetGenes( ); ++i )
00161         for( j = ( i + 1 ); j < pData->GetGenes( ); ++j )
00162             if( pData->IsExample( i, j ) && ( ( iAnswer = pData->GetDiscrete( i, j, 0 ) ) != -1 ) ) {
00163                 if( ( iVal = pData->GetDiscrete( i, j, iNode ) ) == -1 ) {
00164                     if( iZero == -1 )
00165                         continue;
00166                     iVal = iZero; }
00167                 if( ( iAnswer >= MatCounts.GetRows( ) ) || ( iVal >= MatCounts.GetColumns( ) ) )
00168                     return false;
00169                 MatCounts.Get( iAnswer, iVal )++;
00170                 veciSums[ iAnswer ]++; }
00171 
00172     for( i = 0; i < m_Params.GetRows( ); ++i )
00173         for( j = 0; j < m_Params.GetColumns( ); ++j )
00174             m_Params.Set( i, j, (float)MatCounts.Get( i, j ) / veciSums[ i ] );
00175 
00176     return true; }
00177 
00178 bool CBayesNetFNNodeDiscrete::Evaluate( float dValue, vector<float>& vecdOut ) const {
00179     size_t  i;
00180 
00181     if( CMeta::IsNaN( dValue ) ) {
00182         if( m_Params.GetRows( ) != 1 )
00183             return false;
00184         vecdOut.resize( m_Params.GetColumns( ) );
00185         for( i = 0; i < vecdOut.size( ); ++i )
00186             vecdOut[ i ] = m_Params.Get( 0, i );
00187         return true; }
00188 
00189     vecdOut.resize( m_Params.GetRows( ) );
00190     for( i = 0; i < vecdOut.size( ); ++i )
00191         vecdOut[ i ] = m_Params.Get( i, (unsigned char)dValue );
00192 
00193     return true; }
00194 
00195 // CBayesNetFNNodeGaussian //////////////////////////////////////////////////
00196 
00197 void CBayesNetFNNodeGaussian::Randomize( ) {
00198     size_t  i;
00199 
00200     for( i = 0; i < m_Params.GetRows( ); ++i ) {
00201         m_Params.Set( i, c_iMu, (float)( rand( ) - ( RAND_MAX / 2 ) ) );
00202         m_Params.Set( i, c_iSigma, (float)rand( ) / RAND_MAX ); } }
00203 
00204 bool CBayesNetFNNodeGaussian::Learn( const IDataset* pData, size_t iNode, size_t iZero ) {
00205     float           d, dVal;
00206     size_t          i, j, iAnswer;
00207     vector<size_t>  veciCounts;
00208 
00209     for( i = 0; i < m_Params.GetRows( ); ++i )
00210         for( j = 0; j < m_Params.GetColumns( ); ++j )
00211             m_Params.Set( i, j, 0 );
00212     veciCounts.resize( m_Params.GetRows( ) );
00213     for( i = 0; i < pData->GetGenes( ); ++i )
00214         for( j = ( i + 1 ); j < pData->GetGenes( ); ++j )
00215             if( pData->IsExample( i, j ) && ( ( iAnswer = pData->GetDiscrete( i, j, 0 ) ) != -1 ) ) {
00216                 if( CMeta::IsNaN( dVal = pData->GetContinuous( i, j, iNode ) ) ) {
00217                     if( iZero == -1 )
00218                         continue;
00219                     dVal = (float)iZero; }
00220                 if( iAnswer >= m_Params.GetRows( ) )
00221                     return false;
00222                 veciCounts[ iAnswer ]++;
00223                 m_Params.Get( iAnswer, c_iMu ) += dVal;
00224                 m_Params.Get( iAnswer, c_iSigma ) += dVal * dVal; }
00225     for( i = 0; i < m_Params.GetRows( ); ++i ) {
00226         if( !veciCounts[ i ] )
00227             veciCounts[ i ] = 1;
00228         d = ( m_Params.Get( i, c_iMu ) /= veciCounts[ i ] );
00229         d *= d;
00230         dVal = m_Params.Get( i, c_iSigma );
00231         dVal = ( dVal == d ) ? 1 : sqrt( ( dVal / ( veciCounts[ i ] - 1 ) ) - d );
00232         m_Params.Set( i, c_iSigma, dVal ); }
00233 
00234     return true; }
00235 
00236 bool CBayesNetFNNodeGaussian::Evaluate( float dValue, vector<float>& vecdOut ) const {
00237     float   dSum;
00238     size_t  i;
00239 
00240     vecdOut.resize( m_Params.GetRows( ) );
00241     dSum = 0;
00242     for( i = 0; i < vecdOut.size( ); ++i )
00243         dSum += ( vecdOut[ i ] = (float)CStatistics::NormalPDF( dValue, m_Params.Get( i, c_iMu ),
00244             m_Params.Get( i, c_iSigma ) ) );
00245     for( i = 0; i < vecdOut.size( ); ++i )
00246         vecdOut[ i ] /= dSum;
00247 
00248     return true; }
00249 
00250 // CBayesNetFNNodeBeta //////////////////////////////////////////////////////
00251 
00252 void CBayesNetFNNodeBeta::Randomize( ) {
00253     size_t  i;
00254 
00255     for( i = 0; i < m_Params.GetRows( ); ++i ) {
00256         m_Params.Set( i, c_iMin, -( (float)rand( ) / RAND_MAX ) );
00257         m_Params.Set( i, c_iMax, (float)rand( ) / RAND_MAX );
00258         m_Params.Set( i, c_iAlpha, (float)rand( ) / RAND_MAX );
00259         m_Params.Set( i, c_iBeta, (float)rand( ) / RAND_MAX ); } }
00260 
00261 bool CBayesNetFNNodeBeta::Learn( const IDataset* pData, size_t iNode, size_t iZero ) {
00262     float           d, dVal, dMean, dVariance;
00263     size_t          i, j, iAnswer;
00264     vector<size_t>  veciCounts;
00265 
00266     for( i = 0; i < m_Params.GetRows( ); ++i ) {
00267         m_Params.Set( i, c_iMin, FLT_MAX );
00268         m_Params.Set( i, c_iMax, -FLT_MAX );
00269         m_Params.Set( i, c_iAlpha, 0 );
00270         m_Params.Set( i, c_iBeta, 0 ); }
00271     veciCounts.resize( m_Params.GetRows( ) );
00272     for( i = 0; i < pData->GetGenes( ); ++i )
00273         for( j = ( i + 1 ); j < pData->GetGenes( ); ++j )
00274             if( pData->IsExample( i, j ) && ( ( iAnswer = pData->GetDiscrete( i, j, 0 ) ) != -1 ) ) {
00275                 if( CMeta::IsNaN( dVal = pData->GetContinuous( i, j, iNode ) ) ) {
00276                     if( iZero == -1 )
00277                         continue;
00278                     dVal = (float)iZero; }
00279                 if( iAnswer >= m_Params.GetRows( ) )
00280                     return false;
00281                 veciCounts[ iAnswer ]++;
00282                 m_Params.Get( iAnswer, c_iAlpha ) += dVal;
00283                 m_Params.Get( iAnswer, c_iBeta ) += dVal * dVal;
00284                 if( dVal < m_Params.Get( iAnswer, c_iMin ) )
00285                     m_Params.Set( iAnswer, c_iMin, dVal );
00286                 if( dVal > m_Params.Get( iAnswer, c_iMax ) )
00287                     m_Params.Set( iAnswer, c_iMax, dVal ); }
00288     for( i = 0; i < m_Params.GetRows( ); ++i ) {
00289         if( !veciCounts[ i ] )
00290             veciCounts[ i ] = 1;
00291         d = m_Params.Get( i, c_iMax ) - m_Params.Get( i, c_iMin );
00292         dMean = m_Params.Get( i, c_iAlpha ) / veciCounts[ i ];
00293         dVariance = ( m_Params.Get( i, c_iBeta ) / ( veciCounts[ i ] - 1 ) ) - ( dMean * dMean );
00294         dMean = ( dMean - m_Params.Get( i, c_iMin ) ) / d;
00295         dVariance /= d * d;
00296 
00297         m_Params.Set( i, c_iAlpha, dMean * ( ( dMean * ( 1 - dMean ) / dVariance ) - 1 ) );
00298         m_Params.Set( i, c_iBeta, ( 1 - dMean ) * ( ( dMean * ( 1 - dMean ) / dVariance ) - 1 ) ); }
00299 
00300     return true; }
00301 
00302 bool CBayesNetFNNodeBeta::Evaluate( float dValue, vector<float>& vecdOut ) const {
00303     float   d, dSum;
00304     size_t  i;
00305 
00306     vecdOut.resize( m_Params.GetRows( ) );
00307     dSum = 0;
00308     for( i = 0; i < vecdOut.size( ); ++i ) {
00309         if( ( d = dValue ) < m_Params.Get( i, c_iMin ) )
00310             d = m_Params.Get( i, c_iMin );
00311         else if( d > m_Params.Get( i, c_iMax ) )
00312             d = m_Params.Get( i, c_iMax );
00313         dSum += ( vecdOut[ i ] = (float)CStatistics::BetaPDF( d, m_Params.Get( i, c_iMin ),
00314             m_Params.Get( i, c_iMax ), m_Params.Get( i, c_iAlpha ), m_Params.Get( i, c_iBeta ) ) ); }
00315     for( i = 0; i < vecdOut.size( ); ++i )
00316         vecdOut[ i ] /= dSum;
00317 
00318     return true; }
00319 
00320 // CBayesNetFNNodeExponential ///////////////////////////////////////////////
00321 
00322 void CBayesNetFNNodeExponential::Randomize( ) {
00323     size_t  i;
00324 
00325     for( i = 0; i < m_Params.GetRows( ); ++i ) {
00326         m_Params.Set( i, c_iMin, (float)( rand( ) - ( RAND_MAX / 2 ) ) );
00327         m_Params.Set( i, c_iBeta, (float)rand( ) / RAND_MAX ); } }
00328 
00329 bool CBayesNetFNNodeExponential::Learn( const IDataset* pData, size_t iNode, size_t iZero ) {
00330     float           dVal;
00331     size_t          i, j, iAnswer;
00332     vector<size_t>  veciCounts;
00333 
00334     for( i = 0; i < m_Params.GetRows( ); ++i ) {
00335         m_Params.Set( i, c_iMin, FLT_MAX );
00336         m_Params.Set( i, c_iBeta, 0 ); }
00337     veciCounts.resize( m_Params.GetRows( ) );
00338     for( i = 0; i < pData->GetGenes( ); ++i )
00339         for( j = ( i + 1 ); j < pData->GetGenes( ); ++j )
00340             if( pData->IsExample( i, j ) && ( ( iAnswer = pData->GetDiscrete( i, j, 0 ) ) != -1 ) ) {
00341                 if( CMeta::IsNaN( dVal = pData->GetContinuous( i, j, iNode ) ) ) {
00342                     if( iZero == -1 )
00343                         continue;
00344                     dVal = (float)iZero; }
00345                 if( iAnswer >= m_Params.GetRows( ) )
00346                     return false;
00347                 veciCounts[ iAnswer ]++;
00348                 m_Params.Get( iAnswer, c_iBeta ) += dVal;
00349                 if( dVal < m_Params.Get( iAnswer, c_iMin ) )
00350                     m_Params.Set( iAnswer, c_iMin, dVal ); }
00351     for( i = 0; i < m_Params.GetRows( ); ++i ) {
00352         if( !veciCounts[ i ] )
00353             veciCounts[ i ] = 1;
00354         m_Params.Set( i, c_iBeta, ( m_Params.Get( i, c_iBeta ) / veciCounts[ i ] ) - m_Params.Get( i, c_iMin ) ); }
00355 
00356     return true; }
00357 
00358 bool CBayesNetFNNodeExponential::Evaluate( float dValue, vector<float>& vecdOut ) const {
00359     float   d, dSum;
00360     size_t  i;
00361 
00362     vecdOut.resize( m_Params.GetRows( ) );
00363     dSum = 0;
00364     for( i = 0; i < vecdOut.size( ); ++i ) {
00365         d = ( dValue < m_Params.Get( i, c_iMin ) ) ? c_iMin : dValue;
00366         dSum += ( vecdOut[ i ] = exp( ( m_Params.Get( i, c_iMin ) - d ) / m_Params.Get( i, c_iBeta ) ) /
00367             m_Params.Get( i, c_iBeta ) ); }
00368     for( i = 0; i < vecdOut.size( ); ++i )
00369         vecdOut[ i ] /= dSum;
00370 
00371     return true; }
00372 
00373 // CBayesNetFNNodeMOG ///////////////////////////////////////////////////////
00374 
00375 void CBayesNetFNNodeMOG::Randomize( ) {
00376     size_t  i, j;
00377 
00378     for( i = 0; i < m_Params.GetRows( ); ++i )
00379         for( j = 0; j < m_Params.GetColumns( ); j += 2 ) {
00380             m_Params.Set( i, j + c_iMu, (float)( rand( ) - ( RAND_MAX / 2 ) ) );
00381             m_Params.Set( i, j + c_iSigma, (float)rand( ) / RAND_MAX ); } }
00382 
00383 bool CBayesNetFNNodeMOG::Learn( const IDataset* pData, size_t iNode, size_t iZero ) {
00384 
00385     return false; }
00386 /*
00387     float           d, dVal;
00388     size_t          i, j, iAnswer;
00389     vector<size_t>  veciCounts;
00390 
00391     for( i = 0; i < m_Params.GetRows( ); ++i )
00392         for( j = 0; j < m_Params.GetColumns( ); ++j )
00393             m_Params.Set( i, j, 0 );
00394     veciCounts.resize( m_Params.GetRows( ) );
00395     for( i = 0; i < pData->GetGenes( ); ++i )
00396         for( j = ( i + 1 ); j < pData->GetGenes( ); ++j )
00397             if( pData->IsExample( i, j ) && ( ( iAnswer = pData->GetDiscrete( i, j, 0 ) ) != -1 ) ) {
00398                 if( CMeta::IsNaN( dVal = pData->GetContinuous( i, j, iNode ) ) ) {
00399                     if( iZero == -1 )
00400                         continue;
00401                     dVal = iZero; }
00402                 if( iAnswer >= m_Params.GetRows( ) )
00403                     return false;
00404                 veciCounts[ iAnswer ]++;
00405                 m_Params.Get( iAnswer, c_iMu ) += dVal;
00406                 m_Params.Get( iAnswer, c_iSigma ) += dVal * dVal; }
00407     for( i = 0; i < m_Params.GetRows( ); ++i ) {
00408         if( !veciCounts[ i ] )
00409             veciCounts[ i ] = 1;
00410         d = ( m_Params.Get( i, c_iMu ) /= veciCounts[ i ] );
00411         d *= d;
00412         dVal = m_Params.Get( i, c_iSigma );
00413         dVal = ( dVal == d ) ? 1 : sqrt( ( dVal / ( veciCounts[ i ] - 1 ) ) - d );
00414         m_Params.Set( i, c_iSigma, dVal ); }
00415 
00416     return true; }
00417 */
00418 
00419 bool CBayesNetFNNodeMOG::Evaluate( float dValue, vector<float>& vecdOut ) const {
00420     float   dCur, dSum;
00421     size_t  i, j;
00422 
00423     vecdOut.resize( m_Params.GetRows( ) );
00424     dSum = 0;
00425     for( i = 0; i < vecdOut.size( ); ++i ) {
00426         dCur = 0;
00427         for( j = 0; j < m_Params.GetColumns( ); j += 2 )
00428             dCur += (float)CStatistics::NormalPDF( dValue, m_Params.Get( i, j + c_iMu ),
00429                 m_Params.Get( i, j + c_iSigma ) );
00430         dSum += ( vecdOut[ i ] = dCur ); }
00431     for( i = 0; i < vecdOut.size( ); ++i )
00432         vecdOut[ i ] /= dSum;
00433 
00434     return true; }
00435 
00436 // CBayesNetFN //////////////////////////////////////////////////////////////
00437 
00438 CBayesNetFNImpl::CBayesNetFNImpl( ) : CBayesNetImpl( true ), m_iNodes(0), m_apNodes(NULL), m_fSmileNet(false) { }
00439 
00440 CBayesNetFNImpl::~CBayesNetFNImpl( ) {
00441 
00442     Reset( ); }
00443 
00444 void CBayesNetFNImpl::Reset( ) {
00445     size_t  i;
00446 
00447     m_fSmileNet = false;
00448     if( m_apNodes ) {
00449         for( i = 0; i < m_iNodes; ++i )
00450             if( m_apNodes[ i ] )
00451                 delete m_apNodes[ i ];
00452         delete[] m_apNodes; } }
00453 
00454 bool CBayesNetFN::Open( const char* szFile ) {
00455     size_t  i;
00456 
00457     Reset( );
00458     if( !( ( m_fSmileNet = !m_SmileNet.ReadFile( szFile ) ) && CBayesNetSmileImpl::IsNaive( m_SmileNet ) ) )
00459         return false;
00460 
00461     m_iNodes = m_SmileNet.GetNumberOfNodes( );
00462     m_apNodes = new CBayesNetFNNode*[ m_iNodes ];
00463     for( i = 0; i < m_iNodes; ++i )
00464         if( !( m_apNodes[ i ] = CBayesNetFNNode::Open( m_SmileNet.GetNode( (int)i ) ) ) )
00465             return false;
00466 
00467     return true; }
00468 
00469 bool CBayesNetFN::Save( const char* szFile ) const {
00470     size_t  i;
00471 
00472     if( !m_fSmileNet )
00473         return false;
00474 
00475     for( i = 0; i < m_iNodes; ++i )
00476         if( !m_apNodes[ i ]->Save( m_SmileNet.GetNode( (int)i ) ) )
00477             return false;
00478 
00479     return !((CBayesNetFN*)this)->m_SmileNet.WriteFile( szFile ); }
00480 
00481 bool CBayesNetFN::Learn( const IDataset* pData, size_t iIterations, bool fZero, bool fELR ) {
00482     size_t          i, j, iAnswer, iZero;
00483     vector<size_t>  veciCounts;
00484     int             iProp;
00485 
00486     if( !m_iNodes )
00487         return false;
00488 
00489     veciCounts.resize( m_apNodes[ 0 ]->GetParameters( ) );
00490     for( i = 0; i < pData->GetGenes( ); ++i )
00491         for( j = ( i + 1 ); j < pData->GetGenes( ); ++j )
00492             if( pData->IsExample( i, j ) && ( ( iAnswer = pData->GetDiscrete( i, j, 0 ) ) != -1 ) )
00493                 veciCounts[ iAnswer ]++;
00494 
00495     if( !m_apNodes[ 0 ]->Learn( veciCounts ) )
00496         return false;
00497     for( i = 1; i < m_iNodes; ++i ) {
00498         DSL_userProperties& Props   = m_SmileNet.GetNode( (int)i )->Info( ).UserProperties( );
00499 
00500         if( ( iProp = Props.FindProperty( c_szZero ) ) < 0 )
00501             iZero = fZero ? 0 : -1;
00502         else
00503             iZero = atoi( Props.GetPropertyValue( iProp ) );
00504         if( !m_apNodes[ i ]->Learn( pData, i, iZero ) )
00505             return false; }
00506 
00507     return true; }
00508 
00509 bool CBayesNetFNImpl::Evaluate( const IDataset* pData, CDat* pDatOut, vector<vector<float> >* pvecvecdOut,
00510     bool fZero ) const {
00511     size_t                      i, j, k;
00512     string                      strCur;
00513     vector<float>               vecdCur;
00514     map<string,float>           mapData;
00515     map<string,float>::iterator iterDatum;
00516     bool                        fContinuous;
00517 
00518     if( !m_iNodes )
00519         return false;
00520 
00521     for( i = 0; i < pData->GetGenes( ); ++i ) {
00522         if( !( i % 250 ) )
00523             g_CatSleipnir( ).notice( "CBayesNetFN::Evaluate( %d ) %d/%d", fZero, i, pData->GetGenes( ) );
00524         for( j = ( i + 1 ); j < pData->GetGenes( ); ++j ) {
00525             if( !pData->IsExample( i, j ) )
00526                 continue;
00527             fContinuous = false;
00528             for( k = 1; k < m_iNodes; ++k )
00529                 if( m_apNodes[ k ]->IsContinuous( ) && !CMeta::IsNaN( pData->GetContinuous( i, j, k ) ) ) {
00530                     fContinuous = true;
00531                     break; }
00532             if( !fContinuous ) {
00533                 strCur = EncodeDatum( pData, i, j );
00534                 if( ( iterDatum = mapData.find( strCur ) ) != mapData.end( ) ) {
00535                     if( pDatOut )
00536                         pDatOut->Set( i, j, iterDatum->second );
00537                     if( pvecvecdOut ) {
00538                         pvecvecdOut->resize( pvecvecdOut->size( ) + 1 );
00539                         (*pvecvecdOut)[ pvecvecdOut->size( ) - 1 ].push_back(
00540                             iterDatum->second ); }
00541                     continue; } }
00542 
00543             if( !Evaluate( pData, i, j, fZero, vecdCur ) )
00544                 return false;
00545             if( !fContinuous )
00546                 mapData[ strCur ] = vecdCur[ 0 ];
00547             if( pvecvecdOut ) {
00548                 pvecvecdOut->resize( pvecvecdOut->size( ) + 1 );
00549                 {
00550                     vector<float>&  vecdOut = (*pvecvecdOut)[ pvecvecdOut->size( ) - 1 ];
00551 
00552                     for( k = 0; ( k + 1 ) < vecdCur.size( ); ++k )
00553                         vecdOut.push_back( vecdCur[ k ] );
00554                 } }
00555             if( pDatOut )
00556                 pDatOut->Set( i, j, vecdCur[ 0 ] ); } }
00557 
00558     return true; }
00559 
00560 bool CBayesNetFNImpl::Evaluate( const IDataset* pData, size_t iOne, size_t iTwo, bool fZero,
00561     vector<float>& vecdOut ) const {
00562     vector<float>   vecdCur;
00563     float           dValue;
00564     size_t          i, j, iZero;
00565     int             iProp;
00566 
00567     if( !m_apNodes[ 0 ]->Evaluate( CMeta::GetNaN( ), vecdOut ) )
00568         return false;
00569     for( i = 0; i < vecdOut.size( ); ++i )
00570         vecdOut[ i ] = log( vecdOut[ i ] );
00571     for( i = 1; i < m_iNodes; ++i ) {
00572         DSL_userProperties& Props   = m_SmileNet.GetNode( (int)i )->Info( ).UserProperties( );
00573 
00574         if( ( iProp = Props.FindProperty( c_szZero ) ) < 0 )
00575             iZero = fZero ? 0 : -1;
00576         else
00577             iZero = atoi( Props.GetPropertyValue( iProp ) );
00578 
00579         dValue = 0;
00580         if( m_apNodes[ i ]->IsContinuous( ) ) {
00581             if( CMeta::IsNaN( dValue = pData->GetContinuous( iOne, iTwo, i ) ) ) {
00582                 if( iZero == -1 )
00583                     continue;
00584                 dValue = (float)iZero; } }
00585         else {
00586             if( ( j = pData->GetDiscrete( iOne, iTwo, i ) ) == -1 ) {
00587                 if( iZero == -1 )
00588                     continue;
00589                 j = iZero; }
00590             dValue = (float)j; }
00591         if( !m_apNodes[ i ]->Evaluate( dValue, vecdCur ) || ( vecdCur.size( ) != vecdOut.size( ) ) )
00592             return false;
00593         for( j = 0; j < vecdCur.size( ); ++j )
00594             vecdOut[ j ] += log( vecdCur[ j ] ); }
00595 
00596     dValue = 0;
00597     for( i = 0; i < vecdOut.size( ); ++i )
00598         dValue += ( vecdOut[ i ] = exp( vecdOut[ i ] ) );
00599     for( i = 0; i < vecdOut.size( ); ++i )
00600         vecdOut[ i ] /= dValue;
00601 
00602     return true; }
00603 
00604 bool CBayesNetFN::Evaluate( const vector<unsigned char>& vecbDatum, vector<float>& vecdOut, bool fZero,
00605     size_t iNode, bool fNoData ) const {
00606     vector<float>   vecdProd, vecdCur;
00607     float           dValue;
00608     size_t          i, j, iZero;
00609     int             iProp;
00610 
00611     if( !m_iNodes )
00612         return false;
00613 
00614     if( !m_apNodes[ iNode ]->Evaluate( CMeta::GetNaN( ), vecdProd ) )
00615         return false;
00616     for( i = 0; i < vecdProd.size( ); ++i )
00617         vecdProd[ i ] = log( vecdProd[ i ] );
00618     for( i = 1; i < m_iNodes; ++i ) {
00619         DSL_userProperties& Props   = m_SmileNet.GetNode( (int)i )->Info( ).UserProperties( );
00620 
00621         if( ( iProp = Props.FindProperty( c_szZero ) ) < 0 )
00622             iZero = fZero ? 0 : -1;
00623         else
00624             iZero = atoi( Props.GetPropertyValue( iProp ) );
00625 
00626         if( !( dValue = (float)vecbDatum[ i ] ) ) {
00627             if( fNoData || ( iZero == -1 ) )
00628                 continue;
00629             dValue = (float)iZero; }
00630         else
00631             dValue--;
00632         if( !m_apNodes[ i ]->Evaluate( dValue, vecdCur ) )
00633             return false;
00634         for( j = 0; j < vecdCur.size( ); ++j )
00635             vecdProd[ j ] += log( vecdCur[ j ] ); }
00636     for( i = 0; ( i + 1 ) < vecdProd.size( ); ++i )
00637         vecdOut.push_back( exp( vecdProd[ i ] ) );
00638 
00639     return true; }
00640 
00641 void CBayesNetFN::GetNodes( std::vector<std::string>& vecstrNodes ) const {
00642     size_t  i;
00643 
00644     for( i = 0; i < m_iNodes; ++i )
00645         vecstrNodes.push_back( m_apNodes[ i ]->GetName( ) ); }
00646 
00647 unsigned char CBayesNetFN::GetValues( size_t iNode ) const {
00648     const CBayesNetFNNode*  pNode;
00649 
00650     pNode = m_apNodes[ iNode ];
00651     return ( pNode->IsContinuous( ) ? -1 : pNode->GetParameters( ) ); }
00652 
00653 bool CBayesNetFN::IsContinuous( ) const {
00654     size_t  i;
00655 
00656     for( i = 0; i < m_iNodes; ++i )
00657         if( IsContinuous( i ) )
00658             return true;
00659 
00660     return false; }
00661 
00662 // CBayesNetMinimal //////////////////////////////////////////////////////////
00663 
00664 bool CBayesNetMinimalImpl::Counts2Probs( const std::vector<std::string>& vecstrCounts,
00665     std::vector<float>& vecdProbs, float dAlpha, float dPseudocounts, const CBayesNetMinimal* pBNDefault,
00666     size_t iNode, size_t iClass ) {
00667     size_t          i, iTotal;
00668     vector<size_t>  veciCounts;
00669     float           dScale, dTotal;
00670 
00671     veciCounts.resize( vecstrCounts.size( ) );
00672     for( iTotal = i = 0; i < veciCounts.size( ); ++i ) {
00673         veciCounts[ i ] = atol( vecstrCounts[ i ].c_str( ) );
00674         iTotal += veciCounts[ i ]; }
00675 
00676     vecdProbs.resize( veciCounts.size( ) );
00677     if( ( iTotal < c_iMinimum ) && pBNDefault ) {
00678         const CDataMatrix&  MatDefault  = pBNDefault->m_vecNodes[ iNode ].m_MatCPT;
00679 
00680         if( MatDefault.GetRows( ) != vecdProbs.size( ) ) {
00681             g_CatSleipnir( ).error( "CBayesNetMinimal::Counts2Probs( ) default distribution size mismatch: wanted %d, got %d",
00682                 vecdProbs.size( ), MatDefault.GetRows( ) );
00683             return false; }
00684         for( i = 0; i < vecdProbs.size( ); ++i )
00685             vecdProbs[ i ] = MatDefault.Get( i, iClass ); }
00686     else {
00687         dTotal = (float)iTotal;
00688         if( CMeta::IsNaN( dPseudocounts ) )
00689             dScale = 1;
00690         else if( iTotal ) {
00691             dScale = dPseudocounts / iTotal;
00692             dTotal = dPseudocounts; }
00693         else
00694             dScale = 0;
00695         for( i = 0; i < vecdProbs.size( ); ++i ){
00696           // skip zero                                                                                                                                                                                                       
00697                   if(dTotal == 0 && dAlpha == 0)
00698                     vecdProbs[ i ] = 1.0 / vecdProbs.size( );
00699                   else // laplace smooth and regularize 
00700                     vecdProbs[ i ] = ( ( dScale * (veciCounts[ i ] + 1) ) + dAlpha ) /
00701                       ( dTotal + ( dAlpha * vecdProbs.size( ) ) );
00702         }
00703     }
00704     return true; }
00705 
00719 bool CBayesNetMinimal::Open( const CBayesNetSmile& BNSmile ) {
00720     CDataMatrix     Mat;
00721     vector<string>  vecstrNodes;
00722     size_t          i;
00723 
00724     if( m_adNY ) {
00725         delete[] m_adNY;
00726         m_adNY = NULL; }
00727     BNSmile.GetNodes( vecstrNodes );
00728     if( !vecstrNodes.size( ) )
00729         return false;
00730     BNSmile.GetCPT( 0, m_MatRoot );
00731     m_vecNodes.resize( vecstrNodes.size( ) - 1 );
00732     for( i = 0; i < m_vecNodes.size( ); ++i ) {
00733         BNSmile.GetCPT( i + 1, m_vecNodes[ i ].m_MatCPT );
00734         if( m_vecNodes[ i ].m_MatCPT.GetColumns( ) != m_MatRoot.GetRows( ) )
00735             return false;
00736         m_vecNodes[ i ].m_bDefault = BNSmile.GetDefault( i + 1 ); }
00737     m_adNY = new long double[ m_MatRoot.GetRows( ) ];
00738 
00739     return true; }
00740 
00741 #endif // NO_SMILE
00742 
00756 bool CBayesNetMinimal::Open( std::istream& istm ) {
00757     uint32_t    iSize;
00758     size_t      i;
00759 
00760     if( m_adNY ) {
00761         delete[] m_adNY;
00762         m_adNY = NULL; }
00763     istm.read( (char*)&iSize, sizeof(iSize) );
00764     m_strID.resize( iSize );
00765     istm.read( &m_strID[ 0 ], iSize * sizeof(*m_strID.c_str( )) );
00766     if( !m_MatRoot.Open( istm, true ) )
00767         return false;
00768     m_adNY = new long double[ m_MatRoot.GetRows( ) ];
00769     istm.read( (char*)&iSize, sizeof(iSize) );
00770     m_vecNodes.resize( iSize );
00771     for( i = 0; i < m_vecNodes.size( ); ++i ) {
00772         CBayesNetMinimalNode&   BNNode  = m_vecNodes[ i ];
00773 
00774         istm.read( (char*)&BNNode.m_bDefault, sizeof(BNNode.m_bDefault) );
00775         if( !BNNode.m_MatCPT.Open( istm, true ) )
00776             return false; }
00777 
00778     return true; }
00779 
00790 void CBayesNetMinimal::Save( std::ostream& ostm ) const {
00791     uint32_t    iSize;
00792     size_t      i;
00793 
00794     iSize = (uint32_t)m_strID.length( );
00795     ostm.write( (const char*)&iSize, sizeof(iSize) );
00796     ostm.write( m_strID.c_str( ), iSize * sizeof(*m_strID.c_str( )) );
00797     m_MatRoot.Save( ostm, true );
00798     iSize = (uint32_t)m_vecNodes.size( );
00799     ostm.write( (const char*)&iSize, sizeof(iSize) );
00800     for( i = 0; i < m_vecNodes.size( ); ++i ) {
00801         const CBayesNetMinimalNode& BNNode  = m_vecNodes[ i ];
00802 
00803         ostm.write( (const char*)&BNNode.m_bDefault, sizeof(BNNode.m_bDefault) );
00804         BNNode.m_MatCPT.Save( ostm, true ); } }
00805 
00829 float CBayesNetMinimal::Evaluate( const vector<unsigned char>& vecbDatum, size_t iOffset ) const {
00830     long double     dNum, dDen;
00831     size_t          i, j;
00832     unsigned char   c;
00833 
00834     if( !m_adNY )
00835         return CMeta::GetNaN( );
00836 
00837     for( i = 0; i < m_MatRoot.GetRows( ); ++i )
00838         m_adNY[ i ] = m_MatRoot.Get( i, 0 );
00839     for( i = 0; i < m_vecNodes.size( ); ++i ) {
00840         c = vecbDatum[ ( i / 2 ) + iOffset ];
00841         if( i % 2 )
00842             c >>= 4;
00843         if( ( ( c &= 0xF ) == 0xF ) && ( ( c = m_vecNodes[ i ].m_bDefault ) == 0xFF ) )
00844             continue;
00845 
00846         const CDataMatrix&  MatCPT  = m_vecNodes[ i ].m_MatCPT;
00847         for( j = 0; j < MatCPT.GetColumns( ); ++j ) {
00848             if( c >= MatCPT.GetRows( ) ) {
00849                 g_CatSleipnir( ).error( "CBayesNetMinimal::Evaluate( %d ) illegal value: %d/%d in %d", iOffset, c, MatCPT.GetRows( ), i );
00850                 return CMeta::GetNaN( ); }
00851             m_adNY[ j ] *= MatCPT.Get( c, j ); } }
00852 
00853     dNum = dDen = m_adNY[ m_MatRoot.GetRows( ) - 1 ];
00854     for( i = 0; ( i + 1 ) < m_MatRoot.GetRows( ); ++i )
00855         dDen += m_adNY[ i ];
00856 
00857     return (float)( dNum / dDen ); }
00858 
00898 bool CBayesNetMinimal::Evaluate( const vector<unsigned char>& vecbData, float* adResults,
00899     size_t iGenes, size_t iStart ) const {
00900     size_t  iGene, iOffset, iChunk;
00901 
00902     if( !adResults )
00903         return false;
00904 
00905     iChunk = ( m_vecNodes.size( ) + 1 ) / 2;
00906     iOffset = iChunk * iStart;
00907     for( iGene = iStart; ( iGene < iGenes ) && ( iOffset < vecbData.size( ) ); ++iGene,iOffset += iChunk )
00908         adResults[ iGene ] = Evaluate( vecbData, iOffset );
00909 
00910     return true; }
00911 
00991 bool CBayesNetMinimal::OpenCounts( const char* szFileCounts, const std::map<std::string, size_t>& mapstriNodes,
00992     const std::vector<unsigned char>& vecbDefaults, const std::vector<float>& vecdAlphas, float dPseudocounts,
00993     const CBayesNetMinimal* pBNDefault ) {
00994     static const size_t c_iStateInitial = 0;
00995     static const size_t c_iStateRoot    = c_iStateInitial + 1;
00996     static const size_t c_iStatePreCPT  = c_iStateRoot + 1;
00997     static const size_t c_iStateCPT     = c_iStatePreCPT + 1;
00998     ifstream        ifsm;
00999     char            szBuffer[ c_iBufferSize ];
01000     size_t          i, iState, iClass, iNode;
01001     vector<string>  vecstrLine;
01002     vector<float>   vecdProbs;
01003     map<string, size_t>::const_iterator iterNode;
01004 
01005     if( m_adNY ) {
01006         delete[] m_adNY;
01007         m_adNY = NULL; }
01008 
01009     iNode = 0;
01010     iState = c_iStateInitial;
01011     ifsm.open( szFileCounts );
01012     if( !ifsm.is_open( ) ) {
01013         g_CatSleipnir( ).error( "CBayesNetMinimal::OpenCounts( %s ) could not open file", szFileCounts );
01014         return false; }
01015     while( !ifsm.eof( ) ) {
01016         ifsm.getline( szBuffer, CFile::c_iBufferSize - 1 );
01017         szBuffer[ CFile::c_iBufferSize - 1 ] = 0;
01018         if( !szBuffer[ 0 ] )
01019             continue;
01020         vecstrLine.clear( );
01021         CMeta::Tokenize( szBuffer, vecstrLine );
01022         switch( iState ) {
01023             case c_iStateInitial:
01024                 if( vecstrLine.size( ) != 2 ) {
01025                     g_CatSleipnir( ).error( "CBayesNetMinimal::OpenCounts( %s ) illegal line: %s", szFileCounts,
01026                         szBuffer );
01027                     return false; }
01028                 m_strID = vecstrLine[ 0 ];
01029                 m_vecNodes.resize( atol( vecstrLine[ 1 ].c_str( ) ) );
01030                 if( !vecbDefaults.empty( ) )
01031                     for( i = 0; i < m_vecNodes.size( ); ++i )
01032                         m_vecNodes[ i ].m_bDefault = vecbDefaults[ i ];
01033                 iState = c_iStateRoot;
01034                 break;
01035 
01036             case c_iStateRoot:
01037                 m_MatRoot.Initialize( vecstrLine.size( ), 1 );
01038                 if( !Counts2Probs( vecstrLine, vecdProbs ) )
01039                     return false;
01040                 for( i = 0; i < m_MatRoot.GetRows( ); ++i )
01041                     m_MatRoot.Set( i, 0, vecdProbs[ i ] );
01042                 iState = c_iStatePreCPT;
01043                 break;
01044 
01045             case c_iStatePreCPT:
01046                 if( ( iterNode = mapstriNodes.find( vecstrLine[ 0 ] ) ) == mapstriNodes.end( ) ) {
01047                     g_CatSleipnir( ).error( "CBayesNetMinimal::OpenCounts( %s ) could not identify node: %s",
01048                         szFileCounts, vecstrLine[ 0 ].c_str( ) );
01049                     return false; }
01050                 iNode = iterNode->second;
01051                 iClass = 0;
01052                 iState = c_iStateCPT;
01053                 break;
01054 
01055             case c_iStateCPT:
01056                 if( !Counts2Probs( vecstrLine, vecdProbs, vecdAlphas.empty( ) ? 0 : vecdAlphas[ iNode ],
01057                     dPseudocounts, pBNDefault, iNode, iClass ) )
01058                     return false;
01059                 {
01060                     CDataMatrix&    MatCPT  = m_vecNodes[ iNode ].m_MatCPT;
01061 
01062                     if( iClass ) {
01063                         if( MatCPT.GetRows( ) != vecdProbs.size( ) ) {
01064                             g_CatSleipnir( ).error( "CBayesNetMinimal::OpenCounts( %s ) illegal count number: given %d, expected %d",
01065                                 szFileCounts, vecdProbs.size( ), MatCPT.GetRows( ) );
01066                             return false; } }
01067                     else
01068                         MatCPT.Initialize( vecdProbs.size( ), m_MatRoot.GetRows( ) );
01069                     for( i = 0; i < vecdProbs.size( ); ++i )
01070                         MatCPT.Set( i, iClass, vecdProbs[ i ] );
01071                 }
01072                 if( ++iClass >= m_MatRoot.GetRows( ) )
01073                     iState = c_iStatePreCPT;
01074                 break; } }
01075     ifsm.close( );
01076 
01077     return true; }
01078 
01079 float CBayesNetMinimal::Regularize( vector<float>& vecdAlphas ) const {
01080     CDistanceMatrix Mat;
01081     size_t          iNodeOne, iNodeTwo, iAnswer, iValOne, iValTwo;
01082     float           dPOne, dPTwo, dPostOne, dPostOneTwo, dRet;
01083 
01084     Mat.Initialize( m_vecNodes.size( ) );
01085     Mat.Clear( );
01086     for( iNodeOne = 0; iNodeOne < m_vecNodes.size( ); ++iNodeOne ) {
01087         const CDataMatrix&  MatOne  = m_vecNodes[iNodeOne].m_MatCPT;
01088 
01089         for( iNodeTwo = 0; iNodeTwo < m_vecNodes.size( ); ++iNodeTwo ) {
01090             const CDataMatrix&  MatTwo  = m_vecNodes[iNodeTwo].m_MatCPT;
01091 
01092             if( iNodeOne == iNodeTwo )
01093                 continue;
01094             for( iValOne = 0; iValOne < MatOne.GetColumns( ); ++iValOne ) {
01095                 dPOne = 0;
01096                 for( iAnswer = 0; iAnswer < m_MatRoot.GetRows( ); ++iAnswer )
01097                     dPOne += m_MatRoot.Get( iAnswer, 0 ) * MatOne.Get( iAnswer, iValOne );
01098                 dPostOne = MatOne.Get( 1, iValOne ) * m_MatRoot.Get( 1, 0 ) / dPOne;
01099 
01100                 for( iValTwo = 0; iValTwo < MatTwo.GetColumns( ); ++iValTwo ) {
01101                     dPTwo = 0;
01102                     for( iAnswer = 0; iAnswer < m_MatRoot.GetRows( ); ++iAnswer )
01103                         dPTwo += m_MatRoot.Get( iAnswer, 0 ) * MatTwo.Get( iAnswer, iValTwo );
01104                     dPostOneTwo = dPostOne * MatTwo.Get( 1, iValTwo ) / dPTwo;
01105 
01106                     Mat.Get( iNodeOne, iNodeTwo ) += dPOne * dPTwo * fabs( log( dPostOneTwo / dPostOne ) ); } } } }
01107 
01108     dRet = 0;
01109     vecdAlphas.resize( m_vecNodes.size( ) );
01110     for( iNodeOne = 0; iNodeOne < m_vecNodes.size( ); ++iNodeOne ) {
01111         vecdAlphas[iNodeOne] = 0;
01112         for( iNodeTwo = 0; iNodeTwo < m_vecNodes.size( ); ++iNodeTwo )
01113             if( iNodeOne != iNodeTwo )
01114                 vecdAlphas[iNodeOne] += Mat.Get( iNodeOne, iNodeTwo );
01115         dRet += vecdAlphas[iNodeOne]; }
01116     dRet /= m_vecNodes.size( );
01117     for( iNodeOne = 0; iNodeOne < m_vecNodes.size( ); ++iNodeOne )
01118         vecdAlphas[iNodeOne] = dRet / vecdAlphas[iNodeOne];
01119     dRet = 1;
01120 
01121     return dRet; }
01122 
01123 }