Leaked source code of windows server 2003
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.

415 lines
10 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1997
  6. //
  7. // File: testinfo.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. //
  11. // testinfo.cpp: test file generation
  12. //
  13. #include "testinfo.h"
  14. ////////////////////////////////////////////////////////////////////////////////////////////////
  15. ////////////////////////////////////////////////////////////////////////////////////////////////
  16. /*
  17. Test inference and optionally Write an inference output file.
  18. The format is the same as the program DXTEST, which uses the older DXC32.DLL.
  19. The format is:
  20. $COMPLETE << Indicates a complete pass without instantiations
  21. Alternator,0,0.99 << One record for each state of each node, alphabetically,
  22. Alternator,1,0.01 with either the full or symbolic name (fSymName)
  23. Battery,0,0.9927
  24. Battery,1,0.0073
  25. Charge Delivered,0,0.95934
  26. Charge Delivered,1,0.0406603
  27. ... << Similar records for all other nodes
  28. ...
  29. $INSTANTIATE,Alternator,0 << Indicates a node clamped to a state
  30. Alternator,0,1
  31. Alternator,1,0
  32. Battery,0,0.9927
  33. ...
  34. ...
  35. $PROBLEMINST,Engine Start,1 << Indicates a PD node instantiated
  36. $UTILITY,Node Name,3.14159 << Indicates an entropic utility record (fUtil)
  37. ...
  38. $RECOMEND,Node Name,-122.2222 << Indicates a troubleshooting recommendations record (fTSUtil)
  39. ...
  40. This routine is used to compare both timings and numerical results with the older
  41. software. The "fOutputFile" flag indicates whether an output file should be
  42. written. The "fPassCountMask" indicates how many times the loop should be performed;
  43. this value is defaulted to 1.
  44. The logic works as follows:
  45. for each pass
  46. for 1 + each problem-defining (PD) node
  47. for each non-PD node
  48. if no non-PD node is instantiated
  49. print $COMPLETE
  50. else
  51. print $INSTANTIATE and data about instantiated node
  52. for each state of each non-PD node
  53. print the name, state and value (belief)
  54. print utilities if required
  55. print recommendations if required
  56. end for each state of each non-PD node
  57. advance to the next state of the next node
  58. unclamp previous node/sate
  59. clamp (next) node to next state
  60. end for eacn non-PD node
  61. advance to the next state of the next PD node
  62. end for each problem-defining node
  63. end for each pass
  64. Note that each pass is set up so that all the uninstantiated values are printed first.
  65. */
  66. ////////////////////////////////////////////////////////////////////////////////////////////////
  67. ////////////////////////////////////////////////////////////////////////////////////////////////
  68. inline
  69. SZC TESTINFO :: SzcNdName ( GNODEMBN * pgnd )
  70. {
  71. return FCtl() & fSymName
  72. ? pgnd->ZsrefName().Szc()
  73. : pgnd->ZsFullName().Szc();
  74. }
  75. inline
  76. SZC TESTINFO :: SzcNdName ( ZSREF zsSymName )
  77. {
  78. if ( FCtl() & fSymName )
  79. return zsSymName.Szc();
  80. GNODEMBN * pgnd;
  81. DynCastThrow( Mbnet().PgobjFind( zsSymName ), pgnd );
  82. return SzcNdName( pgnd );
  83. }
  84. void TESTINFO :: GetUtilities ()
  85. {
  86. // Compute the utilities
  87. MbUtil()();
  88. if ( ! Postream() )
  89. return;
  90. const VZSREF & vzsrNodes = MbUtil().VzsrefNodes();
  91. const VLREAL & vlrUtil = MbUtil().VlrValues();
  92. for ( int ind = 0; ind < vzsrNodes.size(); ind++ )
  93. {
  94. SZC szcName = SzcNdName( vzsrNodes[ind] );
  95. Ostream()
  96. << "$UTILITY,"
  97. << szcName
  98. << ","
  99. << vlrUtil[ind]
  100. << "\n";
  101. _clOut++;
  102. }
  103. }
  104. void TESTINFO :: GetTSUtilities ()
  105. {
  106. if ( ! MbRecom().BReady() )
  107. return; // Invalid state for recommendations
  108. // Compute the utilities
  109. MbRecom()();
  110. if ( ! Postream() )
  111. return;
  112. const VZSREF & vzsrNodes = MbRecom().VzsrefNodes();
  113. const VLREAL & vlrUtil = MbRecom().VlrValues();
  114. for ( int ind = 0; ind < vzsrNodes.size(); ind++ )
  115. {
  116. SZC szcName = SzcNdName( vzsrNodes[ind] );
  117. Ostream()
  118. << "$RECOMMEND,"
  119. << szcName
  120. << ","
  121. << vlrUtil[ind]
  122. << "\n";
  123. _clOut++;
  124. }
  125. }
  126. // Get the beliefs for the nodes in the given map; write data records if stream given
  127. void TESTINFO :: GetBeliefs ()
  128. {
  129. MDVCPD mdvBel;
  130. // Prepare to check for impossible states of information
  131. GOBJMBN_CLIQSET * pCliqueSet = NULL;
  132. if ( BFlag( fImpossible ) )
  133. pCliqueSet = dynamic_cast<GOBJMBN_CLIQSET *>(&InferEng());
  134. // See if this state of information is impossible
  135. bool bIsImposs = pCliqueSet != NULL
  136. && pCliqueSet->BImpossible();
  137. for ( MPSTRPND::iterator mpit = Mpstrpnd().begin();
  138. mpit != Mpstrpnd().end();
  139. mpit++ )
  140. {
  141. GNODEMBND * pgndd = (*mpit).second;
  142. int cState = pgndd->CState();
  143. if ( ! bIsImposs )
  144. {
  145. InferEng().GetBelief( pgndd, mdvBel );
  146. assert( cState == mdvBel.size() );
  147. }
  148. if ( Postream() )
  149. {
  150. SZC szcName = SzcNdName( pgndd );
  151. for ( int ist = 0; ist < cState; ist++ )
  152. {
  153. Ostream() << szcName << "," << ist << ",";
  154. if ( bIsImposs )
  155. Ostream() << _rImposs;
  156. else
  157. Ostream() << mdvBel[ist];
  158. Ostream() << "\n";
  159. _clOut++;
  160. }
  161. }
  162. }
  163. if ( BFlag( fUtil ) )
  164. {
  165. GetUtilities();
  166. }
  167. else
  168. if ( BFlag( fTSUtil ) )
  169. {
  170. GetTSUtilities();
  171. }
  172. #ifdef _DEBUG
  173. if ( Postream() )
  174. Ostream().flush();
  175. #endif
  176. }
  177. void TESTINFO :: InferTest ()
  178. {
  179. bool bOutput = Postream() != NULL;
  180. int cPass = FCtl() & fPassCountMask;
  181. // Is network expanded?
  182. bool bExpanded = Mbnet().BFlag( EIBF_Expanded );
  183. PROPMGR propmgr( Mbnet() ); // Property manager
  184. int iLblProblem = propmgr.ILblToUser( ESTDLBL_problem );
  185. ZSREF zsrPropTypeLabel = propmgr.ZsrPropType( ESTDP_label );
  186. MPSTRPND & mpstrpnd = Mpstrpnd(); // Map of strings to node ptrs
  187. MPSTRPND mpstrpndProblem; // Map of PD nodes
  188. for ( int inode = 0; inode < Mbnet().CNameMax(); inode++ )
  189. {
  190. GOBJMBN * pgobj = Mbnet().PgobjFindByIndex( inode );
  191. if ( ! pgobj )
  192. continue;
  193. GNODEMBND * pgndd = dynamic_cast<GNODEMBND *>(pgobj);
  194. if ( ! pgndd )
  195. continue;
  196. SZC szcName = FCtl() & fSymName
  197. ? pgndd->ZsrefName().Szc()
  198. : pgndd->ZsFullName().Szc();
  199. // See if this is a problem-defining node
  200. PROPMBN * propLbl = pgndd->LtProp().PFind( zsrPropTypeLabel );
  201. if ( propLbl && propLbl->Real() == iLblProblem )
  202. {
  203. // Put PD nodes into separate map
  204. mpstrpndProblem[szcName] = pgndd;
  205. }
  206. // If the network is expanded, use only regular nodes
  207. if ( (! bExpanded) || ! pgndd->BFlag( EIBF_Expansion ) )
  208. {
  209. mpstrpnd[szcName] = pgndd;
  210. }
  211. }
  212. for ( int iPass = 0; iPass < cPass; iPass++ )
  213. {
  214. int iProb = -1;
  215. int iProbState = 0;
  216. int cProbState = 0;
  217. GNODEMBND * pgnddProblem = NULL;
  218. MPSTRPND::iterator mpitPd = mpstrpndProblem.begin();
  219. MPSTRPND::iterator mpitPdEnd = mpstrpndProblem.end();
  220. for (;;)
  221. {
  222. // After 1st cycle, advance the problem state of the PD node
  223. if ( pgnddProblem )
  224. {
  225. ZSTR zsNamePD;
  226. CLAMP clampProblemState(true, iProbState, true);
  227. InferEng().EnterEvidence( pgnddProblem, clampProblemState );
  228. if ( FCtl() & fSymName )
  229. zsNamePD = pgnddProblem->ZsrefName();
  230. else
  231. zsNamePD = pgnddProblem->ZsFullName();
  232. if ( bOutput )
  233. {
  234. Ostream() << "$PROBLEMINST,"
  235. << zsNamePD.Szc()
  236. << ","
  237. << iProbState
  238. << "\n";
  239. _clOut++;
  240. }
  241. }
  242. MPSTRPND::iterator mpit = mpstrpnd.begin();
  243. MPSTRPND::iterator mpend = mpstrpnd.end();
  244. int cpnd = mpstrpnd.size();
  245. for ( int inid = -1; inid < cpnd; inid++ )
  246. {
  247. GNODEMBND * pgndd = NULL;
  248. ZSTR zsName;
  249. int cst = 0; // Cause inner loop to run once on first cycle
  250. if ( inid >= 0 )
  251. {
  252. pgndd = (*mpit++).second;
  253. if ( FCtl() & fSymName )
  254. zsName = pgndd->ZsrefName();
  255. else
  256. zsName = pgndd->ZsFullName();
  257. cst = pgndd->CState();
  258. }
  259. for ( int ist = -1; ist < cst; ist++ )
  260. {
  261. if ( ist < 0 )
  262. {
  263. // The first time through, print all the beliefs
  264. // with no instantiations; do nothing on later cycles.
  265. if ( pgndd != NULL )
  266. continue;
  267. if ( bOutput )
  268. {
  269. Ostream() << "$COMPLETE\n";
  270. _clOut++;
  271. }
  272. }
  273. else
  274. {
  275. CLAMP clampState(true, ist, true);
  276. InferEng().EnterEvidence( pgndd, clampState );
  277. if ( bOutput )
  278. {
  279. Ostream() << "$INSTANTIATE,"
  280. << zsName.Szc()
  281. << ","
  282. << ist
  283. << "\n";
  284. _clOut++;
  285. }
  286. }
  287. GetBeliefs();
  288. }
  289. if ( pgndd )
  290. {
  291. // Clear the instantitation of this node.
  292. InferEng().EnterEvidence( pgndd, CLAMP() );
  293. }
  294. }
  295. // If this is the last abnormal state for this problem node,
  296. // advance to the next node.
  297. if ( ++iProbState >= cProbState )
  298. {
  299. // Unclamp the last problem node, if any
  300. if ( pgnddProblem )
  301. InferEng().EnterEvidence( pgnddProblem, CLAMP() );
  302. // Move on to the next PD node
  303. if ( mpitPd == mpitPdEnd )
  304. break;
  305. pgnddProblem = (*mpitPd++).second;
  306. cProbState = pgnddProblem->CState();
  307. // Reset to 1st problem state
  308. iProbState = 1;
  309. }
  310. }
  311. }
  312. }
  313. // Return a displayable string of the current options settings
  314. ZSTR TESTINFO :: ZsOptions ( ULONG fFlag )
  315. {
  316. static
  317. struct
  318. {
  319. ULONG _f; // Bit flag
  320. SZC _szc; // Option name
  321. }
  322. vOptMap [] =
  323. {
  324. { fVerbose, "verbose" },
  325. { fCliquing, "clique" },
  326. { fInference, "infer" },
  327. { fMulti, "multipass" },
  328. { fOutputFile, "outfile" },
  329. { fShowTime, "times" },
  330. { fSaveDsc, "dscout" },
  331. { fPause, "pause" },
  332. { fSymName, "symname" },
  333. { fExpand, "expand" },
  334. { fClone, "clone" },
  335. { fUtil, "utilities" },
  336. { fReg, "registry" },
  337. { fTSUtil, "recommend" },
  338. { fInferStats, "inferstats"},
  339. { fImpossible, "impossible"},
  340. { 0, "" }
  341. };
  342. ZSTR zs;
  343. ULONG cpass = fFlag & fPassCountMask;
  344. fFlag &= ~ fPassCountMask;
  345. for ( int i = 0; vOptMap[i]._f != 0; i++ )
  346. {
  347. if ( fFlag & vOptMap[i]._f )
  348. {
  349. if ( zs.length() > 0 )
  350. zs += ',';
  351. zs += vOptMap[i]._szc;
  352. }
  353. }
  354. if ( fFlag & fMulti )
  355. {
  356. if ( zs.length() > 0 )
  357. zs += ",";
  358. zs.FormatAppend("passes=%d", cpass);
  359. }
  360. return zs;
  361. }