CCPD*
CMlStaticStructLearn::CreateRandomCPD(int nfamily, const int* family, CGraphicalModel* pGrModel)
{
    CModelDomain* pMD = pGrModel->GetModelDomain();
    EDistributionType dt = pnlDetermineDistributionType( pMD, nfamily, family, NULL);

    CCPD* pCPD;

    int i;
    int j;
    // checking SoftMax distribution
    for( i = 0; i < nfamily; i++ )
    {
        if( (!pMD->GetVariableType(family[i])->IsDiscrete())
                && pMD->GetVariableType(family[nfamily-1])->IsDiscrete() )
        {
            for( j = 0; j < nfamily-1; j++ )
                if(pMD->GetVariableType(family[j])->IsDiscrete())
                {
                    dt = dtCondSoftMax;
                    break;
                };
            dt =  dtSoftMax;
            break;
        }
    }
    // end of checking
    switch (dt)
    {
    case dtTabular :
        pCPD = CTabularCPD::Create(family, nfamily, pMD);
        pCPD->CreateAllNecessaryMatrices(1);
        break;

    case dtTree :
        pCPD = CTreeCPD::Create(family, nfamily, pMD);
        break;

    case dtGaussian :
    case dtCondGaussian :
        pCPD = CGaussianCPD::Create(family, nfamily, pMD);
        pCPD->CreateAllNecessaryMatrices(1);
        break;
    case dtSoftMax:
    case dtCondSoftMax:
        pCPD = CSoftMaxCPD::Create(family, nfamily, pMD);
        pCPD->CreateAllNecessaryMatrices(1);
        break;
    default:
        PNL_THROW(CNotImplemented, "This type of distribution has not been implemented yet");
        break;
    }
    return pCPD;
}
void CGibbsSamplingInfEngine::
MarginalNodes( const int *queryIn, int querySz, int notExpandJPD )
{
  delete m_pQueryJPD;
  m_pQueryJPD = NULL;
  
  delete m_pPotMPE;
  m_pPotMPE = NULL;
  
  delete m_pEvidenceMPE;
  m_pEvidenceMPE = NULL;
  
  const CFactor *pFactor;
  CPotential *pPot =  NULL;
  int *begin1;
  int *end1;
  int *begin2;
  int *end2;
  
  intVector domainVec;
  intVector queryVec;
  intVector obsQueryVec;
  queryVec.reserve(querySz);
  obsQueryVec.reserve(querySz);
  int i;
  for( i = 0; i < querySz; i++ )
  {
    m_pEvidence->IsNodeObserved(queryIn[i]) ? 
      obsQueryVec.push_back(queryIn[i]):
    queryVec.push_back(queryIn[i]);
  }
  
  
  CPotential *tmpPot = NULL;
  
  if( queryVec.size() )
  {
    for( i = 0; i < m_queryFactors.size(); i++)     
    {
      
      domainVec.clear();
      pFactor = m_queryFactors[i];
      pFactor->GetDomain(&domainVec);
      begin1 = &domainVec.front();
      end1 = &domainVec.back() + 1;
      std::sort(begin1, end1);
      
      begin2 = &queryVec.front();
      end2 = &queryVec.back() + 1;
      std::sort(begin2, end2);
      
      if( std::includes(begin1, end1, begin2, end2) )
      {
        pPot = pFactor->ConvertStatisticToPot( (GetMaxTime()-GetBurnIn()-1)*GetNumStreams() );
        tmpPot = pPot->Marginalize( queryVec );
        delete pPot;
        break;
      }
      		   
    }
    if( !tmpPot )
    {
      PNL_THROW(CInvalidOperation, "Invalid query");
    }
  }
  delete m_pQueryJPD; 
  
  if( obsQueryVec.size() )
  {
    
    EDistributionType paramDistrType = 
      pnlDetermineDistributionType( GetModel()->GetModelDomain(), querySz, queryIn, m_pEvidence);
    
    
    CPotential *pQueryPot;
    switch( paramDistrType )
    {
    case dtTabular:
      {
        pQueryPot = CTabularPotential::CreateUnitFunctionDistribution(
          queryIn, querySz, m_pGraphicalModel->GetModelDomain() );
        break;
      }
      
    case dtGaussian:
      {
        pQueryPot = CGaussianPotential::CreateUnitFunctionDistribution(
          queryIn, querySz, m_pGraphicalModel->GetModelDomain()  );
        break;
      }
    case dtScalar:
      {
        pQueryPot = CScalarPotential::Create(
          queryIn, querySz, m_pGraphicalModel->GetModelDomain()  );
        break;
      }
    case dtCondGaussian:
      {
        PNL_THROW( CNotImplemented, "conditional gaussian factors" )
          break;
      }
    default:
      {
        PNL_THROW( CInconsistentType, "distribution type" )
      }
    }
    
    if( tmpPot)
    {
      (*pQueryPot) *= (*tmpPot);
      delete tmpPot;
    }
    
    if( m_bMaximize )
    {
      m_pPotMPE   = static_cast<CPotential*>
        ( pQueryPot->ExpandObservedNodes( m_pEvidence, 0) );
      
      m_pEvidenceMPE = m_pPotMPE->GetMPE();
    }
    else
    {
      m_pQueryJPD = static_cast<CPotential*>( pQueryPot->ExpandObservedNodes( m_pEvidence, 0) );
    }
    
    delete pQueryPot;
  }
void CSpecPearlInfEngine::InitEngine(const CEvidence* pEvidence)
{
    //determine distribution type for messages
//    intVector         obsNds;
//    pConstValueVector obsNdsVals;

    const int nObsNodes = pEvidence->GetNumberObsNodes();
    
    const int *ObsNodes = pEvidence->GetAllObsNodes();
    
    const int *ReallyObs = pEvidence->GetObsNodesFlags();
    
    intVector ReallyObsNodes;

    int i = 0;

    for ( ; i < nObsNodes; i++ )
    {
        if( ReallyObs[i] )
        {
            ReallyObsNodes.push_back(ObsNodes[i]);
        }
    }
    
    int NumReallyObs = ReallyObsNodes.size();

    pConstNodeTypeVector nodeTypes(m_numOfNdsInModel);

    for ( i = 0; i < m_numOfNdsInModel; i++ )
    {
        nodeTypes[i] = m_pGraphicalModel->GetNodeType(i);
    }

    m_modelDt = pnlDetermineDistributionType( m_numOfNdsInModel, NumReallyObs,
                                              &ReallyObsNodes.front(), &nodeTypes.front() );
    

    EDistributionType dtWithoutEv = pnlDetermineDistributionType( m_numOfNdsInModel, 0,
                                                                  &ReallyObsNodes.front(), &nodeTypes.front() );

    switch (dtWithoutEv)
    {
        //create vector of connected nodes
        case dtTabular: case dtGaussian:
        {
            m_connNodes = intVector(m_numOfNdsInModel);

            for( i = 0; i < m_numOfNdsInModel; ++i )
            {
                m_connNodes[i] = i;
            }

            break;
        }
        case dtCondGaussian:
        {	
            int loc;
            
            for( i = 0; i < m_numOfNdsInModel; i++ )
            {
                loc = std::find( ReallyObsNodes.begin(), ReallyObsNodes.end(),
                    i ) - ReallyObsNodes.begin();
            
                if(( loc < ReallyObsNodes.size() )&&
                    ( nodeTypes[ReallyObsNodes[loc]]->IsDiscrete() ))
                {
                    m_connNodes.push_back(i);
                }
            }
            
            break;
        }
        default:
        {
            PNL_THROW( CInconsistentType, "only for fully tabular or fully gaussian models" )
                break;
        }
    }
}