From e45dce569a96a9ccc68f1f2c6b623a9101de5c2f Mon Sep 17 00:00:00 2001
From: Jakhes <dean.schmitz@schmitzbauer.de>
Date: Tue, 25 Oct 2022 13:56:40 +0200
Subject: [PATCH] Adding approx_kfn tests

---
 src/methods/approx_kfn/approx_kfn.cpp     | 175 +++++++++----
 src/methods/approx_kfn/approx_kfn.pl      |  84 +++++--
 src/methods/approx_kfn/approx_kfn_test.pl | 294 ++++++++++++++++++++--
 test_all.pl                               |   2 +-
 4 files changed, 472 insertions(+), 83 deletions(-)

diff --git a/src/methods/approx_kfn/approx_kfn.cpp b/src/methods/approx_kfn/approx_kfn.cpp
index cc77858..5a11190 100644
--- a/src/methods/approx_kfn/approx_kfn.cpp
+++ b/src/methods/approx_kfn/approx_kfn.cpp
@@ -18,160 +18,241 @@ using namespace mlpack::neighbor;
 
 // Global Variable of the DrusillaSelect object so it can be accessed from all functions
 DrusillaSelect<mat> drusillaSelect = DrusillaSelect(1,1);
+bool isDrusillaTrained = false;
 
 // Global Variable of the QDAFN object so it can be accessed from all functions
 QDAFN<mat> qdafn = QDAFN(1,1);
+bool isQDAFNTrained = false;
+
 
-// TODO: 
 // input:   const size_t 	l,
 //          const size_t 	m
 // output: 
 // description: 
+//          Initiates the DrusillaSearch Model but doesnt train it.
+//
 void initDrusillaModelNoTrain(SP_integer l, SP_integer m)
 {
     drusillaSelect = DrusillaSelect(l, m);
+    isDrusillaTrained = false;
 }
 
-// TODO: 
+
 // input:   const MatType & 	referenceSet,
 //          const size_t 	    l,
 //          const size_t 	    m
 // output: 
 // description: 
-void initDrusillaModelWithTrain(float *referenceSetMatArr, SP_integer referenceSetMatSize, SP_integer referenceSetMatRowNum, SP_integer l, SP_integer m)
+//          Initiates the DrusillaSearch Model and trains it with the given reference Set.
+//
+void initDrusillaModelWithTrain(float *referenceSetMatArr, SP_integer referenceSetMatSize, SP_integer referenceSetMatRowNum, 
+                                SP_integer l, SP_integer m)
 {
     // convert the Prolog arrays to arma::mat
     mat referenceSet = convertArrayToMat(referenceSetMatArr, referenceSetMatSize, referenceSetMatRowNum);
     
-    drusillaSelect = DrusillaSelect(referenceSet, l, m);
+    
+    try
+    {
+        drusillaSelect = DrusillaSelect(referenceSet, l, m);
+    }
+    catch(const std::exception& e)
+    {
+        raisePrologSystemExeption(e.what());
+        return;
+    }
+    isDrusillaTrained = true;
 }
 
-// TODO: 
+
 // input:   const MatType & 	    querySet,
 //          const size_t 	        k,
 //          arma::Mat< size_t > & 	neighbors,
 //          arma::mat & 	        distances
 // output: 
 // description: 
