windows-nt/Source/XPSP1/NT/enduser/troubleshoot/bn/bnts/bnts.cpp
2020-09-26 16:20:57 +08:00

553 lines
11 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: bnts.cpp
//
//--------------------------------------------------------------------------
//
// BNTS.CPP: Belief Network Troubleshooting interface
//
#include <windows.h>
#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<GNODEMBND *>( 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<MBNETDSCTS &>(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