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

namespace smartcomparator
{
	namespace weights
	{
		CRmDmi::CRmDmi(Matrices::SuperMatrixPtr m) : WeightFeature(m)
		{
			Matrices::FeatureVectorPtr colfeatures = m_pMatrix->GetColumnFeatures();
			for(Matrices::FeatureVector::iterator i = colfeatures->begin(); i != colfeatures->end(); i++  )
				sum_tf_ci += i->GetTermFrequency();
			N = 0;				
			for(Matrices::FeatureVector::iterator i = m_pMatrix->GetRowFeatures()->begin(); 
				i != m_pMatrix->GetRowFeatures()->end(); i++)
				N += i->GetGlobalTermFrequency();
		}

		CRmDmi::~CRmDmi(void)
		{
		}

		void CRmDmi::Weight(size_t rowindex, Matrices::CompressedVector *v, std::set<size_t> &filteredIndices) 
		{
			std::set<size_t> toRemove;
			Matrices::FeatureVectorPtr column_features = m_pMatrix->GetColumnFeatures();
			Matrices::FeatureVectorPtr row_features = m_pMatrix->GetRowFeatures();
			double TFn = (double) (* row_features)[rowindex].GetGlobalTermFrequency();
			double Pn = TFn / (double) N;

			for(std::set<size_t>::iterator i = filteredIndices.begin(); i != filteredIndices.end(); i++)
			{
				double Cnc = (*v)[*i];
				if(Cnc == 0 )
				{
					toRemove.insert(*i);
					continue;
				}

				double Pnc = Cnc/(double)N;

				double tf_c = (double) (*column_features)[*i].GetTermFrequency();
				double Pc = tf_c / sum_tf_ci;

				double toLog = (Pnc) / (Pc*Pn);


				double Dmi = log ( toLog );

				if(  Dmi <= 0)
				{
					toRemove.insert(*i);
					continue;
				}
				else
					v->SetElement(*i, Dmi);


			}

			for(std::set<size_t>::iterator i = toRemove.begin(); i != toRemove.end(); i++)
				filteredIndices.erase( *i );


		}
	}
}
