franyack / IMachineApp

This Android application uses the CIEngine module to automatically manage the photos and images on the device. Then you will be able to manage the result according to your criteria, by moving or erasing images as you want.
1 stars 0 forks source link

Librería más indicada en Java para resolver álgebra lineal #6

Closed franyack closed 6 years ago

franyack commented 6 years ago

Debemos encontrar que librería en java puede resolver problemas relacionados a la ciencia de la computación (como lo es NumPy en Python), ya sea para operar matrices, vectores, etc.

leferrad commented 6 years ago

Aquí, un benchmark de referencia. Yo priorizaría tanto que sea simple de usar como performante, sin buscar el más performante necesariamente. De estos, me convence por ahora EJML aunque no he llegado a probarlo

https://github.com/optimatika/ojAlgo/wiki/Java-Matrix-Benchmark

franyack commented 6 years ago

Muy bueno Lea!!! Según la gráfica que se encuentra en ese benchmark EJML parece bancársela bastante a medida que crece el size de las matrices por lo que también creo que es una gran alternativa. La estuve probando y por lo poco que hice, anda bien, parece ser intiutiva y en la documentación se encuentran las diferentes operaciones. Además, hace comparativos sobre como se hacen en Matlab y como se hacen con SimpleMatrix (objeto que se debe crear para operar con esta libreria en Java) los diferentes métodos para trabajar con matrices y vectores.

Para realizar las pruebas he creado un proyecto en Java: 1 - Me descargué el IDE Eclipse (la instalación en Ubuntu fue super rápida e intuitiva). 2 - Hice un nuevo proyecto con gradle (similar a la utilización de este herramienta en Android), allí agregué dentro de las dependencias la siguiente línea: compile group: 'org.ejml', name: 'ejml-all', version: '0.34' la cual descarga y compila todas las dependencias de EJML 3- Luego hice una nueva clase que se llama StatisticsMatrix (ejemplo en internet) y el código es el siguiente:

import org.ejml.data.DMatrixRMaj;
import org.ejml.data.Matrix;
import org.ejml.data.MatrixType;
import org.ejml.dense.row.RandomMatrices_DDRM;
import org.ejml.simple.SimpleBase;
import org.ejml.simple.SimpleMatrix;

import java.util.Random;

public class StatisticsMatrix extends SimpleBase<StatisticsMatrix> {

    public StatisticsMatrix( int numRows , int numCols ) {
        super(numRows,numCols);
    }

    protected StatisticsMatrix(){}

     /**
     * Wraps a StatisticsMatrix around 'm'.  Does NOT create a copy of 'm' but saves a reference
     * to it.
     */
    public static StatisticsMatrix wrap( DMatrixRMaj m ) {
        StatisticsMatrix ret = new StatisticsMatrix();
        ret.setMatrix( m );

        return ret;
    }

    /**
     * Computes the mean or average of all the elements.
     *
     * @return mean
     */
    public double mean() {
        double total = 0;

        final int N = getNumElements();
        for( int i = 0; i < N; i++ ) {
            total += get(i);
        }

        return total/N;
    }

    /**
     * Computes the unbiased standard deviation of all the elements.
     *
     * @return standard deviation
     */
    public double stdev() {
        double m = mean();

        double total = 0;

        final int N = getNumElements();
        if( N <= 1 )
            throw new IllegalArgumentException("There must be more than one element to compute stdev");

        for( int i = 0; i < N; i++ ) {
            double x = get(i);

            total += (x - m)*(x - m);
        }

        total /= (N-1);

        return Math.sqrt(total);
    }

    /**
     * Returns a matrix of StatisticsMatrix type so that SimpleMatrix functions create matrices
     * of the correct type.
     */
    @Override
    protected StatisticsMatrix createMatrix(int numRows, int numCols, MatrixType type) {
        return new StatisticsMatrix(numRows,numCols);
    }

    @Override
    protected StatisticsMatrix wrapMatrix(Matrix m) {
        StatisticsMatrix r = new StatisticsMatrix();
        r.setMatrix( m );
        return r;
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Random rand = new Random(24234);

        int N = 500;

        // create two vectors whose elements are drawn from uniform distributions
        StatisticsMatrix A = StatisticsMatrix.wrap(RandomMatrices_DDRM.rectangle(N,1,0,1,rand));
        StatisticsMatrix B = StatisticsMatrix.wrap(RandomMatrices_DDRM.rectangle(N,1,1,2,rand));

        // the mean should be about 0.5
        System.out.println("Mean of A is               "+A.mean());
        // the mean should be about 1.5
        System.out.println("Mean of B is               "+B.mean());

        StatisticsMatrix C = A.plus(B);

        // the mean should be about 2.0
        System.out.println("Mean of C = A + B is       "+C.mean());

        System.out.println("Standard deviation of A is "+A.stdev());
        System.out.println("Standard deviation of B is "+B.stdev());
        System.out.println("Standard deviation of C is "+C.stdev());

        double[][] datos = {{1, 2}, {3, 4}};
        SimpleMatrix F = new SimpleMatrix(datos);
        F.print();

        SimpleMatrix G = F.plus(F);
        G.print();

    }
}
leferrad commented 6 years ago

Excelente Fran! Sii y lo que estuve viendo es que soporta sparse matrices y demás funcionalidades que no encuentro en JBlas por ejemplo. Así que por ahora le metemos con esa librería si te parece, ya que no encontré ninguna mejor en términos de rapido-facil de usar- completo.

leferrad commented 6 years ago

Este benchmark es más completo: http://lessthanoptimal.github.io/Java-Matrix-Benchmark/runtime/2013_10_Corei7v2600/

Por ahí lo que veo es que el total de Jars pesa 2MB, suponiendo que se van a necesitar todos. Estaba viendo que la4J es mucho más liviano (al orden d cientos de KB) pero no parece ser para nada más óptimo, e incluso tiene muy poca documentación. Quise seguir un ejemplo pero no encontré las funciones para completar lo que quería, asi que por ahora resulta mejor EJML.

leferrad commented 6 years ago

Por el momento, la elección sería EJML ya que muestra ser una librería apropiada y fácil de usar. Por lo tanto se puede cerrar este issue