/*
    Copyright (C) 2012 Bartosz Broda, Jacek Bochenek, Łukasz Biłeńkij, 
    Damian Jaworski, Wojciech Mazur, Dominik Piasecki, Maciej Piasecki, 
    Radosław Ramocki
    
    This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option)
any later version.

    This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. 

    See the LICENSE and COPYING files for more details.
*/

#include "../comparator_stdheaders.h"
#include "PEntP.h"


namespace smartcomparator
{
	namespace simfunctions
	{
		PEntP::PEntP(Matrices::SuperMatrixPtr m)
			: SimilarityFunction(m)
		{
		}
		PEntP::~PEntP(void)
		{
		}

		double PEntP::CountSimilarity(Matrices::CompressedVector& v1, Matrices::CompressedVector& v2,
			size_t v1ind, size_t v2ind,	const std::set<size_t> &v1Ind, const std::set<size_t> &v2Ind) 
		{
			std::set<size_t> filteredIndices;

			std::insert_iterator<std::set<size_t> > inserter(filteredIndices, filteredIndices.begin());

			std::set_intersection(v1Ind.begin(), v1Ind.end(), v2Ind.begin(), v2Ind.end(), inserter);


			double numerator = 0, denominator = 0;

			Matrices::FeatureVectorPtr column_features = m_pMatrix->GetColumnFeatures();

			bool wlazl = false;

			for(std::set<size_t>::const_iterator iter = filteredIndices.begin(); iter != filteredIndices.end();iter++)
			{
				wlazl = true;
				double v1Val = (v1)[(*iter)];
				double v2Val = (v2)[(*iter)];
				double tf_v1 = (double) (*column_features)[*iter].GetTermFrequency();
				double tf_v2 = (double) (*column_features)[*iter].GetTermFrequency();


				double P1 = 1.0 - (v1Val / tf_v1);
				double P2 = 1.0 - (v2Val / tf_v2);

				if(P1 == 0 || P2 == 0)
					continue;

				//double ent = (*column_ent)[*iter];

				numerator += log(P1*P2);///ent;		

			}

			
			for(std::set<size_t>::const_iterator iter = v2Ind.begin(); iter != v2Ind.end();iter++)
			{
				wlazl = true;
				double v2Val = (v2)[(*iter)];
				double tf_v2 = (double) (*column_features)[*iter].GetTermFrequency();

				double P2 = 1.0- (v2Val / tf_v2);

				/*double ent = (*column_ent)[*iter];
				if(ent == 0)
					continue;*/

				if(P2 == 0)
					continue;

				denominator += log(P2);///ent;		
			}


			for(std::set<size_t>::const_iterator iter = v1Ind.begin(); iter != v1Ind.end();iter++)
			{
				double v1Val = (v1)[(*iter)];
				double tf_v1 = (double) (*column_features)[*iter].GetTermFrequency();

				double P1 = 1.0- (v1Val / tf_v1);

				//double ent = (*column_ent)[*iter];

/*				if(ent == 0)
					continue;*/

				if(P1 == 0)
					continue;

				denominator += log(P1);///ent;		

				
			}

			if (denominator == 0 || numerator == 0)
			//if(denominator < 0.0000001 && denominator >= -0.0000001 )
				return 0;

			return numerator / denominator;
		}

		double PEntP::MinValue() const 
		{
			return -10000;
		}
	}// namespace simfunctions
}// namespace smartcomparator

