Sleipnir
|
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 }