Una forma sencilla y rápida de aprender JAVA, observando y deduciendo cómo se comporta el lenguaje a través de ejemplos prácticos.

Archivo del blog

martes, 9 de julio de 2024

Conversor matriz de distancias a coordenadas cartesianas (MDS).

El algoritmo es conocido como Escalamiento Multidimensional(MDS) y puede ser utilizado para:

   . Reconstrucción de coordenadas: A partir de las distancias entre puntos, reconstruye sus posiciones relativas en un espacio en coordenadas cartesianas.
   . Visualización de datos: Permite representar en un espacio de menor dimensión (generalmente 2D o 3D) datos que originalmente están en un espacio de mayor dimensión.


Funcionamiento:

   1. Entrada: El algoritmo toma como entrada las distancias entre cuatro puntos o nodos en un espacio tridimensional.
   2. Proceso: Utiliza estas distancias para construir una matriz de distancias, la cual se transforma y se somete a una descomposición en valores singulares (SVD).
   3. Salida: Produce las coordenadas cartesianas (x, y, z) de los cuatro puntos (en el espacio 3D).


Código Java (CalculadorCoordenadasMDS.java):

package calculadorcoordenadasmds;

public class CalculadorCoordenadasMDS {

    public static void main(String[] args) {
        // Distancias dadas entre los nodos
        double d12 = 17;
        double d13 = 40;
        double d14 = 12;
        double d23 = 64;
        double d24 = 88;
        double d34 = 12;

        try {
            double[][] coordinates = calculateCoordinates(d12, d13, d14, d23, d24, d34);
            for (int i = 0; i < coordinates.length; i++) {
                System.out.printf("Nodo %d: (%.4f, %.4f, %.4f)%n",
                        i + 1, coordinates[i][0], coordinates[i][1], coordinates[i][2]);
            }
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
    }

    public static double[][] calculateCoordinates(double d12, double d13, double d14, double d23, double d24, double d34) {
        double[][] distances = {
            {0, d12, d13, d14},
            {d12, 0, d23, d24},
            {d13, d23, 0, d34},
            {d14, d24, d34, 0}
        };

        double[][] b = new double[4][4];
        // Doble centrado de la matriz de distancias
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                b[i][j] = -0.5 * (distances[i][j] * distances[i][j]);
            }
        }

        double[] rowMeans = new double[4];
        double[] colMeans = new double[4];
        double totalMean = 0.0;

        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                rowMeans[i] += b[i][j];
                colMeans[j] += b[i][j];
            }
            rowMeans[i] /= 4.0;
            totalMean += rowMeans[i];
        }
        totalMean /= 4.0;

        for (int i = 0; i < 4; i++) {
            colMeans[i] /= 4.0;
        }

        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                b[i][j] += totalMean - rowMeans[i] - colMeans[j];
            }
        }

        SVDResult svd = svd(b);
        double[][] coordinates = new double[4][3];

        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 3; j++) {
                coordinates[i][j] = svd.u[i][j] * Math.sqrt(svd.s[j]);
            }
        }

        return coordinates;
    }

    // Implementación simple de SVD
    private static SVDResult svd(double[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;
        double[][] u = new double[m][m];
        double[] s = new double[Math.min(m, n)];
        double[][] v = new double[n][n];

        // Implementación simplificada de SVD (no es una implementación completa)
        // Esta implementación asume que la matriz es simétrica y positiva semidefinida

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                u[i][j] = matrix[i][j];
            }
        }

        // Calculamos los valores propios (que serán nuestros valores singulares)
        for (int i = 0; i < s.length; i++) {
            double sum = 0;
            for (int j = 0; j < n; j++) {
                sum += matrix[i][j] * matrix[i][j];
            }
            s[i] = Math.sqrt(sum);
        }

        // Normalizamos las columnas de U
        for (int j = 0; j < m; j++) {
            double norm = 0;
            for (int i = 0; i < m; i++) {
                norm += u[i][j] * u[i][j];
            }
            norm = Math.sqrt(norm);
            if (norm > 0) {
                for (int i = 0; i < m; i++) {
                    u[i][j] /= norm;
                }
            }
        }

        return new SVDResult(u, s, v);
    }

    private static class SVDResult {

        double[][] u;
        double[] s;
        double[][] v;

        SVDResult(double[][] u, double[] s, double[][] v) {
            this.u = u;
            this.s = s;
            this.v = v;
        }
    }
}


Resultado:

run:
Nodo 1: (-10,9518, 13,1281, -18,6443)
Nodo 2: (22,3223, 37,7579, -18,2671)
Nodo 3: (-20,6027, -11,8716, 15,7343)
Nodo 4: (9,2322, -39,0143, 21,1772)
BUILD SUCCESSFUL (total time: 0 seconds)


Con la tecnología de Blogger.