diff --git a/CHANGELIST.md b/CHANGELIST.md index 75e0d646c..bad1d94b7 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -4,6 +4,22 @@ ChangeList Master branch release --------------------- +- Solved bug at `Matrix::select(...)` C++ method. The matrix offset wasn't be + added to the resulting matrix offset. +- Solved bug at `SlidingWindow::setAtWindow(...)` C++ method. The matrix offset + wasn't be added to the computed window position. +- Solved bug at `buffered_memory.h`. Such bug introduces an early stop when + reading matrices, ignoring the last lines of files. +- Added `DEPENDENCIES-INSTALLER.sh`. +- Added syntactic sugar for `matrix:slice(...)` method: `m("1:2","3:4")` or + `m({1,2},{3,4})`, like in Matlab or Octave. +- Solved problem with `rlcompleter`, which didn't work properly when loaded as a + Lua module. +- Modified `configure.sh` to inform about any error during Lua building. +- Loadable modules are working on MacOs X. +- Added `matrix.svd` and `matrix.diagonalize`. +- Added `stats.pca`, `stats.mean_centered`, `stats.pca_whitening`. + v0.3.0-beta relase ------------------ diff --git a/DEPENDENCIES-INSTALLER.sh b/DEPENDENCIES-INSTALLER.sh new file mode 100755 index 000000000..c340c8971 --- /dev/null +++ b/DEPENDENCIES-INSTALLER.sh @@ -0,0 +1,32 @@ +#!/bin/bash +UNAME=`uname` +echo "System: $UNAME" +if [ $UNAME = "Linux" ]; then + if [ `which apt-get` ]; then + apt-get install libz-dev libreadline-dev libblas-dev libatlas-dev libpng12-dev libtiff-dev liblua5.2-dev || + (echo "ERROR INSTALLING DEPENDENCIES" && exit 10) + else + echo "Error, impossible to install dependencies, this script only works with apt-get" + exit 10 + fi +elif [ $UNAME = "Darwin" ]; then + if [ `which port` ]; then + port install zlib readline libpng tiff findutils || + (echo "ERROR INSTALLING DEPENDENCIES" && exit 10) + echo "This script will change the default system BSD find by GNU find" + echo "BSD find will be renamed as bfind" + if [ ! -e /usr/find/bfind ]; then + mv /usr/bin/find /usr/find/bfind + else + rm -f /usr/bin/find + fi + ln -s `which gfind` /usr/bin/find + else + echo "Error, impossible to install dependencies, this scripts needs MacPorts" + exit 10 + fi +else + echo "Error, impossible to install dependencies, not recognized system: $UNAME" + exit 10 +fi +exit 0 diff --git a/README.md b/README.md index 0408f0460..17c7d76f0 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,11 @@ April-ANN Requirements ------------ -Requires the following libraries. Versions are only orientative, it could work with older and newer versions. +Requires the following libraries. Versions are only orientative, it could work +with older and newer versions whenver the API was compatible. - GNU C++ compiler (g++): v 4.7.2 +- Only in Linux systems: Lua 5.2 headers to tell April-ANN the default system path for Lua modules (`lua5.2-deb-multiarch.h` header). - BLAS implementation: ATLAS (v. 3), Intel MKL (v. 10.3.6), MacOS Accelerate Framework - Threads posix (pthread) - Readline (libreadline) @@ -21,6 +23,11 @@ The following libreries are recommended, but optional: For perform computation on GPU, this optional library: - [OPTIONAL] CUDA and CUBLAS: release 4.2.6 +It is possible to install dependencies in Linux (via apt-get) and in MacOS X +(via MacPorts) running: + +- `$ sudo ./DEPENDENCIES-INSTALLER.sh` + Compilation ----------- @@ -141,12 +148,33 @@ you can use this bibitem: ```bibtex @misc{aprilann, - Author = {Francisco Zamora-Mart\'inez and Salvador Espa\~na-Boquera and Jorge Gorbe-Moya and Joan Pastor-Pellicer and Adrian Palacios}, - Note = {{https://github.com/pakozm/april-ann}}, - Title = {{April-ANN toolkit, A Pattern Recognizer In Lua with Artificial Neural Networks}}, - Year = {2013}} + Author = {Francisco Zamora-Mart\'inez and Salvador Espa\~na-Boquera and + Jorge Gorbe-Moya and Joan Pastor-Pellicer and Adrian Palacios}, + Note = {{https://github.com/pakozm/april-ann}}, + Title = {{April-ANN toolkit, A Pattern Recognizer In Lua with Artificial Neural Networks}}, + Year = {2013}} ``` +Publications +------------ + +List of research papers which uses this tool: + +- Francisco Zamora-Martínez, Pablo Romeu, Paloma Botella-Rocamora, and Juan + Pardo. [Towards Energy Efficiency: Forecasting Indoor Temperature via Multivariate Analysis](http://www.mdpi.com/1996-1073/6/9/4639). + *Energies*, 6(9):4639-4659, 2013. + +- Pablo Romeu, Francisco Zamora-Martinez, Paloma Botella, and Juan Pardo. + [Time-Series Forecasting of Indoor Temperature Using Pre-trained Deep Neural Networks](http://dx.doi.org/10.1007/978-3-642-40728-4_57). + In *ICANN*, pages 451-458. 2013. + +- Joan Pastor-Pellicer, Francisco Zamora-Martinez, Salvador España-Boquera, and M.J. Castro-Bleda. + [F-Measure as the error function to train Neural Networks](http://dx.doi.org/10.1007/978-3-642-38679-4). + In *Advances in Computational Intelligence, IWANN, part I*, LNCS, pages 376-384. Springer, 2013. + +- F. Zamora-Martínez, Pablo Romeu, Juan Pardo, and Daniel Tormo. + Some empirical evaluations of a temperature forecasting module based on Artificial Neural Networks for a domotic home environment. + In *IC3K - KDIR*, pages 206-211, 2012. Packages -------- @@ -193,10 +221,18 @@ Doxygen documentation LINUX installation ------------------ -Install g++, libatlas-dev, libreadline-dev, libpng-dev, libtiff-dev, libz-dev, libopenmp-dev. +Install g++, libatlas-dev, libreadline-dev, libpng-dev, libtiff-dev, libz-dev, +libopenmp-dev or execute: `$ sudo ./DEPENDENCIES-INSTALLER.sh` MAC OS X installation --------------------- -- Install libpng, from (sourceforge)[http://sourceforge.net/projects/libpng/files/]. Follow INSTALL information. -- Install findutils, from (GNU)[http://ftp.gnu.org/pub/gnu/findutils/]. Follow INSTALL instructions. Execute `./configure --prefix=/usr` in order to substitute BSD find of your MacOS. +Via MacPorts: + +- Install [MacPorts](http://www.macports.org/) +- Execute `$ sudo ./DEPENDENCIES-INSTALLER.sh` + +Or manually: + +- Install libpng, from [sourceforge](http://sourceforge.net/projects/libpng/files/). Follow INSTALL information. +- Install findutils, from [GNU](http://ftp.gnu.org/pub/gnu/findutils/). Follow INSTALL instructions. Execute `./configure --prefix=/usr` in order to substitute BSD find of your MacOS. diff --git a/binding/bind_templates/luabind_template.cc b/binding/bind_templates/luabind_template.cc index 042a62370..e460412c6 100644 --- a/binding/bind_templates/luabind_template.cc +++ b/binding/bind_templates/luabind_template.cc @@ -175,6 +175,8 @@ void lua_push$$ClassName$$(lua_State *L, $$ClassName$$ *obj){ #include "luabindmacros.h" int lua_new_$$ClassName$$_$$FILENAME2$$(lua_State *L) { + // stops garbage collector to avoid problems with reference counting + lua_gc(L, LUA_GCSTOP, 0); lua_remove(L,1); // primer parametro es la metatabla __call(table,...) $$ClassName$$ UNUSED *obj = 0; DEBUG("lua_new_$$ClassName$$ (begin)"); @@ -184,10 +186,14 @@ int lua_new_$$ClassName$$_$$FILENAME2$$(lua_State *L) { if (luabind_num_returned_values != 1) { LUABIND_ERROR("constructors must return 1 (and only 1) value"); } + // restart the garbage collector + lua_gc(L, LUA_GCRESTART, 0); return luabind_num_returned_values; } int lua_delete_$$ClassName$$_$$FILENAME2$$(lua_State *L){ + // stops garbage collector to avoid problems with reference counting + lua_gc(L, LUA_GCSTOP, 0); $$ClassName$$ *obj = lua_rawget$$ClassName$$_$$FILENAME2$$(L,1); if (obj != 0) { DEBUG_OBJ("lua_delete_$$ClassName$$ (begin)",obj); @@ -202,6 +208,8 @@ int lua_delete_$$ClassName$$_$$FILENAME2$$(lua_State *L){ else { DEBUG_OBJ("lua_delete_$$ClassName$$ WARNING!! NULL pointer", obj); } + // restart the garbage collector + lua_gc(L, LUA_GCRESTART, 0); return 0; } @@ -374,6 +382,8 @@ void bindluaopen_$$ClassName$$_$$FILENAME2$$(lua_State *L){ #include "luabindmacros.h" int lua_call_$$ClassName$$_$$MethodName$$(lua_State *L){ + // stops garbage collector to avoid problems with reference counting + lua_gc(L, LUA_GCSTOP, 0); //Comprobamos que el primer elemento sea el userdata que esperamos if (!lua_is$$ClassName$$(L,1)) { lua_pushstring(L, "First argument of $$MethodName$$ must be of type " @@ -389,6 +399,8 @@ int lua_call_$$ClassName$$_$$MethodName$$(lua_State *L){ $$code$$ } DEBUG_OBJ("lua_call_$$ClassName$$_$$MethodName$$ (end)", obj); + // restart the garbage collector + lua_gc(L, LUA_GCRESTART, 0); return luabind_num_returned_values; } //LUA end @@ -401,11 +413,15 @@ int lua_call_$$ClassName$$_$$MethodName$$(lua_State *L){ int lua_call_class_$$ClassName$$_$$ClassMethodName$$(lua_State *L){ DEBUG("lua_call_class_$$ClassName$$_$$ClassMethodName$$"); + // stops garbage collector to avoid problems with reference counting + lua_gc(L, LUA_GCSTOP, 0); int luabind_num_returned_values = 0; // CODE: { $$code$$ } + // restart the garbage collector + lua_gc(L, LUA_GCRESTART, 0); return luabind_num_returned_values; } //LUA end @@ -419,10 +435,14 @@ int lua_call_class_$$ClassName$$_$$ClassMethodName$$(lua_State *L){ #include "luabindmacros.h" static int lua_call_$$string.gsub(func_name,"%p","_")$$(lua_State *L){ + // stops garbage collector to avoid problems with reference counting + lua_gc(L, LUA_GCSTOP, 0); lua_remove(L,1); // primer parametro es la metatabla __call(table,...) DEBUG("lua_call_$$string.gsub(func_name,"%p","_")$$ (begin)"); int luabind_num_returned_values = 0; $$code$$ + // restart the garbage collector + lua_gc(L, LUA_GCRESTART, 0); DEBUG("lua_call_$$string.gsub(func_name,"%p","_")$$ (end)"); return luabind_num_returned_values; } diff --git a/binding/formiga.lua b/binding/formiga.lua index 95df470ea..5eadbaa96 100644 --- a/binding/formiga.lua +++ b/binding/formiga.lua @@ -106,7 +106,7 @@ formiga = { CPPcompiler = os.getenv("CXX") or "g++", Ccompiler = os.getenv("CC") or "gcc", extra_libs = {"-ldl"}, - shared_extra_libs = {"-shared"}, + shared_extra_libs = { }, extra_flags = { string.format("-DGIT_COMMIT=%d", commit_count), }, language_by_extension = { c = "c", cc = "c++", cxx = "c++", CC = "c++", cpp = "c++", diff --git a/build_NOBLAS_debug.lua b/build_NOBLAS_debug.lua index 5dae6658b..f614d042c 100644 --- a/build_NOBLAS_debug.lua +++ b/build_NOBLAS_debug.lua @@ -30,6 +30,7 @@ luapkg{ "-Wl,-E -ldl" }, shared_extra_libs={ + "-shared", "-llua5.2", }, }, diff --git a/build_NOBLAS_release.lua b/build_NOBLAS_release.lua index 486b53a33..3146a2eb3 100644 --- a/build_NOBLAS_release.lua +++ b/build_NOBLAS_release.lua @@ -30,6 +30,7 @@ luapkg{ "-Wl,-E -ldl" }, shared_extra_libs={ + "-shared", "-llua5.2", }, }, diff --git a/build_cuda_and_mkl_debug.lua b/build_cuda_and_mkl_debug.lua index 29b150c5e..fe18fd883 100644 --- a/build_cuda_and_mkl_debug.lua +++ b/build_cuda_and_mkl_debug.lua @@ -8,6 +8,8 @@ luapkg{ program_name = "april-ann.debug", verbosity_level = 0, -- 0 => NONE, 1 => ONLY TARGETS, 2 => ALL packages = packages, + version_flags = dofile "VERSION.lua", + disclaimer_strings = dofile "DISCLAIMER.lua", global_flags = { debug="yes", use_lstrip = "no", @@ -24,11 +26,14 @@ luapkg{ "-msse", "-pg", "-DNO_POOL", + "-DNO_OMP", + "-fPIC", -- For CUDA "-I/usr/local/cuda/include", "-L/usr/local/cuda/lib", }, extra_libs={ + "-fPIC", "-pg", "-lpthread", "-rdynamic", @@ -43,6 +48,10 @@ luapkg{ -- For CUBLAS "-lcublas", }, + shared_extra_libs={ + "-shared", + "-llua5.2", + }, }, main_package = package{ diff --git a/build_cuda_and_mkl_release.lua b/build_cuda_and_mkl_release.lua index 1dc24b689..0e39ce09d 100644 --- a/build_cuda_and_mkl_release.lua +++ b/build_cuda_and_mkl_release.lua @@ -8,6 +8,8 @@ luapkg{ program_name = "april-ann", verbosity_level = 0, -- 0 => NONE, 1 => ONLY TARGETS, 2 => ALL packages = packages, + version_flags = dofile "VERSION.lua", + disclaimer_strings = dofile "DISCLAIMER.lua", global_flags = { debug="no", use_lstrip = "yes", @@ -24,11 +26,14 @@ luapkg{ "-msse", "-DNDEBUG", "-DNO_POOL", + "-DNO_OMP", + "-fPIC", -- For CUDA "-I/usr/local/cuda/include", "-L/usr/local/cuda/lib", }, extra_libs={ + "-fPIC", "-lpthread", "-rdynamic", -- For Intel MKL :) @@ -42,6 +47,10 @@ luapkg{ -- For CUBLAS "-lcublas", }, + shared_extra_libs={ + "-shared", + "-llua5.2", + }, }, main_package = package{ diff --git a/build_debug.lua b/build_debug.lua index 3d995951f..25632f52f 100644 --- a/build_debug.lua +++ b/build_debug.lua @@ -34,6 +34,7 @@ luapkg{ "-llapack_atlas", }, shared_extra_libs={ + "-shared", "-llua5.2", }, }, diff --git a/build_debug_macosx.lua b/build_debug_macosx.lua index bc97183f0..a1ffaa6b0 100644 --- a/build_debug_macosx.lua +++ b/build_debug_macosx.lua @@ -37,6 +37,8 @@ luapkg{ "-fPIC", }, shared_extra_libs={ + "-flat_namespace", + "-bundle", assert(io.popen("pkg-config --libs 'lua >= 5.2'"):read("*l")) }, }, diff --git a/build_mkl_debug.lua b/build_mkl_debug.lua index cc629f4ee..c5ae7601f 100644 --- a/build_mkl_debug.lua +++ b/build_mkl_debug.lua @@ -43,6 +43,7 @@ luapkg{ "-liomp5" }, shared_extra_libs={ + "-shared", "-llua5.2", }, }, diff --git a/build_mkl_release.lua b/build_mkl_release.lua index 9180792a5..e7ac51b3f 100644 --- a/build_mkl_release.lua +++ b/build_mkl_release.lua @@ -41,6 +41,7 @@ luapkg{ "-liomp5", }, shared_extra_libs={ + "-shared", "-llua5.2", }, }, diff --git a/build_release.lua b/build_release.lua index 99807b887..faf2da9ff 100644 --- a/build_release.lua +++ b/build_release.lua @@ -33,6 +33,7 @@ luapkg{ "-llapack_atlas", }, shared_extra_libs={ + "-shared", "-llua5.2", }, }, diff --git a/build_release_macosx.lua b/build_release_macosx.lua index 09431632b..bce4003f6 100644 --- a/build_release_macosx.lua +++ b/build_release_macosx.lua @@ -35,6 +35,8 @@ luapkg{ "-fPIC", }, shared_extra_libs={ + "-flat_namespace", + "-bundle", assert(io.popen("pkg-config --libs 'lua >= 5.2'"):read("*l")) }, }, diff --git a/build_release_pi.lua b/build_release_pi.lua index 7c117f76b..3b5949eca 100644 --- a/build_release_pi.lua +++ b/build_release_pi.lua @@ -32,6 +32,7 @@ luapkg{ "-llapack_atlas", }, shared_extra_libs={ + "-shared", "-llua5.2", }, }, diff --git a/configure.sh b/configure.sh index 5e7959efe..57f7747bd 100755 --- a/configure.sh +++ b/configure.sh @@ -5,9 +5,10 @@ if [ -z $APRILANN_CONFIGURED ]; then #export LUA_PATH="`pwd`""/binding/?.lua;?" fi export LUA_DIR="`pwd`"/lua/lua-5.2.2 -make -C $LUA_DIR -make -C $LUA_DIR install -make -C "`pwd`"/lua/lstrip +(make -C $LUA_DIR && + make -C $LUA_DIR install && + make -C "`pwd`"/lua/lstrip) || +(echo "Error building Lua!!!" && exit -1) if [ -z $APRIL_EXEC ]; then export APRIL_EXEC=`pwd`/bin/april-ann fi diff --git a/lua/lua-5.2.2/src/Makefile b/lua/lua-5.2.2/src/Makefile index 13f2b29ec..1c3440902 100644 --- a/lua/lua-5.2.2/src/Makefile +++ b/lua/lua-5.2.2/src/Makefile @@ -49,7 +49,7 @@ ALL_A= $(LUA_A) # Targets start here. DetectOS: - -@make $(UNAME) + @make $(UNAME) Linux: linux diff --git a/packages/basics/mathcore/c_src/lapack_headers.cc b/packages/basics/mathcore/c_src/lapack_headers.cc index b5abb68ae..a1b470541 100644 --- a/packages/basics/mathcore/c_src/lapack_headers.cc +++ b/packages/basics/mathcore/c_src/lapack_headers.cc @@ -18,6 +18,7 @@ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ +#include "unused_variable.h" #include "lapack_headers.h" #include "error_print.h" @@ -42,6 +43,29 @@ int clapack_sgetri(const int Order, const int N, delete[] WORK; return INFO; } +int clapack_sgesdd(const int Order, const int M, const int N, const int LDA, + float *A, float *U, float *S, float *VT) { + if (Order != CblasColMajor) + ERROR_EXIT(256, "Only col_major order is allowed\n"); + const int numSV = (Msvd(&U, &S, &V); + LUABIND_RETURN(MatrixFloat, U); + LUABIND_RETURN(MatrixFloat, S); + LUABIND_RETURN(MatrixFloat, V); +} +//BIND_END + //BIND_METHOD MatrixFloat contiguous { if (obj->getIsContiguous()) @@ -1471,7 +1481,11 @@ typedef MatrixFloat::sliding_window SlidingWindow; // CALL lua_call(L, N+1, 1); // pop the result, a number - *it = lua_tofloat(L, -1); + if (!lua_isnil(L, -1)) { + if (!lua_isfloat(L, -1)) + LUABIND_ERROR("Incorrect returned value type, expected NIL or FLOAT\n"); + *it = lua_tofloat(L, -1); + } lua_pop(L, 1); } delete[] v; @@ -1480,5 +1494,11 @@ typedef MatrixFloat::sliding_window SlidingWindow; } //BIND_END -////////////////////////////////////////////////////////////////////// +//BIND_METHOD MatrixFloat diagonalize +{ + MatrixFloat *resul = obj->diagonalize(); + LUABIND_RETURN(MatrixFloat, resul); +} +//BIND_END +////////////////////////////////////////////////////////////////////// diff --git a/packages/basics/matrix/c_src/matrix-iterators.impl.h b/packages/basics/matrix/c_src/matrix-iterators.impl.h index 3f8518ad3..3c215f5c2 100644 --- a/packages/basics/matrix/c_src/matrix-iterators.impl.h +++ b/packages/basics/matrix/c_src/matrix-iterators.impl.h @@ -1086,7 +1086,7 @@ int Matrix::sliding_window::numWindows() const { template void Matrix::sliding_window::setAtWindow(int windex) { if (windex < num_windows) { - raw_pos = 0; + raw_pos = m->offset; for (int i=0; i < m->getNumDim();i++) { int j = order_step[i]; coords[j] = offset[j] + (windex % num_steps[j])*step[j]; diff --git a/packages/basics/matrix/c_src/matrix-math.impl.h b/packages/basics/matrix/c_src/matrix-math.impl.h index 4984ff5cd..d3a4e4d1c 100644 --- a/packages/basics/matrix/c_src/matrix-math.impl.h +++ b/packages/basics/matrix/c_src/matrix-math.impl.h @@ -375,3 +375,11 @@ template Matrix *Matrix::inv() { ERROR_EXIT(128, "NOT IMPLEMENTED!!!\n"); } + +template +void Matrix::svd(Matrix **U, Matrix **S, Matrix **V) { + UNUSED_VARIABLE(U); + UNUSED_VARIABLE(S); + UNUSED_VARIABLE(V); + ERROR_EXIT(128, "NOT IMPLEMENTED!!!\n"); +} diff --git a/packages/basics/matrix/c_src/matrix.h b/packages/basics/matrix/c_src/matrix.h index 2a1128a12..6b97b5e6b 100644 --- a/packages/basics/matrix/c_src/matrix.h +++ b/packages/basics/matrix/c_src/matrix.h @@ -616,8 +616,12 @@ class Matrix : public Referenced { IntGPUMirroredMemoryBlock *raw_positions=0, int shift = 0) const; + // Expands current matrix to a diagonal matrix + Matrix *diagonalize() const; + /**** LAPACK OPERATIONS ****/ Matrix *inv(); + void svd(Matrix **U, Matrix **S, Matrix **V); private: void allocate_memory(int size); diff --git a/packages/basics/matrix/c_src/matrix.impl.h b/packages/basics/matrix/c_src/matrix.impl.h index 03eaa7aaa..8e1105841 100644 --- a/packages/basics/matrix/c_src/matrix.impl.h +++ b/packages/basics/matrix/c_src/matrix.impl.h @@ -545,7 +545,7 @@ Matrix *Matrix::select(int dim, int index, Matrix *dest) { result->matrixSize = new int[d]; result->stride = new int[d]; result->major_order = major_order; - result->offset = index*stride[dim]; // the select implies an offset + result->offset = offset + index*stride[dim]; // the select implies an offset result->last_raw_pos = result->offset; result->data = data; result->mmapped_data = 0; @@ -567,7 +567,7 @@ Matrix *Matrix::select(int dim, int index, Matrix *dest) { april_assert(dest->total_size == total_size/matrixSize[dim]); april_assert(dest->numDim == numDim-1); // - int dest_offset = index*stride[dim]; + int dest_offset = offset + index*stride[dim]; int dest_last_raw_pos = dest_offset; for(int i=0; i::getIsContiguous() const { is_contiguous = CONTIGUOUS; return true; } + +// expands current matrix to a diagonal matrix +template +Matrix *Matrix::diagonalize() const { + if (numDim != 1) + ERROR_EXIT(128, "Only one-dimensional matrix is allowed\n"); + const int dims[2] = { matrixSize[0], matrixSize[0] }; + Matrix *resul = new Matrix(2, dims, major_order); + // resul_diag is a submatrix of resul, build to do a diagonal traverse + const int stride = matrixSize[0] + 1; + Matrix *resul_diag = new Matrix(1, &stride, 0, dims, dims[0], + resul->last_raw_pos, resul->data, + resul->major_order, + resul->use_cuda); + resul->zeros(); + resul_diag->copy(this); + delete resul_diag; + return resul; +} diff --git a/packages/basics/matrix/c_src/matrixFloat.cc b/packages/basics/matrix/c_src/matrixFloat.cc index 3bdae51f3..2a79edd40 100644 --- a/packages/basics/matrix/c_src/matrixFloat.cc +++ b/packages/basics/matrix/c_src/matrixFloat.cc @@ -802,4 +802,31 @@ Matrix *Matrix::inv() { return ret; } +// FIXME: using WRAPPER for generalized CULA, LAPACK, float and complex numbers +// WARNING: the V matrix is returned transposed +template <> +void Matrix::svd(Matrix **U, Matrix **S, Matrix **VT) { + if (numDim != 2) + ERROR_EXIT(128, "Only bi-dimensional matrices are allowed\n"); + Matrix *A = this; + if (this->major_order != CblasColMajor || !this->getIsContiguous()) + A = this->clone(CblasColMajor); + IncRef(A); + int INFO; + const int m = A->matrixSize[0]; // cols + const int n = A->matrixSize[1]; // rows + const int lda = A->stride[1]; + const int numSV = m(2, dimsU, CblasColMajor); + *S = new Matrix(1, dimsS, CblasColMajor); + *VT = new Matrix(2, dimsVT, CblasColMajor); + INFO = clapack_sgesdd(CblasColMajor, m, n, lda, A->getData(), + (*U)->getData(), (*S)->getData(), (*VT)->getData()); + checkLapackInfo(INFO); + DecRef(A); +} + template class Matrix; diff --git a/packages/basics/matrix/c_src/matrixFloat.h b/packages/basics/matrix/c_src/matrixFloat.h index add0969c7..f78b6a93a 100644 --- a/packages/basics/matrix/c_src/matrixFloat.h +++ b/packages/basics/matrix/c_src/matrixFloat.h @@ -174,6 +174,9 @@ void Matrix::adjustRange(float rmin, float rmax); template<> Matrix *Matrix::inv(); +template <> +void Matrix::svd(Matrix **U, Matrix **S, Matrix **V); + //////////////////////////////////////////////////////////////////////////// typedef Matrix MatrixFloat; diff --git a/packages/basics/matrix/c_src/utilMatrixFloat.cc b/packages/basics/matrix/c_src/utilMatrixFloat.cc index a60b4f101..b3542e24d 100644 --- a/packages/basics/matrix/c_src/utilMatrixFloat.cc +++ b/packages/basics/matrix/c_src/utilMatrixFloat.cc @@ -302,7 +302,7 @@ MatrixFloat *readMatrixFloatFromTabFile(const char *filename, do { BufferedGZFile f(filename, "r"); FloatAsciiExtractor extractor; - constString line; + constString line(""); while (f.good()) { line = f.extract_u_line(); ++nrows; @@ -320,7 +320,7 @@ MatrixFloat *readMatrixFloatFromTabFile(const char *filename, do { BufferedFile f(filename, "r"); FloatAsciiExtractor extractor; - constString line; + constString line(""); while (f.good()) { line = f.extract_u_line(); ++nrows; diff --git a/packages/basics/matrix/lua_src/matrix.lua b/packages/basics/matrix/lua_src/matrix.lua index 786d64167..fe7439d82 100644 --- a/packages/basics/matrix/lua_src/matrix.lua +++ b/packages/basics/matrix/lua_src/matrix.lua @@ -10,6 +10,34 @@ matrix.row_major = function(...) return matrix(...) end +matrix.meta_instance.__call = function(self,...) + local arg = table.pack(...) + local dims = self:dim() + local pos,size = {},{} + for i=1,#arg do + local t = arg[i] + local tt = luatype(t) + local a,b + if tt == "table" then + a,b = table.unpack(t) + assert(tonumber(a) and tonumber(b), + "The table " .. i .. " must contain two numbers") + elseif tt == "string" then + a = t:match("^(%d+)%:.*$") or 1 + b = t:match("^.*%:(%d+)$") or dims[i] + else + error("The argument " .. i .. " is not a table neither a string") + end + table.insert(pos, a) + table.insert(size, b - a + 1) + end + for i=#arg+1,#dims do + table.insert(pos, 1) + table.insert(size, dims[i]) + end + return self:slice(pos,size) +end + matrix.meta_instance.__tostring = function(self) local dims = self:dim() local major = self:get_major_order() @@ -112,7 +140,12 @@ function matrix.join(dim, ...) end end -- JOIN - local outm = matrix(table.unpack(size)) + local outm + if arg[1]:get_major_order() == "col_major" then + outm = matrix.col_major(table.unpack(size)) + else + outm = matrix(table.unpack(size)) + end local first = matrix(#size):ones():toTable() for i=1,#arg do local m = arg[i] @@ -1129,6 +1162,34 @@ april_set_doc("matrix.inv", outputs = { "The matrix inverse" }, }) +april_set_doc("matrix.svd", + { + class = "method", + summary = "Computes the SVD of a matrix", + description = { + "This method computes the SVD of matrix.", + "It is adapted to work with row_major matrices, but", + "internally they are transformed to col_major, so", + "it is more efficient to compute the SVD over", + "col_major matrices. The computation returns three matrices", + "in col_major, so A=U * S * V'.", + }, + outputs = { + "The matrix U", + "The vector S with the eigenvalues", + "The matrix V', the transposed of V", + }, + }) + +april_set_doc("matrix.diagonalize", + { + class = "method", + summary = "Converts the given uni-dimensional matrix in a bi-dimensional diagonal matrix", + outputs = { + "A matrix which is the diagonalized version of the caller matrix", + }, + }) + april_set_doc("matrix.contiguous", { class = "method", diff --git a/packages/basics/matrix/test/test_matrix_math.lua b/packages/basics/matrix/test/test_matrix_math.lua index 02d83d12e..cef532d2b 100644 --- a/packages/basics/matrix/test/test_matrix_math.lua +++ b/packages/basics/matrix/test/test_matrix_math.lua @@ -113,3 +113,40 @@ assert(j:equals(matrix.col_major(2,2,{ 35, 44, 44, 56, }))) + +--------------------------------------------------------------- +--------------------------------------------------------------- +--------------------------------------------------------------- + +local m = matrix.col_major(4,5,{1,0,0,0,2, + 0,0,3,0,0, + 0,0,0,0,0, + 0,4,0,0,0}) +local U,S,V = m:svd() +assert(U:equals(matrix.col_major(4,4, + { + 0,0,1, 0, + 0,1,0, 0, + 0,0,0,-1, + 1,0,0, 0, + }))) +assert(S:equals(matrix.col_major(4,{4,3,2.23607,0}))) +assert(V:equals(matrix.col_major(5,5, + { + 0,1,0,0,0, + 0,0,1,0,0, + 0.447214,0,0,0,0.894427, + 0,0,0,1,0, + -0.894427,0,0,0,0.447214, + }))) + +--------------------------------------------------------------- +--------------------------------------------------------------- +--------------------------------------------------------------- + +local m = matrix(20,20):uniformf() +local subm = m:slice({5,4},{6,9}) +subm:equals( m("5:10","4:12") ) +subm:equals( m({5,10},{4,12}) ) +local subm = m:slice({1,4},{6,m:dim(2)-3}) +subm:equals( m(":6","4:") ) diff --git a/packages/basics/stats/lua_src/pca.lua b/packages/basics/stats/lua_src/pca.lua index 832bda059..f2942ec47 100644 --- a/packages/basics/stats/lua_src/pca.lua +++ b/packages/basics/stats/lua_src/pca.lua @@ -10,6 +10,50 @@ local function re_orhtonormalize(submatrix,colmatrix,aux) colmatrix:gemv{ alpha=-1.0, A=submatrix, X=aux, beta=1.0, trans_A=false } end +------------------------------------------------------------------------------- + +function stats.mean_centered_by_pattern(X,major_order) + local dim = X:dim() + assert(#dim == 2, "Expected a bi-dimensional matrix") + local M,N = table.unpack(dim) + local R = X:clone(major_order) + -- U is the mean over all rows + local U,auxR = R:sum(2):rewrap(M):scal(1/N) + -- R is centered subtracting by -U + for i=1,R:dim(2) do auxR=R:select(2,i,auxR):axpy(-1, U) end + return R,U +end + +------------------------------------------------------------------------------- + +function stats.pca_whitening(X,S,U,epsilon) + local epsilon = epsilon or 0.0 + local XW = X:clone():gemm{ A=X, B=U, trans_B=true, beta=0, alpha=1 } + local aux + for i=1,S:dim(1) do + aux = XW:select(2,i,aux):scal( 1/math.sqrt(S:get(i) + epsilon) ) + end +end + +------------------------------------------------------------------------------- + +-- PCA algorithm based on covariance matrix and SVD decomposition +function stats.pca(X) + local dim = X:dim() + assert(#dim == 2, "Expected a bi-dimensional matrix") + local M,N = table.unpack(dim) + local Xc,avg = stats.mean_centered_by_pattern(X, "col_major") + local sigma = matrix.col_major(N,N):gemm{ A=Xc, B=Xc, + trans_A=true, + trans_B=false, + alpha=1/M, + beta=0, } + local U,S,VT = sigma:svd() + return U,S,VT +end + +------------------------------------------------------------------------------- + april_set_doc("stats.iterative_pca", { class = "function", @@ -21,9 +65,11 @@ april_set_doc("stats.iterative_pca", epsilon = "A number with the convergence criterion [optional], by default 1e-07", }, outputs = { - "The T scores matrix, size MxK", - "The P loads matrix, size NxK", + "The T=V*S=X*U scores matrix, size MxK", + "The P loads matrix, or U right eigenvectors matrix, size NxK", "The R residuals matrix, size MxN", + "The V left eigenvectors matrix, size MxN", + "The S singular values vector, size K", }, }) -- EXTRACTED FROM: @@ -41,6 +87,8 @@ april_set_doc("stats.iterative_pca", -- output: T is a MxK scores matrix -- output: P is a NxK loads matrix -- output: R is a MxN residuals matrix +-- +-- PCA model: X = TLP’ + R function stats.iterative_pca(params) local params = get_table_fields( { @@ -61,17 +109,13 @@ function stats.iterative_pca(params) local T = matrix[major_order](M,K):zeros() -- left eigenvectors local P = matrix[major_order](N,K):zeros() -- right eigenvectors local L = matrix[major_order](K):zeros() -- eigenvalues - local R = X:clone() -- residual - -- U is the sum over all columns - local U,auxR = R:sum(2):rewrap(M) - -- R is centered subtracting by -1/N*U - for i=1,R:dim(2) do auxR=R:select(2,i,auxR):axpy(-1/N, U) end + local R,U = stats.mean_centered_by_pattern(X, major_order) -- residual and means -- GS-PCA local Tcol, Rcol, Pcol, Uslice, Pslice, Tslice, Lk for k=1,K do - Tcol = T:select(2,k) - Rcol = R:select(2,k) - Pcol = P:select(2,k) + Tcol = T:select(2,k,Tcol) + Rcol = R:select(2,k,Rcol) + Pcol = P:select(2,k,Pcol) -- if k > 1 then Uslice = U:slice({1},{k-1}) @@ -95,6 +139,7 @@ function stats.iterative_pca(params) L:set(k, Lk) R:ger{ alpha=-Lk, X=Tcol, Y=Pcol } end + local V = T:clone() for k=1,K do T:select(2,k):scal( L:get(k) ) end - return T,P,R + return T,P,R,V,L end diff --git a/packages/basics/stats/misc/gs-pca.cc b/packages/basics/stats/misc/gs-pca.cc index 3d83093b9..1a4b50aeb 100644 --- a/packages/basics/stats/misc/gs-pca.cc +++ b/packages/basics/stats/misc/gs-pca.cc @@ -60,7 +60,7 @@ int main(int argc, char** argv) htime = ((double)clock()-start)/CLOCKS_PER_SEC; printf("\n\nTime for GS-PCA host computation: %f\n", htime); // the results are in T, P, R - print_results(M, N, K, X, T, P, R); + // print_results(M, N, K, X, T, P, R); // memory clean up and shutdown gsl_matrix_free(R); gsl_matrix_free(P); @@ -153,6 +153,9 @@ int gs_pca_gsl(int M, int N, int K, gsl_blas_dscal (gsl_vector_get(L, k), &gsl_matrix_column(T, k).vector); } + for(k=0; kbuffer_pos || + !memory.eofS()); } /// Closes the memory void close(); /// Forces to write pending data diff --git a/packages/misc/rlcompleter/binding/bind_rlcompleter.lua.cc b/packages/misc/rlcompleter/binding/bind_rlcompleter.lua.cc index 122313e29..1410807b6 100644 --- a/packages/misc/rlcompleter/binding/bind_rlcompleter.lua.cc +++ b/packages/misc/rlcompleter/binding/bind_rlcompleter.lua.cc @@ -227,6 +227,7 @@ class DIRRef : public Referenced { { storedL = L; rl_basic_word_break_characters = breaks; + rl_completer_word_break_characters = breaks; rl_attempted_completion_function = do_completion; } //BIND_END diff --git a/packages/misc/rlcompleter/lua_src/rlcompleter.lua b/packages/misc/rlcompleter/lua_src/rlcompleter.lua index 262070487..d329d100b 100644 --- a/packages/misc/rlcompleter/lua_src/rlcompleter.lua +++ b/packages/misc/rlcompleter/lua_src/rlcompleter.lua @@ -9,6 +9,9 @@ local keywords = { 'return', 'then', 'true', 'until', 'while' } +-- in case you want to use this software without April-ANN +local luatype = luatype or type + -- This function is called back by C function do_completion, itself called -- back by readline library, in order to complete the current input line. rlcompleter._set( @@ -25,7 +28,7 @@ rlcompleter._set( -- This function does the same job as the default completion of readline, -- completing paths and filenames. Rewritten because -- rl_basic_word_break_characters is different. - -- Uses LuaFileSystem (lfs) module for this task. + -- Uses binding functions for directory traversal (based on LuaFileSystem) local function filename_list(str) local path, name = str:match("(.*)[\\/]+(.*)") path = (path or ".") .. "/" @@ -147,9 +150,9 @@ rlcompleter._set( end -- Now call the processing functions and return the list of results. local str, expr, sep = simplify_expression(line:sub(1, endpos)) - + contextual_list(expr, sep, str) - + -- FIXME: Is this feature good to be really used? if false and #matches == 1 and word == matches[1] then print("\n----------------- DOCUMENTATION ----------------------") diff --git a/tools/HMM_ANN/training/train.lua b/tools/HMM_ANN/training/train.lua index b6ad86d33..07e02678d 100644 --- a/tools/HMM_ANN/training/train.lua +++ b/tools/HMM_ANN/training/train.lua @@ -211,18 +211,21 @@ function initialize_neural_network() end -- generamos la red if initial_mlp then + print("# LOADING ANN FROM PREVIOUS HMMANN") mlp_str = initial_mlp ann_table.trainer = trainable.supervised_trainer.load(initial_mlp, ann.loss[error_function](ann_table.num_outputs), bunch_size) ann_table.thenet = ann_table.trainer:get_component() elseif pretrained_mlp then + print("# LOADING PRETRAINED ANN") mlp_str = pretrained_mlp ann_table.trainer = trainable.supervised_trainer.load(pretrained_mlp, ann.loss[error_function](ann_table.num_outputs), bunch_size) ann_table.thenet = ann_table.trainer:get_component() else + print("# CREATING ANN FROM SCRATCH") ann_table.thenet = ann.components.stack() mlp_str = string.format("%d inputs",ann_table.num_entradas) -- diff --git a/tools/MapReduce/task-example.lua b/tools/MapReduce/task-example.lua index c4d07f862..4593832f0 100644 --- a/tools/MapReduce/task-example.lua +++ b/tools/MapReduce/task-example.lua @@ -58,10 +58,13 @@ local function mmap(key,value) local data,first,last = load(value)() local f = io.open(data) for i=1,first-1 do f:read("*l") end - local out = iterator(range(first,last)): - map(function(i) return f:read("*l") or "" end): + local out = iterator(io.lines(data)): + enumerate(): + filter(function(idx, line) return idx >= first and idx <= last end): + select(2): map(string.tokenize): - iterate(ipairs):select(2): + iterate(ipairs): + select(2): reduce(function(acc,w) acc[w] = (acc[w] or 0) + 1 return acc @@ -73,7 +76,7 @@ end -- receive a key and an array of values, and produces a pair of strings -- key,value (or able to be string-converted by Lua) pairs local function mreduce(key,values) - local sum = 0 for i=1,#values do sum=sum+values[i] end + local sum = iterator(ipairs(values)):select(2):reduce(math.add,0) return key,sum end @@ -81,7 +84,7 @@ end -- between all workers, and shows the result on user screen local function sequential(list) iterator(pairs(list)):apply(function(k,v)print(v,k)end) - return {1,2,3,4} + return {} end -- this function receives the shared value returned by sequential function diff --git a/tools/statistics/pearson-correlation-coefficient.lua b/tools/statistics/pearson-correlation-coefficient.lua index 1bf7db3b9..00b3a69d1 100644 --- a/tools/statistics/pearson-correlation-coefficient.lua +++ b/tools/statistics/pearson-correlation-coefficient.lua @@ -12,8 +12,9 @@ col1 = tonumber(arg[2]) col2 = tonumber(arg[3]) seed = tonumber(arg[4]) conf = tonumber(arg[5]) -reps = 1000 +reps = 100 +if conf > 0.5 then reps = 1000 end if conf > 0.95 then reps = 10000 end if conf > 0.99 then reps = 100000 end