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