//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1997 - 1997 // // File: recomend.h // //-------------------------------------------------------------------------- // // recomend.h: Recommendations computations // #ifndef _RECOMEND_H_ #define _RECOMEND_H_ #include "cliqset.h" const IST istNormal = 0; // MSRDEVBUG! class MBNET_RECOMMENDER; class GPNDDDIST { public: GPNDDDIST ( GNODEMBND * pgndd = NULL ) :_pgndd(pgndd) { } GNODEMBND & Gnd() { assert( _pgndd != NULL ); return *_pgndd; } GNODEMBND * & Pgnd() { return _pgndd; } MDVCPD & Dist () { return _dd; } DECLARE_ORDERING_OPERATORS(GPNDDDIST); protected: GNODEMBND * _pgndd; MDVCPD _dd; }; inline bool GPNDDDIST :: operator < ( const GPNDDDIST & gpndist ) const { return _pgndd < gpndist._pgndd; } // Define VGPNDDDIST, an array of GPNDDDISTs DEFINEV(GPNDDDIST); // Define a pair of node pointer and state index typedef pair PNDD_IST; // Define VPNDD_IST DEFINEV(PNDD_IST); // // Helper class containing processed node information extracted from // the belief network. // class GNODEREFP { public: GNODEREFP ( PROPMGR & propMgr, GNODEMBND * pgndd ); const COST CostObserve () const { return _costObserve; } const COST CostFix () const { return _costFix; } COST & Util () { return _costUtil; } ESTDLBL ELbl () const { return _eLbl; } GNODEMBND & Gndd () { return *_pgndd; } GNODEMBND * Pgndd () { return _pgndd; } bool BLeak () const { return _bLeak; } bool operator == ( const GNODEREFP & gndref ) const { return _pgndd == gndref._pgndd ; } bool operator < ( const GNODEREFP & gndref ) const { return _pgndd < gndref._pgndd; } bool operator != ( const GNODEREFP & gndref ) const { return !(self == gndref); } bool operator == ( const GNODEMBND * pgndd ) const { return _pgndd == pgndd ; } bool operator < ( const GNODEMBND * pgndd ) const { return _pgndd < pgndd; } bool operator != ( const GNODEMBND * pgndd ) const { return !(self == pgndd); } protected: GNODEMBND * _pgndd; // Node pointer ESTDLBL _eLbl; // Standard label COST _costObserve; // Cost to observe COST _costFix; // Cost to fix COST _costUtil; // Computed utility bool _bLeak; // Leak node from CI expansion? }; class VPGNODEREFP : public vector { public: ~ VPGNODEREFP () { clear(); } int ifind ( const GNODEMBND * pgndd ) { for ( int indref = 0; indref < size(); indref++ ) { if ( self[indref]->Pgndd() == pgndd ) return indref; } return -1; } void clear () { for ( int i = 0; i < size(); i++ ) delete self[i]; vector::clear(); } }; // // Recommendations work node structure. (Formerly 'PROBNODE') // class GNODERECWORK { friend class VGNODERECWORK; public: GNODERECWORK () : _pgndref(NULL), _pbFault(0), _pbOverCost(0) {} GNODEREFP * operator -> () { return _pgndref; } GNODEREFP * operator -> () const { return _pgndref; } COST CostObsIfFixable () const { return BFixable() ? _pgndref->CostObserve() : 0.0; } GNODEREFP * Pgndref () const { return _pgndref; } GNODEREFP & Gndref () const { assert( _pgndref ); return *_pgndref; } void SetCost ( COST cost ) { assert( _pgndref ); _pgndref->Util() = - cost; } bool BFixable () const { ESTDLBL elbl = Pgndref()->ELbl(); return elbl == ESTDLBL_fixunobs || elbl == ESTDLBL_fixobs; } PROB PbOverCost () const { return _pbOverCost; } PROB PbFault () const { return _pbFault; } void SetPbFault ( PROB prob ) { _pbFault = prob ; } DECLARE_ORDERING_OPERATORS(GNODERECWORK); protected: GNODEREFP * _pgndref; PROB _pbFault; PROB _pbOverCost; protected: void Init ( MBNET_RECOMMENDER & mbnRecom, GNODEREFP * pgndref ); void Init ( GNODEREFP * pgndref, PROB pbFault ); }; // // Controlled array of recommendations node work structures (Formerly RGPROBNODE). // class VGNODERECWORK : public vector { public: VGNODERECWORK ( MBNET_RECOMMENDER * pmbnRec = NULL ) : _pmbnRec( pmbnRec ), _bSeqSet( false ), _iFixedK(-1) {} void InitElem ( GNODEMBND * pgndd, int index = -1 ); void InitElem ( GNODEREFP * pgndref, int index = -1 ); enum ESORT { ESRT_ProbOverCost, ESRT_SgnProb, ESRT_NegCost, ESRT_SgnUtil }; void Sort ( ESORT esort ); void Rescale (); COST Cost ( int ielemFirst = 0, int * piMinK = NULL ); bool BSameSequence ( const VGNODERECWORK & vgnw ); void SetSequenceCost (); COST CostECRDefault () const { assert( _bSeqSet ); return size() ? self[0]->Util() : CostService(); } MBNET_RECOMMENDER & MbnRec () { assert( _pmbnRec ); return *_pmbnRec; } const MBNET_RECOMMENDER & MbnRec () const { assert( _pmbnRec ); return *_pmbnRec; } MBNET_RECOMMENDER * & PmbnRec () { return _pmbnRec; } COST CostService () const; protected: MBNET_RECOMMENDER * _pmbnRec; // The controlling recommendations object bool _bSeqSet; // Has the sequence been set yet? int _iFixedK; // Fixed state point }; DEFINEV(VGNODERECWORK); /////////////////////////////////////////////////////////////////////////////////////// // // MBNET_RECOMMENDER: // // The troubleshooting recommendations object. It's a "node ranker", // so its results are a list of node pointers and real values stored in members // of the base class, MBNET_NODE_RANKER. // // Since all evidence is relative to a particular inference engine, that engine // must be used during construction. // // To invoke, use operator(). To determine if network state is compatible with // troubleshooting recommendations, call BReady(). If successful, the information // collected is saved for the next recommendations call. To force recollection // of troubleshooting information, call Unready(). // /////////////////////////////////////////////////////////////////////////////////////// class MBNET_RECOMMENDER : public MBNET_NODE_RANKER { public: // Recommendations computation method enum ERCMETHOD { ERCM_None, ERCM_FixPlan, ERCM_Cheap, ERCM_MostLikely, ERCM_Random, ERCM_FixPlanOnly, ERCM_Max }; // Construct using the appropriate inference engine MBNET_RECOMMENDER ( GOBJMBN_CLIQSET & inferEng, ERCMETHOD ercm = ERCM_FixPlan ); virtual ~ MBNET_RECOMMENDER (); INT EType () const { return EBNO_RANKER_RECOMMENDATIONS; } // The ranking function virtual void operator () (); // Return true if the network is in a state compatible with // troubleshooting recommendations or sets ErcError(). Can // be called separately or will be called by ranking operator(). bool BReady (); // Clear the "ready" condition of the object void Unready () { _bReady = false; } // Check to see if the object is in the "ready" condition bool BIsReady() const { return _bReady; } // Enter evidence for a troubleshooting model void EnterEvidence ( GNODEMBND * pgndd, // Node to set/observe const CLAMP & clamp, // Value to set/unset bool bSet = true ); // Set or observe? // Return the cost-of-service from the model; it's stored as // the model's 'cost-to-fix'. COST CostServiceModel (); // General accessors ECGM EcError () const { return _err; } ERCMETHOD ErcMethod () const { return _ercm; } COST CostService () const { return _costService; } COST CostObsProbDef () const { return _costObsProbDef; } PROPMGR & PropMgr() { return _propMgr; } GNODEMBND * PgnddProbDefAbnormal () const { return _pgnddPDAbnormal; } VPGNODEMBND & VpgnddFix () { return _vpgnddFix; } VPGNODEREFP & Vpgndref () { return _vpgndref; } ESTDLBL ELbl ( GNODEMBN & gnd ); // Result array of relevant fixables; if 'bUsePriorList' // is true, member array is starting point. 'pgnddInfo' // is optional pointer to info node used in INFOPLAN. void DetermineRelevantFixableNodes ( VGPNDDDIST & vgndddFixRelevant, bool bUsePriorList, GNODEMBND * pgnddInfoPlan = NULL ); void ComputeFixSequence ( VGPNDDDIST & vgndddFixRelevant, // IN: Relevant fixable nodes VGNODERECWORK & vgnrwFix ); // OUT: Ordered fix/repair sequence // Interface to inference engine void InferGetBelief ( GNODEMBND * pgndd, MDVCPD & mdvBel ); void InferGetEvidence ( GNODEMBND * pgndd, CLAMP & clamp ); void InferEnterEvidence ( GNODEMBND * pgndd, const CLAMP & clamp ); bool BInferImpossible (); protected: GOBJMBN_CLIQSET & _inferEng; // Inference engine PROPMGR _propMgr; // Property handler ECGM _err; // Last error code ERCMETHOD _ercm; // Planning method GNODEMBND * _pgnddPDAbnormal; // Abnormal PD node COST _costService; // Service cost; cost-to-fix of network COST _costObsProbDef; // Cost to observe PD node VPGNODEMBND _vpgnddFix; // Fixable nodes VPGNODEREFP _vpgndref; // Array of references to all nodes bool _bReady; // BReady() has been successfully called VGPNDDDIST _vgndddFixRelevant; // Relevant fixable nodes with unconditional distributions protected: GOBJMBN_CLIQSET & InferEng () { return _inferEng; } // Formerly "ComputeCosts" void DetermineRelevantInfoNodes ( VGNODERECWORK & vgnrwFix, // IN: relevant fixables VGNODERECWORK & vgnrwInfo ); // OUT: relevant infos // Add to the given array all nodes which are downstream void ExpandDownstream ( VPGNODEMBND & vpgndd ); // Return true if the current state of evidence gives a different probability // distribution that the one stored bool BProbsChange ( GPNDDDIST & gpndddist ); void PrintInstantiations (); HIDE_UNSAFE(MBNET_RECOMMENDER); }; #endif // _RECOMEND_H_