/*
    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 "LinSimilarity.h"

namespace smartcomparator
{

	namespace simfunctions
	{

		LinSimilarity::LinSimilarity (Matrices::SuperMatrixPtr m)
				: SimilarityFunction ( m )
		{
			std::map<size_t, std::string> boundaries = m_pMatrix->Boundaries();
			for(std::map<size_t, std::string>::iterator iter = boundaries.begin(); iter != boundaries.end(); ++iter)
				m_vOperatorIndices.push_back( iter->first );
		}

		double LinSimilarity::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> intersection;

			std::set_intersection(v1Ind.begin(), v1Ind.end(), v2Ind.begin(), v2Ind.end(),
				std::insert_iterator< std::set<size_t> >(intersection, intersection.begin()));

			// T_{w} = number of pairs (r, w') where I > 0.
			// I is the amount of infotmation in || w, r, w' || = c
			// Matrix should be transformed by LinSMeasure, so that every cell contains I
			// numerator = \sum_{pairs \in T_{w1} \intersection T_{w2}} (I_{w_1, pair} + I{w_2, pair} )
			// aDenominator = \sum_{pairs \in T_{w1}} I(w1, pair)
			// bDenominator = \sum_{pairs \in T_{w2}} I(w2, pair)

			double numerator = 0, aDenominator = 0, bDenominator = 0;

			for( std::set<size_t>::iterator index = intersection.begin();
				index != intersection.end() ; ++index )
			{
				double I_w1 = v1[*index];
				double I_w2 = v2[*index];

				if(I_w1 > 0 && I_w2 > 0)
					numerator += I_w1 + I_w2;
			}
			for( std::set<size_t>::iterator index = v1Ind.begin();	index != v1Ind.end() ; ++index )
			{
				double I_w1 = v1[*index];
				if(I_w1 > 0)
					aDenominator += I_w1;
			}

			for( std::set<size_t>::iterator index = v1Ind.begin();	index != v1Ind.end() ; ++index )
			{
				double I_w2 = v2[*index];
				if(I_w2 > 0)
					bDenominator += I_w2;
			}

			if (aDenominator + bDenominator == 0)
			{
				return 0;
			}

			return numerator / (aDenominator+bDenominator);
		}

		double LinSimilarity::MinValue() const
		{
			return 0;
		}
	}

}
