//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1997 - 1999 // // File: bnts.cpp // //-------------------------------------------------------------------------- // // BNTS.CPP: Belief Network Troubleshooting interface // #include #include "bnts.h" #include "gmobj.h" #include "recomend.h" #include "tchar.h" ///////////////////////////////////////////////////////////////////////////////////// // class MBNETDSCTS: slightly extended version of MBNETDSC to simplify T/S interface ///////////////////////////////////////////////////////////////////////////////////// class MBNETDSCTS : public MBNETDSC { friend class BNTS; public: MBNETDSCTS (); virtual ~ MBNETDSCTS (); void PrepareForTS (); const VPGNODEMBND & Vpgndd () { return _vpgndd; } PROPMGR & PropMgr () { return _propMgr; } GOBJMBN_CLIQSET & InferEng () { assert( _pCliqueSet ); return *_pCliqueSet; } MBNET_RECOMMENDER & MbRecom () { assert( _pmbRecom ); return *_pmbRecom; } int INode ( int inodeSparse ); int INode ( ZSREF zsr ); bool BValid () const { return _pCliqueSet != NULL && _pmbRecom != NULL; } bool BDirty () const { return _bDirty; } void SetDirty ( bool bSet = true ) { _bDirty = bSet; } protected: void BuildNodeMap (); protected: VPGNODEMBND _vpgndd; // Map to node ptrs based on dense inode VINT _vimap; // Map to dense inodes based on real (sparse) inodes PROPMGR _propMgr; // Property management GOBJMBN_CLIQSET * _pCliqueSet; // The clique tree inference engine MBNET_RECOMMENDER * _pmbRecom; // The recommender bool _bDirty; // Do recommendations need to be recalced? // Result fields for API ZSTR _zstr; VREAL _vreal; VINT _vint; }; MBNETDSCTS :: MBNETDSCTS () : _propMgr(self), _pmbRecom(NULL), _pCliqueSet(NULL), _bDirty(true) { } MBNETDSCTS :: ~ MBNETDSCTS () { delete _pmbRecom; if ( PInferEngine() ) DestroyInferEngine(); } // Convert from the model's node index to the user's index int MBNETDSCTS :: INode ( int inodeSparse ) { return _vimap[inodeSparse]; } // Convert from a string name to the user's node index int MBNETDSCTS :: INode ( ZSREF zsr ) { int inode = INameIndex( zsr ); if ( inode < 0 ) return -1; return INode(inode); } // Build the bi-directional maps void MBNETDSCTS :: BuildNodeMap () { // Allocate room to store pointers to all the named objects _vpgndd.resize( CNameMax() ); _vimap.resize( CNameMax() ); // Find the discrete nodes GNODEMBND * pgndd; int igndd = 0; for ( int i = 0; i < CNameMax(); i++ ) { _vimap[i] = -1; GOBJMBN * pgobj = PgobjFindByIndex( i ); if ( pgobj == NULL ) continue; pgndd = dynamic_cast( pgobj ); if ( pgndd == NULL ) continue; _vpgndd[igndd] = pgndd; _vimap[i] = igndd++; } _vpgndd.resize(igndd); } void MBNETDSCTS :: PrepareForTS () { BuildNodeMap(); CreateInferEngine(); DynCastThrow( PInferEngine(), _pCliqueSet); _pmbRecom = new MBNET_RECOMMENDER( *_pCliqueSet ); } // CTOR and DTOR BNTS :: BNTS () :_pmbnet(NULL), _inodeCurrent(-1) { } BNTS :: ~ BNTS () { Clear(); } void BNTS :: Clear () { delete _pmbnet; _pmbnet = NULL; _inodeCurrent = -1; } void BNTS :: ClearArrays () { if ( ! _pmbnet ) return; Mbnet()._vreal.resize(0); Mbnet()._vint.resize(0); } ZSTR & BNTS :: ZstrResult () { return Mbnet()._zstr; } void BNTS :: ClearString () { ZstrResult() == ""; } MBNETDSCTS & BNTS :: Mbnet() { assert( _pmbnet ); return *_pmbnet; } const MBNETDSCTS & BNTS :: Mbnet() const { assert( _pmbnet ); return *_pmbnet; } bool BNTS :: BValidNet () const { return _pmbnet != NULL && Mbnet().BValid(); } bool BNTS :: BValidNode () const { MBNETDSCTS & mbnts = const_cast(Mbnet()); return BValidNet() && _inodeCurrent >= 0 && _inodeCurrent < mbnts.Vpgndd().size(); } //////////////////////////////////////////////////////////////////// // Model-level queries and functions //////////////////////////////////////////////////////////////////// // Load and process a DSC-based model BOOL BNTS :: BReadModel ( SZC szcFn, SZC szcFnError ) { BOOL bResult = FALSE;; try { Clear(); _pmbnet = new MBNETDSCTS; assert( _pmbnet ); FILE * pfErr = szcFnError ? fopen( szcFnError, "w" ) : NULL; if ( ! Mbnet().BParse( szcFn, pfErr ) ) { Clear(); } else { Mbnet().PrepareForTS(); bResult = TRUE; } } catch ( GMException & ) { } return bResult; } // Return the number of (pre-expansion) nodes in the model int BNTS :: CNode () { if ( ! BValidNet() ) return -1; return Mbnet().Vpgndd().size(); } // Return our dense node index given a node name int BNTS :: INode ( SZC szcNodeSymName ) { GOBJMBN * pgobj = Mbnet().Mpsymtbl().find( szcNodeSymName ); if ( pgobj == NULL ) return -1; ZSREF zsrNodeSymName = Mbnet().Mpsymtbl().intern( szcNodeSymName ); return Mbnet().INode( zsrNodeSymName ); } // Return TRUE if the state of information is impossible BOOL BNTS :: BImpossible () { if ( ! BValidNet() ) return FALSE; return Mbnet().InferEng().BImpossible(); } // Return a property item string from the network BOOL BNTS :: BGetPropItemStr ( LTBNPROP & ltprop, SZC szcPropType, int index, ZSTR & zstr ) { ZSREF zsrPropName = Mbnet().Mpsymtbl().intern( szcPropType ); PROPMBN * pprop = ltprop.PFind( zsrPropName ); if ( pprop == NULL ) return FALSE; // Not present in network property list if ( (pprop->FPropType() & fPropString) == 0 ) return FALSE; // Not a string if ( index >= pprop->Count() ) return FALSE; // Out of range zstr = pprop->Zsr( index ); return true; } // Return a property item number from the network BOOL BNTS :: BGetPropItemReal ( LTBNPROP & ltprop, SZC szcPropType, int index, double & dbl ) { ZSREF zsrPropName = Mbnet().Mpsymtbl().intern( szcPropType ); PROPMBN * pprop = ltprop.PFind( zsrPropName ); if ( pprop == NULL ) return FALSE; // Not present in network property list if ( (pprop->FPropType() & fPropString) != 0 ) return FALSE; // Not a number if ( index >= pprop->Count() ) return FALSE; // Out of range dbl = pprop->Real(index); return true; } BOOL BNTS :: BNetPropItemStr ( SZC szcPropType, int index) { return BGetPropItemStr( Mbnet().LtProp(), szcPropType, index, ZstrResult() ); } BOOL BNTS :: BNetPropItemReal ( SZC szcPropType, int index, double & dbl ) { return BGetPropItemReal( Mbnet().LtProp(), szcPropType, index, dbl ); } //////////////////////////////////////////////////////////////////// // Operations involving the "Currrent Node": call NodeSetCurrent() //////////////////////////////////////////////////////////////////// // Set the current node for other calls BOOL BNTS :: BNodeSetCurrent( int inode ) { _inodeCurrent = inode; if ( ! BValidNode() ) { _inodeCurrent = -1; return FALSE; } return TRUE; } // Get the current node int BNTS :: INodeCurrent () { return _inodeCurrent; } // Return the label of the current node ESTDLBL BNTS :: ELblNode () { GNODEMBND * pgndd = Pgndd(); if ( pgndd == NULL ) return ESTDLBL_other; return Mbnet().MbRecom().ELbl( *pgndd ); } // Return the number of discrete states in the current node int BNTS :: INodeCst () { GNODEMBND * pgndd = Pgndd(); if ( pgndd == NULL ) return -1; return pgndd->CState(); } // Set the state of a node BOOL BNTS :: BNodeSet ( int istate, bool bSet ) { GNODEMBND * pgndd = Pgndd(); if ( pgndd == NULL ) return FALSE; Mbnet().SetDirty(); int cst = pgndd->CState(); if ( cst <= istate ) return FALSE; CLAMP clamp( true, istate, istate >= 0 ); Mbnet().MbRecom().EnterEvidence( pgndd, clamp, bSet ) ; return TRUE; } // Return the state of a node int BNTS :: INodeState () { GNODEMBND * pgndd = Pgndd(); if ( pgndd == NULL ) return FALSE; CLAMP clamp; Mbnet().InferEng().GetEvidence( pgndd, clamp ) ; return clamp.BActive() ? clamp.Ist() : -1; } // Return the name of a node's state void BNTS :: NodeStateName ( int istate ) { ClearString(); GNODEMBND * pgndd = Pgndd(); if ( pgndd == NULL ) return; if ( istate >= pgndd->CState() ) return; ZstrResult() = pgndd->VzsrStates()[istate]; } // Return the symbolic name of the node void BNTS :: NodeSymName () { ClearString(); GNODEMBND * pgndd = Pgndd(); if ( pgndd == NULL ) return; ZstrResult() = pgndd->ZsrefName(); } // Return the full name of the node void BNTS :: NodeFullName () { ClearString(); GNODEMBND * pgndd = Pgndd(); if ( pgndd == NULL ) return; ZstrResult() = pgndd->ZsFullName(); } GNODEMBND * BNTS :: Pgndd () { if ( ! BValidNode() ) return NULL; GNODEMBND * pgndd = Mbnet().Vpgndd()[_inodeCurrent]; assert( pgndd ); return pgndd; } // Return a property item string from the node BOOL BNTS :: BNodePropItemStr ( SZC szcPropType, int index ) { GNODEMBND * pgndd = Pgndd(); if ( pgndd == NULL ) return FALSE; return BGetPropItemStr( pgndd->LtProp(), szcPropType, index, ZstrResult() ); } // Return a property item number from the node BOOL BNTS :: BNodePropItemReal ( SZC szcPropType, int index, double & dbl ) { GNODEMBND * pgndd = Pgndd(); if ( pgndd == NULL ) return FALSE; return BGetPropItemReal( pgndd->LtProp(), szcPropType, index, dbl ); } // Return the belief for a node void BNTS :: NodeBelief () { ClearArrays(); GNODEMBND * pgndd = Pgndd(); if ( pgndd == NULL ) return; int cState = pgndd->CState(); MDVCPD mdvBel; Mbnet().InferEng().GetBelief( pgndd, mdvBel ); assert( cState == mdvBel.size() ); VREAL & vr = Mbnet()._vreal; vr.resize( cState ); for ( int i = 0; i < cState; i++ ) { vr[i] = mdvBel[i]; } } // Return the recommended nodes and, optionally, their values BOOL BNTS :: BGetRecommendations () { ClearArrays(); if ( ! BValidNet() ) return FALSE; if ( Mbnet().BDirty() ) { Mbnet().SetDirty( false ); // Compute the recommendations try { Mbnet().MbRecom()(); } catch ( GMException & ex ) { BOOL bResult = FALSE; switch ( ex.Ec() ) { case EC_VOI_PROBDEF_ABNORMAL: // This is an expected condition bResult = TRUE; break; default: break; } return bResult; } } const VZSREF & vzsrNodes = Mbnet().MbRecom().VzsrefNodes(); const VLREAL & vlrUtil = Mbnet().MbRecom().VlrValues(); VREAL & vr = Mbnet()._vreal; VINT & vi = Mbnet()._vint; vr.resize( vzsrNodes.size() ); vi.resize( vzsrNodes.size() ); for ( int i = 0; i < vzsrNodes.size(); i++ ) { int inode = Mbnet().INode( vzsrNodes[i] ); assert( inode >= 0 ) ; vi[i] = inode; vr[i] = vlrUtil[i]; } return TRUE; } SZC BNTS :: SzcResult () const { return Mbnet()._zstr.Szc(); } const REAL * BNTS :: RgReal () const { return & Mbnet()._vreal[0]; } const int * BNTS :: RgInt () const { return & Mbnet()._vint[0]; } int BNTS :: CReal () const { return Mbnet()._vreal.size(); } int BNTS :: CInt () const { return Mbnet()._vint.size(); } // End of BNTS.CPP