package de.lmu.ifi.dbs.elki.visualization.parallel3d.layout;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
Copyright (C) 2015
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
import java.util.List;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.math.dimensionsimilarity.DimensionSimilarity;
import de.lmu.ifi.dbs.elki.math.dimensionsimilarity.DimensionSimilarityMatrix;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
import de.lmu.ifi.dbs.elki.math.linearalgebra.SingularValueDecomposition;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
* Layout the axes by multi-dimensional scaling.
*
* Reference:
*
* Elke Achtert, Hans-Peter Kriegel, Erich Schubert, Arthur Zimek:
* Interactive Data Mining with 3D-Parallel-Coordinate-Trees.
* Proceedings of the 2013 ACM International Conference on Management of Data
* (SIGMOD), New York City, NY, 2013.
*
*
* @author Erich Schubert
* @since 0.6.0
*/
@Reference(authors = "Elke Achtert, Hans-Peter Kriegel, Erich Schubert, Arthur Zimek", title = "Interactive Data Mining with 3D-Parallel-Coordinate-Trees", booktitle = "Proc. of the 2013 ACM International Conference on Management of Data (SIGMOD)", url = "http://dx.doi.org/10.1145/2463676.2463696")
public class MultidimensionalScalingMSTLayout3DPC extends AbstractLayout3DPC {
/**
* Constructor.
*
* @param sim Similarity measure
*/
public MultidimensionalScalingMSTLayout3DPC(DimensionSimilarity sim) {
super(sim);
}
/**
* Node class for this layout.
*
* @author Erich Schubert
*/
public static class Node extends AbstractLayout3DPC.AbstractNode {
/**
* Constructor.
*
* @param dim Dimensionality
* @param children Number of children
*/
public Node(int dim, List children) {
super(dim, children);
}
}
@Override
Node makeNode(int dim, List children) {
return new Node(dim, children);
}
@Override
public Layout layout(int dim, DimensionSimilarityMatrix mat) {
// Find maximum of |cij|
double max = 0;
for (int i = 0; i < dim; i++) {
for (int j = i + 1; j < dim; j++) {
double v = Math.abs(mat.get(j, i));
if (v > max) {
max = v;
}
}
}
// Assume that "max - |cij|" is now a distance.
// We use sqrt(v) instead of v*v, since this makes the method
// less aggressive overall, and we are not using euclidean anyway.
double means[] = new double[dim];
double mean = 0.0;
for (int i = 0; i < dim; i++) {
for (int j = i + 1; j < dim; j++) {
double v = max - Math.abs(mat.get(i, j));
v = -.5 * Math.sqrt(v);
means[i] += v;
means[j] += v;
mean += 2 * v;
}
}
for (int i = 0; i < dim; i++) {
means[i] /= dim;
}
mean /= (dim * dim);
// Build double centered matrix:
Matrix d = new Matrix(dim, dim);
for (int i = 0; i < dim; i++) {
d.set(i, i, -2 * means[i] + mean);
for (int j = i + 1; j < dim; j++) {
double v = max - Math.abs(mat.get(i, j));
v = -.5 * Math.sqrt(v) - means[i] - means[j] + mean;
d.set(i, j, v);
d.set(j, i, v);
}
}
SingularValueDecomposition svd = new SingularValueDecomposition(d);
Matrix u = svd.getU();
double[] lambda = svd.getSingularValues();
lambda[0] = Math.sqrt(Math.abs(lambda[0]));
lambda[1] = Math.sqrt(Math.abs(lambda[1]));
Layout l = new Layout();
buildSpanningTree(mat, l);
double maxabs = 0;
for (int i = 0; i < dim; i++) {
Node n = (Node) l.getNode(i);
n.x = u.get(i, 0) * lambda[0];
n.y = u.get(i, 1) * lambda[1];
double v = n.x * n.x + n.y * n.y;
if (v > maxabs) {
maxabs = v;
}
}
maxabs = 1. / Math.sqrt(maxabs);
for (int i = 0; i < dim; i++) {
Node n = (Node) l.getNode(i);
n.x *= maxabs;
n.y *= maxabs;
}
return l;
}
/**
* Parameteriation class.
*
* @author Erich Schubert
*
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractLayout3DPC.Parameterizer {
@Override
protected MultidimensionalScalingMSTLayout3DPC makeInstance() {
return new MultidimensionalScalingMSTLayout3DPC(sim);
}
}
}