+//          Run Search on the given Queryset with the Drusilla Search Policy.
+//
 void searchDrusilla(float *querySetMatArr, SP_integer querySetMatSize, SP_integer querySetMatRowNum, 
                     SP_integer k,
                     float **neighborsMatArr, SP_integer *neighborsMatColNum, SP_integer *neighborsMatRowNum, 
                     float **distancesMatArr, SP_integer *distancesMatColNum, SP_integer *distancesMatRowNum)
 {
+    if (!isDrusillaTrained)
+    {
+        raisePrologSystemExeption("The Model is not Trained!");
+        return;
+    }
+    
     // convert the Prolog arrays to arma::mat
     mat querySet = convertArrayToMat(querySetMatArr, querySetMatSize, querySetMatRowNum);
 
     // create the ReturnMat
     Mat< size_t > neighborsReturnMat;
-
-    // create the ReturnMat
     mat distancesReturnMat;
     
-    drusillaSelect.Search(querySet, k, neighborsReturnMat, distancesReturnMat);
-    
-    // return the Matrix dimensions
-    *neighborsMatColNum = neighborsReturnMat.n_cols;
-    *neighborsMatRowNum = neighborsReturnMat.n_rows;
-    
-    // return the Matrix as one long Array
-    *neighborsMatArr = convertToArray(neighborsReturnMat);
+
+    try
+    {
+        drusillaSelect.Search(querySet, k, neighborsReturnMat, distancesReturnMat);
+    }
+    catch(const std::exception& e)
+    {
+        raisePrologSystemExeption(e.what());
+        return;
+    }
     
-    // return the Matrix dimensions
-    *distancesMatColNum = distancesReturnMat.n_cols;
-    *distancesMatRowNum = distancesReturnMat.n_rows;
     
-    // return the Matrix as one long Array
-    *distancesMatArr = convertToArray(distancesReturnMat);
+    // return the Matrices
+    returnMatrixInformation(neighborsReturnMat, neighborsMatArr, neighborsMatColNum, neighborsMatRowNum);
+    returnMatrixInformation(distancesReturnMat, distancesMatArr, distancesMatColNum, distancesMatRowNum);
     
 }
 
-// TODO: 
+
 // input:   const MatType & 	referenceSet,
 //          const size_t 	    l = 0,
 //          const size_t 	    m = 0 
 // output: 
 // description: 
-void trainDrusilla(float *referenceSetMatArr, SP_integer referenceSetMatSize, SP_integer referenceSetMatRowNum, SP_integer l, SP_integer m)
+//          Trains the DrusillaSearch Model with the given reference Set.
+//
+void trainDrusilla(float *referenceSetMatArr, SP_integer referenceSetMatSize, SP_integer referenceSetMatRowNum, 
+                    SP_integer l, SP_integer m)
 {
     // convert the Prolog arrays to arma::mat
     mat referenceSet = convertArrayToMat(referenceSetMatArr, referenceSetMatSize, referenceSetMatRowNum);
     
-    drusillaSelect.Train(referenceSet, l, m);
+    
+    try
+    {
+        drusillaSelect.Train(referenceSet, l, m);
+    }
+    catch(const std::exception& e)
+    {
+        raisePrologSystemExeption(e.what());
+        return;
+    }
+    isDrusillaTrained = true;
 }
 
-// TODO: 
+
 // input:   const size_t 	l,
 //          const size_t 	m
 // output: 
 // description: 
+//          Initiates the QDAFNSearch Model but doesnt train it.
+//
 void initQDAFNModelNoTrain(SP_integer l, SP_integer m)
 {
     qdafn = QDAFN(l, m);
+    isQDAFNTrained = false;
 }
 
-// TODO: 
+
 // input:   const MatType & 	referenceSet,
 //          const size_t 	    l,
 //          const size_t 	    m
 // output: 
 // description: 
-void initQDAFNModelWithTrain(float *referenceSetMatArr, SP_integer referenceSetMatSize, SP_integer referenceSetMatRowNum, SP_integer l, SP_integer m)
+//          Initiates the QDAFNSearch Model and trains it with the given reference Set.
+//
+void initQDAFNModelWithTrain(float *referenceSetMatArr, SP_integer referenceSetMatSize, SP_integer referenceSetMatRowNum, 
+                                SP_integer l, SP_integer m)
 {
     // convert the Prolog arrays to arma::mat
     mat referenceSet = convertArrayToMat(referenceSetMatArr, referenceSetMatSize, referenceSetMatRowNum);
     
-    qdafn = QDAFN(referenceSet, l, m);
+    
+    try
+    {
+        qdafn = QDAFN(referenceSet, l, m);
+    }
+    catch(const std::out_of_range& e)
+    {
+        raisePrologSystemExeption("l*m must be smaller than the number of points in the dataset.");
+        return;
+    }
+    catch(const std::exception& e)
+    {
+        raisePrologSystemExeption(e.what());
+        return;
+    }
+    isQDAFNTrained = true;
 }
 
-// TODO: 
+
 // input:   const MatType & 	    querySet,
 //          const size_t 	        k,
 //          arma::Mat< size_t > & 	neighbors,
 //          arma::mat & 	        distances
 // output: 
 // description: 
