diff --git a/Makefile b/Makefile
index 7be3f52f04333a13dd3997d4c5684d3c2cb1b9ce..4cc8bfa0dc4ff0af31c328211b34836a0d205f22 100644
--- a/Makefile
+++ b/Makefile
@@ -2,9 +2,11 @@ SPLFR_PATH=/usr/local/sicstus4.7.1/bin/splfr
 
 
 all:
+	@echo "Start compiling!"
 	make -C src/methods/ada_boost splfr=$(SPLFR_PATH)
+	@echo "AdaBoost!"
 	make -C src/methods/bayesian_linear_regression splfr=$(SPLFR_PATH)
-	make -C src/methods/cf splfr=$(SPLFR_PATH)
+	#make -C src/methods/cf splfr=$(SPLFR_PATH)
 	make -C src/methods/dbscan splfr=$(SPLFR_PATH)
 	make -C src/methods/emst splfr=$(SPLFR_PATH)
 	make -C src/methods/fastmks splfr=$(SPLFR_PATH)
@@ -17,15 +19,16 @@ all:
 	make -C src/methods/lsh splfr=$(SPLFR_PATH)
 	make -C src/methods/mean_shift splfr=$(SPLFR_PATH)
 	make -C src/methods/naive_bayes_classifier splfr=$(SPLFR_PATH)
+	make -C src/methods/nmf splfr=$(SPLFR_PATH)
 	make -C src/methods/perceptron splfr=$(SPLFR_PATH)
 	make -C src/methods/random_forest splfr=$(SPLFR_PATH)
-	make -C src/methods/softmac_regression splfr=$(SPLFR_PATH)
+	make -C src/methods/softmax_regression splfr=$(SPLFR_PATH)
 	make -C src/methods/approx_kfn splfr=$(SPLFR_PATH)
 
 clean:
 	make -C src/methods/ada_boost clean
 	make -C src/methods/bayesian_linear_regression clean
-	make -C src/methods/cf clean
+	#make -C src/methods/cf clean
 	make -C src/methods/dbscan clean
 	make -C src/methods/emst clean
 	make -C src/methods/fastmks clean
@@ -38,9 +41,10 @@ clean:
 	make -C src/methods/lsh clean
 	make -C src/methods/mean_shift clean
 	make -C src/methods/naive_bayes_classifier clean
+	make -C src/methods/nmf clean
 	make -C src/methods/perceptron clean
 	make -C src/methods/random_forest clean
-	make -C src/methods/softmac_regression clean
+	make -C src/methods/softmax_regression clean
 	make -C src/methods/approx_kfn clean
 
