/*
* File: VectorInteroperabilityTest.java
* Authors: Justin Basilico
* Project: Cognitive Foundry
*
* Copyright 2015 Cognitive Foundry. All rights reserved.
*/
package gov.sandia.cognition.math.matrix;
import gov.sandia.cognition.collection.CollectionUtil;
import gov.sandia.cognition.math.matrix.mtj.DenseVectorFactoryMTJ;
import gov.sandia.cognition.math.matrix.mtj.SparseVectorFactoryMTJ;
import gov.sandia.cognition.math.matrix.custom.CustomDenseVectorFactory;
import gov.sandia.cognition.math.matrix.custom.CustomSparseVectorFactory;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import junit.framework.TestCase;
import static junit.framework.TestCase.assertTrue;
import static junit.framework.TestCase.fail;
import org.junit.Before;
import org.junit.Test;
/**
* Unit tests for the interoperability of different {@link Vector}
* implementations.
*
* @author Justin Basilico
* @since 3.4.3
*/
public class VectorInteroperabilityTest
{
protected List<List<List<Vector>>> groups;
protected Random random = new Random(22223);
protected double epsilon = 1e-10;
public VectorInteroperabilityTest()
{
super();
}
public static List<VectorFactory<?>> getFactories()
{
List<VectorFactory<?>> factories = new LinkedList<>();
factories.add(new DenseVectorFactoryMTJ());
factories.add(new SparseVectorFactoryMTJ());
factories.add(new CustomDenseVectorFactory());
factories.add(new CustomSparseVectorFactory());
// Add new factories above here.
return factories;
}
@Before
public void setUp()
{
this.groups = new LinkedList<>();
List<VectorFactory<?>> factories = getFactories();
for (int i = 0; i < 10; i++)
{
// General-purpose ones.
int d = 1 + random.nextInt(10);
for (VectorFactory<?> f : factories)
{
Vector a = f.createUniformRandom(d, -10, 10, random);
Vector b = f.createUniformRandom(d, -10, 10, random);
List<Vector> as = new ArrayList<>();
as.add(a);
List<Vector> bs = new ArrayList<>();
bs.add(b);
for (VectorFactory<?> g : factories)
{
as.add(g.copyVector(a));
bs.add(g.copyVector(b));
}
groups.add(CollectionUtil.createArrayList(as, bs));
}
}
}
@Test
public void testEquals()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
boolean expected = as.get(0).equals(bs.get(0));
for (Vector a1 : as)
{
for (Vector a2 : as)
{
assertTrue("" + a1.getClass() + " -> " + a2.getClass(),
a1.clone().equals(a2.clone()));
}
}
for (Vector a : as)
{
for (Vector b : bs)
{
TestCase.assertEquals(expected, a.clone().equals(b.clone()));
}
}
for (Vector b1 : bs)
{
for (Vector b2 : bs)
{
assertTrue(b1.clone().equals(b2.clone()));
}
}
}
}
@Test
public void testEqualsWithEffectiveZero()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
boolean expected = as.get(0).equals(bs.get(0), epsilon);
for (Vector a1 : as)
{
for (Vector a2 : as)
{
assertTrue(a1.clone().equals(a2.clone(), epsilon));
}
}
for (Vector a : as)
{
for (Vector b : bs)
{
TestCase.assertEquals(expected, a.clone().equals(b.clone(), epsilon));
}
}
for (Vector b1 : bs)
{
for (Vector b2 : bs)
{
assertTrue(b1.clone().equals(b2.clone(), epsilon));
}
}
}
}
@Test
public void testPlus()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
Vector expected = as.get(0).plus(bs.get(0));
for (Vector a : as)
{
for (Vector b : bs)
{
Vector actual = a.clone().plus(b.clone());
assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testPlusEquals()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
Vector expected = as.get(0).clone();
expected.plusEquals(bs.get(0).clone());
for (Vector a : as)
{
for (Vector b : bs)
{
Vector actual = a.clone();
actual.plusEquals(b.clone());
assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testMinus()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
Vector expected = as.get(0).minus(bs.get(0));
for (Vector a : as)
{
for (Vector b : bs)
{
Vector actual = a.clone().minus(b.clone());
assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testMinusEquals()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
Vector expected = as.get(0).clone();
expected.minusEquals(bs.get(0).clone());
for (Vector a : as)
{
for (Vector b : bs)
{
Vector actual = a.clone();
actual.minusEquals(b.clone());
assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testDotTimes()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
Vector expected = as.get(0).dotTimes(bs.get(0));
for (Vector a : as)
{
for (Vector b : bs)
{
Vector actual = a.clone().dotTimes(b.clone());
assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testDotTimesEquals()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
Vector expected = as.get(0).clone();
expected.dotTimesEquals(bs.get(0).clone());
for (Vector a : as)
{
for (Vector b : bs)
{
Vector actual = a.clone();
actual.dotTimesEquals(b.clone());
assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testDotDivide()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
Vector expected = as.get(0).dotDivide(bs.get(0));
for (Vector a : as)
{
for (Vector b : bs)
{
Vector actual = a.clone().dotDivide(b.clone());
assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testDotDivideEquals()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
Vector expected = as.get(0).clone();
expected.dotDivideEquals(bs.get(0).clone());
for (Vector a : as)
{
for (Vector b : bs)
{
Vector actual = a.clone();
actual.dotDivideEquals(b.clone());
assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testScaledPlus()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
double scale = this.random.nextGaussian();
Vector expected = as.get(0).scaledPlus(scale, bs.get(0));
for (Vector a : as)
{
for (Vector b : bs)
{
Vector actual = a.clone().scaledPlus(scale, b.clone());
assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testScaledPlusEquals()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
double scale = this.random.nextGaussian();
Vector expected = as.get(0).clone();
expected.scaledPlusEquals(scale, bs.get(0).clone());
for (Vector a : as)
{
for (Vector b : bs)
{
Vector actual = a.clone();
actual.scaledPlusEquals(scale, b.clone());
assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testScaledMinus()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
double scale = this.random.nextGaussian();
Vector expected = as.get(0).scaledMinus(scale, bs.get(0));
for (Vector a : as)
{
for (Vector b : bs)
{
Vector actual = a.clone().scaledMinus(scale, b.clone());
assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testScaledMinusEquals()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
double scale = this.random.nextGaussian();
Vector expected = as.get(0).clone();
expected.scaledMinusEquals(scale, bs.get(0).clone());
for (Vector a : as)
{
for (Vector b : bs)
{
Vector actual = a.clone();
actual.scaledMinusEquals(scale, b.clone());
assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testDot()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
double expected = as.get(0).dot(bs.get(0));
for (Vector a : as)
{
for (Vector b : bs)
{
double actual = a.clone().dot(b.clone());
TestCase.assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testDotProduct()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
double expected = as.get(0).dotProduct(bs.get(0));
for (Vector a : as)
{
for (Vector b : bs)
{
double actual = a.clone().dotProduct(b.clone());
TestCase.assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testAngle()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
double expected = as.get(0).angle(bs.get(0));
for (Vector a : as)
{
for (Vector b : bs)
{
double actual = a.clone().angle(b.clone());
TestCase.assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testCosine()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
double expected = as.get(0).cosine(bs.get(0));
for (Vector a : as)
{
for (Vector b : bs)
{
double actual = a.clone().cosine(b.clone());
TestCase.assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testEuclideanDistance()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
double expected = as.get(0).euclideanDistance(bs.get(0));
for (Vector a : as)
{
for (Vector b : bs)
{
double actual = a.clone().euclideanDistance(b.clone());
TestCase.assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testEuclideanDistanceSquared()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
double expected = as.get(0).euclideanDistanceSquared(bs.get(0));
for (Vector a : as)
{
for (Vector b : bs)
{
double actual = a.clone().euclideanDistanceSquared(b.clone());
TestCase.assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testOuterProduct()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
Matrix expected = as.get(0).outerProduct(bs.get(0));
for (Vector a : as)
{
for (Vector b : bs)
{
Matrix actual = a.clone().outerProduct(b.clone());
MatrixInteroperabilityTest.assertEquals(
expected, actual, epsilon);
}
}
}
}
@Test
public void testStack()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
List<Vector> bs = group.get(1);
Vector expected = as.get(0).stack(bs.get(0));
for (Vector a : as)
{
for (Vector b : bs)
{
Vector actual = a.clone().stack(b.clone());
assertEquals(expected, actual, epsilon);
}
}
}
}
@Test
public void testTimesMatrix()
{
for (List<List<Vector>> group : groups)
{
List<Vector> as = group.get(0);
final Vector a1 = as.get(0);
for (MatrixFactory<?> f : MatrixInteroperabilityTest.getFactories())
{
int n = 1 + random.nextInt(10);
Matrix m1 = f.createUniformRandom(a1.getDimensionality(), n, -10, 10, random);
Vector expected = a1.times(m1);
for (MatrixFactory<?> g : MatrixInteroperabilityTest.getFactories())
{
Matrix m = g.copyMatrix(m1);
Vector actual = a1.clone().times(m);
assertEquals(expected, actual, epsilon);
}
}
}
}
public static void assertEquals(
final Vector expected,
final Vector actual,
final double effectiveZero)
{
TestCase.assertEquals(0.0, expected.minus(actual).norm2(), effectiveZero);
}
}