+//          Run Search on the given Queryset with the QDAFN Search Policy.
+//
 void searchQDAFN(float *querySetMatArr, SP_integer querySetMatSize, SP_integer querySetMatRowNum, 
                     SP_integer k,
                     float **neighborsMatArr, SP_integer *neighborsMatColNum, SP_integer *neighborsMatRowNum, 
                     float **distancesMatArr, SP_integer *distancesMatColNum, SP_integer *distancesMatRowNum)
 {
+    if (!isQDAFNTrained)
+    {
+        raisePrologSystemExeption("The Model is not Trained!");
+        return;
+    }
+
     // convert the Prolog arrays to arma::mat
     mat querySet = convertArrayToMat(querySetMatArr, querySetMatSize, querySetMatRowNum);
 
     // create the ReturnMat
     Mat< size_t > neighborsReturnMat;
-
-    // create the ReturnMat
     mat distancesReturnMat;
     
-    qdafn.Search(querySet, k, neighborsReturnMat, distancesReturnMat);
-    
-    // return the Matrix dimensions
-    *neighborsMatColNum = neighborsReturnMat.n_cols;
-    *neighborsMatRowNum = neighborsReturnMat.n_rows;
-    
-    // return the Matrix as one long Array
-    *neighborsMatArr = convertToArray(neighborsReturnMat);
-    
-    // return the Matrix dimensions
-    *distancesMatColNum = distancesReturnMat.n_cols;
-    *distancesMatRowNum = distancesReturnMat.n_rows;
+
+    try
+    {
+        qdafn.Search(querySet, k, neighborsReturnMat, distancesReturnMat);
+    }
+    catch(const std::exception& e)
+    {
+        raisePrologSystemExeption(e.what());
+        return;
+    }
     
-    // return the Matrix as one long Array
-    *distancesMatArr = convertToArray(distancesReturnMat);
     
+    // return the Matrices
+    returnMatrixInformation(neighborsReturnMat, neighborsMatArr, neighborsMatColNum, neighborsMatRowNum);
+    returnMatrixInformation(distancesReturnMat, distancesMatArr, distancesMatColNum, distancesMatRowNum);
 }
 
-// TODO: 
+
 // input:   const MatType & 	referenceSet,
 //          const size_t 	    l = 0,
 //          const size_t 	    m = 0 
 // output: 
 // description: 
-void trainQDAFN(float *referenceSetMatArr, SP_integer referenceSetMatSize, SP_integer referenceSetMatRowNum, SP_integer l, SP_integer m)
+//          Trains the QDAFNSearch Model with the given reference Set.
+//
+void trainQDAFN(float *referenceSetMatArr, SP_integer referenceSetMatSize, SP_integer referenceSetMatRowNum, 
+                SP_integer l, SP_integer m)
 {
     // convert the Prolog arrays to arma::mat
     mat referenceSet = convertArrayToMat(referenceSetMatArr, referenceSetMatSize, referenceSetMatRowNum);
     
-    qdafn.Train(referenceSet, l, m);
+    
+    try
+    {
+        qdafn.Train(referenceSet, l, m);
+    }
+    catch(const std::out_of_range& e)
+    {
+        raisePrologSystemExeption("l*m must be smaller than the number of points in the dataset.");
+        return;
+    }
+    catch(const std::exception& e)
+    {
+        raisePrologSystemExeption(e.what());
+        return;
+    }
+    isQDAFNTrained = true;
 }
