/*
* 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 definicions;
import inicial.Language;
import java.io.Serializable;
import java.util.Vector;
import tipus.tipusDades;
/**
* <p>
* <b>MultiDendrograms</b>
* </p>
*
* Stores the distances matrix and implements methods for its management
*
* @author Justo Montiel, David Torres, Sergio Gómez, Alberto Fernández
*
* @since JDK 6.0
*/
public class MatriuDistancies implements Serializable {
// Type of data stored in the matrix
private tipusDades tipDades = tipusDades.DISTANCIA;
// When it's 'true', it indicates that the matrix has a single element
private boolean isCopa = false;
private int numElems = 0;
// Distances minimum and maximum among all existing distances
private double minValue = Double.MAX_VALUE;
private double maxValue = Double.MIN_VALUE;
// Storage of distance data
private Vector<Cluster> arrClusters;
private Vector<Vector<Double>> arrDistancies;
private Id_To_Key<Integer> claus;
public MatriuDistancies(int size, final tipusDades tip) throws Exception {
tipDades = tip;
if (size < 2) {
isCopa = true;
size = 2;
} else {
isCopa = false;
}
this.inicialitza(size);
}
public MatriuDistancies(int size) throws Exception {
tipDades = tipusDades.DISTANCIA;
if (size < 2) {
isCopa = true;
size = 2;
} else {
isCopa = false;
}
this.inicialitza(size);
}
private void inicialitza(final int size) throws Exception {
arrClusters = new Vector<Cluster>(size);
arrDistancies = new Vector<Vector<Double>>(size);
for (int n = 0; n < size; n++) {
try {
arrDistancies.add(new Vector<Double>((size - n - 1)));
for (int nn = 0; nn < (size - n - 1); nn++) {
arrDistancies.get(n).add(null);
}
} catch (final Exception e) {
String err_msg;
err_msg = e.getMessage();
err_msg += "\n" + Language.getLabel(73);
throw new Exception(err_msg);
}
}
claus = new Id_To_Key<Integer>();
}
public boolean isUnari() {
return isCopa;
}
public boolean existDistance(final Cluster ci, final Cluster cii) {
return (claus.containsKey(ci.getId()) && claus.containsKey(cii.getId()));
}
public void setDistancia(final Cluster ci, final Cluster cii,
final double dis) throws Exception {
int k1, k2, tmp;
if (claus.containsKey(ci.getId())) {
k1 = claus.getInd(ci.getId());
} else {
k1 = claus.setInd(ci.getId());
numElems++;
arrClusters.add(k1, ci);
}
if (claus.containsKey(cii.getId())) {
k2 = claus.getInd(cii.getId());
} else {
k2 = claus.setInd(cii.getId());
numElems++;
arrClusters.add(k2, cii);
}
try {
if (k1 > k2) {
tmp = k2;
k2 = k1;
k1 = tmp;
} else if ((k1 == k2) && (k1 == 0)) {
// single cluster matrix
arrDistancies.get(k1).setElementAt(new Double(dis), k1);
} else {
arrDistancies.get(k1)
.setElementAt(new Double(dis), k2 - k1 - 1);
}
} catch (final Exception e) {
String err_msg;
err_msg = e.getMessage();
err_msg += "\n" + Language.getLabel(71);
throw new Exception(err_msg);
}
if (dis < minValue || minValue == Double.MAX_VALUE) {
minValue = new Double(dis);
}
if (dis > maxValue || maxValue == Double.MIN_VALUE) {
maxValue = new Double(dis);
}
}
public void setDistancia(final Cluster ci) throws Exception {
if (numElems == 0) {
this.setDistancia(ci, ci, 0);
isCopa = true;
numElems = 1;
}
}
public Double getDistancia(final Cluster i, final Cluster ii)
throws Exception {
int tmp;
int k1 = 0, k2 = 0;
double dis = 0.0;
try {
k1 = claus.getInd(i.getId());
k2 = claus.getInd(ii.getId());
if (k1 > k2) {
tmp = k2;
k2 = k1;
k1 = tmp;
}
dis = arrDistancies.get(k1).get(k2 - k1 - 1);
} catch (final Exception e) {
String err_msg;
err_msg = e.getMessage();
err_msg += "\n" + Language.getLabel(70);
throw new Exception(err_msg);
}
return dis;
}
public int getCardinalitat() {
return numElems;
}
public Double minValue() {
return minValue;
}
public Double maxValue() {
return maxValue;
}
public Vector<Cluster> getClusters() {
return arrClusters;
}
public Cluster getCluster(final int pos) {
return arrClusters.elementAt(pos);
}
public double[][] getMatriu() throws Exception {
final double[][] matriu = new double[numElems][numElems];
try {
for (int n = 0; n < numElems - 1; n++) {
for (int m = n + 1; m < numElems; m++) {
matriu[n][m] = this.getDistancia(arrClusters.get(n),
arrClusters.get(m));
matriu[m][n] = matriu[n][m];
}
}
} catch (Exception e) {
String err_msg;
err_msg = e.getMessage();
err_msg += "\n" + Language.getLabel(72);
throw new Exception(err_msg);
}
return matriu;
}
public Cluster getArrel() {
return this.getCluster(0);
}
public tipusDades getTipDades() {
return tipDades;
}
public void setTipDades(final tipusDades tipDades) {
this.tipDades = tipDades;
}
public boolean isTipusDistancies() {
return tipDades.equals(tipusDades.DISTANCIA);
}
public void setArrel(Cluster c) {
arrClusters.add(0,c);
}
}