
#include "PartialMSR2Bp.h"


namespace smartcomparator
{
	namespace simfunctions
	{


PartialMSR2Bp::PartialMSR2Bp(
	Matrices::SuperMatrixPtr&	pWeightsMatrix,
	SimilarityFunctionPtr&		pSimilarityFunction,
	SynsetClassSetPtrS&			pSynsetClasses,
	Params&						pParams,
	ParamsBp&					pParamsBp )
:
	PartialMSR2Base( pWeightsMatrix, pSimilarityFunction, pSynsetClasses, pParams ),
	mParamsBp( pParamsBp )
{

}

PartialMSR2Bp::~PartialMSR2Bp(){

}


double PartialMSR2Bp::CountSimilarity(
	Matrices::CompressedVector& pMatrixRow1,
	Matrices::CompressedVector& pMatrixRow2,
	size_t 						pLemmaIndex1,
	size_t 						pLemmaIndex2,
	const std::set<size_t>&		pNonZeroFeaturesIndices1,
	const std::set<size_t>&		pNonZeroFeaturesIndices2 )
{
	return InnerCountSimilarityBp( pMatrixRow1, pMatrixRow2, pLemmaIndex1,
		pLemmaIndex2, pNonZeroFeaturesIndices1, pNonZeroFeaturesIndices2 );
}


void PartialMSR2Bp::init( Matrices::SuperMatrixPtr& pFrequencies ){
	PartialMSR2Base::init( pFrequencies );
}


// CountSimilarity
double PartialMSR2Bp::InnerCountSimilarityBp(
	Matrices::CompressedVector& pMatrixRow1,
	Matrices::CompressedVector& pMatrixRow2,
	size_t 						pLemmaIndex1,
	size_t 						pLemmaIndex2,
	const std::set<size_t>&		pNonZeroFeaturesIndices1,
	const std::set<size_t>&		pNonZeroFeaturesIndices2 )
{
	//DONE: 1) features mapping required

	typedef unsigned int UINT;
	UINT sameCls = 0U;
	UINT diffCls = 0U;

	bool pCompute = false;
	{
		// this part could be optimized by avoiding using lemmas mapping and use class matrix
		ClassIdsSetPtrS lemma1Cls;
		ClassIdsSetPtrS lemma2Cls;
		{
			std::string lemma1 = m_pMatrix->GetRowFeatures()->at( pLemmaIndex1 ).GetLabel();
			std::string lemma2 = m_pMatrix->GetRowFeatures()->at( pLemmaIndex2 ).GetLabel();
			lemma1 = lemma1.substr( lemma1.rfind(":") + 1 );
			lemma2 = lemma2.substr( lemma2.rfind(":") + 1 );
			ClassIdsSetByLemmasMap::iterator i1 = mLemmasMapping->find( lemma1 );
			ClassIdsSetByLemmasMap::iterator i2 = mLemmasMapping->find( lemma2 );

			// CHECK RULE 1
			if( i1 == mLemmasMapping->end() || i2 == mLemmasMapping->end() )
				return MinValue();

			lemma1Cls = i1->second;
			lemma2Cls = i2->second;
		}

		bool lemmasBelongToTheSameClass = false;
		{
			ClassIdsSet::iterator lemma1ClsIter = lemma1Cls->begin();
			ClassIdsSet::iterator lemma1ClsEnd	= lemma1Cls->end();
			for(; lemma1ClsIter != lemma1ClsEnd; ++lemma1ClsIter ){
				ClassIdsSet::iterator is = lemma2Cls->find( *lemma1ClsIter );
				if( is == lemma2Cls->end() )
					continue;
				lemmasBelongToTheSameClass = true;
				break;
			}
		}

		std::map<size_t, double>* row1Values 		= pMatrixRow1.GetValues();
		std::map<size_t, double>* row2Values 		= pMatrixRow2.GetValues();
		std::map<size_t, double>::iterator row1Iter = row1Values->begin();
		std::map<size_t, double>::iterator row1End 	= row1Values->end();
		for(; row1Iter != row1End; ++row1Iter ){

			size_t clsFeatureIdx = (*mWWordsToWClass)[ row1Iter->first ];
			if( clsFeatureIdx == static_cast<size_t>( -1 ) )
				continue;

			// DONE: 1)
			// check if feature entrophy is small enough
			if( mSmCxF->GetColumnFeatures()->at( clsFeatureIdx ).GetEntropy() > mMaxEntrophy )
				continue;

			// if both lemmas have not the same feature then continue
			if( row2Values->find( row1Iter->first ) == row2Values->end() )
				continue;

			// both lemmas have the same feature
			++diffCls;

			// check if both lemmas belong to the same class
			if( lemmasBelongToTheSameClass )
				++sameCls;

			if( diffCls > mParamsBp.n || sameCls >= mParamsBp.k ){
				pCompute = true;
				break;
			}
		}

	}

	return pCompute ?
		mSimFunction->CountSimilarity(
			pMatrixRow1, pMatrixRow2,
			pLemmaIndex1, pLemmaIndex2,
			pNonZeroFeaturesIndices1, pNonZeroFeaturesIndices2 ) :
		MinValue();
}


	}
}


