Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
5.1 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1998
  6. //
  7. // File: utility.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. //
  11. // utility.cpp: utility computation
  12. //
  13. #include <basetsd.h>
  14. #include <math.h>
  15. #include "utility.h"
  16. #include "infer.h"
  17. MBNET_ENTROPIC_UTILITY :: MBNET_ENTROPIC_UTILITY ( GOBJMBN_INFER_ENGINE & inferEng )
  18. : MBNET_NODE_RANKER( inferEng.Model() ),
  19. _inferEng( inferEng ),
  20. _propMgr( inferEng.Model() ),
  21. _cHypo(0),
  22. _cInfo(0)
  23. {
  24. _iLblHypo = _propMgr.ILblToUser( ESTDLBL_hypo );
  25. _iLblInfo = _propMgr.ILblToUser( ESTDLBL_info );
  26. _iLblProblem = _propMgr.ILblToUser( ESTDLBL_problem );
  27. BuildWorkItems();
  28. }
  29. //
  30. // Collect all informational, problem defining and hypothesis nodes
  31. // into a structure with additional working data.
  32. //
  33. void MBNET_ENTROPIC_UTILITY :: BuildWorkItems ()
  34. {
  35. ZSREF zsrPropTypeLabel = _propMgr.ZsrPropType( ESTDP_label );
  36. MODEL::MODELENUM mdlenum( Model() );
  37. _dquwrk.clear();
  38. _cHypo = 0;
  39. _cInfo = 0;
  40. UTILWORK uwDummy;
  41. GELEMLNK * pgelm;
  42. // Collect all the nodes into a pointer array. Three node labels
  43. // are collected: info and probdef nodes (considered as info)
  44. // and hypo nodes (considered as hypo).
  45. while ( pgelm = mdlenum.PlnkelNext() )
  46. {
  47. if ( pgelm->EType() != GOBJMBN::EBNO_NODE )
  48. continue;
  49. // We only support discrete nodes for now.
  50. DynCastThrow( pgelm, uwDummy._pgndd );
  51. // See if this is an expansion (created) node
  52. if ( uwDummy._pgndd->BFlag( EIBF_Expansion ) )
  53. continue; // not a user-identifiable artifact; skip it
  54. // See if it has a label
  55. PROPMBN * propLbl = uwDummy._pgndd->LtProp().PFind( zsrPropTypeLabel );
  56. if ( ! propLbl )
  57. continue; // no label; skip it
  58. uwDummy._iLbl = propLbl->Real();
  59. if ( uwDummy._iLbl == _iLblHypo )
  60. _cHypo++;
  61. else
  62. if ( uwDummy._iLbl == _iLblInfo || uwDummy._iLbl == _iLblProblem )
  63. _cInfo++;
  64. else
  65. continue; // not a label of interest
  66. // Initialize the other member variables
  67. uwDummy._rUtil = 0.0;
  68. uwDummy._iClamp = -1;
  69. // Put the item on the work queue
  70. _dquwrk.push_back( uwDummy );
  71. }
  72. }
  73. REAL MBNET_ENTROPIC_UTILITY :: RComputeHypoGivenInfo (
  74. UTILWORK & uwHypo,
  75. UTILWORK & uwInfo )
  76. {
  77. assert( uwHypo._iLbl == _iLblHypo );
  78. assert( uwInfo._iLbl != _iLblHypo );
  79. // Clamped nodes are irrelevant
  80. if ( uwHypo._iClamp >= 0 || uwInfo._iClamp >= 0 )
  81. return 0.0;
  82. REAL rUtilOfInfoForHypo = 0.0;
  83. int cState = uwInfo._pgndd->CState();
  84. int cStateHypo = uwHypo._pgndd->CState();
  85. MDVCPD mdvhi;
  86. REAL rp_h0 = uwHypo._dd[0]; // Probability of hypo node being normal
  87. for ( int istInfo = 0; istInfo < cState; istInfo++ )
  88. {
  89. // Get belief of hypo node given info state
  90. _inferEng.EnterEvidence( uwInfo._pgndd, CLAMP( true, istInfo, true ) );
  91. _inferEng.GetBelief( uwHypo._pgndd, mdvhi );
  92. REAL rp_h0xj = mdvhi[0]; // p(h0|xj)
  93. REAL rLogSum = 0.0;
  94. for ( int istHypo = 1; istHypo < cStateHypo; istHypo++ )
  95. {
  96. REAL rp_hi = uwHypo._dd[istHypo];
  97. REAL rp_hixj = mdvhi[istHypo];
  98. rLogSum += fabs( log(rp_hixj) - log(rp_h0xj) - log(rp_hi) + log(rp_h0) );
  99. }
  100. rUtilOfInfoForHypo += rLogSum * uwInfo._dd[istInfo];
  101. }
  102. // Clear evidence against info node
  103. _inferEng.EnterEvidence( uwInfo._pgndd, CLAMP() );
  104. return rUtilOfInfoForHypo;
  105. }
  106. DEFINEVP(UTILWORK);
  107. void MBNET_ENTROPIC_UTILITY :: ComputeWorkItems()
  108. {
  109. CLAMP clamp;
  110. VPUTILWORK vpuw; // Remember pointers to hypo items
  111. // Get unconditional beliefs of all relevant (unclamped) nodes
  112. for ( DQUTILWORK::iterator itdq = _dquwrk.begin();
  113. itdq != _dquwrk.end();
  114. itdq++ )
  115. {
  116. UTILWORK & ut = *itdq;
  117. ut._rUtil = 0.0;
  118. ut._iClamp = -1;
  119. // Remember the indicies of the hypo nodes
  120. if ( ut._iLbl == _iLblHypo )
  121. vpuw.push_back( & (*itdq) );
  122. // Get the current evidence for the node
  123. _inferEng.GetEvidence( ut._pgndd, clamp );
  124. // If node is unclamped,
  125. if ( ! clamp.BActive() )
  126. {
  127. // get unconditional probs, else
  128. _inferEng.GetBelief( ut._pgndd, ut._dd );
  129. }
  130. else
  131. {
  132. // remember clamped state (serves as marker)
  133. ut._iClamp = clamp.Ist();
  134. }
  135. }
  136. for ( itdq = _dquwrk.begin();
  137. itdq != _dquwrk.end();
  138. itdq++ )
  139. {
  140. UTILWORK & utInfo = *itdq;
  141. if ( utInfo._iLbl == _iLblHypo )
  142. continue;
  143. utInfo._rUtil = 0.0;
  144. for ( int ih = 0; ih < vpuw.size(); ih++ )
  145. {
  146. utInfo._rUtil += RComputeHypoGivenInfo( *vpuw[ih], utInfo );
  147. }
  148. }
  149. }
  150. void MBNET_ENTROPIC_UTILITY :: operator () ()
  151. {
  152. // Clear any old results
  153. Clear();
  154. if ( _cHypo == 0 || _cInfo == 0 )
  155. return; // Nothing to do
  156. // Compute all utilities
  157. ComputeWorkItems();
  158. // Sort the work queue by utility
  159. sort( _dquwrk.begin(), _dquwrk.end() );
  160. // Pour the information into the output work areas
  161. _vzsrNodes.resize(_cInfo);
  162. _vlrValues.resize(_cInfo);
  163. int iInfo = 0;
  164. for ( DQUTILWORK::reverse_iterator ritdq = _dquwrk.rbegin();
  165. ritdq != _dquwrk.rend();
  166. ritdq++ )
  167. {
  168. UTILWORK & ut = *ritdq;
  169. if ( ut._iLbl == _iLblHypo )
  170. continue;
  171. _vzsrNodes[iInfo] = ut._pgndd->ZsrefName();
  172. _vlrValues[iInfo++] = ut._rUtil;
  173. }
  174. assert( iInfo == _cInfo );
  175. }