diff --git a/src/helper_files/helper.cpp b/src/helper_files/helper.cpp index 2321d2e4fe610eac4e3e1f8fdb5db6cc6919a91a..05b47f5c46d2a981a617b0bf739bdd89d9efa8e3 100644 --- a/src/helper_files/helper.cpp +++ b/src/helper_files/helper.cpp @@ -33,6 +33,21 @@ float *convertToArray(mat matrix) return convertToArray(vector); } +float *convertToArray(arma::Mat< unsigned long > matrix) +{ + int vectorSize = matrix.size(); + + // using malloc so the memory is still valid outside of the function + float *arr = (float *)malloc (sizeof(float) * vectorSize); + + // save the data in a normal array so it can be send to prolog + for(int i = 0; i < vectorSize; i++) + { + arr[i] = (double)matrix[i]; + } + return arr; +} + float *convertToArray(vector<size_t> vec) { colvec newVec = conv_to<colvec>::from(vec); @@ -62,7 +77,6 @@ float *convertToArray(vector<vec> matrix) vec c = arma::join_cols(a, b); newVec = c; } - cout << newVec << endl; return convertToArray(newVec); } diff --git a/src/helper_files/helper.hpp b/src/helper_files/helper.hpp index 2900ca5d2618a4e24b44195b7ae0c0d6bfbe99f1..15dee9381356ed95961cd303c656f2e7db6c061e 100644 --- a/src/helper_files/helper.hpp +++ b/src/helper_files/helper.hpp @@ -13,6 +13,8 @@ float *convertToArray(rowvec vec); float *convertToArray(mat matrix); +float *convertToArray(arma::Mat< size_t > matrix); + float *convertToArray(vector<size_t> vec); float *convertToArray(vector<double> vec); diff --git a/src/methods/fastmks/fastmks.cpp b/src/methods/fastmks/fastmks.cpp index 7240f26019c06c61cbdf650420b6ab09a8c1d24a..2137686dd17a9dc2e4407bc453e1e26bfe1d15ea 100644 --- a/src/methods/fastmks/fastmks.cpp +++ b/src/methods/fastmks/fastmks.cpp @@ -18,8 +18,9 @@ using namespace mlpack::kernel; // Global Variable of the FastMKSModel object so it can be accessed from all functions FastMKSModel fastMKSModel; +bool isModelTrained = false; + -// TODO: // input: util::Timers & timers, // arma::mat && referenceData, // TKernelType & kernel, @@ -32,9 +33,16 @@ FastMKSModel fastMKSModel; // const double base // output: // description: -void initModel(float *referenceMatArr, SP_integer referenceMatSize, SP_integer referenceMatRowNum, char const *kernel, double degree, double offset, double bandwidth, double scale, SP_integer singleMode, SP_integer naive, double base) +// Initializes the model on the given reference set. +// +void initModel(float *referenceMatArr, SP_integer referenceMatSize, SP_integer referenceMatRowNum, + char const *kernel, + double degree, double offset, double bandwidth, double scale, + SP_integer singleMode, + SP_integer naive, + double base) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat reference = convertArrayToMat(referenceMatArr, referenceMatSize, referenceMatRowNum); if (strcmp(kernel, "linear") == 0) @@ -42,46 +50,59 @@ void initModel(float *referenceMatArr, SP_integer referenceMatSize, SP_integer r fastMKSModel = FastMKSModel(0); LinearKernel lk; fastMKSModel.BuildModel(move(reference), lk, (singleMode == 1), (naive == 1), base); + isModelTrained = true; } else if (strcmp(kernel, "polynomial") == 0) { PolynomialKernel pk(degree, offset); fastMKSModel.KernelType() = FastMKSModel::POLYNOMIAL_KERNEL; fastMKSModel.BuildModel(move(reference), pk, (singleMode == 1), (naive == 1), base); + isModelTrained = true; } else if (strcmp(kernel, "cosine") == 0) { CosineDistance cd; fastMKSModel.KernelType() = FastMKSModel::COSINE_DISTANCE; fastMKSModel.BuildModel(move(reference), cd, (singleMode == 1), (naive == 1), base); + isModelTrained = true; } else if (strcmp(kernel, "gaussian") == 0) { GaussianKernel gk(bandwidth); fastMKSModel.KernelType() = FastMKSModel::GAUSSIAN_KERNEL; fastMKSModel.BuildModel(move(reference), gk, (singleMode == 1), (naive == 1), base); + isModelTrained = true; } else if (strcmp(kernel, "epanechnikov") == 0) { EpanechnikovKernel ek(bandwidth); fastMKSModel.KernelType() = FastMKSModel::EPANECHNIKOV_KERNEL; fastMKSModel.BuildModel(move(reference), ek, (singleMode == 1), (naive == 1), base); + isModelTrained = true; } else if (strcmp(kernel, "triangular") == 0) { TriangularKernel tk(bandwidth); fastMKSModel.KernelType() = FastMKSModel::TRIANGULAR_KERNEL; fastMKSModel.BuildModel(move(reference), tk, (singleMode == 1), (naive == 1), base); + isModelTrained = true; } else if (strcmp(kernel, "hyptan") == 0) { + HyperbolicTangentKernel htk(scale, offset); fastMKSModel.KernelType() = FastMKSModel::HYPTAN_KERNEL; fastMKSModel.BuildModel(move(reference), htk, (singleMode == 1), (naive == 1), base); + isModelTrained = true; + } + else + { + raisePrologDomainExeption(kernel, 2, "The given kernel is unkown!", "initModel"); } + } -// TODO: + // input: util::Timers & timers, // const arma::mat & querySet, // const size_t k, @@ -90,62 +111,77 @@ void initModel(float *referenceMatArr, SP_integer referenceMatSize, SP_integer r // const double base // output: // description: -void searchWithQuery(float *querySetMatArr, SP_integer querySetMatSize, SP_integer querySetMatRowNum, SP_integer k, float **indicesMatArr, SP_integer *indicesMatColNum, SP_integer *indicesMatRowNum, float **kernelsMatArr, SP_integer *kernelsMatColNum, SP_integer *kernelsMatRowNum, double base) +// Search with a different query set. +// +void searchWithQuery(float *querySetMatArr, SP_integer querySetMatSize, SP_integer querySetMatRowNum, + SP_integer k, + float **indicesMatArr, SP_integer *indicesMatColNum, SP_integer *indicesMatRowNum, + float **kernelsMatArr, SP_integer *kernelsMatColNum, SP_integer *kernelsMatRowNum, + double base) { - // convert the Prolog arrays to arma::mat + if (!isModelTrained) + { + raisePrologSystemExeption("The Model hasnt been trained yet!"); + return; + } + + // convert the Prolog array to arma::mat mat querySet = convertArrayToMat(querySetMatArr, querySetMatSize, querySetMatRowNum); - // create the ReturnMat + // create the ReturnMats arma::Mat< size_t > indicesReturnMat; - - // create the ReturnMat mat kernelsReturnMat; - fastMKSModel.Search(querySet, k, indicesReturnMat, kernelsReturnMat, base); - - // return the Matrix dimensions - *indicesMatColNum = indicesReturnMat.n_cols; - *indicesMatRowNum = indicesReturnMat.n_rows; - // return the Matrix as one long Array - *indicesMatArr = convertToArray(indicesReturnMat); - - // return the Matrix dimensions - *kernelsMatColNum = kernelsReturnMat.n_cols; - *kernelsMatRowNum = kernelsReturnMat.n_rows; + try + { + fastMKSModel.Search(querySet, k, indicesReturnMat, kernelsReturnMat, base); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + } + - // return the Matrix as one long Array - *kernelsMatArr = convertToArray(kernelsReturnMat); + // return the Matrices + returnMatrixInformation(indicesReturnMat, indicesMatArr, indicesMatColNum, indicesMatRowNum); + returnMatrixInformation(kernelsReturnMat, kernelsMatArr, kernelsMatColNum, kernelsMatRowNum); } -// TODO: + // input: util::Timers & timers, // const size_t k, // arma::Mat< size_t > & indices <-, // arma::mat & kernels <- // output: // description: -void searchNoQuery(SP_integer k, float **indicesMatArr, SP_integer *indicesMatColNum, SP_integer *indicesMatRowNum, float **kernelsMatArr, SP_integer *kernelsMatColNum, SP_integer *kernelsMatRowNum) +// Search with the reference set as the query set. +// +void searchNoQuery(SP_integer k, + float **indicesMatArr, SP_integer *indicesMatColNum, SP_integer *indicesMatRowNum, + float **kernelsMatArr, SP_integer *kernelsMatColNum, SP_integer *kernelsMatRowNum) { - // create the ReturnMat + if (!isModelTrained) + { + raisePrologSystemExeption("The Model hasnt been trained yet!"); + return; + } + // create the ReturnMats arma::Mat< size_t > indicesReturnMat; - - // create the ReturnMat - mat kernelsReturnMat; - - fastMKSModel.Search(k, indicesReturnMat, kernelsReturnMat); - - // return the Matrix dimensions - *indicesMatColNum = indicesReturnMat.n_cols; - *indicesMatRowNum = indicesReturnMat.n_rows; + arma::mat kernelsReturnMat; - // return the Matrix as one long Array - *indicesMatArr = convertToArray(indicesReturnMat); - // return the Matrix dimensions - *kernelsMatColNum = kernelsReturnMat.n_cols; - *kernelsMatRowNum = kernelsReturnMat.n_rows; - - // return the Matrix as one long Array - *kernelsMatArr = convertToArray(kernelsReturnMat); + try + { + fastMKSModel.Search((size_t)k, indicesReturnMat, kernelsReturnMat); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } + + + returnMatrixInformation(indicesReturnMat, indicesMatArr, indicesMatColNum, indicesMatRowNum); + returnMatrixInformation(kernelsReturnMat, kernelsMatArr, kernelsMatColNum, kernelsMatRowNum); } diff --git a/src/methods/fastmks/fastmks.pl b/src/methods/fastmks/fastmks.pl index 134fcaaddfe6fbe7bacb74f0134c387bb7569896..70cde77fa4bedf41fc59edb1cb6eaf6e7be9f8d8 100644 --- a/src/methods/fastmks/fastmks.pl +++ b/src/methods/fastmks/fastmks.pl @@ -1,7 +1,7 @@ -:- module(fastmks, [ initModel/11, - searchWithQuery/11, - searchNoQuery/7]). +:- module(fastmks, [ initModel/10, + searchWithQuery/8, + searchNoQuery/5]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -19,6 +19,11 @@ %% definitions for the connected function +foreign(initModel, c, initModelI( +pointer(float_array), +integer, +integer, + +string, + +float32, +float32, +float32, +float32, + +integer, +integer, + +float32)). %% --Input-- %% mat referenceData, %% string kernel "linear", "polynomial", "cosine", "gaussian", "epanechnikov", "triangular", "hyptan" @@ -35,13 +40,19 @@ %% --Description-- %% Initializes the model on the given reference set. %% -foreign(initModel, c, initModel(+pointer(float_array), +integer, +integer, - +string, - +float32, +float32, +float32, +float32, - +integer, +integer, - +float32)). +initModel(DataList, DataRows, Kernel, Degree, Offset, Bandwidth, Scale, SingleMode, Naive, Base) :- + Base > 1.0, + Bandwidth > 0.0, + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrows, X)), + initModelI(X, Xsize, Xrows, Kernel, Degree, Offset, Bandwidth, Scale, SingleMode, Naive, Base). + +foreign(searchWithQuery, c, searchWithQueryI( +pointer(float_array), +integer, +integer, + +integer, + -pointer(float_array), -integer, -integer, + -pointer(float_array), -integer, -integer, + +float32)). %% --Input-- %% mat querySet, %% int k, @@ -54,13 +65,19 @@ foreign(initModel, c, initModel(+pointer(float_array), +integer, +integer, %% --Description-- %% Search with a different query set. %% -foreign(searchWithQuery, c, searchWithQuery( +pointer(float_array), +integer, +integer, - +integer, - -pointer(float_array), -integer, -integer, - -pointer(float_array), -integer, -integer, - +float32)). +searchWithQuery(DataList, DataRows, K, IndicesList, YCols, KernelsList, ZCols, Base) :- + K > 0, + Base > 1.0, + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrows, X)), + searchWithQueryI(X, Xsize, Xrows, K, Y, YCols, YRows, Z, ZCols, ZRows, Base), + convert_float_array_to_2d_list(Y, YCols, YRows, IndicesList), + convert_float_array_to_2d_list(Z, ZCols, ZRows, KernelsList). + +foreign(searchNoQuery, c, searchNoQueryI( +integer, + -pointer(float_array), -integer, -integer, + -pointer(float_array), -integer, -integer)). %% --Input-- %% int k %% @@ -71,9 +88,11 @@ foreign(searchWithQuery, c, searchWithQuery( +pointer(float_array), +integer, %% --Description-- %% Search with the reference set as the query set. %% -foreign(searchNoQuery, c, searchNoQuery(+integer, - -pointer(float_array), -integer, -integer, - -pointer(float_array), -integer, -integer)). +searchNoQuery(K, IndicesList, YCols, KernelsList, ZCols) :- + K > 0, + searchNoQueryI(K, Y, YCols, YRows, Z, ZCols, ZRows), + convert_float_array_to_2d_list(Y, YCols, YRows, IndicesList), + convert_float_array_to_2d_list(Z, ZCols, ZRows, KernelsList). %% Defines the functions that get connected from main.cpp @@ -81,4 +100,5 @@ foreign_resource(fastmks, [ initModel, searchWithQuery, searchNoQuery]). + :- load_foreign_resource(fastmks). diff --git a/src/methods/fastmks/fastmks_test.pl b/src/methods/fastmks/fastmks_test.pl index b33843d3fc0f4ac3c1171762a9ce01567ec375db..1ba17d322316918212569df26e4022412fbd7596 100644 --- a/src/methods/fastmks/fastmks_test.pl +++ b/src/methods/fastmks/fastmks_test.pl @@ -1,56 +1,154 @@ + +:- module(fastmks_tests, [run_fastmks_tests/0]). + :- use_module(library(plunit)). :- use_module(fastmks). :- use_module('../../helper_files/helper.pl'). reset_Model :- - initModel(1,0,50,0.0001). + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,10, Data), + initModel(Data, 4, linear, 0.0, 0.0, 1.0, 0.0, 0, 0, 1.2). -:- begin_tests(lists). -%% alpha tests -test(alpha_std_init) :- - reset_Model, - alpha(0). -test(alpha_wrong_input, fail) :- - reset_Model, - alpha(1). -test(alpha_after_train, A =:= 9223372036854775808) :- +%% +%% TESTING predicate initModel/10 +%% +:- begin_tests(initModel). + +%% Failure Tests + +test(searchWithQuery_Fastmks_Search_Before_Init, [error(_,system_error('The Model hasnt been trained yet!'))]) :- + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,5, Data), + searchWithQuery(Data, 4, 2, _, _, _, _, 1.1). + +test(searchNoQuery_Fastmks_Search_Before_Init, [error(_,system_error('The Model hasnt been trained yet!'))]) :- + searchNoQuery(2, _, _, _, _). + +test(initModel_Fatsmks_WrongKernel_Input, [error(domain_error('The given kernel is unkown!' , wrongKernel), _)]) :- + initModel([5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 3, wrongKernel, 0.0, 0.0, 1.0, 0.0, 0, 0, 1.2). + +test(initModel_Fatsmks_Bad_Base_Input, fail) :- + initModel([5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 3, linear, 0.0, 0.0, 1.0, 0.0, 0, 0, -0.1). + + +%% Successful Tests + +test(iniModel_Fastmks_Linear) :- + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,10, Data), + initModel(Data, 4, linear, 0.0, 0.0, 1.0, 0.0, 0, 0, 1.5). + +test(iniModel_Fastmks_Polynomial) :- + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,10, Data), + initModel(Data, 4, polynomial, 0.0, 0.0, 1.0, 0.0, 0, 0, 1.5). + +test(iniModel_Fastmks_Cosine) :- + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,10, Data), + initModel(Data, 4, cosine, 0.0, 0.0, 1.0, 0.0, 0, 0, 1.5). + +test(iniModel_Fastmks_Gaussian) :- + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,10, Data), + initModel(Data, 4, gaussian, 0.5, 0.5, 0.5, 0.5, 0, 0, 1.5). + +test(iniModel_Fastmks_Epanechnikov) :- + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,10, Data), + initModel(Data, 4, epanechnikov, 0.0, 0.0, 1.0, 0.0, 0, 0, 1.5). + +test(iniModel_Fastmks_Triangular) :- + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,10, Data), + initModel(Data, 4, triangular, 0.0, 0.0, 1.0, 0.0, 0, 0, 1.5). + +test(iniModel_Fastmks_Hyptan) :- + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,10, Data), + initModel(Data, 4, hyptan, 0.0, 0.0, 1.0, 1.0, 0, 0, 1.5). + +:- end_tests(initModel). + + +%% +%% TESTING predicate searchWithQuery/8 +%% +:- begin_tests(searchWithQuery). + +%% Failure Tests + +test(searchWithQuery_Fastmks_Negative_K, fail) :- reset_Model, - convert_list_to_float_array([5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5],3, array(Xsize, Xrownum, X)), - convert_list_to_float_array([0.2,0.2,0.2,0.2], array(Ysize, Y)), - train(X,Xsize, Xrownum,Y, Ysize), - alpha(A). + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,5, Data), + searchWithQuery(Data, 4, -2, _, _, _, _, 1.1). -%% train tests -test(correct_train) :- +test(searchWithQuery_Fastmks_Negative_Base, fail) :- reset_Model, - convert_list_to_float_array([5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5],3, array(Xsize, Xrownum, X)), - convert_list_to_float_array([0.2,0.2,0.2,0.2], array(Ysize, Y)), - train(X,Xsize, Xrownum,Y, Ysize). -test(false_train, fail) :- + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,5, Data), + searchWithQuery(Data, 4, 2, _, _, _, _, -1.1). + + +%% Successful Tests + +test(searchWithQuery_Fastmks_New_Query) :- reset_Model, - convert_list_to_float_array([],3, array(Xsize, Xrownum, X)), - convert_list_to_float_array([0.2,0.2,0.2,0.2], array(Ysize, Y)), - train(X,Xsize, Xrownum,Y, Ysize). -test(false_train2, fail) :- + searchWithQuery([3, 2, 0, 5, 1, 4, 0, 0, 4, 3, 3, 5, 0, 5, 5, 2, 5, 5, 0, 2], 4, 2, IndicesList, _, KernelsList, _, 1.1), + print('Indices:\n'), + print(IndicesList), + print('Kernels:\n'), + print(KernelsList). + +test(searchWithQuery_Fastmks_Training_Data_Query) :- reset_Model, - convert_list_to_float_array([],0, array(Xsize, Xrownum, X)), - convert_list_to_float_array([0.2,0.2,0.2,0.2], array(Ysize, Y)), - train(X,Xsize, Xrownum,Y, Ysize). -test(false_train3, fail) :- + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,5, Data), + searchWithQuery(Data, 4, 2, IndicesList, _, KernelsList, _, 1.1), + print('Indices:\n'), + print(IndicesList), + print('Kernels:\n'), + print(KernelsList). + +:- end_tests(searchWithQuery). + + +%% +%% TESTING predicate searchNoQuery/5 +%% +:- begin_tests(searchNoQuery). + +%% Failure Tests + +test(searchNoQuery_Fastmks_Negative_K, fail) :- reset_Model, - convert_list_to_float_array([1,2],0, array(Xsize, Xrownum, X)), - convert_list_to_float_array([0.2,0.2,0.2,0.2], array(Ysize, Y)), - train(X,Xsize, Xrownum,Y, Ysize). -test(false_train3, fail) :- + searchNoQuery(-2, _, _, _, _). + + +%% Successful Tests + +test(testDescription) :- reset_Model, - convert_list_to_float_array([1,2,44,3],3, array(Xsize, Xrownum, X)), - convert_list_to_float_array([0.2,0.2,0.2,0.2], array(Ysize, Y)), - train(X,Xsize, Xrownum,Y, Ysize). -test(false_train4) :- + searchNoQuery(2, IndicesList, _, KernelsList, _), + print('Indices:\n'), + print(IndicesList), + print('Kernels:\n'), + print(KernelsList). + +test(testDescription) :- reset_Model, - convert_list_to_float_array([1,2,44,3],2, array(Xsize, Xrownum, X)), - convert_list_to_float_array([0.2,0.2,0.2,0.2], array(Ysize, Y)), - train(X,Xsize, Xrownum,Y, Ysize). -:- end_tests(lists). \ No newline at end of file + searchNoQuery(5, IndicesList, _, KernelsList, _), + print('Indices:\n'), + print(IndicesList), + print('Kernels:\n'), + print(KernelsList). + +:- end_tests(searchNoQuery). + +run_fastmks_tests :- + run_tests. + diff --git a/test_all.pl b/test_all.pl index e4fe222b3433d0cb3513a86ce1a0826d30c888a7..749d0c92d1249e5a03f5388ece6608b30108fefd 100644 --- a/test_all.pl +++ b/test_all.pl @@ -6,6 +6,10 @@ :- use_module('src/methods/decision_tree/decision_tree_test.pl'). +:- use_module('src/methods/emst/emst_test.pl'). + +:- use_module('src/methods/fastmks/fastmks_test.pl'). + :- use_module('src/methods/sparse_coding/sparse_coding_test.pl'). :- use_module('src/helper_files/helper_tests.pl'). @@ -14,5 +18,7 @@ run :- run_adaboost_tests, run_dbscan_tests, run_decision_tree_tests, + run_emst_tests, + run_fastmks_tests, run_sparse_coding_tests, run_helper_tests. \ No newline at end of file