Пример #1
0
int testSEGaussian()
{
    PNL_USING
   
    int i;
    int ret = TRS_OK;
    float eps = 1e-4f;
    //create Gaussian distribution (inside the potential) and try to multiply
    //is by Delta
    
    //create Model Domain
    int nSimNodes = 3;
    CNodeType simNT = CNodeType(0, 2);
    CModelDomain* pSimDomain = CModelDomain::Create( nSimNodes, simNT );
    //create 2 potentials
    intVector dom;
    dom.assign(3,0);
    dom[1] = 1;
    dom[2] = 2;
    floatVector mean;
    mean.assign(6, 0);
    floatVector cov;
    cov.assign(36, 0.1f);
    for( i = 0; i < 6; i++ )
    {
        mean[i] = 1.1f*i;
        cov[i*7] = 2.0f;
    }

	CGaussianPotential* pPot = CGaussianPotential::Create( dom, pSimDomain, 1,
        mean, cov, 1.0f );

    //create gaussian CPD with gaussian parent
    const pConstNodeTypeVector* pTypes = pPot->GetArgType();
    //create data weigth
    floatVector weights1;
    weights1.assign(4, 1.0f);
    floatVector weights2;
    weights2.assign(4, 2.0f);
    const float* weights[] = { &weights1.front(), &weights2.front()};
    CGaussianDistribFun* pGauCPD = CGaussianDistribFun::CreateInMomentForm( 0,
        3, &pTypes->front(), &mean.front(), &cov.front(), weights );

    pPot->Dump();
    pPot->Normalize();
    //try to get multiplied delta
    intVector pos;
    floatVector valuesDelta;
    intVector offsets;
    pPot->GetMultipliedDelta(&pos, &valuesDelta, &offsets);
    if( pos.size() != 0 )
    {
        ret = TRS_FAIL;
    }


    //enter evidence to the pot and after that expand and compare results
    //create evidence object
/*    valueVector obsVals;
    obsVals.assign(6,Value(0) );
    obsVals[0].SetFlt(1.0f);
    obsVals[1].SetFlt(1.5f);
    obsVals[2].SetFlt(2.0f);
    obsVals[3].SetFlt(2.5f);
    obsVals[4].SetFlt(3.0f);
    obsVals[5].SetFlt(3.5f);
    CEvidence* pEvid = CEvidence::Create( pSimDomain, 3, &dom.front(), obsVals );
    CPotential* pShrPot = pPot->ShrinkObservedNodes( pEvid );*/
    
    
    CGaussianPotential* pCanonicalPot = CGaussianPotential::Create( dom,
        pSimDomain, 0, mean, cov, 1.0f );
    CMatrix<float>* matrK = pCanonicalPot->GetMatrix(matK);
    intVector multIndex;
    multIndex.assign(2,5);
    matrK->SetElementByIndexes( 3.0f, &multIndex.front() );
    CMatrix<float>* matrH = pCanonicalPot->GetMatrix(matH);
    multIndex[0] = 0;
    matrH->SetElementByIndexes(0.0f, &multIndex.front());
    pPot->ConvertToSparse();
    pPot->ConvertToDense();
    //create other Gaussian potential for division
    i = 1;
    floatVector meanSmall;
    meanSmall.assign(2, 1.0f);
    floatVector covSmall;
    covSmall.assign(4, 0.0f);
    covSmall[0] = 1.0f;
    covSmall[3] = 1.0f;
    CGaussianPotential* pSmallPot = CGaussianPotential::Create( &i, 1,
        pSimDomain, 1, &meanSmall.front(), &covSmall.front(), 1.0f );
    //divide by distribution in moment form
    (*pCanonicalPot) /= (*pSmallPot);

    //create big unit function distribution and marginalize it
    CGaussianPotential* pBigUnitPot = 
        CGaussianPotential::CreateUnitFunctionDistribution(dom, pSimDomain, 1);
	CGaussianPotential* pCloneBigUniPot = static_cast<CGaussianPotential*>(
		pBigUnitPot->CloneWithSharedMatrices());
	if( !pCloneBigUniPot->IsFactorsDistribFunEqual(pBigUnitPot, eps) )
	{
		ret = TRS_FAIL;
	}
    CPotential* pMargUniPot = pBigUnitPot->Marginalize(&dom.front(), 1, 0);
    (*pBigUnitPot) /= (*pSmallPot);
    (*pBigUnitPot) *= (*pSmallPot);
    
    //check if there are some problems
    static_cast<CGaussianDistribFun*>(pBigUnitPot->GetDistribFun())->CheckCanonialFormValidity();

    if( pBigUnitPot->IsDistributionSpecific() != 1 )
    {
        ret = TRS_FAIL;
    }

    (*pBigUnitPot) /= (*pCanonicalPot);
    (*pBigUnitPot) *= (*pCanonicalPot);

    static_cast<CGaussianDistribFun*>(pBigUnitPot->GetDistribFun())->CheckCanonialFormValidity();

    if( pBigUnitPot->IsDistributionSpecific() != 1 )
    {
        ret = TRS_FAIL;
    }

    static_cast<CGaussianDistribFun*>(pSmallPot->GetDistribFun())->
        UpdateCanonicalForm();
    (*pPot) /= (*pSmallPot);
    pSmallPot->SetCoefficient(0.0f,1);
    pSmallPot->Dump();

    //create canonical potential without coefficient
    i = 0;

    CDistribFun* pCopyPotDistr = pPot->GetDistribFun()->ConvertCPDDistribFunToPot();
    CGaussianPotential* pCanSmallPot = CGaussianPotential::Create( &i, 1,
        pSimDomain, 0, &meanSmall.front(), &covSmall.front(), 1.0f );
    CGaussianPotential* pCanPotCopy = 
        static_cast<CGaussianPotential*>(pCanSmallPot->Clone());
    CGaussianPotential* pCanPotCopy1 = 
        static_cast<CGaussianPotential*>(pCanPotCopy->CloneWithSharedMatrices());

    (*pPot) /= (*pCanSmallPot);
    (*pPot) *= (*pCanSmallPot);
    //can compare results, if we want
    CDistribFun* pMultDivRes = pPot->GetDistribFun();
    float diff = 0;
    if( !pMultDivRes->IsEqual(pCopyPotDistr, eps,1, &diff) )
    {
        ret = TRS_FAIL;
        std::cout<<"the diff is "<<diff<<std::endl;
    }
    delete pCopyPotDistr;
    
    //create delta distribution
    floatVector deltaMean;
    deltaMean.assign( 2, 1.5f );
    i = 0;
    CGaussianPotential* pDeltaPot = CGaussianPotential::CreateDeltaFunction( 
        &i, 1, pSimDomain, &deltaMean.front(), 1 );
    
    CGaussianDistribFun* pDeltaDistr = static_cast<CGaussianDistribFun*>(
        pDeltaPot->GetDistribFun());
    pDeltaDistr->CheckMomentFormValidity();
    pDeltaDistr->CheckCanonialFormValidity();
    pDeltaPot->Dump();


    //multiply some potential by delta
    (*pCanSmallPot) *= (*pDeltaPot);

    (*pPot) *= (*pDeltaPot);
    //(*pPot) *= (*pDeltaPot);
    
    pPot->GetMultipliedDelta(&pos, &valuesDelta, &offsets);
    (*pCanonicalPot) *= (*pDeltaPot);
    //marginalize this distribFun multiplied by delta
    intVector margDims;
    margDims.assign(2,1);
    margDims[1] = 2;
    CPotential* pMargPot = pPot->Marginalize( &margDims.front(), 2 );
    i = 0;
    CPotential* pSmallMargPot = pPot->Marginalize(&i, 1);
    //marginalize in canonical form
    CPotential* pMargCanPot = pCanonicalPot->Marginalize( &margDims.front(), 2 );
    CPotential* pSmallCanPot = pCanonicalPot->Marginalize(&i,1);
    
    //create unit function distribution in canonical form
    i = 0;
    CGaussianPotential* pUnitPot = 
        CGaussianPotential::CreateUnitFunctionDistribution( &i, 1, pSimDomain,
        1);
    pUnitPot->Dump();
    CGaussianDistribFun* pUnitDistr = static_cast<CGaussianDistribFun*>(
        pUnitPot->GetDistribFun());
    pUnitDistr->CheckCanonialFormValidity();
    pUnitDistr->CheckMomentFormValidity();

    (*pPot) *= (*pUnitPot);

    if( pUnitPot->IsFactorsDistribFunEqual(pBigUnitPot, eps, 1) )
    {
        ret = TRS_FAIL;
    }

    deltaMean.resize(6);
    deltaMean[2] = 2.5f;
    deltaMean[3] = 2.5f;
    deltaMean[4] = 3.5f;
    deltaMean[5] = 3.5f;
    CGaussianPotential* pBigDeltaPot = CGaussianPotential::CreateDeltaFunction( 
        dom, pSimDomain, deltaMean, 1 );
    CGaussianPotential* pCloneBigDeltaPot = static_cast<CGaussianPotential*>(
		pBigDeltaPot->CloneWithSharedMatrices());
    //we can shrink observed nodes in this potential
    valueVector vals;
    vals.resize(2);
    vals[0].SetFlt(1.5f);
    vals[1].SetFlt(1.5f);
    i = 0;
    CEvidence* pDeltaEvid = CEvidence::Create( pSimDomain, 1, &i,vals ); 
    CGaussianPotential* pShrGauDeltaPot = static_cast<CGaussianPotential*>(
        pBigDeltaPot->ShrinkObservedNodes( pDeltaEvid ));
    delete pDeltaEvid;
    pShrGauDeltaPot->Dump();
    delete pShrGauDeltaPot;
    CPotential* pSmallDeltaMarg = pBigDeltaPot->Marginalize( &dom.front(), 1, 0 );
    pSmallDeltaMarg->Normalize();
    pDeltaPot->Normalize();
    if( !pSmallDeltaMarg->IsFactorsDistribFunEqual( pDeltaPot, eps, 1 ) )
    {
        ret = TRS_FAIL;
    }
    //call operator = for delta distributions
    (*pSmallDeltaMarg) = (*pDeltaPot);

    //call operator = for canonical and delta distribution
    (*pCanPotCopy) = (*pUnitPot);

    //call operator = for canonical and unit distribution
    (*pCanPotCopy1) = (*pDeltaPot);

    (*pUnitPot) = (*pUnitPot);
    

    (*pPot) *= (*pBigDeltaPot);

    (*pCloneBigDeltaPot) *= (*pDeltaPot);

	if( !pCloneBigDeltaPot->IsFactorsDistribFunEqual(pBigDeltaPot, eps) )
	{
		ret = TRS_FAIL;
	}

    //we can create the matrix which will be almost delta distribution,
    //but covariance matrix will contain almost zeros
    floatVector almostDeltaCov;
    almostDeltaCov.assign(4, 0.0f);
    almostDeltaCov[0] = 0.00001f;
    almostDeltaCov[3] = 0.00001f;
    i = 0;
    CGaussianPotential* pAlmostDeltaPot = CGaussianPotential::Create( &i, 1, 
        pSimDomain, 1, &deltaMean.front(), &almostDeltaCov.front(), 1.0f );
    if( !pDeltaPot->IsFactorsDistribFunEqual( pAlmostDeltaPot, eps, 0 ) )
    {
        ret = TRS_FAIL;
    }
    if( !pAlmostDeltaPot->IsFactorsDistribFunEqual( pDeltaPot, eps, 0 ) )
    {
        ret = TRS_FAIL;
    }
	(*pCloneBigUniPot ) = ( *pPot );
	if( !(pCloneBigUniPot->IsFactorsDistribFunEqual(pPot, eps)) )
	{
		ret = TRS_FAIL;
	}
	(*pCloneBigDeltaPot) = (*pPot);
	if( !(pCloneBigDeltaPot->IsFactorsDistribFunEqual(pPot, eps))  )
	{
		ret = TRS_FAIL;
	}

    delete pCanPotCopy;
    delete pCanPotCopy1;
    delete pAlmostDeltaPot;
    delete pMargUniPot;
	delete pCloneBigUniPot;
    delete pBigUnitPot;
    delete pCanSmallPot;
    delete pDeltaPot; 
    delete pUnitPot;
	delete pCloneBigDeltaPot;
    delete pBigDeltaPot;
    delete pMargCanPot;
    delete pSmallCanPot;
    delete pMargPot;
    delete pSmallMargPot;
    delete pCanonicalPot;
    //delete pShrPot;
    //delete pEvid;
	delete pGauCPD;
    delete pPot;
    delete pSimDomain;
    return trsResult( ret, ret == TRS_OK ? "No errors" : 
                        "Bad test on SEGaussian");

}
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;
    }
}