package org.streaminer.util.distance;
import java.util.LinkedList;
import java.util.List;
public class CosineDistance {
public static <T extends List<Double>> Double distanceBetween(T firstVector, T secondVector){
if (firstVector.size() != secondVector.size()) {
throw new RuntimeException("Vectors must have the same dimension");
}
Double numerator = 0d;
Double dimSumFirst = 0d;
Double dimSumSecond = 0d;
for (int i = 0; i < firstVector.size(); i++){
numerator += firstVector.get(i) * secondVector.get(i);
dimSumFirst += Math.pow(firstVector.get(i), 2);
dimSumSecond += Math.pow(secondVector.get(i), 2);
}
Double cosine = numerator / Math.sqrt(dimSumFirst + dimSumSecond);
return (1 - cosine);
}
public static <T extends List<Double>> T getFarestVector(List<T> vectors, T comparator){
Double distance = Double.MIN_VALUE;
T farest = vectors.get(0);
for (int i = 0; i < vectors.size(); i++){
if (CosineDistance.distanceBetween(comparator, vectors.get(i)) > distance){
farest = vectors.get(i);
distance = CosineDistance.distanceBetween(comparator, vectors.get(i));
}
}
return farest;
}
public static <T extends List<Double>> T getNearestVector(List<T> vectors, T comparator){
Double distance = Double.MAX_VALUE;
T nearest = vectors.get(0);
for (int i = 0; i < vectors.size(); i++){
if (CosineDistance.distanceBetween(comparator, vectors.get(i)) < distance){
nearest = vectors.get(i);
distance = CosineDistance.distanceBetween(comparator, vectors.get(i));
}
}
return nearest;
}
public static <T extends List<Double>> List<T> getPairWithSmallestDistance(List<T> vectors) {
if (vectors.size() < 2){
throw new RuntimeException("List of vectors must at least contain two vectors");
}
LinkedList<T> bestPair = new LinkedList<T>();
T comparator;
double minimalDistance = Double.MAX_VALUE;
for (int i = 0; i < vectors.size() - 1; i++){
comparator = vectors.get(i);
for (int j = i+1; j < vectors.size(); j++){
if(CosineDistance.distanceBetween(comparator, vectors.get(j)) < minimalDistance){
minimalDistance = CosineDistance.distanceBetween(comparator, vectors.get(j));
bestPair = new LinkedList<T>();
bestPair.add(comparator);
bestPair.add(vectors.get(j));
}
}
}
return bestPair;
}
public static <T extends List<Double>> List<T> getPairWithFurthestDistance(List<T> vectors) {
LinkedList<T> worstPair = new LinkedList<T>();
T comparator;
double maximumDistance = Double.MIN_VALUE;
for (int i = 0; i < vectors.size() - 1; i++){
comparator = vectors.get(i);
for (int j = i+1; j < vectors.size(); j++){
if (CosineDistance.distanceBetween(comparator, vectors.get(j)) > maximumDistance){
maximumDistance = CosineDistance.distanceBetween(comparator, vectors.get(j));
worstPair = new LinkedList<T>();
worstPair.add(comparator);
worstPair.add(vectors.get(j));
}
}
}
return worstPair;
}
}