/*
    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 <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>

#include <test_utils/utils.h>

BOOST_AUTO_TEST_CASE(parsing)
{

}

BOOST_AUTO_TEST_CASE(sanity_check)
{
	Matrices::SuperMatrixPtr testMatrix1 = getTestMatrix();
	Matrices::SuperMatrixPtr testMatrix2 = getTestMatrix();
	matrixCompareCRS(testMatrix1,testMatrix2);
	matrixCompareCCS(testMatrix1,testMatrix2);
}

//BOOST_AUTO_TEST_CASE(MI_Lin)
//{
//	Matrices::SuperMatrixPtr testMatrix1 = Matrices::IO::LoadSuperMatrix(TEST_DATA_DIR,"landauer",false,true);
//	Matrices::SuperMatrixPtr testMatrix2 = Matrices::IO::LoadSuperMatrix(TEST_DATA_DIR,"landauer",false,true);
//	smartcomparator::weights::WeightFeaturePtr w(new smartcomparator::weights::MIWeight(testMatrix1,0));
//	matrixCompare(testMatrix1,testMatrix2);
//}

BOOST_AUTO_TEST_CASE(dice_testmatrix)
{
	Matrices::SuperMatrixPtr testMatrix = getTestMatrix();
	std::set<size_t> fullIndices = getTestIndices(testMatrix);
	smartcomparator::simfunctions::Dice diceFunction(testMatrix);

	double compar = diceFunction.CountSimilarity(*(testMatrix->GetCRS()->GetCompressedRow(0)),*(testMatrix->GetCRS()->GetCompressedRow(3)),fullIndices,fullIndices);
	//human, user - these have no common features
	BOOST_CHECK_CLOSE(0.,compar,0.000001);

	compar = diceFunction.CountSimilarity(*(testMatrix->GetCRS()->GetCompressedRow(5)),*(testMatrix->GetCRS()->GetCompressedRow(6)),fullIndices,fullIndices);
	//respones,time - these have equal feature vectors
	BOOST_CHECK_CLOSE(1.,compar,0.000001);

	compar = diceFunction.CountSimilarity(*(testMatrix->GetCRS()->GetCompressedRow(0)),*(testMatrix->GetCRS()->GetCompressedRow(1)),fullIndices,fullIndices);
	BOOST_CHECK_CLOSE(0.5,compar,0.000001);

	compar = diceFunction.CountSimilarity(*(testMatrix->GetCRS()->GetCompressedRow(3)),*(testMatrix->GetCRS()->GetCompressedRow(4)),fullIndices,fullIndices);
	BOOST_CHECK_CLOSE(0.444444444,compar,0.000001);
}

BOOST_AUTO_TEST_CASE(jaccard_testmatrix)
{
	Matrices::SuperMatrixPtr testMatrix = getTestMatrix();
	std::set<size_t> fullIndices = getTestIndices(testMatrix);
	smartcomparator::simfunctions::Jaccard JaccardFunction(testMatrix);

	double compar = JaccardFunction.CountSimilarity(*(testMatrix->GetCRS()->GetCompressedRow(0)),*(testMatrix->GetCRS()->GetCompressedRow(3)),fullIndices,fullIndices);
	//human, user - these have no common features
	BOOST_CHECK_CLOSE(0.,compar,0.000001);

	compar = JaccardFunction.CountSimilarity(*(testMatrix->GetCRS()->GetCompressedRow(5)),*(testMatrix->GetCRS()->GetCompressedRow(6)),fullIndices,fullIndices);
	//respones,time - these have equal feature vectors
	BOOST_CHECK_CLOSE(1.,compar,0.000001);

	compar = JaccardFunction.CountSimilarity(*(testMatrix->GetCRS()->GetCompressedRow(0)),*(testMatrix->GetCRS()->GetCompressedRow(1)),fullIndices,fullIndices);
	BOOST_CHECK_CLOSE(0.333333333,compar,0.000001);

	compar = JaccardFunction.CountSimilarity(*(testMatrix->GetCRS()->GetCompressedRow(3)),*(testMatrix->GetCRS()->GetCompressedRow(4)),fullIndices,fullIndices);
	BOOST_CHECK_CLOSE(0.285714286,compar,0.000001);
}

BOOST_AUTO_TEST_CASE(cosine_testmatrix)
{
	Matrices::SuperMatrixPtr testMatrix = getTestMatrix();
	std::set<size_t> fullIndices = getTestIndices(testMatrix);
	smartcomparator::simfunctions::CosineFunction cosFunction(testMatrix);

	double compar = cosFunction.CountSimilarity(*(testMatrix->GetCRS()->GetCompressedRow(0)),*(testMatrix->GetCRS()->GetCompressedRow(3)),fullIndices,fullIndices);
	//human, user - these have no common features
	BOOST_CHECK_CLOSE(0.,compar,0.000001);

	compar = cosFunction.CountSimilarity(*(testMatrix->GetCRS()->GetCompressedRow(5)),*(testMatrix->GetCRS()->GetCompressedRow(6)),fullIndices,fullIndices);
	//respones,time - these have equal feature vectors
	BOOST_CHECK_CLOSE(1.,compar,0.000001);

	compar = cosFunction.CountSimilarity(*(testMatrix->GetCRS()->GetCompressedRow(0)),*(testMatrix->GetCRS()->GetCompressedRow(1)),fullIndices,fullIndices);
	BOOST_CHECK_CLOSE(0.5,compar,0.000001);

	compar = cosFunction.CountSimilarity(*(testMatrix->GetCRS()->GetCompressedRow(3)),*(testMatrix->GetCRS()->GetCompressedRow(4)),fullIndices,fullIndices);
	BOOST_CHECK_CLOSE(0.471404521,compar,0.000001);
}



BOOST_AUTO_TEST_CASE(cosine_function_randomvector)
{
	srand(9798678);
	//Random sequence
	int N = 10000;
	std::vector<std::vector<double> > vect;
	vect.push_back(std::vector<double>());
	vect.push_back(std::vector<double>());



	for(int i=0;i<N;i++)
	{
		vect[0].push_back(((double)rand()/(double)RAND_MAX)*100);
		vect[1].push_back(((double)rand()/(double)RAND_MAX)*100);
	}
	std::set<size_t> indices0,indices1;

	for(int i=0;i<N;i++)
	{
		if((double)rand()/(double)RAND_MAX > 0.5)
		{
			vect[0][i]=0;
		}
		else
			indices0.insert(i);
	}
	double len0=0;
	double len1=0;
	double dotProd=0;
	for(int i=0;i<N;i++)
	{
		if((double)rand()/(double)RAND_MAX > 0.5)
			vect[1][i]=0;
		else
			indices1.insert(i);
		len0+=vect[0][i]*vect[0][i];
		len1+=vect[1][i]*vect[1][i];
		dotProd+=vect[0][i]*vect[1][i];
	}
	len0=sqrt(len0);
	len1=sqrt(len1);
	double cosinRes = dotProd/(len0*len1);
	Matrices::SuperMatrixPtr matrix=buildSuperMatrix(vect);
	smartcomparator::simfunctions::CosineFunction cosF(matrix);
	Matrices::CompressedVectorPtr r0 = matrix->GetCRS()->GetCompressedRow(0);
	Matrices::CompressedVectorPtr r1 = matrix->GetCRS()->GetCompressedRow(1);
	double cosFRes = 666;
	cosFRes = cosF.CountSimilarity(*r0,*r1,indices0,indices1);
	BOOST_CHECK_CLOSE(cosinRes,cosFRes,0.00001);
	matrix.reset();
	vect.clear();
	indices0.clear();
	indices1.clear();
	vect.push_back(std::vector<double>());
	vect.push_back(std::vector<double>());
	vect[0].push_back(3);
	indices0.insert(0);
	vect[0].push_back(0);
	vect[1].push_back(0);
	vect[1].push_back(4);
	indices1.insert(1);
	matrix=buildSuperMatrix(vect);
	smartcomparator::simfunctions::CosineFunction cosF2(matrix);
	cosFRes = cosF2.CountSimilarity(*(matrix->GetCRS()->GetCompressedRow(0)),*(matrix->GetCRS()->GetCompressedRow(1)),indices0,indices1);


	BOOST_CHECK_CLOSE(0,cosFRes,0.00001);
}