-	
\ No newline at end of file
+	
diff --git a/src/methods/nmf/Makefile b/src/methods/nmf/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..387b1e095d43b830cd142d27f9d7fd7721d2aa02
--- /dev/null
+++ b/src/methods/nmf/Makefile
@@ -0,0 +1,8 @@
+splfr=/usr/local/sicstus4.7.1/bin/splfr
+
+METHOD_NAME=nmf
+
+$(METHOD_NAME).so: $(METHOD_NAME).pl $(METHOD_NAME).cpp
+	$(splfr) -larmadillo -fopenmp -lmlpack -lstdc++ -cxx --struct $(METHOD_NAME).pl $(METHOD_NAME).cpp ../../helper_files/helper.cpp
+clean:
+	rm $(METHOD_NAME).so
diff --git a/src/methods/nmf/nmf.cpp b/src/methods/nmf/nmf.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d2bd5e933c9a7049b8496349000e7e7295521929
--- /dev/null
+++ b/src/methods/nmf/nmf.cpp
@@ -0,0 +1,74 @@
+#include <sicstus/sicstus.h>
+/* ex_glue.h is generated by splfr from the foreign/[2,3] facts.
+   Always include the glue header in your foreign resource code.
+*/
+#include "nmf_glue.h"
+#include <mlpack/methods/amf/amf.hpp>
+#include <mlpack/core.hpp>
+
+#include <mlpack/methods/amf/update_rules/nmf_mult_div.hpp>
+
+// including helper functions for converting between arma structures and arrays
+#include "../../helper_files/helper.hpp"
+
+// some of the most used namespaces
+using namespace arma;
+using namespace mlpack;
+using namespace std;
+using namespace mlpack::amf;
+
+
+// TODO: 
+// input:   const TerminationPolicyType & 	terminationPolicy = TerminationPolicyType(),
+//          const InitializationRuleType & 	initializeRule = InitializationRuleType(),
+//          const UpdateRuleType & 	        update = UpdateRuleType()
+//          const MatType & 	            V,
+//          const size_t 	                r,
+//          arma::mat & 	                W,
+//          arma::mat & 	                H
+//
+// output:  double
+//
+// description: 
+void nmf(char const *updateRule, SP_integer maxIterations, double minResidue,
+            float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum,
+            SP_integer rank,
+            float **WMatArr, SP_integer *WMatColNum, SP_integer *WMatRowNum,
+            float **HMatArr, SP_integer *HMatColNum, SP_integer *HMatRowNum)
+{
+    // convert the Prolog arrays to arma::mat
+    mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum);
+    
+    // create the ReturnMat
+    mat WReturnMat;
+
+    // create the ReturnMat
+    mat HReturnMat;
+
+    // decide which update rule to use
+    if (strcmp(updateRule, "multdist") == 0)        
+    {
+        AMF<SimpleResidueTermination, RandomAcolInitialization<>,NMFMultiplicativeDistanceUpdate>(SimpleResidueTermination(minResidue, maxIterations))
+        .Apply(data, rank, WReturnMat, HReturnMat);
+    }
+    else if (strcmp(updateRule, "multdiv") == 0)
+    {
+        AMF<SimpleResidueTermination, RandomAcolInitialization<>,NMFMultiplicativeDivergenceUpdate>(SimpleResidueTermination(minResidue, maxIterations))
+        .Apply(data, rank, WReturnMat, HReturnMat);
+    }
+    else if (strcmp(updateRule, "als") == 0)
+    {
+        AMF<SimpleResidueTermination, RandomAcolInitialization<>,NMFALSUpdate>(SimpleResidueTermination(minResidue, maxIterations))
+        .Apply(data, rank, WReturnMat, HReturnMat);
+    }
+    else
+    {
+        cout << "wrong updateRule input" << endl;
+    }
+    
+    // return the Matrix
+    returnMatrixInformation(WReturnMat, WMatArr, WMatColNum, WMatRowNum);
+
+    // return the Matrix
+    returnMatrixInformation(HReturnMat, HMatArr, HMatColNum, HMatRowNum);
+}
\ No newline at end of file
diff --git a/src/methods/nmf/nmf.pl b/src/methods/nmf/nmf.pl
new file mode 100644
index 0000000000000000000000000000000000000000..98b6ac3b5aa84278c1a80fe49e4b4d00fd2e73ee
--- /dev/null
+++ b/src/methods/nmf/nmf.pl
@@ -0,0 +1,41 @@
+:- module(nmf, [nmf/13]).
+
+%% requirements of library(struct)
+:- load_files(library(str_decl),
+        [when(compile_time), if(changed)]).
+
+%% needed for using the array type
+:- use_module(library(structs)).
+:- use_module('../../helper_files/helper.pl').
+
+%% type definitions for the float array
+:- foreign_type
+        float32          = float_32,
+        float_array      = array(float32).
+
+%% definitions for the connected function
+
+%% TODO: 
+%% --Input--
+%%              bool    updateRuel      => (1)true / (0)false,
+%%              int     maxIterations   => 10000,
+%%              float32 minResidue      => 1e-05,
+%%              mat     data,
+%%              int     rank
+%%
+%% --Output--
+%%              mat     W,
+%%              mat     H
+%%
+%% --Description--
+foreign(nmf, c, nmf(+string, +integer, +float32,
+                        +pointer(float_array), +integer, +integer,
+                        +integer,
+                        -pointer(float_array), -integer, -integer,
+                        -pointer(float_array), -integer, -integer)).
+
+
+%% Defines the functions that get connected from main.cpp
+foreign_resource(nmf, [nmf]).
+
+:- load_foreign_resource(nmf).
\ No newline at end of file
diff --git a/src/methods/nmf/nmf_test.pl b/src/methods/nmf/nmf_test.pl
new file mode 100644
index 0000000000000000000000000000000000000000..3132d0d859bd5228b4fb5f523f073d4b9dec55d0
--- /dev/null
+++ b/src/methods/nmf/nmf_test.pl
@@ -0,0 +1,56 @@
+:- use_module(library(plunit)).
+
+:- use_module(nmf).
+:- use_module('../../helper_files/helper.pl').
+
+reset_Model :-
+        initModel(1,0,50,0.0001).
+
+:- 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) :-
+        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).
+
+%% train tests
+test(correct_train) :-
+        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) :-
+        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) :-
+        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) :-
+        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) :-
+        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) :-
+        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