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

static log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("SuperMatrix.comparator.weights.RWFZScore"));

namespace smartcomparator
{
	namespace weights
	{
		RWFZScore::RWFZScore(Matrices::SuperMatrixPtr m, RankBuilderPtr pRankBuilder, double treshold) 
			: RWFBase(m, pRankBuilder ),
			m_dTreshold(treshold)
		{
			W = (double) m_pMatrix->GetTokenCount();

			if(W <= 0 )
			{
				W = 254524624.;
				LOG4CXX_ERROR(logger, "Matrix does not contain information about number of tokens in corpus... Using "
							  << W << " as this value (number of tokens in KIPI 2.0");
			}
		}

		RWFZScore::~RWFZScore(void)
		{
		}

		void RWFZScore::DoWeight(size_t rowIndex, Matrices::CompressedVector *v,	std::set<size_t> &filteredIndices, 
				std::multimap<double,size_t> &val_to_co_no) 
		{	
			double TFn = (double) m_pMatrix->GetRowFeatures()->operator[](rowIndex).GetGlobalTermFrequency();

			for(std::set<size_t>::const_iterator i = filteredIndices.begin(); i != filteredIndices.end(); i++)
			{
				double Cnc = (*v)[*i];
				if(Cnc == 0) 
					continue;
				double col_global_tf_i = (*m_pMatrix->GetColumnFeatures())[*i].GetGlobalTermFrequency();
				double part = (TFn* col_global_tf_i) / W;

				double Rz = (Cnc - part) / sqrt(part);

				if(Rz > m_dTreshold)
					val_to_co_no.insert(std::pair<double,size_t>(Rz,*i));
			}

		}//DoWeight

		/////////////////////// RWFZScoreInMatrixWeight ///////////////////////////

		RWFZScoreInMatrixWeight::RWFZScoreInMatrixWeight(Matrices::SuperMatrixPtr m, RankBuilderPtr pRankBuilder, double treshold) 
			: RWFBase(m, pRankBuilder ),
			m_dMinRz(treshold)
		{
			CountMatrixSum();
		}

		RWFZScoreInMatrixWeight::~RWFZScoreInMatrixWeight(void)
		{
		}

		void RWFZScoreInMatrixWeight::CountMatrixSum()
		{
			size_t sum_tf = 0;
			for(size_t row_no = 0; row_no < m_pMatrix->NumberOfRows(); row_no++)
				sum_tf += m_pMatrix->GetRowFeatures()->operator[](row_no).GetTermFrequency();
			m_dMatrixSum = (double) sum_tf;
		}

		void RWFZScoreInMatrixWeight::DoWeight(size_t row_no, Matrices::CompressedVector *v, std::set<size_t> &filteredIndices, 
				std::multimap<double,size_t> &val_to_col_no) 
		{	
			double row_tf = (double) m_pMatrix->GetRowFeatures()->operator[](row_no).GetGlobalTermFrequency();
			const Matrices::CompressedVectorPtr row = m_pMatrix->GetCRS()->GetCompressedRow(row_no);

			for(std::set<size_t>::const_iterator i = filteredIndices.begin(); i != filteredIndices.end(); i++)
			{
				double Cnc = (*row)[*i];
				if(Cnc == 0) 
					continue;
				double column_i_tf = (*m_pMatrix->GetColumnFeatures())[*i].GetTermFrequency();
				double part = (row_tf* column_i_tf) ;// / m_dMatrixSum;
				double rz = (Cnc - part) / sqrt(part);

				if(rz > m_dMinRz)
					val_to_col_no.insert(std::pair<double,size_t>(rz,*i));
			}
		}//DoWeight
		//
		///////////////////////// RWFLocalZScoreWeight ///////////////////////////

		RWFLocalZScoreWeight::RWFLocalZScoreWeight(Matrices::SuperMatrixPtr m, RankBuilderPtr pRankBuilder, double treshold ) 
			: RWFBase(m, pRankBuilder),
			m_dMinRz(treshold)
		{
		}

		RWFLocalZScoreWeight::~RWFLocalZScoreWeight(void)
		{
		}

		void RWFLocalZScoreWeight::DoWeight(size_t rowIndex, Matrices::CompressedVector *v, std::set<size_t> &filteredIndices, 
				std::multimap<double, size_t> &val_to_col_no) 
		{	
			double cn_X = (double) m_pMatrix->GetRowFeatures()->operator[](rowIndex).GetTermFrequency();
			const Matrices::CompressedVectorPtr row = m_pMatrix->GetCRS()->GetCompressedRow(rowIndex);

			for(std::set<size_t>::const_iterator i = filteredIndices.begin(); i != filteredIndices.end(); i++)
			{
				double Cnc = (*row)[*i];
				if(Cnc == 0) 
					continue;
				double cX_n = (*m_pMatrix->GetColumnFeatures())[*i].GetTermFrequency();
				double part = ( cn_X * cX_n ) / (cn_X + cX_n);

				double rz = (Cnc - part) / sqrt(part);

				if(rz > m_dMinRz)
					val_to_col_no.insert(std::pair<double,size_t>(rz,*i));
			}
		}
	}
}

