/*
    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 "IntersectionScaledSimilarity.h"
namespace smartcomparator
{
	namespace simfunctions
	{
		IntersectionScaledSimilarity::IntersectionScaledSimilarity(Matrices::SuperMatrixPtr m, SimilarityFunctionPtr pSimInner, bool cVals)
				: SimilarityFunction(m),
				m_pSimilarity(pSimInner)

		{
			countVals = cVals;
		}

		IntersectionScaledSimilarity::~IntersectionScaledSimilarity()
		{
		}


		bool IntersectionScaledSimilarity::IsSymmetrical() const
		{
			return m_pSimilarity->IsSymmetrical();
		}

		double IntersectionScaledSimilarity::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)
		{
			double single_sum = std::max(CountSum(v1Ind, v1), CountSum(v2Ind, v2));
			double common_sum = CountIntersectionSum(v1Ind, v2Ind, v1, v2);

			return m_pSimilarity->CountSimilarity(v1, v2, v1ind, v2ind, v1Ind, v2Ind) * (single_sum/common_sum);
		}

		double IntersectionScaledSimilarity::CountSum(const std::set<size_t> &ind, const Matrices::CompressedVector& v)

		{
			double res = 0;
			if (countVals)
			{
				for (std::set<size_t>::iterator it = ind.begin(); it != ind.end(); ++it)
				{
					res += v[*it];
				}
				return res;
			}
			else
			{
				return ind.size();
			}

		}


		double IntersectionScaledSimilarity::CountIntersectionSum(const std::set<size_t> &ind1, const std::set<size_t> &ind2,
									  const Matrices::CompressedVector& v1, const Matrices::CompressedVector& v2)
		{
			double res = 0;
			for (std::set<size_t>::iterator it = ind1.begin(); it != ind1.end(); ++it)
			{
				if (ind2.find(*it) != ind2.end())
				{
					if(countVals)
					{
						res += std::max(v1[*it],v2[*it]);
					}
					else
					{
						res++;
					}
				}
			}
			return res;
		}

		double IntersectionScaledSimilarity::MinValue() const
		{
			return m_pSimilarity->MinValue();
		}
	}//namespace simfunctions



}//namespace smartcomparator
