/*******************************************************************************
* Copyright (c) 2012 Michael Kutschke.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Michael Kutschke - initial API and implementation
******************************************************************************/
package org.eclipse.recommenders.jayes.factor;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.IsSame.sameInstance;
import static org.junit.Assert.*;
import org.eclipse.recommenders.jayes.BayesNet;
import org.eclipse.recommenders.jayes.factor.arraywrapper.DoubleArrayWrapper;
import org.eclipse.recommenders.jayes.factor.arraywrapper.FloatArrayWrapper;
import org.eclipse.recommenders.jayes.util.MathUtils;
import org.eclipse.recommenders.testing.jayes.NetExamples;
import org.junit.Test;
public class SparseFactorTest {
@Test
public void testIsSuitableNoFactors() {
// no NullPointerException should be thrown
assertFalse(SparseFactor.isSuitable(1, (AbstractFactor[]) null));
assertFalse(SparseFactor.isSuitable(1, new AbstractFactor[0]));
}
@Test
public void testIsSuitableSparseFactor() {
BayesNet sparseNet = NetExamples.sparseNet();
AbstractFactor sparse = sparseNet.getNode("c").getFactor();
assertTrue(SparseFactor.isSuitable(MathUtils.product(sparse.getDimensions()), sparse));
}
@Test
public void testIsSuitableNonSparseFactor() {
AbstractFactor nonsparse = NetExamples.sparseNet().getNode("d").getFactor();
assertFalse(SparseFactor.isSuitable(MathUtils.product(nonsparse.getDimensions()), nonsparse));
}
@Test
public void testBlocksizeOne() {
AbstractFactor dense = new DenseFactor();
dense.setDimensionIDs(0);
dense.setDimensions(12);
dense.setValues(new DoubleArrayWrapper(0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6));
SparseFactor sparse = SparseFactor.fromFactor(dense);
assertEquals(7, sparse.getValues().length());
assertThat(sparse.getValues().toDoubleArray(), is(new double[] { 0, 1, 2, 3, 4, 5, 6 }));
}
@Test
public void testEvenBlocksize() {
AbstractFactor dense = new DenseFactor();
dense.setDimensionIDs(0);
dense.setDimensions(16);
dense.setValues(new FloatArrayWrapper(0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 5, 6, 7, 8));
SparseFactor sparse = SparseFactor.fromFactor(dense);
// is 12 if a blocksize of 4 is chosen (which is best here, because of lower overhead)
// would be 13 if a blocksize of 3 was chosen
// would be 10 in case of a blocksize of 2
assertEquals(12, sparse.getValues().length());
assertThat(sparse.getValues().toDoubleArray(), is(new double[] { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8 }));
}
@Test
public void testOddBlocksize() {
AbstractFactor dense = new DenseFactor();
dense.setDimensionIDs(0);
dense.setDimensions(12);
dense.setValues(new DoubleArrayWrapper(0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5, 6));
SparseFactor sparse = SparseFactor.fromFactor(dense);
// is 9 if a blocksize of 3 is chosen
// would be 10 in case of a blocksize of 2
assertEquals(9, sparse.getValues().length());
assertThat(sparse.getValues().toDoubleArray(), is(new double[] { 0, 0, 0, 1, 2, 3, 4, 5, 6 }));
}
@Test
public void testZeroDimensional() {
AbstractFactor dense = new DenseFactor();
dense.setDimensionIDs();
dense.setDimensions();
dense.setValues(new DoubleArrayWrapper(2));
SparseFactor sparse = SparseFactor.fromFactor(dense);
assertEquals(2, sparse.getValues().length());
assertThat(sparse.getValues().toDoubleArray(), is(new double[] { 0, 2 }));
}
/*
* zero-dimensional dense factor, but one-dimensional sparse factor
*/
@Test
public void testZeroDimensional2() {
AbstractFactor dense = new DenseFactor();
dense.setDimensionIDs();
dense.setDimensions();
dense.setValues(new DoubleArrayWrapper(2));
SparseFactor sparse = new SparseFactor();
sparse.setDimensionIDs(0);
sparse.setDimensions(2);
sparse.sparsify(dense);
sparse.fill(1);
sparse.multiplyCompatible(dense);
assertThat(sparse.getValues().toDoubleArray(), is(new double[] { 0, 2, 2 }));
}
@Test
public void testDimensionReordering() {
AbstractFactor dense = new DenseFactor();
dense.setDimensionIDs(0, 1);
dense.setDimensions(2, 2);
dense.setValues(new DoubleArrayWrapper(0, 1, 0, 2));
SparseFactor sparse = SparseFactor.fromFactor(dense);
int[] reorderedDimensionIds = new int[] { 1, 0 };
assertThat(sparse.getDimensionIDs(), is(reorderedDimensionIds));
assertEquals(4, sparse.getValues().length());
assertThat(sparse.getValues().toDoubleArray(), is(new double[] { 0, 0, 1, 2 }));
}
@SuppressWarnings("deprecation")
@Test
public void testSum() {
AbstractFactor dense = new DenseFactor();
dense.setDimensionIDs(0);
dense.setDimensions(12);
dense.setValues(new DoubleArrayWrapper(0, 1, 0, 2, 0, 4, 0, 8, 0, 16, 0, 32));
SparseFactor sparse = SparseFactor.fromFactor(dense);
assertThat(sparse.marginalizeAllBut(0), is(new double[] { 0, 1, 0, 2, 0, 4, 0, 8, 0, 16, 0, 32 }));
}
@Test
public void testFromSparseFactor() {
AbstractFactor dense = new DenseFactor();
dense.setDimensionIDs(0);
dense.setDimensions(12);
dense.setValues(new DoubleArrayWrapper(0, 1, 0, 2, 0, 4, 0, 8, 0, 16, 0, 32));
SparseFactor sparse = SparseFactor.fromFactor(dense);
SparseFactor sparse2 = SparseFactor.fromFactor(sparse);
assertThat(sparse2.getValues(), is(not(sameInstance(sparse.getValues()))));
assertThat(sparse2.getValues().toDoubleArray(), is(sparse.getValues().toDoubleArray()));
}
}