/* * Copyright (C) Justo Montiel, David Torres, Sergio Gomez, Alberto Fernandez * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see * <http://www.gnu.org/licenses/> */ package utils; import java.util.Vector; /** * <p> * <b>MultiDendrograms</b> * </p> * * Calculation of deviation measures * * @author Justo Montiel, David Torres, Sergio Gómez, Alberto Fernández * * @since JDK 6.0 */ public class DeviationMeasures { private final Vector<Double> dists_eucl = new Vector<Double>(); private final Vector<Double> dists_dendro = new Vector<Double>(); private final Double[] avgs = new Double[2]; private int count = 0; private static Double distance(Double x, Double y) { return Math.abs(x - y); } private Double average(Vector<Double> list) { double sum = 0.0; int count = 0; for (int i = 0; i < list.size(); i++) { sum += list.get(i); count++; } return sum / count; } private void calculateDistances(Double[][] mat_orig, Double[][] mat_um) { // Calculem la mitjana de les distancies euclidianes i dendrogramatiques int n = 0; for (int i = 0; i < mat_um.length; i++) for (int j = 0; j < mat_um.length; j++) if (i < j) { dists_eucl.add(n, mat_orig[i][j]); dists_dendro.add(n, mat_um[i][j]); n++; } count = n; avgs[0] = average(dists_eucl); // mitjana dists. eucl. avgs[1] = average(dists_dendro); // mitjana dists. dendro. (altures) } public Double getCopheneticCorrelation(Double[][] matriu_orig, Double[][] matriu_ultram) { calculateDistances(matriu_orig, matriu_ultram); return cc_num(matriu_orig, matriu_ultram) / cc_den(matriu_orig, matriu_ultram); } private Double cc_num(Double[][] mat_orig, Double[][] mat) { Double sum = 0.0; for (int i = 0; i < mat.length; i++) for (int j = 0; j < mat.length; j++) if (i < j) { Double sum1 = mat_orig[i][j] - avgs[0]; // x(i,j)-x Double sum2 = mat[i][j] - avgs[1]; // t(i,j)-t sum += sum1 * sum2; } Double num = sum / count; return num; } private Double cc_den(Double[][] mat_orig, Double[][] mat) { Double sum_x = 0.0; // sum_i<j (x(i,j)-x)**2 Double sum_y = 0.0; // sum_i<j (t(i,j)-t)**2 for (int i = 0; i < mat.length; i++) for (int j = 0; j < mat.length; j++) if (i < j) { sum_x += Math.pow(mat_orig[i][j] - avgs[0], 2); // [x(i,j)-x]**2 sum_y += Math.pow(mat[i][j] - avgs[1], 2); // [t(i,j)-t]**2 } Double sigma_x = Math.sqrt(sum_x / count); Double sigma_y = Math.sqrt(sum_y / count); Double den = sigma_x * sigma_y; return den; } public Double getSquaredError(Double[][] matriu_orig, Double[][] matriu_ultram) { calculateDistances(matriu_orig, matriu_ultram); Double num = 0.0, den = 0.0; for (int i = 0; i < matriu_orig.length; i++) for (int j = 0; j < matriu_orig.length; j++) if (i < j) { num += Math .pow(distance(matriu_orig[i][j], matriu_ultram[i][j]), 2); // |x-t|**2 den += Math.pow(matriu_orig[i][j], 2); // x**2 } return num / den; } public Double getAbsoluteError(Double[][] matriu_orig, Double[][] matriu_ultram) { calculateDistances(matriu_orig, matriu_ultram); Double num = 0.0, den = 0.0; for (int i = 0; i < matriu_orig.length; i++) for (int j = 0; j < matriu_orig.length; j++) if (i < j) { num += distance(matriu_orig[i][j], matriu_ultram[i][j]); // |x-t| den += matriu_orig[i][j]; // x } return num / den; } }