
#include "PartialMSR2A.h"


namespace smartcomparator
{
	namespace simfunctions
	{


PartialMSR2A::PartialMSR2A(
	Matrices::SuperMatrixPtr&	pWeightsMatrix,
	SimilarityFunctionPtr&		pSimilarityFunction,
	SynsetClassSetPtrS&			pSynsetClasses,
	Params&						pParams,
	ParamsA&					pParamsA  )
:
	PartialMSR2Base( pWeightsMatrix, pSimilarityFunction, pSynsetClasses, pParams ),
	mParamsA( pParamsA )
{

}

PartialMSR2A::~PartialMSR2A(){

}

double PartialMSR2A::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 InnerCountSimilarityA( pMatrixRow1, pMatrixRow2, pLemmaIndex1,
		pLemmaIndex2, pNonZeroFeaturesIndices1, pNonZeroFeaturesIndices2 );
}


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

	mFrequencies 	= pFrequencies;
	mWWordsToFWords	= buildFeaturesMapping( m_pMatrix, mFrequencies );
}

/*
Wariant A
Modyfikacje do alg. ze str. 52, draft książki.
globalnie nieistone = cechy filtrowane entropijnie względem słów (1%) plus 5% cech wg najwyższej entropii cech względem klas

funkcja fzn wyznaczajaca zbiór cech lokalnie znaczacych =
- zakładają ważenie za pomocą PMI
- Jako cechy lokalnie nieistotne dla lematu i przyjmujemy cechy o wadze <= 1 dla lematu i, pozostałe uznajemy za lokalnie znaczace dla danego lematu.

Wyliczenie podobienstwa: -- pozostaje bez zmian.
*/
double PartialMSR2A::InnerCountSimilarityA(
	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: WeightedWords -> WeightedClasses
	//DONE: 2) features mapping required: WeightedWords -> FreqWords
	//DONE: 3) lemmas mapping required: WeightedWords -> FreqWords (without vector coz lemmas num << features num)

	size_t 		mutalFeaturesCounter 		= 0UL;
	bool 		pCompute 					= false;

	std::set<size_t> localyImportantFeatures1;
	std::set<size_t> localyImportantFeatures2;


	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 ) && !pCompute; ++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;

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

		// check if feature weights for this lemmas is bigger than min
		bool isFirstImp = pMatrixRow1[ row1Iter->first ] > mParams.minFeatureWeightForLemma;
		bool isSecImp 	= pMatrixRow2[ row1Iter->first ] > mParams.minFeatureWeightForLemma;
		if( !( isFirstImp && isSecImp ) ){
			size_t freqFeatureIdx = (*mWWordsToFWords)[ row1Iter->first ];
			// required coz freq mtx may be != weight mtx
			if(freqFeatureIdx == static_cast<size_t>(-1))
				continue;
			if( isFirstImp )
				//DONE: 2) or skip here and do it in Fcz below
				localyImportantFeatures1.insert( freqFeatureIdx );
			else
				//DONE: 2)
				localyImportantFeatures2.insert( freqFeatureIdx );
			continue;
		}

		if( ++mutalFeaturesCounter >= mParamsA.k )
			pCompute = true;
	}

	//2nd req. from draft for fcz
	//this one might be a parameter


	{
		// required min of mutal features which are important for both lemmas
		size_t req = 1UL;
		if( !pCompute && mutalFeaturesCounter == req ){

			//DONE: 3) lemmas mapping
			std::string const& label = m_pMatrix->GetRowFeatures()->at( pLemmaIndex2 ).GetLabel();
			size_t freqRowIdx = mFrequencies->GetRowIndex( label );
			// ther's an option that there will be no this lemma in freqencies matrix
			if(freqRowIdx != static_cast<size_t>(-1)){
				size_t localyImportantPairs 			= 0UL;	// must be (req) + (number of pairs features distinct from req pairs - here 1)
				std::set<size_t>::iterator localIter1 	= localyImportantFeatures1.begin();
				for(; localIter1 != localyImportantFeatures1.end(); ++localIter1 ){
					double cell = mFrequencies->GetCRS()->GetCell( freqRowIdx, *localIter1 );
					if( cell <= 0.0 )
						continue;
					if( ++localyImportantPairs < ( req + 1 ) )
						continue;
					pCompute = true;
					break;
				}
			}
		}

		if( !pCompute && mutalFeaturesCounter == req ){

			//DONE: 3) lemmas mapping
			std::string const& label = m_pMatrix->GetRowFeatures()->at( pLemmaIndex1 ).GetLabel();
			size_t freqRowIdx = mFrequencies->GetRowIndex( label );
			// ther's an option that there will be no this lemma in freqencies matrix coz
			if(freqRowIdx != static_cast<size_t>(-1)){
				size_t localyImportantPairs 			= 0UL;
				std::set<size_t>::iterator localIter2 	= localyImportantFeatures2.begin();
				for(; localIter2 != localyImportantFeatures2.end(); ++localIter2 ){
					double cell = mFrequencies->GetCRS()->GetCell( freqRowIdx, *localIter2 );
					if( cell <= 0.0 )
						continue;
					if( ++localyImportantPairs < ( req + 1 ) )
						continue;
					pCompute = true;
					break;
				}
			}
		}
	}

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


	}
}


