package edu.indiana.soic.ts.dist.impl;
import edu.indiana.soic.ts.dist.DistanceFunction;
import edu.indiana.soic.ts.utils.VectorPoint;
import org.apache.commons.math3.stat.correlation.PearsonsCorrelation;
import org.apache.commons.math3.stat.regression.SimpleRegression;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
public class LogDistanceFunction implements DistanceFunction {
private static Logger LOG = LoggerFactory.getLogger(LogDistanceFunction.class);
private int type = 5;
public void prepare(Map conf) {
}
public double calc(VectorPoint v1, VectorPoint v2) {
if (type == 1) {
double c = corr(v1, v2);
double l1 = vectorLength(1, v1);
double l2 = vectorLength(1, v2);
return Math.sqrt(Math.pow(l1, 2) + Math.pow(l2, 2) - 2 * l1 * l2 * c);
} else {
double c = corr(v1, v2);
double l1 = 1;
double l2 = 1;
return Math.sqrt(Math.pow(l1, 2) + Math.pow(l2, 2) - 2 * l1 * l2 * c);
}
}
public static double vectorLength(int type, VectorPoint vp) {
if (vp.getKey() == 0) return 0;
double change = change(vp);
if (type == 1) {
return 10 * Math.abs(Math.log(change));
} else if (type == 2) {
return 10 * (change > 1 ? (change - 1) : (1 / change) - 1);
} else if (type == 3) {
SimpleRegression regression = new SimpleRegression();
for (int i = 0; i < vp.getElements(); i++) {
regression.addData(i, vp.getNumbers()[i]);
}
return regression.getSlope();
}
return 0;
}
public static double change(VectorPoint vp) {
int elements = vp.getElements();
if (elements >= 2) {
double numbers[] = vp.getNumbers();
if (numbers[0] > 0) {
double v = numbers[elements - 1] / numbers[0];
if (v > 10) v = 10;
if (v < .1) v = .1;
return v;
}
}
return 1;
}
public static double corr(VectorPoint v1, VectorPoint v2) {
final int start = 1;
double []xs;
double []ys;
ys = v2.getNumbers();
xs = v1.getNumbers();
if (v1.getKey() == v2.getKey()) {
// both are same so return 1
return 1;
}
if (v1.getKey() == 0 || v2.getKey() == 0) {
return 0;
}
double point1Delta = 0.01/250;
double alpha10 = 0.1;
double alpha10Day = alpha10 / 250;
double alpha20 = 0.2;
double alpha20Day = alpha20 / 250;
int noOfElements = v2.noOfElements() > 1 ? v2.noOfElements() : 100;
if (v1.getKey() < 10) {
if (v2.getKey() < 10) {
xs = new double[noOfElements];
} else {
xs = new double[ys.length];
}
double bd = 1.0;
double ed = 0.0;
if (v1.getKey() == 0) {
for (int i = 0; i < xs.length; i++) {
if (i % 2 == 0) {
xs[i] = start + point1Delta;
} else {
xs[i] = start - point1Delta;
}
}
}
else if (v1.getKey() == 1) {
for (int i = 0; i < xs.length; i++) {
ed = (1 + alpha10Day) * bd;
bd = ed;
xs[i] = ed;
}
}
else if (v1.getKey() == 2) {
for (int i = 0; i < xs.length; i++) {
ed = (1 + alpha20Day) * bd;
bd = ed;
xs[i] = ed;
}
}
else if (v1.getKey() == 3) {
for (int i = 0; i < xs.length; i++) {
ed = bd / (1 + alpha10Day);
bd = ed;
xs[i] = ed;
}
}
else if (v1.getKey() == 4) {
for (int i = 0; i < xs.length; i++) {
ed = bd / (1 + alpha20Day);
bd = ed;
xs[i] = ed;
}
}
}
if (v2.getKey() < 10) {
if (v1.getKey() < 10) {
ys = new double[noOfElements];
} else {
ys = new double[xs.length];
}
double bd = 1.0;
double ed = 0.0;
if (v2.getKey() == 0) {
for (int i = 0; i < ys.length; i++) {
if (i % 2 == 0) {
ys[i] = start + point1Delta;
} else {
ys[i] = start - point1Delta;
}
}
}
if (v2.getKey() == 1) {
for (int i = 0; i < ys.length; i++) {
ed = (1 + alpha10Day) * bd;
bd = ed;
ys[i] = ed;
}
}
if (v2.getKey() == 2) {
for (int i = 0; i < ys.length; i++) {
ed = (1 + alpha20Day) * bd;
bd = ed;
ys[i] = ed;
}
}
if (v2.getKey() == 3) {
for (int i = 0; i < ys.length; i++) {
ed = bd / (1 + alpha10Day);
bd = ed;
ys[i] = ed;
}
}
if (v2.getKey() == 4) {
for (int i = 0; i < ys.length; i++) {
ed = bd / (1 + alpha20Day);
bd = ed;
ys[i] = ed;
}
}
}
PearsonsCorrelation pearsonsCorrelation = new PearsonsCorrelation();
try {
return pearsonsCorrelation.correlation(xs, ys);
} catch (Exception e) {
System.out.println(xs.length + " " + ys.length);
e.printStackTrace();
throw new RuntimeException(e);
}
}
}