diff --git a/src/methods/approx_kfn/approx_kfn.pl b/src/methods/approx_kfn/approx_kfn.pl
index 78bbf17..6815eac 100644
--- a/src/methods/approx_kfn/approx_kfn.pl
+++ b/src/methods/approx_kfn/approx_kfn.pl
@@ -1,12 +1,12 @@
 
 :- module(approx_kfn, [ initDrusillaModelNoTrain/2,
-                        initDrusillaModelWithTrain/5,
-                        searchDrusilla/10,
-                        trainDrusilla/5,
+                        initDrusillaModelWithTrain/4,
+                        searchDrusilla/7,
+                        trainDrusilla/4,
                         initQDAFNModelNoTrain/2,
-                        initQDAFNModelWithTrain/5,
-                        searchQDAFN/10,
-                        trainQDAFN/5]).
+                        initQDAFNModelWithTrain/4,
+                        searchQDAFN/7,
+                        trainQDAFN/4]).
 
 %% requirements of library(struct)
 :- load_files(library(str_decl),
@@ -34,7 +34,12 @@
 %%              Initiates the DrusillaSearch Model but doesnt train it.
 %%              trainDrusilla has to be used before searchDrusilla can be used.
 %%
-foreign(initDrusillaModelNoTrain, c, initDrusillaModelNoTrain(+integer, +integer)).
+initDrusillaModelNoTrain(L, M) :-
+        L > 0,
+        M > 0,
+        initDrusillaModelNoTrainI(L, M).
+
+foreign(initDrusillaModelNoTrain, c, initDrusillaModelNoTrainI(+integer, +integer)).
 
 
 %% --Input--
@@ -48,7 +53,13 @@ foreign(initDrusillaModelNoTrain, c, initDrusillaModelNoTrain(+integer, +integer
 %%              Initiates the DrusillaSearch Model and trains it with the given reference Set.
 %%              Afterwards searchDrusilla can be used.
 %%
-foreign(initDrusillaModelWithTrain, c, initDrusillaModelWithTrain(      +pointer(float_array), +integer, +integer, 
+initDrusillaModelWithTrain(DataList, DataRows, L, M) :-
+        L > 0,
+        M > 0,
+        convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)),
+        initDrusillaModelWithTrainI(X, Xsize, Xrownum, L, M).
+        
+foreign(initDrusillaModelWithTrain, c, initDrusillaModelWithTrainI(     +pointer(float_array), +integer, +integer, 
                                                                         +integer, +integer)).
 
 
@@ -61,9 +72,16 @@ foreign(initDrusillaModelWithTrain, c, initDrusillaModelWithTrain(      +pointer
 %%              mat     distances
 %%
 %% --Description--
-%%              
+%%              Run Search on the given Queryset with the Drusilla Search Policy.
 %%
-foreign(searchDrusilla, c, searchDrusilla(      +pointer(float_array), +integer, +integer, 
+searchDrusilla(DataList, DataRows, K, NeighborsList, YCols, DistancesList, ZCols) :-
+        K > 0,
+        convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)),
+        searchDrusillaI(X, Xsize, Xrownum, K, Y, YCols, YRows, Z, ZCols, ZRows),
+        convert_float_array_to_2d_list(Y, YCols, YRows, NeighborsList),
+        convert_float_array_to_2d_list(Z, ZCols, ZRows, DistancesList).
+
+foreign(searchDrusilla, c, searchDrusillaI(     +pointer(float_array), +integer, +integer, 
                                                 +integer, 
                                                 -pointer(float_array), -integer, -integer, 
                                                 -pointer(float_array), -integer, -integer)).
@@ -79,8 +97,14 @@ foreign(searchDrusilla, c, searchDrusilla(      +pointer(float_array), +integer,
 %% --Description--
 %%              Trains the DrusillaSearch Model with the given reference Set.
 %%
-foreign(trainDrusilla, c, trainDrusilla(+pointer(float_array), +integer, +integer, 
-                                        +integer, +integer)).
+trainDrusilla(DataList, DataRows, L, M) :-
+        L > 0,
+        M > 0,
+        convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)),
+        trainDrusillaI(X, Xsize, Xrownum, L, M).
+
+foreign(trainDrusilla, c, trainDrusillaI(       +pointer(float_array), +integer, +integer, 
+                                                +integer, +integer)).
 
 
 %% --Input--
@@ -93,7 +117,12 @@ foreign(trainDrusilla, c, trainDrusilla(+pointer(float_array), +integer, +intege
 %%              Initiates the QDAFNSearch Model but doesnt train it.
 %%              trainQDAFN has to be used before searchQDAFN can be used.
 %%
-foreign(initQDAFNModelNoTrain, c, initQDAFNModelNoTrain(+integer, +integer)).
+initQDAFNModelNoTrain(L, M) :-
+        L > 0,
+        M > 0,
+        initQDAFNModelNoTrainI(L, M).
+
+foreign(initQDAFNModelNoTrain, c, initQDAFNModelNoTrainI(+integer, +integer)).
 
 
 %% --Input--
@@ -107,7 +136,13 @@ foreign(initQDAFNModelNoTrain, c, initQDAFNModelNoTrain(+integer, +integer)).
 %%              Initiates the QDAFNSearch Model and trains it with the given reference Set.
 %%              Afterwards searchQDAFN can be used.
 %%
-foreign(initQDAFNModelWithTrain, c, initQDAFNModelWithTrain(    +pointer(float_array), +integer, +integer, 
+initQDAFNModelWithTrain(DataList, DataRows, L, M) :-
+        L > 0,
+        M > 0,
+        convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)),
+        initQDAFNModelWithTrainI(X, Xsize, Xrownum, L, M).
+
+foreign(initQDAFNModelWithTrain, c, initQDAFNModelWithTrainI(   +pointer(float_array), +integer, +integer, 
                                                                 +integer, +integer)).
 
 
@@ -120,14 +155,21 @@ foreign(initQDAFNModelWithTrain, c, initQDAFNModelWithTrain(    +pointer(float_a
 %%              mat     distances
 %%
 %% --Description--
-%%
+%%              Run Search on the given Queryset with the QDAFN Search Policy.
 %%              
-foreign(searchQDAFN, c, searchQDAFN(    +pointer(float_array), +integer, +integer, 
+searchQDAFN(DataList, DataRows, K, NeighborsList, YCols, DistancesList, ZCols) :-
+        K > 0,
+        convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)),
+        searchQDAFNI(X, Xsize, Xrownum, K, Y, YCols, YRows, Z, ZCols, ZRows),
+        convert_float_array_to_2d_list(Y, YCols, YRows, NeighborsList),
+        convert_float_array_to_2d_list(Z, ZCols, ZRows, DistancesList).
+
+foreign(searchQDAFN, c, searchQDAFNI(   +pointer(float_array), +integer, +integer, 
                                         +integer, 
                                         -pointer(float_array), -integer, -integer, 
                                         -pointer(float_array), -integer, -integer)).
 
-%% TODO: 
+
 %% --Input--
 %%              mat     referenceSet,
 %%              int     l               => 0,
@@ -138,7 +180,13 @@ foreign(searchQDAFN, c, searchQDAFN(    +pointer(float_array), +integer, +intege
 %% --Description--
 %%              Trains the QDAFNSearch Model with the given reference Set.
 %%
-foreign(trainQDAFN, c, trainQDAFN(      +pointer(float_array), +integer, +integer, 
+trainQDAFN(DataList, DataRows, L, M) :-
+        L > 0,
+        M > 0,
+        convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)),
+        trainQDAFNI(X, Xsize, Xrownum, L, M).
+
+foreign(trainQDAFN, c, trainQDAFNI(     +pointer(float_array), +integer, +integer, 
                                         +integer, +integer)).
 
 
diff --git a/src/methods/approx_kfn/approx_kfn_test.pl b/src/methods/approx_kfn/approx_kfn_test.pl
index b37a384..7b21249 100644
--- a/src/methods/approx_kfn/approx_kfn_test.pl
+++ b/src/methods/approx_kfn/approx_kfn_test.pl
@@ -6,38 +6,298 @@
 :- use_module(approx_kfn).
 :- use_module('../../helper_files/helper.pl').
 
-reset_Model :-
-        initModel(1,0,50,0.0001).
+reset_DrusillaModel_NoTrain :-
+        initDrusillaModelNoTrain(2, 2).
+
+reset_DrusillaModel_WithTrain :-
+        initDrusillaModelWithTrain([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, 2, 2).
+
+reset_QDAFNModel_NoTrain :-
+        initQDAFNModelNoTrain(2, 2).
+
+reset_QDAFNModel_WithTrain :-
+        initQDAFNModelWithTrain([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, 2, 2).
+
+%%
+%% TESTING predicate initDrusillaModelNoTrain/2
+%%
+:- begin_tests(initDrusillaModelNoTrain).      
+
+%% Failure Tests
+                                            
+test(approx_KFN_InitDrusillaNoTrain_Negative_L, fail) :-
+        initDrusillaModelNoTrain(-5,5).
+
+test(approx_KFN_InitDrusillaNoTrain_Negative_M, fail) :-
+        initDrusillaModelNoTrain(5,-5).
+        
+
+%% Successful Tests
+
+test(approx_KFN_InitDrusillaNoTrain_Normal) :-
+        initDrusillaModelNoTrain(5,5).
+
+test(approx_KFN_InitDrusillaNoTrain_Alternative) :-
+        initDrusillaModelNoTrain(10,3).
+
+:- end_tests(initDrusillaModelNoTrain).
+
+
+
+%%
+%% TESTING predicate initDrusillaModelWithTrain/4
+%%
+:- begin_tests(initDrusillaModelWithTrain).      
+
+%% Failure Tests
+                                            
+test(approx_KFN_InitDrusillaWithTrain_Negative_L, fail) :-
+        initDrusillaModelWithTrain([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, -5, 5).
+
+test(approx_KFN_InitDrusillaWithTrain_Negative_M, fail) :-
+        initDrusillaModelWithTrain([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, 5, -5).
+
+test(approx_KFN_InitDrusillaWithTrain_Normal,
+     [error(_,system_error('DrusillaSelect::Train(): l and m are too large!  Choose smaller values.  l*m must be smaller than the number of points in the dataset.'))]) :-
+        initDrusillaModelWithTrain([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, 5, 5).
+
+
+%% Successful Tests
+
+test(approx_KFN_InitDrusillaWithTrain_Normal) :-
+        initDrusillaModelWithTrain([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, 2, 2).
+
+test(approx_KFN_InitDrusillaWithTrain_Alternative) :-
+        open('src/data_csv/iris2.csv', read, File),
+        take_csv_row(File, skipFirstRow,10, Data),
+        initDrusillaModelWithTrain(Data, 4, 5, 2).
+
+:- end_tests(initDrusillaModelWithTrain).
+
+
 
 %%
-%% TESTING predicate predicate/10
+%% TESTING predicate searchDrusilla/7
+%%
+:- begin_tests(searchDrusilla).      
+
+%% Failure Tests
+
+test(approx_KFN_SearchDrusilla_Negative_K, fail) :-
+        reset_DrusillaModel_WithTrain,
+        searchDrusilla([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, -2, _, _, _, _).
+                                            
+test(approx_KFN_SearchDrusilla_Diffrent_Query_Dims, [error(_,system_error('subtraction: incompatible matrix dimensions: 4x1 and 3x1'))]) :-
+        reset_DrusillaModel_WithTrain,
+        open('src/data_csv/iris2.csv', read, File),
+        take_csv_row(File, skipFirstRow,10, Data),
+        searchDrusilla(Data, 4, 2, _, _, _, _).
+
+test(approx_KFN_SearchDrusilla_Befor_Train, [error(_,system_error('The Model is not Trained!'))]) :-
+        reset_DrusillaModel_NoTrain,
+        searchDrusilla([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, 2, _, _, _, _).
+        
+
+%% Successful Tests
+
+test(approx_KFN_SearchDrusilla_Normal) :-
+        reset_DrusillaModel_WithTrain,
+        searchDrusilla([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, 2, NeighborsList, _, DistancesList, _),
+        print('\nNeighbors: '),
+        print(NeighborsList),
+        print('\nDistances: '),
+        print(DistancesList).
+                                            
+test(approx_KFN_SearchDrusilla_Alternative) :-
+        open('src/data_csv/iris2.csv', read, File),
+        take_csv_row(File, skipFirstRow,10, Data),
+        initDrusillaModelWithTrain(Data, 4, 2, 5),
+        searchDrusilla(Data, 4, 3, NeighborsList, _, DistancesList, _),
+        print('\nNeighbors: '),
+        print(NeighborsList),
+        print('\nDistances: '),
+        print(DistancesList).
+
+:- end_tests(searchDrusilla).
+
+
+
+%% TESTING predicate trainDrusilla/4
 %%
-:- begin_tests(predicate).      
+:- begin_tests(trainDrusilla).      
 
 %% Failure Tests
                                             
-test(testDescription, [error(domain_error('expectation' , culprit), _)]) :-
-        reset_Model_No_Train(perceptron),
-        train([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, [0,0,0,0], 2, culprit, 50, 0.0001, _).
+test(approx_KFN_TrainDrusilla_Negative_L, fail) :-
+        reset_DrusillaModel_NoTrain,
+        trainDrusilla([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, -5, 5).
+
+test(approx_KFN_TrainDrusilla_Negative_M, fail) :-
+        reset_DrusillaModel_NoTrain,
+        trainDrusilla([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, 5, -5).
+
+test(approx_KFN_TrainDrusilla_Too_Large_M_And_L,
+     [error(_,system_error('DrusillaSelect::Train(): l and m are too large!  Choose smaller values.  l*m must be smaller than the number of points in the dataset.'))]) :-
+        reset_DrusillaModel_NoTrain,
+        trainDrusilla([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, 5, 5).
+        
+
+%% Successful Tests
+
+test(approx_KFN_TrainDrusilla_Normal) :-
+        reset_DrusillaModel_NoTrain,
+        trainDrusilla([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, 2, 1).
+
+test(approx_KFN_TrainDrusilla_Alternative) :-
+        reset_DrusillaModel_NoTrain,
+        open('src/data_csv/iris2.csv', read, File),
+        take_csv_row(File, skipFirstRow,10, Data),
+        trainDrusilla(Data, 4, 2, 3).
+
+:- end_tests(trainDrusilla).
+
+
+
+%%
+%% TESTING predicate initQDAFNModelNoTrain/2
+%%
+:- begin_tests(initQDAFNModelNoTrain).      
+
+%% Failure Tests
+                                            
+test(approx_KFN_InitQDAFNNoTrain_Negative_L, fail) :-
+        initQDAFNModelNoTrain(-5,5).
+
+test(approx_KFN_InitQDAFNNoTrain_Negative_M, fail) :-
+        initQDAFNModelNoTrain(5,-5).
+        
+
+%% Successful Tests
+
+test(approx_KFN_InitQDAFNNoTrain_Normal) :-
+        initQDAFNModelNoTrain(5,5).
+
+test(approx_KFN_InitQDAFNNoTrain_Alternative) :-
+        initQDAFNModelNoTrain(10,3).
+
+:- end_tests(initQDAFNModelNoTrain).
+
+
+
+%%
+%% TESTING predicate initQDAFNModelWithTrain/4
+%%
+:- begin_tests(initQDAFNModelWithTrain).      
+
+%% Failure Tests
+                                            
+test(approx_KFN_InitQDAFNWithTrain_Negative_L, fail) :-
+        initQDAFNModelWithTrain([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, -5, 5).
+
+test(approx_KFN_InitQDAFNWithTrain_Negative_M, fail) :-
+        initQDAFNModelWithTrain([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, 5, -5).
+
+test(approx_KFN_InitQDAFNWithTrain_Too_Large_L_And_M, [error(_,system_error('l*m must be smaller than the number of points in the dataset.'))]) :-
+        initQDAFNModelWithTrain([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, 5, 5).
+
+
+%% Successful Tests
+
+test(approx_KFN_InitQDAFNWithTrain_Normal) :-
+        initQDAFNModelWithTrain([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, 1, 2).
+
+test(approx_KFN_InitQDAFNWithTrain_Alternative) :-
+        open('src/data_csv/iris2.csv', read, File),
+        take_csv_row(File, skipFirstRow,10, Data),
+        initQDAFNModelWithTrain(Data, 4, 5, 2).
+
+:- end_tests(initQDAFNModelWithTrain).
+
+
+
+%%
+%% TESTING predicate searchQDAFN/7
+%%
+:- begin_tests(searchQDAFN).      
+
+%% Failure Tests
+
+test(approx_KFN_SearchQDAFN_Negative_K, fail) :-
+        reset_QDAFNModel_WithTrain,
+        searchQDAFN([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, -2, _, _, _, _).
+                                            
+test(approx_KFN_SearchQDAFN_Diffrent_Query_Dims, [error(_,system_error('dot(): objects must have the same number of elements'))]) :-
+        reset_QDAFNModel_WithTrain,
+        open('src/data_csv/iris2.csv', read, File),
+        take_csv_row(File, skipFirstRow,10, Data),
+        searchQDAFN(Data, 4, 2, _, _, _, _).
+
+test(approx_KFN_SearchQDAFN_Befor_Train, [error(_,system_error('The Model is not Trained!'))]) :-
+        reset_QDAFNModel_NoTrain,
+        searchQDAFN([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, 2, _, _, _, _).
+
+test(approx_KFN_SearchQDAFN_Too_Large_K, [error(_,system_error('QDAFN::Search(): requested k is greater than value of m!'))]) :-
+        reset_QDAFNModel_WithTrain,
+        searchQDAFN([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, 3, _, _, _, _).
+        
+
+%% Successful Tests
+
+test(approx_KFN_SearchQDAFN_Normal) :-
+        reset_QDAFNModel_WithTrain,
+        searchQDAFN([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, 2, NeighborsList, _, DistancesList, _),
+        print('\nNeighbors: '),
+        print(NeighborsList),
+        print('\nDistances: '),
+        print(DistancesList).
+                                            
+test(approx_KFN_SearchQDAFN_Alternative) :-
+        open('src/data_csv/iris2.csv', read, File),
+        take_csv_row(File, skipFirstRow,10, Data),
+        initQDAFNModelWithTrain(Data, 4, 2, 3),
+        searchQDAFN(Data, 4, 2, NeighborsList, _, DistancesList, _),
+        print('\nNeighbors: '),
+        print(NeighborsList),
+        print('\nDistances: '),
+        print(DistancesList).
+
+:- end_tests(searchQDAFN).
+
+
+
+%% TESTING predicate trainQDAFN/4
+%%
+:- begin_tests(trainQDAFN).      
+
+%% Failure Tests
+                                            
+test(approx_KFN_TrainQDAFN_Negative_L, fail) :-
+        reset_QDAFNModel_NoTrain,
+        trainQDAFN([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, -5, 5).
+
+test(approx_KFN_TrainQDAFN_Negative_M, fail) :-
+        reset_QDAFNModel_NoTrain,
+        trainQDAFN([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, 5, -5).
 
-test(testDescription2, [error(_,system_error('The values of the Label have to start at 0 and be >= 0 and < the given numClass!'))]) :-
-        reset_Model_No_Train(perceptron),
-        train([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, [0,1,0,2], 2, perceptron, 50, 0.0001, _).
+test(approx_KFN_TrainQDAFN_Too_Large_M_And_L,
+     [error(_,system_error('l*m must be smaller than the number of points in the dataset.'))]) :-
+        reset_QDAFNModel_NoTrain,
+        trainQDAFN([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, 5, 5).
         
 
 %% Successful Tests
 
-test(testDescription3, [true(Error =:= 1)]) :-
-        reset_Model_No_Train(perceptron),
-        train([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, [0,0,0,0], 2, perceptron, 50, 0.0001, Error).
+test(approx_KFN_TrainQDAFN_Normal) :-
+        reset_QDAFNModel_NoTrain,
+        trainQDAFN([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, 2, 1).
 
-test(testDescription4, [true(Error =:= 0.9797958971132711)]) :-
-        reset_Model_No_Train(perceptron),
+test(approx_KFN_TrainQDAFN_Alternative) :-
+        reset_QDAFNModel_NoTrain,
         open('src/data_csv/iris2.csv', read, File),
         take_csv_row(File, skipFirstRow,10, Data),
-        train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error).
+        trainQDAFN(Data, 4, 2, 3).
 
-:- end_tests(predicate).
+:- end_tests(trainQDAFN).
 
 run_approx_kfn_tests :-
         run_tests.
diff --git a/test_all.pl b/test_all.pl
index a7b0293..f23cb27 100644
--- a/test_all.pl
+++ b/test_all.pl
@@ -12,7 +12,7 @@
 
 :- use_module('src/methods/adaboost/adaboost_test.pl').
 
-%%:- use_module('src/methods/approx_kfn/approx_kfn_test.pl').
+:- use_module('src/methods/approx_kfn/approx_kfn_test.pl').
 
 %%:- use_module('src/methods/bayesian_linear_regression/bayesian_linear_regression_test.pl').
 
-- 
GitLab