void CGibbsSamplingInfEngine::SetQueries(intVecVector &queryes) { int nQueryes = queryes.size(); PNL_CHECK_LEFT_BORDER( nQueryes, 1 ); int i; for( i = 0; i < m_queryFactors.size(); i++ ) { delete m_queryFactors[i]; } intVector tmp; for( i = 0; i < nQueryes; i++ ) { PNL_CHECK_RANGES( queryes[i].size(), 1, m_pGraphicalModel->GetNumberOfNodes() ); tmp = queryes[i]; std::sort( tmp.begin(), tmp.end() ); intVector::iterator it = std::unique( tmp.begin(), tmp.end() ); tmp.erase( it, tmp.end() ); if( tmp.size() != queryes[i].size() ) { PNL_THROW(CAlgorithmicException, "equal nodes in qurey"); } tmp.clear(); } m_queryes = queryes; }
CMlStaticStructLearn::CMlStaticStructLearn(CStaticGraphicalModel *pGrModel, ELearningTypes LearnType, EOptimizeTypes AlgorithmType, EScoreFunTypes ScoreType, int nMaxFanIn, intVector& vAncestor, intVector& vDescent) :CStaticLearningEngine(pGrModel, LearnType), m_pResultBNet(NULL), m_pResultDAG(NULL) { int nnodes = pGrModel->GetNumberOfNodes(); m_nNodes = nnodes; int i; for (i = 0; i<nnodes; i++) m_vResultRenaming.push_back(i); m_ScoreType = ScoreType; m_Algorithm = AlgorithmType; m_nMaxFanIn = nMaxFanIn; m_ScoreMethod = MaxLh; m_priorType = Dirichlet; m_K2alfa = 0; m_vAncestor.assign(vAncestor.begin(), vAncestor.end()); m_vDescent.assign(vDescent.begin(),vDescent.end()); PNL_CHECK_RANGES(nMaxFanIn, 1, nnodes); intVector ranges(nMaxFanIn); for(i=0; i<nMaxFanIn; i++) ranges[i] = nnodes+1; float max = 0.0f; m_pNodeScoreCache = (CSparseMatrix<float>**)malloc(nnodes * sizeof(CSparseMatrix<float>*)); for(i=0; i<nnodes; i++) { m_pNodeScoreCache[i] = CSparseMatrix<float>::Create(nMaxFanIn, &ranges.front(), max, 0); } }
void CFactor::CreateAllNecessaryMatrices( int typeOfMatrices ) { PNL_CHECK_RANGES( typeOfMatrices, 1, 1 ); //we have only one type of matrices now if( m_CorrespDistribFun->IsDistributionSpecific() == 1 ) { PNL_THROW( CInconsistentType, "uniform distribution can't have any matrices with data" ); } m_CorrespDistribFun->CreateDefaultMatrices(typeOfMatrices); }
CGraph* CreateRandomGraphWithToyQMRSpecific(int num_nodes, int num_indep_nodes, int max_size_family) { PNL_CHECK_LEFT_BORDER( num_nodes, 10 ); PNL_CHECK_RANGES( num_indep_nodes, 1, num_nodes-1 ); PNL_CHECK_RANGES( max_size_family, 2, num_nodes ); int i, j, k; CGraph *pGraph = CGraph::Create(0, NULL, NULL, NULL); PNL_CHECK_IF_MEMORY_ALLOCATED( pGraph ); srand((unsigned int)time(NULL)); pGraph->AddNodes(num_nodes); int num_parents; int ind_parent; intVector prev_nodes(0); for ( i = num_indep_nodes; i < num_nodes; i++) { prev_nodes.resize(0); for ( j = 0; j < num_indep_nodes; j++) prev_nodes.push_back(j); num_parents = rand() % (max_size_family - 1); num_parents += 1; num_parents = (num_parents > i) ? i : num_parents; for ( j = 0; j < num_parents; j++) { ind_parent = rand() % prev_nodes.size(); pGraph->AddEdge(prev_nodes[ind_parent], i, 1); prev_nodes.erase(prev_nodes.begin() + ind_parent); } } return pGraph; }
int CMRF2::GetFactors( int numberOfNodes, const int *nodes, pFactorVector *params ) const { /* bad-args check */ PNL_CHECK_RANGES( numberOfNodes, 1, 2 ); PNL_CHECK_IS_NULL_POINTER(nodes); PNL_CHECK_IS_NULL_POINTER(params); /* bad-args check end */ params->clear(); int numOfClqsFrstNode; const int *clqsFrstNode; GetClqsNumsForNode( *nodes, &numOfClqsFrstNode, &clqsFrstNode ); if( numberOfNodes == 1 ) { const int *clqsIt = clqsFrstNode, *clqs_end = clqsFrstNode + numOfClqsFrstNode; for( ; clqs_end - clqsIt; ++clqsIt ) { params->push_back(GetFactor(*clqsIt)); } } else { int numOfClqsScndNode; const int *clqsScndNode; GetClqsNumsForNode( *(nodes + 1), &numOfClqsScndNode, &clqsScndNode ); const int *pClqNum = std::find_first_of( clqsFrstNode, clqsFrstNode + numOfClqsFrstNode, clqsScndNode, clqsScndNode + numOfClqsScndNode ); if( pClqNum == clqsFrstNode + numOfClqsFrstNode ) { return 0; } params->push_back(GetFactor(*pClqNum)); } assert( params->size() != 0 ); return 1; }
void CJtreeInfEngine::EnterEvidence( const CEvidence *pEvidence, int maximize, int sumOnMixtureNode ) { // bad-args check PNL_CHECK_IS_NULL_POINTER(pEvidence); PNL_CHECK_RANGES( maximize, 0, 2 ); if( pEvidence->GetModelDomain() != m_pGraphicalModel->GetModelDomain() ) { PNL_THROW( CInvalidOperation, "evidence and the Graphical Model must be on one Model Domain" ); } // bad-args check end int i; ShrinkObserved( pEvidence, maximize, sumOnMixtureNode ); CollectEvidence(); DistributeEvidence(); for (i = 0; i < m_pJTree->GetNumberOfNodes(); i++) { EDistributionType dt = m_pJTree->GetNodePotential(i)->GetDistribFun()-> GetDistributionType(); if(dt == dtGaussian) { static_cast<CGaussianDistribFun*>(m_pJTree->GetNodePotential(i)-> GetDistribFun())->UpdateCanonicalCoefficient(); } } if (GetModel()->GetModelType() == mtBNet) { for (i = 0; i < GetModel()->GetNumberOfNodes(); i++) { if (GetModel()->GetFactor(i)->GetDistributionType() == dtSoftMax) { GetModel()->GetModelDomain()->ChangeNodeType(i, 0); } } } }
void CJtreeInfEngine:: DivideJTreeNodePotByDistribFun( int clqPotNum, const int *domain, const CDistribFun *pDistrFun ) { // bad-args check PNL_CHECK_RANGES( clqPotNum, 0, m_pJTree->GetNumberOfNodes() - 1 ); PNL_CHECK_IS_NULL_POINTER(domain); PNL_CHECK_IS_NULL_POINTER(pDistrFun); // bad-args check end CPotential *pNodePot = m_pJTree->GetNodePotential(clqPotNum); int nodePotDomSz; const int *nodePotDomain; pNodePot->GetDomain( &nodePotDomSz, &nodePotDomain ); pNodePot->GetDistribFun()->DivideInSelfData( nodePotDomain, domain, pDistrFun ); }
float CMlStaticStructLearn::ScoreFamily(intVector vFamily) { int nParents = vFamily.size() - 1; PNL_CHECK_RANGES(nParents, 0, m_nMaxFanIn); intVector indexes(m_nMaxFanIn,0); int i; for(i=0; i<nParents; i++) { indexes[i] = vFamily[i]+1; } int node = vFamily[nParents]; float score; float defval = m_pNodeScoreCache[node]->GetDefaultValue(); score = m_pNodeScoreCache[node]->GetElementByIndexes(&indexes.front()); if(score == defval) { score = ComputeFamilyScore(vFamily); m_pNodeScoreCache[node]->SetElementByIndexes(score, &indexes.front()); } return score; }
CMNet* CMNet::Create( int numberOfNodes, int numberOfNodeTypes, const CNodeType *nodeTypes, const int *nodeAssociation, int numberOfCliques, const int *cliqueSizes, const int **cliques ) { /* bad-args check */ PNL_CHECK_LEFT_BORDER( numberOfNodes, 1 ); PNL_CHECK_RANGES( numberOfNodeTypes, 1, numberOfNodes ); PNL_CHECK_IS_NULL_POINTER(nodeTypes); PNL_CHECK_IS_NULL_POINTER(nodeAssociation); PNL_CHECK_LEFT_BORDER( numberOfCliques, 1 ); PNL_CHECK_IS_NULL_POINTER(cliqueSizes); PNL_CHECK_IS_NULL_POINTER(cliques); /* bad-args check end */ /* creating the model */ CMNet *pMNet = new CMNet( numberOfNodes, numberOfNodeTypes, nodeTypes, nodeAssociation, numberOfCliques, cliqueSizes, cliques ); PNL_CHECK_IF_MEMORY_ALLOCATED(pMNet); return pMNet; }
void CBKInfEngine:: MarginalNodes( const int *query, int querySize, int slice, int notExpandJPD ) { ///////////////////////////////////////////////////////////////////////// if( GetProcedureType() == ptFiltering ) { PNL_CHECK_LEFT_BORDER(m_CRingpEv.size(), 1); } else { PNL_CHECK_LEFT_BORDER(m_CRingpEv.size() , m_CRingJtreeInf.size()); } ///////////////////////////////////////////////////////////////////////// if( GetEvidenceMPE() ) { delete GetEvidenceMPE(); SetEvidenceMPE(NULL); } if( GetQueryPot() ) { delete GetQueryPot(); SetQueryPot(NULL); } SetQueryNodes(querySize, query); intVector queryVec; queryVec.assign(query, query + querySize); intVector finalQuery; switch( m_ProcedureType ) { case ptFiltering: { FindFinalQuery( queryVec, m_CurrentTime - 1, &finalQuery); m_QuerryJTree = m_CRingJtreeInf[m_CurrentTime - 1]; m_QuerryJTree->MarginalNodes( &finalQuery.front(), querySize, notExpandJPD ); break; } case ptFixLagSmoothing: { FindFinalQuery( queryVec, m_CurrentTime - m_Lag - 1, &finalQuery); m_QuerryJTree = m_CRingJtreeInf[m_CurrentTime - m_Lag - 1]; m_QuerryJTree->MarginalNodes( &finalQuery.front(), querySize, notExpandJPD ); break; } case ptSmoothing: case ptViterbi: { PNL_CHECK_RANGES(slice, 0, m_Lag); FindFinalQuery( queryVec, slice, &finalQuery); m_QuerryJTree = m_CRingJtreeInf[slice]; m_QuerryJTree->MarginalNodes( &finalQuery.front(), querySize, notExpandJPD ); break; } } }
void CJtreeInfEngine::PropagateBetweenClqs(int source, int sink, bool isCollect) { PNL_CHECK_RANGES( source, 0, m_pJTree->GetNumberOfNodes() - 1 ); PNL_CHECK_RANGES( sink, 0, m_pJTree->GetNumberOfNodes() - 1 ); if (source == sink) { PNL_THROW(CInvalidOperation, " source and sink should differ "); } if (!m_pJTree->GetGraph()->IsExistingEdge(source, sink)) { PNL_THROW(CInvalidOperation, " there is no edge between source and sink "); } bool isDense = true; if(!m_pJTree->GetNodeType(source)->IsDiscrete() || !m_pJTree->GetNodeType(sink)->IsDiscrete()) { isDense = false; } CPotential *potSource = m_pJTree->GetNodePotential(source), *potSink = m_pJTree->GetNodePotential(sink); if(potSource->IsSparse() || potSink->IsSparse()) { isDense = false; } // check that nodes source and sink are discrete if(isDense && !m_bMaximize) { pnl::CNumericDenseMatrix< float > *sorceMatrix, *sepMatrix, *sinkMatrix; int *dims_to_keep, *dims_to_mul; int num_dims_to_keep, num_dims_to_mul; if (GetDataForMargAndMult(source, sink, &sorceMatrix, &dims_to_keep, num_dims_to_keep, &sepMatrix, &sinkMatrix, &dims_to_mul, num_dims_to_mul)) { DoPropagate(sorceMatrix, dims_to_keep, num_dims_to_keep, sepMatrix, sinkMatrix, dims_to_mul, num_dims_to_mul, isCollect); delete [] dims_to_keep; delete [] dims_to_mul; } else { CPotential *potSink = m_pJTree->GetNodePotential(sink); potSink->Normalize(); } } else { int numNdsInSepDom; const int *sepDom; int numNdsInSDom; const int *sDom; potSource->GetDomain( &numNdsInSDom, &sDom ); CPotential *potSep = m_pJTree->GetSeparatorPotential( source, sink ); CPotential *newPotSep, *updateRatio; potSep->GetDomain( &numNdsInSepDom, &sepDom ); newPotSep = potSource->Marginalize( sepDom, numNdsInSepDom, m_bMaximize ); updateRatio = newPotSep->Divide(potSep); *potSink *= *updateRatio; potSink->Normalize(); potSep->SetDistribFun(newPotSep->GetDistribFun()); delete newPotSep; delete updateRatio; } }
void CJtreeInfEngine::MarginalNodes( const int *query, int querySz, int notExpandJPD ) { // bad-args check PNL_CHECK_IS_NULL_POINTER(query); PNL_CHECK_RANGES( querySz, 1, m_pGraphicalModel->GetNumberOfNodes() ); // bad-args check end /* // the following should be working differently for the case of doing the // whole EnterEvidence procedure or just CollectEvidence for the root node if( ( m_lastOpDone != opsDistribute ) && ( m_lastOpDone != opsMargNodes ) ) { if( m_lastOpDone != opsCollect ) { PNL_THROW( CInvalidOperation, " cannot perform marginalization, infEngine inconsistent " ); } int numOfClqsContQuery; const int *clqsContQuery; m_pOriginalJTree->GetClqNumsContainingSubset( querySz, query, &numOfClqsContQuery, &clqsContQuery ); PNL_CHECK_FOR_ZERO(numOfClqsContQuery); if( std::find( clqsContQuery, clqsContQuery + numOfClqsContQuery, m_JTreeRootNode ) == clqsContQuery + numOfClqsContQuery ) { PNL_THROW( CInvalidOperation, " cannot marginalize to the non-root-clq nodes set " ); } //////// this is to debug for( int i = 0; i < numOfClqsContQuery; ++i ) { CPotential *pJPot = m_pJTree->GetNodePotential(clqsContQuery[i]) ->Marginalize( query, querySz ); CPotential *pJPot1 = pJPot->GetNormalized(); pJPot1->Dump(); delete pJPot; delete pJPot1; } /////////////////////////////////////////////////////// MarginalizeCliqueToQuery( m_JTreeRootNode, querySz, query ); m_lastOpDone = opsMargNodes; } else { */ int numOfClqsContQuery; const int *clqsContQuery; m_pJTree->GetClqNumsContainingSubset( querySz, query, &numOfClqsContQuery, &clqsContQuery ); if(numOfClqsContQuery) { if( std::find( clqsContQuery, clqsContQuery + numOfClqsContQuery, m_JTreeRootNode ) != ( clqsContQuery + numOfClqsContQuery ) ) { MarginalizeCliqueToQuery( m_JTreeRootNode, querySz, query, notExpandJPD ); } else { MarginalizeCliqueToQuery( *clqsContQuery, querySz, query, notExpandJPD ); } } else { const int* clqDomain; int clqSize; CPotential *resPot = NULL; delete m_pQueryJPD; m_pQueryJPD = NULL; ShrinkJTreeCliques(querySz, const_cast<int*>(query)); resPot = MergeCliques(querySz, const_cast<int*>(query)); resPot->GetDomain(&clqSize, &clqDomain); if( !pnlIsIdentical(querySz, const_cast<int*>(query), clqSize, const_cast<int*>(clqDomain)) ) { m_pQueryJPD = resPot->Marginalize(const_cast<int*>(query), querySz); } else { m_pQueryJPD = static_cast<CPotential*>(resPot->Clone()); } m_pQueryJPD->Normalize(); delete resPot; } }
void CJtreeInfEngine::ShrinkObserved( const CEvidence *pEvidence, int maximize, int sumOnMixtureNode, bool bRebuildJTree ) { // bad-args check PNL_CHECK_IS_NULL_POINTER(pEvidence); PNL_CHECK_RANGES( maximize, 0, 2 ); // bad-args check end m_norm = -1; m_pEvidence = pEvidence; m_bMaximize = maximize; // deletes an old internal junction tree to start computations anew m_pOriginalJTree->ClearCharge(); m_pOriginalJTree->InitCharge( m_pGraphicalModel, pEvidence, sumOnMixtureNode ); m_pJTree = m_pOriginalJTree; pConstValueVector allOffsets; m_pEvidence->GetObsNodesWithValues( &m_actuallyObsNodes, &allOffsets ); /* const int numOfNodesInGraph = m_pGraphicalModel->GetNumberOfNodes(); const int numOfClqs = m_pJTree->GetNumberOfNodes(); const int numOfObsNodes = m_pEvidence->GetNumberObsNodes(); const int *obsNodes = m_pEvidence->GetAllObsNodes(); const int *actuallyObsNodesFlags = m_pEvidence->GetObsNodesFlags(); const int *pOffset = m_pEvidence->GetOffset(); const unsigned char *evidData = m_pEvidence->GetRawData(); pnlVector< const unsigned char* > allOffsets( numOfNodesInGraph, NULL ); int i; for( i = 0; i < numOfObsNodes; ++i ) { if( actuallyObsNodesFlags[i] ) { m_actuallyObsNodes.push_back(obsNodes[i]); allOffsets[obsNodes[i]] = evidData + pOffset[i]; } } const int *clqIt, *clq_end; const int *nbrIt, *nbrs_end; const int *sepDomIt, *sepDom_end; intVector obsNodesInClq; intVector obsNodesInSep; obsNodesInClq.reserve(numOfObsNodes); obsNodesInSep.reserve(numOfObsNodes); // shrink node pots and separator pots based on the observed info for( i = 0; i < numOfClqs; ++i ) { int numOfNdsInClq; const int *clique; m_pJTree->GetNodeContent( i, &numOfNdsInClq, &clique ); for( clqIt = clique, clq_end = clique + numOfNdsInClq; clqIt != clq_end; ++clqIt ) { if( std::find( m_actuallyObsNodes.begin(), m_actuallyObsNodes.end(), *clqIt ) != m_actuallyObsNodes.end() ) { obsNodesInClq.push_back(*clqIt); } } if( !obsNodesInClq.empty() ) { // here is a line, why it all should not work for a cond gaussian const CNodeType *pObsNodeNT = m_pJTree->GetNodeType(i)->IsDiscrete() ? &m_ObsNodeType : &m_ObsGaussType; const CPotential *pShrPot = m_pJTree->GetNodePotential(i) ->ShrinkObservedNodes( obsNodesInClq.size(), obsNodesInClq.begin(), allOffsets.begin(), pObsNodeNT ); // this should be changed to perform a safe operation m_pJTree->GetNodePotential(i)->SetDistribFun( pShrPot->GetDistribFun()); delete pShrPot; // when done shrinking node pots, we go on with separator pots int numOfNbrs; const int *nbrs; const ENeighborType *nbrsTypes; m_pJTree->GetGraph()->GetNeighbors( i, &numOfNbrs, &nbrs, &nbrsTypes ); for( nbrIt = nbrs, nbrs_end = nbrs + numOfNbrs; nbrIt != nbrs_end; ++nbrIt ) { if( *nbrIt > i ) { int sepDomSz; const int *sepDomain; m_pJTree->GetSeparatorDomain( i, *nbrIt, &sepDomSz, &sepDomain ); for( sepDomIt = sepDomain, sepDom_end = sepDomain + sepDomSz; sepDomIt != sepDom_end; ++sepDomIt ) { if( std::find( obsNodesInClq.begin(), obsNodesInClq.end(), *sepDomIt ) != obsNodesInClq.end() ) { obsNodesInSep.push_back(*sepDomIt); } } if( !obsNodesInSep.empty() ) { pShrPot = m_pJTree->GetSeparatorPotential(i, *nbrIt) ->ShrinkObservedNodes( obsNodesInSep.size(), obsNodesInSep.begin(), allOffsets.begin(), pObsNodeNT ); m_pJTree->GetSeparatorPotential(i, *nbrIt) ->SetDistribFun(pShrPot->GetDistribFun()); delete pShrPot; } obsNodesInSep.clear(); } } obsNodesInClq.clear(); } } */ m_lastOpDone = opsShrinkEv; }
int CJtreeInfEngine::GetDataForMargAndMult(const int source, const int sink, pnl::CNumericDenseMatrix< float > **sorceMatrix, int **dims_to_keep, int &num_dims_to_keep, pnl::CNumericDenseMatrix< float > **sepMatrix, pnl::CNumericDenseMatrix< float > **sinkMatrix, int **dims_to_mul, int &num_dims_to_mul) { // bad-args check PNL_CHECK_RANGES(source, 0, m_pJTree->GetNumberOfNodes() - 1); PNL_CHECK_RANGES(sink, 0, m_pJTree->GetNumberOfNodes() - 1); // bad-args check end if (source == sink) { PNL_THROW(CInvalidOperation, " source and sink should differ "); } if (!m_pJTree->GetGraph()->IsExistingEdge(source, sink)) { PNL_THROW(CInvalidOperation, " there is no edge between source and sink"); } CPotential *potSource = m_pJTree->GetNodePotential(source), *potSink = m_pJTree->GetNodePotential(sink); int numNdsInSourceDom, numNdsInSinkDom; const int *sourceDom, *sinkDom; potSource->GetDomain(&numNdsInSourceDom, &sourceDom); potSink->GetDomain(&numNdsInSinkDom, &sinkDom); CPotential *potSep = m_pJTree->GetSeparatorPotential(source, sink); int numNdsInSepDom; const int *sepDom; potSep->GetDomain(&numNdsInSepDom, &sepDom); EDistributionType sepDistType = potSep->GetDistributionType(); num_dims_to_keep = numNdsInSepDom; *dims_to_keep = new int [num_dims_to_keep]; int* pEquivPos; for (int i = 0; i < numNdsInSepDom; i++) { pEquivPos = (int*)std::find(sourceDom, sourceDom + numNdsInSourceDom, sepDom[i]); if (pEquivPos != sourceDom + numNdsInSourceDom) { (*dims_to_keep)[i] = (pEquivPos - sourceDom); } else { PNL_THROW( CInconsistentSize, "small domain isn't subset of domain") return 0; } //check that pSmallDom is m_Domain's subset } switch (sepDistType) { case dtTabular: { CDistribFun *sepDistrFun = potSep -> GetDistribFun(); CDistribFun *sourceDistrFun = potSource -> GetDistribFun(); CDistribFun *sinkDistrFun = potSink -> GetDistribFun(); if (!sourceDistrFun->IsValid()) { PNL_THROW( CInconsistentType, "MarginalizeData is invalid" ) } //check if distribution of potSource is Unit Function - do nothing if(sourceDistrFun->IsDistributionSpecific()) { return 0; } if ( sepDistrFun->IsDistributionSpecific() ) { sepDistrFun->SetUnitValue(0); } *sorceMatrix = static_cast<CNumericDenseMatrix<float> *>(sourceDistrFun-> GetMatrix(matTable)); *sepMatrix = static_cast<CNumericDenseMatrix<float> *>(sepDistrFun-> GetMatrix(matTable)); EDistributionType dtsink = sinkDistrFun->GetDistributionType(); if ((dtsink != dtTabular) && (dtsink != dtScalar)) { PNL_THROW(CInvalidOperation, "we can multiply only tabulars") } int location; num_dims_to_mul = numNdsInSepDom; *dims_to_mul = new int [num_dims_to_mul]; for (int i = 0; i < numNdsInSepDom; i++) { location = std::find(sinkDom, sinkDom + numNdsInSinkDom, sepDom[i]) - sinkDom; if (location < numNdsInSinkDom) { (*dims_to_mul)[i] = location; } } if(sinkDistrFun->IsDistributionSpecific()) { sinkDistrFun->SetUnitValue(0); floatVector *aValue = (floatVector *)((CDenseMatrix<float>*)sinkDistrFun-> GetMatrix(matTable))->GetVector(); aValue->assign(aValue->size(), 1.0f); } *sinkMatrix = static_cast<CNumericDenseMatrix<float>*>(sinkDistrFun-> GetMatrix(matTable)); break; } case dtScalar: { // propagate isn't need return 0; } default: { PNL_THROW(CNotImplemented, "we have only Tabular now"); return 0; } } if (numNdsInSepDom == 0) { PNL_THROW(COutOfRange, "domain size should be positive"); } return 1; }
CGraph* CreateRandomAndSpecificForIDNetGraph(int num_nodes, int num_indep_nodes, int max_size_family) { PNL_CHECK_LEFT_BORDER(num_nodes, 10); PNL_CHECK_RANGES(num_indep_nodes, 1, num_nodes-1); PNL_CHECK_RANGES(max_size_family, 2, num_nodes); int i, j, k; CGraph *pGraph = CGraph::Create(0, NULL, NULL, NULL); PNL_CHECK_IF_MEMORY_ALLOCATED(pGraph); srand((unsigned int)time(NULL)); pGraph->AddNodes(num_nodes); int num_parents; int ind_parent; intVector prev_nodes(0); for (i = num_indep_nodes; i < num_nodes; i++) { prev_nodes.resize(0); for (j = 0; j < i; j++) prev_nodes.push_back(j); num_parents = rand() % (max_size_family - 1); num_parents += 1; num_parents = (num_parents > i) ? i : num_parents; for (j = 0; j < num_parents; j++) { ind_parent = rand() % prev_nodes.size(); pGraph->AddEdge(prev_nodes[ind_parent], i, 1); prev_nodes.erase(prev_nodes.begin() + ind_parent); } } intVector parents(0); intVector childs(0); for (i = 0; i < num_nodes; i++) { if (pGraph->GetNumberOfChildren(i) == 0) { pGraph->GetParents(i, &parents); for (j = 0; j < parents.size(); j++) { pGraph->GetChildren(parents[j], &childs); for (k = 0; k < childs.size(); k++) if ((childs[k] != i) && (pGraph->GetNumberOfChildren(childs[k]) == 0) && (pGraph->GetNumberOfParents(childs[k]) == 1)) { if (i < childs[k]) { pGraph->RemoveEdge(parents[j], childs[k]); pGraph->AddEdge(i, childs[k], 1); } else { pGraph->AddEdge(childs[k], i, 1); } } } } } return pGraph; }
CIDNet* CreateRandomIDNet(int num_nodes, int num_indep_nodes, int max_size_family, int num_decision_nodes, int max_num_states_chance_nodes, int max_num_states_decision_nodes, int min_utility, int max_utility, bool is_uniform_start_policy) { PNL_CHECK_RANGES(num_decision_nodes, 1, num_nodes-1); PNL_CHECK_LEFT_BORDER(max_num_states_chance_nodes, 1); PNL_CHECK_LEFT_BORDER(max_num_states_decision_nodes, 1); PNL_CHECK_LEFT_BORDER(max_utility, min_utility); CGraph* pGraph = CreateRandomAndSpecificForIDNetGraph(num_nodes, num_indep_nodes, max_size_family); if (!pGraph->IsDAG()) { PNL_THROW(CInconsistentType, " the graph should be a DAG "); } if (!pGraph->IsTopologicallySorted()) { PNL_THROW(CInconsistentType, " the graph should be sorted topologically "); } if (pGraph->NumberOfConnectivityComponents() > 1) { PNL_THROW(CInconsistentType, " the graph should be linked "); } int i, j, k; CNodeType *nodeTypes = new CNodeType [num_nodes]; intVector nonValueNodes(0); intVector posibleDecisionNodes(0); nonValueNodes.resize(0); posibleDecisionNodes.resize(0); for (i = 0; i < num_nodes; i++) { if (pGraph->GetNumberOfChildren(i) == 0) { nodeTypes[i].SetType(1, 1, nsValue); } else { nonValueNodes.push_back(i); posibleDecisionNodes.push_back(i); } } int ind_decision_node; int num_states; int index; int node; intVector neighbors(0); neighborTypeVector neigh_types(0); num_decision_nodes = (num_decision_nodes > posibleDecisionNodes.size()) ? posibleDecisionNodes.size() : num_decision_nodes; for (i = 0; (i < num_decision_nodes) && (posibleDecisionNodes.size()>0); i++) { ind_decision_node = rand() % posibleDecisionNodes.size(); node = posibleDecisionNodes[ind_decision_node]; num_states = GetRandomNumberOfStates(max_num_states_decision_nodes); nodeTypes[node].SetType(1, num_states, nsDecision); index = -1; for (j = 0; j < nonValueNodes.size(); j++) { if (nonValueNodes[j] == node) { index = j; break; } } if (index != -1) nonValueNodes.erase(nonValueNodes.begin() + index); posibleDecisionNodes.erase(posibleDecisionNodes.begin() + ind_decision_node); pGraph->GetNeighbors(node, &neighbors, &neigh_types); for (j = 0; j < neighbors.size(); j++) { index = -1; for (k = 0; k < posibleDecisionNodes.size(); k++) { if (neighbors[j] == posibleDecisionNodes[k]) { index = k; break; } } if (index != -1) posibleDecisionNodes.erase(posibleDecisionNodes.begin() + index); } } for (i = 0; i < nonValueNodes.size(); i++) { num_states = GetRandomNumberOfStates(max_num_states_chance_nodes); nodeTypes[nonValueNodes[i]].SetType(1, num_states, nsChance); } int *nodeAssociation = new int[num_nodes]; for (i = 0; i < num_nodes; i++) { nodeAssociation[i] = i; } CIDNet *pIDNet = CIDNet::Create(num_nodes, num_nodes, nodeTypes, nodeAssociation, pGraph); pGraph = pIDNet->GetGraph(); CModelDomain* pMD = pIDNet->GetModelDomain(); CFactor **myParams = new CFactor*[num_nodes]; int *nodeNumbers = new int[num_nodes]; int **domains = new int*[num_nodes]; intVector parents(0); for (i = 0; i < num_nodes; i++) { nodeNumbers[i] = pGraph->GetNumberOfParents(i) + 1; domains[i] = new int[nodeNumbers[i]]; pGraph->GetParents(i, &parents); for (j = 0; j < parents.size(); j++) { domains[i][j] = parents[j]; } domains[i][nodeNumbers[i]-1] = i; } pIDNet->AllocFactors(); for (i = 0; i < num_nodes; i++) { myParams[i] = CTabularCPD::Create(domains[i], nodeNumbers[i], pMD); } float **data = new float*[num_nodes]; int size_data; int num_states_node; int num_blocks; intVector size_nodes(0); float belief, sum_beliefs; for (i = 0; i < num_nodes; i++) { size_data = 1; size_nodes.resize(0); for (j = 0; j < nodeNumbers[i]; j++) { size_nodes.push_back(pIDNet->GetNodeType(domains[i][j])->GetNodeSize()); size_data *= size_nodes[j]; } num_states_node = size_nodes[size_nodes.size() - 1]; num_blocks = size_data / num_states_node; data[i] = new float[size_data]; switch (pIDNet->GetNodeType(i)->GetNodeState()) { case nsChance: { for (j = 0; j < num_blocks; j++) { sum_beliefs = 0.0; for (k = 0; k < num_states_node - 1; k++) { belief = GetBelief(1.0f - sum_beliefs); data[i][j * num_states_node + k] = belief; sum_beliefs += belief; } belief = 1.0f - sum_beliefs; data[i][j * num_states_node + num_states_node - 1] = belief; } break; } case nsDecision: { if (is_uniform_start_policy) { belief = 1.0f / float(num_states_node); for (j = 0; j < num_blocks; j++) { sum_beliefs = 0.0; for (k = 0; k < num_states_node - 1; k++) { data[i][j * num_states_node + k] = belief; sum_beliefs += belief; } data[i][j * num_states_node + num_states_node - 1] = 1.0f - sum_beliefs; } } else { for (j = 0; j < num_blocks; j++) { sum_beliefs = 0.0; for (k = 0; k < num_states_node - 1; k++) { belief = GetBelief(1.0f - sum_beliefs); data[i][j * num_states_node + k] = belief; sum_beliefs += belief; } belief = 1.0f - sum_beliefs; data[i][j * num_states_node + num_states_node - 1] = belief; } } break; } case nsValue: { for (j = 0; j < num_blocks; j++) { data[i][j] = float(GetUtility(min_utility, max_utility)); } break; } } } for (i = 0; i < num_nodes; i++) { myParams[i]->AllocMatrix(data[i], matTable); pIDNet->AttachFactor(myParams[i]); } delete [] nodeTypes; delete [] nodeAssociation; return pIDNet; }
void CJtreeInfEngine:: MarginalizeCliqueToQuery( int clqNum, int querySz, const int *query, int notExpandJPD ) { // bad-args check PNL_CHECK_RANGES( clqNum, 0, m_pJTree->GetNumberOfNodes() - 1 ); PNL_CHECK_RANGES( querySz, 1, m_pGraphicalModel->GetNumberOfNodes() ); PNL_CHECK_IS_NULL_POINTER(query); // bad-args check end // Note: cant call expand() for potentials, which contain continuous // observed nodes in domain, cause those are to be expanded to // mixture of gaussians, which we dont support right now. delete m_pQueryJPD; m_pQueryJPD = NULL; delete m_pPotMPE; m_pPotMPE = NULL; delete m_pEvidenceMPE; m_pEvidenceMPE = NULL; bool bExpandAllowed = true; CPotential* clqPotWithQuery = m_pJTree->GetNodePotential(clqNum); EDistributionType dtClqWithQuery = clqPotWithQuery->GetDistributionType(); if( std::find_first_of( query, query + querySz, m_actuallyObsNodes.begin(), m_actuallyObsNodes.end() ) != ( query + querySz ) ) { const int *queryIt = query, *query_end = query + querySz; for( ; queryIt != query_end; ++queryIt ) { if( std::find( m_actuallyObsNodes.begin(), m_actuallyObsNodes.end(), *queryIt ) != m_actuallyObsNodes.end() ) { int shrNodebDiscrete = m_pGraphicalModel->GetNodeType(*queryIt)->IsDiscrete(); if(((dtClqWithQuery == dtTabular)&&( !shrNodebDiscrete )) ||(( dtClqWithQuery == dtGaussian )&&( shrNodebDiscrete ))) { bExpandAllowed = false; break; } } } } if( ( bExpandAllowed == false ) && ( notExpandJPD == false ) ) { PNL_THROW( CAlgorithmicException, " JPD expansion not possible technically " ); } bExpandAllowed = notExpandJPD ? false : bExpandAllowed; CPotential *pMargJPot = clqPotWithQuery->Marginalize( query, querySz, m_bMaximize ); if( bExpandAllowed ) { CPotential *pExpObsJPot = pMargJPot->ExpandObservedNodes(m_pEvidence); if( m_bMaximize ) { if( pMargJPot->GetDistributionType() == dtScalar ) { m_pPotMPE = pExpObsJPot->GetNormalized(); m_pEvidenceMPE = m_pPotMPE->GetMPE(); } else { m_pPotMPE = pMargJPot->GetNormalized(); m_pEvidenceMPE = m_pPotMPE->GetMPE(); } } else { m_pQueryJPD = pExpObsJPot->GetNormalized(); } delete pExpObsJPot; } else { if( m_bMaximize ) { m_pPotMPE = pMargJPot->GetNormalized(); m_pEvidenceMPE = m_pPotMPE->GetMPE(); } else { m_pQueryJPD = pMargJPot->GetNormalized(); } } if((!m_bMaximize)&&(m_pQueryJPD->GetDistributionType() == dtGaussian)) { static_cast<CGaussianDistribFun*>( m_pQueryJPD->GetDistribFun())->UpdateMomentForm(); } if((m_bMaximize)&&(m_pPotMPE->GetDistributionType() == dtGaussian)) { static_cast<CGaussianDistribFun*>( m_pPotMPE->GetDistribFun())->UpdateMomentForm(); } delete pMargJPot; }