/*
* File: MinkowskiDistanceMetricTest.java
* Authors: Justin Basilico
* Project: Cognitive Foundry
*
* Copyright 2011 Cognitive Foundry. All rights reserved.
*/
package gov.sandia.cognition.learning.function.distance;
import gov.sandia.cognition.math.matrix.Vector;
import gov.sandia.cognition.math.matrix.VectorFactory;
import gov.sandia.cognition.math.matrix.Vectorizable;
import gov.sandia.cognition.math.matrix.mtj.Vector2;
/**
* Unit tests for class MinkowskiDistanceMetric.
*
* @author Justin Basilico
* @since 3.3.3
*/
public class MinkowskiDistanceMetricTest
extends MetricTestHarness<Vectorizable>
{
/**
* Creates a new test.
*
* @param testName
* The test name.
*/
public MinkowskiDistanceMetricTest(
final String testName)
{
super(testName);
}
/**
* Test of constructors method, of class MinkowskiDistanceMetric.
*/
public void testConstructors()
{
double power = MinkowskiDistanceMetric.DEFAULT_POWER;
MinkowskiDistanceMetric instance = new MinkowskiDistanceMetric();
assertEquals(power, instance.getPower(), 0.0);
power *= RANDOM.nextDouble();
instance = new MinkowskiDistanceMetric(power);
assertEquals(power, instance.getPower(), 0.0);
}
/**
* Test of evaluate method, of class MinkowskiDistanceMetric.
*/
public void testEvaluate()
{
double epsilon = 1e-10;
int d = 10;
Vector x = VectorFactory.getDefault().createUniformRandom(d, -100, +100, RANDOM);
Vector y = VectorFactory.getDefault().createUniformRandom(d, -100, +100, RANDOM);
MinkowskiDistanceMetric instance = new MinkowskiDistanceMetric();
instance.setPower(1.0);
assertEquals(x.minus(y).norm1(), instance.evaluate(x, y), epsilon);
assertEquals(x.minus(y).norm1(), instance.evaluate(y, x), epsilon);
assertEquals(0.0, instance.evaluate(x, x), epsilon);
assertEquals(0.0, instance.evaluate(y, y), epsilon);
instance.setPower(2.0);
assertEquals(x.minus(y).norm2(), instance.evaluate(x, y), epsilon);
assertEquals(x.minus(y).norm2(), instance.evaluate(y, x), epsilon);
assertEquals(0.0, instance.evaluate(x, x), epsilon);
assertEquals(0.0, instance.evaluate(y, y), epsilon);
}
/**
* Test of getPower method, of class MinkowskiDistanceMetric.
*/
public void testGetPower()
{
this.testSetPower();
}
/**
* Test of setPower method, of class MinkowskiDistanceMetric.
*/
public void testSetPower()
{
double power = MinkowskiDistanceMetric.DEFAULT_POWER;
MinkowskiDistanceMetric instance = new MinkowskiDistanceMetric();
assertEquals(power, instance.getPower(), 0.0);
double[] goodValues = {0.001, 0.2, 1.0, 10.0, 123.0, RANDOM.nextDouble()};
for (double goodValue : goodValues)
{
power = goodValue;
instance.setPower(power);
assertEquals(power, instance.getPower(), 0.0);
}
double[] badValues = {0.0, -0.2, -1.0, -RANDOM.nextDouble()};
for (double badValue : badValues)
{
boolean exceptionThrown = false;
try
{
instance.setPower(badValue);
}
catch (IllegalArgumentException e)
{
exceptionThrown = true;
}
finally
{
assertTrue(exceptionThrown);
}
assertEquals(power, instance.getPower(), 0.0);
}
}
@Override
public MinkowskiDistanceMetric createInstance()
{
return new MinkowskiDistanceMetric(RANDOM.nextDouble() * 10 + 1.0);
}
@Override
public Vector generateRandomFirstType()
{
return VectorFactory.getDefault().createUniformRandom(5,-10.0,5.0, RANDOM);
}
@Override
public void testKnownValues()
{
System.out.println( "Known Values" );
MinkowskiDistanceMetric instance = new MinkowskiDistanceMetric(2.0);
// Create four points to compute the distances between.
Vector2 v00 = new Vector2(0.0, 0.0);
Vector2 v01 = new Vector2(0.0, 1.0);
Vector2 v10 = new Vector2(1.0, 0.0);
Vector2 v11 = new Vector2(1.0, 1.0);
// Make sure the distance to self is zero.
assertEquals(0.0, instance.evaluate(v00, v00));
assertEquals(0.0, instance.evaluate(v01, v01));
assertEquals(0.0, instance.evaluate(v10, v10));
assertEquals(0.0, instance.evaluate(v11, v11));
// Make sure the distances between points are correct.
assertEquals(1.0, instance.evaluate(v00, v01));
assertEquals(1.0, instance.evaluate(v00, v10));
assertEquals(1.0, instance.evaluate(v01, v00));
assertEquals(1.0, instance.evaluate(v01, v11));
assertEquals(Math.sqrt(2), instance.evaluate(v00, v11));
// Make sure that it works with negative points.
assertEquals(1.0, instance.evaluate(v00, v01.scale(-1.0)));
assertEquals(1.0, instance.evaluate(v00, v10.scale(-1.0)));
assertEquals(Math.sqrt(2), instance.evaluate(v00, v11.scale(-1.0)));
// Test examples of manhattan distance by setting power to 2.0.
instance.setPower(1.0);
assertEquals(0.0, instance.evaluate(v00, v00));
assertEquals(0.0, instance.evaluate(v01, v01));
assertEquals(0.0, instance.evaluate(v10, v10));
assertEquals(0.0, instance.evaluate(v11, v11));
// Make sure the distances between points are correct.
assertEquals(1.0, instance.evaluate(v00, v01));
assertEquals(1.0, instance.evaluate(v00, v10));
assertEquals(1.0, instance.evaluate(v01, v00));
assertEquals(1.0, instance.evaluate(v01, v11));
assertEquals(2.0, instance.evaluate(v00, v11));
// Make sure that it works with negative points.
assertEquals(1.0, instance.evaluate(v00, v01.scale(-1.0)));
assertEquals(1.0, instance.evaluate(v00, v10.scale(-1.0)));
assertEquals(2.0, instance.evaluate(v00, v11.scale(-1.0)));
for (int i = 0; i < NUM_SAMPLES; i++)
{
Vector x = this.generateRandomFirstType();
Vector y = this.generateRandomFirstType();
double expected = x.minus(y).norm1();
double result = instance.evaluate(x, y);
assertEquals(expected, result);
assertTrue(result >= 0.0);
assertEquals(0.0, instance.evaluate(x, x), TOLERANCE);
assertEquals(0.0, instance.evaluate(y, y), TOLERANCE);
}
}
}