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

namespace smartcomparator
{
	namespace simfunctions
	{
		LocalIRad::LocalIRad(double beta)
			: m_pWeight(NULL),
			m_dBeta(beta)
		{
			
		}
		LocalIRad::LocalIRad(weights::LocalWeightFeature *pweight, double beta)
			: m_pWeight(pweight),
			m_dBeta(beta)
		{

		}

		LocalIRad::~LocalIRad()
		{

		}

		inline static double h(double x)
		{
			return -x * log(x);
		}

		double LocalIRad::CountSimilarity(Matrices::CompressedVector& v1,
			Matrices::CompressedVector& v2,
			std::set<size_t> &v1Ind, std::set<size_t> &v2Ind)
		{
			if (m_pWeight)
			{
				m_pWeight->Weight(&v1, v1Ind);
				m_pWeight->Weight(&v2, v2Ind);
			}


			std::set<size_t> intersection;

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

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

			
			double sum = 0;
			for (std::set<size_t>::iterator w = intersection.begin(); 
				w != intersection.end();w++)
			{
				double pw = v1[*w];
				double pwPrime = v2[*w];
				sum += h(pw+pwPrime) - h(pw) - h(pwPrime);

			}

			double J = log(2.0) + 0.5 * sum;


			return pow(10.0, -m_dBeta* J);
		}

		double LocalIRad::CountSimilarity(Matrices::CompressedVector& v1, 
			Matrices::CompressedVector& v2)
		{
			std::set<size_t> v1ind, v2ind;
			for (std::map<size_t, double>::iterator i = v1.GetValues()->begin();
				i != v1.GetValues()->end(); i++)
				v1ind.insert(i->first);

			for (std::map<size_t, double>::iterator i = v2.GetValues()->begin();
				i != v2.GetValues()->end(); i++)
				v2ind.insert(i->first);

			return CountSimilarity(v1,v2,v1ind, v2ind);
		}


	}
}
